//============================================================ // // eivcx86.h // // x86 inline implementations for MSVC compiler. // //============================================================ // // Copyright Aaron Giles // All rights reserved. // // Redistribution and use in source and binary forms, with or // without modification, are permitted provided that the // following conditions are met: // // * Redistributions of source code must retain the above // copyright notice, this list of conditions and the // following disclaimer. // * Redistributions in binary form must reproduce the // above copyright notice, this list of conditions and // the following disclaimer in the documentation and/or // other materials provided with the distribution. // * Neither the name 'MAME' nor the names of its // contributors may be used to endorse or promote // products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGE (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //============================================================ #ifndef __EIVCX86__ #define __EIVCX86__ #ifdef PTR64 #include #include #endif /*************************************************************************** INLINE MATH FUNCTIONS ***************************************************************************/ /*------------------------------------------------- mul_32x32 - perform a signed 32 bit x 32 bit multiply and return the full 64 bit result -------------------------------------------------*/ #ifndef PTR64 #define mul_32x32 _mul_32x32 INLINE INT64 _mul_32x32(INT32 a, INT32 b) { // in theory this should work, but it is untested __asm { mov eax,a imul b // leave results in edx:eax } } #endif /*------------------------------------------------- mulu_32x32 - perform an unsigned 32 bit x 32 bit multiply and return the full 64 bit result -------------------------------------------------*/ #ifndef PTR64 #define mulu_32x32 _mulu_32x32 INLINE UINT64 _mulu_32x32(UINT32 a, UINT32 b) { // in theory this should work, but it is untested __asm { mov eax,a mul b // leave results in edx:eax } } #endif /*------------------------------------------------- mul_32x32_hi - perform a signed 32 bit x 32 bit multiply and return the upper 32 bits of the result -------------------------------------------------*/ #ifndef PTR64 #define mul_32x32_hi _mul_32x32_hi INLINE INT32 _mul_32x32_hi(INT32 a, INT32 b) { INT32 result; __asm { mov eax,a imul b mov result,edx } return result; } #endif /*------------------------------------------------- mulu_32x32_hi - perform an unsigned 32 bit x 32 bit multiply and return the upper 32 bits of the result -------------------------------------------------*/ #ifndef PTR64 #define mulu_32x32_hi _mulu_32x32_hi INLINE UINT32 _mulu_32x32_hi(UINT32 a, UINT32 b) { INT32 result; __asm { mov eax,a mul b mov result,edx } return result; } #endif /*------------------------------------------------- mul_32x32_shift - perform a signed 32 bit x 32 bit multiply and shift the result by the given number of bits before truncating the result to 32 bits -------------------------------------------------*/ #ifndef PTR64 #define mul_32x32_shift _mul_32x32_shift INLINE INT32 _mul_32x32_shift(INT32 a, INT32 b, UINT8 shift) { INT32 result; __asm { mov eax,a imul b mov cl,shift shrd eax,edx,cl mov result,eax } return result; } #endif /*------------------------------------------------- mulu_32x32_shift - perform an unsigned 32 bit x 32 bit multiply and shift the result by the given number of bits before truncating the result to 32 bits -------------------------------------------------*/ #ifndef PTR64 #define mulu_32x32_shift _mulu_32x32_shift INLINE UINT32 _mulu_32x32_shift(UINT32 a, UINT32 b, UINT8 shift) { INT32 result; __asm { mov eax,a mul b mov cl,shift shrd eax,edx,cl mov result,eax } return result; } #endif /*------------------------------------------------- div_64x32 - perform a signed 64 bit x 32 bit divide and return the 32 bit quotient -------------------------------------------------*/ #ifndef PTR64 #define div_64x32 _div_64x32 INLINE INT32 _div_64x32(INT64 a, INT32 b) { INT32 result; INT32 alow = a; INT32 ahigh = a >> 32; __asm { mov eax,alow mov edx,ahigh idiv b mov result,eax } return result; } #endif /*------------------------------------------------- divu_64x32 - perform an unsigned 64 bit x 32 bit divide and return the 32 bit quotient -------------------------------------------------*/ #ifndef PTR64 #define divu_64x32 _divu_64x32 INLINE UINT32 _divu_64x32(UINT64 a, UINT32 b) { UINT32 result; UINT32 alow = a; UINT32 ahigh = a >> 32; __asm { mov eax,alow mov edx,ahigh div b mov result,eax } return result; } #endif /*------------------------------------------------- div_64x32_rem - perform a signed 64 bit x 32 bit divide and return the 32 bit quotient and 32 bit remainder -------------------------------------------------*/ #ifndef PTR64 #define div_64x32_rem _div_64x32_rem INLINE INT32 _div_64x32_rem(INT64 a, INT32 b, INT32 *remainder) { INT32 result; INT32 alow = a; INT32 ahigh = a >> 32; INT32 rem; __asm { mov eax,alow mov edx,ahigh idiv b mov result,eax mov rem,edx } *remainder = rem; return result; } #endif /*------------------------------------------------- divu_64x32_rem - perform an unsigned 64 bit x 32 bit divide and return the 32 bit quotient and 32 bit remainder -------------------------------------------------*/ #ifndef PTR64 #define divu_64x32_rem _divu_64x32_rem INLINE UINT32 _divu_64x32_rem(UINT64 a, UINT32 b, UINT32 *remainder) { UINT32 result; UINT32 alow = a; UINT32 ahigh = a >> 32; UINT32 rem; __asm { mov eax,alow mov edx,ahigh div b mov result,eax mov rem,edx } *remainder = rem; return result; } #endif /*------------------------------------------------- div_32x32_shift - perform a signed divide of two 32 bit values, shifting the first before division, and returning the 32 bit quotient -------------------------------------------------*/ #ifndef PTR64 #define div_32x32_shift _div_32x32_shift INLINE INT32 _div_32x32_shift(INT32 a, INT32 b, UINT8 shift) { INT32 result; __asm { mov eax,a cdq mov cl,shift shld edx,eax,cl shl eax,cl idiv b mov result,eax } return result; } #endif /*------------------------------------------------- divu_32x32_shift - perform an unsigned divide of two 32 bit values, shifting the first before division, and returning the 32 bit quotient -------------------------------------------------*/ #ifndef PTR64 #define divu_32x32_shift _divu_32x32_shift INLINE UINT32 _divu_32x32_shift(UINT32 a, UINT32 b, UINT8 shift) { UINT32 result; __asm { mov eax,a xor edx,edx mov cl,shift shld edx,eax,cl shl eax,cl div b mov result,eax } return result; } #endif /*------------------------------------------------- mod_64x32 - perform a signed 64 bit x 32 bit divide and return the 32 bit remainder -------------------------------------------------*/ #ifndef PTR64 #define mod_64x32 _mod_64x32 INLINE INT32 _mod_64x32(INT64 a, INT32 b) { INT32 result; INT32 alow = a; INT32 ahigh = a >> 32; __asm { mov eax,alow mov edx,ahigh idiv b mov result,edx } return result; } #endif /*------------------------------------------------- modu_64x32 - perform an unsigned 64 bit x 32 bit divide and return the 32 bit remainder -------------------------------------------------*/ #ifndef PTR64 #define modu_64x32 _modu_64x32 INLINE UINT32 _modu_64x32(UINT64 a, UINT32 b) { UINT32 result; UINT32 alow = a; UINT32 ahigh = a >> 32; __asm { mov eax,alow mov edx,ahigh div b mov result,edx } return result; } #endif /*------------------------------------------------- recip_approx - compute an approximate floating point reciprocal -------------------------------------------------*/ #ifdef PTR64 #define recip_approx _recip_approx INLINE float _recip_approx(float z) { __m128 mz = _mm_set_ss(z); __m128 mooz = _mm_rcp_ss(mz); float ooz; _mm_store_ss(&ooz, mooz); return ooz; } #endif /*************************************************************************** INLINE BIT MANIPULATION FUNCTIONS ***************************************************************************/ /*------------------------------------------------- count_leading_zeros - return the number of leading zero bits in a 32-bit value -------------------------------------------------*/ #ifndef PTR64 #define count_leading_zeros _count_leading_zeros INLINE UINT8 _count_leading_zeros(UINT32 value) { INT32 result; __asm { bsr eax,value jnz skip mov eax,63 skip: xor eax,31 mov result,eax } return result; } #endif /*------------------------------------------------- count_leading_ones - return the number of leading one bits in a 32-bit value -------------------------------------------------*/ #ifndef PTR64 #define count_leading_ones _count_leading_ones INLINE UINT8 _count_leading_ones(UINT32 value) { INT32 result; __asm { mov eax,value not eax bsr eax,eax jnz skip mov eax,63 skip: xor eax,31 mov result,eax } return result; } #endif /*************************************************************************** INLINE TIMING FUNCTIONS ***************************************************************************/ /*------------------------------------------------- get_profile_ticks - return a tick counter from the processor that can be used for profiling. It does not need to run at any particular rate. -------------------------------------------------*/ #define get_profile_ticks _get_profile_ticks #ifdef PTR64 INLINE osd_ticks_t _get_profile_ticks(void) { return __rdtsc(); } #else INLINE osd_ticks_t _get_profile_ticks(void) { UINT64 result; UINT64 *presult = &result; __asm { __asm _emit 0Fh __asm _emit 031h // rdtsc mov ebx, presult mov [ebx],eax mov [ebx+4],edx } return result; } #endif #endif /* __EIVCX86__ */