RCT_CALLFUNC now saves flags register.

This commit is contained in:
Duncan Frost 2014-10-18 09:43:06 +01:00
parent b348b3a5a8
commit 442794de7d
1 changed files with 115 additions and 93 deletions

View File

@ -486,10 +486,22 @@ static void RCT2_CALLPROC_EBPSAFE(int address)
#endif #endif
} }
/* Returns the flags register
*
*Flags register is as follows:
*0bSZ0A_0P0C_0000_00000
*S = Signed flag
*Z = Zero flag
*C = Carry flag
*A = Adjust flag
*P = Parity flag
*All other bits are undefined.
*/
static int RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx, int _esi, int _edi, int _ebp) static int RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx, int _esi, int _edi, int _ebp)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
__asm { __asm {
push ebp
push address push address
mov eax, _eax mov eax, _eax
mov ebx, _ebx mov ebx, _ebx
@ -500,7 +512,8 @@ static int RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx,
mov ebp, _ebp mov ebp, _ebp
call [esp] call [esp]
lahf lahf
add esp, 4 pop ebp
pop ebp
} }
#else #else
__asm__ ( "\ __asm__ ( "\
@ -568,13 +581,24 @@ static void RCT2_CALLPROC_X_EBPSAFE(int address, int _eax, int _ebx, int _ecx, i
#endif #endif
} }
static void RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp) /* Returns the flags register
*
*Flags register is as follows:
*0bSZ0A_0P0C_0000_00000
*S = Signed flag
*Z = Zero flag
*C = Carry flag
*A = Adjust flag
*P = Parity flag
*All other bits are undefined.
*/
static int RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
__asm { __asm {
// Store C's base pointer // Store C's base pointer
push ebp push ebp
push ebx
// Store address to call // Store address to call
push address push address
@ -596,29 +620,16 @@ static void RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_
// Call function // Call function
call [esp] call [esp]
add esp, 4
// Store output eax // Store output eax
push eax push eax
// Put original C base pointer into eax
mov eax, [esp+4]
// Store output ebp
push ebp push ebp
// Set ebp to the original C base pointer
mov ebp, eax
// Put output ebp into ebp parameter
mov eax, [esp]
push ebx push ebx
mov ebx, [_ebp] mov ebp, [esp + 20]
mov [ebx], eax mov ebx, [esp + 16]
pop ebx
add esp, 4 // Get resulting ecx, edx, esi, edi registers
// Get resulting ebx, ecx, edx, esi, edi registers
mov eax, [_edi] mov eax, [_edi]
mov [eax], edi mov [eax], edi
mov eax, [_esi] mov eax, [_esi]
@ -627,85 +638,96 @@ static void RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_
mov [eax], edx mov [eax], edx
mov eax, [_ecx] mov eax, [_ecx]
mov [eax], ecx mov [eax], ecx
// Pop ebx reg into ecx
pop ecx
mov eax, [_ebx] mov eax, [_ebx]
mov [eax], ebx mov[eax], ecx
// Pop ebp reg into ecx
pop ecx
mov eax, [_ebp]
mov[eax], ecx
pop eax pop eax
// Get resulting eax register // Get resulting eax register
mov ebx, [_eax] mov ecx, [_eax]
mov [ebx], eax mov [ecx], eax
add esp, 4 // Save flags as return in eax
lahf
// Pop address
pop ebp
pop ebx
pop ebp
} }
#else #else
__asm__ ( "\ __asm__ ( "\
\n\ \n\
/* Store C's base pointer*/ \n\ /* Store C's base pointer*/ \n\
push ebx \n\ push ebx \n\
push ebp \n\ push ebp \n\
\n\ \n\
/* Store %[address] to call*/ \n\ /* Store %[address] to call*/ \n\
push %[address] \n\ push %[address] \n\
\n\ \n\
/* Set all registers to the input values*/ \n\ /* Set all registers to the input values*/ \n\
mov eax, [%[_eax]] \n\ mov eax, [%[_eax]] \n\
mov eax, [eax] \n\ mov eax, [eax] \n\
mov ebx, [%[_ebx]] \n\ mov ebx, [%[_ebx]] \n\
mov ebx, [ebx] \n\ mov ebx, [ebx] \n\
mov ecx, [%[_ecx]] \n\ mov ecx, [%[_ecx]] \n\
mov ecx, [ecx] \n\ mov ecx, [ecx] \n\
mov edx, [%[_edx]] \n\ mov edx, [%[_edx]] \n\
mov edx, [edx] \n\ mov edx, [edx] \n\
mov esi, [%[_esi]] \n\ mov esi, [%[_esi]] \n\
mov esi, [esi] \n\ mov esi, [esi] \n\
mov edi, [%[_edi]] \n\ mov edi, [%[_edi]] \n\
mov edi, [edi] \n\ mov edi, [edi] \n\
mov ebp, [%[_ebp]] \n\ mov ebp, [%[_ebp]] \n\
mov ebp, [ebp] \n\ mov ebp, [ebp] \n\
\n\ \n\
/* Call function*/ \n\ /* Call function*/ \n\
call [esp] \n\ call [esp] \n\
add esp, 4 \n\ \n\
\n\ /* Store output eax */ \n\
/* Store output eax*/ \n\ push eax \n\
push eax \n\ push ebp \n\
\n\ push ebx \n\
/* Put original C base pointer into eax*/ \n\ mov ebp, [esp + 20] \n\
mov eax, [esp+4] \n\ mov ebx, [esp + 16] \n\
\n\ /* Get resulting ecx, edx, esi, edi registers*/ \n\
/* Store output ebp*/ \n\ mov eax, [%[_edi]] \n\
push ebp \n\ mov [eax], edi \n\
\n\ mov eax, [%[_esi]] \n\
/* Set ebp to the original C base pointer*/ \n\ mov [eax], esi \n\
mov ebp, eax \n\ mov eax, [%[_edx]] \n\
\n\ mov [eax], edx \n\
/* Put output ebp into ebp parameter*/ \n\ mov eax, [%[_ecx]] \n\
mov eax, [esp] \n\ mov [eax], ecx \n\
push ebx \n\ /* Pop ebx reg into ecx*/ \n\
mov ebx, [%[_ebp]] \n\ pop ecx \n\
mov [ebx], eax \n\ mov eax, [%[_ebx]] \n\
pop ebx \n\ mov[eax], ecx \n\
add esp, 4 \n\ \n\
\n\ /* Pop ebp reg into ecx */\n\
/* Get resulting ebx, ecx, edx, esi, edi registers*/ \n\ pop ecx \n\
mov eax, [%[_edi]] \n\ mov eax, [%[_ebp]] \n\
mov [eax], edi \n\ mov[eax], ecx \n\
mov eax, [%[_esi]] \n\ \n\
mov [eax], esi \n\ pop eax \n\
mov eax, [%[_edx]] \n\ /* Get resulting eax register*/ \n\
mov [eax], edx \n\ mov ecx, [%[_eax]] \n\
mov eax, [%[_ecx]] \n\ mov [ecx], eax \n\
mov [eax], ecx \n\ \n\
mov eax, [%[_ebx]] \n\ /* Save flags as return in eax*/ \n\
mov [eax], ebx \n\ lahf \n\
pop eax \n\ /* Pop address*/ \n\
\n\ pop ebp \n\
/* Get resulting eax register*/ \n\ \n\
mov ebx, [%[_eax]] \n\ pop ebx \n\
mov [ebx], eax \n\ pop ebp \n\
\n\
add esp, 4 \n\
pop ebx \n\
" : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp) " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp)
: :
: "eax","ecx","edx","esi","edi" : "eax","ecx","edx","esi","edi"