diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2014-04-11 17:43:50 +0100 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2014-04-16 14:21:12 +0100 |
commit | 01bc96d007b67fdb7fe349232a83e4b354ce3d08 (patch) | |
tree | 1ed36c2d7c0fb204e6f276bd9853153d9350ad1d /compiler/optimizing/code_generator_arm.cc | |
parent | 2be6fc74bce10ac68d3d1b39a5019f520ad170ea (diff) | |
download | art-01bc96d007b67fdb7fe349232a83e4b354ce3d08.zip art-01bc96d007b67fdb7fe349232a83e4b354ce3d08.tar.gz art-01bc96d007b67fdb7fe349232a83e4b354ce3d08.tar.bz2 |
Long support in optimizing compiler.
- Add stack locations to the Location class.
- Change logic of parameter passing/setup by setting the
location of such instructions the ones for the calling
convention.
Change-Id: I4730ad58732813dcb9c238f44f55dfc0baa18799
Diffstat (limited to 'compiler/optimizing/code_generator_arm.cc')
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 497 |
1 files changed, 416 insertions, 81 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 4e88765..fe61333 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -17,6 +17,7 @@ #include "code_generator_arm.h" #include "utils/assembler.h" #include "utils/arm/assembler_arm.h" +#include "utils/arm/managed_register_arm.h" #include "mirror/array.h" #include "mirror/art_method.h" @@ -24,11 +25,20 @@ #define __ reinterpret_cast<ArmAssembler*>(GetAssembler())-> namespace art { + +arm::ArmManagedRegister Location::AsArm() const { + return reg().AsArm(); +} + namespace arm { static constexpr int kNumberOfPushedRegistersAtEntry = 1; static constexpr int kCurrentMethodStackOffset = 0; +static Location ArmCoreLocation(Register reg) { + return Location::RegisterLocation(ArmManagedRegister::FromCoreRegister(reg)); +} + InstructionCodeGeneratorARM::InstructionCodeGeneratorARM(HGraph* graph, CodeGeneratorARM* codegen) : HGraphVisitor(graph), assembler_(codegen->GetAssembler()), @@ -73,18 +83,171 @@ int32_t CodeGeneratorARM::GetStackSlot(HLocal* local) const { } } +static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 }; +static constexpr RegisterPair kParameterCorePairRegisters[] = { R1_R2, R2_R3 }; +static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); + +class InvokeDexCallingConvention : public CallingConvention<Register> { + public: + InvokeDexCallingConvention() + : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {} + + RegisterPair GetRegisterPairAt(size_t argument_index) { + DCHECK_LT(argument_index + 1, GetNumberOfRegisters()); + return kParameterCorePairRegisters[argument_index]; + } + + private: + DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); +}; + +void CodeGeneratorARM::Move32(Location destination, Location source) { + if (source.Equals(destination)) { + return; + } + if (destination.IsRegister()) { + if (source.IsRegister()) { + __ Mov(destination.AsArm().AsCoreRegister(), source.AsArm().AsCoreRegister()); + } else { + __ ldr(destination.AsArm().AsCoreRegister(), Address(SP, source.GetStackIndex())); + } + } else { + DCHECK(destination.IsStackSlot()); + if (source.IsRegister()) { + __ str(source.AsArm().AsCoreRegister(), Address(SP, destination.GetStackIndex())); + } else { + __ ldr(R0, Address(SP, source.GetStackIndex())); + __ str(R0, Address(SP, destination.GetStackIndex())); + } + } +} + +void CodeGeneratorARM::Move64(Location destination, Location source) { + if (source.Equals(destination)) { + return; + } + if (destination.IsRegister()) { + if (source.IsRegister()) { + __ Mov(destination.AsArm().AsRegisterPairLow(), source.AsArm().AsRegisterPairLow()); + __ Mov(destination.AsArm().AsRegisterPairHigh(), source.AsArm().AsRegisterPairHigh()); + } else if (source.IsQuickParameter()) { + uint32_t argument_index = source.GetQuickParameterIndex(); + InvokeDexCallingConvention calling_convention; + __ Mov(destination.AsArm().AsRegisterPairLow(), + calling_convention.GetRegisterAt(argument_index)); + __ ldr(destination.AsArm().AsRegisterPairHigh(), + Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize())); + } else { + DCHECK(source.IsDoubleStackSlot()); + if (destination.AsArm().AsRegisterPair() == R1_R2) { + __ ldr(R1, Address(SP, source.GetStackIndex())); + __ ldr(R2, Address(SP, source.GetHighStackIndex(kArmWordSize))); + } else { + __ LoadFromOffset(kLoadWordPair, destination.AsArm().AsRegisterPairLow(), + SP, source.GetStackIndex()); + } + } + } else if (destination.IsQuickParameter()) { + InvokeDexCallingConvention calling_convention; + uint32_t argument_index = destination.GetQuickParameterIndex(); + if (source.IsRegister()) { + __ Mov(calling_convention.GetRegisterAt(argument_index), source.AsArm().AsRegisterPairLow()); + __ str(source.AsArm().AsRegisterPairHigh(), + Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1))); + } else { + DCHECK(source.IsDoubleStackSlot()); + __ ldr(calling_convention.GetRegisterAt(argument_index), Address(SP, source.GetStackIndex())); + __ ldr(R0, Address(SP, source.GetHighStackIndex(kArmWordSize))); + __ str(R0, Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1))); + } + } else { + DCHECK(destination.IsDoubleStackSlot()); + if (source.IsRegister()) { + if (source.AsArm().AsRegisterPair() == R1_R2) { + __ str(R1, Address(SP, destination.GetStackIndex())); + __ str(R2, Address(SP, destination.GetHighStackIndex(kArmWordSize))); + } else { + __ StoreToOffset(kStoreWordPair, source.AsArm().AsRegisterPairLow(), + SP, destination.GetStackIndex()); + } + } else if (source.IsQuickParameter()) { + InvokeDexCallingConvention calling_convention; + uint32_t argument_index = source.GetQuickParameterIndex(); + __ str(calling_convention.GetRegisterAt(argument_index), + Address(SP, destination.GetStackIndex())); + __ ldr(R0, + Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize())); + __ str(R0, Address(SP, destination.GetHighStackIndex(kArmWordSize))); + } else { + DCHECK(source.IsDoubleStackSlot()); + __ ldr(R0, Address(SP, source.GetStackIndex())); + __ str(R0, Address(SP, destination.GetStackIndex())); + __ ldr(R0, Address(SP, source.GetHighStackIndex(kArmWordSize))); + __ str(R0, Address(SP, destination.GetHighStackIndex(kArmWordSize))); + } + } +} + void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) { if (instruction->AsIntConstant() != nullptr) { - __ LoadImmediate(location.reg<Register>(), instruction->AsIntConstant()->GetValue()); + int32_t value = instruction->AsIntConstant()->GetValue(); + if (location.IsRegister()) { + __ LoadImmediate(location.AsArm().AsCoreRegister(), value); + } else { + __ LoadImmediate(R0, value); + __ str(R0, Address(SP, location.GetStackIndex())); + } + } else if (instruction->AsLongConstant() != nullptr) { + int64_t value = instruction->AsLongConstant()->GetValue(); + if (location.IsRegister()) { + __ LoadImmediate(location.AsArm().AsRegisterPairLow(), Low32Bits(value)); + __ LoadImmediate(location.AsArm().AsRegisterPairHigh(), High32Bits(value)); + } else { + __ LoadImmediate(R0, Low32Bits(value)); + __ str(R0, Address(SP, location.GetStackIndex())); + __ LoadImmediate(R0, High32Bits(value)); + __ str(R0, Address(SP, location.GetHighStackIndex(kArmWordSize))); + } } else if (instruction->AsLoadLocal() != nullptr) { - __ LoadFromOffset(kLoadWord, location.reg<Register>(), - SP, GetStackSlot(instruction->AsLoadLocal()->GetLocal())); + uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal()); + switch (instruction->GetType()) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + case Primitive::kPrimNot: + Move32(location, Location::StackSlot(stack_slot)); + break; + + case Primitive::kPrimLong: + Move64(location, Location::DoubleStackSlot(stack_slot)); + break; + + default: + LOG(FATAL) << "Unimplemented type " << instruction->GetType(); + } } else { // This can currently only happen when the instruction that requests the move // is the next to be compiled. DCHECK_EQ(instruction->GetNext(), move_for); - __ mov(location.reg<Register>(), - ShifterOperand(instruction->GetLocations()->Out().reg<Register>())); + switch (instruction->GetType()) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimNot: + case Primitive::kPrimInt: + Move32(location, instruction->GetLocations()->Out()); + break; + + case Primitive::kPrimLong: + Move64(location, instruction->GetLocations()->Out()); + break; + + default: + LOG(FATAL) << "Unimplemented type " << instruction->GetType(); + } } } @@ -114,13 +277,13 @@ void InstructionCodeGeneratorARM::VisitExit(HExit* exit) { void LocationsBuilderARM::VisitIf(HIf* if_instr) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr); - locations->SetInAt(0, Location(R0)); + locations->SetInAt(0, ArmCoreLocation(R0)); if_instr->SetLocations(locations); } void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) { // TODO: Generate the input as a condition, instead of materializing in a register. - __ cmp(if_instr->GetLocations()->InAt(0).reg<Register>(), ShifterOperand(0)); + __ cmp(if_instr->GetLocations()->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(0)); __ b(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()), EQ); if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) { __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); @@ -129,18 +292,18 @@ void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) { void LocationsBuilderARM::VisitEqual(HEqual* equal) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal); - locations->SetInAt(0, Location(R0)); - locations->SetInAt(1, Location(R1)); - locations->SetOut(Location(R0)); + locations->SetInAt(0, ArmCoreLocation(R0)); + locations->SetInAt(1, ArmCoreLocation(R1)); + locations->SetOut(ArmCoreLocation(R0)); equal->SetLocations(locations); } void InstructionCodeGeneratorARM::VisitEqual(HEqual* equal) { LocationSummary* locations = equal->GetLocations(); - __ teq(locations->InAt(0).reg<Register>(), - ShifterOperand(locations->InAt(1).reg<Register>())); - __ mov(locations->Out().reg<Register>(), ShifterOperand(1), EQ); - __ mov(locations->Out().reg<Register>(), ShifterOperand(0), NE); + __ teq(locations->InAt(0).AsArm().AsCoreRegister(), + ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister())); + __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(1), EQ); + __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(0), NE); } void LocationsBuilderARM::VisitLocal(HLocal* local) { @@ -161,14 +324,27 @@ void InstructionCodeGeneratorARM::VisitLoadLocal(HLoadLocal* load) { void LocationsBuilderARM::VisitStoreLocal(HStoreLocal* store) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store); - locations->SetInAt(1, Location(R0)); + switch (store->InputAt(1)->GetType()) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + case Primitive::kPrimNot: + locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal()))); + break; + + case Primitive::kPrimLong: + locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal()))); + break; + + default: + LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType(); + } store->SetLocations(locations); } void InstructionCodeGeneratorARM::VisitStoreLocal(HStoreLocal* store) { - LocationSummary* locations = store->GetLocations(); - __ StoreToOffset(kStoreWord, locations->InAt(1).reg<Register>(), - SP, codegen_->GetStackSlot(store->GetLocal())); } void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) { @@ -179,6 +355,14 @@ void InstructionCodeGeneratorARM::VisitIntConstant(HIntConstant* constant) { // Will be generated at use site. } +void LocationsBuilderARM::VisitLongConstant(HLongConstant* constant) { + constant->SetLocations(nullptr); +} + +void InstructionCodeGeneratorARM::VisitLongConstant(HLongConstant* constant) { + // Will be generated at use site. +} + void LocationsBuilderARM::VisitReturnVoid(HReturnVoid* ret) { ret->SetLocations(nullptr); } @@ -189,56 +373,118 @@ void InstructionCodeGeneratorARM::VisitReturnVoid(HReturnVoid* ret) { void LocationsBuilderARM::VisitReturn(HReturn* ret) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret); - locations->SetInAt(0, Location(R0)); + switch (ret->InputAt(0)->GetType()) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + case Primitive::kPrimNot: + locations->SetInAt(0, ArmCoreLocation(R0)); + break; + + case Primitive::kPrimLong: + locations->SetInAt(0, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1))); + break; + + default: + LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType(); + } + ret->SetLocations(locations); } void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) { - DCHECK_EQ(ret->GetLocations()->InAt(0).reg<Register>(), R0); + if (kIsDebugBuild) { + switch (ret->InputAt(0)->GetType()) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + case Primitive::kPrimNot: + DCHECK_EQ(ret->GetLocations()->InAt(0).AsArm().AsCoreRegister(), R0); + break; + + case Primitive::kPrimLong: + DCHECK_EQ(ret->GetLocations()->InAt(0).AsArm().AsRegisterPair(), R0_R1); + break; + + default: + LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType(); + } + } codegen_->GenerateFrameExit(); } -static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 }; -static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); - -class InvokeDexCallingConvention : public CallingConvention<Register> { - public: - InvokeDexCallingConvention() - : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {} - - private: - DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); -}; - void LocationsBuilderARM::VisitPushArgument(HPushArgument* argument) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument); InvokeDexCallingConvention calling_convention; - if (argument->GetArgumentIndex() < calling_convention.GetNumberOfRegisters()) { - Location location = Location(calling_convention.GetRegisterAt(argument->GetArgumentIndex())); - locations->SetInAt(0, location); - locations->SetOut(location); - } else { - locations->SetInAt(0, Location(R0)); + uint32_t argument_index = argument->GetArgumentIndex(); + switch (argument->InputAt(0)->GetType()) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + case Primitive::kPrimNot: { + if (argument_index < calling_convention.GetNumberOfRegisters()) { + locations->SetInAt(0, ArmCoreLocation(calling_convention.GetRegisterAt(argument_index))); + } else { + locations->SetInAt( + 0, Location::StackSlot(calling_convention.GetStackOffsetOf(argument_index))); + } + break; + } + case Primitive::kPrimLong: { + if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) { + Location location = Location::RegisterLocation(ArmManagedRegister::FromRegisterPair( + calling_convention.GetRegisterPairAt(argument_index))); + locations->SetInAt(0, location); + } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) { + locations->SetInAt(0, Location::QuickParameter(argument_index)); + } else { + locations->SetInAt( + 0, Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(argument_index))); + } + break; + } + default: + LOG(FATAL) << "Unimplemented argument type " << argument->InputAt(0)->GetType(); } argument->SetLocations(locations); } void InstructionCodeGeneratorARM::VisitPushArgument(HPushArgument* argument) { - uint8_t argument_index = argument->GetArgumentIndex(); - InvokeDexCallingConvention calling_convention; - size_t parameter_registers = calling_convention.GetNumberOfRegisters(); - LocationSummary* locations = argument->GetLocations(); - if (argument_index >= parameter_registers) { - uint8_t offset = calling_convention.GetStackOffsetOf(argument_index); - __ StoreToOffset(kStoreWord, locations->InAt(0).reg<Register>(), SP, offset); - } else { - DCHECK_EQ(locations->Out().reg<Register>(), locations->InAt(0).reg<Register>()); - } + // Nothing to do. } void LocationsBuilderARM::VisitInvokeStatic(HInvokeStatic* invoke) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke); - locations->AddTemp(Location(R0)); + locations->AddTemp(ArmCoreLocation(R0)); + switch (invoke->GetType()) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + case Primitive::kPrimNot: + locations->SetOut(ArmCoreLocation(R0)); + break; + + case Primitive::kPrimLong: + locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1))); + break; + + case Primitive::kPrimVoid: + break; + + case Primitive::kPrimDouble: + case Primitive::kPrimFloat: + LOG(FATAL) << "Unimplemented return type " << invoke->GetType(); + break; + } + invoke->SetLocations(locations); } @@ -247,7 +493,7 @@ void InstructionCodeGeneratorARM::LoadCurrentMethod(Register reg) { } void InstructionCodeGeneratorARM::VisitInvokeStatic(HInvokeStatic* invoke) { - Register temp = invoke->GetLocations()->GetTemp(0).reg<Register>(); + Register temp = invoke->GetLocations()->GetTemp(0).AsArm().AsCoreRegister(); size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + invoke->GetIndexInDexCache() * kArmWordSize; @@ -277,13 +523,30 @@ void LocationsBuilderARM::VisitAdd(HAdd* add) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add); switch (add->GetResultType()) { case Primitive::kPrimInt: { - locations->SetInAt(0, Location(R0)); - locations->SetInAt(1, Location(R1)); - locations->SetOut(Location(R0)); + locations->SetInAt(0, ArmCoreLocation(R0)); + locations->SetInAt(1, ArmCoreLocation(R1)); + locations->SetOut(ArmCoreLocation(R0)); break; } + + case Primitive::kPrimLong: { + locations->SetInAt( + 0, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1))); + locations->SetInAt( + 1, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R2_R3))); + locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1))); + break; + } + + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + LOG(FATAL) << "Unexpected add type " << add->GetResultType(); + break; + default: - LOG(FATAL) << "Unimplemented"; + LOG(FATAL) << "Unimplemented add type " << add->GetResultType(); } add->SetLocations(locations); } @@ -292,12 +555,29 @@ void InstructionCodeGeneratorARM::VisitAdd(HAdd* add) { LocationSummary* locations = add->GetLocations(); switch (add->GetResultType()) { case Primitive::kPrimInt: - __ add(locations->Out().reg<Register>(), - locations->InAt(0).reg<Register>(), - ShifterOperand(locations->InAt(1).reg<Register>())); + __ add(locations->Out().AsArm().AsCoreRegister(), + locations->InAt(0).AsArm().AsCoreRegister(), + ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister())); + break; + + case Primitive::kPrimLong: + __ adds(locations->Out().AsArm().AsRegisterPairLow(), + locations->InAt(0).AsArm().AsRegisterPairLow(), + ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairLow())); + __ adc(locations->Out().AsArm().AsRegisterPairHigh(), + locations->InAt(0).AsArm().AsRegisterPairHigh(), + ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairHigh())); + break; + + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + LOG(FATAL) << "Unexpected add type " << add->GetResultType(); break; + default: - LOG(FATAL) << "Unimplemented"; + LOG(FATAL) << "Unimplemented add type " << add->GetResultType(); } } @@ -305,13 +585,30 @@ void LocationsBuilderARM::VisitSub(HSub* sub) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub); switch (sub->GetResultType()) { case Primitive::kPrimInt: { - locations->SetInAt(0, Location(R0)); - locations->SetInAt(1, Location(R1)); - locations->SetOut(Location(R0)); + locations->SetInAt(0, ArmCoreLocation(R0)); + locations->SetInAt(1, ArmCoreLocation(R1)); + locations->SetOut(ArmCoreLocation(R0)); + break; + } + + case Primitive::kPrimLong: { + locations->SetInAt( + 0, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1))); + locations->SetInAt( + 1, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R2_R3))); + locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1))); break; } + + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + LOG(FATAL) << "Unexpected sub type " << sub->GetResultType(); + break; + default: - LOG(FATAL) << "Unimplemented"; + LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType(); } sub->SetLocations(locations); } @@ -320,12 +617,29 @@ void InstructionCodeGeneratorARM::VisitSub(HSub* sub) { LocationSummary* locations = sub->GetLocations(); switch (sub->GetResultType()) { case Primitive::kPrimInt: - __ sub(locations->Out().reg<Register>(), - locations->InAt(0).reg<Register>(), - ShifterOperand(locations->InAt(1).reg<Register>())); + __ sub(locations->Out().AsArm().AsCoreRegister(), + locations->InAt(0).AsArm().AsCoreRegister(), + ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister())); break; + + case Primitive::kPrimLong: + __ subs(locations->Out().AsArm().AsRegisterPairLow(), + locations->InAt(0).AsArm().AsRegisterPairLow(), + ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairLow())); + __ sbc(locations->Out().AsArm().AsRegisterPairHigh(), + locations->InAt(0).AsArm().AsRegisterPairHigh(), + ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairHigh())); + break; + + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + LOG(FATAL) << "Unexpected sub type " << sub->GetResultType(); + break; + default: - LOG(FATAL) << "Unimplemented"; + LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType(); } } @@ -345,7 +659,7 @@ class InvokeRuntimeCallingConvention : public CallingConvention<Register> { void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); - locations->SetOut(Location(R0)); + locations->SetOut(ArmCoreLocation(R0)); instruction->SetLocations(locations); } @@ -365,34 +679,55 @@ void LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); InvokeDexCallingConvention calling_convention; uint32_t argument_index = instruction->GetIndex(); - if (argument_index < calling_convention.GetNumberOfRegisters()) { - locations->SetOut(Location(calling_convention.GetRegisterAt(argument_index))); - } else { - locations->SetOut(Location(R0)); + switch (instruction->GetType()) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + case Primitive::kPrimNot: + if (argument_index < calling_convention.GetNumberOfRegisters()) { + locations->SetOut(ArmCoreLocation(calling_convention.GetRegisterAt(argument_index))); + } else { + locations->SetOut(Location::StackSlot( + calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize())); + } + break; + + case Primitive::kPrimLong: + if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) { + locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair( + (calling_convention.GetRegisterPairAt(argument_index))))); + } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) { + // Spanning a register and a stack slot. Use the quick parameter kind. + locations->SetOut(Location::QuickParameter(argument_index)); + } else { + locations->SetOut(Location::DoubleStackSlot( + calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize())); + } + break; + + default: + LOG(FATAL) << "Unimplemented parameter type " << instruction->GetType(); } instruction->SetLocations(locations); } void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instruction) { - LocationSummary* locations = instruction->GetLocations(); - InvokeDexCallingConvention calling_convention; - uint8_t argument_index = instruction->GetIndex(); - if (argument_index >= calling_convention.GetNumberOfRegisters()) { - uint8_t offset = calling_convention.GetStackOffsetOf(argument_index); - __ ldr(locations->Out().reg<Register>(), Address(SP, offset + codegen_->GetFrameSize())); - } + // Nothing to do, the parameter is already at its location. } void LocationsBuilderARM::VisitNot(HNot* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); - locations->SetInAt(0, Location(R0)); - locations->SetOut(Location(R0)); + locations->SetInAt(0, ArmCoreLocation(R0)); + locations->SetOut(ArmCoreLocation(R0)); instruction->SetLocations(locations); } void InstructionCodeGeneratorARM::VisitNot(HNot* instruction) { LocationSummary* locations = instruction->GetLocations(); - __ eor(locations->Out().reg<Register>(), locations->InAt(0).reg<Register>(), ShifterOperand(1)); + __ eor(locations->Out().AsArm().AsCoreRegister(), + locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(1)); } } // namespace arm |