summaryrefslogtreecommitdiff
path: root/vm/arch/sh/CallSH4ABI.S
diff options
context:
space:
mode:
Diffstat (limited to 'vm/arch/sh/CallSH4ABI.S')
-rw-r--r--vm/arch/sh/CallSH4ABI.S400
1 files changed, 400 insertions, 0 deletions
diff --git a/vm/arch/sh/CallSH4ABI.S b/vm/arch/sh/CallSH4ABI.S
new file mode 100644
index 0000000..f8b2ddc
--- /dev/null
+++ b/vm/arch/sh/CallSH4ABI.S
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+/*
+ * Invoking JNI native method via SH4 ABI.
+ * This inplementation follows the spec found in following URL.
+ * http://www.ecos.sourceware.org/docs-1.3.1/ref/gnupro-ref/sh/SH_ch01.html#pgfId-461254
+
+ * This version supports SH4A little endian.
+ */
+ .text
+ .align 4
+ .type dvmPlatformInvoke, #function
+ .globl dvmPlatformInvoke
+
+/*
+ * @param r4 void* pEnv (used as scrach after invoking method)
+ * @param r5 ClassObject* clazz
+ * @param r6 int argInfo
+ * @param r7 int argc
+ * @param r15[0] const u4 * argv
+ * @param r15[1] const char * shorty
+ * @param r15[2] void * func
+ * @param r15[3] JValue * pReturn
+ *
+ * @remark r0,r1 Scratch before invoking method.
+ * Return value after invoking method.
+ * @remark r2 shorty pointer
+ * @remark r3 argv pointer before invoking method.
+ * pReturn after invoking method.
+ * @remark r8-11 Don't touch.
+ * @remark r12 status of r5-7
+ * @remark r13 status of fr4-11
+ * @remark r14 Keep stack pointer.
+ */
+dvmPlatformInvoke:
+ ## save preserved regsiters
+ mov.l r14, @-r15
+ mov r15, r14
+ add #4, r14 /* r14 = original r15 = stack pointer */
+ mov.l r13, @-r15
+ mov.l r12, @-r15
+ sts.l pr, @-r15
+
+ # fetch arguments
+ mov.l @r14, r3 /* argv */
+ mov.l @(4,r14), r2 /* shorty for argumnets */
+ mov #1, r0 /* shorty's 1st byte specify ret value type. */
+ add r0, r2
+
+### initialize local variables
+
+ ## r12 ... status of r6, and r7
+ ## bit 1 << 0 : if r6 is available, it contains 1.
+ ## bit 1 << 1 : if r7 is available, it contains 1.
+ ## Note : r4 is always used to pass pEnv.
+ ## r5 is always used for clazz or object
+ mov #3, r12 /* b0000-0111 : r5-7 avialble. */
+
+ ## r13 ... status of fr4-fr11
+ ## bit 1 << 0 : if fr4 is available, it contains 1.
+ ## bit 1 << 1 : if fr5 is available, it contains 1.
+ ## ...
+ ## bit 1 << 7 : if fr11 is available, it contains 1.
+ mov #0xFF, r13 /* b1111-1111 : fr4-11 avialble. */
+
+### put arguments
+
+ ## ... keep pEnv in r4 as is.
+
+ ## check clazz
+ mov #0, r0
+ cmp/eq r0, r5
+ bf arg_loop /* if r5 has clazz, keep it as is */
+ mov.l @r3+, r5 /* put object arg in r5 */
+
+ ## other args
+arg_loop:
+one_arg_handled:
+ mov.b @r2+, r0
+ cmp/eq #0, r0 /* if (*shorty == '\0) */
+ bf process_one_arg
+ bra arg_end /* no argument left */
+ nop
+
+process_one_arg:
+
+ ## check arg type
+
+ cmp/eq #'F', r0
+ bt jfloat_arg
+
+ cmp/eq #'D', r0
+ bt jdouble_arg
+
+ cmp/eq #'J', r0
+ bt jlong_arg
+
+ ## other 32bit arg types
+ mov r12, r0
+ cmp/eq #0, r0
+ bt put_32bit_on_stack /* r6-7 not available */
+
+ tst #1, r0
+ bt j32_arg_1
+ mov.l @r3+, r6 /* put one arg in r6 */
+ mov #1, r0 /* r6 is not available now. */
+ not r0, r0
+ and r0, r12
+ bra one_arg_handled
+ nop
+j32_arg_1:
+ tst #2, r0
+ bt j32_arg_fatal_error
+ mov.l @r3+, r7 /* put one arg in r7 */
+ mov #2, r0 /* r7 is not available now. */
+ not r0, r0
+ and r0, r12
+ bra one_arg_handled
+ nop
+
+j32_arg_fatal_error:
+ bra j32_arg_fatal_error
+ nop
+
+jlong_arg:
+ mov r12, r0
+ cmp/eq #0, r0
+ bt put_64bit_on_stack /* r6-7 not available */
+
+ and #3, r0
+ cmp/eq #3, r0
+ bf put_64bit_on_stack /* consequent two registers not available. */
+ mov.l @r3+, r6 /* put one arg in r6 and r7 */
+ mov.l @r3+, r7
+ mov #3, r0 /* r6 and r7 are not available now. */
+ not r0, r0
+ and r0, r12
+ bra one_arg_handled
+ nop
+
+ # utility routines are placed here make short range jumps available.
+put_32bit_on_stack:
+ mov.l @r3+, r0
+ mov.l r0, @-r15
+ bra one_arg_handled
+ nop
+
+put_64bit_on_stack:
+ mov.l @r3+, r0
+ mov.l r0, @-r15 /* Pay attention that the endianness is */
+ mov.l @r3+, r0 /* once reversed. It is corrected when the */
+ mov.l r0, @-r15 /* arguments on stack are revesred before */
+ bra one_arg_handled /* jni call */
+ nop
+
+jdouble_arg:
+ mov r13, r0
+ cmp/eq #0, r0
+ bt put_64bit_on_stack /* fr4-11 not available */
+
+ and #3, r0
+ cmp/eq #3, r0
+ bf jdouble_arg_1
+
+ fmov.s @r3+, fr5 /* put one arg to drX */
+ fmov.s @r3+, fr4
+ mov #3, r0 /* fr4-frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jdouble_arg_1:
+ mov r13, r0
+ and #12, r0
+ cmp/eq #12, r0
+ bf jdouble_arg_2
+
+ fmov.s @r3+, fr7 /* put one arg to drX */
+ fmov.s @r3+, fr6
+ mov #15, r0 /* fr4-frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jdouble_arg_2:
+ mov r13, r0
+ and #48, r0
+ cmp/eq #48, r0
+ bf jdouble_arg_3
+ fmov.s @r3+, fr9 /* put one arg to drX */
+ fmov.s @r3+, fr8
+ mov #63, r0 /* fr4-frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jdouble_arg_3:
+ mov r13, r0
+ and #192, r0
+ cmp/eq #192, r0
+ bf put_64bit_on_stack
+ fmov.s @r3+, fr11 /* put one arg to drX */
+ fmov.s @r3+, fr10
+ mov #0, r13 /* fr4-fr11 all not available now. */
+ bra one_arg_handled
+ nop
+
+jfloat_arg:
+ mov r13, r0
+ cmp/eq #0, r0
+ bt put_32bit_on_stack /* fr4-11 not available */
+
+ tst #2, r0
+ bt jfloat_arg_1
+ fmov.s @r3+, fr5 /* put one arg to frX */
+ mov #2, r0 /* frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jfloat_arg_1:
+ tst #1, r0
+ bt jfloat_arg_2
+ fmov.s @r3+, fr4 /* put one arg to frX */
+ mov #1, r0 /* frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jfloat_arg_2:
+ tst #8, r0
+ bt jfloat_arg_3
+ fmov.s @r3+, fr7 /* put one arg to frX */
+ mov #8, r0 /* frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jfloat_arg_3:
+ tst #4, r0
+ bt jfloat_arg_4
+ fmov.s @r3+, fr6 /* put one arg to frX */
+ mov #4, r0 /* frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jfloat_arg_4:
+ tst #32, r0
+ bt jfloat_arg_5
+ fmov.s @r3+, fr9 /* put one arg to frX */
+ mov #32, r0 /* frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jfloat_arg_5:
+ tst #16, r0
+ bt jfloat_arg_6
+ fmov.s @r3+, fr8 /* put one arg to frX */
+ mov #16, r0 /* frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jfloat_arg_6:
+ tst #128, r0
+ bt jfloat_arg_7
+ fmov.s @r3+, fr11 /* put one arg to frX */
+ mov #127, r0 /* frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jfloat_arg_7:
+ tst #64, r0
+ bt jfloat_fatal_error
+ fmov.s @r3+, fr10 /* put one arg to frX */
+ mov #64, r0 /* frX not available now. */
+ not r0, r0
+ and r0, r13
+ bra one_arg_handled
+ nop
+
+jfloat_fatal_error:
+ bra jfloat_fatal_error:
+ nop
+
+arg_end:
+
+
+### reverse the variables on stack
+ mov r14, r12 /* points to first arg on stack */
+ add #-20, r12
+ mov r15, r13 /* points to last arg on stack */
+arg_rev_loop:
+ cmp/hs r12, r13 /* When r13 >= r12 (unsigned), 1->T */
+ bt arg_rev_end
+ mov.l @r12, r0
+ mov.l @r13, r1
+ mov.l r0, @r13
+ mov.l r1, @r12
+ add #-4, r12
+ add #4, r13
+ bra arg_rev_loop
+ nop
+
+arg_rev_end:
+
+### invoke the JNI function.
+
+ mov.l @(8,r14), r0
+ jsr @r0
+ nop
+
+### pass the return value
+
+ /*
+ * r0 and r1 keep return value.
+ */
+
+ ## fetch data
+ mov.l @(4,r14), r2 /* reload shorty */
+ mov.b @r2, r2 /* first byte specifyes return value type. */
+ mov.l @(12,r14), r3 /* pReturn */
+
+ ## check return value types
+
+ mov #'V', r4
+ cmp/eq r4, r2
+ bt end
+
+ mov #'F', r4
+ cmp/eq r4, r2
+ bt jfloat_ret
+
+ mov #'D', r4
+ cmp/eq r4, r2
+ bt jdouble_ret
+
+ mov #'J', r4
+ cmp/eq r4, r2
+ bt jlong_ret
+
+ ## fall-through for other 32 bit java types.
+
+ ## load return values
+j32_ret:
+ bra end
+ mov.l r0, @r3 /* delay slot */
+
+jfloat_ret:
+ bra end
+ fmov.s fr0, @r3 /* delay slot */
+
+jdouble_ret:
+ fmov.s fr1, @r3
+ mov #4, r0
+ bra end
+ fmov.s fr0, @(r0,r3) /* delay slot */
+
+jlong_ret:
+ mov.l r0, @r3
+ bra end
+ mov.l r1, @(4,r3) /* delay slot */
+
+end:
+ ## restore preserved registers
+ mov r14, r15
+ add #-16, r15
+ lds.l @r15+, pr
+ mov.l @r15+, r12
+ mov.l @r15+, r13
+ mov.l @r15+, r14
+
+ rts /* dvmPlatformInvoke returns void. */
+ nop