Darkvater@3383: /* $Id$ */ Darkvater@3383: Darkvater@3383: #include "stdafx.h" Darkvater@3383: Darkvater@3383: #undef RDTSC_AVAILABLE Darkvater@3383: Darkvater@3383: /* rdtsc for MSC_VER, uses simple inline assembly, or _rdtsc Darkvater@3383: * from external win64.asm because VS2005 does not support inline assembly */ Darkvater@3383: #if defined(_MSC_VER) && !defined(RDTSC_AVAILABLE) Darkvater@3383: # if defined (_M_AMD64) Darkvater@3383: extern uint64 _rdtsc(void); Darkvater@3383: # else Darkvater@3383: uint64 _declspec(naked) _rdtsc(void) Darkvater@3383: { Darkvater@3383: _asm { Darkvater@3383: rdtsc Darkvater@3383: ret Darkvater@3383: } Darkvater@3383: } Darkvater@3383: # endif Darkvater@3383: # define RDTSC_AVAILABLE Darkvater@3383: #endif Darkvater@3383: Darkvater@3383: /* rdtsc for OS/2. Hopefully this works, who knows */ Darkvater@3383: #if defined (__WATCOMC__) && !defined(RDTSC_AVAILABLE) Darkvater@3383: unsigned __int64 _rdtsc( void); Darkvater@3383: # pragma aux _rdtsc = 0x0F 0x31 value [edx eax] parm nomemory modify exact [edx eax] nomemory; Darkvater@3383: # define RDTSC_AVAILABLE Darkvater@3383: #endif Darkvater@3383: Darkvater@3383: /* rdtsc for all other *nix-en (hopefully). Use GCC syntax */ Darkvater@3383: #if defined(__i386__) || defined(__x86_64__) && !defined(RDTSC_AVAILABLE) Darkvater@3383: uint64 _rdtsc(void) Darkvater@3383: { Darkvater@3383: uint32 high, low; Darkvater@3383: __asm__ __volatile__ ("rdtsc" : "=a" (low), "=d" (high)); Darkvater@3383: return ((uint64)high << 32) | low; Darkvater@3383: } Darkvater@3383: # define RDTSC_AVAILABLE Darkvater@3383: #endif Darkvater@3383: Darkvater@3383: /* rdtsc for PPC which has this not */ Darkvater@5551: #if (defined(__POWERPC__) || defined(__powerpc__)) && !defined(RDTSC_AVAILABLE) Darkvater@3383: uint64 _rdtsc(void) Darkvater@3383: { Darkvater@3383: uint32 high = 0, high2 = 0, low; Darkvater@3383: /* PPC does not have rdtsc, so we cheat by reading the two 32-bit time-counters Darkvater@3383: * it has, 'Move From Time Base (Upper)'. Since these are two reads, in the Darkvater@3383: * very unlikely event that the lower part overflows to the upper part while we Darkvater@3383: * read it; we double-check and reread the registers */ Darkvater@3383: asm volatile ( Darkvater@3383: "mftbu %0\n" Darkvater@3383: "mftb %1\n" Darkvater@3383: "mftbu %2\n" Darkvater@3383: "cmpw %3,%4\n" Darkvater@3383: "bne- $-16\n" Darkvater@3383: : "=r" (high), "=r" (low), "=r" (high2) Darkvater@3383: : "0" (high), "2" (high2) Darkvater@3383: ); Darkvater@3383: return ((uint64)high << 32) | low; Darkvater@3383: } Darkvater@3383: # define RDTSC_AVAILABLE Darkvater@3383: #endif Darkvater@3383: Darkvater@3383: /* In all other cases we have no support for rdtsc. No major issue, Darkvater@3383: * you just won't be able to profile your code with TIC()/TOC() */ Darkvater@3383: #if !defined(RDTSC_AVAILABLE) Darkvater@3407: #warning "(non-fatal) No support for rdtsc(), you won't be able to profile with TIC/TOC" Darkvater@3383: uint64 _rdtsc(void) {return 0;} Darkvater@3383: #endif