/*	intrinsics.h -- C interface for TriCore special machine instructions.

	Copyright (C) 1999-2003 HighTec EDV-Systeme GmbH.
	
	This file is part of GCC.

	GCC is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 3, or (at your option)
	any later version.

	GCC is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	Under Section 7 of GPL version 3, you are granted additional
	permissions described in the GCC Runtime Library Exception, version
	3.1, as published by the Free Software Foundation.

	You should have received a copy of the GNU General Public License and
	a copy of the GCC Runtime Library Exception along with this program;
	see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
	<http://www.gnu.org/licenses/>.  */


#ifndef __intrinsics_h
#define __intrinsics_h

#define STRINGIFY(x)    #x

/* Note: you must use a numerical constant here (not an integer variable),
   otherwise the assembler will issue an error message.  */
#define __bisr(intlvl) __tric_bisr(intlvl)
#define _bisr(intlvl) __tric_bisr(intlvl)
#define __tric_bisr(intlvl) __asm__ volatile ("bisr "STRINGIFY(intlvl) : : : "memory")

/* Note: The parameter "regaddr" in the _mfcr and _mtcr macros may either
   be specified as a 16-bit constant or as a symbolic name (e.g., $psw).  */
#ifndef __MFCR
#define __MFCR(regaddr) __tric_mfcr(regaddr & 0xffff)
#endif

#define __mfcr(regaddr) __tric_mfcr(regaddr)
#define _mfcr(regaddr) __tric_mfcr(regaddr)
#define __tric_mfcr(regaddr) \
  ({ int res; __asm__ volatile ("mfcr %0,"STRINGIFY(regaddr) : "=d" (res) : : "memory"); res; })

#ifndef __MTCR
#define __MTCR(regaddr,val) __tric_mtcr(regaddr & 0xffff,val)
#endif

#define __mtcr(regaddr,val) __tric_mtcr(regaddr,val)
#define _mtcr(regaddr,val) __tric_mtcr(regaddr,val)
#define __tric_mtcr(regaddr,val) \
  { int newval = (val); __asm__ volatile ("mtcr "STRINGIFY(regaddr)",%0" : : "d" (newval) : "memory"); }

/* Note: you must use a numerical constant here (not an integer variable),
   otherwise the assembler will issue an error message.  */
#define _syscall(svcno) __tric_syscall(svcno)
#define __syscall(svcno) __tric_syscall(svcno)
#define __tric_syscall(svcno) __asm__ volatile ("syscall "STRINGIFY(svcno) : : : "memory")

#define _disable() __asm__ volatile ("disable" : : : "memory")
#define _enable() __asm__ volatile ("enable" : : : "memory")
#define _debug() __asm__ volatile ("debug" : : : "memory")
#define _isync() __asm__ volatile ("isync" : : : "memory")
#define _dsync() __asm__ volatile ("dsync" : : : "memory")
#define _rstv() __asm__ volatile ("rstv" : : : "memory")
#define _rslcx() __asm__ volatile ("rslcx" : : : "memory")
#define _svlcx() __asm__ volatile ("svlcx" : : : "memory")
#define _nop() __asm__ volatile ("nop")

#ifndef __CLZ
#define __CLZ(val)      __builtin_clz(val)
#endif
#ifndef __CTZ
#define __CTZ(val)      __builtin_ctz(val)
#endif
#ifndef __ABS
#define __ABS(val)      __builtin_abs(val)
#endif

#endif /* __intrinsics_h */
