blob: 7507ee7ea73763339320c4b6bdad0bba2dee34cc [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
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000022#include "mirror/array.h"
23#include "mirror/art_method.h"
24
Nicolas Geoffray787c3072014-03-17 10:20:19 +000025#define __ reinterpret_cast<X86Assembler*>(GetAssembler())->
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000026
27namespace 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 Geoffray4a34a422014-04-03 10:38:37 +010035static constexpr int kNumberOfPushedRegistersAtEntry = 1;
36static constexpr int kCurrentMethodStackOffset = 0;
37
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010038static Location X86CpuLocation(Register reg) {
39 return Location::RegisterLocation(X86ManagedRegister::FromCpuRegister(reg));
40}
41
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010042InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen)
43 : HGraphVisitor(graph),
44 assembler_(codegen->GetAssembler()),
45 codegen_(codegen) {}
46
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000047void CodeGeneratorX86::GenerateFrameEntry() {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000048 // Create a fake register to mimic Quick.
49 static const int kFakeReturnRegister = 8;
50 core_spill_mask_ |= (1 << kFakeReturnRegister);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000051
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010052 // Add the current ART method to the frame size, the return PC, and the filler.
53 SetFrameSize(RoundUp((
54 GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs() + 3) * kX86WordSize,
55 kStackAlignment));
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010056 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +010057 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010058 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000059}
60
61void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +010062 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000063}
64
65void CodeGeneratorX86::Bind(Label* label) {
66 __ Bind(label);
67}
68
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000069void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010070 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000071}
72
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010073int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010074 uint16_t reg_number = local->GetRegNumber();
75 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
76 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
77 if (reg_number >= number_of_vregs - number_of_in_vregs) {
78 // Local is a parameter of the method. It is stored in the caller's frame.
79 return GetFrameSize() + kX86WordSize // ART method
80 + (reg_number - number_of_vregs + number_of_in_vregs) * kX86WordSize;
81 } else {
82 // Local is a temporary in this method. It is stored in this method's frame.
83 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
84 - kX86WordSize // filler.
85 - (number_of_vregs * kX86WordSize)
86 + (reg_number * kX86WordSize);
87 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010088}
89
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010090static constexpr Register kParameterCoreRegisters[] = { ECX, EDX, EBX };
91static constexpr RegisterPair kParameterCorePairRegisters[] = { ECX_EDX, EDX_EBX };
92static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
93
94class InvokeDexCallingConvention : public CallingConvention<Register> {
95 public:
96 InvokeDexCallingConvention()
97 : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
98
99 RegisterPair GetRegisterPairAt(size_t argument_index) {
100 DCHECK_LT(argument_index + 1, GetNumberOfRegisters());
101 return kParameterCorePairRegisters[argument_index];
102 }
103
104 private:
105 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
106};
107
108void CodeGeneratorX86::Move32(Location destination, Location source) {
109 if (source.Equals(destination)) {
110 return;
111 }
112 if (destination.IsRegister()) {
113 if (source.IsRegister()) {
114 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
115 } else {
116 DCHECK(source.IsStackSlot());
117 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
118 }
119 } else {
120 if (source.IsRegister()) {
121 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
122 } else {
123 DCHECK(source.IsStackSlot());
124 __ movl(EAX, Address(ESP, source.GetStackIndex()));
125 __ movl(Address(ESP, destination.GetStackIndex()), EAX);
126 }
127 }
128}
129
130void CodeGeneratorX86::Move64(Location destination, Location source) {
131 if (source.Equals(destination)) {
132 return;
133 }
134 if (destination.IsRegister()) {
135 if (source.IsRegister()) {
136 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
137 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
138 } else if (source.IsQuickParameter()) {
139 uint32_t argument_index = source.GetQuickParameterIndex();
140 InvokeDexCallingConvention calling_convention;
141 __ movl(destination.AsX86().AsRegisterPairLow(),
142 calling_convention.GetRegisterAt(argument_index));
143 __ movl(destination.AsX86().AsRegisterPairHigh(),
144 Address(ESP,
145 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
146 } else {
147 DCHECK(source.IsDoubleStackSlot());
148 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
149 __ movl(destination.AsX86().AsRegisterPairHigh(),
150 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
151 }
152 } else if (destination.IsQuickParameter()) {
153 InvokeDexCallingConvention calling_convention;
154 uint32_t argument_index = destination.GetQuickParameterIndex();
155 if (source.IsRegister()) {
156 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
157 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)),
158 source.AsX86().AsRegisterPairHigh());
159 } else {
160 DCHECK(source.IsDoubleStackSlot());
161 __ movl(calling_convention.GetRegisterAt(argument_index),
162 Address(ESP, source.GetStackIndex()));
163 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
164 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)), EAX);
165 }
166 } else {
167 if (source.IsRegister()) {
168 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
169 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
170 source.AsX86().AsRegisterPairHigh());
171 } else if (source.IsQuickParameter()) {
172 InvokeDexCallingConvention calling_convention;
173 uint32_t argument_index = source.GetQuickParameterIndex();
174 __ movl(Address(ESP, destination.GetStackIndex()),
175 calling_convention.GetRegisterAt(argument_index));
176 __ movl(EAX,
177 Address(ESP,
178 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
179 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
180 } else {
181 DCHECK(source.IsDoubleStackSlot());
182 __ movl(EAX, Address(ESP, source.GetStackIndex()));
183 __ movl(Address(ESP, destination.GetStackIndex()), EAX);
184 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
185 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
186 }
187 }
188}
189
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100190void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
191 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100192 Immediate imm(instruction->AsIntConstant()->GetValue());
193 if (location.IsRegister()) {
194 __ movl(location.AsX86().AsCpuRegister(), imm);
195 } else {
196 __ movl(Address(ESP, location.GetStackIndex()), imm);
197 }
198 } else if (instruction->AsLongConstant() != nullptr) {
199 int64_t value = instruction->AsLongConstant()->GetValue();
200 if (location.IsRegister()) {
201 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
202 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
203 } else {
204 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
205 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
206 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100207 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100208 switch (instruction->GetType()) {
209 case Primitive::kPrimBoolean:
210 case Primitive::kPrimByte:
211 case Primitive::kPrimChar:
212 case Primitive::kPrimShort:
213 case Primitive::kPrimInt:
214 case Primitive::kPrimNot:
215 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
216 break;
217
218 case Primitive::kPrimLong:
219 Move64(location, Location::DoubleStackSlot(
220 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
221 break;
222
223 default:
224 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
225 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000226 } else {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100227 // This can currently only happen when the instruction that requests the move
228 // is the next to be compiled.
229 DCHECK_EQ(instruction->GetNext(), move_for);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100230 switch (instruction->GetType()) {
231 case Primitive::kPrimBoolean:
232 case Primitive::kPrimByte:
233 case Primitive::kPrimChar:
234 case Primitive::kPrimShort:
235 case Primitive::kPrimInt:
236 case Primitive::kPrimNot:
237 Move32(location, instruction->GetLocations()->Out());
238 break;
239
240 case Primitive::kPrimLong:
241 Move64(location, instruction->GetLocations()->Out());
242 break;
243
244 default:
245 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
246 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000247 }
248}
249
250void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000251 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000252}
253
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000254void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000255 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000256 if (GetGraph()->GetExitBlock() == successor) {
257 codegen_->GenerateFrameExit();
258 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
259 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000260 }
261}
262
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000263void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000264 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000265}
266
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000267void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000268 if (kIsDebugBuild) {
269 __ Comment("Unreachable");
270 __ int3();
271 }
272}
273
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000274void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000275 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100276 locations->SetInAt(0, X86CpuLocation(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000277 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000278}
279
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000280void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000281 // TODO: Generate the input as a condition, instead of materializing in a register.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100282 __ cmpl(if_instr->GetLocations()->InAt(0).AsX86().AsCpuRegister(), Immediate(0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000283 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
284 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) {
285 __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000286 }
287}
288
289void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000290 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000291}
292
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000293void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
294 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000295}
296
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000297void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100298 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000299}
300
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000301void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100302 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000303}
304
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100305void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
306 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
307 switch (store->InputAt(1)->GetType()) {
308 case Primitive::kPrimBoolean:
309 case Primitive::kPrimByte:
310 case Primitive::kPrimChar:
311 case Primitive::kPrimShort:
312 case Primitive::kPrimInt:
313 case Primitive::kPrimNot:
314 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
315 break;
316
317 case Primitive::kPrimLong:
318 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
319 break;
320
321 default:
322 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
323 }
324 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000325}
326
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000327void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000328}
329
330void LocationsBuilderX86::VisitEqual(HEqual* equal) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000331 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100332 locations->SetInAt(0, X86CpuLocation(EAX));
333 locations->SetInAt(1, X86CpuLocation(ECX));
334 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000335 equal->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000336}
337
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000338void InstructionCodeGeneratorX86::VisitEqual(HEqual* equal) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100339 __ cmpl(equal->GetLocations()->InAt(0).AsX86().AsCpuRegister(),
340 equal->GetLocations()->InAt(1).AsX86().AsCpuRegister());
341 __ setb(kEqual, equal->GetLocations()->Out().AsX86().AsCpuRegister());
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000342}
343
344void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000345 constant->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000346}
347
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000348void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000349 // Will be generated at use site.
350}
351
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100352void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
353 constant->SetLocations(nullptr);
354}
355
356void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
357 // Will be generated at use site.
358}
359
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000360void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000361 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000362}
363
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000364void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
365 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000366 __ ret();
367}
368
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000369void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000370 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100371 switch (ret->InputAt(0)->GetType()) {
372 case Primitive::kPrimBoolean:
373 case Primitive::kPrimByte:
374 case Primitive::kPrimChar:
375 case Primitive::kPrimShort:
376 case Primitive::kPrimInt:
377 case Primitive::kPrimNot:
378 locations->SetInAt(0, X86CpuLocation(EAX));
379 break;
380
381 case Primitive::kPrimLong:
382 locations->SetInAt(
383 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
384 break;
385
386 default:
387 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
388 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000389 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000390}
391
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000392void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100393 if (kIsDebugBuild) {
394 switch (ret->InputAt(0)->GetType()) {
395 case Primitive::kPrimBoolean:
396 case Primitive::kPrimByte:
397 case Primitive::kPrimChar:
398 case Primitive::kPrimShort:
399 case Primitive::kPrimInt:
400 case Primitive::kPrimNot:
401 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
402 break;
403
404 case Primitive::kPrimLong:
405 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
406 break;
407
408 default:
409 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
410 }
411 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000412 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000413 __ ret();
414}
415
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100416static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
417static constexpr size_t kRuntimeParameterCoreRegistersLength =
418 arraysize(kRuntimeParameterCoreRegisters);
419
420class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
421 public:
422 InvokeRuntimeCallingConvention()
423 : CallingConvention(kRuntimeParameterCoreRegisters,
424 kRuntimeParameterCoreRegistersLength) {}
425
426 private:
427 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
428};
429
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100430void LocationsBuilderX86::VisitPushArgument(HPushArgument* argument) {
431 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100432 InvokeDexCallingConvention calling_convention;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100433 uint32_t argument_index = argument->GetArgumentIndex();
434 switch (argument->InputAt(0)->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 if (argument_index < calling_convention.GetNumberOfRegisters()) {
442 locations->SetInAt(
443 0, X86CpuLocation(calling_convention.GetRegisterAt(argument->GetArgumentIndex())));
444 } else {
445 locations->SetInAt(
446 0, Location::StackSlot(calling_convention.GetStackOffsetOf(argument_index)));
447 }
448 break;
449 }
450 case Primitive::kPrimLong: {
451 if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) {
452 Location location = Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
453 calling_convention.GetRegisterPairAt(argument_index)));
454 locations->SetInAt(0, location);
455 } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) {
456 locations->SetInAt(0, Location::QuickParameter(argument_index));
457 } else {
458 locations->SetInAt(
459 0, Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(argument_index)));
460 }
461 break;
462 }
463 default:
464 LOG(FATAL) << "Unimplemented argument type " << argument->InputAt(0)->GetType();
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100465 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100466
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100467 argument->SetLocations(locations);
468}
469
470void InstructionCodeGeneratorX86::VisitPushArgument(HPushArgument* argument) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100471 // Nothing to do.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100472}
473
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000474void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
475 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100476 locations->AddTemp(X86CpuLocation(EAX));
477 switch (invoke->GetType()) {
478 case Primitive::kPrimBoolean:
479 case Primitive::kPrimByte:
480 case Primitive::kPrimChar:
481 case Primitive::kPrimShort:
482 case Primitive::kPrimInt:
483 case Primitive::kPrimNot:
484 locations->SetOut(X86CpuLocation(EAX));
485 break;
486
487 case Primitive::kPrimLong:
488 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
489 break;
490
491 case Primitive::kPrimVoid:
492 break;
493
494 case Primitive::kPrimDouble:
495 case Primitive::kPrimFloat:
496 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
497 break;
498 }
499
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000500 invoke->SetLocations(locations);
501}
502
503void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100504 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000505 size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100506 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000507
508 // TODO: Implement all kinds of calls:
509 // 1) boot -> boot
510 // 2) app -> boot
511 // 3) app -> app
512 //
513 // Currently we implement the app -> app logic, which looks up in the resolve cache.
514
515 // temp = method;
516 LoadCurrentMethod(temp);
517 // temp = temp->dex_cache_resolved_methods_;
518 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
519 // temp = temp[index_in_cache]
520 __ movl(temp, Address(temp, index_in_cache));
521 // (temp + offset_of_quick_compiled_code)()
522 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
523
524 codegen_->RecordPcInfo(invoke->GetDexPc());
525}
526
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000527void LocationsBuilderX86::VisitAdd(HAdd* add) {
528 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
529 switch (add->GetResultType()) {
530 case Primitive::kPrimInt: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100531 locations->SetInAt(0, X86CpuLocation(EAX));
532 locations->SetInAt(1, X86CpuLocation(ECX));
533 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000534 break;
535 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100536 case Primitive::kPrimLong: {
537 locations->SetInAt(
538 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
539 locations->SetInAt(
540 1, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(ECX_EBX)));
541 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
542 break;
543 }
544
545 case Primitive::kPrimBoolean:
546 case Primitive::kPrimByte:
547 case Primitive::kPrimChar:
548 case Primitive::kPrimShort:
549 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
550 break;
551
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000552 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100553 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000554 }
555 add->SetLocations(locations);
556}
557
558void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
559 LocationSummary* locations = add->GetLocations();
560 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100561 case Primitive::kPrimInt: {
562 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
563 locations->Out().AsX86().AsCpuRegister());
564 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
565 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000566 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100567 }
568
569 case Primitive::kPrimLong: {
570 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
571 locations->Out().AsX86().AsRegisterPair());
572 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
573 locations->InAt(1).AsX86().AsRegisterPairLow());
574 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
575 locations->InAt(1).AsX86().AsRegisterPairHigh());
576 break;
577 }
578
579 case Primitive::kPrimBoolean:
580 case Primitive::kPrimByte:
581 case Primitive::kPrimChar:
582 case Primitive::kPrimShort:
583 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
584 break;
585
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000586 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100587 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000588 }
589}
590
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100591void LocationsBuilderX86::VisitSub(HSub* sub) {
592 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
593 switch (sub->GetResultType()) {
594 case Primitive::kPrimInt: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100595 locations->SetInAt(0, X86CpuLocation(EAX));
596 locations->SetInAt(1, X86CpuLocation(ECX));
597 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100598 break;
599 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100600
601 case Primitive::kPrimLong: {
602 locations->SetInAt(
603 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
604 locations->SetInAt(
605 1, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(ECX_EBX)));
606 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
607 break;
608 }
609
610 case Primitive::kPrimBoolean:
611 case Primitive::kPrimByte:
612 case Primitive::kPrimChar:
613 case Primitive::kPrimShort:
614 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
615 break;
616
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100617 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100618 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100619 }
620 sub->SetLocations(locations);
621}
622
623void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
624 LocationSummary* locations = sub->GetLocations();
625 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100626 case Primitive::kPrimInt: {
627 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
628 locations->Out().AsX86().AsCpuRegister());
629 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
630 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100631 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100632 }
633
634 case Primitive::kPrimLong: {
635 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
636 locations->Out().AsX86().AsRegisterPair());
637 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
638 locations->InAt(1).AsX86().AsRegisterPairLow());
639 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
640 locations->InAt(1).AsX86().AsRegisterPairHigh());
641 break;
642 }
643
644 case Primitive::kPrimBoolean:
645 case Primitive::kPrimByte:
646 case Primitive::kPrimChar:
647 case Primitive::kPrimShort:
648 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
649 break;
650
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100651 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100652 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100653 }
654}
655
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100656void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
657 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100658 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100659 instruction->SetLocations(locations);
660}
661
662void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
663 InvokeRuntimeCallingConvention calling_convention;
664 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
665 __ movl(calling_convention.GetRegisterAt(0),
666 Immediate(instruction->GetTypeIndex()));
667
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100668 __ fs()->call(
669 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100670
671 codegen_->RecordPcInfo(instruction->GetDexPc());
672}
673
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100674void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
675 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
676 InvokeDexCallingConvention calling_convention;
677 uint32_t argument_index = instruction->GetIndex();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100678 switch (instruction->GetType()) {
679 case Primitive::kPrimBoolean:
680 case Primitive::kPrimByte:
681 case Primitive::kPrimChar:
682 case Primitive::kPrimShort:
683 case Primitive::kPrimInt:
684 case Primitive::kPrimNot:
685 if (argument_index < calling_convention.GetNumberOfRegisters()) {
686 locations->SetOut(X86CpuLocation(calling_convention.GetRegisterAt(argument_index)));
687 } else {
688 locations->SetOut(Location::StackSlot(
689 calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize()));
690 }
691 break;
692
693 case Primitive::kPrimLong:
694 if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) {
695 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
696 (calling_convention.GetRegisterPairAt(argument_index)))));
697 } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) {
698 locations->SetOut(Location::QuickParameter(argument_index));
699 } else {
700 locations->SetOut(Location::DoubleStackSlot(
701 calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize()));
702 }
703 break;
704
705 default:
706 LOG(FATAL) << "Unimplemented parameter type " << instruction->GetType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100707 }
708 instruction->SetLocations(locations);
709}
710
711void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100712 // Nothing to do, the parameter is already at its location.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100713}
714
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100715void LocationsBuilderX86::VisitNot(HNot* instruction) {
716 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100717 locations->SetInAt(0, X86CpuLocation(EAX));
718 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100719 instruction->SetLocations(locations);
720}
721
722void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
723 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100724 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), locations->Out().AsX86().AsCpuRegister());
725 __ xorl(locations->Out().AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100726}
727
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000728} // namespace x86
729} // namespace art