blob: c7dca86dab1c7b21d509f28354ca7ae33d94ffe3 [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),
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010051 instruction_visitor_(graph, this),
52 move_resolver_(graph->GetArena(), this) {}
53
54void CodeGeneratorX86::ComputeFrameSize(size_t number_of_spill_slots) {
55 SetFrameSize(RoundUp(
56 number_of_spill_slots * kVRegSize
57 + kVRegSize // Art method
58 + kNumberOfPushedRegistersAtEntry * kX86WordSize,
59 kStackAlignment));
60}
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010061
62static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
63 return blocked_registers + kNumberOfAllocIds;
64}
65
66ManagedRegister CodeGeneratorX86::AllocateFreeRegister(Primitive::Type type,
67 bool* blocked_registers) const {
68 switch (type) {
69 case Primitive::kPrimLong: {
70 size_t reg = AllocateFreeRegisterInternal(
71 GetBlockedRegisterPairs(blocked_registers), kNumberOfRegisterPairs);
72 X86ManagedRegister pair =
73 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg));
74 blocked_registers[pair.AsRegisterPairLow()] = true;
75 blocked_registers[pair.AsRegisterPairHigh()] = true;
76 return pair;
77 }
78
79 case Primitive::kPrimByte:
80 case Primitive::kPrimBoolean:
81 case Primitive::kPrimChar:
82 case Primitive::kPrimShort:
83 case Primitive::kPrimInt:
84 case Primitive::kPrimNot: {
85 size_t reg = AllocateFreeRegisterInternal(blocked_registers, kNumberOfCpuRegisters);
86 return X86ManagedRegister::FromCpuRegister(static_cast<Register>(reg));
87 }
88
89 case Primitive::kPrimFloat:
90 case Primitive::kPrimDouble:
91 LOG(FATAL) << "Unimplemented register type " << type;
92
93 case Primitive::kPrimVoid:
94 LOG(FATAL) << "Unreachable type " << type;
95 }
96
97 return ManagedRegister::NoRegister();
98}
99
100void CodeGeneratorX86::SetupBlockedRegisters(bool* blocked_registers) const {
101 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
102
103 // Don't allocate the dalvik style register pair passing.
104 blocked_register_pairs[ECX_EDX] = true;
105
106 // Stack register is always reserved.
107 blocked_registers[ESP] = true;
108
109 // TODO: We currently don't use Quick's callee saved registers.
110 blocked_registers[EBP] = true;
111 blocked_registers[ESI] = true;
112 blocked_registers[EDI] = true;
113 blocked_register_pairs[EAX_EDI] = true;
114 blocked_register_pairs[EDX_EDI] = true;
115 blocked_register_pairs[ECX_EDI] = true;
116 blocked_register_pairs[EBX_EDI] = true;
117}
118
119size_t CodeGeneratorX86::GetNumberOfRegisters() const {
120 return kNumberOfRegIds;
121}
122
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100123static Location X86CpuLocation(Register reg) {
124 return Location::RegisterLocation(X86ManagedRegister::FromCpuRegister(reg));
125}
126
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100127InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen)
128 : HGraphVisitor(graph),
129 assembler_(codegen->GetAssembler()),
130 codegen_(codegen) {}
131
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000132void CodeGeneratorX86::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000133 // Create a fake register to mimic Quick.
134 static const int kFakeReturnRegister = 8;
135 core_spill_mask_ |= (1 << kFakeReturnRegister);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000136
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100137 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100138 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100139 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000140}
141
142void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100143 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000144}
145
146void CodeGeneratorX86::Bind(Label* label) {
147 __ Bind(label);
148}
149
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000150void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100151 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000152}
153
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100154int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100155 uint16_t reg_number = local->GetRegNumber();
156 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
157 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
158 if (reg_number >= number_of_vregs - number_of_in_vregs) {
159 // Local is a parameter of the method. It is stored in the caller's frame.
160 return GetFrameSize() + kX86WordSize // ART method
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100161 + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100162 } else {
163 // Local is a temporary in this method. It is stored in this method's frame.
164 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100165 - kVRegSize // filler.
166 - (number_of_vregs * kVRegSize)
167 + (reg_number * kVRegSize);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100168 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100169}
170
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100171
172Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
173 switch (load->GetType()) {
174 case Primitive::kPrimLong:
175 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
176 break;
177
178 case Primitive::kPrimInt:
179 case Primitive::kPrimNot:
180 return Location::StackSlot(GetStackSlot(load->GetLocal()));
181
182 case Primitive::kPrimFloat:
183 case Primitive::kPrimDouble:
184 LOG(FATAL) << "Unimplemented type " << load->GetType();
185
186 case Primitive::kPrimBoolean:
187 case Primitive::kPrimByte:
188 case Primitive::kPrimChar:
189 case Primitive::kPrimShort:
190 case Primitive::kPrimVoid:
191 LOG(FATAL) << "Unexpected type " << load->GetType();
192 }
193
194 LOG(FATAL) << "Unreachable";
195 return Location();
196}
197
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100198static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
199static constexpr size_t kRuntimeParameterCoreRegistersLength =
200 arraysize(kRuntimeParameterCoreRegisters);
201
202class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
203 public:
204 InvokeRuntimeCallingConvention()
205 : CallingConvention(kRuntimeParameterCoreRegisters,
206 kRuntimeParameterCoreRegistersLength) {}
207
208 private:
209 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
210};
211
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100212Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
213 switch (type) {
214 case Primitive::kPrimBoolean:
215 case Primitive::kPrimByte:
216 case Primitive::kPrimChar:
217 case Primitive::kPrimShort:
218 case Primitive::kPrimInt:
219 case Primitive::kPrimNot: {
220 uint32_t index = gp_index_++;
221 if (index < calling_convention.GetNumberOfRegisters()) {
222 return X86CpuLocation(calling_convention.GetRegisterAt(index));
223 } else {
224 return Location::StackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100225 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100226 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100227
228 case Primitive::kPrimLong: {
229 uint32_t index = gp_index_;
230 gp_index_ += 2;
231 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
232 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
233 calling_convention.GetRegisterPairAt(index)));
234 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
235 return Location::QuickParameter(index);
236 } else {
237 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize));
238 }
239 }
240
241 case Primitive::kPrimDouble:
242 case Primitive::kPrimFloat:
243 LOG(FATAL) << "Unimplemented parameter type " << type;
244 break;
245
246 case Primitive::kPrimVoid:
247 LOG(FATAL) << "Unexpected parameter type " << type;
248 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100249 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100250 return Location();
251}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100252
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100253void CodeGeneratorX86::Move32(Location destination, Location source) {
254 if (source.Equals(destination)) {
255 return;
256 }
257 if (destination.IsRegister()) {
258 if (source.IsRegister()) {
259 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
260 } else {
261 DCHECK(source.IsStackSlot());
262 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
263 }
264 } else {
265 if (source.IsRegister()) {
266 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
267 } else {
268 DCHECK(source.IsStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100269 __ pushl(Address(ESP, source.GetStackIndex()));
270 __ popl(Address(ESP, destination.GetStackIndex()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100271 }
272 }
273}
274
275void CodeGeneratorX86::Move64(Location destination, Location source) {
276 if (source.Equals(destination)) {
277 return;
278 }
279 if (destination.IsRegister()) {
280 if (source.IsRegister()) {
281 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
282 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
283 } else if (source.IsQuickParameter()) {
284 uint32_t argument_index = source.GetQuickParameterIndex();
285 InvokeDexCallingConvention calling_convention;
286 __ movl(destination.AsX86().AsRegisterPairLow(),
287 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100288 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
289 calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100290 } else {
291 DCHECK(source.IsDoubleStackSlot());
292 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
293 __ movl(destination.AsX86().AsRegisterPairHigh(),
294 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
295 }
296 } else if (destination.IsQuickParameter()) {
297 InvokeDexCallingConvention calling_convention;
298 uint32_t argument_index = destination.GetQuickParameterIndex();
299 if (source.IsRegister()) {
300 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100301 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100302 source.AsX86().AsRegisterPairHigh());
303 } else {
304 DCHECK(source.IsDoubleStackSlot());
305 __ movl(calling_convention.GetRegisterAt(argument_index),
306 Address(ESP, source.GetStackIndex()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100307 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
308 __ popl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100309 }
310 } else {
311 if (source.IsRegister()) {
312 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
313 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
314 source.AsX86().AsRegisterPairHigh());
315 } else if (source.IsQuickParameter()) {
316 InvokeDexCallingConvention calling_convention;
317 uint32_t argument_index = source.GetQuickParameterIndex();
318 __ movl(Address(ESP, destination.GetStackIndex()),
319 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100320 __ pushl(Address(ESP,
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100321 calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100322 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100323 } else {
324 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100325 __ pushl(Address(ESP, source.GetStackIndex()));
326 __ popl(Address(ESP, destination.GetStackIndex()));
327 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
328 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100329 }
330 }
331}
332
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100333void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
334 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100335 Immediate imm(instruction->AsIntConstant()->GetValue());
336 if (location.IsRegister()) {
337 __ movl(location.AsX86().AsCpuRegister(), imm);
338 } else {
339 __ movl(Address(ESP, location.GetStackIndex()), imm);
340 }
341 } else if (instruction->AsLongConstant() != nullptr) {
342 int64_t value = instruction->AsLongConstant()->GetValue();
343 if (location.IsRegister()) {
344 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
345 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
346 } else {
347 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
348 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
349 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100350 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100351 switch (instruction->GetType()) {
352 case Primitive::kPrimBoolean:
353 case Primitive::kPrimByte:
354 case Primitive::kPrimChar:
355 case Primitive::kPrimShort:
356 case Primitive::kPrimInt:
357 case Primitive::kPrimNot:
358 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
359 break;
360
361 case Primitive::kPrimLong:
362 Move64(location, Location::DoubleStackSlot(
363 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
364 break;
365
366 default:
367 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
368 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000369 } else {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100370 // This can currently only happen when the instruction that requests the move
371 // is the next to be compiled.
372 DCHECK_EQ(instruction->GetNext(), move_for);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100373 switch (instruction->GetType()) {
374 case Primitive::kPrimBoolean:
375 case Primitive::kPrimByte:
376 case Primitive::kPrimChar:
377 case Primitive::kPrimShort:
378 case Primitive::kPrimInt:
379 case Primitive::kPrimNot:
380 Move32(location, instruction->GetLocations()->Out());
381 break;
382
383 case Primitive::kPrimLong:
384 Move64(location, instruction->GetLocations()->Out());
385 break;
386
387 default:
388 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
389 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000390 }
391}
392
393void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000394 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000395}
396
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000397void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000398 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000399 if (GetGraph()->GetExitBlock() == successor) {
400 codegen_->GenerateFrameExit();
401 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
402 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000403 }
404}
405
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000406void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000407 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000408}
409
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000410void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000411 if (kIsDebugBuild) {
412 __ Comment("Unreachable");
413 __ int3();
414 }
415}
416
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000417void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000418 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100419 locations->SetInAt(0, Location::Any());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000420 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000421}
422
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000423void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000424 // TODO: Generate the input as a condition, instead of materializing in a register.
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100425 Location location = if_instr->GetLocations()->InAt(0);
426 if (location.IsRegister()) {
427 __ cmpl(location.AsX86().AsCpuRegister(), Immediate(0));
428 } else {
429 __ cmpl(Address(ESP, location.GetStackIndex()), Immediate(0));
430 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000431 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
432 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) {
433 __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000434 }
435}
436
437void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000438 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000439}
440
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000441void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
442 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000443}
444
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000445void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100446 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000447}
448
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000449void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100450 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000451}
452
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100453void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
454 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
455 switch (store->InputAt(1)->GetType()) {
456 case Primitive::kPrimBoolean:
457 case Primitive::kPrimByte:
458 case Primitive::kPrimChar:
459 case Primitive::kPrimShort:
460 case Primitive::kPrimInt:
461 case Primitive::kPrimNot:
462 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
463 break;
464
465 case Primitive::kPrimLong:
466 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
467 break;
468
469 default:
470 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
471 }
472 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000473}
474
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000475void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000476}
477
478void LocationsBuilderX86::VisitEqual(HEqual* equal) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000479 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100480 locations->SetInAt(0, Location::RequiresRegister());
481 locations->SetInAt(1, Location::Any());
482 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000483 equal->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000484}
485
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000486void InstructionCodeGeneratorX86::VisitEqual(HEqual* equal) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100487 LocationSummary* locations = equal->GetLocations();
488 if (locations->InAt(1).IsRegister()) {
489 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
490 locations->InAt(1).AsX86().AsCpuRegister());
491 } else {
492 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
493 Address(ESP, locations->InAt(1).GetStackIndex()));
494 }
495 __ setb(kEqual, locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000496}
497
498void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100499 // TODO: Support constant locations.
500 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
501 locations->SetOut(Location::RequiresRegister());
502 constant->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000503}
504
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000505void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100506 codegen_->Move(constant, constant->GetLocations()->Out(), nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000507}
508
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100509void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100510 // TODO: Support constant locations.
511 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
512 locations->SetOut(Location::RequiresRegister());
513 constant->SetLocations(locations);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100514}
515
516void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
517 // Will be generated at use site.
518}
519
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000520void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000521 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000522}
523
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000524void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
525 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000526 __ ret();
527}
528
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000529void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000530 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100531 switch (ret->InputAt(0)->GetType()) {
532 case Primitive::kPrimBoolean:
533 case Primitive::kPrimByte:
534 case Primitive::kPrimChar:
535 case Primitive::kPrimShort:
536 case Primitive::kPrimInt:
537 case Primitive::kPrimNot:
538 locations->SetInAt(0, X86CpuLocation(EAX));
539 break;
540
541 case Primitive::kPrimLong:
542 locations->SetInAt(
543 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
544 break;
545
546 default:
547 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
548 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000549 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000550}
551
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000552void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100553 if (kIsDebugBuild) {
554 switch (ret->InputAt(0)->GetType()) {
555 case Primitive::kPrimBoolean:
556 case Primitive::kPrimByte:
557 case Primitive::kPrimChar:
558 case Primitive::kPrimShort:
559 case Primitive::kPrimInt:
560 case Primitive::kPrimNot:
561 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
562 break;
563
564 case Primitive::kPrimLong:
565 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
566 break;
567
568 default:
569 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
570 }
571 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000572 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000573 __ ret();
574}
575
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000576void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
577 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100578 locations->AddTemp(X86CpuLocation(EAX));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100579
580 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100581 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100582 HInstruction* input = invoke->InputAt(i);
583 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
584 }
585
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100586 switch (invoke->GetType()) {
587 case Primitive::kPrimBoolean:
588 case Primitive::kPrimByte:
589 case Primitive::kPrimChar:
590 case Primitive::kPrimShort:
591 case Primitive::kPrimInt:
592 case Primitive::kPrimNot:
593 locations->SetOut(X86CpuLocation(EAX));
594 break;
595
596 case Primitive::kPrimLong:
597 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
598 break;
599
600 case Primitive::kPrimVoid:
601 break;
602
603 case Primitive::kPrimDouble:
604 case Primitive::kPrimFloat:
605 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
606 break;
607 }
608
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000609 invoke->SetLocations(locations);
610}
611
612void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100613 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000614 size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100615 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000616
617 // TODO: Implement all kinds of calls:
618 // 1) boot -> boot
619 // 2) app -> boot
620 // 3) app -> app
621 //
622 // Currently we implement the app -> app logic, which looks up in the resolve cache.
623
624 // temp = method;
625 LoadCurrentMethod(temp);
626 // temp = temp->dex_cache_resolved_methods_;
627 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
628 // temp = temp[index_in_cache]
629 __ movl(temp, Address(temp, index_in_cache));
630 // (temp + offset_of_quick_compiled_code)()
631 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
632
633 codegen_->RecordPcInfo(invoke->GetDexPc());
634}
635
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000636void LocationsBuilderX86::VisitAdd(HAdd* add) {
637 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
638 switch (add->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100639 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100640 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100641 locations->SetInAt(0, Location::RequiresRegister());
642 locations->SetInAt(1, Location::Any());
643 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100644 break;
645 }
646
647 case Primitive::kPrimBoolean:
648 case Primitive::kPrimByte:
649 case Primitive::kPrimChar:
650 case Primitive::kPrimShort:
651 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
652 break;
653
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000654 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100655 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000656 }
657 add->SetLocations(locations);
658}
659
660void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
661 LocationSummary* locations = add->GetLocations();
662 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100663 case Primitive::kPrimInt: {
664 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
665 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100666 if (locations->InAt(1).IsRegister()) {
667 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
668 locations->InAt(1).AsX86().AsCpuRegister());
669 } else {
670 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
671 Address(ESP, locations->InAt(1).GetStackIndex()));
672 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000673 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100674 }
675
676 case Primitive::kPrimLong: {
677 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
678 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100679 if (locations->InAt(1).IsRegister()) {
680 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
681 locations->InAt(1).AsX86().AsRegisterPairLow());
682 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
683 locations->InAt(1).AsX86().AsRegisterPairHigh());
684 } else {
685 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
686 Address(ESP, locations->InAt(1).GetStackIndex()));
687 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
688 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
689 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100690 break;
691 }
692
693 case Primitive::kPrimBoolean:
694 case Primitive::kPrimByte:
695 case Primitive::kPrimChar:
696 case Primitive::kPrimShort:
697 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
698 break;
699
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000700 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100701 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000702 }
703}
704
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100705void LocationsBuilderX86::VisitSub(HSub* sub) {
706 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
707 switch (sub->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100708 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100709 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100710 locations->SetInAt(0, Location::RequiresRegister());
711 locations->SetInAt(1, Location::Any());
712 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100713 break;
714 }
715
716 case Primitive::kPrimBoolean:
717 case Primitive::kPrimByte:
718 case Primitive::kPrimChar:
719 case Primitive::kPrimShort:
720 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
721 break;
722
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100723 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100724 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100725 }
726 sub->SetLocations(locations);
727}
728
729void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
730 LocationSummary* locations = sub->GetLocations();
731 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100732 case Primitive::kPrimInt: {
733 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
734 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100735 if (locations->InAt(1).IsRegister()) {
736 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
737 locations->InAt(1).AsX86().AsCpuRegister());
738 } else {
739 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
740 Address(ESP, locations->InAt(1).GetStackIndex()));
741 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100742 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100743 }
744
745 case Primitive::kPrimLong: {
746 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
747 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100748 if (locations->InAt(1).IsRegister()) {
749 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
750 locations->InAt(1).AsX86().AsRegisterPairLow());
751 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
752 locations->InAt(1).AsX86().AsRegisterPairHigh());
753 } else {
754 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
755 Address(ESP, locations->InAt(1).GetStackIndex()));
756 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
757 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
758 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100759 break;
760 }
761
762 case Primitive::kPrimBoolean:
763 case Primitive::kPrimByte:
764 case Primitive::kPrimChar:
765 case Primitive::kPrimShort:
766 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
767 break;
768
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100769 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100770 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100771 }
772}
773
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100774void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
775 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100776 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100777 InvokeRuntimeCallingConvention calling_convention;
778 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0)));
779 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100780 instruction->SetLocations(locations);
781}
782
783void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
784 InvokeRuntimeCallingConvention calling_convention;
785 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100786 __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100787
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100788 __ fs()->call(
789 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100790
791 codegen_->RecordPcInfo(instruction->GetDexPc());
792}
793
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100794void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
795 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100796 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
797 if (location.IsStackSlot()) {
798 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
799 } else if (location.IsDoubleStackSlot()) {
800 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100801 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100802 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100803 instruction->SetLocations(locations);
804}
805
806void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100807}
808
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100809void LocationsBuilderX86::VisitNot(HNot* instruction) {
810 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100811 locations->SetInAt(0, Location::RequiresRegister());
812 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100813 instruction->SetLocations(locations);
814}
815
816void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
817 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100818 Location out = locations->Out();
819 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), out.AsX86().AsCpuRegister());
820 __ xorl(out.AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100821}
822
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100823void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100824 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
825 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
826 locations->SetInAt(i, Location::Any());
827 }
828 locations->SetOut(Location::Any());
829 instruction->SetLocations(locations);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100830}
831
832void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100833 LOG(FATAL) << "Unreachable";
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100834}
835
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100836void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100837 LOG(FATAL) << "Unreachable";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100838}
839
840void InstructionCodeGeneratorX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100841 codegen_->GetMoveResolver()->EmitNativeCode(instruction);
842}
843
844X86Assembler* ParallelMoveResolverX86::GetAssembler() const {
845 return codegen_->GetAssembler();
846}
847
848void ParallelMoveResolverX86::MoveMemoryToMemory(int dst, int src) {
849 ScratchRegisterScope ensure_scratch(
850 this, kNoRegister, codegen_->GetNumberOfCoreRegisters());
851 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
852 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, src + stack_offset));
853 __ movl(Address(ESP, dst + stack_offset), static_cast<Register>(ensure_scratch.GetRegister()));
854}
855
856void ParallelMoveResolverX86::EmitMove(size_t index) {
857 MoveOperands* move = moves_.Get(index);
858 Location source = move->GetSource();
859 Location destination = move->GetDestination();
860
861 if (source.IsRegister()) {
862 if (destination.IsRegister()) {
863 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
864 } else {
865 DCHECK(destination.IsStackSlot());
866 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
867 }
868 } else if (source.IsStackSlot()) {
869 if (destination.IsRegister()) {
870 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
871 } else {
872 DCHECK(destination.IsStackSlot());
873 MoveMemoryToMemory(destination.GetStackIndex(),
874 source.GetStackIndex());
875 }
876 } else {
877 LOG(FATAL) << "Unimplemented";
878 }
879}
880
881void ParallelMoveResolverX86::Exchange(Register reg, int mem) {
882 ScratchRegisterScope ensure_scratch(this, reg, codegen_->GetNumberOfCoreRegisters());
883 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
884 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, mem + stack_offset));
885 __ movl(Address(ESP, mem + stack_offset), reg);
886 __ movl(reg, static_cast<Register>(ensure_scratch.GetRegister()));
887}
888
889
890void ParallelMoveResolverX86::Exchange(int mem1, int mem2) {
891 ScratchRegisterScope ensure_scratch1(
892 this, kNoRegister, codegen_->GetNumberOfCoreRegisters());
893 ScratchRegisterScope ensure_scratch2(
894 this, ensure_scratch1.GetRegister(), codegen_->GetNumberOfCoreRegisters());
895 int stack_offset = ensure_scratch1.IsSpilled() ? kX86WordSize : 0;
896 stack_offset += ensure_scratch2.IsSpilled() ? kX86WordSize : 0;
897 __ movl(static_cast<Register>(ensure_scratch1.GetRegister()), Address(ESP, mem1 + stack_offset));
898 __ movl(static_cast<Register>(ensure_scratch2.GetRegister()), Address(ESP, mem2 + stack_offset));
899 __ movl(Address(ESP, mem2 + stack_offset), static_cast<Register>(ensure_scratch1.GetRegister()));
900 __ movl(Address(ESP, mem1 + stack_offset), static_cast<Register>(ensure_scratch2.GetRegister()));
901}
902
903void ParallelMoveResolverX86::EmitSwap(size_t index) {
904 MoveOperands* move = moves_.Get(index);
905 Location source = move->GetSource();
906 Location destination = move->GetDestination();
907
908 if (source.IsRegister() && destination.IsRegister()) {
909 __ xchgl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
910 } else if (source.IsRegister() && destination.IsStackSlot()) {
911 Exchange(source.AsX86().AsCpuRegister(), destination.GetStackIndex());
912 } else if (source.IsStackSlot() && destination.IsRegister()) {
913 Exchange(destination.AsX86().AsCpuRegister(), source.GetStackIndex());
914 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
915 Exchange(destination.GetStackIndex(), source.GetStackIndex());
916 } else {
917 LOG(FATAL) << "Unimplemented";
918 }
919}
920
921void ParallelMoveResolverX86::SpillScratch(int reg) {
922 __ pushl(static_cast<Register>(reg));
923}
924
925void ParallelMoveResolverX86::RestoreScratch(int reg) {
926 __ popl(static_cast<Register>(reg));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100927}
928
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000929} // namespace x86
930} // namespace art