gonum.org/v1/gonum@v0.14.0/internal/asm/c128/axpyunitary_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 AxpyUnitary(alpha complex128, x, y []complex128)
    28  TEXT ·AxpyUnitary(SB), NOSPLIT, $0
    29  	MOVQ    x_base+16(FP), SI // SI = &x
    30  	MOVQ    y_base+40(FP), DI // DI = &y
    31  	MOVQ    x_len+24(FP), CX  // CX = min( len(x), len(y) )
    32  	CMPQ    y_len+48(FP), CX
    33  	CMOVQLE y_len+48(FP), CX
    34  	CMPQ    CX, $0            // if CX == 0 { return }
    35  	JE      caxy_end
    36  	PXOR    X0, X0            // Clear work registers and cache-align loop
    37  	PXOR    X1, X1
    38  	MOVUPS  alpha+0(FP), X0   // X0 = { imag(a), real(a) }
    39  	MOVAPS  X0, X1
    40  	SHUFPD  $0x1, X1, X1      // X1 = { real(a), imag(a) }
    41  	XORQ    AX, AX            // i = 0
    42  	MOVAPS  X0, X10           // Copy X0 and X1 for pipelining
    43  	MOVAPS  X1, X11
    44  	MOVQ    CX, BX
    45  	ANDQ    $3, CX            // CX = n % 4
    46  	SHRQ    $2, BX            // BX = floor( n / 4 )
    47  	JZ      caxy_tail         // if BX == 0 { goto caxy_tail }
    48  
    49  caxy_loop: // do {
    50  	MOVUPS (SI)(AX*8), X2   // X_i = { imag(x[i]), real(x[i]) }
    51  	MOVUPS 16(SI)(AX*8), X4
    52  	MOVUPS 32(SI)(AX*8), X6
    53  	MOVUPS 48(SI)(AX*8), X8
    54  
    55  	// X_(i+1) = { real(x[i], real(x[i]) }
    56  	MOVDDUP_X2_X3
    57  	MOVDDUP_X4_X5
    58  	MOVDDUP_X6_X7
    59  	MOVDDUP_X8_X9
    60  
    61  	// X_i = { imag(x[i]), imag(x[i]) }
    62  	SHUFPD $0x3, X2, X2
    63  	SHUFPD $0x3, X4, X4
    64  	SHUFPD $0x3, X6, X6
    65  	SHUFPD $0x3, X8, X8
    66  
    67  	// X_i     = { real(a) * imag(x[i]), imag(a) * imag(x[i])  }
    68  	// X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i])  }
    69  	MULPD X1, X2
    70  	MULPD X0, X3
    71  	MULPD X11, X4
    72  	MULPD X10, X5
    73  	MULPD X1, X6
    74  	MULPD X0, X7
    75  	MULPD X11, X8
    76  	MULPD X10, X9
    77  
    78  	// X_(i+1) = {
    79  	//	imag(result[i]):  imag(a)*real(x[i]) + real(a)*imag(x[i]),
    80  	//	real(result[i]):  real(a)*real(x[i]) - imag(a)*imag(x[i])
    81  	//  }
    82  	ADDSUBPD_X2_X3
    83  	ADDSUBPD_X4_X5
    84  	ADDSUBPD_X6_X7
    85  	ADDSUBPD_X8_X9
    86  
    87  	// X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) }
    88  	ADDPD  (DI)(AX*8), X3
    89  	ADDPD  16(DI)(AX*8), X5
    90  	ADDPD  32(DI)(AX*8), X7
    91  	ADDPD  48(DI)(AX*8), X9
    92  	MOVUPS X3, (DI)(AX*8)   // y[i] = X_(i+1)
    93  	MOVUPS X5, 16(DI)(AX*8)
    94  	MOVUPS X7, 32(DI)(AX*8)
    95  	MOVUPS X9, 48(DI)(AX*8)
    96  	ADDQ   $8, AX           // i += 8
    97  	DECQ   BX
    98  	JNZ    caxy_loop        // } while --BX > 0
    99  	CMPQ   CX, $0           // if CX == 0 { return }
   100  	JE     caxy_end
   101  
   102  caxy_tail: // do {
   103  	MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) }
   104  	MOVDDUP_X2_X3         // X_(i+1) = { real(x[i], real(x[i]) }
   105  	SHUFPD $0x3, X2, X2   // X_i = { imag(x[i]), imag(x[i]) }
   106  	MULPD  X1, X2         // X_i     = { real(a) * imag(x[i]), imag(a) * imag(x[i])  }
   107  	MULPD  X0, X3         // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i])  }
   108  
   109  	// X_(i+1) = {
   110  	//	imag(result[i]):  imag(a)*real(x[i]) + real(a)*imag(x[i]),
   111  	//	real(result[i]):  real(a)*real(x[i]) - imag(a)*imag(x[i])
   112  	//  }
   113  	ADDSUBPD_X2_X3
   114  
   115  	// X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) }
   116  	ADDPD  (DI)(AX*8), X3
   117  	MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1)
   118  	ADDQ   $2, AX         // i += 2
   119  	LOOP   caxy_tail      // }  while --CX > 0
   120  
   121  caxy_end:
   122  	RET