blob: a8ee6c061e5624061aee657f75caea4d43b1a7a7 [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
Dave Allison20dfc792014-06-16 20:44:29 -070037inline Condition X86Condition(IfCondition cond) {
38 switch (cond) {
39 case kCondEQ: return kEqual;
40 case kCondNE: return kNotEqual;
41 case kCondLT: return kLess;
42 case kCondLE: return kLessEqual;
43 case kCondGT: return kGreater;
44 case kCondGE: return kGreaterEqual;
45 default:
46 LOG(FATAL) << "Unknown if condition";
47 }
48 return kEqual;
49}
50
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010051static constexpr int kNumberOfPushedRegistersAtEntry = 1;
52static constexpr int kCurrentMethodStackOffset = 0;
53
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010054void CodeGeneratorX86::DumpCoreRegister(std::ostream& stream, int reg) const {
55 stream << X86ManagedRegister::FromCpuRegister(Register(reg));
56}
57
58void CodeGeneratorX86::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
59 stream << X86ManagedRegister::FromXmmRegister(XmmRegister(reg));
60}
61
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010062CodeGeneratorX86::CodeGeneratorX86(HGraph* graph)
63 : CodeGenerator(graph, kNumberOfRegIds),
64 location_builder_(graph, this),
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010065 instruction_visitor_(graph, this),
66 move_resolver_(graph->GetArena(), this) {}
67
68void CodeGeneratorX86::ComputeFrameSize(size_t number_of_spill_slots) {
69 SetFrameSize(RoundUp(
70 number_of_spill_slots * kVRegSize
71 + kVRegSize // Art method
72 + kNumberOfPushedRegistersAtEntry * kX86WordSize,
73 kStackAlignment));
74}
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010075
76static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
77 return blocked_registers + kNumberOfAllocIds;
78}
79
80ManagedRegister CodeGeneratorX86::AllocateFreeRegister(Primitive::Type type,
81 bool* blocked_registers) const {
82 switch (type) {
83 case Primitive::kPrimLong: {
84 size_t reg = AllocateFreeRegisterInternal(
85 GetBlockedRegisterPairs(blocked_registers), kNumberOfRegisterPairs);
86 X86ManagedRegister pair =
87 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg));
88 blocked_registers[pair.AsRegisterPairLow()] = true;
89 blocked_registers[pair.AsRegisterPairHigh()] = true;
90 return pair;
91 }
92
93 case Primitive::kPrimByte:
94 case Primitive::kPrimBoolean:
95 case Primitive::kPrimChar:
96 case Primitive::kPrimShort:
97 case Primitive::kPrimInt:
98 case Primitive::kPrimNot: {
99 size_t reg = AllocateFreeRegisterInternal(blocked_registers, kNumberOfCpuRegisters);
100 return X86ManagedRegister::FromCpuRegister(static_cast<Register>(reg));
101 }
102
103 case Primitive::kPrimFloat:
104 case Primitive::kPrimDouble:
105 LOG(FATAL) << "Unimplemented register type " << type;
106
107 case Primitive::kPrimVoid:
108 LOG(FATAL) << "Unreachable type " << type;
109 }
110
111 return ManagedRegister::NoRegister();
112}
113
114void CodeGeneratorX86::SetupBlockedRegisters(bool* blocked_registers) const {
115 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
116
117 // Don't allocate the dalvik style register pair passing.
118 blocked_register_pairs[ECX_EDX] = true;
119
120 // Stack register is always reserved.
121 blocked_registers[ESP] = true;
122
123 // TODO: We currently don't use Quick's callee saved registers.
124 blocked_registers[EBP] = true;
125 blocked_registers[ESI] = true;
126 blocked_registers[EDI] = true;
127 blocked_register_pairs[EAX_EDI] = true;
128 blocked_register_pairs[EDX_EDI] = true;
129 blocked_register_pairs[ECX_EDI] = true;
130 blocked_register_pairs[EBX_EDI] = true;
131}
132
133size_t CodeGeneratorX86::GetNumberOfRegisters() const {
134 return kNumberOfRegIds;
135}
136
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100137static Location X86CpuLocation(Register reg) {
138 return Location::RegisterLocation(X86ManagedRegister::FromCpuRegister(reg));
139}
140
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100141InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen)
142 : HGraphVisitor(graph),
143 assembler_(codegen->GetAssembler()),
144 codegen_(codegen) {}
145
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000146void CodeGeneratorX86::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000147 // Create a fake register to mimic Quick.
148 static const int kFakeReturnRegister = 8;
149 core_spill_mask_ |= (1 << kFakeReturnRegister);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000150
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100151 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100152 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100153 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000154}
155
156void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100157 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000158}
159
160void CodeGeneratorX86::Bind(Label* label) {
161 __ Bind(label);
162}
163
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000164void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100165 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000166}
167
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100168int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100169 uint16_t reg_number = local->GetRegNumber();
170 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
171 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
172 if (reg_number >= number_of_vregs - number_of_in_vregs) {
173 // Local is a parameter of the method. It is stored in the caller's frame.
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100174 return GetFrameSize() + kVRegSize // ART method
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100175 + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100176 } else {
177 // Local is a temporary in this method. It is stored in this method's frame.
178 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100179 - kVRegSize // filler.
180 - (number_of_vregs * kVRegSize)
181 + (reg_number * kVRegSize);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100182 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100183}
184
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100185
186Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
187 switch (load->GetType()) {
188 case Primitive::kPrimLong:
189 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
190 break;
191
192 case Primitive::kPrimInt:
193 case Primitive::kPrimNot:
194 return Location::StackSlot(GetStackSlot(load->GetLocal()));
195
196 case Primitive::kPrimFloat:
197 case Primitive::kPrimDouble:
198 LOG(FATAL) << "Unimplemented type " << load->GetType();
199
200 case Primitive::kPrimBoolean:
201 case Primitive::kPrimByte:
202 case Primitive::kPrimChar:
203 case Primitive::kPrimShort:
204 case Primitive::kPrimVoid:
205 LOG(FATAL) << "Unexpected type " << load->GetType();
206 }
207
208 LOG(FATAL) << "Unreachable";
209 return Location();
210}
211
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100212static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
213static constexpr size_t kRuntimeParameterCoreRegistersLength =
214 arraysize(kRuntimeParameterCoreRegisters);
215
216class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
217 public:
218 InvokeRuntimeCallingConvention()
219 : CallingConvention(kRuntimeParameterCoreRegisters,
220 kRuntimeParameterCoreRegistersLength) {}
221
222 private:
223 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
224};
225
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100226Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
227 switch (type) {
228 case Primitive::kPrimBoolean:
229 case Primitive::kPrimByte:
230 case Primitive::kPrimChar:
231 case Primitive::kPrimShort:
232 case Primitive::kPrimInt:
233 case Primitive::kPrimNot: {
234 uint32_t index = gp_index_++;
235 if (index < calling_convention.GetNumberOfRegisters()) {
236 return X86CpuLocation(calling_convention.GetRegisterAt(index));
237 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100238 return Location::StackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100239 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100240 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100241
242 case Primitive::kPrimLong: {
243 uint32_t index = gp_index_;
244 gp_index_ += 2;
245 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
246 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
247 calling_convention.GetRegisterPairAt(index)));
248 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
249 return Location::QuickParameter(index);
250 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100251 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100252 }
253 }
254
255 case Primitive::kPrimDouble:
256 case Primitive::kPrimFloat:
257 LOG(FATAL) << "Unimplemented parameter type " << type;
258 break;
259
260 case Primitive::kPrimVoid:
261 LOG(FATAL) << "Unexpected parameter type " << type;
262 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100263 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100264 return Location();
265}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100266
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100267void CodeGeneratorX86::Move32(Location destination, Location source) {
268 if (source.Equals(destination)) {
269 return;
270 }
271 if (destination.IsRegister()) {
272 if (source.IsRegister()) {
273 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
274 } else {
275 DCHECK(source.IsStackSlot());
276 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
277 }
278 } else {
279 if (source.IsRegister()) {
280 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
281 } else {
282 DCHECK(source.IsStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100283 __ pushl(Address(ESP, source.GetStackIndex()));
284 __ popl(Address(ESP, destination.GetStackIndex()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100285 }
286 }
287}
288
289void CodeGeneratorX86::Move64(Location destination, Location source) {
290 if (source.Equals(destination)) {
291 return;
292 }
293 if (destination.IsRegister()) {
294 if (source.IsRegister()) {
295 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
296 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
297 } else if (source.IsQuickParameter()) {
298 uint32_t argument_index = source.GetQuickParameterIndex();
299 InvokeDexCallingConvention calling_convention;
300 __ movl(destination.AsX86().AsRegisterPairLow(),
301 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100302 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100303 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100304 } else {
305 DCHECK(source.IsDoubleStackSlot());
306 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
307 __ movl(destination.AsX86().AsRegisterPairHigh(),
308 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
309 }
310 } else if (destination.IsQuickParameter()) {
311 InvokeDexCallingConvention calling_convention;
312 uint32_t argument_index = destination.GetQuickParameterIndex();
313 if (source.IsRegister()) {
314 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100315 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100316 source.AsX86().AsRegisterPairHigh());
317 } else {
318 DCHECK(source.IsDoubleStackSlot());
319 __ movl(calling_convention.GetRegisterAt(argument_index),
320 Address(ESP, source.GetStackIndex()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100321 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100322 __ popl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100323 }
324 } else {
325 if (source.IsRegister()) {
326 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
327 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
328 source.AsX86().AsRegisterPairHigh());
329 } else if (source.IsQuickParameter()) {
330 InvokeDexCallingConvention calling_convention;
331 uint32_t argument_index = source.GetQuickParameterIndex();
332 __ movl(Address(ESP, destination.GetStackIndex()),
333 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100334 __ pushl(Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100335 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100336 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100337 } else {
338 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100339 __ pushl(Address(ESP, source.GetStackIndex()));
340 __ popl(Address(ESP, destination.GetStackIndex()));
341 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
342 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100343 }
344 }
345}
346
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100347void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
348 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100349 Immediate imm(instruction->AsIntConstant()->GetValue());
350 if (location.IsRegister()) {
351 __ movl(location.AsX86().AsCpuRegister(), imm);
352 } else {
353 __ movl(Address(ESP, location.GetStackIndex()), imm);
354 }
355 } else if (instruction->AsLongConstant() != nullptr) {
356 int64_t value = instruction->AsLongConstant()->GetValue();
357 if (location.IsRegister()) {
358 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
359 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
360 } else {
361 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
362 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
363 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100364 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100365 switch (instruction->GetType()) {
366 case Primitive::kPrimBoolean:
367 case Primitive::kPrimByte:
368 case Primitive::kPrimChar:
369 case Primitive::kPrimShort:
370 case Primitive::kPrimInt:
371 case Primitive::kPrimNot:
372 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
373 break;
374
375 case Primitive::kPrimLong:
376 Move64(location, Location::DoubleStackSlot(
377 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
378 break;
379
380 default:
381 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
382 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000383 } else {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100384 // This can currently only happen when the instruction that requests the move
385 // is the next to be compiled.
386 DCHECK_EQ(instruction->GetNext(), move_for);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100387 switch (instruction->GetType()) {
388 case Primitive::kPrimBoolean:
389 case Primitive::kPrimByte:
390 case Primitive::kPrimChar:
391 case Primitive::kPrimShort:
392 case Primitive::kPrimInt:
393 case Primitive::kPrimNot:
394 Move32(location, instruction->GetLocations()->Out());
395 break;
396
397 case Primitive::kPrimLong:
398 Move64(location, instruction->GetLocations()->Out());
399 break;
400
401 default:
402 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
403 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000404 }
405}
406
407void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000408 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000409}
410
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000411void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000412 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000413 if (GetGraph()->GetExitBlock() == successor) {
414 codegen_->GenerateFrameExit();
415 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
416 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000417 }
418}
419
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000420void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000421 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000422}
423
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000424void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000425 if (kIsDebugBuild) {
426 __ Comment("Unreachable");
427 __ int3();
428 }
429}
430
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000431void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000432 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100433 locations->SetInAt(0, Location::Any());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000434 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000435}
436
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000437void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Dave Allison20dfc792014-06-16 20:44:29 -0700438 HInstruction* cond = if_instr->InputAt(0);
439 DCHECK(cond->IsCondition());
440 HCondition* condition = cond->AsCondition();
441 if (condition->NeedsMaterialization()) {
442 // Materialized condition, compare against 0
443 Location lhs = if_instr->GetLocations()->InAt(0);
444 if (lhs.IsRegister()) {
445 __ cmpl(lhs.AsX86().AsCpuRegister(), Immediate(0));
446 } else {
447 __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0));
448 }
449 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100450 } else {
Dave Allison20dfc792014-06-16 20:44:29 -0700451 Location lhs = condition->GetLocations()->InAt(0);
452 Location rhs = condition->GetLocations()->InAt(1);
453 // LHS is guaranteed to be in a register (see LocationsBuilderX86::VisitCondition).
454 if (rhs.IsRegister()) {
455 __ cmpl(lhs.AsX86().AsCpuRegister(), rhs.AsX86().AsCpuRegister());
456 } else {
457 __ cmpl(lhs.AsX86().AsCpuRegister(), Address(ESP, rhs.GetStackIndex()));
458 }
459 __ j(X86Condition(condition->GetCondition()),
460 codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100461 }
Dave Allison20dfc792014-06-16 20:44:29 -0700462 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) {
463 __ jmp(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000464 }
465}
466
467void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000468 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000469}
470
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000471void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
472 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000473}
474
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000475void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100476 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000477}
478
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000479void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100480 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000481}
482
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100483void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
484 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
485 switch (store->InputAt(1)->GetType()) {
486 case Primitive::kPrimBoolean:
487 case Primitive::kPrimByte:
488 case Primitive::kPrimChar:
489 case Primitive::kPrimShort:
490 case Primitive::kPrimInt:
491 case Primitive::kPrimNot:
492 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
493 break;
494
495 case Primitive::kPrimLong:
496 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
497 break;
498
499 default:
500 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
501 }
502 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000503}
504
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000505void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000506}
507
Dave Allison20dfc792014-06-16 20:44:29 -0700508void LocationsBuilderX86::VisitCondition(HCondition* comp) {
509 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100510 locations->SetInAt(0, Location::RequiresRegister());
511 locations->SetInAt(1, Location::Any());
512 locations->SetOut(Location::SameAsFirstInput());
Dave Allison20dfc792014-06-16 20:44:29 -0700513 comp->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000514}
515
Dave Allison20dfc792014-06-16 20:44:29 -0700516void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) {
517 if (comp->NeedsMaterialization()) {
518 LocationSummary* locations = comp->GetLocations();
519 if (locations->InAt(1).IsRegister()) {
520 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
521 locations->InAt(1).AsX86().AsCpuRegister());
522 } else {
523 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
524 Address(ESP, locations->InAt(1).GetStackIndex()));
525 }
526 __ setb(X86Condition(comp->GetCondition()), locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100527 }
Dave Allison20dfc792014-06-16 20:44:29 -0700528}
529
530void LocationsBuilderX86::VisitEqual(HEqual* comp) {
531 VisitCondition(comp);
532}
533
534void InstructionCodeGeneratorX86::VisitEqual(HEqual* comp) {
535 VisitCondition(comp);
536}
537
538void LocationsBuilderX86::VisitNotEqual(HNotEqual* comp) {
539 VisitCondition(comp);
540}
541
542void InstructionCodeGeneratorX86::VisitNotEqual(HNotEqual* comp) {
543 VisitCondition(comp);
544}
545
546void LocationsBuilderX86::VisitLessThan(HLessThan* comp) {
547 VisitCondition(comp);
548}
549
550void InstructionCodeGeneratorX86::VisitLessThan(HLessThan* comp) {
551 VisitCondition(comp);
552}
553
554void LocationsBuilderX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
555 VisitCondition(comp);
556}
557
558void InstructionCodeGeneratorX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
559 VisitCondition(comp);
560}
561
562void LocationsBuilderX86::VisitGreaterThan(HGreaterThan* comp) {
563 VisitCondition(comp);
564}
565
566void InstructionCodeGeneratorX86::VisitGreaterThan(HGreaterThan* comp) {
567 VisitCondition(comp);
568}
569
570void LocationsBuilderX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
571 VisitCondition(comp);
572}
573
574void InstructionCodeGeneratorX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
575 VisitCondition(comp);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000576}
577
578void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100579 // TODO: Support constant locations.
580 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
581 locations->SetOut(Location::RequiresRegister());
582 constant->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000583}
584
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000585void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100586 codegen_->Move(constant, constant->GetLocations()->Out(), nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000587}
588
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100589void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100590 // TODO: Support constant locations.
591 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
592 locations->SetOut(Location::RequiresRegister());
593 constant->SetLocations(locations);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100594}
595
596void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
597 // Will be generated at use site.
598}
599
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000600void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000601 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000602}
603
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000604void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
605 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000606 __ ret();
607}
608
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000609void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000610 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100611 switch (ret->InputAt(0)->GetType()) {
612 case Primitive::kPrimBoolean:
613 case Primitive::kPrimByte:
614 case Primitive::kPrimChar:
615 case Primitive::kPrimShort:
616 case Primitive::kPrimInt:
617 case Primitive::kPrimNot:
618 locations->SetInAt(0, X86CpuLocation(EAX));
619 break;
620
621 case Primitive::kPrimLong:
622 locations->SetInAt(
623 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
624 break;
625
626 default:
627 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
628 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000629 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000630}
631
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000632void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100633 if (kIsDebugBuild) {
634 switch (ret->InputAt(0)->GetType()) {
635 case Primitive::kPrimBoolean:
636 case Primitive::kPrimByte:
637 case Primitive::kPrimChar:
638 case Primitive::kPrimShort:
639 case Primitive::kPrimInt:
640 case Primitive::kPrimNot:
641 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
642 break;
643
644 case Primitive::kPrimLong:
645 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
646 break;
647
648 default:
649 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
650 }
651 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000652 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000653 __ ret();
654}
655
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000656void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
657 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100658 locations->AddTemp(X86CpuLocation(EAX));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100659
660 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100661 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100662 HInstruction* input = invoke->InputAt(i);
663 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
664 }
665
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100666 switch (invoke->GetType()) {
667 case Primitive::kPrimBoolean:
668 case Primitive::kPrimByte:
669 case Primitive::kPrimChar:
670 case Primitive::kPrimShort:
671 case Primitive::kPrimInt:
672 case Primitive::kPrimNot:
673 locations->SetOut(X86CpuLocation(EAX));
674 break;
675
676 case Primitive::kPrimLong:
677 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
678 break;
679
680 case Primitive::kPrimVoid:
681 break;
682
683 case Primitive::kPrimDouble:
684 case Primitive::kPrimFloat:
685 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
686 break;
687 }
688
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000689 invoke->SetLocations(locations);
690}
691
692void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100693 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000694 size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100695 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000696
697 // TODO: Implement all kinds of calls:
698 // 1) boot -> boot
699 // 2) app -> boot
700 // 3) app -> app
701 //
702 // Currently we implement the app -> app logic, which looks up in the resolve cache.
703
704 // temp = method;
705 LoadCurrentMethod(temp);
706 // temp = temp->dex_cache_resolved_methods_;
707 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
708 // temp = temp[index_in_cache]
709 __ movl(temp, Address(temp, index_in_cache));
710 // (temp + offset_of_quick_compiled_code)()
711 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
712
713 codegen_->RecordPcInfo(invoke->GetDexPc());
714}
715
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000716void LocationsBuilderX86::VisitAdd(HAdd* add) {
717 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
718 switch (add->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100719 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100720 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100721 locations->SetInAt(0, Location::RequiresRegister());
722 locations->SetInAt(1, Location::Any());
723 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100724 break;
725 }
726
727 case Primitive::kPrimBoolean:
728 case Primitive::kPrimByte:
729 case Primitive::kPrimChar:
730 case Primitive::kPrimShort:
731 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
732 break;
733
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000734 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100735 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000736 }
737 add->SetLocations(locations);
738}
739
740void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
741 LocationSummary* locations = add->GetLocations();
742 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100743 case Primitive::kPrimInt: {
744 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
745 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100746 if (locations->InAt(1).IsRegister()) {
747 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
748 locations->InAt(1).AsX86().AsCpuRegister());
749 } else {
750 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
751 Address(ESP, locations->InAt(1).GetStackIndex()));
752 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000753 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100754 }
755
756 case Primitive::kPrimLong: {
757 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
758 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100759 if (locations->InAt(1).IsRegister()) {
760 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
761 locations->InAt(1).AsX86().AsRegisterPairLow());
762 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
763 locations->InAt(1).AsX86().AsRegisterPairHigh());
764 } else {
765 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
766 Address(ESP, locations->InAt(1).GetStackIndex()));
767 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
768 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
769 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100770 break;
771 }
772
773 case Primitive::kPrimBoolean:
774 case Primitive::kPrimByte:
775 case Primitive::kPrimChar:
776 case Primitive::kPrimShort:
777 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
778 break;
779
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000780 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100781 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000782 }
783}
784
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100785void LocationsBuilderX86::VisitSub(HSub* sub) {
786 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
787 switch (sub->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100788 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100789 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100790 locations->SetInAt(0, Location::RequiresRegister());
791 locations->SetInAt(1, Location::Any());
792 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100793 break;
794 }
795
796 case Primitive::kPrimBoolean:
797 case Primitive::kPrimByte:
798 case Primitive::kPrimChar:
799 case Primitive::kPrimShort:
800 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
801 break;
802
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100803 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100804 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100805 }
806 sub->SetLocations(locations);
807}
808
809void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
810 LocationSummary* locations = sub->GetLocations();
811 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100812 case Primitive::kPrimInt: {
813 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
814 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100815 if (locations->InAt(1).IsRegister()) {
816 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
817 locations->InAt(1).AsX86().AsCpuRegister());
818 } else {
819 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
820 Address(ESP, locations->InAt(1).GetStackIndex()));
821 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100822 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100823 }
824
825 case Primitive::kPrimLong: {
826 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
827 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100828 if (locations->InAt(1).IsRegister()) {
829 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
830 locations->InAt(1).AsX86().AsRegisterPairLow());
831 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
832 locations->InAt(1).AsX86().AsRegisterPairHigh());
833 } else {
834 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
835 Address(ESP, locations->InAt(1).GetStackIndex()));
836 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
837 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
838 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100839 break;
840 }
841
842 case Primitive::kPrimBoolean:
843 case Primitive::kPrimByte:
844 case Primitive::kPrimChar:
845 case Primitive::kPrimShort:
846 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
847 break;
848
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100849 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100850 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100851 }
852}
853
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100854void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
855 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100856 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100857 InvokeRuntimeCallingConvention calling_convention;
858 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0)));
859 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100860 instruction->SetLocations(locations);
861}
862
863void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
864 InvokeRuntimeCallingConvention calling_convention;
865 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100866 __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100867
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100868 __ fs()->call(
869 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100870
871 codegen_->RecordPcInfo(instruction->GetDexPc());
872}
873
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100874void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
875 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100876 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
877 if (location.IsStackSlot()) {
878 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
879 } else if (location.IsDoubleStackSlot()) {
880 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100881 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100882 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100883 instruction->SetLocations(locations);
884}
885
886void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100887}
888
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100889void LocationsBuilderX86::VisitNot(HNot* instruction) {
890 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100891 locations->SetInAt(0, Location::RequiresRegister());
892 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100893 instruction->SetLocations(locations);
894}
895
896void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
897 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100898 Location out = locations->Out();
899 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), out.AsX86().AsCpuRegister());
900 __ xorl(out.AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100901}
902
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100903void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100904 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
905 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
906 locations->SetInAt(i, Location::Any());
907 }
908 locations->SetOut(Location::Any());
909 instruction->SetLocations(locations);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100910}
911
912void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100913 LOG(FATAL) << "Unreachable";
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100914}
915
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100916void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100917 LOG(FATAL) << "Unreachable";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100918}
919
920void InstructionCodeGeneratorX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100921 codegen_->GetMoveResolver()->EmitNativeCode(instruction);
922}
923
924X86Assembler* ParallelMoveResolverX86::GetAssembler() const {
925 return codegen_->GetAssembler();
926}
927
928void ParallelMoveResolverX86::MoveMemoryToMemory(int dst, int src) {
929 ScratchRegisterScope ensure_scratch(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100930 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100931 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
932 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, src + stack_offset));
933 __ movl(Address(ESP, dst + stack_offset), static_cast<Register>(ensure_scratch.GetRegister()));
934}
935
936void ParallelMoveResolverX86::EmitMove(size_t index) {
937 MoveOperands* move = moves_.Get(index);
938 Location source = move->GetSource();
939 Location destination = move->GetDestination();
940
941 if (source.IsRegister()) {
942 if (destination.IsRegister()) {
943 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
944 } else {
945 DCHECK(destination.IsStackSlot());
946 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
947 }
948 } else if (source.IsStackSlot()) {
949 if (destination.IsRegister()) {
950 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
951 } else {
952 DCHECK(destination.IsStackSlot());
953 MoveMemoryToMemory(destination.GetStackIndex(),
954 source.GetStackIndex());
955 }
956 } else {
957 LOG(FATAL) << "Unimplemented";
958 }
959}
960
961void ParallelMoveResolverX86::Exchange(Register reg, int mem) {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100962 Register suggested_scratch = reg == EAX ? EBX : EAX;
963 ScratchRegisterScope ensure_scratch(
964 this, reg, suggested_scratch, codegen_->GetNumberOfCoreRegisters());
965
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100966 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
967 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, mem + stack_offset));
968 __ movl(Address(ESP, mem + stack_offset), reg);
969 __ movl(reg, static_cast<Register>(ensure_scratch.GetRegister()));
970}
971
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100972void ParallelMoveResolverX86::Exchange(int mem1, int mem2) {
973 ScratchRegisterScope ensure_scratch1(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100974 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
975
976 Register suggested_scratch = ensure_scratch1.GetRegister() == EAX ? EBX : EAX;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100977 ScratchRegisterScope ensure_scratch2(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100978 this, ensure_scratch1.GetRegister(), suggested_scratch, codegen_->GetNumberOfCoreRegisters());
979
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100980 int stack_offset = ensure_scratch1.IsSpilled() ? kX86WordSize : 0;
981 stack_offset += ensure_scratch2.IsSpilled() ? kX86WordSize : 0;
982 __ movl(static_cast<Register>(ensure_scratch1.GetRegister()), Address(ESP, mem1 + stack_offset));
983 __ movl(static_cast<Register>(ensure_scratch2.GetRegister()), Address(ESP, mem2 + stack_offset));
984 __ movl(Address(ESP, mem2 + stack_offset), static_cast<Register>(ensure_scratch1.GetRegister()));
985 __ movl(Address(ESP, mem1 + stack_offset), static_cast<Register>(ensure_scratch2.GetRegister()));
986}
987
988void ParallelMoveResolverX86::EmitSwap(size_t index) {
989 MoveOperands* move = moves_.Get(index);
990 Location source = move->GetSource();
991 Location destination = move->GetDestination();
992
993 if (source.IsRegister() && destination.IsRegister()) {
994 __ xchgl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
995 } else if (source.IsRegister() && destination.IsStackSlot()) {
996 Exchange(source.AsX86().AsCpuRegister(), destination.GetStackIndex());
997 } else if (source.IsStackSlot() && destination.IsRegister()) {
998 Exchange(destination.AsX86().AsCpuRegister(), source.GetStackIndex());
999 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
1000 Exchange(destination.GetStackIndex(), source.GetStackIndex());
1001 } else {
1002 LOG(FATAL) << "Unimplemented";
1003 }
1004}
1005
1006void ParallelMoveResolverX86::SpillScratch(int reg) {
1007 __ pushl(static_cast<Register>(reg));
1008}
1009
1010void ParallelMoveResolverX86::RestoreScratch(int reg) {
1011 __ popl(static_cast<Register>(reg));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001012}
1013
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001014} // namespace x86
1015} // namespace art