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