diff options
| author | 2014-06-11 23:39:15 +0000 | |
|---|---|---|
| committer | 2014-06-11 23:11:06 +0000 | |
| commit | 45ee056ea22f68e1041fee7046e1622876c33271 (patch) | |
| tree | 4c12f95c642155c28cae466072b45c7e7344cdaf | |
| parent | 44405a140f92aefdb18ba48c3762b229b6d7d169 (diff) | |
| parent | d8191d000413504b33702e0f52e1e8e522a47ec0 (diff) | |
Merge "ART: Add mul_long bytecode for X86-64"
| -rw-r--r-- | compiler/dex/quick/x86/int_x86.cc | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 8093fd789e..a98db999e4 100644 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -1095,6 +1095,56 @@ void X86Mir2Lir::GenImulMemImm(RegStorage dest, int sreg, int displacement, int void X86Mir2Lir::GenMulLong(Instruction::Code, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { + if (Gen64Bit()) { + if (rl_src1.is_const) { + std::swap(rl_src1, rl_src2); + } + // Are we multiplying by a constant? + if (rl_src2.is_const) { + int64_t val = mir_graph_->ConstantValueWide(rl_src2); + if (val == 0) { + RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true); + OpRegReg(kOpXor, rl_result.reg, rl_result.reg); + StoreValueWide(rl_dest, rl_result); + return; + } else if (val == 1) { + StoreValueWide(rl_dest, rl_src1); + return; + } else if (val == 2) { + GenAddLong(Instruction::ADD_LONG, rl_dest, rl_src1, rl_src1); + return; + } else if (IsPowerOfTwo(val)) { + int shift_amount = LowestSetBit(val); + if (!BadOverlap(rl_src1, rl_dest)) { + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + RegLocation rl_result = GenShiftImmOpLong(Instruction::SHL_LONG, rl_dest, + rl_src1, shift_amount); + StoreValueWide(rl_dest, rl_result); + return; + } + } + // Falltrhough to handle. + } + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + rl_src2 = LoadValueWide(rl_src2, kCoreReg); + RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true); + if (rl_result.reg.GetReg() == rl_src1.reg.GetReg() && + rl_result.reg.GetReg() == rl_src2.reg.GetReg()) { + NewLIR2(kX86Imul64RR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); + } else if (rl_result.reg.GetReg() != rl_src1.reg.GetReg() && + rl_result.reg.GetReg() == rl_src2.reg.GetReg()) { + NewLIR2(kX86Imul64RR, rl_result.reg.GetReg(), rl_src1.reg.GetReg()); + } else if (rl_result.reg.GetReg() == rl_src1.reg.GetReg() && + rl_result.reg.GetReg() != rl_src2.reg.GetReg()) { + NewLIR2(kX86Imul64RR, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); + } else { + OpRegCopy(rl_result.reg, rl_src1.reg); + NewLIR2(kX86Imul64RR, rl_result.reg.GetReg(), rl_src2.reg.GetReg()); + } + StoreValueWide(rl_dest, rl_result); + return; + } + if (rl_src1.is_const) { std::swap(rl_src1, rl_src2); } |