summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/code_generator_arm.cc
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2014-04-11 17:43:50 +0100
committerNicolas Geoffray <ngeoffray@google.com>2014-04-16 14:21:12 +0100
commit01bc96d007b67fdb7fe349232a83e4b354ce3d08 (patch)
tree1ed36c2d7c0fb204e6f276bd9853153d9350ad1d /compiler/optimizing/code_generator_arm.cc
parent2be6fc74bce10ac68d3d1b39a5019f520ad170ea (diff)
downloadart-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.cc497
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