/* Copyright (C) 2008 The Android Open Source Project
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */

   /*
    * File: OP_EXECUTE_INLINE.S
    *
    * Code: Executes a "native inline" instruction. Uses no substitutions.
    *
    * For: execute-inline
    *
    * Description: Executes a "native inline" instruction. This instruction
    *              is generated by the optimizer.
    *
    * Format:
    *
    * Syntax: vAA, {vC, vD, vE, vF}, inline@BBBB
    */

    FETCH       1, %ecx                 # %ecx<- BBBB
    movl        rGLUE, %eax             # %eax<- MterpGlue pointer
    addl        $$offGlue_retval, %eax  # %eax<- &glue->retval
    EXPORT_PC
    shr         $$4, rINST              # rINST<- B
    movl        %eax, -8(%esp)          # push parameter glue->retval
    lea         -24(%esp), %esp
    jmp         .L${opcode}_continue
%break

   /*
    * Extract args, call function.
    *  rINST = #of args (0-4)
    *  %ecx = call index
    */

.L${opcode}_continue:
    FETCH       2, %edx                 # %edx<- FEDC
    cmp         $$1, rINST              # determine number of arguments
    jl          0f                      # handle zero args
    je          1f                      # handle one arg
    cmp         $$3, rINST
    jl          2f                      # handle two args
    je          3f                      # handle three args
4:
    movl        %edx, rINST             # rINST<- FEDC
    and         $$0xf000, rINST         # isolate F
    shr         $$10, rINST
    movl        (rFP, rINST), rINST     # rINST<- vF
    movl        rINST, 12(%esp)         # push parameter vF
3:
    movl        %edx, rINST             # rINST<- FEDC
    and         $$0x0f00, rINST         # isolate E
    shr         $$6, rINST
    movl        (rFP, rINST), rINST     # rINST<- vE
    movl        rINST, 8(%esp)          # push parameter E
2:
    movl        %edx, rINST             # rINST<- FEDC
    and         $$0x00f0, rINST         # isolate D
    shr         $$2, rINST
    movl        (rFP, rINST), rINST     # rINST<- vD
    movl        rINST, 4(%esp)          # push parameter D
1:
    and         $$0x000f, %edx          # isolate C
    movl        (rFP, %edx, 4), %edx    # rINST<- vC
    movl        %edx, (%esp)            # push parameter C
0:
    shl         $$4, %ecx
    movl        $$gDvmInlineOpsTable, %eax # %eax<- address for table of inline operations
    call        *(%eax, %ecx)           # call function

    cmp         $$0, %eax               # check boolean result of inline
    FFETCH_ADV  3, %eax                 # %eax<- next instruction hi; fetch, advance
    lea         24(%esp), %esp          # update stack pointer
    je          common_exceptionThrown  # handle exception
    FGETOP_JMP  3, %eax                 # jump to next instruction; getop, jmp