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