1 %verify "executed" 2 %verify "exception handled" 3 /* 4 * Execute a "native inline" instruction. 5 * 6 * We need to call an InlineOp4Func: 7 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 8 * 9 * The first four args are in a0-a3, pointer to return value storage 10 * is on the stack. The function's return value is a flag that tells 11 * us if an exception was thrown. 12 * 13 * TUNING: could maintain two tables, pointer in Thread and 14 * swap if profiler/debuggger active. 15 */ 16 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 17 lhu a2, offThread_subMode(rSELF) 18 FETCH(rBIX, 1) # rBIX <- BBBB 19 EXPORT_PC() # can throw 20 and a2, kSubModeDebugProfile # Any going on? 21 bnez a2, .L${opcode}_debugmode # yes - take slow path 22 .L${opcode}_resume: 23 addu a1, rSELF, offThread_retval # a1 <- &self->retval 24 GET_OPB(a0) # a0 <- B 25 # Stack should have 16/20 available 26 sw a1, STACK_OFFSET_ARG04(sp) # push &self->retval 27 BAL(.L${opcode}_continue) # make call; will return after 28 lw gp, STACK_OFFSET_GP(sp) # restore gp 29 # test boolean result of inline 30 beqz v0, common_exceptionThrown # returned false, handle exception 31 FETCH_ADVANCE_INST(3) # advance rPC, load rINST 32 GET_INST_OPCODE(t0) # extract opcode from rINST 33 GOTO_OPCODE(t0) # jump to next instruction 34 %break 35 36 /* 37 * Extract args, call function. 38 * a0 = #of args (0-4) 39 * rBIX = call index 40 * 41 * Other ideas: 42 * - Use a jump table from the main piece to jump directly into the 43 * AND/LW pairs. Costs a data load, saves a branch. 44 * - Have five separate pieces that do the loading, so we can work the 45 * interleave a little better. Increases code size. 46 */ 47 .L${opcode}_continue: 48 FETCH(rINST, 2) # rINST <- FEDC 49 beq a0, 0, 0f 50 beq a0, 1, 1f 51 beq a0, 2, 2f 52 beq a0, 3, 3f 53 beq a0, 4, 4f 54 JAL(common_abort) # too many arguments 55 56 4: 57 and t0, rINST, 0xf000 # isolate F 58 ESRN(t1, rFP, t0, 10) 59 lw a3, 0(t1) # a3 <- vF (shift right 12, left 2) 60 3: 61 and t0, rINST, 0x0f00 # isolate E 62 ESRN(t1, rFP, t0, 6) 63 lw a2, 0(t1) # a2 <- vE 64 2: 65 and t0, rINST, 0x00f0 # isolate D 66 ESRN(t1, rFP, t0, 2) 67 lw a1, 0(t1) # a1 <- vD 68 1: 69 and t0, rINST, 0x000f # isolate C 70 EASN(t1, rFP, t0, 2) 71 lw a0, 0(t1) # a0 <- vC 72 0: 73 la rINST, gDvmInlineOpsTable # table of InlineOperation 74 EAS4(t1, rINST, rBIX) # t1 <- rINST + rBIX<<4 75 lw t9, 0(t1) 76 jr t9 # sizeof=16, "func" is first entry 77 # (not reached) 78 79 /* 80 * We're debugging or profiling. 81 * rBIX: opIndex 82 */ 83 .L${opcode}_debugmode: 84 move a0, rBIX 85 JAL(dvmResolveInlineNative) 86 beqz v0, .L${opcode}_resume # did it resolve? no, just move on 87 move rOBJ, v0 # remember method 88 move a0, v0 89 move a1, rSELF 90 JAL(dvmFastMethodTraceEnter) # (method, self) 91 addu a1, rSELF, offThread_retval # a1<- &self->retval 92 GET_OPB(a0) # a0 <- B 93 # Stack should have 16/20 available 94 sw a1, STACK_OFFSET_ARG04(sp) # push &self->retval 95 BAL(.L${opcode}_continue) # make call; will return after 96 lw gp, STACK_OFFSET_GP(sp) # restore gp 97 move rINST, v0 # save result of inline 98 move a0, rOBJ # a0<- method 99 move a1, rSELF # a1<- self 100 JAL(dvmFastNativeMethodTraceExit) # (method, self) 101 beqz rINST, common_exceptionThrown # returned false, handle exception 102 FETCH_ADVANCE_INST(3) # advance rPC, load rINST 103 GET_INST_OPCODE(t0) # extract opcode from rINST 104 GOTO_OPCODE(t0) # jump to next instruction 105