OP_EXECUTE_INLINE.S revision a8b91c52fd8a90b784835dfe1f8898035266c4dd
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
564:
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)
603:
61    and       t0, rINST, 0x0f00            #  isolate E
62    ESRN(t1, rFP, t0, 6)
63    lw        a2, 0(t1)                    #  a2 <- vE
642:
65    and       t0, rINST, 0x00f0            #  isolate D
66    ESRN(t1, rFP, t0, 2)
67    lw        a1, 0(t1)                    #  a1 <- vD
681:
69    and       t0, rINST, 0x000f            #  isolate C
70    EASN(t1, rFP, t0, 2)
71    lw        a0, 0(t1)                    #  a0 <- vC
720:
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, 16(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(dvmFastMethodTraceExit)            #  (method, self)
101    beqz      v0, 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