github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-317/fp/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, $0x8d512e565dab2aab
    22  DATA q<>+8(SB)/8, $0xd6f339e43424bf7e
    23  DATA q<>+16(SB)/8, $0x169a61e684c73446
    24  DATA q<>+24(SB)/8, $0xf28fc5a0b7f9d039
    25  DATA q<>+32(SB)/8, $0x1058ca226f60892c
    26  GLOBL q<>(SB), (RODATA+NOPTR), $40
    27  
    28  // qInv0 q'[0]
    29  DATA qInv0<>(SB)/8, $0x55b5e0028b047ffd
    30  GLOBL qInv0<>(SB), (RODATA+NOPTR), $8
    31  
    32  #define REDUCE(ra0, ra1, ra2, ra3, ra4, rb0, rb1, rb2, rb3, rb4) \
    33  	MOVQ    ra0, rb0;        \
    34  	SUBQ    q<>(SB), ra0;    \
    35  	MOVQ    ra1, rb1;        \
    36  	SBBQ    q<>+8(SB), ra1;  \
    37  	MOVQ    ra2, rb2;        \
    38  	SBBQ    q<>+16(SB), ra2; \
    39  	MOVQ    ra3, rb3;        \
    40  	SBBQ    q<>+24(SB), ra3; \
    41  	MOVQ    ra4, rb4;        \
    42  	SBBQ    q<>+32(SB), ra4; \
    43  	CMOVQCS rb0, ra0;        \
    44  	CMOVQCS rb1, ra1;        \
    45  	CMOVQCS rb2, ra2;        \
    46  	CMOVQCS rb3, ra3;        \
    47  	CMOVQCS rb4, ra4;        \
    48  
    49  // mul(res, x, y *Element)
    50  TEXT ·mul(SB), $24-24
    51  
    52  	// the algorithm is described in the Element.Mul declaration (.go)
    53  	// however, to benefit from the ADCX and ADOX carry chains
    54  	// we split the inner loops in 2:
    55  	// for i=0 to N-1
    56  	// 		for j=0 to N-1
    57  	// 		    (A,t[j])  := t[j] + x[j]*y[i] + A
    58  	// 		m := t[0]*q'[0] mod W
    59  	// 		C,_ := t[0] + m*q[0]
    60  	// 		for j=1 to N-1
    61  	// 		    (C,t[j-1]) := t[j] + m*q[j] + C
    62  	// 		t[N-1] = C + A
    63  
    64  	NO_LOCAL_POINTERS
    65  	CMPB ·supportAdx(SB), $1
    66  	JNE  l1
    67  	MOVQ x+8(FP), DI
    68  
    69  	// x[0] -> R9
    70  	// x[1] -> R10
    71  	// x[2] -> R11
    72  	MOVQ 0(DI), R9
    73  	MOVQ 8(DI), R10
    74  	MOVQ 16(DI), R11
    75  	MOVQ y+16(FP), R12
    76  
    77  	// A -> BP
    78  	// t[0] -> R14
    79  	// t[1] -> R13
    80  	// t[2] -> CX
    81  	// t[3] -> BX
    82  	// t[4] -> SI
    83  	// clear the flags
    84  	XORQ AX, AX
    85  	MOVQ 0(R12), DX
    86  
    87  	// (A,t[0])  := x[0]*y[0] + A
    88  	MULXQ R9, R14, R13
    89  
    90  	// (A,t[1])  := x[1]*y[0] + A
    91  	MULXQ R10, AX, CX
    92  	ADOXQ AX, R13
    93  
    94  	// (A,t[2])  := x[2]*y[0] + A
    95  	MULXQ R11, AX, BX
    96  	ADOXQ AX, CX
    97  
    98  	// (A,t[3])  := x[3]*y[0] + A
    99  	MULXQ 24(DI), AX, SI
   100  	ADOXQ AX, BX
   101  
   102  	// (A,t[4])  := x[4]*y[0] + A
   103  	MULXQ 32(DI), AX, BP
   104  	ADOXQ AX, SI
   105  
   106  	// A += carries from ADCXQ and ADOXQ
   107  	MOVQ  $0, AX
   108  	ADOXQ AX, BP
   109  
   110  	// m := t[0]*q'[0] mod W
   111  	MOVQ  qInv0<>(SB), DX
   112  	IMULQ R14, DX
   113  
   114  	// clear the flags
   115  	XORQ AX, AX
   116  
   117  	// C,_ := t[0] + m*q[0]
   118  	MULXQ q<>+0(SB), AX, R8
   119  	ADCXQ R14, AX
   120  	MOVQ  R8, R14
   121  
   122  	// (C,t[0]) := t[1] + m*q[1] + C
   123  	ADCXQ R13, R14
   124  	MULXQ q<>+8(SB), AX, R13
   125  	ADOXQ AX, R14
   126  
   127  	// (C,t[1]) := t[2] + m*q[2] + C
   128  	ADCXQ CX, R13
   129  	MULXQ q<>+16(SB), AX, CX
   130  	ADOXQ AX, R13
   131  
   132  	// (C,t[2]) := t[3] + m*q[3] + C
   133  	ADCXQ BX, CX
   134  	MULXQ q<>+24(SB), AX, BX
   135  	ADOXQ AX, CX
   136  
   137  	// (C,t[3]) := t[4] + m*q[4] + C
   138  	ADCXQ SI, BX
   139  	MULXQ q<>+32(SB), AX, SI
   140  	ADOXQ AX, BX
   141  
   142  	// t[4] = C + A
   143  	MOVQ  $0, AX
   144  	ADCXQ AX, SI
   145  	ADOXQ BP, SI
   146  
   147  	// clear the flags
   148  	XORQ AX, AX
   149  	MOVQ 8(R12), DX
   150  
   151  	// (A,t[0])  := t[0] + x[0]*y[1] + A
   152  	MULXQ R9, AX, BP
   153  	ADOXQ AX, R14
   154  
   155  	// (A,t[1])  := t[1] + x[1]*y[1] + A
   156  	ADCXQ BP, R13
   157  	MULXQ R10, AX, BP
   158  	ADOXQ AX, R13
   159  
   160  	// (A,t[2])  := t[2] + x[2]*y[1] + A
   161  	ADCXQ BP, CX
   162  	MULXQ R11, AX, BP
   163  	ADOXQ AX, CX
   164  
   165  	// (A,t[3])  := t[3] + x[3]*y[1] + A
   166  	ADCXQ BP, BX
   167  	MULXQ 24(DI), AX, BP
   168  	ADOXQ AX, BX
   169  
   170  	// (A,t[4])  := t[4] + x[4]*y[1] + A
   171  	ADCXQ BP, SI
   172  	MULXQ 32(DI), AX, BP
   173  	ADOXQ AX, SI
   174  
   175  	// A += carries from ADCXQ and ADOXQ
   176  	MOVQ  $0, AX
   177  	ADCXQ AX, BP
   178  	ADOXQ AX, BP
   179  
   180  	// m := t[0]*q'[0] mod W
   181  	MOVQ  qInv0<>(SB), DX
   182  	IMULQ R14, DX
   183  
   184  	// clear the flags
   185  	XORQ AX, AX
   186  
   187  	// C,_ := t[0] + m*q[0]
   188  	MULXQ q<>+0(SB), AX, R8
   189  	ADCXQ R14, AX
   190  	MOVQ  R8, R14
   191  
   192  	// (C,t[0]) := t[1] + m*q[1] + C
   193  	ADCXQ R13, R14
   194  	MULXQ q<>+8(SB), AX, R13
   195  	ADOXQ AX, R14
   196  
   197  	// (C,t[1]) := t[2] + m*q[2] + C
   198  	ADCXQ CX, R13
   199  	MULXQ q<>+16(SB), AX, CX
   200  	ADOXQ AX, R13
   201  
   202  	// (C,t[2]) := t[3] + m*q[3] + C
   203  	ADCXQ BX, CX
   204  	MULXQ q<>+24(SB), AX, BX
   205  	ADOXQ AX, CX
   206  
   207  	// (C,t[3]) := t[4] + m*q[4] + C
   208  	ADCXQ SI, BX
   209  	MULXQ q<>+32(SB), AX, SI
   210  	ADOXQ AX, BX
   211  
   212  	// t[4] = C + A
   213  	MOVQ  $0, AX
   214  	ADCXQ AX, SI
   215  	ADOXQ BP, SI
   216  
   217  	// clear the flags
   218  	XORQ AX, AX
   219  	MOVQ 16(R12), DX
   220  
   221  	// (A,t[0])  := t[0] + x[0]*y[2] + A
   222  	MULXQ R9, AX, BP
   223  	ADOXQ AX, R14
   224  
   225  	// (A,t[1])  := t[1] + x[1]*y[2] + A
   226  	ADCXQ BP, R13
   227  	MULXQ R10, AX, BP
   228  	ADOXQ AX, R13
   229  
   230  	// (A,t[2])  := t[2] + x[2]*y[2] + A
   231  	ADCXQ BP, CX
   232  	MULXQ R11, AX, BP
   233  	ADOXQ AX, CX
   234  
   235  	// (A,t[3])  := t[3] + x[3]*y[2] + A
   236  	ADCXQ BP, BX
   237  	MULXQ 24(DI), AX, BP
   238  	ADOXQ AX, BX
   239  
   240  	// (A,t[4])  := t[4] + x[4]*y[2] + A
   241  	ADCXQ BP, SI
   242  	MULXQ 32(DI), AX, BP
   243  	ADOXQ AX, SI
   244  
   245  	// A += carries from ADCXQ and ADOXQ
   246  	MOVQ  $0, AX
   247  	ADCXQ AX, BP
   248  	ADOXQ AX, BP
   249  
   250  	// m := t[0]*q'[0] mod W
   251  	MOVQ  qInv0<>(SB), DX
   252  	IMULQ R14, DX
   253  
   254  	// clear the flags
   255  	XORQ AX, AX
   256  
   257  	// C,_ := t[0] + m*q[0]
   258  	MULXQ q<>+0(SB), AX, R8
   259  	ADCXQ R14, AX
   260  	MOVQ  R8, R14
   261  
   262  	// (C,t[0]) := t[1] + m*q[1] + C
   263  	ADCXQ R13, R14
   264  	MULXQ q<>+8(SB), AX, R13
   265  	ADOXQ AX, R14
   266  
   267  	// (C,t[1]) := t[2] + m*q[2] + C
   268  	ADCXQ CX, R13
   269  	MULXQ q<>+16(SB), AX, CX
   270  	ADOXQ AX, R13
   271  
   272  	// (C,t[2]) := t[3] + m*q[3] + C
   273  	ADCXQ BX, CX
   274  	MULXQ q<>+24(SB), AX, BX
   275  	ADOXQ AX, CX
   276  
   277  	// (C,t[3]) := t[4] + m*q[4] + C
   278  	ADCXQ SI, BX
   279  	MULXQ q<>+32(SB), AX, SI
   280  	ADOXQ AX, BX
   281  
   282  	// t[4] = C + A
   283  	MOVQ  $0, AX
   284  	ADCXQ AX, SI
   285  	ADOXQ BP, SI
   286  
   287  	// clear the flags
   288  	XORQ AX, AX
   289  	MOVQ 24(R12), DX
   290  
   291  	// (A,t[0])  := t[0] + x[0]*y[3] + A
   292  	MULXQ R9, AX, BP
   293  	ADOXQ AX, R14
   294  
   295  	// (A,t[1])  := t[1] + x[1]*y[3] + A
   296  	ADCXQ BP, R13
   297  	MULXQ R10, AX, BP
   298  	ADOXQ AX, R13
   299  
   300  	// (A,t[2])  := t[2] + x[2]*y[3] + A
   301  	ADCXQ BP, CX
   302  	MULXQ R11, AX, BP
   303  	ADOXQ AX, CX
   304  
   305  	// (A,t[3])  := t[3] + x[3]*y[3] + A
   306  	ADCXQ BP, BX
   307  	MULXQ 24(DI), AX, BP
   308  	ADOXQ AX, BX
   309  
   310  	// (A,t[4])  := t[4] + x[4]*y[3] + A
   311  	ADCXQ BP, SI
   312  	MULXQ 32(DI), AX, BP
   313  	ADOXQ AX, SI
   314  
   315  	// A += carries from ADCXQ and ADOXQ
   316  	MOVQ  $0, AX
   317  	ADCXQ AX, BP
   318  	ADOXQ AX, BP
   319  
   320  	// m := t[0]*q'[0] mod W
   321  	MOVQ  qInv0<>(SB), DX
   322  	IMULQ R14, DX
   323  
   324  	// clear the flags
   325  	XORQ AX, AX
   326  
   327  	// C,_ := t[0] + m*q[0]
   328  	MULXQ q<>+0(SB), AX, R8
   329  	ADCXQ R14, AX
   330  	MOVQ  R8, R14
   331  
   332  	// (C,t[0]) := t[1] + m*q[1] + C
   333  	ADCXQ R13, R14
   334  	MULXQ q<>+8(SB), AX, R13
   335  	ADOXQ AX, R14
   336  
   337  	// (C,t[1]) := t[2] + m*q[2] + C
   338  	ADCXQ CX, R13
   339  	MULXQ q<>+16(SB), AX, CX
   340  	ADOXQ AX, R13
   341  
   342  	// (C,t[2]) := t[3] + m*q[3] + C
   343  	ADCXQ BX, CX
   344  	MULXQ q<>+24(SB), AX, BX
   345  	ADOXQ AX, CX
   346  
   347  	// (C,t[3]) := t[4] + m*q[4] + C
   348  	ADCXQ SI, BX
   349  	MULXQ q<>+32(SB), AX, SI
   350  	ADOXQ AX, BX
   351  
   352  	// t[4] = C + A
   353  	MOVQ  $0, AX
   354  	ADCXQ AX, SI
   355  	ADOXQ BP, SI
   356  
   357  	// clear the flags
   358  	XORQ AX, AX
   359  	MOVQ 32(R12), DX
   360  
   361  	// (A,t[0])  := t[0] + x[0]*y[4] + A
   362  	MULXQ R9, AX, BP
   363  	ADOXQ AX, R14
   364  
   365  	// (A,t[1])  := t[1] + x[1]*y[4] + A
   366  	ADCXQ BP, R13
   367  	MULXQ R10, AX, BP
   368  	ADOXQ AX, R13
   369  
   370  	// (A,t[2])  := t[2] + x[2]*y[4] + A
   371  	ADCXQ BP, CX
   372  	MULXQ R11, AX, BP
   373  	ADOXQ AX, CX
   374  
   375  	// (A,t[3])  := t[3] + x[3]*y[4] + A
   376  	ADCXQ BP, BX
   377  	MULXQ 24(DI), AX, BP
   378  	ADOXQ AX, BX
   379  
   380  	// (A,t[4])  := t[4] + x[4]*y[4] + A
   381  	ADCXQ BP, SI
   382  	MULXQ 32(DI), AX, BP
   383  	ADOXQ AX, SI
   384  
   385  	// A += carries from ADCXQ and ADOXQ
   386  	MOVQ  $0, AX
   387  	ADCXQ AX, BP
   388  	ADOXQ AX, BP
   389  
   390  	// m := t[0]*q'[0] mod W
   391  	MOVQ  qInv0<>(SB), DX
   392  	IMULQ R14, DX
   393  
   394  	// clear the flags
   395  	XORQ AX, AX
   396  
   397  	// C,_ := t[0] + m*q[0]
   398  	MULXQ q<>+0(SB), AX, R8
   399  	ADCXQ R14, AX
   400  	MOVQ  R8, R14
   401  
   402  	// (C,t[0]) := t[1] + m*q[1] + C
   403  	ADCXQ R13, R14
   404  	MULXQ q<>+8(SB), AX, R13
   405  	ADOXQ AX, R14
   406  
   407  	// (C,t[1]) := t[2] + m*q[2] + C
   408  	ADCXQ CX, R13
   409  	MULXQ q<>+16(SB), AX, CX
   410  	ADOXQ AX, R13
   411  
   412  	// (C,t[2]) := t[3] + m*q[3] + C
   413  	ADCXQ BX, CX
   414  	MULXQ q<>+24(SB), AX, BX
   415  	ADOXQ AX, CX
   416  
   417  	// (C,t[3]) := t[4] + m*q[4] + C
   418  	ADCXQ SI, BX
   419  	MULXQ q<>+32(SB), AX, SI
   420  	ADOXQ AX, BX
   421  
   422  	// t[4] = C + A
   423  	MOVQ  $0, AX
   424  	ADCXQ AX, SI
   425  	ADOXQ BP, SI
   426  
   427  	// reduce element(R14,R13,CX,BX,SI) using temp registers (R8,DI,R12,R9,R10)
   428  	REDUCE(R14,R13,CX,BX,SI,R8,DI,R12,R9,R10)
   429  
   430  	MOVQ res+0(FP), AX
   431  	MOVQ R14, 0(AX)
   432  	MOVQ R13, 8(AX)
   433  	MOVQ CX, 16(AX)
   434  	MOVQ BX, 24(AX)
   435  	MOVQ SI, 32(AX)
   436  	RET
   437  
   438  l1:
   439  	MOVQ res+0(FP), AX
   440  	MOVQ AX, (SP)
   441  	MOVQ x+8(FP), AX
   442  	MOVQ AX, 8(SP)
   443  	MOVQ y+16(FP), AX
   444  	MOVQ AX, 16(SP)
   445  	CALL ·_mulGeneric(SB)
   446  	RET
   447  
   448  TEXT ·fromMont(SB), $8-8
   449  	NO_LOCAL_POINTERS
   450  
   451  	// the algorithm is described here
   452  	// https://hackmd.io/@gnark/modular_multiplication
   453  	// when y = 1 we have:
   454  	// for i=0 to N-1
   455  	// 		t[i] = x[i]
   456  	// for i=0 to N-1
   457  	// 		m := t[0]*q'[0] mod W
   458  	// 		C,_ := t[0] + m*q[0]
   459  	// 		for j=1 to N-1
   460  	// 		    (C,t[j-1]) := t[j] + m*q[j] + C
   461  	// 		t[N-1] = C
   462  	CMPB ·supportAdx(SB), $1
   463  	JNE  l2
   464  	MOVQ res+0(FP), DX
   465  	MOVQ 0(DX), R14
   466  	MOVQ 8(DX), R13
   467  	MOVQ 16(DX), CX
   468  	MOVQ 24(DX), BX
   469  	MOVQ 32(DX), SI
   470  	XORQ DX, DX
   471  
   472  	// m := t[0]*q'[0] mod W
   473  	MOVQ  qInv0<>(SB), DX
   474  	IMULQ R14, DX
   475  	XORQ  AX, AX
   476  
   477  	// C,_ := t[0] + m*q[0]
   478  	MULXQ q<>+0(SB), AX, BP
   479  	ADCXQ R14, AX
   480  	MOVQ  BP, R14
   481  
   482  	// (C,t[0]) := t[1] + m*q[1] + C
   483  	ADCXQ R13, R14
   484  	MULXQ q<>+8(SB), AX, R13
   485  	ADOXQ AX, R14
   486  
   487  	// (C,t[1]) := t[2] + m*q[2] + C
   488  	ADCXQ CX, R13
   489  	MULXQ q<>+16(SB), AX, CX
   490  	ADOXQ AX, R13
   491  
   492  	// (C,t[2]) := t[3] + m*q[3] + C
   493  	ADCXQ BX, CX
   494  	MULXQ q<>+24(SB), AX, BX
   495  	ADOXQ AX, CX
   496  
   497  	// (C,t[3]) := t[4] + m*q[4] + C
   498  	ADCXQ SI, BX
   499  	MULXQ q<>+32(SB), AX, SI
   500  	ADOXQ AX, BX
   501  	MOVQ  $0, AX
   502  	ADCXQ AX, SI
   503  	ADOXQ AX, SI
   504  	XORQ  DX, DX
   505  
   506  	// m := t[0]*q'[0] mod W
   507  	MOVQ  qInv0<>(SB), DX
   508  	IMULQ R14, DX
   509  	XORQ  AX, AX
   510  
   511  	// C,_ := t[0] + m*q[0]
   512  	MULXQ q<>+0(SB), AX, BP
   513  	ADCXQ R14, AX
   514  	MOVQ  BP, R14
   515  
   516  	// (C,t[0]) := t[1] + m*q[1] + C
   517  	ADCXQ R13, R14
   518  	MULXQ q<>+8(SB), AX, R13
   519  	ADOXQ AX, R14
   520  
   521  	// (C,t[1]) := t[2] + m*q[2] + C
   522  	ADCXQ CX, R13
   523  	MULXQ q<>+16(SB), AX, CX
   524  	ADOXQ AX, R13
   525  
   526  	// (C,t[2]) := t[3] + m*q[3] + C
   527  	ADCXQ BX, CX
   528  	MULXQ q<>+24(SB), AX, BX
   529  	ADOXQ AX, CX
   530  
   531  	// (C,t[3]) := t[4] + m*q[4] + C
   532  	ADCXQ SI, BX
   533  	MULXQ q<>+32(SB), AX, SI
   534  	ADOXQ AX, BX
   535  	MOVQ  $0, AX
   536  	ADCXQ AX, SI
   537  	ADOXQ AX, SI
   538  	XORQ  DX, DX
   539  
   540  	// m := t[0]*q'[0] mod W
   541  	MOVQ  qInv0<>(SB), DX
   542  	IMULQ R14, DX
   543  	XORQ  AX, AX
   544  
   545  	// C,_ := t[0] + m*q[0]
   546  	MULXQ q<>+0(SB), AX, BP
   547  	ADCXQ R14, AX
   548  	MOVQ  BP, R14
   549  
   550  	// (C,t[0]) := t[1] + m*q[1] + C
   551  	ADCXQ R13, R14
   552  	MULXQ q<>+8(SB), AX, R13
   553  	ADOXQ AX, R14
   554  
   555  	// (C,t[1]) := t[2] + m*q[2] + C
   556  	ADCXQ CX, R13
   557  	MULXQ q<>+16(SB), AX, CX
   558  	ADOXQ AX, R13
   559  
   560  	// (C,t[2]) := t[3] + m*q[3] + C
   561  	ADCXQ BX, CX
   562  	MULXQ q<>+24(SB), AX, BX
   563  	ADOXQ AX, CX
   564  
   565  	// (C,t[3]) := t[4] + m*q[4] + C
   566  	ADCXQ SI, BX
   567  	MULXQ q<>+32(SB), AX, SI
   568  	ADOXQ AX, BX
   569  	MOVQ  $0, AX
   570  	ADCXQ AX, SI
   571  	ADOXQ AX, SI
   572  	XORQ  DX, DX
   573  
   574  	// m := t[0]*q'[0] mod W
   575  	MOVQ  qInv0<>(SB), DX
   576  	IMULQ R14, DX
   577  	XORQ  AX, AX
   578  
   579  	// C,_ := t[0] + m*q[0]
   580  	MULXQ q<>+0(SB), AX, BP
   581  	ADCXQ R14, AX
   582  	MOVQ  BP, R14
   583  
   584  	// (C,t[0]) := t[1] + m*q[1] + C
   585  	ADCXQ R13, R14
   586  	MULXQ q<>+8(SB), AX, R13
   587  	ADOXQ AX, R14
   588  
   589  	// (C,t[1]) := t[2] + m*q[2] + C
   590  	ADCXQ CX, R13
   591  	MULXQ q<>+16(SB), AX, CX
   592  	ADOXQ AX, R13
   593  
   594  	// (C,t[2]) := t[3] + m*q[3] + C
   595  	ADCXQ BX, CX
   596  	MULXQ q<>+24(SB), AX, BX
   597  	ADOXQ AX, CX
   598  
   599  	// (C,t[3]) := t[4] + m*q[4] + C
   600  	ADCXQ SI, BX
   601  	MULXQ q<>+32(SB), AX, SI
   602  	ADOXQ AX, BX
   603  	MOVQ  $0, AX
   604  	ADCXQ AX, SI
   605  	ADOXQ AX, SI
   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 R13, R14
   620  	MULXQ q<>+8(SB), AX, R13
   621  	ADOXQ AX, R14
   622  
   623  	// (C,t[1]) := t[2] + m*q[2] + C
   624  	ADCXQ CX, R13
   625  	MULXQ q<>+16(SB), AX, CX
   626  	ADOXQ AX, R13
   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  	MOVQ  $0, AX
   638  	ADCXQ AX, SI
   639  	ADOXQ AX, SI
   640  
   641  	// reduce element(R14,R13,CX,BX,SI) using temp registers (DI,R8,R9,R10,R11)
   642  	REDUCE(R14,R13,CX,BX,SI,DI,R8,R9,R10,R11)
   643  
   644  	MOVQ res+0(FP), AX
   645  	MOVQ R14, 0(AX)
   646  	MOVQ R13, 8(AX)
   647  	MOVQ CX, 16(AX)
   648  	MOVQ BX, 24(AX)
   649  	MOVQ SI, 32(AX)
   650  	RET
   651  
   652  l2:
   653  	MOVQ res+0(FP), AX
   654  	MOVQ AX, (SP)
   655  	CALL ·_fromMontGeneric(SB)
   656  	RET