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