From 027f0ff64c2512b9a5f1f54f3fea1bec481eb0f5 Mon Sep 17 00:00:00 2001 From: Douglas Leung Date: Fri, 27 Feb 2015 19:05:03 -0800 Subject: [PATCH] ART: Add Mips32r6 backend support Add Mips32r6 compiler support. Don't use deprecated Mips32r2 instructions if running in Mips32r6 mode. Change-Id: I54e689aa8c026ccb75c4af515aa2794f471c9f67 --- compiler/dex/quick/mips/assemble_mips.cc | 23 +++++ compiler/dex/quick/mips/codegen_mips.h | 8 ++ compiler/dex/quick/mips/fp_mips.cc | 28 +++++- compiler/dex/quick/mips/int_mips.cc | 45 ++++++--- compiler/dex/quick/mips/mips_lir.h | 48 +++++---- compiler/dex/quick/mips/target_mips.cc | 70 ++++++++----- compiler/dex/quick/mips/utility_mips.cc | 168 ++++++++++++++++++++----------- dex2oat/dex2oat.cc | 10 +- disassembler/disassembler_mips.cc | 12 ++- 9 files changed, 280 insertions(+), 132 deletions(-) diff --git a/compiler/dex/quick/mips/assemble_mips.cc b/compiler/dex/quick/mips/assemble_mips.cc index 5c98b10b5..0218dcdd2 100644 --- a/compiler/dex/quick/mips/assemble_mips.cc +++ b/compiler/dex/quick/mips/assemble_mips.cc @@ -393,6 +393,14 @@ const MipsEncodingMap MipsMir2Lir::EncodingMap[kMipsLast] = { kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1, kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1, "mtc1", "!0r,!1s", 4), + ENCODING_MAP(kMipsMfhc1, 0x44600000, + kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1, + kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, + "mfhc1", "!0r,!1s", 4), + ENCODING_MAP(kMipsMthc1, 0x44e00000, + kFmtBitBlt, 20, 16, kFmtSfp, 15, 11, kFmtUnused, -1, -1, + kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1, + "mthc1", "!0r,!1s", 4), ENCODING_MAP(kMipsDelta, 0x27e00000, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, 15, 0, kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | REG_USE_LR | @@ -413,6 +421,21 @@ const MipsEncodingMap MipsMir2Lir::EncodingMap[kMipsLast] = { kFmtBitBlt, 10, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, IS_UNARY_OP, "sync", ";", 4), + + // The following are mips32r6 instructions. + ENCODING_MAP(kMipsR6Div, 0x0000009a, + kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, + kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, + "div", "!0r,!1r,!2r", 4), + ENCODING_MAP(kMipsR6Mod, 0x000000da, + kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, + kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, + "mod", "!0r,!1r,!2r", 4), + ENCODING_MAP(kMipsR6Mul, 0x00000098, + kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, + kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, + "mul", "!0r,!1r,!2r", 4), + ENCODING_MAP(kMipsUndefined, 0x64000000, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, NO_OPERAND, diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h index e1b43ca84..47837a659 100644 --- a/compiler/dex/quick/mips/codegen_mips.h +++ b/compiler/dex/quick/mips/codegen_mips.h @@ -76,7 +76,9 @@ class MipsMir2Lir FINAL : public Mir2Lir { // Required for target - register utilities. RegStorage Solo64ToPair64(RegStorage reg); + RegStorage Fp64ToSolo32(RegStorage reg); RegStorage TargetReg(SpecialTargetRegister reg); + RegStorage TargetReg(SpecialTargetRegister reg, WideKind wide_kind) OVERRIDE; RegLocation GetReturnAlt(); RegLocation GetReturnWideAlt(); RegLocation LocCReturn(); @@ -232,6 +234,12 @@ class MipsMir2Lir FINAL : public Mir2Lir { return false; } + // True if isa is rev R6. + const bool isaIsR6_; + + // True if floating point unit is 32bits. + const bool fpuIs32Bit_; + private: void GenNegLong(RegLocation rl_dest, RegLocation rl_src); void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, diff --git a/compiler/dex/quick/mips/fp_mips.cc b/compiler/dex/quick/mips/fp_mips.cc index d7ed7acf5..37bf1a6b9 100644 --- a/compiler/dex/quick/mips/fp_mips.cc +++ b/compiler/dex/quick/mips/fp_mips.cc @@ -181,6 +181,30 @@ void MipsMir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest, } } +// Get the reg storage for a wide FP. Is either a solo or a pair. Base is Mips-counted, e.g., even +// values are valid (0, 2). +static RegStorage GetWideArgFP(bool fpuIs32Bit, size_t base) { + // Think about how to make this be able to be computed. E.g., rMIPS_FARG0 + base. Right now + // inlining should optimize everything. + if (fpuIs32Bit) { + switch (base) { + case 0: + return RegStorage(RegStorage::k64BitPair, rMIPS_FARG0, rMIPS_FARG1); + case 2: + return RegStorage(RegStorage::k64BitPair, rMIPS_FARG2, rMIPS_FARG3); + } + } else { + switch (base) { + case 0: + return RegStorage(RegStorage::k64BitSolo, rMIPS_FARG0); + case 2: + return RegStorage(RegStorage::k64BitSolo, rMIPS_FARG2); + } + } + LOG(FATAL) << "Unsupported Mips.GetWideFP: " << fpuIs32Bit << " " << base; + UNREACHABLE(); +} + void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { bool wide = true; @@ -208,8 +232,8 @@ void MipsMir2Lir::GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, FlushAllRegs(); LockCallTemps(); if (wide) { - RegStorage r_tmp1(RegStorage::k64BitPair, rMIPS_FARG0, rMIPS_FARG1); - RegStorage r_tmp2(RegStorage::k64BitPair, rMIPS_FARG2, rMIPS_FARG3); + RegStorage r_tmp1 = GetWideArgFP(fpuIs32Bit_, 0); + RegStorage r_tmp2 = GetWideArgFP(fpuIs32Bit_, 2); LoadValueDirectWideFixed(rl_src1, r_tmp1); LoadValueDirectWideFixed(rl_src2, r_tmp2); } else { diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc index 17ac62931..8c9acf60f 100644 --- a/compiler/dex/quick/mips/int_mips.cc +++ b/compiler/dex/quick/mips/int_mips.cc @@ -194,17 +194,34 @@ void MipsMir2Lir::OpRegCopyWide(RegStorage r_dest, RegStorage r_src) { bool src_fp = r_src.IsFloat(); if (dest_fp) { if (src_fp) { + // Here if both src and dest are fp registers. OpRegCopy will choose the right copy + // (solo or pair). OpRegCopy(r_dest, r_src); } else { - /* note the operands are swapped for the mtc1 instr */ - NewLIR2(kMipsMtc1, r_src.GetLowReg(), r_dest.GetLowReg()); - NewLIR2(kMipsMtc1, r_src.GetHighReg(), r_dest.GetHighReg()); + // note the operands are swapped for the mtc1 and mthc1 instr. + // Here if dest is fp reg and src is core reg. + if (fpuIs32Bit_) { + NewLIR2(kMipsMtc1, r_src.GetLowReg(), r_dest.GetLowReg()); + NewLIR2(kMipsMtc1, r_src.GetHighReg(), r_dest.GetHighReg()); + } else { + r_dest = Fp64ToSolo32(r_dest); + NewLIR2(kMipsMtc1, r_src.GetLowReg(), r_dest.GetReg()); + NewLIR2(kMipsMthc1, r_src.GetHighReg(), r_dest.GetReg()); + } } } else { if (src_fp) { - NewLIR2(kMipsMfc1, r_dest.GetLowReg(), r_src.GetLowReg()); - NewLIR2(kMipsMfc1, r_dest.GetHighReg(), r_src.GetHighReg()); + // Here if dest is core reg and src is fp reg. + if (fpuIs32Bit_) { + NewLIR2(kMipsMfc1, r_dest.GetLowReg(), r_src.GetLowReg()); + NewLIR2(kMipsMfc1, r_dest.GetHighReg(), r_src.GetHighReg()); + } else { + r_src = Fp64ToSolo32(r_src); + NewLIR2(kMipsMfc1, r_dest.GetLowReg(), r_src.GetReg()); + NewLIR2(kMipsMfhc1, r_dest.GetHighReg(), r_src.GetReg()); + } } else { + // Here if both src and dest are core registers. // Handle overlap if (r_src.GetHighReg() == r_dest.GetLowReg()) { OpRegCopy(r_dest.GetHigh(), r_src.GetHigh()); @@ -243,12 +260,14 @@ void MipsMir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) { RegLocation MipsMir2Lir::GenDivRem(RegLocation rl_dest, RegStorage reg1, RegStorage reg2, bool is_div) { - NewLIR2(kMipsDiv, reg1.GetReg(), reg2.GetReg()); RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); - if (is_div) { - NewLIR1(kMipsMflo, rl_result.reg.GetReg()); + + if (isaIsR6_) { + NewLIR3(is_div ? kMipsR6Div : kMipsR6Mod, + rl_result.reg.GetReg(), reg1.GetReg(), reg2.GetReg()); } else { - NewLIR1(kMipsMfhi, rl_result.reg.GetReg()); + NewLIR2(kMipsDiv, reg1.GetReg(), reg2.GetReg()); + NewLIR1(is_div ? kMipsMflo : kMipsMfhi, rl_result.reg.GetReg()); } return rl_result; } @@ -257,13 +276,7 @@ RegLocation MipsMir2Lir::GenDivRemLit(RegLocation rl_dest, RegStorage reg1, int bool is_div) { RegStorage t_reg = AllocTemp(); NewLIR3(kMipsAddiu, t_reg.GetReg(), rZERO, lit); - NewLIR2(kMipsDiv, reg1.GetReg(), t_reg.GetReg()); - RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); - if (is_div) { - NewLIR1(kMipsMflo, rl_result.reg.GetReg()); - } else { - NewLIR1(kMipsMfhi, rl_result.reg.GetReg()); - } + RegLocation rl_result = GenDivRem(rl_dest, reg1, t_reg, is_div); FreeTemp(t_reg); return rl_result; } diff --git a/compiler/dex/quick/mips/mips_lir.h b/compiler/dex/quick/mips/mips_lir.h index 66e389420..70370559b 100644 --- a/compiler/dex/quick/mips/mips_lir.h +++ b/compiler/dex/quick/mips/mips_lir.h @@ -236,22 +236,22 @@ enum MipsNativeRegisterPool { // private marker to avoid generate-operator-out. #endif // Double precision registers where the FPU is in 64-bit mode. rD0_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 0, - rD1_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 1, - rD2_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 2, - rD3_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 3, - rD4_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 4, - rD5_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 5, - rD6_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 6, - rD7_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 7, + rD1_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 2, + rD2_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 4, + rD3_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 6, + rD4_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 8, + rD5_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 10, + rD6_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 12, + rD7_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 14, #if 0 // TODO: expand resource mask to enable use of all MIPS fp registers. - rD8_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 8, - rD9_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 9, - rD10_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 10, - rD11_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 11, - rD12_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 12, - rD13_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 13, - rD14_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 14, - rD15_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 15, + rD8_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 16, + rD9_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 18, + rD10_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 20, + rD11_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 22, + rD12_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 24, + rD13_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 26, + rD14_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 28, + rD15_fr1 = RegStorage::k64BitSolo | RegStorage::kFloatingPoint | 30, #endif }; @@ -368,10 +368,12 @@ const RegLocation mips_loc_c_return_wide const RegLocation mips_loc_c_return_float {kLocPhysReg, 0, 0, 0, 1, 0, 0, 0, 1, RegStorage(RegStorage::k32BitSolo, rF0), INVALID_SREG, INVALID_SREG}; -// FIXME: move MIPS to k64Bitsolo for doubles -const RegLocation mips_loc_c_return_double +const RegLocation mips_loc_c_return_double_fr0 {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1, RegStorage(RegStorage::k64BitPair, rF0, rF1), INVALID_SREG, INVALID_SREG}; +const RegLocation mips_loc_c_return_double_fr1 + {kLocPhysReg, 1, 0, 0, 1, 0, 0, 0, 1, + RegStorage(RegStorage::k64BitSolo, rF0), INVALID_SREG, INVALID_SREG}; enum MipsShiftEncodings { kMipsLsl = 0x0, @@ -476,13 +478,21 @@ enum MipsOpCode { kMipsFldc1, // ldc1 t,o(b) [110101] b[25..21] t[20..16] o[15..0]. kMipsFswc1, // swc1 t,o(b) [111001] b[25..21] t[20..16] o[15..0]. kMipsFsdc1, // sdc1 t,o(b) [111101] b[25..21] t[20..16] o[15..0]. - kMipsMfc1, // mfc1 t,s [01000100000] t[20..16] s[15..11] [00000000000]. - kMipsMtc1, // mtc1 t,s [01000100100] t[20..16] s[15..11] [00000000000]. + kMipsMfc1, // mfc1 t,s [01000100000] t[20..16] s[15..11] [00000000000]. + kMipsMtc1, // mtc1 t,s [01000100100] t[20..16] s[15..11] [00000000000]. + kMipsMfhc1, // mfhc1 t,s [01000100011] t[20..16] s[15..11] [00000000000]. + kMipsMthc1, // mthc1 t,s [01000100111] t[20..16] s[15..11] [00000000000]. kMipsDelta, // Psuedo for ori t, s,