You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
345 lines
9.3 KiB
345 lines
9.3 KiB
#ifndef _ASSEMBLY_HPP_
|
|
#define _ASSEMBLY_HPP_
|
|
// Ruler
|
|
// 1 2 3 4 5 6 7 8
|
|
//345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* The standard layout. */
|
|
/* */
|
|
/* The standard layout for 'hpp' files for this code is as */
|
|
/* follows: */
|
|
/* */
|
|
/* 1. Include files. */
|
|
/* 2. Constants exported from the class. */
|
|
/* 3. Data structures exported from the class. */
|
|
/* 4. Forward references to other data structures. */
|
|
/* 5. Class specifications (including inline functions). */
|
|
/* 6. Additional large inline functions. */
|
|
/* */
|
|
/* Any portion that is not required is simply omitted. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
#include "Global.hpp"
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Constants exported from the class. */
|
|
/* */
|
|
/* The assembly constants indicate the location of the thread */
|
|
/* local store. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
#define PcTeb 0x18
|
|
#define IDTeb 0x24
|
|
|
|
#ifdef WINDOWS_95
|
|
CONST SBIT32 TebSlot = 0x88;
|
|
#else
|
|
CONST SBIT32 TebSlot = 0xE10;
|
|
#endif
|
|
|
|
#ifndef ASSEMBLY_PREFETCH_SUPPORT
|
|
#define prefetcht0 __asm _emit 0x0f __asm _emit 0x18 __asm _emit 0x08
|
|
#define prefetcht1 __asm _emit 0x0f __asm _emit 0x18 __asm _emit 0x10
|
|
#define prefetcht2 __asm _emit 0x0f __asm _emit 0x18 __asm _emit 0x18
|
|
#define prefetchnta __asm _emit 0x0f __asm _emit 0x18 __asm _emit 0x00
|
|
#endif
|
|
|
|
#pragma warning( disable : 4035 )
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Assembly language for ultra high performance. */
|
|
/* */
|
|
/* We have coded a few functions in assembly language for */
|
|
/* ultra high performance. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
class ASSEMBLY
|
|
{
|
|
public:
|
|
//
|
|
// Public inline functions.
|
|
//
|
|
ASSEMBLY( VOID )
|
|
{ /* void */ }
|
|
|
|
STATIC INLINE SBIT32 AtomicAdd
|
|
(
|
|
VOLATILE SBIT32 *Address,
|
|
SBIT32 Value
|
|
)
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
__asm
|
|
{
|
|
mov ecx,Address // Load the address.
|
|
mov eax,Value // Load the value.
|
|
lock xadd dword ptr[ecx],eax // Increment the value.
|
|
}
|
|
#else
|
|
return
|
|
(
|
|
(SBIT32) InterlockedExchangeAdd
|
|
(
|
|
((LPLONG) Address),
|
|
((LONG) Value)
|
|
)
|
|
);
|
|
#endif
|
|
}
|
|
|
|
STATIC INLINE SBIT32 AtomicCompareExchange
|
|
(
|
|
VOLATILE SBIT32 *Address,
|
|
SBIT32 NewValue,
|
|
SBIT32 Value
|
|
)
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
__asm
|
|
{
|
|
mov ecx,Address // Load the address.
|
|
mov edx,NewValue // Load the new value.
|
|
mov eax,Value // Load the value.
|
|
lock cmpxchg dword ptr[ecx],edx // Update the value.
|
|
}
|
|
#else
|
|
return
|
|
(
|
|
(SBIT32) InterlockedCompareExchange
|
|
(
|
|
((VOID**) Address),
|
|
((VOID*) NewValue),
|
|
((VOID*) Value)
|
|
)
|
|
);
|
|
#endif
|
|
}
|
|
#ifdef ASSEMBLY_X86
|
|
|
|
STATIC INLINE SBIT64 AtomicCompareExchange64
|
|
(
|
|
VOLATILE SBIT64 *Address,
|
|
SBIT64 NewValue,
|
|
SBIT64 Value
|
|
)
|
|
{
|
|
__asm
|
|
{
|
|
mov esi, Address // Load the adrress.
|
|
mov ebx, dword ptr NewValue[0] // Load the new value.
|
|
mov ecx, dword ptr NewValue[4] // Load the new value.
|
|
mov eax, dword ptr Value[0] // Load the value.
|
|
mov edx, dword ptr Value[4] // Load the value.
|
|
lock cmpxchg8b [esi] // Update the value.
|
|
}
|
|
}
|
|
#endif
|
|
|
|
STATIC INLINE SBIT32 AtomicDecrement( VOLATILE SBIT32 *Address )
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
__asm
|
|
{
|
|
mov ecx,Address // Load the Address.
|
|
mov eax,-1 // Load constant.
|
|
lock xadd dword ptr[ecx],eax // Decrement value.
|
|
dec eax // Correct result.
|
|
}
|
|
#else
|
|
return ((SBIT32) InterlockedDecrement( ((LONG*) Address) ));
|
|
#endif
|
|
}
|
|
|
|
STATIC INLINE SBIT32 AtomicExchange
|
|
(
|
|
VOLATILE SBIT32 *Address,
|
|
SBIT32 NewValue
|
|
)
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
__asm
|
|
{
|
|
mov ecx,Address // Load the Address.
|
|
mov eax,NewValue // Load the value.
|
|
lock xchg dword ptr[ecx],eax // Exchange new value.
|
|
}
|
|
#else
|
|
return
|
|
(
|
|
(SBIT32) InterlockedExchange
|
|
(
|
|
((LONG*) Address),
|
|
((LONG) NewValue)
|
|
)
|
|
);
|
|
#endif
|
|
}
|
|
|
|
STATIC INLINE SBIT32 AtomicIncrement( VOLATILE SBIT32 *Address )
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
__asm
|
|
{
|
|
mov ecx,Address // Load the Address.
|
|
mov eax,1 // Load constant.
|
|
lock xadd dword ptr[ecx],eax // Increment value.
|
|
inc eax // Correct result.
|
|
}
|
|
#else
|
|
return ((SBIT32) InterlockedIncrement( ((LONG*) Address) ));
|
|
#endif
|
|
}
|
|
|
|
STATIC INLINE SBIT32 GetThreadId( VOID )
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
#ifdef ENABLE_NON_STANDARD_ASSEMBLY
|
|
__asm
|
|
{
|
|
mov eax,fs:[PcTeb] // Load TEB base address.
|
|
mov eax,dword ptr[eax+IDTeb] // Load thread ID.
|
|
}
|
|
#else
|
|
return ((SBIT32) GetCurrentThreadId());
|
|
#endif
|
|
#else
|
|
return ((SBIT32) GetCurrentThreadId());
|
|
#endif
|
|
}
|
|
|
|
STATIC INLINE VOID PrefetchL1( VOID *Address )
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
__asm
|
|
{
|
|
mov eax,Address // Load Address.
|
|
#ifdef ASSEMBLY_PREFETCH_SUPPORT
|
|
prefetcht0 [eax] // Prefetch into the L1.
|
|
#else
|
|
prefetcht0 // Prefetch into the L1.
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
STATIC INLINE VOID PrefetchL2( VOID *Address )
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
__asm
|
|
{
|
|
mov eax,Address // Load Address.
|
|
#ifdef ASSEMBLY_PREFETCH_SUPPORT
|
|
prefetcht1 [eax] // Prefetch into the L2.
|
|
#else
|
|
prefetcht1 // Prefetch into the L2.
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
STATIC INLINE VOID PrefetchL3( VOID *Address )
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
__asm
|
|
{
|
|
mov eax,Address // Load Address.
|
|
#ifdef ASSEMBLY_PREFETCH_SUPPORT
|
|
prefetcht2 [eax] // Prefetch into the L3.
|
|
#else
|
|
prefetcht2 // Prefetch into the L3.
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
STATIC INLINE VOID PrefetchNta( VOID *Address )
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
__asm
|
|
{
|
|
mov eax,Address // Load Address.
|
|
#ifdef ASSEMBLY_PREFETCH_SUPPORT
|
|
prefetchnta [eax] // Prefetch into the L1.
|
|
#else
|
|
prefetchnta // Prefetch into the L1.
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef ASSEMBLY_X86
|
|
#ifdef ENABLE_NON_STANDARD_ASSEMBLY
|
|
STATIC INLINE VOID *GetTlsAddress( SBIT32 TlsOffset )
|
|
{
|
|
__asm
|
|
{
|
|
mov eax,TlsOffset // Load TLS offset.
|
|
add eax,fs:[PcTeb] // Add TEB base address.
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
STATIC INLINE VOID *GetTlsValue( SBIT32 TlsIndex,SBIT32 TlsOffset )
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
#ifdef ENABLE_NON_STANDARD_ASSEMBLY
|
|
__asm
|
|
{
|
|
mov eax,TlsOffset // Load TLS offset.
|
|
add eax,fs:[PcTeb] // Add TEB base address.
|
|
mov eax,[eax] // Load TLS value.
|
|
}
|
|
#else
|
|
return (TlsGetValue( ((DWORD) TlsIndex) ));
|
|
#endif
|
|
#else
|
|
return (TlsGetValue( ((DWORD) TlsIndex) ));
|
|
#endif
|
|
}
|
|
|
|
STATIC INLINE VOID SetTlsValue
|
|
(
|
|
SBIT32 TlsIndex,
|
|
SBIT32 TlsOffset,
|
|
VOID *NewPointer
|
|
)
|
|
{
|
|
#ifdef ASSEMBLY_X86
|
|
#ifdef ENABLE_NON_STANDARD_ASSEMBLY
|
|
__asm
|
|
{
|
|
mov eax,TlsOffset // Load TLS offset.
|
|
add eax,fs:[PcTeb] // Add TEB base address.
|
|
mov edx,NewPointer // Load new TLS value.
|
|
mov [eax],edx // Store new TLS value.
|
|
}
|
|
#else
|
|
(VOID) TlsSetValue( ((DWORD) TlsIndex),NewPointer );
|
|
#endif
|
|
#else
|
|
(VOID) TlsSetValue( ((DWORD) TlsIndex),NewPointer );
|
|
#endif
|
|
}
|
|
|
|
~ASSEMBLY( VOID )
|
|
{ /* void */ }
|
|
|
|
private:
|
|
//
|
|
// Disabled operations.
|
|
//
|
|
ASSEMBLY( CONST ASSEMBLY & Copy );
|
|
|
|
VOID operator=( CONST ASSEMBLY & Copy );
|
|
};
|
|
|
|
#pragma warning( default : 4035 )
|
|
#endif
|