Source file src/crypto/internal/fips140/nistec/_asm/p256_asm.go

     1  // Copyright 2024 The Go 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  // This file contains constant-time, 64-bit assembly implementation of
     6  // P256. The optimizations performed here are described in detail in:
     7  // S.Gueron and V.Krasnov, "Fast prime field elliptic-curve cryptography with
     8  //                          256-bit primes"
     9  // https://link.springer.com/article/10.1007%2Fs13389-014-0090-x
    10  // https://eprint.iacr.org/2013/816.pdf
    11  
    12  package main
    13  
    14  import (
    15  	"os"
    16  	"strings"
    17  
    18  	. "github.com/mmcloughlin/avo/build"
    19  	"github.com/mmcloughlin/avo/ir"
    20  	. "github.com/mmcloughlin/avo/operand"
    21  	. "github.com/mmcloughlin/avo/reg"
    22  )
    23  
    24  //go:generate go run . -out ../p256_asm_amd64.s
    25  
    26  var (
    27  	res_ptr GPPhysical = RDI
    28  	x_ptr              = RSI
    29  	y_ptr              = RCX
    30  )
    31  
    32  // These variables have been versioned as they get redfined in the reference implementation.
    33  // This is done to produce a minimal semantic diff.
    34  var (
    35  	acc0_v1 GPPhysical = R8
    36  	acc1_v1            = R9
    37  	acc2_v1            = R10
    38  	acc3_v1            = R11
    39  	acc4_v1            = R12
    40  	acc5_v1            = R13
    41  	t0_v1              = R14
    42  	t1_v1              = R15
    43  )
    44  
    45  func main() {
    46  	Package("crypto/internal/fips140/nistec")
    47  	ConstraintExpr("!purego")
    48  	p256MovCond()
    49  	p256NegCond()
    50  	p256Sqr()
    51  	p256Mul()
    52  	p256FromMont()
    53  	p256Select()
    54  	p256SelectAffine()
    55  	p256OrdMul()
    56  	p256OrdSqr()
    57  	p256SubInternal()
    58  	p256MulInternal()
    59  	p256SqrInternal()
    60  	p256PointAddAffineAsm()
    61  	p256IsZero()
    62  	p256PointAddAsm()
    63  	p256PointDoubleAsm()
    64  	Generate()
    65  
    66  	internalFunctions := []string{
    67  		"·p256SubInternal",
    68  		"·p256MulInternal",
    69  		"·p256SqrInternal",
    70  		"·p256IsZero",
    71  	}
    72  	removePeskyUnicodeDot(internalFunctions, "../p256_asm_amd64.s")
    73  }
    74  
    75  // Implements:
    76  //
    77  //	func p256MovCond(res, a, b *P256Point, cond int)
    78  func p256MovCond() {
    79  	Implement("p256MovCond")
    80  	Attributes(NOSPLIT)
    81  
    82  	Load(Param("res"), res_ptr)
    83  	Load(Param("a"), x_ptr)
    84  	Load(Param("b"), y_ptr)
    85  	Load(Param("cond"), X12)
    86  
    87  	PXOR(X13, X13)
    88  	PSHUFD(Imm(0), X12, X12)
    89  	PCMPEQL(X13, X12)
    90  
    91  	MOVOU(X12, X0)
    92  	MOVOU(Mem{Base: x_ptr}.Offset(16*0), X6)
    93  	PANDN(X6, X0)
    94  	MOVOU(X12, X1)
    95  	MOVOU(Mem{Base: x_ptr}.Offset(16*1), X7)
    96  	PANDN(X7, X1)
    97  	MOVOU(X12, X2)
    98  	MOVOU(Mem{Base: x_ptr}.Offset(16*2), X8)
    99  	PANDN(X8, X2)
   100  	MOVOU(X12, X3)
   101  	MOVOU(Mem{Base: x_ptr}.Offset(16*3), X9)
   102  	PANDN(X9, X3)
   103  	MOVOU(X12, X4)
   104  	MOVOU(Mem{Base: x_ptr}.Offset(16*4), X10)
   105  	PANDN(X10, X4)
   106  	MOVOU(X12, X5)
   107  	MOVOU(Mem{Base: x_ptr}.Offset(16*5), X11)
   108  	PANDN(X11, X5)
   109  
   110  	MOVOU(Mem{Base: y_ptr}.Offset(16*0), X6)
   111  	MOVOU(Mem{Base: y_ptr}.Offset(16*1), X7)
   112  	MOVOU(Mem{Base: y_ptr}.Offset(16*2), X8)
   113  	MOVOU(Mem{Base: y_ptr}.Offset(16*3), X9)
   114  	MOVOU(Mem{Base: y_ptr}.Offset(16*4), X10)
   115  	MOVOU(Mem{Base: y_ptr}.Offset(16*5), X11)
   116  
   117  	PAND(X12, X6)
   118  	PAND(X12, X7)
   119  	PAND(X12, X8)
   120  	PAND(X12, X9)
   121  	PAND(X12, X10)
   122  	PAND(X12, X11)
   123  
   124  	PXOR(X6, X0)
   125  	PXOR(X7, X1)
   126  	PXOR(X8, X2)
   127  	PXOR(X9, X3)
   128  	PXOR(X10, X4)
   129  	PXOR(X11, X5)
   130  
   131  	MOVOU(X0, Mem{Base: res_ptr}.Offset(16*0))
   132  	MOVOU(X1, Mem{Base: res_ptr}.Offset(16*1))
   133  	MOVOU(X2, Mem{Base: res_ptr}.Offset(16*2))
   134  	MOVOU(X3, Mem{Base: res_ptr}.Offset(16*3))
   135  	MOVOU(X4, Mem{Base: res_ptr}.Offset(16*4))
   136  	MOVOU(X5, Mem{Base: res_ptr}.Offset(16*5))
   137  
   138  	RET()
   139  }
   140  
   141  // Implements:
   142  //
   143  //	func p256NegCond(val *p256Element, cond int)
   144  func p256NegCond() {
   145  	Implement("p256NegCond")
   146  	Attributes(NOSPLIT)
   147  
   148  	Load(Param("val"), res_ptr)
   149  	Load(Param("cond"), t0_v1)
   150  
   151  	Comment("acc = poly")
   152  	MOVQ(I32(-1), acc0_v1)
   153  	p256const0 := p256const0_DATA()
   154  	MOVQ(p256const0, acc1_v1)
   155  	MOVQ(I32(0), acc2_v1)
   156  	p256const1 := p256const1_DATA()
   157  	MOVQ(p256const1, acc3_v1)
   158  
   159  	Comment("Load the original value")
   160  	MOVQ(Mem{Base: res_ptr}.Offset(8*0), acc5_v1)
   161  	MOVQ(Mem{Base: res_ptr}.Offset(8*1), x_ptr)
   162  	MOVQ(Mem{Base: res_ptr}.Offset(8*2), y_ptr)
   163  	MOVQ(Mem{Base: res_ptr}.Offset(8*3), t1_v1)
   164  
   165  	Comment("Speculatively subtract")
   166  	SUBQ(acc5_v1, acc0_v1)
   167  	SBBQ(x_ptr, acc1_v1)
   168  	SBBQ(y_ptr, acc2_v1)
   169  	SBBQ(t1_v1, acc3_v1)
   170  
   171  	Comment("If condition is 0, keep original value")
   172  	TESTQ(t0_v1, t0_v1)
   173  	CMOVQEQ(acc5_v1, acc0_v1)
   174  	CMOVQEQ(x_ptr, acc1_v1)
   175  	CMOVQEQ(y_ptr, acc2_v1)
   176  	CMOVQEQ(t1_v1, acc3_v1)
   177  
   178  	Comment("Store result")
   179  	MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*0))
   180  	MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*1))
   181  	MOVQ(acc2_v1, Mem{Base: res_ptr}.Offset(8*2))
   182  	MOVQ(acc3_v1, Mem{Base: res_ptr}.Offset(8*3))
   183  
   184  	RET()
   185  }
   186  
   187  // Implements:
   188  //
   189  //	func p256Sqr(res, in *p256Element, n int)
   190  func p256Sqr() {
   191  	Implement("p256Sqr")
   192  	Attributes(NOSPLIT)
   193  
   194  	Load(Param("res"), res_ptr)
   195  	Load(Param("in"), x_ptr)
   196  	Load(Param("n"), RBX)
   197  
   198  	Label("sqrLoop")
   199  
   200  	Comment("y[1:] * y[0]")
   201  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), t0_v1)
   202  
   203  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   204  	MULQ(t0_v1)
   205  	MOVQ(RAX, acc1_v1)
   206  	MOVQ(RDX, acc2_v1)
   207  
   208  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   209  	MULQ(t0_v1)
   210  	ADDQ(RAX, acc2_v1)
   211  	ADCQ(Imm(0), RDX)
   212  	MOVQ(RDX, acc3_v1)
   213  
   214  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   215  	MULQ(t0_v1)
   216  	ADDQ(RAX, acc3_v1)
   217  	ADCQ(Imm(0), RDX)
   218  	MOVQ(RDX, acc4_v1)
   219  
   220  	Comment("y[2:] * y[1]")
   221  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), t0_v1)
   222  
   223  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   224  	MULQ(t0_v1)
   225  	ADDQ(RAX, acc3_v1)
   226  	ADCQ(Imm(0), RDX)
   227  	MOVQ(RDX, t1_v1)
   228  
   229  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   230  	MULQ(t0_v1)
   231  	ADDQ(t1_v1, acc4_v1)
   232  	ADCQ(Imm(0), RDX)
   233  	ADDQ(RAX, acc4_v1)
   234  	ADCQ(Imm(0), RDX)
   235  	MOVQ(RDX, acc5_v1)
   236  
   237  	Comment("y[3] * y[2]")
   238  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), t0_v1)
   239  
   240  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   241  	MULQ(t0_v1)
   242  	ADDQ(RAX, acc5_v1)
   243  	ADCQ(Imm(0), RDX)
   244  	MOVQ(RDX, y_ptr)
   245  	XORQ(t1_v1, t1_v1)
   246  
   247  	Comment("*2")
   248  	ADDQ(acc1_v1, acc1_v1)
   249  	ADCQ(acc2_v1, acc2_v1)
   250  	ADCQ(acc3_v1, acc3_v1)
   251  	ADCQ(acc4_v1, acc4_v1)
   252  	ADCQ(acc5_v1, acc5_v1)
   253  	ADCQ(y_ptr, y_ptr)
   254  	ADCQ(Imm(0), t1_v1)
   255  
   256  	Comment("Missing products")
   257  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   258  	MULQ(RAX)
   259  	MOVQ(RAX, acc0_v1)
   260  	MOVQ(RDX, t0_v1)
   261  
   262  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   263  	MULQ(RAX)
   264  	ADDQ(t0_v1, acc1_v1)
   265  	ADCQ(RAX, acc2_v1)
   266  	ADCQ(Imm(0), RDX)
   267  	MOVQ(RDX, t0_v1)
   268  
   269  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   270  	MULQ(RAX)
   271  	ADDQ(t0_v1, acc3_v1)
   272  	ADCQ(RAX, acc4_v1)
   273  	ADCQ(Imm(0), RDX)
   274  	MOVQ(RDX, t0_v1)
   275  
   276  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   277  	MULQ(RAX)
   278  	ADDQ(t0_v1, acc5_v1)
   279  	ADCQ(RAX, y_ptr)
   280  	ADCQ(RDX, t1_v1)
   281  	MOVQ(t1_v1, x_ptr)
   282  
   283  	Comment("First reduction step")
   284  	MOVQ(acc0_v1, RAX)
   285  	MOVQ(acc0_v1, t1_v1)
   286  	SHLQ(Imm(32), acc0_v1)
   287  
   288  	p256const1 := p256const1_DATA()
   289  	MULQ(p256const1)
   290  
   291  	SHRQ(Imm(32), t1_v1)
   292  	ADDQ(acc0_v1, acc1_v1)
   293  	ADCQ(t1_v1, acc2_v1)
   294  	ADCQ(RAX, acc3_v1)
   295  	ADCQ(Imm(0), RDX)
   296  	MOVQ(RDX, acc0_v1)
   297  
   298  	Comment("Second reduction step")
   299  	MOVQ(acc1_v1, RAX)
   300  	MOVQ(acc1_v1, t1_v1)
   301  	SHLQ(Imm(32), acc1_v1)
   302  	MULQ(p256const1)
   303  	SHRQ(Imm(32), t1_v1)
   304  	ADDQ(acc1_v1, acc2_v1)
   305  	ADCQ(t1_v1, acc3_v1)
   306  	ADCQ(RAX, acc0_v1)
   307  	ADCQ(Imm(0), RDX)
   308  	MOVQ(RDX, acc1_v1)
   309  
   310  	Comment("Third reduction step")
   311  	MOVQ(acc2_v1, RAX)
   312  	MOVQ(acc2_v1, t1_v1)
   313  	SHLQ(Imm(32), acc2_v1)
   314  	MULQ(p256const1)
   315  	SHRQ(Imm(32), t1_v1)
   316  	ADDQ(acc2_v1, acc3_v1)
   317  	ADCQ(t1_v1, acc0_v1)
   318  	ADCQ(RAX, acc1_v1)
   319  	ADCQ(Imm(0), RDX)
   320  	MOVQ(RDX, acc2_v1)
   321  
   322  	Comment("Last reduction step")
   323  	XORQ(t0_v1, t0_v1)
   324  	MOVQ(acc3_v1, RAX)
   325  	MOVQ(acc3_v1, t1_v1)
   326  	SHLQ(Imm(32), acc3_v1)
   327  	MULQ(p256const1)
   328  	SHRQ(Imm(32), t1_v1)
   329  	ADDQ(acc3_v1, acc0_v1)
   330  	ADCQ(t1_v1, acc1_v1)
   331  	ADCQ(RAX, acc2_v1)
   332  	ADCQ(Imm(0), RDX)
   333  	MOVQ(RDX, acc3_v1)
   334  
   335  	Comment("Add bits [511:256] of the sqr result")
   336  	ADCQ(acc4_v1, acc0_v1)
   337  	ADCQ(acc5_v1, acc1_v1)
   338  	ADCQ(y_ptr, acc2_v1)
   339  	ADCQ(x_ptr, acc3_v1)
   340  	ADCQ(Imm(0), t0_v1)
   341  
   342  	MOVQ(acc0_v1, acc4_v1)
   343  	MOVQ(acc1_v1, acc5_v1)
   344  	MOVQ(acc2_v1, y_ptr)
   345  	MOVQ(acc3_v1, t1_v1)
   346  
   347  	Comment("Subtract p256")
   348  	SUBQ(I8(-1), acc0_v1)
   349  
   350  	p256const0 := p256const0_DATA()
   351  	SBBQ(p256const0, acc1_v1)
   352  	SBBQ(Imm(0), acc2_v1)
   353  	SBBQ(p256const1, acc3_v1)
   354  	SBBQ(Imm(0), t0_v1)
   355  
   356  	CMOVQCS(acc4_v1, acc0_v1)
   357  	CMOVQCS(acc5_v1, acc1_v1)
   358  	CMOVQCS(y_ptr, acc2_v1)
   359  	CMOVQCS(t1_v1, acc3_v1)
   360  
   361  	MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*0))
   362  	MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*1))
   363  	MOVQ(acc2_v1, Mem{Base: res_ptr}.Offset(8*2))
   364  	MOVQ(acc3_v1, Mem{Base: res_ptr}.Offset(8*3))
   365  	MOVQ(res_ptr, x_ptr)
   366  	DECQ(RBX)
   367  	JNE(LabelRef("sqrLoop"))
   368  
   369  	RET()
   370  }
   371  
   372  // Implements:
   373  //
   374  //	func p256Mul(res, in1, in2 *p256Element)
   375  func p256Mul() {
   376  	Implement("p256Mul")
   377  	Attributes(NOSPLIT)
   378  
   379  	Load(Param("res"), res_ptr)
   380  	Load(Param("in1"), x_ptr)
   381  	Load(Param("in2"), y_ptr)
   382  
   383  	Comment("x * y[0]")
   384  	MOVQ(Mem{Base: y_ptr}.Offset(8*0), t0_v1)
   385  
   386  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   387  	MULQ(t0_v1)
   388  	MOVQ(RAX, acc0_v1)
   389  	MOVQ(RDX, acc1_v1)
   390  
   391  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   392  	MULQ(t0_v1)
   393  	ADDQ(RAX, acc1_v1)
   394  	ADCQ(Imm(0), RDX)
   395  	MOVQ(RDX, acc2_v1)
   396  
   397  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   398  	MULQ(t0_v1)
   399  	ADDQ(RAX, acc2_v1)
   400  	ADCQ(Imm(0), RDX)
   401  	MOVQ(RDX, acc3_v1)
   402  
   403  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   404  	MULQ(t0_v1)
   405  	ADDQ(RAX, acc3_v1)
   406  	ADCQ(Imm(0), RDX)
   407  	MOVQ(RDX, acc4_v1)
   408  	XORQ(acc5_v1, acc5_v1)
   409  
   410  	Comment("First reduction step")
   411  	MOVQ(acc0_v1, RAX)
   412  	MOVQ(acc0_v1, t1_v1)
   413  	SHLQ(Imm(32), acc0_v1)
   414  	p256const1 := p256const1_DATA()
   415  	MULQ(p256const1)
   416  	SHRQ(Imm(32), t1_v1)
   417  	ADDQ(acc0_v1, acc1_v1)
   418  	ADCQ(t1_v1, acc2_v1)
   419  	ADCQ(RAX, acc3_v1)
   420  	ADCQ(RDX, acc4_v1)
   421  	ADCQ(Imm(0), acc5_v1)
   422  	XORQ(acc0_v1, acc0_v1)
   423  
   424  	Comment("x * y[1]")
   425  	MOVQ(Mem{Base: y_ptr}.Offset(8*1), t0_v1)
   426  
   427  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   428  	MULQ(t0_v1)
   429  	ADDQ(RAX, acc1_v1)
   430  	ADCQ(Imm(0), RDX)
   431  	MOVQ(RDX, t1_v1)
   432  
   433  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   434  	MULQ(t0_v1)
   435  	ADDQ(t1_v1, acc2_v1)
   436  	ADCQ(Imm(0), RDX)
   437  	ADDQ(RAX, acc2_v1)
   438  	ADCQ(Imm(0), RDX)
   439  	MOVQ(RDX, t1_v1)
   440  
   441  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   442  	MULQ(t0_v1)
   443  	ADDQ(t1_v1, acc3_v1)
   444  	ADCQ(Imm(0), RDX)
   445  	ADDQ(RAX, acc3_v1)
   446  	ADCQ(Imm(0), RDX)
   447  	MOVQ(RDX, t1_v1)
   448  
   449  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   450  	MULQ(t0_v1)
   451  	ADDQ(t1_v1, acc4_v1)
   452  	ADCQ(Imm(0), RDX)
   453  	ADDQ(RAX, acc4_v1)
   454  	ADCQ(RDX, acc5_v1)
   455  	ADCQ(Imm(0), acc0_v1)
   456  
   457  	Comment("Second reduction step")
   458  	MOVQ(acc1_v1, RAX)
   459  	MOVQ(acc1_v1, t1_v1)
   460  	SHLQ(Imm(32), acc1_v1)
   461  	MULQ(p256const1)
   462  	SHRQ(Imm(32), t1_v1)
   463  	ADDQ(acc1_v1, acc2_v1)
   464  	ADCQ(t1_v1, acc3_v1)
   465  	ADCQ(RAX, acc4_v1)
   466  	ADCQ(RDX, acc5_v1)
   467  	ADCQ(Imm(0), acc0_v1)
   468  	XORQ(acc1_v1, acc1_v1)
   469  
   470  	Comment("x * y[2]")
   471  	MOVQ(Mem{Base: y_ptr}.Offset(8*2), t0_v1)
   472  
   473  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   474  	MULQ(t0_v1)
   475  	ADDQ(RAX, acc2_v1)
   476  	ADCQ(Imm(0), RDX)
   477  	MOVQ(RDX, t1_v1)
   478  
   479  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   480  	MULQ(t0_v1)
   481  	ADDQ(t1_v1, acc3_v1)
   482  	ADCQ(Imm(0), RDX)
   483  	ADDQ(RAX, acc3_v1)
   484  	ADCQ(Imm(0), RDX)
   485  	MOVQ(RDX, t1_v1)
   486  
   487  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   488  	MULQ(t0_v1)
   489  	ADDQ(t1_v1, acc4_v1)
   490  	ADCQ(Imm(0), RDX)
   491  	ADDQ(RAX, acc4_v1)
   492  	ADCQ(Imm(0), RDX)
   493  	MOVQ(RDX, t1_v1)
   494  
   495  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   496  	MULQ(t0_v1)
   497  	ADDQ(t1_v1, acc5_v1)
   498  	ADCQ(Imm(0), RDX)
   499  	ADDQ(RAX, acc5_v1)
   500  	ADCQ(RDX, acc0_v1)
   501  	ADCQ(Imm(0), acc1_v1)
   502  
   503  	Comment("Third reduction step")
   504  	MOVQ(acc2_v1, RAX)
   505  	MOVQ(acc2_v1, t1_v1)
   506  	SHLQ(Imm(32), acc2_v1)
   507  	MULQ(p256const1)
   508  	SHRQ(Imm(32), t1_v1)
   509  	ADDQ(acc2_v1, acc3_v1)
   510  	ADCQ(t1_v1, acc4_v1)
   511  	ADCQ(RAX, acc5_v1)
   512  	ADCQ(RDX, acc0_v1)
   513  	ADCQ(Imm(0), acc1_v1)
   514  	XORQ(acc2_v1, acc2_v1)
   515  	Comment("x * y[3]")
   516  
   517  	MOVQ(Mem{Base: y_ptr}.Offset(8*3), t0_v1)
   518  
   519  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   520  	MULQ(t0_v1)
   521  	ADDQ(RAX, acc3_v1)
   522  	ADCQ(Imm(0), RDX)
   523  	MOVQ(RDX, t1_v1)
   524  
   525  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   526  	MULQ(t0_v1)
   527  	ADDQ(t1_v1, acc4_v1)
   528  	ADCQ(Imm(0), RDX)
   529  	ADDQ(RAX, acc4_v1)
   530  	ADCQ(Imm(0), RDX)
   531  	MOVQ(RDX, t1_v1)
   532  
   533  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   534  	MULQ(t0_v1)
   535  	ADDQ(t1_v1, acc5_v1)
   536  	ADCQ(Imm(0), RDX)
   537  	ADDQ(RAX, acc5_v1)
   538  	ADCQ(Imm(0), RDX)
   539  	MOVQ(RDX, t1_v1)
   540  
   541  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   542  	MULQ(t0_v1)
   543  	ADDQ(t1_v1, acc0_v1)
   544  	ADCQ(Imm(0), RDX)
   545  	ADDQ(RAX, acc0_v1)
   546  	ADCQ(RDX, acc1_v1)
   547  	ADCQ(Imm(0), acc2_v1)
   548  
   549  	Comment("Last reduction step")
   550  	MOVQ(acc3_v1, RAX)
   551  	MOVQ(acc3_v1, t1_v1)
   552  	SHLQ(Imm(32), acc3_v1)
   553  	MULQ(p256const1)
   554  	SHRQ(Imm(32), t1_v1)
   555  	ADDQ(acc3_v1, acc4_v1)
   556  	ADCQ(t1_v1, acc5_v1)
   557  	ADCQ(RAX, acc0_v1)
   558  	ADCQ(RDX, acc1_v1)
   559  	ADCQ(Imm(0), acc2_v1)
   560  
   561  	Comment("Copy result [255:0]")
   562  	MOVQ(acc4_v1, x_ptr)
   563  	MOVQ(acc5_v1, acc3_v1)
   564  	MOVQ(acc0_v1, t0_v1)
   565  	MOVQ(acc1_v1, t1_v1)
   566  
   567  	Comment("Subtract p256")
   568  	SUBQ(I8(-1), acc4_v1)
   569  	p256const0 := p256const0_DATA()
   570  	SBBQ(p256const0, acc5_v1)
   571  	SBBQ(Imm(0), acc0_v1)
   572  	// SBBQ p256const1<>(SB), acc1_v1
   573  	SBBQ(p256const1, acc1_v1)
   574  	SBBQ(Imm(0), acc2_v1)
   575  
   576  	CMOVQCS(x_ptr, acc4_v1)
   577  	CMOVQCS(acc3_v1, acc5_v1)
   578  	CMOVQCS(t0_v1, acc0_v1)
   579  	CMOVQCS(t1_v1, acc1_v1)
   580  
   581  	MOVQ(acc4_v1, Mem{Base: res_ptr}.Offset(8*0))
   582  	MOVQ(acc5_v1, Mem{Base: res_ptr}.Offset(8*1))
   583  	MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*2))
   584  	MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*3))
   585  
   586  	RET()
   587  }
   588  
   589  // Implements:
   590  //
   591  //	func p256FromMont(res, in *p256Element)
   592  func p256FromMont() {
   593  	Implement("p256FromMont")
   594  	Attributes(NOSPLIT)
   595  
   596  	Load(Param("res"), res_ptr)
   597  	Load(Param("in"), x_ptr)
   598  
   599  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), acc0_v1)
   600  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), acc1_v1)
   601  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), acc2_v1)
   602  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), acc3_v1)
   603  	XORQ(acc4_v1, acc4_v1)
   604  
   605  	Comment("Only reduce, no multiplications are needed")
   606  	Comment("First stage")
   607  	MOVQ(acc0_v1, RAX)
   608  	MOVQ(acc0_v1, t1_v1)
   609  	SHLQ(Imm(32), acc0_v1)
   610  	p256const1 := p256const1_DATA()
   611  	MULQ(p256const1)
   612  	SHRQ(Imm(32), t1_v1)
   613  	ADDQ(acc0_v1, acc1_v1)
   614  	ADCQ(t1_v1, acc2_v1)
   615  	ADCQ(RAX, acc3_v1)
   616  	ADCQ(RDX, acc4_v1)
   617  	XORQ(acc5_v1, acc5_v1)
   618  
   619  	Comment("Second stage")
   620  	MOVQ(acc1_v1, RAX)
   621  	MOVQ(acc1_v1, t1_v1)
   622  	SHLQ(Imm(32), acc1_v1)
   623  	MULQ(p256const1)
   624  	SHRQ(Imm(32), t1_v1)
   625  	ADDQ(acc1_v1, acc2_v1)
   626  	ADCQ(t1_v1, acc3_v1)
   627  	ADCQ(RAX, acc4_v1)
   628  	ADCQ(RDX, acc5_v1)
   629  	XORQ(acc0_v1, acc0_v1)
   630  
   631  	Comment("Third stage")
   632  	MOVQ(acc2_v1, RAX)
   633  	MOVQ(acc2_v1, t1_v1)
   634  	SHLQ(Imm(32), acc2_v1)
   635  	MULQ(p256const1)
   636  	SHRQ(Imm(32), t1_v1)
   637  	ADDQ(acc2_v1, acc3_v1)
   638  	ADCQ(t1_v1, acc4_v1)
   639  	ADCQ(RAX, acc5_v1)
   640  	ADCQ(RDX, acc0_v1)
   641  	XORQ(acc1_v1, acc1_v1)
   642  
   643  	Comment("Last stage")
   644  	MOVQ(acc3_v1, RAX)
   645  	MOVQ(acc3_v1, t1_v1)
   646  	SHLQ(Imm(32), acc3_v1)
   647  	MULQ(p256const1)
   648  	SHRQ(Imm(32), t1_v1)
   649  	ADDQ(acc3_v1, acc4_v1)
   650  	ADCQ(t1_v1, acc5_v1)
   651  	ADCQ(RAX, acc0_v1)
   652  	ADCQ(RDX, acc1_v1)
   653  
   654  	MOVQ(acc4_v1, x_ptr)
   655  	MOVQ(acc5_v1, acc3_v1)
   656  	MOVQ(acc0_v1, t0_v1)
   657  	MOVQ(acc1_v1, t1_v1)
   658  
   659  	SUBQ(I8(-1), acc4_v1)
   660  	p256const0 := p256const0_DATA()
   661  	SBBQ(p256const0, acc5_v1)
   662  	SBBQ(Imm(0), acc0_v1)
   663  	SBBQ(p256const1, acc1_v1)
   664  
   665  	CMOVQCS(x_ptr, acc4_v1)
   666  	CMOVQCS(acc3_v1, acc5_v1)
   667  	CMOVQCS(t0_v1, acc0_v1)
   668  	CMOVQCS(t1_v1, acc1_v1)
   669  
   670  	MOVQ(acc4_v1, Mem{Base: res_ptr}.Offset(8*0))
   671  	MOVQ(acc5_v1, Mem{Base: res_ptr}.Offset(8*1))
   672  	MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*2))
   673  	MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*3))
   674  
   675  	RET()
   676  }
   677  
   678  // Implements:
   679  //
   680  //	func p256Select(res *P256Point, table *p256Table, idx int)
   681  func p256Select() {
   682  	Implement("p256Select")
   683  	Attributes(NOSPLIT)
   684  
   685  	Load(Param("idx"), RAX)
   686  	Load(Param("table"), RDI)
   687  	Load(Param("res"), RDX)
   688  
   689  	PXOR(X15, X15)    // X15 =  0
   690  	PCMPEQL(X14, X14) // X14 = -1
   691  	PSUBL(X14, X15)   // X15 =  1
   692  	// Force Avo to emit:
   693  	// 	MOVL AX, X14
   694  	Instruction(&ir.Instruction{
   695  		Opcode: "MOVL",
   696  		Operands: []Op{
   697  			EAX, X14,
   698  		},
   699  	})
   700  	PSHUFD(Imm(0), X14, X14)
   701  
   702  	PXOR(X0, X0)
   703  	PXOR(X1, X1)
   704  	PXOR(X2, X2)
   705  	PXOR(X3, X3)
   706  	PXOR(X4, X4)
   707  	PXOR(X5, X5)
   708  	MOVQ(U32(16), RAX)
   709  
   710  	MOVOU(X15, X13)
   711  
   712  	Label("loop_select")
   713  
   714  	MOVOU(X13, X12)
   715  	PADDL(X15, X13)
   716  	PCMPEQL(X14, X12)
   717  
   718  	MOVOU(Mem{Base: DI}.Offset(16*0), X6)
   719  	MOVOU(Mem{Base: DI}.Offset(16*1), X7)
   720  	MOVOU(Mem{Base: DI}.Offset(16*2), X8)
   721  	MOVOU(Mem{Base: DI}.Offset(16*3), X9)
   722  	MOVOU(Mem{Base: DI}.Offset(16*4), X10)
   723  	MOVOU(Mem{Base: DI}.Offset(16*5), X11)
   724  	ADDQ(U8(16*6), RDI)
   725  
   726  	PAND(X12, X6)
   727  	PAND(X12, X7)
   728  	PAND(X12, X8)
   729  	PAND(X12, X9)
   730  	PAND(X12, X10)
   731  	PAND(X12, X11)
   732  
   733  	PXOR(X6, X0)
   734  	PXOR(X7, X1)
   735  	PXOR(X8, X2)
   736  	PXOR(X9, X3)
   737  	PXOR(X10, X4)
   738  	PXOR(X11, X5)
   739  
   740  	DECQ(RAX)
   741  	JNE(LabelRef("loop_select"))
   742  
   743  	MOVOU(X0, Mem{Base: DX}.Offset(16*0))
   744  	MOVOU(X1, Mem{Base: DX}.Offset(16*1))
   745  	MOVOU(X2, Mem{Base: DX}.Offset(16*2))
   746  	MOVOU(X3, Mem{Base: DX}.Offset(16*3))
   747  	MOVOU(X4, Mem{Base: DX}.Offset(16*4))
   748  	MOVOU(X5, Mem{Base: DX}.Offset(16*5))
   749  
   750  	RET()
   751  }
   752  
   753  // Implements:
   754  //
   755  //	func p256SelectAffine(res *p256AffinePoint, table *p256AffineTable, idx int)
   756  func p256SelectAffine() {
   757  	Implement("p256SelectAffine")
   758  	Attributes(NOSPLIT)
   759  
   760  	Load(Param("idx"), RAX)
   761  	Load(Param("table"), RDI)
   762  	Load(Param("res"), RDX)
   763  
   764  	PXOR(X15, X15)    // X15 =  0
   765  	PCMPEQL(X14, X14) // X14 = -1
   766  	PSUBL(X14, X15)   // X15 =  1
   767  
   768  	// Hack to get Avo to emit:
   769  	// 	MOVL AX, X14
   770  	Instruction(&ir.Instruction{Opcode: "MOVL", Operands: []Op{RAX, X14}})
   771  
   772  	PSHUFD(Imm(0), X14, X14)
   773  
   774  	PXOR(X0, X0)
   775  	PXOR(X1, X1)
   776  	PXOR(X2, X2)
   777  	PXOR(X3, X3)
   778  	MOVQ(U32(16), RAX)
   779  
   780  	MOVOU(X15, X13)
   781  
   782  	Label("loop_select_base")
   783  
   784  	MOVOU(X13, X12)
   785  	PADDL(X15, X13)
   786  	PCMPEQL(X14, X12)
   787  
   788  	MOVOU(Mem{Base: DI}.Offset(16*0), X4)
   789  	MOVOU(Mem{Base: DI}.Offset(16*1), X5)
   790  	MOVOU(Mem{Base: DI}.Offset(16*2), X6)
   791  	MOVOU(Mem{Base: DI}.Offset(16*3), X7)
   792  
   793  	MOVOU(Mem{Base: DI}.Offset(16*4), X8)
   794  	MOVOU(Mem{Base: DI}.Offset(16*5), X9)
   795  	MOVOU(Mem{Base: DI}.Offset(16*6), X10)
   796  	MOVOU(Mem{Base: DI}.Offset(16*7), X11)
   797  
   798  	ADDQ(Imm(16*8), RDI)
   799  
   800  	PAND(X12, X4)
   801  	PAND(X12, X5)
   802  	PAND(X12, X6)
   803  	PAND(X12, X7)
   804  
   805  	MOVOU(X13, X12)
   806  	PADDL(X15, X13)
   807  	PCMPEQL(X14, X12)
   808  
   809  	PAND(X12, X8)
   810  	PAND(X12, X9)
   811  	PAND(X12, X10)
   812  	PAND(X12, X11)
   813  
   814  	PXOR(X4, X0)
   815  	PXOR(X5, X1)
   816  	PXOR(X6, X2)
   817  	PXOR(X7, X3)
   818  
   819  	PXOR(X8, X0)
   820  	PXOR(X9, X1)
   821  	PXOR(X10, X2)
   822  	PXOR(X11, X3)
   823  
   824  	DECQ(RAX)
   825  	JNE(LabelRef("loop_select_base"))
   826  
   827  	MOVOU(X0, Mem{Base: DX}.Offset(16*0))
   828  	MOVOU(X1, Mem{Base: DX}.Offset(16*1))
   829  	MOVOU(X2, Mem{Base: DX}.Offset(16*2))
   830  	MOVOU(X3, Mem{Base: DX}.Offset(16*3))
   831  
   832  	RET()
   833  }
   834  
   835  // Implements:
   836  //
   837  //	func p256OrdMul(res, in1, in2 *p256OrdElement)
   838  func p256OrdMul() {
   839  	Implement("p256OrdMul")
   840  	Attributes(NOSPLIT)
   841  
   842  	Load(Param("res"), res_ptr)
   843  	Load(Param("in1"), x_ptr)
   844  	Load(Param("in2"), y_ptr)
   845  
   846  	Comment("x * y[0]")
   847  	MOVQ(Mem{Base: y_ptr}.Offset(8*0), t0_v1)
   848  
   849  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   850  	MULQ(t0_v1)
   851  	MOVQ(RAX, acc0_v1)
   852  	MOVQ(RDX, acc1_v1)
   853  
   854  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   855  	MULQ(t0_v1)
   856  	ADDQ(RAX, acc1_v1)
   857  	ADCQ(Imm(0), RDX)
   858  	MOVQ(RDX, acc2_v1)
   859  
   860  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   861  	MULQ(t0_v1)
   862  	ADDQ(RAX, acc2_v1)
   863  	ADCQ(Imm(0), RDX)
   864  	MOVQ(RDX, acc3_v1)
   865  
   866  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   867  	MULQ(t0_v1)
   868  	ADDQ(RAX, acc3_v1)
   869  	ADCQ(Imm(0), RDX)
   870  	MOVQ(RDX, acc4_v1)
   871  	XORQ(acc5_v1, acc5_v1)
   872  
   873  	Comment("First reduction step")
   874  	MOVQ(acc0_v1, RAX)
   875  	p256ordK0 := p256ordK0_DATA()
   876  	MULQ(p256ordK0)
   877  	MOVQ(RAX, t0_v1)
   878  
   879  	p256ord := p256ord_DATA()
   880  	MOVQ(p256ord.Offset(0x00), RAX)
   881  	MULQ(t0_v1)
   882  	ADDQ(RAX, acc0_v1)
   883  	ADCQ(Imm(0), RDX)
   884  	MOVQ(RDX, t1_v1)
   885  
   886  	MOVQ(p256ord.Offset(0x08), RAX)
   887  	MULQ(t0_v1)
   888  	ADDQ(t1_v1, acc1_v1)
   889  	ADCQ(Imm(0), RDX)
   890  	ADDQ(RAX, acc1_v1)
   891  	ADCQ(Imm(0), RDX)
   892  	MOVQ(RDX, t1_v1)
   893  
   894  	MOVQ(p256ord.Offset(0x10), RAX)
   895  	MULQ(t0_v1)
   896  	ADDQ(t1_v1, acc2_v1)
   897  	ADCQ(Imm(0), RDX)
   898  	ADDQ(RAX, acc2_v1)
   899  	ADCQ(Imm(0), RDX)
   900  	MOVQ(RDX, t1_v1)
   901  
   902  	MOVQ(p256ord.Offset(0x18), RAX)
   903  	MULQ(t0_v1)
   904  	ADDQ(t1_v1, acc3_v1)
   905  	ADCQ(Imm(0), RDX)
   906  	ADDQ(RAX, acc3_v1)
   907  	ADCQ(RDX, acc4_v1)
   908  	ADCQ(Imm(0), acc5_v1)
   909  
   910  	Comment("x * y[1]")
   911  	MOVQ(Mem{Base: y_ptr}.Offset(8*1), t0_v1)
   912  
   913  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   914  	MULQ(t0_v1)
   915  	ADDQ(RAX, acc1_v1)
   916  	ADCQ(Imm(0), RDX)
   917  	MOVQ(RDX, t1_v1)
   918  
   919  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   920  	MULQ(t0_v1)
   921  	ADDQ(t1_v1, acc2_v1)
   922  	ADCQ(Imm(0), RDX)
   923  	ADDQ(RAX, acc2_v1)
   924  	ADCQ(Imm(0), RDX)
   925  	MOVQ(RDX, t1_v1)
   926  
   927  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   928  	MULQ(t0_v1)
   929  	ADDQ(t1_v1, acc3_v1)
   930  	ADCQ(Imm(0), RDX)
   931  	ADDQ(RAX, acc3_v1)
   932  	ADCQ(Imm(0), RDX)
   933  	MOVQ(RDX, t1_v1)
   934  
   935  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   936  	MULQ(t0_v1)
   937  	ADDQ(t1_v1, acc4_v1)
   938  	ADCQ(Imm(0), RDX)
   939  	ADDQ(RAX, acc4_v1)
   940  	ADCQ(RDX, acc5_v1)
   941  	ADCQ(Imm(0), acc0_v1)
   942  
   943  	Comment("Second reduction step")
   944  	MOVQ(acc1_v1, RAX)
   945  	MULQ(p256ordK0)
   946  	MOVQ(RAX, t0_v1)
   947  
   948  	MOVQ(p256ord.Offset(0x00), RAX)
   949  	MULQ(t0_v1)
   950  	ADDQ(RAX, acc1_v1)
   951  	ADCQ(Imm(0), RDX)
   952  	MOVQ(RDX, t1_v1)
   953  
   954  	MOVQ(p256ord.Offset(0x08), RAX)
   955  	MULQ(t0_v1)
   956  	ADDQ(t1_v1, acc2_v1)
   957  	ADCQ(Imm(0), RDX)
   958  	ADDQ(RAX, acc2_v1)
   959  	ADCQ(Imm(0), RDX)
   960  	MOVQ(RDX, t1_v1)
   961  
   962  	MOVQ(p256ord.Offset(0x10), RAX)
   963  	MULQ(t0_v1)
   964  	ADDQ(t1_v1, acc3_v1)
   965  	ADCQ(Imm(0), RDX)
   966  	ADDQ(RAX, acc3_v1)
   967  	ADCQ(Imm(0), RDX)
   968  	MOVQ(RDX, t1_v1)
   969  
   970  	MOVQ(p256ord.Offset(0x18), RAX)
   971  	MULQ(t0_v1)
   972  	ADDQ(t1_v1, acc4_v1)
   973  	ADCQ(Imm(0), RDX)
   974  	ADDQ(RAX, acc4_v1)
   975  	ADCQ(RDX, acc5_v1)
   976  	ADCQ(Imm(0), acc0_v1)
   977  
   978  	Comment("x * y[2]")
   979  	MOVQ(Mem{Base: y_ptr}.Offset(8*2), t0_v1)
   980  
   981  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   982  	MULQ(t0_v1)
   983  	ADDQ(RAX, acc2_v1)
   984  	ADCQ(Imm(0), RDX)
   985  	MOVQ(RDX, t1_v1)
   986  
   987  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   988  	MULQ(t0_v1)
   989  	ADDQ(t1_v1, acc3_v1)
   990  	ADCQ(Imm(0), RDX)
   991  	ADDQ(RAX, acc3_v1)
   992  	ADCQ(Imm(0), RDX)
   993  	MOVQ(RDX, t1_v1)
   994  
   995  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   996  	MULQ(t0_v1)
   997  	ADDQ(t1_v1, acc4_v1)
   998  	ADCQ(Imm(0), RDX)
   999  	ADDQ(RAX, acc4_v1)
  1000  	ADCQ(Imm(0), RDX)
  1001  	MOVQ(RDX, t1_v1)
  1002  
  1003  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
  1004  	MULQ(t0_v1)
  1005  	ADDQ(t1_v1, acc5_v1)
  1006  	ADCQ(Imm(0), RDX)
  1007  	ADDQ(RAX, acc5_v1)
  1008  	ADCQ(RDX, acc0_v1)
  1009  	ADCQ(Imm(0), acc1_v1)
  1010  
  1011  	Comment("Third reduction step")
  1012  	MOVQ(acc2_v1, RAX)
  1013  	MULQ(p256ordK0)
  1014  	MOVQ(RAX, t0_v1)
  1015  
  1016  	MOVQ(p256ord.Offset(0x00), RAX)
  1017  	MULQ(t0_v1)
  1018  	ADDQ(RAX, acc2_v1)
  1019  	ADCQ(Imm(0), RDX)
  1020  	MOVQ(RDX, t1_v1)
  1021  
  1022  	MOVQ(p256ord.Offset(0x08), RAX)
  1023  	MULQ(t0_v1)
  1024  	ADDQ(t1_v1, acc3_v1)
  1025  	ADCQ(Imm(0), RDX)
  1026  	ADDQ(RAX, acc3_v1)
  1027  	ADCQ(Imm(0), RDX)
  1028  	MOVQ(RDX, t1_v1)
  1029  
  1030  	MOVQ(p256ord.Offset(0x10), RAX)
  1031  	MULQ(t0_v1)
  1032  	ADDQ(t1_v1, acc4_v1)
  1033  	ADCQ(Imm(0), RDX)
  1034  	ADDQ(RAX, acc4_v1)
  1035  	ADCQ(Imm(0), RDX)
  1036  	MOVQ(RDX, t1_v1)
  1037  
  1038  	MOVQ(p256ord.Offset(0x18), RAX)
  1039  	MULQ(t0_v1)
  1040  	ADDQ(t1_v1, acc5_v1)
  1041  	ADCQ(Imm(0), RDX)
  1042  	ADDQ(RAX, acc5_v1)
  1043  	ADCQ(RDX, acc0_v1)
  1044  	ADCQ(Imm(0), acc1_v1)
  1045  
  1046  	Comment("x * y[3]")
  1047  	MOVQ(Mem{Base: y_ptr}.Offset(8*3), t0_v1)
  1048  
  1049  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
  1050  	MULQ(t0_v1)
  1051  	ADDQ(RAX, acc3_v1)
  1052  	ADCQ(Imm(0), RDX)
  1053  	MOVQ(RDX, t1_v1)
  1054  
  1055  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
  1056  	MULQ(t0_v1)
  1057  	ADDQ(t1_v1, acc4_v1)
  1058  	ADCQ(Imm(0), RDX)
  1059  	ADDQ(RAX, acc4_v1)
  1060  	ADCQ(Imm(0), RDX)
  1061  	MOVQ(RDX, t1_v1)
  1062  
  1063  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
  1064  	MULQ(t0_v1)
  1065  	ADDQ(t1_v1, acc5_v1)
  1066  	ADCQ(Imm(0), RDX)
  1067  	ADDQ(RAX, acc5_v1)
  1068  	ADCQ(Imm(0), RDX)
  1069  	MOVQ(RDX, t1_v1)
  1070  
  1071  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
  1072  	MULQ(t0_v1)
  1073  	ADDQ(t1_v1, acc0_v1)
  1074  	ADCQ(Imm(0), RDX)
  1075  	ADDQ(RAX, acc0_v1)
  1076  	ADCQ(RDX, acc1_v1)
  1077  	ADCQ(Imm(0), acc2_v1)
  1078  
  1079  	Comment("Last reduction step")
  1080  	MOVQ(acc3_v1, RAX)
  1081  	MULQ(p256ordK0)
  1082  	MOVQ(RAX, t0_v1)
  1083  
  1084  	MOVQ(p256ord.Offset(0x00), RAX)
  1085  	MULQ(t0_v1)
  1086  	ADDQ(RAX, acc3_v1)
  1087  	ADCQ(Imm(0), RDX)
  1088  	MOVQ(RDX, t1_v1)
  1089  
  1090  	MOVQ(p256ord.Offset(0x08), RAX)
  1091  	MULQ(t0_v1)
  1092  	ADDQ(t1_v1, acc4_v1)
  1093  	ADCQ(Imm(0), RDX)
  1094  	ADDQ(RAX, acc4_v1)
  1095  	ADCQ(Imm(0), RDX)
  1096  	MOVQ(RDX, t1_v1)
  1097  
  1098  	MOVQ(p256ord.Offset(0x10), RAX)
  1099  	MULQ(t0_v1)
  1100  	ADDQ(t1_v1, acc5_v1)
  1101  	ADCQ(Imm(0), RDX)
  1102  	ADDQ(RAX, acc5_v1)
  1103  	ADCQ(Imm(0), RDX)
  1104  	MOVQ(RDX, t1_v1)
  1105  
  1106  	MOVQ(p256ord.Offset(0x18), RAX)
  1107  	MULQ(t0_v1)
  1108  	ADDQ(t1_v1, acc0_v1)
  1109  	ADCQ(Imm(0), RDX)
  1110  	ADDQ(RAX, acc0_v1)
  1111  	ADCQ(RDX, acc1_v1)
  1112  	ADCQ(Imm(0), acc2_v1)
  1113  
  1114  	Comment("Copy result [255:0]")
  1115  	MOVQ(acc4_v1, x_ptr)
  1116  	MOVQ(acc5_v1, acc3_v1)
  1117  	MOVQ(acc0_v1, t0_v1)
  1118  	MOVQ(acc1_v1, t1_v1)
  1119  
  1120  	Comment("Subtract p256")
  1121  	SUBQ(p256ord.Offset(0x00), acc4_v1)
  1122  	SBBQ(p256ord.Offset(0x08), acc5_v1)
  1123  	SBBQ(p256ord.Offset(0x10), acc0_v1)
  1124  	SBBQ(p256ord.Offset(0x18), acc1_v1)
  1125  	SBBQ(Imm(0), acc2_v1)
  1126  
  1127  	CMOVQCS(x_ptr, acc4_v1)
  1128  	CMOVQCS(acc3_v1, acc5_v1)
  1129  	CMOVQCS(t0_v1, acc0_v1)
  1130  	CMOVQCS(t1_v1, acc1_v1)
  1131  
  1132  	MOVQ(acc4_v1, Mem{Base: res_ptr}.Offset(8*0))
  1133  	MOVQ(acc5_v1, Mem{Base: res_ptr}.Offset(8*1))
  1134  	MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*2))
  1135  	MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*3))
  1136  
  1137  	RET()
  1138  }
  1139  
  1140  // Implements:
  1141  //
  1142  //	func p256OrdSqr(res, in *p256OrdElement, n int)
  1143  func p256OrdSqr() {
  1144  	Implement("p256OrdSqr")
  1145  	Attributes(NOSPLIT)
  1146  
  1147  	Load(Param("res"), res_ptr)
  1148  	Load(Param("in"), x_ptr)
  1149  	Load(Param("n"), RBX)
  1150  
  1151  	Label("ordSqrLoop")
  1152  
  1153  	Comment("y[1:] * y[0]")
  1154  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), t0_v1)
  1155  
  1156  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
  1157  	MULQ(t0_v1)
  1158  	MOVQ(RAX, acc1_v1)
  1159  	MOVQ(RDX, acc2_v1)
  1160  
  1161  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
  1162  	MULQ(t0_v1)
  1163  	ADDQ(RAX, acc2_v1)
  1164  	ADCQ(Imm(0), RDX)
  1165  	MOVQ(RDX, acc3_v1)
  1166  
  1167  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
  1168  	MULQ(t0_v1)
  1169  	ADDQ(RAX, acc3_v1)
  1170  	ADCQ(Imm(0), RDX)
  1171  	MOVQ(RDX, acc4_v1)
  1172  
  1173  	Comment("y[2:] * y[1]")
  1174  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), t0_v1)
  1175  
  1176  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
  1177  	MULQ(t0_v1)
  1178  	ADDQ(RAX, acc3_v1)
  1179  	ADCQ(Imm(0), RDX)
  1180  	MOVQ(RDX, t1_v1)
  1181  
  1182  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
  1183  	MULQ(t0_v1)
  1184  	ADDQ(t1_v1, acc4_v1)
  1185  	ADCQ(Imm(0), RDX)
  1186  	ADDQ(RAX, acc4_v1)
  1187  	ADCQ(Imm(0), RDX)
  1188  	MOVQ(RDX, acc5_v1)
  1189  
  1190  	Comment("y[3] * y[2]")
  1191  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), t0_v1)
  1192  
  1193  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
  1194  	MULQ(t0_v1)
  1195  	ADDQ(RAX, acc5_v1)
  1196  	ADCQ(Imm(0), RDX)
  1197  	MOVQ(RDX, y_ptr)
  1198  	XORQ(t1_v1, t1_v1)
  1199  
  1200  	Comment("*2")
  1201  	ADDQ(acc1_v1, acc1_v1)
  1202  	ADCQ(acc2_v1, acc2_v1)
  1203  	ADCQ(acc3_v1, acc3_v1)
  1204  	ADCQ(acc4_v1, acc4_v1)
  1205  	ADCQ(acc5_v1, acc5_v1)
  1206  	ADCQ(y_ptr, y_ptr)
  1207  	ADCQ(Imm(0), t1_v1)
  1208  
  1209  	Comment("Missing products")
  1210  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
  1211  	MULQ(RAX)
  1212  	MOVQ(RAX, acc0_v1)
  1213  	MOVQ(RDX, t0_v1)
  1214  
  1215  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
  1216  	MULQ(RAX)
  1217  	ADDQ(t0_v1, acc1_v1)
  1218  	ADCQ(RAX, acc2_v1)
  1219  	ADCQ(Imm(0), RDX)
  1220  	MOVQ(RDX, t0_v1)
  1221  
  1222  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
  1223  	MULQ(RAX)
  1224  	ADDQ(t0_v1, acc3_v1)
  1225  	ADCQ(RAX, acc4_v1)
  1226  	ADCQ(Imm(0), RDX)
  1227  	MOVQ(RDX, t0_v1)
  1228  
  1229  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
  1230  	MULQ(RAX)
  1231  	ADDQ(t0_v1, acc5_v1)
  1232  	ADCQ(RAX, y_ptr)
  1233  	ADCQ(RDX, t1_v1)
  1234  	MOVQ(t1_v1, x_ptr)
  1235  
  1236  	Comment("First reduction step")
  1237  	MOVQ(acc0_v1, RAX)
  1238  	p256ordK0 := p256ordK0_DATA()
  1239  	MULQ(p256ordK0)
  1240  	MOVQ(RAX, t0_v1)
  1241  
  1242  	p256ord := p256ord_DATA()
  1243  	MOVQ(p256ord.Offset(0x00), RAX)
  1244  	MULQ(t0_v1)
  1245  	ADDQ(RAX, acc0_v1)
  1246  	ADCQ(Imm(0), RDX)
  1247  	MOVQ(RDX, t1_v1)
  1248  
  1249  	MOVQ(p256ord.Offset(0x08), RAX)
  1250  	MULQ(t0_v1)
  1251  	ADDQ(t1_v1, acc1_v1)
  1252  	ADCQ(Imm(0), RDX)
  1253  	ADDQ(RAX, acc1_v1)
  1254  
  1255  	MOVQ(t0_v1, t1_v1)
  1256  	ADCQ(RDX, acc2_v1)
  1257  	ADCQ(Imm(0), t1_v1)
  1258  	SUBQ(t0_v1, acc2_v1)
  1259  	SBBQ(Imm(0), t1_v1)
  1260  
  1261  	MOVQ(t0_v1, RAX)
  1262  	MOVQ(t0_v1, RDX)
  1263  	MOVQ(t0_v1, acc0_v1)
  1264  	SHLQ(Imm(32), RAX)
  1265  	SHRQ(Imm(32), RDX)
  1266  
  1267  	ADDQ(t1_v1, acc3_v1)
  1268  	ADCQ(Imm(0), acc0_v1)
  1269  	SUBQ(RAX, acc3_v1)
  1270  	SBBQ(RDX, acc0_v1)
  1271  
  1272  	Comment("Second reduction step")
  1273  	MOVQ(acc1_v1, RAX)
  1274  	MULQ(p256ordK0)
  1275  	MOVQ(RAX, t0_v1)
  1276  
  1277  	MOVQ(p256ord.Offset(0x00), RAX)
  1278  	MULQ(t0_v1)
  1279  	ADDQ(RAX, acc1_v1)
  1280  	ADCQ(Imm(0), RDX)
  1281  	MOVQ(RDX, t1_v1)
  1282  
  1283  	MOVQ(p256ord.Offset(0x08), RAX)
  1284  	MULQ(t0_v1)
  1285  	ADDQ(t1_v1, acc2_v1)
  1286  	ADCQ(Imm(0), RDX)
  1287  	ADDQ(RAX, acc2_v1)
  1288  
  1289  	MOVQ(t0_v1, t1_v1)
  1290  	ADCQ(RDX, acc3_v1)
  1291  	ADCQ(Imm(0), t1_v1)
  1292  	SUBQ(t0_v1, acc3_v1)
  1293  	SBBQ(Imm(0), t1_v1)
  1294  
  1295  	MOVQ(t0_v1, RAX)
  1296  	MOVQ(t0_v1, RDX)
  1297  	MOVQ(t0_v1, acc1_v1)
  1298  	SHLQ(Imm(32), RAX)
  1299  	SHRQ(Imm(32), RDX)
  1300  
  1301  	ADDQ(t1_v1, acc0_v1)
  1302  	ADCQ(Imm(0), acc1_v1)
  1303  	SUBQ(RAX, acc0_v1)
  1304  	SBBQ(RDX, acc1_v1)
  1305  
  1306  	Comment("Third reduction step")
  1307  	MOVQ(acc2_v1, RAX)
  1308  	MULQ(p256ordK0)
  1309  	MOVQ(RAX, t0_v1)
  1310  
  1311  	MOVQ(p256ord.Offset(0x00), RAX)
  1312  	MULQ(t0_v1)
  1313  	ADDQ(RAX, acc2_v1)
  1314  	ADCQ(Imm(0), RDX)
  1315  	MOVQ(RDX, t1_v1)
  1316  
  1317  	MOVQ(p256ord.Offset(0x08), RAX)
  1318  	MULQ(t0_v1)
  1319  	ADDQ(t1_v1, acc3_v1)
  1320  	ADCQ(Imm(0), RDX)
  1321  	ADDQ(RAX, acc3_v1)
  1322  
  1323  	MOVQ(t0_v1, t1_v1)
  1324  	ADCQ(RDX, acc0_v1)
  1325  	ADCQ(Imm(0), t1_v1)
  1326  	SUBQ(t0_v1, acc0_v1)
  1327  	SBBQ(Imm(0), t1_v1)
  1328  
  1329  	MOVQ(t0_v1, RAX)
  1330  	MOVQ(t0_v1, RDX)
  1331  	MOVQ(t0_v1, acc2_v1)
  1332  	SHLQ(Imm(32), RAX)
  1333  	SHRQ(Imm(32), RDX)
  1334  
  1335  	ADDQ(t1_v1, acc1_v1)
  1336  	ADCQ(Imm(0), acc2_v1)
  1337  	SUBQ(RAX, acc1_v1)
  1338  	SBBQ(RDX, acc2_v1)
  1339  
  1340  	Comment("Last reduction step")
  1341  	MOVQ(acc3_v1, RAX)
  1342  	MULQ(p256ordK0)
  1343  	MOVQ(RAX, t0_v1)
  1344  
  1345  	MOVQ(p256ord.Offset(0x00), RAX)
  1346  	MULQ(t0_v1)
  1347  	ADDQ(RAX, acc3_v1)
  1348  	ADCQ(Imm(0), RDX)
  1349  	MOVQ(RDX, t1_v1)
  1350  
  1351  	MOVQ(p256ord.Offset(0x08), RAX)
  1352  	MULQ(t0_v1)
  1353  	ADDQ(t1_v1, acc0_v1)
  1354  	ADCQ(Imm(0), RDX)
  1355  	ADDQ(RAX, acc0_v1)
  1356  	ADCQ(Imm(0), RDX)
  1357  	MOVQ(RDX, t1_v1)
  1358  
  1359  	MOVQ(t0_v1, t1_v1)
  1360  	ADCQ(RDX, acc1_v1)
  1361  	ADCQ(Imm(0), t1_v1)
  1362  	SUBQ(t0_v1, acc1_v1)
  1363  	SBBQ(Imm(0), t1_v1)
  1364  
  1365  	MOVQ(t0_v1, RAX)
  1366  	MOVQ(t0_v1, RDX)
  1367  	MOVQ(t0_v1, acc3_v1)
  1368  	SHLQ(Imm(32), RAX)
  1369  	SHRQ(Imm(32), RDX)
  1370  
  1371  	ADDQ(t1_v1, acc2_v1)
  1372  	ADCQ(Imm(0), acc3_v1)
  1373  	SUBQ(RAX, acc2_v1)
  1374  	SBBQ(RDX, acc3_v1)
  1375  	XORQ(t0_v1, t0_v1)
  1376  
  1377  	Comment("Add bits [511:256] of the sqr result")
  1378  	ADCQ(acc4_v1, acc0_v1)
  1379  	ADCQ(acc5_v1, acc1_v1)
  1380  	ADCQ(y_ptr, acc2_v1)
  1381  	ADCQ(x_ptr, acc3_v1)
  1382  	ADCQ(Imm(0), t0_v1)
  1383  
  1384  	MOVQ(acc0_v1, acc4_v1)
  1385  	MOVQ(acc1_v1, acc5_v1)
  1386  	MOVQ(acc2_v1, y_ptr)
  1387  	MOVQ(acc3_v1, t1_v1)
  1388  
  1389  	Comment("Subtract p256")
  1390  	SUBQ(p256ord.Offset(0x00), acc0_v1)
  1391  	SBBQ(p256ord.Offset(0x08), acc1_v1)
  1392  	SBBQ(p256ord.Offset(0x10), acc2_v1)
  1393  	SBBQ(p256ord.Offset(0x18), acc3_v1)
  1394  	SBBQ(Imm(0), t0_v1)
  1395  
  1396  	CMOVQCS(acc4_v1, acc0_v1)
  1397  	CMOVQCS(acc5_v1, acc1_v1)
  1398  	CMOVQCS(y_ptr, acc2_v1)
  1399  	CMOVQCS(t1_v1, acc3_v1)
  1400  
  1401  	MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*0))
  1402  	MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*1))
  1403  	MOVQ(acc2_v1, Mem{Base: res_ptr}.Offset(8*2))
  1404  	MOVQ(acc3_v1, Mem{Base: res_ptr}.Offset(8*3))
  1405  	MOVQ(res_ptr, x_ptr)
  1406  	DECQ(RBX)
  1407  	JNE(LabelRef("ordSqrLoop"))
  1408  
  1409  	RET()
  1410  }
  1411  
  1412  // These variables have been versioned as they get redfined in the reference implementation.
  1413  // This is done to produce a minimal semantic diff.
  1414  var (
  1415  	mul0_v2 = RAX
  1416  	mul1_v2 = RDX
  1417  	acc0_v2 = RBX
  1418  	acc1_v2 = RCX
  1419  	acc2_v2 = R8
  1420  	acc3_v2 = R9
  1421  	acc4_v2 = R10
  1422  	acc5_v2 = R11
  1423  	acc6_v2 = R12
  1424  	acc7_v2 = R13
  1425  	t0_v2   = R14
  1426  	t1_v2   = R15
  1427  	t2_v2   = RDI
  1428  	t3_v2   = RSI
  1429  	hlp_v2  = RBP
  1430  )
  1431  
  1432  func p256SubInternal() {
  1433  	Function("p256SubInternal")
  1434  	Attributes(NOSPLIT)
  1435  
  1436  	XORQ(mul0_v2, mul0_v2)
  1437  	SUBQ(t0_v2, acc4_v2)
  1438  	SBBQ(t1_v2, acc5_v2)
  1439  	SBBQ(t2_v2, acc6_v2)
  1440  	SBBQ(t3_v2, acc7_v2)
  1441  	SBBQ(Imm(0), mul0_v2)
  1442  
  1443  	MOVQ(acc4_v2, acc0_v2)
  1444  	MOVQ(acc5_v2, acc1_v2)
  1445  	MOVQ(acc6_v2, acc2_v2)
  1446  	MOVQ(acc7_v2, acc3_v2)
  1447  
  1448  	ADDQ(I8(-1), acc4_v2)
  1449  	p256const0 := p256const0_DATA()
  1450  	ADCQ(p256const0, acc5_v2)
  1451  	ADCQ(Imm(0), acc6_v2)
  1452  	p256const1 := p256const1_DATA()
  1453  	ADCQ(p256const1, acc7_v2)
  1454  	ANDQ(Imm(1), mul0_v2)
  1455  
  1456  	CMOVQEQ(acc0_v2, acc4_v2)
  1457  	CMOVQEQ(acc1_v2, acc5_v2)
  1458  	CMOVQEQ(acc2_v2, acc6_v2)
  1459  	CMOVQEQ(acc3_v2, acc7_v2)
  1460  
  1461  	RET()
  1462  }
  1463  
  1464  func p256MulInternal() {
  1465  	Function("p256MulInternal")
  1466  	Attributes(NOSPLIT)
  1467  
  1468  	MOVQ(acc4_v2, mul0_v2)
  1469  	MULQ(t0_v2)
  1470  	MOVQ(mul0_v2, acc0_v2)
  1471  	MOVQ(mul1_v2, acc1_v2)
  1472  
  1473  	MOVQ(acc4_v2, mul0_v2)
  1474  	MULQ(t1_v2)
  1475  	ADDQ(mul0_v2, acc1_v2)
  1476  	ADCQ(Imm(0), mul1_v2)
  1477  	MOVQ(mul1_v2, acc2_v2)
  1478  
  1479  	MOVQ(acc4_v2, mul0_v2)
  1480  	MULQ(t2_v2)
  1481  	ADDQ(mul0_v2, acc2_v2)
  1482  	ADCQ(Imm(0), mul1_v2)
  1483  	MOVQ(mul1_v2, acc3_v2)
  1484  
  1485  	MOVQ(acc4_v2, mul0_v2)
  1486  	MULQ(t3_v2)
  1487  	ADDQ(mul0_v2, acc3_v2)
  1488  	ADCQ(Imm(0), mul1_v2)
  1489  	MOVQ(mul1_v2, acc4_v2)
  1490  
  1491  	MOVQ(acc5_v2, mul0_v2)
  1492  	MULQ(t0_v2)
  1493  	ADDQ(mul0_v2, acc1_v2)
  1494  	ADCQ(Imm(0), mul1_v2)
  1495  	MOVQ(mul1_v2, hlp_v2)
  1496  
  1497  	MOVQ(acc5_v2, mul0_v2)
  1498  	MULQ(t1_v2)
  1499  	ADDQ(hlp_v2, acc2_v2)
  1500  	ADCQ(Imm(0), mul1_v2)
  1501  	ADDQ(mul0_v2, acc2_v2)
  1502  	ADCQ(Imm(0), mul1_v2)
  1503  	MOVQ(mul1_v2, hlp_v2)
  1504  
  1505  	MOVQ(acc5_v2, mul0_v2)
  1506  	MULQ(t2_v2)
  1507  	ADDQ(hlp_v2, acc3_v2)
  1508  	ADCQ(Imm(0), mul1_v2)
  1509  	ADDQ(mul0_v2, acc3_v2)
  1510  	ADCQ(Imm(0), mul1_v2)
  1511  	MOVQ(mul1_v2, hlp_v2)
  1512  
  1513  	MOVQ(acc5_v2, mul0_v2)
  1514  	MULQ(t3_v2)
  1515  	ADDQ(hlp_v2, acc4_v2)
  1516  	ADCQ(Imm(0), mul1_v2)
  1517  	ADDQ(mul0_v2, acc4_v2)
  1518  	ADCQ(Imm(0), mul1_v2)
  1519  	MOVQ(mul1_v2, acc5_v2)
  1520  
  1521  	MOVQ(acc6_v2, mul0_v2)
  1522  	MULQ(t0_v2)
  1523  	ADDQ(mul0_v2, acc2_v2)
  1524  	ADCQ(Imm(0), mul1_v2)
  1525  	MOVQ(mul1_v2, hlp_v2)
  1526  
  1527  	MOVQ(acc6_v2, mul0_v2)
  1528  	MULQ(t1_v2)
  1529  	ADDQ(hlp_v2, acc3_v2)
  1530  	ADCQ(Imm(0), mul1_v2)
  1531  	ADDQ(mul0_v2, acc3_v2)
  1532  	ADCQ(Imm(0), mul1_v2)
  1533  	MOVQ(mul1_v2, hlp_v2)
  1534  
  1535  	MOVQ(acc6_v2, mul0_v2)
  1536  	MULQ(t2_v2)
  1537  	ADDQ(hlp_v2, acc4_v2)
  1538  	ADCQ(Imm(0), mul1_v2)
  1539  	ADDQ(mul0_v2, acc4_v2)
  1540  	ADCQ(Imm(0), mul1_v2)
  1541  	MOVQ(mul1_v2, hlp_v2)
  1542  
  1543  	MOVQ(acc6_v2, mul0_v2)
  1544  	MULQ(t3_v2)
  1545  	ADDQ(hlp_v2, acc5_v2)
  1546  	ADCQ(Imm(0), mul1_v2)
  1547  	ADDQ(mul0_v2, acc5_v2)
  1548  	ADCQ(Imm(0), mul1_v2)
  1549  	MOVQ(mul1_v2, acc6_v2)
  1550  
  1551  	MOVQ(acc7_v2, mul0_v2)
  1552  	MULQ(t0_v2)
  1553  	ADDQ(mul0_v2, acc3_v2)
  1554  	ADCQ(Imm(0), mul1_v2)
  1555  	MOVQ(mul1_v2, hlp_v2)
  1556  
  1557  	MOVQ(acc7_v2, mul0_v2)
  1558  	MULQ(t1_v2)
  1559  	ADDQ(hlp_v2, acc4_v2)
  1560  	ADCQ(Imm(0), mul1_v2)
  1561  	ADDQ(mul0_v2, acc4_v2)
  1562  	ADCQ(Imm(0), mul1_v2)
  1563  	MOVQ(mul1_v2, hlp_v2)
  1564  
  1565  	MOVQ(acc7_v2, mul0_v2)
  1566  	MULQ(t2_v2)
  1567  	ADDQ(hlp_v2, acc5_v2)
  1568  	ADCQ(Imm(0), mul1_v2)
  1569  	ADDQ(mul0_v2, acc5_v2)
  1570  	ADCQ(Imm(0), mul1_v2)
  1571  	MOVQ(mul1_v2, hlp_v2)
  1572  
  1573  	MOVQ(acc7_v2, mul0_v2)
  1574  	MULQ(t3_v2)
  1575  	ADDQ(hlp_v2, acc6_v2)
  1576  	ADCQ(Imm(0), mul1_v2)
  1577  	ADDQ(mul0_v2, acc6_v2)
  1578  	ADCQ(Imm(0), mul1_v2)
  1579  	MOVQ(mul1_v2, acc7_v2)
  1580  
  1581  	Comment("First reduction step")
  1582  	MOVQ(acc0_v2, mul0_v2)
  1583  	MOVQ(acc0_v2, hlp_v2)
  1584  	SHLQ(Imm(32), acc0_v2)
  1585  	p256const1 := p256const1_DATA()
  1586  	MULQ(p256const1)
  1587  	SHRQ(Imm(32), hlp_v2)
  1588  	ADDQ(acc0_v2, acc1_v2)
  1589  	ADCQ(hlp_v2, acc2_v2)
  1590  	ADCQ(mul0_v2, acc3_v2)
  1591  	ADCQ(Imm(0), mul1_v2)
  1592  	MOVQ(mul1_v2, acc0_v2)
  1593  
  1594  	Comment("Second reduction step")
  1595  	MOVQ(acc1_v2, mul0_v2)
  1596  	MOVQ(acc1_v2, hlp_v2)
  1597  	SHLQ(Imm(32), acc1_v2)
  1598  	MULQ(p256const1)
  1599  	SHRQ(Imm(32), hlp_v2)
  1600  	ADDQ(acc1_v2, acc2_v2)
  1601  	ADCQ(hlp_v2, acc3_v2)
  1602  	ADCQ(mul0_v2, acc0_v2)
  1603  	ADCQ(Imm(0), mul1_v2)
  1604  	MOVQ(mul1_v2, acc1_v2)
  1605  
  1606  	Comment("Third reduction step")
  1607  	MOVQ(acc2_v2, mul0_v2)
  1608  	MOVQ(acc2_v2, hlp_v2)
  1609  	SHLQ(Imm(32), acc2_v2)
  1610  	MULQ(p256const1)
  1611  	SHRQ(Imm(32), hlp_v2)
  1612  	ADDQ(acc2_v2, acc3_v2)
  1613  	ADCQ(hlp_v2, acc0_v2)
  1614  	ADCQ(mul0_v2, acc1_v2)
  1615  	ADCQ(Imm(0), mul1_v2)
  1616  	MOVQ(mul1_v2, acc2_v2)
  1617  
  1618  	Comment("Last reduction step")
  1619  	MOVQ(acc3_v2, mul0_v2)
  1620  	MOVQ(acc3_v2, hlp_v2)
  1621  	SHLQ(Imm(32), acc3_v2)
  1622  	MULQ(p256const1)
  1623  	SHRQ(Imm(32), hlp_v2)
  1624  	ADDQ(acc3_v2, acc0_v2)
  1625  	ADCQ(hlp_v2, acc1_v2)
  1626  	ADCQ(mul0_v2, acc2_v2)
  1627  	ADCQ(Imm(0), mul1_v2)
  1628  	MOVQ(mul1_v2, acc3_v2)
  1629  	MOVQ(U32(0), RBP)
  1630  
  1631  	Comment("Add bits [511:256] of the result")
  1632  	ADCQ(acc0_v2, acc4_v2)
  1633  	ADCQ(acc1_v2, acc5_v2)
  1634  	ADCQ(acc2_v2, acc6_v2)
  1635  	ADCQ(acc3_v2, acc7_v2)
  1636  	ADCQ(Imm(0), hlp_v2)
  1637  
  1638  	Comment("Copy result")
  1639  	MOVQ(acc4_v2, acc0_v2)
  1640  	MOVQ(acc5_v2, acc1_v2)
  1641  	MOVQ(acc6_v2, acc2_v2)
  1642  	MOVQ(acc7_v2, acc3_v2)
  1643  
  1644  	Comment("Subtract p256")
  1645  	SUBQ(I8(-1), acc4_v2)
  1646  	p256const0 := p256const0_DATA()
  1647  	SBBQ(p256const0, acc5_v2)
  1648  	SBBQ(Imm(0), acc6_v2)
  1649  	SBBQ(p256const1, acc7_v2)
  1650  	SBBQ(Imm(0), hlp_v2)
  1651  
  1652  	Comment("If the result of the subtraction is negative, restore the previous result")
  1653  	CMOVQCS(acc0_v2, acc4_v2)
  1654  	CMOVQCS(acc1_v2, acc5_v2)
  1655  	CMOVQCS(acc2_v2, acc6_v2)
  1656  	CMOVQCS(acc3_v2, acc7_v2)
  1657  
  1658  	RET()
  1659  }
  1660  
  1661  func p256SqrInternal() {
  1662  	Function("p256SqrInternal")
  1663  	Attributes(NOSPLIT)
  1664  
  1665  	MOVQ(acc4_v2, mul0_v2)
  1666  	MULQ(acc5_v2)
  1667  	MOVQ(mul0_v2, acc1_v2)
  1668  	MOVQ(mul1_v2, acc2_v2)
  1669  
  1670  	MOVQ(acc4_v2, mul0_v2)
  1671  	MULQ(acc6_v2)
  1672  	ADDQ(mul0_v2, acc2_v2)
  1673  	ADCQ(Imm(0), mul1_v2)
  1674  	MOVQ(mul1_v2, acc3_v2)
  1675  
  1676  	MOVQ(acc4_v2, mul0_v2)
  1677  	MULQ(acc7_v2)
  1678  	ADDQ(mul0_v2, acc3_v2)
  1679  	ADCQ(Imm(0), mul1_v2)
  1680  	MOVQ(mul1_v2, t0_v2)
  1681  
  1682  	MOVQ(acc5_v2, mul0_v2)
  1683  	MULQ(acc6_v2)
  1684  	ADDQ(mul0_v2, acc3_v2)
  1685  	ADCQ(Imm(0), mul1_v2)
  1686  	MOVQ(mul1_v2, hlp_v2)
  1687  
  1688  	MOVQ(acc5_v2, mul0_v2)
  1689  	MULQ(acc7_v2)
  1690  	ADDQ(hlp_v2, t0_v2)
  1691  	ADCQ(Imm(0), mul1_v2)
  1692  	ADDQ(mul0_v2, t0_v2)
  1693  	ADCQ(Imm(0), mul1_v2)
  1694  	MOVQ(mul1_v2, t1_v2)
  1695  
  1696  	MOVQ(acc6_v2, mul0_v2)
  1697  	MULQ(acc7_v2)
  1698  	ADDQ(mul0_v2, t1_v2)
  1699  	ADCQ(Imm(0), mul1_v2)
  1700  	MOVQ(mul1_v2, t2_v2)
  1701  	XORQ(t3_v2, t3_v2)
  1702  
  1703  	Comment("*2")
  1704  	ADDQ(acc1_v2, acc1_v2)
  1705  	ADCQ(acc2_v2, acc2_v2)
  1706  	ADCQ(acc3_v2, acc3_v2)
  1707  	ADCQ(t0_v2, t0_v2)
  1708  	ADCQ(t1_v2, t1_v2)
  1709  	ADCQ(t2_v2, t2_v2)
  1710  	ADCQ(Imm(0), t3_v2)
  1711  
  1712  	Comment("Missing products")
  1713  	MOVQ(acc4_v2, mul0_v2)
  1714  	MULQ(mul0_v2)
  1715  	MOVQ(mul0_v2, acc0_v2)
  1716  	MOVQ(RDX, acc4_v2)
  1717  
  1718  	MOVQ(acc5_v2, mul0_v2)
  1719  	MULQ(mul0_v2)
  1720  	ADDQ(acc4_v2, acc1_v2)
  1721  	ADCQ(mul0_v2, acc2_v2)
  1722  	ADCQ(Imm(0), RDX)
  1723  	MOVQ(RDX, acc4_v2)
  1724  
  1725  	MOVQ(acc6_v2, mul0_v2)
  1726  	MULQ(mul0_v2)
  1727  	ADDQ(acc4_v2, acc3_v2)
  1728  	ADCQ(mul0_v2, t0_v2)
  1729  	ADCQ(Imm(0), RDX)
  1730  	MOVQ(RDX, acc4_v2)
  1731  
  1732  	MOVQ(acc7_v2, mul0_v2)
  1733  	MULQ(mul0_v2)
  1734  	ADDQ(acc4_v2, t1_v2)
  1735  	ADCQ(mul0_v2, t2_v2)
  1736  	ADCQ(RDX, t3_v2)
  1737  
  1738  	Comment("First reduction step")
  1739  	MOVQ(acc0_v2, mul0_v2)
  1740  	MOVQ(acc0_v2, hlp_v2)
  1741  	SHLQ(Imm(32), acc0_v2)
  1742  	p256const1 := p256const1_DATA()
  1743  	MULQ(p256const1)
  1744  	SHRQ(Imm(32), hlp_v2)
  1745  	ADDQ(acc0_v2, acc1_v2)
  1746  	ADCQ(hlp_v2, acc2_v2)
  1747  	ADCQ(mul0_v2, acc3_v2)
  1748  	ADCQ(Imm(0), mul1_v2)
  1749  	MOVQ(mul1_v2, acc0_v2)
  1750  
  1751  	Comment("Second reduction step")
  1752  	MOVQ(acc1_v2, mul0_v2)
  1753  	MOVQ(acc1_v2, hlp_v2)
  1754  	SHLQ(Imm(32), acc1_v2)
  1755  	MULQ(p256const1)
  1756  	SHRQ(Imm(32), hlp_v2)
  1757  	ADDQ(acc1_v2, acc2_v2)
  1758  	ADCQ(hlp_v2, acc3_v2)
  1759  	ADCQ(mul0_v2, acc0_v2)
  1760  	ADCQ(Imm(0), mul1_v2)
  1761  	MOVQ(mul1_v2, acc1_v2)
  1762  
  1763  	Comment("Third reduction step")
  1764  	MOVQ(acc2_v2, mul0_v2)
  1765  	MOVQ(acc2_v2, hlp_v2)
  1766  	SHLQ(Imm(32), acc2_v2)
  1767  	MULQ(p256const1)
  1768  	SHRQ(Imm(32), hlp_v2)
  1769  	ADDQ(acc2_v2, acc3_v2)
  1770  	ADCQ(hlp_v2, acc0_v2)
  1771  	ADCQ(mul0_v2, acc1_v2)
  1772  	ADCQ(Imm(0), mul1_v2)
  1773  	MOVQ(mul1_v2, acc2_v2)
  1774  
  1775  	Comment("Last reduction step")
  1776  	MOVQ(acc3_v2, mul0_v2)
  1777  	MOVQ(acc3_v2, hlp_v2)
  1778  	SHLQ(Imm(32), acc3_v2)
  1779  	MULQ(p256const1)
  1780  	SHRQ(Imm(32), hlp_v2)
  1781  	ADDQ(acc3_v2, acc0_v2)
  1782  	ADCQ(hlp_v2, acc1_v2)
  1783  	ADCQ(mul0_v2, acc2_v2)
  1784  	ADCQ(Imm(0), mul1_v2)
  1785  	MOVQ(mul1_v2, acc3_v2)
  1786  	MOVQ(U32(0), RBP)
  1787  
  1788  	Comment("Add bits [511:256] of the result")
  1789  	ADCQ(acc0_v2, t0_v2)
  1790  	ADCQ(acc1_v2, t1_v2)
  1791  	ADCQ(acc2_v2, t2_v2)
  1792  	ADCQ(acc3_v2, t3_v2)
  1793  	ADCQ(Imm(0), hlp_v2)
  1794  
  1795  	Comment("Copy result")
  1796  	MOVQ(t0_v2, acc4_v2)
  1797  	MOVQ(t1_v2, acc5_v2)
  1798  	MOVQ(t2_v2, acc6_v2)
  1799  	MOVQ(t3_v2, acc7_v2)
  1800  
  1801  	Comment("Subtract p256")
  1802  	SUBQ(I8(-1), acc4_v2)
  1803  	p256const0 := p256const0_DATA()
  1804  	SBBQ(p256const0, acc5_v2)
  1805  	SBBQ(Imm(0), acc6_v2)
  1806  	SBBQ(p256const1, acc7_v2)
  1807  	SBBQ(Imm(0), hlp_v2)
  1808  
  1809  	Comment("If the result of the subtraction is negative, restore the previous result")
  1810  	CMOVQCS(t0_v2, acc4_v2)
  1811  	CMOVQCS(t1_v2, acc5_v2)
  1812  	CMOVQCS(t2_v2, acc6_v2)
  1813  	CMOVQCS(t3_v2, acc7_v2)
  1814  
  1815  	RET()
  1816  }
  1817  
  1818  func p256MulBy2Inline() {
  1819  	XORQ(mul0_v2, mul0_v2)
  1820  	ADDQ(acc4_v2, acc4_v2)
  1821  	ADCQ(acc5_v2, acc5_v2)
  1822  	ADCQ(acc6_v2, acc6_v2)
  1823  	ADCQ(acc7_v2, acc7_v2)
  1824  	ADCQ(I8(0), mul0_v2)
  1825  	MOVQ(acc4_v2, t0_v2)
  1826  	MOVQ(acc5_v2, t1_v2)
  1827  	MOVQ(acc6_v2, t2_v2)
  1828  	MOVQ(acc7_v2, t3_v2)
  1829  	SUBQ(I8(-1), t0_v2)
  1830  	p256const0 := p256const0_DATA()
  1831  	SBBQ(p256const0, t1_v2)
  1832  	SBBQ(I8(0), t2_v2)
  1833  	p256const1 := p256const1_DATA()
  1834  	SBBQ(p256const1, t3_v2)
  1835  	SBBQ(I8(0), mul0_v2)
  1836  	CMOVQCS(acc4_v2, t0_v2)
  1837  	CMOVQCS(acc5_v2, t1_v2)
  1838  	CMOVQCS(acc6_v2, t2_v2)
  1839  	CMOVQCS(acc7_v2, t3_v2)
  1840  }
  1841  
  1842  func p256AddInline() {
  1843  	XORQ(mul0_v2, mul0_v2)
  1844  	ADDQ(t0_v2, acc4_v2)
  1845  	ADCQ(t1_v2, acc5_v2)
  1846  	ADCQ(t2_v2, acc6_v2)
  1847  	ADCQ(t3_v2, acc7_v2)
  1848  	ADCQ(I8(0), mul0_v2)
  1849  	MOVQ(acc4_v2, t0_v2)
  1850  	MOVQ(acc5_v2, t1_v2)
  1851  	MOVQ(acc6_v2, t2_v2)
  1852  	MOVQ(acc7_v2, t3_v2)
  1853  	SUBQ(I8(-1), t0_v2)
  1854  	p256const0 := p256const0_DATA()
  1855  	SBBQ(p256const0, t1_v2)
  1856  	SBBQ(I8(0), t2_v2)
  1857  	p256const1 := p256const1_DATA()
  1858  	SBBQ(p256const1, t3_v2)
  1859  	SBBQ(I8(0), mul0_v2)
  1860  	CMOVQCS(acc4_v2, t0_v2)
  1861  	CMOVQCS(acc5_v2, t1_v2)
  1862  	CMOVQCS(acc6_v2, t2_v2)
  1863  	CMOVQCS(acc7_v2, t3_v2)
  1864  }
  1865  
  1866  /* ---------------------------------------*/
  1867  
  1868  type MemFunc func(off int) Mem
  1869  
  1870  func LDacc(src MemFunc) {
  1871  	MOVQ(src(8*0), acc4_v2)
  1872  	MOVQ(src(8*1), acc5_v2)
  1873  	MOVQ(src(8*2), acc6_v2)
  1874  	MOVQ(src(8*3), acc7_v2)
  1875  }
  1876  
  1877  func LDt(src MemFunc) {
  1878  	MOVQ(src(8*0), t0_v2)
  1879  	MOVQ(src(8*1), t1_v2)
  1880  	MOVQ(src(8*2), t2_v2)
  1881  	MOVQ(src(8*3), t3_v2)
  1882  }
  1883  
  1884  func ST(dst MemFunc) {
  1885  	MOVQ(acc4_v2, dst(8*0))
  1886  	MOVQ(acc5_v2, dst(8*1))
  1887  	MOVQ(acc6_v2, dst(8*2))
  1888  	MOVQ(acc7_v2, dst(8*3))
  1889  }
  1890  
  1891  func STt(dst MemFunc) {
  1892  	MOVQ(t0_v2, dst(8*0))
  1893  	MOVQ(t1_v2, dst(8*1))
  1894  	MOVQ(t2_v2, dst(8*2))
  1895  	MOVQ(t3_v2, dst(8*3))
  1896  }
  1897  
  1898  func acc2t() {
  1899  	MOVQ(acc4_v2, t0_v2)
  1900  	MOVQ(acc5_v2, t1_v2)
  1901  	MOVQ(acc6_v2, t2_v2)
  1902  	MOVQ(acc7_v2, t3_v2)
  1903  }
  1904  
  1905  func t2acc() {
  1906  	MOVQ(t0_v2, acc4_v2)
  1907  	MOVQ(t1_v2, acc5_v2)
  1908  	MOVQ(t2_v2, acc6_v2)
  1909  	MOVQ(t3_v2, acc7_v2)
  1910  }
  1911  
  1912  /* ---------------------------------------*/
  1913  
  1914  // These functions exist as #define macros in the reference implementation.
  1915  //
  1916  // In the reference assembly, these macros are later undefined and redefined.
  1917  // They are implemented here as versioned functions.
  1918  
  1919  func x1in_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*0 + off) }
  1920  func y1in_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*1 + off) }
  1921  func z1in_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*2 + off) }
  1922  func x2in_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*3 + off) }
  1923  func y2in_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*4 + off) }
  1924  func xout_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*5 + off) }
  1925  func yout_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*6 + off) }
  1926  func zout_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*7 + off) }
  1927  func s2_v1(off int) Mem    { return Mem{Base: SP}.Offset(32*8 + off) }
  1928  func z1sqr_v1(off int) Mem { return Mem{Base: SP}.Offset(32*9 + off) }
  1929  func h_v1(off int) Mem     { return Mem{Base: SP}.Offset(32*10 + off) }
  1930  func r_v1(off int) Mem     { return Mem{Base: SP}.Offset(32*11 + off) }
  1931  func hsqr_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*12 + off) }
  1932  func rsqr_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*13 + off) }
  1933  func hcub_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*14 + off) }
  1934  
  1935  var (
  1936  	rptr_v1      Mem = Mem{Base: SP}.Offset(32*15 + 0)
  1937  	sel_save_v1      = Mem{Base: SP}.Offset(32*15 + 8)
  1938  	zero_save_v1     = Mem{Base: SP}.Offset(32*15 + 8 + 4)
  1939  )
  1940  
  1941  // Implements:
  1942  //
  1943  //	func p256PointAddAffineAsm(res, in1 *P256Point, in2 *p256AffinePoint, sign, sel, zero int)
  1944  func p256PointAddAffineAsm() {
  1945  	Implement("p256PointAddAffineAsm")
  1946  	AllocLocal(512)
  1947  
  1948  	Load(Param("res"), RAX)
  1949  	Load(Param("in1"), RBX)
  1950  	Load(Param("in2"), RCX)
  1951  	Load(Param("sign"), RDX)
  1952  	Load(Param("sel"), t1_v2)
  1953  	Load(Param("zero"), t2_v2)
  1954  
  1955  	MOVOU(Mem{Base: BX}.Offset(16*0), X0)
  1956  	MOVOU(Mem{Base: BX}.Offset(16*1), X1)
  1957  	MOVOU(Mem{Base: BX}.Offset(16*2), X2)
  1958  	MOVOU(Mem{Base: BX}.Offset(16*3), X3)
  1959  	MOVOU(Mem{Base: BX}.Offset(16*4), X4)
  1960  	MOVOU(Mem{Base: BX}.Offset(16*5), X5)
  1961  
  1962  	MOVOU(X0, x1in_v1(16*0))
  1963  	MOVOU(X1, x1in_v1(16*1))
  1964  	MOVOU(X2, y1in_v1(16*0))
  1965  	MOVOU(X3, y1in_v1(16*1))
  1966  	MOVOU(X4, z1in_v1(16*0))
  1967  	MOVOU(X5, z1in_v1(16*1))
  1968  
  1969  	MOVOU(Mem{Base: CX}.Offset(16*0), X0)
  1970  	MOVOU(Mem{Base: CX}.Offset(16*1), X1)
  1971  
  1972  	MOVOU(X0, x2in_v1(16*0))
  1973  	MOVOU(X1, x2in_v1(16*1))
  1974  
  1975  	Comment("Store pointer to result")
  1976  	MOVQ(mul0_v2, rptr_v1)
  1977  
  1978  	// Hack to get Avo to emit:
  1979  	// 	MOVL t1, sel_save_v1
  1980  	Instruction(&ir.Instruction{
  1981  		Opcode:   "MOVL",
  1982  		Operands: []Op{t1_v2, sel_save_v1},
  1983  	})
  1984  
  1985  	// Hack to get Avo to emit:
  1986  	// 	MOVL t2_v2, zero_save_v1
  1987  	Instruction(&ir.Instruction{
  1988  		Opcode:   "MOVL",
  1989  		Operands: []Op{t2_v2, zero_save_v1},
  1990  	})
  1991  
  1992  	Comment("Negate y2in based on sign")
  1993  	MOVQ(Mem{Base: CX}.Offset(16*2+8*0), acc4_v2)
  1994  	MOVQ(Mem{Base: CX}.Offset(16*2+8*1), acc5_v2)
  1995  	MOVQ(Mem{Base: CX}.Offset(16*2+8*2), acc6_v2)
  1996  	MOVQ(Mem{Base: CX}.Offset(16*2+8*3), acc7_v2)
  1997  	MOVQ(I32(-1), acc0_v2)
  1998  	p256const0 := p256const0_DATA()
  1999  	MOVQ(p256const0, acc1_v2)
  2000  	MOVQ(U32(0), acc2_v2)
  2001  	p256const1 := p256const1_DATA()
  2002  	MOVQ(p256const1, acc3_v2)
  2003  	XORQ(mul0_v2, mul0_v2)
  2004  
  2005  	Comment("Speculatively subtract")
  2006  	SUBQ(acc4_v2, acc0_v2)
  2007  	SBBQ(acc5_v2, acc1_v2)
  2008  	SBBQ(acc6_v2, acc2_v2)
  2009  	SBBQ(acc7_v2, acc3_v2)
  2010  	SBBQ(Imm(0), mul0_v2)
  2011  	MOVQ(acc0_v2, t0_v2)
  2012  	MOVQ(acc1_v2, t1_v2)
  2013  	MOVQ(acc2_v2, t2_v2)
  2014  	MOVQ(acc3_v2, t3_v2)
  2015  
  2016  	Comment("Add in case the operand was > p256")
  2017  	ADDQ(I8(-1), acc0_v2)
  2018  	ADCQ(p256const0, acc1_v2)
  2019  	ADCQ(Imm(0), acc2_v2)
  2020  	ADCQ(p256const1, acc3_v2)
  2021  	ADCQ(Imm(0), mul0_v2)
  2022  	CMOVQNE(t0_v2, acc0_v2)
  2023  	CMOVQNE(t1_v2, acc1_v2)
  2024  	CMOVQNE(t2_v2, acc2_v2)
  2025  	CMOVQNE(t3_v2, acc3_v2)
  2026  
  2027  	Comment("If condition is 0, keep original value")
  2028  	TESTQ(RDX, RDX)
  2029  	CMOVQEQ(acc4_v2, acc0_v2)
  2030  	CMOVQEQ(acc5_v2, acc1_v2)
  2031  	CMOVQEQ(acc6_v2, acc2_v2)
  2032  	CMOVQEQ(acc7_v2, acc3_v2)
  2033  
  2034  	Comment("Store result")
  2035  	MOVQ(acc0_v2, y2in_v1(8*0))
  2036  	MOVQ(acc1_v2, y2in_v1(8*1))
  2037  	MOVQ(acc2_v2, y2in_v1(8*2))
  2038  	MOVQ(acc3_v2, y2in_v1(8*3))
  2039  
  2040  	Comment("Begin point add")
  2041  	LDacc(z1in_v1)
  2042  	CALL(LabelRef("p256SqrInternal(SB)")) //                  z1ˆ2
  2043  	ST(z1sqr_v1)
  2044  
  2045  	LDt(x2in_v1)
  2046  	CALL(LabelRef("p256MulInternal(SB)")) //             x2 * z1ˆ2
  2047  
  2048  	LDt(x1in_v1)
  2049  	CALL(LabelRef("p256SubInternal(SB)")) //          h = u2 - u1)
  2050  	ST(h_v1)
  2051  
  2052  	LDt(z1in_v1)
  2053  	CALL(LabelRef("p256MulInternal(SB)")) //           z3 = h * z1
  2054  	ST(zout_v1)
  2055  
  2056  	LDacc(z1sqr_v1)
  2057  	CALL(LabelRef("p256MulInternal(SB)")) //                  z1ˆ3
  2058  
  2059  	LDt(y2in_v1)
  2060  	CALL(LabelRef("p256MulInternal(SB)")) //        s2 = y2 * z1ˆ3
  2061  	ST(s2_v1)
  2062  
  2063  	LDt(y1in_v1)
  2064  	CALL(LabelRef("p256SubInternal(SB)")) //          r = s2 - s1)
  2065  	ST(r_v1)
  2066  
  2067  	CALL(LabelRef("p256SqrInternal(SB)")) //            rsqr = rˆ2
  2068  	ST(rsqr_v1)
  2069  
  2070  	LDacc(h_v1)
  2071  	CALL(LabelRef("p256SqrInternal(SB)")) //            hsqr = hˆ2
  2072  	ST(hsqr_v1)
  2073  
  2074  	LDt(h_v1)
  2075  	CALL(LabelRef("p256MulInternal(SB)")) //            hcub = hˆ3
  2076  	ST(hcub_v1)
  2077  
  2078  	LDt(y1in_v1)
  2079  	CALL(LabelRef("p256MulInternal(SB)")) //             y1 * hˆ3
  2080  	ST(s2_v1)
  2081  
  2082  	LDacc(x1in_v1)
  2083  	LDt(hsqr_v1)
  2084  	CALL(LabelRef("p256MulInternal(SB)")) //             u1 * hˆ2
  2085  	ST(h_v1)
  2086  
  2087  	p256MulBy2Inline() //                    u1 * hˆ2 * 2, inline
  2088  	LDacc(rsqr_v1)
  2089  	CALL(LabelRef("p256SubInternal(SB)")) //  rˆ2 - u1 * hˆ2 * 2)
  2090  
  2091  	LDt(hcub_v1)
  2092  	CALL(LabelRef("p256SubInternal(SB)"))
  2093  	ST(xout_v1)
  2094  
  2095  	MOVQ(acc4_v2, t0_v2)
  2096  	MOVQ(acc5_v2, t1_v2)
  2097  	MOVQ(acc6_v2, t2_v2)
  2098  	MOVQ(acc7_v2, t3_v2)
  2099  	LDacc(h_v1)
  2100  	CALL(LabelRef("p256SubInternal(SB)"))
  2101  
  2102  	LDt(r_v1)
  2103  	CALL(LabelRef("p256MulInternal(SB)"))
  2104  
  2105  	LDt(s2_v1)
  2106  	CALL(LabelRef("p256SubInternal(SB)"))
  2107  	ST(yout_v1)
  2108  
  2109  	Comment("Load stored values from stack")
  2110  	MOVQ(rptr_v1, RAX)
  2111  	MOVL(sel_save_v1, EBX)
  2112  	MOVL(zero_save_v1, ECX)
  2113  
  2114  	Comment("The result is not valid if (sel == 0), conditional choose")
  2115  	MOVOU(xout_v1(16*0), X0)
  2116  	MOVOU(xout_v1(16*1), X1)
  2117  	MOVOU(yout_v1(16*0), X2)
  2118  	MOVOU(yout_v1(16*1), X3)
  2119  	MOVOU(zout_v1(16*0), X4)
  2120  	MOVOU(zout_v1(16*1), X5)
  2121  
  2122  	// Hack to get Avo to emit:
  2123  	// 	MOVL BX, X6
  2124  	Instruction(&ir.Instruction{
  2125  		Opcode:   "MOVL",
  2126  		Operands: []Op{EBX, X6},
  2127  	})
  2128  
  2129  	// Hack to get Avo to emit:
  2130  	// 	MOVL CX, X7
  2131  	Instruction(&ir.Instruction{
  2132  		Opcode:   "MOVL",
  2133  		Operands: []Op{ECX, X7},
  2134  	})
  2135  
  2136  	PXOR(X8, X8)
  2137  	PCMPEQL(X9, X9)
  2138  
  2139  	PSHUFD(Imm(0), X6, X6)
  2140  	PSHUFD(Imm(0), X7, X7)
  2141  
  2142  	PCMPEQL(X8, X6)
  2143  	PCMPEQL(X8, X7)
  2144  
  2145  	MOVOU(X6, X15)
  2146  	PANDN(X9, X15)
  2147  
  2148  	MOVOU(x1in_v1(16*0), X9)
  2149  	MOVOU(x1in_v1(16*1), X10)
  2150  	MOVOU(y1in_v1(16*0), X11)
  2151  	MOVOU(y1in_v1(16*1), X12)
  2152  	MOVOU(z1in_v1(16*0), X13)
  2153  	MOVOU(z1in_v1(16*1), X14)
  2154  
  2155  	PAND(X15, X0)
  2156  	PAND(X15, X1)
  2157  	PAND(X15, X2)
  2158  	PAND(X15, X3)
  2159  	PAND(X15, X4)
  2160  	PAND(X15, X5)
  2161  
  2162  	PAND(X6, X9)
  2163  	PAND(X6, X10)
  2164  	PAND(X6, X11)
  2165  	PAND(X6, X12)
  2166  	PAND(X6, X13)
  2167  	PAND(X6, X14)
  2168  
  2169  	PXOR(X9, X0)
  2170  	PXOR(X10, X1)
  2171  	PXOR(X11, X2)
  2172  	PXOR(X12, X3)
  2173  	PXOR(X13, X4)
  2174  	PXOR(X14, X5)
  2175  
  2176  	Comment("Similarly if zero == 0")
  2177  	PCMPEQL(X9, X9)
  2178  	MOVOU(X7, X15)
  2179  	PANDN(X9, X15)
  2180  
  2181  	MOVOU(x2in_v1(16*0), X9)
  2182  	MOVOU(x2in_v1(16*1), X10)
  2183  	MOVOU(y2in_v1(16*0), X11)
  2184  	MOVOU(y2in_v1(16*1), X12)
  2185  	p256one := p256one_DATA()
  2186  	MOVOU(p256one.Offset(0x00), X13)
  2187  	MOVOU(p256one.Offset(0x10), X14)
  2188  
  2189  	PAND(X15, X0)
  2190  	PAND(X15, X1)
  2191  	PAND(X15, X2)
  2192  	PAND(X15, X3)
  2193  	PAND(X15, X4)
  2194  	PAND(X15, X5)
  2195  
  2196  	PAND(X7, X9)
  2197  	PAND(X7, X10)
  2198  	PAND(X7, X11)
  2199  	PAND(X7, X12)
  2200  	PAND(X7, X13)
  2201  	PAND(X7, X14)
  2202  
  2203  	PXOR(X9, X0)
  2204  	PXOR(X10, X1)
  2205  	PXOR(X11, X2)
  2206  	PXOR(X12, X3)
  2207  	PXOR(X13, X4)
  2208  	PXOR(X14, X5)
  2209  
  2210  	Comment("Finally output the result")
  2211  	MOVOU(X0, Mem{Base: AX}.Offset(16*0))
  2212  	MOVOU(X1, Mem{Base: AX}.Offset(16*1))
  2213  	MOVOU(X2, Mem{Base: AX}.Offset(16*2))
  2214  	MOVOU(X3, Mem{Base: AX}.Offset(16*3))
  2215  	MOVOU(X4, Mem{Base: AX}.Offset(16*4))
  2216  	MOVOU(X5, Mem{Base: AX}.Offset(16*5))
  2217  	MOVQ(U32(0), rptr_v1)
  2218  
  2219  	RET()
  2220  }
  2221  
  2222  // p256IsZero returns 1 in AX if [acc4..acc7] represents zero and zero
  2223  // otherwise. It writes to [acc4..acc7], t0 and t1.
  2224  func p256IsZero() {
  2225  	Function("p256IsZero")
  2226  	Attributes(NOSPLIT)
  2227  
  2228  	Comment("AX contains a flag that is set if the input is zero.")
  2229  	XORQ(RAX, RAX)
  2230  	MOVQ(U32(1), t1_v2)
  2231  
  2232  	Comment("Check whether [acc4..acc7] are all zero.")
  2233  	MOVQ(acc4_v2, t0_v2)
  2234  	ORQ(acc5_v2, t0_v2)
  2235  	ORQ(acc6_v2, t0_v2)
  2236  	ORQ(acc7_v2, t0_v2)
  2237  
  2238  	Comment("Set the zero flag if so. (CMOV of a constant to a register doesn't")
  2239  	Comment("appear to be supported in Go. Thus t1 = 1.)")
  2240  	CMOVQEQ(t1_v2, RAX)
  2241  
  2242  	Comment("XOR [acc4..acc7] with P and compare with zero again.")
  2243  	XORQ(I8(-1), acc4_v2)
  2244  	p256const0 := p256const0_DATA()
  2245  	XORQ(p256const0, acc5_v2)
  2246  	p256const1 := p256const1_DATA()
  2247  	XORQ(p256const1, acc7_v2)
  2248  	ORQ(acc5_v2, acc4_v2)
  2249  	ORQ(acc6_v2, acc4_v2)
  2250  	ORQ(acc7_v2, acc4_v2)
  2251  
  2252  	Comment("Set the zero flag if so.")
  2253  	CMOVQEQ(t1_v2, RAX)
  2254  	RET()
  2255  }
  2256  
  2257  func x1in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*0 + off) }
  2258  func y1in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*1 + off) }
  2259  func z1in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*2 + off) }
  2260  func x2in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*3 + off) }
  2261  func y2in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*4 + off) }
  2262  func z2in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*5 + off) }
  2263  
  2264  func xout_v2(off int) Mem { return Mem{Base: SP}.Offset(32*6 + off) }
  2265  func yout_v2(off int) Mem { return Mem{Base: SP}.Offset(32*7 + off) }
  2266  func zout_v2(off int) Mem { return Mem{Base: SP}.Offset(32*8 + off) }
  2267  
  2268  func u1_v2(off int) Mem    { return Mem{Base: SP}.Offset(32*9 + off) }
  2269  func u2_v2(off int) Mem    { return Mem{Base: SP}.Offset(32*10 + off) }
  2270  func s1_v2(off int) Mem    { return Mem{Base: SP}.Offset(32*11 + off) }
  2271  func s2_v2(off int) Mem    { return Mem{Base: SP}.Offset(32*12 + off) }
  2272  func z1sqr_v2(off int) Mem { return Mem{Base: SP}.Offset(32*13 + off) }
  2273  func z2sqr_v2(off int) Mem { return Mem{Base: SP}.Offset(32*14 + off) }
  2274  func h_v2(off int) Mem     { return Mem{Base: SP}.Offset(32*15 + off) }
  2275  func r_v2(off int) Mem     { return Mem{Base: SP}.Offset(32*16 + off) }
  2276  func hsqr_v2(off int) Mem  { return Mem{Base: SP}.Offset(32*17 + off) }
  2277  func rsqr_v2(off int) Mem  { return Mem{Base: SP}.Offset(32*18 + off) }
  2278  func hcub_v2(off int) Mem  { return Mem{Base: SP}.Offset(32*19 + off) }
  2279  
  2280  var (
  2281  	rptr_v2      Mem = Mem{Base: SP}.Offset(32 * 20)
  2282  	points_eq_v2     = Mem{Base: SP}.Offset(32*20 + 8)
  2283  )
  2284  
  2285  // Implements:
  2286  //
  2287  //	func p256PointAddAsm(res, in1, in2 *P256Point) int
  2288  //
  2289  // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
  2290  func p256PointAddAsm() {
  2291  	Implement("p256PointAddAsm")
  2292  	AllocLocal(680)
  2293  
  2294  	Comment("Move input to stack in order to free registers")
  2295  	Load(Param("res"), RAX)
  2296  	Load(Param("in1"), RBX)
  2297  	Load(Param("in2"), RCX)
  2298  
  2299  	MOVOU(Mem{Base: BX}.Offset(16*0), X0)
  2300  	MOVOU(Mem{Base: BX}.Offset(16*1), X1)
  2301  	MOVOU(Mem{Base: BX}.Offset(16*2), X2)
  2302  	MOVOU(Mem{Base: BX}.Offset(16*3), X3)
  2303  	MOVOU(Mem{Base: BX}.Offset(16*4), X4)
  2304  	MOVOU(Mem{Base: BX}.Offset(16*5), X5)
  2305  
  2306  	MOVOU(X0, x1in_v2(16*0))
  2307  	MOVOU(X1, x1in_v2(16*1))
  2308  	MOVOU(X2, y1in_v2(16*0))
  2309  	MOVOU(X3, y1in_v2(16*1))
  2310  	MOVOU(X4, z1in_v2(16*0))
  2311  	MOVOU(X5, z1in_v2(16*1))
  2312  
  2313  	MOVOU(Mem{Base: CX}.Offset(16*0), X0)
  2314  	MOVOU(Mem{Base: CX}.Offset(16*1), X1)
  2315  	MOVOU(Mem{Base: CX}.Offset(16*2), X2)
  2316  	MOVOU(Mem{Base: CX}.Offset(16*3), X3)
  2317  	MOVOU(Mem{Base: CX}.Offset(16*4), X4)
  2318  	MOVOU(Mem{Base: CX}.Offset(16*5), X5)
  2319  
  2320  	MOVOU(X0, x2in_v2(16*0))
  2321  	MOVOU(X1, x2in_v2(16*1))
  2322  	MOVOU(X2, y2in_v2(16*0))
  2323  	MOVOU(X3, y2in_v2(16*1))
  2324  	MOVOU(X4, z2in_v2(16*0))
  2325  	MOVOU(X5, z2in_v2(16*1))
  2326  
  2327  	Comment("Store pointer to result")
  2328  	MOVQ(RAX, rptr_v2)
  2329  
  2330  	Comment("Begin point add")
  2331  	LDacc(z2in_v2)
  2332  	CALL(LabelRef("p256SqrInternal(SB)")) //               z2ˆ2
  2333  	ST(z2sqr_v2)
  2334  	LDt(z2in_v2)
  2335  	CALL(LabelRef("p256MulInternal(SB)")) //               z2ˆ3
  2336  	LDt(y1in_v2)
  2337  	CALL(LabelRef("p256MulInternal(SB)")) //       s1 = z2ˆ3*y1
  2338  	ST(s1_v2)
  2339  
  2340  	LDacc(z1in_v2)
  2341  	CALL(LabelRef("p256SqrInternal(SB)")) //               z1ˆ2
  2342  	ST(z1sqr_v2)
  2343  	LDt(z1in_v2)
  2344  	CALL(LabelRef("p256MulInternal(SB)")) //               z1ˆ3
  2345  	LDt(y2in_v2)
  2346  	CALL(LabelRef("p256MulInternal(SB)")) //       s2 = z1ˆ3*y2
  2347  	ST(s2_v2)
  2348  
  2349  	LDt(s1_v2)
  2350  	CALL(LabelRef("p256SubInternal(SB)")) //        r = s2 - s1
  2351  	ST(r_v2)
  2352  	CALL(LabelRef("p256IsZero(SB)"))
  2353  	MOVQ(RAX, points_eq_v2)
  2354  
  2355  	LDacc(z2sqr_v2)
  2356  	LDt(x1in_v2)
  2357  	CALL(LabelRef("p256MulInternal(SB)")) //     u1 = x1 * z2ˆ2
  2358  	ST(u1_v2)
  2359  	LDacc(z1sqr_v2)
  2360  	LDt(x2in_v2)
  2361  	CALL(LabelRef("p256MulInternal(SB)")) //     u2 = x2 * z1ˆ2
  2362  	ST(u2_v2)
  2363  
  2364  	LDt(u1_v2)
  2365  	CALL(LabelRef("p256SubInternal(SB)")) //        h = u2 - u1
  2366  	ST(h_v2)
  2367  	CALL(LabelRef("p256IsZero(SB)"))
  2368  	ANDQ(points_eq_v2, RAX)
  2369  	MOVQ(RAX, points_eq_v2)
  2370  
  2371  	LDacc(r_v2)
  2372  	CALL(LabelRef("p256SqrInternal(SB)")) //         rsqr = rˆ2
  2373  	ST(rsqr_v2)
  2374  
  2375  	LDacc(h_v2)
  2376  	CALL(LabelRef("p256SqrInternal(SB)")) //         hsqr = hˆ2
  2377  	ST(hsqr_v2)
  2378  
  2379  	LDt(h_v2)
  2380  	CALL(LabelRef("p256MulInternal(SB)")) //         hcub = hˆ3
  2381  	ST(hcub_v2)
  2382  
  2383  	LDt(s1_v2)
  2384  	CALL(LabelRef("p256MulInternal(SB)"))
  2385  	ST(s2_v2)
  2386  
  2387  	LDacc(z1in_v2)
  2388  	LDt(z2in_v2)
  2389  	CALL(LabelRef("p256MulInternal(SB)")) //            z1 * z2
  2390  	LDt(h_v2)
  2391  	CALL(LabelRef("p256MulInternal(SB)")) //        z1 * z2 * h
  2392  	ST(zout_v2)
  2393  
  2394  	LDacc(hsqr_v2)
  2395  	LDt(u1_v2)
  2396  	CALL(LabelRef("p256MulInternal(SB)")) //           hˆ2 * u1
  2397  	ST(u2_v2)
  2398  
  2399  	p256MulBy2Inline() //                  u1 * hˆ2 * 2, inline
  2400  	LDacc(rsqr_v2)
  2401  	CALL(LabelRef("p256SubInternal(SB)")) // rˆ2 - u1 * hˆ2 * 2
  2402  
  2403  	LDt(hcub_v2)
  2404  	CALL(LabelRef("p256SubInternal(SB)"))
  2405  	ST(xout_v2)
  2406  
  2407  	MOVQ(acc4_v2, t0_v2)
  2408  	MOVQ(acc5_v2, t1_v2)
  2409  	MOVQ(acc6_v2, t2_v2)
  2410  	MOVQ(acc7_v2, t3_v2)
  2411  	LDacc(u2_v2)
  2412  	CALL(LabelRef("p256SubInternal(SB)"))
  2413  
  2414  	LDt(r_v2)
  2415  	CALL(LabelRef("p256MulInternal(SB)"))
  2416  
  2417  	LDt(s2_v2)
  2418  	CALL(LabelRef("p256SubInternal(SB)"))
  2419  	ST(yout_v2)
  2420  
  2421  	MOVOU(xout_v2(16*0), X0)
  2422  	MOVOU(xout_v2(16*1), X1)
  2423  	MOVOU(yout_v2(16*0), X2)
  2424  	MOVOU(yout_v2(16*1), X3)
  2425  	MOVOU(zout_v2(16*0), X4)
  2426  	MOVOU(zout_v2(16*1), X5)
  2427  
  2428  	Comment("Finally output the result")
  2429  	MOVQ(rptr_v2, RAX)
  2430  	MOVQ(U32(0), rptr_v2)
  2431  	MOVOU(X0, Mem{Base: AX}.Offset(16*0))
  2432  	MOVOU(X1, Mem{Base: AX}.Offset(16*1))
  2433  	MOVOU(X2, Mem{Base: AX}.Offset(16*2))
  2434  	MOVOU(X3, Mem{Base: AX}.Offset(16*3))
  2435  	MOVOU(X4, Mem{Base: AX}.Offset(16*4))
  2436  	MOVOU(X5, Mem{Base: AX}.Offset(16*5))
  2437  
  2438  	MOVQ(points_eq_v2, RAX)
  2439  	ret := NewParamAddr("ret", 24)
  2440  	MOVQ(RAX, ret)
  2441  
  2442  	RET()
  2443  }
  2444  
  2445  func x(off int) Mem { return Mem{Base: SP}.Offset(32*0 + off) }
  2446  func y(off int) Mem { return Mem{Base: SP}.Offset(32*1 + off) }
  2447  func z(off int) Mem { return Mem{Base: SP}.Offset(32*2 + off) }
  2448  
  2449  func s(off int) Mem    { return Mem{Base: SP}.Offset(32*3 + off) }
  2450  func m(off int) Mem    { return Mem{Base: SP}.Offset(32*4 + off) }
  2451  func zsqr(off int) Mem { return Mem{Base: SP}.Offset(32*5 + off) }
  2452  func tmp(off int) Mem  { return Mem{Base: SP}.Offset(32*6 + off) }
  2453  
  2454  var rptr_v3 = Mem{Base: SP}.Offset(32 * 7)
  2455  
  2456  // Implements:
  2457  //
  2458  //	func p256PointDoubleAsm(res, in *P256Point)
  2459  func p256PointDoubleAsm() {
  2460  	Implement("p256PointDoubleAsm")
  2461  	Attributes(NOSPLIT)
  2462  	AllocLocal(256)
  2463  
  2464  	Load(Param("res"), RAX)
  2465  	Load(Param("in"), RBX)
  2466  
  2467  	MOVOU(Mem{Base: BX}.Offset(16*0), X0)
  2468  	MOVOU(Mem{Base: BX}.Offset(16*1), X1)
  2469  	MOVOU(Mem{Base: BX}.Offset(16*2), X2)
  2470  	MOVOU(Mem{Base: BX}.Offset(16*3), X3)
  2471  	MOVOU(Mem{Base: BX}.Offset(16*4), X4)
  2472  	MOVOU(Mem{Base: BX}.Offset(16*5), X5)
  2473  
  2474  	MOVOU(X0, x(16*0))
  2475  	MOVOU(X1, x(16*1))
  2476  	MOVOU(X2, y(16*0))
  2477  	MOVOU(X3, y(16*1))
  2478  	MOVOU(X4, z(16*0))
  2479  	MOVOU(X5, z(16*1))
  2480  
  2481  	Comment("Store pointer to result")
  2482  	MOVQ(RAX, rptr_v3)
  2483  
  2484  	Comment("Begin point double")
  2485  	LDacc(z)
  2486  	CALL(LabelRef("p256SqrInternal(SB)"))
  2487  	ST(zsqr)
  2488  
  2489  	LDt(x)
  2490  	p256AddInline()
  2491  	STt(m)
  2492  
  2493  	LDacc(z)
  2494  	LDt(y)
  2495  	CALL(LabelRef("p256MulInternal(SB)"))
  2496  	p256MulBy2Inline()
  2497  	MOVQ(rptr_v3, RAX)
  2498  
  2499  	Comment("Store z")
  2500  	MOVQ(t0_v2, Mem{Base: AX}.Offset(16*4+8*0))
  2501  	MOVQ(t1_v2, Mem{Base: AX}.Offset(16*4+8*1))
  2502  	MOVQ(t2_v2, Mem{Base: AX}.Offset(16*4+8*2))
  2503  	MOVQ(t3_v2, Mem{Base: AX}.Offset(16*4+8*3))
  2504  
  2505  	LDacc(x)
  2506  	LDt(zsqr)
  2507  	CALL(LabelRef("p256SubInternal(SB)"))
  2508  	LDt(m)
  2509  	CALL(LabelRef("p256MulInternal(SB)"))
  2510  	ST(m)
  2511  
  2512  	Comment("Multiply by 3")
  2513  	p256MulBy2Inline()
  2514  	LDacc(m)
  2515  	p256AddInline()
  2516  	STt(m)
  2517  	Comment("////////////////////////")
  2518  	LDacc(y)
  2519  	p256MulBy2Inline()
  2520  	t2acc()
  2521  	CALL(LabelRef("p256SqrInternal(SB)"))
  2522  	ST(s)
  2523  	CALL(LabelRef("p256SqrInternal(SB)"))
  2524  
  2525  	Comment("Divide by 2")
  2526  	XORQ(mul0_v2, mul0_v2)
  2527  	MOVQ(acc4_v2, t0_v2)
  2528  	MOVQ(acc5_v2, t1_v2)
  2529  	MOVQ(acc6_v2, t2_v2)
  2530  	MOVQ(acc7_v2, t3_v2)
  2531  
  2532  	ADDQ(I8(-1), acc4_v2)
  2533  	p256const0 := p256const0_DATA()
  2534  	ADCQ(p256const0, acc5_v2)
  2535  	ADCQ(Imm(0), acc6_v2)
  2536  	p256const1 := p256const1_DATA()
  2537  	ADCQ(p256const1, acc7_v2)
  2538  	ADCQ(Imm(0), mul0_v2)
  2539  	TESTQ(U32(1), t0_v2)
  2540  
  2541  	CMOVQEQ(t0_v2, acc4_v2)
  2542  	CMOVQEQ(t1_v2, acc5_v2)
  2543  	CMOVQEQ(t2_v2, acc6_v2)
  2544  	CMOVQEQ(t3_v2, acc7_v2)
  2545  	ANDQ(t0_v2, mul0_v2)
  2546  
  2547  	SHRQ(Imm(1), acc5_v2, acc4_v2)
  2548  	SHRQ(Imm(1), acc6_v2, acc5_v2)
  2549  	SHRQ(Imm(1), acc7_v2, acc6_v2)
  2550  	SHRQ(Imm(1), mul0_v2, acc7_v2)
  2551  	ST(y)
  2552  	Comment("/////////////////////////")
  2553  	LDacc(x)
  2554  	LDt(s)
  2555  	CALL(LabelRef("p256MulInternal(SB)"))
  2556  	ST(s)
  2557  	p256MulBy2Inline()
  2558  	STt(tmp)
  2559  
  2560  	LDacc(m)
  2561  	CALL(LabelRef("p256SqrInternal(SB)"))
  2562  	LDt(tmp)
  2563  	CALL(LabelRef("p256SubInternal(SB)"))
  2564  
  2565  	MOVQ(rptr_v3, RAX)
  2566  
  2567  	Comment("Store x")
  2568  	MOVQ(acc4_v2, Mem{Base: AX}.Offset(16*0+8*0))
  2569  	MOVQ(acc5_v2, Mem{Base: AX}.Offset(16*0+8*1))
  2570  	MOVQ(acc6_v2, Mem{Base: AX}.Offset(16*0+8*2))
  2571  	MOVQ(acc7_v2, Mem{Base: AX}.Offset(16*0+8*3))
  2572  
  2573  	acc2t()
  2574  	LDacc(s)
  2575  	CALL(LabelRef("p256SubInternal(SB)"))
  2576  
  2577  	LDt(m)
  2578  	CALL(LabelRef("p256MulInternal(SB)"))
  2579  
  2580  	LDt(y)
  2581  	CALL(LabelRef("p256SubInternal(SB)"))
  2582  	MOVQ(rptr_v3, RAX)
  2583  
  2584  	Comment("Store y")
  2585  	MOVQ(acc4_v2, Mem{Base: AX}.Offset(16*2+8*0))
  2586  	MOVQ(acc5_v2, Mem{Base: AX}.Offset(16*2+8*1))
  2587  	MOVQ(acc6_v2, Mem{Base: AX}.Offset(16*2+8*2))
  2588  	MOVQ(acc7_v2, Mem{Base: AX}.Offset(16*2+8*3))
  2589  	Comment("///////////////////////")
  2590  	MOVQ(U32(0), rptr_v3)
  2591  
  2592  	RET()
  2593  }
  2594  
  2595  // #----------------------------DATA SECTION-----------------------------------##
  2596  
  2597  // Pointers for memoizing Data section symbols
  2598  var p256const0_ptr, p256const1_ptr, p256ordK0_ptr, p256ord_ptr, p256one_ptr *Mem
  2599  
  2600  func p256const0_DATA() Mem {
  2601  	if p256const0_ptr != nil {
  2602  		return *p256const0_ptr
  2603  	}
  2604  
  2605  	p256const0 := GLOBL("p256const0", 8)
  2606  	p256const0_ptr = &p256const0
  2607  	DATA(0, U64(0x00000000ffffffff))
  2608  	return p256const0
  2609  }
  2610  
  2611  func p256const1_DATA() Mem {
  2612  	if p256const1_ptr != nil {
  2613  		return *p256const1_ptr
  2614  	}
  2615  
  2616  	p256const1 := GLOBL("p256const1", 8)
  2617  	p256const1_ptr = &p256const1
  2618  	DATA(0, U64(0xffffffff00000001))
  2619  	return p256const1
  2620  }
  2621  
  2622  func p256ordK0_DATA() Mem {
  2623  	if p256ordK0_ptr != nil {
  2624  		return *p256ordK0_ptr
  2625  	}
  2626  
  2627  	p256ordK0 := GLOBL("p256ordK0", 8)
  2628  	p256ordK0_ptr = &p256ordK0
  2629  	DATA(0, U64(0xccd1c8aaee00bc4f))
  2630  	return p256ordK0
  2631  }
  2632  
  2633  var p256ordConstants = [4]uint64{
  2634  	0xf3b9cac2fc632551,
  2635  	0xbce6faada7179e84,
  2636  	0xffffffffffffffff,
  2637  	0xffffffff00000000,
  2638  }
  2639  
  2640  func p256ord_DATA() Mem {
  2641  	if p256ord_ptr != nil {
  2642  		return *p256ord_ptr
  2643  	}
  2644  
  2645  	p256ord := GLOBL("p256ord", 8)
  2646  	p256ord_ptr = &p256ord
  2647  
  2648  	for i, k := range p256ordConstants {
  2649  		DATA(i*8, U64(k))
  2650  	}
  2651  
  2652  	return p256ord
  2653  }
  2654  
  2655  var p256oneConstants = [4]uint64{
  2656  	0x0000000000000001,
  2657  	0xffffffff00000000,
  2658  	0xffffffffffffffff,
  2659  	0x00000000fffffffe,
  2660  }
  2661  
  2662  func p256one_DATA() Mem {
  2663  	if p256one_ptr != nil {
  2664  		return *p256one_ptr
  2665  	}
  2666  
  2667  	p256one := GLOBL("p256one", 8)
  2668  	p256one_ptr = &p256one
  2669  
  2670  	for i, k := range p256oneConstants {
  2671  		DATA(i*8, U64(k))
  2672  	}
  2673  
  2674  	return p256one
  2675  }
  2676  
  2677  const ThatPeskyUnicodeDot = "\u00b7"
  2678  
  2679  // removePeskyUnicodeDot strips the dot from the relevant TEXT directives such that they
  2680  // can exist as internal assembly functions
  2681  //
  2682  // Avo v0.6.0 does not support the generation of internal assembly functions. Go's unicode
  2683  // dot tells the compiler to link a TEXT symbol to a function in the current Go package
  2684  // (or another package if specified). Avo unconditionally prepends the unicode dot to all
  2685  // TEXT symbols, making it impossible to emit an internal function without this hack.
  2686  //
  2687  // There is a pending PR to add internal functions to Avo:
  2688  // https://github.com/mmcloughlin/avo/pull/443
  2689  //
  2690  // If merged it should allow the usage of InternalFunction("NAME") for the specified functions
  2691  func removePeskyUnicodeDot(internalFunctions []string, target string) {
  2692  	bytes, err := os.ReadFile(target)
  2693  	if err != nil {
  2694  		panic(err)
  2695  	}
  2696  
  2697  	content := string(bytes)
  2698  
  2699  	for _, from := range internalFunctions {
  2700  		to := strings.ReplaceAll(from, ThatPeskyUnicodeDot, "")
  2701  		content = strings.ReplaceAll(content, from, to)
  2702  	}
  2703  
  2704  	err = os.WriteFile(target, []byte(content), 0644)
  2705  	if err != nil {
  2706  		panic(err)
  2707  	}
  2708  }
  2709  

View as plain text