Home | History | Annotate | Download | only in armv5te
      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  */
     45 dvmMterpStdRun:
     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
     86 1:
     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
     98 0:  add     r0, pc
     99     @ r1 holds value of entryPoint
    100     bl      printf
    101     bl      dvmAbort
    102     .fnend
    103     .size   dvmMterpStdRun, .-dvmMterpStdRun
    104 
    105 strBadEntryPoint:
    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  */
    123 dvmMterpStdBail:
    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