From cf36d4ba58ed12987107fe44e810f148dca48801 Mon Sep 17 00:00:00 2001
From: Maarten ter Huurne <maarten@treewalker.org>
Date: Fri, 5 Sep 2008 01:48:16 +0000
Subject: [PATCH] Fixed ProtectFunction(): it should copy parameters using the
 padded size. Actually, I am not sure this function is correct, but at least
 its implementation is now equivalent to the original (before rev 439).

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@441 8ced0084-cf51-0410-be5f-012b33b47a6e
---
 Source/Core/Common/Src/ABI.cpp   | 34 ++++++++++++++++++++------------
 Source/Core/Common/Src/ABI.h     |  1 +
 Source/Core/Common/Src/Thunk.cpp |  3 ++-
 3 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/Source/Core/Common/Src/ABI.cpp b/Source/Core/Common/Src/ABI.cpp
index d41225a964..097d6fc45b 100644
--- a/Source/Core/Common/Src/ABI.cpp
+++ b/Source/Core/Common/Src/ABI.cpp
@@ -65,6 +65,17 @@ void ABI_PopAllCalleeSavedRegsAndAdjustStack() {
 	POP(EBP);
 }
 
+unsigned int ABI_GetAlignedFrameSize(unsigned int frameSize) {
+	frameSize += 4; // reserve space for return address
+	unsigned int alignedSize =
+#ifdef __GNUC__
+		(frameSize + 15) & -16;
+#else
+		frameSize;
+#endif
+	return alignedSize;
+}
+
 void ABI_AlignStack(unsigned int frameSize) {
 // Mac OS X requires the stack to be 16-byte aligned before every call.
 // Linux requires the stack to be 16-byte aligned before calls that put SSE
@@ -74,9 +85,8 @@ void ABI_AlignStack(unsigned int frameSize) {
 // expect that GCC on Windows acts the same as GCC on Linux in this respect.
 // It would be nice if someone could verify this.
 #ifdef __GNUC__
-	frameSize += 4; // reserve space for return address
-	unsigned int paddedSize = (frameSize + 15) & -16;
-	unsigned int fillSize = paddedSize - frameSize;
+	unsigned int fillSize =
+		ABI_GetAlignedFrameSize(frameSize) - (frameSize + 4);
 	if (fillSize != 0) {
 		SUB(32, R(ESP), Imm8(fillSize));
 	}
@@ -84,16 +94,10 @@ void ABI_AlignStack(unsigned int frameSize) {
 }
 
 void ABI_RestoreStack(unsigned int frameSize) {
-	frameSize += 4; // reserve space for return address
-	unsigned int paddedSize =
-#ifdef __GNUC__
-		(frameSize + 15) & -16;
-#else
-		frameSize;
-#endif
-	paddedSize -= 4; // return address is already consumed
-	if (paddedSize != 0) {
-		ADD(32, R(ESP), Imm8(paddedSize));
+	unsigned int alignedSize = ABI_GetAlignedFrameSize(frameSize);
+	alignedSize -= 4; // return address is POPped at end of call
+	if (alignedSize != 0) {
+		ADD(32, R(ESP), Imm8(alignedSize));
 	}
 }
 
@@ -137,6 +141,10 @@ void ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2)
 	CALL(func);
 }
 
+unsigned int ABI_GetAlignedFrameSize(unsigned int frameSize) {
+	return frameSize;
+}
+
 void ABI_AlignStack(unsigned int /*frameSize*/) {
 }
 
diff --git a/Source/Core/Common/Src/ABI.h b/Source/Core/Common/Src/ABI.h
index b84e92bef9..2bbd169d00 100644
--- a/Source/Core/Common/Src/ABI.h
+++ b/Source/Core/Common/Src/ABI.h
@@ -103,6 +103,7 @@ void ABI_PopAllCalleeSavedRegsAndAdjustStack();
 void ABI_PushAllCallerSavedRegsAndAdjustStack();
 void ABI_PopAllCallerSavedRegsAndAdjustStack();
 
+unsigned int ABI_GetAlignedFrameSize(unsigned int frameSize);
 void ABI_AlignStack(unsigned int frameSize);
 void ABI_RestoreStack(unsigned int frameSize);
 
diff --git a/Source/Core/Common/Src/Thunk.cpp b/Source/Core/Common/Src/Thunk.cpp
index 086ad66cbb..73ad098090 100644
--- a/Source/Core/Common/Src/Thunk.cpp
+++ b/Source/Core/Common/Src/Thunk.cpp
@@ -137,9 +137,10 @@ void *ProtectFunction(void *function, int num_params)
 	// trickery : we simply re-push the parameters. might not be optimal, but that doesn't really
 	// matter.
 	ABI_AlignStack(num_params * 4);
+	unsigned int alignedSize = ABI_GetAlignedFrameSize(num_params * 4);
 	for (int i = 0; i < num_params; i++) {
 		// ESP is changing, so we do not need i
-		PUSH(32, MDisp(ESP, num_params * 4));
+		PUSH(32, MDisp(ESP, alignedSize - 4));
 	}
 	CALL(function);
 	ABI_RestoreStack(num_params * 4);