Instrumentation support for x86.

Change-Id: I8f960973d7459491ccd4b44d5bd66407a2ab816e
diff --git a/src/oat/runtime/x86/runtime_support_x86.S b/src/oat/runtime/x86/runtime_support_x86.S
index 1d24606..379fcce 100644
--- a/src/oat/runtime/x86/runtime_support_x86.S
+++ b/src/oat/runtime/x86/runtime_support_x86.S
@@ -374,15 +374,20 @@
 TWO_ARG_DOWNCALL art_initialize_type_from_code, artInitializeTypeFromCode, RETURN_IF_EAX_NOT_ZERO
 TWO_ARG_DOWNCALL art_initialize_type_and_verify_access_from_code, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_EAX_NOT_ZERO
 
+    /*
+     * On entry, eax and ecx must be preserved, edx is dex PC
+     */
 DEFINE_FUNCTION art_update_debugger
-    mov  %eax, %ebx               // stash away eax so that it's saved as if it were an argument
+    mov %eax, %ebx                // stash away eax so that it's saved as if it were an argument
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+    subl LITERAL(4), %esp         // alignment padding
     pushl %esp                    // pass arg2 (sp)
     pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
     pushl %edx                    // pass arg0 (dex pc)
     call SYMBOL(artUpdateDebuggerFromCode) // artUpdateDebuggerFromCode(int32_t, Thread*, Method**)
+    addl LITERAL(16), %esp        // pop arguments
     RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
-    mov  %ebx, %eax               // restore original eax
+    mov %ebx, %eax                // restore original eax
     ret
 
 DEFINE_FUNCTION art_get_and_clear_exception
@@ -745,13 +750,68 @@
     addl LITERAL(44), %esp        // pop arguments
     RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
 
+    /*
+     * Routine that intercepts method calls and returns.
+     */
 DEFINE_FUNCTION art_instrumentation_entry_from_code
-    ret
+    xchgl %eax, (%esp)            // place LR in eax, save eax
+    pushl %ecx                    // save ecx
+    pushl %edx                    // save edx
+    pushl %ebx                    // save ebx
+    lea   16(%esp), %edx          // remember bottom of caller's frame
+    pushl %eax                    // pass LR
+    pushl %edx                    // pass SP
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    pushl 24(%esp)                // pass Method*
+    call  SYMBOL(artInstrumentationMethodEntryFromCode) // (Method*, Thread*, SP, LR)
+    addl  LITERAL(16), %esp       // pop arguments
+    popl  %ebx                    // restore ebx
+    popl  %edx                    // restore edx
+    movl  (%esp), %ecx            // restore ecx (without popping)
+    movl  %eax, (%esp)            // place method's code pointer on stack
+    movl  4(%esp), %eax           // restore eax (without popping)
+    movl  LITERAL(SYMBOL(art_instrumentation_exit_from_code)), 4(%esp)
+                                  // place instrumentation exit as return pc
+    ret                           // call method (and pop)
 DEFINE_FUNCTION art_instrumentation_exit_from_code
-    ret
+    mov   %esp, %ecx              // remember bottom of caller's frame
+    pushl %edx                    // save return value
+    pushl %eax                    // save other half of return value
+    pushl %ecx                    // pass SP
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current
+    call  SYMBOL(artInstrumentationMethodExitFromCode)  // (Thread*, SP)
+    mov   %eax, %ecx              // move returned link register
+    // TODO: Set link register for deopt
+    addl  LITERAL(8), %esp        // pop arguments
+    popl  %eax                    // restore return value
+    popl  %edx                    // restore other half of return value
+    jmp   *%ecx                   // return
 
+    /*
+     * The thread's enter interpreter flag is set and so we should transition to the interpreter
+     * rather than allow execution to continue in the frame below. There may be live results in
+     * registers depending on how complete the operation is when we safepoint - for example, a
+     * set operation may have completed while a get operation needs writing back into the vregs.
+     */
 DEFINE_FUNCTION art_deoptimize
-    ret
+    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
+    pushl %esp                    // pass SP
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    pushl %edx                    // push half of return value
+    pushl %eax                    // push other half of return value
+    call SYMBOL(artDeoptimize)    // artDeoptimize(return value, Thread*, SP)
+                                  // Returns caller method's frame size.
+    addl LITERAL(16), %esp        // pop arguments
+    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+    testl %eax, %eax              // Was the caller an upcall?
+    jz    1f                      // Return if caller was upcall.
+    lea   (%esp, %eax), %edx      // edx == bottom of caller's frame.
+    mov   %edx, %esp              // Remove frame.
+    SETUP_REF_ONLY_CALLEE_SAVE_FRAME
+    call SYMBOL(artEnterInterpreterFromDeoptimize) // Enter interpreter, callee-save ends stack fragment.
+    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+1:
+    ret                           // Return to caller.
 
     /*
      * String's indexOf.