| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- ///////////////////////////////////////////////////////////////////////////////
- // Copyright (c) Electronic Arts Inc. All rights reserved.
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- // See the header file for documentation and example usage.
- ///////////////////////////////////////////////////////////////////////////////
- #include <EAStdC/internal/Config.h>
- #include <EAStdC/EAFixedPoint.h>
- #include <EAAssert/eaassert.h>
- namespace EA
- {
- namespace StdC
- {
- ///////////////////////////////////////////////////////////////////////////////
- // SFixed16::FixedMul
- //
- // returns a*b
- //
- #ifdef FP_USE_INTEL_ASM
- EASTDC_API __declspec(naked)
- int32_t __stdcall SFixed16::FixedMul(const int32_t /*a*/, const int32_t /*b*/)
- {
- __asm{ // VC++ compiler will choke if you put ";" comments with a templated inline assembly function.
- mov eax, [esp+4] // Move a into eax
- mov ecx, [esp+8] // Move b into ecx
- imul ecx // Multiply by b, storing the result in edx:eax
- shrd eax, edx, 16 // Do shift and leave result in eax.
- ret 8
- }
- #ifdef EA_COMPILER_INTEL // Intel C++
- return 0; // Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- int32_t FP_PASCAL SFixed16::FixedMul(const int32_t a, const int32_t b)
- {
- const int64_t c = (int64_t)a * b;
- return (int32_t)(c >> 16);
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // SFixed16::FixedMul
- //
- // returns a*b
- //
- #ifdef FP_USE_INTEL_ASM
- EASTDC_API __declspec(naked)
- uint32_t __stdcall UFixed16::FixedMul(const uint32_t /*a*/, const uint32_t /*b*/)
- {
- __asm{ // VC++ compiler will choke if you put ";" comments with a templated inline assembly function.
- mov eax, [esp+4] // Move a into eax
- mov ecx, [esp+8] // Move b into ecx
- mul ecx // Multiply by b, storing the result in edx:eax
- shrd eax, edx, 16 // Do shift and leave result in eax.
- ret 8
- }
- #ifdef EA_COMPILER_INTEL // Intel C++
- return 0; // Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- uint32_t FP_PASCAL UFixed16::FixedMul(const uint32_t a, const uint32_t b)
- {
- const uint64_t c = (uint64_t)a * b;
- return (uint32_t)(c >> 16);
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // SFixed16::FixedDiv
- //
- // returns a/b
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- int32_t FP_PASCAL SFixed16::FixedDiv(const int32_t /*a*/, const int32_t /*b*/)
- {
- __asm{
- mov eax, [esp+4] // Prepare the number for division
- rol eax, 16 // Put the fractional part of the number in the top half of eax, rotating the top part to the bottom part for later use
- movsx edx, ax // Put the integer part in edx
- xor ax, ax // Clear the integer part from eax
- mov ecx, [esp+8] // Move b into ecx
- idiv ecx // Divide and store. Divide the signed 64 bit value in edx:eax by the 32 bit value in ecx.
- ret 8
- }
- #ifdef EA_COMPILER_INTEL // Intel C++
- return 0; // Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- int32_t FP_PASCAL SFixed16::FixedDiv(const int32_t a, const int32_t b)
- {
- const int64_t c = ((uint64_t)a) << 16;
- return (int32_t)(c / b);
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // UFixed16::FixedDiv
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- uint32_t __stdcall UFixed16::FixedDiv(const uint32_t /*a*/, const uint32_t /*b*/)
- {
- __asm{
- mov eax, [esp+4] // Prepare the number for division
- rol eax, 16 // Put the fractional part of the number in the top half of eax, rotating the top part to the bottom part for later use
- movsx edx, ax // Put the integer part in edx
- xor ax, ax // Clear the integer part from eax
- mov ecx, [esp+8] // Move b into ecx
- div ecx // Divide and store. Divide the signed 64 bit value in edx:eax by the 32 bit value in ecx.
- ret 8
- }
- #ifdef EA_COMPILER_INTEL // Intel C++
- return 0; // Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- uint32_t FP_PASCAL UFixed16::FixedDiv(const uint32_t a, const uint32_t b)
- {
- const uint64_t c = ((uint64_t)a) << 16;
- return (uint32_t)(c / b);
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // SFixed16::FixedDivSafe
- //
- // returns a/b. Checks for overflow and returns max value if so, instead of bombing.
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- int32_t __stdcall SFixed16::FixedDivSafe(const int32_t /*a*/, const int32_t /*b*/)
- {
- __asm{
- mov ecx, [esp+8] // Move b into ecx.
- or ecx, ecx // Test to see if equal to zero.
- je NOT_OK // if not OK
- mov eax, [esp+4] // Put a into eax.
- xor edx, edx // Clear out edx, since we'll be shifting into it.
- shld edx,eax,16 // double fixed
- cmp edx, ecx // do a test for overflow.
- jge NOT_OK // If edx is greater than ecx, then we will overflow on the divide.
- shl eax,16 // double fixed
- idiv ecx // Divide and store. Divide the signed 64 bit value in edx:eax by the 32 bit value in ecx.
- ret 8
- NOT_OK:
- mov eax, 0x7FFFFFFF // put in max value
- ret 8
- }
- #ifdef EA_COMPILER_INTEL // Intel C++
- return 0; // Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- int32_t FP_PASCAL SFixed16::FixedDivSafe(const int32_t a, const int32_t b)
- {
- if(b)
- {
- const int64_t c = ((int64_t)a) << 16;
- return (int32_t)(c / b);
- }
- return INT32_MAX;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // UFixed16::FixedDivSafe
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- uint32_t __stdcall UFixed16::FixedDivSafe(const uint32_t /*a*/, const uint32_t /*b*/)
- {
- __asm{
- mov ecx, [esp+8] // Move b into ecx.
- or ecx, ecx // Test to see if equal to zero.
- je NOT_OK // if not OK
- mov eax, [esp+4] // Put a into eax.
- xor edx, edx // Clear out edx, since we'll be shifting into it.
- shld edx,eax,16 // double fixed
- cmp edx, ecx // do a test for overflow.
- jae NOT_OK // If edx is greater than ecx, then we will overflow on the divide.
- shl eax,16 // double fixed
- div ecx // Divide and store. Divide the signed 64 bit value in edx:eax by the 32 bit value in ecx.
- ret 8 // return
- NOT_OK:
- mov eax, 0xFFFFFFFF // put in max value
- ret 8
- }
- #ifdef EA_COMPILER_INTEL //Intel C++
- return 0; //Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- uint32_t FP_PASCAL UFixed16::FixedDivSafe(const uint32_t a, const uint32_t b)
- {
- if(b)
- {
- const uint64_t c = ((uint64_t)a) << 16;
- return (uint32_t)(c / b);
- }
- return UINT32_MAX;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // SFixed16::FixedMulDiv
- //
- // returns a*b/c Faster than separate mul and div.
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- int32_t __stdcall SFixed16::FixedMulDiv(const int32_t /*a*/, const int32_t /*b*/, const int32_t /*c*/)
- {
- __asm{
- mov eax, [esp+4] // First set up the multiply. Put a into eax.
- mov ecx, [esp+8] // Put b into ecx.
- imul ecx // Multiply. The result is in edx:eax.
- mov ecx, [esp+12] // Put the denominator into ecx.
- idiv ecx // Divide, leaving the result in eax and remainder in edx.
- ret 12
- }
- #ifdef EA_COMPILER_INTEL // Intel C++
- return 0; // Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- int32_t FP_PASCAL SFixed16::FixedMulDiv(const int32_t /*a*/, const int32_t /*b*/, const int32_t /*c*/)
- {
- // EA_ASSERT(false); // This is not yet finished.
- return 0;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // UFixed16::FixedMulDiv
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- uint32_t __stdcall UFixed16::FixedMulDiv(const uint32_t /*a*/, const uint32_t /*b*/, const uint32_t /*c*/)
- {
- __asm{
- mov eax, [esp+4] // First set up the multiply. Put a into eax.
- mov ecx, [esp+8] // Put b into ecx.
- mul ecx // Multiply. The result is in edx:eax.
- mov ecx, [esp+12] // Put the denominator into ecx.
- div ecx // Divide, leaving the result in eax and remainder in edx.
- ret 12
- }
- #ifdef EA_COMPILER_INTEL //Intel C++
- return 0; //Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- uint32_t FP_PASCAL UFixed16::FixedMulDiv(const uint32_t /*a*/, const uint32_t /*b*/, const uint32_t /*c*/)
- {
- // EA_ASSERT(false); // This is not yet finished.
- return 0;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // SFixed16::FixedMulDivSafe
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- int32_t __stdcall SFixed16::FixedMulDivSafe(const int32_t /*a*/, const int32_t /*b*/, const int32_t /*c*/)
- {
- __asm{
- mov ecx, [esp+12] // Move b into ecx.
- or ecx, ecx // Test to see if equal to zero.
- je NOT_OK // if not OK
- mov eax, [esp+4] //
- mov ebx, [esp+8] //
- imul ebx //
- cmp edx, ecx // do a test for overflow.
- jge NOT_OK // If edx is greater than ecx, then we will overflow on the divide.
- idiv ecx // Result is in eax.
- ret 12
- NOT_OK:
- mov eax, 0x7FFFFFFF // put in max value
- ret 12
- }
- #ifdef EA_COMPILER_INTEL //Intel C++
- return 0; //Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- int32_t FP_PASCAL SFixed16::FixedMulDivSafe(const int32_t /*a*/, const int32_t /*b*/, const int32_t /*c*/)
- {
- // EA_ASSERT(false); // This is not yet finished.
- return 0;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // UFixed16::FixedMulDivSafe
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- uint32_t __stdcall UFixed16::FixedMulDivSafe(const uint32_t /*a*/, const uint32_t /*b*/, const uint32_t /*c*/)
- {
- __asm{
- mov ecx, [esp+12] // Move b into ecx.
- or ecx, ecx // Test to see if equal to zero.
- je NOT_OK // if not OK
- mov eax, [esp+4] //
- mov ebx, [esp+8] //
- mul ebx //
- cmp edx, ecx // do a test for overflow.
- jae NOT_OK // If edx is greater than ecx, then we will overflow on the divide.
- div ecx // Result is in eax.
- ret 12
- NOT_OK:
- mov eax, 0xFFFFFFFF // put in max value
- ret 12
- }
- #ifdef EA_COMPILER_INTEL //Intel C++
- return 0; //Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- uint32_t FP_PASCAL UFixed16::FixedMulDivSafe(const uint32_t /*a*/, const uint32_t /*b*/, const uint32_t /*c*/)
- {
- // EA_ASSERT(false); // This is not yet finished.
- return 0;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // SFixed16::FixedMod
- //
- // returns a%b
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- int32_t __stdcall SFixed16::FixedMod(const int32_t /*a*/, const int32_t /*b*/)
- {
- __asm{
- mov eax, [esp+4] // Prepare the number for division
- rol eax, 16 // Put the fractional part of the number in the top half of eax, rotating the top part to the bottom part for later use
- movsx edx, ax // Put the integer part in edx
- xor ax, ax // Clear the integer part from eax
- mov ecx, [esp+8] // Move b into ecx
- idiv ecx // Divide and store. Divide the signed 64 bit value in edx:eax by the 32 bit value in ecx.
- mov eax, edx // The remainder after idiv is in edx. So we move it to eax before the return.
- ret 8
- }
- #ifdef EA_COMPILER_INTEL // Intel C++
- return 0; // Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- int32_t FP_PASCAL SFixed16::FixedMod(const int32_t a, const int32_t b)
- {
- const uint64_t c = ((uint64_t)a) << 16;
- return (int32_t)(c % b);
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // UFixed16::FixedMod
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- uint32_t __stdcall UFixed16::FixedMod(const uint32_t /*a*/, const uint32_t /*b*/)
- {
- __asm{
- mov eax, [esp+4] // Prepare the number for division
- rol eax, 16 // Put the fractional part of the number in the top half of eax, rotating the top part to the bottom part for later use
- movsx edx, ax // Put the integer part in edx
- xor ax, ax // Clear the integer part from eax
- mov ecx, [esp+8] // Move b into ecx
- div ecx // Divide and store. Divide the signed 64 bit value in edx:eax by the 32 bit value in ecx.
- mov eax, edx // The remainder after div is in edx. So we move it to eax before the return.
- ret 8
- }
- #ifdef EA_COMPILER_INTEL // Intel C++
- return 0; // Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- uint32_t FP_PASCAL UFixed16::FixedMod(const uint32_t a, const uint32_t b)
- {
- const uint64_t c = ((uint64_t)a) << 16;
- return (uint32_t)(c % b);
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // SFixed16::FixedModSafe
- //
- // returns a%b
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- int32_t __stdcall SFixed16::FixedModSafe(const int32_t /*a*/, const int32_t /*b*/)
- {
- __asm{
- mov ecx, [esp+8] // Move b into ecx
- or ecx, ecx // Test to see if equal to zero.
- je NOT_OK // if not OK
- mov eax, [esp+4] // Prepare the number for division
- rol eax, 16 // Put the fractional part of the number in the top half of eax, rotating the top part to the bottom part for later use
- movsx edx, ax // Put the integer part in edx
- xor ax, ax // Clear the integer part from eax
- cmp edx, ecx // do a test for overflow.
- jge NOT_OK // If edx is greater than ecx, then we will overflow on the divide.
- div ecx // Divide and store. Divide the signed 64 bit value in edx:eax by the 32 bit value in ecx.
- mov eax, edx // The remainder after idiv is in edx. So we move it to eax before the return.
- ret 8
- NOT_OK:
- mov eax, 0xFFFFFFFF // put in max value
- ret 8
- }
- #ifdef EA_COMPILER_INTEL // Intel C++
- return 0; // Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- int32_t FP_PASCAL SFixed16::FixedModSafe(const int32_t a, const int32_t b)
- {
- if(b)
- {
- const uint64_t c = ((uint64_t)a) << 16;
- return (int32_t)(c % b);
- }
- return INT32_MAX;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // UFixed16::FixedModSafe
- //
- #ifdef FP_USE_INTEL_ASM
- __declspec(naked)
- uint32_t __stdcall UFixed16::FixedModSafe(const uint32_t /*a*/, const uint32_t /*b*/)
- {
- __asm{
- mov ecx, [esp+8] // Move b into ecx
- or ecx, ecx // Test to see if equal to zero.
- je NOT_OK // if not OK
- mov eax, [esp+4] // Prepare the number for division
- rol eax, 16 // Put the fractional part of the number in the top half of eax, rotating the top part to the bottom part for later use
- movsx edx, ax // Put the integer part in edx
- xor ax, ax // Clear the integer part from eax
- cmp edx, ecx // do a test for overflow.
- jae NOT_OK // If edx is greater than ecx, then we will overflow on the divide.
- div ecx // Divide and store. Divide the signed 64 bit value in edx:eax by the 32 bit value in ecx.
- mov eax, edx // The remainder after div is in edx. So we move it to eax before the return.
- ret 8
- NOT_OK:
- mov eax, 0xFFFFFFFF // put in max value
- ret 8
- }
- #ifdef EA_COMPILER_INTEL // Intel C++
- return 0; // Just to get the compiler to shut up.
- #endif
- }
- #else
- template<> EASTDC_API
- uint32_t FP_PASCAL UFixed16::FixedModSafe(const uint32_t a, const uint32_t b)
- {
- if(b)
- {
- const uint64_t c = ((uint64_t)a) << 16;
- return (uint32_t)(c % b);
- }
- return UINT32_MAX;
- }
- #endif
- } // namespace StdC
- } // namespace EA
- // For unity build friendliness, undef all local #defines.
- #undef FP_USE_INTEL_ASM
|