summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorDouglas Leung <douglas.leung@imgtec.com>2015-02-27 19:05:03 -0800
committerAndreas Gampe <agampe@google.com>2015-03-20 16:51:56 -0700
commit027f0ff64c2512b9a5f1f54f3fea1bec481eb0f5 (patch)
tree9202535f219d7343b4c26d5c43f0bcb7c31650df /compiler
parent6cc763c8b8157fb42dd44e1dfb84812546500dc1 (diff)
downloadart-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.cc23
-rw-r--r--compiler/dex/quick/mips/codegen_mips.h8
-rw-r--r--compiler/dex/quick/mips/fp_mips.cc28
-rw-r--r--compiler/dex/quick/mips/int_mips.cc45
-rw-r--r--compiler/dex/quick/mips/mips_lir.h48
-rw-r--r--compiler/dex/quick/mips/target_mips.cc70
-rw-r--r--compiler/dex/quick/mips/utility_mips.cc168
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 */);
}
}