From: Chris Larsen Date: Wed, 17 Feb 2016 01:10:40 +0000 (-0800) Subject: MIPS32: Highest/Lowest One Bit Set: X-Git-Tag: android-x86-7.1-r1~340^2~24^2~5^2~23^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=9775934cb141deb096183f89449ca28ec7c11798;p=android-x86%2Fart.git MIPS32: Highest/Lowest One Bit Set: - int java.lang.Integer.highestOneBit(int) - int java.lang.Integer.lowestOneBit(int) - long java.lang.Long.highestOneBit(long) - long java.lang.Long.lowestOneBit(long) Change-Id: I575ec6f70cf5cac620cc5d9e49ec3f7b554b4622 --- diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 0622610ec..710df0a82 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -1663,6 +1663,119 @@ void IntrinsicCodeGeneratorMIPS::VisitDoubleIsInfinite(HInvoke* invoke) { GenIsInfinite(invoke->GetLocations(), Primitive::kPrimDouble, IsR6(), GetAssembler()); } +static void GenHighestOneBit(LocationSummary* locations, + const Primitive::Type type, + bool isR6, + MipsAssembler* assembler) { + DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + + if (type == Primitive::kPrimLong) { + Register in_lo = locations->InAt(0).AsRegisterPairLow(); + Register in_hi = locations->InAt(0).AsRegisterPairHigh(); + Register out_lo = locations->Out().AsRegisterPairLow(); + Register out_hi = locations->Out().AsRegisterPairHigh(); + + if (isR6) { + __ ClzR6(TMP, in_hi); + } else { + __ ClzR2(TMP, in_hi); + } + __ LoadConst32(AT, 0x80000000); + __ Srlv(out_hi, AT, TMP); + __ And(out_hi, out_hi, in_hi); + if (isR6) { + __ ClzR6(TMP, in_lo); + } else { + __ ClzR2(TMP, in_lo); + } + __ Srlv(out_lo, AT, TMP); + __ And(out_lo, out_lo, in_lo); + if (isR6) { + __ Seleqz(out_lo, out_lo, out_hi); + } else { + __ Movn(out_lo, ZERO, out_hi); + } + } else { + Register in = locations->InAt(0).AsRegister(); + Register out = locations->Out().AsRegister(); + + if (isR6) { + __ ClzR6(TMP, in); + } else { + __ ClzR2(TMP, in); + } + __ LoadConst32(AT, 0x80000000); + __ Srlv(AT, AT, TMP); // Srlv shifts in the range of [0;31] bits (lower 5 bits of arg). + __ And(out, AT, in); // So this is required for 0 (=shift by 32). + } +} + +// int java.lang.Integer.highestOneBit(int) +void IntrinsicLocationsBuilderMIPS::VisitIntegerHighestOneBit(HInvoke* invoke) { + CreateIntToIntLocations(arena_, invoke); +} + +void IntrinsicCodeGeneratorMIPS::VisitIntegerHighestOneBit(HInvoke* invoke) { + GenHighestOneBit(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler()); +} + +// long java.lang.Long.highestOneBit(long) +void IntrinsicLocationsBuilderMIPS::VisitLongHighestOneBit(HInvoke* invoke) { + CreateIntToIntLocations(arena_, invoke, Location::kOutputOverlap); +} + +void IntrinsicCodeGeneratorMIPS::VisitLongHighestOneBit(HInvoke* invoke) { + GenHighestOneBit(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler()); +} + +static void GenLowestOneBit(LocationSummary* locations, + const Primitive::Type type, + bool isR6, + MipsAssembler* assembler) { + DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + + if (type == Primitive::kPrimLong) { + Register in_lo = locations->InAt(0).AsRegisterPairLow(); + Register in_hi = locations->InAt(0).AsRegisterPairHigh(); + Register out_lo = locations->Out().AsRegisterPairLow(); + Register out_hi = locations->Out().AsRegisterPairHigh(); + + __ Subu(TMP, ZERO, in_lo); + __ And(out_lo, TMP, in_lo); + __ Subu(TMP, ZERO, in_hi); + __ And(out_hi, TMP, in_hi); + if (isR6) { + __ Seleqz(out_hi, out_hi, out_lo); + } else { + __ Movn(out_hi, ZERO, out_lo); + } + } else { + Register in = locations->InAt(0).AsRegister(); + Register out = locations->Out().AsRegister(); + + __ Subu(TMP, ZERO, in); + __ And(out, TMP, in); + } +} + +// int java.lang.Integer.lowestOneBit(int) +void IntrinsicLocationsBuilderMIPS::VisitIntegerLowestOneBit(HInvoke* invoke) { + CreateIntToIntLocations(arena_, invoke); +} + +void IntrinsicCodeGeneratorMIPS::VisitIntegerLowestOneBit(HInvoke* invoke) { + GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimInt, IsR6(), GetAssembler()); +} + +// long java.lang.Long.lowestOneBit(long) +void IntrinsicLocationsBuilderMIPS::VisitLongLowestOneBit(HInvoke* invoke) { + CreateIntToIntLocations(arena_, invoke); +} + +void IntrinsicCodeGeneratorMIPS::VisitLongLowestOneBit(HInvoke* invoke) { + GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler()); +} + // Unimplemented intrinsics. UNIMPLEMENTED_INTRINSIC(MIPS, MathCeil) @@ -1719,11 +1832,6 @@ UNIMPLEMENTED_INTRINSIC(MIPS, MathSinh) UNIMPLEMENTED_INTRINSIC(MIPS, MathTan) UNIMPLEMENTED_INTRINSIC(MIPS, MathTanh) -UNIMPLEMENTED_INTRINSIC(MIPS, IntegerHighestOneBit) -UNIMPLEMENTED_INTRINSIC(MIPS, LongHighestOneBit) -UNIMPLEMENTED_INTRINSIC(MIPS, IntegerLowestOneBit) -UNIMPLEMENTED_INTRINSIC(MIPS, LongLowestOneBit) - UNREACHABLE_INTRINSICS(MIPS) #undef UNIMPLEMENTED_INTRINSIC