1%default { "isrange":"0", "routine":"NoRange" }
2%verify "executed"
3%verify "unknown method"
4    /*
5     * Handle a "super" method call.
6     *
7     * for: invoke-super, invoke-super/range
8     */
9    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
10    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
11    GET_GLUE(rINST_FULL)
12    movzwl    2(rPC),%eax               # eax<- BBBB
13    movl      offGlue_methodClassDex(rINST_FULL),%ecx # ecx<- pDvmDex
14    EXPORT_PC()
15    movl      offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
16    movl      (%ecx,%eax,4),%ecx        # ecx<- resolved baseMethod
17    movl      offGlue_method(rINST_FULL),%eax # eax<- method
18    movzwl    4(rPC),rINST_FULL         # rINST_FULL<- GFED or CCCC
19    .if       (!$isrange)
20    andl      $$0xf,rINST_FULL          # rINST_FULL<- D (or stays CCCC)
21    .endif
22    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- "this" ptr
23    testl     rINST_FULL,rINST_FULL     # null "this"?
24    je        common_errNullObject      # yes, throw
25    movl      offMethod_clazz(%eax),%eax # eax<- method->clazz
26    testl     %ecx,%ecx                 # already resolved?
27    jne       .L${opcode}_continue      # yes - go on
28    jmp       .L${opcode}_resolve
29%break
30
31    /*
32     * At this point:
33     *  ecx = resolved base method [r0]
34     *  eax = method->clazz [r9]
35     */
36.L${opcode}_continue:
37    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
38    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
39    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
40    jae     .L${opcode}_nsm           # method not present in superclass
41    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
42    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
43    jmp     common_invokeMethod${routine}
44
45
46    /* At this point:
47     * ecx = null (needs to be resolved base method)
48     * eax = method->clazz
49    */
50.L${opcode}_resolve:
51    SPILL_TMP(%eax)                     # method->clazz
52    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
53    movzwl  2(rPC),%ecx                 # ecx<- BBBB
54    movl    $$METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
55    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
56    SPILL(rPC)
57    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
58    UNSPILL(rPC)
59    testl   %eax,%eax                   # got null?
60    movl    %eax,%ecx                   # ecx<- resolved base method
61    UNSPILL_TMP(%eax)                   # restore method->clazz
62    jne     .L${opcode}_continue        # good to go - continue
63    jmp     common_exceptionThrown      # handle exception
64
65    /*
66     * Throw a NoSuchMethodError with the method name as the message.
67     *  ecx = resolved base method
68     */
69.L${opcode}_nsm:
70    movl    offMethod_name(%ecx),%eax
71    mov     %eax,OUT_ARG1(%esp)
72    jmp     common_errNoSuchMethod
73