1%verify "executed"
2%verify "null object"
3%verify "class cast exception thrown, with correct class name"
4%verify "class cast exception not thrown on same class"
5%verify "class cast exception not thrown on subclass"
6%verify "class not resolved"
7%verify "class already resolved"
8    /*
9     * Check to see if a cast from one class to another is allowed.
10     */
11    /* check-cast vAA, class@BBBB */
12    movl      rSELF,%ecx
13    GET_VREG_R  rINST,rINST             # rINST<- vAA (object)
14    movzwl    2(rPC),%eax               # eax<- BBBB
15    movl      offThread_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
16    testl     rINST,rINST               # is oject null?
17    movl      offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
18    je        .L${opcode}_okay          # null obj, cast always succeeds
19    movl      (%ecx,%eax,4),%eax        # eax<- resolved class
20    movl      offObject_clazz(rINST),%ecx # ecx<- obj->clazz
21    testl     %eax,%eax                 # have we resolved this before?
22    je        .L${opcode}_resolve       # no, go do it now
23.L${opcode}_resolved:
24    cmpl      %eax,%ecx                 # same class (trivial success)?
25    jne       .L${opcode}_fullcheck     # no, do full check
26.L${opcode}_okay:
27    FETCH_INST_OPCODE 2 %ecx
28    ADVANCE_PC 2
29    GOTO_NEXT_R %ecx
30
31    /*
32     * Trivial test failed, need to perform full check.  This is common.
33     *  ecx holds obj->clazz
34     *  eax holds class resolved from BBBB
35     *  rINST holds object
36     */
37.L${opcode}_fullcheck:
38    movl    %eax,sReg0                 # we'll need the desired class on failure
39    movl    %eax,OUT_ARG1(%esp)
40    movl    %ecx,OUT_ARG0(%esp)
41    SPILL(rIBASE)
42    call    dvmInstanceofNonTrivial    # eax<- boolean result
43    UNSPILL(rIBASE)
44    testl   %eax,%eax                  # failed?
45    jne     .L${opcode}_okay           # no, success
46
47    # A cast has failed.  We need to throw a ClassCastException.
48    EXPORT_PC
49    movl    offObject_clazz(rINST),%eax
50    movl    %eax,OUT_ARG0(%esp)                 # arg0<- obj->clazz
51    movl    sReg0,%ecx
52    movl    %ecx,OUT_ARG1(%esp)                 # arg1<- desired class
53    call    dvmThrowClassCastException
54    jmp     common_exceptionThrown
55
56    /*
57     * Resolution required.  This is the least-likely path, and we're
58     * going to have to recreate some data.
59     *
60     *  rINST holds object
61     */
62.L${opcode}_resolve:
63    movl    rSELF,%ecx
64    EXPORT_PC
65    movzwl  2(rPC),%eax                # eax<- BBBB
66    movl    offThread_method(%ecx),%ecx  # ecx<- self->method
67    movl    %eax,OUT_ARG1(%esp)        # arg1<- BBBB
68    movl    offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz
69    movl    $$0,OUT_ARG2(%esp)         # arg2<- false
70    movl    %ecx,OUT_ARG0(%esp)        # arg0<- method->clazz
71    SPILL(rIBASE)
72    call    dvmResolveClass            # eax<- resolved ClassObject ptr
73    UNSPILL(rIBASE)
74    testl   %eax,%eax                  # got null?
75    je      common_exceptionThrown     # yes, handle exception
76    movl    offObject_clazz(rINST),%ecx  # ecx<- obj->clazz
77    jmp     .L${opcode}_resolved       # pick up where we left off
78