blob: dc10830e7f8f67b79fb17496b082085c72d02473 [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 Geoffraya747a392014-04-17 14:56:23 +010052 SetFrameSize(RoundUp(
53 (GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs()) * kVRegSize
54 + kVRegSize // filler
55 + kX86WordSize // Art method
56 + kNumberOfPushedRegistersAtEntry * kX86WordSize,
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010057 kStackAlignment));
Nicolas Geoffraya747a392014-04-17 14:56:23 +010058
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010059 // The return PC has already been pushed on the stack.
Nicolas Geoffray707c8092014-04-04 10:50:14 +010060 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010061 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000062}
63
64void CodeGeneratorX86::GenerateFrameExit() {
Nicolas Geoffray707c8092014-04-04 10:50:14 +010065 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000066}
67
68void CodeGeneratorX86::Bind(Label* label) {
69 __ Bind(label);
70}
71
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000072void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010073 __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000074}
75
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010076int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010077 uint16_t reg_number = local->GetRegNumber();
78 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
79 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
80 if (reg_number >= number_of_vregs - number_of_in_vregs) {
81 // Local is a parameter of the method. It is stored in the caller's frame.
82 return GetFrameSize() + kX86WordSize // ART method
Nicolas Geoffraya747a392014-04-17 14:56:23 +010083 + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010084 } else {
85 // Local is a temporary in this method. It is stored in this method's frame.
86 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
Nicolas Geoffraya747a392014-04-17 14:56:23 +010087 - kVRegSize // filler.
88 - (number_of_vregs * kVRegSize)
89 + (reg_number * kVRegSize);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010090 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010091}
92
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +010093static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
94static constexpr size_t kRuntimeParameterCoreRegistersLength =
95 arraysize(kRuntimeParameterCoreRegisters);
96
97class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
98 public:
99 InvokeRuntimeCallingConvention()
100 : CallingConvention(kRuntimeParameterCoreRegisters,
101 kRuntimeParameterCoreRegistersLength) {}
102
103 private:
104 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
105};
106
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100107Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) {
108 switch (type) {
109 case Primitive::kPrimBoolean:
110 case Primitive::kPrimByte:
111 case Primitive::kPrimChar:
112 case Primitive::kPrimShort:
113 case Primitive::kPrimInt:
114 case Primitive::kPrimNot: {
115 uint32_t index = gp_index_++;
116 if (index < calling_convention.GetNumberOfRegisters()) {
117 return X86CpuLocation(calling_convention.GetRegisterAt(index));
118 } else {
119 return Location::StackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100120 }
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100121 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100122
123 case Primitive::kPrimLong: {
124 uint32_t index = gp_index_;
125 gp_index_ += 2;
126 if (index + 1 < calling_convention.GetNumberOfRegisters()) {
127 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
128 calling_convention.GetRegisterPairAt(index)));
129 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
130 return Location::QuickParameter(index);
131 } else {
132 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize));
133 }
134 }
135
136 case Primitive::kPrimDouble:
137 case Primitive::kPrimFloat:
138 LOG(FATAL) << "Unimplemented parameter type " << type;
139 break;
140
141 case Primitive::kPrimVoid:
142 LOG(FATAL) << "Unexpected parameter type " << type;
143 break;
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100144 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100145 return Location();
146}
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100147
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100148void CodeGeneratorX86::Move32(Location destination, Location source) {
149 if (source.Equals(destination)) {
150 return;
151 }
152 if (destination.IsRegister()) {
153 if (source.IsRegister()) {
154 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister());
155 } else {
156 DCHECK(source.IsStackSlot());
157 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex()));
158 }
159 } else {
160 if (source.IsRegister()) {
161 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister());
162 } else {
163 DCHECK(source.IsStackSlot());
164 __ movl(EAX, Address(ESP, source.GetStackIndex()));
165 __ movl(Address(ESP, destination.GetStackIndex()), EAX);
166 }
167 }
168}
169
170void CodeGeneratorX86::Move64(Location destination, Location source) {
171 if (source.Equals(destination)) {
172 return;
173 }
174 if (destination.IsRegister()) {
175 if (source.IsRegister()) {
176 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow());
177 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh());
178 } else if (source.IsQuickParameter()) {
179 uint32_t argument_index = source.GetQuickParameterIndex();
180 InvokeDexCallingConvention calling_convention;
181 __ movl(destination.AsX86().AsRegisterPairLow(),
182 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100183 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
184 calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100185 } else {
186 DCHECK(source.IsDoubleStackSlot());
187 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
188 __ movl(destination.AsX86().AsRegisterPairHigh(),
189 Address(ESP, source.GetHighStackIndex(kX86WordSize)));
190 }
191 } else if (destination.IsQuickParameter()) {
192 InvokeDexCallingConvention calling_convention;
193 uint32_t argument_index = destination.GetQuickParameterIndex();
194 if (source.IsRegister()) {
195 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100196 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100197 source.AsX86().AsRegisterPairHigh());
198 } else {
199 DCHECK(source.IsDoubleStackSlot());
200 __ movl(calling_convention.GetRegisterAt(argument_index),
201 Address(ESP, source.GetStackIndex()));
202 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100203 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)), EAX);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100204 }
205 } else {
206 if (source.IsRegister()) {
207 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow());
208 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)),
209 source.AsX86().AsRegisterPairHigh());
210 } else if (source.IsQuickParameter()) {
211 InvokeDexCallingConvention calling_convention;
212 uint32_t argument_index = source.GetQuickParameterIndex();
213 __ movl(Address(ESP, destination.GetStackIndex()),
214 calling_convention.GetRegisterAt(argument_index));
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100215 __ movl(EAX, Address(ESP,
216 calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize()));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100217 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
218 } else {
219 DCHECK(source.IsDoubleStackSlot());
220 __ movl(EAX, Address(ESP, source.GetStackIndex()));
221 __ movl(Address(ESP, destination.GetStackIndex()), EAX);
222 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
223 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
224 }
225 }
226}
227
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100228void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
229 if (instruction->AsIntConstant() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100230 Immediate imm(instruction->AsIntConstant()->GetValue());
231 if (location.IsRegister()) {
232 __ movl(location.AsX86().AsCpuRegister(), imm);
233 } else {
234 __ movl(Address(ESP, location.GetStackIndex()), imm);
235 }
236 } else if (instruction->AsLongConstant() != nullptr) {
237 int64_t value = instruction->AsLongConstant()->GetValue();
238 if (location.IsRegister()) {
239 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value)));
240 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value)));
241 } else {
242 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
243 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
244 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100245 } else if (instruction->AsLoadLocal() != nullptr) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100246 switch (instruction->GetType()) {
247 case Primitive::kPrimBoolean:
248 case Primitive::kPrimByte:
249 case Primitive::kPrimChar:
250 case Primitive::kPrimShort:
251 case Primitive::kPrimInt:
252 case Primitive::kPrimNot:
253 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
254 break;
255
256 case Primitive::kPrimLong:
257 Move64(location, Location::DoubleStackSlot(
258 GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
259 break;
260
261 default:
262 LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
263 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000264 } else {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100265 // This can currently only happen when the instruction that requests the move
266 // is the next to be compiled.
267 DCHECK_EQ(instruction->GetNext(), move_for);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100268 switch (instruction->GetType()) {
269 case Primitive::kPrimBoolean:
270 case Primitive::kPrimByte:
271 case Primitive::kPrimChar:
272 case Primitive::kPrimShort:
273 case Primitive::kPrimInt:
274 case Primitive::kPrimNot:
275 Move32(location, instruction->GetLocations()->Out());
276 break;
277
278 case Primitive::kPrimLong:
279 Move64(location, instruction->GetLocations()->Out());
280 break;
281
282 default:
283 LOG(FATAL) << "Unimplemented type " << instruction->GetType();
284 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000285 }
286}
287
288void LocationsBuilderX86::VisitGoto(HGoto* got) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000289 got->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000290}
291
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000292void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000293 HBasicBlock* successor = got->GetSuccessor();
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000294 if (GetGraph()->GetExitBlock() == successor) {
295 codegen_->GenerateFrameExit();
296 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) {
297 __ jmp(codegen_->GetLabelOf(successor));
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000298 }
299}
300
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000301void LocationsBuilderX86::VisitExit(HExit* exit) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000302 exit->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000303}
304
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000305void InstructionCodeGeneratorX86::VisitExit(HExit* exit) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000306 if (kIsDebugBuild) {
307 __ Comment("Unreachable");
308 __ int3();
309 }
310}
311
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000312void LocationsBuilderX86::VisitIf(HIf* if_instr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000313 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100314 locations->SetInAt(0, X86CpuLocation(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000315 if_instr->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000316}
317
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000318void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000319 // TODO: Generate the input as a condition, instead of materializing in a register.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100320 __ cmpl(if_instr->GetLocations()->InAt(0).AsX86().AsCpuRegister(), Immediate(0));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000321 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
322 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) {
323 __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000324 }
325}
326
327void LocationsBuilderX86::VisitLocal(HLocal* local) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000328 local->SetLocations(nullptr);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000329}
330
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000331void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) {
332 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000333}
334
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000335void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100336 local->SetLocations(nullptr);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000337}
338
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000339void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100340 // Nothing to do, this is driven by the code generator.
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000341}
342
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100343void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) {
344 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
345 switch (store->InputAt(1)->GetType()) {
346 case Primitive::kPrimBoolean:
347 case Primitive::kPrimByte:
348 case Primitive::kPrimChar:
349 case Primitive::kPrimShort:
350 case Primitive::kPrimInt:
351 case Primitive::kPrimNot:
352 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
353 break;
354
355 case Primitive::kPrimLong:
356 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
357 break;
358
359 default:
360 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
361 }
362 store->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000363}
364
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000365void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000366}
367
368void LocationsBuilderX86::VisitEqual(HEqual* equal) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000369 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100370 locations->SetInAt(0, X86CpuLocation(EAX));
371 locations->SetInAt(1, X86CpuLocation(ECX));
372 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000373 equal->SetLocations(locations);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000374}
375
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000376void InstructionCodeGeneratorX86::VisitEqual(HEqual* equal) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100377 __ cmpl(equal->GetLocations()->InAt(0).AsX86().AsCpuRegister(),
378 equal->GetLocations()->InAt(1).AsX86().AsCpuRegister());
379 __ setb(kEqual, equal->GetLocations()->Out().AsX86().AsCpuRegister());
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000380}
381
382void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000383 constant->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000384}
385
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000386void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000387 // Will be generated at use site.
388}
389
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100390void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
391 constant->SetLocations(nullptr);
392}
393
394void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) {
395 // Will be generated at use site.
396}
397
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000398void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000399 ret->SetLocations(nullptr);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000400}
401
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000402void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) {
403 codegen_->GenerateFrameExit();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000404 __ ret();
405}
406
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000407void LocationsBuilderX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000408 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100409 switch (ret->InputAt(0)->GetType()) {
410 case Primitive::kPrimBoolean:
411 case Primitive::kPrimByte:
412 case Primitive::kPrimChar:
413 case Primitive::kPrimShort:
414 case Primitive::kPrimInt:
415 case Primitive::kPrimNot:
416 locations->SetInAt(0, X86CpuLocation(EAX));
417 break;
418
419 case Primitive::kPrimLong:
420 locations->SetInAt(
421 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
422 break;
423
424 default:
425 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
426 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000427 ret->SetLocations(locations);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000428}
429
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000430void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100431 if (kIsDebugBuild) {
432 switch (ret->InputAt(0)->GetType()) {
433 case Primitive::kPrimBoolean:
434 case Primitive::kPrimByte:
435 case Primitive::kPrimChar:
436 case Primitive::kPrimShort:
437 case Primitive::kPrimInt:
438 case Primitive::kPrimNot:
439 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX);
440 break;
441
442 case Primitive::kPrimLong:
443 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX);
444 break;
445
446 default:
447 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
448 }
449 }
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000450 codegen_->GenerateFrameExit();
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000451 __ ret();
452}
453
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000454void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
455 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100456 locations->AddTemp(X86CpuLocation(EAX));
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100457
458 InvokeDexCallingConventionVisitor calling_convention_visitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100459 for (size_t i = 0; i < invoke->InputCount(); i++) {
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100460 HInstruction* input = invoke->InputAt(i);
461 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
462 }
463
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100464 switch (invoke->GetType()) {
465 case Primitive::kPrimBoolean:
466 case Primitive::kPrimByte:
467 case Primitive::kPrimChar:
468 case Primitive::kPrimShort:
469 case Primitive::kPrimInt:
470 case Primitive::kPrimNot:
471 locations->SetOut(X86CpuLocation(EAX));
472 break;
473
474 case Primitive::kPrimLong:
475 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
476 break;
477
478 case Primitive::kPrimVoid:
479 break;
480
481 case Primitive::kPrimDouble:
482 case Primitive::kPrimFloat:
483 LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
484 break;
485 }
486
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000487 invoke->SetLocations(locations);
488}
489
490void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100491 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister();
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000492 size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100493 invoke->GetIndexInDexCache() * kX86WordSize;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000494
495 // TODO: Implement all kinds of calls:
496 // 1) boot -> boot
497 // 2) app -> boot
498 // 3) app -> app
499 //
500 // Currently we implement the app -> app logic, which looks up in the resolve cache.
501
502 // temp = method;
503 LoadCurrentMethod(temp);
504 // temp = temp->dex_cache_resolved_methods_;
505 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
506 // temp = temp[index_in_cache]
507 __ movl(temp, Address(temp, index_in_cache));
508 // (temp + offset_of_quick_compiled_code)()
509 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()));
510
511 codegen_->RecordPcInfo(invoke->GetDexPc());
512}
513
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000514void LocationsBuilderX86::VisitAdd(HAdd* add) {
515 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
516 switch (add->GetResultType()) {
517 case Primitive::kPrimInt: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100518 locations->SetInAt(0, X86CpuLocation(EAX));
519 locations->SetInAt(1, X86CpuLocation(ECX));
520 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000521 break;
522 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100523 case Primitive::kPrimLong: {
524 locations->SetInAt(
525 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
526 locations->SetInAt(
527 1, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(ECX_EBX)));
528 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
529 break;
530 }
531
532 case Primitive::kPrimBoolean:
533 case Primitive::kPrimByte:
534 case Primitive::kPrimChar:
535 case Primitive::kPrimShort:
536 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
537 break;
538
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000539 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100540 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000541 }
542 add->SetLocations(locations);
543}
544
545void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
546 LocationSummary* locations = add->GetLocations();
547 switch (add->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100548 case Primitive::kPrimInt: {
549 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
550 locations->Out().AsX86().AsCpuRegister());
551 __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
552 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000553 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100554 }
555
556 case Primitive::kPrimLong: {
557 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
558 locations->Out().AsX86().AsRegisterPair());
559 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(),
560 locations->InAt(1).AsX86().AsRegisterPairLow());
561 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
562 locations->InAt(1).AsX86().AsRegisterPairHigh());
563 break;
564 }
565
566 case Primitive::kPrimBoolean:
567 case Primitive::kPrimByte:
568 case Primitive::kPrimChar:
569 case Primitive::kPrimShort:
570 LOG(FATAL) << "Unexpected add type " << add->GetResultType();
571 break;
572
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000573 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100574 LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000575 }
576}
577
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100578void LocationsBuilderX86::VisitSub(HSub* sub) {
579 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
580 switch (sub->GetResultType()) {
581 case Primitive::kPrimInt: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100582 locations->SetInAt(0, X86CpuLocation(EAX));
583 locations->SetInAt(1, X86CpuLocation(ECX));
584 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100585 break;
586 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100587
588 case Primitive::kPrimLong: {
589 locations->SetInAt(
590 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
591 locations->SetInAt(
592 1, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(ECX_EBX)));
593 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX)));
594 break;
595 }
596
597 case Primitive::kPrimBoolean:
598 case Primitive::kPrimByte:
599 case Primitive::kPrimChar:
600 case Primitive::kPrimShort:
601 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
602 break;
603
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100604 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100605 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100606 }
607 sub->SetLocations(locations);
608}
609
610void InstructionCodeGeneratorX86::VisitSub(HSub* sub) {
611 LocationSummary* locations = sub->GetLocations();
612 switch (sub->GetResultType()) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100613 case Primitive::kPrimInt: {
614 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(),
615 locations->Out().AsX86().AsCpuRegister());
616 __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
617 locations->InAt(1).AsX86().AsCpuRegister());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100618 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100619 }
620
621 case Primitive::kPrimLong: {
622 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(),
623 locations->Out().AsX86().AsRegisterPair());
624 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(),
625 locations->InAt(1).AsX86().AsRegisterPairLow());
626 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(),
627 locations->InAt(1).AsX86().AsRegisterPairHigh());
628 break;
629 }
630
631 case Primitive::kPrimBoolean:
632 case Primitive::kPrimByte:
633 case Primitive::kPrimChar:
634 case Primitive::kPrimShort:
635 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
636 break;
637
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100638 default:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100639 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100640 }
641}
642
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100643void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
644 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100645 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100646 instruction->SetLocations(locations);
647}
648
649void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
650 InvokeRuntimeCallingConvention calling_convention;
651 LoadCurrentMethod(calling_convention.GetRegisterAt(1));
652 __ movl(calling_convention.GetRegisterAt(0),
653 Immediate(instruction->GetTypeIndex()));
654
Nicolas Geoffray707c8092014-04-04 10:50:14 +0100655 __ fs()->call(
656 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck)));
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100657
658 codegen_->RecordPcInfo(instruction->GetDexPc());
659}
660
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100661void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
662 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100663 Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
664 if (location.IsStackSlot()) {
665 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
666 } else if (location.IsDoubleStackSlot()) {
667 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100668 }
Nicolas Geoffraya747a392014-04-17 14:56:23 +0100669 locations->SetOut(location);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100670 instruction->SetLocations(locations);
671}
672
673void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100674 // Nothing to do, the parameter is already at its location.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100675}
676
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100677void LocationsBuilderX86::VisitNot(HNot* instruction) {
678 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100679 locations->SetInAt(0, X86CpuLocation(EAX));
680 locations->SetOut(X86CpuLocation(EAX));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100681 instruction->SetLocations(locations);
682}
683
684void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) {
685 LocationSummary* locations = instruction->GetLocations();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100686 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), locations->Out().AsX86().AsCpuRegister());
687 __ xorl(locations->Out().AsX86().AsCpuRegister(), Immediate(1));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100688}
689
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100690void LocationsBuilderX86::VisitPhi(HPhi* instruction) {
691 LOG(FATAL) << "Unimplemented";
692}
693
694void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) {
695 LOG(FATAL) << "Unimplemented";
696}
697
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000698} // namespace x86
699} // namespace art