github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-761/fr/element_mul_amd64.s (about)

     1  // +build !purego
     2  
     3  // Copyright 2020 ConsenSys Software Inc.
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  #include "textflag.h"
    18  #include "funcdata.h"
    19  
    20  // modulus q
    21  DATA q<>+0(SB)/8, $0x8508c00000000001
    22  DATA q<>+8(SB)/8, $0x170b5d4430000000
    23  DATA q<>+16(SB)/8, $0x1ef3622fba094800
    24  DATA q<>+24(SB)/8, $0x1a22d9f300f5138f
    25  DATA q<>+32(SB)/8, $0xc63b05c06ca1493b
    26  DATA q<>+40(SB)/8, $0x01ae3a4617c510ea
    27  GLOBL q<>(SB), (RODATA+NOPTR), $48
    28  
    29  // qInv0 q'[0]
    30  DATA qInv0<>(SB)/8, $0x8508bfffffffffff
    31  GLOBL qInv0<>(SB), (RODATA+NOPTR), $8
    32  
    33  #define REDUCE(ra0, ra1, ra2, ra3, ra4, ra5, rb0, rb1, rb2, rb3, rb4, rb5) \
    34  	MOVQ    ra0, rb0;        \
    35  	SUBQ    q<>(SB), ra0;    \
    36  	MOVQ    ra1, rb1;        \
    37  	SBBQ    q<>+8(SB), ra1;  \
    38  	MOVQ    ra2, rb2;        \
    39  	SBBQ    q<>+16(SB), ra2; \
    40  	MOVQ    ra3, rb3;        \
    41  	SBBQ    q<>+24(SB), ra3; \
    42  	MOVQ    ra4, rb4;        \
    43  	SBBQ    q<>+32(SB), ra4; \
    44  	MOVQ    ra5, rb5;        \
    45  	SBBQ    q<>+40(SB), ra5; \
    46  	CMOVQCS rb0, ra0;        \
    47  	CMOVQCS rb1, ra1;        \
    48  	CMOVQCS rb2, ra2;        \
    49  	CMOVQCS rb3, ra3;        \
    50  	CMOVQCS rb4, ra4;        \
    51  	CMOVQCS rb5, ra5;        \
    52  
    53  // mul(res, x, y *Element)
    54  TEXT ·mul(SB), $24-24
    55  
    56  	// the algorithm is described in the Element.Mul declaration (.go)
    57  	// however, to benefit from the ADCX and ADOX carry chains
    58  	// we split the inner loops in 2:
    59  	// for i=0 to N-1
    60  	// 		for j=0 to N-1
    61  	// 		    (A,t[j])  := t[j] + x[j]*y[i] + A
    62  	// 		m := t[0]*q'[0] mod W
    63  	// 		C,_ := t[0] + m*q[0]
    64  	// 		for j=1 to N-1
    65  	// 		    (C,t[j-1]) := t[j] + m*q[j] + C
    66  	// 		t[N-1] = C + A
    67  
    68  	NO_LOCAL_POINTERS
    69  	CMPB ·supportAdx(SB), $1
    70  	JNE  l1
    71  	MOVQ x+8(FP), R8
    72  
    73  	// x[0] -> R10
    74  	// x[1] -> R11
    75  	// x[2] -> R12
    76  	MOVQ 0(R8), R10
    77  	MOVQ 8(R8), R11
    78  	MOVQ 16(R8), R12
    79  	MOVQ y+16(FP), R13
    80  
    81  	// A -> BP
    82  	// t[0] -> R14
    83  	// t[1] -> R15
    84  	// t[2] -> CX
    85  	// t[3] -> BX
    86  	// t[4] -> SI
    87  	// t[5] -> DI
    88  	// clear the flags
    89  	XORQ AX, AX
    90  	MOVQ 0(R13), DX
    91  
    92  	// (A,t[0])  := x[0]*y[0] + A
    93  	MULXQ R10, R14, R15
    94  
    95  	// (A,t[1])  := x[1]*y[0] + A
    96  	MULXQ R11, AX, CX
    97  	ADOXQ AX, R15
    98  
    99  	// (A,t[2])  := x[2]*y[0] + A
   100  	MULXQ R12, AX, BX
   101  	ADOXQ AX, CX
   102  
   103  	// (A,t[3])  := x[3]*y[0] + A
   104  	MULXQ 24(R8), AX, SI
   105  	ADOXQ AX, BX
   106  
   107  	// (A,t[4])  := x[4]*y[0] + A
   108  	MULXQ 32(R8), AX, DI
   109  	ADOXQ AX, SI
   110  
   111  	// (A,t[5])  := x[5]*y[0] + A
   112  	MULXQ 40(R8), AX, BP
   113  	ADOXQ AX, DI
   114  
   115  	// A += carries from ADCXQ and ADOXQ
   116  	MOVQ  $0, AX
   117  	ADOXQ AX, BP
   118  
   119  	// m := t[0]*q'[0] mod W
   120  	MOVQ  qInv0<>(SB), DX
   121  	IMULQ R14, DX
   122  
   123  	// clear the flags
   124  	XORQ AX, AX
   125  
   126  	// C,_ := t[0] + m*q[0]
   127  	MULXQ q<>+0(SB), AX, R9
   128  	ADCXQ R14, AX
   129  	MOVQ  R9, R14
   130  
   131  	// (C,t[0]) := t[1] + m*q[1] + C
   132  	ADCXQ R15, R14
   133  	MULXQ q<>+8(SB), AX, R15
   134  	ADOXQ AX, R14
   135  
   136  	// (C,t[1]) := t[2] + m*q[2] + C
   137  	ADCXQ CX, R15
   138  	MULXQ q<>+16(SB), AX, CX
   139  	ADOXQ AX, R15
   140  
   141  	// (C,t[2]) := t[3] + m*q[3] + C
   142  	ADCXQ BX, CX
   143  	MULXQ q<>+24(SB), AX, BX
   144  	ADOXQ AX, CX
   145  
   146  	// (C,t[3]) := t[4] + m*q[4] + C
   147  	ADCXQ SI, BX
   148  	MULXQ q<>+32(SB), AX, SI
   149  	ADOXQ AX, BX
   150  
   151  	// (C,t[4]) := t[5] + m*q[5] + C
   152  	ADCXQ DI, SI
   153  	MULXQ q<>+40(SB), AX, DI
   154  	ADOXQ AX, SI
   155  
   156  	// t[5] = C + A
   157  	MOVQ  $0, AX
   158  	ADCXQ AX, DI
   159  	ADOXQ BP, DI
   160  
   161  	// clear the flags
   162  	XORQ AX, AX
   163  	MOVQ 8(R13), DX
   164  
   165  	// (A,t[0])  := t[0] + x[0]*y[1] + A
   166  	MULXQ R10, AX, BP
   167  	ADOXQ AX, R14
   168  
   169  	// (A,t[1])  := t[1] + x[1]*y[1] + A
   170  	ADCXQ BP, R15
   171  	MULXQ R11, AX, BP
   172  	ADOXQ AX, R15
   173  
   174  	// (A,t[2])  := t[2] + x[2]*y[1] + A
   175  	ADCXQ BP, CX
   176  	MULXQ R12, AX, BP
   177  	ADOXQ AX, CX
   178  
   179  	// (A,t[3])  := t[3] + x[3]*y[1] + A
   180  	ADCXQ BP, BX
   181  	MULXQ 24(R8), AX, BP
   182  	ADOXQ AX, BX
   183  
   184  	// (A,t[4])  := t[4] + x[4]*y[1] + A
   185  	ADCXQ BP, SI
   186  	MULXQ 32(R8), AX, BP
   187  	ADOXQ AX, SI
   188  
   189  	// (A,t[5])  := t[5] + x[5]*y[1] + A
   190  	ADCXQ BP, DI
   191  	MULXQ 40(R8), AX, BP
   192  	ADOXQ AX, DI
   193  
   194  	// A += carries from ADCXQ and ADOXQ
   195  	MOVQ  $0, AX
   196  	ADCXQ AX, BP
   197  	ADOXQ AX, BP
   198  
   199  	// m := t[0]*q'[0] mod W
   200  	MOVQ  qInv0<>(SB), DX
   201  	IMULQ R14, DX
   202  
   203  	// clear the flags
   204  	XORQ AX, AX
   205  
   206  	// C,_ := t[0] + m*q[0]
   207  	MULXQ q<>+0(SB), AX, R9
   208  	ADCXQ R14, AX
   209  	MOVQ  R9, R14
   210  
   211  	// (C,t[0]) := t[1] + m*q[1] + C
   212  	ADCXQ R15, R14
   213  	MULXQ q<>+8(SB), AX, R15
   214  	ADOXQ AX, R14
   215  
   216  	// (C,t[1]) := t[2] + m*q[2] + C
   217  	ADCXQ CX, R15
   218  	MULXQ q<>+16(SB), AX, CX
   219  	ADOXQ AX, R15
   220  
   221  	// (C,t[2]) := t[3] + m*q[3] + C
   222  	ADCXQ BX, CX
   223  	MULXQ q<>+24(SB), AX, BX
   224  	ADOXQ AX, CX
   225  
   226  	// (C,t[3]) := t[4] + m*q[4] + C
   227  	ADCXQ SI, BX
   228  	MULXQ q<>+32(SB), AX, SI
   229  	ADOXQ AX, BX
   230  
   231  	// (C,t[4]) := t[5] + m*q[5] + C
   232  	ADCXQ DI, SI
   233  	MULXQ q<>+40(SB), AX, DI
   234  	ADOXQ AX, SI
   235  
   236  	// t[5] = C + A
   237  	MOVQ  $0, AX
   238  	ADCXQ AX, DI
   239  	ADOXQ BP, DI
   240  
   241  	// clear the flags
   242  	XORQ AX, AX
   243  	MOVQ 16(R13), DX
   244  
   245  	// (A,t[0])  := t[0] + x[0]*y[2] + A
   246  	MULXQ R10, AX, BP
   247  	ADOXQ AX, R14
   248  
   249  	// (A,t[1])  := t[1] + x[1]*y[2] + A
   250  	ADCXQ BP, R15
   251  	MULXQ R11, AX, BP
   252  	ADOXQ AX, R15
   253  
   254  	// (A,t[2])  := t[2] + x[2]*y[2] + A
   255  	ADCXQ BP, CX
   256  	MULXQ R12, AX, BP
   257  	ADOXQ AX, CX
   258  
   259  	// (A,t[3])  := t[3] + x[3]*y[2] + A
   260  	ADCXQ BP, BX
   261  	MULXQ 24(R8), AX, BP
   262  	ADOXQ AX, BX
   263  
   264  	// (A,t[4])  := t[4] + x[4]*y[2] + A
   265  	ADCXQ BP, SI
   266  	MULXQ 32(R8), AX, BP
   267  	ADOXQ AX, SI
   268  
   269  	// (A,t[5])  := t[5] + x[5]*y[2] + A
   270  	ADCXQ BP, DI
   271  	MULXQ 40(R8), AX, BP
   272  	ADOXQ AX, DI
   273  
   274  	// A += carries from ADCXQ and ADOXQ
   275  	MOVQ  $0, AX
   276  	ADCXQ AX, BP
   277  	ADOXQ AX, BP
   278  
   279  	// m := t[0]*q'[0] mod W
   280  	MOVQ  qInv0<>(SB), DX
   281  	IMULQ R14, DX
   282  
   283  	// clear the flags
   284  	XORQ AX, AX
   285  
   286  	// C,_ := t[0] + m*q[0]
   287  	MULXQ q<>+0(SB), AX, R9
   288  	ADCXQ R14, AX
   289  	MOVQ  R9, R14
   290  
   291  	// (C,t[0]) := t[1] + m*q[1] + C
   292  	ADCXQ R15, R14
   293  	MULXQ q<>+8(SB), AX, R15
   294  	ADOXQ AX, R14
   295  
   296  	// (C,t[1]) := t[2] + m*q[2] + C
   297  	ADCXQ CX, R15
   298  	MULXQ q<>+16(SB), AX, CX
   299  	ADOXQ AX, R15
   300  
   301  	// (C,t[2]) := t[3] + m*q[3] + C
   302  	ADCXQ BX, CX
   303  	MULXQ q<>+24(SB), AX, BX
   304  	ADOXQ AX, CX
   305  
   306  	// (C,t[3]) := t[4] + m*q[4] + C
   307  	ADCXQ SI, BX
   308  	MULXQ q<>+32(SB), AX, SI
   309  	ADOXQ AX, BX
   310  
   311  	// (C,t[4]) := t[5] + m*q[5] + C
   312  	ADCXQ DI, SI
   313  	MULXQ q<>+40(SB), AX, DI
   314  	ADOXQ AX, SI
   315  
   316  	// t[5] = C + A
   317  	MOVQ  $0, AX
   318  	ADCXQ AX, DI
   319  	ADOXQ BP, DI
   320  
   321  	// clear the flags
   322  	XORQ AX, AX
   323  	MOVQ 24(R13), DX
   324  
   325  	// (A,t[0])  := t[0] + x[0]*y[3] + A
   326  	MULXQ R10, AX, BP
   327  	ADOXQ AX, R14
   328  
   329  	// (A,t[1])  := t[1] + x[1]*y[3] + A
   330  	ADCXQ BP, R15
   331  	MULXQ R11, AX, BP
   332  	ADOXQ AX, R15
   333  
   334  	// (A,t[2])  := t[2] + x[2]*y[3] + A
   335  	ADCXQ BP, CX
   336  	MULXQ R12, AX, BP
   337  	ADOXQ AX, CX
   338  
   339  	// (A,t[3])  := t[3] + x[3]*y[3] + A
   340  	ADCXQ BP, BX
   341  	MULXQ 24(R8), AX, BP
   342  	ADOXQ AX, BX
   343  
   344  	// (A,t[4])  := t[4] + x[4]*y[3] + A
   345  	ADCXQ BP, SI
   346  	MULXQ 32(R8), AX, BP
   347  	ADOXQ AX, SI
   348  
   349  	// (A,t[5])  := t[5] + x[5]*y[3] + A
   350  	ADCXQ BP, DI
   351  	MULXQ 40(R8), AX, BP
   352  	ADOXQ AX, DI
   353  
   354  	// A += carries from ADCXQ and ADOXQ
   355  	MOVQ  $0, AX
   356  	ADCXQ AX, BP
   357  	ADOXQ AX, BP
   358  
   359  	// m := t[0]*q'[0] mod W
   360  	MOVQ  qInv0<>(SB), DX
   361  	IMULQ R14, DX
   362  
   363  	// clear the flags
   364  	XORQ AX, AX
   365  
   366  	// C,_ := t[0] + m*q[0]
   367  	MULXQ q<>+0(SB), AX, R9
   368  	ADCXQ R14, AX
   369  	MOVQ  R9, R14
   370  
   371  	// (C,t[0]) := t[1] + m*q[1] + C
   372  	ADCXQ R15, R14
   373  	MULXQ q<>+8(SB), AX, R15
   374  	ADOXQ AX, R14
   375  
   376  	// (C,t[1]) := t[2] + m*q[2] + C
   377  	ADCXQ CX, R15
   378  	MULXQ q<>+16(SB), AX, CX
   379  	ADOXQ AX, R15
   380  
   381  	// (C,t[2]) := t[3] + m*q[3] + C
   382  	ADCXQ BX, CX
   383  	MULXQ q<>+24(SB), AX, BX
   384  	ADOXQ AX, CX
   385  
   386  	// (C,t[3]) := t[4] + m*q[4] + C
   387  	ADCXQ SI, BX
   388  	MULXQ q<>+32(SB), AX, SI
   389  	ADOXQ AX, BX
   390  
   391  	// (C,t[4]) := t[5] + m*q[5] + C
   392  	ADCXQ DI, SI
   393  	MULXQ q<>+40(SB), AX, DI
   394  	ADOXQ AX, SI
   395  
   396  	// t[5] = C + A
   397  	MOVQ  $0, AX
   398  	ADCXQ AX, DI
   399  	ADOXQ BP, DI
   400  
   401  	// clear the flags
   402  	XORQ AX, AX
   403  	MOVQ 32(R13), DX
   404  
   405  	// (A,t[0])  := t[0] + x[0]*y[4] + A
   406  	MULXQ R10, AX, BP
   407  	ADOXQ AX, R14
   408  
   409  	// (A,t[1])  := t[1] + x[1]*y[4] + A
   410  	ADCXQ BP, R15
   411  	MULXQ R11, AX, BP
   412  	ADOXQ AX, R15
   413  
   414  	// (A,t[2])  := t[2] + x[2]*y[4] + A
   415  	ADCXQ BP, CX
   416  	MULXQ R12, AX, BP
   417  	ADOXQ AX, CX
   418  
   419  	// (A,t[3])  := t[3] + x[3]*y[4] + A
   420  	ADCXQ BP, BX
   421  	MULXQ 24(R8), AX, BP
   422  	ADOXQ AX, BX
   423  
   424  	// (A,t[4])  := t[4] + x[4]*y[4] + A
   425  	ADCXQ BP, SI
   426  	MULXQ 32(R8), AX, BP
   427  	ADOXQ AX, SI
   428  
   429  	// (A,t[5])  := t[5] + x[5]*y[4] + A
   430  	ADCXQ BP, DI
   431  	MULXQ 40(R8), AX, BP
   432  	ADOXQ AX, DI
   433  
   434  	// A += carries from ADCXQ and ADOXQ
   435  	MOVQ  $0, AX
   436  	ADCXQ AX, BP
   437  	ADOXQ AX, BP
   438  
   439  	// m := t[0]*q'[0] mod W
   440  	MOVQ  qInv0<>(SB), DX
   441  	IMULQ R14, DX
   442  
   443  	// clear the flags
   444  	XORQ AX, AX
   445  
   446  	// C,_ := t[0] + m*q[0]
   447  	MULXQ q<>+0(SB), AX, R9
   448  	ADCXQ R14, AX
   449  	MOVQ  R9, R14
   450  
   451  	// (C,t[0]) := t[1] + m*q[1] + C
   452  	ADCXQ R15, R14
   453  	MULXQ q<>+8(SB), AX, R15
   454  	ADOXQ AX, R14
   455  
   456  	// (C,t[1]) := t[2] + m*q[2] + C
   457  	ADCXQ CX, R15
   458  	MULXQ q<>+16(SB), AX, CX
   459  	ADOXQ AX, R15
   460  
   461  	// (C,t[2]) := t[3] + m*q[3] + C
   462  	ADCXQ BX, CX
   463  	MULXQ q<>+24(SB), AX, BX
   464  	ADOXQ AX, CX
   465  
   466  	// (C,t[3]) := t[4] + m*q[4] + C
   467  	ADCXQ SI, BX
   468  	MULXQ q<>+32(SB), AX, SI
   469  	ADOXQ AX, BX
   470  
   471  	// (C,t[4]) := t[5] + m*q[5] + C
   472  	ADCXQ DI, SI
   473  	MULXQ q<>+40(SB), AX, DI
   474  	ADOXQ AX, SI
   475  
   476  	// t[5] = C + A
   477  	MOVQ  $0, AX
   478  	ADCXQ AX, DI
   479  	ADOXQ BP, DI
   480  
   481  	// clear the flags
   482  	XORQ AX, AX
   483  	MOVQ 40(R13), DX
   484  
   485  	// (A,t[0])  := t[0] + x[0]*y[5] + A
   486  	MULXQ R10, AX, BP
   487  	ADOXQ AX, R14
   488  
   489  	// (A,t[1])  := t[1] + x[1]*y[5] + A
   490  	ADCXQ BP, R15
   491  	MULXQ R11, AX, BP
   492  	ADOXQ AX, R15
   493  
   494  	// (A,t[2])  := t[2] + x[2]*y[5] + A
   495  	ADCXQ BP, CX
   496  	MULXQ R12, AX, BP
   497  	ADOXQ AX, CX
   498  
   499  	// (A,t[3])  := t[3] + x[3]*y[5] + A
   500  	ADCXQ BP, BX
   501  	MULXQ 24(R8), AX, BP
   502  	ADOXQ AX, BX
   503  
   504  	// (A,t[4])  := t[4] + x[4]*y[5] + A
   505  	ADCXQ BP, SI
   506  	MULXQ 32(R8), AX, BP
   507  	ADOXQ AX, SI
   508  
   509  	// (A,t[5])  := t[5] + x[5]*y[5] + A
   510  	ADCXQ BP, DI
   511  	MULXQ 40(R8), AX, BP
   512  	ADOXQ AX, DI
   513  
   514  	// A += carries from ADCXQ and ADOXQ
   515  	MOVQ  $0, AX
   516  	ADCXQ AX, BP
   517  	ADOXQ AX, BP
   518  
   519  	// m := t[0]*q'[0] mod W
   520  	MOVQ  qInv0<>(SB), DX
   521  	IMULQ R14, DX
   522  
   523  	// clear the flags
   524  	XORQ AX, AX
   525  
   526  	// C,_ := t[0] + m*q[0]
   527  	MULXQ q<>+0(SB), AX, R9
   528  	ADCXQ R14, AX
   529  	MOVQ  R9, R14
   530  
   531  	// (C,t[0]) := t[1] + m*q[1] + C
   532  	ADCXQ R15, R14
   533  	MULXQ q<>+8(SB), AX, R15
   534  	ADOXQ AX, R14
   535  
   536  	// (C,t[1]) := t[2] + m*q[2] + C
   537  	ADCXQ CX, R15
   538  	MULXQ q<>+16(SB), AX, CX
   539  	ADOXQ AX, R15
   540  
   541  	// (C,t[2]) := t[3] + m*q[3] + C
   542  	ADCXQ BX, CX
   543  	MULXQ q<>+24(SB), AX, BX
   544  	ADOXQ AX, CX
   545  
   546  	// (C,t[3]) := t[4] + m*q[4] + C
   547  	ADCXQ SI, BX
   548  	MULXQ q<>+32(SB), AX, SI
   549  	ADOXQ AX, BX
   550  
   551  	// (C,t[4]) := t[5] + m*q[5] + C
   552  	ADCXQ DI, SI
   553  	MULXQ q<>+40(SB), AX, DI
   554  	ADOXQ AX, SI
   555  
   556  	// t[5] = C + A
   557  	MOVQ  $0, AX
   558  	ADCXQ AX, DI
   559  	ADOXQ BP, DI
   560  
   561  	// reduce element(R14,R15,CX,BX,SI,DI) using temp registers (R9,R8,R13,R10,R11,R12)
   562  	REDUCE(R14,R15,CX,BX,SI,DI,R9,R8,R13,R10,R11,R12)
   563  
   564  	MOVQ res+0(FP), AX
   565  	MOVQ R14, 0(AX)
   566  	MOVQ R15, 8(AX)
   567  	MOVQ CX, 16(AX)
   568  	MOVQ BX, 24(AX)
   569  	MOVQ SI, 32(AX)
   570  	MOVQ DI, 40(AX)
   571  	RET
   572  
   573  l1:
   574  	MOVQ res+0(FP), AX
   575  	MOVQ AX, (SP)
   576  	MOVQ x+8(FP), AX
   577  	MOVQ AX, 8(SP)
   578  	MOVQ y+16(FP), AX
   579  	MOVQ AX, 16(SP)
   580  	CALL ·_mulGeneric(SB)
   581  	RET
   582  
   583  TEXT ·fromMont(SB), $8-8
   584  	NO_LOCAL_POINTERS
   585  
   586  	// the algorithm is described here
   587  	// https://hackmd.io/@gnark/modular_multiplication
   588  	// when y = 1 we have:
   589  	// for i=0 to N-1
   590  	// 		t[i] = x[i]
   591  	// for i=0 to N-1
   592  	// 		m := t[0]*q'[0] mod W
   593  	// 		C,_ := t[0] + m*q[0]
   594  	// 		for j=1 to N-1
   595  	// 		    (C,t[j-1]) := t[j] + m*q[j] + C
   596  	// 		t[N-1] = C
   597  	CMPB ·supportAdx(SB), $1
   598  	JNE  l2
   599  	MOVQ res+0(FP), DX
   600  	MOVQ 0(DX), R14
   601  	MOVQ 8(DX), R15
   602  	MOVQ 16(DX), CX
   603  	MOVQ 24(DX), BX
   604  	MOVQ 32(DX), SI
   605  	MOVQ 40(DX), DI
   606  	XORQ DX, DX
   607  
   608  	// m := t[0]*q'[0] mod W
   609  	MOVQ  qInv0<>(SB), DX
   610  	IMULQ R14, DX
   611  	XORQ  AX, AX
   612  
   613  	// C,_ := t[0] + m*q[0]
   614  	MULXQ q<>+0(SB), AX, BP
   615  	ADCXQ R14, AX
   616  	MOVQ  BP, R14
   617  
   618  	// (C,t[0]) := t[1] + m*q[1] + C
   619  	ADCXQ R15, R14
   620  	MULXQ q<>+8(SB), AX, R15
   621  	ADOXQ AX, R14
   622  
   623  	// (C,t[1]) := t[2] + m*q[2] + C
   624  	ADCXQ CX, R15
   625  	MULXQ q<>+16(SB), AX, CX
   626  	ADOXQ AX, R15
   627  
   628  	// (C,t[2]) := t[3] + m*q[3] + C
   629  	ADCXQ BX, CX
   630  	MULXQ q<>+24(SB), AX, BX
   631  	ADOXQ AX, CX
   632  
   633  	// (C,t[3]) := t[4] + m*q[4] + C
   634  	ADCXQ SI, BX
   635  	MULXQ q<>+32(SB), AX, SI
   636  	ADOXQ AX, BX
   637  
   638  	// (C,t[4]) := t[5] + m*q[5] + C
   639  	ADCXQ DI, SI
   640  	MULXQ q<>+40(SB), AX, DI
   641  	ADOXQ AX, SI
   642  	MOVQ  $0, AX
   643  	ADCXQ AX, DI
   644  	ADOXQ AX, DI
   645  	XORQ  DX, DX
   646  
   647  	// m := t[0]*q'[0] mod W
   648  	MOVQ  qInv0<>(SB), DX
   649  	IMULQ R14, DX
   650  	XORQ  AX, AX
   651  
   652  	// C,_ := t[0] + m*q[0]
   653  	MULXQ q<>+0(SB), AX, BP
   654  	ADCXQ R14, AX
   655  	MOVQ  BP, R14
   656  
   657  	// (C,t[0]) := t[1] + m*q[1] + C
   658  	ADCXQ R15, R14
   659  	MULXQ q<>+8(SB), AX, R15
   660  	ADOXQ AX, R14
   661  
   662  	// (C,t[1]) := t[2] + m*q[2] + C
   663  	ADCXQ CX, R15
   664  	MULXQ q<>+16(SB), AX, CX
   665  	ADOXQ AX, R15
   666  
   667  	// (C,t[2]) := t[3] + m*q[3] + C
   668  	ADCXQ BX, CX
   669  	MULXQ q<>+24(SB), AX, BX
   670  	ADOXQ AX, CX
   671  
   672  	// (C,t[3]) := t[4] + m*q[4] + C
   673  	ADCXQ SI, BX
   674  	MULXQ q<>+32(SB), AX, SI
   675  	ADOXQ AX, BX
   676  
   677  	// (C,t[4]) := t[5] + m*q[5] + C
   678  	ADCXQ DI, SI
   679  	MULXQ q<>+40(SB), AX, DI
   680  	ADOXQ AX, SI
   681  	MOVQ  $0, AX
   682  	ADCXQ AX, DI
   683  	ADOXQ AX, DI
   684  	XORQ  DX, DX
   685  
   686  	// m := t[0]*q'[0] mod W
   687  	MOVQ  qInv0<>(SB), DX
   688  	IMULQ R14, DX
   689  	XORQ  AX, AX
   690  
   691  	// C,_ := t[0] + m*q[0]
   692  	MULXQ q<>+0(SB), AX, BP
   693  	ADCXQ R14, AX
   694  	MOVQ  BP, R14
   695  
   696  	// (C,t[0]) := t[1] + m*q[1] + C
   697  	ADCXQ R15, R14
   698  	MULXQ q<>+8(SB), AX, R15
   699  	ADOXQ AX, R14
   700  
   701  	// (C,t[1]) := t[2] + m*q[2] + C
   702  	ADCXQ CX, R15
   703  	MULXQ q<>+16(SB), AX, CX
   704  	ADOXQ AX, R15
   705  
   706  	// (C,t[2]) := t[3] + m*q[3] + C
   707  	ADCXQ BX, CX
   708  	MULXQ q<>+24(SB), AX, BX
   709  	ADOXQ AX, CX
   710  
   711  	// (C,t[3]) := t[4] + m*q[4] + C
   712  	ADCXQ SI, BX
   713  	MULXQ q<>+32(SB), AX, SI
   714  	ADOXQ AX, BX
   715  
   716  	// (C,t[4]) := t[5] + m*q[5] + C
   717  	ADCXQ DI, SI
   718  	MULXQ q<>+40(SB), AX, DI
   719  	ADOXQ AX, SI
   720  	MOVQ  $0, AX
   721  	ADCXQ AX, DI
   722  	ADOXQ AX, DI
   723  	XORQ  DX, DX
   724  
   725  	// m := t[0]*q'[0] mod W
   726  	MOVQ  qInv0<>(SB), DX
   727  	IMULQ R14, DX
   728  	XORQ  AX, AX
   729  
   730  	// C,_ := t[0] + m*q[0]
   731  	MULXQ q<>+0(SB), AX, BP
   732  	ADCXQ R14, AX
   733  	MOVQ  BP, R14
   734  
   735  	// (C,t[0]) := t[1] + m*q[1] + C
   736  	ADCXQ R15, R14
   737  	MULXQ q<>+8(SB), AX, R15
   738  	ADOXQ AX, R14
   739  
   740  	// (C,t[1]) := t[2] + m*q[2] + C
   741  	ADCXQ CX, R15
   742  	MULXQ q<>+16(SB), AX, CX
   743  	ADOXQ AX, R15
   744  
   745  	// (C,t[2]) := t[3] + m*q[3] + C
   746  	ADCXQ BX, CX
   747  	MULXQ q<>+24(SB), AX, BX
   748  	ADOXQ AX, CX
   749  
   750  	// (C,t[3]) := t[4] + m*q[4] + C
   751  	ADCXQ SI, BX
   752  	MULXQ q<>+32(SB), AX, SI
   753  	ADOXQ AX, BX
   754  
   755  	// (C,t[4]) := t[5] + m*q[5] + C
   756  	ADCXQ DI, SI
   757  	MULXQ q<>+40(SB), AX, DI
   758  	ADOXQ AX, SI
   759  	MOVQ  $0, AX
   760  	ADCXQ AX, DI
   761  	ADOXQ AX, DI
   762  	XORQ  DX, DX
   763  
   764  	// m := t[0]*q'[0] mod W
   765  	MOVQ  qInv0<>(SB), DX
   766  	IMULQ R14, DX
   767  	XORQ  AX, AX
   768  
   769  	// C,_ := t[0] + m*q[0]
   770  	MULXQ q<>+0(SB), AX, BP
   771  	ADCXQ R14, AX
   772  	MOVQ  BP, R14
   773  
   774  	// (C,t[0]) := t[1] + m*q[1] + C
   775  	ADCXQ R15, R14
   776  	MULXQ q<>+8(SB), AX, R15
   777  	ADOXQ AX, R14
   778  
   779  	// (C,t[1]) := t[2] + m*q[2] + C
   780  	ADCXQ CX, R15
   781  	MULXQ q<>+16(SB), AX, CX
   782  	ADOXQ AX, R15
   783  
   784  	// (C,t[2]) := t[3] + m*q[3] + C
   785  	ADCXQ BX, CX
   786  	MULXQ q<>+24(SB), AX, BX
   787  	ADOXQ AX, CX
   788  
   789  	// (C,t[3]) := t[4] + m*q[4] + C
   790  	ADCXQ SI, BX
   791  	MULXQ q<>+32(SB), AX, SI
   792  	ADOXQ AX, BX
   793  
   794  	// (C,t[4]) := t[5] + m*q[5] + C
   795  	ADCXQ DI, SI
   796  	MULXQ q<>+40(SB), AX, DI
   797  	ADOXQ AX, SI
   798  	MOVQ  $0, AX
   799  	ADCXQ AX, DI
   800  	ADOXQ AX, DI
   801  	XORQ  DX, DX
   802  
   803  	// m := t[0]*q'[0] mod W
   804  	MOVQ  qInv0<>(SB), DX
   805  	IMULQ R14, DX
   806  	XORQ  AX, AX
   807  
   808  	// C,_ := t[0] + m*q[0]
   809  	MULXQ q<>+0(SB), AX, BP
   810  	ADCXQ R14, AX
   811  	MOVQ  BP, R14
   812  
   813  	// (C,t[0]) := t[1] + m*q[1] + C
   814  	ADCXQ R15, R14
   815  	MULXQ q<>+8(SB), AX, R15
   816  	ADOXQ AX, R14
   817  
   818  	// (C,t[1]) := t[2] + m*q[2] + C
   819  	ADCXQ CX, R15
   820  	MULXQ q<>+16(SB), AX, CX
   821  	ADOXQ AX, R15
   822  
   823  	// (C,t[2]) := t[3] + m*q[3] + C
   824  	ADCXQ BX, CX
   825  	MULXQ q<>+24(SB), AX, BX
   826  	ADOXQ AX, CX
   827  
   828  	// (C,t[3]) := t[4] + m*q[4] + C
   829  	ADCXQ SI, BX
   830  	MULXQ q<>+32(SB), AX, SI
   831  	ADOXQ AX, BX
   832  
   833  	// (C,t[4]) := t[5] + m*q[5] + C
   834  	ADCXQ DI, SI
   835  	MULXQ q<>+40(SB), AX, DI
   836  	ADOXQ AX, SI
   837  	MOVQ  $0, AX
   838  	ADCXQ AX, DI
   839  	ADOXQ AX, DI
   840  
   841  	// reduce element(R14,R15,CX,BX,SI,DI) using temp registers (R8,R9,R10,R11,R12,R13)
   842  	REDUCE(R14,R15,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13)
   843  
   844  	MOVQ res+0(FP), AX
   845  	MOVQ R14, 0(AX)
   846  	MOVQ R15, 8(AX)
   847  	MOVQ CX, 16(AX)
   848  	MOVQ BX, 24(AX)
   849  	MOVQ SI, 32(AX)
   850  	MOVQ DI, 40(AX)
   851  	RET
   852  
   853  l2:
   854  	MOVQ res+0(FP), AX
   855  	MOVQ AX, (SP)
   856  	CALL ·_fromMontGeneric(SB)
   857  	RET