From e384547851a9d9e5d89ae5bb4c16bfd7d93cc12e Mon Sep 17 00:00:00 2001 From: Chris Larsen Date: Wed, 18 Nov 2015 12:27:15 -0800 Subject: [PATCH] MIPS32: int java.lang.*.numberOfLeadingZeros - int java.lang.Integer.numberOfLeadingZeros(int) - int java.lang.Long.numberOfLeadingZeros(long) Change-Id: Icaf746cb807863f944ff4ebb5da6e6b2846eac58 --- compiler/optimizing/intrinsics_mips.cc | 56 ++++++++++++++++++++++++++++++++-- compiler/utils/mips/assembler_mips.cc | 40 ++++++++++++++++++++++++ compiler/utils/mips/assembler_mips.h | 9 ++++++ disassembler/disassembler_mips.cc | 36 +++++++++++++++++----- 4 files changed, 132 insertions(+), 9 deletions(-) diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 9f1646226..a97473902 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -426,6 +426,60 @@ void IntrinsicCodeGeneratorMIPS::VisitShortReverseBytes(HInvoke* invoke) { GetAssembler()); } +static void GenNumberOfLeadingZeroes(LocationSummary* locations, + bool is64bit, + bool isR6, + MipsAssembler* assembler) { + Register out = locations->Out().AsRegister(); + if (is64bit) { + Register in_lo = locations->InAt(0).AsRegisterPairLow(); + Register in_hi = locations->InAt(0).AsRegisterPairHigh(); + + if (isR6) { + __ ClzR6(AT, in_hi); + __ ClzR6(TMP, in_lo); + __ Seleqz(TMP, TMP, in_hi); + } else { + __ ClzR2(AT, in_hi); + __ ClzR2(TMP, in_lo); + __ Movn(TMP, ZERO, in_hi); + } + __ Addu(out, AT, TMP); + } else { + Register in = locations->InAt(0).AsRegister(); + + if (isR6) { + __ ClzR6(out, in); + } else { + __ ClzR2(out, in); + } + } +} + +// int java.lang.Integer.numberOfLeadingZeros(int i) +void IntrinsicLocationsBuilderMIPS::VisitIntegerNumberOfLeadingZeros(HInvoke* invoke) { + CreateIntToIntLocations(arena_, invoke); +} + +void IntrinsicCodeGeneratorMIPS::VisitIntegerNumberOfLeadingZeros(HInvoke* invoke) { + GenNumberOfLeadingZeroes(invoke->GetLocations(), + false, + codegen_->GetInstructionSetFeatures().IsR6(), + GetAssembler()); +} + +// int java.lang.Long.numberOfLeadingZeros(long i) +void IntrinsicLocationsBuilderMIPS::VisitLongNumberOfLeadingZeros(HInvoke* invoke) { + CreateIntToIntLocations(arena_, invoke); +} + +void IntrinsicCodeGeneratorMIPS::VisitLongNumberOfLeadingZeros(HInvoke* invoke) { + GenNumberOfLeadingZeroes(invoke->GetLocations(), + true, + codegen_->GetInstructionSetFeatures().IsR6(), + GetAssembler()); +} + // int java.lang.Integer.reverse(int) void IntrinsicLocationsBuilderMIPS::VisitIntegerReverse(HInvoke* invoke) { CreateIntToIntLocations(arena_, invoke); @@ -564,8 +618,6 @@ void IntrinsicLocationsBuilderMIPS::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUS void IntrinsicCodeGeneratorMIPS::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ } -UNIMPLEMENTED_INTRINSIC(LongNumberOfLeadingZeros) -UNIMPLEMENTED_INTRINSIC(IntegerNumberOfLeadingZeros) UNIMPLEMENTED_INTRINSIC(MathAbsDouble) UNIMPLEMENTED_INTRINSIC(MathAbsFloat) UNIMPLEMENTED_INTRINSIC(MathAbsInt) diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc index 86e5762f9..5a4de82ea 100644 --- a/compiler/utils/mips/assembler_mips.cc +++ b/compiler/utils/mips/assembler_mips.cc @@ -302,6 +302,46 @@ void MipsAssembler::Nor(Register rd, Register rs, Register rt) { EmitR(0, rs, rt, rd, 0, 0x27); } +void MipsAssembler::Movz(Register rd, Register rs, Register rt) { + CHECK(!IsR6()); + EmitR(0, rs, rt, rd, 0, 0x0A); +} + +void MipsAssembler::Movn(Register rd, Register rs, Register rt) { + CHECK(!IsR6()); + EmitR(0, rs, rt, rd, 0, 0x0B); +} + +void MipsAssembler::Seleqz(Register rd, Register rs, Register rt) { + CHECK(IsR6()); + EmitR(0, rs, rt, rd, 0, 0x35); +} + +void MipsAssembler::Selnez(Register rd, Register rs, Register rt) { + CHECK(IsR6()); + EmitR(0, rs, rt, rd, 0, 0x37); +} + +void MipsAssembler::ClzR6(Register rd, Register rs) { + CHECK(IsR6()); + EmitR(0, rs, static_cast(0), rd, 0x01, 0x10); +} + +void MipsAssembler::ClzR2(Register rd, Register rs) { + CHECK(!IsR6()); + EmitR(0x1C, rs, rd, rd, 0, 0x20); +} + +void MipsAssembler::CloR6(Register rd, Register rs) { + CHECK(IsR6()); + EmitR(0, rs, static_cast(0), rd, 0x01, 0x11); +} + +void MipsAssembler::CloR2(Register rd, Register rs) { + CHECK(!IsR6()); + EmitR(0x1C, rs, rd, rd, 0, 0x21); +} + void MipsAssembler::Seb(Register rd, Register rt) { EmitR(0x1f, static_cast(0), rt, rd, 0x10, 0x20); } diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h index 6a37cc9b1..91ec80425 100644 --- a/compiler/utils/mips/assembler_mips.h +++ b/compiler/utils/mips/assembler_mips.h @@ -133,6 +133,15 @@ class MipsAssembler FINAL : public Assembler { void Xori(Register rt, Register rs, uint16_t imm16); void Nor(Register rd, Register rs, Register rt); + void Movz(Register rd, Register rs, Register rt); // R2 + void Movn(Register rd, Register rs, Register rt); // R2 + void Seleqz(Register rd, Register rs, Register rt); // R6 + void Selnez(Register rd, Register rs, Register rt); // R6 + void ClzR6(Register rd, Register rs); + void ClzR2(Register rd, Register rs); + void CloR6(Register rd, Register rs); + void CloR2(Register rd, Register rs); + void Seb(Register rd, Register rt); // R2+ void Seh(Register rd, Register rt); // R2+ void Wsbh(Register rd, Register rt); // R2+ diff --git a/disassembler/disassembler_mips.cc b/disassembler/disassembler_mips.cc index c2f23aa52..2d15f6f41 100644 --- a/disassembler/disassembler_mips.cc +++ b/disassembler/disassembler_mips.cc @@ -139,6 +139,7 @@ static const MipsInstruction gMipsInstructions[] = { // SPECIAL2 { kSpecial2Mask | 0x7ff, (28 << kOpcodeShift) | 2, "mul", "DST" }, { kSpecial2Mask | 0x7ff, (28 << kOpcodeShift) | 32, "clz", "DS" }, + { kSpecial2Mask | 0x7ff, (28 << kOpcodeShift) | 33, "clo", "DS" }, { kSpecial2Mask | 0xffff, (28 << kOpcodeShift) | 0, "madd", "ST" }, { kSpecial2Mask | 0xffff, (28 << kOpcodeShift) | 1, "maddu", "ST" }, { kSpecial2Mask | 0xffff, (28 << kOpcodeShift) | 2, "mul", "DST" }, @@ -148,13 +149,34 @@ static const MipsInstruction gMipsInstructions[] = { // SPECIAL3 { kSpecial3Mask | 0x3f, (31 << kOpcodeShift) | 3, "dext", "TSAZ", }, - { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, (31 << kOpcodeShift) | (16 << 6) | 32, "seb", "DT", }, - { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, (31 << kOpcodeShift) | (24 << 6) | 32, "seh", "DT", }, - { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, (31 << kOpcodeShift) | 32, "bitswap", "DT", }, - { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, (31 << kOpcodeShift) | 36, "dbitswap", "DT", }, - { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, (31 << kOpcodeShift) | (2 << 6) | 36, "dsbh", "DT", }, - { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, (31 << kOpcodeShift) | (5 << 6) | 36, "dshd", "DT", }, - { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, (31 << kOpcodeShift) | (2 << 6) | 32, "wsbh", "DT", }, + { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, + (31 << kOpcodeShift) | (16 << 6) | 32, + "seb", + "DT", }, + { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, + (31 << kOpcodeShift) | (24 << 6) | 32, + "seh", + "DT", }, + { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, + (31 << kOpcodeShift) | 32, + "bitswap", + "DT", }, + { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, + (31 << kOpcodeShift) | 36, + "dbitswap", + "DT", }, + { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, + (31 << kOpcodeShift) | (2 << 6) | 36, + "dsbh", + "DT", }, + { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, + (31 << kOpcodeShift) | (5 << 6) | 36, + "dshd", + "DT", }, + { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f, + (31 << kOpcodeShift) | (2 << 6) | 32, + "wsbh", + "DT", }, { kSpecial3Mask | 0x7f, (31 << kOpcodeShift) | 0x26, "sc", "Tl", }, { kSpecial3Mask | 0x7f, (31 << kOpcodeShift) | 0x27, "scd", "Tl", }, { kSpecial3Mask | 0x7f, (31 << kOpcodeShift) | 0x36, "ll", "Tl", }, -- 2.11.0