code_generator_x86.cc revision b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cf
1/* 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" 20#include "utils/x86/managed_register_x86.h" 21 22#include "entrypoints/quick/quick_entrypoints.h" 23#include "mirror/array.h" 24#include "mirror/art_method.h" 25#include "thread.h" 26 27#define __ reinterpret_cast<X86Assembler*>(GetAssembler())-> 28 29namespace art { 30 31x86::X86ManagedRegister Location::AsX86() const { 32 return reg().AsX86(); 33} 34 35namespace x86 { 36 37static constexpr int kNumberOfPushedRegistersAtEntry = 1; 38static constexpr int kCurrentMethodStackOffset = 0; 39 40CodeGeneratorX86::CodeGeneratorX86(HGraph* graph) 41 : CodeGenerator(graph, kNumberOfRegIds), 42 location_builder_(graph, this), 43 instruction_visitor_(graph, this) {} 44 45static bool* GetBlockedRegisterPairs(bool* blocked_registers) { 46 return blocked_registers + kNumberOfAllocIds; 47} 48 49ManagedRegister CodeGeneratorX86::AllocateFreeRegister(Primitive::Type type, 50 bool* blocked_registers) const { 51 switch (type) { 52 case Primitive::kPrimLong: { 53 size_t reg = AllocateFreeRegisterInternal( 54 GetBlockedRegisterPairs(blocked_registers), kNumberOfRegisterPairs); 55 X86ManagedRegister pair = 56 X86ManagedRegister::FromRegisterPair(static_cast<RegisterPair>(reg)); 57 blocked_registers[pair.AsRegisterPairLow()] = true; 58 blocked_registers[pair.AsRegisterPairHigh()] = true; 59 return pair; 60 } 61 62 case Primitive::kPrimByte: 63 case Primitive::kPrimBoolean: 64 case Primitive::kPrimChar: 65 case Primitive::kPrimShort: 66 case Primitive::kPrimInt: 67 case Primitive::kPrimNot: { 68 size_t reg = AllocateFreeRegisterInternal(blocked_registers, kNumberOfCpuRegisters); 69 return X86ManagedRegister::FromCpuRegister(static_cast<Register>(reg)); 70 } 71 72 case Primitive::kPrimFloat: 73 case Primitive::kPrimDouble: 74 LOG(FATAL) << "Unimplemented register type " << type; 75 76 case Primitive::kPrimVoid: 77 LOG(FATAL) << "Unreachable type " << type; 78 } 79 80 return ManagedRegister::NoRegister(); 81} 82 83void CodeGeneratorX86::SetupBlockedRegisters(bool* blocked_registers) const { 84 bool* blocked_register_pairs = GetBlockedRegisterPairs(blocked_registers); 85 86 // Don't allocate the dalvik style register pair passing. 87 blocked_register_pairs[ECX_EDX] = true; 88 89 // Stack register is always reserved. 90 blocked_registers[ESP] = true; 91 92 // TODO: We currently don't use Quick's callee saved registers. 93 blocked_registers[EBP] = true; 94 blocked_registers[ESI] = true; 95 blocked_registers[EDI] = true; 96 blocked_register_pairs[EAX_EDI] = true; 97 blocked_register_pairs[EDX_EDI] = true; 98 blocked_register_pairs[ECX_EDI] = true; 99 blocked_register_pairs[EBX_EDI] = true; 100} 101 102size_t CodeGeneratorX86::GetNumberOfRegisters() const { 103 return kNumberOfRegIds; 104} 105 106static Location X86CpuLocation(Register reg) { 107 return Location::RegisterLocation(X86ManagedRegister::FromCpuRegister(reg)); 108} 109 110InstructionCodeGeneratorX86::InstructionCodeGeneratorX86(HGraph* graph, CodeGeneratorX86* codegen) 111 : HGraphVisitor(graph), 112 assembler_(codegen->GetAssembler()), 113 codegen_(codegen) {} 114 115void CodeGeneratorX86::GenerateFrameEntry() { 116 // Create a fake register to mimic Quick. 117 static const int kFakeReturnRegister = 8; 118 core_spill_mask_ |= (1 << kFakeReturnRegister); 119 120 SetFrameSize(RoundUp( 121 (GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs()) * kVRegSize 122 + kVRegSize // filler 123 + kX86WordSize // Art method 124 + kNumberOfPushedRegistersAtEntry * kX86WordSize, 125 kStackAlignment)); 126 127 // The return PC has already been pushed on the stack. 128 __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize)); 129 __ movl(Address(ESP, kCurrentMethodStackOffset), EAX); 130} 131 132void CodeGeneratorX86::GenerateFrameExit() { 133 __ addl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize)); 134} 135 136void CodeGeneratorX86::Bind(Label* label) { 137 __ Bind(label); 138} 139 140void InstructionCodeGeneratorX86::LoadCurrentMethod(Register reg) { 141 __ movl(reg, Address(ESP, kCurrentMethodStackOffset)); 142} 143 144int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const { 145 uint16_t reg_number = local->GetRegNumber(); 146 uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs(); 147 uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs(); 148 if (reg_number >= number_of_vregs - number_of_in_vregs) { 149 // Local is a parameter of the method. It is stored in the caller's frame. 150 return GetFrameSize() + kX86WordSize // ART method 151 + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize; 152 } else { 153 // Local is a temporary in this method. It is stored in this method's frame. 154 return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize) 155 - kVRegSize // filler. 156 - (number_of_vregs * kVRegSize) 157 + (reg_number * kVRegSize); 158 } 159} 160 161 162Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const { 163 switch (load->GetType()) { 164 case Primitive::kPrimLong: 165 return Location::DoubleStackSlot(GetStackSlot(load->GetLocal())); 166 break; 167 168 case Primitive::kPrimInt: 169 case Primitive::kPrimNot: 170 return Location::StackSlot(GetStackSlot(load->GetLocal())); 171 172 case Primitive::kPrimFloat: 173 case Primitive::kPrimDouble: 174 LOG(FATAL) << "Unimplemented type " << load->GetType(); 175 176 case Primitive::kPrimBoolean: 177 case Primitive::kPrimByte: 178 case Primitive::kPrimChar: 179 case Primitive::kPrimShort: 180 case Primitive::kPrimVoid: 181 LOG(FATAL) << "Unexpected type " << load->GetType(); 182 } 183 184 LOG(FATAL) << "Unreachable"; 185 return Location(); 186} 187 188static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX }; 189static constexpr size_t kRuntimeParameterCoreRegistersLength = 190 arraysize(kRuntimeParameterCoreRegisters); 191 192class InvokeRuntimeCallingConvention : public CallingConvention<Register> { 193 public: 194 InvokeRuntimeCallingConvention() 195 : CallingConvention(kRuntimeParameterCoreRegisters, 196 kRuntimeParameterCoreRegistersLength) {} 197 198 private: 199 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); 200}; 201 202Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type) { 203 switch (type) { 204 case Primitive::kPrimBoolean: 205 case Primitive::kPrimByte: 206 case Primitive::kPrimChar: 207 case Primitive::kPrimShort: 208 case Primitive::kPrimInt: 209 case Primitive::kPrimNot: { 210 uint32_t index = gp_index_++; 211 if (index < calling_convention.GetNumberOfRegisters()) { 212 return X86CpuLocation(calling_convention.GetRegisterAt(index)); 213 } else { 214 return Location::StackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize)); 215 } 216 } 217 218 case Primitive::kPrimLong: { 219 uint32_t index = gp_index_; 220 gp_index_ += 2; 221 if (index + 1 < calling_convention.GetNumberOfRegisters()) { 222 return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair( 223 calling_convention.GetRegisterPairAt(index))); 224 } else if (index + 1 == calling_convention.GetNumberOfRegisters()) { 225 return Location::QuickParameter(index); 226 } else { 227 return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index, kX86WordSize)); 228 } 229 } 230 231 case Primitive::kPrimDouble: 232 case Primitive::kPrimFloat: 233 LOG(FATAL) << "Unimplemented parameter type " << type; 234 break; 235 236 case Primitive::kPrimVoid: 237 LOG(FATAL) << "Unexpected parameter type " << type; 238 break; 239 } 240 return Location(); 241} 242 243void CodeGeneratorX86::Move32(Location destination, Location source) { 244 if (source.Equals(destination)) { 245 return; 246 } 247 if (destination.IsRegister()) { 248 if (source.IsRegister()) { 249 __ movl(destination.AsX86().AsCpuRegister(), source.AsX86().AsCpuRegister()); 250 } else { 251 DCHECK(source.IsStackSlot()); 252 __ movl(destination.AsX86().AsCpuRegister(), Address(ESP, source.GetStackIndex())); 253 } 254 } else { 255 if (source.IsRegister()) { 256 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsCpuRegister()); 257 } else { 258 DCHECK(source.IsStackSlot()); 259 __ movl(EAX, Address(ESP, source.GetStackIndex())); 260 __ movl(Address(ESP, destination.GetStackIndex()), EAX); 261 } 262 } 263} 264 265void CodeGeneratorX86::Move64(Location destination, Location source) { 266 if (source.Equals(destination)) { 267 return; 268 } 269 if (destination.IsRegister()) { 270 if (source.IsRegister()) { 271 __ movl(destination.AsX86().AsRegisterPairLow(), source.AsX86().AsRegisterPairLow()); 272 __ movl(destination.AsX86().AsRegisterPairHigh(), source.AsX86().AsRegisterPairHigh()); 273 } else if (source.IsQuickParameter()) { 274 uint32_t argument_index = source.GetQuickParameterIndex(); 275 InvokeDexCallingConvention calling_convention; 276 __ movl(destination.AsX86().AsRegisterPairLow(), 277 calling_convention.GetRegisterAt(argument_index)); 278 __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP, 279 calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize())); 280 } else { 281 DCHECK(source.IsDoubleStackSlot()); 282 __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex())); 283 __ movl(destination.AsX86().AsRegisterPairHigh(), 284 Address(ESP, source.GetHighStackIndex(kX86WordSize))); 285 } 286 } else if (destination.IsQuickParameter()) { 287 InvokeDexCallingConvention calling_convention; 288 uint32_t argument_index = destination.GetQuickParameterIndex(); 289 if (source.IsRegister()) { 290 __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow()); 291 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)), 292 source.AsX86().AsRegisterPairHigh()); 293 } else { 294 DCHECK(source.IsDoubleStackSlot()); 295 __ movl(calling_convention.GetRegisterAt(argument_index), 296 Address(ESP, source.GetStackIndex())); 297 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize))); 298 __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)), EAX); 299 } 300 } else { 301 if (source.IsRegister()) { 302 __ movl(Address(ESP, destination.GetStackIndex()), source.AsX86().AsRegisterPairLow()); 303 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), 304 source.AsX86().AsRegisterPairHigh()); 305 } else if (source.IsQuickParameter()) { 306 InvokeDexCallingConvention calling_convention; 307 uint32_t argument_index = source.GetQuickParameterIndex(); 308 __ movl(Address(ESP, destination.GetStackIndex()), 309 calling_convention.GetRegisterAt(argument_index)); 310 __ movl(EAX, Address(ESP, 311 calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize())); 312 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX); 313 } else { 314 DCHECK(source.IsDoubleStackSlot()); 315 __ movl(EAX, Address(ESP, source.GetStackIndex())); 316 __ movl(Address(ESP, destination.GetStackIndex()), EAX); 317 __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize))); 318 __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX); 319 } 320 } 321} 322 323void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) { 324 if (instruction->AsIntConstant() != nullptr) { 325 Immediate imm(instruction->AsIntConstant()->GetValue()); 326 if (location.IsRegister()) { 327 __ movl(location.AsX86().AsCpuRegister(), imm); 328 } else { 329 __ movl(Address(ESP, location.GetStackIndex()), imm); 330 } 331 } else if (instruction->AsLongConstant() != nullptr) { 332 int64_t value = instruction->AsLongConstant()->GetValue(); 333 if (location.IsRegister()) { 334 __ movl(location.AsX86().AsRegisterPairLow(), Immediate(Low32Bits(value))); 335 __ movl(location.AsX86().AsRegisterPairHigh(), Immediate(High32Bits(value))); 336 } else { 337 __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value))); 338 __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value))); 339 } 340 } else if (instruction->AsLoadLocal() != nullptr) { 341 switch (instruction->GetType()) { 342 case Primitive::kPrimBoolean: 343 case Primitive::kPrimByte: 344 case Primitive::kPrimChar: 345 case Primitive::kPrimShort: 346 case Primitive::kPrimInt: 347 case Primitive::kPrimNot: 348 Move32(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal()))); 349 break; 350 351 case Primitive::kPrimLong: 352 Move64(location, Location::DoubleStackSlot( 353 GetStackSlot(instruction->AsLoadLocal()->GetLocal()))); 354 break; 355 356 default: 357 LOG(FATAL) << "Unimplemented local type " << instruction->GetType(); 358 } 359 } else { 360 // This can currently only happen when the instruction that requests the move 361 // is the next to be compiled. 362 DCHECK_EQ(instruction->GetNext(), move_for); 363 switch (instruction->GetType()) { 364 case Primitive::kPrimBoolean: 365 case Primitive::kPrimByte: 366 case Primitive::kPrimChar: 367 case Primitive::kPrimShort: 368 case Primitive::kPrimInt: 369 case Primitive::kPrimNot: 370 Move32(location, instruction->GetLocations()->Out()); 371 break; 372 373 case Primitive::kPrimLong: 374 Move64(location, instruction->GetLocations()->Out()); 375 break; 376 377 default: 378 LOG(FATAL) << "Unimplemented type " << instruction->GetType(); 379 } 380 } 381} 382 383void LocationsBuilderX86::VisitGoto(HGoto* got) { 384 got->SetLocations(nullptr); 385} 386 387void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) { 388 HBasicBlock* successor = got->GetSuccessor(); 389 if (GetGraph()->GetExitBlock() == successor) { 390 codegen_->GenerateFrameExit(); 391 } else if (!codegen_->GoesToNextBlock(got->GetBlock(), successor)) { 392 __ jmp(codegen_->GetLabelOf(successor)); 393 } 394} 395 396void LocationsBuilderX86::VisitExit(HExit* exit) { 397 exit->SetLocations(nullptr); 398} 399 400void InstructionCodeGeneratorX86::VisitExit(HExit* exit) { 401 if (kIsDebugBuild) { 402 __ Comment("Unreachable"); 403 __ int3(); 404 } 405} 406 407void LocationsBuilderX86::VisitIf(HIf* if_instr) { 408 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr); 409 locations->SetInAt(0, Location::Any()); 410 if_instr->SetLocations(locations); 411} 412 413void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) { 414 // TODO: Generate the input as a condition, instead of materializing in a register. 415 Location location = if_instr->GetLocations()->InAt(0); 416 if (location.IsRegister()) { 417 __ cmpl(location.AsX86().AsCpuRegister(), Immediate(0)); 418 } else { 419 __ cmpl(Address(ESP, location.GetStackIndex()), Immediate(0)); 420 } 421 __ j(kEqual, codegen_->GetLabelOf(if_instr->IfFalseSuccessor())); 422 if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) { 423 __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); 424 } 425} 426 427void LocationsBuilderX86::VisitLocal(HLocal* local) { 428 local->SetLocations(nullptr); 429} 430 431void InstructionCodeGeneratorX86::VisitLocal(HLocal* local) { 432 DCHECK_EQ(local->GetBlock(), GetGraph()->GetEntryBlock()); 433} 434 435void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) { 436 local->SetLocations(nullptr); 437} 438 439void InstructionCodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) { 440 // Nothing to do, this is driven by the code generator. 441} 442 443void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* store) { 444 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store); 445 switch (store->InputAt(1)->GetType()) { 446 case Primitive::kPrimBoolean: 447 case Primitive::kPrimByte: 448 case Primitive::kPrimChar: 449 case Primitive::kPrimShort: 450 case Primitive::kPrimInt: 451 case Primitive::kPrimNot: 452 locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal()))); 453 break; 454 455 case Primitive::kPrimLong: 456 locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal()))); 457 break; 458 459 default: 460 LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType(); 461 } 462 store->SetLocations(locations); 463} 464 465void InstructionCodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) { 466} 467 468void LocationsBuilderX86::VisitEqual(HEqual* equal) { 469 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal); 470 locations->SetInAt(0, Location::RequiresRegister()); 471 locations->SetInAt(1, Location::Any()); 472 locations->SetOut(Location::SameAsFirstInput()); 473 equal->SetLocations(locations); 474} 475 476void InstructionCodeGeneratorX86::VisitEqual(HEqual* equal) { 477 LocationSummary* locations = equal->GetLocations(); 478 if (locations->InAt(1).IsRegister()) { 479 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), 480 locations->InAt(1).AsX86().AsCpuRegister()); 481 } else { 482 __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), 483 Address(ESP, locations->InAt(1).GetStackIndex())); 484 } 485 __ setb(kEqual, locations->Out().AsX86().AsCpuRegister()); 486} 487 488void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) { 489 constant->SetLocations(nullptr); 490} 491 492void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) { 493 // Will be generated at use site. 494} 495 496void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) { 497 constant->SetLocations(nullptr); 498} 499 500void InstructionCodeGeneratorX86::VisitLongConstant(HLongConstant* constant) { 501 // Will be generated at use site. 502} 503 504void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) { 505 ret->SetLocations(nullptr); 506} 507 508void InstructionCodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) { 509 codegen_->GenerateFrameExit(); 510 __ ret(); 511} 512 513void LocationsBuilderX86::VisitReturn(HReturn* ret) { 514 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret); 515 switch (ret->InputAt(0)->GetType()) { 516 case Primitive::kPrimBoolean: 517 case Primitive::kPrimByte: 518 case Primitive::kPrimChar: 519 case Primitive::kPrimShort: 520 case Primitive::kPrimInt: 521 case Primitive::kPrimNot: 522 locations->SetInAt(0, X86CpuLocation(EAX)); 523 break; 524 525 case Primitive::kPrimLong: 526 locations->SetInAt( 527 0, Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX))); 528 break; 529 530 default: 531 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType(); 532 } 533 ret->SetLocations(locations); 534} 535 536void InstructionCodeGeneratorX86::VisitReturn(HReturn* ret) { 537 if (kIsDebugBuild) { 538 switch (ret->InputAt(0)->GetType()) { 539 case Primitive::kPrimBoolean: 540 case Primitive::kPrimByte: 541 case Primitive::kPrimChar: 542 case Primitive::kPrimShort: 543 case Primitive::kPrimInt: 544 case Primitive::kPrimNot: 545 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsCpuRegister(), EAX); 546 break; 547 548 case Primitive::kPrimLong: 549 DCHECK_EQ(ret->GetLocations()->InAt(0).AsX86().AsRegisterPair(), EAX_EDX); 550 break; 551 552 default: 553 LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType(); 554 } 555 } 556 codegen_->GenerateFrameExit(); 557 __ ret(); 558} 559 560void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) { 561 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke); 562 locations->AddTemp(Location::RequiresRegister()); 563 564 InvokeDexCallingConventionVisitor calling_convention_visitor; 565 for (size_t i = 0; i < invoke->InputCount(); i++) { 566 HInstruction* input = invoke->InputAt(i); 567 locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType())); 568 } 569 570 switch (invoke->GetType()) { 571 case Primitive::kPrimBoolean: 572 case Primitive::kPrimByte: 573 case Primitive::kPrimChar: 574 case Primitive::kPrimShort: 575 case Primitive::kPrimInt: 576 case Primitive::kPrimNot: 577 locations->SetOut(X86CpuLocation(EAX)); 578 break; 579 580 case Primitive::kPrimLong: 581 locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(EAX_EDX))); 582 break; 583 584 case Primitive::kPrimVoid: 585 break; 586 587 case Primitive::kPrimDouble: 588 case Primitive::kPrimFloat: 589 LOG(FATAL) << "Unimplemented return type " << invoke->GetType(); 590 break; 591 } 592 593 invoke->SetLocations(locations); 594} 595 596void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) { 597 Register temp = invoke->GetLocations()->GetTemp(0).AsX86().AsCpuRegister(); 598 size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + 599 invoke->GetIndexInDexCache() * kX86WordSize; 600 601 // TODO: Implement all kinds of calls: 602 // 1) boot -> boot 603 // 2) app -> boot 604 // 3) app -> app 605 // 606 // Currently we implement the app -> app logic, which looks up in the resolve cache. 607 608 // temp = method; 609 LoadCurrentMethod(temp); 610 // temp = temp->dex_cache_resolved_methods_; 611 __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value())); 612 // temp = temp[index_in_cache] 613 __ movl(temp, Address(temp, index_in_cache)); 614 // (temp + offset_of_quick_compiled_code)() 615 __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value())); 616 617 codegen_->RecordPcInfo(invoke->GetDexPc()); 618} 619 620void LocationsBuilderX86::VisitAdd(HAdd* add) { 621 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add); 622 switch (add->GetResultType()) { 623 case Primitive::kPrimInt: 624 case Primitive::kPrimLong: { 625 locations->SetInAt(0, Location::RequiresRegister()); 626 locations->SetInAt(1, Location::Any()); 627 locations->SetOut(Location::SameAsFirstInput()); 628 break; 629 } 630 631 case Primitive::kPrimBoolean: 632 case Primitive::kPrimByte: 633 case Primitive::kPrimChar: 634 case Primitive::kPrimShort: 635 LOG(FATAL) << "Unexpected add type " << add->GetResultType(); 636 break; 637 638 default: 639 LOG(FATAL) << "Unimplemented add type " << add->GetResultType(); 640 } 641 add->SetLocations(locations); 642} 643 644void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) { 645 LocationSummary* locations = add->GetLocations(); 646 switch (add->GetResultType()) { 647 case Primitive::kPrimInt: { 648 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), 649 locations->Out().AsX86().AsCpuRegister()); 650 if (locations->InAt(1).IsRegister()) { 651 __ addl(locations->InAt(0).AsX86().AsCpuRegister(), 652 locations->InAt(1).AsX86().AsCpuRegister()); 653 } else { 654 __ addl(locations->InAt(0).AsX86().AsCpuRegister(), 655 Address(ESP, locations->InAt(1).GetStackIndex())); 656 } 657 break; 658 } 659 660 case Primitive::kPrimLong: { 661 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(), 662 locations->Out().AsX86().AsRegisterPair()); 663 if (locations->InAt(1).IsRegister()) { 664 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(), 665 locations->InAt(1).AsX86().AsRegisterPairLow()); 666 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(), 667 locations->InAt(1).AsX86().AsRegisterPairHigh()); 668 } else { 669 __ addl(locations->InAt(0).AsX86().AsRegisterPairLow(), 670 Address(ESP, locations->InAt(1).GetStackIndex())); 671 __ adcl(locations->InAt(0).AsX86().AsRegisterPairHigh(), 672 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize))); 673 } 674 break; 675 } 676 677 case Primitive::kPrimBoolean: 678 case Primitive::kPrimByte: 679 case Primitive::kPrimChar: 680 case Primitive::kPrimShort: 681 LOG(FATAL) << "Unexpected add type " << add->GetResultType(); 682 break; 683 684 default: 685 LOG(FATAL) << "Unimplemented add type " << add->GetResultType(); 686 } 687} 688 689void LocationsBuilderX86::VisitSub(HSub* sub) { 690 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub); 691 switch (sub->GetResultType()) { 692 case Primitive::kPrimInt: 693 case Primitive::kPrimLong: { 694 locations->SetInAt(0, Location::RequiresRegister()); 695 locations->SetInAt(1, Location::Any()); 696 locations->SetOut(Location::SameAsFirstInput()); 697 break; 698 } 699 700 case Primitive::kPrimBoolean: 701 case Primitive::kPrimByte: 702 case Primitive::kPrimChar: 703 case Primitive::kPrimShort: 704 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType(); 705 break; 706 707 default: 708 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType(); 709 } 710 sub->SetLocations(locations); 711} 712 713void InstructionCodeGeneratorX86::VisitSub(HSub* sub) { 714 LocationSummary* locations = sub->GetLocations(); 715 switch (sub->GetResultType()) { 716 case Primitive::kPrimInt: { 717 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), 718 locations->Out().AsX86().AsCpuRegister()); 719 if (locations->InAt(1).IsRegister()) { 720 __ subl(locations->InAt(0).AsX86().AsCpuRegister(), 721 locations->InAt(1).AsX86().AsCpuRegister()); 722 } else { 723 __ subl(locations->InAt(0).AsX86().AsCpuRegister(), 724 Address(ESP, locations->InAt(1).GetStackIndex())); 725 } 726 break; 727 } 728 729 case Primitive::kPrimLong: { 730 DCHECK_EQ(locations->InAt(0).AsX86().AsRegisterPair(), 731 locations->Out().AsX86().AsRegisterPair()); 732 if (locations->InAt(1).IsRegister()) { 733 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(), 734 locations->InAt(1).AsX86().AsRegisterPairLow()); 735 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(), 736 locations->InAt(1).AsX86().AsRegisterPairHigh()); 737 } else { 738 __ subl(locations->InAt(0).AsX86().AsRegisterPairLow(), 739 Address(ESP, locations->InAt(1).GetStackIndex())); 740 __ sbbl(locations->InAt(0).AsX86().AsRegisterPairHigh(), 741 Address(ESP, locations->InAt(1).GetHighStackIndex(kX86WordSize))); 742 } 743 break; 744 } 745 746 case Primitive::kPrimBoolean: 747 case Primitive::kPrimByte: 748 case Primitive::kPrimChar: 749 case Primitive::kPrimShort: 750 LOG(FATAL) << "Unexpected sub type " << sub->GetResultType(); 751 break; 752 753 default: 754 LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType(); 755 } 756} 757 758void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) { 759 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); 760 locations->SetOut(X86CpuLocation(EAX)); 761 InvokeRuntimeCallingConvention calling_convention; 762 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(0))); 763 locations->AddTemp(X86CpuLocation(calling_convention.GetRegisterAt(1))); 764 instruction->SetLocations(locations); 765} 766 767void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) { 768 InvokeRuntimeCallingConvention calling_convention; 769 LoadCurrentMethod(calling_convention.GetRegisterAt(1)); 770 __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex())); 771 772 __ fs()->call( 773 Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pAllocObjectWithAccessCheck))); 774 775 codegen_->RecordPcInfo(instruction->GetDexPc()); 776} 777 778void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) { 779 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); 780 Location location = parameter_visitor_.GetNextLocation(instruction->GetType()); 781 if (location.IsStackSlot()) { 782 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize()); 783 } else if (location.IsDoubleStackSlot()) { 784 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize()); 785 } 786 locations->SetOut(location); 787 instruction->SetLocations(locations); 788} 789 790void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) { 791 // Nothing to do, the parameter is already at its location. 792} 793 794void LocationsBuilderX86::VisitNot(HNot* instruction) { 795 LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); 796 locations->SetInAt(0, Location::RequiresRegister()); 797 locations->SetOut(Location::SameAsFirstInput()); 798 instruction->SetLocations(locations); 799} 800 801void InstructionCodeGeneratorX86::VisitNot(HNot* instruction) { 802 LocationSummary* locations = instruction->GetLocations(); 803 Location out = locations->Out(); 804 DCHECK_EQ(locations->InAt(0).AsX86().AsCpuRegister(), out.AsX86().AsCpuRegister()); 805 __ xorl(out.AsX86().AsCpuRegister(), Immediate(1)); 806} 807 808void LocationsBuilderX86::VisitPhi(HPhi* instruction) { 809 LOG(FATAL) << "Unimplemented"; 810} 811 812void InstructionCodeGeneratorX86::VisitPhi(HPhi* instruction) { 813 LOG(FATAL) << "Unimplemented"; 814} 815 816} // namespace x86 817} // namespace art 818