- // save main registers
-#if defined(__APPLE__)
- "stmfd sp!, {r4, r5, r6, r7, lr}\n"
- "mov r0, r7\n" // stub's frame
- "stmfd sp!, {r8, r10, r11}\n"
-#else
- "mov ip, sp\n"
- "stmfd sp!, {fp, ip, lr, pc}\n"
- "sub fp, ip, #4\n"
-#endif // __APPLE__
- // arguments to Compilation Callback
- // r0 - our lr (address of the call instruction in stub plus 4)
- // r1 - stub's lr (address of instruction that called the stub plus 4)
-#if defined(__APPLE__)
- "mov r0, r7\n" // stub's frame
-#else
- "mov r0, fp\n" // stub's frame
-#endif // __APPLE__
- "mov r1, lr\n" // stub's lr
- "bl " ASMPREFIX "ARMCompilationCallbackC\n"
- // restore main registers
-#if defined(__APPLE__)
- "ldmfd sp!, {r8, r10, r11}\n"
- "ldmfd sp!, {r4, r5, r6, r7, pc}\n"
-#else
- "ldmfd sp, {fp, sp, pc}\n"
-#endif // __APPLE__
+ // Save caller saved registers since they may contain stuff
+ // for the real target function right now. We have to act as if this
+ // whole compilation callback doesn't exist as far as the caller is
+ // concerned, so we can't just preserve the callee saved regs.
+ "push {r0, r1, r2, r3, lr}\n"
+ // The LR contains the address of the stub function on entry.
+ // pass it as the argument to the C part of the callback
+ "mov r0, lr\n"
+ "sub sp, sp, #4\n"
+ // Call the C portion of the callback
+ "bl " ASMPREFIX "ARMCompilationCallbackC\n"
+ "add sp, sp, #4\n"
+ // Restoring the LR to the return address of the function that invoked
+ // the stub and de-allocating the stack space for it requires us to
+ // swap the two saved LR values on the stack, as they're backwards
+ // for what we need since the pop instruction has a pre-determined
+ // order for the registers.
+ // +--------+
+ // 0 | LR | Original return address
+ // +--------+
+ // 1 | LR | Stub address (start of stub)
+ // 2-5 | R3..R0 | Saved registers (we need to preserve all regs)
+ // +--------+
+ //
+ // We need to exchange the values in slots 0 and 1 so we can
+ // return to the address in slot 1 with the address in slot 0
+ // restored to the LR.
+ "ldr r0, [sp,#20]\n"
+ "ldr r1, [sp,#16]\n"
+ "str r1, [sp,#20]\n"
+ "str r0, [sp,#16]\n"
+ // Return to the (newly modified) stub to invoke the real function.
+ // The above twiddling of the saved return addresses allows us to
+ // deallocate everything, including the LR the stub saved, all in one
+ // pop instruction.
+ "pop {r0, r1, r2, r3, lr, pc}\n"