1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 17 дек. 2018 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef DSP_ARCH_X86_AVX2_PMATH_EXP_H_ 23 #define DSP_ARCH_X86_AVX2_PMATH_EXP_H_ 24 25 #ifndef DSP_ARCH_X86_AVX2_IMPL 26 #error "This header should not be included directly" 27 #endif /* DSP_ARCH_X86_AVX2_IMPL */ 28 29 #ifdef ARCH_X86_64 30 31 namespace avx2 32 { 33 #define X8VEC(x) x, x, x, x, x, x, x, x 34 35 IF_ARCH_X86( 36 static const uint32_t EXP2_CONST[] __lsp_aligned32 = 37 { 38 X8VEC(0x7fffffff), // sign 39 X8VEC(0x7f), // 0x7f 40 X8VEC(0x3f317218), // ln(2) 41 X8VEC(0x40e00000), // C5 = 7!/6! = 7.0000000000000000 42 X8VEC(0x42280000), // C4 = 7!/5! = 42.0000000000000000 43 X8VEC(0x43520000), // C3 = 7!/4! = 210.0000000000000000 44 X8VEC(0x44520000), // C2 = 7!/3! = 840.0000000000000000 45 X8VEC(0x451d8000), // C1 = 7!/2! = 2520.0000000000000000 46 X8VEC(0x459d8000), // C0 = 7!/1! = 5040.0000000000000000 47 X8VEC(0x39500d01), // 1/7! = 0.0001984127011383 48 X8VEC(0x3f800000), // 1.0 49 }; 50 51 static const float EXP_LOG2E[] __lsp_aligned32 = 52 { 53 X8VEC(M_LOG2E) 54 }; 55 ) 56 57 #undef X8VEC 58 59 #define POW2_CORE_X32 \ 60 /* ymm0 = x */ \ 61 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm0, %%ymm2") /* ymm2 = XP = fabs(x) */ \ 62 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm4, %%ymm6") \ 63 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm8, %%ymm10") \ 64 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm12, %%ymm14") \ 65 __ASM_EMIT("vcvttps2dq %%ymm2, %%ymm1") /* ymm1 = R = int(XP) */ \ 66 __ASM_EMIT("vcvttps2dq %%ymm6, %%ymm5") \ 67 __ASM_EMIT("vcvttps2dq %%ymm10, %%ymm9") \ 68 __ASM_EMIT("vcvttps2dq %%ymm14, %%ymm13") \ 69 __ASM_EMIT("vcvtdq2ps %%ymm1, %%ymm3") /* ymm3 = float(R) */ \ 70 __ASM_EMIT("vcvtdq2ps %%ymm5, %%ymm7") \ 71 __ASM_EMIT("vcvtdq2ps %%ymm9, %%ymm11") \ 72 __ASM_EMIT("vcvtdq2ps %%ymm13, %%ymm15") \ 73 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm1, %%ymm1") /* ymm1 = R + 127 */ \ 74 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm5, %%ymm5") \ 75 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm9, %%ymm9") \ 76 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm13, %%ymm13") \ 77 __ASM_EMIT("vsubps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = XP - float(R) */ \ 78 __ASM_EMIT("vsubps %%ymm7, %%ymm6, %%ymm6") \ 79 __ASM_EMIT("vsubps %%ymm11, %%ymm10, %%ymm10") \ 80 __ASM_EMIT("vsubps %%ymm15, %%ymm14, %%ymm14") \ 81 __ASM_EMIT("vpslld $23, %%ymm1, %%ymm1") /* ymm1 = 1 << (R+127) */ \ 82 __ASM_EMIT("vpslld $23, %%ymm5, %%ymm5") \ 83 __ASM_EMIT("vpslld $23, %%ymm9, %%ymm9") \ 84 __ASM_EMIT("vpslld $23, %%ymm13, %%ymm13") \ 85 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm2, %%ymm2") /* ymm2 = X = ln(2) * (XP - float(R)) */ \ 86 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm6, %%ymm6") \ 87 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm10, %%ymm10") \ 88 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm14, %%ymm14") \ 89 /* ymm0 = [x<0], ymm1 = 1 << R, ymm2 = X */ \ 90 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C5+X */ \ 91 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm6, %%ymm7") \ 92 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm10, %%ymm11") \ 93 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm14, %%ymm15") \ 94 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C5+X) */ \ 95 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 96 __ASM_EMIT("vmulps %%ymm10, %%ymm11, %%ymm11") \ 97 __ASM_EMIT("vmulps %%ymm14, %%ymm15, %%ymm15") \ 98 __ASM_EMIT("vaddps 0x080 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C4+X*(C5+X) */ \ 99 __ASM_EMIT("vaddps 0x080 + %[E2C], %%ymm7, %%ymm7") \ 100 __ASM_EMIT("vaddps 0x080 + %[E2C], %%ymm11, %%ymm11") \ 101 __ASM_EMIT("vaddps 0x080 + %[E2C], %%ymm15, %%ymm15") \ 102 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C4+X*(C5+X)) */ \ 103 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 104 __ASM_EMIT("vmulps %%ymm10, %%ymm11, %%ymm11") \ 105 __ASM_EMIT("vmulps %%ymm14, %%ymm15, %%ymm15") \ 106 __ASM_EMIT("vaddps 0x0a0 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C3+X*(C4+X*(C5+X)) */ \ 107 __ASM_EMIT("vaddps 0x0a0 + %[E2C], %%ymm7, %%ymm7") \ 108 __ASM_EMIT("vaddps 0x0a0 + %[E2C], %%ymm11, %%ymm11") \ 109 __ASM_EMIT("vaddps 0x0a0 + %[E2C], %%ymm15, %%ymm15") \ 110 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C3+X*(C4+X*(C5+X))) */ \ 111 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 112 __ASM_EMIT("vmulps %%ymm10, %%ymm11, %%ymm11") \ 113 __ASM_EMIT("vmulps %%ymm14, %%ymm15, %%ymm15") \ 114 __ASM_EMIT("vaddps 0x0c0 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C2+X*(C3+X*(C4+X*(C5+X))) */ \ 115 __ASM_EMIT("vaddps 0x0c0 + %[E2C], %%ymm7, %%ymm7") \ 116 __ASM_EMIT("vaddps 0x0c0 + %[E2C], %%ymm11, %%ymm11") \ 117 __ASM_EMIT("vaddps 0x0c0 + %[E2C], %%ymm15, %%ymm15") \ 118 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 119 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 120 __ASM_EMIT("vmulps %%ymm10, %%ymm11, %%ymm11") \ 121 __ASM_EMIT("vmulps %%ymm14, %%ymm15, %%ymm15") \ 122 __ASM_EMIT("vaddps 0x0e0 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 123 __ASM_EMIT("vaddps 0x0e0 + %[E2C], %%ymm7, %%ymm7") \ 124 __ASM_EMIT("vaddps 0x0e0 + %[E2C], %%ymm11, %%ymm11") \ 125 __ASM_EMIT("vaddps 0x0e0 + %[E2C], %%ymm15, %%ymm15") \ 126 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 127 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 128 __ASM_EMIT("vmulps %%ymm10, %%ymm11, %%ymm11") \ 129 __ASM_EMIT("vmulps %%ymm14, %%ymm15, %%ymm15") \ 130 __ASM_EMIT("vaddps 0x100 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 131 __ASM_EMIT("vaddps 0x100 + %[E2C], %%ymm7, %%ymm7") \ 132 __ASM_EMIT("vaddps 0x100 + %[E2C], %%ymm11, %%ymm11") \ 133 __ASM_EMIT("vaddps 0x100 + %[E2C], %%ymm15, %%ymm15") \ 134 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 135 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 136 __ASM_EMIT("vmulps %%ymm10, %%ymm11, %%ymm11") \ 137 __ASM_EMIT("vmulps %%ymm14, %%ymm15, %%ymm15") \ 138 __ASM_EMIT("vmulps 0x120 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 139 __ASM_EMIT("vmulps 0x120 + %[E2C], %%ymm7, %%ymm7") \ 140 __ASM_EMIT("vmulps 0x120 + %[E2C], %%ymm11, %%ymm11") \ 141 __ASM_EMIT("vmulps 0x120 + %[E2C], %%ymm15, %%ymm15") \ 142 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm2") /* ymm2 = 1 */ \ 143 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm6") \ 144 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm10") \ 145 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm14") \ 146 __ASM_EMIT("vaddps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = 1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 147 __ASM_EMIT("vaddps %%ymm6, %%ymm7, %%ymm7") \ 148 __ASM_EMIT("vaddps %%ymm10, %%ymm11, %%ymm11") \ 149 __ASM_EMIT("vaddps %%ymm14, %%ymm15, %%ymm15") \ 150 __ASM_EMIT("vmulps %%ymm1, %%ymm3, %%ymm3") /* ymm3 = p = (1<<R)*(1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))))) */ \ 151 __ASM_EMIT("vmulps %%ymm5, %%ymm7, %%ymm7") \ 152 __ASM_EMIT("vmulps %%ymm9, %%ymm11, %%ymm11") \ 153 __ASM_EMIT("vmulps %%ymm13, %%ymm15, %%ymm15") \ 154 __ASM_EMIT("vdivps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = 1/p */ \ 155 __ASM_EMIT("vdivps %%ymm7, %%ymm6, %%ymm6") \ 156 __ASM_EMIT("vdivps %%ymm11, %%ymm10, %%ymm10") \ 157 __ASM_EMIT("vdivps %%ymm15, %%ymm14, %%ymm14") \ 158 /* ymm0 = x, ymm2 = 1/p, ymm3 = p */ \ 159 __ASM_EMIT("vblendvps %%ymm0, %%ymm2, %%ymm3, %%ymm0") /* ymm0 = ([x<0]&(1/p)) | ([x>=0]&p) */ \ 160 __ASM_EMIT("vblendvps %%ymm4, %%ymm6, %%ymm7, %%ymm4") \ 161 __ASM_EMIT("vblendvps %%ymm8, %%ymm10, %%ymm11, %%ymm8") \ 162 __ASM_EMIT("vblendvps %%ymm12, %%ymm14, %%ymm15, %%ymm12") 163 164 #define POW2_CORE_X16 \ 165 /* ymm0 = x */ \ 166 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm0, %%ymm2") /* ymm2 = XP = fabs(x) */ \ 167 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm4, %%ymm6") \ 168 __ASM_EMIT("vcvttps2dq %%ymm2, %%ymm1") /* ymm1 = R = int(XP) */ \ 169 __ASM_EMIT("vcvttps2dq %%ymm6, %%ymm5") \ 170 __ASM_EMIT("vcvtdq2ps %%ymm1, %%ymm3") /* ymm3 = float(R) */ \ 171 __ASM_EMIT("vcvtdq2ps %%ymm5, %%ymm7") \ 172 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm1, %%ymm1") /* ymm1 = R + 127 */ \ 173 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm5, %%ymm5") \ 174 __ASM_EMIT("vsubps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = XP - float(R) */ \ 175 __ASM_EMIT("vsubps %%ymm7, %%ymm6, %%ymm6") \ 176 __ASM_EMIT("vpslld $23, %%ymm1, %%ymm1") /* ymm1 = 1 << (R+127) */ \ 177 __ASM_EMIT("vpslld $23, %%ymm5, %%ymm5") \ 178 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm2, %%ymm2") /* ymm2 = X = ln(2) * (XP - float(R)) */ \ 179 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm6, %%ymm6") \ 180 /* ymm0 = [x<0], ymm1 = 1 << R, ymm2 = X */ \ 181 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C5+X */ \ 182 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm6, %%ymm7") \ 183 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C5+X) */ \ 184 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 185 __ASM_EMIT("vaddps 0x080 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C4+X*(C5+X) */ \ 186 __ASM_EMIT("vaddps 0x080 + %[E2C], %%ymm7, %%ymm7") \ 187 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C4+X*(C5+X)) */ \ 188 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 189 __ASM_EMIT("vaddps 0x0a0 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C3+X*(C4+X*(C5+X)) */ \ 190 __ASM_EMIT("vaddps 0x0a0 + %[E2C], %%ymm7, %%ymm7") \ 191 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C3+X*(C4+X*(C5+X))) */ \ 192 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 193 __ASM_EMIT("vaddps 0x0c0 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C2+X*(C3+X*(C4+X*(C5+X))) */ \ 194 __ASM_EMIT("vaddps 0x0c0 + %[E2C], %%ymm7, %%ymm7") \ 195 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 196 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 197 __ASM_EMIT("vaddps 0x0e0 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 198 __ASM_EMIT("vaddps 0x0e0 + %[E2C], %%ymm7, %%ymm7") \ 199 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 200 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 201 __ASM_EMIT("vaddps 0x100 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 202 __ASM_EMIT("vaddps 0x100 + %[E2C], %%ymm7, %%ymm7") \ 203 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 204 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 205 __ASM_EMIT("vmulps 0x120 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 206 __ASM_EMIT("vmulps 0x120 + %[E2C], %%ymm7, %%ymm7") \ 207 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm2") /* ymm2 = 1 */ \ 208 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm6") \ 209 __ASM_EMIT("vaddps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = 1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 210 __ASM_EMIT("vaddps %%ymm6, %%ymm7, %%ymm7") \ 211 __ASM_EMIT("vmulps %%ymm1, %%ymm3, %%ymm3") /* ymm3 = p = (1<<R)*(1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))))) */ \ 212 __ASM_EMIT("vmulps %%ymm5, %%ymm7, %%ymm7") \ 213 __ASM_EMIT("vdivps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = 1/p */ \ 214 __ASM_EMIT("vdivps %%ymm7, %%ymm6, %%ymm6") \ 215 /* ymm0 = x, ymm2 = 1/p, ymm3 = p */ \ 216 __ASM_EMIT("vblendvps %%ymm0, %%ymm2, %%ymm3, %%ymm0") /* ymm0 = ([x<0]&(1/p)) | ([x>=0]&p) */ \ 217 __ASM_EMIT("vblendvps %%ymm4, %%ymm6, %%ymm7, %%ymm4") 218 219 220 #define POW2_CORE_X8 \ 221 /* ymm0 = x */ \ 222 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm0, %%ymm2") /* ymm2 = XP = fabs(x) */ \ 223 __ASM_EMIT("vcvttps2dq %%ymm2, %%ymm1") /* ymm1 = R = int(XP) */ \ 224 __ASM_EMIT("vcvtdq2ps %%ymm1, %%ymm3") /* ymm3 = float(R) */ \ 225 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm1, %%ymm1") /* ymm1 = R + 127 */ \ 226 __ASM_EMIT("vsubps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = XP - float(R) */ \ 227 __ASM_EMIT("vpslld $23, %%ymm1, %%ymm1") /* ymm1 = 1 << (R+127) */ \ 228 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm2, %%ymm2") /* ymm2 = X = ln(2) * (XP - float(R)) */ \ 229 /* ymm0 = [x<0], ymm1 = 1 << R, ymm2 = X */ \ 230 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C5+X */ \ 231 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C5+X) */ \ 232 __ASM_EMIT("vaddps 0x080 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C4+X*(C5+X) */ \ 233 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C4+X*(C5+X)) */ \ 234 __ASM_EMIT("vaddps 0x0a0 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C3+X*(C4+X*(C5+X)) */ \ 235 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C3+X*(C4+X*(C5+X))) */ \ 236 __ASM_EMIT("vaddps 0x0c0 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C2+X*(C3+X*(C4+X*(C5+X))) */ \ 237 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 238 __ASM_EMIT("vaddps 0x0e0 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 239 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 240 __ASM_EMIT("vaddps 0x100 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 241 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 242 __ASM_EMIT("vmulps 0x120 + %[E2C], %%ymm3, %%ymm3") /* ymm3 = 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 243 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm2") /* ymm2 = 1 */ \ 244 __ASM_EMIT("vaddps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = 1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 245 __ASM_EMIT("vmulps %%ymm1, %%ymm3, %%ymm3") /* ymm3 = p = (1<<R)*(1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))))) */ \ 246 __ASM_EMIT("vdivps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = 1/p */ \ 247 /* ymm0 = x, ymm2 = 1/p, ymm3 = p */ \ 248 __ASM_EMIT("vblendvps %%ymm0, %%ymm2, %%ymm3, %%ymm0") /* ymm0 = ([x<0]&(1/p)) | ([x>=0]&p) */ 249 250 #define POW2_CORE_X4 \ 251 /* xmm0 = x */ \ 252 __ASM_EMIT("vandps 0x000 + %[E2C], %%xmm0, %%xmm2") /* xmm2 = XP = fabs(x) */ \ 253 __ASM_EMIT("vcvttps2dq %%xmm2, %%xmm1") /* xmm1 = R = int(XP) */ \ 254 __ASM_EMIT("vcvtdq2ps %%xmm1, %%xmm3") /* xmm3 = float(R) */ \ 255 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%xmm1, %%xmm1") /* xmm1 = R + 127 */ \ 256 __ASM_EMIT("vsubps %%xmm3, %%xmm2, %%xmm2") /* xmm2 = XP - float(R) */ \ 257 __ASM_EMIT("vpslld $23, %%xmm1, %%xmm1") /* xmm1 = 1 << (R+127) */ \ 258 __ASM_EMIT("vmulps 0x040 + %[E2C], %%xmm2, %%xmm2") /* xmm2 = X = ln(2) * (XP - float(R)) */ \ 259 /* xmm0 = [x<0], xmm1 = 1 << R, xmm2 = X */ \ 260 __ASM_EMIT("vaddps 0x060 + %[E2C], %%xmm2, %%xmm3") /* xmm3 = C5+X */ \ 261 __ASM_EMIT("vmulps %%xmm2, %%xmm3, %%xmm3") /* xmm3 = X*(C5+X) */ \ 262 __ASM_EMIT("vaddps 0x080 + %[E2C], %%xmm3, %%xmm3") /* xmm3 = C4+X*(C5+X) */ \ 263 __ASM_EMIT("vmulps %%xmm2, %%xmm3, %%xmm3") /* xmm3 = X*(C4+X*(C5+X)) */ \ 264 __ASM_EMIT("vaddps 0x0a0 + %[E2C], %%xmm3, %%xmm3") /* xmm3 = C3+X*(C4+X*(C5+X)) */ \ 265 __ASM_EMIT("vmulps %%xmm2, %%xmm3, %%xmm3") /* xmm3 = X*(C3+X*(C4+X*(C5+X))) */ \ 266 __ASM_EMIT("vaddps 0x0c0 + %[E2C], %%xmm3, %%xmm3") /* xmm3 = C2+X*(C3+X*(C4+X*(C5+X))) */ \ 267 __ASM_EMIT("vmulps %%xmm2, %%xmm3, %%xmm3") /* xmm3 = X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 268 __ASM_EMIT("vaddps 0x0e0 + %[E2C], %%xmm3, %%xmm3") /* xmm3 = C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 269 __ASM_EMIT("vmulps %%xmm2, %%xmm3, %%xmm3") /* xmm3 = X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 270 __ASM_EMIT("vaddps 0x100 + %[E2C], %%xmm3, %%xmm3") /* xmm3 = C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 271 __ASM_EMIT("vmulps %%xmm2, %%xmm3, %%xmm3") /* xmm3 = X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 272 __ASM_EMIT("vmulps 0x120 + %[E2C], %%xmm3, %%xmm3") /* xmm3 = 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 273 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%xmm2") /* xmm2 = 1 */ \ 274 __ASM_EMIT("vaddps %%xmm2, %%xmm3, %%xmm3") /* xmm3 = 1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 275 __ASM_EMIT("vmulps %%xmm1, %%xmm3, %%xmm3") /* xmm3 = p = (1<<R)*(1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))))) */ \ 276 __ASM_EMIT("vdivps %%xmm3, %%xmm2, %%xmm2") /* xmm2 = 1/p */ \ 277 /* xmm0 = x, xmm2 = 1/p, xmm3 = p */ \ 278 __ASM_EMIT("vblendvps %%xmm0, %%xmm2, %%xmm3, %%xmm0") /* xmm0 = ([x<0]&(1/p)) | ([x>=0]&p) */ 279 x64_exp1(float * dst,size_t count)280 void x64_exp1(float *dst, size_t count) 281 { 282 IF_ARCH_X86(float *src); 283 284 ARCH_X86_ASM( 285 // x32 blocks 286 __ASM_EMIT("sub $32, %[count]") 287 __ASM_EMIT("jb 2f") 288 __ASM_EMIT("1:") 289 __ASM_EMIT("vmovups 0x00(%[dst]), %%ymm0") 290 __ASM_EMIT("vmovups 0x20(%[dst]), %%ymm4") 291 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 292 __ASM_EMIT("vmovups 0x40(%[dst]), %%ymm8") 293 __ASM_EMIT("vmulps %[LOG2E], %%ymm4, %%ymm4") 294 __ASM_EMIT("vmovups 0x60(%[dst]), %%ymm12") 295 __ASM_EMIT("vmulps %[LOG2E], %%ymm8, %%ymm8") 296 __ASM_EMIT("vmulps %[LOG2E], %%ymm12, %%ymm12") 297 POW2_CORE_X32 298 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 299 __ASM_EMIT("vmovups %%ymm4, 0x20(%[dst])") 300 __ASM_EMIT("vmovups %%ymm8, 0x40(%[dst])") 301 __ASM_EMIT("vmovups %%ymm12, 0x60(%[dst])") 302 __ASM_EMIT("add $0x80, %[dst]") 303 __ASM_EMIT("sub $32, %[count]") 304 __ASM_EMIT("jae 1b") 305 306 // x16 block 307 __ASM_EMIT("2:") 308 __ASM_EMIT("add $16, %[count]") 309 __ASM_EMIT("jl 4f") 310 __ASM_EMIT("vmovups 0x00(%[dst]), %%ymm0") 311 __ASM_EMIT("vmovups 0x20(%[dst]), %%ymm4") 312 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 313 __ASM_EMIT("vmulps %[LOG2E], %%ymm4, %%ymm4") 314 POW2_CORE_X16 315 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 316 __ASM_EMIT("vmovups %%ymm4, 0x20(%[dst])") 317 __ASM_EMIT("sub $16, %[count]") 318 __ASM_EMIT("add $0x40, %[dst]") 319 320 // x8 block 321 __ASM_EMIT("4:") 322 __ASM_EMIT("add $8, %[count]") 323 __ASM_EMIT("jl 6f") 324 __ASM_EMIT("vmovups 0x00(%[dst]), %%ymm0") 325 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 326 POW2_CORE_X8 327 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 328 __ASM_EMIT("sub $8, %[count]") 329 __ASM_EMIT("add $0x20, %[dst]") 330 331 // x4 block 332 __ASM_EMIT("6:") 333 __ASM_EMIT("add $4, %[count]") 334 __ASM_EMIT("jl 8f") 335 __ASM_EMIT("vmovups 0x00(%[dst]), %%xmm0") 336 __ASM_EMIT("vmulps %[LOG2E], %%xmm0, %%xmm0") 337 POW2_CORE_X4 338 __ASM_EMIT("vmovups %%xmm0, 0x00(%[dst])") 339 __ASM_EMIT("sub $4, %[count]") 340 __ASM_EMIT("add $0x10, %[dst]") 341 342 // Tail: 1x-3x block 343 __ASM_EMIT("8:") 344 __ASM_EMIT("add $4, %[count]") 345 __ASM_EMIT("jle 16f") 346 __ASM_EMIT("mov %[dst], %[src]") 347 __ASM_EMIT("test $1, %[count]") 348 __ASM_EMIT("jz 10f") 349 __ASM_EMIT("vmovss 0x00(%[src]), %%xmm0") 350 __ASM_EMIT("add $4, %[src]") 351 __ASM_EMIT("10:") 352 __ASM_EMIT("test $2, %[count]") 353 __ASM_EMIT("jz 12f") 354 __ASM_EMIT("vmovhps 0x00(%[src]), %%xmm0, %%xmm0") 355 __ASM_EMIT("12:") 356 357 __ASM_EMIT("vmulps %[LOG2E], %%xmm0, %%xmm0") 358 POW2_CORE_X4 359 360 __ASM_EMIT("test $1, %[count]") 361 __ASM_EMIT("jz 14f") 362 __ASM_EMIT("vmovss %%xmm0, 0x00(%[dst])") 363 __ASM_EMIT("add $4, %[dst]") 364 __ASM_EMIT("14:") 365 __ASM_EMIT("test $2, %[count]") 366 __ASM_EMIT("jz 16f") 367 __ASM_EMIT("vmovhps %%xmm0, 0x00(%[dst])") 368 369 // End 370 __ASM_EMIT("16:") 371 __ASM_EMIT("vzeroupper") 372 373 : [dst] "+r" (dst), [src] "=&r" (src), [count] "+r" (count) 374 : [E2C] "o" (EXP2_CONST), 375 [LOG2E] "m" (EXP_LOG2E) 376 : "cc", "memory", 377 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", 378 "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" 379 ); 380 } 381 x64_exp2(float * dst,const float * src,size_t count)382 void x64_exp2(float *dst, const float *src, size_t count) 383 { 384 ARCH_X86_ASM( 385 // x32 blocks 386 __ASM_EMIT("sub $32, %[count]") 387 __ASM_EMIT("jb 2f") 388 __ASM_EMIT("1:") 389 __ASM_EMIT("vmovups 0x00(%[src]), %%ymm0") 390 __ASM_EMIT("vmovups 0x20(%[src]), %%ymm4") 391 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 392 __ASM_EMIT("vmovups 0x40(%[src]), %%ymm8") 393 __ASM_EMIT("vmulps %[LOG2E], %%ymm4, %%ymm4") 394 __ASM_EMIT("vmovups 0x60(%[src]), %%ymm12") 395 __ASM_EMIT("vmulps %[LOG2E], %%ymm8, %%ymm8") 396 __ASM_EMIT("vmulps %[LOG2E], %%ymm12, %%ymm12") 397 POW2_CORE_X32 398 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 399 __ASM_EMIT("vmovups %%ymm4, 0x20(%[dst])") 400 __ASM_EMIT("vmovups %%ymm8, 0x40(%[dst])") 401 __ASM_EMIT("vmovups %%ymm12, 0x60(%[dst])") 402 __ASM_EMIT("add $0x80, %[src]") 403 __ASM_EMIT("add $0x80, %[dst]") 404 __ASM_EMIT("sub $32, %[count]") 405 __ASM_EMIT("jae 1b") 406 407 // x16 block 408 __ASM_EMIT("2:") 409 __ASM_EMIT("add $16, %[count]") 410 __ASM_EMIT("jl 4f") 411 __ASM_EMIT("vmovups 0x00(%[src]), %%ymm0") 412 __ASM_EMIT("vmovups 0x20(%[src]), %%ymm4") 413 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 414 __ASM_EMIT("vmulps %[LOG2E], %%ymm4, %%ymm4") 415 POW2_CORE_X16 416 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 417 __ASM_EMIT("vmovups %%ymm4, 0x20(%[dst])") 418 __ASM_EMIT("sub $16, %[count]") 419 __ASM_EMIT("add $0x40, %[src]") 420 __ASM_EMIT("add $0x40, %[dst]") 421 422 // x8 block 423 __ASM_EMIT("4:") 424 __ASM_EMIT("add $8, %[count]") 425 __ASM_EMIT("jl 6f") 426 __ASM_EMIT("vmovups 0x00(%[src]), %%ymm0") 427 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 428 POW2_CORE_X8 429 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 430 __ASM_EMIT("sub $8, %[count]") 431 __ASM_EMIT("add $0x20, %[src]") 432 __ASM_EMIT("add $0x20, %[dst]") 433 434 // x4 block 435 __ASM_EMIT("6:") 436 __ASM_EMIT("add $4, %[count]") 437 __ASM_EMIT("jl 8f") 438 __ASM_EMIT("vmovups 0x00(%[src]), %%xmm0") 439 __ASM_EMIT("vmulps %[LOG2E], %%xmm0, %%xmm0") 440 POW2_CORE_X4 441 __ASM_EMIT("vmovups %%xmm0, 0x00(%[dst])") 442 __ASM_EMIT("sub $4, %[count]") 443 __ASM_EMIT("add $0x10, %[src]") 444 __ASM_EMIT("add $0x10, %[dst]") 445 446 // Tail: 1x-3x block 447 __ASM_EMIT("8:") 448 __ASM_EMIT("add $4, %[count]") 449 __ASM_EMIT("jle 16f") 450 __ASM_EMIT("test $1, %[count]") 451 __ASM_EMIT("jz 10f") 452 __ASM_EMIT("vmovss 0x00(%[src]), %%xmm0") 453 __ASM_EMIT("add $4, %[src]") 454 __ASM_EMIT("10:") 455 __ASM_EMIT("test $2, %[count]") 456 __ASM_EMIT("jz 12f") 457 __ASM_EMIT("vmovhps 0x00(%[src]), %%xmm0, %%xmm0") 458 __ASM_EMIT("12:") 459 460 __ASM_EMIT("vmulps %[LOG2E], %%xmm0, %%xmm0") 461 POW2_CORE_X4 462 463 __ASM_EMIT("test $1, %[count]") 464 __ASM_EMIT("jz 14f") 465 __ASM_EMIT("vmovss %%xmm0, 0x00(%[dst])") 466 __ASM_EMIT("add $4, %[dst]") 467 __ASM_EMIT("14:") 468 __ASM_EMIT("test $2, %[count]") 469 __ASM_EMIT("jz 16f") 470 __ASM_EMIT("vmovhps %%xmm0, 0x00(%[dst])") 471 472 // End 473 __ASM_EMIT("16:") 474 __ASM_EMIT("vzeroupper") 475 476 : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count) 477 : [E2C] "o" (EXP2_CONST), 478 [LOG2E] "m" (EXP_LOG2E) 479 : "cc", "memory", 480 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", 481 "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" 482 ); 483 } 484 485 486 #define POW2_FMA3_CORE_X32 \ 487 /* ymm0 = x */ \ 488 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm0, %%ymm2") /* ymm2 = XP = fabs(x) */ \ 489 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm4, %%ymm6") \ 490 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm8, %%ymm10") \ 491 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm12, %%ymm14") \ 492 __ASM_EMIT("vcvttps2dq %%ymm2, %%ymm1") /* ymm1 = R = int(XP) */ \ 493 __ASM_EMIT("vcvttps2dq %%ymm6, %%ymm5") \ 494 __ASM_EMIT("vcvttps2dq %%ymm10, %%ymm9") \ 495 __ASM_EMIT("vcvttps2dq %%ymm14, %%ymm13") \ 496 __ASM_EMIT("vcvtdq2ps %%ymm1, %%ymm3") /* ymm3 = float(R) */ \ 497 __ASM_EMIT("vcvtdq2ps %%ymm5, %%ymm7") \ 498 __ASM_EMIT("vcvtdq2ps %%ymm9, %%ymm11") \ 499 __ASM_EMIT("vcvtdq2ps %%ymm13, %%ymm15") \ 500 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm1, %%ymm1") /* ymm1 = R + 127 */ \ 501 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm5, %%ymm5") \ 502 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm9, %%ymm9") \ 503 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm13, %%ymm13") \ 504 __ASM_EMIT("vsubps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = XP - float(R) */ \ 505 __ASM_EMIT("vsubps %%ymm7, %%ymm6, %%ymm6") \ 506 __ASM_EMIT("vsubps %%ymm11, %%ymm10, %%ymm10") \ 507 __ASM_EMIT("vsubps %%ymm15, %%ymm14, %%ymm14") \ 508 __ASM_EMIT("vpslld $23, %%ymm1, %%ymm1") /* ymm1 = 1 << (R+127) */ \ 509 __ASM_EMIT("vpslld $23, %%ymm5, %%ymm5") \ 510 __ASM_EMIT("vpslld $23, %%ymm9, %%ymm9") \ 511 __ASM_EMIT("vpslld $23, %%ymm13, %%ymm13") \ 512 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm2, %%ymm2") /* ymm2 = X = ln(2) * (XP - float(R)) */ \ 513 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm6, %%ymm6") \ 514 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm10, %%ymm10") \ 515 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm14, %%ymm14") \ 516 /* ymm0 = [x<0], ymm1 = 1 << R, ymm2 = X */ \ 517 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C5+X */ \ 518 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm6, %%ymm7") \ 519 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm10, %%ymm11") \ 520 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm14, %%ymm15") \ 521 __ASM_EMIT("vfmadd213ps 0x080 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C4+X*(C5+X) */ \ 522 __ASM_EMIT("vfmadd213ps 0x080 + %[E2C], %%ymm6, %%ymm7") \ 523 __ASM_EMIT("vfmadd213ps 0x080 + %[E2C], %%ymm10, %%ymm11") \ 524 __ASM_EMIT("vfmadd213ps 0x080 + %[E2C], %%ymm14, %%ymm15") \ 525 __ASM_EMIT("vfmadd213ps 0x0a0 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C3+X*(C4+X*(C5+X)) */ \ 526 __ASM_EMIT("vfmadd213ps 0x0a0 + %[E2C], %%ymm6, %%ymm7") \ 527 __ASM_EMIT("vfmadd213ps 0x0a0 + %[E2C], %%ymm10, %%ymm11") \ 528 __ASM_EMIT("vfmadd213ps 0x0a0 + %[E2C], %%ymm14, %%ymm15") \ 529 __ASM_EMIT("vfmadd213ps 0x0c0 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C2+X*(C3+X*(C4+X*(C5+X))) */ \ 530 __ASM_EMIT("vfmadd213ps 0x0c0 + %[E2C], %%ymm6, %%ymm7") \ 531 __ASM_EMIT("vfmadd213ps 0x0c0 + %[E2C], %%ymm10, %%ymm11") \ 532 __ASM_EMIT("vfmadd213ps 0x0c0 + %[E2C], %%ymm14, %%ymm15") \ 533 __ASM_EMIT("vfmadd213ps 0x0e0 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 534 __ASM_EMIT("vfmadd213ps 0x0e0 + %[E2C], %%ymm6, %%ymm7") \ 535 __ASM_EMIT("vfmadd213ps 0x0e0 + %[E2C], %%ymm10, %%ymm11") \ 536 __ASM_EMIT("vfmadd213ps 0x0e0 + %[E2C], %%ymm14, %%ymm15") \ 537 __ASM_EMIT("vfmadd213ps 0x100 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 538 __ASM_EMIT("vfmadd213ps 0x100 + %[E2C], %%ymm6, %%ymm7") \ 539 __ASM_EMIT("vfmadd213ps 0x100 + %[E2C], %%ymm10, %%ymm11") \ 540 __ASM_EMIT("vfmadd213ps 0x100 + %[E2C], %%ymm14, %%ymm15") \ 541 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 542 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 543 __ASM_EMIT("vmulps %%ymm10, %%ymm11, %%ymm11") \ 544 __ASM_EMIT("vmulps %%ymm14, %%ymm15, %%ymm15") \ 545 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm2") /* ymm2 = 1 */ \ 546 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm6") \ 547 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm10") \ 548 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm14") \ 549 __ASM_EMIT("vfmadd132ps 0x120 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = 1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 550 __ASM_EMIT("vfmadd132ps 0x120 + %[E2C], %%ymm6, %%ymm7") \ 551 __ASM_EMIT("vfmadd132ps 0x120 + %[E2C], %%ymm10, %%ymm11") \ 552 __ASM_EMIT("vfmadd132ps 0x120 + %[E2C], %%ymm14, %%ymm15") \ 553 __ASM_EMIT("vmulps %%ymm1, %%ymm3, %%ymm3") /* ymm3 = p = (1<<R)*(1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))))) */ \ 554 __ASM_EMIT("vmulps %%ymm5, %%ymm7, %%ymm7") \ 555 __ASM_EMIT("vmulps %%ymm9, %%ymm11, %%ymm11") \ 556 __ASM_EMIT("vmulps %%ymm13, %%ymm15, %%ymm15") \ 557 __ASM_EMIT("vdivps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = 1/p */ \ 558 __ASM_EMIT("vdivps %%ymm7, %%ymm6, %%ymm6") \ 559 __ASM_EMIT("vdivps %%ymm11, %%ymm10, %%ymm10") \ 560 __ASM_EMIT("vdivps %%ymm15, %%ymm14, %%ymm14") \ 561 /* ymm0 = x, ymm2 = 1/p, ymm3 = p */ \ 562 __ASM_EMIT("vblendvps %%ymm0, %%ymm2, %%ymm3, %%ymm0") /* ymm0 = ([x<0]&(1/p)) | ([x>=0]&p) */ \ 563 __ASM_EMIT("vblendvps %%ymm4, %%ymm6, %%ymm7, %%ymm4") \ 564 __ASM_EMIT("vblendvps %%ymm8, %%ymm10, %%ymm11, %%ymm8") \ 565 __ASM_EMIT("vblendvps %%ymm12, %%ymm14, %%ymm15, %%ymm12") 566 567 568 #define POW2_FMA3_CORE_X16 \ 569 /* ymm0 = x */ \ 570 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm0, %%ymm2") /* ymm2 = XP = fabs(x) */ \ 571 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm4, %%ymm6") \ 572 __ASM_EMIT("vcvttps2dq %%ymm2, %%ymm1") /* ymm1 = R = int(XP) */ \ 573 __ASM_EMIT("vcvttps2dq %%ymm6, %%ymm5") \ 574 __ASM_EMIT("vcvtdq2ps %%ymm1, %%ymm3") /* ymm3 = float(R) */ \ 575 __ASM_EMIT("vcvtdq2ps %%ymm5, %%ymm7") \ 576 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm1, %%ymm1") /* ymm1 = R + 127 */ \ 577 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm5, %%ymm5") \ 578 __ASM_EMIT("vsubps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = XP - float(R) */ \ 579 __ASM_EMIT("vsubps %%ymm7, %%ymm6, %%ymm6") \ 580 __ASM_EMIT("vpslld $23, %%ymm1, %%ymm1") /* ymm1 = 1 << (R+127) */ \ 581 __ASM_EMIT("vpslld $23, %%ymm5, %%ymm5") \ 582 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm2, %%ymm2") /* ymm2 = X = ln(2) * (XP - float(R)) */ \ 583 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm6, %%ymm6") \ 584 /* ymm0 = [x<0], ymm1 = 1 << R, ymm2 = X */ \ 585 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C5+X */ \ 586 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm6, %%ymm7") \ 587 __ASM_EMIT("vfmadd213ps 0x080 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C4+X*(C5+X) */ \ 588 __ASM_EMIT("vfmadd213ps 0x080 + %[E2C], %%ymm6, %%ymm7") \ 589 __ASM_EMIT("vfmadd213ps 0x0a0 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C3+X*(C4+X*(C5+X)) */ \ 590 __ASM_EMIT("vfmadd213ps 0x0a0 + %[E2C], %%ymm6, %%ymm7") \ 591 __ASM_EMIT("vfmadd213ps 0x0c0 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C2+X*(C3+X*(C4+X*(C5+X))) */ \ 592 __ASM_EMIT("vfmadd213ps 0x0c0 + %[E2C], %%ymm6, %%ymm7") \ 593 __ASM_EMIT("vfmadd213ps 0x0e0 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 594 __ASM_EMIT("vfmadd213ps 0x0e0 + %[E2C], %%ymm6, %%ymm7") \ 595 __ASM_EMIT("vfmadd213ps 0x100 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 596 __ASM_EMIT("vfmadd213ps 0x100 + %[E2C], %%ymm6, %%ymm7") \ 597 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 598 __ASM_EMIT("vmulps %%ymm6, %%ymm7, %%ymm7") \ 599 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm2") /* ymm2 = 1 */ \ 600 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm6") \ 601 __ASM_EMIT("vfmadd132ps 0x120 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = 1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 602 __ASM_EMIT("vfmadd132ps 0x120 + %[E2C], %%ymm6, %%ymm7") \ 603 __ASM_EMIT("vmulps %%ymm1, %%ymm3, %%ymm3") /* ymm3 = p = (1<<R)*(1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))))) */ \ 604 __ASM_EMIT("vmulps %%ymm5, %%ymm7, %%ymm7") \ 605 __ASM_EMIT("vdivps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = 1/p */ \ 606 __ASM_EMIT("vdivps %%ymm7, %%ymm6, %%ymm6") \ 607 /* ymm0 = x, ymm2 = 1/p, ymm3 = p */ \ 608 __ASM_EMIT("vblendvps %%ymm0, %%ymm2, %%ymm3, %%ymm0") /* ymm0 = ([x<0]&(1/p)) | ([x>=0]&p) */ \ 609 __ASM_EMIT("vblendvps %%ymm4, %%ymm6, %%ymm7, %%ymm4") 610 611 #define POW2_FMA3_CORE_X8 \ 612 /* ymm0 = x */ \ 613 __ASM_EMIT("vandps 0x000 + %[E2C], %%ymm0, %%ymm2") /* ymm2 = XP = fabs(x) */ \ 614 __ASM_EMIT("vcvttps2dq %%ymm2, %%ymm1") /* ymm1 = R = int(XP) */ \ 615 __ASM_EMIT("vcvtdq2ps %%ymm1, %%ymm3") /* ymm3 = float(R) */ \ 616 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%ymm1, %%ymm1") /* ymm1 = R + 127 */ \ 617 __ASM_EMIT("vsubps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = XP - float(R) */ \ 618 __ASM_EMIT("vpslld $23, %%ymm1, %%ymm1") /* ymm1 = 1 << (R+127) */ \ 619 __ASM_EMIT("vmulps 0x040 + %[E2C], %%ymm2, %%ymm2") /* ymm2 = X = ln(2) * (XP - float(R)) */ \ 620 /* ymm0 = [x<0], ymm1 = 1 << R, ymm2 = X */ \ 621 __ASM_EMIT("vaddps 0x060 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C5+X */ \ 622 __ASM_EMIT("vfmadd213ps 0x080 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C4+X*(C5+X) */ \ 623 __ASM_EMIT("vfmadd213ps 0x0a0 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C3+X*(C4+X*(C5+X)) */ \ 624 __ASM_EMIT("vfmadd213ps 0x0c0 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C2+X*(C3+X*(C4+X*(C5+X))) */ \ 625 __ASM_EMIT("vfmadd213ps 0x0e0 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 626 __ASM_EMIT("vfmadd213ps 0x100 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 627 __ASM_EMIT("vmulps %%ymm2, %%ymm3, %%ymm3") /* ymm3 = X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 628 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%ymm2") /* ymm2 = 1 */ \ 629 __ASM_EMIT("vfmadd132ps 0x120 + %[E2C], %%ymm2, %%ymm3") /* ymm3 = 1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 630 __ASM_EMIT("vmulps %%ymm1, %%ymm3, %%ymm3") /* ymm3 = p = (1<<R)*(1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))))) */ \ 631 __ASM_EMIT("vdivps %%ymm3, %%ymm2, %%ymm2") /* ymm2 = 1/p */ \ 632 /* ymm0 = x, ymm2 = 1/p, ymm3 = p */ \ 633 __ASM_EMIT("vblendvps %%ymm0, %%ymm2, %%ymm3, %%ymm0") /* ymm0 = ([x<0]&(1/p)) | ([x>=0]&p) */ 634 635 #define POW2_FMA3_CORE_X4 \ 636 /* xmm0 = x */ \ 637 __ASM_EMIT("vandps 0x000 + %[E2C], %%xmm0, %%xmm2") /* xmm2 = XP = fabs(x) */ \ 638 __ASM_EMIT("vcvttps2dq %%xmm2, %%xmm1") /* xmm1 = R = int(XP) */ \ 639 __ASM_EMIT("vcvtdq2ps %%xmm1, %%xmm3") /* xmm3 = float(R) */ \ 640 __ASM_EMIT("vpaddd 0x020 + %[E2C], %%xmm1, %%xmm1") /* xmm1 = R + 127 */ \ 641 __ASM_EMIT("vsubps %%xmm3, %%xmm2, %%xmm2") /* xmm2 = XP - float(R) */ \ 642 __ASM_EMIT("vpslld $23, %%xmm1, %%xmm1") /* xmm1 = 1 << (R+127) */ \ 643 __ASM_EMIT("vmulps 0x040 + %[E2C], %%xmm2, %%xmm2") /* xmm2 = X = ln(2) * (XP - float(R)) */ \ 644 /* xmm0 = [x<0], xmm1 = 1 << R, xmm2 = X */ \ 645 __ASM_EMIT("vaddps 0x060 + %[E2C], %%xmm2, %%xmm3") /* xmm3 = C5+X */ \ 646 __ASM_EMIT("vfmadd213ps 0x080 + %[E2C], %%xmm2, %%xmm3") /* xmm3 = C4+X*(C5+X) */ \ 647 __ASM_EMIT("vfmadd213ps 0x0a0 + %[E2C], %%xmm2, %%xmm3") /* xmm3 = C3+X*(C4+X*(C5+X)) */ \ 648 __ASM_EMIT("vfmadd213ps 0x0c0 + %[E2C], %%xmm2, %%xmm3") /* xmm3 = C2+X*(C3+X*(C4+X*(C5+X))) */ \ 649 __ASM_EMIT("vfmadd213ps 0x0e0 + %[E2C], %%xmm2, %%xmm3") /* xmm3 = C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))) */ \ 650 __ASM_EMIT("vfmadd213ps 0x100 + %[E2C], %%xmm2, %%xmm3") /* xmm3 = C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))) */ \ 651 __ASM_EMIT("vmulps %%xmm2, %%xmm3, %%xmm3") /* xmm3 = X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 652 __ASM_EMIT("vmovaps 0x140 + %[E2C], %%xmm2") /* xmm2 = 1 */ \ 653 __ASM_EMIT("vfmadd132ps 0x120 + %[E2C], %%xmm2, %%xmm3") /* xmm3 = 1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X)))))) */ \ 654 __ASM_EMIT("vmulps %%xmm1, %%xmm3, %%xmm3") /* xmm3 = p = (1<<R)*(1 + 1/7!*X*(C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X))))))) */ \ 655 __ASM_EMIT("vdivps %%xmm3, %%xmm2, %%xmm2") /* xmm2 = 1/p */ \ 656 /* xmm0 = x, xmm2 = 1/p, xmm3 = p */ \ 657 __ASM_EMIT("vblendvps %%xmm0, %%xmm2, %%xmm3, %%xmm0") /* xmm0 = ([x<0]&(1/p)) | ([x>=0]&p) */ 658 x64_exp1_fma3(float * dst,size_t count)659 void x64_exp1_fma3(float *dst, size_t count) 660 { 661 IF_ARCH_X86(float *src); 662 663 ARCH_X86_ASM( 664 // x32 blocks 665 __ASM_EMIT("sub $32, %[count]") 666 __ASM_EMIT("jb 2f") 667 __ASM_EMIT("1:") 668 __ASM_EMIT("vmovups 0x00(%[dst]), %%ymm0") 669 __ASM_EMIT("vmovups 0x20(%[dst]), %%ymm4") 670 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 671 __ASM_EMIT("vmovups 0x40(%[dst]), %%ymm8") 672 __ASM_EMIT("vmulps %[LOG2E], %%ymm4, %%ymm4") 673 __ASM_EMIT("vmovups 0x60(%[dst]), %%ymm12") 674 __ASM_EMIT("vmulps %[LOG2E], %%ymm8, %%ymm8") 675 __ASM_EMIT("vmulps %[LOG2E], %%ymm12, %%ymm12") 676 POW2_FMA3_CORE_X32 677 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 678 __ASM_EMIT("vmovups %%ymm4, 0x20(%[dst])") 679 __ASM_EMIT("vmovups %%ymm8, 0x40(%[dst])") 680 __ASM_EMIT("vmovups %%ymm12, 0x60(%[dst])") 681 __ASM_EMIT("add $0x80, %[dst]") 682 __ASM_EMIT("sub $32, %[count]") 683 __ASM_EMIT("jae 1b") 684 685 // x16 block 686 __ASM_EMIT("2:") 687 __ASM_EMIT("add $16, %[count]") 688 __ASM_EMIT("jl 4f") 689 __ASM_EMIT("vmovups 0x00(%[dst]), %%ymm0") 690 __ASM_EMIT("vmovups 0x20(%[dst]), %%ymm4") 691 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 692 __ASM_EMIT("vmulps %[LOG2E], %%ymm4, %%ymm4") 693 POW2_FMA3_CORE_X16 694 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 695 __ASM_EMIT("vmovups %%ymm4, 0x20(%[dst])") 696 __ASM_EMIT("sub $16, %[count]") 697 __ASM_EMIT("add $0x40, %[dst]") 698 699 // x8 block 700 __ASM_EMIT("4:") 701 __ASM_EMIT("add $8, %[count]") 702 __ASM_EMIT("jl 6f") 703 __ASM_EMIT("vmovups 0x00(%[dst]), %%ymm0") 704 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 705 POW2_FMA3_CORE_X8 706 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 707 __ASM_EMIT("sub $8, %[count]") 708 __ASM_EMIT("add $0x20, %[dst]") 709 710 // x4 block 711 __ASM_EMIT("6:") 712 __ASM_EMIT("add $4, %[count]") 713 __ASM_EMIT("jl 8f") 714 __ASM_EMIT("vmovups 0x00(%[dst]), %%xmm0") 715 __ASM_EMIT("vmulps %[LOG2E], %%xmm0, %%xmm0") 716 POW2_FMA3_CORE_X4 717 __ASM_EMIT("vmovups %%xmm0, 0x00(%[dst])") 718 __ASM_EMIT("sub $4, %[count]") 719 __ASM_EMIT("add $0x10, %[dst]") 720 721 // Tail: 1x-3x block 722 __ASM_EMIT("8:") 723 __ASM_EMIT("add $4, %[count]") 724 __ASM_EMIT("jle 16f") 725 __ASM_EMIT("mov %[dst], %[src]") 726 __ASM_EMIT("test $1, %[count]") 727 __ASM_EMIT("jz 10f") 728 __ASM_EMIT("vmovss 0x00(%[src]), %%xmm0") 729 __ASM_EMIT("add $4, %[src]") 730 __ASM_EMIT("10:") 731 __ASM_EMIT("test $2, %[count]") 732 __ASM_EMIT("jz 12f") 733 __ASM_EMIT("vmovhps 0x00(%[src]), %%xmm0, %%xmm0") 734 __ASM_EMIT("12:") 735 736 __ASM_EMIT("vmulps %[LOG2E], %%xmm0, %%xmm0") 737 POW2_FMA3_CORE_X4 738 739 __ASM_EMIT("test $1, %[count]") 740 __ASM_EMIT("jz 14f") 741 __ASM_EMIT("vmovss %%xmm0, 0x00(%[dst])") 742 __ASM_EMIT("add $4, %[dst]") 743 __ASM_EMIT("14:") 744 __ASM_EMIT("test $2, %[count]") 745 __ASM_EMIT("jz 16f") 746 __ASM_EMIT("vmovhps %%xmm0, 0x00(%[dst])") 747 748 // End 749 __ASM_EMIT("16:") 750 __ASM_EMIT("vzeroupper") 751 752 : [dst] "+r" (dst), [src] "=&r" (src), [count] "+r" (count) 753 : [E2C] "o" (EXP2_CONST), 754 [LOG2E] "m" (EXP_LOG2E) 755 : "cc", "memory", 756 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", 757 "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" 758 ); 759 } 760 x64_exp2_fma3(float * dst,const float * src,size_t count)761 void x64_exp2_fma3(float *dst, const float *src, size_t count) 762 { 763 ARCH_X86_ASM( 764 // x32 blocks 765 __ASM_EMIT("sub $32, %[count]") 766 __ASM_EMIT("jb 2f") 767 __ASM_EMIT("1:") 768 __ASM_EMIT("vmovups 0x00(%[src]), %%ymm0") 769 __ASM_EMIT("vmovups 0x20(%[src]), %%ymm4") 770 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 771 __ASM_EMIT("vmovups 0x40(%[src]), %%ymm8") 772 __ASM_EMIT("vmulps %[LOG2E], %%ymm4, %%ymm4") 773 __ASM_EMIT("vmovups 0x60(%[src]), %%ymm12") 774 __ASM_EMIT("vmulps %[LOG2E], %%ymm8, %%ymm8") 775 __ASM_EMIT("vmulps %[LOG2E], %%ymm12, %%ymm12") 776 POW2_FMA3_CORE_X32 777 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 778 __ASM_EMIT("vmovups %%ymm4, 0x20(%[dst])") 779 __ASM_EMIT("vmovups %%ymm8, 0x40(%[dst])") 780 __ASM_EMIT("vmovups %%ymm12, 0x60(%[dst])") 781 __ASM_EMIT("add $0x80, %[src]") 782 __ASM_EMIT("add $0x80, %[dst]") 783 __ASM_EMIT("sub $32, %[count]") 784 __ASM_EMIT("jae 1b") 785 786 // x16 block 787 __ASM_EMIT("2:") 788 __ASM_EMIT("add $16, %[count]") 789 __ASM_EMIT("jl 4f") 790 __ASM_EMIT("vmovups 0x00(%[src]), %%ymm0") 791 __ASM_EMIT("vmovups 0x20(%[src]), %%ymm4") 792 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 793 __ASM_EMIT("vmulps %[LOG2E], %%ymm4, %%ymm4") 794 POW2_FMA3_CORE_X16 795 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 796 __ASM_EMIT("vmovups %%ymm4, 0x20(%[dst])") 797 __ASM_EMIT("sub $16, %[count]") 798 __ASM_EMIT("add $0x40, %[src]") 799 __ASM_EMIT("add $0x40, %[dst]") 800 801 // x8 block 802 __ASM_EMIT("4:") 803 __ASM_EMIT("add $8, %[count]") 804 __ASM_EMIT("jl 6f") 805 __ASM_EMIT("vmovups 0x00(%[src]), %%ymm0") 806 __ASM_EMIT("vmulps %[LOG2E], %%ymm0, %%ymm0") 807 POW2_FMA3_CORE_X8 808 __ASM_EMIT("vmovups %%ymm0, 0x00(%[dst])") 809 __ASM_EMIT("sub $8, %[count]") 810 __ASM_EMIT("add $0x20, %[src]") 811 __ASM_EMIT("add $0x20, %[dst]") 812 813 // x4 block 814 __ASM_EMIT("6:") 815 __ASM_EMIT("add $4, %[count]") 816 __ASM_EMIT("jl 8f") 817 __ASM_EMIT("vmovups 0x00(%[src]), %%xmm0") 818 __ASM_EMIT("vmulps %[LOG2E], %%xmm0, %%xmm0") 819 POW2_FMA3_CORE_X4 820 __ASM_EMIT("vmovups %%xmm0, 0x00(%[dst])") 821 __ASM_EMIT("sub $4, %[count]") 822 __ASM_EMIT("add $0x10, %[src]") 823 __ASM_EMIT("add $0x10, %[dst]") 824 825 // Tail: 1x-3x block 826 __ASM_EMIT("8:") 827 __ASM_EMIT("add $4, %[count]") 828 __ASM_EMIT("jle 16f") 829 __ASM_EMIT("test $1, %[count]") 830 __ASM_EMIT("jz 10f") 831 __ASM_EMIT("vmovss 0x00(%[src]), %%xmm0") 832 __ASM_EMIT("add $4, %[src]") 833 __ASM_EMIT("10:") 834 __ASM_EMIT("test $2, %[count]") 835 __ASM_EMIT("jz 12f") 836 __ASM_EMIT("vmovhps 0x00(%[src]), %%xmm0, %%xmm0") 837 __ASM_EMIT("12:") 838 839 __ASM_EMIT("vmulps %[LOG2E], %%xmm0, %%xmm0") 840 POW2_FMA3_CORE_X4 841 842 __ASM_EMIT("test $1, %[count]") 843 __ASM_EMIT("jz 14f") 844 __ASM_EMIT("vmovss %%xmm0, 0x00(%[dst])") 845 __ASM_EMIT("add $4, %[dst]") 846 __ASM_EMIT("14:") 847 __ASM_EMIT("test $2, %[count]") 848 __ASM_EMIT("jz 16f") 849 __ASM_EMIT("vmovhps %%xmm0, 0x00(%[dst])") 850 851 // End 852 __ASM_EMIT("16:") 853 __ASM_EMIT("vzeroupper") 854 855 : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count) 856 : [E2C] "o" (EXP2_CONST), 857 [LOG2E] "m" (EXP_LOG2E) 858 : "cc", "memory", 859 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", 860 "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" 861 ); 862 } 863 864 } 865 866 #endif /* ARCH_X86_64 */ 867 868 #endif /* DSP_ARCH_X86_AVX2_PMATH_EXP_H_ */ 869