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

View as plain text