1#ifndef _ASM_IA64_GCC_INTRIN_H
2#define _ASM_IA64_GCC_INTRIN_H
3/*
4 *
5 * Copyright (C) 2002,2003 Jun Nakajima <jun.nakajima@intel.com>
6 * Copyright (C) 2002,2003 Suresh Siddha <suresh.b.siddha@intel.com>
7 */
8
9#include <linux/compiler.h>
10
11/* define this macro to get some asm stmts included in 'c' files */
12#define ASM_SUPPORTED
13
14/* Optimization barrier */
15/* The "volatile" is due to gcc bugs */
16#define ia64_barrier()	asm volatile ("":::"memory")
17
18#define ia64_stop()	asm volatile (";;"::)
19
20#define ia64_invala_gr(regnum)	asm volatile ("invala.e r%0" :: "i"(regnum))
21
22#define ia64_invala_fr(regnum)	asm volatile ("invala.e f%0" :: "i"(regnum))
23
24extern void ia64_bad_param_for_setreg (void);
25extern void ia64_bad_param_for_getreg (void);
26
27register unsigned long ia64_r13 asm ("r13") __attribute_used__;
28
29#define ia64_setreg(regnum, val)						\
30({										\
31	switch (regnum) {							\
32	    case _IA64_REG_PSR_L:						\
33		    asm volatile ("mov psr.l=%0" :: "r"(val) : "memory");	\
34		    break;							\
35	    case _IA64_REG_AR_KR0 ... _IA64_REG_AR_EC:				\
36		    asm volatile ("mov ar%0=%1" ::				\
37		    			  "i" (regnum - _IA64_REG_AR_KR0),	\
38					  "r"(val): "memory");			\
39		    break;							\
40	    case _IA64_REG_CR_DCR ... _IA64_REG_CR_LRR1:			\
41		    asm volatile ("mov cr%0=%1" ::				\
42				          "i" (regnum - _IA64_REG_CR_DCR),	\
43					  "r"(val): "memory" );			\
44		    break;							\
45	    case _IA64_REG_SP:							\
46		    asm volatile ("mov r12=%0" ::				\
47			    		  "r"(val): "memory");			\
48		    break;							\
49	    case _IA64_REG_GP:							\
50		    asm volatile ("mov gp=%0" :: "r"(val) : "memory");		\
51		break;								\
52	    default:								\
53		    ia64_bad_param_for_setreg();				\
54		    break;							\
55	}									\
56})
57
58#define ia64_getreg(regnum)							\
59({										\
60	__u64 ia64_intri_res;							\
61										\
62	switch (regnum) {							\
63	case _IA64_REG_GP:							\
64		asm volatile ("mov %0=gp" : "=r"(ia64_intri_res));		\
65		break;								\
66	case _IA64_REG_IP:							\
67		asm volatile ("mov %0=ip" : "=r"(ia64_intri_res));		\
68		break;								\
69	case _IA64_REG_PSR:							\
70		asm volatile ("mov %0=psr" : "=r"(ia64_intri_res));		\
71		break;								\
72	case _IA64_REG_TP:	/* for current() */				\
73		ia64_intri_res = ia64_r13;					\
74		break;								\
75	case _IA64_REG_AR_KR0 ... _IA64_REG_AR_EC:				\
76		asm volatile ("mov %0=ar%1" : "=r" (ia64_intri_res)		\
77				      : "i"(regnum - _IA64_REG_AR_KR0));	\
78		break;								\
79	case _IA64_REG_CR_DCR ... _IA64_REG_CR_LRR1:				\
80		asm volatile ("mov %0=cr%1" : "=r" (ia64_intri_res)		\
81				      : "i" (regnum - _IA64_REG_CR_DCR));	\
82		break;								\
83	case _IA64_REG_SP:							\
84		asm volatile ("mov %0=sp" : "=r" (ia64_intri_res));		\
85		break;								\
86	default:								\
87		ia64_bad_param_for_getreg();					\
88		break;								\
89	}									\
90	ia64_intri_res;								\
91})
92
93#define ia64_hint_pause 0
94
95#define ia64_hint(mode)						\
96({								\
97	switch (mode) {						\
98	case ia64_hint_pause:					\
99		asm volatile ("hint @pause" ::: "memory");	\
100		break;						\
101	}							\
102})
103
104
105/* Integer values for mux1 instruction */
106#define ia64_mux1_brcst 0
107#define ia64_mux1_mix   8
108#define ia64_mux1_shuf  9
109#define ia64_mux1_alt  10
110#define ia64_mux1_rev  11
111
112#define ia64_mux1(x, mode)							\
113({										\
114	__u64 ia64_intri_res;							\
115										\
116	switch (mode) {								\
117	case ia64_mux1_brcst:							\
118		asm ("mux1 %0=%1,@brcst" : "=r" (ia64_intri_res) : "r" (x));	\
119		break;								\
120	case ia64_mux1_mix:							\
121		asm ("mux1 %0=%1,@mix" : "=r" (ia64_intri_res) : "r" (x));	\
122		break;								\
123	case ia64_mux1_shuf:							\
124		asm ("mux1 %0=%1,@shuf" : "=r" (ia64_intri_res) : "r" (x));	\
125		break;								\
126	case ia64_mux1_alt:							\
127		asm ("mux1 %0=%1,@alt" : "=r" (ia64_intri_res) : "r" (x));	\
128		break;								\
129	case ia64_mux1_rev:							\
130		asm ("mux1 %0=%1,@rev" : "=r" (ia64_intri_res) : "r" (x));	\
131		break;								\
132	}									\
133	ia64_intri_res;								\
134})
135
136#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
137# define ia64_popcnt(x)		__builtin_popcountl(x)
138#else
139# define ia64_popcnt(x)						\
140  ({								\
141	__u64 ia64_intri_res;					\
142	asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x));	\
143								\
144	ia64_intri_res;						\
145  })
146#endif
147
148#define ia64_getf_exp(x)					\
149({								\
150	long ia64_intri_res;					\
151								\
152	asm ("getf.exp %0=%1" : "=r"(ia64_intri_res) : "f"(x));	\
153								\
154	ia64_intri_res;						\
155})
156
157#define ia64_shrp(a, b, count)								\
158({											\
159	__u64 ia64_intri_res;								\
160	asm ("shrp %0=%1,%2,%3" : "=r"(ia64_intri_res) : "r"(a), "r"(b), "i"(count));	\
161	ia64_intri_res;									\
162})
163
164#define ia64_ldfs(regnum, x)					\
165({								\
166	register double __f__ asm ("f"#regnum);			\
167	asm volatile ("ldfs %0=[%1]" :"=f"(__f__): "r"(x));	\
168})
169
170#define ia64_ldfd(regnum, x)					\
171({								\
172	register double __f__ asm ("f"#regnum);			\
173	asm volatile ("ldfd %0=[%1]" :"=f"(__f__): "r"(x));	\
174})
175
176#define ia64_ldfe(regnum, x)					\
177({								\
178	register double __f__ asm ("f"#regnum);			\
179	asm volatile ("ldfe %0=[%1]" :"=f"(__f__): "r"(x));	\
180})
181
182#define ia64_ldf8(regnum, x)					\
183({								\
184	register double __f__ asm ("f"#regnum);			\
185	asm volatile ("ldf8 %0=[%1]" :"=f"(__f__): "r"(x));	\
186})
187
188#define ia64_ldf_fill(regnum, x)				\
189({								\
190	register double __f__ asm ("f"#regnum);			\
191	asm volatile ("ldf.fill %0=[%1]" :"=f"(__f__): "r"(x));	\
192})
193
194#define ia64_stfs(x, regnum)						\
195({									\
196	register double __f__ asm ("f"#regnum);				\
197	asm volatile ("stfs [%0]=%1" :: "r"(x), "f"(__f__) : "memory");	\
198})
199
200#define ia64_stfd(x, regnum)						\
201({									\
202	register double __f__ asm ("f"#regnum);				\
203	asm volatile ("stfd [%0]=%1" :: "r"(x), "f"(__f__) : "memory");	\
204})
205
206#define ia64_stfe(x, regnum)						\
207({									\
208	register double __f__ asm ("f"#regnum);				\
209	asm volatile ("stfe [%0]=%1" :: "r"(x), "f"(__f__) : "memory");	\
210})
211
212#define ia64_stf8(x, regnum)						\
213({									\
214	register double __f__ asm ("f"#regnum);				\
215	asm volatile ("stf8 [%0]=%1" :: "r"(x), "f"(__f__) : "memory");	\
216})
217
218#define ia64_stf_spill(x, regnum)						\
219({										\
220	register double __f__ asm ("f"#regnum);					\
221	asm volatile ("stf.spill [%0]=%1" :: "r"(x), "f"(__f__) : "memory");	\
222})
223
224#define ia64_fetchadd4_acq(p, inc)						\
225({										\
226										\
227	__u64 ia64_intri_res;							\
228	asm volatile ("fetchadd4.acq %0=[%1],%2"				\
229				: "=r"(ia64_intri_res) : "r"(p), "i" (inc)	\
230				: "memory");					\
231										\
232	ia64_intri_res;								\
233})
234
235#define ia64_fetchadd4_rel(p, inc)						\
236({										\
237	__u64 ia64_intri_res;							\
238	asm volatile ("fetchadd4.rel %0=[%1],%2"				\
239				: "=r"(ia64_intri_res) : "r"(p), "i" (inc)	\
240				: "memory");					\
241										\
242	ia64_intri_res;								\
243})
244
245#define ia64_fetchadd8_acq(p, inc)						\
246({										\
247										\
248	__u64 ia64_intri_res;							\
249	asm volatile ("fetchadd8.acq %0=[%1],%2"				\
250				: "=r"(ia64_intri_res) : "r"(p), "i" (inc)	\
251				: "memory");					\
252										\
253	ia64_intri_res;								\
254})
255
256#define ia64_fetchadd8_rel(p, inc)						\
257({										\
258	__u64 ia64_intri_res;							\
259	asm volatile ("fetchadd8.rel %0=[%1],%2"				\
260				: "=r"(ia64_intri_res) : "r"(p), "i" (inc)	\
261				: "memory");					\
262										\
263	ia64_intri_res;								\
264})
265
266#define ia64_xchg1(ptr,x)							\
267({										\
268	__u64 ia64_intri_res;							\
269	asm volatile ("xchg1 %0=[%1],%2"					\
270		      : "=r" (ia64_intri_res) : "r" (ptr), "r" (x) : "memory");	\
271	ia64_intri_res;								\
272})
273
274#define ia64_xchg2(ptr,x)						\
275({									\
276	__u64 ia64_intri_res;						\
277	asm volatile ("xchg2 %0=[%1],%2" : "=r" (ia64_intri_res)	\
278		      : "r" (ptr), "r" (x) : "memory");			\
279	ia64_intri_res;							\
280})
281
282#define ia64_xchg4(ptr,x)						\
283({									\
284	__u64 ia64_intri_res;						\
285	asm volatile ("xchg4 %0=[%1],%2" : "=r" (ia64_intri_res)	\
286		      : "r" (ptr), "r" (x) : "memory");			\
287	ia64_intri_res;							\
288})
289
290#define ia64_xchg8(ptr,x)						\
291({									\
292	__u64 ia64_intri_res;						\
293	asm volatile ("xchg8 %0=[%1],%2" : "=r" (ia64_intri_res)	\
294		      : "r" (ptr), "r" (x) : "memory");			\
295	ia64_intri_res;							\
296})
297
298#define ia64_cmpxchg1_acq(ptr, new, old)						\
299({											\
300	__u64 ia64_intri_res;								\
301	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
302	asm volatile ("cmpxchg1.acq %0=[%1],%2,ar.ccv":					\
303			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
304	ia64_intri_res;									\
305})
306
307#define ia64_cmpxchg1_rel(ptr, new, old)						\
308({											\
309	__u64 ia64_intri_res;								\
310	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
311	asm volatile ("cmpxchg1.rel %0=[%1],%2,ar.ccv":					\
312			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
313	ia64_intri_res;									\
314})
315
316#define ia64_cmpxchg2_acq(ptr, new, old)						\
317({											\
318	__u64 ia64_intri_res;								\
319	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
320	asm volatile ("cmpxchg2.acq %0=[%1],%2,ar.ccv":					\
321			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
322	ia64_intri_res;									\
323})
324
325#define ia64_cmpxchg2_rel(ptr, new, old)						\
326({											\
327	__u64 ia64_intri_res;								\
328	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
329											\
330	asm volatile ("cmpxchg2.rel %0=[%1],%2,ar.ccv":					\
331			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
332	ia64_intri_res;									\
333})
334
335#define ia64_cmpxchg4_acq(ptr, new, old)						\
336({											\
337	__u64 ia64_intri_res;								\
338	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
339	asm volatile ("cmpxchg4.acq %0=[%1],%2,ar.ccv":					\
340			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
341	ia64_intri_res;									\
342})
343
344#define ia64_cmpxchg4_rel(ptr, new, old)						\
345({											\
346	__u64 ia64_intri_res;								\
347	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
348	asm volatile ("cmpxchg4.rel %0=[%1],%2,ar.ccv":					\
349			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
350	ia64_intri_res;									\
351})
352
353#define ia64_cmpxchg8_acq(ptr, new, old)						\
354({											\
355	__u64 ia64_intri_res;								\
356	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
357	asm volatile ("cmpxchg8.acq %0=[%1],%2,ar.ccv":					\
358			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
359	ia64_intri_res;									\
360})
361
362#define ia64_cmpxchg8_rel(ptr, new, old)						\
363({											\
364	__u64 ia64_intri_res;								\
365	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
366											\
367	asm volatile ("cmpxchg8.rel %0=[%1],%2,ar.ccv":					\
368			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
369	ia64_intri_res;									\
370})
371
372#define ia64_mf()	asm volatile ("mf" ::: "memory")
373#define ia64_mfa()	asm volatile ("mf.a" ::: "memory")
374
375#define ia64_invala() asm volatile ("invala" ::: "memory")
376
377#define ia64_thash(addr)							\
378({										\
379	__u64 ia64_intri_res;							\
380	asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr));	\
381	ia64_intri_res;								\
382})
383
384#define ia64_srlz_i()	asm volatile (";; srlz.i ;;" ::: "memory")
385#define ia64_srlz_d()	asm volatile (";; srlz.d" ::: "memory");
386
387#ifdef HAVE_SERIALIZE_DIRECTIVE
388# define ia64_dv_serialize_data()		asm volatile (".serialize.data");
389# define ia64_dv_serialize_instruction()	asm volatile (".serialize.instruction");
390#else
391# define ia64_dv_serialize_data()
392# define ia64_dv_serialize_instruction()
393#endif
394
395#define ia64_nop(x)	asm volatile ("nop %0"::"i"(x));
396
397#define ia64_itci(addr)	asm volatile ("itc.i %0;;" :: "r"(addr) : "memory")
398
399#define ia64_itcd(addr)	asm volatile ("itc.d %0;;" :: "r"(addr) : "memory")
400
401
402#define ia64_itri(trnum, addr) asm volatile ("itr.i itr[%0]=%1"				\
403					     :: "r"(trnum), "r"(addr) : "memory")
404
405#define ia64_itrd(trnum, addr) asm volatile ("itr.d dtr[%0]=%1"				\
406					     :: "r"(trnum), "r"(addr) : "memory")
407
408#define ia64_tpa(addr)								\
409({										\
410	__u64 ia64_pa;								\
411	asm volatile ("tpa %0 = %1" : "=r"(ia64_pa) : "r"(addr) : "memory");	\
412	ia64_pa;								\
413})
414
415#define __ia64_set_dbr(index, val)						\
416	asm volatile ("mov dbr[%0]=%1" :: "r"(index), "r"(val) : "memory")
417
418#define ia64_set_ibr(index, val)						\
419	asm volatile ("mov ibr[%0]=%1" :: "r"(index), "r"(val) : "memory")
420
421#define ia64_set_pkr(index, val)						\
422	asm volatile ("mov pkr[%0]=%1" :: "r"(index), "r"(val) : "memory")
423
424#define ia64_set_pmc(index, val)						\
425	asm volatile ("mov pmc[%0]=%1" :: "r"(index), "r"(val) : "memory")
426
427#define ia64_set_pmd(index, val)						\
428	asm volatile ("mov pmd[%0]=%1" :: "r"(index), "r"(val) : "memory")
429
430#define ia64_set_rr(index, val)							\
431	asm volatile ("mov rr[%0]=%1" :: "r"(index), "r"(val) : "memory");
432
433#define ia64_get_cpuid(index)								\
434({											\
435	__u64 ia64_intri_res;								\
436	asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index));	\
437	ia64_intri_res;									\
438})
439
440#define __ia64_get_dbr(index)							\
441({										\
442	__u64 ia64_intri_res;							\
443	asm volatile ("mov %0=dbr[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
444	ia64_intri_res;								\
445})
446
447#define ia64_get_ibr(index)							\
448({										\
449	__u64 ia64_intri_res;							\
450	asm volatile ("mov %0=ibr[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
451	ia64_intri_res;								\
452})
453
454#define ia64_get_pkr(index)							\
455({										\
456	__u64 ia64_intri_res;							\
457	asm volatile ("mov %0=pkr[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
458	ia64_intri_res;								\
459})
460
461#define ia64_get_pmc(index)							\
462({										\
463	__u64 ia64_intri_res;							\
464	asm volatile ("mov %0=pmc[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
465	ia64_intri_res;								\
466})
467
468
469#define ia64_get_pmd(index)							\
470({										\
471	__u64 ia64_intri_res;							\
472	asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
473	ia64_intri_res;								\
474})
475
476#define ia64_get_rr(index)							\
477({										\
478	__u64 ia64_intri_res;							\
479	asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index));	\
480	ia64_intri_res;								\
481})
482
483#define ia64_fc(addr)	asm volatile ("fc %0" :: "r"(addr) : "memory")
484
485
486#define ia64_sync_i()	asm volatile (";; sync.i" ::: "memory")
487
488#define ia64_ssm(mask)	asm volatile ("ssm %0":: "i"((mask)) : "memory")
489#define ia64_rsm(mask)	asm volatile ("rsm %0":: "i"((mask)) : "memory")
490#define ia64_sum(mask)	asm volatile ("sum %0":: "i"((mask)) : "memory")
491#define ia64_rum(mask)	asm volatile ("rum %0":: "i"((mask)) : "memory")
492
493#define ia64_ptce(addr)	asm volatile ("ptc.e %0" :: "r"(addr))
494
495#define ia64_ptcga(addr, size)							\
496do {										\
497	asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory");	\
498	ia64_dv_serialize_data();						\
499} while (0)
500
501#define ia64_ptcl(addr, size)							\
502do {										\
503	asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory");	\
504	ia64_dv_serialize_data();						\
505} while (0)
506
507#define ia64_ptri(addr, size)						\
508	asm volatile ("ptr.i %0,%1" :: "r"(addr), "r"(size) : "memory")
509
510#define ia64_ptrd(addr, size)						\
511	asm volatile ("ptr.d %0,%1" :: "r"(addr), "r"(size) : "memory")
512
513/* Values for lfhint in ia64_lfetch and ia64_lfetch_fault */
514
515#define ia64_lfhint_none   0
516#define ia64_lfhint_nt1    1
517#define ia64_lfhint_nt2    2
518#define ia64_lfhint_nta    3
519
520#define ia64_lfetch(lfhint, y)					\
521({								\
522        switch (lfhint) {					\
523        case ia64_lfhint_none:					\
524                asm volatile ("lfetch [%0]" : : "r"(y));	\
525                break;						\
526        case ia64_lfhint_nt1:					\
527                asm volatile ("lfetch.nt1 [%0]" : : "r"(y));	\
528                break;						\
529        case ia64_lfhint_nt2:					\
530                asm volatile ("lfetch.nt2 [%0]" : : "r"(y));	\
531                break;						\
532        case ia64_lfhint_nta:					\
533                asm volatile ("lfetch.nta [%0]" : : "r"(y));	\
534                break;						\
535        }							\
536})
537
538#define ia64_lfetch_excl(lfhint, y)					\
539({									\
540        switch (lfhint) {						\
541        case ia64_lfhint_none:						\
542                asm volatile ("lfetch.excl [%0]" :: "r"(y));		\
543                break;							\
544        case ia64_lfhint_nt1:						\
545                asm volatile ("lfetch.excl.nt1 [%0]" :: "r"(y));	\
546                break;							\
547        case ia64_lfhint_nt2:						\
548                asm volatile ("lfetch.excl.nt2 [%0]" :: "r"(y));	\
549                break;							\
550        case ia64_lfhint_nta:						\
551                asm volatile ("lfetch.excl.nta [%0]" :: "r"(y));	\
552                break;							\
553        }								\
554})
555
556#define ia64_lfetch_fault(lfhint, y)					\
557({									\
558        switch (lfhint) {						\
559        case ia64_lfhint_none:						\
560                asm volatile ("lfetch.fault [%0]" : : "r"(y));		\
561                break;							\
562        case ia64_lfhint_nt1:						\
563                asm volatile ("lfetch.fault.nt1 [%0]" : : "r"(y));	\
564                break;							\
565        case ia64_lfhint_nt2:						\
566                asm volatile ("lfetch.fault.nt2 [%0]" : : "r"(y));	\
567                break;							\
568        case ia64_lfhint_nta:						\
569                asm volatile ("lfetch.fault.nta [%0]" : : "r"(y));	\
570                break;							\
571        }								\
572})
573
574#define ia64_lfetch_fault_excl(lfhint, y)				\
575({									\
576        switch (lfhint) {						\
577        case ia64_lfhint_none:						\
578                asm volatile ("lfetch.fault.excl [%0]" :: "r"(y));	\
579                break;							\
580        case ia64_lfhint_nt1:						\
581                asm volatile ("lfetch.fault.excl.nt1 [%0]" :: "r"(y));	\
582                break;							\
583        case ia64_lfhint_nt2:						\
584                asm volatile ("lfetch.fault.excl.nt2 [%0]" :: "r"(y));	\
585                break;							\
586        case ia64_lfhint_nta:						\
587                asm volatile ("lfetch.fault.excl.nta [%0]" :: "r"(y));	\
588                break;							\
589        }								\
590})
591
592#define ia64_intrin_local_irq_restore(x)			\
593do {								\
594	asm volatile (";;   cmp.ne p6,p7=%0,r0;;"		\
595		      "(p6) ssm psr.i;"				\
596		      "(p7) rsm psr.i;;"			\
597		      "(p6) srlz.d"				\
598		      :: "r"((x)) : "p6", "p7", "memory");	\
599} while (0)
600
601#endif /* _ASM_IA64_GCC_INTRIN_H */
602