Introduce "just interpret" chainable pseudo-translation.

This is the first step towards enabling translation & self-cosim stress modes.
When trace selection begins, the trace head address is pinned and
remains in a limbo state until the translation is complete.  Previously,
if the trace selected aborted for any reason, the trace head would remain
forever in limbo.  This was not a correctness problem, but caused some
small performance anomolies and made life more difficult for self-cosimulation
mode.

This CL introduces a pseudo-translation that simply routes control to
the interpreter.  When we detect that a trace selection attempt has
failed, the trace head is associated with this fully-chainable
pseudo-translation.  This also has the benefit for self-cosimulation that
we are guaranteed forward progress.
diff --git a/vm/Globals.h b/vm/Globals.h
index b4d1f17..152008e 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -768,6 +768,9 @@
     /* Vector to disable selected optimizations */
     int disableOpt;
 
+    /* Code address of special interpret-only pseudo-translation */
+    void *interpretTemplate;
+
     /* Table to track the overall and trace statistics of hot methods */
     HashTable*  methodStatsTable;
 
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index bc39479..8e977c1 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -1259,16 +1259,28 @@
         info->codeAddress = (char*)info->codeAddress + 1;
 }
 
-static u4 assembleBXPair(int branchOffset)
+/*
+ * Returns the skeleton bit pattern associated with an opcode.  All
+ * variable fields are zeroed.
+ */
+static u4 getSkeleton(ArmOpCode op)
+{
+    return EncodingMap[op].skeleton;
+}
+
+static u4 assembleChainingBranch(int branchOffset, bool thumbTarget)
 {
     u4 thumb1, thumb2;
 
-    if ((branchOffset < -2048) | (branchOffset > 2046)) {
-        thumb1 =  (0xf000 | ((branchOffset>>12) & 0x7ff));
-        thumb2 =  (0xf800 | ((branchOffset>> 1) & 0x7ff));
+    if (!thumbTarget) {
+        thumb1 =  (getSkeleton(kThumbBlx1) | ((branchOffset>>12) & 0x7ff));
+        thumb2 =  (getSkeleton(kThumbBlx2) | ((branchOffset>> 1) & 0x7ff));
+    } else if ((branchOffset < -2048) | (branchOffset > 2046)) {
+        thumb1 =  (getSkeleton(kThumbBl1) | ((branchOffset>>12) & 0x7ff));
+        thumb2 =  (getSkeleton(kThumbBl2) | ((branchOffset>> 1) & 0x7ff));
     } else {
-        thumb1 =  (0xe000 | ((branchOffset>> 1) & 0x7ff));
-        thumb2 =  0x4300;  /* nop -> or r0, r0 */
+        thumb1 =  (getSkeleton(kThumbBUncond) | ((branchOffset>> 1) & 0x7ff));
+        thumb2 =  getSkeleton(kThumbOrr);  /* nop -> or r0, r0 */
     }
 
     return thumb2<<16 | thumb1;
@@ -1278,7 +1290,8 @@
  * Perform translation chain operation.
  * For ARM, we'll use a pair of thumb instructions to generate
  * an unconditional chaining branch of up to 4MB in distance.
- * Use a BL, though we don't really need the link.  The format is
+ * Use a BL, because the generic "interpret" translation needs
+ * the link register to find the dalvik pc of teh target.
  *     111HHooooooooooo
  * Where HH is 10 for the 1st inst, and 11 for the second and
  * the "o" field is each instruction's 11-bit contribution to the
@@ -1291,6 +1304,7 @@
     int baseAddr = (u4) branchAddr + 4;
     int branchOffset = (int) tgtAddr - baseAddr;
     u4 newInst;
+    bool thumbTarget;
 
     if (gDvm.sumThreadSuspendCount == 0) {
         assert((branchOffset >= -(1<<22)) && (branchOffset <= ((1<<22)-2)));
@@ -1301,7 +1315,16 @@
             LOGD("Jit Runtime: chaining 0x%x to 0x%x\n",
                  (int) branchAddr, (int) tgtAddr & -2));
 
-        newInst = assembleBXPair(branchOffset);
+        /*
+         * NOTE: normally, all translations are Thumb[2] mode, with
+         * a single exception: the default TEMPLATE_INTERPRET
+         * pseudo-translation.  If the need ever arises to
+         * mix Arm & Thumb[2] translations, the following code should be
+         * generalized.
+         */
+        thumbTarget = (tgtAddr != gDvmJit.interpretTemplate);
+
+        newInst = assembleChainingBranch(branchOffset, thumbTarget);
 
         *branchAddr = newInst;
         cacheflush((long)branchAddr, (long)branchAddr + 4, 0);
@@ -1354,7 +1377,7 @@
      * Compilation not made yet for the callee. Reset the counter to a small
      * value and come back to check soon.
      */
-    if (tgtAddr == 0) {
+    if ((tgtAddr == 0) || ((void*)tgtAddr == gDvmJit.interpretTemplate)) {
         /*
          * Wait for a few invocations (currently set to be 16) before trying
          * to setup the chain again.
@@ -1388,7 +1411,7 @@
              clazz->descriptor,
              method->name));
 
-    cell->branch = assembleBXPair(branchOffset);
+    cell->branch = assembleChainingBranch(branchOffset, true);
     cell->clazz = clazz;
     cell->method = method;
     /*
@@ -1517,7 +1540,9 @@
         dvmLockMutex(&gDvmJit.tableLock);
         for (i = 0; i < gDvmJit.jitTableSize; i++) {
             if (gDvmJit.pJitEntryTable[i].dPC &&
-                   gDvmJit.pJitEntryTable[i].codeAddress) {
+                   gDvmJit.pJitEntryTable[i].codeAddress &&
+                   (gDvmJit.pJitEntryTable[i].codeAddress !=
+                    gDvmJit.interpretTemplate)) {
                 u4* lastAddress;
                 lastAddress =
                       dvmJitUnchain(gDvmJit.pJitEntryTable[i].codeAddress);
@@ -1573,6 +1598,10 @@
         LOGD("TRACEPROFILE 0x%08x 0 NULL 0 0", (int)traceBase);
         return 0;
     }
+    if (p->codeAddress == gDvmJit.interpretTemplate) {
+        LOGD("TRACEPROFILE 0x%08x 0 INTERPRET_ONLY  0 0", (int)traceBase);
+        return 0;
+    }
 
     pExecutionCount = (u4*) (traceBase);
     pCellOffset = (u2*) (traceBase + 4);
diff --git a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
index 8c61322..3a46cac 100644
--- a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
@@ -53,6 +53,12 @@
             (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
 }
 
+void *dvmCompilerGetInterpretTemplate()
+{
+    return (void*) ((int)gDvmJit.codeCache +
+                    templateEntryOffsets[TEMPLATE_INTERPRET]);
+}
+
 /* Architecture-specific initializations and checks go here */
 static bool compilerArchVariantInit(void)
 {
diff --git a/vm/compiler/codegen/arm/armv5te/ArchVariant.c b/vm/compiler/codegen/arm/armv5te/ArchVariant.c
index a4b9ae3..4178c23 100644
--- a/vm/compiler/codegen/arm/armv5te/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv5te/ArchVariant.c
@@ -90,6 +90,12 @@
     return true;
 }
 
+void *dvmCompilerGetInterpretTemplate()
+{
+    return (void*) ((int)gDvmJit.codeCache +
+                    templateEntryOffsets[TEMPLATE_INTERPRET]);
+}
+
 static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
 {
     return false;   /* punt to C handler */
diff --git a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
index 0409135..02b9b79 100644
--- a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
@@ -54,6 +54,12 @@
             (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
 }
 
+void *dvmCompilerGetInterpretTemplate()
+{
+    return (void*) ((int)gDvmJit.codeCache +
+                    templateEntryOffsets[TEMPLATE_INTERPRET]);
+}
+
 /* Architecture-specific initializations and checks go here */
 static bool compilerArchVariantInit(void)
 {
diff --git a/vm/compiler/template/armv5te-vfp/TemplateOpList.h b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
index 1608920..d414e1b 100644
--- a/vm/compiler/template/armv5te-vfp/TemplateOpList.h
+++ b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
@@ -55,3 +55,4 @@
 JIT_TEMPLATE(RESTORE_STATE)
 JIT_TEMPLATE(STRING_COMPARETO)
 JIT_TEMPLATE(STRING_INDEXOF)
+JIT_TEMPLATE(INTERPRET)
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INTERPRET.S b/vm/compiler/template/armv5te/TEMPLATE_INTERPRET.S
new file mode 100644
index 0000000..5484400
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_INTERPRET.S
@@ -0,0 +1,23 @@
+    /*
+     * This handler transfers control to the interpeter without performing
+     * any lookups.  It may be called either as part of a normal chaining
+     * operation, or from the transition code in header.S.  We distinquish
+     * the two cases by looking at the link register.  If called from a
+     * translation chain, it will point to the chaining Dalvik PC + 1.
+     * On entry:
+     *    lr - if NULL:
+     *        r1 - the Dalvik PC to begin interpretation.
+     *    else
+     *        [lr, #-1] contains Dalvik PC to begin interpretation
+     *    rGLUE - pointer to interpState
+     *    rFP - Dalvik frame pointer
+     */
+    cmp     lr, #0
+    ldrne   r1,[lr, #-1]
+    ldr     r2, .LinterpPunt
+    mov     r0, r1                       @ set Dalvik PC
+    bx      r2
+    @ doesn't return
+
+.LinterpPunt:
+    .word   dvmJitToInterpPunt
diff --git a/vm/compiler/template/armv5te/TemplateOpList.h b/vm/compiler/template/armv5te/TemplateOpList.h
index 88cc60a..1b5e6ea 100644
--- a/vm/compiler/template/armv5te/TemplateOpList.h
+++ b/vm/compiler/template/armv5te/TemplateOpList.h
@@ -40,3 +40,4 @@
 JIT_TEMPLATE(RESTORE_STATE)
 JIT_TEMPLATE(STRING_COMPARETO)
 JIT_TEMPLATE(STRING_INDEXOF)
+JIT_TEMPLATE(INTERPRET)
diff --git a/vm/compiler/template/armv5te/header.S b/vm/compiler/template/armv5te/header.S
index 9651032..c257105 100644
--- a/vm/compiler/template/armv5te/header.S
+++ b/vm/compiler/template/armv5te/header.S
@@ -85,6 +85,9 @@
 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
     sub     _reg, _fpreg, #sizeofStackSaveArea
 
+#define EXPORT_PC() \
+    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
+
 /*
  * This is a #include, not a %include, because we want the C pre-processor
  * to expand the macros into assembler assignment statements.
diff --git a/vm/compiler/template/armv7-a/TemplateOpList.h b/vm/compiler/template/armv7-a/TemplateOpList.h
index 1608920..d414e1b 100644
--- a/vm/compiler/template/armv7-a/TemplateOpList.h
+++ b/vm/compiler/template/armv7-a/TemplateOpList.h
@@ -55,3 +55,4 @@
 JIT_TEMPLATE(RESTORE_STATE)
 JIT_TEMPLATE(STRING_COMPARETO)
 JIT_TEMPLATE(STRING_INDEXOF)
+JIT_TEMPLATE(INTERPRET)
diff --git a/vm/compiler/template/config-armv5te-vfp b/vm/compiler/template/config-armv5te-vfp
index b5ca397..fc968fe 100644
--- a/vm/compiler/template/config-armv5te-vfp
+++ b/vm/compiler/template/config-armv5te-vfp
@@ -45,6 +45,7 @@
     op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
     op TEMPLATE_STRING_COMPARETO armv5te
     op TEMPLATE_STRING_INDEXOF armv5te
+    op TEMPLATE_INTERPRET armv5te
 
 op-end
 
diff --git a/vm/compiler/template/config-armv7-a b/vm/compiler/template/config-armv7-a
index 1d3d331..7f7b478 100644
--- a/vm/compiler/template/config-armv7-a
+++ b/vm/compiler/template/config-armv7-a
@@ -45,6 +45,7 @@
     op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
     op TEMPLATE_STRING_COMPARETO armv5te
     op TEMPLATE_STRING_INDEXOF armv5te
+    op TEMPLATE_INTERPRET armv5te
 
 op-end
 
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
index cc86848..6604773 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -92,6 +92,9 @@
 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
     sub     _reg, _fpreg, #sizeofStackSaveArea
 
+#define EXPORT_PC() \
+    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
+
 /*
  * This is a #include, not a %include, because we want the C pre-processor
  * to expand the macros into assembler assignment statements.
@@ -1296,6 +1299,35 @@
     bx    lr
 
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INTERPRET
+dvmCompiler_TEMPLATE_INTERPRET:
+/* File: armv5te/TEMPLATE_INTERPRET.S */
+    /*
+     * This handler transfers control to the interpeter without performing
+     * any lookups.  It may be called either as part of a normal chaining
+     * operation, or from the transition code in header.S.  We distinquish
+     * the two cases by looking at the link register.  If called from a
+     * translation chain, it will point to the chaining Dalvik PC + 1.
+     * On entry:
+     *    lr - if NULL:
+     *        r1 - the Dalvik PC to begin interpretation.
+     *    else
+     *        [lr, #-1] contains Dalvik PC to begin interpretation
+     *    rGLUE - pointer to interpState
+     *    rFP - Dalvik frame pointer
+     */
+    cmp     lr, #0
+    ldrne   r1,[lr, #-1]
+    ldr     r2, .LinterpPunt
+    mov     r0, r1                       @ set Dalvik PC
+    bx      r2
+    @ doesn't return
+
+.LinterpPunt:
+    .word   dvmJitToInterpPunt
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
index fbfaf86..cee118b 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -92,6 +92,9 @@
 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
     sub     _reg, _fpreg, #sizeofStackSaveArea
 
+#define EXPORT_PC() \
+    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
+
 /*
  * This is a #include, not a %include, because we want the C pre-processor
  * to expand the macros into assembler assignment statements.
@@ -1021,6 +1024,35 @@
     bx    lr
 
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INTERPRET
+dvmCompiler_TEMPLATE_INTERPRET:
+/* File: armv5te/TEMPLATE_INTERPRET.S */
+    /*
+     * This handler transfers control to the interpeter without performing
+     * any lookups.  It may be called either as part of a normal chaining
+     * operation, or from the transition code in header.S.  We distinquish
+     * the two cases by looking at the link register.  If called from a
+     * translation chain, it will point to the chaining Dalvik PC + 1.
+     * On entry:
+     *    lr - if NULL:
+     *        r1 - the Dalvik PC to begin interpretation.
+     *    else
+     *        [lr, #-1] contains Dalvik PC to begin interpretation
+     *    rGLUE - pointer to interpState
+     *    rFP - Dalvik frame pointer
+     */
+    cmp     lr, #0
+    ldrne   r1,[lr, #-1]
+    ldr     r2, .LinterpPunt
+    mov     r0, r1                       @ set Dalvik PC
+    bx      r2
+    @ doesn't return
+
+.LinterpPunt:
+    .word   dvmJitToInterpPunt
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index 4d479da..aab5067 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -92,6 +92,9 @@
 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
     sub     _reg, _fpreg, #sizeofStackSaveArea
 
+#define EXPORT_PC() \
+    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
+
 /*
  * This is a #include, not a %include, because we want the C pre-processor
  * to expand the macros into assembler assignment statements.
@@ -1296,6 +1299,35 @@
     bx    lr
 
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INTERPRET
+dvmCompiler_TEMPLATE_INTERPRET:
+/* File: armv5te/TEMPLATE_INTERPRET.S */
+    /*
+     * This handler transfers control to the interpeter without performing
+     * any lookups.  It may be called either as part of a normal chaining
+     * operation, or from the transition code in header.S.  We distinquish
+     * the two cases by looking at the link register.  If called from a
+     * translation chain, it will point to the chaining Dalvik PC + 1.
+     * On entry:
+     *    lr - if NULL:
+     *        r1 - the Dalvik PC to begin interpretation.
+     *    else
+     *        [lr, #-1] contains Dalvik PC to begin interpretation
+     *    rGLUE - pointer to interpState
+     *    rFP - Dalvik frame pointer
+     */
+    cmp     lr, #0
+    ldrne   r1,[lr, #-1]
+    ldr     r2, .LinterpPunt
+    mov     r0, r1                       @ set Dalvik PC
+    bx      r2
+    @ doesn't return
+
+.LinterpPunt:
+    .word   dvmJitToInterpPunt
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
diff --git a/vm/interp/InterpDefs.h b/vm/interp/InterpDefs.h
index f397a34..41a2bb8 100644
--- a/vm/interp/InterpDefs.h
+++ b/vm/interp/InterpDefs.h
@@ -150,6 +150,7 @@
     JitState           jitState;
     void*              jitResume;
     u2*                jitResumePC;
+    const u2*          jitTraceInProgress;
 #endif
 
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index aaeeff6..d9b9caa 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -60,7 +60,7 @@
  * Return a pointer to the shadow space for JIT to use.
  */
 void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
-                                   InterpState* interpState)
+                                   InterpState* interpState, int targetTrace)
 {
     Thread *self = dvmThreadSelf();
     ShadowSpace *shadowSpace = self->shadowSpace;
@@ -444,13 +444,17 @@
     int hit;
     int not_hit;
     int chains;
+    int stubs;
     if (gDvmJit.pJitEntryTable) {
-        for (i=0, chains=hit=not_hit=0;
+        for (i=0, stubs=chains=hit=not_hit=0;
              i < (int) gDvmJit.jitTableSize;
              i++) {
-            if (gDvmJit.pJitEntryTable[i].dPC != 0)
+            if (gDvmJit.pJitEntryTable[i].dPC != 0) {
                 hit++;
-            else
+                if (gDvmJit.pJitEntryTable[i].codeAddress ==
+                      gDvmJit.interpretTemplate)
+                    stubs++;
+            } else
                 not_hit++;
             if (gDvmJit.pJitEntryTable[i].u.info.chain != gDvmJit.jitTableSize)
                 chains++;
@@ -470,7 +474,8 @@
          gDvmJit.noChainExit[kCallsiteInterpreted],
          gDvmJit.noChainExit[kSwitchOverflow]);
 #endif
-        LOGD("JIT: %d Translation chains", gDvmJit.translationChains);
+        LOGD("JIT: %d Translation chains, %d interp stubs",
+             gDvmJit.translationChains, stubs);
 #if defined(INVOKE_STATS)
         LOGD("JIT: Invoke: %d chainable, %d pred. chain, %d native, "
              "%d return",
@@ -645,6 +650,7 @@
 #endif
                 dvmCompilerWorkEnqueue(
                        interpState->currTraceHead,kWorkOrderTrace,desc);
+                interpState->jitTraceInProgress = NULL;
                 if (gDvmJit.blockingMode) {
                     dvmCompilerDrainQueue();
                 }
@@ -815,7 +821,10 @@
             }
         }
         if (gDvmJit.pJitEntryTable[idx].dPC == NULL) {
-           /* Allocate the slot */
+            /*
+             * Initialize codeAddress and allocate the slot.  Must
+             * happen in this order (ince dPC is set, the entry is live.
+             */
             gDvmJit.pJitEntryTable[idx].dPC = dPC;
             gDvmJit.jitTableEntriesUsed++;
         } else {
@@ -828,7 +837,7 @@
 }
 /*
  * Register the translated code pointer into the JitTable.
- * NOTE: Once a codeAddress field transitions from NULL to
+ * NOTE: Once a codeAddress field transitions from initial state to
  * JIT'd code, it must not be altered without first halting all
  * threads.  This routine should only be called by the compiler
  * thread.
@@ -860,6 +869,15 @@
 {
     bool res = false;         /* Assume success */
     int i;
+    /*
+     * If previous trace-building attempt failed, force it's head to be
+     * interpret-only.
+     */
+    if (interpState->jitTraceInProgress) {
+        JitEntry *slot = dvmJitLookupAndAdd(interpState->jitTraceInProgress);
+        slot->codeAddress = gDvmJit.interpretTemplate;
+        interpState->jitTraceInProgress = NULL;
+    }
     if (gDvmJit.pJitEntryTable != NULL) {
         /* Two-level filtering scheme */
         for (i=0; i< JIT_TRACE_THRESH_FILTER_SIZE; i++) {
@@ -880,8 +898,8 @@
          * If the compiler is backlogged, or if a debugger or profiler is
          * active, cancel any JIT actions
          */
-        if ( res || (gDvmJit.compilerQueueLength >= gDvmJit.compilerHighWater) ||
-              gDvm.debuggerActive || self->suspendCount
+        if (res || (gDvmJit.compilerQueueLength >= gDvmJit.compilerHighWater)
+            || gDvm.debuggerActive || self->suspendCount
 #if defined(WITH_PROFILER)
                  || gDvm.activeProfilers
 #endif
@@ -920,6 +938,7 @@
             case kJitTSelectRequest:
                  interpState->jitState = kJitTSelect;
                  interpState->currTraceHead = interpState->pc;
+                 interpState->jitTraceInProgress = interpState->pc;
                  interpState->currTraceRun = 0;
                  interpState->totalTraceLen = 0;
                  interpState->currRunHead = interpState->pc;
diff --git a/vm/interp/Jit.h b/vm/interp/Jit.h
index fe740e5..a69a1f0 100644
--- a/vm/interp/Jit.h
+++ b/vm/interp/Jit.h
@@ -64,7 +64,8 @@
 void* dvmSelfVerificationShadowSpaceAlloc(Thread* self);
 void dvmSelfVerificationShadowSpaceFree(Thread* self);
 void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
-                                   InterpState* interpState);
+                                   InterpState* interpState,
+                                   int targetTrace);
 void* dvmSelfVerificationRestoreState(const u2* pc, const void* fp,
                                       SelfVerificationState exitPoint);
 #endif
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index bca89c1..e6c6cfc 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -24,19 +24,19 @@
 
     .global dvmJitToTraceSelect
 dvmJitToTraceSelect:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
     .global dvmJitToBackwardBranch
 dvmJitToBackwardBranch:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
     .global dvmJitToInterpNormal
 dvmJitToInterpNormal:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
@@ -96,14 +96,16 @@
  */
     .global dvmJitToTraceSelect
 dvmJitToTraceSelect:
-    ldr    rPC,[r14, #-1]           @ get our target PC
-    add    rINST,r14,#-5            @ save start of chain branch
+    ldr    rPC,[lr, #-1]           @ get our target PC
+    add    rINST,lr,#-5            @ save start of chain branch
     mov    r0,rPC
     bl     dvmJitGetCodeAddr        @ Is there a translation?
     cmp    r0,#0
     beq    2f
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -134,8 +136,8 @@
  */
     .global dvmJitToInterpNormal
 dvmJitToInterpNormal:
-    ldr    rPC,[r14, #-1]           @ get our target PC
-    add    rINST,r14,#-5            @ save start of chain branch
+    ldr    rPC,[lr, #-1]           @ get our target PC
+    add    rINST,lr,#-5            @ save start of chain branch
 #ifdef EXIT_STATS
     bl     dvmBumpNormal
 #endif
@@ -145,6 +147,8 @@
     beq    toInterpreter            @ go if not, otherwise do chain
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -160,6 +164,8 @@
 #endif
     mov    r0,rPC
     bl     dvmJitGetCodeAddr        @ Is there a translation?
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
     cmp    r0,#0
     bxne   r0                       @ continue native execution if so
 #endif
@@ -208,13 +214,27 @@
     EXPORT_PC()
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
+    mov    r1, rPC                      @ arg1 of translation may need this
+    mov    lr, #0                       @  in case target is HANDLER_INTERPRET
     cmp     r0,#0
-    beq     common_selectTrace
 #if !defined(WITH_SELF_VERIFICATION)
     bxne    r0                          @ jump to the translation
 #else
-    bne     dvmJitSelfVerificationStart @ set up self verification
+    beq     common_selectTrace
+    /*
+     * At this point, we have a target translation.  However, if
+     * that translation is actually the interpret-only pseudo-translation
+     * we want to treat it the same as no translation.
+     */
+    mov     r10, r0                      @ save target
+    bl      dvmCompilerGetInterpretTemplate
+    cmp     r0, r10                      @ special case?
+    bne     dvmJitSelfVerificationStart  @ set up self verification
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+    /* no return */
 #endif
+
 common_selectTrace:
     mov     r2,#kJitTSelectRequest      @ ask for trace selection
     str     r2,[rGLUE,#offGlue_jitState]
@@ -227,12 +247,13 @@
 /*
  * Save PC and registers to shadow memory for self verification mode
  * before jumping to native translation.
+ * On entry, r10 contains the address of the target translation.
  */
 dvmJitSelfVerificationStart:
-    mov     r10, r0                     @ r10 <- dvmJitGetCodeAddr(rPC)
     mov     r0,rPC                      @ r0<- program counter
     mov     r1,rFP                      @ r1<- frame pointer
     mov     r2,rGLUE                    @ r2<- InterpState pointer
+    mov     r3,r10                      @ r3<- target translation
     bl      dvmSelfVerificationSaveState @ save registers to shadow space
     ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
     add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index 6153010..f1729eb 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -9496,19 +9496,19 @@
 
     .global dvmJitToTraceSelect
 dvmJitToTraceSelect:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
     .global dvmJitToBackwardBranch
 dvmJitToBackwardBranch:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
     .global dvmJitToInterpNormal
 dvmJitToInterpNormal:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
@@ -9568,14 +9568,16 @@
  */
     .global dvmJitToTraceSelect
 dvmJitToTraceSelect:
-    ldr    rPC,[r14, #-1]           @ get our target PC
-    add    rINST,r14,#-5            @ save start of chain branch
+    ldr    rPC,[lr, #-1]           @ get our target PC
+    add    rINST,lr,#-5            @ save start of chain branch
     mov    r0,rPC
     bl     dvmJitGetCodeAddr        @ Is there a translation?
     cmp    r0,#0
     beq    2f
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9606,8 +9608,8 @@
  */
     .global dvmJitToInterpNormal
 dvmJitToInterpNormal:
-    ldr    rPC,[r14, #-1]           @ get our target PC
-    add    rINST,r14,#-5            @ save start of chain branch
+    ldr    rPC,[lr, #-1]           @ get our target PC
+    add    rINST,lr,#-5            @ save start of chain branch
 #ifdef EXIT_STATS
     bl     dvmBumpNormal
 #endif
@@ -9617,6 +9619,8 @@
     beq    toInterpreter            @ go if not, otherwise do chain
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9632,6 +9636,8 @@
 #endif
     mov    r0,rPC
     bl     dvmJitGetCodeAddr        @ Is there a translation?
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
     cmp    r0,#0
     bxne   r0                       @ continue native execution if so
 #endif
@@ -9680,13 +9686,27 @@
     EXPORT_PC()
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
+    mov    r1, rPC                      @ arg1 of translation may need this
+    mov    lr, #0                       @  in case target is HANDLER_INTERPRET
     cmp     r0,#0
-    beq     common_selectTrace
 #if !defined(WITH_SELF_VERIFICATION)
     bxne    r0                          @ jump to the translation
 #else
-    bne     dvmJitSelfVerificationStart @ set up self verification
+    beq     common_selectTrace
+    /*
+     * At this point, we have a target translation.  However, if
+     * that translation is actually the interpret-only pseudo-translation
+     * we want to treat it the same as no translation.
+     */
+    mov     r10, r0                      @ save target
+    bl      dvmCompilerGetInterpretTemplate
+    cmp     r0, r10                      @ special case?
+    bne     dvmJitSelfVerificationStart  @ set up self verification
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+    /* no return */
 #endif
+
 common_selectTrace:
     mov     r2,#kJitTSelectRequest      @ ask for trace selection
     str     r2,[rGLUE,#offGlue_jitState]
@@ -9699,12 +9719,13 @@
 /*
  * Save PC and registers to shadow memory for self verification mode
  * before jumping to native translation.
+ * On entry, r10 contains the address of the target translation.
  */
 dvmJitSelfVerificationStart:
-    mov     r10, r0                     @ r10 <- dvmJitGetCodeAddr(rPC)
     mov     r0,rPC                      @ r0<- program counter
     mov     r1,rFP                      @ r1<- frame pointer
     mov     r2,rGLUE                    @ r2<- InterpState pointer
+    mov     r3,r10                      @ r3<- target translation
     bl      dvmSelfVerificationSaveState @ save registers to shadow space
     ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
     add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index dde4bd5..5cf8cca 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -9014,19 +9014,19 @@
 
     .global dvmJitToTraceSelect
 dvmJitToTraceSelect:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
     .global dvmJitToBackwardBranch
 dvmJitToBackwardBranch:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
     .global dvmJitToInterpNormal
 dvmJitToInterpNormal:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
@@ -9086,14 +9086,16 @@
  */
     .global dvmJitToTraceSelect
 dvmJitToTraceSelect:
-    ldr    rPC,[r14, #-1]           @ get our target PC
-    add    rINST,r14,#-5            @ save start of chain branch
+    ldr    rPC,[lr, #-1]           @ get our target PC
+    add    rINST,lr,#-5            @ save start of chain branch
     mov    r0,rPC
     bl     dvmJitGetCodeAddr        @ Is there a translation?
     cmp    r0,#0
     beq    2f
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9124,8 +9126,8 @@
  */
     .global dvmJitToInterpNormal
 dvmJitToInterpNormal:
-    ldr    rPC,[r14, #-1]           @ get our target PC
-    add    rINST,r14,#-5            @ save start of chain branch
+    ldr    rPC,[lr, #-1]           @ get our target PC
+    add    rINST,lr,#-5            @ save start of chain branch
 #ifdef EXIT_STATS
     bl     dvmBumpNormal
 #endif
@@ -9135,6 +9137,8 @@
     beq    toInterpreter            @ go if not, otherwise do chain
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9150,6 +9154,8 @@
 #endif
     mov    r0,rPC
     bl     dvmJitGetCodeAddr        @ Is there a translation?
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
     cmp    r0,#0
     bxne   r0                       @ continue native execution if so
 #endif
@@ -9198,13 +9204,27 @@
     EXPORT_PC()
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
+    mov    r1, rPC                      @ arg1 of translation may need this
+    mov    lr, #0                       @  in case target is HANDLER_INTERPRET
     cmp     r0,#0
-    beq     common_selectTrace
 #if !defined(WITH_SELF_VERIFICATION)
     bxne    r0                          @ jump to the translation
 #else
-    bne     dvmJitSelfVerificationStart @ set up self verification
+    beq     common_selectTrace
+    /*
+     * At this point, we have a target translation.  However, if
+     * that translation is actually the interpret-only pseudo-translation
+     * we want to treat it the same as no translation.
+     */
+    mov     r10, r0                      @ save target
+    bl      dvmCompilerGetInterpretTemplate
+    cmp     r0, r10                      @ special case?
+    bne     dvmJitSelfVerificationStart  @ set up self verification
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+    /* no return */
 #endif
+
 common_selectTrace:
     mov     r2,#kJitTSelectRequest      @ ask for trace selection
     str     r2,[rGLUE,#offGlue_jitState]
@@ -9217,12 +9237,13 @@
 /*
  * Save PC and registers to shadow memory for self verification mode
  * before jumping to native translation.
+ * On entry, r10 contains the address of the target translation.
  */
 dvmJitSelfVerificationStart:
-    mov     r10, r0                     @ r10 <- dvmJitGetCodeAddr(rPC)
     mov     r0,rPC                      @ r0<- program counter
     mov     r1,rFP                      @ r1<- frame pointer
     mov     r2,rGLUE                    @ r2<- InterpState pointer
+    mov     r3,r10                      @ r3<- target translation
     bl      dvmSelfVerificationSaveState @ save registers to shadow space
     ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
     add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index b7d8a6c..5e1ed1c 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -9490,19 +9490,19 @@
 
     .global dvmJitToTraceSelect
 dvmJitToTraceSelect:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
     .global dvmJitToBackwardBranch
 dvmJitToBackwardBranch:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
     .global dvmJitToInterpNormal
 dvmJitToInterpNormal:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
@@ -9562,14 +9562,16 @@
  */
     .global dvmJitToTraceSelect
 dvmJitToTraceSelect:
-    ldr    rPC,[r14, #-1]           @ get our target PC
-    add    rINST,r14,#-5            @ save start of chain branch
+    ldr    rPC,[lr, #-1]           @ get our target PC
+    add    rINST,lr,#-5            @ save start of chain branch
     mov    r0,rPC
     bl     dvmJitGetCodeAddr        @ Is there a translation?
     cmp    r0,#0
     beq    2f
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9600,8 +9602,8 @@
  */
     .global dvmJitToInterpNormal
 dvmJitToInterpNormal:
-    ldr    rPC,[r14, #-1]           @ get our target PC
-    add    rINST,r14,#-5            @ save start of chain branch
+    ldr    rPC,[lr, #-1]           @ get our target PC
+    add    rINST,lr,#-5            @ save start of chain branch
 #ifdef EXIT_STATS
     bl     dvmBumpNormal
 #endif
@@ -9611,6 +9613,8 @@
     beq    toInterpreter            @ go if not, otherwise do chain
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9626,6 +9630,8 @@
 #endif
     mov    r0,rPC
     bl     dvmJitGetCodeAddr        @ Is there a translation?
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
     cmp    r0,#0
     bxne   r0                       @ continue native execution if so
 #endif
@@ -9674,13 +9680,27 @@
     EXPORT_PC()
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
+    mov    r1, rPC                      @ arg1 of translation may need this
+    mov    lr, #0                       @  in case target is HANDLER_INTERPRET
     cmp     r0,#0
-    beq     common_selectTrace
 #if !defined(WITH_SELF_VERIFICATION)
     bxne    r0                          @ jump to the translation
 #else
-    bne     dvmJitSelfVerificationStart @ set up self verification
+    beq     common_selectTrace
+    /*
+     * At this point, we have a target translation.  However, if
+     * that translation is actually the interpret-only pseudo-translation
+     * we want to treat it the same as no translation.
+     */
+    mov     r10, r0                      @ save target
+    bl      dvmCompilerGetInterpretTemplate
+    cmp     r0, r10                      @ special case?
+    bne     dvmJitSelfVerificationStart  @ set up self verification
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+    /* no return */
 #endif
+
 common_selectTrace:
     mov     r2,#kJitTSelectRequest      @ ask for trace selection
     str     r2,[rGLUE,#offGlue_jitState]
@@ -9693,12 +9713,13 @@
 /*
  * Save PC and registers to shadow memory for self verification mode
  * before jumping to native translation.
+ * On entry, r10 contains the address of the target translation.
  */
 dvmJitSelfVerificationStart:
-    mov     r10, r0                     @ r10 <- dvmJitGetCodeAddr(rPC)
     mov     r0,rPC                      @ r0<- program counter
     mov     r1,rFP                      @ r1<- frame pointer
     mov     r2,rGLUE                    @ r2<- InterpState pointer
+    mov     r3,r10                      @ r3<- target translation
     bl      dvmSelfVerificationSaveState @ save registers to shadow space
     ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
     add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index ea9e713..7af0a79 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -8950,19 +8950,19 @@
 
     .global dvmJitToTraceSelect
 dvmJitToTraceSelect:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
     .global dvmJitToBackwardBranch
 dvmJitToBackwardBranch:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
     .global dvmJitToInterpNormal
 dvmJitToInterpNormal:
-    ldr    r0,[r14, #-1]                @ pass our target PC
+    ldr    r0,[lr, #-1]                 @ pass our target PC
     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
     b      dvmJitSelfVerificationEnd    @ doesn't return
 
@@ -9022,14 +9022,16 @@
  */
     .global dvmJitToTraceSelect
 dvmJitToTraceSelect:
-    ldr    rPC,[r14, #-1]           @ get our target PC
-    add    rINST,r14,#-5            @ save start of chain branch
+    ldr    rPC,[lr, #-1]           @ get our target PC
+    add    rINST,lr,#-5            @ save start of chain branch
     mov    r0,rPC
     bl     dvmJitGetCodeAddr        @ Is there a translation?
     cmp    r0,#0
     beq    2f
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9060,8 +9062,8 @@
  */
     .global dvmJitToInterpNormal
 dvmJitToInterpNormal:
-    ldr    rPC,[r14, #-1]           @ get our target PC
-    add    rINST,r14,#-5            @ save start of chain branch
+    ldr    rPC,[lr, #-1]           @ get our target PC
+    add    rINST,lr,#-5            @ save start of chain branch
 #ifdef EXIT_STATS
     bl     dvmBumpNormal
 #endif
@@ -9071,6 +9073,8 @@
     beq    toInterpreter            @ go if not, otherwise do chain
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9086,6 +9090,8 @@
 #endif
     mov    r0,rPC
     bl     dvmJitGetCodeAddr        @ Is there a translation?
+    mov    r1, rPC                  @ arg1 of translation may need this
+    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
     cmp    r0,#0
     bxne   r0                       @ continue native execution if so
 #endif
@@ -9134,13 +9140,27 @@
     EXPORT_PC()
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
+    mov    r1, rPC                      @ arg1 of translation may need this
+    mov    lr, #0                       @  in case target is HANDLER_INTERPRET
     cmp     r0,#0
-    beq     common_selectTrace
 #if !defined(WITH_SELF_VERIFICATION)
     bxne    r0                          @ jump to the translation
 #else
-    bne     dvmJitSelfVerificationStart @ set up self verification
+    beq     common_selectTrace
+    /*
+     * At this point, we have a target translation.  However, if
+     * that translation is actually the interpret-only pseudo-translation
+     * we want to treat it the same as no translation.
+     */
+    mov     r10, r0                      @ save target
+    bl      dvmCompilerGetInterpretTemplate
+    cmp     r0, r10                      @ special case?
+    bne     dvmJitSelfVerificationStart  @ set up self verification
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+    /* no return */
 #endif
+
 common_selectTrace:
     mov     r2,#kJitTSelectRequest      @ ask for trace selection
     str     r2,[rGLUE,#offGlue_jitState]
@@ -9153,12 +9173,13 @@
 /*
  * Save PC and registers to shadow memory for self verification mode
  * before jumping to native translation.
+ * On entry, r10 contains the address of the target translation.
  */
 dvmJitSelfVerificationStart:
-    mov     r10, r0                     @ r10 <- dvmJitGetCodeAddr(rPC)
     mov     r0,rPC                      @ r0<- program counter
     mov     r1,rFP                      @ r1<- frame pointer
     mov     r2,rGLUE                    @ r2<- InterpState pointer
+    mov     r3,r10                      @ r3<- target translation
     bl      dvmSelfVerificationSaveState @ save registers to shadow space
     ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
     add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space