blob: c44b761fe11b37faed2c15825fadb2c3969c8963 [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"
20#include "utils/x86/assembler_x86.h"
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010021#include "utils/x86/managed_register_x86.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000022
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070023#include "entrypoints/quick/quick_entrypoints.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000024#include "mirror/array.h"
25#include "mirror/art_method.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070026#include "thread.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000027
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000028namespace art {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010029
30x86::X86ManagedRegister Location::AsX86() const {
31 return reg().AsX86();
32}
33
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000034namespace x86 {
35
Nicolas Geoffraye5038322014-07-04 09:41:32 +010036#define __ reinterpret_cast<X86Assembler*>(codegen->GetAssembler())->
37
38class NullCheckSlowPathX86 : public SlowPathCode {
39 public:
40 explicit NullCheckSlowPathX86(uint32_t dex_pc) : dex_pc_(dex_pc) {}
41
42 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
43 __ Bind(GetEntryLabel());
44 __ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pThrowNullPointer)));
45 codegen->RecordPcInfo(dex_pc_);
46 }
47
48 private:
49 const uint32_t dex_pc_;
50 DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathX86);
51};
52
53#undef __
54#define __ reinterpret_cast<X86Assembler*>(GetAssembler())->
55
Dave Allison20dfc792014-06-16 20:44:29 -070056inline Condition X86Condition(IfCondition cond) {
57 switch (cond) {
58 case kCondEQ: return kEqual;
59 case kCondNE: return kNotEqual;
60 case kCondLT: return kLess;
61 case kCondLE: return kLessEqual;
62 case kCondGT: return kGreater;
63 case kCondGE: return kGreaterEqual;
64 default:
65 LOG(FATAL) << "Unknown if condition";
66 }
67 return kEqual;
68}
69
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010070static constexpr int kNumberOfPushedRegistersAtEntry = 1;
71static constexpr int kCurrentMethodStackOffset = 0;
72
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010073void CodeGeneratorX86::DumpCoreRegister(std::ostream& stream, int reg) const {
74 stream << X86ManagedRegister::FromCpuRegister(Register(reg));
75}
76
77void CodeGeneratorX86::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
78 stream << X86ManagedRegister::FromXmmRegister(XmmRegister(reg));
79}
80
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010081CodeGeneratorX86::CodeGeneratorX86(HGraph* graph)
82 : CodeGenerator(graph, kNumberOfRegIds),
83 location_builder_(graph, this),
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010084 instruction_visitor_(graph, this),
85 move_resolver_(graph->GetArena(), this) {}
86
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +010087size_t CodeGeneratorX86::FrameEntrySpillSize() const {
88 return kNumberOfPushedRegistersAtEntry * kX86WordSize;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010089}
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010090
91static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
92 return blocked_registers + kNumberOfAllocIds;
93}
94
95ManagedRegister CodeGeneratorX86::AllocateFreeRegister(Primitive::Type type,
96 bool* blocked_registers) const {
97 switch (type) {
98 case Primitive::kPrimLong: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +010099 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
100 size_t reg = AllocateFreeRegisterInternal(blocked_register_pairs, kNumberOfRegisterPairs);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100101 X86ManagedRegister pair =
102 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg));
103 blocked_registers[pair.AsRegisterPairLow()] = true;
104 blocked_registers[pair.AsRegisterPairHigh()] = true;
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100105 // Block all other register pairs that share a register with `pair`.
106 for (int i = 0; i < kNumberOfRegisterPairs; i++) {
107 X86ManagedRegister current =
108 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(i));
109 if (current.AsRegisterPairLow() == pair.AsRegisterPairLow()
110 || current.AsRegisterPairLow() == pair.AsRegisterPairHigh()
111 || current.AsRegisterPairHigh() == pair.AsRegisterPairLow()
112 || current.AsRegisterPairHigh() == pair.AsRegisterPairHigh()) {
113 blocked_register_pairs[i] = true;
114 }
115 }
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100116 return pair;
117 }
118
119 case Primitive::kPrimByte:
120 case Primitive::kPrimBoolean:
121 case Primitive::kPrimChar:
122 case Primitive::kPrimShort:
123 case Primitive::kPrimInt:
124 case Primitive::kPrimNot: {
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100125 Register reg = static_cast<Register>(
126 AllocateFreeRegisterInternal(blocked_registers, kNumberOfCpuRegisters));
127 // Block all register pairs that contain `reg`.
128 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
129 for (int i = 0; i < kNumberOfRegisterPairs; i++) {
130 X86ManagedRegister current =
131 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(i));
132 if (current.AsRegisterPairLow() == reg || current.AsRegisterPairHigh() == reg) {
133 blocked_register_pairs[i] = true;
134 }
135 }
136 return X86ManagedRegister::FromCpuRegister(reg);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100137 }
138
139 case Primitive::kPrimFloat:
140 case Primitive::kPrimDouble:
141 LOG(FATAL) << "Unimplemented register type " << type;
142
143 case Primitive::kPrimVoid:
144 LOG(FATAL) << "Unreachable type " << type;
145 }
146
147 return ManagedRegister::NoRegister();
148}
149
150void CodeGeneratorX86::SetupBlockedRegisters(bool* blocked_registers) const {
151 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
152
153 // Don't allocate the dalvik style register pair passing.
154 blocked_register_pairs[ECX_EDX] = true;
155
156 // Stack register is always reserved.
157 blocked_registers[ESP] = true;
158
159 // TODO: We currently don't use Quick's callee saved registers.
160 blocked_registers[EBP] = true;
161 blocked_registers[ESI] = true;
162 blocked_registers[EDI] = true;
163 blocked_register_pairs[EAX_EDI] = true;
164 blocked_register_pairs[EDX_EDI] = true;
165 blocked_register_pairs[ECX_EDI] = true;
166 blocked_register_pairs[EBX_EDI] = true;
167}
168
169size_t CodeGeneratorX86::GetNumberOfRegisters() const {
170 return kNumberOfRegIds;
171}
172
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100173static Location X86CpuLocation(Register reg) {
174 return Location::RegisterLocation(X86ManagedRegister::FromCpuRegister(reg));
175}
176
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100177InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen)
178 : HGraphVisitor(graph),
179 assembler_(codegen->GetAssembler()),
180 codegen_(codegen) {}
181
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000182void CodeGeneratorX86::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000183 // Create a fake register to mimic Quick.
184 static const int kFakeReturnRegister = 8;
185 core_spill_mask_ |= (1 << kFakeReturnRegister);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000186
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100187 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100188 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100189 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000190}
191
192void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100193 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000194}
195
196void CodeGeneratorX86::Bind(Label* label) {
197 __ Bind(label);
198}
199
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000200void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100201 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000202}
203
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100204Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
205 switch (load->GetType()) {
206 case Primitive::kPrimLong:
207 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
208 break;
209
210 case Primitive::kPrimInt:
211 case Primitive::kPrimNot:
212 return Location::StackSlot(GetStackSlot(load->GetLocal()));
213
214 case Primitive::kPrimFloat:
215 case Primitive::kPrimDouble:
216 LOG(FATAL) << "Unimplemented type " << load->GetType();
217
218 case Primitive::kPrimBoolean:
219 case Primitive::kPrimByte:
220 case Primitive::kPrimChar:
221 case Primitive::kPrimShort:
222 case Primitive::kPrimVoid:
223 LOG(FATAL) << "Unexpected type " << load->GetType();
224 }
225
226 LOG(FATAL) << "Unreachable";
227 return Location();
228}
229
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100230static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
231static constexpr size_t kRuntimeParameterCoreRegistersLength =
232 arraysize(kRuntimeParameterCoreRegisters);
233
234class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
235 public:
236 InvokeRuntimeCallingConvention()
237 : CallingConvention(kRuntimeParameterCoreRegisters,
238 kRuntimeParameterCoreRegistersLength) {}
239
240 private:
241 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
242};
243
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100244Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
245 switch (type) {
246 case Primitive::kPrimBoolean:
247 case Primitive::kPrimByte:
248 case Primitive::kPrimChar:
249 case Primitive::kPrimShort:
250 case Primitive::kPrimInt:
251 case Primitive::kPrimNot: {
252 uint32_t index = gp_index_++;
253 if (index < calling_convention.GetNumberOfRegisters()) {
254 return X86CpuLocation(calling_convention.GetRegisterAt(index));
255 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100256 return Location::StackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100257 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100258 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100259
260 case Primitive::kPrimLong: {
261 uint32_t index = gp_index_;
262 gp_index_ += 2;
263 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
264 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
265 calling_convention.GetRegisterPairAt(index)));
266 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
267 return Location::QuickParameter(index);
268 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100269 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100270 }
271 }
272
273 case Primitive::kPrimDouble:
274 case Primitive::kPrimFloat:
275 LOG(FATAL) << "Unimplemented parameter type " << type;
276 break;
277
278 case Primitive::kPrimVoid:
279 LOG(FATAL) << "Unexpected parameter type " << type;
280 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100281 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100282 return Location();
283}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100284
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100285void CodeGeneratorX86::Move32(Location destination, Location source) {
286 if (source.Equals(destination)) {
287 return;
288 }
289 if (destination.IsRegister()) {
290 if (source.IsRegister()) {
291 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
292 } else {
293 DCHECK(source.IsStackSlot());
294 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
295 }
296 } else {
297 if (source.IsRegister()) {
298 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
299 } else {
300 DCHECK(source.IsStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100301 __ pushl(Address(ESP, source.GetStackIndex()));
302 __ popl(Address(ESP, destination.GetStackIndex()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100303 }
304 }
305}
306
307void CodeGeneratorX86::Move64(Location destination, Location source) {
308 if (source.Equals(destination)) {
309 return;
310 }
311 if (destination.IsRegister()) {
312 if (source.IsRegister()) {
313 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
314 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
315 } else if (source.IsQuickParameter()) {
316 uint32_t argument_index = source.GetQuickParameterIndex();
317 InvokeDexCallingConvention calling_convention;
318 __ movl(destination.AsX86().AsRegisterPairLow(),
319 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100320 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100321 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100322 } else {
323 DCHECK(source.IsDoubleStackSlot());
324 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
325 __ movl(destination.AsX86().AsRegisterPairHigh(),
326 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
327 }
328 } else if (destination.IsQuickParameter()) {
329 InvokeDexCallingConvention calling_convention;
330 uint32_t argument_index = destination.GetQuickParameterIndex();
331 if (source.IsRegister()) {
332 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100333 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100334 source.AsX86().AsRegisterPairHigh());
335 } else {
336 DCHECK(source.IsDoubleStackSlot());
337 __ movl(calling_convention.GetRegisterAt(argument_index),
338 Address(ESP, source.GetStackIndex()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100339 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100340 __ popl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100341 }
342 } else {
343 if (source.IsRegister()) {
344 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
345 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
346 source.AsX86().AsRegisterPairHigh());
347 } else if (source.IsQuickParameter()) {
348 InvokeDexCallingConvention calling_convention;
349 uint32_t argument_index = source.GetQuickParameterIndex();
350 __ movl(Address(ESP, destination.GetStackIndex()),
351 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100352 __ pushl(Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100353 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100354 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100355 } else {
356 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100357 __ pushl(Address(ESP, source.GetStackIndex()));
358 __ popl(Address(ESP, destination.GetStackIndex()));
359 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
360 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100361 }
362 }
363}
364
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100365void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
366 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100367 Immediate imm(instruction->AsIntConstant()->GetValue());
368 if (location.IsRegister()) {
369 __ movl(location.AsX86().AsCpuRegister(), imm);
370 } else {
371 __ movl(Address(ESP, location.GetStackIndex()), imm);
372 }
373 } else if (instruction->AsLongConstant() != nullptr) {
374 int64_t value = instruction->AsLongConstant()->GetValue();
375 if (location.IsRegister()) {
376 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
377 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
378 } else {
379 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
380 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
381 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100382 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100383 switch (instruction->GetType()) {
384 case Primitive::kPrimBoolean:
385 case Primitive::kPrimByte:
386 case Primitive::kPrimChar:
387 case Primitive::kPrimShort:
388 case Primitive::kPrimInt:
389 case Primitive::kPrimNot:
390 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
391 break;
392
393 case Primitive::kPrimLong:
394 Move64(location, Location::DoubleStackSlot(
395 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
396 break;
397
398 default:
399 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
400 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000401 } else {
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100402 DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100403 switch (instruction->GetType()) {
404 case Primitive::kPrimBoolean:
405 case Primitive::kPrimByte:
406 case Primitive::kPrimChar:
407 case Primitive::kPrimShort:
408 case Primitive::kPrimInt:
409 case Primitive::kPrimNot:
410 Move32(location, instruction->GetLocations()->Out());
411 break;
412
413 case Primitive::kPrimLong:
414 Move64(location, instruction->GetLocations()->Out());
415 break;
416
417 default:
418 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
419 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000420 }
421}
422
423void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000424 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000425}
426
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000427void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000428 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000429 if (GetGraph()->GetExitBlock() == successor) {
430 codegen_->GenerateFrameExit();
431 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
432 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000433 }
434}
435
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000436void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000437 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000438}
439
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000440void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000441 if (kIsDebugBuild) {
442 __ Comment("Unreachable");
443 __ int3();
444 }
445}
446
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000447void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000448 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100449 HInstruction* cond = if_instr->InputAt(0);
450 DCHECK(cond->IsCondition());
451 HCondition* condition = cond->AsCondition();
452 if (condition->NeedsMaterialization()) {
453 locations->SetInAt(0, Location::Any());
454 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000455 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000456}
457
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000458void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Dave Allison20dfc792014-06-16 20:44:29 -0700459 HInstruction* cond = if_instr->InputAt(0);
460 DCHECK(cond->IsCondition());
461 HCondition* condition = cond->AsCondition();
462 if (condition->NeedsMaterialization()) {
463 // Materialized condition, compare against 0
464 Location lhs = if_instr->GetLocations()->InAt(0);
465 if (lhs.IsRegister()) {
466 __ cmpl(lhs.AsX86().AsCpuRegister(), Immediate(0));
467 } else {
468 __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0));
469 }
470 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100471 } else {
Dave Allison20dfc792014-06-16 20:44:29 -0700472 Location lhs = condition->GetLocations()->InAt(0);
473 Location rhs = condition->GetLocations()->InAt(1);
474 // LHS is guaranteed to be in a register (see LocationsBuilderX86::VisitCondition).
475 if (rhs.IsRegister()) {
476 __ cmpl(lhs.AsX86().AsCpuRegister(), rhs.AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100477 } else if (rhs.IsConstant()) {
478 HIntConstant* instruction = rhs.GetConstant()->AsIntConstant();
479 Immediate imm(instruction->AsIntConstant()->GetValue());
480 __ cmpl(lhs.AsX86().AsCpuRegister(), imm);
Dave Allison20dfc792014-06-16 20:44:29 -0700481 } else {
482 __ cmpl(lhs.AsX86().AsCpuRegister(), Address(ESP, rhs.GetStackIndex()));
483 }
484 __ j(X86Condition(condition->GetCondition()),
485 codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100486 }
Dave Allison20dfc792014-06-16 20:44:29 -0700487 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) {
488 __ jmp(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000489 }
490}
491
492void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000493 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000494}
495
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000496void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
497 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000498}
499
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000500void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100501 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000502}
503
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000504void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100505 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000506}
507
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100508void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
509 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
510 switch (store->InputAt(1)->GetType()) {
511 case Primitive::kPrimBoolean:
512 case Primitive::kPrimByte:
513 case Primitive::kPrimChar:
514 case Primitive::kPrimShort:
515 case Primitive::kPrimInt:
516 case Primitive::kPrimNot:
517 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
518 break;
519
520 case Primitive::kPrimLong:
521 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
522 break;
523
524 default:
525 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
526 }
527 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000528}
529
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000530void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000531}
532
Dave Allison20dfc792014-06-16 20:44:29 -0700533void LocationsBuilderX86::VisitCondition(HCondition* comp) {
534 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100535 locations->SetInAt(0, Location::RequiresRegister());
536 locations->SetInAt(1, Location::Any());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100537 if (comp->NeedsMaterialization()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100538 locations->SetOut(Location::RequiresRegister());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100539 }
Dave Allison20dfc792014-06-16 20:44:29 -0700540 comp->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000541}
542
Dave Allison20dfc792014-06-16 20:44:29 -0700543void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) {
544 if (comp->NeedsMaterialization()) {
545 LocationSummary* locations = comp->GetLocations();
546 if (locations->InAt(1).IsRegister()) {
547 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
548 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100549 } else if (locations->InAt(1).IsConstant()) {
550 HConstant* instruction = locations->InAt(1).GetConstant();
551 Immediate imm(instruction->AsIntConstant()->GetValue());
552 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
Dave Allison20dfc792014-06-16 20:44:29 -0700553 } else {
554 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
555 Address(ESP, locations->InAt(1).GetStackIndex()));
556 }
557 __ setb(X86Condition(comp->GetCondition()), locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100558 }
Dave Allison20dfc792014-06-16 20:44:29 -0700559}
560
561void LocationsBuilderX86::VisitEqual(HEqual* comp) {
562 VisitCondition(comp);
563}
564
565void InstructionCodeGeneratorX86::VisitEqual(HEqual* comp) {
566 VisitCondition(comp);
567}
568
569void LocationsBuilderX86::VisitNotEqual(HNotEqual* comp) {
570 VisitCondition(comp);
571}
572
573void InstructionCodeGeneratorX86::VisitNotEqual(HNotEqual* comp) {
574 VisitCondition(comp);
575}
576
577void LocationsBuilderX86::VisitLessThan(HLessThan* comp) {
578 VisitCondition(comp);
579}
580
581void InstructionCodeGeneratorX86::VisitLessThan(HLessThan* comp) {
582 VisitCondition(comp);
583}
584
585void LocationsBuilderX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
586 VisitCondition(comp);
587}
588
589void InstructionCodeGeneratorX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
590 VisitCondition(comp);
591}
592
593void LocationsBuilderX86::VisitGreaterThan(HGreaterThan* comp) {
594 VisitCondition(comp);
595}
596
597void InstructionCodeGeneratorX86::VisitGreaterThan(HGreaterThan* comp) {
598 VisitCondition(comp);
599}
600
601void LocationsBuilderX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
602 VisitCondition(comp);
603}
604
605void InstructionCodeGeneratorX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
606 VisitCondition(comp);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000607}
608
609void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100610 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100611 locations->SetOut(Location::ConstantLocation(constant));
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100612 constant->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000613}
614
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000615void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000616}
617
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100618void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100619 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100620 locations->SetOut(Location::ConstantLocation(constant));
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100621 constant->SetLocations(locations);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100622}
623
624void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
625 // Will be generated at use site.
626}
627
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000628void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000629 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000630}
631
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000632void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
633 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000634 __ ret();
635}
636
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000637void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000638 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100639 switch (ret->InputAt(0)->GetType()) {
640 case Primitive::kPrimBoolean:
641 case Primitive::kPrimByte:
642 case Primitive::kPrimChar:
643 case Primitive::kPrimShort:
644 case Primitive::kPrimInt:
645 case Primitive::kPrimNot:
646 locations->SetInAt(0, X86CpuLocation(EAX));
647 break;
648
649 case Primitive::kPrimLong:
650 locations->SetInAt(
651 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
652 break;
653
654 default:
655 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
656 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000657 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000658}
659
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000660void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100661 if (kIsDebugBuild) {
662 switch (ret->InputAt(0)->GetType()) {
663 case Primitive::kPrimBoolean:
664 case Primitive::kPrimByte:
665 case Primitive::kPrimChar:
666 case Primitive::kPrimShort:
667 case Primitive::kPrimInt:
668 case Primitive::kPrimNot:
669 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
670 break;
671
672 case Primitive::kPrimLong:
673 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
674 break;
675
676 default:
677 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
678 }
679 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000680 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000681 __ ret();
682}
683
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000684void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
685 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100686 locations->AddTemp(X86CpuLocation(EAX));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100687
688 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100689 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100690 HInstruction* input = invoke->InputAt(i);
691 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
692 }
693
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100694 switch (invoke->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 locations->SetOut(X86CpuLocation(EAX));
702 break;
703
704 case Primitive::kPrimLong:
705 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
706 break;
707
708 case Primitive::kPrimVoid:
709 break;
710
711 case Primitive::kPrimDouble:
712 case Primitive::kPrimFloat:
713 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
714 break;
715 }
716
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000717 invoke->SetLocations(locations);
718}
719
720void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100721 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffrayf61b5372014-06-25 14:35:34 +0100722 uint32_t heap_reference_size = sizeof(mirror::HeapReference<mirror::Object>);
723 size_t index_in_cache = mirror::Array::DataOffset(heap_reference_size).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100724 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000725
726 // TODO: Implement all kinds of calls:
727 // 1) boot -> boot
728 // 2) app -> boot
729 // 3) app -> app
730 //
731 // Currently we implement the app -> app logic, which looks up in the resolve cache.
732
733 // temp = method;
734 LoadCurrentMethod(temp);
735 // temp = temp->dex_cache_resolved_methods_;
736 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
737 // temp = temp[index_in_cache]
738 __ movl(temp, Address(temp, index_in_cache));
739 // (temp + offset_of_quick_compiled_code)()
740 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
741
742 codegen_->RecordPcInfo(invoke->GetDexPc());
743}
744
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000745void LocationsBuilderX86::VisitAdd(HAdd* add) {
746 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
747 switch (add->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100748 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100749 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100750 locations->SetInAt(0, Location::RequiresRegister());
751 locations->SetInAt(1, Location::Any());
752 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100753 break;
754 }
755
756 case Primitive::kPrimBoolean:
757 case Primitive::kPrimByte:
758 case Primitive::kPrimChar:
759 case Primitive::kPrimShort:
760 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
761 break;
762
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000763 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100764 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000765 }
766 add->SetLocations(locations);
767}
768
769void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
770 LocationSummary* locations = add->GetLocations();
771 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100772 case Primitive::kPrimInt: {
773 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
774 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100775 if (locations->InAt(1).IsRegister()) {
776 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
777 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100778 } else if (locations->InAt(1).IsConstant()) {
779 HConstant* instruction = locations->InAt(1).GetConstant();
780 Immediate imm(instruction->AsIntConstant()->GetValue());
781 __ addl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100782 } else {
783 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
784 Address(ESP, locations->InAt(1).GetStackIndex()));
785 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000786 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100787 }
788
789 case Primitive::kPrimLong: {
790 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
791 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100792 if (locations->InAt(1).IsRegister()) {
793 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
794 locations->InAt(1).AsX86().AsRegisterPairLow());
795 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
796 locations->InAt(1).AsX86().AsRegisterPairHigh());
797 } else {
798 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
799 Address(ESP, locations->InAt(1).GetStackIndex()));
800 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
801 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
802 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100803 break;
804 }
805
806 case Primitive::kPrimBoolean:
807 case Primitive::kPrimByte:
808 case Primitive::kPrimChar:
809 case Primitive::kPrimShort:
810 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
811 break;
812
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000813 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100814 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000815 }
816}
817
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100818void LocationsBuilderX86::VisitSub(HSub* sub) {
819 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
820 switch (sub->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100821 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100822 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100823 locations->SetInAt(0, Location::RequiresRegister());
824 locations->SetInAt(1, Location::Any());
825 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100826 break;
827 }
828
829 case Primitive::kPrimBoolean:
830 case Primitive::kPrimByte:
831 case Primitive::kPrimChar:
832 case Primitive::kPrimShort:
833 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
834 break;
835
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100836 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100837 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100838 }
839 sub->SetLocations(locations);
840}
841
842void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
843 LocationSummary* locations = sub->GetLocations();
844 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100845 case Primitive::kPrimInt: {
846 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
847 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100848 if (locations->InAt(1).IsRegister()) {
849 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
850 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100851 } else if (locations->InAt(1).IsConstant()) {
852 HConstant* instruction = locations->InAt(1).GetConstant();
853 Immediate imm(instruction->AsIntConstant()->GetValue());
854 __ subl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100855 } else {
856 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
857 Address(ESP, locations->InAt(1).GetStackIndex()));
858 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100859 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100860 }
861
862 case Primitive::kPrimLong: {
863 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
864 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100865 if (locations->InAt(1).IsRegister()) {
866 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
867 locations->InAt(1).AsX86().AsRegisterPairLow());
868 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
869 locations->InAt(1).AsX86().AsRegisterPairHigh());
870 } else {
871 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
872 Address(ESP, locations->InAt(1).GetStackIndex()));
873 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
874 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
875 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100876 break;
877 }
878
879 case Primitive::kPrimBoolean:
880 case Primitive::kPrimByte:
881 case Primitive::kPrimChar:
882 case Primitive::kPrimShort:
883 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
884 break;
885
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100886 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100887 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100888 }
889}
890
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100891void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
892 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100893 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100894 InvokeRuntimeCallingConvention calling_convention;
895 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0)));
896 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100897 instruction->SetLocations(locations);
898}
899
900void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
901 InvokeRuntimeCallingConvention calling_convention;
902 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100903 __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100904
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100905 __ fs()->call(
906 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100907
908 codegen_->RecordPcInfo(instruction->GetDexPc());
909}
910
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100911void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
912 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100913 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
914 if (location.IsStackSlot()) {
915 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
916 } else if (location.IsDoubleStackSlot()) {
917 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100918 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100919 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100920 instruction->SetLocations(locations);
921}
922
923void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100924}
925
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100926void LocationsBuilderX86::VisitNot(HNot* instruction) {
927 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100928 locations->SetInAt(0, Location::RequiresRegister());
929 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100930 instruction->SetLocations(locations);
931}
932
933void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
934 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100935 Location out = locations->Out();
936 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), out.AsX86().AsCpuRegister());
937 __ xorl(out.AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100938}
939
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100940void LocationsBuilderX86::VisitCompare(HCompare* compare) {
941 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
942 locations->SetInAt(0, Location::RequiresRegister());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100943 locations->SetInAt(1, Location::Any());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100944 locations->SetOut(Location::RequiresRegister());
945 compare->SetLocations(locations);
946}
947
948void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) {
949 Label greater, done;
950 LocationSummary* locations = compare->GetLocations();
951 switch (compare->InputAt(0)->GetType()) {
952 case Primitive::kPrimLong: {
953 Label less, greater, done;
954 Register output = locations->Out().AsX86().AsCpuRegister();
955 X86ManagedRegister left = locations->InAt(0).AsX86();
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100956 Location right = locations->InAt(1);
957 if (right.IsRegister()) {
958 __ cmpl(left.AsRegisterPairHigh(), right.AsX86().AsRegisterPairHigh());
959 } else {
960 DCHECK(right.IsDoubleStackSlot());
961 __ cmpl(left.AsRegisterPairHigh(), Address(ESP, right.GetHighStackIndex(kX86WordSize)));
962 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100963 __ j(kLess, &less); // Signed compare.
964 __ j(kGreater, &greater); // Signed compare.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100965 if (right.IsRegister()) {
966 __ cmpl(left.AsRegisterPairLow(), right.AsX86().AsRegisterPairLow());
967 } else {
968 DCHECK(right.IsDoubleStackSlot());
969 __ cmpl(left.AsRegisterPairLow(), Address(ESP, right.GetStackIndex()));
970 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100971 __ movl(output, Immediate(0));
972 __ j(kEqual, &done);
973 __ j(kBelow, &less); // Unsigned compare.
974
975 __ Bind(&greater);
976 __ movl(output, Immediate(1));
977 __ jmp(&done);
978
979 __ Bind(&less);
980 __ movl(output, Immediate(-1));
981
982 __ Bind(&done);
983 break;
984 }
985 default:
986 LOG(FATAL) << "Unimplemented compare type " << compare->InputAt(0)->GetType();
987 }
988}
989
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100990void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100991 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
992 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
993 locations->SetInAt(i, Location::Any());
994 }
995 locations->SetOut(Location::Any());
996 instruction->SetLocations(locations);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100997}
998
999void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001000 LOG(FATAL) << "Unreachable";
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001001}
1002
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001003void LocationsBuilderX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
1004 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1005 locations->SetInAt(0, Location::RequiresRegister());
1006 Primitive::Type field_type = instruction->InputAt(1)->GetType();
1007 if (field_type == Primitive::kPrimBoolean || field_type == Primitive::kPrimByte) {
1008 // Ensure the value is in a byte register.
1009 locations->SetInAt(1, X86CpuLocation(EAX));
1010 } else {
1011 locations->SetInAt(1, Location::RequiresRegister());
1012 }
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001013 // Temporary registers for the write barrier.
1014 if (instruction->InputAt(1)->GetType() == Primitive::kPrimNot) {
1015 locations->AddTemp(Location::RequiresRegister());
1016 // Ensure the card is in a byte register.
1017 locations->AddTemp(X86CpuLocation(ECX));
1018 }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001019 instruction->SetLocations(locations);
1020}
1021
1022void InstructionCodeGeneratorX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
1023 LocationSummary* locations = instruction->GetLocations();
1024 Register obj = locations->InAt(0).AsX86().AsCpuRegister();
1025 uint32_t offset = instruction->GetFieldOffset().Uint32Value();
1026 Primitive::Type field_type = instruction->InputAt(1)->GetType();
1027
1028 switch (field_type) {
1029 case Primitive::kPrimBoolean:
1030 case Primitive::kPrimByte: {
1031 ByteRegister value = locations->InAt(1).AsX86().AsByteRegister();
1032 __ movb(Address(obj, offset), value);
1033 break;
1034 }
1035
1036 case Primitive::kPrimShort:
1037 case Primitive::kPrimChar: {
1038 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1039 __ movw(Address(obj, offset), value);
1040 break;
1041 }
1042
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001043 case Primitive::kPrimInt: {
1044 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1045 __ movl(Address(obj, offset), value);
1046 break;
1047 }
1048
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001049 case Primitive::kPrimNot: {
1050 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1051 __ movl(Address(obj, offset), value);
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001052 Label is_null;
1053 Register temp = locations->GetTemp(0).AsX86().AsCpuRegister();
1054 Register card = locations->GetTemp(1).AsX86().AsCpuRegister();
1055 __ testl(value, value);
1056 __ j(kEqual, &is_null);
1057 __ fs()->movl(card, Address::Absolute(Thread::CardTableOffset<kX86WordSize>().Int32Value()));
1058 __ movl(temp, obj);
1059 __ shrl(temp, Immediate(gc::accounting::CardTable::kCardShift));
1060 __ movb(Address(temp, card, TIMES_1, 0), locations->GetTemp(1).AsX86().AsByteRegister());
1061 __ Bind(&is_null);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001062 break;
1063 }
1064
1065 case Primitive::kPrimLong: {
1066 X86ManagedRegister value = locations->InAt(1).AsX86();
1067 __ movl(Address(obj, offset), value.AsRegisterPairLow());
1068 __ movl(Address(obj, kX86WordSize + offset), value.AsRegisterPairHigh());
1069 break;
1070 }
1071
1072 case Primitive::kPrimFloat:
1073 case Primitive::kPrimDouble:
1074 LOG(FATAL) << "Unimplemented register type " << field_type;
1075
1076 case Primitive::kPrimVoid:
1077 LOG(FATAL) << "Unreachable type " << field_type;
1078 }
1079}
1080
1081void LocationsBuilderX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
1082 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1083 locations->SetInAt(0, Location::RequiresRegister());
1084 locations->SetOut(Location::RequiresRegister());
1085 instruction->SetLocations(locations);
1086}
1087
1088void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
1089 LocationSummary* locations = instruction->GetLocations();
1090 Register obj = locations->InAt(0).AsX86().AsCpuRegister();
1091 uint32_t offset = instruction->GetFieldOffset().Uint32Value();
1092
1093 switch (instruction->GetType()) {
1094 case Primitive::kPrimBoolean: {
1095 Register out = locations->Out().AsX86().AsCpuRegister();
1096 __ movzxb(out, Address(obj, offset));
1097 break;
1098 }
1099
1100 case Primitive::kPrimByte: {
1101 Register out = locations->Out().AsX86().AsCpuRegister();
1102 __ movsxb(out, Address(obj, offset));
1103 break;
1104 }
1105
1106 case Primitive::kPrimShort: {
1107 Register out = locations->Out().AsX86().AsCpuRegister();
1108 __ movsxw(out, Address(obj, offset));
1109 break;
1110 }
1111
1112 case Primitive::kPrimChar: {
1113 Register out = locations->Out().AsX86().AsCpuRegister();
1114 __ movzxw(out, Address(obj, offset));
1115 break;
1116 }
1117
1118 case Primitive::kPrimInt:
1119 case Primitive::kPrimNot: {
1120 Register out = locations->Out().AsX86().AsCpuRegister();
1121 __ movl(out, Address(obj, offset));
1122 break;
1123 }
1124
1125 case Primitive::kPrimLong: {
1126 // TODO: support volatile.
1127 X86ManagedRegister out = locations->Out().AsX86();
1128 __ movl(out.AsRegisterPairLow(), Address(obj, offset));
1129 __ movl(out.AsRegisterPairHigh(), Address(obj, kX86WordSize + offset));
1130 break;
1131 }
1132
1133 case Primitive::kPrimFloat:
1134 case Primitive::kPrimDouble:
1135 LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
1136
1137 case Primitive::kPrimVoid:
1138 LOG(FATAL) << "Unreachable type " << instruction->GetType();
1139 }
1140}
1141
1142void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
1143 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1144 locations->SetInAt(0, Location::Any());
1145 // TODO: Have a normalization phase that makes this instruction never used.
1146 locations->SetOut(Location::SameAsFirstInput());
1147 instruction->SetLocations(locations);
1148}
1149
1150void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
1151 SlowPathCode* slow_path =
1152 new (GetGraph()->GetArena()) NullCheckSlowPathX86(instruction->GetDexPc());
1153 codegen_->AddSlowPath(slow_path);
1154
1155 LocationSummary* locations = instruction->GetLocations();
1156 Location obj = locations->InAt(0);
1157 DCHECK(obj.Equals(locations->Out()));
1158
1159 if (obj.IsRegister()) {
1160 __ cmpl(obj.AsX86().AsCpuRegister(), Immediate(0));
1161 } else {
1162 DCHECK(locations->InAt(0).IsStackSlot());
1163 __ cmpl(Address(ESP, obj.GetStackIndex()), Immediate(0));
1164 }
1165 __ j(kEqual, slow_path->GetEntryLabel());
1166}
1167
1168void LocationsBuilderX86::VisitTemporary(HTemporary* temp) {
1169 temp->SetLocations(nullptr);
1170}
1171
1172void InstructionCodeGeneratorX86::VisitTemporary(HTemporary* temp) {
1173 // Nothing to do, this is driven by the code generator.
1174}
1175
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001176void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001177 LOG(FATAL) << "Unreachable";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001178}
1179
1180void InstructionCodeGeneratorX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001181 codegen_->GetMoveResolver()->EmitNativeCode(instruction);
1182}
1183
1184X86Assembler* ParallelMoveResolverX86::GetAssembler() const {
1185 return codegen_->GetAssembler();
1186}
1187
1188void ParallelMoveResolverX86::MoveMemoryToMemory(int dst, int src) {
1189 ScratchRegisterScope ensure_scratch(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001190 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001191 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
1192 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, src + stack_offset));
1193 __ movl(Address(ESP, dst + stack_offset), static_cast<Register>(ensure_scratch.GetRegister()));
1194}
1195
1196void ParallelMoveResolverX86::EmitMove(size_t index) {
1197 MoveOperands* move = moves_.Get(index);
1198 Location source = move->GetSource();
1199 Location destination = move->GetDestination();
1200
1201 if (source.IsRegister()) {
1202 if (destination.IsRegister()) {
1203 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
1204 } else {
1205 DCHECK(destination.IsStackSlot());
1206 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
1207 }
1208 } else if (source.IsStackSlot()) {
1209 if (destination.IsRegister()) {
1210 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
1211 } else {
1212 DCHECK(destination.IsStackSlot());
1213 MoveMemoryToMemory(destination.GetStackIndex(),
1214 source.GetStackIndex());
1215 }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001216 } else if (source.IsConstant()) {
1217 HIntConstant* instruction = source.GetConstant()->AsIntConstant();
1218 Immediate imm(instruction->AsIntConstant()->GetValue());
1219 if (destination.IsRegister()) {
1220 __ movl(destination.AsX86().AsCpuRegister(), imm);
1221 } else {
1222 __ movl(Address(ESP, destination.GetStackIndex()), imm);
1223 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001224 } else {
1225 LOG(FATAL) << "Unimplemented";
1226 }
1227}
1228
1229void ParallelMoveResolverX86::Exchange(Register reg, int mem) {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001230 Register suggested_scratch = reg == EAX ? EBX : EAX;
1231 ScratchRegisterScope ensure_scratch(
1232 this, reg, suggested_scratch, codegen_->GetNumberOfCoreRegisters());
1233
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001234 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
1235 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, mem + stack_offset));
1236 __ movl(Address(ESP, mem + stack_offset), reg);
1237 __ movl(reg, static_cast<Register>(ensure_scratch.GetRegister()));
1238}
1239
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001240void ParallelMoveResolverX86::Exchange(int mem1, int mem2) {
1241 ScratchRegisterScope ensure_scratch1(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001242 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
1243
1244 Register suggested_scratch = ensure_scratch1.GetRegister() == EAX ? EBX : EAX;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001245 ScratchRegisterScope ensure_scratch2(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001246 this, ensure_scratch1.GetRegister(), suggested_scratch, codegen_->GetNumberOfCoreRegisters());
1247
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001248 int stack_offset = ensure_scratch1.IsSpilled() ? kX86WordSize : 0;
1249 stack_offset += ensure_scratch2.IsSpilled() ? kX86WordSize : 0;
1250 __ movl(static_cast<Register>(ensure_scratch1.GetRegister()), Address(ESP, mem1 + stack_offset));
1251 __ movl(static_cast<Register>(ensure_scratch2.GetRegister()), Address(ESP, mem2 + stack_offset));
1252 __ movl(Address(ESP, mem2 + stack_offset), static_cast<Register>(ensure_scratch1.GetRegister()));
1253 __ movl(Address(ESP, mem1 + stack_offset), static_cast<Register>(ensure_scratch2.GetRegister()));
1254}
1255
1256void ParallelMoveResolverX86::EmitSwap(size_t index) {
1257 MoveOperands* move = moves_.Get(index);
1258 Location source = move->GetSource();
1259 Location destination = move->GetDestination();
1260
1261 if (source.IsRegister() && destination.IsRegister()) {
1262 __ xchgl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
1263 } else if (source.IsRegister() && destination.IsStackSlot()) {
1264 Exchange(source.AsX86().AsCpuRegister(), destination.GetStackIndex());
1265 } else if (source.IsStackSlot() && destination.IsRegister()) {
1266 Exchange(destination.AsX86().AsCpuRegister(), source.GetStackIndex());
1267 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
1268 Exchange(destination.GetStackIndex(), source.GetStackIndex());
1269 } else {
1270 LOG(FATAL) << "Unimplemented";
1271 }
1272}
1273
1274void ParallelMoveResolverX86::SpillScratch(int reg) {
1275 __ pushl(static_cast<Register>(reg));
1276}
1277
1278void ParallelMoveResolverX86::RestoreScratch(int reg) {
1279 __ popl(static_cast<Register>(reg));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001280}
1281
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001282} // namespace x86
1283} // namespace art