github.com/gopherd/gonum@v0.0.4/internal/asm/c128/axpyincto_amd64.s (about) 1 // Copyright ©2016 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build !noasm,!gccgo,!safe 6 7 #include "textflag.h" 8 9 // MOVDDUP X2, X3 10 #define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA 11 // MOVDDUP X4, X5 12 #define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC 13 // MOVDDUP X6, X7 14 #define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE 15 // MOVDDUP X8, X9 16 #define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 17 18 // ADDSUBPD X2, X3 19 #define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA 20 // ADDSUBPD X4, X5 21 #define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC 22 // ADDSUBPD X6, X7 23 #define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE 24 // ADDSUBPD X8, X9 25 #define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 26 27 // func AxpyIncTo(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) 28 TEXT ·AxpyIncTo(SB), NOSPLIT, $0 29 MOVQ dst_base+0(FP), DI // DI = &dst 30 MOVQ x_base+56(FP), SI // SI = &x 31 MOVQ y_base+80(FP), DX // DX = &y 32 MOVQ n+104(FP), CX // CX = n 33 CMPQ CX, $0 // if n==0 { return } 34 JE axpyi_end 35 MOVQ ix+128(FP), R8 // R8 = ix // Load the first index 36 SHLQ $4, R8 // R8 *= sizeof(complex128) 37 MOVQ iy+136(FP), R9 // R9 = iy 38 SHLQ $4, R9 // R9 *= sizeof(complex128) 39 MOVQ idst+32(FP), R10 // R10 = idst 40 SHLQ $4, R10 // R10 *= sizeof(complex128) 41 LEAQ (SI)(R8*1), SI // SI = &(x[ix]) 42 LEAQ (DX)(R9*1), DX // DX = &(y[iy]) 43 LEAQ (DI)(R10*1), DI // DI = &(dst[idst]) 44 MOVQ incX+112(FP), R8 // R8 = incX 45 SHLQ $4, R8 // R8 *= sizeof(complex128) 46 MOVQ incY+120(FP), R9 // R9 = incY 47 SHLQ $4, R9 // R9 *= sizeof(complex128) 48 MOVQ incDst+24(FP), R10 // R10 = incDst 49 SHLQ $4, R10 // R10 *= sizeof(complex128) 50 MOVUPS alpha+40(FP), X0 // X0 = { imag(a), real(a) } 51 MOVAPS X0, X1 52 SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } 53 MOVAPS X0, X10 // Copy X0 and X1 for pipelining 54 MOVAPS X1, X11 55 MOVQ CX, BX 56 ANDQ $3, CX // CX = n % 4 57 SHRQ $2, BX // BX = floor( n / 4 ) 58 JZ axpyi_tail // if BX == 0 { goto axpyi_tail } 59 60 axpyi_loop: // do { 61 MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } 62 MOVUPS (SI)(R8*1), X4 63 LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) 64 65 MOVUPS (SI), X6 66 MOVUPS (SI)(R8*1), X8 67 68 // X_(i+1) = { real(x[i], real(x[i]) } 69 MOVDDUP_X2_X3 70 MOVDDUP_X4_X5 71 MOVDDUP_X6_X7 72 MOVDDUP_X8_X9 73 74 // X_i = { imag(x[i]), imag(x[i]) } 75 SHUFPD $0x3, X2, X2 76 SHUFPD $0x3, X4, X4 77 SHUFPD $0x3, X6, X6 78 SHUFPD $0x3, X8, X8 79 80 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } 81 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } 82 MULPD X1, X2 83 MULPD X0, X3 84 MULPD X11, X4 85 MULPD X10, X5 86 MULPD X1, X6 87 MULPD X0, X7 88 MULPD X11, X8 89 MULPD X10, X9 90 91 // X_(i+1) = { 92 // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), 93 // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) 94 // } 95 ADDSUBPD_X2_X3 96 ADDSUBPD_X4_X5 97 ADDSUBPD_X6_X7 98 ADDSUBPD_X8_X9 99 100 // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } 101 ADDPD (DX), X3 102 ADDPD (DX)(R9*1), X5 103 LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) 104 ADDPD (DX), X7 105 ADDPD (DX)(R9*1), X9 106 MOVUPS X3, (DI) // dst[i] = X_(i+1) 107 MOVUPS X5, (DI)(R10*1) 108 LEAQ (DI)(R10*2), DI 109 MOVUPS X7, (DI) 110 MOVUPS X9, (DI)(R10*1) 111 LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) 112 LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) 113 LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) 114 DECQ BX 115 JNZ axpyi_loop // } while --BX > 0 116 CMPQ CX, $0 // if CX == 0 { return } 117 JE axpyi_end 118 119 axpyi_tail: // do { 120 MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } 121 MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } 122 SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } 123 MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } 124 MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } 125 126 // X_(i+1) = { 127 // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), 128 // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) 129 // } 130 ADDSUBPD_X2_X3 131 132 // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } 133 ADDPD (DX), X3 134 MOVUPS X3, (DI) // y[i] X_(i+1) 135 ADDQ R8, SI // SI += incX 136 ADDQ R9, DX // DX += incY 137 ADDQ R10, DI // DI += incDst 138 LOOP axpyi_tail // } while --CX > 0 139 140 axpyi_end: 141 RET