/*
 * LTTTypes.h
 *
 * Copyright (C) 2000 Karim Yaghmour (karym@opersys.com).
 *
 * This is distributed under GPL.
 *
 * Header for LTT-secific types.
 *
 * History : 
 *    JAL,  05/01/2001, Modified PPC bit manipulation functions for x86 compatibility.
 *                      (andy_lowe@mvista.com)
 *    K.Y., 31/05/2000, Initial typing.
 */

#ifndef __TRACE_TOOLKIT_TYPES_HEADER__
#define __TRACE_TOOLKIT_TYPES_HEADER__

#include <Arch.h>  /* This is to find out which architecture we are actually running on */

#include <sys/types.h>
#include <sys/time.h>
#ifdef ARCH_I386
#include <asm/bitops.h>
#endif

#ifdef ARCH_PPC
extern __inline__ int ltt_set_bit(int nr, volatile void * addr)
{
	unsigned long old, t;
	unsigned long mask = 1 << (24 - (nr & 0x18) + (nr & 0x7));
	volatile unsigned long *p = ((volatile unsigned long *)addr) + (nr >> 5);
	
	__asm__ __volatile__(
		"1:lwarx %0,0,%3 \n\t"
		"or	%1,%0,%2 \n\t"
		"stwcx.	%1,0,%3 \n\t"
		"bne	1b \n\t"
		: "=&r" (old), "=&r" (t)	/*, "=m" (*p)*/
		: "r" (mask), "r" (p)
		/*: "cc" */);

	return (old & mask) != 0;
}

extern __inline__  int ltt_clear_bit(unsigned long nr, volatile void *addr)
{
	unsigned long old, t;
	unsigned long mask = 1 << (24 - (nr & 0x18) + (nr & 0x7));
	volatile unsigned long *p = ((volatile unsigned long *)addr) + (nr >> 5);

	__asm__ __volatile__("\n\
1:	lwarx	%0,0,%3
	andc	%1,%0,%2
	stwcx.	%1,0,%3
	bne	1b"
	: "=&r" (old), "=&r" (t)	/*, "=m" (*p)*/
	: "r" (mask), "r" (p)
      /*: "cc"*/);

	return (old & mask) != 0;
}

extern __inline__ int ltt_test_bit(int nr, __const__ volatile void *addr)
{
	__const__ volatile unsigned int *p = (__const__ volatile unsigned int *) addr;

	return ((p[nr >> 5] >> (24 - (nr & 0x18) + (nr & 0x7))) & 1) != 0;
}

#else  /* ifdef ARCH_PPC */

#define ltt_set_bit          set_bit
#define ltt_clear_bit        clear_bit
#define ltt_test_bit         test_bit

#endif /* ifdef ARCH_PPC */

/* Big-endian/little-endian conversion macros for cross-development. */
#if TARGET_NATIVE
/* For native development, these conversion macros aren't needed. */
#define BREV16(x)   (x)
#define BREV32(x)   (x)
#define BREV64(x)   (x)
#define RFT8(db,x)  (x)
#define RFT16(db,x) (x)
#define RFT32(db,x) (x)
#define RFT64(db,x) (x)

/* Non-native development */
#else
        /* BREV16: byte-reverse a 16-bit integer */
#define BREV16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8))
	/* BREV32: byte-reverse a 32-bit integer */
#define BREV32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \
		 | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
	/* BREV64: byte-reverse a 64-bit integer */
#define BREV64(x) ((((x) & 0xff00000000000000) >> 56) \
                 | (((x) & 0x00ff000000000000) >> 40) \
		 | (((x) & 0x0000ff0000000000) >> 24) \
		 | (((x) & 0x000000ff00000000) >>  8) \
		 | (((x) & 0x00000000ff000000) <<  8) \
		 | (((x) & 0x0000000000ff0000) << 24) \
		 | (((x) & 0x000000000000ff00) << 40) \
		 | (((x) & 0x00000000000000ff) << 56))
	/* RFTn: Read From Trace
	 *	Conditionally byte-reverse an 8-, 16-, 32-, or 64-bit integer
	 *      based on the value of the ByteRev member of the trace database
	 *      structure pointer passed as the first argument..
	 */
#define RFT8(db,x)  (x)
#define RFT16(db,x) ((db)->ByteRev ? BREV16(x) : (x))
#define RFT32(db,x) ((db)->ByteRev ? BREV32(x) : (x))
#define RFT64(db,x) ((db)->ByteRev ? BREV64(x) : (x))
#endif /* TRACE_TARGET_NATIVE */

/* Some type corrections, just in case */
#ifndef uint8_t
#define uint8_t u_int8_t
#endif
#ifndef uint16_t
#define uint16_t u_int16_t
#endif
#ifndef uint32_t
#define uint32_t u_int32_t
#endif
#ifndef uint64_t
#define uint64_t u_int64_t
#endif

/* Structure packing */
#if LTT_UNPACKED_STRUCTS
#define LTT_PACKED_STRUCT
#else
#define LTT_PACKED_STRUCT __attribute__ ((packed));
#endif /* UNPACKED_STRUCTS */

/* Trace mask */
typedef uint64_t trace_event_mask;

/* Boolean stuff */
#define TRUE  1
#define FALSE 0

#endif /* __TRACE_TOOLKIT_TYPES_HEADER__ */
