entry.S revision 5dfcc78af479937ba8dafceefd9b1931a88dfaaf
1/*
2 * Copyright (C) 2008 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 * Interpreter entry point.
18 */
19
20/*
21 * We don't have formal stack frames, so gdb scans upward in the code
22 * to find the start of the function (a label with the %function type),
23 * and then looks at the next few instructions to figure out what
24 * got pushed onto the stack.  From this it figures out how to restore
25 * the registers, including PC, for the previous stack frame.  If gdb
26 * sees a non-function label, it stops scanning, so either we need to
27 * have nothing but assembler-local labels between the entry point and
28 * the break, or we need to fake it out.
29 *
30 * When this is defined, we add some stuff to make gdb less confused.
31 */
32#define ASSIST_DEBUGGER 1
33
34    .text
35    .align  2
36    .global dvmMterpStdRun
37    .type   dvmMterpStdRun, %function
38
39/*
40 * On entry:
41 *  r0  Thread* self
42 *
43 * The return comes via a call to dvmMterpStdBail().
44 */
45dvmMterpStdRun:
46#define MTERP_ENTRY1 \
47    .save {r4-r10,fp,lr}; \
48    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
49#define MTERP_ENTRY2 \
50    .pad    #4; \
51    sub     sp, sp, #4                  @ align 64
52
53    .fnstart
54    MTERP_ENTRY1
55    MTERP_ENTRY2
56
57    /* save stack pointer, add magic word for debuggerd */
58    str     sp, [r0, #offThread_bailPtr]  @ save SP for eventual return
59
60    /* set up "named" registers, figure out entry point */
61    mov     rSELF, r0                   @ set rSELF
62    LOAD_PC_FP_FROM_SELF()              @ load rPC and rFP from "thread"
63    ldr     rIBASE, [rSELF, #offThread_curHandlerTable] @ set rIBASE
64
65#if defined(WITH_JIT)
66.LentryInstr:
67    /* Entry is always a possible trace start */
68    ldr     r0, [rSELF, #offThread_pJitProfTable]
69    FETCH_INST()
70    mov     r1, #0                      @ prepare the value for the new state
71    str     r1, [rSELF, #offThread_inJitCodeCache] @ back to the interp land
72    cmp     r0,#0                       @ is profiling disabled?
73#if !defined(WITH_SELF_VERIFICATION)
74    bne     common_updateProfile        @ profiling is enabled
75#else
76    ldr     r2, [rSELF, #offThread_shadowSpace] @ to find out the jit exit state
77    beq     1f                          @ profiling is disabled
78    ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
79    cmp     r3, #kSVSTraceSelect        @ hot trace following?
80    moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
81    beq     common_selectTrace          @ go build the trace
82    cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
83    beq     1f                          @ intrepret the next instruction
84    b       common_updateProfile        @ collect profiles
85#endif
861:
87    GET_INST_OPCODE(ip)
88    GOTO_OPCODE(ip)
89#else
90    /* start executing the instruction at rPC */
91    FETCH_INST()                        @ load rINST from rPC
92    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
93    GOTO_OPCODE(ip)                     @ jump to next instruction
94#endif
95
96.Lbad_arg:
97    ldr     r0, strBadEntryPoint
980:  add     r0, pc
99    @ r1 holds value of entryPoint
100    bl      printf
101    bl      dvmAbort
102    .fnend
103    .size   dvmMterpStdRun, .-dvmMterpStdRun
104
105strBadEntryPoint:
106    .word   PCREL_REF(.LstrBadEntryPoint,0b)
107
108    .global dvmMterpStdBail
109    .type   dvmMterpStdBail, %function
110
111/*
112 * Restore the stack pointer and PC from the save point established on entry.
113 * This is essentially the same as a longjmp, but should be cheaper.  The
114 * last instruction causes us to return to whoever called dvmMterpStdRun.
115 *
116 * We pushed some registers on the stack in dvmMterpStdRun, then saved
117 * SP and LR.  Here we restore SP, restore the registers, and then restore
118 * LR to PC.
119 *
120 * On entry:
121 *  r0  Thread* self
122 */
123dvmMterpStdBail:
124    ldr     sp, [r0, #offThread_bailPtr]    @ sp<- saved SP
125    add     sp, sp, #4                      @ un-align 64
126    ldmfd   sp!, {r4-r10,fp,pc}             @ restore 9 regs and return
127
128