/*   SCE CONFIDENTIAL                                       */
/*   PLAYSTATION(R)3 Programmer Tool Runtime Library 082.011 */
/*   Copyright (C) 2006 Sony Computer Entertainment Inc.    */
/*   All Rights Reserved.                                   */

//////////////////////////////////////////////////////////////////////
// Author: Steven Osman
// There's a very basic clock implementation here.
//////////////////////////////////////////////////////////////////////

#ifndef __CLOCK_H
#define __CLOCK_H

#include <stdint.h>
#include <sys/sys_time.h>

#if defined(__LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus)
extern "C" {
#endif
	inline float clockGetFrequency();

	extern uint64_t gs_ulClock;

	/**
	 * E Resets the default clock.
	 * Future calls to clockCycles() and clockSeconds() will be relative to
	 * this time.
	 */
	inline void clockInit();

	/**
	 * E Initializes a user clock.
	 */
	inline uint64_t clockInitEx();

   
	/**
	 * E Reads in the default clock.
	 * Returns the number of cycles/100 since the last call to clockInit
	 */
	inline uint64_t clockCycles();

	/**
	 * E Reads in a user clock.
	 * Returns the number of cycles/100 since the clockInitEx call for this 
	 * clock.
	 */
	inline uint64_t clockCyclesEx(uint64_t ulClock);
  
	/**
	 * E Reads in the default clock.
	 * Returns the number of seconds since the last call to clockInit.
	 */
	inline float clockSeconds();

	/**
	 * E Reads in a user clock.
	 * Returns the number of seconds since the clockInitEx call for this clock.
	 */
	inline float clockSecondsEx(uint64_t ulClock);

	inline float clockGetFrequency() {
		static float fFrequency=0.0f;
  
		if (fFrequency==0) 
			fFrequency = (float) sys_time_get_timebase_frequency();
  
		return fFrequency;
	}

	extern uint64_t gs_ulClock;

	inline void clockInit() {
		__asm __volatile__( "mftb %0" : "=r" (gs_ulClock) : : "memory");
	}

	inline uint64_t clockInitEx() {
		uint64_t result;
		__asm __volatile__( "mftb %0" : "=r" (result) : : "memory");
		return result;
	}

	inline uint64_t clockCycles() {
		return clockInitEx()-gs_ulClock;
	}

	inline uint64_t clockCyclesEx(uint64_t ulClock) {
		return clockInitEx()-ulClock;
	}

	inline float clockSeconds() {
		return clockCycles()/clockGetFrequency();
	}

	inline float clockSecondsEx(uint64_t ulClock) {
		return clockCyclesEx(ulClock)/clockGetFrequency();
	}
  
#if defined(__LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus)
};
#endif

#endif
