Merge
diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S
index 8571682..e3ed65f 100644
--- a/vm/mterp/out/InterpAsm-x86.S
+++ b/vm/mterp/out/InterpAsm-x86.S
@@ -2854,9 +2854,7 @@
 .LOP_INVOKE_DIRECT_finish:
     UNSPILL(rPC)
     testl     %ecx,%ecx                # null "this"?
-    movl      $0,%ecx
-    #jne       common_invokeMethodNoRange  # no, continue on
-    jne       common_invokeOld          # no, continue on, eax<- method, ecx<- methodCallRange
+    jne       common_invokeMethodNoRange  # no, continue on
     jmp       common_errNullObject
 
 /* ------------------------------ */
@@ -2876,10 +2874,8 @@
     EXPORT_PC()
     movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
     movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
-    movl      $0,%ecx           # needed by common_invokeOld - revisit
     testl     %eax,%eax
-    #jne       common_invokeMethodNoRange
-    jne       common_invokeOld
+    jne       common_invokeMethodNoRange
     GET_GLUE(%ecx)
     movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
     movzwl    2(rPC),%eax
@@ -3021,9 +3017,7 @@
 .LOP_INVOKE_DIRECT_RANGE_finish:
     UNSPILL(rPC)
     testl     %ecx,%ecx                # null "this"?
-    movl      $1,%ecx
-    #jne       common_invokeMethodRange  # no, continue on
-    jne       common_invokeOld          # no, continue on, eax<- method, ecx<- methodCallRange
+    jne       common_invokeMethodRange  # no, continue on
     jmp       common_errNullObject
 
 
@@ -3045,10 +3039,8 @@
     EXPORT_PC()
     movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
     movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
-    movl      $1,%ecx           # needed by common_invokeOld - revisit
     testl     %eax,%eax
-    #jne       common_invokeMethodRange
-    jne       common_invokeOld
+    jne       common_invokeMethodRange
     GET_GLUE(%ecx)
     movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
     movzwl    2(rPC),%eax
@@ -6029,9 +6021,8 @@
     movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
     EXPORT_PC()                         # might throw later - get ready
     movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
-    movl      $0,%ecx           # pass range flag
-    #jmp       common_invokeMethodNoRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodNoRange
+
 
 
 /* ------------------------------ */
@@ -6058,9 +6049,8 @@
     movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
     EXPORT_PC()                         # might throw later - get ready
     movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
-    movl      $1,%ecx           # pass range flag
-    #jmp       common_invokeMethodRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodRange
+
 
 
 
@@ -6090,9 +6080,7 @@
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
     EXPORT_PC()
     movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
-    movl      $0,%ecx           # ecx<- range flag
-    #jmp       common_invokeMethodNoRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodNoRange
 
 
 /* ------------------------------ */
@@ -6122,9 +6110,7 @@
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
     EXPORT_PC()
     movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
-    movl      $1,%ecx           # ecx<- range flag
-    #jmp       common_invokeMethodRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodRange
 
 
 
@@ -7661,9 +7647,7 @@
     movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
     movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
-    movl      $0,%ecx           # needed for common_invokeOld
-    #jmp       common_invokeMethodNoRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodNoRange
 
 
 /* continuation for OP_INVOKE_SUPER */
@@ -7680,9 +7664,8 @@
     jae     .LOP_INVOKE_SUPER_nsm           # method not present in superclass
     movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
     movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
-    movl    $0,%ecx
-    #jmp     common_invokeMethodNoRange
-    jmp     common_invokeOld
+    jmp     common_invokeMethodNoRange
+
 
     /* At this point:
      * ecx = null (needs to be resolved base method)
@@ -7745,10 +7728,8 @@
     SPILL(rPC)
     call      dvmResolveMethod          # call(clazz,ref,flags)
     UNSPILL(rPC)
-    movl      $0,%ecx
     testl     %eax,%eax                 # got null?
-    #jne       common_invokeMethodNoRange
-    jne       common_invokeOld
+    jne       common_invokeMethodNoRange
     jmp       common_exceptionThrown
 
 
@@ -7759,9 +7740,7 @@
     UNSPILL(rPC)
     testl      %eax,%eax
     je         common_exceptionThrown
-    movl       $0,%ecx
-    #jmp        common_invokeMethodNoRange
-    jmp        common_invokeOld
+    jmp        common_invokeMethodNoRange
 
 
 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
@@ -7793,9 +7772,7 @@
     movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
     movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
-    movl      $1,%ecx           # needed for common_invokeOld
-    #jmp       common_invokeMethodRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodRange
 
 
 /* continuation for OP_INVOKE_SUPER_RANGE */
@@ -7812,9 +7789,8 @@
     jae     .LOP_INVOKE_SUPER_RANGE_nsm           # method not present in superclass
     movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
     movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
-    movl    $1,%ecx
-    #jmp     common_invokeMethodRange
-    jmp     common_invokeOld
+    jmp     common_invokeMethodRange
+
 
     /* At this point:
      * ecx = null (needs to be resolved base method)
@@ -7877,10 +7853,8 @@
     SPILL(rPC)
     call      dvmResolveMethod          # call(clazz,ref,flags)
     UNSPILL(rPC)
-    movl      $1,%ecx
     testl     %eax,%eax                 # got null?
-    #jne       common_invokeMethodRange
-    jne       common_invokeOld
+    jne       common_invokeMethodRange
     jmp       common_exceptionThrown
 
 
@@ -7891,9 +7865,7 @@
     UNSPILL(rPC)
     testl      %eax,%eax
     je         common_exceptionThrown
-    movl       $1,%ecx
-    #jmp        common_invokeMethodRange
-    jmp        common_invokeOld
+    jmp        common_invokeMethodRange
 
 
 /* continuation for OP_FLOAT_TO_INT */
@@ -8527,11 +8499,217 @@
  */
 common_backwardBranch:
     GET_GLUE(%ecx)
-    call   common_periodicChecks      # Note: expects rPC to be preserved
+    call   common_periodicChecks  # Note: expects rPC to be preserved
     ADVANCE_PC_INDEXED(rINST_FULL)
     FETCH_INST()
     GOTO_NEXT
 
+
+
+/*
+ * Common code for method invocation with range.
+ *
+ * On entry:
+ *   eax = Method* methodToCall
+ *   rINST trashed, must reload
+ */
+
+common_invokeMethodRange:
+.LinvokeNewRange:
+
+   /*
+    * prepare to copy args to "outs" area of current frame
+    */
+
+    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- AA
+    movzwl      4(rPC), %ecx            # %ecx<- CCCC
+    SPILL(rPC)
+    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
+    test        rINST_FULL, rINST_FULL
+    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
+    jz          .LinvokeArgsDone        # no args; jump to args done
+
+
+   /*
+    * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
+    * (very few methods have > 10 args; could unroll for common cases)
+    */
+
+    movl        %ebx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- save %ebx
+    lea         (rFP, %ecx, 4), %ecx    # %ecx<- &vCCCC
+    shll        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
+    subl        LOCAL0_OFFSET(%ebp), %edx       # %edx<- update &outs
+    shrl        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
+1:
+    movl        (%ecx), %ebx            # %ebx<- vCCCC
+    lea         4(%ecx), %ecx           # %ecx<- &vCCCC++
+    subl        $1, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET<- LOCAL0_OFFSET--
+    movl        %ebx, (%edx)            # *outs<- vCCCC
+    lea         4(%edx), %edx           # outs++
+    jne         1b                      # loop if count (LOCAL0_OFFSET(%ebp)) not zero
+    movl        LOCAL1_OFFSET(%ebp), %ebx       # %ebx<- restore %ebx
+    jmp         .LinvokeArgsDone        # continue
+
+   /*
+    * %eax is "Method* methodToCall", the method we're trying to call
+    * prepare to copy args to "outs" area of current frame
+    */
+
+common_invokeMethodNoRange:
+.LinvokeNewNoRange:
+    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- BA
+    SPILL(rPC)
+    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
+    shrl        $4, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- B
+    je          .LinvokeArgsDone        # no args; jump to args done
+    movzwl      4(rPC), %ecx            # %ecx<- GFED
+    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
+
+   /*
+    * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
+    */
+
+.LinvokeNonRange:
+    cmp         $2, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 2
+    movl        %ecx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- GFED
+    jl          1f                      # handle 1 arg
+    je          2f                      # handle 2 args
+    cmp         $4, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 4
+    jl          3f                      # handle 3 args
+    je          4f                      # handle 4 args
+5:
+    andl        $15, rINST_FULL        # rINST<- A
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, rINST_FULL, 4), %ecx # %ecx<- vA
+    movl        %ecx, (%edx)            # *outs<- vA
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+4:
+    shr         $12, %ecx              # %ecx<- G
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vG
+    movl        %ecx, (%edx)            # *outs<- vG
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+3:
+    and         $0x0f00, %ecx          # %ecx<- 0F00
+    shr         $8, %ecx               # %ecx<- F
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vF
+    movl        %ecx, (%edx)            # *outs<- vF
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+2:
+    and         $0x00f0, %ecx          # %ecx<- 00E0
+    shr         $4, %ecx               # %ecx<- E
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vE
+    movl        %ecx, (%edx)            # *outs<- vE
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+1:
+    and         $0x000f, %ecx          # %ecx<- 000D
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
+    movl        %ecx, -4(%edx)          # *--outs<- vD
+0:
+
+   /*
+    * %eax is "Method* methodToCall", the method we're trying to call
+    * find space for the new stack frame, check for overflow
+    */
+
+.LinvokeArgsDone:
+    movzwl      offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
+    movzwl      offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
+    movl        %eax, LOCAL0_OFFSET(%ebp)       # LOCAL0_OFFSET<- methodToCall
+    shl         $2, %edx               # %edx<- update offset
+    SAVEAREA_FROM_FP(%eax,rFP)          # %eax<- &StackSaveArea
+    subl        %edx, %eax              # %eax<- newFP; (old savearea - regsSize)
+    GET_GLUE(%edx)                      # %edx<- pMterpGlue
+    movl        %eax, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- &outs
+    subl        $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
+    movl        offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
+    movl        %edx, LOCAL2_OFFSET(%ebp)       # LOCAL2_OFFSET<- glue->interpStackEnd
+    shl         $2, %ecx               # %ecx<- update offset for outsSize
+    movl        %eax, %edx              # %edx<- newSaveArea
+    sub         %ecx, %eax              # %eax<- bottom; (newSaveArea - outsSize)
+    cmp         LOCAL2_OFFSET(%ebp), %eax       # compare interpStackEnd and bottom
+    movl        LOCAL0_OFFSET(%ebp), %eax       # %eax<- restore methodToCall
+    jl          .LstackOverflow         # handle frame overflow
+
+   /*
+    * set up newSaveArea
+    */
+
+#ifdef EASY_GDB
+    SAVEAREA_FROM_FP(%ecx,rFP)          # %ecx<- &StackSaveArea
+    movl        %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
+#endif
+    movl        rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
+    movl        rPC_SPILL(%ebp), %ecx
+    movl        %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
+    testl       $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
+    movl        %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
+    jne         .LinvokeNative          # handle native call
+
+   /*
+    * Update "glue" values for the new method
+    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
+    */
+
+    movl        offMethod_clazz(%eax), %edx # %edx<- method->clazz
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
+    movl        %eax, offGlue_method(%ecx) # glue->method<- methodToCall
+    movl        %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
+    movl        offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
+    movl        offGlue_self(%ecx), %eax # %eax<- glue->self
+    movl        LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
+    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
+    FETCH_INST()
+    GOTO_NEXT                           # jump to methodToCall->insns
+
+   /*
+    * Prep for the native call
+    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
+    */
+
+.LinvokeNative:
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
+    movl        offGlue_self(%ecx), %ecx        # %ecx<- glue->self
+    movl        offThread_jniLocal_nextEntry(%ecx), %eax # %eax<- glue->self->thread->refNext
+    movl        %eax, offStackSaveArea_localRefTop(%edx) # newSaveArea->localRefTop<- refNext
+    movl        %edx, OUT_ARG4(%esp)    # save newSaveArea
+    movl        LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
+    movl        %edx, offThread_curFrame(%ecx)  # glue->self->curFrame<- newFP
+    movl        %ecx, OUT_ARG3(%esp)    # save glue->self
+    movl        %ecx, OUT_ARG2(%esp)    # push parameter glue->self
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        OUT_ARG1(%esp), %eax    # %eax<- methodToCall
+    lea         offGlue_retval(%ecx), %ecx # %ecx<- &retval
+    movl        %ecx, OUT_ARG0(%esp)    # push parameter pMterpGlue
+    push        %edx                    # push parameter newFP
+
+    call        *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
+    lea         4(%esp), %esp
+    movl        OUT_ARG4(%esp), %ecx    # %ecx<- newSaveArea
+    movl        OUT_ARG3(%esp), %eax    # %eax<- glue->self
+    movl        offStackSaveArea_localRefTop(%ecx), %edx # %edx<- newSaveArea->localRefTop
+    cmp         $0, offThread_exception(%eax) # check for exception
+    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
+    movl        %edx, offThread_jniLocal_nextEntry(%eax) # glue->self<- newSaveArea->localRefTop
+    UNSPILL(rPC)
+    jne         common_exceptionThrown  # handle exception
+    FETCH_INST_WORD(3)
+    ADVANCE_PC(3)
+    GOTO_NEXT                           # jump to next instruction
+
+.LstackOverflow:
+    GET_GLUE(%eax)                      # %eax<- pMterpGlue
+    movl        offGlue_self(%eax), %eax # %eax<- glue->self
+    movl        %eax, OUT_ARG0(%esp)    # push parameter self
+    call        dvmHandleStackOverflow  # call: (Thread* self)
+    UNSPILL(rPC)                        # return: void
+    jmp         common_exceptionThrown  # handle exception
+
+
 /*
  * Common invoke code (old-style).
  * TUNING:  Rewrite along lines of new armv5 code?
diff --git a/vm/mterp/x86/OP_INVOKE_DIRECT.S b/vm/mterp/x86/OP_INVOKE_DIRECT.S
index a772540..f423dc3 100644
--- a/vm/mterp/x86/OP_INVOKE_DIRECT.S
+++ b/vm/mterp/x86/OP_INVOKE_DIRECT.S
@@ -30,9 +30,7 @@
 .L${opcode}_finish:
     UNSPILL(rPC)
     testl     %ecx,%ecx                # null "this"?
-    movl      $$$isrange,%ecx
-    #jne       common_invokeMethod${routine}  # no, continue on
-    jne       common_invokeOld          # no, continue on, eax<- method, ecx<- methodCallRange
+    jne       common_invokeMethod${routine}  # no, continue on
     jmp       common_errNullObject
 %break
 
diff --git a/vm/mterp/x86/OP_INVOKE_INTERFACE.S b/vm/mterp/x86/OP_INVOKE_INTERFACE.S
index 02dc76f..1631177 100644
--- a/vm/mterp/x86/OP_INVOKE_INTERFACE.S
+++ b/vm/mterp/x86/OP_INVOKE_INTERFACE.S
@@ -35,7 +35,5 @@
     UNSPILL(rPC)
     testl      %eax,%eax
     je         common_exceptionThrown
-    movl       $$$isrange,%ecx
-    #jmp        common_invokeMethod${routine}
-    jmp        common_invokeOld
+    jmp        common_invokeMethod${routine}
 
diff --git a/vm/mterp/x86/OP_INVOKE_STATIC.S b/vm/mterp/x86/OP_INVOKE_STATIC.S
index c65fc1f..40dac06 100644
--- a/vm/mterp/x86/OP_INVOKE_STATIC.S
+++ b/vm/mterp/x86/OP_INVOKE_STATIC.S
@@ -14,10 +14,8 @@
     EXPORT_PC()
     movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
     movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
-    movl      $$$isrange,%ecx           # needed by common_invokeOld - revisit
     testl     %eax,%eax
-    #jne       common_invokeMethod${routine}
-    jne       common_invokeOld
+    jne       common_invokeMethod${routine}
     GET_GLUE(%ecx)
     movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
     movzwl    2(rPC),%eax
@@ -33,9 +31,7 @@
     SPILL(rPC)
     call      dvmResolveMethod          # call(clazz,ref,flags)
     UNSPILL(rPC)
-    movl      $$$isrange,%ecx
     testl     %eax,%eax                 # got null?
-    #jne       common_invokeMethod${routine}
-    jne       common_invokeOld
+    jne       common_invokeMethod${routine}
     jmp       common_exceptionThrown
 
diff --git a/vm/mterp/x86/OP_INVOKE_SUPER.S b/vm/mterp/x86/OP_INVOKE_SUPER.S
index d0a6ad6..013fc01 100644
--- a/vm/mterp/x86/OP_INVOKE_SUPER.S
+++ b/vm/mterp/x86/OP_INVOKE_SUPER.S
@@ -40,9 +40,8 @@
     jae     .L${opcode}_nsm           # method not present in superclass
     movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
     movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
-    movl    $$$isrange,%ecx
-    #jmp     common_invokeMethod${routine}
-    jmp     common_invokeOld
+    jmp     common_invokeMethod${routine}
+
 
     /* At this point:
      * ecx = null (needs to be resolved base method)
diff --git a/vm/mterp/x86/OP_INVOKE_SUPER_QUICK.S b/vm/mterp/x86/OP_INVOKE_SUPER_QUICK.S
index b050c82..7545eb0 100644
--- a/vm/mterp/x86/OP_INVOKE_SUPER_QUICK.S
+++ b/vm/mterp/x86/OP_INVOKE_SUPER_QUICK.S
@@ -23,7 +23,5 @@
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
     EXPORT_PC()
     movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
-    movl      $$$isrange,%ecx           # ecx<- range flag
-    #jmp       common_invokeMethod${routine}
-    jmp       common_invokeOld
+    jmp       common_invokeMethod${routine}
 
diff --git a/vm/mterp/x86/OP_INVOKE_VIRTUAL.S b/vm/mterp/x86/OP_INVOKE_VIRTUAL.S
index 6d32a81..20d9120 100644
--- a/vm/mterp/x86/OP_INVOKE_VIRTUAL.S
+++ b/vm/mterp/x86/OP_INVOKE_VIRTUAL.S
@@ -52,7 +52,5 @@
     movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
     movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
-    movl      $$$isrange,%ecx           # needed for common_invokeOld
-    #jmp       common_invokeMethod${routine}
-    jmp       common_invokeOld
+    jmp       common_invokeMethod${routine}
 
diff --git a/vm/mterp/x86/OP_INVOKE_VIRTUAL_QUICK.S b/vm/mterp/x86/OP_INVOKE_VIRTUAL_QUICK.S
index d197f29..f36ed2d 100644
--- a/vm/mterp/x86/OP_INVOKE_VIRTUAL_QUICK.S
+++ b/vm/mterp/x86/OP_INVOKE_VIRTUAL_QUICK.S
@@ -20,7 +20,6 @@
     movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
     EXPORT_PC()                         # might throw later - get ready
     movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
-    movl      $$$isrange,%ecx           # pass range flag
-    #jmp       common_invokeMethod${routine}
-    jmp       common_invokeOld
+    jmp       common_invokeMethod${routine}
+
 
diff --git a/vm/mterp/x86/footer.S b/vm/mterp/x86/footer.S
index 50634dd..70b829c 100644
--- a/vm/mterp/x86/footer.S
+++ b/vm/mterp/x86/footer.S
@@ -25,11 +25,217 @@
  */
 common_backwardBranch:
     GET_GLUE(%ecx)
-    call   common_periodicChecks      # Note: expects rPC to be preserved
+    call   common_periodicChecks  # Note: expects rPC to be preserved
     ADVANCE_PC_INDEXED(rINST_FULL)
     FETCH_INST()
     GOTO_NEXT
 
+
+
+/*
+ * Common code for method invocation with range.
+ *
+ * On entry:
+ *   eax = Method* methodToCall
+ *   rINST trashed, must reload
+ */
+
+common_invokeMethodRange:
+.LinvokeNewRange:
+
+   /*
+    * prepare to copy args to "outs" area of current frame
+    */
+
+    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- AA
+    movzwl      4(rPC), %ecx            # %ecx<- CCCC
+    SPILL(rPC)
+    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
+    test        rINST_FULL, rINST_FULL
+    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
+    jz          .LinvokeArgsDone        # no args; jump to args done
+
+
+   /*
+    * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
+    * (very few methods have > 10 args; could unroll for common cases)
+    */
+
+    movl        %ebx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- save %ebx
+    lea         (rFP, %ecx, 4), %ecx    # %ecx<- &vCCCC
+    shll        $$2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
+    subl        LOCAL0_OFFSET(%ebp), %edx       # %edx<- update &outs
+    shrl        $$2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
+1:
+    movl        (%ecx), %ebx            # %ebx<- vCCCC
+    lea         4(%ecx), %ecx           # %ecx<- &vCCCC++
+    subl        $$1, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET<- LOCAL0_OFFSET--
+    movl        %ebx, (%edx)            # *outs<- vCCCC
+    lea         4(%edx), %edx           # outs++
+    jne         1b                      # loop if count (LOCAL0_OFFSET(%ebp)) not zero
+    movl        LOCAL1_OFFSET(%ebp), %ebx       # %ebx<- restore %ebx
+    jmp         .LinvokeArgsDone        # continue
+
+   /*
+    * %eax is "Method* methodToCall", the method we're trying to call
+    * prepare to copy args to "outs" area of current frame
+    */
+
+common_invokeMethodNoRange:
+.LinvokeNewNoRange:
+    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- BA
+    SPILL(rPC)
+    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
+    shrl        $$4, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- B
+    je          .LinvokeArgsDone        # no args; jump to args done
+    movzwl      4(rPC), %ecx            # %ecx<- GFED
+    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
+
+   /*
+    * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
+    */
+
+.LinvokeNonRange:
+    cmp         $$2, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 2
+    movl        %ecx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- GFED
+    jl          1f                      # handle 1 arg
+    je          2f                      # handle 2 args
+    cmp         $$4, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 4
+    jl          3f                      # handle 3 args
+    je          4f                      # handle 4 args
+5:
+    andl        $$15, rINST_FULL        # rINST<- A
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, rINST_FULL, 4), %ecx # %ecx<- vA
+    movl        %ecx, (%edx)            # *outs<- vA
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+4:
+    shr         $$12, %ecx              # %ecx<- G
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vG
+    movl        %ecx, (%edx)            # *outs<- vG
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+3:
+    and         $$0x0f00, %ecx          # %ecx<- 0F00
+    shr         $$8, %ecx               # %ecx<- F
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vF
+    movl        %ecx, (%edx)            # *outs<- vF
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+2:
+    and         $$0x00f0, %ecx          # %ecx<- 00E0
+    shr         $$4, %ecx               # %ecx<- E
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vE
+    movl        %ecx, (%edx)            # *outs<- vE
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+1:
+    and         $$0x000f, %ecx          # %ecx<- 000D
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
+    movl        %ecx, -4(%edx)          # *--outs<- vD
+0:
+
+   /*
+    * %eax is "Method* methodToCall", the method we're trying to call
+    * find space for the new stack frame, check for overflow
+    */
+
+.LinvokeArgsDone:
+    movzwl      offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
+    movzwl      offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
+    movl        %eax, LOCAL0_OFFSET(%ebp)       # LOCAL0_OFFSET<- methodToCall
+    shl         $$2, %edx               # %edx<- update offset
+    SAVEAREA_FROM_FP(%eax,rFP)          # %eax<- &StackSaveArea
+    subl        %edx, %eax              # %eax<- newFP; (old savearea - regsSize)
+    GET_GLUE(%edx)                      # %edx<- pMterpGlue
+    movl        %eax, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- &outs
+    subl        $$sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
+    movl        offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
+    movl        %edx, LOCAL2_OFFSET(%ebp)       # LOCAL2_OFFSET<- glue->interpStackEnd
+    shl         $$2, %ecx               # %ecx<- update offset for outsSize
+    movl        %eax, %edx              # %edx<- newSaveArea
+    sub         %ecx, %eax              # %eax<- bottom; (newSaveArea - outsSize)
+    cmp         LOCAL2_OFFSET(%ebp), %eax       # compare interpStackEnd and bottom
+    movl        LOCAL0_OFFSET(%ebp), %eax       # %eax<- restore methodToCall
+    jl          .LstackOverflow         # handle frame overflow
+
+   /*
+    * set up newSaveArea
+    */
+
+#ifdef EASY_GDB
+    SAVEAREA_FROM_FP(%ecx,rFP)          # %ecx<- &StackSaveArea
+    movl        %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
+#endif
+    movl        rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
+    movl        rPC_SPILL(%ebp), %ecx
+    movl        %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
+    testl       $$ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
+    movl        %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
+    jne         .LinvokeNative          # handle native call
+
+   /*
+    * Update "glue" values for the new method
+    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
+    */
+
+    movl        offMethod_clazz(%eax), %edx # %edx<- method->clazz
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
+    movl        %eax, offGlue_method(%ecx) # glue->method<- methodToCall
+    movl        %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
+    movl        offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
+    movl        offGlue_self(%ecx), %eax # %eax<- glue->self
+    movl        LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
+    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
+    FETCH_INST()
+    GOTO_NEXT                           # jump to methodToCall->insns
+
+   /*
+    * Prep for the native call
+    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
+    */
+
+.LinvokeNative:
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
+    movl        offGlue_self(%ecx), %ecx        # %ecx<- glue->self
+    movl        offThread_jniLocal_nextEntry(%ecx), %eax # %eax<- glue->self->thread->refNext
+    movl        %eax, offStackSaveArea_localRefTop(%edx) # newSaveArea->localRefTop<- refNext
+    movl        %edx, OUT_ARG4(%esp)    # save newSaveArea
+    movl        LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
+    movl        %edx, offThread_curFrame(%ecx)  # glue->self->curFrame<- newFP
+    movl        %ecx, OUT_ARG3(%esp)    # save glue->self
+    movl        %ecx, OUT_ARG2(%esp)    # push parameter glue->self
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        OUT_ARG1(%esp), %eax    # %eax<- methodToCall
+    lea         offGlue_retval(%ecx), %ecx # %ecx<- &retval
+    movl        %ecx, OUT_ARG0(%esp)    # push parameter pMterpGlue
+    push        %edx                    # push parameter newFP
+
+    call        *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
+    lea         4(%esp), %esp
+    movl        OUT_ARG4(%esp), %ecx    # %ecx<- newSaveArea
+    movl        OUT_ARG3(%esp), %eax    # %eax<- glue->self
+    movl        offStackSaveArea_localRefTop(%ecx), %edx # %edx<- newSaveArea->localRefTop
+    cmp         $$0, offThread_exception(%eax) # check for exception
+    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
+    movl        %edx, offThread_jniLocal_nextEntry(%eax) # glue->self<- newSaveArea->localRefTop
+    UNSPILL(rPC)
+    jne         common_exceptionThrown  # handle exception
+    FETCH_INST_WORD(3)
+    ADVANCE_PC(3)
+    GOTO_NEXT                           # jump to next instruction
+
+.LstackOverflow:
+    GET_GLUE(%eax)                      # %eax<- pMterpGlue
+    movl        offGlue_self(%eax), %eax # %eax<- glue->self
+    movl        %eax, OUT_ARG0(%esp)    # push parameter self
+    call        dvmHandleStackOverflow  # call: (Thread* self)
+    UNSPILL(rPC)                        # return: void
+    jmp         common_exceptionThrown  # handle exception
+
+
 /*
  * Common invoke code (old-style).
  * TUNING:  Rewrite along lines of new armv5 code?