blob: 7b3d31ddffe01587dd595d5440cafee54e1fddb8 [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
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100108static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
109static constexpr size_t kRuntimeParameterCoreRegistersLength =
110 arraysize(kRuntimeParameterCoreRegisters);
111
112class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
113 public:
114 InvokeRuntimeCallingConvention()
115 : CallingConvention(kRuntimeParameterCoreRegisters,
116 kRuntimeParameterCoreRegistersLength) {}
117
118 private:
119 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
120};
121
122class InvokeDexCallingConventionVisitor {
123 public:
124 InvokeDexCallingConventionVisitor() : gp_index_(0) {}
125
126 Location GetNextLocation(Primitive::Type type) {
127 switch (type) {
128 case Primitive::kPrimBoolean:
129 case Primitive::kPrimByte:
130 case Primitive::kPrimChar:
131 case Primitive::kPrimShort:
132 case Primitive::kPrimInt:
133 case Primitive::kPrimNot: {
134 uint32_t index = gp_index_++;
135 if (index < calling_convention.GetNumberOfRegisters()) {
136 return X86CpuLocation(calling_convention.GetRegisterAt(index));
137 } else {
138 return Location::StackSlot(calling_convention.GetStackOffsetOf(index));
139 }
140 }
141
142 case Primitive::kPrimLong: {
143 uint32_t index = gp_index_;
144 gp_index_ += 2;
145 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
146 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
147 calling_convention.GetRegisterPairAt(index)));
148 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
149 return Location::QuickParameter(index);
150 } else {
151 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
152 }
153 }
154
155 case Primitive::kPrimDouble:
156 case Primitive::kPrimFloat:
157 LOG(FATAL) << "Unimplemented parameter type " << type;
158 break;
159
160 case Primitive::kPrimVoid:
161 LOG(FATAL) << "Unexpected parameter type " << type;
162 break;
163 }
164 return Location();
165 }
166
167 private:
168 InvokeDexCallingConvention calling_convention;
169 uint32_t gp_index_;
170
171 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
172};
173
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100174void CodeGeneratorX86::Move32(Location destination, Location source) {
175 if (source.Equals(destination)) {
176 return;
177 }
178 if (destination.IsRegister()) {
179 if (source.IsRegister()) {
180 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
181 } else {
182 DCHECK(source.IsStackSlot());
183 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
184 }
185 } else {
186 if (source.IsRegister()) {
187 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
188 } else {
189 DCHECK(source.IsStackSlot());
190 __ movl(EAX, Address(ESP, source.GetStackIndex()));
191 __ movl(Address(ESP, destination.GetStackIndex()), EAX);
192 }
193 }
194}
195
196void CodeGeneratorX86::Move64(Location destination, Location source) {
197 if (source.Equals(destination)) {
198 return;
199 }
200 if (destination.IsRegister()) {
201 if (source.IsRegister()) {
202 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
203 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
204 } else if (source.IsQuickParameter()) {
205 uint32_t argument_index = source.GetQuickParameterIndex();
206 InvokeDexCallingConvention calling_convention;
207 __ movl(destination.AsX86().AsRegisterPairLow(),
208 calling_convention.GetRegisterAt(argument_index));
209 __ movl(destination.AsX86().AsRegisterPairHigh(),
210 Address(ESP,
211 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
212 } else {
213 DCHECK(source.IsDoubleStackSlot());
214 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
215 __ movl(destination.AsX86().AsRegisterPairHigh(),
216 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
217 }
218 } else if (destination.IsQuickParameter()) {
219 InvokeDexCallingConvention calling_convention;
220 uint32_t argument_index = destination.GetQuickParameterIndex();
221 if (source.IsRegister()) {
222 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
223 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)),
224 source.AsX86().AsRegisterPairHigh());
225 } else {
226 DCHECK(source.IsDoubleStackSlot());
227 __ movl(calling_convention.GetRegisterAt(argument_index),
228 Address(ESP, source.GetStackIndex()));
229 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
230 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)), EAX);
231 }
232 } else {
233 if (source.IsRegister()) {
234 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
235 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
236 source.AsX86().AsRegisterPairHigh());
237 } else if (source.IsQuickParameter()) {
238 InvokeDexCallingConvention calling_convention;
239 uint32_t argument_index = source.GetQuickParameterIndex();
240 __ movl(Address(ESP, destination.GetStackIndex()),
241 calling_convention.GetRegisterAt(argument_index));
242 __ movl(EAX,
243 Address(ESP,
244 calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
245 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
246 } else {
247 DCHECK(source.IsDoubleStackSlot());
248 __ movl(EAX, Address(ESP, source.GetStackIndex()));
249 __ movl(Address(ESP, destination.GetStackIndex()), EAX);
250 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
251 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
252 }
253 }
254}
255
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100256void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
257 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100258 Immediate imm(instruction->AsIntConstant()->GetValue());
259 if (location.IsRegister()) {
260 __ movl(location.AsX86().AsCpuRegister(), imm);
261 } else {
262 __ movl(Address(ESP, location.GetStackIndex()), imm);
263 }
264 } else if (instruction->AsLongConstant() != nullptr) {
265 int64_t value = instruction->AsLongConstant()->GetValue();
266 if (location.IsRegister()) {
267 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
268 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
269 } else {
270 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
271 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
272 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100273 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100274 switch (instruction->GetType()) {
275 case Primitive::kPrimBoolean:
276 case Primitive::kPrimByte:
277 case Primitive::kPrimChar:
278 case Primitive::kPrimShort:
279 case Primitive::kPrimInt:
280 case Primitive::kPrimNot:
281 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
282 break;
283
284 case Primitive::kPrimLong:
285 Move64(location, Location::DoubleStackSlot(
286 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
287 break;
288
289 default:
290 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
291 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000292 } else {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100293 // This can currently only happen when the instruction that requests the move
294 // is the next to be compiled.
295 DCHECK_EQ(instruction->GetNext(), move_for);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100296 switch (instruction->GetType()) {
297 case Primitive::kPrimBoolean:
298 case Primitive::kPrimByte:
299 case Primitive::kPrimChar:
300 case Primitive::kPrimShort:
301 case Primitive::kPrimInt:
302 case Primitive::kPrimNot:
303 Move32(location, instruction->GetLocations()->Out());
304 break;
305
306 case Primitive::kPrimLong:
307 Move64(location, instruction->GetLocations()->Out());
308 break;
309
310 default:
311 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
312 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000313 }
314}
315
316void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000317 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000318}
319
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000320void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000321 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000322 if (GetGraph()->GetExitBlock() == successor) {
323 codegen_->GenerateFrameExit();
324 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
325 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000326 }
327}
328
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000329void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000330 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000331}
332
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000333void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000334 if (kIsDebugBuild) {
335 __ Comment("Unreachable");
336 __ int3();
337 }
338}
339
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000340void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000341 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100342 locations->SetInAt(0, X86CpuLocation(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000343 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000344}
345
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000346void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000347 // TODO: Generate the input as a condition, instead of materializing in a register.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100348 __ cmpl(if_instr->GetLocations()->InAt(0).AsX86().AsCpuRegister(), Immediate(0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000349 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
350 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) {
351 __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000352 }
353}
354
355void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000356 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000357}
358
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000359void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
360 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000361}
362
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000363void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100364 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000365}
366
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000367void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100368 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000369}
370
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100371void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
372 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
373 switch (store->InputAt(1)->GetType()) {
374 case Primitive::kPrimBoolean:
375 case Primitive::kPrimByte:
376 case Primitive::kPrimChar:
377 case Primitive::kPrimShort:
378 case Primitive::kPrimInt:
379 case Primitive::kPrimNot:
380 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
381 break;
382
383 case Primitive::kPrimLong:
384 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
385 break;
386
387 default:
388 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
389 }
390 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000391}
392
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000393void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000394}
395
396void LocationsBuilderX86::VisitEqual(HEqual* equal) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000397 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100398 locations->SetInAt(0, X86CpuLocation(EAX));
399 locations->SetInAt(1, X86CpuLocation(ECX));
400 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000401 equal->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000402}
403
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000404void InstructionCodeGeneratorX86::VisitEqual(HEqual* equal) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100405 __ cmpl(equal->GetLocations()->InAt(0).AsX86().AsCpuRegister(),
406 equal->GetLocations()->InAt(1).AsX86().AsCpuRegister());
407 __ setb(kEqual, equal->GetLocations()->Out().AsX86().AsCpuRegister());
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000408}
409
410void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000411 constant->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000412}
413
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000414void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000415 // Will be generated at use site.
416}
417
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100418void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
419 constant->SetLocations(nullptr);
420}
421
422void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
423 // Will be generated at use site.
424}
425
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000426void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000427 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000428}
429
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000430void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
431 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000432 __ ret();
433}
434
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000435void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000436 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100437 switch (ret->InputAt(0)->GetType()) {
438 case Primitive::kPrimBoolean:
439 case Primitive::kPrimByte:
440 case Primitive::kPrimChar:
441 case Primitive::kPrimShort:
442 case Primitive::kPrimInt:
443 case Primitive::kPrimNot:
444 locations->SetInAt(0, X86CpuLocation(EAX));
445 break;
446
447 case Primitive::kPrimLong:
448 locations->SetInAt(
449 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
450 break;
451
452 default:
453 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
454 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000455 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000456}
457
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000458void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100459 if (kIsDebugBuild) {
460 switch (ret->InputAt(0)->GetType()) {
461 case Primitive::kPrimBoolean:
462 case Primitive::kPrimByte:
463 case Primitive::kPrimChar:
464 case Primitive::kPrimShort:
465 case Primitive::kPrimInt:
466 case Primitive::kPrimNot:
467 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
468 break;
469
470 case Primitive::kPrimLong:
471 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
472 break;
473
474 default:
475 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
476 }
477 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000478 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000479 __ ret();
480}
481
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000482void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
483 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100484 locations->AddTemp(X86CpuLocation(EAX));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100485
486 InvokeDexCallingConventionVisitor calling_convention_visitor;
487 for (int i = 0; i < invoke->InputCount(); i++) {
488 HInstruction* input = invoke->InputAt(i);
489 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
490 }
491
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100492 switch (invoke->GetType()) {
493 case Primitive::kPrimBoolean:
494 case Primitive::kPrimByte:
495 case Primitive::kPrimChar:
496 case Primitive::kPrimShort:
497 case Primitive::kPrimInt:
498 case Primitive::kPrimNot:
499 locations->SetOut(X86CpuLocation(EAX));
500 break;
501
502 case Primitive::kPrimLong:
503 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
504 break;
505
506 case Primitive::kPrimVoid:
507 break;
508
509 case Primitive::kPrimDouble:
510 case Primitive::kPrimFloat:
511 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
512 break;
513 }
514
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000515 invoke->SetLocations(locations);
516}
517
518void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100519 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000520 size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100521 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000522
523 // TODO: Implement all kinds of calls:
524 // 1) boot -> boot
525 // 2) app -> boot
526 // 3) app -> app
527 //
528 // Currently we implement the app -> app logic, which looks up in the resolve cache.
529
530 // temp = method;
531 LoadCurrentMethod(temp);
532 // temp = temp->dex_cache_resolved_methods_;
533 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
534 // temp = temp[index_in_cache]
535 __ movl(temp, Address(temp, index_in_cache));
536 // (temp + offset_of_quick_compiled_code)()
537 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
538
539 codegen_->RecordPcInfo(invoke->GetDexPc());
540}
541
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000542void LocationsBuilderX86::VisitAdd(HAdd* add) {
543 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
544 switch (add->GetResultType()) {
545 case Primitive::kPrimInt: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100546 locations->SetInAt(0, X86CpuLocation(EAX));
547 locations->SetInAt(1, X86CpuLocation(ECX));
548 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000549 break;
550 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100551 case Primitive::kPrimLong: {
552 locations->SetInAt(
553 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
554 locations->SetInAt(
555 1, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(ECX_EBX)));
556 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
557 break;
558 }
559
560 case Primitive::kPrimBoolean:
561 case Primitive::kPrimByte:
562 case Primitive::kPrimChar:
563 case Primitive::kPrimShort:
564 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
565 break;
566
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000567 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100568 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000569 }
570 add->SetLocations(locations);
571}
572
573void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
574 LocationSummary* locations = add->GetLocations();
575 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100576 case Primitive::kPrimInt: {
577 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
578 locations->Out().AsX86().AsCpuRegister());
579 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
580 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000581 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100582 }
583
584 case Primitive::kPrimLong: {
585 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
586 locations->Out().AsX86().AsRegisterPair());
587 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
588 locations->InAt(1).AsX86().AsRegisterPairLow());
589 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
590 locations->InAt(1).AsX86().AsRegisterPairHigh());
591 break;
592 }
593
594 case Primitive::kPrimBoolean:
595 case Primitive::kPrimByte:
596 case Primitive::kPrimChar:
597 case Primitive::kPrimShort:
598 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
599 break;
600
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000601 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100602 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000603 }
604}
605
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100606void LocationsBuilderX86::VisitSub(HSub* sub) {
607 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
608 switch (sub->GetResultType()) {
609 case Primitive::kPrimInt: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100610 locations->SetInAt(0, X86CpuLocation(EAX));
611 locations->SetInAt(1, X86CpuLocation(ECX));
612 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100613 break;
614 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100615
616 case Primitive::kPrimLong: {
617 locations->SetInAt(
618 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
619 locations->SetInAt(
620 1, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(ECX_EBX)));
621 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
622 break;
623 }
624
625 case Primitive::kPrimBoolean:
626 case Primitive::kPrimByte:
627 case Primitive::kPrimChar:
628 case Primitive::kPrimShort:
629 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
630 break;
631
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100632 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100633 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100634 }
635 sub->SetLocations(locations);
636}
637
638void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
639 LocationSummary* locations = sub->GetLocations();
640 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100641 case Primitive::kPrimInt: {
642 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
643 locations->Out().AsX86().AsCpuRegister());
644 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
645 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100646 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100647 }
648
649 case Primitive::kPrimLong: {
650 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
651 locations->Out().AsX86().AsRegisterPair());
652 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
653 locations->InAt(1).AsX86().AsRegisterPairLow());
654 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
655 locations->InAt(1).AsX86().AsRegisterPairHigh());
656 break;
657 }
658
659 case Primitive::kPrimBoolean:
660 case Primitive::kPrimByte:
661 case Primitive::kPrimChar:
662 case Primitive::kPrimShort:
663 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
664 break;
665
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100666 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100667 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100668 }
669}
670
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100671void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
672 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100673 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100674 instruction->SetLocations(locations);
675}
676
677void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
678 InvokeRuntimeCallingConvention calling_convention;
679 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
680 __ movl(calling_convention.GetRegisterAt(0),
681 Immediate(instruction->GetTypeIndex()));
682
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100683 __ fs()->call(
684 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100685
686 codegen_->RecordPcInfo(instruction->GetDexPc());
687}
688
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100689void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
690 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
691 InvokeDexCallingConvention calling_convention;
692 uint32_t argument_index = instruction->GetIndex();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100693 switch (instruction->GetType()) {
694 case Primitive::kPrimBoolean:
695 case Primitive::kPrimByte:
696 case Primitive::kPrimChar:
697 case Primitive::kPrimShort:
698 case Primitive::kPrimInt:
699 case Primitive::kPrimNot:
700 if (argument_index < calling_convention.GetNumberOfRegisters()) {
701 locations->SetOut(X86CpuLocation(calling_convention.GetRegisterAt(argument_index)));
702 } else {
703 locations->SetOut(Location::StackSlot(
704 calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize()));
705 }
706 break;
707
708 case Primitive::kPrimLong:
709 if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) {
710 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
711 (calling_convention.GetRegisterPairAt(argument_index)))));
712 } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) {
713 locations->SetOut(Location::QuickParameter(argument_index));
714 } else {
715 locations->SetOut(Location::DoubleStackSlot(
716 calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize()));
717 }
718 break;
719
720 default:
721 LOG(FATAL) << "Unimplemented parameter type " << instruction->GetType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100722 }
723 instruction->SetLocations(locations);
724}
725
726void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100727 // Nothing to do, the parameter is already at its location.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100728}
729
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100730void LocationsBuilderX86::VisitNot(HNot* instruction) {
731 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100732 locations->SetInAt(0, X86CpuLocation(EAX));
733 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100734 instruction->SetLocations(locations);
735}
736
737void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
738 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100739 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), locations->Out().AsX86().AsCpuRegister());
740 __ xorl(locations->Out().AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100741}
742
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000743} // namespace x86
744} // namespace art