1327952Sdim/* PPU intrinsics as defined by the C/C++ Language extension for Cell BEA.
2259698Sdim   Copyright (C) 2007-2020 Free Software Foundation, Inc.
3353358Sdim
4353358Sdim   This file is free software; you can redistribute it and/or modify it under
5353358Sdim   the terms of the GNU General Public License as published by the Free
6259698Sdim   Software Foundation; either version 3 of the License, or (at your option)
7259698Sdim   any later version.
8259698Sdim
9259698Sdim   This file is distributed in the hope that it will be useful, but WITHOUT
10259698Sdim   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11259698Sdim   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12259698Sdim   for more details.
13259698Sdim
14259698Sdim   Under Section 7 of GPL version 3, you are granted additional
15341825Sdim   permissions described in the GCC Runtime Library Exception, version
16259698Sdim   3.1, as published by the Free Software Foundation.
17327952Sdim
18259698Sdim   You should have received a copy of the GNU General Public License and
19327952Sdim   a copy of the GCC Runtime Library Exception along with this program;
20327952Sdim   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
21327952Sdim   <http://www.gnu.org/licenses/>.  */
22327952Sdim
23327952Sdim/*  TODO:
24259698Sdim    misc ops (traps)
25259698Sdim    supervisor/hypervisor mode ops.  */
26259698Sdim
27327952Sdim#ifndef  _PPU_INTRINSICS_H
28327952Sdim#define _PPU_INTRINSICS_H
29259698Sdim
30259698Sdim#if !defined(__PPU__) && !defined(__ppc__) && !defined(__ppc64__) \
31276479Sdim    && !defined(__GNUC__)
32276479Sdim  #error ppu_intrinsics.h included on wrong platform/compiler
33259698Sdim#endif
34327952Sdim
35259698Sdim#ifdef __cplusplus
36259698Sdimextern "C" {
37327952Sdim#endif
38341825Sdim
39259698Sdim/*
40296417Sdim * unsigned int __cntlzw(unsigned int)
41327952Sdim * unsigned int __cntlzd(unsigned long long)
42341825Sdim * int __mulhw(int, int)
43259698Sdim * unsigned int __mulhwu(unsigned int, unsigned int)
44259698Sdim * long long __mulhd(long long, long long)
45296417Sdim * unsigned long long __mulhdu(unsigned long long, unsigned long long)
46327952Sdim *
47341825Sdim * void __sync(void)
48259698Sdim * void __isync(void)
49259698Sdim * void __lwsync(void)
50259698Sdim * void __eieio(void)
51259698Sdim *
52259698Sdim * void __nop(void)
53259698Sdim * void __cctpl(void)
54259698Sdim * void __cctpm(void)
55259698Sdim * void __cctph(void)
56259698Sdim * void __db8cyc(void)
57327952Sdim * void __db10cyc(void)
58259698Sdim * void __db12cyc(void)
59259698Sdim * void __db16cyc(void)
60259698Sdim *
61327952Sdim * void __mtspr(unsigned int spr, unsigned long long value)
62327952Sdim * unsigned long long __mfspr(unsigned int spr)
63259698Sdim * unsigned long long __mftb(void)
64259698Sdim *
65259698Sdim * void __icbi(void *base)
66259698Sdim * void __dcbi(void *base)
67259698Sdim *
68259698Sdim * void __dcbf(void *base)
69259698Sdim * void __dcbz(void *base)
70360784Sdim * void __dcbst(void *base)
71259698Sdim * void __dcbtst(void *base)
72259698Sdim * void __dcbt(void *base)
73259698Sdim * void __dcbt_TH1000(void *EATRUNC, bool D, bool UG, int ID)
74259698Sdim * void __dcbt_TH1010(bool GO, int S, int UNITCNT, bool T, bool U, int ID)
75259698Sdim *
76259698Sdim * unsigned __lwarx(void *base)
77259698Sdim * unsigned long long __ldarx(void *base)
78259698Sdim * bool __stwcx(void *base, unsigned value)
79259698Sdim * bool __stdcx(void *base, unsigned long long value)
80259698Sdim *
81259698Sdim * unsigned short __lhbrx(void *base)
82259698Sdim * unsigned int __lwbrx(void *base)
83259698Sdim * unsigned long long __ldbrx(void *base)
84259698Sdim * void __sthbrx(void *base, unsigned short value)
85259698Sdim * void __stwbrx(void *base, unsigned int value)
86259698Sdim * void __stdbrx(void *base, unsigned long long value)
87259698Sdim *
88259698Sdim * double __fabs(double x)
89259698Sdim * float __fabsf(float x)
90259698Sdim * double __fnabs(double x)
91259698Sdim * float __fnabsf(float x)
92259698Sdim * double __fmadd(double x, double y, double z)
93259698Sdim * double __fmsub(double x, double y, double z)
94259698Sdim * double __fnmadd(double x, double y, double z)
95259698Sdim * double __fnmsub(double x, double y, double z)
96259698Sdim * float __fmadds(float x, float y, float z)
97259698Sdim * float __fmsubs(float x, float y, float z)
98259698Sdim * float __fnmadds(float x, float y, float z)
99259698Sdim * float __fnmsubs(float x, float y, float z)
100259698Sdim * double __fsel(double x, double y, double z)
101259698Sdim * float __fsels(float x, float y, float z)
102259698Sdim * double __frsqrte(double x)
103259698Sdim * float __fres(float x)
104259698Sdim * double __fsqrt(double x)
105259698Sdim * float __fsqrts(float x)
106259698Sdim * long long __fctid(double x)
107259698Sdim * long long __fctiw(double x)
108259698Sdim * double __fcfid(long long x)
109259698Sdim * double __mffs(void)
110259698Sdim * void __mtfsf(int mask, double value)
111259698Sdim * void __mtfsfi(int bits, int field)
112259698Sdim * void __mtfsb0(int)
113259698Sdim * void __mtfsb1(int)
114259698Sdim * double __setflm(double)
115259698Sdim *
116259698Sdim * dcbt intrinsics
117259698Sdim * void __protected_unlimited_stream_set (unsigned int direction, const void *add, unsigned int ID)
118259698Sdim * void __protected_stream_set (unsigned int direction, const void *add, unsigned int ID)
119259698Sdim * void __protected_stream_stop_all (void)
120259698Sdim * void __protected_stream_stop (unsigned int ID)
121259698Sdim * void __protected_stream_count (unsigned int unit_cnt, unsigned int ID)
122259698Sdim * void __protected_stream_go (void)
123259698Sdim */
124259698Sdim
125259698Sdimtypedef int __V4SI __attribute__((vector_size(16)));
126259698Sdim
127259698Sdim#define __cntlzw(v) __builtin_clz(v)
128259698Sdim#define __cntlzd(v) __builtin_clzll(v)
129259698Sdim
130259698Sdim#define __mulhw(a,b) __extension__ \
131259698Sdim  ({int result;			   \
132259698Sdim  __asm__ ("mulhw %0,%1,%2"	   \
133259698Sdim	   : "=r" (result)	   \
134259698Sdim	   : "r" ((int) (a)),	   \
135259698Sdim	     "r" ((int) (b)));	   \
136296417Sdim  result; })
137259698Sdim
138259698Sdim#define __mulhwu(a,b) __extension__	\
139259698Sdim  ({unsigned int result;		\
140259698Sdim  __asm__ ("mulhwu %0,%1,%2"		\
141276479Sdim	   : "=r" (result)		\
142276479Sdim	   : "r" ((unsigned int) (a)),	\
143276479Sdim	     "r" ((unsigned int) (b))); \
144259698Sdim  result; })
145259698Sdim
146259698Sdim#ifdef __powerpc64__
147259698Sdim#define __mulhd(a,b) __extension__   \
148259698Sdim  ({ long long result;		     \
149259698Sdim  __asm__ ("mulhd %0,%1,%2"	     \
150259698Sdim	   : "=r" (result)	     \
151259698Sdim	   : "r" ((long long) (a)),  \
152259698Sdim	     "r" ((long long) (b))); \
153259698Sdim  result; })
154259698Sdim
155259698Sdim#define __mulhdu(a,b) __extension__	      \
156259698Sdim  ({unsigned long long result;		      \
157259698Sdim  __asm__ ("mulhdu %0,%1,%2"		      \
158259698Sdim	   : "=r" (result)		      \
159259698Sdim	   : "r" ((unsigned long long) (a)),  \
160259698Sdim	     "r" ((unsigned long long) (b))); \
161259698Sdim  result; })
162259698Sdim#endif /* __powerpc64__ */
163259698Sdim
164259698Sdim#define __sync() __asm__ volatile ("sync" : : : "memory")
165259698Sdim#define __isync() __asm__ volatile ("isync" : : : "memory")
166259698Sdim#define __lwsync() __asm__ volatile ("lwsync" : : : "memory")
167259698Sdim#define __eieio() __asm__ volatile ("eieio" : : : "memory")
168259698Sdim
169259698Sdim#define __nop() __asm__ volatile ("ori 0,0,0" : : : "memory")
170259698Sdim#define __cctpl() __asm__ volatile ("or 1,1,1" : : : "memory")
171259698Sdim#define __cctpm() __asm__ volatile ("or 2,2,2" : : : "memory")
172259698Sdim#define __cctph() __asm__ volatile ("or 3,3,3" : : : "memory")
173259698Sdim#define __db8cyc() __asm__ volatile ("or 28,28,28" : : : "memory")
174259698Sdim#define __db10cyc() __asm__ volatile ("or 29,29,29" : : : "memory")
175259698Sdim#define __db12cyc() __asm__ volatile ("or 30,30,30" : : : "memory")
176259698Sdim#define __db16cyc() __asm__ volatile ("or 31,31,31" : : : "memory")
177259698Sdim
178259698Sdim#ifdef __powerpc64__
179259698Sdim#define __mtspr(spr, value) \
180259698Sdim  __asm__ volatile ("mtspr %0,%1" : : "n" (spr), "r" (value))
181259698Sdim
182259698Sdim#define __mfspr(spr) __extension__				\
183259698Sdim  ({ unsigned long long result;					\
184259698Sdim  __asm__ volatile ("mfspr %0,%1" : "=r" (result) : "n" (spr)); \
185259698Sdim  result; })
186259698Sdim#endif /* __powerpc64__ */
187259698Sdim
188259698Sdim#ifdef __powerpc64__
189259698Sdim/* Work around the hardware bug in the current Cell implementation.  */
190296417Sdim#define __mftb() __extension__					\
191296417Sdim  ({ unsigned long long result;					\
192296417Sdim  __asm__ volatile ("1: mftb %[current_tb]\n"			\
193259698Sdim      "\tcmpwi 7, %[current_tb], 0\n"				\
194259698Sdim      "\tbeq-  7, 1b"						\
195259698Sdim      : [current_tb] "=r" (result):				\
196259698Sdim      :"cr7");							\
197259698Sdim  result; })
198259698Sdim#else
199259698Sdim#define __mftb() __extension__			\
200259698Sdim  ({ unsigned long long result;			\
201259698Sdim  unsigned long t;				\
202259698Sdim  __asm__ volatile ("1:\n"			\
203259698Sdim		    "\tmftbu %0\n"		\
204259698Sdim		    "\tmftb %L0\n"		\
205259698Sdim		    "\tmftbu %1\n"		\
206259698Sdim		    "\tcmpw %0,%1\n"		\
207259698Sdim		    "\tbne 1b"			\
208259698Sdim		    : "=r" (result), "=r" (t));	\
209259698Sdim  result; })
210259698Sdim#endif /* __powerpc64__ */
211259698Sdim
212259698Sdim#define __dcbf(base) \
213259698Sdim  __asm__ volatile ("dcbf %y0" : "=Z" (*(__V4SI*) (base)) : : "memory")
214259698Sdim
215259698Sdim#define __dcbz(base) \
216259698Sdim  __asm__ volatile ("dcbz %y0" : "=Z" (*(__V4SI*) (base)) : : "memory")
217259698Sdim
218259698Sdim#define __dcbst(base) \
219259698Sdim  __asm__ volatile ("dcbst %y0" : "=Z" (*(__V4SI*) (base)) : : "memory")
220259698Sdim
221259698Sdim#define __dcbtst(base) \
222259698Sdim  __asm__ volatile ("dcbtst %y0" : "=Z" (*(__V4SI*) (base)) : : "memory")
223259698Sdim
224259698Sdim#define __dcbt(base) \
225259698Sdim  __asm__ volatile ("dcbt %y0" : "=Z" (*(__V4SI*) (base)) : : "memory")
226259698Sdim
227259698Sdim#define __icbi(base) \
228259698Sdim  __asm__ volatile ("icbi %y0" : "=Z" (*(__V4SI*) (base)) : : "memory")
229259698Sdim
230259698Sdim#define __dcbt_TH1000(EATRUNC, D, UG, ID)				\
231259698Sdim  __asm__ volatile ("dcbt %y0,8"					\
232259698Sdim	   : "=Z" (*(__V4SI*) (__SIZE_TYPE__)((((__SIZE_TYPE__) (EATRUNC)) & ~0x7F)	\
233259698Sdim	   		       | ((((D) & 1) << 6)			\
234344779Sdim	   		       | (((UG) & 1) << 5)			\
235259698Sdim	   		       | ((ID) & 0xF)))) : : "memory")
236259698Sdim
237259698Sdim#define __dcbt_TH1010(GO, S, UNITCNT, T, U, ID)			     \
238259698Sdim  __asm__ volatile ("dcbt %y0,10"				     \
239259698Sdim	   : "=Z" (*(__V4SI*) (__SIZE_TYPE__)((((__SIZE_TYPE__) (GO) & 1) << 31) \
240259698Sdim	   		       | (((S) & 0x3) << 29)		     \
241259698Sdim	   		       | (((UNITCNT) & 0x3FF) << 7)	     \
242259698Sdim	   		       | (((T) & 1) << 6)			     \
243259698Sdim	   		       | (((U) & 1) << 5)			     \
244259698Sdim	   		       | ((ID) & 0xF))) : : "memory")
245259698Sdim
246259698Sdim#define __protected_unlimited_stream_set(DIRECTION, ADDR, ID)	\
247259698Sdim	__dcbt_TH1000 ((ADDR), (DIRECTION)>>1, 1, (ID))
248259698Sdim
249259698Sdim#define __protected_stream_set(DIRECTION, ADDR, ID)	\
250259698Sdim	__dcbt_TH1000 ((ADDR), (DIRECTION)>>1, 0, (ID))
251259698Sdim
252327952Sdim#define __protected_stream_stop_all()			\
253327952Sdim	__dcbt_TH1010 (0, 3, 0, 0, 0, 0)
254360784Sdim
255360784Sdim#define __protected_stream_stop(ID)			\
256280031Sdim	__dcbt_TH1010 (0, 2, 0, 0, 0, (ID))
257280031Sdim
258280031Sdim#define __protected_stream_count(COUNT, ID)		\
259259698Sdim	__dcbt_TH1010 (0, 0, (COUNT), 0, 0, (ID))
260276479Sdim
261259698Sdim#define __protected_stream_go()				\
262259698Sdim	__dcbt_TH1010 (1, 0, 0, 0, 0, 0)
263259698Sdim
264259698Sdim#define __lhbrx(base) __extension__		\
265259698Sdim  ({unsigned short result;	       		\
266259698Sdim    typedef  struct {char a[2];} halfwordsize;	\
267259698Sdim    halfwordsize *ptrp = (halfwordsize*)(void*)(base);	\
268259698Sdim  __asm__ ("lhbrx %0,%y1"			\
269259698Sdim	   : "=r" (result)			\
270259698Sdim	   : "Z" (*ptrp));			\
271259698Sdim  result; })
272259698Sdim
273259698Sdim#define __lwbrx(base) __extension__		\
274259698Sdim  ({unsigned int result;	       		\
275259698Sdim    typedef  struct {char a[4];} wordsize;	\
276259698Sdim    wordsize *ptrp = (wordsize*)(void*)(base);		\
277259698Sdim  __asm__ ("lwbrx %0,%y1"			\
278259698Sdim	   : "=r" (result)			\
279259698Sdim	   : "Z" (*ptrp));			\
280259698Sdim  result; })
281360784Sdim
282259698Sdim
283259698Sdim#ifdef __powerpc64__
284259698Sdim#define __ldbrx(base) __extension__			\
285259698Sdim  ({unsigned long long result;	       			\
286259698Sdim    typedef  struct {char a[8];} doublewordsize;	\
287259698Sdim    doublewordsize *ptrp = (doublewordsize*)(void*)(base);	\
288259698Sdim  __asm__ ("ldbrx %0,%y1"				\
289259698Sdim	   : "=r" (result)				\
290259698Sdim	   : "Z" (*ptrp));				\
291259698Sdim  result; })
292259698Sdim#else
293259698Sdim#define __ldbrx(base) __extension__			\
294259698Sdim  ({unsigned long long result;	       			\
295259698Sdim    typedef  struct {char a[8];} doublewordsize;	\
296259698Sdim    doublewordsize *ptrp = (doublewordsize*)(void*)(base);	\
297259698Sdim  __asm__ ("lwbrx %L0,%y1\n"				\
298259698Sdim	   "\tlwbrx %0,%y2"				\
299259698Sdim	   : "=&r" (result)				\
300259698Sdim	   : "Z" (*ptrp), "Z" (*((char *) ptrp + 4)));	\
301259698Sdim  result; })
302259698Sdim#endif /* __powerpc64__ */
303259698Sdim
304259698Sdim
305259698Sdim#define __sthbrx(base, value) do {			\
306259698Sdim    typedef  struct {char a[2];} halfwordsize;		\
307259698Sdim    halfwordsize *ptrp = (halfwordsize*)(void*)(base);		\
308259698Sdim    __asm__ ("sthbrx %1,%y0"				\
309259698Sdim	   : "=Z" (*ptrp)				\
310259698Sdim	   : "r" (value));				\
311259698Sdim   } while (0)
312259698Sdim
313259698Sdim#define __stwbrx(base, value) do {		\
314341825Sdim    typedef  struct {char a[4];} wordsize;	\
315259698Sdim    wordsize *ptrp = (wordsize*)(void*)(base);		\
316259698Sdim    __asm__ ("stwbrx %1,%y0"			\
317259698Sdim	   : "=Z" (*ptrp)			\
318259698Sdim	   : "r" (value));			\
319259698Sdim   } while (0)
320259698Sdim
321259698Sdim#ifdef __powerpc64__
322259698Sdim#define __stdbrx(base, value) do {			\
323259698Sdim    typedef  struct {char a[8];} doublewordsize;	\
324259698Sdim    doublewordsize *ptrp = (doublewordsize*)(void*)(base);	\
325259698Sdim    __asm__ ("stdbrx %1,%y0"				\
326259698Sdim	   : "=Z" (*ptrp)				\
327344779Sdim	   : "r" (value));				\
328296417Sdim   } while (0)
329259698Sdim#else
330259698Sdim#define __stdbrx(base, value) do {			\
331259698Sdim    typedef  struct {char a[8];} doublewordsize;	\
332259698Sdim    doublewordsize *ptrp = (doublewordsize*)(void*)(base);	\
333259698Sdim    __asm__ ("stwbrx %L2,%y0\n"				\
334259698Sdim	     "\tstwbrx %2,%y1"				\
335259698Sdim	   : "=Z" (*ptrp), "=Z" (*((char *) ptrp + 4))	\
336259698Sdim	   : "r" (value));				\
337259698Sdim   } while (0)
338259698Sdim#endif /* __powerpc64__ */
339259698Sdim
340296417Sdim
341259698Sdim#define __lwarx(base) __extension__		\
342296417Sdim  ({unsigned int result;	       		\
343259698Sdim    typedef  struct {char a[4];} wordsize;	\
344327952Sdim    wordsize *ptrp = (wordsize*)(void*)(base);	\
345259698Sdim  __asm__ volatile ("lwarx %0,%y1"		\
346259698Sdim	   : "=r" (result)			\
347259698Sdim	   : "Z" (*ptrp));			\
348259698Sdim  result; })
349259698Sdim
350259698Sdim#ifdef __powerpc64__
351296417Sdim#define __ldarx(base) __extension__			\
352259698Sdim  ({unsigned long long result;	       			\
353259698Sdim    typedef  struct {char a[8];} doublewordsize;	\
354259698Sdim    doublewordsize *ptrp = (doublewordsize*)(void*)(base);	\
355259698Sdim  __asm__ volatile ("ldarx %0,%y1"			\
356259698Sdim	   : "=r" (result)				\
357259698Sdim	   : "Z" (*ptrp));				\
358259698Sdim  result; })
359259698Sdim#endif /* __powerpc64__ */
360259698Sdim
361259698Sdim#define __stwcx(base, value) __extension__	\
362259698Sdim  ({unsigned int result;			\
363259698Sdim    typedef  struct {char a[4];} wordsize;	\
364259698Sdim    wordsize *ptrp = (wordsize*)(void*)(base);	\
365259698Sdim  __asm__ volatile ("stwcx. %2,%y1\n"		\
366259698Sdim	   "\tmfocrf %0,0x80"			\
367259698Sdim	   : "=r" (result),			\
368259698Sdim	     "=Z" (*ptrp)			\
369296417Sdim	   : "r" (value) : "cr0");		\
370259698Sdim  ((result & 0x20000000) >> 29); })
371259698Sdim
372296417Sdim
373259698Sdim#ifdef __powerpc64__
374259698Sdim#define __stdcx(base, value) __extension__		\
375259698Sdim  ({unsigned long long result;				\
376259698Sdim    typedef  struct {char a[8];} doublewordsize;	\
377259698Sdim    doublewordsize *ptrp = (doublewordsize*)(void*)(base);	\
378259698Sdim  __asm__ volatile ("stdcx. %2,%y1\n"			\
379259698Sdim	   "\tmfocrf %0,0x80"				\
380259698Sdim	   : "=r" (result),				\
381259698Sdim	     "=Z" (*ptrp)				\
382259698Sdim	   : "r" (value) : "cr0");			\
383259698Sdim  ((result & 0x20000000) >> 29); })
384259698Sdim#endif /* __powerpc64__ */
385259698Sdim
386259698Sdim#define __mffs() __extension__			\
387259698Sdim  ({double result;				\
388259698Sdim  __asm__ volatile ("mffs %0" : "=d" (result)); \
389259698Sdim  result; })
390259698Sdim
391259698Sdim#define __mtfsf(mask,value) \
392259698Sdim  __asm__ volatile ("mtfsf %0,%1" : : "n" (mask), "d" ((double) (value)))
393259698Sdim
394259698Sdim#define __mtfsfi(bits,field) \
395259698Sdim  __asm__ volatile ("mtfsfi %0,%1" : : "n" (bits), "n" (field))
396259698Sdim
397259698Sdim#define __mtfsb0(bit) __asm__ volatile ("mtfsb0 %0" : : "n" (bit))
398296417Sdim#define __mtfsb1(bit) __asm__ volatile ("mtfsb1 %0" : : "n" (bit))
399259698Sdim
400259698Sdim#define __setflm(v) __extension__	      \
401259698Sdim  ({double result;			      \
402259698Sdim  __asm__ volatile ("mffs %0\n\tmtfsf 255,%1" \
403259698Sdim		    : "=&d" (result)	      \
404259698Sdim		    : "d" ((double) (v)));    \
405259698Sdim  result; })
406259698Sdim
407259698Sdim/* __builtin_fabs may perform unnecessary rounding.  */
408259698Sdim
409259698Sdim/* Rename __fabs and __fabsf to work around internal prototypes defined
410259698Sdim   in bits/mathcalls.h with some glibc versions.  */
411259698Sdim#define __fabs __ppu_fabs
412259698Sdim#define __fabsf __ppu_fabsf
413259698Sdim
414259698Sdimstatic __inline__ double __fabs(double x) __attribute__((always_inline));
415259698Sdimstatic __inline__ double
416259698Sdim__fabs(double x)
417259698Sdim{
418259698Sdim  double r;
419259698Sdim  __asm__("fabs %0,%1" : "=d"(r) : "d"(x));
420259698Sdim  return r;
421259698Sdim}
422259698Sdim
423344779Sdimstatic __inline__ float __fabsf(float x) __attribute__((always_inline));
424296417Sdimstatic __inline__ float
425259698Sdim__fabsf(float x)
426259698Sdim{
427259698Sdim  float r;
428259698Sdim  __asm__("fabs %0,%1" : "=f"(r) : "f"(x));
429259698Sdim  return r;
430259698Sdim}
431259698Sdim
432259698Sdimstatic __inline__ double __fnabs(double x) __attribute__((always_inline));
433259698Sdimstatic __inline__ double
434259698Sdim__fnabs(double x)
435259698Sdim{
436296417Sdim  double r;
437296417Sdim  __asm__("fnabs %0,%1" : "=d"(r) : "d"(x));
438259698Sdim  return r;
439259698Sdim}
440259698Sdim
441259698Sdimstatic __inline__ float __fnabsf(float x) __attribute__((always_inline));
442259698Sdimstatic __inline__ float
443259698Sdim__fnabsf(float x)
444259698Sdim{
445259698Sdim  float r;
446259698Sdim  __asm__("fnabs %0,%1" : "=f"(r) : "f"(x));
447360784Sdim  return r;
448259698Sdim}
449259698Sdim
450259698Sdimstatic __inline__ double __fmadd(double x, double y, double z)
451259698Sdim  __attribute__((always_inline));
452259698Sdimstatic __inline__ double
453259698Sdim__fmadd(double x, double y, double z)
454259698Sdim{
455259698Sdim  double r;
456360784Sdim  __asm__("fmadd %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
457360784Sdim  return r;
458360784Sdim}
459360784Sdim
460360784Sdimstatic __inline__ double __fmsub(double x, double y, double z)
461360784Sdim  __attribute__((always_inline));
462360784Sdimstatic __inline__ double
463360784Sdim__fmsub(double x, double y, double z)
464360784Sdim{
465360784Sdim  double r;
466259698Sdim  __asm__("fmsub %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
467259698Sdim  return r;
468259698Sdim}
469259698Sdim
470259698Sdimstatic __inline__ double __fnmadd(double x, double y, double z)
471259698Sdim  __attribute__((always_inline));
472259698Sdimstatic __inline__ double
473259698Sdim__fnmadd(double x, double y, double z)
474259698Sdim{
475259698Sdim  double r;
476259698Sdim  __asm__("fnmadd %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
477259698Sdim  return r;
478259698Sdim}
479259698Sdim
480259698Sdimstatic __inline__ double __fnmsub(double x, double y, double z)
481341825Sdim  __attribute__((always_inline));
482259698Sdimstatic __inline__ double
483259698Sdim__fnmsub(double x, double y, double z)
484259698Sdim{
485259698Sdim  double r;
486259698Sdim  __asm__("fnmsub %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
487259698Sdim  return r;
488259698Sdim}
489259698Sdim
490259698Sdimstatic __inline__ float __fmadds(float x, float y, float z)
491314564Sdim  __attribute__((always_inline));
492259698Sdimstatic __inline__ float
493314564Sdim__fmadds(float x, float y, float z)
494259698Sdim{
495259698Sdim  float r;
496259698Sdim  __asm__("fmadds %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z));
497259698Sdim  return r;
498327952Sdim}
499259698Sdim
500259698Sdimstatic __inline__ float __fmsubs(float x, float y, float z)
501259698Sdim  __attribute__((always_inline));
502static __inline__ float
503__fmsubs(float x, float y, float z)
504{
505  float r;
506  __asm__("fmsubs %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z));
507  return r;
508}
509
510static __inline__ float __fnmadds(float x, float y, float z)
511  __attribute__((always_inline));
512static __inline__ float
513__fnmadds(float x, float y, float z)
514{
515  float r;
516  __asm__("fnmadds %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z));
517  return r;
518}
519
520static __inline__ float __fnmsubs(float x, float y, float z)
521  __attribute__((always_inline));
522static __inline__ float
523__fnmsubs(float x, float y, float z)
524{
525  float r;
526  __asm__("fnmsubs %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z));
527  return r;
528}
529
530static __inline__ double __fsel(double x, double y, double z)
531  __attribute__((always_inline));
532static __inline__ double
533__fsel(double x, double y, double z)
534{
535  double r;
536  __asm__("fsel %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z));
537  return r;
538}
539
540static __inline__ float __fsels(float x, float y, float z)
541  __attribute__((always_inline));
542static __inline__ float
543__fsels(float x, float y, float z)
544{
545  float r;
546  __asm__("fsel %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z));
547  return r;
548}
549
550static __inline__ double __frsqrte(double x) __attribute__((always_inline));
551static __inline__ double
552__frsqrte(double x)
553{
554  double r;
555  __asm__("frsqrte %0,%1" : "=d" (r) : "d" (x));
556  return r;
557}
558
559static __inline__ float __fres(float x) __attribute__((always_inline));
560static __inline__ float
561__fres(float x)
562{
563  float r;
564  __asm__("fres %0,%1" : "=f"(r) : "f"(x));
565  return r;
566}
567
568static __inline__ double __fsqrt(double x) __attribute__((always_inline));
569static __inline__ double
570__fsqrt(double x)
571{
572  double r;
573  __asm__("fsqrt %0,%1" : "=d"(r) : "d"(x));
574  return r;
575}
576
577static __inline__ float __fsqrts(float x) __attribute__((always_inline));
578static __inline__ float
579__fsqrts(float x)
580{
581  float r;
582  __asm__("fsqrts %0,%1" : "=f"(r) : "f"(x));
583  return r;
584}
585
586static __inline__ double __fmul (double a, double b) __attribute__ ((always_inline));
587static __inline__ double
588__fmul(double a, double b)
589{
590  double d;
591  __asm__ ("fmul %0,%1,%2" : "=d" (d) : "d" (a), "d" (b));
592  return d;
593}
594
595static __inline__ float __fmuls (float a, float b) __attribute__ ((always_inline));
596static __inline__ float
597__fmuls (float a, float b)
598{
599  float d;
600  __asm__ ("fmuls %0,%1,%2" : "=d" (d) : "f" (a), "f" (b));
601  return d;
602}
603
604static __inline__ float __frsp (float a) __attribute__ ((always_inline));
605static __inline__ float
606__frsp (float a)
607{
608  float d;
609  __asm__ ("frsp %0,%1" : "=d" (d) : "f" (a));
610  return d;
611}
612
613static __inline__ double __fcfid (long long a) __attribute__((always_inline));
614static __inline__ double
615__fcfid (long long a)
616{
617  double d;
618  __asm__ ("fcfid %0,%1" : "=d" (d) : "d" (a));
619  return d;
620}
621
622static __inline__ long long __fctid (double a) __attribute__ ((always_inline));
623static __inline__ long long
624__fctid (double a)
625{
626  long long d;
627  __asm__ ("fctid %0,%1" : "=d" (d) : "d" (a));
628  return d;
629}
630
631static __inline__ long long __fctidz (double a) __attribute__ ((always_inline));
632static __inline__ long long
633__fctidz (double a)
634{
635  long long d;
636  __asm__ ("fctidz %0,%1" : "=d" (d) : "d" (a));
637  return d;
638}
639
640static __inline__ int __fctiw (double a) __attribute__ ((always_inline));
641static __inline__ int
642__fctiw (double a)
643{
644  unsigned long long d;
645  __asm__ ("fctiw %0,%1" : "=d" (d) : "d" (a));
646  return (int) d;
647}
648
649static __inline__ int __fctiwz (double a) __attribute__ ((always_inline));
650static __inline__ int
651__fctiwz (double a)
652{
653  long long d;
654  __asm__ ("fctiwz %0,%1" : "=d" (d) : "d" (a));
655  return (int) d;
656}
657
658#ifdef __powerpc64__
659#define __rldcl(a,b,mb) __extension__ \
660  ({ \
661    unsigned long long d; \
662    __asm__ ("rldcl %0,%1,%2,%3" : "=r" (d) : "r" (a), "r" (b), "i" (mb)); \
663    d; \
664  })
665
666#define __rldcr(a,b,me) __extension__ \
667  ({ \
668    unsigned long long d; \
669    __asm__ ("rldcr %0,%1,%2,%3" : "=r" (d) : "r" (a), "r" (b), "i" (me)); \
670    d; \
671  })
672
673#define __rldic(a,sh,mb) __extension__ \
674  ({ \
675    unsigned long long d; \
676    __asm__ ("rldic %0,%1,%2,%3" : "=r" (d) : "r" (a), "i" (sh), "i" (mb)); \
677    d; \
678  })
679
680#define __rldicl(a,sh,mb) __extension__ \
681  ({ \
682    unsigned long long d; \
683    __asm__ ("rldicl %0,%1,%2,%3" : "=r" (d) : "r" (a), "i" (sh), "i" (mb)); \
684    d; \
685  })
686
687#define __rldicr(a,sh,me) __extension__ \
688  ({ \
689    unsigned long long d; \
690    __asm__ ("rldicr %0,%1,%2,%3" : "=r" (d) : "r" (a), "i" (sh), "i" (me)); \
691    d; \
692  })
693
694#define __rldimi(a,b,sh,mb) __extension__ \
695  ({ \
696    unsigned long long d; \
697    __asm__ ("rldimi %0,%1,%2,%3" : "=r" (d) : "r" (b), "i" (sh), "i" (mb), "0" (a)); \
698    d; \
699  })
700#endif /* __powerpc64__ */
701
702#define __rlwimi(a,b,sh,mb,me) __extension__ \
703  ({ \
704    unsigned int d; \
705    __asm__ ("rlwimi %0,%1,%2,%3,%4" : "=r" (d) : "r" (b), "i" (sh), "i" (mb), "i" (me), "0" (a)); \
706    d; \
707  })
708
709#define __rlwinm(a,sh,mb,me) __extension__ \
710  ({ \
711    unsigned int d; \
712    __asm__ ("rlwinm %0,%1,%2,%3,%4" : "=r" (d) : "r" (a), "i" (sh), "i" (mb), "i" (me)); \
713    d; \
714  })
715
716#define __rlwnm(a,b,mb,me) __extension__ \
717  ({ \
718    unsigned int d; \
719    __asm__ ("rlwnm %0,%1,%2,%3,%4" : "=r" (d) : "r" (a), "r" (b), "i" (mb), "i" (me)); \
720    d; \
721  })
722
723#ifdef __cplusplus
724}
725#endif
726
727#endif /* _PPU_INTRINSICS_H */
728