blob: 572d49471929de8a31cf6b9d18c9b88ac6ce33b6 [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: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +010084 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
85 size_t reg = AllocateFreeRegisterInternal(blocked_register_pairs, kNumberOfRegisterPairs);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010086 X86ManagedRegister pair =
87 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg));
88 blocked_registers[pair.AsRegisterPairLow()] = true;
89 blocked_registers[pair.AsRegisterPairHigh()] = true;
Nicolas Geoffray412f10c2014-06-19 10:00:34 +010090 // Block all other register pairs that share a register with `pair`.
91 for (int i = 0; i < kNumberOfRegisterPairs; i++) {
92 X86ManagedRegister current =
93 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(i));
94 if (current.AsRegisterPairLow() == pair.AsRegisterPairLow()
95 || current.AsRegisterPairLow() == pair.AsRegisterPairHigh()
96 || current.AsRegisterPairHigh() == pair.AsRegisterPairLow()
97 || current.AsRegisterPairHigh() == pair.AsRegisterPairHigh()) {
98 blocked_register_pairs[i] = true;
99 }
100 }
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100101 return pair;
102 }
103
104 case Primitive::kPrimByte:
105 case Primitive::kPrimBoolean:
106 case Primitive::kPrimChar:
107 case Primitive::kPrimShort:
108 case Primitive::kPrimInt:
109 case Primitive::kPrimNot: {
110 size_t reg = AllocateFreeRegisterInternal(blocked_registers, kNumberOfCpuRegisters);
111 return X86ManagedRegister::FromCpuRegister(static_cast<Register>(reg));
112 }
113
114 case Primitive::kPrimFloat:
115 case Primitive::kPrimDouble:
116 LOG(FATAL) << "Unimplemented register type " << type;
117
118 case Primitive::kPrimVoid:
119 LOG(FATAL) << "Unreachable type " << type;
120 }
121
122 return ManagedRegister::NoRegister();
123}
124
125void CodeGeneratorX86::SetupBlockedRegisters(bool* blocked_registers) const {
126 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
127
128 // Don't allocate the dalvik style register pair passing.
129 blocked_register_pairs[ECX_EDX] = true;
130
131 // Stack register is always reserved.
132 blocked_registers[ESP] = true;
133
134 // TODO: We currently don't use Quick's callee saved registers.
135 blocked_registers[EBP] = true;
136 blocked_registers[ESI] = true;
137 blocked_registers[EDI] = true;
138 blocked_register_pairs[EAX_EDI] = true;
139 blocked_register_pairs[EDX_EDI] = true;
140 blocked_register_pairs[ECX_EDI] = true;
141 blocked_register_pairs[EBX_EDI] = true;
142}
143
144size_t CodeGeneratorX86::GetNumberOfRegisters() const {
145 return kNumberOfRegIds;
146}
147
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100148static Location X86CpuLocation(Register reg) {
149 return Location::RegisterLocation(X86ManagedRegister::FromCpuRegister(reg));
150}
151
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100152InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen)
153 : HGraphVisitor(graph),
154 assembler_(codegen->GetAssembler()),
155 codegen_(codegen) {}
156
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000157void CodeGeneratorX86::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000158 // Create a fake register to mimic Quick.
159 static const int kFakeReturnRegister = 8;
160 core_spill_mask_ |= (1 << kFakeReturnRegister);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000161
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100162 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100163 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100164 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000165}
166
167void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100168 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000169}
170
171void CodeGeneratorX86::Bind(Label* label) {
172 __ Bind(label);
173}
174
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000175void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100176 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000177}
178
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100179int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100180 uint16_t reg_number = local->GetRegNumber();
181 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
182 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
183 if (reg_number >= number_of_vregs - number_of_in_vregs) {
184 // Local is a parameter of the method. It is stored in the caller's frame.
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100185 return GetFrameSize() + kVRegSize // ART method
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100186 + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100187 } else {
188 // Local is a temporary in this method. It is stored in this method's frame.
189 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100190 - kVRegSize // filler.
191 - (number_of_vregs * kVRegSize)
192 + (reg_number * kVRegSize);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100193 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100194}
195
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100196
197Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
198 switch (load->GetType()) {
199 case Primitive::kPrimLong:
200 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
201 break;
202
203 case Primitive::kPrimInt:
204 case Primitive::kPrimNot:
205 return Location::StackSlot(GetStackSlot(load->GetLocal()));
206
207 case Primitive::kPrimFloat:
208 case Primitive::kPrimDouble:
209 LOG(FATAL) << "Unimplemented type " << load->GetType();
210
211 case Primitive::kPrimBoolean:
212 case Primitive::kPrimByte:
213 case Primitive::kPrimChar:
214 case Primitive::kPrimShort:
215 case Primitive::kPrimVoid:
216 LOG(FATAL) << "Unexpected type " << load->GetType();
217 }
218
219 LOG(FATAL) << "Unreachable";
220 return Location();
221}
222
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100223static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
224static constexpr size_t kRuntimeParameterCoreRegistersLength =
225 arraysize(kRuntimeParameterCoreRegisters);
226
227class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
228 public:
229 InvokeRuntimeCallingConvention()
230 : CallingConvention(kRuntimeParameterCoreRegisters,
231 kRuntimeParameterCoreRegistersLength) {}
232
233 private:
234 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
235};
236
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100237Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
238 switch (type) {
239 case Primitive::kPrimBoolean:
240 case Primitive::kPrimByte:
241 case Primitive::kPrimChar:
242 case Primitive::kPrimShort:
243 case Primitive::kPrimInt:
244 case Primitive::kPrimNot: {
245 uint32_t index = gp_index_++;
246 if (index < calling_convention.GetNumberOfRegisters()) {
247 return X86CpuLocation(calling_convention.GetRegisterAt(index));
248 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100249 return Location::StackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100250 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100251 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100252
253 case Primitive::kPrimLong: {
254 uint32_t index = gp_index_;
255 gp_index_ += 2;
256 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
257 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
258 calling_convention.GetRegisterPairAt(index)));
259 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
260 return Location::QuickParameter(index);
261 } else {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100262 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100263 }
264 }
265
266 case Primitive::kPrimDouble:
267 case Primitive::kPrimFloat:
268 LOG(FATAL) << "Unimplemented parameter type " << type;
269 break;
270
271 case Primitive::kPrimVoid:
272 LOG(FATAL) << "Unexpected parameter type " << type;
273 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100274 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100275 return Location();
276}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100277
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100278void CodeGeneratorX86::Move32(Location destination, Location source) {
279 if (source.Equals(destination)) {
280 return;
281 }
282 if (destination.IsRegister()) {
283 if (source.IsRegister()) {
284 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
285 } else {
286 DCHECK(source.IsStackSlot());
287 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
288 }
289 } else {
290 if (source.IsRegister()) {
291 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
292 } else {
293 DCHECK(source.IsStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100294 __ pushl(Address(ESP, source.GetStackIndex()));
295 __ popl(Address(ESP, destination.GetStackIndex()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100296 }
297 }
298}
299
300void CodeGeneratorX86::Move64(Location destination, Location source) {
301 if (source.Equals(destination)) {
302 return;
303 }
304 if (destination.IsRegister()) {
305 if (source.IsRegister()) {
306 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
307 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
308 } else if (source.IsQuickParameter()) {
309 uint32_t argument_index = source.GetQuickParameterIndex();
310 InvokeDexCallingConvention calling_convention;
311 __ movl(destination.AsX86().AsRegisterPairLow(),
312 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100313 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100314 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100315 } else {
316 DCHECK(source.IsDoubleStackSlot());
317 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
318 __ movl(destination.AsX86().AsRegisterPairHigh(),
319 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
320 }
321 } else if (destination.IsQuickParameter()) {
322 InvokeDexCallingConvention calling_convention;
323 uint32_t argument_index = destination.GetQuickParameterIndex();
324 if (source.IsRegister()) {
325 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100326 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100327 source.AsX86().AsRegisterPairHigh());
328 } else {
329 DCHECK(source.IsDoubleStackSlot());
330 __ movl(calling_convention.GetRegisterAt(argument_index),
331 Address(ESP, source.GetStackIndex()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100332 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100333 __ popl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100334 }
335 } else {
336 if (source.IsRegister()) {
337 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
338 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
339 source.AsX86().AsRegisterPairHigh());
340 } else if (source.IsQuickParameter()) {
341 InvokeDexCallingConvention calling_convention;
342 uint32_t argument_index = source.GetQuickParameterIndex();
343 __ movl(Address(ESP, destination.GetStackIndex()),
344 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100345 __ pushl(Address(ESP,
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100346 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100347 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100348 } else {
349 DCHECK(source.IsDoubleStackSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100350 __ pushl(Address(ESP, source.GetStackIndex()));
351 __ popl(Address(ESP, destination.GetStackIndex()));
352 __ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
353 __ popl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100354 }
355 }
356}
357
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100358void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
359 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100360 Immediate imm(instruction->AsIntConstant()->GetValue());
361 if (location.IsRegister()) {
362 __ movl(location.AsX86().AsCpuRegister(), imm);
363 } else {
364 __ movl(Address(ESP, location.GetStackIndex()), imm);
365 }
366 } else if (instruction->AsLongConstant() != nullptr) {
367 int64_t value = instruction->AsLongConstant()->GetValue();
368 if (location.IsRegister()) {
369 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
370 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
371 } else {
372 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
373 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
374 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100375 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100376 switch (instruction->GetType()) {
377 case Primitive::kPrimBoolean:
378 case Primitive::kPrimByte:
379 case Primitive::kPrimChar:
380 case Primitive::kPrimShort:
381 case Primitive::kPrimInt:
382 case Primitive::kPrimNot:
383 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
384 break;
385
386 case Primitive::kPrimLong:
387 Move64(location, Location::DoubleStackSlot(
388 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
389 break;
390
391 default:
392 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
393 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000394 } else {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100395 // This can currently only happen when the instruction that requests the move
396 // is the next to be compiled.
397 DCHECK_EQ(instruction->GetNext(), move_for);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100398 switch (instruction->GetType()) {
399 case Primitive::kPrimBoolean:
400 case Primitive::kPrimByte:
401 case Primitive::kPrimChar:
402 case Primitive::kPrimShort:
403 case Primitive::kPrimInt:
404 case Primitive::kPrimNot:
405 Move32(location, instruction->GetLocations()->Out());
406 break;
407
408 case Primitive::kPrimLong:
409 Move64(location, instruction->GetLocations()->Out());
410 break;
411
412 default:
413 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
414 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000415 }
416}
417
418void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000419 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000420}
421
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000422void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000423 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000424 if (GetGraph()->GetExitBlock() == successor) {
425 codegen_->GenerateFrameExit();
426 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
427 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000428 }
429}
430
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000431void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000432 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000433}
434
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000435void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000436 if (kIsDebugBuild) {
437 __ Comment("Unreachable");
438 __ int3();
439 }
440}
441
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000442void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000443 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100444 locations->SetInAt(0, Location::Any());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000445 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000446}
447
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000448void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Dave Allison20dfc792014-06-16 20:44:29 -0700449 HInstruction* cond = if_instr->InputAt(0);
450 DCHECK(cond->IsCondition());
451 HCondition* condition = cond->AsCondition();
452 if (condition->NeedsMaterialization()) {
453 // Materialized condition, compare against 0
454 Location lhs = if_instr->GetLocations()->InAt(0);
455 if (lhs.IsRegister()) {
456 __ cmpl(lhs.AsX86().AsCpuRegister(), Immediate(0));
457 } else {
458 __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0));
459 }
460 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100461 } else {
Dave Allison20dfc792014-06-16 20:44:29 -0700462 Location lhs = condition->GetLocations()->InAt(0);
463 Location rhs = condition->GetLocations()->InAt(1);
464 // LHS is guaranteed to be in a register (see LocationsBuilderX86::VisitCondition).
465 if (rhs.IsRegister()) {
466 __ cmpl(lhs.AsX86().AsCpuRegister(), rhs.AsX86().AsCpuRegister());
467 } else {
468 __ cmpl(lhs.AsX86().AsCpuRegister(), Address(ESP, rhs.GetStackIndex()));
469 }
470 __ j(X86Condition(condition->GetCondition()),
471 codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100472 }
Dave Allison20dfc792014-06-16 20:44:29 -0700473 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) {
474 __ jmp(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000475 }
476}
477
478void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000479 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000480}
481
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000482void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
483 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000484}
485
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000486void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100487 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000488}
489
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000490void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100491 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000492}
493
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100494void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
495 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
496 switch (store->InputAt(1)->GetType()) {
497 case Primitive::kPrimBoolean:
498 case Primitive::kPrimByte:
499 case Primitive::kPrimChar:
500 case Primitive::kPrimShort:
501 case Primitive::kPrimInt:
502 case Primitive::kPrimNot:
503 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
504 break;
505
506 case Primitive::kPrimLong:
507 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
508 break;
509
510 default:
511 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
512 }
513 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000514}
515
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000516void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000517}
518
Dave Allison20dfc792014-06-16 20:44:29 -0700519void LocationsBuilderX86::VisitCondition(HCondition* comp) {
520 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100521 locations->SetInAt(0, Location::RequiresRegister());
522 locations->SetInAt(1, Location::Any());
523 locations->SetOut(Location::SameAsFirstInput());
Dave Allison20dfc792014-06-16 20:44:29 -0700524 comp->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000525}
526
Dave Allison20dfc792014-06-16 20:44:29 -0700527void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) {
528 if (comp->NeedsMaterialization()) {
529 LocationSummary* locations = comp->GetLocations();
530 if (locations->InAt(1).IsRegister()) {
531 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
532 locations->InAt(1).AsX86().AsCpuRegister());
533 } else {
534 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
535 Address(ESP, locations->InAt(1).GetStackIndex()));
536 }
537 __ setb(X86Condition(comp->GetCondition()), locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100538 }
Dave Allison20dfc792014-06-16 20:44:29 -0700539}
540
541void LocationsBuilderX86::VisitEqual(HEqual* comp) {
542 VisitCondition(comp);
543}
544
545void InstructionCodeGeneratorX86::VisitEqual(HEqual* comp) {
546 VisitCondition(comp);
547}
548
549void LocationsBuilderX86::VisitNotEqual(HNotEqual* comp) {
550 VisitCondition(comp);
551}
552
553void InstructionCodeGeneratorX86::VisitNotEqual(HNotEqual* comp) {
554 VisitCondition(comp);
555}
556
557void LocationsBuilderX86::VisitLessThan(HLessThan* comp) {
558 VisitCondition(comp);
559}
560
561void InstructionCodeGeneratorX86::VisitLessThan(HLessThan* comp) {
562 VisitCondition(comp);
563}
564
565void LocationsBuilderX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
566 VisitCondition(comp);
567}
568
569void InstructionCodeGeneratorX86::VisitLessThanOrEqual(HLessThanOrEqual* comp) {
570 VisitCondition(comp);
571}
572
573void LocationsBuilderX86::VisitGreaterThan(HGreaterThan* comp) {
574 VisitCondition(comp);
575}
576
577void InstructionCodeGeneratorX86::VisitGreaterThan(HGreaterThan* comp) {
578 VisitCondition(comp);
579}
580
581void LocationsBuilderX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
582 VisitCondition(comp);
583}
584
585void InstructionCodeGeneratorX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* comp) {
586 VisitCondition(comp);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000587}
588
589void LocationsBuilderX86::VisitIntConstant(HIntConstant* 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 Geoffray3ff386a2014-03-04 14:46:47 +0000594}
595
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000596void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100597 codegen_->Move(constant, constant->GetLocations()->Out(), nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000598}
599
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100600void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100601 // TODO: Support constant locations.
602 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
603 locations->SetOut(Location::RequiresRegister());
604 constant->SetLocations(locations);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100605}
606
607void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
608 // Will be generated at use site.
609}
610
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000611void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000612 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000613}
614
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000615void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
616 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000617 __ ret();
618}
619
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000620void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000621 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100622 switch (ret->InputAt(0)->GetType()) {
623 case Primitive::kPrimBoolean:
624 case Primitive::kPrimByte:
625 case Primitive::kPrimChar:
626 case Primitive::kPrimShort:
627 case Primitive::kPrimInt:
628 case Primitive::kPrimNot:
629 locations->SetInAt(0, X86CpuLocation(EAX));
630 break;
631
632 case Primitive::kPrimLong:
633 locations->SetInAt(
634 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
635 break;
636
637 default:
638 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
639 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000640 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000641}
642
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000643void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100644 if (kIsDebugBuild) {
645 switch (ret->InputAt(0)->GetType()) {
646 case Primitive::kPrimBoolean:
647 case Primitive::kPrimByte:
648 case Primitive::kPrimChar:
649 case Primitive::kPrimShort:
650 case Primitive::kPrimInt:
651 case Primitive::kPrimNot:
652 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
653 break;
654
655 case Primitive::kPrimLong:
656 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
657 break;
658
659 default:
660 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
661 }
662 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000663 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000664 __ ret();
665}
666
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000667void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
668 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100669 locations->AddTemp(X86CpuLocation(EAX));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100670
671 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100672 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100673 HInstruction* input = invoke->InputAt(i);
674 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
675 }
676
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100677 switch (invoke->GetType()) {
678 case Primitive::kPrimBoolean:
679 case Primitive::kPrimByte:
680 case Primitive::kPrimChar:
681 case Primitive::kPrimShort:
682 case Primitive::kPrimInt:
683 case Primitive::kPrimNot:
684 locations->SetOut(X86CpuLocation(EAX));
685 break;
686
687 case Primitive::kPrimLong:
688 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
689 break;
690
691 case Primitive::kPrimVoid:
692 break;
693
694 case Primitive::kPrimDouble:
695 case Primitive::kPrimFloat:
696 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
697 break;
698 }
699
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000700 invoke->SetLocations(locations);
701}
702
703void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100704 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffrayf61b5372014-06-25 14:35:34 +0100705 uint32_t heap_reference_size = sizeof(mirror::HeapReference<mirror::Object>);
706 size_t index_in_cache = mirror::Array::DataOffset(heap_reference_size).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100707 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000708
709 // TODO: Implement all kinds of calls:
710 // 1) boot -> boot
711 // 2) app -> boot
712 // 3) app -> app
713 //
714 // Currently we implement the app -> app logic, which looks up in the resolve cache.
715
716 // temp = method;
717 LoadCurrentMethod(temp);
718 // temp = temp->dex_cache_resolved_methods_;
719 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
720 // temp = temp[index_in_cache]
721 __ movl(temp, Address(temp, index_in_cache));
722 // (temp + offset_of_quick_compiled_code)()
723 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
724
725 codegen_->RecordPcInfo(invoke->GetDexPc());
726}
727
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000728void LocationsBuilderX86::VisitAdd(HAdd* add) {
729 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
730 switch (add->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100731 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100732 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100733 locations->SetInAt(0, Location::RequiresRegister());
734 locations->SetInAt(1, Location::Any());
735 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100736 break;
737 }
738
739 case Primitive::kPrimBoolean:
740 case Primitive::kPrimByte:
741 case Primitive::kPrimChar:
742 case Primitive::kPrimShort:
743 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
744 break;
745
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000746 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100747 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000748 }
749 add->SetLocations(locations);
750}
751
752void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
753 LocationSummary* locations = add->GetLocations();
754 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100755 case Primitive::kPrimInt: {
756 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
757 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100758 if (locations->InAt(1).IsRegister()) {
759 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
760 locations->InAt(1).AsX86().AsCpuRegister());
761 } else {
762 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
763 Address(ESP, locations->InAt(1).GetStackIndex()));
764 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000765 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100766 }
767
768 case Primitive::kPrimLong: {
769 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
770 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100771 if (locations->InAt(1).IsRegister()) {
772 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
773 locations->InAt(1).AsX86().AsRegisterPairLow());
774 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
775 locations->InAt(1).AsX86().AsRegisterPairHigh());
776 } else {
777 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
778 Address(ESP, locations->InAt(1).GetStackIndex()));
779 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
780 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
781 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100782 break;
783 }
784
785 case Primitive::kPrimBoolean:
786 case Primitive::kPrimByte:
787 case Primitive::kPrimChar:
788 case Primitive::kPrimShort:
789 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
790 break;
791
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000792 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100793 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000794 }
795}
796
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100797void LocationsBuilderX86::VisitSub(HSub* sub) {
798 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
799 switch (sub->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100800 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100801 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100802 locations->SetInAt(0, Location::RequiresRegister());
803 locations->SetInAt(1, Location::Any());
804 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100805 break;
806 }
807
808 case Primitive::kPrimBoolean:
809 case Primitive::kPrimByte:
810 case Primitive::kPrimChar:
811 case Primitive::kPrimShort:
812 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
813 break;
814
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100815 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100816 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100817 }
818 sub->SetLocations(locations);
819}
820
821void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
822 LocationSummary* locations = sub->GetLocations();
823 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100824 case Primitive::kPrimInt: {
825 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
826 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100827 if (locations->InAt(1).IsRegister()) {
828 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
829 locations->InAt(1).AsX86().AsCpuRegister());
830 } else {
831 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
832 Address(ESP, locations->InAt(1).GetStackIndex()));
833 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100834 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100835 }
836
837 case Primitive::kPrimLong: {
838 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
839 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100840 if (locations->InAt(1).IsRegister()) {
841 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
842 locations->InAt(1).AsX86().AsRegisterPairLow());
843 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
844 locations->InAt(1).AsX86().AsRegisterPairHigh());
845 } else {
846 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
847 Address(ESP, locations->InAt(1).GetStackIndex()));
848 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
849 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
850 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100851 break;
852 }
853
854 case Primitive::kPrimBoolean:
855 case Primitive::kPrimByte:
856 case Primitive::kPrimChar:
857 case Primitive::kPrimShort:
858 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
859 break;
860
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100861 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100862 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100863 }
864}
865
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100866void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
867 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100868 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100869 InvokeRuntimeCallingConvention calling_convention;
870 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0)));
871 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100872 instruction->SetLocations(locations);
873}
874
875void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
876 InvokeRuntimeCallingConvention calling_convention;
877 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100878 __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100879
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100880 __ fs()->call(
881 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100882
883 codegen_->RecordPcInfo(instruction->GetDexPc());
884}
885
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100886void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
887 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100888 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
889 if (location.IsStackSlot()) {
890 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
891 } else if (location.IsDoubleStackSlot()) {
892 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100893 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100894 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100895 instruction->SetLocations(locations);
896}
897
898void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100899}
900
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100901void LocationsBuilderX86::VisitNot(HNot* instruction) {
902 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100903 locations->SetInAt(0, Location::RequiresRegister());
904 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100905 instruction->SetLocations(locations);
906}
907
908void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
909 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100910 Location out = locations->Out();
911 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), out.AsX86().AsCpuRegister());
912 __ xorl(out.AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100913}
914
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100915void LocationsBuilderX86::VisitCompare(HCompare* compare) {
916 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(compare);
917 locations->SetInAt(0, Location::RequiresRegister());
918 locations->SetInAt(1, Location::RequiresRegister());
919 locations->SetOut(Location::RequiresRegister());
920 compare->SetLocations(locations);
921}
922
923void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) {
924 Label greater, done;
925 LocationSummary* locations = compare->GetLocations();
926 switch (compare->InputAt(0)->GetType()) {
927 case Primitive::kPrimLong: {
928 Label less, greater, done;
929 Register output = locations->Out().AsX86().AsCpuRegister();
930 X86ManagedRegister left = locations->InAt(0).AsX86();
931 X86ManagedRegister right = locations->InAt(1).AsX86();
932 __ cmpl(left.AsRegisterPairHigh(), right.AsRegisterPairHigh());
933 __ j(kLess, &less); // Signed compare.
934 __ j(kGreater, &greater); // Signed compare.
935 __ cmpl(left.AsRegisterPairLow(), right.AsRegisterPairLow());
936 __ movl(output, Immediate(0));
937 __ j(kEqual, &done);
938 __ j(kBelow, &less); // Unsigned compare.
939
940 __ Bind(&greater);
941 __ movl(output, Immediate(1));
942 __ jmp(&done);
943
944 __ Bind(&less);
945 __ movl(output, Immediate(-1));
946
947 __ Bind(&done);
948 break;
949 }
950 default:
951 LOG(FATAL) << "Unimplemented compare type " << compare->InputAt(0)->GetType();
952 }
953}
954
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100955void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100956 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
957 for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
958 locations->SetInAt(i, Location::Any());
959 }
960 locations->SetOut(Location::Any());
961 instruction->SetLocations(locations);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100962}
963
964void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100965 LOG(FATAL) << "Unreachable";
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100966}
967
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100968void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100969 LOG(FATAL) << "Unreachable";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100970}
971
972void InstructionCodeGeneratorX86::VisitParallelMove(HParallelMove* instruction) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100973 codegen_->GetMoveResolver()->EmitNativeCode(instruction);
974}
975
976X86Assembler* ParallelMoveResolverX86::GetAssembler() const {
977 return codegen_->GetAssembler();
978}
979
980void ParallelMoveResolverX86::MoveMemoryToMemory(int dst, int src) {
981 ScratchRegisterScope ensure_scratch(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +0100982 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100983 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
984 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, src + stack_offset));
985 __ movl(Address(ESP, dst + stack_offset), static_cast<Register>(ensure_scratch.GetRegister()));
986}
987
988void ParallelMoveResolverX86::EmitMove(size_t index) {
989 MoveOperands* move = moves_.Get(index);
990 Location source = move->GetSource();
991 Location destination = move->GetDestination();
992
993 if (source.IsRegister()) {
994 if (destination.IsRegister()) {
995 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
996 } else {
997 DCHECK(destination.IsStackSlot());
998 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
999 }
1000 } else if (source.IsStackSlot()) {
1001 if (destination.IsRegister()) {
1002 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
1003 } else {
1004 DCHECK(destination.IsStackSlot());
1005 MoveMemoryToMemory(destination.GetStackIndex(),
1006 source.GetStackIndex());
1007 }
1008 } else {
1009 LOG(FATAL) << "Unimplemented";
1010 }
1011}
1012
1013void ParallelMoveResolverX86::Exchange(Register reg, int mem) {
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001014 Register suggested_scratch = reg == EAX ? EBX : EAX;
1015 ScratchRegisterScope ensure_scratch(
1016 this, reg, suggested_scratch, codegen_->GetNumberOfCoreRegisters());
1017
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001018 int stack_offset = ensure_scratch.IsSpilled() ? kX86WordSize : 0;
1019 __ movl(static_cast<Register>(ensure_scratch.GetRegister()), Address(ESP, mem + stack_offset));
1020 __ movl(Address(ESP, mem + stack_offset), reg);
1021 __ movl(reg, static_cast<Register>(ensure_scratch.GetRegister()));
1022}
1023
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001024void ParallelMoveResolverX86::Exchange(int mem1, int mem2) {
1025 ScratchRegisterScope ensure_scratch1(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001026 this, kNoRegister, EAX, codegen_->GetNumberOfCoreRegisters());
1027
1028 Register suggested_scratch = ensure_scratch1.GetRegister() == EAX ? EBX : EAX;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001029 ScratchRegisterScope ensure_scratch2(
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001030 this, ensure_scratch1.GetRegister(), suggested_scratch, codegen_->GetNumberOfCoreRegisters());
1031
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001032 int stack_offset = ensure_scratch1.IsSpilled() ? kX86WordSize : 0;
1033 stack_offset += ensure_scratch2.IsSpilled() ? kX86WordSize : 0;
1034 __ movl(static_cast<Register>(ensure_scratch1.GetRegister()), Address(ESP, mem1 + stack_offset));
1035 __ movl(static_cast<Register>(ensure_scratch2.GetRegister()), Address(ESP, mem2 + stack_offset));
1036 __ movl(Address(ESP, mem2 + stack_offset), static_cast<Register>(ensure_scratch1.GetRegister()));
1037 __ movl(Address(ESP, mem1 + stack_offset), static_cast<Register>(ensure_scratch2.GetRegister()));
1038}
1039
1040void ParallelMoveResolverX86::EmitSwap(size_t index) {
1041 MoveOperands* move = moves_.Get(index);
1042 Location source = move->GetSource();
1043 Location destination = move->GetDestination();
1044
1045 if (source.IsRegister() && destination.IsRegister()) {
1046 __ xchgl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
1047 } else if (source.IsRegister() && destination.IsStackSlot()) {
1048 Exchange(source.AsX86().AsCpuRegister(), destination.GetStackIndex());
1049 } else if (source.IsStackSlot() && destination.IsRegister()) {
1050 Exchange(destination.AsX86().AsCpuRegister(), source.GetStackIndex());
1051 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
1052 Exchange(destination.GetStackIndex(), source.GetStackIndex());
1053 } else {
1054 LOG(FATAL) << "Unimplemented";
1055 }
1056}
1057
1058void ParallelMoveResolverX86::SpillScratch(int reg) {
1059 __ pushl(static_cast<Register>(reg));
1060}
1061
1062void ParallelMoveResolverX86::RestoreScratch(int reg) {
1063 __ popl(static_cast<Register>(reg));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001064}
1065
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001066} // namespace x86
1067} // namespace art