MIPS32: java.lang.Thread, and java.lang.String intrinsics:
- Thread java.lang.Thread.currentThread()
- int java.lang.String.compareTo(String anotherString)
- int java.lang.String.indexOf(int ch)
- int java.lang.String.indexOf(int ch, int fromIndex)
- java.lang.StringFactory.newStringFromBytes(byte[] data,
int high,
int offset,
int byteCount)
- java.lang.StringFactory.newStringFromChars(int offset,
int charCount,
char[] data)
- java.lang.StringFactory.newStringFromString(String toCopy)
Change-Id: I96a06ff81e1e3bf18d45760282356854efaf4945
diff --git a/runtime/arch/mips/asm_support_mips.S b/runtime/arch/mips/asm_support_mips.S
index 51e224c..801f708 100644
--- a/runtime/arch/mips/asm_support_mips.S
+++ b/runtime/arch/mips/asm_support_mips.S
@@ -129,4 +129,43 @@
#endif // USE_HEAP_POISONING
.endm
+// Based on contents of creg select the minimum integer
+// At the end of the macro the original value of creg is lost
+.macro MINint dreg,rreg,sreg,creg
+ .set push
+ .set noat
+#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6)
+ .ifc \dreg, \rreg
+ selnez \dreg, \rreg, \creg
+ seleqz \creg, \sreg, \creg
+ .else
+ seleqz \dreg, \sreg, \creg
+ selnez \creg, \rreg, \creg
+ .endif
+ or \dreg, \dreg, \creg
+#else
+ movn \dreg, \rreg, \creg
+ movz \dreg, \sreg, \creg
+#endif
+ .set pop
+.endm
+
+// Find minimum of two signed registers
+.macro MINs dreg,rreg,sreg
+ .set push
+ .set noat
+ slt $at, \rreg, \sreg
+ MINint \dreg, \rreg, \sreg, $at
+ .set pop
+.endm
+
+// Find minimum of two unsigned registers
+.macro MINu dreg,rreg,sreg
+ .set push
+ .set noat
+ sltu $at, \rreg, \sreg
+ MINint \dreg, \rreg, \sreg, $at
+ .set pop
+.endm
+
#endif // ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_S_
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 699ab3e..6c7d510 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -1416,7 +1416,7 @@
SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
jal artAllocObjectFromCodeRosAlloc
- move $a2 ,$s1 # Pass self as argument.
+ move $a2, $s1 # Pass self as argument.
RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
END art_quick_alloc_object_rosalloc
@@ -1744,5 +1744,74 @@
nop
END art_quick_ushr_long
-UNIMPLEMENTED art_quick_indexof
-UNIMPLEMENTED art_quick_string_compareto
+/* java.lang.String.indexOf(int ch, int fromIndex=0) */
+ENTRY_NO_GP art_quick_indexof
+/* $a0 holds address of "this" */
+/* $a1 holds "ch" */
+/* $a2 holds "fromIndex" */
+ lw $t0, MIRROR_STRING_COUNT_OFFSET($a0) # this.length()
+ slt $at, $a2, $zero # if fromIndex < 0
+#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6)
+ seleqz $a2, $a2, $at # fromIndex = 0;
+#else
+ movn $a2, $zero, $at # fromIndex = 0;
+#endif
+ subu $t0, $t0, $a2 # this.length() - fromIndex
+ blez $t0, 6f # if this.length()-fromIndex <= 0
+ li $v0, -1 # return -1;
+
+ sll $v0, $a2, 1 # $a0 += $a2 * 2
+ addu $a0, $a0, $v0 # " " " " "
+ move $v0, $a2 # Set i to fromIndex.
+
+1:
+ lhu $t3, MIRROR_STRING_VALUE_OFFSET($a0) # if this.charAt(i) == ch
+ beq $t3, $a1, 6f # return i;
+ addu $a0, $a0, 2 # i++
+ subu $t0, $t0, 1 # this.length() - i
+ bnez $t0, 1b # while this.length() - i > 0
+ addu $v0, $v0, 1 # i++
+
+ li $v0, -1 # if this.length() - i <= 0
+ # return -1;
+
+6:
+ j $ra
+ nop
+END art_quick_indexof
+
+ .set push
+ .set noat
+/* java.lang.String.compareTo(String anotherString) */
+ENTRY_NO_GP art_quick_string_compareto
+/* $a0 holds address of "this" */
+/* $a1 holds address of "anotherString" */
+ beq $a0, $a1, 9f # this and anotherString are the same object
+ move $v0, $zero
+
+ lw $a2, MIRROR_STRING_COUNT_OFFSET($a0) # this.length()
+ lw $a3, MIRROR_STRING_COUNT_OFFSET($a1) # anotherString.length()
+ MINu $t2, $a2, $a3
+# $t2 now holds min(this.length(),anotherString.length())
+
+ beqz $t2, 9f # while min(this.length(),anotherString.length())-i != 0
+ subu $v0, $a2, $a3 # if $t2==0 return
+ # (this.length() - anotherString.length())
+1:
+ lhu $t0, MIRROR_STRING_VALUE_OFFSET($a0) # while this.charAt(i) == anotherString.charAt(i)
+ lhu $t1, MIRROR_STRING_VALUE_OFFSET($a1)
+ bne $t0, $t1, 9f # if this.charAt(i) != anotherString.charAt(i)
+ subu $v0, $t0, $t1 # return (this.charAt(i) - anotherString.charAt(i))
+ addiu $a0, $a0, 2 # point at this.charAt(i++)
+ subu $t2, $t2, 1 # new value of
+ # min(this.length(),anotherString.length())-i
+ bnez $t2, 1b
+ addiu $a1, $a1, 2 # point at anotherString.charAt(i++)
+ subu $v0, $a2, $a3
+
+9:
+ j $ra
+ nop
+END art_quick_string_compareto
+
+ .set pop
diff --git a/runtime/arch/mips64/asm_support_mips64.S b/runtime/arch/mips64/asm_support_mips64.S
index b859c70..786e860 100644
--- a/runtime/arch/mips64/asm_support_mips64.S
+++ b/runtime/arch/mips64/asm_support_mips64.S
@@ -83,4 +83,38 @@
#endif // USE_HEAP_POISONING
.endm
+// Based on contents of creg select the minimum integer
+// At the end of the macro the original value of creg is lost
+.macro MINint dreg,rreg,sreg,creg
+ .set push
+ .set noat
+ .ifc \dreg, \rreg
+ selnez \dreg, \rreg, \creg
+ seleqz \creg, \sreg, \creg
+ .else
+ seleqz \dreg, \sreg, \creg
+ selnez \creg, \rreg, \creg
+ .endif
+ or \dreg, \dreg, \creg
+ .set pop
+.endm
+
+// Find minimum of two signed registers
+.macro MINs dreg,rreg,sreg
+ .set push
+ .set noat
+ slt $at, \rreg, \sreg
+ MINint \dreg, \rreg, \sreg, $at
+ .set pop
+.endm
+
+// Find minimum of two unsigned registers
+.macro MINu dreg,rreg,sreg
+ .set push
+ .set noat
+ sltu $at, \rreg, \sreg
+ MINint \dreg, \rreg, \sreg, $at
+ .set pop
+.endm
+
#endif // ART_RUNTIME_ARCH_MIPS64_ASM_SUPPORT_MIPS64_S_
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index d264c9b..b4e2fcc 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -1725,10 +1725,8 @@
lw $a2,MIRROR_STRING_COUNT_OFFSET($a0) # this.length()
lw $a3,MIRROR_STRING_COUNT_OFFSET($a1) # anotherString.length()
- sltu $at,$a2,$a3
- seleqz $t2,$a3,$at
- selnez $at,$a2,$at
- or $t2,$t2,$at # $t2 now holds min(this.length(),anotherString.length())
+ MINu $t2, $a2, $a3
+# $t2 now holds min(this.length(),anotherString.length())
beqz $t2,9f # while min(this.length(),anotherString.length())-i != 0
subu $v0,$a2,$a3 # if $t2==0 return
@@ -1753,16 +1751,18 @@
/* java.lang.String.indexOf(int ch, int fromIndex=0) */
ENTRY_NO_GP art_quick_indexof
/* $a0 holds address of "this" */
-/* $a1 holds address of "ch" */
-/* $a2 holds address of "fromIndex" */
+/* $a1 holds "ch" */
+/* $a2 holds "fromIndex" */
lw $t0,MIRROR_STRING_COUNT_OFFSET($a0) # this.length()
- subu $t0,$t0,$a2 # this.length() - offset
- blez $t0,6f # if this.length()-offset <= 0
+ slt $at, $a2, $zero # if fromIndex < 0
+ seleqz $a2, $a2, $at # fromIndex = 0;
+ subu $t0,$t0,$a2 # this.length() - fromIndex
+ blez $t0,6f # if this.length()-fromIndex <= 0
li $v0,-1 # return -1;
sll $v0,$a2,1 # $a0 += $a2 * 2
daddu $a0,$a0,$v0 # " " " " "
- move $v0,$a2 # Set i to offset.
+ move $v0,$a2 # Set i to fromIndex.
1:
lhu $t3,MIRROR_STRING_VALUE_OFFSET($a0) # if this.charAt(i) == ch
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index d5807e2..4236c28 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -1205,7 +1205,7 @@
TEST_F(StubTest, StringCompareTo) {
#if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \
- (defined(__mips__) && defined(__LP64__)) || (defined(__x86_64__) && !defined(__APPLE__))
+ defined(__mips__) || (defined(__x86_64__) && !defined(__APPLE__))
// TODO: Check the "Unresolved" allocation stubs
Thread* self = Thread::Current();
@@ -2054,7 +2054,7 @@
}
TEST_F(StubTest, StringIndexOf) {
-#if defined(__arm__) || defined(__aarch64__) || (defined(__mips__) && defined(__LP64__))
+#if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
// garbage is created during ClassLinker::Init