122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch   /* Copyright (C) 2008 The Android Open Source Project
222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *
322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * Licensed under the Apache License, Version 2.0 (the "License");
422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * you may not use this file except in compliance with the License.
522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * You may obtain a copy of the License at
622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *
722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * http://www.apache.org/licenses/LICENSE-2.0
822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *
922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * Unless required by applicable law or agreed to in writing, software
1022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * distributed under the License is distributed on an "AS IS" BASIS,
1122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * See the License for the specific language governing permissions and
1322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * limitations under the License.
1422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    */
1522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
1622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch   /*
1722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * File: OP_CHECK_CAST.S
1822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *
1922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * Code: Checks to see if a cast is allowed. Uses no substitutions.
2022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *
2122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * For: check-cast
2222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *
2322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * Description: Throw if the reference in the given register cannot be
2422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *              cast to the indicated type. The type must be a reference
2522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *              type (not a primitive type).
2622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *
2722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * Format: AA|op BBBB (21c)
2822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *
2922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * Syntax: op vAA, type@BBBB
3022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    */
3122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
3222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        rGLUE, %edx             # get MterpGlue pointer
3322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        offGlue_methodClassDex(%edx), %eax # %eax<- pDvmDex
3422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    GET_VREG    rINST                   # rINST<- vAA
3522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        offDvmDex_pResClasses(%eax), %eax # %eax<- pDvmDex->pResClasses
3622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    cmp         $$0, rINST              # check for null reference object
3722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    je          .L${opcode}_okay        # can always cast null object
3822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FETCH       1, %ecx                 # %ecx<- BBBB
3922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        (%eax, %ecx, 4), %ecx   # %ecx<- resolved class
4022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    cmp         $$0, %ecx               # check if classes is resolved before?
4122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    je          .L${opcode}_resolve     # resolve class
4222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    jmp         .L${opcode}_resolved    # continue
4322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch%break
4422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
4522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch.L${opcode}_resolved:
4622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    cmp         %ecx, offObject_clazz(rINST) # check for same class
4722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    jne         .L${opcode}_fullcheck   # not same class; do full check
4822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
4922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch.L${opcode}_okay:
5022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH      2                       # jump to next instruction
5122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
5222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch   /*
5322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *  Trivial test failed, need to perform full check.
5422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *  offObject_clazz(rINST) holds obj->clazz
5522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *  %ecx holds class resolved from BBBB
5622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *  rINST holds object
5722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    */
5822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
5922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch.L${opcode}_fullcheck:
6022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        offObject_clazz(rINST), %eax  # %eax<- obj->clazz
6122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        %eax, -12(%esp)         # push parameter obj->clazz
6222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        %ecx, -8(%esp)          # push parameter # push parameter resolved class
6322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    lea         -12(%esp), %esp
6422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    call        dvmInstanceofNonTrivial # call: (ClassObject* instance, ClassObject* clazz)
6522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                                        # return: int
6622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    lea         12(%esp), %esp
6722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    cmp         $$0, %eax               # failed?
6822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    jne         .L${opcode}_okay        # success
6922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
7022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch   /*
7122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * A cast has failed.  We need to throw a ClassCastException with the
7222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * class of the object that failed to be cast.
7322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    */
7422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
7522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    EXPORT_PC                           # we will throw an exception
766d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein#error BIT ROT!!!
776d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    /*
786d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein     * TODO: Code here needs to call dvmThrowClassCastException with two
796d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein     * arguments.
806d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein     */
816d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein#if 0
826d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    /* old obsolete code that called dvmThrowExceptionWithClassMessage */
8322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        $$.LstrClassCastExceptionPtr, -8(%esp) # push parameter message
8422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        offObject_clazz(rINST), rINST # rINST<- obj->clazz
8522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        offClassObject_descriptor(rINST), rINST # rINST<- obj->clazz->descriptor
8622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        rINST, -4(%esp)         # push parameter obj->clazz->descriptor
8722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    lea         -8(%esp), %esp
8822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    call        dvmThrowExceptionWithClassMessage # call: (const char* exceptionDescriptor,
8922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                                                  #       const char* messageDescriptor, Object* cause)
9022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                                                  # return: void
916d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein#endif
9222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    lea         8(%esp), %esp
9322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    jmp         common_exceptionThrown
9422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
9522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch   /*
9622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    * Resolution required.  This is the least-likely path.
9722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *
9822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *  rINST holds object
9922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    */
10022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
10122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch.L${opcode}_resolve:
10222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        offGlue_method(%edx), %eax # %eax<- glue->method
10322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FETCH       1, %ecx                 # %ecx holds BBBB
10422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    EXPORT_PC                           # in case we throw an exception
10522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        $$0, -8(%esp)           # push parameter false
10622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        offMethod_clazz(%eax), %eax # %eax<- glue->method->clazz
10722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        %ecx, -12(%esp)         # push parameter BBBB
10822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        %eax, -16(%esp)         # push parameter glue->method>clazz
10922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    lea         -16(%esp), %esp
11022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    call        dvmResolveClass         # resolve ClassObject pointer
11122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                                        # call: (const ClassObject* referrer, u4 classIdx,
11222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                                        #        bool fromUnverifiedConstant)
11322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                                        # return ClassObject*
11422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    lea         16(%esp), %esp
11522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    cmp         $$0, %eax               # check for null pointer
11622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    je          common_exceptionThrown  # handle excpetion
11722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    movl        %eax, %ecx              # %ecx<- resolved class
11822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    jmp         .L${opcode}_resolved
119