blob: 52cb39dc7f98be4113a5b4e5e1af9897ca302c7e [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 Geoffrayd4dd2552014-02-28 10:23:58 +000027namespace art {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010028
29x86::X86ManagedRegister Location::AsX86() const {
30 return reg().AsX86();
31}
32
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000033namespace x86 {
34
Nicolas Geoffraye5038322014-07-04 09:41:32 +010035#define __ reinterpret_cast<X86Assembler*>(codegen->GetAssembler())->
36
37class NullCheckSlowPathX86 : public SlowPathCode {
38 public:
39 explicit NullCheckSlowPathX86(uint32_t dex_pc) : dex_pc_(dex_pc) {}
40
41 virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
42 __ Bind(GetEntryLabel());
43 __ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pThrowNullPointer)));
44 codegen->RecordPcInfo(dex_pc_);
45 }
46
47 private:
48 const uint32_t dex_pc_;
49 DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathX86);
50};
51
52#undef __
53#define __ reinterpret_cast<X86Assembler*>(GetAssembler())->
54
Dave Allison20dfc792014-06-16 20:44:29 -070055inline Condition X86Condition(IfCondition cond) {
56 switch (cond) {
57 case kCondEQ: return kEqual;
58 case kCondNE: return kNotEqual;
59 case kCondLT: return kLess;
60 case kCondLE: return kLessEqual;
61 case kCondGT: return kGreater;
62 case kCondGE: return kGreaterEqual;
63 default:
64 LOG(FATAL) << "Unknown if condition";
65 }
66 return kEqual;
67}
68
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010069static constexpr int kNumberOfPushedRegistersAtEntry = 1;
70static constexpr int kCurrentMethodStackOffset = 0;
71
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010072void CodeGeneratorX86::DumpCoreRegister(std::ostream& stream, int reg) const {
73 stream << X86ManagedRegister::FromCpuRegister(Register(reg));
74}
75
76void CodeGeneratorX86::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
77 stream << X86ManagedRegister::FromXmmRegister(XmmRegister(reg));
78}
79
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010080CodeGeneratorX86::CodeGeneratorX86(HGraph* graph)
81 : CodeGenerator(graph, kNumberOfRegIds),
82 location_builder_(graph, this),
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010083 instruction_visitor_(graph, this),
84 move_resolver_(graph->GetArena(), this) {}
85
86void CodeGeneratorX86::ComputeFrameSize(size_t number_of_spill_slots) {
87 SetFrameSize(RoundUp(
88 number_of_spill_slots * kVRegSize
89 + kVRegSize // Art method
90 + kNumberOfPushedRegistersAtEntry * kX86WordSize,
91 kStackAlignment));
92}
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010093
94static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
95 return blocked_registers + kNumberOfAllocIds;
96}
97
98ManagedRegister CodeGeneratorX86::AllocateFreeRegister(Primitive::Type type,
99 bool* blocked_registers) const {
100 switch (type) {
101 case Primitive::kPrimLong: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100102 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
103 size_t reg = AllocateFreeRegisterInternal(blocked_register_pairs, kNumberOfRegisterPairs);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100104 X86ManagedRegister pair =
105 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg));
106 blocked_registers[pair.AsRegisterPairLow()] = true;
107 blocked_registers[pair.AsRegisterPairHigh()] = true;
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100108 // Block all other register pairs that share a register with `pair`.
109 for (int i = 0; i < kNumberOfRegisterPairs; i++) {
110 X86ManagedRegister current =
111 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(i));
112 if (current.AsRegisterPairLow() == pair.AsRegisterPairLow()
113 || current.AsRegisterPairLow() == pair.AsRegisterPairHigh()
114 || current.AsRegisterPairHigh() == pair.AsRegisterPairLow()
115 || current.AsRegisterPairHigh() == pair.AsRegisterPairHigh()) {
116 blocked_register_pairs[i] = true;
117 }
118 }
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100119 return pair;
120 }
121
122 case Primitive::kPrimByte:
123 case Primitive::kPrimBoolean:
124 case Primitive::kPrimChar:
125 case Primitive::kPrimShort:
126 case Primitive::kPrimInt:
127 case Primitive::kPrimNot: {
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100128 Register reg = static_cast<Register>(
129 AllocateFreeRegisterInternal(blocked_registers, kNumberOfCpuRegisters));
130 // Block all register pairs that contain `reg`.
131 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
132 for (int i = 0; i < kNumberOfRegisterPairs; i++) {
133 X86ManagedRegister current =
134 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(i));
135 if (current.AsRegisterPairLow() == reg || current.AsRegisterPairHigh() == reg) {
136 blocked_register_pairs[i] = true;
137 }
138 }
139 return X86ManagedRegister::FromCpuRegister(reg);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100140 }
141
142 case Primitive::kPrimFloat:
143 case Primitive::kPrimDouble:
144 LOG(FATAL) << "Unimplemented register type " << type;
145
146 case Primitive::kPrimVoid:
147 LOG(FATAL) << "Unreachable type " << type;
148 }
149
150 return ManagedRegister::NoRegister();
151}
152
153void CodeGeneratorX86::SetupBlockedRegisters(bool* blocked_registers) const {
154 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
155
156 // Don't allocate the dalvik style register pair passing.
157 blocked_register_pairs[ECX_EDX] = true;
158
159 // Stack register is always reserved.
160 blocked_registers[ESP] = true;
161
162 // TODO: We currently don't use Quick's callee saved registers.
163 blocked_registers[EBP] = true;
164 blocked_registers[ESI] = true;
165 blocked_registers[EDI] = true;
166 blocked_register_pairs[EAX_EDI] = true;
167 blocked_register_pairs[EDX_EDI] = true;
168 blocked_register_pairs[ECX_EDI] = true;
169 blocked_register_pairs[EBX_EDI] = true;
170}
171
172size_t CodeGeneratorX86::GetNumberOfRegisters() const {
173 return kNumberOfRegIds;
174}
175
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100176static Location X86CpuLocation(Register reg) {
177 return Location::RegisterLocation(X86ManagedRegister::FromCpuRegister(reg));
178}
179
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100180InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen)
181 : HGraphVisitor(graph),
182 assembler_(codegen->GetAssembler()),
183 codegen_(codegen) {}
184
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000185void CodeGeneratorX86::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000186 // Create a fake register to mimic Quick.
187 static const int kFakeReturnRegister = 8;
188 core_spill_mask_ |= (1 << kFakeReturnRegister);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000189
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100190 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100191 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100192 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000193}
194
195void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100196 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000197}
198
199void CodeGeneratorX86::Bind(Label* label) {
200 __ Bind(label);
201}
202
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000203void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100204 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000205}
206
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100207Location CodeGeneratorX86::GetTemporaryLocation(HTemporary* temp) const {
208 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
209 // Use the temporary region (right below the dex registers).
210 int32_t slot = GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
211 - kVRegSize // filler
212 - (number_of_vregs * kVRegSize)
213 - ((1 + temp->GetIndex()) * kVRegSize);
214 return Location::StackSlot(slot);
215}
216
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100217int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100218 uint16_t reg_number = local->GetRegNumber();
219 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
220 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
221 if (reg_number >= number_of_vregs - number_of_in_vregs) {
222 // Local is a parameter of the method. It is stored in the caller's frame.
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100223 return GetFrameSize() + kVRegSize // ART method
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100224 + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100225 } else {
226 // Local is a temporary in this method. It is stored in this method's frame.
227 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100228 - kVRegSize // filler.
229 - (number_of_vregs * kVRegSize)
230 + (reg_number * kVRegSize);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100231 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100232}
233
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100234
235Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
236 switch (load->GetType()) {
237 case Primitive::kPrimLong:
238 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
239 break;
240
241 case Primitive::kPrimInt:
242 case Primitive::kPrimNot:
243 return Location::StackSlot(GetStackSlot(load->GetLocal()));
244
245 case Primitive::kPrimFloat:
246 case Primitive::kPrimDouble:
247 LOG(FATAL) << "Unimplemented type " << load->GetType();
248
249 case Primitive::kPrimBoolean:
250 case Primitive::kPrimByte:
251 case Primitive::kPrimChar:
252 case Primitive::kPrimShort:
253 case Primitive::kPrimVoid:
254 LOG(FATAL) << "Unexpected type " << load->GetType();
255 }
256
257 LOG(FATAL) << "Unreachable";
258 return Location();
259}
260
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100261static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
262static constexpr size_t kRuntimeParameterCoreRegistersLength =
263 arraysize(kRuntimeParameterCoreRegisters);
264
265class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
266 public:
267 InvokeRuntimeCallingConvention()
268 : CallingConvention(kRuntimeParameterCoreRegisters,
269 kRuntimeParameterCoreRegistersLength) {}
270
271 private:
272 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
273};
274
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100275Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
276 switch (type) {
277 case Primitive::kPrimBoolean:
278 case Primitive::kPrimByte:
279 case Primitive::kPrimChar:
280 case Primitive::kPrimShort:
281 case Primitive::kPrimInt:
282 case Primitive::kPrimNot: {
283 uint32_t index = gp_index_++;
284 if (index < calling_convention.GetNumberOfRegisters()) {
285 return X86CpuLocation(calling_convention.GetRegisterAt(index));
286 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100287 return Location::StackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100288 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100289 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100290
291 case Primitive::kPrimLong: {
292 uint32_t index = gp_index_;
293 gp_index_ += 2;
294 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
295 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
296 calling_convention.GetRegisterPairAt(index)));
297 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
298 return Location::QuickParameter(index);
299 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100300 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100301 }
302 }
303
304 case Primitive::kPrimDouble:
305 case Primitive::kPrimFloat:
306 LOG(FATAL) << "Unimplemented parameter type " << type;
307 break;
308
309 case Primitive::kPrimVoid:
310 LOG(FATAL) << "Unexpected parameter type " << type;
311 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100312 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100313 return Location();
314}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100315
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100316void CodeGeneratorX86::Move32(Location destination, Location source) {
317 if (source.Equals(destination)) {
318 return;
319 }
320 if (destination.IsRegister()) {
321 if (source.IsRegister()) {
322 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
323 } else {
324 DCHECK(source.IsStackSlot());
325 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
326 }
327 } else {
328 if (source.IsRegister()) {
329 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
330 } else {
331 DCHECK(source.IsStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100332 __ pushl(Address(ESP, source.GetStackIndex()));
333 __ popl(Address(ESP, destination.GetStackIndex()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100334 }
335 }
336}
337
338void CodeGeneratorX86::Move64(Location destination, Location source) {
339 if (source.Equals(destination)) {
340 return;
341 }
342 if (destination.IsRegister()) {
343 if (source.IsRegister()) {
344 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
345 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
346 } else if (source.IsQuickParameter()) {
347 uint32_t argument_index = source.GetQuickParameterIndex();
348 InvokeDexCallingConvention calling_convention;
349 __ movl(destination.AsX86().AsRegisterPairLow(),
350 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100351 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100352 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100353 } else {
354 DCHECK(source.IsDoubleStackSlot());
355 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
356 __ movl(destination.AsX86().AsRegisterPairHigh(),
357 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
358 }
359 } else if (destination.IsQuickParameter()) {
360 InvokeDexCallingConvention calling_convention;
361 uint32_t argument_index = destination.GetQuickParameterIndex();
362 if (source.IsRegister()) {
363 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100364 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100365 source.AsX86().AsRegisterPairHigh());
366 } else {
367 DCHECK(source.IsDoubleStackSlot());
368 __ movl(calling_convention.GetRegisterAt(argument_index),
369 Address(ESP, source.GetStackIndex()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100370 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100371 __ popl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100372 }
373 } else {
374 if (source.IsRegister()) {
375 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
376 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
377 source.AsX86().AsRegisterPairHigh());
378 } else if (source.IsQuickParameter()) {
379 InvokeDexCallingConvention calling_convention;
380 uint32_t argument_index = source.GetQuickParameterIndex();
381 __ movl(Address(ESP, destination.GetStackIndex()),
382 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100383 __ pushl(Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100384 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100385 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100386 } else {
387 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100388 __ pushl(Address(ESP, source.GetStackIndex()));
389 __ popl(Address(ESP, destination.GetStackIndex()));
390 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
391 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100392 }
393 }
394}
395
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100396void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
397 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100398 Immediate imm(instruction->AsIntConstant()->GetValue());
399 if (location.IsRegister()) {
400 __ movl(location.AsX86().AsCpuRegister(), imm);
401 } else {
402 __ movl(Address(ESP, location.GetStackIndex()), imm);
403 }
404 } else if (instruction->AsLongConstant() != nullptr) {
405 int64_t value = instruction->AsLongConstant()->GetValue();
406 if (location.IsRegister()) {
407 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
408 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
409 } else {
410 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
411 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
412 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100413 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100414 switch (instruction->GetType()) {
415 case Primitive::kPrimBoolean:
416 case Primitive::kPrimByte:
417 case Primitive::kPrimChar:
418 case Primitive::kPrimShort:
419 case Primitive::kPrimInt:
420 case Primitive::kPrimNot:
421 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
422 break;
423
424 case Primitive::kPrimLong:
425 Move64(location, Location::DoubleStackSlot(
426 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
427 break;
428
429 default:
430 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
431 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000432 } else {
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100433 DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100434 switch (instruction->GetType()) {
435 case Primitive::kPrimBoolean:
436 case Primitive::kPrimByte:
437 case Primitive::kPrimChar:
438 case Primitive::kPrimShort:
439 case Primitive::kPrimInt:
440 case Primitive::kPrimNot:
441 Move32(location, instruction->GetLocations()->Out());
442 break;
443
444 case Primitive::kPrimLong:
445 Move64(location, instruction->GetLocations()->Out());
446 break;
447
448 default:
449 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
450 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000451 }
452}
453
454void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000455 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000456}
457
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000458void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000459 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000460 if (GetGraph()->GetExitBlock() == successor) {
461 codegen_->GenerateFrameExit();
462 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
463 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000464 }
465}
466
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000467void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000468 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000469}
470
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000471void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000472 if (kIsDebugBuild) {
473 __ Comment("Unreachable");
474 __ int3();
475 }
476}
477
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000478void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000479 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100480 HInstruction* cond = if_instr->InputAt(0);
481 DCHECK(cond->IsCondition());
482 HCondition* condition = cond->AsCondition();
483 if (condition->NeedsMaterialization()) {
484 locations->SetInAt(0, Location::Any());
485 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000486 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000487}
488
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000489void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Dave Allison20dfc792014-06-16 20:44:29 -0700490 HInstruction* cond = if_instr->InputAt(0);
491 DCHECK(cond->IsCondition());
492 HCondition* condition = cond->AsCondition();
493 if (condition->NeedsMaterialization()) {
494 // Materialized condition, compare against 0
495 Location lhs = if_instr->GetLocations()->InAt(0);
496 if (lhs.IsRegister()) {
497 __ cmpl(lhs.AsX86().AsCpuRegister(), Immediate(0));
498 } else {
499 __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0));
500 }
501 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100502 } else {
Dave Allison20dfc792014-06-16 20:44:29 -0700503 Location lhs = condition->GetLocations()->InAt(0);
504 Location rhs = condition->GetLocations()->InAt(1);
505 // LHS is guaranteed to be in a register (see LocationsBuilderX86::VisitCondition).
506 if (rhs.IsRegister()) {
507 __ cmpl(lhs.AsX86().AsCpuRegister(), rhs.AsX86().AsCpuRegister());
508 } else {
509 __ cmpl(lhs.AsX86().AsCpuRegister(), Address(ESP, rhs.GetStackIndex()));
510 }
511 __ j(X86Condition(condition->GetCondition()),
512 codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100513 }
Dave Allison20dfc792014-06-16 20:44:29 -0700514 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) {
515 __ jmp(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000516 }
517}
518
519void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000520 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000521}
522
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000523void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
524 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000525}
526
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000527void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100528 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000529}
530
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000531void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100532 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000533}
534
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100535void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
536 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
537 switch (store->InputAt(1)->GetType()) {
538 case Primitive::kPrimBoolean:
539 case Primitive::kPrimByte:
540 case Primitive::kPrimChar:
541 case Primitive::kPrimShort:
542 case Primitive::kPrimInt:
543 case Primitive::kPrimNot:
544 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
545 break;
546
547 case Primitive::kPrimLong:
548 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
549 break;
550
551 default:
552 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
553 }
554 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000555}
556
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000557void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000558}
559
Dave Allison20dfc792014-06-16 20:44:29 -0700560void LocationsBuilderX86::VisitCondition(HCondition* comp) {
561 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100562 locations->SetInAt(0, Location::RequiresRegister());
563 locations->SetInAt(1, Location::Any());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100564 if (comp->NeedsMaterialization()) {
565 locations->SetOut(Location::SameAsFirstInput());
566 }
Dave Allison20dfc792014-06-16 20:44:29 -0700567 comp->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000568}
569
Dave Allison20dfc792014-06-16 20:44:29 -0700570void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) {
571 if (comp->NeedsMaterialization()) {
572 LocationSummary* locations = comp->GetLocations();
573 if (locations->InAt(1).IsRegister()) {
574 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
575 locations->InAt(1).AsX86().AsCpuRegister());
576 } else {
577 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
578 Address(ESP, locations->InAt(1).GetStackIndex()));
579 }
580 __ setb(X86Condition(comp->GetCondition()), locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100581 }
Dave Allison20dfc792014-06-16 20:44:29 -0700582}
583
584void LocationsBuilderX86::VisitEqual(HEqual* comp) {
585 VisitCondition(comp);
586}
587
588void InstructionCodeGeneratorX86::VisitEqual(HEqual* comp) {
589 VisitCondition(comp);
590}
591
592void LocationsBuilderX86::VisitNotEqual(HNotEqual* comp) {
593 VisitCondition(comp);
594}
595
596void InstructionCodeGeneratorX86::VisitNotEqual(HNotEqual* comp) {
597 VisitCondition(comp);
598}
599
600void LocationsBuilderX86::VisitLessThan(HLessThan* comp) {
601 VisitCondition(comp);
602}
603
604void InstructionCodeGeneratorX86::VisitLessThan(HLessThan* comp) {
605 VisitCondition(comp);
606}
607
608void LocationsBuilderX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
609 VisitCondition(comp);
610}
611
612void InstructionCodeGeneratorX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
613 VisitCondition(comp);
614}
615
616void LocationsBuilderX86::VisitGreaterThan(HGreaterThan* comp) {
617 VisitCondition(comp);
618}
619
620void InstructionCodeGeneratorX86::VisitGreaterThan(HGreaterThan* comp) {
621 VisitCondition(comp);
622}
623
624void LocationsBuilderX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
625 VisitCondition(comp);
626}
627
628void InstructionCodeGeneratorX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
629 VisitCondition(comp);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000630}
631
632void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100633 // TODO: Support constant locations.
634 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
635 locations->SetOut(Location::RequiresRegister());
636 constant->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000637}
638
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000639void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100640 codegen_->Move(constant, constant->GetLocations()->Out(), nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000641}
642
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100643void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100644 // TODO: Support constant locations.
645 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
646 locations->SetOut(Location::RequiresRegister());
647 constant->SetLocations(locations);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100648}
649
650void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
651 // Will be generated at use site.
652}
653
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000654void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000655 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000656}
657
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000658void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
659 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000660 __ ret();
661}
662
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000663void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000664 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100665 switch (ret->InputAt(0)->GetType()) {
666 case Primitive::kPrimBoolean:
667 case Primitive::kPrimByte:
668 case Primitive::kPrimChar:
669 case Primitive::kPrimShort:
670 case Primitive::kPrimInt:
671 case Primitive::kPrimNot:
672 locations->SetInAt(0, X86CpuLocation(EAX));
673 break;
674
675 case Primitive::kPrimLong:
676 locations->SetInAt(
677 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
678 break;
679
680 default:
681 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
682 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000683 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000684}
685
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000686void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100687 if (kIsDebugBuild) {
688 switch (ret->InputAt(0)->GetType()) {
689 case Primitive::kPrimBoolean:
690 case Primitive::kPrimByte:
691 case Primitive::kPrimChar:
692 case Primitive::kPrimShort:
693 case Primitive::kPrimInt:
694 case Primitive::kPrimNot:
695 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
696 break;
697
698 case Primitive::kPrimLong:
699 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
700 break;
701
702 default:
703 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
704 }
705 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000706 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000707 __ ret();
708}
709
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000710void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
711 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100712 locations->AddTemp(X86CpuLocation(EAX));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100713
714 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100715 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100716 HInstruction* input = invoke->InputAt(i);
717 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
718 }
719
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100720 switch (invoke->GetType()) {
721 case Primitive::kPrimBoolean:
722 case Primitive::kPrimByte:
723 case Primitive::kPrimChar:
724 case Primitive::kPrimShort:
725 case Primitive::kPrimInt:
726 case Primitive::kPrimNot:
727 locations->SetOut(X86CpuLocation(EAX));
728 break;
729
730 case Primitive::kPrimLong:
731 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
732 break;
733
734 case Primitive::kPrimVoid:
735 break;
736
737 case Primitive::kPrimDouble:
738 case Primitive::kPrimFloat:
739 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
740 break;
741 }
742
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000743 invoke->SetLocations(locations);
744}
745
746void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100747 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffrayf61b5372014-06-25 14:35:34 +0100748 uint32_t heap_reference_size = sizeof(mirror::HeapReference<mirror::Object>);
749 size_t index_in_cache = mirror::Array::DataOffset(heap_reference_size).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100750 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000751
752 // TODO: Implement all kinds of calls:
753 // 1) boot -> boot
754 // 2) app -> boot
755 // 3) app -> app
756 //
757 // Currently we implement the app -> app logic, which looks up in the resolve cache.
758
759 // temp = method;
760 LoadCurrentMethod(temp);
761 // temp = temp->dex_cache_resolved_methods_;
762 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
763 // temp = temp[index_in_cache]
764 __ movl(temp, Address(temp, index_in_cache));
765 // (temp + offset_of_quick_compiled_code)()
766 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
767
768 codegen_->RecordPcInfo(invoke->GetDexPc());
769}
770
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000771void LocationsBuilderX86::VisitAdd(HAdd* add) {
772 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
773 switch (add->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100774 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100775 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100776 locations->SetInAt(0, Location::RequiresRegister());
777 locations->SetInAt(1, Location::Any());
778 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100779 break;
780 }
781
782 case Primitive::kPrimBoolean:
783 case Primitive::kPrimByte:
784 case Primitive::kPrimChar:
785 case Primitive::kPrimShort:
786 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
787 break;
788
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000789 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100790 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000791 }
792 add->SetLocations(locations);
793}
794
795void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
796 LocationSummary* locations = add->GetLocations();
797 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100798 case Primitive::kPrimInt: {
799 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
800 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100801 if (locations->InAt(1).IsRegister()) {
802 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
803 locations->InAt(1).AsX86().AsCpuRegister());
804 } else {
805 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
806 Address(ESP, locations->InAt(1).GetStackIndex()));
807 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000808 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100809 }
810
811 case Primitive::kPrimLong: {
812 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
813 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100814 if (locations->InAt(1).IsRegister()) {
815 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
816 locations->InAt(1).AsX86().AsRegisterPairLow());
817 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
818 locations->InAt(1).AsX86().AsRegisterPairHigh());
819 } else {
820 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
821 Address(ESP, locations->InAt(1).GetStackIndex()));
822 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
823 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
824 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100825 break;
826 }
827
828 case Primitive::kPrimBoolean:
829 case Primitive::kPrimByte:
830 case Primitive::kPrimChar:
831 case Primitive::kPrimShort:
832 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
833 break;
834
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000835 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100836 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000837 }
838}
839
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100840void LocationsBuilderX86::VisitSub(HSub* sub) {
841 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
842 switch (sub->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100843 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100844 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100845 locations->SetInAt(0, Location::RequiresRegister());
846 locations->SetInAt(1, Location::Any());
847 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100848 break;
849 }
850
851 case Primitive::kPrimBoolean:
852 case Primitive::kPrimByte:
853 case Primitive::kPrimChar:
854 case Primitive::kPrimShort:
855 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
856 break;
857
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100858 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100859 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100860 }
861 sub->SetLocations(locations);
862}
863
864void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
865 LocationSummary* locations = sub->GetLocations();
866 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100867 case Primitive::kPrimInt: {
868 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
869 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100870 if (locations->InAt(1).IsRegister()) {
871 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
872 locations->InAt(1).AsX86().AsCpuRegister());
873 } else {
874 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
875 Address(ESP, locations->InAt(1).GetStackIndex()));
876 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100877 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100878 }
879
880 case Primitive::kPrimLong: {
881 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
882 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100883 if (locations->InAt(1).IsRegister()) {
884 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
885 locations->InAt(1).AsX86().AsRegisterPairLow());
886 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
887 locations->InAt(1).AsX86().AsRegisterPairHigh());
888 } else {
889 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
890 Address(ESP, locations->InAt(1).GetStackIndex()));
891 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
892 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
893 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100894 break;
895 }
896
897 case Primitive::kPrimBoolean:
898 case Primitive::kPrimByte:
899 case Primitive::kPrimChar:
900 case Primitive::kPrimShort:
901 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
902 break;
903
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100904 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100905 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100906 }
907}
908
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100909void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
910 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100911 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100912 InvokeRuntimeCallingConvention calling_convention;
913 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0)));
914 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100915 instruction->SetLocations(locations);
916}
917
918void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
919 InvokeRuntimeCallingConvention calling_convention;
920 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100921 __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100922
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100923 __ fs()->call(
924 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100925
926 codegen_->RecordPcInfo(instruction->GetDexPc());
927}
928
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100929void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
930 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100931 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
932 if (location.IsStackSlot()) {
933 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
934 } else if (location.IsDoubleStackSlot()) {
935 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100936 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100937 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100938 instruction->SetLocations(locations);
939}
940
941void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100942}
943
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100944void LocationsBuilderX86::VisitNot(HNot* instruction) {
945 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100946 locations->SetInAt(0, Location::RequiresRegister());
947 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100948 instruction->SetLocations(locations);
949}
950
951void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
952 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100953 Location out = locations->Out();
954 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), out.AsX86().AsCpuRegister());
955 __ xorl(out.AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100956}
957
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100958void LocationsBuilderX86::VisitCompare(HCompare* compare) {
959 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
960 locations->SetInAt(0, Location::RequiresRegister());
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100961 locations->SetInAt(1, Location::Any());
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100962 locations->SetOut(Location::RequiresRegister());
963 compare->SetLocations(locations);
964}
965
966void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) {
967 Label greater, done;
968 LocationSummary* locations = compare->GetLocations();
969 switch (compare->InputAt(0)->GetType()) {
970 case Primitive::kPrimLong: {
971 Label less, greater, done;
972 Register output = locations->Out().AsX86().AsCpuRegister();
973 X86ManagedRegister left = locations->InAt(0).AsX86();
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100974 Location right = locations->InAt(1);
975 if (right.IsRegister()) {
976 __ cmpl(left.AsRegisterPairHigh(), right.AsX86().AsRegisterPairHigh());
977 } else {
978 DCHECK(right.IsDoubleStackSlot());
979 __ cmpl(left.AsRegisterPairHigh(), Address(ESP, right.GetHighStackIndex(kX86WordSize)));
980 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100981 __ j(kLess, &less); // Signed compare.
982 __ j(kGreater, &greater); // Signed compare.
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100983 if (right.IsRegister()) {
984 __ cmpl(left.AsRegisterPairLow(), right.AsX86().AsRegisterPairLow());
985 } else {
986 DCHECK(right.IsDoubleStackSlot());
987 __ cmpl(left.AsRegisterPairLow(), Address(ESP, right.GetStackIndex()));
988 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100989 __ movl(output, Immediate(0));
990 __ j(kEqual, &done);
991 __ j(kBelow, &less); // Unsigned compare.
992
993 __ Bind(&greater);
994 __ movl(output, Immediate(1));
995 __ jmp(&done);
996
997 __ Bind(&less);
998 __ movl(output, Immediate(-1));
999
1000 __ Bind(&done);
1001 break;
1002 }
1003 default:
1004 LOG(FATAL) << "Unimplemented compare type " << compare->InputAt(0)->GetType();
1005 }
1006}
1007
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001008void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001009 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1010 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
1011 locations->SetInAt(i, Location::Any());
1012 }
1013 locations->SetOut(Location::Any());
1014 instruction->SetLocations(locations);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001015}
1016
1017void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001018 LOG(FATAL) << "Unreachable";
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001019}
1020
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001021void LocationsBuilderX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
1022 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1023 locations->SetInAt(0, Location::RequiresRegister());
1024 Primitive::Type field_type = instruction->InputAt(1)->GetType();
1025 if (field_type == Primitive::kPrimBoolean || field_type == Primitive::kPrimByte) {
1026 // Ensure the value is in a byte register.
1027 locations->SetInAt(1, X86CpuLocation(EAX));
1028 } else {
1029 locations->SetInAt(1, Location::RequiresRegister());
1030 }
1031 instruction->SetLocations(locations);
1032}
1033
1034void InstructionCodeGeneratorX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
1035 LocationSummary* locations = instruction->GetLocations();
1036 Register obj = locations->InAt(0).AsX86().AsCpuRegister();
1037 uint32_t offset = instruction->GetFieldOffset().Uint32Value();
1038 Primitive::Type field_type = instruction->InputAt(1)->GetType();
1039
1040 switch (field_type) {
1041 case Primitive::kPrimBoolean:
1042 case Primitive::kPrimByte: {
1043 ByteRegister value = locations->InAt(1).AsX86().AsByteRegister();
1044 __ movb(Address(obj, offset), value);
1045 break;
1046 }
1047
1048 case Primitive::kPrimShort:
1049 case Primitive::kPrimChar: {
1050 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1051 __ movw(Address(obj, offset), value);
1052 break;
1053 }
1054
1055 case Primitive::kPrimInt:
1056 case Primitive::kPrimNot: {
1057 Register value = locations->InAt(1).AsX86().AsCpuRegister();
1058 __ movl(Address(obj, offset), value);
1059 break;
1060 }
1061
1062 case Primitive::kPrimLong: {
1063 X86ManagedRegister value = locations->InAt(1).AsX86();
1064 __ movl(Address(obj, offset), value.AsRegisterPairLow());
1065 __ movl(Address(obj, kX86WordSize + offset), value.AsRegisterPairHigh());
1066 break;
1067 }
1068
1069 case Primitive::kPrimFloat:
1070 case Primitive::kPrimDouble:
1071 LOG(FATAL) << "Unimplemented register type " << field_type;
1072
1073 case Primitive::kPrimVoid:
1074 LOG(FATAL) << "Unreachable type " << field_type;
1075 }
1076}
1077
1078void LocationsBuilderX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
1079 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1080 locations->SetInAt(0, Location::RequiresRegister());
1081 locations->SetOut(Location::RequiresRegister());
1082 instruction->SetLocations(locations);
1083}
1084
1085void InstructionCodeGeneratorX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
1086 LocationSummary* locations = instruction->GetLocations();
1087 Register obj = locations->InAt(0).AsX86().AsCpuRegister();
1088 uint32_t offset = instruction->GetFieldOffset().Uint32Value();
1089
1090 switch (instruction->GetType()) {
1091 case Primitive::kPrimBoolean: {
1092 Register out = locations->Out().AsX86().AsCpuRegister();
1093 __ movzxb(out, Address(obj, offset));
1094 break;
1095 }
1096
1097 case Primitive::kPrimByte: {
1098 Register out = locations->Out().AsX86().AsCpuRegister();
1099 __ movsxb(out, Address(obj, offset));
1100 break;
1101 }
1102
1103 case Primitive::kPrimShort: {
1104 Register out = locations->Out().AsX86().AsCpuRegister();
1105 __ movsxw(out, Address(obj, offset));
1106 break;
1107 }
1108
1109 case Primitive::kPrimChar: {
1110 Register out = locations->Out().AsX86().AsCpuRegister();
1111 __ movzxw(out, Address(obj, offset));
1112 break;
1113 }
1114
1115 case Primitive::kPrimInt:
1116 case Primitive::kPrimNot: {
1117 Register out = locations->Out().AsX86().AsCpuRegister();
1118 __ movl(out, Address(obj, offset));
1119 break;
1120 }
1121
1122 case Primitive::kPrimLong: {
1123 // TODO: support volatile.
1124 X86ManagedRegister out = locations->Out().AsX86();
1125 __ movl(out.AsRegisterPairLow(), Address(obj, offset));
1126 __ movl(out.AsRegisterPairHigh(), Address(obj, kX86WordSize + offset));
1127 break;
1128 }
1129
1130 case Primitive::kPrimFloat:
1131 case Primitive::kPrimDouble:
1132 LOG(FATAL) << "Unimplemented register type " << instruction->GetType();
1133
1134 case Primitive::kPrimVoid:
1135 LOG(FATAL) << "Unreachable type " << instruction->GetType();
1136 }
1137}
1138
1139void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
1140 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
1141 locations->SetInAt(0, Location::Any());
1142 // TODO: Have a normalization phase that makes this instruction never used.
1143 locations->SetOut(Location::SameAsFirstInput());
1144 instruction->SetLocations(locations);
1145}
1146
1147void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
1148 SlowPathCode* slow_path =
1149 new (GetGraph()->GetArena()) NullCheckSlowPathX86(instruction->GetDexPc());
1150 codegen_->AddSlowPath(slow_path);
1151
1152 LocationSummary* locations = instruction->GetLocations();
1153 Location obj = locations->InAt(0);
1154 DCHECK(obj.Equals(locations->Out()));
1155
1156 if (obj.IsRegister()) {
1157 __ cmpl(obj.AsX86().AsCpuRegister(), Immediate(0));
1158 } else {
1159 DCHECK(locations->InAt(0).IsStackSlot());
1160 __ cmpl(Address(ESP, obj.GetStackIndex()), Immediate(0));
1161 }
1162 __ j(kEqual, slow_path->GetEntryLabel());
1163}
1164
1165void LocationsBuilderX86::VisitTemporary(HTemporary* temp) {
1166 temp->SetLocations(nullptr);
1167}
1168
1169void InstructionCodeGeneratorX86::VisitTemporary(HTemporary* temp) {
1170 // Nothing to do, this is driven by the code generator.
1171}
1172
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001173void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001174 LOG(FATAL) << "Unreachable";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001175}
1176
1177void InstructionCodeGeneratorX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001178 codegen_->GetMoveResolver()->EmitNativeCode(instruction);
1179}
1180
1181X86Assembler* ParallelMoveResolverX86::GetAssembler() const {
1182 return codegen_->GetAssembler();
1183}
1184
1185void ParallelMoveResolverX86::MoveMemoryToMemory(int dst, int src) {
1186 ScratchRegisterScope ensure_scratch(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001187 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001188 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
1189 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, src + stack_offset));
1190 __ movl(Address(ESP, dst + stack_offset), static_cast<Register>(ensure_scratch.GetRegister()));
1191}
1192
1193void ParallelMoveResolverX86::EmitMove(size_t index) {
1194 MoveOperands* move = moves_.Get(index);
1195 Location source = move->GetSource();
1196 Location destination = move->GetDestination();
1197
1198 if (source.IsRegister()) {
1199 if (destination.IsRegister()) {
1200 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
1201 } else {
1202 DCHECK(destination.IsStackSlot());
1203 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
1204 }
1205 } else if (source.IsStackSlot()) {
1206 if (destination.IsRegister()) {
1207 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
1208 } else {
1209 DCHECK(destination.IsStackSlot());
1210 MoveMemoryToMemory(destination.GetStackIndex(),
1211 source.GetStackIndex());
1212 }
1213 } else {
1214 LOG(FATAL) << "Unimplemented";
1215 }
1216}
1217
1218void ParallelMoveResolverX86::Exchange(Register reg, int mem) {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001219 Register suggested_scratch = reg == EAX ? EBX : EAX;
1220 ScratchRegisterScope ensure_scratch(
1221 this, reg, suggested_scratch, codegen_->GetNumberOfCoreRegisters());
1222
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001223 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
1224 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, mem + stack_offset));
1225 __ movl(Address(ESP, mem + stack_offset), reg);
1226 __ movl(reg, static_cast<Register>(ensure_scratch.GetRegister()));
1227}
1228
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001229void ParallelMoveResolverX86::Exchange(int mem1, int mem2) {
1230 ScratchRegisterScope ensure_scratch1(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001231 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
1232
1233 Register suggested_scratch = ensure_scratch1.GetRegister() == EAX ? EBX : EAX;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001234 ScratchRegisterScope ensure_scratch2(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001235 this, ensure_scratch1.GetRegister(), suggested_scratch, codegen_->GetNumberOfCoreRegisters());
1236
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001237 int stack_offset = ensure_scratch1.IsSpilled() ? kX86WordSize : 0;
1238 stack_offset += ensure_scratch2.IsSpilled() ? kX86WordSize : 0;
1239 __ movl(static_cast<Register>(ensure_scratch1.GetRegister()), Address(ESP, mem1 + stack_offset));
1240 __ movl(static_cast<Register>(ensure_scratch2.GetRegister()), Address(ESP, mem2 + stack_offset));
1241 __ movl(Address(ESP, mem2 + stack_offset), static_cast<Register>(ensure_scratch1.GetRegister()));
1242 __ movl(Address(ESP, mem1 + stack_offset), static_cast<Register>(ensure_scratch2.GetRegister()));
1243}
1244
1245void ParallelMoveResolverX86::EmitSwap(size_t index) {
1246 MoveOperands* move = moves_.Get(index);
1247 Location source = move->GetSource();
1248 Location destination = move->GetDestination();
1249
1250 if (source.IsRegister() && destination.IsRegister()) {
1251 __ xchgl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
1252 } else if (source.IsRegister() && destination.IsStackSlot()) {
1253 Exchange(source.AsX86().AsCpuRegister(), destination.GetStackIndex());
1254 } else if (source.IsStackSlot() && destination.IsRegister()) {
1255 Exchange(destination.AsX86().AsCpuRegister(), source.GetStackIndex());
1256 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
1257 Exchange(destination.GetStackIndex(), source.GetStackIndex());
1258 } else {
1259 LOG(FATAL) << "Unimplemented";
1260 }
1261}
1262
1263void ParallelMoveResolverX86::SpillScratch(int reg) {
1264 __ pushl(static_cast<Register>(reg));
1265}
1266
1267void ParallelMoveResolverX86::RestoreScratch(int reg) {
1268 __ popl(static_cast<Register>(reg));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001269}
1270
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001271} // namespace x86
1272} // namespace art