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