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  MterpGlue* glue
42 *
43 * This function returns a boolean "changeInterp" value.  The return comes
44 * via a call to dvmMterpStdBail().
45 */
46dvmMterpStdRun:
47#define MTERP_ENTRY1 \
48    .save {r4-r10,fp,lr}; \
49    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
50#define MTERP_ENTRY2 \
51    .pad    #4; \
52    sub     sp, sp, #4                  @ align 64
53
54    .fnstart
55    MTERP_ENTRY1
56    MTERP_ENTRY2
57
58    /* save stack pointer, add magic word for debuggerd */
59    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
60
61    /* set up "named" registers, figure out entry point */
62    mov     rGLUE, r0                   @ set rGLUE
63    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
64    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
65    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
66    cmp     r1, #kInterpEntryInstr      @ usual case?
67    bne     .Lnot_instr                 @ no, handle it
68
69#if defined(WITH_JIT)
70.LentryInstr:
71    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
72    /* Entry is always a possible trace start */
73    GET_JIT_PROF_TABLE(r0)
74    FETCH_INST()
75    mov     r1, #0                      @ prepare the value for the new state
76    str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
77    cmp     r0,#0                       @ is profiling disabled?
78#if !defined(WITH_SELF_VERIFICATION)
79    bne     common_updateProfile        @ profiling is enabled
80#else
81    ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
82    beq     1f                          @ profiling is disabled
83    ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
84    cmp     r3, #kSVSTraceSelect        @ hot trace following?
85    moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
86    beq     common_selectTrace          @ go build the trace
87    cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
88    beq     1f                          @ intrepret the next instruction
89    b       common_updateProfile        @ collect profiles
90#endif
911:
92    GET_INST_OPCODE(ip)
93    GOTO_OPCODE(ip)
94#else
95    /* start executing the instruction at rPC */
96    FETCH_INST()                        @ load rINST from rPC
97    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
98    GOTO_OPCODE(ip)                     @ jump to next instruction
99#endif
100
101.Lnot_instr:
102    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
103    beq     common_returnFromMethod
104
105.Lnot_return:
106    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
107    beq     common_exceptionThrown
108
109#if defined(WITH_JIT)
110.Lnot_throw:
111    ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
112    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
113    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
114    bne     .Lbad_arg
115    cmp     rPC,r2
116    bne     .LentryInstr                @ must have branched, don't resume
117#if defined(WITH_SELF_VERIFICATION)
118    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
119    b       jitSVShadowRunStart         @ re-enter the translation after the
120                                        @ single-stepped instruction
121    @noreturn
122#endif
123    mov     r1, #kInterpEntryInstr
124    str     r1, [rGLUE, #offGlue_entryPoint]
125    bx      r10                         @ re-enter the translation
126#endif
127
128.Lbad_arg:
129    ldr     r0, strBadEntryPoint
130    @ r1 holds value of entryPoint
131    bl      printf
132    bl      dvmAbort
133    .fnend
134
135
136    .global dvmMterpStdBail
137    .type   dvmMterpStdBail, %function
138
139/*
140 * Restore the stack pointer and PC from the save point established on entry.
141 * This is essentially the same as a longjmp, but should be cheaper.  The
142 * last instruction causes us to return to whoever called dvmMterpStdRun.
143 *
144 * We pushed some registers on the stack in dvmMterpStdRun, then saved
145 * SP and LR.  Here we restore SP, restore the registers, and then restore
146 * LR to PC.
147 *
148 * On entry:
149 *  r0  MterpGlue* glue
150 *  r1  bool changeInterp
151 */
152dvmMterpStdBail:
153    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
154    mov     r0, r1                          @ return the changeInterp value
155    add     sp, sp, #4                      @ un-align 64
156    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
157
158
159/*
160 * String references.
161 */
162strBadEntryPoint:
163    .word   .LstrBadEntryPoint
164