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 */
48dvmPlatformInvoke:
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
90arg_loop:
91one_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
98process_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
124j32_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
134j32_arg_fatal_error:
135    bra     j32_arg_fatal_error
136    nop
137
138jlong_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.
155put_32bit_on_stack:
156    mov.l   @r3+, r0
157    mov.l   r0, @-r15
158    bra     one_arg_handled
159    nop
160
161put_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
169jdouble_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
186jdouble_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
200jdouble_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
213jdouble_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
224jfloat_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
238jfloat_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
248jfloat_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
258jfloat_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
268jfloat_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
278jfloat_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
288jfloat_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
298jfloat_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
308jfloat_fatal_error:
309    bra     jfloat_fatal_error:
310    nop
311
312arg_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 */
319arg_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
331arg_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
371j32_ret:
372    bra     end
373    mov.l   r0, @r3             /* delay slot */
374
375jfloat_ret:
376    bra     end
377    fmov.s  fr0, @r3            /* delay slot */
378
379jdouble_ret:
380    fmov.s  fr1, @r3
381    mov     #4, r0
382    bra     end
383    fmov.s  fr0, @(r0,r3)       /* delay slot */
384
385jlong_ret:
386    mov.l   r0, @r3
387    bra     end
388    mov.l   r1, @(4,r3)         /* delay slot */
389
390end:
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