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