| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "asm_support_mips.S" |
| |
| .set noreorder |
| .balign 4 |
| |
| .extern artPortableProxyInvokeHandler |
| ENTRY art_portable_proxy_invoke_handler |
| GENERATE_GLOBAL_POINTER |
| # Fake callee save ref and args frame set up, note portable doesn't use callee save frames. |
| # TODO: just save the registers that are needed in artPortableProxyInvokeHandler. |
| addiu $sp, $sp, -64 |
| .cfi_adjust_cfa_offset 64 |
| 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, 12($sp) |
| .cfi_rel_offset 7, 12 |
| sw $a2, 8($sp) |
| .cfi_rel_offset 6, 8 |
| sw $a1, 4($sp) |
| .cfi_rel_offset 5, 4 |
| # Begin argument set up. |
| sw $a0, 0($sp) # place proxy method at bottom of frame |
| move $a2, rSELF # pass Thread::Current |
| jal artPortableProxyInvokeHandler # (Method* proxy method, receiver, Thread*, SP) |
| move $a3, $sp # pass $sp |
| lw $ra, 60($sp) # restore $ra |
| jr $ra |
| addiu $sp, $sp, 64 # pop frame |
| .cfi_adjust_cfa_offset -64 |
| END art_portable_proxy_invoke_handler |
| |
| /* |
| * Invocation stub for portable 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] = result type char |
| */ |
| ENTRY art_portable_invoke_stub |
| GENERATE_GLOBAL_POINTER |
| 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, 16 # create space for method pointer in frame |
| srl $t0, $t0, 3 # shift the frame size right 3 |
| sll $t0, $t0, 3 # shift the frame size left 3 to align to 16 bytes |
| subu $sp, $sp, $t0 # reserve stack space for argument array |
| addiu $a0, $sp, 4 # pass stack pointer + method ptr 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 $t9, METHOD_PORTABLE_CODE_OFFSET($a0) # get pointer to the code |
| jalr $t9 # call the method |
| sw $zero, 0($sp) # store NULL for method* 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 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' |
| sw $v0, 0($t0) # store the result |
| jr $ra |
| sw $v1, 4($t0) # store the other half of the result |
| 1: |
| s.s $f0, 0($t0) # store floating point result |
| jr $ra |
| s.s $f1, 4($t0) # store other half of floating point result |
| END art_portable_invoke_stub |
| |
| UNIMPLEMENTED art_portable_resolution_trampoline |
| UNIMPLEMENTED art_portable_to_interpreter_bridge |