github.com/gopherd/gonum@v0.0.4/internal/asm/f32/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 // func AxpyIncTo(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) 10 TEXT ·AxpyIncTo(SB), NOSPLIT, $0 11 MOVQ n+96(FP), CX // CX = n 12 CMPQ CX, $0 // if n==0 { return } 13 JLE axpyi_end 14 MOVQ dst_base+0(FP), DI // DI = &dst 15 MOVQ x_base+48(FP), SI // SI = &x 16 MOVQ y_base+72(FP), DX // DX = &y 17 MOVQ ix+120(FP), R8 // R8 = ix // Load the first index 18 MOVQ iy+128(FP), R9 // R9 = iy 19 MOVQ idst+32(FP), R10 // R10 = idst 20 LEAQ (SI)(R8*4), SI // SI = &(x[ix]) 21 LEAQ (DX)(R9*4), DX // DX = &(y[iy]) 22 LEAQ (DI)(R10*4), DI // DI = &(dst[idst]) 23 MOVQ incX+104(FP), R8 // R8 = incX 24 SHLQ $2, R8 // R8 *= sizeof(float32) 25 MOVQ incY+112(FP), R9 // R9 = incY 26 SHLQ $2, R9 // R9 *= sizeof(float32) 27 MOVQ incDst+24(FP), R10 // R10 = incDst 28 SHLQ $2, R10 // R10 *= sizeof(float32) 29 MOVSS alpha+40(FP), X0 // X0 = alpha 30 MOVSS X0, X1 // X1 = X0 // for pipelining 31 MOVQ CX, BX 32 ANDQ $3, BX // BX = n % 4 33 SHRQ $2, CX // CX = floor( n / 4 ) 34 JZ axpyi_tail_start // if CX == 0 { goto axpyi_tail_start } 35 36 axpyi_loop: // Loop unrolled 4x do { 37 MOVSS (SI), X2 // X_i = x[i] 38 MOVSS (SI)(R8*1), X3 39 LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) 40 MOVSS (SI), X4 41 MOVSS (SI)(R8*1), X5 42 MULSS X1, X2 // X_i *= a 43 MULSS X0, X3 44 MULSS X1, X4 45 MULSS X0, X5 46 ADDSS (DX), X2 // X_i += y[i] 47 ADDSS (DX)(R9*1), X3 48 LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) 49 ADDSS (DX), X4 50 ADDSS (DX)(R9*1), X5 51 MOVSS X2, (DI) // dst[i] = X_i 52 MOVSS X3, (DI)(R10*1) 53 LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) 54 MOVSS X4, (DI) 55 MOVSS X5, (DI)(R10*1) 56 LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) // Increment addresses 57 LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) 58 LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) 59 LOOP axpyi_loop // } while --CX > 0 60 CMPQ BX, $0 // if BX == 0 { return } 61 JE axpyi_end 62 63 axpyi_tail_start: // Reset loop registers 64 MOVQ BX, CX // Loop counter: CX = BX 65 66 axpyi_tail: // do { 67 MOVSS (SI), X2 // X2 = x[i] 68 MULSS X1, X2 // X2 *= a 69 ADDSS (DX), X2 // X2 += y[i] 70 MOVSS X2, (DI) // dst[i] = X2 71 ADDQ R8, SI // SI = &(SI[incX]) 72 ADDQ R9, DX // DX = &(DX[incY]) 73 ADDQ R10, DI // DI = &(DI[incY]) 74 LOOP axpyi_tail // } while --CX > 0 75 76 axpyi_end: 77 RET 78