From bb9863af3a98622e650de78fb235ab484b50eb1f Mon Sep 17 00:00:00 2001 From: Alexey Frunze Date: Mon, 11 Jan 2016 15:51:16 -0800 Subject: [PATCH] MIPS32: don't use R2+ instructions (mthc1, mfhc1) on MIPS32R1 or with 32-bit FPUs. Change-Id: If66932fb39cdd5946f6c05c82036191ad405a877 --- compiler/optimizing/code_generator_mips.cc | 16 ++++++++-------- compiler/optimizing/intrinsics_mips.cc | 12 ++++++++---- compiler/optimizing/intrinsics_mips.h | 5 +++-- compiler/utils/mips/assembler_mips.cc | 22 ++++++++++++++++++++-- compiler/utils/mips/assembler_mips.h | 2 ++ 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index 75f5fb3ba..015618776 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -605,9 +605,9 @@ void ParallelMoveResolverMIPS::EmitSwap(size_t index) { // then swap the high 32 bits of the same FPR. mtc1 makes the high 32 bits of an FPR // unpredictable and the following mfch1 will fail. __ Mfc1(TMP, f1); - __ Mfhc1(AT, f1); + __ MoveFromFpuHigh(AT, f1); __ Mtc1(r2_l, f1); - __ Mthc1(r2_h, f1); + __ MoveToFpuHigh(r2_h, f1); __ Move(r2_l, TMP); __ Move(r2_h, AT); } else if (loc1.IsStackSlot() && loc2.IsStackSlot()) { @@ -859,7 +859,7 @@ void CodeGeneratorMIPS::Move64(Location destination, Location source) { Register dst_low = destination.AsRegisterPairLow(); FRegister src = source.AsFpuRegister(); __ Mfc1(dst_low, src); - __ Mfhc1(dst_high, src); + __ MoveFromFpuHigh(dst_high, src); } else { DCHECK(source.IsDoubleStackSlot()) << "Cannot move from " << source << " to " << destination; int32_t off = source.GetStackIndex(); @@ -872,7 +872,7 @@ void CodeGeneratorMIPS::Move64(Location destination, Location source) { Register src_high = source.AsRegisterPairHigh(); Register src_low = source.AsRegisterPairLow(); __ Mtc1(src_low, dst); - __ Mthc1(src_high, dst); + __ MoveToFpuHigh(src_high, dst); } else if (source.IsFpuRegister()) { __ MovD(destination.AsFpuRegister(), source.AsFpuRegister()); } else { @@ -3525,8 +3525,8 @@ void InstructionCodeGeneratorMIPS::HandleFieldGet(HInstruction* instruction, // Need to move to FP regs since FP results are returned in core registers. __ Mtc1(locations->GetTemp(1).AsRegister(), locations->Out().AsFpuRegister()); - __ Mthc1(locations->GetTemp(2).AsRegister(), - locations->Out().AsFpuRegister()); + __ MoveToFpuHigh(locations->GetTemp(2).AsRegister(), + locations->Out().AsFpuRegister()); } } else { if (!Primitive::IsFloatingPointType(type)) { @@ -3646,8 +3646,8 @@ void InstructionCodeGeneratorMIPS::HandleFieldSet(HInstruction* instruction, // Pass FP parameters in core registers. __ Mfc1(locations->GetTemp(1).AsRegister(), locations->InAt(1).AsFpuRegister()); - __ Mfhc1(locations->GetTemp(2).AsRegister(), - locations->InAt(1).AsFpuRegister()); + __ MoveFromFpuHigh(locations->GetTemp(2).AsRegister(), + locations->InAt(1).AsFpuRegister()); } codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pA64Store), instruction, diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 06fab616a..bc126a271 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -43,14 +43,18 @@ ArenaAllocator* IntrinsicCodeGeneratorMIPS::GetAllocator() { return codegen_->GetGraph()->GetArena(); } -inline bool IntrinsicCodeGeneratorMIPS::IsR2OrNewer() { +inline bool IntrinsicCodeGeneratorMIPS::IsR2OrNewer() const { return codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(); } -inline bool IntrinsicCodeGeneratorMIPS::IsR6() { +inline bool IntrinsicCodeGeneratorMIPS::IsR6() const { return codegen_->GetInstructionSetFeatures().IsR6(); } +inline bool IntrinsicCodeGeneratorMIPS::Is32BitFPU() const { + return codegen_->GetInstructionSetFeatures().Is32BitFloatingPoint(); +} + #define __ codegen->GetAssembler()-> static void MoveFromReturnRegister(Location trg, @@ -162,7 +166,7 @@ static void MoveFPToInt(LocationSummary* locations, bool is64bit, MipsAssembler* Register out_hi = locations->Out().AsRegisterPairHigh(); __ Mfc1(out_lo, in); - __ Mfhc1(out_hi, in); + __ MoveFromFpuHigh(out_hi, in); } else { Register out = locations->Out().AsRegister(); @@ -204,7 +208,7 @@ static void MoveIntToFP(LocationSummary* locations, bool is64bit, MipsAssembler* Register in_hi = locations->InAt(0).AsRegisterPairHigh(); __ Mtc1(in_lo, out); - __ Mthc1(in_hi, out); + __ MoveToFpuHigh(in_hi, out); } else { Register in = locations->InAt(0).AsRegister(); diff --git a/compiler/optimizing/intrinsics_mips.h b/compiler/optimizing/intrinsics_mips.h index f86b0efe4..575a7d0a2 100644 --- a/compiler/optimizing/intrinsics_mips.h +++ b/compiler/optimizing/intrinsics_mips.h @@ -67,8 +67,9 @@ INTRINSICS_LIST(OPTIMIZING_INTRINSICS) #undef INTRINSICS_LIST #undef OPTIMIZING_INTRINSICS - bool IsR2OrNewer(void); - bool IsR6(void); + bool IsR2OrNewer() const; + bool IsR6() const; + bool Is32BitFPU() const; private: MipsAssembler* GetAssembler(); diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc index 0dc307c9a..8c462436a 100644 --- a/compiler/utils/mips/assembler_mips.cc +++ b/compiler/utils/mips/assembler_mips.cc @@ -1067,6 +1067,24 @@ void MipsAssembler::Mthc1(Register rt, FRegister fs) { EmitFR(0x11, 0x07, static_cast(rt), fs, static_cast(0), 0x0); } +void MipsAssembler::MoveFromFpuHigh(Register rt, FRegister fs) { + if (Is32BitFPU()) { + CHECK_EQ(fs % 2, 0) << fs; + Mfc1(rt, static_cast(fs + 1)); + } else { + Mfhc1(rt, fs); + } +} + +void MipsAssembler::MoveToFpuHigh(Register rt, FRegister fs) { + if (Is32BitFPU()) { + CHECK_EQ(fs % 2, 0) << fs; + Mtc1(rt, static_cast(fs + 1)); + } else { + Mthc1(rt, fs); + } +} + void MipsAssembler::Lwc1(FRegister ft, Register rs, uint16_t imm16) { EmitI(0x31, rs, static_cast(ft), imm16); } @@ -1213,10 +1231,10 @@ void MipsAssembler::LoadDConst64(FRegister rd, int64_t value, Register temp) { Mtc1(temp, rd); } if (high == 0) { - Mthc1(ZERO, rd); + MoveToFpuHigh(ZERO, rd); } else { LoadConst32(temp, high); - Mthc1(temp, rd); + MoveToFpuHigh(temp, rd); } } diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h index 066e7b001..9aed3463b 100644 --- a/compiler/utils/mips/assembler_mips.h +++ b/compiler/utils/mips/assembler_mips.h @@ -274,6 +274,8 @@ class MipsAssembler FINAL : public Assembler { void Mtc1(Register rt, FRegister fs); void Mfhc1(Register rt, FRegister fs); void Mthc1(Register rt, FRegister fs); + void MoveFromFpuHigh(Register rt, FRegister fs); + void MoveToFpuHigh(Register rt, FRegister fs); void Lwc1(FRegister ft, Register rs, uint16_t imm16); void Ldc1(FRegister ft, Register rs, uint16_t imm16); void Swc1(FRegister ft, Register rs, uint16_t imm16); -- 2.11.0