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 ymm0
24 #define F1 ymm1
25 #define F2 ymm2
26 #define F3 ymm3
27 #define F4 ymm4
28 #define F5 ymm5
29 #define F6 ymm6
30 #define F7 ymm7
31 
32 typedef union {
33   float _float[8];
34   double _double[4];
35   long _long[4];
36   int _int[8];
37   unsigned long _ulong[4];
38   __m64 _m64[4];
39   __m128 _m128[2];
40   __m256 _m256[1];
41 } YMM_T;
42 
43 typedef union {
44   float _float;
45   double _double;
46   long double _ldouble;
47   unsigned long _ulong[2];
48 } X87_T;
49 extern void (*callthis)(void);
50 extern unsigned long rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15;
51 YMM_T ymm_regs[16];
52 X87_T x87_regs[8];
53 extern volatile unsigned long volatile_var;
54 extern void snapshot (void);
55 extern void snapshot_ret (void);
56 #define WRAP_CALL(N) \
57   (callthis = (void (*)()) (N), (typeof (&N)) snapshot)
58 #define WRAP_RET(N) \
59   (callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
60 
61 /* Clear all integer registers.  */
62 #define clear_int_hardware_registers \
63   asm __volatile__ ("xor %%rax, %%rax\n\t" \
64 		    "xor %%rbx, %%rbx\n\t" \
65 		    "xor %%rcx, %%rcx\n\t" \
66 		    "xor %%rdx, %%rdx\n\t" \
67 		    "xor %%rsi, %%rsi\n\t" \
68 		    "xor %%rdi, %%rdi\n\t" \
69 		    "xor %%r8, %%r8\n\t" \
70 		    "xor %%r9, %%r9\n\t" \
71 		    "xor %%r10, %%r10\n\t" \
72 		    "xor %%r11, %%r11\n\t" \
73 		    "xor %%r12, %%r12\n\t" \
74 		    "xor %%r13, %%r13\n\t" \
75 		    "xor %%r14, %%r14\n\t" \
76 		    "xor %%r15, %%r15\n\t" \
77 		    ::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", \
78 		    "r9", "r10", "r11", "r12", "r13", "r14", "r15");
79 
80 /* This is the list of registers available for passing arguments. Not all of
81    these are used or even really available.  */
82 struct IntegerRegisters
83 {
84   unsigned long rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
85 };
86 struct FloatRegisters
87 {
88   double mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
89   long double st0, st1, st2, st3, st4, st5, st6, st7;
90   YMM_T ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, ymm8, ymm9,
91         ymm10, ymm11, ymm12, ymm13, ymm14, ymm15;
92 };
93 
94 /* Implemented in scalarargs.c  */
95 extern struct IntegerRegisters iregs;
96 extern struct FloatRegisters fregs;
97 extern unsigned int num_iregs, num_fregs;
98 
99 #define check_int_arguments do { \
100   assert (num_iregs <= 0 || iregs.I0 == I0); \
101   assert (num_iregs <= 1 || iregs.I1 == I1); \
102   assert (num_iregs <= 2 || iregs.I2 == I2); \
103   assert (num_iregs <= 3 || iregs.I3 == I3); \
104   assert (num_iregs <= 4 || iregs.I4 == I4); \
105   assert (num_iregs <= 5 || iregs.I5 == I5); \
106   } while (0)
107 
108 #define check_char_arguments check_int_arguments
109 #define check_short_arguments check_int_arguments
110 #define check_long_arguments check_int_arguments
111 
112 /* Clear register struct.  */
113 #define clear_struct_registers \
114   rax = rbx = rcx = rdx = rdi = rsi = rbp = rsp \
115     = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0; \
116   memset (&iregs, 0, sizeof (iregs)); \
117   memset (&fregs, 0, sizeof (fregs)); \
118   memset (ymm_regs, 0, sizeof (ymm_regs)); \
119   memset (x87_regs, 0, sizeof (x87_regs));
120 
121 /* Clear both hardware and register structs for integers.  */
122 #define clear_int_registers \
123   clear_struct_registers \
124   clear_int_hardware_registers
125 
126 /* TODO: Do the checking.  */
127 #define check_f_arguments(T) do { \
128   assert (num_fregs <= 0 || fregs.ymm0._ ## T [0] == ymm_regs[0]._ ## T [0]); \
129   assert (num_fregs <= 1 || fregs.ymm1._ ## T [0] == ymm_regs[1]._ ## T [0]); \
130   assert (num_fregs <= 2 || fregs.ymm2._ ## T [0] == ymm_regs[2]._ ## T [0]); \
131   assert (num_fregs <= 3 || fregs.ymm3._ ## T [0] == ymm_regs[3]._ ## T [0]); \
132   assert (num_fregs <= 4 || fregs.ymm4._ ## T [0] == ymm_regs[4]._ ## T [0]); \
133   assert (num_fregs <= 5 || fregs.ymm5._ ## T [0] == ymm_regs[5]._ ## T [0]); \
134   assert (num_fregs <= 6 || fregs.ymm6._ ## T [0] == ymm_regs[6]._ ## T [0]); \
135   assert (num_fregs <= 7 || fregs.ymm7._ ## T [0] == ymm_regs[7]._ ## T [0]); \
136   } while (0)
137 
138 #define check_float_arguments check_f_arguments(float)
139 #define check_double_arguments check_f_arguments(double)
140 
141 #define check_vector_arguments(T,O) do { \
142   assert (num_fregs <= 0 \
143 	  || memcmp (((char *) &fregs.ymm0) + (O), \
144 		     &ymm_regs[0], \
145 		     sizeof (__ ## T) - (O)) == 0); \
146   assert (num_fregs <= 1 \
147 	  || memcmp (((char *) &fregs.ymm1) + (O), \
148 		     &ymm_regs[1], \
149 		     sizeof (__ ## T) - (O)) == 0); \
150   assert (num_fregs <= 2 \
151 	  || memcmp (((char *) &fregs.ymm2) + (O), \
152 		     &ymm_regs[2], \
153 		     sizeof (__ ## T) - (O)) == 0); \
154   assert (num_fregs <= 3 \
155 	  || memcmp (((char *) &fregs.ymm3) + (O), \
156 		     &ymm_regs[3], \
157 		     sizeof (__ ## T) - (O)) == 0); \
158   assert (num_fregs <= 4 \
159 	  || memcmp (((char *) &fregs.ymm4) + (O), \
160 		     &ymm_regs[4], \
161 		     sizeof (__ ## T) - (O)) == 0); \
162   assert (num_fregs <= 5 \
163 	  || memcmp (((char *) &fregs.ymm5) + (O), \
164 		     &ymm_regs[5], \
165 		     sizeof (__ ## T) - (O)) == 0); \
166   assert (num_fregs <= 6 \
167 	  || memcmp (((char *) &fregs.ymm6) + (O), \
168 		     &ymm_regs[6], \
169 		     sizeof (__ ## T) - (O)) == 0); \
170   assert (num_fregs <= 7 \
171 	  || memcmp (((char *) &fregs.ymm7) + (O), \
172 		     &ymm_regs[7], \
173 		     sizeof (__ ## T) - (O)) == 0); \
174   } while (0)
175 
176 #define check_m64_arguments check_vector_arguments(m64, 0)
177 #define check_m128_arguments check_vector_arguments(m128, 0)
178 #define check_m256_arguments check_vector_arguments(m256, 0)
179 
180 #endif /* INCLUDED_ARGS_H  */
181