summaryrefslogtreecommitdiff
path: root/compiler/optimizing/code_generator_mips.cc
diff options
context:
space:
mode:
authorAlexey Frunze <Alexey.Frunze@imgtec.com>2016-01-13 16:24:25 -0800
committerAlexey Frunze <Alexey.Frunze@imgtec.com>2016-01-13 16:25:51 -0800
commit0d9150b80fbae08dff6431b693de2e4e7b9697d8 (patch)
tree2b25b645493f489c4ffb6c94a123897ce9e38ab2 /compiler/optimizing/code_generator_mips.cc
parent08d3ab591d98fce33b7ab552a10cec04aaff6ce1 (diff)
MIPS: HRor clean-up
This is a follow up to https://android-review.googlesource.com/#/c/194590/. Change-Id: Ia37faa02736e5dd54c1e71fd2a4d94e074746757
Diffstat (limited to 'compiler/optimizing/code_generator_mips.cc')
-rw-r--r--compiler/optimizing/code_generator_mips.cc37
1 files changed, 22 insertions, 15 deletions
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 75f5fb3bab..fdca0b301b 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1539,8 +1539,10 @@ void InstructionCodeGeneratorMIPS::HandleShift(HBinaryOperation* instr) {
bool use_imm = rhs_location.IsConstant();
Register rhs_reg = use_imm ? ZERO : rhs_location.AsRegister<Register>();
int64_t rhs_imm = use_imm ? CodeGenerator::GetInt64ValueOf(rhs_location.GetConstant()) : 0;
- uint32_t shift_mask = (type == Primitive::kPrimInt) ? kMaxIntShiftValue : kMaxLongShiftValue;
- uint32_t shift_value = rhs_imm & shift_mask;
+ const uint32_t shift_mask = (type == Primitive::kPrimInt)
+ ? kMaxIntShiftValue
+ : kMaxLongShiftValue;
+ const uint32_t shift_value = rhs_imm & shift_mask;
// Are the INS (Insert Bit Field) and ROTR instructions supported?
bool has_ins_rotr = codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2();
@@ -1580,6 +1582,11 @@ void InstructionCodeGeneratorMIPS::HandleShift(HBinaryOperation* instr) {
__ Rotrv(dst, lhs, rhs_reg);
} else {
__ Subu(TMP, ZERO, rhs_reg);
+ // 32-bit shift instructions use the 5 least significant bits of the shift count, so
+ // shifting by `-rhs_reg` is equivalent to shifting by `(32 - rhs_reg) & 31`. The case
+ // when `rhs_reg & 31 == 0` is OK even though we don't shift `lhs` left all the way out
+ // by 32, because the result in this case is computed as `(lhs >> 0) | (lhs << 0)`,
+ // IOW, the OR'd values are equal.
__ Sllv(TMP, lhs, TMP);
__ Srlv(dst, lhs, rhs_reg);
__ Or(dst, dst, TMP);
@@ -1643,33 +1650,33 @@ void InstructionCodeGeneratorMIPS::HandleShift(HBinaryOperation* instr) {
}
}
} else {
- shift_value -= kMipsBitsPerWord;
+ const uint32_t shift_value_high = shift_value - kMipsBitsPerWord;
if (instr->IsShl()) {
- __ Sll(dst_high, lhs_low, shift_value);
+ __ Sll(dst_high, lhs_low, shift_value_high);
__ Move(dst_low, ZERO);
} else if (instr->IsShr()) {
- __ Sra(dst_low, lhs_high, shift_value);
+ __ Sra(dst_low, lhs_high, shift_value_high);
__ Sra(dst_high, dst_low, kMipsBitsPerWord - 1);
} else if (instr->IsUShr()) {
- __ Srl(dst_low, lhs_high, shift_value);
+ __ Srl(dst_low, lhs_high, shift_value_high);
__ Move(dst_high, ZERO);
} else {
- if (shift_value == 0) {
+ if (shift_value == kMipsBitsPerWord) {
// 64-bit rotation by 32 is just a swap.
__ Move(dst_low, lhs_high);
__ Move(dst_high, lhs_low);
} else {
if (has_ins_rotr) {
- __ Srl(dst_low, lhs_high, shift_value);
- __ Ins(dst_low, lhs_low, kMipsBitsPerWord - shift_value, shift_value);
- __ Srl(dst_high, lhs_low, shift_value);
- __ Ins(dst_high, lhs_high, kMipsBitsPerWord - shift_value, shift_value);
+ __ Srl(dst_low, lhs_high, shift_value_high);
+ __ Ins(dst_low, lhs_low, kMipsBitsPerWord - shift_value_high, shift_value_high);
+ __ Srl(dst_high, lhs_low, shift_value_high);
+ __ Ins(dst_high, lhs_high, kMipsBitsPerWord - shift_value_high, shift_value_high);
} else {
- __ Sll(TMP, lhs_low, kMipsBitsPerWord - shift_value);
- __ Srl(dst_low, lhs_high, shift_value);
+ __ Sll(TMP, lhs_low, kMipsBitsPerWord - shift_value_high);
+ __ Srl(dst_low, lhs_high, shift_value_high);
__ Or(dst_low, dst_low, TMP);
- __ Sll(TMP, lhs_high, kMipsBitsPerWord - shift_value);
- __ Srl(dst_high, lhs_low, shift_value);
+ __ Sll(TMP, lhs_high, kMipsBitsPerWord - shift_value_high);
+ __ Srl(dst_high, lhs_low, shift_value_high);
__ Or(dst_high, dst_high, TMP);
}
}