summaryrefslogtreecommitdiff
path: root/src/vm/i386/cgenx86.cpp
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2017-04-13 14:17:19 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2017-04-13 14:17:19 +0900
commita56e30c8d33048216567753d9d3fefc2152af8ac (patch)
tree7e5d979695fc4a431740982eb1cfecc2898b23a5 /src/vm/i386/cgenx86.cpp
parent4b11dc566a5bbfa1378d6266525c281b028abcc8 (diff)
downloadcoreclr-a56e30c8d33048216567753d9d3fefc2152af8ac.tar.gz
coreclr-a56e30c8d33048216567753d9d3fefc2152af8ac.tar.bz2
coreclr-a56e30c8d33048216567753d9d3fefc2152af8ac.zip
Imported Upstream version 2.0.0.11353upstream/2.0.0.11353
Diffstat (limited to 'src/vm/i386/cgenx86.cpp')
-rw-r--r--src/vm/i386/cgenx86.cpp590
1 files changed, 43 insertions, 547 deletions
diff --git a/src/vm/i386/cgenx86.cpp b/src/vm/i386/cgenx86.cpp
index 528629c3a2..4c83265ff4 100644
--- a/src/vm/i386/cgenx86.cpp
+++ b/src/vm/i386/cgenx86.cpp
@@ -24,9 +24,6 @@
#include "array.h"
#include "jitinterface.h"
#include "codeman.h"
-#ifdef FEATURE_REMOTING
-#include "remoting.h"
-#endif
#include "dbginterface.h"
#include "eeprofinterfaces.h"
#include "eeconfig.h"
@@ -301,6 +298,7 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
MethodDesc * pFunc = GetFunction();
_ASSERTE(pFunc != NULL);
+
UpdateRegDisplayHelper(pRD, pFunc->CbStackPop());
LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP));
@@ -326,11 +324,14 @@ void TransitionFrame::UpdateRegDisplayHelper(const PREGDISPLAY pRD, UINT cbStack
#ifdef WIN64EXCEPTIONS
+ DWORD CallerSP = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
+
pRD->IsCallerContextValid = FALSE;
pRD->IsCallerSPValid = FALSE;
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);;
- pRD->pCurrentContext->Esp = GetSP();
+ pRD->pCurrentContext->Esp = CallerSP;
+ pRD->pCurrentContext->ResumeEsp = CallerSP + cbStackPop;
UpdateRegDisplayFromCalleeSavedRegisters(pRD, regs);
ClearRegDisplayArgumentAndScratchRegisters(pRD);
@@ -383,7 +384,7 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
#endif // DACCESS_COMPILE
pRD->pCurrentContext->Eip = pRD->ControlPC = m_MachState.GetRetAddr();
- pRD->pCurrentContext->Esp = pRD->SP = (DWORD) m_MachState.esp();
+ pRD->pCurrentContext->Esp = pRD->pCurrentContext->ResumeEsp = pRD->SP = (DWORD) m_MachState.esp();
#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContext->regname = *((DWORD*) m_MachState.p##regname());
ENUM_CALLEE_SAVED_REGISTERS();
@@ -522,6 +523,8 @@ void ExternalMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
UpdateRegDisplayHelper(pRD, CbStackPopUsingGCRefMap(GetGCRefMap()));
+ LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ExternalMethodFrane::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP));
+
RETURN;
}
@@ -560,6 +563,8 @@ void StubDispatchFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
pRD->ControlPC = GetAdjustedCallAddress(pRD->ControlPC);
}
+ LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK StubDispatchFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP));
+
RETURN;
}
@@ -593,9 +598,6 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
}
CONTRACT_END;
- // reset pContext; it's only valid for active (top-most) frame
- pRD->pContext = NULL;
-
pRD->PCTAddr = GetReturnAddressPtr();
#ifdef WIN64EXCEPTIONS
@@ -618,6 +620,9 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
#else // WIN64EXCEPTIONS
+ // reset pContext; it's only valid for active (top-most) frame
+ pRD->pContext = NULL;
+
CalleeSavedRegisters* regs = GetCalleeSavedRegisters();
#define CALLEE_SAVED_REGISTER(regname) pRD->p##regname = (DWORD*) &regs->regname;
@@ -683,7 +688,8 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary.
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);
- pRD->pCurrentContext->Esp = (DWORD) dac_cast<TADDR>(m_pCallSiteSP) + stackArgSize;
+ pRD->pCurrentContext->Esp = (DWORD) dac_cast<TADDR>(m_pCallSiteSP);
+ pRD->pCurrentContext->ResumeEsp = (DWORD) dac_cast<TADDR>(m_pCallSiteSP) + stackArgSize;
pRD->pCurrentContext->Ebp = (DWORD) m_pCalleeSavedFP;
ClearRegDisplayArgumentAndScratchRegisters(pRD);
@@ -740,7 +746,7 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
#ifdef WIN64EXCEPTIONS
- memcpy(pRD->pCurrentContext, &m_Regs, sizeof(CONTEXT));
+ CopyMemory(pRD->pCurrentContext, m_Regs, sizeof(T_CONTEXT));
pRD->SP = m_Regs->Esp;
pRD->ControlPC = m_Regs->Eip;
@@ -798,10 +804,13 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
#endif // !WIN64EXCEPTIONS
+ LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK ResumableFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP));
+
RETURN;
}
// The HijackFrame has to know the registers that are pushed by OnHijackTripThread
+// -> HijackFrame::UpdateRegDisplay should restore all the registers pushed by OnHijackTripThread
void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
{
CONTRACTL {
@@ -820,21 +829,17 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary.
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);
- pRD->pCurrentContext->Esp = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
-
-#define CALLEE_SAVED_REGISTER(reg) pRD->pCurrentContext->reg = m_Args->reg;
- ENUM_CALLEE_SAVED_REGISTERS();
-#undef CALLEE_SAVED_REGISTER
+ pRD->pCurrentContext->Esp = pRD->pCurrentContext->ResumeEsp = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
-#define CALLEE_SAVED_REGISTER(reg) pRD->pCurrentContextPointers->reg = NULL;
+#define RESTORE_REG(reg) { pRD->pCurrentContext->reg = m_Args->reg; pRD->pCurrentContextPointers->reg = &m_Args->reg; }
+#define CALLEE_SAVED_REGISTER(reg) RESTORE_REG(reg)
ENUM_CALLEE_SAVED_REGISTERS();
#undef CALLEE_SAVED_REGISTER
-#define ARGUMENT_AND_SCRATCH_REGISTER(reg) pRD->pCurrentContextPointers->reg = NULL;
+#define ARGUMENT_AND_SCRATCH_REGISTER(reg) RESTORE_REG(reg)
ENUM_ARGUMENT_AND_SCRATCH_REGISTERS();
#undef ARGUMENT_AND_SCRATCH_REGISTER
-
- pRD->pCurrentContextPointers->Eax = (PDWORD) &m_Args->Eax;
+#undef RESTORE_REG
SyncRegDisplayToCurrentContext(pRD);
@@ -843,18 +848,22 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
// This only describes the top-most frame
pRD->pContext = NULL;
- pRD->pEdi = &m_Args->Edi;
- pRD->pEsi = &m_Args->Esi;
- pRD->pEbx = &m_Args->Ebx;
- pRD->pEdx = &m_Args->Edx;
- pRD->pEcx = &m_Args->Ecx;
- pRD->pEax = &m_Args->Eax;
+#define RESTORE_REG(reg) { pRD->p##reg = &m_Args->reg; }
+#define CALLEE_SAVED_REGISTER(reg) RESTORE_REG(reg)
+ ENUM_CALLEE_SAVED_REGISTERS();
+#undef CALLEE_SAVED_REGISTER
+
+#define ARGUMENT_AND_SCRATCH_REGISTER(reg) RESTORE_REG(reg)
+ ENUM_ARGUMENT_AND_SCRATCH_REGISTERS();
+#undef ARGUMENT_AND_SCRATCH_REGISTER
+#undef RESTORE_REG
- pRD->pEbp = &m_Args->Ebp;
pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr);
pRD->SP = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
#endif // WIN64EXCEPTIONS
+
+ LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK HijackFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP));
}
#endif // FEATURE_HIJACK
@@ -874,6 +883,8 @@ void PInvokeCalliFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
VASigCookie *pVASigCookie = GetVASigCookie();
UpdateRegDisplayHelper(pRD, pVASigCookie->sizeOfArgs+sizeof(int));
+ LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK PInvokeCalliFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP));
+
RETURN;
}
@@ -889,8 +900,6 @@ void TailCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
}
CONTRACT_END;
- // reset pContext; it's only valid for active (top-most) frame
- pRD->pContext = NULL;
pRD->PCTAddr = GetReturnAddressPtr();
#ifdef WIN64EXCEPTIONS
@@ -899,7 +908,7 @@ void TailCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary.
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);
- pRD->pCurrentContext->Esp = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
+ pRD->pCurrentContext->Esp = pRD->pCurrentContext->ResumeEsp = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
UpdateRegDisplayFromCalleeSavedRegisters(pRD, &m_regs);
ClearRegDisplayArgumentAndScratchRegisters(pRD);
@@ -908,6 +917,9 @@ void TailCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
#else
+ // reset pContext; it's only valid for active (top-most) frame
+ pRD->pContext = NULL;
+
#define CALLEE_SAVED_REGISTER(regname) pRD->p##regname = (DWORD*) &m_regs.regname;
ENUM_CALLEE_SAVED_REGISTERS();
#undef CALLEE_SAVED_REGISTER
@@ -1068,522 +1080,6 @@ Stub *GenerateInitPInvokeFrameHelper()
RETURN psl->Link(SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap());
}
-#ifdef FEATURE_INCLUDE_ALL_INTERFACES
-
-static void STDCALL LeaveRuntimeHelperWithFrame (Thread *pThread, size_t target, Frame *pFrame)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_PREEMPTIVE;
- ENTRY_POINT;
- }
- CONTRACTL_END;
-
- Thread::LeaveRuntimeThrowComplus(target);
- GCX_COOP_THREAD_EXISTS(pThread);
- pFrame->Push(pThread);
-
-}
-
-static void STDCALL EnterRuntimeHelperWithFrame (Thread *pThread, Frame *pFrame)
-{
- // make sure we restore the original Win32 last error before leaving this function - we are
- // called right after returning from the P/Invoke target and the error has not been saved yet
- BEGIN_PRESERVE_LAST_ERROR;
-
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_PREEMPTIVE;
- ENTRY_POINT;
- }
- CONTRACTL_END;
-
- {
- HRESULT hr = Thread::EnterRuntimeNoThrow();
- GCX_COOP_THREAD_EXISTS(pThread);
- if (FAILED(hr))
- {
- INSTALL_UNWIND_AND_CONTINUE_HANDLER;
- ThrowHR (hr);
- UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
- }
-
- pFrame->Pop(pThread);
- }
-
- END_PRESERVE_LAST_ERROR;
-}
-
-// "ip" is the return address
-// This function disassembles the code at the return address to determine
-// how many arguments to pop off.
-// Returns the number of DWORDs that should be popped off on return.
-
-static int STDCALL GetStackSizeForVarArgCall(BYTE* ip)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- int retValue = 0;
- //BEGIN_ENTRYPOINT_VOIDRET;
-
- // The instruction immediately following the call may be a move into esp used for
- // P/Invoke stack resilience. For caller-pop calls it's always mov esp, [ebp-n].
- if (ip[0] == 0x8b)
- {
- if (ip[1] == 0x65)
- {
- // mov esp, [ebp+disp8]
- ip += 3;
- }
- else if (ip[1] == 0xa5)
- {
- // mov esp, [ebp+disp32]
- ip += 6;
- }
- }
-
- if (ip[0] == 0x81 && ip[1] == 0xc4)
- {
- // add esp, imm32
- retValue = (*(int*)&ip[2])/4;
- }
- else if (ip[0] == 0x83 && ip[1] == 0xc4)
- {
- // add esp, imm8
- retValue = ip[2]/4;
- }
- else if (ip[0] == 0x59)
- {
- // pop ecx
- retValue = 1;
- }
- else
- {
- retValue = 0;
- }
- //END_ENTRYPOINT_VOIDRET;
- return retValue;
-}
-
-void LeaveRuntimeStackProbeOnly()
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- ENTRY_POINT;
- }
- CONTRACTL_END;
-
-#ifdef FEATURE_STACK_PROBE
- RetailStackProbe(ADJUST_PROBE(DEFAULT_ENTRY_PROBE_AMOUNT));
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Hosting stub for calls from CLR code to unmanaged code
-//
-// We push a LeaveRuntimeFrame, and then re-push all the arguments.
-// Note that we have to support all the different native calling conventions
-// viz. stdcall, thiscall, cdecl, varargs
-
-#if 0
-
-This is a diagramatic description of what the stub does:
-
- (lower addresses)
-
- | |
- +----------------+ <--- ESP
- | |
- | copied |
- | arguments |
- | |
- | |
- +----------------+
- | EDX |
- | ECX |
- +----------------+
-| | | GSCookie |
-| | +----------------+ <--- ESI
-| | | vptr |
-| | +----------------+
-| | | m_Next |
-| | +----------------+
-| | | EDI | Scratch register
-| | | ESI | For LeaveRuntimeFrame*
-| | | EBX | For Thread*
-| | +----------------+ <--- EBP
-| | | EBP |
-+----------------+ <---ESP +----------------+
-| ret addr | | ret addr |
-+----------------+ +----------------+
-| | | |
-| arguments | | arguments |
-| | | |
-| | | |
-+----------------+ +----------------+
-| | | |
-| caller's frame | | caller's frame |
-| | | |
-
- (higher addresses)
-
- Stack on entry Stack before the call
- to this stub. to unmanaged code.
-
-#endif
-
-//-----------------------------------------------------------------------------
-// This the layout of the frame of the stub
-
-struct StubForHostStackFrame
-{
- LPVOID m_outgingArgs[1];
- ArgumentRegisters m_argumentRegisters;
- GSCookie m_gsCookie;
- LeaveRuntimeFrame m_LeaveRuntimeFrame;
- CalleeSavedRegisters m_calleeSavedRegisters;
- LPVOID m_retAddr;
- LPVOID m_incomingArgs[1];
-
-public:
-
- // Where does the FP/EBP point to?
- static INT32 GetFPpositionOffset()
- {
- LIMITED_METHOD_CONTRACT;
- return offsetof(StubForHostStackFrame, m_calleeSavedRegisters) +
- offsetof(CalleeSavedRegisters, Ebp);
- }
-
- static INT32 GetFPrelOffsOfArgumentRegisters()
- {
- LIMITED_METHOD_CONTRACT;
- return offsetof(StubForHostStackFrame, m_argumentRegisters) - GetFPpositionOffset();
- }
-
- static INT32 GetFPrelOffsOfCalleeSavedRegisters()
- {
- LIMITED_METHOD_CONTRACT;
- return offsetof(StubForHostStackFrame, m_calleeSavedRegisters) - GetFPpositionOffset();
- }
-
- static INT32 GetFPrelOffsOfRetAddr()
- {
- LIMITED_METHOD_CONTRACT;
- return offsetof(StubForHostStackFrame, m_retAddr) - GetFPpositionOffset();
- }
-
- static INT32 GetFPrelOffsOfIncomingArgs()
- {
- LIMITED_METHOD_CONTRACT;
- return offsetof(StubForHostStackFrame, m_incomingArgs) - GetFPpositionOffset();
- }
-};
-
-static Stub *GenerateStubForHostWorker(LoaderHeap *pHeap,
- LPVOID pNativeTarget, // NULL to fetch from the last pushed argument (COM)
- Stub *pInnerStub, // stub to call instead of pNativeTarget, or NULL
- LONG dwComSlot, // only valid if pNativeTarget is NULL
- WORD wStackArgumentSize, // -1 for varargs
- WORD wStackPopSize) // 0 for cdecl
-{
- STANDARD_VM_CONTRACT;
-
- // We need to call LeaveRuntime before the target, and EnterRuntime after the target
- CPUSTUBLINKER sl;
-
- sl.X86EmitPushEBPframe();
-
- // save EBX, ESI, EDI
- sl.X86EmitPushReg(kEBX);
- sl.X86EmitPushReg(kESI);
- sl.X86EmitPushReg(kEDI);
-
- // Frame
- sl.X86EmitPushReg(kDummyPushReg); // m_Next
- sl.X86EmitPushImm32((UINT)(size_t)LeaveRuntimeFrame::GetMethodFrameVPtr());
-
- // mov esi, esp; esi is Frame
- sl.X86EmitMovRegSP(kESI);
-
- sl.X86EmitPushImmPtr((LPVOID)GetProcessGSCookie());
-
- // Save outgoing arguments on the stack
- sl.X86EmitPushReg(kECX);
- sl.X86EmitPushReg(kEDX);
-
- INT32 offs = 0;
- if (wStackArgumentSize == (WORD)-1)
- {
- // Re-push the return address as an argument to GetStackSizeForVarArgCall()
- // This will return the number of stack arguments (in DWORDs)
- sl.X86EmitIndexPush(kEBP, StubForHostStackFrame::GetFPrelOffsOfRetAddr());
- sl.X86EmitCall(sl.NewExternalCodeLabel((LPVOID)GetStackSizeForVarArgCall), 4);
-
- // We generate the following code sequence to re-push all the arguments
- //
- // Note that we cannot use "sub ESP, EAX" as ESP might jump past the
- // stack guard-page.
- //
- // cmp EAX, 0
- // LoopTop:
- // jz LoopDone
- // push dword ptr[EBP + EAX*4 + 4]
- // sub EAX, 1
- // jmp LoopTop
- // LoopDone:
- // ...
-
- sl.X86EmitCmpRegImm32(kEAX, 0);
- CodeLabel * pLoopTop = sl.EmitNewCodeLabel();
- CodeLabel * pLoopDone = sl.NewCodeLabel();
- sl.X86EmitCondJump(pLoopDone, X86CondCode::kJZ);
- sl.X86EmitBaseIndexPush(kEBP, kEAX, 4, StubForHostStackFrame::GetFPrelOffsOfIncomingArgs() - sizeof(LPVOID));
- sl.X86EmitSubReg(kEAX, 1);
- sl.X86EmitNearJump(pLoopTop);
- sl.EmitLabel(pLoopDone);
- }
- else
- {
- offs = StubForHostStackFrame::GetFPrelOffsOfIncomingArgs() + wStackArgumentSize;
-
- int numStackSlots = wStackArgumentSize / sizeof(LPVOID);
- for (int i = 0; i < numStackSlots; i++) {
- offs -= sizeof(LPVOID);
- sl.X86EmitIndexPush(kEBP, offs);
- }
- }
-
- //-------------------------------------------------------------------------
-
- // EBX has Thread*
- // X86TLSFetch_TRASHABLE_REGS will get trashed
- sl.X86EmitCurrentThreadFetch(kEBX, 0);
-
- if (pNativeTarget != NULL)
- {
- // push Frame
- sl.X86EmitPushReg(kESI);
-
- // push target
- if (pNativeTarget == (LPVOID)-1)
- {
- // target comes right above arguments
- sl.X86EmitIndexPush(kEBP, StubForHostStackFrame::GetFPrelOffsOfIncomingArgs() + wStackArgumentSize);
- }
- else
- {
- // target is fixed
- sl.X86EmitPushImm32((UINT)(size_t)pNativeTarget);
- }
- }
- else
- {
- // mov eax, [first_arg]
- // mov eax, [eax]
- // push [eax + slot_offset]
- sl.X86EmitIndexRegLoad(kEAX, kEBP, offs);
- sl.X86EmitIndexRegLoad(kEAX, kEAX, 0);
- sl.X86EmitIndexPush(kEAX, sizeof(LPVOID) * dwComSlot);
-
- // push Frame
- sl.X86EmitPushReg(kESI);
- // push [esp + 4]
- sl.X86EmitEspOffset(0xff, (X86Reg)6, 4);
- }
-
- // push Thread
- sl.X86EmitPushReg(kEBX);
- sl.X86EmitCall(sl.NewExternalCodeLabel((LPVOID)LeaveRuntimeHelperWithFrame), 0xc);
-
- //-------------------------------------------------------------------------
- // call NDirect
- // See diagram above to see what the stack looks like at this point
-
- // Restore outgoing arguments
- unsigned offsToArgRegs = StubForHostStackFrame::GetFPrelOffsOfArgumentRegisters();
- sl.X86EmitIndexRegLoad(kECX, kEBP, offsToArgRegs + offsetof(ArgumentRegisters, ECX));
- sl.X86EmitIndexRegLoad(kEDX, kEBP, offsToArgRegs + offsetof(ArgumentRegisters, EDX));
-
- if (pNativeTarget != NULL || pInnerStub != NULL)
- {
- if (pNativeTarget == (LPVOID)-1)
- {
- // mov eax, target
- sl.X86EmitIndexRegLoad(kEAX, kEBP, StubForHostStackFrame::GetFPrelOffsOfIncomingArgs() + wStackArgumentSize);
- // call eax
- sl.Emit16(X86_INSTR_CALL_EAX);
- }
- else
- {
- if (pNativeTarget == NULL)
- {
- // pop target and discard it (we go to the inner stub)
- _ASSERTE(pInnerStub != NULL);
- sl.X86EmitPopReg(kEAX);
- }
-
- LPVOID pTarget = (pInnerStub != NULL ? (LPVOID)pInnerStub->GetEntryPoint() : pNativeTarget);
- sl.X86EmitCall(sl.NewExternalCodeLabel(pTarget), wStackPopSize / 4);
- }
- }
- else
- {
- // pop target
- sl.X86EmitPopReg(kEAX);
- // call eax
- sl.Emit16(X86_INSTR_CALL_EAX);
- }
-
- //-------------------------------------------------------------------------
- // Save return value registers and call EnterRuntimeHelperWithFrame
- //
-
- sl.X86EmitPushReg(kEAX);
- sl.X86EmitPushReg(kEDX);
-
- // push Frame
- sl.X86EmitPushReg(kESI);
- // push Thread
- sl.X86EmitPushReg(kEBX);
- // call EnterRuntime
- sl.X86EmitCall(sl.NewExternalCodeLabel((LPVOID)EnterRuntimeHelperWithFrame), 8);
-
- sl.X86EmitPopReg(kEDX);
- sl.X86EmitPopReg(kEAX);
-
- //-------------------------------------------------------------------------
- // Tear down the frame
- //
-
- sl.EmitCheckGSCookie(kESI, LeaveRuntimeFrame::GetOffsetOfGSCookie());
-
- // lea esp, [ebp - offsToCalleeSavedRegs]
- unsigned offsToCalleeSavedRegs = StubForHostStackFrame::GetFPrelOffsOfCalleeSavedRegisters();
- sl.X86EmitIndexLea((X86Reg)kESP_Unsafe, kEBP, offsToCalleeSavedRegs);
-
- sl.X86EmitPopReg(kEDI);
- sl.X86EmitPopReg(kESI);
- sl.X86EmitPopReg(kEBX);
-
- sl.X86EmitPopReg(kEBP);
-
- // ret [wStackPopSize]
- sl.X86EmitReturn(wStackPopSize);
-
- if (pInnerStub != NULL)
- {
- // this stub calls another stub
- return sl.LinkInterceptor(pHeap, pInnerStub, pNativeTarget);
- }
- else
- {
- return sl.Link(pHeap);
- }
-}
-
-
-//-----------------------------------------------------------------------------
-Stub *NDirectMethodDesc::GenerateStubForHost(LPVOID pNativeTarget, Stub *pInnerStub)
-{
- STANDARD_VM_CONTRACT;
-
- // We need to call LeaveRuntime before the target, and EnterRuntime after the target
-
- if (IsQCall())
- {
- // We need just the stack probe for QCalls
- CPUSTUBLINKER sl;
- sl.X86EmitCall(sl.NewExternalCodeLabel((LPVOID)LeaveRuntimeStackProbeOnly), 0);
-
- sl.X86EmitNearJump(sl.NewExternalCodeLabel((LPVOID)pNativeTarget));
-
- return sl.Link(GetLoaderAllocator()->GetStubHeap());
- }
-
- WORD wArgSize = (IsVarArgs() ? (WORD)-1 : GetStackArgumentSize());
- WORD wPopSize = ((IsStdCall() || IsThisCall()) ? GetStackArgumentSize() : 0);
-
- return GenerateStubForHostWorker(GetDomain()->GetLoaderAllocator()->GetStubHeap(),
- pNativeTarget,
- pInnerStub,
- 0,
- wArgSize,
- wPopSize);
-}
-
-
-#ifdef FEATURE_COMINTEROP
-
-//-----------------------------------------------------------------------------
-Stub *ComPlusCallInfo::GenerateStubForHost(LoaderHeap *pHeap, Stub *pInnerStub)
-{
- STANDARD_VM_CONTRACT;
-
- WORD wArgSize = GetStackArgumentSize();
-
- return GenerateStubForHostWorker(pHeap,
- NULL,
- pInnerStub,
- m_cachedComSlot,
- wArgSize,
- wArgSize); // always stdcall
-}
-
-#endif // FEATURE_COMINTEROP
-
-//-----------------------------------------------------------------------------
-// static
-Stub *COMDelegate::GenerateStubForHost(MethodDesc *pInvokeMD, MethodDesc *pStubMD, LPVOID pNativeTarget, Stub *pInnerStub)
-{
- STANDARD_VM_CONTRACT;
-
- // get unmanaged calling convention from pInvokeMD's metadata
- PInvokeStaticSigInfo sigInfo(pInvokeMD);
- CorPinvokeMap callConv = sigInfo.GetCallConv();
-
- WORD wArgSize = pStubMD->AsDynamicMethodDesc()->GetNativeStackArgSize();
- WORD wPopSize = (callConv == pmCallConvCdecl ? 0 : wArgSize);
-
- return GenerateStubForHostWorker(NULL, // we want to free this stub when the delegate dies
- pNativeTarget,
- pInnerStub,
- 0,
- wArgSize,
- wPopSize);
-}
-
-//-----------------------------------------------------------------------------
-// static
-Stub *NDirect::GenerateStubForHost(Module *pModule, CorUnmanagedCallingConvention callConv, WORD wArgSize)
-{
- STANDARD_VM_CONTRACT;
-
- // This one is for unmanaged CALLI where the target is passed as last argument
- // (first pushed to stack)
-
- WORD wPopSize = (callConv == IMAGE_CEE_CS_CALLCONV_C ? 0 : (wArgSize + STACK_ELEM_SIZE));
-
- return GenerateStubForHostWorker(pModule->GetDomain()->GetLoaderAllocator()->GetStubHeap(),
- (LPVOID)-1,
- NULL,
- 0,
- wArgSize,
- wPopSize);
-}
-
-#endif // FEATURE_INCLUDE_ALL_INTERFACES
#ifdef MDA_SUPPORTED
@@ -1976,7 +1472,7 @@ extern "C" DWORD __stdcall getcpuid(DWORD arg, unsigned char result[16])
" mov %%edx, 12(%[result])\n" \
: "=a"(eax) /*output in eax*/\
: "a"(arg), [result]"r"(result) /*inputs - arg in eax, result in any register*/\
- : "eax", "rbx", "ecx", "edx", "memory" /* registers that are clobbered, *result is clobbered */
+ : "eax", "ebx", "ecx", "edx", "memory" /* registers that are clobbered, *result is clobbered */
);
return eax;
}
@@ -1991,7 +1487,7 @@ extern "C" DWORD __stdcall getextcpuid(DWORD arg1, DWORD arg2, unsigned char res
" mov %%edx, 12(%[result])\n" \
: "=a"(eax) /*output in eax*/\
: "c"(arg1), "a"(arg2), [result]"r"(result) /*inputs - arg1 in ecx, arg2 in eax, result in any register*/\
- : "eax", "rbx", "ecx", "edx", "memory" /* registers that are clobbered, *result is clobbered */
+ : "eax", "ebx", "ecx", "edx", "memory" /* registers that are clobbered, *result is clobbered */
);
return eax;
}