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