src/os_timer.cpp
author bjarni
Mon, 28 May 2007 21:40:40 +0000
changeset 6735 dd792fed65e2
parent 6351 8d0b6cce8d6d
child 7405 2fd57f130eca
permissions -rw-r--r--
(svn r9967) -Fix (r9938): autoreplace would in certain conditions move dualheaded engines in a train (usually to the rear)
-Change: moving an engine in between the two ends of a dualheaded engine will now move the rear dualheaded engine to the front of the newly added engine (instead of moving the new engine to the rear of the rear dualheaded engine)
This can make a difference if there are wagons in the train
3383
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     1
/* $Id$ */
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     2
6351
8d0b6cce8d6d (svn r9390) -Documentation : correct Doxygen of comments and @file inclusion. This time, brought to you by the letter O
belugas
parents: 6247
diff changeset
     3
/** @file os_timer.cpp */
8d0b6cce8d6d (svn r9390) -Documentation : correct Doxygen of comments and @file inclusion. This time, brought to you by the letter O
belugas
parents: 6247
diff changeset
     4
3383
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     5
#include "stdafx.h"
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     6
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     7
#undef RDTSC_AVAILABLE
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     8
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     9
/* rdtsc for MSC_VER, uses simple inline assembly, or _rdtsc
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    10
 * from external win64.asm because VS2005 does not support inline assembly */
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    11
#if defined(_MSC_VER) && !defined(RDTSC_AVAILABLE)
6171
fb9997933c24 (svn r8933) -Fix [Win64]: rdtsc now uses intrinsic on VC8 (michi_cc)
KUDr
parents: 5584
diff changeset
    12
# if _MSC_VER >= 1400
fb9997933c24 (svn r8933) -Fix [Win64]: rdtsc now uses intrinsic on VC8 (michi_cc)
KUDr
parents: 5584
diff changeset
    13
#include <intrin.h>
6247
7d81e3a5d803 (svn r9050) -Codechange: Foo(void) -> Foo()
rubidium
parents: 6171
diff changeset
    14
uint64 _rdtsc()
6171
fb9997933c24 (svn r8933) -Fix [Win64]: rdtsc now uses intrinsic on VC8 (michi_cc)
KUDr
parents: 5584
diff changeset
    15
{
fb9997933c24 (svn r8933) -Fix [Win64]: rdtsc now uses intrinsic on VC8 (michi_cc)
KUDr
parents: 5584
diff changeset
    16
	return __rdtsc();
fb9997933c24 (svn r8933) -Fix [Win64]: rdtsc now uses intrinsic on VC8 (michi_cc)
KUDr
parents: 5584
diff changeset
    17
}
3383
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    18
#	else
6247
7d81e3a5d803 (svn r9050) -Codechange: Foo(void) -> Foo()
rubidium
parents: 6171
diff changeset
    19
uint64 _declspec(naked) _rdtsc()
3383
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    20
{
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    21
	_asm {
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    22
		rdtsc
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    23
		ret
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    24
	}
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    25
}
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    26
# endif
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    27
# define RDTSC_AVAILABLE
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    28
#endif
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    29
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    30
/* rdtsc for OS/2. Hopefully this works, who knows */
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    31
#if defined (__WATCOMC__) && !defined(RDTSC_AVAILABLE)
6247
7d81e3a5d803 (svn r9050) -Codechange: Foo(void) -> Foo()
rubidium
parents: 6171
diff changeset
    32
unsigned __int64 _rdtsc();
3383
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    33
# pragma aux _rdtsc = 0x0F 0x31 value [edx eax] parm nomemory modify exact [edx eax] nomemory;
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    34
# define RDTSC_AVAILABLE
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    35
#endif
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    36
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    37
/* rdtsc for all other *nix-en (hopefully). Use GCC syntax */
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    38
#if defined(__i386__) || defined(__x86_64__) && !defined(RDTSC_AVAILABLE)
6247
7d81e3a5d803 (svn r9050) -Codechange: Foo(void) -> Foo()
rubidium
parents: 6171
diff changeset
    39
uint64 _rdtsc()
3383
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    40
{
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    41
	uint32 high, low;
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    42
	__asm__ __volatile__ ("rdtsc" : "=a" (low), "=d" (high));
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    43
	return ((uint64)high << 32) | low;
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    44
}
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    45
# define RDTSC_AVAILABLE
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    46
#endif
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    47
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    48
/* rdtsc for PPC which has this not */
5363
11cbdbe10de6 (svn r7548) -Codechange: Some MorphOS changes to get OpenTTD compiled, packaged (tokai)
Darkvater
parents: 3407
diff changeset
    49
#if (defined(__POWERPC__) || defined(__powerpc__)) && !defined(RDTSC_AVAILABLE)
6247
7d81e3a5d803 (svn r9050) -Codechange: Foo(void) -> Foo()
rubidium
parents: 6171
diff changeset
    50
uint64 _rdtsc()
3383
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    51
{
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    52
	uint32 high = 0, high2 = 0, low;
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    53
	/* PPC does not have rdtsc, so we cheat by reading the two 32-bit time-counters
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    54
	 * it has, 'Move From Time Base (Upper)'. Since these are two reads, in the
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    55
	 * very unlikely event that the lower part overflows to the upper part while we
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    56
	 * read it; we double-check and reread the registers */
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    57
	asm volatile (
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    58
				  "mftbu %0\n"
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    59
				  "mftb %1\n"
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    60
				  "mftbu %2\n"
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    61
				  "cmpw %3,%4\n"
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    62
				  "bne- $-16\n"
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    63
				  : "=r" (high), "=r" (low), "=r" (high2)
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    64
				  : "0" (high), "2" (high2)
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    65
				  );
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    66
	return ((uint64)high << 32) | low;
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    67
}
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    68
# define RDTSC_AVAILABLE
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    69
#endif
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    70
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    71
/* In all other cases we have no support for rdtsc. No major issue,
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    72
 * you just won't be able to profile your code with TIC()/TOC() */
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    73
#if !defined(RDTSC_AVAILABLE)
3407
150783e37553 (svn r4218) - Codechange: Try to make the rdtsc() not present warning message a bit more clear
Darkvater
parents: 3383
diff changeset
    74
#warning "(non-fatal) No support for rdtsc(), you won't be able to profile with TIC/TOC"
6247
7d81e3a5d803 (svn r9050) -Codechange: Foo(void) -> Foo()
rubidium
parents: 6171
diff changeset
    75
uint64 _rdtsc() {return 0;}
3383
a4828297b799 (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    76
#endif