#ifndef _POSTINC_H_
#define _POSTINC_H_

/* Post incrementing stores  */

#define __post_inc_store(o, t, p, v, c)			\
  ({ __asm__ ( #o " %0, %2, %3"				\
	       : "+r" (p), "=m" (*(t *)p)		\
	       : "r" ((long long)v), "i" (c) ); })

#define __insn_st1_add(p, v, i)  		\
  __post_inc_store(st1_add, char, p, v, i)

#define __insn_st2_add(p, v, i)  		\
  __post_inc_store(st2_add, short, p, v, i)

#define __insn_st4_add(p, v, i)  		\
  __post_inc_store(st4_add, int, p, v, i)

#define __insn_st_add(p, v, i)  		\
  __post_inc_store(st_add, long long, p, v, i)

#define __insn_stnt1_add(p, v, i)  		\
  __post_inc_store(stnt1_add, char, p, v, i)

#define __insn_stnt2_add(p, v, i)  		\
  __post_inc_store(stnt2_add, short, p, v, i)

#define __insn_stnt4_add(p, v, i)  		\
  __post_inc_store(stnt4_add, int, p, v, i)

#define __insn_stnt_add(p, v, i)  		\
  __post_inc_store(stnt_add, long long, p, v, i)

/* Post incrementing loads  */

#define __post_inc_load(o, t, p, c)		\
  ({ long long res;				\
    __asm__ ( #o " %0, %1, %3"			\
	      : "=r" (res), "+r" (p)		\
	      : "m" (*(t *)p), "i" (c) );	\
    res; })					\

#define __insn_ld1s_add(p, i)  			\
  __post_inc_load(ld1s_add, char, p, i)

#define __insn_ld1u_add(p, i)  			\
  __post_inc_load(ld1u_add, char, p, i)

#define __insn_ld2s_add(p, i)  			\
  __post_inc_load(ld2s_add, short, p, i)

#define __insn_ld2u_add(p, i)  			\
  __post_inc_load(ld2u_add, short, p, i)

#define __insn_ld4s_add(p, i)  			\
  __post_inc_load(ld4s_add, int, p, i)

#define __insn_ld4u_add(p, i)  			\
  __post_inc_load(ld4u_add, int, p, i)

#define __insn_ld_add(p, i)  			\
  __post_inc_load(ld_add, long long, p, i)

#define __insn_ldnt1s_add(p, i)  		\
  __post_inc_load(ldnt1s_add, char, p, i)

#define __insn_ldnt1u_add(p, i)  		\
  __post_inc_load(ldnt1u_add, char, p, i)

#define __insn_ldnt2s_add(p, i)  		\
  __post_inc_load(ldnt2s_add, short, p, i)

#define __insn_ldnt2u_add(p, i)  		\
  __post_inc_load(ldnt2u_add, short, p, i)

#define __insn_ldnt4s_add(p, i)  		\
  __post_inc_load(ldnt4s_add, int, p, i)

#define __insn_ldnt4u_add(p, i)  		\
  __post_inc_load(ldnt4u_add, int, p, i)

#define __insn_ldnt_add(p, i)			\
  __post_inc_load(ldnt_add, long long, p, i)

#define __insn_ldna_add(p, i)			\
  __post_inc_load(ldna_add, long long, p, i)

#define __insn_ld1s_add_L2(p, i)  		\
  __post_inc_load(ld1s_add_L2, char, p, i)

#define __insn_ld1u_add_L2(p, i)  		\
  __post_inc_load(ld1u_add_L2, char, p, i)

#define __insn_ld2s_add_L2(p, i)  		\
  __post_inc_load(ld2s_add_L2, short, p, i)

#define __insn_ld2u_add_L2(p, i)  		\
  __post_inc_load(ld2u_add_L2, short, p, i)

#define __insn_ld4s_add_L2(p, i)  		\
  __post_inc_load(ld4s_add_L2, int, p, i)

#define __insn_ld4u_add_L2(p, i)  		\
  __post_inc_load(ld4u_add_L2, int, p, i)

#define __insn_ld_add_L2(p, i)			\
  __post_inc_load(ld_add_L2, long long, p, i)

#define __insn_ldnt1s_add_L2(p, i)  		\
  __post_inc_load(ldnt1s_add_L2, char, p, i)

#define __insn_ldnt1u_add_L2(p, i)  		\
  __post_inc_load(ldnt1u_add_L2, char, p, i)

#define __insn_ldnt2s_add_L2(p, i)  		\
  __post_inc_load(ldnt2s_add_L2, short, p, i)

#define __insn_ldnt2u_add_L2(p, i)  		\
  __post_inc_load(ldnt2u_add_L2, short, p, i)

#define __insn_ldnt4s_add_L2(p, i)  		\
  __post_inc_load(ldnt4s_add_L2, int, p, i)

#define __insn_ldnt4u_add_L2(p, i)  		\
  __post_inc_load(ldnt4u_add_L2, int, p, i)

#define __insn_ldnt_add_L2(p, i)		\
  __post_inc_load(ldnt_add_L2, long long, p, i)

#define __insn_ldna_add_L2(p, i)		\
  __post_inc_load(ldna_add_L2, long long, p, i)

#define __insn_ld1s_add_miss(p, i)		\
  __post_inc_load(ld1s_add_miss, char, p, i)

#define __insn_ld1u_add_miss(p, i)		\
  __post_inc_load(ld1u_add_miss, char, p, i)

#define __insn_ld2s_add_miss(p, i)		\
  __post_inc_load(ld2s_add_miss, short, p, i)

#define __insn_ld2u_add_miss(p, i)		\
  __post_inc_load(ld2u_add_miss, short, p, i)

#define __insn_ld4s_add_miss(p, i)		\
  __post_inc_load(ld4s_add_miss, int, p, i)

#define __insn_ld4u_add_miss(p, i)		\
  __post_inc_load(ld4u_add_miss, int, p, i)

#define __insn_ld_add_miss(p, i)		\
  __post_inc_load(ld_add_miss, long long, p, i)

#define __insn_ldnt1s_add_miss(p, i)		\
  __post_inc_load(ldnt1s_add_miss, char, p, i)

#define __insn_ldnt1u_add_miss(p, i)		\
  __post_inc_load(ldnt1u_add_miss, char, p, i)

#define __insn_ldnt2s_add_miss(p, i)		\
  __post_inc_load(ldnt2s_add_miss, short, p, i)

#define __insn_ldnt2u_add_miss(p, i)		\
  __post_inc_load(ldnt2u_add_miss, short, p, i)

#define __insn_ldnt4s_add_miss(p, i)		\
  __post_inc_load(ldnt4s_add_miss, int, p, i)

#define __insn_ldnt4u_add_miss(p, i)		\
  __post_inc_load(ldnt4u_add_miss, int, p, i)

#define __insn_ldnt_add_miss(p, i)  		\
  __post_inc_load(ldnt_add_miss, long long, p, i)

#define __insn_ldna_add_miss(p, i)  		\
  __post_inc_load(ldna_add_miss, long long, p, i)

/* Post incrementing prefetches  */

#define __post_inc_prefetch(o, p, c)		\
  ({ __asm__ __volatile__ ( #o " %0, %1"	\
			    : "+r" (p)		\
			    : "i" (c) ); })

#define __insn_prefetch_add_l1(p, i)  		\
  __post_inc_prefetch(prefetch_add_l1, p, i)

#define __insn_prefetch_add_l1_fault(p, i)	\
  __post_inc_prefetch(prefetch_add_l1_fault, p, i)

#define __insn_prefetch_add_l2(p, i)  		\
  __post_inc_prefetch(prefetch_add_l2, p, i)

#define __insn_prefetch_add_l2_fault(p, i)	\
  __post_inc_prefetch(prefetch_add_l2_fault, p, i)

#define __insn_prefetch_add_l3(p, i)  		\
  __post_inc_prefetch(prefetch_add_l3, p, i)

#define __insn_prefetch_add_l3_fault(p, i)	\
  __post_inc_prefetch(prefetch_add_l3_fault, p, i)

#endif /* _POSTINC_H_ */
