blob: 72c697ffee4b18b6bcade4d802281a5fd07180dc [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"
18#include "utils/assembler.h"
19#include "utils/x86/assembler_x86.h"
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010020#include "utils/x86/managed_register_x86.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000021
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070022#include "entrypoints/quick/quick_entrypoints.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000023#include "mirror/array.h"
24#include "mirror/art_method.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070025#include "thread.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000026
Nicolas Geoffray787c3072014-03-17 10:20:19 +000027#define __ reinterpret_cast<X86Assembler*>(GetAssembler())->
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000028
29namespace 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 Geoffray4a34a422014-04-03 10:38:37 +010037static constexpr int kNumberOfPushedRegistersAtEntry = 1;
38static constexpr int kCurrentMethodStackOffset = 0;
39
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010040void CodeGeneratorX86::DumpCoreRegister(std::ostream& stream, int reg) const {
41 stream << X86ManagedRegister::FromCpuRegister(Register(reg));
42}
43
44void CodeGeneratorX86::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
45 stream << X86ManagedRegister::FromXmmRegister(XmmRegister(reg));
46}
47
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010048CodeGeneratorX86::CodeGeneratorX86(HGraph* graph)
49 : CodeGenerator(graph, kNumberOfRegIds),
50 location_builder_(graph, this),
51 instruction_visitor_(graph, this) {}
52
53static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
54 return blocked_registers + kNumberOfAllocIds;
55}
56
57ManagedRegister CodeGeneratorX86::AllocateFreeRegister(Primitive::Type type,
58 bool* blocked_registers) const {
59 switch (type) {
60 case Primitive::kPrimLong: {
61 size_t reg = AllocateFreeRegisterInternal(
62 GetBlockedRegisterPairs(blocked_registers), kNumberOfRegisterPairs);
63 X86ManagedRegister pair =
64 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg));
65 blocked_registers[pair.AsRegisterPairLow()] = true;
66 blocked_registers[pair.AsRegisterPairHigh()] = true;
67 return pair;
68 }
69
70 case Primitive::kPrimByte:
71 case Primitive::kPrimBoolean:
72 case Primitive::kPrimChar:
73 case Primitive::kPrimShort:
74 case Primitive::kPrimInt:
75 case Primitive::kPrimNot: {
76 size_t reg = AllocateFreeRegisterInternal(blocked_registers, kNumberOfCpuRegisters);
77 return X86ManagedRegister::FromCpuRegister(static_cast<Register>(reg));
78 }
79
80 case Primitive::kPrimFloat:
81 case Primitive::kPrimDouble:
82 LOG(FATAL) << "Unimplemented register type " << type;
83
84 case Primitive::kPrimVoid:
85 LOG(FATAL) << "Unreachable type " << type;
86 }
87
88 return ManagedRegister::NoRegister();
89}
90
91void CodeGeneratorX86::SetupBlockedRegisters(bool* blocked_registers) const {
92 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
93
94 // Don't allocate the dalvik style register pair passing.
95 blocked_register_pairs[ECX_EDX] = true;
96
97 // Stack register is always reserved.
98 blocked_registers[ESP] = true;
99
100 // TODO: We currently don't use Quick's callee saved registers.
101 blocked_registers[EBP] = true;
102 blocked_registers[ESI] = true;
103 blocked_registers[EDI] = true;
104 blocked_register_pairs[EAX_EDI] = true;
105 blocked_register_pairs[EDX_EDI] = true;
106 blocked_register_pairs[ECX_EDI] = true;
107 blocked_register_pairs[EBX_EDI] = true;
108}
109
110size_t CodeGeneratorX86::GetNumberOfRegisters() const {
111 return kNumberOfRegIds;
112}
113
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100114static Location X86CpuLocation(Register reg) {
115 return Location::RegisterLocation(X86ManagedRegister::FromCpuRegister(reg));
116}
117
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100118InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen)
119 : HGraphVisitor(graph),
120 assembler_(codegen->GetAssembler()),
121 codegen_(codegen) {}
122
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000123void CodeGeneratorX86::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000124 // Create a fake register to mimic Quick.
125 static const int kFakeReturnRegister = 8;
126 core_spill_mask_ |= (1 << kFakeReturnRegister);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000127
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100128 SetFrameSize(RoundUp(
129 (GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs()) * kVRegSize
130 + kVRegSize // filler
131 + kX86WordSize // Art method
132 + kNumberOfPushedRegistersAtEntry * kX86WordSize,
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100133 kStackAlignment));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100134
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100135 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100136 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100137 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000138}
139
140void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100141 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000142}
143
144void CodeGeneratorX86::Bind(Label* label) {
145 __ Bind(label);
146}
147
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000148void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100149 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000150}
151
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100152int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100153 uint16_t reg_number = local->GetRegNumber();
154 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
155 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
156 if (reg_number >= number_of_vregs - number_of_in_vregs) {
157 // Local is a parameter of the method. It is stored in the caller's frame.
158 return GetFrameSize() + kX86WordSize // ART method
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100159 + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100160 } else {
161 // Local is a temporary in this method. It is stored in this method's frame.
162 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100163 - kVRegSize // filler.
164 - (number_of_vregs * kVRegSize)
165 + (reg_number * kVRegSize);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100166 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100167}
168
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100169
170Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
171 switch (load->GetType()) {
172 case Primitive::kPrimLong:
173 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
174 break;
175
176 case Primitive::kPrimInt:
177 case Primitive::kPrimNot:
178 return Location::StackSlot(GetStackSlot(load->GetLocal()));
179
180 case Primitive::kPrimFloat:
181 case Primitive::kPrimDouble:
182 LOG(FATAL) << "Unimplemented type " << load->GetType();
183
184 case Primitive::kPrimBoolean:
185 case Primitive::kPrimByte:
186 case Primitive::kPrimChar:
187 case Primitive::kPrimShort:
188 case Primitive::kPrimVoid:
189 LOG(FATAL) << "Unexpected type " << load->GetType();
190 }
191
192 LOG(FATAL) << "Unreachable";
193 return Location();
194}
195
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100196static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
197static constexpr size_t kRuntimeParameterCoreRegistersLength =
198 arraysize(kRuntimeParameterCoreRegisters);
199
200class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
201 public:
202 InvokeRuntimeCallingConvention()
203 : CallingConvention(kRuntimeParameterCoreRegisters,
204 kRuntimeParameterCoreRegistersLength) {}
205
206 private:
207 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
208};
209
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100210Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
211 switch (type) {
212 case Primitive::kPrimBoolean:
213 case Primitive::kPrimByte:
214 case Primitive::kPrimChar:
215 case Primitive::kPrimShort:
216 case Primitive::kPrimInt:
217 case Primitive::kPrimNot: {
218 uint32_t index = gp_index_++;
219 if (index < calling_convention.GetNumberOfRegisters()) {
220 return X86CpuLocation(calling_convention.GetRegisterAt(index));
221 } else {
222 return Location::StackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100223 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100224 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100225
226 case Primitive::kPrimLong: {
227 uint32_t index = gp_index_;
228 gp_index_ += 2;
229 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
230 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
231 calling_convention.GetRegisterPairAt(index)));
232 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
233 return Location::QuickParameter(index);
234 } else {
235 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize));
236 }
237 }
238
239 case Primitive::kPrimDouble:
240 case Primitive::kPrimFloat:
241 LOG(FATAL) << "Unimplemented parameter type " << type;
242 break;
243
244 case Primitive::kPrimVoid:
245 LOG(FATAL) << "Unexpected parameter type " << type;
246 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100247 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100248 return Location();
249}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100250
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100251void CodeGeneratorX86::Move32(Location destination, Location source) {
252 if (source.Equals(destination)) {
253 return;
254 }
255 if (destination.IsRegister()) {
256 if (source.IsRegister()) {
257 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
258 } else {
259 DCHECK(source.IsStackSlot());
260 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
261 }
262 } else {
263 if (source.IsRegister()) {
264 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
265 } else {
266 DCHECK(source.IsStackSlot());
267 __ movl(EAX, Address(ESP, source.GetStackIndex()));
268 __ movl(Address(ESP, destination.GetStackIndex()), EAX);
269 }
270 }
271}
272
273void CodeGeneratorX86::Move64(Location destination, Location source) {
274 if (source.Equals(destination)) {
275 return;
276 }
277 if (destination.IsRegister()) {
278 if (source.IsRegister()) {
279 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
280 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
281 } else if (source.IsQuickParameter()) {
282 uint32_t argument_index = source.GetQuickParameterIndex();
283 InvokeDexCallingConvention calling_convention;
284 __ movl(destination.AsX86().AsRegisterPairLow(),
285 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100286 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
287 calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100288 } else {
289 DCHECK(source.IsDoubleStackSlot());
290 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
291 __ movl(destination.AsX86().AsRegisterPairHigh(),
292 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
293 }
294 } else if (destination.IsQuickParameter()) {
295 InvokeDexCallingConvention calling_convention;
296 uint32_t argument_index = destination.GetQuickParameterIndex();
297 if (source.IsRegister()) {
298 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100299 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100300 source.AsX86().AsRegisterPairHigh());
301 } else {
302 DCHECK(source.IsDoubleStackSlot());
303 __ movl(calling_convention.GetRegisterAt(argument_index),
304 Address(ESP, source.GetStackIndex()));
305 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100306 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)), EAX);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100307 }
308 } else {
309 if (source.IsRegister()) {
310 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
311 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
312 source.AsX86().AsRegisterPairHigh());
313 } else if (source.IsQuickParameter()) {
314 InvokeDexCallingConvention calling_convention;
315 uint32_t argument_index = source.GetQuickParameterIndex();
316 __ movl(Address(ESP, destination.GetStackIndex()),
317 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100318 __ movl(EAX, Address(ESP,
319 calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100320 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
321 } else {
322 DCHECK(source.IsDoubleStackSlot());
323 __ movl(EAX, Address(ESP, source.GetStackIndex()));
324 __ movl(Address(ESP, destination.GetStackIndex()), EAX);
325 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
326 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
327 }
328 }
329}
330
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100331void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
332 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100333 Immediate imm(instruction->AsIntConstant()->GetValue());
334 if (location.IsRegister()) {
335 __ movl(location.AsX86().AsCpuRegister(), imm);
336 } else {
337 __ movl(Address(ESP, location.GetStackIndex()), imm);
338 }
339 } else if (instruction->AsLongConstant() != nullptr) {
340 int64_t value = instruction->AsLongConstant()->GetValue();
341 if (location.IsRegister()) {
342 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
343 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
344 } else {
345 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
346 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
347 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100348 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100349 switch (instruction->GetType()) {
350 case Primitive::kPrimBoolean:
351 case Primitive::kPrimByte:
352 case Primitive::kPrimChar:
353 case Primitive::kPrimShort:
354 case Primitive::kPrimInt:
355 case Primitive::kPrimNot:
356 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
357 break;
358
359 case Primitive::kPrimLong:
360 Move64(location, Location::DoubleStackSlot(
361 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
362 break;
363
364 default:
365 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
366 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000367 } else {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100368 // This can currently only happen when the instruction that requests the move
369 // is the next to be compiled.
370 DCHECK_EQ(instruction->GetNext(), move_for);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100371 switch (instruction->GetType()) {
372 case Primitive::kPrimBoolean:
373 case Primitive::kPrimByte:
374 case Primitive::kPrimChar:
375 case Primitive::kPrimShort:
376 case Primitive::kPrimInt:
377 case Primitive::kPrimNot:
378 Move32(location, instruction->GetLocations()->Out());
379 break;
380
381 case Primitive::kPrimLong:
382 Move64(location, instruction->GetLocations()->Out());
383 break;
384
385 default:
386 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
387 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000388 }
389}
390
391void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000392 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000393}
394
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000395void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000396 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000397 if (GetGraph()->GetExitBlock() == successor) {
398 codegen_->GenerateFrameExit();
399 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
400 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000401 }
402}
403
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000404void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000405 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000406}
407
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000408void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000409 if (kIsDebugBuild) {
410 __ Comment("Unreachable");
411 __ int3();
412 }
413}
414
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000415void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000416 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100417 locations->SetInAt(0, Location::Any());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000418 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000419}
420
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000421void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000422 // TODO: Generate the input as a condition, instead of materializing in a register.
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100423 Location location = if_instr->GetLocations()->InAt(0);
424 if (location.IsRegister()) {
425 __ cmpl(location.AsX86().AsCpuRegister(), Immediate(0));
426 } else {
427 __ cmpl(Address(ESP, location.GetStackIndex()), Immediate(0));
428 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000429 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
430 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) {
431 __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000432 }
433}
434
435void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000436 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000437}
438
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000439void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
440 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000441}
442
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000443void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100444 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000445}
446
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000447void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100448 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000449}
450
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100451void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
452 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
453 switch (store->InputAt(1)->GetType()) {
454 case Primitive::kPrimBoolean:
455 case Primitive::kPrimByte:
456 case Primitive::kPrimChar:
457 case Primitive::kPrimShort:
458 case Primitive::kPrimInt:
459 case Primitive::kPrimNot:
460 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
461 break;
462
463 case Primitive::kPrimLong:
464 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
465 break;
466
467 default:
468 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
469 }
470 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000471}
472
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000473void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000474}
475
476void LocationsBuilderX86::VisitEqual(HEqual* equal) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000477 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100478 locations->SetInAt(0, Location::RequiresRegister());
479 locations->SetInAt(1, Location::Any());
480 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000481 equal->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000482}
483
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000484void InstructionCodeGeneratorX86::VisitEqual(HEqual* equal) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100485 LocationSummary* locations = equal->GetLocations();
486 if (locations->InAt(1).IsRegister()) {
487 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
488 locations->InAt(1).AsX86().AsCpuRegister());
489 } else {
490 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
491 Address(ESP, locations->InAt(1).GetStackIndex()));
492 }
493 __ setb(kEqual, locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000494}
495
496void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100497 // TODO: Support constant locations.
498 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
499 locations->SetOut(Location::RequiresRegister());
500 constant->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000501}
502
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000503void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000504 // Will be generated at use site.
505}
506
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100507void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100508 // TODO: Support constant locations.
509 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
510 locations->SetOut(Location::RequiresRegister());
511 constant->SetLocations(locations);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100512}
513
514void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
515 // Will be generated at use site.
516}
517
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000518void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000519 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000520}
521
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000522void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
523 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000524 __ ret();
525}
526
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000527void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000528 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100529 switch (ret->InputAt(0)->GetType()) {
530 case Primitive::kPrimBoolean:
531 case Primitive::kPrimByte:
532 case Primitive::kPrimChar:
533 case Primitive::kPrimShort:
534 case Primitive::kPrimInt:
535 case Primitive::kPrimNot:
536 locations->SetInAt(0, X86CpuLocation(EAX));
537 break;
538
539 case Primitive::kPrimLong:
540 locations->SetInAt(
541 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
542 break;
543
544 default:
545 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
546 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000547 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000548}
549
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000550void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100551 if (kIsDebugBuild) {
552 switch (ret->InputAt(0)->GetType()) {
553 case Primitive::kPrimBoolean:
554 case Primitive::kPrimByte:
555 case Primitive::kPrimChar:
556 case Primitive::kPrimShort:
557 case Primitive::kPrimInt:
558 case Primitive::kPrimNot:
559 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
560 break;
561
562 case Primitive::kPrimLong:
563 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
564 break;
565
566 default:
567 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
568 }
569 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000570 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000571 __ ret();
572}
573
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000574void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
575 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100576 locations->AddTemp(Location::RequiresRegister());
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100577
578 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100579 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100580 HInstruction* input = invoke->InputAt(i);
581 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
582 }
583
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100584 switch (invoke->GetType()) {
585 case Primitive::kPrimBoolean:
586 case Primitive::kPrimByte:
587 case Primitive::kPrimChar:
588 case Primitive::kPrimShort:
589 case Primitive::kPrimInt:
590 case Primitive::kPrimNot:
591 locations->SetOut(X86CpuLocation(EAX));
592 break;
593
594 case Primitive::kPrimLong:
595 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
596 break;
597
598 case Primitive::kPrimVoid:
599 break;
600
601 case Primitive::kPrimDouble:
602 case Primitive::kPrimFloat:
603 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
604 break;
605 }
606
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000607 invoke->SetLocations(locations);
608}
609
610void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100611 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000612 size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100613 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000614
615 // TODO: Implement all kinds of calls:
616 // 1) boot -> boot
617 // 2) app -> boot
618 // 3) app -> app
619 //
620 // Currently we implement the app -> app logic, which looks up in the resolve cache.
621
622 // temp = method;
623 LoadCurrentMethod(temp);
624 // temp = temp->dex_cache_resolved_methods_;
625 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
626 // temp = temp[index_in_cache]
627 __ movl(temp, Address(temp, index_in_cache));
628 // (temp + offset_of_quick_compiled_code)()
629 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
630
631 codegen_->RecordPcInfo(invoke->GetDexPc());
632}
633
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000634void LocationsBuilderX86::VisitAdd(HAdd* add) {
635 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
636 switch (add->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100637 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100638 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100639 locations->SetInAt(0, Location::RequiresRegister());
640 locations->SetInAt(1, Location::Any());
641 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100642 break;
643 }
644
645 case Primitive::kPrimBoolean:
646 case Primitive::kPrimByte:
647 case Primitive::kPrimChar:
648 case Primitive::kPrimShort:
649 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
650 break;
651
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000652 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100653 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000654 }
655 add->SetLocations(locations);
656}
657
658void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
659 LocationSummary* locations = add->GetLocations();
660 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100661 case Primitive::kPrimInt: {
662 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
663 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100664 if (locations->InAt(1).IsRegister()) {
665 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
666 locations->InAt(1).AsX86().AsCpuRegister());
667 } else {
668 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
669 Address(ESP, locations->InAt(1).GetStackIndex()));
670 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000671 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100672 }
673
674 case Primitive::kPrimLong: {
675 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
676 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100677 if (locations->InAt(1).IsRegister()) {
678 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
679 locations->InAt(1).AsX86().AsRegisterPairLow());
680 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
681 locations->InAt(1).AsX86().AsRegisterPairHigh());
682 } else {
683 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
684 Address(ESP, locations->InAt(1).GetStackIndex()));
685 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
686 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
687 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100688 break;
689 }
690
691 case Primitive::kPrimBoolean:
692 case Primitive::kPrimByte:
693 case Primitive::kPrimChar:
694 case Primitive::kPrimShort:
695 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
696 break;
697
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000698 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100699 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000700 }
701}
702
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100703void LocationsBuilderX86::VisitSub(HSub* sub) {
704 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
705 switch (sub->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100706 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100707 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100708 locations->SetInAt(0, Location::RequiresRegister());
709 locations->SetInAt(1, Location::Any());
710 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100711 break;
712 }
713
714 case Primitive::kPrimBoolean:
715 case Primitive::kPrimByte:
716 case Primitive::kPrimChar:
717 case Primitive::kPrimShort:
718 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
719 break;
720
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100721 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100722 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100723 }
724 sub->SetLocations(locations);
725}
726
727void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
728 LocationSummary* locations = sub->GetLocations();
729 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100730 case Primitive::kPrimInt: {
731 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
732 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100733 if (locations->InAt(1).IsRegister()) {
734 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
735 locations->InAt(1).AsX86().AsCpuRegister());
736 } else {
737 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
738 Address(ESP, locations->InAt(1).GetStackIndex()));
739 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100740 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100741 }
742
743 case Primitive::kPrimLong: {
744 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
745 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100746 if (locations->InAt(1).IsRegister()) {
747 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
748 locations->InAt(1).AsX86().AsRegisterPairLow());
749 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
750 locations->InAt(1).AsX86().AsRegisterPairHigh());
751 } else {
752 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
753 Address(ESP, locations->InAt(1).GetStackIndex()));
754 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
755 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
756 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100757 break;
758 }
759
760 case Primitive::kPrimBoolean:
761 case Primitive::kPrimByte:
762 case Primitive::kPrimChar:
763 case Primitive::kPrimShort:
764 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
765 break;
766
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100767 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100768 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100769 }
770}
771
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100772void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
773 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100774 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100775 InvokeRuntimeCallingConvention calling_convention;
776 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0)));
777 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100778 instruction->SetLocations(locations);
779}
780
781void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
782 InvokeRuntimeCallingConvention calling_convention;
783 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100784 __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100785
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100786 __ fs()->call(
787 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100788
789 codegen_->RecordPcInfo(instruction->GetDexPc());
790}
791
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100792void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
793 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100794 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
795 if (location.IsStackSlot()) {
796 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
797 } else if (location.IsDoubleStackSlot()) {
798 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100799 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100800 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100801 instruction->SetLocations(locations);
802}
803
804void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100805 // Nothing to do, the parameter is already at its location.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100806}
807
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100808void LocationsBuilderX86::VisitNot(HNot* instruction) {
809 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100810 locations->SetInAt(0, Location::RequiresRegister());
811 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100812 instruction->SetLocations(locations);
813}
814
815void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
816 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100817 Location out = locations->Out();
818 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), out.AsX86().AsCpuRegister());
819 __ xorl(out.AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100820}
821
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100822void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100823 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
824 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
825 locations->SetInAt(i, Location::Any());
826 }
827 locations->SetOut(Location::Any());
828 instruction->SetLocations(locations);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100829}
830
831void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
832 LOG(FATAL) << "Unimplemented";
833}
834
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100835void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction) {
836 LOG(FATAL) << "Unimplemented";
837}
838
839void InstructionCodeGeneratorX86::VisitParallelMove(HParallelMove* instruction) {
840 LOG(FATAL) << "Unimplemented";
841}
842
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000843} // namespace x86
844} // namespace art