/*
 * 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.
 */


    .text
    .global dvmMterpStdRun
    .type   dvmMterpStdRun, %function
/*
 * bool dvmMterpStdRun(Thread* self)
 *
 * Interpreter entry point.  Returns changeInterp.
 *
 */
dvmMterpStdRun:
    push    %ebp                 # save caller base pointer
    movl    %esp, %ebp           # set our %ebp
    movl    rSELF, %ecx          # get incoming rSELF
/*
 * At this point we've allocated one slot on the stack
 * via push and stack is 8-byte aligned.  Allocate space
 * for 9 spill slots, 4 local slots, 5 arg slots to bring
 * us to 16-byte alignment
 */
    subl    $$(FRAME_SIZE-4), %esp

/* Spill callee save regs */
    movl    %edi,EDI_SPILL(%ebp)
    movl    %esi,ESI_SPILL(%ebp)
    movl    %ebx,EBX_SPILL(%ebp)

/* Set up "named" registers */
    movl    offThread_pc(%ecx),rPC
    movl    offThread_curFrame(%ecx),rFP
    movl    offThread_curHandlerTable(%ecx),rIBASE

    /* Remember %esp for future "longjmp" */
    movl    %esp,offThread_bailPtr(%ecx)

    /* Fetch next instruction before potential jump */
    FETCH_INST
#if defined(WITH_JIT)
    GET_JIT_PROF_TABLE %ecx %eax
    movl        $$0, offThread_inJitCodeCache(%ecx)
    cmpl        $$0, %eax
    jne         common_updateProfile # set up %ebx & %edx & rPC
#endif

   /* Normal case: start executing the instruction at rPC */
    GOTO_NEXT

    .global dvmMterpStdBail
    .type   dvmMterpStdBail, %function
/*
 * void dvmMterpStdBail(Thread* self, bool changeInterp)
 *
 * Restore the stack pointer and PC from the save point established on entry.
 * This is essentially the same as a longjmp, but should be cheaper.  The
 * last instruction causes us to return to whoever called dvmMterpStdRun.
 *
 * We're not going to build a standard frame here, so the arg accesses will
 * look a little strange.
 *
 * On entry:
 *  esp+4 (arg0)  Thread* self
 *  esp+8 (arg1)  bool changeInterp
 */
dvmMterpStdBail:
    movl    4(%esp),%ecx                 # grab self
    movl    8(%esp),%eax                 # changeInterp to return reg
    movl    offThread_bailPtr(%ecx),%esp # Restore "setjmp" esp
    movl    %esp,%ebp
    addl    $$(FRAME_SIZE-4), %ebp       # Restore %ebp at point of setjmp
    movl    EDI_SPILL(%ebp),%edi
    movl    ESI_SPILL(%ebp),%esi
    movl    EBX_SPILL(%ebp),%ebx
    movl    %ebp, %esp                   # strip frame
    pop     %ebp                         # restore caller's ebp
    ret                                  # return to dvmMterpStdRun's caller


#ifdef WITH_JIT
    .global     dvmNcgInvokeInterpreter
    .type       dvmNcgInvokeInterpreter, %function
/* input: start of method in %eax */
dvmNcgInvokeInterpreter:
    movl        %eax, rPC
    movl   rSELF, %ecx
    movl   offThread_curHandlerTable(%ecx),rIBASE
    FETCH_INST_R %ecx                    # %edx<- opcode
    GOTO_NEXT_R %ecx                    # start executing the instruction at rPC
#endif

/*
 * Strings
 */
    .section    .rodata
.LstrBadEntryPoint:
    .asciz  "Bad entry point %d\n"