github.com/gopherd/gonum@v0.0.4/internal/asm/f64/ger_amd64.s (about)

     1  // Copyright ©2017 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  #define SIZE 8
    10  
    11  #define M_DIM m+0(FP)
    12  #define M CX
    13  #define N_DIM n+8(FP)
    14  #define N BX
    15  
    16  #define TMP1 R14
    17  #define TMP2 R15
    18  
    19  #define X_PTR SI
    20  #define Y y_base+56(FP)
    21  #define Y_PTR DX
    22  #define A_ROW AX
    23  #define A_PTR DI
    24  
    25  #define INC_X R8
    26  #define INC3_X R9
    27  
    28  #define INC_Y R10
    29  #define INC3_Y R11
    30  
    31  #define LDA R12
    32  #define LDA3 R13
    33  
    34  #define ALPHA X0
    35  
    36  #define LOAD4 \
    37  	PREFETCHNTA (X_PTR )(INC_X*8)     \
    38  	MOVDDUP     (X_PTR), X1           \
    39  	MOVDDUP     (X_PTR)(INC_X*1), X2  \
    40  	MOVDDUP     (X_PTR)(INC_X*2), X3  \
    41  	MOVDDUP     (X_PTR)(INC3_X*1), X4 \
    42  	MULPD       ALPHA, X1             \
    43  	MULPD       ALPHA, X2             \
    44  	MULPD       ALPHA, X3             \
    45  	MULPD       ALPHA, X4
    46  
    47  #define LOAD2 \
    48  	MOVDDUP (X_PTR), X1          \
    49  	MOVDDUP (X_PTR)(INC_X*1), X2 \
    50  	MULPD   ALPHA, X1            \
    51  	MULPD   ALPHA, X2
    52  
    53  #define LOAD1 \
    54  	MOVDDUP (X_PTR), X1 \
    55  	MULPD   ALPHA, X1
    56  
    57  #define KERNEL_LOAD4 \
    58  	MOVUPS (Y_PTR), X5       \
    59  	MOVUPS 2*SIZE(Y_PTR), X6
    60  
    61  #define KERNEL_LOAD4_INC \
    62  	MOVLPD (Y_PTR), X5           \
    63  	MOVHPD (Y_PTR)(INC_Y*1), X5  \
    64  	MOVLPD (Y_PTR)(INC_Y*2), X6  \
    65  	MOVHPD (Y_PTR)(INC3_Y*1), X6
    66  
    67  #define KERNEL_LOAD2 \
    68  	MOVUPS (Y_PTR), X5
    69  
    70  #define KERNEL_LOAD2_INC \
    71  	MOVLPD (Y_PTR), X5          \
    72  	MOVHPD (Y_PTR)(INC_Y*1), X5
    73  
    74  #define KERNEL_4x4 \
    75  	MOVUPS X5, X7  \
    76  	MOVUPS X6, X8  \
    77  	MOVUPS X5, X9  \
    78  	MOVUPS X6, X10 \
    79  	MOVUPS X5, X11 \
    80  	MOVUPS X6, X12 \
    81  	MULPD  X1, X5  \
    82  	MULPD  X1, X6  \
    83  	MULPD  X2, X7  \
    84  	MULPD  X2, X8  \
    85  	MULPD  X3, X9  \
    86  	MULPD  X3, X10 \
    87  	MULPD  X4, X11 \
    88  	MULPD  X4, X12
    89  
    90  #define STORE_4x4 \
    91  	MOVUPS (A_PTR), X13               \
    92  	ADDPD  X13, X5                    \
    93  	MOVUPS 2*SIZE(A_PTR), X14         \
    94  	ADDPD  X14, X6                    \
    95  	MOVUPS (A_PTR)(LDA*1), X15        \
    96  	ADDPD  X15, X7                    \
    97  	MOVUPS 2*SIZE(A_PTR)(LDA*1), X0   \
    98  	ADDPD  X0, X8                     \
    99  	MOVUPS (A_PTR)(LDA*2), X13        \
   100  	ADDPD  X13, X9                    \
   101  	MOVUPS 2*SIZE(A_PTR)(LDA*2), X14  \
   102  	ADDPD  X14, X10                   \
   103  	MOVUPS (A_PTR)(LDA3*1), X15       \
   104  	ADDPD  X15, X11                   \
   105  	MOVUPS 2*SIZE(A_PTR)(LDA3*1), X0  \
   106  	ADDPD  X0, X12                    \
   107  	MOVUPS X5, (A_PTR)                \
   108  	MOVUPS X6, 2*SIZE(A_PTR)          \
   109  	MOVUPS X7, (A_PTR)(LDA*1)         \
   110  	MOVUPS X8, 2*SIZE(A_PTR)(LDA*1)   \
   111  	MOVUPS X9, (A_PTR)(LDA*2)         \
   112  	MOVUPS X10, 2*SIZE(A_PTR)(LDA*2)  \
   113  	MOVUPS X11, (A_PTR)(LDA3*1)       \
   114  	MOVUPS X12, 2*SIZE(A_PTR)(LDA3*1) \
   115  	ADDQ   $4*SIZE, A_PTR
   116  
   117  #define KERNEL_4x2 \
   118  	MOVUPS X5, X6 \
   119  	MOVUPS X5, X7 \
   120  	MOVUPS X5, X8 \
   121  	MULPD  X1, X5 \
   122  	MULPD  X2, X6 \
   123  	MULPD  X3, X7 \
   124  	MULPD  X4, X8
   125  
   126  #define STORE_4x2 \
   127  	MOVUPS (A_PTR), X9          \
   128  	ADDPD  X9, X5               \
   129  	MOVUPS (A_PTR)(LDA*1), X10  \
   130  	ADDPD  X10, X6              \
   131  	MOVUPS (A_PTR)(LDA*2), X11  \
   132  	ADDPD  X11, X7              \
   133  	MOVUPS (A_PTR)(LDA3*1), X12 \
   134  	ADDPD  X12, X8              \
   135  	MOVUPS X5, (A_PTR)          \
   136  	MOVUPS X6, (A_PTR)(LDA*1)   \
   137  	MOVUPS X7, (A_PTR)(LDA*2)   \
   138  	MOVUPS X8, (A_PTR)(LDA3*1)  \
   139  	ADDQ   $2*SIZE, A_PTR
   140  
   141  #define KERNEL_4x1 \
   142  	MOVSD (Y_PTR), X5 \
   143  	MOVSD X5, X6      \
   144  	MOVSD X5, X7      \
   145  	MOVSD X5, X8      \
   146  	MULSD X1, X5      \
   147  	MULSD X2, X6      \
   148  	MULSD X3, X7      \
   149  	MULSD X4, X8
   150  
   151  #define STORE_4x1 \
   152  	ADDSD (A_PTR), X5         \
   153  	ADDSD (A_PTR)(LDA*1), X6  \
   154  	ADDSD (A_PTR)(LDA*2), X7  \
   155  	ADDSD (A_PTR)(LDA3*1), X8 \
   156  	MOVSD X5, (A_PTR)         \
   157  	MOVSD X6, (A_PTR)(LDA*1)  \
   158  	MOVSD X7, (A_PTR)(LDA*2)  \
   159  	MOVSD X8, (A_PTR)(LDA3*1) \
   160  	ADDQ  $SIZE, A_PTR
   161  
   162  #define KERNEL_2x4 \
   163  	MOVUPS X5, X7 \
   164  	MOVUPS X6, X8 \
   165  	MULPD  X1, X5 \
   166  	MULPD  X1, X6 \
   167  	MULPD  X2, X7 \
   168  	MULPD  X2, X8
   169  
   170  #define STORE_2x4 \
   171  	MOVUPS (A_PTR), X9               \
   172  	ADDPD  X9, X5                    \
   173  	MOVUPS 2*SIZE(A_PTR), X10        \
   174  	ADDPD  X10, X6                   \
   175  	MOVUPS (A_PTR)(LDA*1), X11       \
   176  	ADDPD  X11, X7                   \
   177  	MOVUPS 2*SIZE(A_PTR)(LDA*1), X12 \
   178  	ADDPD  X12, X8                   \
   179  	MOVUPS X5, (A_PTR)               \
   180  	MOVUPS X6, 2*SIZE(A_PTR)         \
   181  	MOVUPS X7, (A_PTR)(LDA*1)        \
   182  	MOVUPS X8, 2*SIZE(A_PTR)(LDA*1)  \
   183  	ADDQ   $4*SIZE, A_PTR
   184  
   185  #define KERNEL_2x2 \
   186  	MOVUPS X5, X6 \
   187  	MULPD  X1, X5 \
   188  	MULPD  X2, X6
   189  
   190  #define STORE_2x2 \
   191  	MOVUPS (A_PTR), X7        \
   192  	ADDPD  X7, X5             \
   193  	MOVUPS (A_PTR)(LDA*1), X8 \
   194  	ADDPD  X8, X6             \
   195  	MOVUPS X5, (A_PTR)        \
   196  	MOVUPS X6, (A_PTR)(LDA*1) \
   197  	ADDQ   $2*SIZE, A_PTR
   198  
   199  #define KERNEL_2x1 \
   200  	MOVSD (Y_PTR), X5 \
   201  	MOVSD X5, X6      \
   202  	MULSD X1, X5      \
   203  	MULSD X2, X6
   204  
   205  #define STORE_2x1 \
   206  	ADDSD (A_PTR), X5        \
   207  	ADDSD (A_PTR)(LDA*1), X6 \
   208  	MOVSD X5, (A_PTR)        \
   209  	MOVSD X6, (A_PTR)(LDA*1) \
   210  	ADDQ  $SIZE, A_PTR
   211  
   212  #define KERNEL_1x4 \
   213  	MULPD X1, X5 \
   214  	MULPD X1, X6
   215  
   216  #define STORE_1x4 \
   217  	MOVUPS (A_PTR), X7       \
   218  	ADDPD  X7, X5            \
   219  	MOVUPS 2*SIZE(A_PTR), X8 \
   220  	ADDPD  X8, X6            \
   221  	MOVUPS X5, (A_PTR)       \
   222  	MOVUPS X6, 2*SIZE(A_PTR) \
   223  	ADDQ   $4*SIZE, A_PTR
   224  
   225  #define KERNEL_1x2 \
   226  	MULPD X1, X5
   227  
   228  #define STORE_1x2 \
   229  	MOVUPS (A_PTR), X6    \
   230  	ADDPD  X6, X5         \
   231  	MOVUPS X5, (A_PTR)    \
   232  	ADDQ   $2*SIZE, A_PTR
   233  
   234  #define KERNEL_1x1 \
   235  	MOVSD (Y_PTR), X5 \
   236  	MULSD X1, X5
   237  
   238  #define STORE_1x1 \
   239  	ADDSD (A_PTR), X5  \
   240  	MOVSD X5, (A_PTR)  \
   241  	ADDQ  $SIZE, A_PTR
   242  
   243  // func Ger(m, n uintptr, alpha float64,
   244  //	x []float64, incX uintptr,
   245  //	y []float64, incY uintptr,
   246  //	a []float64, lda uintptr)
   247  TEXT ·Ger(SB), NOSPLIT, $0
   248  	MOVQ M_DIM, M
   249  	MOVQ N_DIM, N
   250  	CMPQ M, $0
   251  	JE   end
   252  	CMPQ N, $0
   253  	JE   end
   254  
   255  	MOVDDUP alpha+16(FP), ALPHA
   256  
   257  	MOVQ x_base+24(FP), X_PTR
   258  	MOVQ y_base+56(FP), Y_PTR
   259  	MOVQ a_base+88(FP), A_ROW
   260  	MOVQ incX+48(FP), INC_X       // INC_X = incX * sizeof(float64)
   261  	SHLQ $3, INC_X
   262  	MOVQ lda+112(FP), LDA         // LDA = LDA * sizeof(float64)
   263  	SHLQ $3, LDA
   264  	LEAQ (LDA)(LDA*2), LDA3       // LDA3 = LDA * 3
   265  	LEAQ (INC_X)(INC_X*2), INC3_X // INC3_X = INC_X * 3
   266  	MOVQ A_ROW, A_PTR
   267  
   268  	XORQ    TMP2, TMP2
   269  	MOVQ    M, TMP1
   270  	SUBQ    $1, TMP1
   271  	IMULQ   INC_X, TMP1
   272  	NEGQ    TMP1
   273  	CMPQ    INC_X, $0
   274  	CMOVQLT TMP1, TMP2
   275  	LEAQ    (X_PTR)(TMP2*SIZE), X_PTR
   276  
   277  	CMPQ incY+80(FP), $1 // Check for dense vector Y (fast-path)
   278  	JG   inc
   279  	JL   end
   280  
   281  	SHRQ $2, M
   282  	JZ   r2
   283  
   284  r4:
   285  	// LOAD 4
   286  	LOAD4
   287  
   288  	MOVQ N_DIM, N
   289  	SHRQ $2, N
   290  	JZ   r4c2
   291  
   292  r4c4:
   293  	// 4x4 KERNEL
   294  	KERNEL_LOAD4
   295  	KERNEL_4x4
   296  	STORE_4x4
   297  
   298  	ADDQ $4*SIZE, Y_PTR
   299  
   300  	DECQ N
   301  	JNZ  r4c4
   302  
   303  	// Reload ALPHA after it's clobbered by STORE_4x4
   304  	MOVDDUP alpha+16(FP), ALPHA
   305  
   306  r4c2:
   307  	TESTQ $2, N_DIM
   308  	JZ    r4c1
   309  
   310  	// 4x2 KERNEL
   311  	KERNEL_LOAD2
   312  	KERNEL_4x2
   313  	STORE_4x2
   314  
   315  	ADDQ $2*SIZE, Y_PTR
   316  
   317  r4c1:
   318  	TESTQ $1, N_DIM
   319  	JZ    r4end
   320  
   321  	// 4x1 KERNEL
   322  	KERNEL_4x1
   323  	STORE_4x1
   324  
   325  	ADDQ $SIZE, Y_PTR
   326  
   327  r4end:
   328  	LEAQ (X_PTR)(INC_X*4), X_PTR
   329  	MOVQ Y, Y_PTR
   330  	LEAQ (A_ROW)(LDA*4), A_ROW
   331  	MOVQ A_ROW, A_PTR
   332  
   333  	DECQ M
   334  	JNZ  r4
   335  
   336  r2:
   337  	TESTQ $2, M_DIM
   338  	JZ    r1
   339  
   340  	// LOAD 2
   341  	LOAD2
   342  
   343  	MOVQ N_DIM, N
   344  	SHRQ $2, N
   345  	JZ   r2c2
   346  
   347  r2c4:
   348  	// 2x4 KERNEL
   349  	KERNEL_LOAD4
   350  	KERNEL_2x4
   351  	STORE_2x4
   352  
   353  	ADDQ $4*SIZE, Y_PTR
   354  
   355  	DECQ N
   356  	JNZ  r2c4
   357  
   358  r2c2:
   359  	TESTQ $2, N_DIM
   360  	JZ    r2c1
   361  
   362  	// 2x2 KERNEL
   363  	KERNEL_LOAD2
   364  	KERNEL_2x2
   365  	STORE_2x2
   366  
   367  	ADDQ $2*SIZE, Y_PTR
   368  
   369  r2c1:
   370  	TESTQ $1, N_DIM
   371  	JZ    r2end
   372  
   373  	// 2x1 KERNEL
   374  	KERNEL_2x1
   375  	STORE_2x1
   376  
   377  	ADDQ $SIZE, Y_PTR
   378  
   379  r2end:
   380  	LEAQ (X_PTR)(INC_X*2), X_PTR
   381  	MOVQ Y, Y_PTR
   382  	LEAQ (A_ROW)(LDA*2), A_ROW
   383  	MOVQ A_ROW, A_PTR
   384  
   385  r1:
   386  	TESTQ $1, M_DIM
   387  	JZ    end
   388  
   389  	// LOAD 1
   390  	LOAD1
   391  
   392  	MOVQ N_DIM, N
   393  	SHRQ $2, N
   394  	JZ   r1c2
   395  
   396  r1c4:
   397  	// 1x4 KERNEL
   398  	KERNEL_LOAD4
   399  	KERNEL_1x4
   400  	STORE_1x4
   401  
   402  	ADDQ $4*SIZE, Y_PTR
   403  
   404  	DECQ N
   405  	JNZ  r1c4
   406  
   407  r1c2:
   408  	TESTQ $2, N_DIM
   409  	JZ    r1c1
   410  
   411  	// 1x2 KERNEL
   412  	KERNEL_LOAD2
   413  	KERNEL_1x2
   414  	STORE_1x2
   415  
   416  	ADDQ $2*SIZE, Y_PTR
   417  
   418  r1c1:
   419  	TESTQ $1, N_DIM
   420  	JZ    end
   421  
   422  	// 1x1 KERNEL
   423  	KERNEL_1x1
   424  	STORE_1x1
   425  
   426  	ADDQ $SIZE, Y_PTR
   427  
   428  end:
   429  	RET
   430  
   431  inc:  // Algorithm for incY != 1 ( split loads in kernel )
   432  
   433  	MOVQ incY+80(FP), INC_Y       // INC_Y = incY * sizeof(float64)
   434  	SHLQ $3, INC_Y
   435  	LEAQ (INC_Y)(INC_Y*2), INC3_Y // INC3_Y = INC_Y * 3
   436  
   437  	XORQ    TMP2, TMP2
   438  	MOVQ    N, TMP1
   439  	SUBQ    $1, TMP1
   440  	IMULQ   INC_Y, TMP1
   441  	NEGQ    TMP1
   442  	CMPQ    INC_Y, $0
   443  	CMOVQLT TMP1, TMP2
   444  	LEAQ    (Y_PTR)(TMP2*SIZE), Y_PTR
   445  
   446  	SHRQ $2, M
   447  	JZ   inc_r2
   448  
   449  inc_r4:
   450  	// LOAD 4
   451  	LOAD4
   452  
   453  	MOVQ N_DIM, N
   454  	SHRQ $2, N
   455  	JZ   inc_r4c2
   456  
   457  inc_r4c4:
   458  	// 4x4 KERNEL
   459  	KERNEL_LOAD4_INC
   460  	KERNEL_4x4
   461  	STORE_4x4
   462  
   463  	LEAQ (Y_PTR)(INC_Y*4), Y_PTR
   464  	DECQ N
   465  	JNZ  inc_r4c4
   466  
   467  	// Reload ALPHA after it's clobbered by STORE_4x4
   468  	MOVDDUP alpha+16(FP), ALPHA
   469  
   470  inc_r4c2:
   471  	TESTQ $2, N_DIM
   472  	JZ    inc_r4c1
   473  
   474  	// 4x2 KERNEL
   475  	KERNEL_LOAD2_INC
   476  	KERNEL_4x2
   477  	STORE_4x2
   478  
   479  	LEAQ (Y_PTR)(INC_Y*2), Y_PTR
   480  
   481  inc_r4c1:
   482  	TESTQ $1, N_DIM
   483  	JZ    inc_r4end
   484  
   485  	// 4x1 KERNEL
   486  	KERNEL_4x1
   487  	STORE_4x1
   488  
   489  	ADDQ INC_Y, Y_PTR
   490  
   491  inc_r4end:
   492  	LEAQ (X_PTR)(INC_X*4), X_PTR
   493  	MOVQ Y, Y_PTR
   494  	LEAQ (A_ROW)(LDA*4), A_ROW
   495  	MOVQ A_ROW, A_PTR
   496  
   497  	DECQ M
   498  	JNZ  inc_r4
   499  
   500  inc_r2:
   501  	TESTQ $2, M_DIM
   502  	JZ    inc_r1
   503  
   504  	// LOAD 2
   505  	LOAD2
   506  
   507  	MOVQ N_DIM, N
   508  	SHRQ $2, N
   509  	JZ   inc_r2c2
   510  
   511  inc_r2c4:
   512  	// 2x4 KERNEL
   513  	KERNEL_LOAD4_INC
   514  	KERNEL_2x4
   515  	STORE_2x4
   516  
   517  	LEAQ (Y_PTR)(INC_Y*4), Y_PTR
   518  	DECQ N
   519  	JNZ  inc_r2c4
   520  
   521  inc_r2c2:
   522  	TESTQ $2, N_DIM
   523  	JZ    inc_r2c1
   524  
   525  	// 2x2 KERNEL
   526  	KERNEL_LOAD2_INC
   527  	KERNEL_2x2
   528  	STORE_2x2
   529  
   530  	LEAQ (Y_PTR)(INC_Y*2), Y_PTR
   531  
   532  inc_r2c1:
   533  	TESTQ $1, N_DIM
   534  	JZ    inc_r2end
   535  
   536  	// 2x1 KERNEL
   537  	KERNEL_2x1
   538  	STORE_2x1
   539  
   540  	ADDQ INC_Y, Y_PTR
   541  
   542  inc_r2end:
   543  	LEAQ (X_PTR)(INC_X*2), X_PTR
   544  	MOVQ Y, Y_PTR
   545  	LEAQ (A_ROW)(LDA*2), A_ROW
   546  	MOVQ A_ROW, A_PTR
   547  
   548  inc_r1:
   549  	TESTQ $1, M_DIM
   550  	JZ    end
   551  
   552  	// LOAD 1
   553  	LOAD1
   554  
   555  	MOVQ N_DIM, N
   556  	SHRQ $2, N
   557  	JZ   inc_r1c2
   558  
   559  inc_r1c4:
   560  	// 1x4 KERNEL
   561  	KERNEL_LOAD4_INC
   562  	KERNEL_1x4
   563  	STORE_1x4
   564  
   565  	LEAQ (Y_PTR)(INC_Y*4), Y_PTR
   566  	DECQ N
   567  	JNZ  inc_r1c4
   568  
   569  inc_r1c2:
   570  	TESTQ $2, N_DIM
   571  	JZ    inc_r1c1
   572  
   573  	// 1x2 KERNEL
   574  	KERNEL_LOAD2_INC
   575  	KERNEL_1x2
   576  	STORE_1x2
   577  
   578  	LEAQ (Y_PTR)(INC_Y*2), Y_PTR
   579  
   580  inc_r1c1:
   581  	TESTQ $1, N_DIM
   582  	JZ    end
   583  
   584  	// 1x1 KERNEL
   585  	KERNEL_1x1
   586  	STORE_1x1
   587  
   588  	ADDQ INC_Y, Y_PTR
   589  
   590  inc_end:
   591  	RET