1 #ifndef INCLUDED_ARGS_H
2 #define INCLUDED_ARGS_H
3 
4 #include <immintrin.h>
5 #include <string.h>
6 
7 /* Assertion macro.  */
8 #define assert(test) if (!(test)) abort()
9 
10 #ifdef __GNUC__
11 #define ATTRIBUTE_UNUSED __attribute__((__unused__))
12 #else
13 #define ATTRIBUTE_UNUSED
14 #endif
15 
16 /* This defines the calling sequences for integers and floats.  */
17 #define I0 rdi
18 #define I1 rsi
19 #define I2 rdx
20 #define I3 rcx
21 #define I4 r8
22 #define I5 r9
23 #define F0 zmm0
24 #define F1 zmm1
25 #define F2 zmm2
26 #define F3 zmm3
27 #define F4 zmm4
28 #define F5 zmm5
29 #define F6 zmm6
30 #define F7 zmm7
31 
32 typedef union {
33   float _float[16];
34   double _double[8];
35   long _long[8];
36   int _int[16];
37   unsigned long _ulong[8];
38   __m64 _m64[8];
39   __m128 _m128[4];
40   __m256 _m256[2];
41   __m512 _m512[1];
42 } ZMM_T;
43 
44 typedef union {
45   float _float;
46   double _double;
47   long double _ldouble;
48   unsigned long _ulong[2];
49 } X87_T;
50 extern void (*callthis)(void);
51 extern unsigned long rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15;
52 ZMM_T zmm_regs[32];
53 X87_T x87_regs[8];
54 extern volatile unsigned long volatile_var;
55 extern void snapshot (void);
56 extern void snapshot_ret (void);
57 #define WRAP_CALL(N) \
58   (callthis = (void (*)()) (N), (typeof (&N)) snapshot)
59 #define WRAP_RET(N) \
60   (callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
61 
62 /* Clear all integer registers.  */
63 #define clear_int_hardware_registers \
64   asm __volatile__ ("xor %%rax, %%rax\n\t" \
65 		    "xor %%rbx, %%rbx\n\t" \
66 		    "xor %%rcx, %%rcx\n\t" \
67 		    "xor %%rdx, %%rdx\n\t" \
68 		    "xor %%rsi, %%rsi\n\t" \
69 		    "xor %%rdi, %%rdi\n\t" \
70 		    "xor %%r8, %%r8\n\t" \
71 		    "xor %%r9, %%r9\n\t" \
72 		    "xor %%r10, %%r10\n\t" \
73 		    "xor %%r11, %%r11\n\t" \
74 		    "xor %%r12, %%r12\n\t" \
75 		    "xor %%r13, %%r13\n\t" \
76 		    "xor %%r14, %%r14\n\t" \
77 		    "xor %%r15, %%r15\n\t" \
78 		    ::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", \
79 		    "r9", "r10", "r11", "r12", "r13", "r14", "r15");
80 
81 /* This is the list of registers available for passing arguments. Not all of
82    these are used or even really available.  */
83 struct IntegerRegisters
84 {
85   unsigned long rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
86 };
87 struct FloatRegisters
88 {
89   double mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
90   long double st0, st1, st2, st3, st4, st5, st6, st7;
91   ZMM_T zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7, zmm8, zmm9,
92         zmm10, zmm11, zmm12, zmm13, zmm14, zmm15, zmm16, zmm17, zmm18,
93 	zmm19, zmm20, zmm21, zmm22, zmm23, zmm24, zmm25, zmm26, zmm27,
94 	zmm28, zmm29, zmm30, zmm31;
95 };
96 
97 /* Implemented in scalarargs.c  */
98 extern struct IntegerRegisters iregs;
99 extern struct FloatRegisters fregs;
100 extern unsigned int num_iregs, num_fregs;
101 
102 #define check_int_arguments do { \
103   assert (num_iregs <= 0 || iregs.I0 == I0); \
104   assert (num_iregs <= 1 || iregs.I1 == I1); \
105   assert (num_iregs <= 2 || iregs.I2 == I2); \
106   assert (num_iregs <= 3 || iregs.I3 == I3); \
107   assert (num_iregs <= 4 || iregs.I4 == I4); \
108   assert (num_iregs <= 5 || iregs.I5 == I5); \
109   } while (0)
110 
111 #define check_char_arguments check_int_arguments
112 #define check_short_arguments check_int_arguments
113 #define check_long_arguments check_int_arguments
114 
115 /* Clear register struct.  */
116 #define clear_struct_registers \
117   rax = rbx = rcx = rdx = rdi = rsi = rbp = rsp \
118     = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0; \
119   memset (&iregs, 0, sizeof (iregs)); \
120   memset (&fregs, 0, sizeof (fregs)); \
121   memset (zmm_regs, 0, sizeof (zmm_regs)); \
122   memset (x87_regs, 0, sizeof (x87_regs));
123 
124 /* Clear both hardware and register structs for integers.  */
125 #define clear_int_registers \
126   clear_struct_registers \
127   clear_int_hardware_registers
128 
129 /* TODO: Do the checking.  */
130 #define check_f_arguments(T) do { \
131   assert (num_fregs <= 0 || fregs.zmm0._ ## T [0] == zmm_regs[0]._ ## T [0]); \
132   assert (num_fregs <= 1 || fregs.zmm1._ ## T [0] == zmm_regs[1]._ ## T [0]); \
133   assert (num_fregs <= 2 || fregs.zmm2._ ## T [0] == zmm_regs[2]._ ## T [0]); \
134   assert (num_fregs <= 3 || fregs.zmm3._ ## T [0] == zmm_regs[3]._ ## T [0]); \
135   assert (num_fregs <= 4 || fregs.zmm4._ ## T [0] == zmm_regs[4]._ ## T [0]); \
136   assert (num_fregs <= 5 || fregs.zmm5._ ## T [0] == zmm_regs[5]._ ## T [0]); \
137   assert (num_fregs <= 6 || fregs.zmm6._ ## T [0] == zmm_regs[6]._ ## T [0]); \
138   assert (num_fregs <= 7 || fregs.zmm7._ ## T [0] == zmm_regs[7]._ ## T [0]); \
139   } while (0)
140 
141 #define check_float_arguments check_f_arguments(float)
142 #define check_double_arguments check_f_arguments(double)
143 
144 #define check_vector_arguments(T,O) do { \
145   assert (num_fregs <= 0 \
146 	  || memcmp (((char *) &fregs.zmm0) + (O), \
147 		     &zmm_regs[0], \
148 		     sizeof (__ ## T) - (O)) == 0); \
149   assert (num_fregs <= 1 \
150 	  || memcmp (((char *) &fregs.zmm1) + (O), \
151 		     &zmm_regs[1], \
152 		     sizeof (__ ## T) - (O)) == 0); \
153   assert (num_fregs <= 2 \
154 	  || memcmp (((char *) &fregs.zmm2) + (O), \
155 		     &zmm_regs[2], \
156 		     sizeof (__ ## T) - (O)) == 0); \
157   assert (num_fregs <= 3 \
158 	  || memcmp (((char *) &fregs.zmm3) + (O), \
159 		     &zmm_regs[3], \
160 		     sizeof (__ ## T) - (O)) == 0); \
161   assert (num_fregs <= 4 \
162 	  || memcmp (((char *) &fregs.zmm4) + (O), \
163 		     &zmm_regs[4], \
164 		     sizeof (__ ## T) - (O)) == 0); \
165   assert (num_fregs <= 5 \
166 	  || memcmp (((char *) &fregs.zmm5) + (O), \
167 		     &zmm_regs[5], \
168 		     sizeof (__ ## T) - (O)) == 0); \
169   assert (num_fregs <= 6 \
170 	  || memcmp (((char *) &fregs.zmm6) + (O), \
171 		     &zmm_regs[6], \
172 		     sizeof (__ ## T) - (O)) == 0); \
173   assert (num_fregs <= 7 \
174 	  || memcmp (((char *) &fregs.zmm7) + (O), \
175 		     &zmm_regs[7], \
176 		     sizeof (__ ## T) - (O)) == 0); \
177   } while (0)
178 
179 #define check_m64_arguments check_vector_arguments(m64, 0)
180 #define check_m128_arguments check_vector_arguments(m128, 0)
181 #define check_m256_arguments check_vector_arguments(m256, 0)
182 #define check_m512_arguments check_vector_arguments(m512, 0)
183 
184 #endif /* INCLUDED_ARGS_H  */
185