blob: e4f95c795f96a2629f5dd9a688ade12d1edb90b7 [file] [log] [blame]
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "code_generator_x86.h"
18#include "utils/assembler.h"
19#include "utils/x86/assembler_x86.h"
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010020#include "utils/x86/managed_register_x86.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000021
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070022#include "entrypoints/quick/quick_entrypoints.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000023#include "mirror/array.h"
24#include "mirror/art_method.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070025#include "thread.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000026
Nicolas Geoffray787c3072014-03-17 10:20:19 +000027#define __ reinterpret_cast<X86Assembler*>(GetAssembler())->
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000028
29namespace art {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010030
31x86::X86ManagedRegister Location::AsX86() const {
32 return reg().AsX86();
33}
34
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000035namespace x86 {
36
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010037static constexpr int kNumberOfPushedRegistersAtEntry = 1;
38static constexpr int kCurrentMethodStackOffset = 0;
39
Nicolas Geoffraya7aca372014-04-28 17:47:12 +010040CodeGeneratorX86::CodeGeneratorX86(HGraph* graph)
41 : CodeGenerator(graph, kNumberOfRegIds),
42 location_builder_(graph, this),
43 instruction_visitor_(graph, this) {}
44
45static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
46 return blocked_registers + kNumberOfAllocIds;
47}
48
49ManagedRegister CodeGeneratorX86::AllocateFreeRegister(Primitive::Type type,
50 bool* blocked_registers) const {
51 switch (type) {
52 case Primitive::kPrimLong: {
53 size_t reg = AllocateFreeRegisterInternal(
54 GetBlockedRegisterPairs(blocked_registers), kNumberOfRegisterPairs);
55 X86ManagedRegister pair =
56 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg));
57 blocked_registers[pair.AsRegisterPairLow()] = true;
58 blocked_registers[pair.AsRegisterPairHigh()] = true;
59 return pair;
60 }
61
62 case Primitive::kPrimByte:
63 case Primitive::kPrimBoolean:
64 case Primitive::kPrimChar:
65 case Primitive::kPrimShort:
66 case Primitive::kPrimInt:
67 case Primitive::kPrimNot: {
68 size_t reg = AllocateFreeRegisterInternal(blocked_registers, kNumberOfCpuRegisters);
69 return X86ManagedRegister::FromCpuRegister(static_cast<Register>(reg));
70 }
71
72 case Primitive::kPrimFloat:
73 case Primitive::kPrimDouble:
74 LOG(FATAL) << "Unimplemented register type " << type;
75
76 case Primitive::kPrimVoid:
77 LOG(FATAL) << "Unreachable type " << type;
78 }
79
80 return ManagedRegister::NoRegister();
81}
82
83void CodeGeneratorX86::SetupBlockedRegisters(bool* blocked_registers) const {
84 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers);
85
86 // Don't allocate the dalvik style register pair passing.
87 blocked_register_pairs[ECX_EDX] = true;
88
89 // Stack register is always reserved.
90 blocked_registers[ESP] = true;
91
92 // TODO: We currently don't use Quick's callee saved registers.
93 blocked_registers[EBP] = true;
94 blocked_registers[ESI] = true;
95 blocked_registers[EDI] = true;
96 blocked_register_pairs[EAX_EDI] = true;
97 blocked_register_pairs[EDX_EDI] = true;
98 blocked_register_pairs[ECX_EDI] = true;
99 blocked_register_pairs[EBX_EDI] = true;
100}
101
102size_t CodeGeneratorX86::GetNumberOfRegisters() const {
103 return kNumberOfRegIds;
104}
105
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100106static Location X86CpuLocation(Register reg) {
107 return Location::RegisterLocation(X86ManagedRegister::FromCpuRegister(reg));
108}
109
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100110InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen)
111 : HGraphVisitor(graph),
112 assembler_(codegen->GetAssembler()),
113 codegen_(codegen) {}
114
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000115void CodeGeneratorX86::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000116 // Create a fake register to mimic Quick.
117 static const int kFakeReturnRegister = 8;
118 core_spill_mask_ |= (1 << kFakeReturnRegister);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000119
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100120 SetFrameSize(RoundUp(
121 (GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs()) * kVRegSize
122 + kVRegSize // filler
123 + kX86WordSize // Art method
124 + kNumberOfPushedRegistersAtEntry * kX86WordSize,
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100125 kStackAlignment));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100126
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100127 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100128 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100129 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000130}
131
132void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100133 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000134}
135
136void CodeGeneratorX86::Bind(Label* label) {
137 __ Bind(label);
138}
139
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000140void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100141 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000142}
143
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100144int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100145 uint16_t reg_number = local->GetRegNumber();
146 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
147 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
148 if (reg_number >= number_of_vregs - number_of_in_vregs) {
149 // Local is a parameter of the method. It is stored in the caller's frame.
150 return GetFrameSize() + kX86WordSize // ART method
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100151 + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100152 } else {
153 // Local is a temporary in this method. It is stored in this method's frame.
154 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100155 - kVRegSize // filler.
156 - (number_of_vregs * kVRegSize)
157 + (reg_number * kVRegSize);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100158 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100159}
160
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100161
162Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
163 switch (load->GetType()) {
164 case Primitive::kPrimLong:
165 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal()));
166 break;
167
168 case Primitive::kPrimInt:
169 case Primitive::kPrimNot:
170 return Location::StackSlot(GetStackSlot(load->GetLocal()));
171
172 case Primitive::kPrimFloat:
173 case Primitive::kPrimDouble:
174 LOG(FATAL) << "Unimplemented type " << load->GetType();
175
176 case Primitive::kPrimBoolean:
177 case Primitive::kPrimByte:
178 case Primitive::kPrimChar:
179 case Primitive::kPrimShort:
180 case Primitive::kPrimVoid:
181 LOG(FATAL) << "Unexpected type " << load->GetType();
182 }
183
184 LOG(FATAL) << "Unreachable";
185 return Location();
186}
187
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100188static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
189static constexpr size_t kRuntimeParameterCoreRegistersLength =
190 arraysize(kRuntimeParameterCoreRegisters);
191
192class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
193 public:
194 InvokeRuntimeCallingConvention()
195 : CallingConvention(kRuntimeParameterCoreRegisters,
196 kRuntimeParameterCoreRegistersLength) {}
197
198 private:
199 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
200};
201
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100202Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
203 switch (type) {
204 case Primitive::kPrimBoolean:
205 case Primitive::kPrimByte:
206 case Primitive::kPrimChar:
207 case Primitive::kPrimShort:
208 case Primitive::kPrimInt:
209 case Primitive::kPrimNot: {
210 uint32_t index = gp_index_++;
211 if (index < calling_convention.GetNumberOfRegisters()) {
212 return X86CpuLocation(calling_convention.GetRegisterAt(index));
213 } else {
214 return Location::StackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100215 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100216 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100217
218 case Primitive::kPrimLong: {
219 uint32_t index = gp_index_;
220 gp_index_ += 2;
221 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
222 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
223 calling_convention.GetRegisterPairAt(index)));
224 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
225 return Location::QuickParameter(index);
226 } else {
227 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize));
228 }
229 }
230
231 case Primitive::kPrimDouble:
232 case Primitive::kPrimFloat:
233 LOG(FATAL) << "Unimplemented parameter type " << type;
234 break;
235
236 case Primitive::kPrimVoid:
237 LOG(FATAL) << "Unexpected parameter type " << type;
238 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100239 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100240 return Location();
241}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100242
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100243void CodeGeneratorX86::Move32(Location destination, Location source) {
244 if (source.Equals(destination)) {
245 return;
246 }
247 if (destination.IsRegister()) {
248 if (source.IsRegister()) {
249 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
250 } else {
251 DCHECK(source.IsStackSlot());
252 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
253 }
254 } else {
255 if (source.IsRegister()) {
256 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
257 } else {
258 DCHECK(source.IsStackSlot());
259 __ movl(EAX, Address(ESP, source.GetStackIndex()));
260 __ movl(Address(ESP, destination.GetStackIndex()), EAX);
261 }
262 }
263}
264
265void CodeGeneratorX86::Move64(Location destination, Location source) {
266 if (source.Equals(destination)) {
267 return;
268 }
269 if (destination.IsRegister()) {
270 if (source.IsRegister()) {
271 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
272 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
273 } else if (source.IsQuickParameter()) {
274 uint32_t argument_index = source.GetQuickParameterIndex();
275 InvokeDexCallingConvention calling_convention;
276 __ movl(destination.AsX86().AsRegisterPairLow(),
277 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100278 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
279 calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100280 } else {
281 DCHECK(source.IsDoubleStackSlot());
282 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
283 __ movl(destination.AsX86().AsRegisterPairHigh(),
284 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
285 }
286 } else if (destination.IsQuickParameter()) {
287 InvokeDexCallingConvention calling_convention;
288 uint32_t argument_index = destination.GetQuickParameterIndex();
289 if (source.IsRegister()) {
290 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100291 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100292 source.AsX86().AsRegisterPairHigh());
293 } else {
294 DCHECK(source.IsDoubleStackSlot());
295 __ movl(calling_convention.GetRegisterAt(argument_index),
296 Address(ESP, source.GetStackIndex()));
297 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100298 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)), EAX);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100299 }
300 } else {
301 if (source.IsRegister()) {
302 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
303 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
304 source.AsX86().AsRegisterPairHigh());
305 } else if (source.IsQuickParameter()) {
306 InvokeDexCallingConvention calling_convention;
307 uint32_t argument_index = source.GetQuickParameterIndex();
308 __ movl(Address(ESP, destination.GetStackIndex()),
309 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100310 __ movl(EAX, Address(ESP,
311 calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100312 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
313 } else {
314 DCHECK(source.IsDoubleStackSlot());
315 __ movl(EAX, Address(ESP, source.GetStackIndex()));
316 __ movl(Address(ESP, destination.GetStackIndex()), EAX);
317 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
318 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
319 }
320 }
321}
322
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100323void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
324 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100325 Immediate imm(instruction->AsIntConstant()->GetValue());
326 if (location.IsRegister()) {
327 __ movl(location.AsX86().AsCpuRegister(), imm);
328 } else {
329 __ movl(Address(ESP, location.GetStackIndex()), imm);
330 }
331 } else if (instruction->AsLongConstant() != nullptr) {
332 int64_t value = instruction->AsLongConstant()->GetValue();
333 if (location.IsRegister()) {
334 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
335 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
336 } else {
337 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
338 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
339 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100340 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100341 switch (instruction->GetType()) {
342 case Primitive::kPrimBoolean:
343 case Primitive::kPrimByte:
344 case Primitive::kPrimChar:
345 case Primitive::kPrimShort:
346 case Primitive::kPrimInt:
347 case Primitive::kPrimNot:
348 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
349 break;
350
351 case Primitive::kPrimLong:
352 Move64(location, Location::DoubleStackSlot(
353 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
354 break;
355
356 default:
357 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
358 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000359 } else {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100360 // This can currently only happen when the instruction that requests the move
361 // is the next to be compiled.
362 DCHECK_EQ(instruction->GetNext(), move_for);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100363 switch (instruction->GetType()) {
364 case Primitive::kPrimBoolean:
365 case Primitive::kPrimByte:
366 case Primitive::kPrimChar:
367 case Primitive::kPrimShort:
368 case Primitive::kPrimInt:
369 case Primitive::kPrimNot:
370 Move32(location, instruction->GetLocations()->Out());
371 break;
372
373 case Primitive::kPrimLong:
374 Move64(location, instruction->GetLocations()->Out());
375 break;
376
377 default:
378 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
379 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000380 }
381}
382
383void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000384 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000385}
386
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000387void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000388 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000389 if (GetGraph()->GetExitBlock() == successor) {
390 codegen_->GenerateFrameExit();
391 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
392 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000393 }
394}
395
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000396void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000397 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000398}
399
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000400void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000401 if (kIsDebugBuild) {
402 __ Comment("Unreachable");
403 __ int3();
404 }
405}
406
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000407void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000408 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100409 locations->SetInAt(0, Location::Any());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000410 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000411}
412
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000413void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000414 // TODO: Generate the input as a condition, instead of materializing in a register.
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100415 Location location = if_instr->GetLocations()->InAt(0);
416 if (location.IsRegister()) {
417 __ cmpl(location.AsX86().AsCpuRegister(), Immediate(0));
418 } else {
419 __ cmpl(Address(ESP, location.GetStackIndex()), Immediate(0));
420 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000421 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
422 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) {
423 __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000424 }
425}
426
427void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000428 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000429}
430
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000431void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
432 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000433}
434
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000435void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100436 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000437}
438
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000439void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100440 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000441}
442
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100443void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
444 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
445 switch (store->InputAt(1)->GetType()) {
446 case Primitive::kPrimBoolean:
447 case Primitive::kPrimByte:
448 case Primitive::kPrimChar:
449 case Primitive::kPrimShort:
450 case Primitive::kPrimInt:
451 case Primitive::kPrimNot:
452 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
453 break;
454
455 case Primitive::kPrimLong:
456 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
457 break;
458
459 default:
460 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
461 }
462 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000463}
464
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000465void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000466}
467
468void LocationsBuilderX86::VisitEqual(HEqual* equal) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000469 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100470 locations->SetInAt(0, Location::RequiresRegister());
471 locations->SetInAt(1, Location::Any());
472 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000473 equal->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000474}
475
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000476void InstructionCodeGeneratorX86::VisitEqual(HEqual* equal) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100477 LocationSummary* locations = equal->GetLocations();
478 if (locations->InAt(1).IsRegister()) {
479 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
480 locations->InAt(1).AsX86().AsCpuRegister());
481 } else {
482 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
483 Address(ESP, locations->InAt(1).GetStackIndex()));
484 }
485 __ setb(kEqual, locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000486}
487
488void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000489 constant->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000490}
491
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000492void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000493 // Will be generated at use site.
494}
495
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100496void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
497 constant->SetLocations(nullptr);
498}
499
500void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
501 // Will be generated at use site.
502}
503
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000504void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000505 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000506}
507
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000508void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
509 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000510 __ ret();
511}
512
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000513void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000514 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100515 switch (ret->InputAt(0)->GetType()) {
516 case Primitive::kPrimBoolean:
517 case Primitive::kPrimByte:
518 case Primitive::kPrimChar:
519 case Primitive::kPrimShort:
520 case Primitive::kPrimInt:
521 case Primitive::kPrimNot:
522 locations->SetInAt(0, X86CpuLocation(EAX));
523 break;
524
525 case Primitive::kPrimLong:
526 locations->SetInAt(
527 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
528 break;
529
530 default:
531 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
532 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000533 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000534}
535
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000536void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100537 if (kIsDebugBuild) {
538 switch (ret->InputAt(0)->GetType()) {
539 case Primitive::kPrimBoolean:
540 case Primitive::kPrimByte:
541 case Primitive::kPrimChar:
542 case Primitive::kPrimShort:
543 case Primitive::kPrimInt:
544 case Primitive::kPrimNot:
545 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
546 break;
547
548 case Primitive::kPrimLong:
549 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
550 break;
551
552 default:
553 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
554 }
555 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000556 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000557 __ ret();
558}
559
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000560void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
561 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100562 locations->AddTemp(Location::RequiresRegister());
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100563
564 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100565 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100566 HInstruction* input = invoke->InputAt(i);
567 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
568 }
569
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100570 switch (invoke->GetType()) {
571 case Primitive::kPrimBoolean:
572 case Primitive::kPrimByte:
573 case Primitive::kPrimChar:
574 case Primitive::kPrimShort:
575 case Primitive::kPrimInt:
576 case Primitive::kPrimNot:
577 locations->SetOut(X86CpuLocation(EAX));
578 break;
579
580 case Primitive::kPrimLong:
581 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
582 break;
583
584 case Primitive::kPrimVoid:
585 break;
586
587 case Primitive::kPrimDouble:
588 case Primitive::kPrimFloat:
589 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
590 break;
591 }
592
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000593 invoke->SetLocations(locations);
594}
595
596void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100597 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000598 size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100599 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000600
601 // TODO: Implement all kinds of calls:
602 // 1) boot -> boot
603 // 2) app -> boot
604 // 3) app -> app
605 //
606 // Currently we implement the app -> app logic, which looks up in the resolve cache.
607
608 // temp = method;
609 LoadCurrentMethod(temp);
610 // temp = temp->dex_cache_resolved_methods_;
611 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
612 // temp = temp[index_in_cache]
613 __ movl(temp, Address(temp, index_in_cache));
614 // (temp + offset_of_quick_compiled_code)()
615 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
616
617 codegen_->RecordPcInfo(invoke->GetDexPc());
618}
619
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000620void LocationsBuilderX86::VisitAdd(HAdd* add) {
621 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
622 switch (add->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100623 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100624 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100625 locations->SetInAt(0, Location::RequiresRegister());
626 locations->SetInAt(1, Location::Any());
627 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100628 break;
629 }
630
631 case Primitive::kPrimBoolean:
632 case Primitive::kPrimByte:
633 case Primitive::kPrimChar:
634 case Primitive::kPrimShort:
635 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
636 break;
637
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000638 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100639 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000640 }
641 add->SetLocations(locations);
642}
643
644void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
645 LocationSummary* locations = add->GetLocations();
646 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100647 case Primitive::kPrimInt: {
648 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
649 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100650 if (locations->InAt(1).IsRegister()) {
651 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
652 locations->InAt(1).AsX86().AsCpuRegister());
653 } else {
654 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
655 Address(ESP, locations->InAt(1).GetStackIndex()));
656 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000657 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100658 }
659
660 case Primitive::kPrimLong: {
661 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
662 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100663 if (locations->InAt(1).IsRegister()) {
664 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
665 locations->InAt(1).AsX86().AsRegisterPairLow());
666 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
667 locations->InAt(1).AsX86().AsRegisterPairHigh());
668 } else {
669 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
670 Address(ESP, locations->InAt(1).GetStackIndex()));
671 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
672 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
673 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100674 break;
675 }
676
677 case Primitive::kPrimBoolean:
678 case Primitive::kPrimByte:
679 case Primitive::kPrimChar:
680 case Primitive::kPrimShort:
681 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
682 break;
683
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000684 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100685 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000686 }
687}
688
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100689void LocationsBuilderX86::VisitSub(HSub* sub) {
690 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
691 switch (sub->GetResultType()) {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100692 case Primitive::kPrimInt:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100693 case Primitive::kPrimLong: {
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100694 locations->SetInAt(0, Location::RequiresRegister());
695 locations->SetInAt(1, Location::Any());
696 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100697 break;
698 }
699
700 case Primitive::kPrimBoolean:
701 case Primitive::kPrimByte:
702 case Primitive::kPrimChar:
703 case Primitive::kPrimShort:
704 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
705 break;
706
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100707 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100708 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100709 }
710 sub->SetLocations(locations);
711}
712
713void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
714 LocationSummary* locations = sub->GetLocations();
715 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100716 case Primitive::kPrimInt: {
717 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
718 locations->Out().AsX86().AsCpuRegister());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100719 if (locations->InAt(1).IsRegister()) {
720 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
721 locations->InAt(1).AsX86().AsCpuRegister());
722 } else {
723 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
724 Address(ESP, locations->InAt(1).GetStackIndex()));
725 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100726 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100727 }
728
729 case Primitive::kPrimLong: {
730 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
731 locations->Out().AsX86().AsRegisterPair());
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100732 if (locations->InAt(1).IsRegister()) {
733 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
734 locations->InAt(1).AsX86().AsRegisterPairLow());
735 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
736 locations->InAt(1).AsX86().AsRegisterPairHigh());
737 } else {
738 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
739 Address(ESP, locations->InAt(1).GetStackIndex()));
740 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
741 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize)));
742 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100743 break;
744 }
745
746 case Primitive::kPrimBoolean:
747 case Primitive::kPrimByte:
748 case Primitive::kPrimChar:
749 case Primitive::kPrimShort:
750 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
751 break;
752
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100753 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100754 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100755 }
756}
757
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100758void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
759 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100760 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100761 InvokeRuntimeCallingConvention calling_convention;
762 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0)));
763 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100764 instruction->SetLocations(locations);
765}
766
767void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
768 InvokeRuntimeCallingConvention calling_convention;
769 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100770 __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100771
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100772 __ fs()->call(
773 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100774
775 codegen_->RecordPcInfo(instruction->GetDexPc());
776}
777
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100778void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
779 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100780 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
781 if (location.IsStackSlot()) {
782 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
783 } else if (location.IsDoubleStackSlot()) {
784 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100785 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100786 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100787 instruction->SetLocations(locations);
788}
789
790void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100791 // Nothing to do, the parameter is already at its location.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100792}
793
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100794void LocationsBuilderX86::VisitNot(HNot* instruction) {
795 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100796 locations->SetInAt(0, Location::RequiresRegister());
797 locations->SetOut(Location::SameAsFirstInput());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100798 instruction->SetLocations(locations);
799}
800
801void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
802 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffraya7aca372014-04-28 17:47:12 +0100803 Location out = locations->Out();
804 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), out.AsX86().AsCpuRegister());
805 __ xorl(out.AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100806}
807
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100808void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
809 LOG(FATAL) << "Unimplemented";
810}
811
812void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
813 LOG(FATAL) << "Unimplemented";
814}
815
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000816} // namespace x86
817} // namespace art