diff options
author | Douglas Leung <douglas.leung@imgtec.com> | 2015-02-27 19:05:03 -0800 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2015-03-20 16:51:56 -0700 |
commit | 027f0ff64c2512b9a5f1f54f3fea1bec481eb0f5 (patch) | |
tree | 9202535f219d7343b4c26d5c43f0bcb7c31650df /compiler | |
parent | 6cc763c8b8157fb42dd44e1dfb84812546500dc1 (diff) | |
download | art-027f0ff64c2512b9a5f1f54f3fea1bec481eb0f5.zip art-027f0ff64c2512b9a5f1f54f3fea1bec481eb0f5.tar.gz art-027f0ff64c2512b9a5f1f54f3fea1bec481eb0f5.tar.bz2 |
ART: Add Mips32r6 backend support
Add Mips32r6 compiler support.
Don't use deprecated Mips32r2 instructions if running in Mips32r6
mode.
Change-Id: I54e689aa8c026ccb75c4af515aa2794f471c9f67
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/dex/quick/mips/assemble_mips.cc | 23 | ||||
-rw-r--r-- | compiler/dex/quick/mips/codegen_mips.h | 8 | ||||
-rw-r--r-- | compiler/dex/quick/mips/fp_mips.cc | 28 | ||||
-rw-r--r-- | compiler/dex/quick/mips/int_mips.cc | 45 | ||||
-rw-r--r-- | compiler/dex/quick/mips/mips_lir.h | 48 | ||||
-rw-r--r-- | compiler/dex/quick/mips/target_mips.cc | 70 | ||||
-rw-r--r-- | compiler/dex/quick/mips/utility_mips.cc | 168 |
7 files changed, 271 insertions, 119 deletions
diff --git a/compiler/dex/quick/mips/assemble_mips.cc b/compiler/dex/quick/mips/assemble_mips.cc index 5c98b10..0218dcd 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 e1b43ca..47837a6 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 d7ed7ac..37bf1a6 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 17ac629..8c9acf6 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 66e3894..7037055 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, <label>-<label>. kMipsDeltaHi, // Pseudo for lui t, high16(<label>-<label>). kMipsDeltaLo, // Pseudo for ori t, s, low16(<label>-<label>). kMipsCurrPC, // jal to .+8 to materialize pc. kMipsSync, // sync kind [000000] [0000000000000000] s[10..6] [001111]. + + // The following are mips32r6 instructions. + kMipsR6Div, // div d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011010]. + kMipsR6Mod, // mod d,s,t [000000] s[25..21] t[20..16] d[15..11] [00011011010]. + kMipsR6Mul, // mul d,s,t [000000] s[25..21] t[20..16] d[15..11] [00010011000]. + kMipsUndefined, // undefined [011001xxxxxxxxxxxxxxxx]. kMipsLast }; diff --git a/compiler/dex/quick/mips/target_mips.cc b/compiler/dex/quick/mips/target_mips.cc index 8574ffd..830f63a 100644 --- a/compiler/dex/quick/mips/target_mips.cc +++ b/compiler/dex/quick/mips/target_mips.cc @@ -86,16 +86,48 @@ RegLocation MipsMir2Lir::LocCReturnFloat() { } RegLocation MipsMir2Lir::LocCReturnDouble() { - return mips_loc_c_return_double; + if (fpuIs32Bit_) { + return mips_loc_c_return_double_fr0; + } else { + return mips_loc_c_return_double_fr1; + } } // Convert k64BitSolo into k64BitPair RegStorage MipsMir2Lir::Solo64ToPair64(RegStorage reg) { DCHECK(reg.IsDouble()); + DCHECK_EQ(reg.GetRegNum() & 1, 0); int reg_num = (reg.GetRegNum() & ~1) | RegStorage::kFloatingPoint; return RegStorage(RegStorage::k64BitPair, reg_num, reg_num + 1); } +// Convert 64bit FP (k64BitSolo or k64BitPair) into k32BitSolo. +// This routine is only used to allow a 64bit FPU to access FP registers 32bits at a time. +RegStorage MipsMir2Lir::Fp64ToSolo32(RegStorage reg) { + DCHECK(!fpuIs32Bit_); + DCHECK(reg.IsDouble()); + DCHECK(!reg.IsPair()); + int reg_num = reg.GetRegNum() | RegStorage::kFloatingPoint; + return RegStorage(RegStorage::k32BitSolo, reg_num); +} + +// Return a target-dependent special register. +RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg, WideKind wide_kind) { + if (wide_kind == kWide) { + DCHECK((kArg0 <= reg && reg < kArg7) || (kFArg0 <= reg && reg < kFArg15) || (kRet0 == reg)); + RegStorage ret_reg = RegStorage::MakeRegPair(TargetReg(reg), + TargetReg(static_cast<SpecialTargetRegister>(reg + 1))); + if (!fpuIs32Bit_ && ret_reg.IsFloat()) { + // convert 64BitPair to 64BitSolo for 64bit FPUs. + RegStorage low = ret_reg.GetLow(); + ret_reg = RegStorage::FloatSolo64(low.GetRegNum()); + } + return ret_reg; + } else { + return TargetReg(reg); + } +} + // Return a target-dependent special register. RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) { RegStorage res_reg; @@ -145,12 +177,7 @@ RegStorage MipsMir2Lir::InToRegStorageMipsMapper::GetNextReg(ShortyArg arg) { */ ResourceMask MipsMir2Lir::GetRegMaskCommon(const RegStorage& reg) const { if (reg.IsDouble()) { - if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures() - ->Is32BitFloatingPoint()) { - return ResourceMask::TwoBits((reg.GetRegNum() & ~1) + kMipsFPReg0); - } else { - return ResourceMask::TwoBits(reg.GetRegNum() * 2 + kMipsFPReg0); - } + return ResourceMask::TwoBits((reg.GetRegNum() & ~1) + kMipsFPReg0); } else if (reg.IsSingle()) { return ResourceMask::Bit(reg.GetRegNum() + kMipsFPReg0); } else { @@ -401,8 +428,7 @@ void MipsMir2Lir::ClobberCallerSave() { Clobber(rs_rF13); Clobber(rs_rF14); Clobber(rs_rF15); - if (cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures() - ->Is32BitFloatingPoint()) { + if (fpuIs32Bit_) { Clobber(rs_rD0_fr0); Clobber(rs_rD1_fr0); Clobber(rs_rD2_fr0); @@ -462,28 +488,20 @@ bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind ATTRIBUTE_UNUSED) { } void MipsMir2Lir::CompilerInitializeRegAlloc() { - const bool fpu_is_32bit = - cu_->compiler_driver->GetInstructionSetFeatures()->AsMipsInstructionSetFeatures() - ->Is32BitFloatingPoint(); reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */, sp_regs, - fpu_is_32bit ? dp_fr0_regs : dp_fr1_regs, + fpuIs32Bit_ ? dp_fr0_regs : dp_fr1_regs, reserved_regs, empty_pool /* reserved64 */, core_temps, empty_pool /* core64_temps */, sp_temps, - fpu_is_32bit ? dp_fr0_temps : dp_fr1_temps)); + fpuIs32Bit_ ? dp_fr0_temps : dp_fr1_temps)); // Target-specific adjustments. // Alias single precision floats to appropriate half of overlapping double. for (RegisterInfo* info : reg_pool_->sp_regs_) { int sp_reg_num = info->GetReg().GetRegNum(); - int dp_reg_num; - if (fpu_is_32bit) { - dp_reg_num = sp_reg_num & ~1; - } else { - dp_reg_num = sp_reg_num >> 1; - } + int dp_reg_num = sp_reg_num & ~1; RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num); RegisterInfo* dp_reg_info = GetRegInfo(dp_reg); // Double precision register's master storage should refer to itself. @@ -502,11 +520,7 @@ void MipsMir2Lir::CompilerInitializeRegAlloc() { // TODO: adjust when we roll to hard float calling convention. reg_pool_->next_core_reg_ = 2; reg_pool_->next_sp_reg_ = 2; - if (fpu_is_32bit) { - reg_pool_->next_dp_reg_ = 2; - } else { - reg_pool_->next_dp_reg_ = 1; - } + reg_pool_->next_dp_reg_ = 2; } /* @@ -610,7 +624,11 @@ RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volati } MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena) - : Mir2Lir(cu, mir_graph, arena), in_to_reg_storage_mips_mapper_(this) { + : Mir2Lir(cu, mir_graph, arena), in_to_reg_storage_mips_mapper_(this), + isaIsR6_(cu->compiler_driver->GetInstructionSetFeatures() + ->AsMipsInstructionSetFeatures()->IsR6()), + fpuIs32Bit_(cu->compiler_driver->GetInstructionSetFeatures() + ->AsMipsInstructionSetFeatures()->Is32BitFloatingPoint()) { for (int i = 0; i < kMipsLast; i++) { DCHECK_EQ(MipsMir2Lir::EncodingMap[i].opcode, i) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name diff --git a/compiler/dex/quick/mips/utility_mips.cc b/compiler/dex/quick/mips/utility_mips.cc index 2d26922..3b7e0ed 100644 --- a/compiler/dex/quick/mips/utility_mips.cc +++ b/compiler/dex/quick/mips/utility_mips.cc @@ -182,7 +182,11 @@ LIR* MipsMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, R opcode = kMipsAnd; break; case kOpMul: - opcode = kMipsMul; + if (isaIsR6_) { + opcode = kMipsR6Mul; + } else { + opcode = kMipsMul; + } break; case kOpOr: opcode = kMipsOr; @@ -271,7 +275,11 @@ LIR* MipsMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, i break; case kOpMul: short_form = false; - opcode = kMipsMul; + if (isaIsR6_) { + opcode = kMipsR6Mul; + } else { + opcode = kMipsMul; + } break; default: LOG(FATAL) << "Bad case in OpRegRegImm"; @@ -359,12 +367,23 @@ LIR* MipsMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, R LIR* MipsMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) { LIR *res; - if (!r_dest.IsPair()) { - // Form 64-bit pair - r_dest = Solo64ToPair64(r_dest); + if (fpuIs32Bit_ || !r_dest.IsFloat()) { + // 32bit FPU (pairs) or loading into GPR. + if (!r_dest.IsPair()) { + // Form 64-bit pair + r_dest = Solo64ToPair64(r_dest); + } + res = LoadConstantNoClobber(r_dest.GetLow(), Low32Bits(value)); + LoadConstantNoClobber(r_dest.GetHigh(), High32Bits(value)); + } else { + // Here if we have a 64bit FPU and loading into FPR. + RegStorage r_temp = AllocTemp(); + r_dest = Fp64ToSolo32(r_dest); + res = LoadConstantNoClobber(r_dest, Low32Bits(value)); + LoadConstantNoClobber(r_temp, High32Bits(value)); + NewLIR2(kMipsMthc1, r_temp.GetReg(), r_dest.GetReg()); + FreeTemp(r_temp); } - res = LoadConstantNoClobber(r_dest.GetLow(), Low32Bits(value)); - LoadConstantNoClobber(r_dest.GetHigh(), High32Bits(value)); return res; } @@ -483,32 +502,29 @@ LIR* MipsMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStora LIR *load2 = NULL; MipsOpCode opcode = kMipsNop; bool short_form = IS_SIMM16(displacement); - bool pair = r_dest.IsPair(); + bool is64bit = false; switch (size) { case k64: case kDouble: - if (!pair) { + is64bit = true; + if (fpuIs32Bit_ && !r_dest.IsPair()) { // Form 64-bit pair r_dest = Solo64ToPair64(r_dest); - pair = 1; - } - if (r_dest.IsFloat()) { - DCHECK_EQ(r_dest.GetLowReg(), r_dest.GetHighReg() - 1); - opcode = kMipsFlwc1; - } else { - opcode = kMipsLw; } short_form = IS_SIMM16_2WORD(displacement); - DCHECK_EQ((displacement & 0x3), 0); - break; + FALLTHROUGH_INTENDED; case k32: case kSingle: case kReference: opcode = kMipsLw; if (r_dest.IsFloat()) { opcode = kMipsFlwc1; - DCHECK(r_dest.IsSingle()); + if (!is64bit) { + DCHECK(r_dest.IsSingle()); + } else { + DCHECK(r_dest.IsDouble()); + } } DCHECK_EQ((displacement & 0x3), 0); break; @@ -531,35 +547,56 @@ LIR* MipsMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStora } if (short_form) { - if (!pair) { + if (!is64bit) { load = res = NewLIR3(opcode, r_dest.GetReg(), displacement, r_base.GetReg()); } else { - load = res = NewLIR3(opcode, r_dest.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg()); - load2 = NewLIR3(opcode, r_dest.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg()); + if (fpuIs32Bit_ || !r_dest.IsFloat()) { + DCHECK(r_dest.IsPair()); + load = res = NewLIR3(opcode, r_dest.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg()); + load2 = NewLIR3(opcode, r_dest.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg()); + } else { + // Here if 64bit fpu and r_dest is a 64bit fp register. + RegStorage r_tmp = AllocTemp(); + // FIXME: why is r_dest a 64BitPair here??? + r_dest = Fp64ToSolo32(r_dest); + load = res = NewLIR3(kMipsFlwc1, r_dest.GetReg(), displacement + LOWORD_OFFSET, r_base.GetReg()); + load2 = NewLIR3(kMipsLw, r_tmp.GetReg(), displacement + HIWORD_OFFSET, r_base.GetReg()); + NewLIR2(kMipsMthc1, r_tmp.GetReg(), r_dest.GetReg()); + FreeTemp(r_tmp); + } } } else { - if (pair) { - RegStorage r_tmp = AllocTemp(); - res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement); - load = NewLIR3(opcode, r_dest.GetLowReg(), LOWORD_OFFSET, r_tmp.GetReg()); - load2 = NewLIR3(opcode, r_dest.GetHighReg(), HIWORD_OFFSET, r_tmp.GetReg()); - FreeTemp(r_tmp); - } else { - RegStorage r_tmp = (r_base == r_dest) ? AllocTemp() : r_dest; + if (!is64bit) { + RegStorage r_tmp = (r_base == r_dest || r_dest.IsFloat()) ? AllocTemp() : r_dest; res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement); load = NewLIR3(opcode, r_dest.GetReg(), 0, r_tmp.GetReg()); if (r_tmp != r_dest) FreeTemp(r_tmp); + } else { + RegStorage r_tmp = AllocTemp(); + res = OpRegRegImm(kOpAdd, r_tmp, r_base, displacement); + if (fpuIs32Bit_ || !r_dest.IsFloat()) { + DCHECK(r_dest.IsPair()); + load = NewLIR3(opcode, r_dest.GetLowReg(), LOWORD_OFFSET, r_tmp.GetReg()); + load2 = NewLIR3(opcode, r_dest.GetHighReg(), HIWORD_OFFSET, r_tmp.GetReg()); + } else { + // Here if 64bit fpu and r_dest is a 64bit fp register + r_dest = Fp64ToSolo32(r_dest); + load = res = NewLIR3(kMipsFlwc1, r_dest.GetReg(), LOWORD_OFFSET, r_tmp.GetReg()); + load2 = NewLIR3(kMipsLw, r_tmp.GetReg(), HIWORD_OFFSET, r_tmp.GetReg()); + NewLIR2(kMipsMthc1, r_tmp.GetReg(), r_dest.GetReg()); + } + FreeTemp(r_tmp); } } if (mem_ref_type_ == ResourceMask::kDalvikReg) { DCHECK_EQ(r_base, rs_rMIPS_SP); - AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, - true /* is_load */, pair /* is64bit */); - if (pair) { + AnnotateDalvikRegAccess(load, (displacement + (is64bit ? LOWORD_OFFSET : 0)) >> 2, + true /* is_load */, is64bit /* is64bit */); + if (is64bit) { AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2, - true /* is_load */, pair /* is64bit */); + true /* is_load */, is64bit /* is64bit */); } } return load; @@ -594,32 +631,29 @@ LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, LIR *store2 = NULL; MipsOpCode opcode = kMipsNop; bool short_form = IS_SIMM16(displacement); - bool pair = r_src.IsPair(); + bool is64bit = false; switch (size) { case k64: case kDouble: - if (!pair) { + is64bit = true; + if (fpuIs32Bit_ && !r_src.IsPair()) { // Form 64-bit pair r_src = Solo64ToPair64(r_src); - pair = 1; - } - if (r_src.IsFloat()) { - DCHECK_EQ(r_src.GetLowReg(), r_src.GetHighReg() - 1); - opcode = kMipsFswc1; - } else { - opcode = kMipsSw; } short_form = IS_SIMM16_2WORD(displacement); - DCHECK_EQ((displacement & 0x3), 0); - break; + FALLTHROUGH_INTENDED; case k32: case kSingle: case kReference: opcode = kMipsSw; if (r_src.IsFloat()) { opcode = kMipsFswc1; - DCHECK(r_src.IsSingle()); + if (!is64bit) { + DCHECK(r_src.IsSingle()); + } else { + DCHECK(r_src.IsDouble()); + } } DCHECK_EQ((displacement & 0x3), 0); break; @@ -637,31 +671,53 @@ LIR* MipsMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, } if (short_form) { - if (!pair) { + if (!is64bit) { store = res = NewLIR3(opcode, r_src.GetReg(), displacement, r_base.GetReg()); } else { - store = res = NewLIR3(opcode, r_src.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg()); - store2 = NewLIR3(opcode, r_src.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg()); + if (fpuIs32Bit_ || !r_src.IsFloat()) { + DCHECK(r_src.IsPair()); + store = res = NewLIR3(opcode, r_src.GetLowReg(), displacement + LOWORD_OFFSET, r_base.GetReg()); + store2 = NewLIR3(opcode, r_src.GetHighReg(), displacement + HIWORD_OFFSET, r_base.GetReg()); + } else { + // Here if 64bit fpu and r_src is a 64bit fp register + RegStorage r_tmp = AllocTemp(); + r_src = Fp64ToSolo32(r_src); + store = res = NewLIR3(kMipsFswc1, r_src.GetReg(), displacement + LOWORD_OFFSET, r_base.GetReg()); + NewLIR2(kMipsMfhc1, r_tmp.GetReg(), r_src.GetReg()); + store2 = NewLIR3(kMipsSw, r_tmp.GetReg(), displacement + HIWORD_OFFSET, r_base.GetReg()); + FreeTemp(r_tmp); + } } } else { RegStorage r_scratch = AllocTemp(); res = OpRegRegImm(kOpAdd, r_scratch, r_base, displacement); - if (!pair) { + if (!is64bit) { store = NewLIR3(opcode, r_src.GetReg(), 0, r_scratch.GetReg()); } else { - store = NewLIR3(opcode, r_src.GetLowReg(), LOWORD_OFFSET, r_scratch.GetReg()); - store2 = NewLIR3(opcode, r_src.GetHighReg(), HIWORD_OFFSET, r_scratch.GetReg()); + if (fpuIs32Bit_ || !r_src.IsFloat()) { + DCHECK(r_src.IsPair()); + store = NewLIR3(opcode, r_src.GetLowReg(), LOWORD_OFFSET, r_scratch.GetReg()); + store2 = NewLIR3(opcode, r_src.GetHighReg(), HIWORD_OFFSET, r_scratch.GetReg()); + } else { + // Here if 64bit fpu and r_src is a 64bit fp register + RegStorage r_tmp = AllocTemp(); + r_src = Fp64ToSolo32(r_src); + store = NewLIR3(kMipsFswc1, r_src.GetReg(), LOWORD_OFFSET, r_scratch.GetReg()); + NewLIR2(kMipsMfhc1, r_tmp.GetReg(), r_src.GetReg()); + store2 = NewLIR3(kMipsSw, r_tmp.GetReg(), HIWORD_OFFSET, r_scratch.GetReg()); + FreeTemp(r_tmp); + } } FreeTemp(r_scratch); } if (mem_ref_type_ == ResourceMask::kDalvikReg) { DCHECK_EQ(r_base, rs_rMIPS_SP); - AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2, - false /* is_load */, pair /* is64bit */); - if (pair) { + AnnotateDalvikRegAccess(store, (displacement + (is64bit ? LOWORD_OFFSET : 0)) >> 2, + false /* is_load */, is64bit /* is64bit */); + if (is64bit) { AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2, - false /* is_load */, pair /* is64bit */); + false /* is_load */, is64bit /* is64bit */); } } |