1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * JNI method invocation. This is used to call a C/C++ JNI method. The 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * argument list has to be pushed onto the native stack according to 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * local calling conventions. 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This version supports the "old" ARM ABI. 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <machine/cpu-features.h> 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef __ARM_EABI__ 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFunction prototype: 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc, 33de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro const u4* argv, const char* signature, void* func, JValue* pReturn) 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe method we are calling has the form: 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return_type func(JNIEnv* pEnv, ClassObject* clazz, ...) 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project -or- 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return_type func(JNIEnv* pEnv, Object* this, ...) 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe receive a collection of 32-bit values which correspond to arguments from 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe interpreter (e.g. float occupies one, double occupies two). It's up to 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectus to convert these into local calling conventions. 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectARM ABI notes: 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr0-r3 hold first 4 args to a method 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr9 is given special treatment in some situations, but not for us 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr10 (sl) seems to be generally available 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr11 (fp) is used by gcc 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr12 (ip) is scratch -- not preserved across method calls 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr13 (sp) should be managed carefully in case a signal arrives 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr14 (lr) must be preserved 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr15 (pc) can be tinkered with directly 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr0 holds returns <= 4 bytes 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr0-r1 hold returns of 5-8 bytes, low word in r0 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectStack is "full descending". Only the arguments that don't fit in the first 4 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectregisters are placed on the stack. "sp" points at the first stacked argument 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(i.e. the 5th arg). 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectVFP: single-precision results in s0, double-precision results in d0. 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectHappily we don't have to do anything special here -- the args from the 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectinterpreter work directly as C/C++ args on ARM (with the "classic" ABI). 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/ 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .text 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .align 2 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .global dvmPlatformInvoke 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .type dvmPlatformInvoke, %function 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectOn entry: 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project r0 JNIEnv 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project r1 clazz (NULL for virtual method calls, non-NULL for static) 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project r2 arg info (ignored) 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project r3 argc 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [sp] argv 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [sp,#4] signature (ignored) 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [sp,#8] func 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [sp,#12] pReturn 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/ 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmPlatformInvoke: 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ Standard gcc stack frame setup. We don't need to push the original 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ sp or the current pc if "-fomit-frame-pointer" is in use for the 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ rest of the code. If we don't plan to use a debugger we can speed 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ this up a little. 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mov ip, sp 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stmfd sp!, {r4, r5, r6, fp, ip, lr, pc} 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sub fp, ip, #4 @ set up fp, same way gdb does 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ We need to push a variable number of arguments onto the stack. 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ Rather than keep a count and pop them off after, we just hold on to 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ the stack pointers. 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ In theory we don't need to keep sp -- we can do an ldmdb instead of 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ an ldmia -- but we're doing the gcc frame trick where we push the 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ pc on with stmfd and don't pop it off. 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mov r4, ip 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mov r5, sp 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ argc is already in a scratch register (r3). Put argv into one. Note 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ argv can't go into r0-r3 because we need to use it to load those. 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ldr ip, [r4, #0] @ ip <-- argv 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ Is this a static method? 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cmp r1, #0 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ No: set r1 to *argv++, and set argc--. 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ (r0=pEnv, r1=this) 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ldreq r1, [ip], #4 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project subeq r3, r3, #1 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ While we still have the use of r2/r3, copy excess args from argv 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ to the stack. We need to push the last item in argv first, and we 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ want the first two items in argv to end up in r2/r3. 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project subs r3, r3, #2 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ble .Lno_copy 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ If there are N args, we want to skip 0 and 1, and push (N-1)..2. We 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ have N-2 in r3. If we set argv=argv+1, we can count from N-2 to 1 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ inclusive and get the right set of args. 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project add r6, ip, #4 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project.Lcopy: 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ *--sp = argv[count] 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ldr r2, [r6, r3, lsl #2] 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project str r2, [sp, #-4]! 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project subs r3, r3, #1 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bne .Lcopy 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project.Lno_copy: 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ Load the last two args. These are coming out of the interpreted stack, 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ and the VM preserves an overflow region at the bottom, so it should be 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ safe to load two items out of argv even if we're at the end. 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ldr r2, [ip] 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ldr r3, [ip, #4] 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ Show time. Tuck the pc into lr and load the pc from the method 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ address supplied by the caller. The value for "pc" is offset by 8 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ due to instruction prefetching. 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef __ARM_HAVE_PC_INTERWORK 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mov lr, pc 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ldr pc, [r4, #8] 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ldr ip, [r4, #8] 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project blx ip 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ We're back, result is in r0 or (for long/double) r0-r1. 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ In theory, we need to use the "return type" arg to figure out what 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ we have and how to return it. However, unless we have an FPU, 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ all we need to do is copy r0-r1 into the JValue union. 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ldr ip, [r4, #12] 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stmia ip, {r0-r1} 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef __ARM_HAVE_PC_INTERWORK 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ Restore the registers we saved and return. Note this remaps stuff, 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ so that "sp" comes from "ip", "pc" comes from "lr", and the "pc" 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @ we pushed on evaporates when we restore "sp". 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ldmfd r5, {r4, r5, r6, fp, sp, pc} 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ldmfd r5, {r4, r5, r6, fp, sp, lr} 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bx lr 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif /*__ARM_EABI__*/ 174