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