/***************************************
					$Header$

					
***************************************/


#ifndef CAMM_UTIL_H
#define CAMM_UTIL_H    /*+ To stop multiple inclusions. +*/

typedef struct {
  float r,i;
} Complex;

typedef struct {
  double r,i;
} Dcomplex;

#define str(a_) xstr(a_)
#define xstr(a_) #a_

#define val(a_) xval(a_)
#define xval(a_) a_

#define Mjoin(a,b) mjoin(a,b)
#define mjoin(a,b) a ## b

#define VOLATILE __volatile__
#define ASM __asm__ VOLATILE

#ifdef BETA0
#define BL b0
#endif
#ifdef BETA1
#define BL b1
#endif
#ifdef BETAX
#define BL bX
#endif
#ifdef BETAXI0
#define BL bXi0
#endif

#ifdef NO_TRANSPOSE
#ifdef GER
#ifdef Conj_
#define FEXT Gc
#else
#define FEXT Gu
#endif
#else
#ifdef Conj_
#define FEXT Nc
#else
#define FEXT N
#endif
#endif
#else
#ifdef Conj_
#define FEXT C
#else
#define FEXT T
#endif
#endif

#define BLC Mjoin(FEXT,BL)

#ifdef __GNUC__
#define NO_INLINE  double sq(double x) {return x*x;}
#else
#define NO_INLINE
#endif

#define lab(a_)     "\n" __FUNCTION__  "_" str(a_) ":\n\t"
#define jmp(a_)     "jmp " __FUNCTION__ "_" str(a_) "\n\t"
#define je(a_)      "je " __FUNCTION__ "_" str(a_) "\n\t"
#define jge(a_)     "jge " __FUNCTION__ "_" str(a_) "\n\t"
#define jle(a_)     "jle " __FUNCTION__ "_" str(a_) "\n\t"
#define jne(a_)     "jne " __FUNCTION__ "_" str(a_) "\n\t"
#define align       ".align 16\n\t"
#define test(a_,b_)    "testl $" str(a_) ",%%e" str(b_) "\n\t"
#define and(a_,b_)    "andl $" str(a_) ",%%e" str(b_) "\n\t"
#define sub(a_,b_)     "subl $" str(a_) ",%%e" str(b_) "\n\t"

#ifdef SCPLX
#define TYPE Complex
#define SCALAR Complex *
#define PREC c
#endif
#ifdef SREAL
#define TYPE float
#define SCALAR float
#define PREC s
#endif
#ifdef DREAL
#define TYPE double
#define SCALAR double
#define PREC d
#endif
#ifdef DCPLX
#define TYPE Dcomplex
#define SCALAR Dcomplex *
#define PREC z
#endif

#define M11 0
#define M12 1
#define M13 2
#define M14 3
#define M15 4
#define M16 5
#define M17 6
#define M18 7

#define M23 1
#define M24 2
#define M25 3
#define M26 4
#define M27 5
#define M28 6

#define M33 0
#define M34 1
#define M35 2
#define M36 3
#define M37 4
#define M38 5

#define P10 1
#define P11 2
#define P12 3
#define P13 4
#define P14 5
#define P15 6
#define P16 7

#define XM(a_,b_)     M ## b_ ## a_
#define M(a_,b_)      XM(a_,b_)

#define XP(a_,b_)     P ## b_ ## a_
#define P(a_,b_)      XP(a_,b_)

#define mex(a_)       str(%%e ## a_)
#define msx(a_)       str(%%st( ## a_ ## ))


#define cmp(a_,b_)    "cmp " mex(a_) "," mex(b_) "\n\t"
#define f(a_,b_,c_)   "prefetch" str(a_) " " str(b_) "(%%e" #c_ ")\n\t"
#define a(a_,b_)      "addl $" str(a_) "," mex(b_) "\n\t"
#define m(a_,b_)      "imul $" str(a_) "," mex(b_) "\n\t"
#define shl(a_,b_)    "shl $" str(a_) "," mex(b_) "\n\t"
#define shr(a_,b_)    "shr $" str(a_) "," mex(b_) "\n\t"
#define mm(a_,b_)     "mov $" str(a_) "," mex(b_) "\n\t"
#define ra(a_,b_)     "addl %%e" str(a_) "," mex(b_) "\n\t"
#define rs(a_,b_)     "subl %%e" str(a_) "," mex(b_) "\n\t"

#define fl(a_,b_)     "fldl " str(a_) "(" mex(b_) ")\n\t"
#define fp(a_,b_)     "fstpl " str(a_) "(" mex(b_) ")\n\t"
#define fd(a_)        "fld " msx(a_) "\n\t"
#define fap(a_,b_)    "faddp " msx(a_) "," msx(b_) "\n\t"
/* #define fsp(a_)       fx(a_) "fsubp %%st," msx(a_) "\n\t" */
#define fsp(a_)       "fsubrp %%st," msx(a_) "\n\t"
#define fmp(a_,b_)    "fmulp " msx(a_) "," msx(b_) "\n\t"
#define fa(a_,b_)     "fadd " msx(a_) "," msx(b_) "\n\t"
#define fm(a_,b_)     "fmul " msx(a_) "," msx(b_) "\n\t"
#define faa(a_,b_)    "faddl " str(a_) "(" mex(b_) ")\n\t"
#define fma(a_,b_)    "fmull " str(a_) "(" mex(b_) ")\n\t"
#define fz            "fldz\n\t"
#define fx(a_)        "fxch " msx(a_) "\n\t"
#define fx1           "fxch\n\t"
#define fc(a_)        "fstp " msx(a_) "\n\t"


#ifndef ATHLON

#define RS4 16
#define RS  4

#define mxx(a_)        str(%%xmm ## a_)
#define px(a_)         "xorps " mxx(a_) "," mxx(a_) "\n\t"
#define pm(a_,b_)      "mulps " mxx(a_) "," mxx(b_) "\n\t"
#define pa(a_,b_)      "addps " mxx(a_) "," mxx(b_) "\n\t"
#define pmm(a_,b_,c_)  "mulps " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pam(a_,b_,c_)  "addps " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pl(a_,b_,c_)   "movups " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pla(a_,b_,c_)  "movaps " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pu(a_,b_,c_)   "movups " mxx(a_) "," str(b_) "(" mex(c_) ")\n\t"
#define punt(a_,b_,c_) "movntps " mxx(a_) "," str(b_) "(" mex(c_) ")\n\t"
#define pua(a_,b_,c_)  "movaps " mxx(a_) "," str(b_) "(" mex(c_) ")\n\t"
#define pud(a_,b_,c_)  "movlps " mxx(a_) "," str(b_) "(" mex(c_) ")\n\t"
#define pudr(a_,b_)    "movlps " mxx(a_) "," mxx(b_) "\n\t"
#define pc(a_,b_)      "movaps " mxx(a_) "," mxx(b_) "\n\t"
#define ps(a_,b_,c_)   "shufps $" str(a_) "," mxx(b_) "," mxx(c_) "\n\t"
#define phl(a_,b_)     "movhlps " mxx(a_) "," mxx(b_) "\n\t"
#define pus(a_,b_,c_)  "movss " mxx(a_) "," str(b_) "(" mex(c_) ")\n\t"
#define pls(a_,b_,c_)  "movss " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pld(a_,b_,c_)  "movlps " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define plh(a_,b_)     "movlhps " mxx(a_) "," mxx(b_) "\n\t"
#define pas(a_,b_,c_)  "addss " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pms(a_,b_,c_)  "mulss " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pcs(a_,b_)     "movss " mxx(a_) "," mxx(b_) "\n\t"
#define pasr(a_,b_)    "addss " mxx(a_) "," mxx(b_) "\n\t"
#define pmsr(a_,b_)    "mulss " mxx(a_) "," mxx(b_) "\n\t"
#define pul(a_,b_)     "unpcklps " mxx(a_) "," mxx(b_) "\n\t"
#define puh(a_,b_)     "unpckhps " mxx(a_) "," mxx(b_) "\n\t"

#define plsx(a_,b_,c_,d_,e_) \
                       "movss " str(a_) "(" mex(b_) "," mex(c_) "," #d_ ")," mxx(e_) "\n\t"
#define pasx(a_,b_,c_,d_,e_) \
                       "addss " str(a_) "(" mex(b_) "," mex(c_) "," #d_ ")," mxx(e_) "\n\t"
#define pusx(a_,b_,c_,d_,e_) \
                       "movss " mxx(a_) "," str(b_) "(" mex(c_) "," mex(d_) "," #e_ ")\n\t"
#define pudx(a_,b_,c_,d_,e_) \
                       "movlps " mxx(a_) "," str(b_) "(" mex(c_) "," mex(d_) "," #e_ ")\n\t"

#else

#define RS4 8
#define RS  2

#define mxx(a_)       str(%%mm ## a_)
#define pul(a_,b_)    "punpckldq " mxx(a_) "," mxx(b_) "\n\t"
#define puh(a_,b_)    "punpckhdq " mxx(a_) "," mxx(b_) "\n\t"

#define px(a_)        "pxor " mxx(a_) "," mxx(a_) "\n\t"
#define pm(a_,b_)     "pfmul " mxx(a_) "," mxx(b_) "\n\t"
#define pa(a_,b_)     "pfadd " mxx(a_) "," mxx(b_) "\n\t"
#define pac(a_,b_)    "pfacc " mxx(a_) "," mxx(b_) "\n\t"
#define pmm(a_,b_,c_) "pfmul " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pam(a_,b_,c_) "pfadd " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pl(a_,b_,c_)  "movq " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pla(a_,b_,c_) "movq " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"
#define pu(a_,b_,c_)  "movq " mxx(a_) "," str(b_) "(" mex(c_) ")\n\t"
#define pc(a_,b_)     "movq " mxx(a_) "," mxx(b_) "\n\t"
#define ps(a_,b_,c_)  "pswapd " mxx(b_) "," mxx(c_) "\n\t"
#define phl(a_,b_)    "punpckhdq " mxx(a_) "," mxx(b_) "\n\t"
#define plh(a_,b_)    "punpckldq " mxx(a_) "," mxx(b_) "\n\t"
#define pus(a_,b_,c_) "movd " mxx(a_) "," str(b_) "(" mex(c_) ")\n\t"
#define pls(a_,b_,c_) "movd " str(a_) "(" mex(b_) ")," mxx(c_) "\n\t"

#define plsx(a_,b_,c_,d_,e_) \
                      "movd " str(a_) "(" mex(b_) "," mex(c_) "," #d_ ")," mxx(e_) "\n\t"
#define plx(a_,b_,c_,d_,e_)  \
                      "movq " str(a_) "(" mex(b_) "," mex(c_) "," #d_ ")," mxx(e_) "\n\t"
#define pasx(a_,b_,c_,d_,e_) \
                      "addss " str(a_) "(" mex(b_) "," mex(c_) "," #d_ ")," mxx(e_) "\n\t"
#define pusx(a_,b_,c_,d_,e_) \
                      "movd " mxx(a_) "," str(b_) "(" mex(c_) "," mex(d_) "," #e_ ")\n\t"
#define pux(a_,b_,c_,d_,e_)  \
                      "movq " mxx(a_) "," str(b_) "(" mex(c_) "," mex(d_) "," #e_ ")\n\t"
#endif

#endif /* CAMM_UTIL_H */
