MIPS32: int java.lang.*.numberOfTrailingZeros
- int java.lang.Integer.numberOfTrailingZeros(int)
- int java.lang.Long.numberOfTrailingZeros(long)
Change-Id: I3392cfad40b2a9f076912f8041cd0a60b6b680ea
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc
index a974739..8c16b39 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -222,12 +222,14 @@
MoveIntToFP(invoke->GetLocations(), false, GetAssembler());
}
-static void CreateIntToIntLocations(ArenaAllocator* arena, HInvoke* invoke) {
+static void CreateIntToIntLocations(ArenaAllocator* arena,
+ HInvoke* invoke,
+ Location::OutputOverlap overlaps = Location::kNoOutputOverlap) {
LocationSummary* locations = new (arena) LocationSummary(invoke,
LocationSummary::kNoCall,
kIntrinsified);
locations->SetInAt(0, Location::RequiresRegister());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+ locations->SetOut(Location::RequiresRegister(), overlaps);
}
static void GenReverse(LocationSummary* locations,
@@ -480,6 +482,127 @@
GetAssembler());
}
+static void GenNumberOfTrailingZeroes(LocationSummary* locations,
+ bool is64bit,
+ bool isR6,
+ bool isR2OrNewer,
+ MipsAssembler* assembler) {
+ Register out = locations->Out().AsRegister<Register>();
+ Register in_lo;
+ Register in;
+
+ if (is64bit) {
+ MipsLabel done;
+ Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>();
+
+ in_lo = locations->InAt(0).AsRegisterPairLow<Register>();
+
+ // If in_lo is zero then count the number of trailing zeroes in in_hi;
+ // otherwise count the number of trailing zeroes in in_lo.
+ // AT = in_lo ? in_lo : in_hi;
+ if (isR6) {
+ __ Seleqz(out, in_hi, in_lo);
+ __ Selnez(TMP, in_lo, in_lo);
+ __ Or(out, out, TMP);
+ } else {
+ __ Movz(out, in_hi, in_lo);
+ __ Movn(out, in_lo, in_lo);
+ }
+
+ in = out;
+ } else {
+ in = locations->InAt(0).AsRegister<Register>();
+ // Give in_lo a dummy value to keep the compiler from complaining.
+ // Since we only get here in the 32-bit case, this value will never
+ // be used.
+ in_lo = in;
+ }
+
+ // We don't have an instruction to count the number of trailing zeroes.
+ // Start by flipping the bits end-for-end so we can count the number of
+ // leading zeroes instead.
+ if (isR2OrNewer) {
+ __ Rotr(out, in, 16);
+ __ Wsbh(out, out);
+ } else {
+ // MIPS32r1
+ // __ Rotr(out, in, 16);
+ __ Sll(TMP, in, 16);
+ __ Srl(out, in, 16);
+ __ Or(out, out, TMP);
+ // __ Wsbh(out, out);
+ __ LoadConst32(AT, 0x00FF00FF);
+ __ And(TMP, out, AT);
+ __ Sll(TMP, TMP, 8);
+ __ Srl(out, out, 8);
+ __ And(out, out, AT);
+ __ Or(out, out, TMP);
+ }
+
+ if (isR6) {
+ __ Bitswap(out, out);
+ __ ClzR6(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);
+ __ ClzR2(out, out);
+ }
+
+ if (is64bit) {
+ // If in_lo is zero, then we counted the number of trailing zeroes in in_hi so we must add the
+ // number of trailing zeroes in in_lo (32) to get the correct final count
+ __ LoadConst32(TMP, 32);
+ if (isR6) {
+ __ Seleqz(TMP, TMP, in_lo);
+ } else {
+ __ Movn(TMP, ZERO, in_lo);
+ }
+ __ Addu(out, out, TMP);
+ }
+}
+
+// int java.lang.Integer.numberOfTrailingZeros(int i)
+void IntrinsicLocationsBuilderMIPS::VisitIntegerNumberOfTrailingZeros(HInvoke* invoke) {
+ CreateIntToIntLocations(arena_, invoke, Location::kOutputOverlap);
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitIntegerNumberOfTrailingZeros(HInvoke* invoke) {
+ GenNumberOfTrailingZeroes(invoke->GetLocations(),
+ false,
+ codegen_->GetInstructionSetFeatures().IsR6(),
+ codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(),
+ GetAssembler());
+}
+
+// int java.lang.Long.numberOfTrailingZeros(long i)
+void IntrinsicLocationsBuilderMIPS::VisitLongNumberOfTrailingZeros(HInvoke* invoke) {
+ CreateIntToIntLocations(arena_, invoke, Location::kOutputOverlap);
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitLongNumberOfTrailingZeros(HInvoke* invoke) {
+ GenNumberOfTrailingZeroes(invoke->GetLocations(),
+ true,
+ codegen_->GetInstructionSetFeatures().IsR6(),
+ codegen_->GetInstructionSetFeatures().IsMipsIsaRevGreaterThanEqual2(),
+ GetAssembler());
+}
+
// int java.lang.Integer.reverse(int)
void IntrinsicLocationsBuilderMIPS::VisitIntegerReverse(HInvoke* invoke) {
CreateIntToIntLocations(arena_, invoke);
@@ -672,10 +795,8 @@
UNIMPLEMENTED_INTRINSIC(StringNewStringFromString)
UNIMPLEMENTED_INTRINSIC(LongRotateLeft)
UNIMPLEMENTED_INTRINSIC(LongRotateRight)
-UNIMPLEMENTED_INTRINSIC(LongNumberOfTrailingZeros)
UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft)
UNIMPLEMENTED_INTRINSIC(IntegerRotateRight)
-UNIMPLEMENTED_INTRINSIC(IntegerNumberOfTrailingZeros)
UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck)