MIPS32: Block callee save fp registers in debuggable
This fixes tests 454-get-vreg and 457-regs in debuggable.
Additional changes in LocationsBuilderMIPS::HandleFieldGet/Set
to prevent situations when running out of available fp registers.
Test: mma -j2 ART_TEST_RUN_TEST_DEBUGGABLE=true test-art-target-run-test
Change-Id: Iaad6a6e414ff747b39209780c21aeddc225a04c1
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 39248aa..91b431b 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1067,6 +1067,15 @@
blocked_fpu_registers_[i] = true;
}
+ if (GetGraph()->IsDebuggable()) {
+ // Stubs do not save callee-save floating point registers. If the graph
+ // is debuggable, we need to deal with these registers differently. For
+ // now, just block them.
+ for (size_t i = 0; i < arraysize(kFpuCalleeSaves); ++i) {
+ blocked_fpu_registers_[kFpuCalleeSaves[i]] = true;
+ }
+ }
+
UpdateBlockedPairRegisters();
}
@@ -3440,7 +3449,8 @@
if (field_type == Primitive::kPrimLong) {
locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimLong));
} else {
- locations->SetOut(Location::RequiresFpuRegister());
+ // Use Location::Any() to prevent situations when running out of available fp registers.
+ locations->SetOut(Location::Any());
// Need some temp core regs since FP results are returned in core registers
Location reg = calling_convention.GetReturnLocation(Primitive::kPrimLong);
locations->AddTemp(Location::RegisterLocation(reg.AsRegisterPairLow<Register>()));
@@ -3505,11 +3515,23 @@
IsDirectEntrypoint(kQuickA64Load));
CheckEntrypointTypes<kQuickA64Load, int64_t, volatile const int64_t*>();
if (type == Primitive::kPrimDouble) {
- // Need to move to FP regs since FP results are returned in core registers.
- __ Mtc1(locations->GetTemp(1).AsRegister<Register>(),
- locations->Out().AsFpuRegister<FRegister>());
- __ MoveToFpuHigh(locations->GetTemp(2).AsRegister<Register>(),
- locations->Out().AsFpuRegister<FRegister>());
+ // FP results are returned in core registers. Need to move them.
+ Location out = locations->Out();
+ if (out.IsFpuRegister()) {
+ __ Mtc1(locations->GetTemp(1).AsRegister<Register>(), out.AsFpuRegister<FRegister>());
+ __ MoveToFpuHigh(locations->GetTemp(2).AsRegister<Register>(),
+ out.AsFpuRegister<FRegister>());
+ } else {
+ DCHECK(out.IsDoubleStackSlot());
+ __ StoreToOffset(kStoreWord,
+ locations->GetTemp(1).AsRegister<Register>(),
+ SP,
+ out.GetStackIndex());
+ __ StoreToOffset(kStoreWord,
+ locations->GetTemp(2).AsRegister<Register>(),
+ SP,
+ out.GetStackIndex() + 4);
+ }
}
} else {
if (!Primitive::IsFloatingPointType(type)) {
@@ -3568,7 +3590,8 @@
locations->SetInAt(1, Location::RegisterPairLocation(
calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3)));
} else {
- locations->SetInAt(1, Location::RequiresFpuRegister());
+ // Use Location::Any() to prevent situations when running out of available fp registers.
+ locations->SetInAt(1, Location::Any());
// Pass FP parameters in core registers.
locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(3)));
@@ -3627,10 +3650,28 @@
codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
if (type == Primitive::kPrimDouble) {
// Pass FP parameters in core registers.
- __ Mfc1(locations->GetTemp(1).AsRegister<Register>(),
- locations->InAt(1).AsFpuRegister<FRegister>());
- __ MoveFromFpuHigh(locations->GetTemp(2).AsRegister<Register>(),
- locations->InAt(1).AsFpuRegister<FRegister>());
+ Location in = locations->InAt(1);
+ if (in.IsFpuRegister()) {
+ __ Mfc1(locations->GetTemp(1).AsRegister<Register>(), in.AsFpuRegister<FRegister>());
+ __ MoveFromFpuHigh(locations->GetTemp(2).AsRegister<Register>(),
+ in.AsFpuRegister<FRegister>());
+ } else if (in.IsDoubleStackSlot()) {
+ __ LoadFromOffset(kLoadWord,
+ locations->GetTemp(1).AsRegister<Register>(),
+ SP,
+ in.GetStackIndex());
+ __ LoadFromOffset(kLoadWord,
+ locations->GetTemp(2).AsRegister<Register>(),
+ SP,
+ in.GetStackIndex() + 4);
+ } else {
+ DCHECK(in.IsConstant());
+ DCHECK(in.GetConstant()->IsDoubleConstant());
+ int64_t value = bit_cast<int64_t, double>(in.GetConstant()->AsDoubleConstant()->GetValue());
+ __ LoadConst64(locations->GetTemp(2).AsRegister<Register>(),
+ locations->GetTemp(1).AsRegister<Register>(),
+ value);
+ }
}
codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pA64Store),
instruction,