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 78 bne common_updateProfile 79 GET_INST_OPCODE(ip) 80 GOTO_OPCODE(ip) 81 #else 82 /* start executing the instruction at rPC */ 83 FETCH_INST() @ load rINST from rPC 84 GET_INST_OPCODE(ip) @ extract opcode from rINST 85 GOTO_OPCODE(ip) @ jump to next instruction 86 #endif 87 88 .Lnot_instr: 89 cmp r1, #kInterpEntryReturn @ were we returning from a method? 90 beq common_returnFromMethod 91 92 .Lnot_return: 93 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 94 beq common_exceptionThrown 95 96 #if defined(WITH_JIT) 97 .Lnot_throw: 98 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 99 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 100 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 101 bne .Lbad_arg 102 cmp rPC,r2 103 bne .LentryInstr @ must have branched, don't resume 104 #if defined(WITH_SELF_VERIFICATION) 105 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 106 b jitSVShadowRunStart @ re-enter the translation after the 107 @ single-stepped instruction 108 @noreturn 109 #endif 110 mov r1, #kInterpEntryInstr 111 str r1, [rGLUE, #offGlue_entryPoint] 112 bx r10 @ re-enter the translation 113 #endif 114 115 .Lbad_arg: 116 ldr r0, strBadEntryPoint 117 @ r1 holds value of entryPoint 118 bl printf 119 bl dvmAbort 120 .fnend 121 122 123 .global dvmMterpStdBail 124 .type dvmMterpStdBail, %function 125 126 /* 127 * Restore the stack pointer and PC from the save point established on entry. 128 * This is essentially the same as a longjmp, but should be cheaper. The 129 * last instruction causes us to return to whoever called dvmMterpStdRun. 130 * 131 * We pushed some registers on the stack in dvmMterpStdRun, then saved 132 * SP and LR. Here we restore SP, restore the registers, and then restore 133 * LR to PC. 134 * 135 * On entry: 136 * r0 MterpGlue* glue 137 * r1 bool changeInterp 138 */ 139 dvmMterpStdBail: 140 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 141 mov r0, r1 @ return the changeInterp value 142 add sp, sp, #4 @ un-align 64 143 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 144 145 146 /* 147 * String references. 148 */ 149 strBadEntryPoint: 150 .word .LstrBadEntryPoint 151 152