1 /* 2 * =========================================================================== 3 * Common subroutines and data 4 * =========================================================================== 5 */ 6 7 .text 8 .align 2 9 10 /* 11 * We've detected a condition that will result in an exception, but the exception 12 * has not yet been thrown. Just bail out to the reference interpreter to deal with it. 13 * TUNING: for consistency, we may want to just go ahead and handle these here. 14 */ 15 common_errDivideByZero: 16 EXPORT_PC() 17 #if MTERP_LOGGING 18 move a0, rSELF 19 addu a1, rFP, OFF_FP_SHADOWFRAME 20 JAL(MterpLogDivideByZeroException) 21 #endif 22 b MterpCommonFallback 23 24 common_errArrayIndex: 25 EXPORT_PC() 26 #if MTERP_LOGGING 27 move a0, rSELF 28 addu a1, rFP, OFF_FP_SHADOWFRAME 29 JAL(MterpLogArrayIndexException) 30 #endif 31 b MterpCommonFallback 32 33 common_errNegativeArraySize: 34 EXPORT_PC() 35 #if MTERP_LOGGING 36 move a0, rSELF 37 addu a1, rFP, OFF_FP_SHADOWFRAME 38 JAL(MterpLogNegativeArraySizeException) 39 #endif 40 b MterpCommonFallback 41 42 common_errNoSuchMethod: 43 EXPORT_PC() 44 #if MTERP_LOGGING 45 move a0, rSELF 46 addu a1, rFP, OFF_FP_SHADOWFRAME 47 JAL(MterpLogNoSuchMethodException) 48 #endif 49 b MterpCommonFallback 50 51 common_errNullObject: 52 EXPORT_PC() 53 #if MTERP_LOGGING 54 move a0, rSELF 55 addu a1, rFP, OFF_FP_SHADOWFRAME 56 JAL(MterpLogNullObjectException) 57 #endif 58 b MterpCommonFallback 59 60 common_exceptionThrown: 61 EXPORT_PC() 62 #if MTERP_LOGGING 63 move a0, rSELF 64 addu a1, rFP, OFF_FP_SHADOWFRAME 65 JAL(MterpLogExceptionThrownException) 66 #endif 67 b MterpCommonFallback 68 69 MterpSuspendFallback: 70 EXPORT_PC() 71 #if MTERP_LOGGING 72 move a0, rSELF 73 addu a1, rFP, OFF_FP_SHADOWFRAME 74 lw a2, THREAD_FLAGS_OFFSET(rSELF) 75 JAL(MterpLogSuspendFallback) 76 #endif 77 b MterpCommonFallback 78 79 /* 80 * If we're here, something is out of the ordinary. If there is a pending 81 * exception, handle it. Otherwise, roll back and retry with the reference 82 * interpreter. 83 */ 84 MterpPossibleException: 85 lw a0, THREAD_EXCEPTION_OFFSET(rSELF) 86 beqz a0, MterpFallback # If exception, fall back to reference interpreter. 87 /* intentional fallthrough - handle pending exception. */ 88 /* 89 * On return from a runtime helper routine, we've found a pending exception. 90 * Can we handle it here - or need to bail out to caller? 91 * 92 */ 93 MterpException: 94 move a0, rSELF 95 addu a1, rFP, OFF_FP_SHADOWFRAME 96 JAL(MterpHandleException) # (self, shadow_frame) 97 beqz v0, MterpExceptionReturn # no local catch, back to caller. 98 lw a0, OFF_FP_CODE_ITEM(rFP) 99 lw a1, OFF_FP_DEX_PC(rFP) 100 lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) 101 addu rPC, a0, CODEITEM_INSNS_OFFSET 102 sll a1, a1, 1 103 addu rPC, rPC, a1 # generate new dex_pc_ptr 104 /* Do we need to switch interpreters? */ 105 JAL(MterpShouldSwitchInterpreters) 106 bnez v0, MterpFallback 107 /* resume execution at catch block */ 108 EXPORT_PC() 109 FETCH_INST() 110 GET_INST_OPCODE(t0) 111 GOTO_OPCODE(t0) 112 /* NOTE: no fallthrough */ 113 114 /* 115 * Check for suspend check request. Assumes rINST already loaded, rPC advanced and 116 * still needs to get the opcode and branch to it, and flags are in lr. 117 */ 118 MterpCheckSuspendAndContinue: 119 lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh rIBASE 120 and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) 121 bnez ra, 1f 122 GET_INST_OPCODE(t0) # extract opcode from rINST 123 GOTO_OPCODE(t0) # jump to next instruction 124 1: 125 EXPORT_PC() 126 move a0, rSELF 127 JAL(MterpSuspendCheck) # (self) 128 bnez v0, MterpFallback 129 GET_INST_OPCODE(t0) # extract opcode from rINST 130 GOTO_OPCODE(t0) # jump to next instruction 131 132 /* 133 * On-stack replacement has happened, and now we've returned from the compiled method. 134 */ 135 MterpOnStackReplacement: 136 #if MTERP_LOGGING 137 move a0, rSELF 138 addu a1, rFP, OFF_FP_SHADOWFRAME 139 move a2, rINST 140 JAL(MterpLogOSR) 141 #endif 142 li v0, 1 # Signal normal return 143 b MterpDone 144 145 /* 146 * Bail out to reference interpreter. 147 */ 148 MterpFallback: 149 EXPORT_PC() 150 #if MTERP_LOGGING 151 move a0, rSELF 152 addu a1, rFP, OFF_FP_SHADOWFRAME 153 JAL(MterpLogFallback) 154 #endif 155 MterpCommonFallback: 156 move v0, zero # signal retry with reference interpreter. 157 b MterpDone 158 /* 159 * We pushed some registers on the stack in ExecuteMterpImpl, then saved 160 * SP and LR. Here we restore SP, restore the registers, and then restore 161 * LR to PC. 162 * 163 * On entry: 164 * uint32_t* rFP (should still be live, pointer to base of vregs) 165 */ 166 MterpExceptionReturn: 167 li v0, 1 # signal return to caller. 168 b MterpDone 169 MterpReturn: 170 lw a2, OFF_FP_RESULT_REGISTER(rFP) 171 sw v0, 0(a2) 172 sw v1, 4(a2) 173 li v0, 1 # signal return to caller. 174 MterpDone: 175 /* Restore from the stack and return. Frame size = STACK_SIZE */ 176 STACK_LOAD_FULL() 177 jalr zero, ra 178 179 .end ExecuteMterpImpl 180