diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/optimizing/intrinsics_mips.cc | 135 | ||||
| -rw-r--r-- | compiler/utils/mips/assembler_mips.cc | 5 | ||||
| -rw-r--r-- | compiler/utils/mips/assembler_mips.h | 1 |
3 files changed, 123 insertions, 18 deletions
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 326844526e..9f1646226b 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -230,13 +230,16 @@ static void CreateIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) { locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); } -static void GenReverseBytes(LocationSummary* locations, - Primitive::Type type, - MipsAssembler* assembler, - bool isR2OrNewer) { +static void GenReverse(LocationSummary* locations, + Primitive::Type type, + bool isR2OrNewer, + bool isR6, + bool reverseBits, + MipsAssembler* assembler) { DCHECK(type == Primitive::kPrimShort || type == Primitive::kPrimInt || type == Primitive::kPrimLong); + DCHECK(type != Primitive::kPrimShort || !reverseBits); if (type == Primitive::kPrimShort) { Register in = locations->InAt(0).AsRegister<Register>(); @@ -273,6 +276,30 @@ static void GenReverseBytes(LocationSummary* locations, __ And(out, out, AT); __ Or(out, out, TMP); } + if (reverseBits) { + if (isR6) { + __ Bitswap(out, out); + } else { + __ LoadConst32(AT, 0x0F0F0F0F); + __ And(TMP, out, AT); + __ Sll(TMP, TMP, 4); + __ Srl(out, out, 4); + __ And(out, out, AT); + __ Or(out, TMP, out); + __ LoadConst32(AT, 0x33333333); + __ And(TMP, out, AT); + __ Sll(TMP, TMP, 2); + __ Srl(out, out, 2); + __ And(out, out, AT); + __ Or(out, TMP, out); + __ LoadConst32(AT, 0x55555555); + __ And(TMP, out, AT); + __ Sll(TMP, TMP, 1); + __ Srl(out, out, 1); + __ And(out, out, AT); + __ Or(out, TMP, out); + } + } } else if (type == Primitive::kPrimLong) { Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>(); Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>(); @@ -314,6 +341,46 @@ static void GenReverseBytes(LocationSummary* locations, __ And(out_lo, out_lo, AT); __ Or(out_lo, out_lo, TMP); } + if (reverseBits) { + if (isR6) { + __ Bitswap(out_hi, out_hi); + __ Bitswap(out_lo, out_lo); + } else { + __ LoadConst32(AT, 0x0F0F0F0F); + __ And(TMP, out_hi, AT); + __ Sll(TMP, TMP, 4); + __ Srl(out_hi, out_hi, 4); + __ And(out_hi, out_hi, AT); + __ Or(out_hi, TMP, out_hi); + __ And(TMP, out_lo, AT); + __ Sll(TMP, TMP, 4); + __ Srl(out_lo, out_lo, 4); + __ And(out_lo, out_lo, AT); + __ Or(out_lo, TMP, out_lo); + __ LoadConst32(AT, 0x33333333); + __ And(TMP, out_hi, AT); + __ Sll(TMP, TMP, 2); + __ Srl(out_hi, out_hi, 2); + __ And(out_hi, out_hi, AT); + __ Or(out_hi, TMP, out_hi); + __ And(TMP, out_lo, AT); + __ Sll(TMP, TMP, 2); + __ Srl(out_lo, out_lo, 2); + __ And(out_lo, out_lo, AT); + __ Or(out_lo, TMP, out_lo); + __ LoadConst32(AT, 0x55555555); + __ And(TMP, out_hi, AT); + __ Sll(TMP, TMP, 1); + __ Srl(out_hi, out_hi, 1); + __ And(out_hi, out_hi, AT); + __ Or(out_hi, TMP, out_hi); + __ And(TMP, out_lo, AT); + __ Sll(TMP, TMP, 1); + __ Srl(out_lo, out_lo, 1); + __ And(out_lo, out_lo, AT); + __ Or(out_lo, TMP, out_lo); + } + } } } @@ -323,10 +390,12 @@ void IntrinsicLocationsBuilderMIPS::VisitIntegerReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitIntegerReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), - Primitive::kPrimInt, - GetAssembler(), - codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2()); + GenReverse(invoke->GetLocations(), + Primitive::kPrimInt, + codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(), + codegen_->GetInstructionSetFeatures().IsR6(), + false, + GetAssembler()); } // long java.lang.Long.reverseBytes(long) @@ -335,10 +404,12 @@ void IntrinsicLocationsBuilderMIPS::VisitLongReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitLongReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), - Primitive::kPrimLong, - GetAssembler(), - codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2()); + GenReverse(invoke->GetLocations(), + Primitive::kPrimLong, + codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(), + codegen_->GetInstructionSetFeatures().IsR6(), + false, + GetAssembler()); } // short java.lang.Short.reverseBytes(short) @@ -347,10 +418,40 @@ void IntrinsicLocationsBuilderMIPS::VisitShortReverseBytes(HInvoke* invoke) { } void IntrinsicCodeGeneratorMIPS::VisitShortReverseBytes(HInvoke* invoke) { - GenReverseBytes(invoke->GetLocations(), - Primitive::kPrimShort, - GetAssembler(), - codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2()); + GenReverse(invoke->GetLocations(), + Primitive::kPrimShort, + codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(), + codegen_->GetInstructionSetFeatures().IsR6(), + false, + GetAssembler()); +} + +// int java.lang.Integer.reverse(int) +void IntrinsicLocationsBuilderMIPS::VisitIntegerReverse(HInvoke* invoke) { + CreateIntToIntLocations(arena_, invoke); +} + +void IntrinsicCodeGeneratorMIPS::VisitIntegerReverse(HInvoke* invoke) { + GenReverse(invoke->GetLocations(), + Primitive::kPrimInt, + codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(), + codegen_->GetInstructionSetFeatures().IsR6(), + true, + GetAssembler()); +} + +// long java.lang.Long.reverse(long) +void IntrinsicLocationsBuilderMIPS::VisitLongReverse(HInvoke* invoke) { + CreateIntToIntLocations(arena_, invoke); +} + +void IntrinsicCodeGeneratorMIPS::VisitLongReverse(HInvoke* invoke) { + GenReverse(invoke->GetLocations(), + Primitive::kPrimLong, + codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(), + codegen_->GetInstructionSetFeatures().IsR6(), + true, + GetAssembler()); } // boolean java.lang.String.equals(Object anObject) @@ -463,8 +564,6 @@ void IntrinsicLocationsBuilderMIPS::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUS void IntrinsicCodeGeneratorMIPS::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ } -UNIMPLEMENTED_INTRINSIC(IntegerReverse) -UNIMPLEMENTED_INTRINSIC(LongReverse) UNIMPLEMENTED_INTRINSIC(LongNumberOfLeadingZeros) UNIMPLEMENTED_INTRINSIC(IntegerNumberOfLeadingZeros) UNIMPLEMENTED_INTRINSIC(MathAbsDouble) diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc index fc7ac7061a..86e5762f9c 100644 --- a/compiler/utils/mips/assembler_mips.cc +++ b/compiler/utils/mips/assembler_mips.cc @@ -314,6 +314,11 @@ void MipsAssembler::Wsbh(Register rd, Register rt) { EmitR(0x1f, static_cast<Register>(0), rt, rd, 2, 0x20); } +void MipsAssembler::Bitswap(Register rd, Register rt) { + CHECK(IsR6()); + EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x0, 0x20); +} + void MipsAssembler::Sll(Register rd, Register rt, int shamt) { CHECK(IsUint<5>(shamt)) << shamt; EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x00); diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h index 1ef0992dac..6a37cc9b1c 100644 --- a/compiler/utils/mips/assembler_mips.h +++ b/compiler/utils/mips/assembler_mips.h @@ -136,6 +136,7 @@ class MipsAssembler FINAL : public Assembler { void Seb(Register rd, Register rt); // R2+ void Seh(Register rd, Register rt); // R2+ void Wsbh(Register rd, Register rt); // R2+ + void Bitswap(Register rd, Register rt); // R6 void Sll(Register rd, Register rt, int shamt); void Srl(Register rd, Register rt, int shamt); |