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