diff options
| author | 2015-12-04 18:05:28 -0800 | |
|---|---|---|
| committer | 2015-12-04 18:05:28 -0800 | |
| commit | 1f1899a73dc4ee7b521e760414a47e1723b566af (patch) | |
| tree | b0c33ad60b447f3385cd8fefb91c6b8f995fd1f0 /compiler/optimizing/intrinsics_mips.cc | |
| parent | 203cab2091f9ac1d0a472f9a453b22bbc8ca4103 (diff) | |
| parent | fdacff89f5b5c276254beb5643fda5df16ba7dd3 (diff) | |
Merge "MIPS32: int java.lang.*.numberOfTrailingZeros"
am: fdacff89f5
* commit 'fdacff89f5b5c276254beb5643fda5df16ba7dd3':
  MIPS32: int java.lang.*.numberOfTrailingZeros
Diffstat (limited to 'compiler/optimizing/intrinsics_mips.cc')
| -rw-r--r-- | compiler/optimizing/intrinsics_mips.cc | 129 | 
1 files changed, 125 insertions, 4 deletions
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index a97473902d..8c16b39d11 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -222,12 +222,14 @@ void IntrinsicCodeGeneratorMIPS::VisitFloatIntBitsToFloat(HInvoke* invoke) {    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 @@ void IntrinsicCodeGeneratorMIPS::VisitLongNumberOfLeadingZeros(HInvoke* invoke)                             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(StringNewStringFromChars)  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)  |