Revert "Revert "[MIPS] Use hard float calling convention for managed code""
This reverts commit 7fee84c087e0f903e7d43bef180df047db1c8051.
Fixed issue with temporary registers on Mips32r6.
Change-Id: I93018927e6a6036cff2d55e6cda66d3212a4316b
diff --git a/runtime/arch/mips/asm_support_mips.h b/runtime/arch/mips/asm_support_mips.h
index 390c606..453056d 100644
--- a/runtime/arch/mips/asm_support_mips.h
+++ b/runtime/arch/mips/asm_support_mips.h
@@ -21,6 +21,6 @@
#define FRAME_SIZE_SAVE_ALL_CALLEE_SAVE 96
#define FRAME_SIZE_REFS_ONLY_CALLEE_SAVE 48
-#define FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE 64
+#define FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE 80
#endif // ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_H_
diff --git a/runtime/arch/mips/context_mips.cc b/runtime/arch/mips/context_mips.cc
index 53f2b65..bc2bf68 100644
--- a/runtime/arch/mips/context_mips.cc
+++ b/runtime/arch/mips/context_mips.cc
@@ -76,6 +76,11 @@
gprs_[A1] = nullptr;
gprs_[A2] = nullptr;
gprs_[A3] = nullptr;
+
+ fprs_[F12] = nullptr;
+ fprs_[F13] = nullptr;
+ fprs_[F14] = nullptr;
+ fprs_[F15] = nullptr;
}
extern "C" NO_RETURN void art_quick_do_long_jump(uint32_t*, uint32_t*);
diff --git a/runtime/arch/mips/jni_entrypoints_mips.S b/runtime/arch/mips/jni_entrypoints_mips.S
index fbc81d5..3558efd 100644
--- a/runtime/arch/mips/jni_entrypoints_mips.S
+++ b/runtime/arch/mips/jni_entrypoints_mips.S
@@ -24,17 +24,19 @@
*/
.extern artFindNativeMethod
ENTRY art_jni_dlsym_lookup_stub
- addiu $sp, $sp, -32 # leave room for $a0, $a1, $a2, $a3, and $ra
- .cfi_adjust_cfa_offset 32
- sw $ra, 16($sp)
- .cfi_rel_offset 31, 16
- sw $a3, 12($sp)
+ addiu $sp, $sp, -48 # leave room for $f12, $f13, $f14, $f15, $a0, $a1, $a2, $a3, and $ra
+ .cfi_adjust_cfa_offset 48
+ sw $ra, 32($sp)
+ .cfi_rel_offset 31, 32
+ SDu $f14, $f15, 24, $sp, $t0
+ SDu $f12, $f13, 16, $sp, $t0
+ sw $a3, 12($sp)
.cfi_rel_offset 7, 12
- sw $a2, 8($sp)
+ sw $a2, 8($sp)
.cfi_rel_offset 6, 8
- sw $a1, 4($sp)
+ sw $a1, 4($sp)
.cfi_rel_offset 5, 4
- sw $a0, 0($sp)
+ sw $a0, 0($sp)
.cfi_rel_offset 4, 0
jal artFindNativeMethod # (Thread*)
move $a0, $s1 # pass Thread::Current()
@@ -42,10 +44,12 @@
lw $a1, 4($sp)
lw $a2, 8($sp)
lw $a3, 12($sp)
- lw $ra, 16($sp)
+ LDu $f12, $f13, 16, $sp, $t0
+ LDu $f14, $f15, 24, $sp, $t0
+ lw $ra, 32($sp)
beq $v0, $zero, .Lno_native_code_found
- addiu $sp, $sp, 32 # restore the stack
- .cfi_adjust_cfa_offset -32
+ addiu $sp, $sp, 48 # restore the stack
+ .cfi_adjust_cfa_offset -48
move $t9, $v0 # put method code result in $t9
jalr $zero, $t9 # leaf call to method's code
nop
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 4d5004f..8bc75e5 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -170,45 +170,47 @@
* callee-save: $a1-$a3, $s2-$s8 + $gp + $ra, 12 total + 3 words padding + method*
*/
.macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_REGISTERS_ONLY
- addiu $sp, $sp, -64
- .cfi_adjust_cfa_offset 64
+ addiu $sp, $sp, -80
+ .cfi_adjust_cfa_offset 80
// Ugly compile-time check, but we only have the preprocessor.
-#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 64)
+#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 80)
#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(MIPS) size not as expected."
#endif
- sw $ra, 60($sp)
- .cfi_rel_offset 31, 60
- sw $s8, 56($sp)
- .cfi_rel_offset 30, 56
- sw $gp, 52($sp)
- .cfi_rel_offset 28, 52
- sw $s7, 48($sp)
- .cfi_rel_offset 23, 48
- sw $s6, 44($sp)
- .cfi_rel_offset 22, 44
- sw $s5, 40($sp)
- .cfi_rel_offset 21, 40
- sw $s4, 36($sp)
- .cfi_rel_offset 20, 36
- sw $s3, 32($sp)
- .cfi_rel_offset 19, 32
- sw $s2, 28($sp)
- .cfi_rel_offset 18, 28
- sw $a3, 24($sp)
- .cfi_rel_offset 7, 24
- sw $a2, 20($sp)
- .cfi_rel_offset 6, 20
- sw $a1, 16($sp)
- .cfi_rel_offset 5, 16
+ sw $ra, 76($sp)
+ .cfi_rel_offset 31, 76
+ sw $s8, 72($sp)
+ .cfi_rel_offset 30, 72
+ sw $gp, 68($sp)
+ .cfi_rel_offset 28, 68
+ sw $s7, 64($sp)
+ .cfi_rel_offset 23, 64
+ sw $s6, 60($sp)
+ .cfi_rel_offset 22, 60
+ sw $s5, 56($sp)
+ .cfi_rel_offset 21, 56
+ sw $s4, 52($sp)
+ .cfi_rel_offset 20, 52
+ sw $s3, 48($sp)
+ .cfi_rel_offset 19, 48
+ sw $s2, 44($sp)
+ .cfi_rel_offset 18, 44
+ sw $a3, 40($sp)
+ .cfi_rel_offset 7, 40
+ sw $a2, 36($sp)
+ .cfi_rel_offset 6, 36
+ sw $a1, 32($sp)
+ .cfi_rel_offset 5, 32
+ SDu $f14, $f15, 24, $sp, $t0
+ SDu $f12, $f13, 16, $sp, $t0
# bottom will hold Method*
.endm
/*
* Macro that sets up the callee save frame to conform with
* Runtime::CreateCalleeSaveMethod(kRefsAndArgs). Restoration assumes non-moving GC.
- * callee-save: $a1-$a3, $s2-$s8 + $gp + $ra, 12 total + 3 words padding + method*
+ * callee-save: $a1-$a3, $f12-$f15, $s2-$s8 + $gp + $ra, 12 total + 3 words padding + method*
* Clobbers $t0 and $sp
* Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
* Reserves FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE + ARG_SLOT_SIZE bytes on the stack
@@ -227,7 +229,7 @@
/*
* Macro that sets up the callee save frame to conform with
* Runtime::CreateCalleeSaveMethod(kRefsAndArgs). Restoration assumes non-moving GC.
- * callee-save: $a1-$a3, $s2-$s8 + $gp + $ra, 12 total + 3 words padding + method*
+ * callee-save: $a1-$a3, $f12-$f15, $s2-$s8 + $gp + $ra, 12 total + 3 words padding + method*
* Clobbers $sp
* Use $a0 as the Method* and loads it into bottom of stack.
* Allocates ARG_SLOT_SIZE bytes at the bottom of the stack for arg slots.
@@ -244,32 +246,34 @@
.macro RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
addiu $sp, $sp, ARG_SLOT_SIZE # remove argument slots on the stack
.cfi_adjust_cfa_offset -ARG_SLOT_SIZE
- lw $ra, 60($sp)
+ lw $ra, 76($sp)
.cfi_restore 31
- lw $s8, 56($sp)
+ lw $s8, 72($sp)
.cfi_restore 30
- lw $gp, 52($sp)
+ lw $gp, 68($sp)
.cfi_restore 28
- lw $s7, 48($sp)
+ lw $s7, 64($sp)
.cfi_restore 23
- lw $s6, 44($sp)
+ lw $s6, 60($sp)
.cfi_restore 22
- lw $s5, 40($sp)
+ lw $s5, 56($sp)
.cfi_restore 21
- lw $s4, 36($sp)
+ lw $s4, 52($sp)
.cfi_restore 20
- lw $s3, 32($sp)
+ lw $s3, 48($sp)
.cfi_restore 19
- lw $s2, 28($sp)
+ lw $s2, 44($sp)
.cfi_restore 18
- lw $a3, 24($sp)
+ lw $a3, 40($sp)
.cfi_restore 7
- lw $a2, 20($sp)
+ lw $a2, 36($sp)
.cfi_restore 6
- lw $a1, 16($sp)
+ lw $a1, 32($sp)
.cfi_restore 5
- addiu $sp, $sp, 64 # pop frame
- .cfi_adjust_cfa_offset -64
+ LDu $f14, $f15, 24, $sp, $t1
+ LDu $f12, $f13, 16, $sp, $t1
+ addiu $sp, $sp, 80 # pop frame
+ .cfi_adjust_cfa_offset -80
.endm
/*
@@ -484,6 +488,32 @@
INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
+.macro LOAD_WORD_TO_REG reg, next_arg, index, label
+ lw $\reg, -4($\next_arg) # next_arg points to argument after the current one (offset is 4)
+ b \label
+ addiu $\index, 1
+.endm
+
+.macro LOAD_LONG_TO_REG reg1, reg2, next_arg, index, label
+ lw $\reg1, -8($\next_arg) # next_arg points to argument after the current one (offset is 8)
+ lw $\reg2, -4($\next_arg)
+ b \label
+ li $\index, 4 # long can be loaded only to a2_a3 pair so index will be always 4
+.endm
+
+.macro LOAD_FLOAT_TO_REG reg, next_arg, index, label
+ lwc1 $\reg, -4($\next_arg) # next_arg points to argument after the current one (offset is 4)
+ b \label
+ addiu $\index, 1
+.endm
+
+.macro LOAD_DOUBLE_TO_REG reg1, reg2, next_arg, index, tmp, label
+ LDu $\reg1, $\reg2, -8, $\next_arg, $\tmp # next_arg points to argument after the current one
+ # (offset is 8)
+ b \label
+ addiu $\index, 1
+.endm
+
/*
* Invocation stub for quick code.
* On entry:
@@ -510,21 +540,76 @@
.cfi_def_cfa_register 30
move $s1, $a3 # move managed thread pointer into s1
addiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset s0 to suspend check interval
- addiu $t0, $a2, 4 # create space for method pointer in frame.
+ addiu $t0, $a2, 4 # create space for ArtMethod* in frame.
subu $t0, $sp, $t0 # reserve & align *stack* to 16 bytes:
- srl $t0, $t0, 4 # native calling convention only aligns to 8B,
- sll $sp, $t0, 4 # so we have to ensure ART 16B alignment ourselves.
- addiu $a0, $sp, 4 # pass stack pointer + method ptr as dest for memcpy
+ srl $t0, $t0, 4 # native calling convention only aligns to 8B,
+ sll $sp, $t0, 4 # so we have to ensure ART 16B alignment ourselves.
+ addiu $a0, $sp, 4 # pass stack pointer + ArtMethod* as dest for memcpy
jal memcpy # (dest, src, bytes)
addiu $sp, $sp, -16 # make space for argument slots for memcpy
addiu $sp, $sp, 16 # restore stack after memcpy
- lw $a0, 16($fp) # restore method*
- lw $a1, 4($sp) # copy arg value for a1
- lw $a2, 8($sp) # copy arg value for a2
- lw $a3, 12($sp) # copy arg value for a3
+ lw $a0, 16($fp) # restore ArtMethod*
+ lw $a1, 4($sp) # a1 = this*
+ addiu $t0, $sp, 8 # t0 = pointer to the current argument (skip ArtMethod* and this*)
+ li $t3, 2 # t3 = gpr_index = 2 (skip A0 and A1)
+ move $t4, $zero # t4 = fp_index = 0
+ lw $t1, 20+16($fp) # get shorty (20 is offset from the $sp on entry + 16 as the $fp is
+ # 16 bytes below the $sp on entry)
+ addiu $t1, 1 # t1 = shorty + 1 (skip 1 for return type)
+loop:
+ lbu $t2, 0($t1) # t2 = shorty[i]
+ beqz $t2, loopEnd # finish getting args when shorty[i] == '\0'
+ addiu $t1, 1
+
+ li $t9, 'J' # put char 'J' into t9
+ beq $t9, $t2, isLong # branch if result type char == 'J'
+ li $t9, 'D' # put char 'D' into t9
+ beq $t9, $t2, isDouble # branch if result type char == 'D'
+ li $t9, 'F' # put char 'F' into t9
+ beq $t9, $t2, isSingle # branch if result type char == 'F'
+ addiu $t0, 4 # next_arg = curr_arg + 4 (in branch delay slot,
+ # for both, int and single)
+
+ li $t5, 2 # skip a0 and a1 (ArtMethod* and this*)
+ bne $t5, $t3, 1f # if (gpr_index == 2)
+ addiu $t5, 1
+ LOAD_WORD_TO_REG a2, t0, t3, loop # a2 = current argument, gpr_index++
+1: bne $t5, $t3, loop # else if (gpr_index == 3)
+ nop
+ LOAD_WORD_TO_REG a3, t0, t3, loop # a3 = current argument, gpr_index++
+
+isLong:
+ addiu $t0, 8 # next_arg = curr_arg + 8
+ slti $t5, $t3, 3
+ beqz $t5, 2f # if (gpr_index < 3)
+ nop
+ LOAD_LONG_TO_REG a2, a3, t0, t3, loop # a2_a3 = curr_arg, gpr_index = 4
+2: b loop # else
+ li $t3, 4 # gpr_index = 4
+
+isDouble:
+ addiu $t0, 8 # next_arg = curr_arg + 8
+ li $t5, 0
+ bne $t5, $t4, 3f # if (fp_index == 0)
+ addiu $t5, 1
+ LOAD_DOUBLE_TO_REG f12, f13, t0, t4, t9, loop # f12_f13 = curr_arg, fp_index++
+3: bne $t5, $t4, loop # else if (fp_index == 1)
+ nop
+ LOAD_DOUBLE_TO_REG f14, f15, t0, t4, t9, loop # f14_f15 = curr_arg, fp_index++
+
+isSingle:
+ li $t5, 0
+ bne $t5, $t4, 4f # if (fp_index == 0)
+ addiu $t5, 1
+ LOAD_FLOAT_TO_REG f12, t0, t4, loop # f12 = curr_arg, fp_index++
+4: bne $t5, $t4, loop # else if (fp_index == 1)
+ nop
+ LOAD_FLOAT_TO_REG f14, t0, t4, loop # f14 = curr_arg, fp_index++
+
+loopEnd:
lw $t9, ART_METHOD_QUICK_CODE_OFFSET_32($a0) # get pointer to the code
jalr $t9 # call the method
- sw $zero, 0($sp) # store null for method* at bottom of frame
+ sw $zero, 0($sp) # store null for ArtMethod* at bottom of frame
move $sp, $fp # restore the stack
lw $s0, 0($sp)
.cfi_restore 16
@@ -539,20 +624,145 @@
lw $t0, 16($sp) # get result pointer
lw $t1, 20($sp) # get shorty
lb $t1, 0($t1) # get result type char
- li $t2, 68 # put char 'D' into t2
- beq $t1, $t2, 1f # branch if result type char == 'D'
- li $t3, 70 # put char 'F' into t3
- beq $t1, $t3, 1f # branch if result type char == 'F'
+ li $t2, 'D' # put char 'D' into t2
+ beq $t1, $t2, 5f # branch if result type char == 'D'
+ li $t3, 'F' # put char 'F' into t3
+ beq $t1, $t3, 5f # branch if result type char == 'F'
sw $v0, 0($t0) # store the result
jalr $zero, $ra
sw $v1, 4($t0) # store the other half of the result
-1:
+5:
SDu $f0, $f1, 0, $t0, $t1 # store floating point result
jalr $zero, $ra
nop
END art_quick_invoke_stub
/*
+ * Invocation static stub for quick code.
+ * On entry:
+ * a0 = method pointer
+ * a1 = argument array or null for no argument methods
+ * a2 = size of argument array in bytes
+ * a3 = (managed) thread pointer
+ * [sp + 16] = JValue* result
+ * [sp + 20] = shorty
+ */
+ENTRY art_quick_invoke_static_stub
+ sw $a0, 0($sp) # save out a0
+ addiu $sp, $sp, -16 # spill s0, s1, fp, ra
+ .cfi_adjust_cfa_offset 16
+ sw $ra, 12($sp)
+ .cfi_rel_offset 31, 12
+ sw $fp, 8($sp)
+ .cfi_rel_offset 30, 8
+ sw $s1, 4($sp)
+ .cfi_rel_offset 17, 4
+ sw $s0, 0($sp)
+ .cfi_rel_offset 16, 0
+ move $fp, $sp # save sp in fp
+ .cfi_def_cfa_register 30
+ move $s1, $a3 # move managed thread pointer into s1
+ addiu $s0, $zero, SUSPEND_CHECK_INTERVAL # reset s0 to suspend check interval
+ addiu $t0, $a2, 4 # create space for ArtMethod* in frame.
+ subu $t0, $sp, $t0 # reserve & align *stack* to 16 bytes:
+ srl $t0, $t0, 4 # native calling convention only aligns to 8B,
+ sll $sp, $t0, 4 # so we have to ensure ART 16B alignment ourselves.
+ addiu $a0, $sp, 4 # pass stack pointer + ArtMethod* as dest for memcpy
+ jal memcpy # (dest, src, bytes)
+ addiu $sp, $sp, -16 # make space for argument slots for memcpy
+ addiu $sp, $sp, 16 # restore stack after memcpy
+ lw $a0, 16($fp) # restore ArtMethod*
+ addiu $t0, $sp, 4 # t0 = pointer to the current argument (skip ArtMethod*)
+ li $t3, 1 # t3 = gpr_index = 1 (skip A0)
+ move $t4, $zero # t4 = fp_index = 0
+ lw $t1, 20+16($fp) # get shorty (20 is offset from the $sp on entry + 16 as the $fp is
+ # 16 bytes below the $sp on entry)
+ addiu $t1, 1 # t1 = shorty + 1 (skip 1 for return type)
+loopS:
+ lbu $t2, 0($t1) # t2 = shorty[i]
+ beqz $t2, loopEndS # finish getting args when shorty[i] == '\0'
+ addiu $t1, 1
+
+ li $t9, 'J' # put char 'J' into t9
+ beq $t9, $t2, isLongS # branch if result type char == 'J'
+ li $t9, 'D' # put char 'D' into t9
+ beq $t9, $t2, isDoubleS # branch if result type char == 'D'
+ li $t9, 'F' # put char 'F' into t9
+ beq $t9, $t2, isSingleS # branch if result type char == 'F'
+ addiu $t0, 4 # next_arg = curr_arg + 4 (in branch delay slot,
+ # for both, int and single)
+
+ li $t5, 1 # skip a0 (ArtMethod*)
+ bne $t5, $t3, 1f # if (gpr_index == 1)
+ addiu $t5, 1
+ LOAD_WORD_TO_REG a1, t0, t3, loopS # a1 = current argument, gpr_index++
+1: bne $t5, $t3, 2f # else if (gpr_index == 2)
+ addiu $t5, 1
+ LOAD_WORD_TO_REG a2, t0, t3, loopS # a2 = current argument, gpr_index++
+2: bne $t5, $t3, loopS # else if (gpr_index == 3)
+ nop
+ LOAD_WORD_TO_REG a3, t0, t3, loopS # a3 = current argument, gpr_index++
+
+isLongS:
+ addiu $t0, 8 # next_arg = curr_arg + 8
+ slti $t5, $t3, 3
+ beqz $t5, 3f # if (gpr_index < 3)
+ nop
+ LOAD_LONG_TO_REG a2, a3, t0, t3, loopS # a2_a3 = curr_arg, gpr_index = 4
+3: b loopS # else
+ li $t3, 4 # gpr_index = 4
+
+isDoubleS:
+ addiu $t0, 8 # next_arg = curr_arg + 8
+ li $t5, 0
+ bne $t5, $t4, 4f # if (fp_index == 0)
+ addiu $t5, 1
+ LOAD_DOUBLE_TO_REG f12, f13, t0, t4, t9, loopS # f12_f13 = curr_arg, fp_index++
+4: bne $t5, $t4, loopS # else if (fp_index == 1)
+ nop
+ LOAD_DOUBLE_TO_REG f14, f15, t0, t4, t9, loopS # f14_f15 = curr_arg, fp_index++
+
+isSingleS:
+ li $t5, 0
+ bne $t5, $t4, 5f # if (fp_index == 0)
+ addiu $t5, 1
+ LOAD_FLOAT_TO_REG f12, t0, t4, loopS # f12 = curr_arg, fp_index++
+5: bne $t5, $t4, loopS # else if (fp_index == 1)
+ nop
+ LOAD_FLOAT_TO_REG f14, t0, t4, loopS # f14 = curr_arg, fp_index++
+
+loopEndS:
+ lw $t9, ART_METHOD_QUICK_CODE_OFFSET_32($a0) # get pointer to the code
+ jalr $t9 # call the method
+ sw $zero, 0($sp) # store null for ArtMethod* at bottom of frame
+ move $sp, $fp # restore the stack
+ lw $s0, 0($sp)
+ .cfi_restore 16
+ lw $s1, 4($sp)
+ .cfi_restore 17
+ lw $fp, 8($sp)
+ .cfi_restore 30
+ lw $ra, 12($sp)
+ .cfi_restore 31
+ addiu $sp, $sp, 16
+ .cfi_adjust_cfa_offset -16
+ lw $t0, 16($sp) # get result pointer
+ lw $t1, 20($sp) # get shorty
+ lb $t1, 0($t1) # get result type char
+ li $t2, 'D' # put char 'D' into t2
+ beq $t1, $t2, 6f # branch if result type char == 'D'
+ li $t3, 'F' # put char 'F' into t3
+ beq $t1, $t3, 6f # branch if result type char == 'F'
+ sw $v0, 0($t0) # store the result
+ jalr $zero, $ra
+ sw $v1, 4($t0) # store the other half of the result
+6:
+ SDu $f0, $f1, 0, $t0, $t1 # store floating point result
+ jalr $zero, $ra
+ nop
+END art_quick_invoke_static_stub
+
+ /*
* Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
* failure.
*/
diff --git a/runtime/arch/mips/quick_method_frame_info_mips.h b/runtime/arch/mips/quick_method_frame_info_mips.h
index dd5ac80..f5d13c2 100644
--- a/runtime/arch/mips/quick_method_frame_info_mips.h
+++ b/runtime/arch/mips/quick_method_frame_info_mips.h
@@ -25,6 +25,8 @@
namespace art {
namespace mips {
+static constexpr uint32_t kMipsCalleeSaveAlwaysSpills =
+ (1 << art::mips::RA);
static constexpr uint32_t kMipsCalleeSaveRefSpills =
(1 << art::mips::S2) | (1 << art::mips::S3) | (1 << art::mips::S4) | (1 << art::mips::S5) |
(1 << art::mips::S6) | (1 << art::mips::S7) | (1 << art::mips::GP) | (1 << art::mips::FP);
@@ -32,19 +34,26 @@
(1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3);
static constexpr uint32_t kMipsCalleeSaveAllSpills =
(1 << art::mips::S0) | (1 << art::mips::S1);
+
+static constexpr uint32_t kMipsCalleeSaveFpAlwaysSpills = 0;
+static constexpr uint32_t kMipsCalleeSaveFpRefSpills = 0;
+static constexpr uint32_t kMipsCalleeSaveFpArgSpills =
+ (1 << art::mips::F12) | (1 << art::mips::F13) | (1 << art::mips::F14) | (1 << art::mips::F15);
static constexpr uint32_t kMipsCalleeSaveAllFPSpills =
(1 << art::mips::F20) | (1 << art::mips::F21) | (1 << art::mips::F22) | (1 << art::mips::F23) |
(1 << art::mips::F24) | (1 << art::mips::F25) | (1 << art::mips::F26) | (1 << art::mips::F27) |
(1 << art::mips::F28) | (1 << art::mips::F29) | (1 << art::mips::F30) | (1 << art::mips::F31);
constexpr uint32_t MipsCalleeSaveCoreSpills(Runtime::CalleeSaveType type) {
- return kMipsCalleeSaveRefSpills |
+ return kMipsCalleeSaveAlwaysSpills | kMipsCalleeSaveRefSpills |
(type == Runtime::kRefsAndArgs ? kMipsCalleeSaveArgSpills : 0) |
- (type == Runtime::kSaveAll ? kMipsCalleeSaveAllSpills : 0) | (1 << art::mips::RA);
+ (type == Runtime::kSaveAll ? kMipsCalleeSaveAllSpills : 0);
}
constexpr uint32_t MipsCalleeSaveFPSpills(Runtime::CalleeSaveType type) {
- return type == Runtime::kSaveAll ? kMipsCalleeSaveAllFPSpills : 0;
+ return kMipsCalleeSaveFpAlwaysSpills | kMipsCalleeSaveFpRefSpills |
+ (type == Runtime::kRefsAndArgs ? kMipsCalleeSaveFpArgSpills : 0) |
+ (type == Runtime::kSaveAll ? kMipsCalleeSaveAllFPSpills : 0);
}
constexpr uint32_t MipsCalleeSaveFrameSize(Runtime::CalleeSaveType type) {
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index f4c6473..56f7b35 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -45,10 +45,8 @@
extern "C" void art_quick_invoke_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*,
const char*);
-#if defined(__LP64__) || defined(__arm__) || defined(__i386__)
extern "C" void art_quick_invoke_static_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*,
const char*);
-#endif
ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
jobject jlr_method) {
@@ -417,15 +415,11 @@
<< "Don't call compiled code when -Xint " << PrettyMethod(this);
}
-#if defined(__LP64__) || defined(__arm__) || defined(__i386__)
if (!IsStatic()) {
(*art_quick_invoke_stub)(this, args, args_size, self, result, shorty);
} else {
(*art_quick_invoke_static_stub)(this, args, args_size, self, result, shorty);
}
-#else
- (*art_quick_invoke_stub)(this, args, args_size, self, result, shorty);
-#endif
if (UNLIKELY(self->GetException() == Thread::GetDeoptimizationException())) {
// Unusual case where we were running generated code and an
// exception was thrown to force the activations to be removed from the
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index da4b82c..aa35ec1 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -65,6 +65,7 @@
static constexpr bool kAlignPairRegister = !kArm32QuickCodeUseSoftFloat;
static constexpr bool kQuickSoftFloatAbi = kArm32QuickCodeUseSoftFloat;
static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = !kArm32QuickCodeUseSoftFloat;
+ static constexpr bool kQuickSkipOddFpRegisters = false;
static constexpr size_t kNumQuickGprArgs = 3;
static constexpr size_t kNumQuickFprArgs = kArm32QuickCodeUseSoftFloat ? 0 : 16;
static constexpr bool kGprFprLockstep = false;
@@ -102,6 +103,7 @@
static constexpr bool kAlignPairRegister = false;
static constexpr bool kQuickSoftFloatAbi = false; // This is a hard float ABI.
static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false;
+ static constexpr bool kQuickSkipOddFpRegisters = false;
static constexpr size_t kNumQuickGprArgs = 7; // 7 arguments passed in GPRs.
static constexpr size_t kNumQuickFprArgs = 8; // 8 arguments passed in FPRs.
static constexpr bool kGprFprLockstep = false;
@@ -128,17 +130,25 @@
// | A3 | arg3
// | A2 | arg2
// | A1 | arg1
+ // | F15 |
+ // | F14 | f_arg1
+ // | F13 |
+ // | F12 | f_arg0
+ // | | padding
// | A0/Method* | <- sp
- static constexpr bool kSplitPairAcrossRegisterAndStack = true;
- static constexpr bool kAlignPairRegister = false;
- static constexpr bool kQuickSoftFloatAbi = true; // This is a soft float ABI.
+ static constexpr bool kSplitPairAcrossRegisterAndStack = false;
+ static constexpr bool kAlignPairRegister = true;
+ static constexpr bool kQuickSoftFloatAbi = false;
static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false;
+ static constexpr bool kQuickSkipOddFpRegisters = true;
static constexpr size_t kNumQuickGprArgs = 3; // 3 arguments passed in GPRs.
- static constexpr size_t kNumQuickFprArgs = 0; // 0 arguments passed in FPRs.
+ static constexpr size_t kNumQuickFprArgs = 4; // 2 arguments passed in FPRs. Floats can be passed
+ // only in even numbered registers and each double
+ // occupies two registers.
static constexpr bool kGprFprLockstep = false;
- static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 0; // Offset of first FPR arg.
- static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 16; // Offset of first GPR arg.
- static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 60; // Offset of return address.
+ static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 16; // Offset of first FPR arg.
+ static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 32; // Offset of first GPR arg.
+ static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 76; // Offset of return address.
static size_t GprIndexToGprOffset(uint32_t gpr_index) {
return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA);
}
@@ -153,14 +163,6 @@
// | Method* | ---
// | RA |
// | ... | callee saves
- // | F7 | f_arg7
- // | F6 | f_arg6
- // | F5 | f_arg5
- // | F4 | f_arg4
- // | F3 | f_arg3
- // | F2 | f_arg2
- // | F1 | f_arg1
- // | F0 | f_arg0
// | A7 | arg7
// | A6 | arg6
// | A5 | arg5
@@ -168,6 +170,14 @@
// | A3 | arg3
// | A2 | arg2
// | A1 | arg1
+ // | F19 | f_arg7
+ // | F18 | f_arg6
+ // | F17 | f_arg5
+ // | F16 | f_arg4
+ // | F15 | f_arg3
+ // | F14 | f_arg2
+ // | F13 | f_arg1
+ // | F12 | f_arg0
// | | padding
// | A0/Method* | <- sp
// NOTE: for Mip64, when A0 is skipped, F0 is also skipped.
@@ -175,9 +185,7 @@
static constexpr bool kAlignPairRegister = false;
static constexpr bool kQuickSoftFloatAbi = false;
static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false;
- // These values are set to zeros because GPR and FPR register
- // assignments for Mips64 are interleaved, which the current VisitArguments()
- // function does not support.
+ static constexpr bool kQuickSkipOddFpRegisters = false;
static constexpr size_t kNumQuickGprArgs = 7; // 7 arguments passed in GPRs.
static constexpr size_t kNumQuickFprArgs = 7; // 7 arguments passed in FPRs.
static constexpr bool kGprFprLockstep = true;
@@ -211,6 +219,7 @@
static constexpr bool kAlignPairRegister = false;
static constexpr bool kQuickSoftFloatAbi = false; // This is a hard float ABI.
static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false;
+ static constexpr bool kQuickSkipOddFpRegisters = false;
static constexpr size_t kNumQuickGprArgs = 3; // 3 arguments passed in GPRs.
static constexpr size_t kNumQuickFprArgs = 4; // 4 arguments passed in FPRs.
static constexpr bool kGprFprLockstep = false;
@@ -252,6 +261,7 @@
static constexpr bool kAlignPairRegister = false;
static constexpr bool kQuickSoftFloatAbi = false; // This is a hard float ABI.
static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false;
+ static constexpr bool kQuickSkipOddFpRegisters = false;
static constexpr size_t kNumQuickGprArgs = 5; // 5 arguments passed in GPRs.
static constexpr size_t kNumQuickFprArgs = 8; // 8 arguments passed in FPRs.
static constexpr bool kGprFprLockstep = false;
@@ -475,6 +485,8 @@
if (fpr_index_ % 2 == 0) {
fpr_index_ = std::max(fpr_double_index_, fpr_index_);
}
+ } else if (kQuickSkipOddFpRegisters) {
+ IncFprIndex();
}
}
}
@@ -483,8 +495,9 @@
case Primitive::kPrimLong:
if (kQuickSoftFloatAbi || (cur_type_ == Primitive::kPrimLong)) {
if (cur_type_ == Primitive::kPrimLong && kAlignPairRegister && gpr_index_ == 0) {
- // Currently, this is only for ARM, where the first available parameter register
- // is R1. So we skip it, and use R2 instead.
+ // Currently, this is only for ARM and MIPS, where the first available parameter
+ // register is R1 (on ARM) or A1 (on MIPS). So we skip it, and use R2 (on ARM) or
+ // A2 (on MIPS) instead.
IncGprIndex();
}
is_split_long_or_double_ = (GetBytesPerGprSpillLocation(kRuntimeISA) == 4) &&