Home | History | Annotate | Download | only in sh
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 /*
     17  * Invoking JNI native method via SH4 ABI.
     18  * This inplementation follows the spec found in following URL.
     19  * http://www.ecos.sourceware.org/docs-1.3.1/ref/gnupro-ref/sh/SH_ch01.html#pgfId-461254
     20 
     21  * This version supports SH4A little endian.
     22  */
     23     .text
     24     .align 4
     25     .type  dvmPlatformInvoke, #function
     26     .globl dvmPlatformInvoke
     27 
     28 /*
     29  * @param r4 void* pEnv  (used as scrach after invoking method)
     30  * @param r5 ClassObject* clazz
     31  * @param r6 int argInfo
     32  * @param r7 int argc
     33  * @param r15[0] const u4 * argv
     34  * @param r15[1] const char * shorty
     35  * @param r15[2] void * func
     36  * @param r15[3] JValue * pReturn
     37  *
     38  * @remark r0,r1  Scratch before invoking method.
     39  *                Return value after invoking method.
     40  * @remark r2  shorty pointer
     41  * @remark r3  argv pointer before invoking method.
     42  *             pReturn after invoking method.
     43  * @remark r8-11 Don't touch.
     44  * @remark r12 status of r5-7
     45  * @remark r13 status of fr4-11
     46  * @remark r14 Keep stack pointer.
     47  */
     48 dvmPlatformInvoke:
     49     ## save preserved regsiters
     50     mov.l   r14, @-r15
     51     mov     r15, r14
     52     add     #4, r14             /* r14 = original r15 = stack pointer */
     53     mov.l   r13, @-r15
     54     mov.l   r12, @-r15
     55     sts.l   pr, @-r15
     56 
     57     # fetch arguments
     58     mov.l   @r14, r3            /* argv */
     59     mov.l   @(4,r14), r2        /* shorty for argumnets */
     60     mov     #1, r0              /* shorty's 1st byte specify ret value type. */
     61     add     r0, r2
     62 
     63 ### initialize local variables
     64 
     65     ## r12 ... status of r6, and r7
     66     ##          bit 1 << 0 : if r6 is available, it contains 1.
     67     ##          bit 1 << 1 : if r7 is available, it contains 1.
     68     ##  Note : r4 is always used to pass pEnv.
     69     ##         r5 is always used for clazz or object
     70     mov     #3, r12             /* b0000-0111 : r5-7 avialble. */
     71 
     72     ## r13 ... status of fr4-fr11
     73     ##          bit 1 << 0 : if fr4 is available, it contains 1.
     74     ##          bit 1 << 1 : if fr5 is available, it contains 1.
     75     ##      ...
     76     ##          bit 1 << 7 : if fr11 is available, it contains 1.
     77     mov     #0xFF, r13          /* b1111-1111 : fr4-11 avialble. */
     78 
     79 ### put arguments
     80 
     81     ## ... keep pEnv in r4 as is.
     82 
     83     ## check clazz
     84     mov     #0, r0
     85     cmp/eq  r0, r5
     86     bf      arg_loop            /* if r5 has clazz, keep it as is */
     87     mov.l   @r3+, r5            /* put object arg in r5 */
     88 
     89     ## other args
     90 arg_loop:
     91 one_arg_handled:
     92     mov.b   @r2+, r0
     93     cmp/eq  #0, r0              /* if (*shorty == '\0) */
     94     bf      process_one_arg
     95     bra     arg_end             /* no argument left */
     96     nop
     97 
     98 process_one_arg:
     99 
    100     ## check arg type
    101 
    102     cmp/eq  #'F', r0
    103     bt      jfloat_arg
    104 
    105     cmp/eq  #'D', r0
    106     bt      jdouble_arg
    107 
    108     cmp/eq  #'J', r0
    109     bt      jlong_arg
    110 
    111     ## other 32bit arg types
    112     mov     r12, r0
    113     cmp/eq  #0, r0
    114     bt      put_32bit_on_stack  /* r6-7 not available */
    115 
    116     tst     #1, r0
    117     bt      j32_arg_1
    118     mov.l   @r3+, r6            /* put one arg in r6 */
    119     mov     #1, r0              /* r6 is not available now. */
    120     not     r0, r0
    121     and     r0, r12
    122     bra     one_arg_handled
    123     nop
    124 j32_arg_1:
    125     tst     #2, r0
    126     bt      j32_arg_fatal_error
    127     mov.l   @r3+, r7            /* put one arg in r7 */
    128     mov     #2, r0              /* r7 is not available now. */
    129     not     r0, r0
    130     and     r0, r12
    131     bra     one_arg_handled
    132     nop
    133 
    134 j32_arg_fatal_error:
    135     bra     j32_arg_fatal_error
    136     nop
    137 
    138 jlong_arg:
    139     mov     r12, r0
    140     cmp/eq  #0, r0
    141     bt      put_64bit_on_stack  /* r6-7 not available */
    142 
    143     and     #3, r0
    144     cmp/eq  #3, r0
    145     bf      put_64bit_on_stack  /* consequent two registers not available. */
    146     mov.l   @r3+, r6            /* put one arg in r6 and r7 */
    147     mov.l   @r3+, r7
    148     mov     #3, r0              /* r6 and r7 are not available now. */
    149     not     r0, r0
    150     and     r0, r12
    151     bra     one_arg_handled
    152     nop
    153 
    154     # utility routines are placed here make short range jumps available.
    155 put_32bit_on_stack:
    156     mov.l   @r3+, r0
    157     mov.l   r0, @-r15
    158     bra     one_arg_handled
    159     nop
    160 
    161 put_64bit_on_stack:
    162     mov.l   @r3+, r0
    163     mov.l   r0, @-r15           /* Pay attention that the endianness is */
    164     mov.l   @r3+, r0            /* once reversed.  It is corrected when the */
    165     mov.l   r0, @-r15           /* arguments on stack are revesred before */
    166     bra     one_arg_handled     /* jni call */
    167     nop
    168 
    169 jdouble_arg:
    170     mov     r13, r0
    171     cmp/eq  #0, r0
    172     bt      put_64bit_on_stack  /* fr4-11 not available */
    173 
    174     and     #3, r0
    175     cmp/eq  #3, r0
    176     bf      jdouble_arg_1
    177 
    178     fmov.s  @r3+, fr5           /* put one arg to drX */
    179     fmov.s  @r3+, fr4
    180     mov     #3, r0              /* fr4-frX not available now. */
    181     not     r0, r0
    182     and     r0, r13
    183     bra     one_arg_handled
    184     nop
    185 
    186 jdouble_arg_1:
    187     mov     r13, r0
    188     and     #12, r0
    189     cmp/eq  #12, r0
    190     bf      jdouble_arg_2
    191 
    192     fmov.s  @r3+, fr7           /* put one arg to drX */
    193     fmov.s  @r3+, fr6
    194     mov     #15, r0             /* fr4-frX not available now. */
    195     not     r0, r0
    196     and     r0, r13
    197     bra     one_arg_handled
    198     nop
    199 
    200 jdouble_arg_2:
    201     mov     r13, r0
    202     and     #48, r0
    203     cmp/eq  #48, r0
    204     bf      jdouble_arg_3
    205     fmov.s  @r3+, fr9           /* put one arg to drX */
    206     fmov.s  @r3+, fr8
    207     mov     #63, r0             /* fr4-frX not available now. */
    208     not     r0, r0
    209     and     r0, r13
    210     bra     one_arg_handled
    211     nop
    212 
    213 jdouble_arg_3:
    214     mov     r13, r0
    215     and     #192, r0
    216     cmp/eq  #192, r0
    217     bf      put_64bit_on_stack
    218     fmov.s  @r3+, fr11          /* put one arg to drX */
    219     fmov.s  @r3+, fr10
    220     mov     #0, r13             /* fr4-fr11 all not available now. */
    221     bra     one_arg_handled
    222     nop
    223 
    224 jfloat_arg:
    225     mov     r13, r0
    226     cmp/eq  #0, r0
    227     bt      put_32bit_on_stack  /* fr4-11 not available */
    228 
    229     tst     #2, r0
    230     bt      jfloat_arg_1
    231     fmov.s  @r3+, fr5           /* put one arg to frX */
    232     mov     #2, r0              /* frX not available now. */
    233     not     r0, r0
    234     and     r0, r13
    235     bra     one_arg_handled
    236     nop
    237 
    238 jfloat_arg_1:
    239     tst     #1, r0
    240     bt      jfloat_arg_2
    241     fmov.s  @r3+, fr4           /* put one arg to frX */
    242     mov     #1, r0              /* frX not available now. */
    243     not     r0, r0
    244     and     r0, r13
    245     bra     one_arg_handled
    246     nop
    247 
    248 jfloat_arg_2:
    249     tst     #8, r0
    250     bt      jfloat_arg_3
    251     fmov.s  @r3+, fr7           /* put one arg to frX */
    252     mov     #8, r0              /* frX not available now. */
    253     not     r0, r0
    254     and     r0, r13
    255     bra     one_arg_handled
    256     nop
    257 
    258 jfloat_arg_3:
    259     tst     #4, r0
    260     bt      jfloat_arg_4
    261     fmov.s  @r3+, fr6           /* put one arg to frX */
    262     mov     #4, r0              /* frX not available now. */
    263     not     r0, r0
    264     and     r0, r13
    265     bra     one_arg_handled
    266     nop
    267 
    268 jfloat_arg_4:
    269     tst     #32, r0
    270     bt      jfloat_arg_5
    271     fmov.s  @r3+, fr9           /* put one arg to frX */
    272     mov     #32, r0             /* frX not available now. */
    273     not     r0, r0
    274     and     r0, r13
    275     bra     one_arg_handled
    276     nop
    277 
    278 jfloat_arg_5:
    279     tst     #16, r0
    280     bt      jfloat_arg_6
    281     fmov.s  @r3+, fr8           /* put one arg to frX */
    282     mov     #16, r0             /* frX not available now. */
    283     not     r0, r0
    284     and     r0, r13
    285     bra     one_arg_handled
    286     nop
    287 
    288 jfloat_arg_6:
    289     tst     #128, r0
    290     bt      jfloat_arg_7
    291     fmov.s  @r3+, fr11          /* put one arg to frX */
    292     mov     #127, r0            /* frX not available now. */
    293     not     r0, r0
    294     and     r0, r13
    295     bra     one_arg_handled
    296     nop
    297 
    298 jfloat_arg_7:
    299     tst     #64, r0
    300     bt      jfloat_fatal_error
    301     fmov.s  @r3+, fr10          /* put one arg to frX */
    302     mov     #64, r0             /* frX not available now. */
    303     not     r0, r0
    304     and     r0, r13
    305     bra     one_arg_handled
    306     nop
    307 
    308 jfloat_fatal_error:
    309     bra     jfloat_fatal_error:
    310     nop
    311 
    312 arg_end:
    313 
    314 
    315 ### reverse the variables on stack
    316     mov     r14, r12            /* points to first arg on stack */
    317     add     #-20, r12
    318     mov     r15, r13            /* points to last arg on stack */
    319 arg_rev_loop:
    320     cmp/hs  r12, r13            /* When r13 >= r12 (unsigned), 1->T */
    321     bt      arg_rev_end
    322     mov.l   @r12, r0
    323     mov.l   @r13, r1
    324     mov.l   r0, @r13
    325     mov.l   r1, @r12
    326     add     #-4, r12
    327     add     #4, r13
    328     bra     arg_rev_loop
    329     nop
    330 
    331 arg_rev_end:
    332 
    333 ### invoke the JNI function.
    334 
    335     mov.l   @(8,r14), r0
    336     jsr     @r0
    337     nop
    338 
    339 ### pass the return value
    340 
    341     /*
    342      * r0 and r1 keep return value.
    343      */
    344 
    345     ## fetch data
    346     mov.l   @(4,r14), r2        /* reload shorty */
    347     mov.b   @r2, r2             /* first byte specifyes return value type. */
    348     mov.l   @(12,r14), r3       /* pReturn */
    349 
    350     ## check return value types
    351 
    352     mov     #'V', r4
    353     cmp/eq  r4, r2
    354     bt      end
    355 
    356     mov     #'F', r4
    357     cmp/eq  r4, r2
    358     bt      jfloat_ret
    359 
    360     mov     #'D', r4
    361     cmp/eq  r4, r2
    362     bt      jdouble_ret
    363 
    364     mov     #'J', r4
    365     cmp/eq  r4, r2
    366     bt      jlong_ret
    367 
    368     ## fall-through for other 32 bit java types.
    369 
    370     ## load return values
    371 j32_ret:
    372     bra     end
    373     mov.l   r0, @r3             /* delay slot */
    374 
    375 jfloat_ret:
    376     bra     end
    377     fmov.s  fr0, @r3            /* delay slot */
    378 
    379 jdouble_ret:
    380     fmov.s  fr1, @r3
    381     mov     #4, r0
    382     bra     end
    383     fmov.s  fr0, @(r0,r3)       /* delay slot */
    384 
    385 jlong_ret:
    386     mov.l   r0, @r3
    387     bra     end
    388     mov.l   r1, @(4,r3)         /* delay slot */
    389 
    390 end:
    391     ## restore preserved registers
    392     mov     r14, r15
    393     add     #-16, r15
    394     lds.l   @r15+, pr
    395     mov.l   @r15+, r12
    396     mov.l   @r15+, r13
    397     mov.l   @r15+, r14
    398 
    399     rts                         /* dvmPlatformInvoke returns void. */
    400     nop
    401