From: Franz Bachler on
Hello,

this is part of a CPU-Speed-Detection Program:

#ifdef __BORLANDC__
void getRdtsc( UINT64* pResult )
{
_asm
{
db 0x0F
db 0x31
mov ebx, pResult
mov [ebx], eax
mov [ebx+4], edx
}
}

UINT64 rdtsc(void)
{
UINT64 result;
getRdtsc( &result );
return result;
}
#else // Visual Studio
inline UINT64 rdtsc(void)
{
_asm __emit 0x0F
_asm __emit 0x31
}
#endif

How to encode this in MinGW?

Greetings,
Franz

--
Franz Bachler, A-3250 Wieselburg
E-Mail: fraba (at) gmx.at
Homepage: http://members.aon.at/fraba
or http://home.pages.at/fraba



From: Alf P. Steinbach /Usenet on
* Franz Bachler, on 07.07.2010 21:10:
> Hello,
>
> this is part of a CPU-Speed-Detection Program:
>
> #ifdef __BORLANDC__
> void getRdtsc( UINT64* pResult )
> {
> _asm
> {
> db 0x0F
> db 0x31
> mov ebx, pResult
> mov [ebx], eax
> mov [ebx+4], edx
> }
> }
>
> UINT64 rdtsc(void)
> {
> UINT64 result;
> getRdtsc(&result );
> return result;
> }
> #else // Visual Studio
> inline UINT64 rdtsc(void)
> {
> _asm __emit 0x0F
> _asm __emit 0x31
> }
> #endif
>
> How to encode this in MinGW?

You can use the -S option to check the generated assembly. MinGW g++ supports
both Intel and AT&T assembly syntax, and this is a bit problematic. The default
is AT&T (your examples above are Intel syntax). You can specify the syntax using
option -masm=intel or -masm=att, I think it was. There's also an assembler
directive for switching syntax. I don't recall but google it if you need it.

Essentially you just declare the function, like

extern "C" void UINT64 rtdsc();

and immediately follow that with an 'asm' directive. It needs each line of
assembly as a string literal, IIRC.


Good luck!

- Alf

--
blog at <url: http://alfps.wordpress.com>
From: Franz Bachler on
here we go:

if you compile it with -Wall you'll get the following warning:

cpumingw.c: In function `rdtsc':
cpumingw.c:15: warning: control reaches end of non-void function

but it works fine

/* MinGW
*
* gcc -o cpuspeed.exe -s cpuspeed.c -masm=intel -mwindows
*/

#include <windows.h>

UINT64 rdtsc(void)
{
asm
(
".byte 0x0F\n"
".byte 0x31\n"
);
}

typedef LRESULT (WINAPI * CALLNTPOWERINFORMATION)(POWER_INFORMATION_LEVEL,
PVOID, ULONG, PVOID, ULONG);

typedef struct _PROCESSOR_POWER_INFORMATION
{
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;

typedef LONG NTSTATUS;

UINT_PTR GetCpuSpeed(VOID)
{
PROCESSOR_POWER_INFORMATION ppi;
CALLNTPOWERINFORMATION pfn;
LARGE_INTEGER liFreq,li1,li2;
OSVERSIONINFO osvi;
HINSTANCE hDll;
NTSTATUS stat;
UINT_PTR uSpeed;
UINT64 timestamp;
HANDLE hThread;
int nPriority;

ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);

// not for Windows NT4 and 9x
if (osvi.dwMajorVersion>=5)
{
ZeroMemory(&ppi, sizeof(ppi));
stat = ERROR_CALL_NOT_IMPLEMENTED;

if (NULL != (hDll = LoadLibrary(TEXT("powrprof.dll"))))
{
if (NULL != (pfn = (CALLNTPOWERINFORMATION)GetProcAddress(hDll,
"CallNtPowerInformation")))
{
stat = pfn(ProcessorInformation, NULL, 0, &ppi, sizeof(ppi));
}
FreeLibrary(hDll);
}

if (ERROR_SUCCESS == stat)
return(ppi.CurrentMhz);
}

hThread = GetCurrentThread();
nPriority = GetThreadPriority(hThread);

QueryPerformanceFrequency(&liFreq);
liFreq.QuadPart /= 10;
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);

timestamp = rdtsc();
QueryPerformanceCounter(&li1);

do
{
QueryPerformanceCounter(&li2);
} while ((li2.QuadPart - li1.QuadPart) < liFreq.QuadPart);

uSpeed = (UINT_PTR)((rdtsc() - timestamp) / 100000);
SetThreadPriority(hThread, nPriority);
return(uSpeed);
}

int main(void)

{
TCHAR szSpeed[128];
wsprintf(szSpeed, TEXT("CPU-Speed: ~%u MHz \n"), GetCpuSpeed());
MessageBox(NULL, szSpeed, TEXT(" Info "), MB_OK);
return(0);
}


From: Franz Bachler on
Hello,

and the next problem & solution for MinGW:

The FPU is very slow, up to 3times slower than as with other compilers.
I've found this page

http://www.network-theory.co.uk/docs/gccintro/gccintro_70.html

and created the following code based of this information:

#if !defined (__BORLANDC__) && !defined (_MSC_VER)
// use double-precision rounding for MinGW
unsigned short cw=0x027F;
asm("fldcw %0" : : "m" (*&cw));
// this works only if cw is a global variable
// asm("fldcw _cw");
#endif

Put this in the beginning of main() and look: the FPU is fast now.

Greetings,
Franz


From: Alf P. Steinbach /Usenet on
* Franz Bachler, on 16.07.2010 13:24:
> Hello,
>
> and the next problem& solution for MinGW:
>
> The FPU is very slow, up to 3times slower than as with other compilers.
> I've found this page
>
> http://www.network-theory.co.uk/docs/gccintro/gccintro_70.html
>
> and created the following code based of this information:
>
> #if !defined (__BORLANDC__)&& !defined (_MSC_VER)
> // use double-precision rounding for MinGW
> unsigned short cw=0x027F;
> asm("fldcw %0" : : "m" (*&cw));
> // this works only if cw is a global variable
> // asm("fldcw _cw");
> #endif
>
> Put this in the beginning of main() and look: the FPU is fast now.

Oh, interesting.

Probably there is some gcc runtime lib function for setting the rounding mode.


Cheers,

- Alf

--
blog at <url: http://alfps.wordpress.com>