os_timer.c
author peter1138
Mon, 01 Jan 2007 01:40:56 +0000
changeset 5703 3f848403a814
parent 5551 5cc56d0e6f5f
permissions -rw-r--r--
(svn r7711) -Fix (r7354): NewGRF Action 7, GRF check condition 10 didn't ignore unknown GRF IDs. Also separate GRF ID conditions
from parameter conditions to remove code duplication in GRF checking code.
3383
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     1
/* $Id$ */
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     2
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     3
#include "stdafx.h"
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     4
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     5
#undef RDTSC_AVAILABLE
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     6
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     7
/* rdtsc for MSC_VER, uses simple inline assembly, or _rdtsc
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     8
 * from external win64.asm because VS2005 does not support inline assembly */
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
     9
#if defined(_MSC_VER) && !defined(RDTSC_AVAILABLE)
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    10
# if defined (_M_AMD64)
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    11
extern uint64 _rdtsc(void);
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    12
#	else
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    13
uint64 _declspec(naked) _rdtsc(void)
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    14
{
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    15
	_asm {
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    16
		rdtsc
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    17
		ret
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    18
	}
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    19
}
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    20
# endif
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    21
# define RDTSC_AVAILABLE
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    22
#endif
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    23
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    24
/* rdtsc for OS/2. Hopefully this works, who knows */
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    25
#if defined (__WATCOMC__) && !defined(RDTSC_AVAILABLE)
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    26
unsigned __int64 _rdtsc( void);
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    27
# pragma aux _rdtsc = 0x0F 0x31 value [edx eax] parm nomemory modify exact [edx eax] nomemory;
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    28
# define RDTSC_AVAILABLE
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    29
#endif
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    30
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    31
/* rdtsc for all other *nix-en (hopefully). Use GCC syntax */
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    32
#if defined(__i386__) || defined(__x86_64__) && !defined(RDTSC_AVAILABLE)
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    33
uint64 _rdtsc(void)
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    34
{
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    35
	uint32 high, low;
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    36
	__asm__ __volatile__ ("rdtsc" : "=a" (low), "=d" (high));
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    37
	return ((uint64)high << 32) | low;
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    38
}
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    39
# define RDTSC_AVAILABLE
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    40
#endif
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    41
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    42
/* rdtsc for PPC which has this not */
5551
5cc56d0e6f5f (svn r7548) -Codechange: Some MorphOS changes to get OpenTTD compiled, packaged (tokai)
Darkvater
parents: 3407
diff changeset
    43
#if (defined(__POWERPC__) || defined(__powerpc__)) && !defined(RDTSC_AVAILABLE)
3383
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    44
uint64 _rdtsc(void)
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    45
{
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    46
	uint32 high = 0, high2 = 0, low;
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    47
	/* PPC does not have rdtsc, so we cheat by reading the two 32-bit time-counters
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    48
	 * it has, 'Move From Time Base (Upper)'. Since these are two reads, in the
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    49
	 * very unlikely event that the lower part overflows to the upper part while we
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    50
	 * read it; we double-check and reread the registers */
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    51
	asm volatile (
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    52
				  "mftbu %0\n"
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    53
				  "mftb %1\n"
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    54
				  "mftbu %2\n"
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    55
				  "cmpw %3,%4\n"
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    56
				  "bne- $-16\n"
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    57
				  : "=r" (high), "=r" (low), "=r" (high2)
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    58
				  : "0" (high), "2" (high2)
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    59
				  );
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    60
	return ((uint64)high << 32) | low;
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    61
}
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    62
# define RDTSC_AVAILABLE
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    63
#endif
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    64
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    65
/* In all other cases we have no support for rdtsc. No major issue,
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    66
 * you just won't be able to profile your code with TIC()/TOC() */
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    67
#if !defined(RDTSC_AVAILABLE)
3407
eb0845aa1db7 (svn r4218) - Codechange: Try to make the rdtsc() not present warning message a bit more clear
Darkvater
parents: 3383
diff changeset
    68
#warning "(non-fatal) No support for rdtsc(), you won't be able to profile with TIC/TOC"
3383
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    69
uint64 _rdtsc(void) {return 0;}
24871cb73dbf (svn r4191) - Codechange: Properly set newlines and id for os_timer.c
Darkvater
parents: 3362
diff changeset
    70
#endif