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