1 |
328 |
jeremybenn |
#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 */
|