/*
 * SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of Synopsys,
 * Inc., and is fully protected under copyright and trade secret laws. You may
 * not view, use, disclose, copy, or distribute this file or any information
 * contained herein except pursuant to a valid written license from Synopsys.
 */

//
//	The purpose of this file is to define SSE2 data types to abstacr from the compiler 
//	specific constructs. Currently the target compilers are GCC and the MS VC 2005.
//

#ifndef _SSE2_CMPL_ABSTRACTION_H_
#define _SSE2_CMPL_ABSTRACTION_H_

#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//
//	Ms Visual Studio
//
#if defined( _MSC_VER ) &&  _MSC_VER

#include "SSE_cmplr_abstraction_MSC.h"

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//
//	the GCC
//
#elif defined( _gcc )

#include "SSE_cmplr_abstraction_GCC.h"

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//
//	Other
//
#else

#include "SSE_cmplr_abstraction_other.h"


#endif

//
//	Namespace sse2
//
namespace sse2
{

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//
///	the wrapper for 128 bit xmm registers.
//
template <class X, class T, int N = (16/sizeof(T)) >
class xmm128
{
//	Type
protected:

	//
	///	The XMM register type.
	//
	typedef X MY_XMM;

	//
	///	The XMM register type.
	//
	typedef T MY_TYPE;

//	Data
protected:

	//
	///	The union of
	//
	union
	{
		MY_XMM x;
		MY_TYPE n[N];
	};

//	Construction
public:

	//
	///	The default constructor.
	//
	xmm128()
	{
		//
		//	We must be 128 bits only.
		//
		BOOST_STATIC_ASSERT( 16/sizeof( MY_TYPE ) == N );
	}

	//
	///	The copy constructor.
	//
	xmm128( const xmm128& op )
	{
		//
		//	We must be 128 bits only.
		//
		BOOST_STATIC_ASSERT( 16/sizeof( MY_TYPE ) == N );

		//
		//	Just assign.
		//
		x = op.x;
	}

	//
	///	The copy constructor.
	//
	xmm128( const MY_XMM& op )
	{
		//
		//	We must be 128 bits only.
		//
		BOOST_STATIC_ASSERT( 16/sizeof( MY_TYPE ) == N );

		//
		//	Just assign.
		//
		x = op.x;
		x = op;
	}

	//
	///	The destructor.
	//
	~xmm128()
	{}

//	Interface
public:

	//
	///	Assign our kind.
	//
	xmm128& operator= ( const xmm128& op )
	{
		x = op.x;
		return *this;
	}

	//
	///	Assign the xmm type.
	//
	xmm128& operator= ( const MY_XMM& op )
	{
		x = op;
		return *this;
	}

	//
	///	Operator to get packed type. The const version.
	//
	operator MY_XMM () const
	{
		return x;
	}

	//
	///	Operator to get packed type reference. Can be used as a lvalue.
	//
	MY_TYPE& operator[] ( int idx )
	{
		assert( 0<= idx && idx < N );
		return n[idx];
	}

	//
	///	Operator to get packed type. The const version.
	//
	MY_TYPE operator[] ( int idx ) const
	{
		assert( 0<= idx && idx < N );
		return n[idx];
	}

	//
	///	Set from two values.
	//
	void set( MY_TYPE v1, MY_TYPE v2 )
	{
		BOOST_STATIC_ASSERT( 16 / sizeof( MY_TYPE ) == 2 );
		operator[0] = v1;
		operator[1] = v2;
	}

	//
	///	Set from two values.
	//
	void set( MY_TYPE v1, MY_TYPE v2, MY_TYPE v2, MY_TYPE v4 )
	{
		BOOST_STATIC_ASSERT( 16 / sizeof( MY_TYPE ) == 4 );
		operator[0] = v1;
		operator[1] = v2;
		operator[2] = v3;
		operator[3] = v4;
	}

	add
	sub
	andnot
	and
	or
	xor

	sqrt
	mul
	div
	min
	max

	shift

	comp
};

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/*
class xmm128d : public xmm128 < rxmm128d, double, 2 >
{
//	Construction
public: 

	//
	///	The default constructor.
	//
	xmm128d()
	{}

	//
	///	The copy constructor.
	//
	xmm128d( const xmm128d& op )
		: xmm128( op )
	{}

	//
	///	The copy constructor.
	//
	xmm128d( const MY_XMM& op )
		: xmm128( op )
	{}

	//
	///	The copy constructor.
	//
	xmm128d( double d1, double d2 )
	{
		set( d1, d2 );
	}


//	Interface
public:

	//
	///	Set from two doubles.
	//
	void set( double d1, double d2 )
	{
		operator[0] = d1;
		operator[1] = d2;
	}
};
*/

//
//	Namespace sse2
//
}

#endif/*_SSE2_CMPL_ABSTRACTION_H_*/
