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  MterpGlue* glue
     42  *
     43  * This function returns a boolean "changeInterp" value.  The return comes
     44  * via a call to dvmMterpStdBail().
     45  */
     46 dvmMterpStdRun:
     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
     91 1:
     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  */
    152 dvmMterpStdBail:
    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  */
    162 strBadEntryPoint:
    163     .word   .LstrBadEntryPoint
    164