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  	p256SubInternal()
    56  	p256MulInternal()
    57  	p256SqrInternal()
    58  	p256PointAddAffineAsm()
    59  	p256IsZero()
    60  	p256PointAddAsm()
    61  	p256PointDoubleAsm()
    62  	Generate()
    63  
    64  	internalFunctions := []string{
    65  		"·p256SubInternal",
    66  		"·p256MulInternal",
    67  		"·p256SqrInternal",
    68  		"·p256IsZero",
    69  	}
    70  	removePeskyUnicodeDot(internalFunctions, "../p256_asm_amd64.s")
    71  }
    72  
    73  // Implements:
    74  //
    75  //	func p256MovCond(res, a, b *P256Point, cond int)
    76  func p256MovCond() {
    77  	Implement("p256MovCond")
    78  	Attributes(NOSPLIT)
    79  
    80  	Load(Param("res"), res_ptr)
    81  	Load(Param("a"), x_ptr)
    82  	Load(Param("b"), y_ptr)
    83  	Load(Param("cond"), X12)
    84  
    85  	PXOR(X13, X13)
    86  	PSHUFD(Imm(0), X12, X12)
    87  	PCMPEQL(X13, X12)
    88  
    89  	MOVOU(X12, X0)
    90  	MOVOU(Mem{Base: x_ptr}.Offset(16*0), X6)
    91  	PANDN(X6, X0)
    92  	MOVOU(X12, X1)
    93  	MOVOU(Mem{Base: x_ptr}.Offset(16*1), X7)
    94  	PANDN(X7, X1)
    95  	MOVOU(X12, X2)
    96  	MOVOU(Mem{Base: x_ptr}.Offset(16*2), X8)
    97  	PANDN(X8, X2)
    98  	MOVOU(X12, X3)
    99  	MOVOU(Mem{Base: x_ptr}.Offset(16*3), X9)
   100  	PANDN(X9, X3)
   101  	MOVOU(X12, X4)
   102  	MOVOU(Mem{Base: x_ptr}.Offset(16*4), X10)
   103  	PANDN(X10, X4)
   104  	MOVOU(X12, X5)
   105  	MOVOU(Mem{Base: x_ptr}.Offset(16*5), X11)
   106  	PANDN(X11, X5)
   107  
   108  	MOVOU(Mem{Base: y_ptr}.Offset(16*0), X6)
   109  	MOVOU(Mem{Base: y_ptr}.Offset(16*1), X7)
   110  	MOVOU(Mem{Base: y_ptr}.Offset(16*2), X8)
   111  	MOVOU(Mem{Base: y_ptr}.Offset(16*3), X9)
   112  	MOVOU(Mem{Base: y_ptr}.Offset(16*4), X10)
   113  	MOVOU(Mem{Base: y_ptr}.Offset(16*5), X11)
   114  
   115  	PAND(X12, X6)
   116  	PAND(X12, X7)
   117  	PAND(X12, X8)
   118  	PAND(X12, X9)
   119  	PAND(X12, X10)
   120  	PAND(X12, X11)
   121  
   122  	PXOR(X6, X0)
   123  	PXOR(X7, X1)
   124  	PXOR(X8, X2)
   125  	PXOR(X9, X3)
   126  	PXOR(X10, X4)
   127  	PXOR(X11, X5)
   128  
   129  	MOVOU(X0, Mem{Base: res_ptr}.Offset(16*0))
   130  	MOVOU(X1, Mem{Base: res_ptr}.Offset(16*1))
   131  	MOVOU(X2, Mem{Base: res_ptr}.Offset(16*2))
   132  	MOVOU(X3, Mem{Base: res_ptr}.Offset(16*3))
   133  	MOVOU(X4, Mem{Base: res_ptr}.Offset(16*4))
   134  	MOVOU(X5, Mem{Base: res_ptr}.Offset(16*5))
   135  
   136  	RET()
   137  }
   138  
   139  // Implements:
   140  //
   141  //	func p256NegCond(val *p256Element, cond int)
   142  func p256NegCond() {
   143  	Implement("p256NegCond")
   144  	Attributes(NOSPLIT)
   145  
   146  	Load(Param("val"), res_ptr)
   147  	Load(Param("cond"), t0_v1)
   148  
   149  	Comment("acc = poly")
   150  	MOVQ(I32(-1), acc0_v1)
   151  	p256const0 := p256const0_DATA()
   152  	MOVQ(p256const0, acc1_v1)
   153  	MOVQ(I32(0), acc2_v1)
   154  	p256const1 := p256const1_DATA()
   155  	MOVQ(p256const1, acc3_v1)
   156  
   157  	Comment("Load the original value")
   158  	MOVQ(Mem{Base: res_ptr}.Offset(8*0), acc5_v1)
   159  	MOVQ(Mem{Base: res_ptr}.Offset(8*1), x_ptr)
   160  	MOVQ(Mem{Base: res_ptr}.Offset(8*2), y_ptr)
   161  	MOVQ(Mem{Base: res_ptr}.Offset(8*3), t1_v1)
   162  
   163  	Comment("Speculatively subtract")
   164  	SUBQ(acc5_v1, acc0_v1)
   165  	SBBQ(x_ptr, acc1_v1)
   166  	SBBQ(y_ptr, acc2_v1)
   167  	SBBQ(t1_v1, acc3_v1)
   168  
   169  	Comment("If condition is 0, keep original value")
   170  	TESTQ(t0_v1, t0_v1)
   171  	CMOVQEQ(acc5_v1, acc0_v1)
   172  	CMOVQEQ(x_ptr, acc1_v1)
   173  	CMOVQEQ(y_ptr, acc2_v1)
   174  	CMOVQEQ(t1_v1, acc3_v1)
   175  
   176  	Comment("Store result")
   177  	MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*0))
   178  	MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*1))
   179  	MOVQ(acc2_v1, Mem{Base: res_ptr}.Offset(8*2))
   180  	MOVQ(acc3_v1, Mem{Base: res_ptr}.Offset(8*3))
   181  
   182  	RET()
   183  }
   184  
   185  // Implements:
   186  //
   187  //	func p256Sqr(res, in *p256Element, n int)
   188  func p256Sqr() {
   189  	Implement("p256Sqr")
   190  	Attributes(NOSPLIT)
   191  
   192  	Load(Param("res"), res_ptr)
   193  	Load(Param("in"), x_ptr)
   194  	Load(Param("n"), RBX)
   195  
   196  	Label("sqrLoop")
   197  
   198  	Comment("y[1:] * y[0]")
   199  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), t0_v1)
   200  
   201  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   202  	MULQ(t0_v1)
   203  	MOVQ(RAX, acc1_v1)
   204  	MOVQ(RDX, acc2_v1)
   205  
   206  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   207  	MULQ(t0_v1)
   208  	ADDQ(RAX, acc2_v1)
   209  	ADCQ(Imm(0), RDX)
   210  	MOVQ(RDX, acc3_v1)
   211  
   212  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   213  	MULQ(t0_v1)
   214  	ADDQ(RAX, acc3_v1)
   215  	ADCQ(Imm(0), RDX)
   216  	MOVQ(RDX, acc4_v1)
   217  
   218  	Comment("y[2:] * y[1]")
   219  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), t0_v1)
   220  
   221  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   222  	MULQ(t0_v1)
   223  	ADDQ(RAX, acc3_v1)
   224  	ADCQ(Imm(0), RDX)
   225  	MOVQ(RDX, t1_v1)
   226  
   227  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   228  	MULQ(t0_v1)
   229  	ADDQ(t1_v1, acc4_v1)
   230  	ADCQ(Imm(0), RDX)
   231  	ADDQ(RAX, acc4_v1)
   232  	ADCQ(Imm(0), RDX)
   233  	MOVQ(RDX, acc5_v1)
   234  
   235  	Comment("y[3] * y[2]")
   236  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), t0_v1)
   237  
   238  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   239  	MULQ(t0_v1)
   240  	ADDQ(RAX, acc5_v1)
   241  	ADCQ(Imm(0), RDX)
   242  	MOVQ(RDX, y_ptr)
   243  	XORQ(t1_v1, t1_v1)
   244  
   245  	Comment("*2")
   246  	ADDQ(acc1_v1, acc1_v1)
   247  	ADCQ(acc2_v1, acc2_v1)
   248  	ADCQ(acc3_v1, acc3_v1)
   249  	ADCQ(acc4_v1, acc4_v1)
   250  	ADCQ(acc5_v1, acc5_v1)
   251  	ADCQ(y_ptr, y_ptr)
   252  	ADCQ(Imm(0), t1_v1)
   253  
   254  	Comment("Missing products")
   255  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   256  	MULQ(RAX)
   257  	MOVQ(RAX, acc0_v1)
   258  	MOVQ(RDX, t0_v1)
   259  
   260  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   261  	MULQ(RAX)
   262  	ADDQ(t0_v1, acc1_v1)
   263  	ADCQ(RAX, acc2_v1)
   264  	ADCQ(Imm(0), RDX)
   265  	MOVQ(RDX, t0_v1)
   266  
   267  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   268  	MULQ(RAX)
   269  	ADDQ(t0_v1, acc3_v1)
   270  	ADCQ(RAX, acc4_v1)
   271  	ADCQ(Imm(0), RDX)
   272  	MOVQ(RDX, t0_v1)
   273  
   274  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   275  	MULQ(RAX)
   276  	ADDQ(t0_v1, acc5_v1)
   277  	ADCQ(RAX, y_ptr)
   278  	ADCQ(RDX, t1_v1)
   279  	MOVQ(t1_v1, x_ptr)
   280  
   281  	Comment("First reduction step")
   282  	MOVQ(acc0_v1, RAX)
   283  	MOVQ(acc0_v1, t1_v1)
   284  	SHLQ(Imm(32), acc0_v1)
   285  
   286  	p256const1 := p256const1_DATA()
   287  	MULQ(p256const1)
   288  
   289  	SHRQ(Imm(32), t1_v1)
   290  	ADDQ(acc0_v1, acc1_v1)
   291  	ADCQ(t1_v1, acc2_v1)
   292  	ADCQ(RAX, acc3_v1)
   293  	ADCQ(Imm(0), RDX)
   294  	MOVQ(RDX, acc0_v1)
   295  
   296  	Comment("Second reduction step")
   297  	MOVQ(acc1_v1, RAX)
   298  	MOVQ(acc1_v1, t1_v1)
   299  	SHLQ(Imm(32), acc1_v1)
   300  	MULQ(p256const1)
   301  	SHRQ(Imm(32), t1_v1)
   302  	ADDQ(acc1_v1, acc2_v1)
   303  	ADCQ(t1_v1, acc3_v1)
   304  	ADCQ(RAX, acc0_v1)
   305  	ADCQ(Imm(0), RDX)
   306  	MOVQ(RDX, acc1_v1)
   307  
   308  	Comment("Third reduction step")
   309  	MOVQ(acc2_v1, RAX)
   310  	MOVQ(acc2_v1, t1_v1)
   311  	SHLQ(Imm(32), acc2_v1)
   312  	MULQ(p256const1)
   313  	SHRQ(Imm(32), t1_v1)
   314  	ADDQ(acc2_v1, acc3_v1)
   315  	ADCQ(t1_v1, acc0_v1)
   316  	ADCQ(RAX, acc1_v1)
   317  	ADCQ(Imm(0), RDX)
   318  	MOVQ(RDX, acc2_v1)
   319  
   320  	Comment("Last reduction step")
   321  	XORQ(t0_v1, t0_v1)
   322  	MOVQ(acc3_v1, RAX)
   323  	MOVQ(acc3_v1, t1_v1)
   324  	SHLQ(Imm(32), acc3_v1)
   325  	MULQ(p256const1)
   326  	SHRQ(Imm(32), t1_v1)
   327  	ADDQ(acc3_v1, acc0_v1)
   328  	ADCQ(t1_v1, acc1_v1)
   329  	ADCQ(RAX, acc2_v1)
   330  	ADCQ(Imm(0), RDX)
   331  	MOVQ(RDX, acc3_v1)
   332  
   333  	Comment("Add bits [511:256] of the sqr result")
   334  	ADCQ(acc4_v1, acc0_v1)
   335  	ADCQ(acc5_v1, acc1_v1)
   336  	ADCQ(y_ptr, acc2_v1)
   337  	ADCQ(x_ptr, acc3_v1)
   338  	ADCQ(Imm(0), t0_v1)
   339  
   340  	MOVQ(acc0_v1, acc4_v1)
   341  	MOVQ(acc1_v1, acc5_v1)
   342  	MOVQ(acc2_v1, y_ptr)
   343  	MOVQ(acc3_v1, t1_v1)
   344  
   345  	Comment("Subtract p256")
   346  	SUBQ(I8(-1), acc0_v1)
   347  
   348  	p256const0 := p256const0_DATA()
   349  	SBBQ(p256const0, acc1_v1)
   350  	SBBQ(Imm(0), acc2_v1)
   351  	SBBQ(p256const1, acc3_v1)
   352  	SBBQ(Imm(0), t0_v1)
   353  
   354  	CMOVQCS(acc4_v1, acc0_v1)
   355  	CMOVQCS(acc5_v1, acc1_v1)
   356  	CMOVQCS(y_ptr, acc2_v1)
   357  	CMOVQCS(t1_v1, acc3_v1)
   358  
   359  	MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*0))
   360  	MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*1))
   361  	MOVQ(acc2_v1, Mem{Base: res_ptr}.Offset(8*2))
   362  	MOVQ(acc3_v1, Mem{Base: res_ptr}.Offset(8*3))
   363  	MOVQ(res_ptr, x_ptr)
   364  	DECQ(RBX)
   365  	JNE(LabelRef("sqrLoop"))
   366  
   367  	RET()
   368  }
   369  
   370  // Implements:
   371  //
   372  //	func p256Mul(res, in1, in2 *p256Element)
   373  func p256Mul() {
   374  	Implement("p256Mul")
   375  	Attributes(NOSPLIT)
   376  
   377  	Load(Param("res"), res_ptr)
   378  	Load(Param("in1"), x_ptr)
   379  	Load(Param("in2"), y_ptr)
   380  
   381  	Comment("x * y[0]")
   382  	MOVQ(Mem{Base: y_ptr}.Offset(8*0), t0_v1)
   383  
   384  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   385  	MULQ(t0_v1)
   386  	MOVQ(RAX, acc0_v1)
   387  	MOVQ(RDX, acc1_v1)
   388  
   389  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   390  	MULQ(t0_v1)
   391  	ADDQ(RAX, acc1_v1)
   392  	ADCQ(Imm(0), RDX)
   393  	MOVQ(RDX, acc2_v1)
   394  
   395  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   396  	MULQ(t0_v1)
   397  	ADDQ(RAX, acc2_v1)
   398  	ADCQ(Imm(0), RDX)
   399  	MOVQ(RDX, acc3_v1)
   400  
   401  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   402  	MULQ(t0_v1)
   403  	ADDQ(RAX, acc3_v1)
   404  	ADCQ(Imm(0), RDX)
   405  	MOVQ(RDX, acc4_v1)
   406  	XORQ(acc5_v1, acc5_v1)
   407  
   408  	Comment("First reduction step")
   409  	MOVQ(acc0_v1, RAX)
   410  	MOVQ(acc0_v1, t1_v1)
   411  	SHLQ(Imm(32), acc0_v1)
   412  	p256const1 := p256const1_DATA()
   413  	MULQ(p256const1)
   414  	SHRQ(Imm(32), t1_v1)
   415  	ADDQ(acc0_v1, acc1_v1)
   416  	ADCQ(t1_v1, acc2_v1)
   417  	ADCQ(RAX, acc3_v1)
   418  	ADCQ(RDX, acc4_v1)
   419  	ADCQ(Imm(0), acc5_v1)
   420  	XORQ(acc0_v1, acc0_v1)
   421  
   422  	Comment("x * y[1]")
   423  	MOVQ(Mem{Base: y_ptr}.Offset(8*1), t0_v1)
   424  
   425  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   426  	MULQ(t0_v1)
   427  	ADDQ(RAX, acc1_v1)
   428  	ADCQ(Imm(0), RDX)
   429  	MOVQ(RDX, t1_v1)
   430  
   431  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   432  	MULQ(t0_v1)
   433  	ADDQ(t1_v1, acc2_v1)
   434  	ADCQ(Imm(0), RDX)
   435  	ADDQ(RAX, acc2_v1)
   436  	ADCQ(Imm(0), RDX)
   437  	MOVQ(RDX, t1_v1)
   438  
   439  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   440  	MULQ(t0_v1)
   441  	ADDQ(t1_v1, acc3_v1)
   442  	ADCQ(Imm(0), RDX)
   443  	ADDQ(RAX, acc3_v1)
   444  	ADCQ(Imm(0), RDX)
   445  	MOVQ(RDX, t1_v1)
   446  
   447  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   448  	MULQ(t0_v1)
   449  	ADDQ(t1_v1, acc4_v1)
   450  	ADCQ(Imm(0), RDX)
   451  	ADDQ(RAX, acc4_v1)
   452  	ADCQ(RDX, acc5_v1)
   453  	ADCQ(Imm(0), acc0_v1)
   454  
   455  	Comment("Second reduction step")
   456  	MOVQ(acc1_v1, RAX)
   457  	MOVQ(acc1_v1, t1_v1)
   458  	SHLQ(Imm(32), acc1_v1)
   459  	MULQ(p256const1)
   460  	SHRQ(Imm(32), t1_v1)
   461  	ADDQ(acc1_v1, acc2_v1)
   462  	ADCQ(t1_v1, acc3_v1)
   463  	ADCQ(RAX, acc4_v1)
   464  	ADCQ(RDX, acc5_v1)
   465  	ADCQ(Imm(0), acc0_v1)
   466  	XORQ(acc1_v1, acc1_v1)
   467  
   468  	Comment("x * y[2]")
   469  	MOVQ(Mem{Base: y_ptr}.Offset(8*2), t0_v1)
   470  
   471  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   472  	MULQ(t0_v1)
   473  	ADDQ(RAX, acc2_v1)
   474  	ADCQ(Imm(0), RDX)
   475  	MOVQ(RDX, t1_v1)
   476  
   477  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   478  	MULQ(t0_v1)
   479  	ADDQ(t1_v1, acc3_v1)
   480  	ADCQ(Imm(0), RDX)
   481  	ADDQ(RAX, acc3_v1)
   482  	ADCQ(Imm(0), RDX)
   483  	MOVQ(RDX, t1_v1)
   484  
   485  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   486  	MULQ(t0_v1)
   487  	ADDQ(t1_v1, acc4_v1)
   488  	ADCQ(Imm(0), RDX)
   489  	ADDQ(RAX, acc4_v1)
   490  	ADCQ(Imm(0), RDX)
   491  	MOVQ(RDX, t1_v1)
   492  
   493  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   494  	MULQ(t0_v1)
   495  	ADDQ(t1_v1, acc5_v1)
   496  	ADCQ(Imm(0), RDX)
   497  	ADDQ(RAX, acc5_v1)
   498  	ADCQ(RDX, acc0_v1)
   499  	ADCQ(Imm(0), acc1_v1)
   500  
   501  	Comment("Third reduction step")
   502  	MOVQ(acc2_v1, RAX)
   503  	MOVQ(acc2_v1, t1_v1)
   504  	SHLQ(Imm(32), acc2_v1)
   505  	MULQ(p256const1)
   506  	SHRQ(Imm(32), t1_v1)
   507  	ADDQ(acc2_v1, acc3_v1)
   508  	ADCQ(t1_v1, acc4_v1)
   509  	ADCQ(RAX, acc5_v1)
   510  	ADCQ(RDX, acc0_v1)
   511  	ADCQ(Imm(0), acc1_v1)
   512  	XORQ(acc2_v1, acc2_v1)
   513  	Comment("x * y[3]")
   514  
   515  	MOVQ(Mem{Base: y_ptr}.Offset(8*3), t0_v1)
   516  
   517  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), RAX)
   518  	MULQ(t0_v1)
   519  	ADDQ(RAX, acc3_v1)
   520  	ADCQ(Imm(0), RDX)
   521  	MOVQ(RDX, t1_v1)
   522  
   523  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), RAX)
   524  	MULQ(t0_v1)
   525  	ADDQ(t1_v1, acc4_v1)
   526  	ADCQ(Imm(0), RDX)
   527  	ADDQ(RAX, acc4_v1)
   528  	ADCQ(Imm(0), RDX)
   529  	MOVQ(RDX, t1_v1)
   530  
   531  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), RAX)
   532  	MULQ(t0_v1)
   533  	ADDQ(t1_v1, acc5_v1)
   534  	ADCQ(Imm(0), RDX)
   535  	ADDQ(RAX, acc5_v1)
   536  	ADCQ(Imm(0), RDX)
   537  	MOVQ(RDX, t1_v1)
   538  
   539  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), RAX)
   540  	MULQ(t0_v1)
   541  	ADDQ(t1_v1, acc0_v1)
   542  	ADCQ(Imm(0), RDX)
   543  	ADDQ(RAX, acc0_v1)
   544  	ADCQ(RDX, acc1_v1)
   545  	ADCQ(Imm(0), acc2_v1)
   546  
   547  	Comment("Last reduction step")
   548  	MOVQ(acc3_v1, RAX)
   549  	MOVQ(acc3_v1, t1_v1)
   550  	SHLQ(Imm(32), acc3_v1)
   551  	MULQ(p256const1)
   552  	SHRQ(Imm(32), t1_v1)
   553  	ADDQ(acc3_v1, acc4_v1)
   554  	ADCQ(t1_v1, acc5_v1)
   555  	ADCQ(RAX, acc0_v1)
   556  	ADCQ(RDX, acc1_v1)
   557  	ADCQ(Imm(0), acc2_v1)
   558  
   559  	Comment("Copy result [255:0]")
   560  	MOVQ(acc4_v1, x_ptr)
   561  	MOVQ(acc5_v1, acc3_v1)
   562  	MOVQ(acc0_v1, t0_v1)
   563  	MOVQ(acc1_v1, t1_v1)
   564  
   565  	Comment("Subtract p256")
   566  	SUBQ(I8(-1), acc4_v1)
   567  	p256const0 := p256const0_DATA()
   568  	SBBQ(p256const0, acc5_v1)
   569  	SBBQ(Imm(0), acc0_v1)
   570  	// SBBQ p256const1<>(SB), acc1_v1
   571  	SBBQ(p256const1, acc1_v1)
   572  	SBBQ(Imm(0), acc2_v1)
   573  
   574  	CMOVQCS(x_ptr, acc4_v1)
   575  	CMOVQCS(acc3_v1, acc5_v1)
   576  	CMOVQCS(t0_v1, acc0_v1)
   577  	CMOVQCS(t1_v1, acc1_v1)
   578  
   579  	MOVQ(acc4_v1, Mem{Base: res_ptr}.Offset(8*0))
   580  	MOVQ(acc5_v1, Mem{Base: res_ptr}.Offset(8*1))
   581  	MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*2))
   582  	MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*3))
   583  
   584  	RET()
   585  }
   586  
   587  // Implements:
   588  //
   589  //	func p256FromMont(res, in *p256Element)
   590  func p256FromMont() {
   591  	Implement("p256FromMont")
   592  	Attributes(NOSPLIT)
   593  
   594  	Load(Param("res"), res_ptr)
   595  	Load(Param("in"), x_ptr)
   596  
   597  	MOVQ(Mem{Base: x_ptr}.Offset(8*0), acc0_v1)
   598  	MOVQ(Mem{Base: x_ptr}.Offset(8*1), acc1_v1)
   599  	MOVQ(Mem{Base: x_ptr}.Offset(8*2), acc2_v1)
   600  	MOVQ(Mem{Base: x_ptr}.Offset(8*3), acc3_v1)
   601  	XORQ(acc4_v1, acc4_v1)
   602  
   603  	Comment("Only reduce, no multiplications are needed")
   604  	Comment("First stage")
   605  	MOVQ(acc0_v1, RAX)
   606  	MOVQ(acc0_v1, t1_v1)
   607  	SHLQ(Imm(32), acc0_v1)
   608  	p256const1 := p256const1_DATA()
   609  	MULQ(p256const1)
   610  	SHRQ(Imm(32), t1_v1)
   611  	ADDQ(acc0_v1, acc1_v1)
   612  	ADCQ(t1_v1, acc2_v1)
   613  	ADCQ(RAX, acc3_v1)
   614  	ADCQ(RDX, acc4_v1)
   615  	XORQ(acc5_v1, acc5_v1)
   616  
   617  	Comment("Second stage")
   618  	MOVQ(acc1_v1, RAX)
   619  	MOVQ(acc1_v1, t1_v1)
   620  	SHLQ(Imm(32), acc1_v1)
   621  	MULQ(p256const1)
   622  	SHRQ(Imm(32), t1_v1)
   623  	ADDQ(acc1_v1, acc2_v1)
   624  	ADCQ(t1_v1, acc3_v1)
   625  	ADCQ(RAX, acc4_v1)
   626  	ADCQ(RDX, acc5_v1)
   627  	XORQ(acc0_v1, acc0_v1)
   628  
   629  	Comment("Third stage")
   630  	MOVQ(acc2_v1, RAX)
   631  	MOVQ(acc2_v1, t1_v1)
   632  	SHLQ(Imm(32), acc2_v1)
   633  	MULQ(p256const1)
   634  	SHRQ(Imm(32), t1_v1)
   635  	ADDQ(acc2_v1, acc3_v1)
   636  	ADCQ(t1_v1, acc4_v1)
   637  	ADCQ(RAX, acc5_v1)
   638  	ADCQ(RDX, acc0_v1)
   639  	XORQ(acc1_v1, acc1_v1)
   640  
   641  	Comment("Last stage")
   642  	MOVQ(acc3_v1, RAX)
   643  	MOVQ(acc3_v1, t1_v1)
   644  	SHLQ(Imm(32), acc3_v1)
   645  	MULQ(p256const1)
   646  	SHRQ(Imm(32), t1_v1)
   647  	ADDQ(acc3_v1, acc4_v1)
   648  	ADCQ(t1_v1, acc5_v1)
   649  	ADCQ(RAX, acc0_v1)
   650  	ADCQ(RDX, acc1_v1)
   651  
   652  	MOVQ(acc4_v1, x_ptr)
   653  	MOVQ(acc5_v1, acc3_v1)
   654  	MOVQ(acc0_v1, t0_v1)
   655  	MOVQ(acc1_v1, t1_v1)
   656  
   657  	SUBQ(I8(-1), acc4_v1)
   658  	p256const0 := p256const0_DATA()
   659  	SBBQ(p256const0, acc5_v1)
   660  	SBBQ(Imm(0), acc0_v1)
   661  	SBBQ(p256const1, acc1_v1)
   662  
   663  	CMOVQCS(x_ptr, acc4_v1)
   664  	CMOVQCS(acc3_v1, acc5_v1)
   665  	CMOVQCS(t0_v1, acc0_v1)
   666  	CMOVQCS(t1_v1, acc1_v1)
   667  
   668  	MOVQ(acc4_v1, Mem{Base: res_ptr}.Offset(8*0))
   669  	MOVQ(acc5_v1, Mem{Base: res_ptr}.Offset(8*1))
   670  	MOVQ(acc0_v1, Mem{Base: res_ptr}.Offset(8*2))
   671  	MOVQ(acc1_v1, Mem{Base: res_ptr}.Offset(8*3))
   672  
   673  	RET()
   674  }
   675  
   676  // Implements:
   677  //
   678  //	func p256Select(res *P256Point, table *p256Table, idx int)
   679  func p256Select() {
   680  	Implement("p256Select")
   681  	Attributes(NOSPLIT)
   682  
   683  	Load(Param("idx"), RAX)
   684  	Load(Param("table"), RDI)
   685  	Load(Param("res"), RDX)
   686  
   687  	PXOR(X15, X15)    // X15 =  0
   688  	PCMPEQL(X14, X14) // X14 = -1
   689  	PSUBL(X14, X15)   // X15 =  1
   690  	// Force Avo to emit:
   691  	// 	MOVL AX, X14
   692  	Instruction(&ir.Instruction{
   693  		Opcode: "MOVL",
   694  		Operands: []Op{
   695  			EAX, X14,
   696  		},
   697  	})
   698  	PSHUFD(Imm(0), X14, X14)
   699  
   700  	PXOR(X0, X0)
   701  	PXOR(X1, X1)
   702  	PXOR(X2, X2)
   703  	PXOR(X3, X3)
   704  	PXOR(X4, X4)
   705  	PXOR(X5, X5)
   706  	MOVQ(U32(16), RAX)
   707  
   708  	MOVOU(X15, X13)
   709  
   710  	Label("loop_select")
   711  
   712  	MOVOU(X13, X12)
   713  	PADDL(X15, X13)
   714  	PCMPEQL(X14, X12)
   715  
   716  	MOVOU(Mem{Base: DI}.Offset(16*0), X6)
   717  	MOVOU(Mem{Base: DI}.Offset(16*1), X7)
   718  	MOVOU(Mem{Base: DI}.Offset(16*2), X8)
   719  	MOVOU(Mem{Base: DI}.Offset(16*3), X9)
   720  	MOVOU(Mem{Base: DI}.Offset(16*4), X10)
   721  	MOVOU(Mem{Base: DI}.Offset(16*5), X11)
   722  	ADDQ(U8(16*6), RDI)
   723  
   724  	PAND(X12, X6)
   725  	PAND(X12, X7)
   726  	PAND(X12, X8)
   727  	PAND(X12, X9)
   728  	PAND(X12, X10)
   729  	PAND(X12, X11)
   730  
   731  	PXOR(X6, X0)
   732  	PXOR(X7, X1)
   733  	PXOR(X8, X2)
   734  	PXOR(X9, X3)
   735  	PXOR(X10, X4)
   736  	PXOR(X11, X5)
   737  
   738  	DECQ(RAX)
   739  	JNE(LabelRef("loop_select"))
   740  
   741  	MOVOU(X0, Mem{Base: DX}.Offset(16*0))
   742  	MOVOU(X1, Mem{Base: DX}.Offset(16*1))
   743  	MOVOU(X2, Mem{Base: DX}.Offset(16*2))
   744  	MOVOU(X3, Mem{Base: DX}.Offset(16*3))
   745  	MOVOU(X4, Mem{Base: DX}.Offset(16*4))
   746  	MOVOU(X5, Mem{Base: DX}.Offset(16*5))
   747  
   748  	RET()
   749  }
   750  
   751  // Implements:
   752  //
   753  //	func p256SelectAffine(res *p256AffinePoint, table *p256AffineTable, idx int)
   754  func p256SelectAffine() {
   755  	Implement("p256SelectAffine")
   756  	Attributes(NOSPLIT)
   757  
   758  	Load(Param("idx"), RAX)
   759  	Load(Param("table"), RDI)
   760  	Load(Param("res"), RDX)
   761  
   762  	PXOR(X15, X15)    // X15 =  0
   763  	PCMPEQL(X14, X14) // X14 = -1
   764  	PSUBL(X14, X15)   // X15 =  1
   765  
   766  	// Hack to get Avo to emit:
   767  	// 	MOVL AX, X14
   768  	Instruction(&ir.Instruction{Opcode: "MOVL", Operands: []Op{RAX, X14}})
   769  
   770  	PSHUFD(Imm(0), X14, X14)
   771  
   772  	PXOR(X0, X0)
   773  	PXOR(X1, X1)
   774  	PXOR(X2, X2)
   775  	PXOR(X3, X3)
   776  	MOVQ(U32(16), RAX)
   777  
   778  	MOVOU(X15, X13)
   779  
   780  	Label("loop_select_base")
   781  
   782  	MOVOU(X13, X12)
   783  	PADDL(X15, X13)
   784  	PCMPEQL(X14, X12)
   785  
   786  	MOVOU(Mem{Base: DI}.Offset(16*0), X4)
   787  	MOVOU(Mem{Base: DI}.Offset(16*1), X5)
   788  	MOVOU(Mem{Base: DI}.Offset(16*2), X6)
   789  	MOVOU(Mem{Base: DI}.Offset(16*3), X7)
   790  
   791  	MOVOU(Mem{Base: DI}.Offset(16*4), X8)
   792  	MOVOU(Mem{Base: DI}.Offset(16*5), X9)
   793  	MOVOU(Mem{Base: DI}.Offset(16*6), X10)
   794  	MOVOU(Mem{Base: DI}.Offset(16*7), X11)
   795  
   796  	ADDQ(Imm(16*8), RDI)
   797  
   798  	PAND(X12, X4)
   799  	PAND(X12, X5)
   800  	PAND(X12, X6)
   801  	PAND(X12, X7)
   802  
   803  	MOVOU(X13, X12)
   804  	PADDL(X15, X13)
   805  	PCMPEQL(X14, X12)
   806  
   807  	PAND(X12, X8)
   808  	PAND(X12, X9)
   809  	PAND(X12, X10)
   810  	PAND(X12, X11)
   811  
   812  	PXOR(X4, X0)
   813  	PXOR(X5, X1)
   814  	PXOR(X6, X2)
   815  	PXOR(X7, X3)
   816  
   817  	PXOR(X8, X0)
   818  	PXOR(X9, X1)
   819  	PXOR(X10, X2)
   820  	PXOR(X11, X3)
   821  
   822  	DECQ(RAX)
   823  	JNE(LabelRef("loop_select_base"))
   824  
   825  	MOVOU(X0, Mem{Base: DX}.Offset(16*0))
   826  	MOVOU(X1, Mem{Base: DX}.Offset(16*1))
   827  	MOVOU(X2, Mem{Base: DX}.Offset(16*2))
   828  	MOVOU(X3, Mem{Base: DX}.Offset(16*3))
   829  
   830  	RET()
   831  }
   832  
   833  // These variables have been versioned as they get redfined in the reference implementation.
   834  // This is done to produce a minimal semantic diff.
   835  var (
   836  	mul0_v2 = RAX
   837  	mul1_v2 = RDX
   838  	acc0_v2 = RBX
   839  	acc1_v2 = RCX
   840  	acc2_v2 = R8
   841  	acc3_v2 = R9
   842  	acc4_v2 = R10
   843  	acc5_v2 = R11
   844  	acc6_v2 = R12
   845  	acc7_v2 = R13
   846  	t0_v2   = R14
   847  	t1_v2   = R15
   848  	t2_v2   = RDI
   849  	t3_v2   = RSI
   850  	hlp_v2  = RBP
   851  )
   852  
   853  func p256SubInternal() {
   854  	Function("p256SubInternal")
   855  	Attributes(NOSPLIT)
   856  
   857  	XORQ(mul0_v2, mul0_v2)
   858  	SUBQ(t0_v2, acc4_v2)
   859  	SBBQ(t1_v2, acc5_v2)
   860  	SBBQ(t2_v2, acc6_v2)
   861  	SBBQ(t3_v2, acc7_v2)
   862  	SBBQ(Imm(0), mul0_v2)
   863  
   864  	MOVQ(acc4_v2, acc0_v2)
   865  	MOVQ(acc5_v2, acc1_v2)
   866  	MOVQ(acc6_v2, acc2_v2)
   867  	MOVQ(acc7_v2, acc3_v2)
   868  
   869  	ADDQ(I8(-1), acc4_v2)
   870  	p256const0 := p256const0_DATA()
   871  	ADCQ(p256const0, acc5_v2)
   872  	ADCQ(Imm(0), acc6_v2)
   873  	p256const1 := p256const1_DATA()
   874  	ADCQ(p256const1, acc7_v2)
   875  	ANDQ(Imm(1), mul0_v2)
   876  
   877  	CMOVQEQ(acc0_v2, acc4_v2)
   878  	CMOVQEQ(acc1_v2, acc5_v2)
   879  	CMOVQEQ(acc2_v2, acc6_v2)
   880  	CMOVQEQ(acc3_v2, acc7_v2)
   881  
   882  	RET()
   883  }
   884  
   885  func p256MulInternal() {
   886  	Function("p256MulInternal")
   887  	Attributes(NOSPLIT)
   888  
   889  	MOVQ(acc4_v2, mul0_v2)
   890  	MULQ(t0_v2)
   891  	MOVQ(mul0_v2, acc0_v2)
   892  	MOVQ(mul1_v2, acc1_v2)
   893  
   894  	MOVQ(acc4_v2, mul0_v2)
   895  	MULQ(t1_v2)
   896  	ADDQ(mul0_v2, acc1_v2)
   897  	ADCQ(Imm(0), mul1_v2)
   898  	MOVQ(mul1_v2, acc2_v2)
   899  
   900  	MOVQ(acc4_v2, mul0_v2)
   901  	MULQ(t2_v2)
   902  	ADDQ(mul0_v2, acc2_v2)
   903  	ADCQ(Imm(0), mul1_v2)
   904  	MOVQ(mul1_v2, acc3_v2)
   905  
   906  	MOVQ(acc4_v2, mul0_v2)
   907  	MULQ(t3_v2)
   908  	ADDQ(mul0_v2, acc3_v2)
   909  	ADCQ(Imm(0), mul1_v2)
   910  	MOVQ(mul1_v2, acc4_v2)
   911  
   912  	MOVQ(acc5_v2, mul0_v2)
   913  	MULQ(t0_v2)
   914  	ADDQ(mul0_v2, acc1_v2)
   915  	ADCQ(Imm(0), mul1_v2)
   916  	MOVQ(mul1_v2, hlp_v2)
   917  
   918  	MOVQ(acc5_v2, mul0_v2)
   919  	MULQ(t1_v2)
   920  	ADDQ(hlp_v2, acc2_v2)
   921  	ADCQ(Imm(0), mul1_v2)
   922  	ADDQ(mul0_v2, acc2_v2)
   923  	ADCQ(Imm(0), mul1_v2)
   924  	MOVQ(mul1_v2, hlp_v2)
   925  
   926  	MOVQ(acc5_v2, mul0_v2)
   927  	MULQ(t2_v2)
   928  	ADDQ(hlp_v2, acc3_v2)
   929  	ADCQ(Imm(0), mul1_v2)
   930  	ADDQ(mul0_v2, acc3_v2)
   931  	ADCQ(Imm(0), mul1_v2)
   932  	MOVQ(mul1_v2, hlp_v2)
   933  
   934  	MOVQ(acc5_v2, mul0_v2)
   935  	MULQ(t3_v2)
   936  	ADDQ(hlp_v2, acc4_v2)
   937  	ADCQ(Imm(0), mul1_v2)
   938  	ADDQ(mul0_v2, acc4_v2)
   939  	ADCQ(Imm(0), mul1_v2)
   940  	MOVQ(mul1_v2, acc5_v2)
   941  
   942  	MOVQ(acc6_v2, mul0_v2)
   943  	MULQ(t0_v2)
   944  	ADDQ(mul0_v2, acc2_v2)
   945  	ADCQ(Imm(0), mul1_v2)
   946  	MOVQ(mul1_v2, hlp_v2)
   947  
   948  	MOVQ(acc6_v2, mul0_v2)
   949  	MULQ(t1_v2)
   950  	ADDQ(hlp_v2, acc3_v2)
   951  	ADCQ(Imm(0), mul1_v2)
   952  	ADDQ(mul0_v2, acc3_v2)
   953  	ADCQ(Imm(0), mul1_v2)
   954  	MOVQ(mul1_v2, hlp_v2)
   955  
   956  	MOVQ(acc6_v2, mul0_v2)
   957  	MULQ(t2_v2)
   958  	ADDQ(hlp_v2, acc4_v2)
   959  	ADCQ(Imm(0), mul1_v2)
   960  	ADDQ(mul0_v2, acc4_v2)
   961  	ADCQ(Imm(0), mul1_v2)
   962  	MOVQ(mul1_v2, hlp_v2)
   963  
   964  	MOVQ(acc6_v2, mul0_v2)
   965  	MULQ(t3_v2)
   966  	ADDQ(hlp_v2, acc5_v2)
   967  	ADCQ(Imm(0), mul1_v2)
   968  	ADDQ(mul0_v2, acc5_v2)
   969  	ADCQ(Imm(0), mul1_v2)
   970  	MOVQ(mul1_v2, acc6_v2)
   971  
   972  	MOVQ(acc7_v2, mul0_v2)
   973  	MULQ(t0_v2)
   974  	ADDQ(mul0_v2, acc3_v2)
   975  	ADCQ(Imm(0), mul1_v2)
   976  	MOVQ(mul1_v2, hlp_v2)
   977  
   978  	MOVQ(acc7_v2, mul0_v2)
   979  	MULQ(t1_v2)
   980  	ADDQ(hlp_v2, acc4_v2)
   981  	ADCQ(Imm(0), mul1_v2)
   982  	ADDQ(mul0_v2, acc4_v2)
   983  	ADCQ(Imm(0), mul1_v2)
   984  	MOVQ(mul1_v2, hlp_v2)
   985  
   986  	MOVQ(acc7_v2, mul0_v2)
   987  	MULQ(t2_v2)
   988  	ADDQ(hlp_v2, acc5_v2)
   989  	ADCQ(Imm(0), mul1_v2)
   990  	ADDQ(mul0_v2, acc5_v2)
   991  	ADCQ(Imm(0), mul1_v2)
   992  	MOVQ(mul1_v2, hlp_v2)
   993  
   994  	MOVQ(acc7_v2, mul0_v2)
   995  	MULQ(t3_v2)
   996  	ADDQ(hlp_v2, acc6_v2)
   997  	ADCQ(Imm(0), mul1_v2)
   998  	ADDQ(mul0_v2, acc6_v2)
   999  	ADCQ(Imm(0), mul1_v2)
  1000  	MOVQ(mul1_v2, acc7_v2)
  1001  
  1002  	Comment("First reduction step")
  1003  	MOVQ(acc0_v2, mul0_v2)
  1004  	MOVQ(acc0_v2, hlp_v2)
  1005  	SHLQ(Imm(32), acc0_v2)
  1006  	p256const1 := p256const1_DATA()
  1007  	MULQ(p256const1)
  1008  	SHRQ(Imm(32), hlp_v2)
  1009  	ADDQ(acc0_v2, acc1_v2)
  1010  	ADCQ(hlp_v2, acc2_v2)
  1011  	ADCQ(mul0_v2, acc3_v2)
  1012  	ADCQ(Imm(0), mul1_v2)
  1013  	MOVQ(mul1_v2, acc0_v2)
  1014  
  1015  	Comment("Second reduction step")
  1016  	MOVQ(acc1_v2, mul0_v2)
  1017  	MOVQ(acc1_v2, hlp_v2)
  1018  	SHLQ(Imm(32), acc1_v2)
  1019  	MULQ(p256const1)
  1020  	SHRQ(Imm(32), hlp_v2)
  1021  	ADDQ(acc1_v2, acc2_v2)
  1022  	ADCQ(hlp_v2, acc3_v2)
  1023  	ADCQ(mul0_v2, acc0_v2)
  1024  	ADCQ(Imm(0), mul1_v2)
  1025  	MOVQ(mul1_v2, acc1_v2)
  1026  
  1027  	Comment("Third reduction step")
  1028  	MOVQ(acc2_v2, mul0_v2)
  1029  	MOVQ(acc2_v2, hlp_v2)
  1030  	SHLQ(Imm(32), acc2_v2)
  1031  	MULQ(p256const1)
  1032  	SHRQ(Imm(32), hlp_v2)
  1033  	ADDQ(acc2_v2, acc3_v2)
  1034  	ADCQ(hlp_v2, acc0_v2)
  1035  	ADCQ(mul0_v2, acc1_v2)
  1036  	ADCQ(Imm(0), mul1_v2)
  1037  	MOVQ(mul1_v2, acc2_v2)
  1038  
  1039  	Comment("Last reduction step")
  1040  	MOVQ(acc3_v2, mul0_v2)
  1041  	MOVQ(acc3_v2, hlp_v2)
  1042  	SHLQ(Imm(32), acc3_v2)
  1043  	MULQ(p256const1)
  1044  	SHRQ(Imm(32), hlp_v2)
  1045  	ADDQ(acc3_v2, acc0_v2)
  1046  	ADCQ(hlp_v2, acc1_v2)
  1047  	ADCQ(mul0_v2, acc2_v2)
  1048  	ADCQ(Imm(0), mul1_v2)
  1049  	MOVQ(mul1_v2, acc3_v2)
  1050  	MOVQ(U32(0), RBP)
  1051  
  1052  	Comment("Add bits [511:256] of the result")
  1053  	ADCQ(acc0_v2, acc4_v2)
  1054  	ADCQ(acc1_v2, acc5_v2)
  1055  	ADCQ(acc2_v2, acc6_v2)
  1056  	ADCQ(acc3_v2, acc7_v2)
  1057  	ADCQ(Imm(0), hlp_v2)
  1058  
  1059  	Comment("Copy result")
  1060  	MOVQ(acc4_v2, acc0_v2)
  1061  	MOVQ(acc5_v2, acc1_v2)
  1062  	MOVQ(acc6_v2, acc2_v2)
  1063  	MOVQ(acc7_v2, acc3_v2)
  1064  
  1065  	Comment("Subtract p256")
  1066  	SUBQ(I8(-1), acc4_v2)
  1067  	p256const0 := p256const0_DATA()
  1068  	SBBQ(p256const0, acc5_v2)
  1069  	SBBQ(Imm(0), acc6_v2)
  1070  	SBBQ(p256const1, acc7_v2)
  1071  	SBBQ(Imm(0), hlp_v2)
  1072  
  1073  	Comment("If the result of the subtraction is negative, restore the previous result")
  1074  	CMOVQCS(acc0_v2, acc4_v2)
  1075  	CMOVQCS(acc1_v2, acc5_v2)
  1076  	CMOVQCS(acc2_v2, acc6_v2)
  1077  	CMOVQCS(acc3_v2, acc7_v2)
  1078  
  1079  	RET()
  1080  }
  1081  
  1082  func p256SqrInternal() {
  1083  	Function("p256SqrInternal")
  1084  	Attributes(NOSPLIT)
  1085  
  1086  	MOVQ(acc4_v2, mul0_v2)
  1087  	MULQ(acc5_v2)
  1088  	MOVQ(mul0_v2, acc1_v2)
  1089  	MOVQ(mul1_v2, acc2_v2)
  1090  
  1091  	MOVQ(acc4_v2, mul0_v2)
  1092  	MULQ(acc6_v2)
  1093  	ADDQ(mul0_v2, acc2_v2)
  1094  	ADCQ(Imm(0), mul1_v2)
  1095  	MOVQ(mul1_v2, acc3_v2)
  1096  
  1097  	MOVQ(acc4_v2, mul0_v2)
  1098  	MULQ(acc7_v2)
  1099  	ADDQ(mul0_v2, acc3_v2)
  1100  	ADCQ(Imm(0), mul1_v2)
  1101  	MOVQ(mul1_v2, t0_v2)
  1102  
  1103  	MOVQ(acc5_v2, mul0_v2)
  1104  	MULQ(acc6_v2)
  1105  	ADDQ(mul0_v2, acc3_v2)
  1106  	ADCQ(Imm(0), mul1_v2)
  1107  	MOVQ(mul1_v2, hlp_v2)
  1108  
  1109  	MOVQ(acc5_v2, mul0_v2)
  1110  	MULQ(acc7_v2)
  1111  	ADDQ(hlp_v2, t0_v2)
  1112  	ADCQ(Imm(0), mul1_v2)
  1113  	ADDQ(mul0_v2, t0_v2)
  1114  	ADCQ(Imm(0), mul1_v2)
  1115  	MOVQ(mul1_v2, t1_v2)
  1116  
  1117  	MOVQ(acc6_v2, mul0_v2)
  1118  	MULQ(acc7_v2)
  1119  	ADDQ(mul0_v2, t1_v2)
  1120  	ADCQ(Imm(0), mul1_v2)
  1121  	MOVQ(mul1_v2, t2_v2)
  1122  	XORQ(t3_v2, t3_v2)
  1123  
  1124  	Comment("*2")
  1125  	ADDQ(acc1_v2, acc1_v2)
  1126  	ADCQ(acc2_v2, acc2_v2)
  1127  	ADCQ(acc3_v2, acc3_v2)
  1128  	ADCQ(t0_v2, t0_v2)
  1129  	ADCQ(t1_v2, t1_v2)
  1130  	ADCQ(t2_v2, t2_v2)
  1131  	ADCQ(Imm(0), t3_v2)
  1132  
  1133  	Comment("Missing products")
  1134  	MOVQ(acc4_v2, mul0_v2)
  1135  	MULQ(mul0_v2)
  1136  	MOVQ(mul0_v2, acc0_v2)
  1137  	MOVQ(RDX, acc4_v2)
  1138  
  1139  	MOVQ(acc5_v2, mul0_v2)
  1140  	MULQ(mul0_v2)
  1141  	ADDQ(acc4_v2, acc1_v2)
  1142  	ADCQ(mul0_v2, acc2_v2)
  1143  	ADCQ(Imm(0), RDX)
  1144  	MOVQ(RDX, acc4_v2)
  1145  
  1146  	MOVQ(acc6_v2, mul0_v2)
  1147  	MULQ(mul0_v2)
  1148  	ADDQ(acc4_v2, acc3_v2)
  1149  	ADCQ(mul0_v2, t0_v2)
  1150  	ADCQ(Imm(0), RDX)
  1151  	MOVQ(RDX, acc4_v2)
  1152  
  1153  	MOVQ(acc7_v2, mul0_v2)
  1154  	MULQ(mul0_v2)
  1155  	ADDQ(acc4_v2, t1_v2)
  1156  	ADCQ(mul0_v2, t2_v2)
  1157  	ADCQ(RDX, t3_v2)
  1158  
  1159  	Comment("First reduction step")
  1160  	MOVQ(acc0_v2, mul0_v2)
  1161  	MOVQ(acc0_v2, hlp_v2)
  1162  	SHLQ(Imm(32), acc0_v2)
  1163  	p256const1 := p256const1_DATA()
  1164  	MULQ(p256const1)
  1165  	SHRQ(Imm(32), hlp_v2)
  1166  	ADDQ(acc0_v2, acc1_v2)
  1167  	ADCQ(hlp_v2, acc2_v2)
  1168  	ADCQ(mul0_v2, acc3_v2)
  1169  	ADCQ(Imm(0), mul1_v2)
  1170  	MOVQ(mul1_v2, acc0_v2)
  1171  
  1172  	Comment("Second reduction step")
  1173  	MOVQ(acc1_v2, mul0_v2)
  1174  	MOVQ(acc1_v2, hlp_v2)
  1175  	SHLQ(Imm(32), acc1_v2)
  1176  	MULQ(p256const1)
  1177  	SHRQ(Imm(32), hlp_v2)
  1178  	ADDQ(acc1_v2, acc2_v2)
  1179  	ADCQ(hlp_v2, acc3_v2)
  1180  	ADCQ(mul0_v2, acc0_v2)
  1181  	ADCQ(Imm(0), mul1_v2)
  1182  	MOVQ(mul1_v2, acc1_v2)
  1183  
  1184  	Comment("Third reduction step")
  1185  	MOVQ(acc2_v2, mul0_v2)
  1186  	MOVQ(acc2_v2, hlp_v2)
  1187  	SHLQ(Imm(32), acc2_v2)
  1188  	MULQ(p256const1)
  1189  	SHRQ(Imm(32), hlp_v2)
  1190  	ADDQ(acc2_v2, acc3_v2)
  1191  	ADCQ(hlp_v2, acc0_v2)
  1192  	ADCQ(mul0_v2, acc1_v2)
  1193  	ADCQ(Imm(0), mul1_v2)
  1194  	MOVQ(mul1_v2, acc2_v2)
  1195  
  1196  	Comment("Last reduction step")
  1197  	MOVQ(acc3_v2, mul0_v2)
  1198  	MOVQ(acc3_v2, hlp_v2)
  1199  	SHLQ(Imm(32), acc3_v2)
  1200  	MULQ(p256const1)
  1201  	SHRQ(Imm(32), hlp_v2)
  1202  	ADDQ(acc3_v2, acc0_v2)
  1203  	ADCQ(hlp_v2, acc1_v2)
  1204  	ADCQ(mul0_v2, acc2_v2)
  1205  	ADCQ(Imm(0), mul1_v2)
  1206  	MOVQ(mul1_v2, acc3_v2)
  1207  	MOVQ(U32(0), RBP)
  1208  
  1209  	Comment("Add bits [511:256] of the result")
  1210  	ADCQ(acc0_v2, t0_v2)
  1211  	ADCQ(acc1_v2, t1_v2)
  1212  	ADCQ(acc2_v2, t2_v2)
  1213  	ADCQ(acc3_v2, t3_v2)
  1214  	ADCQ(Imm(0), hlp_v2)
  1215  
  1216  	Comment("Copy result")
  1217  	MOVQ(t0_v2, acc4_v2)
  1218  	MOVQ(t1_v2, acc5_v2)
  1219  	MOVQ(t2_v2, acc6_v2)
  1220  	MOVQ(t3_v2, acc7_v2)
  1221  
  1222  	Comment("Subtract p256")
  1223  	SUBQ(I8(-1), acc4_v2)
  1224  	p256const0 := p256const0_DATA()
  1225  	SBBQ(p256const0, acc5_v2)
  1226  	SBBQ(Imm(0), acc6_v2)
  1227  	SBBQ(p256const1, acc7_v2)
  1228  	SBBQ(Imm(0), hlp_v2)
  1229  
  1230  	Comment("If the result of the subtraction is negative, restore the previous result")
  1231  	CMOVQCS(t0_v2, acc4_v2)
  1232  	CMOVQCS(t1_v2, acc5_v2)
  1233  	CMOVQCS(t2_v2, acc6_v2)
  1234  	CMOVQCS(t3_v2, acc7_v2)
  1235  
  1236  	RET()
  1237  }
  1238  
  1239  func p256MulBy2Inline() {
  1240  	XORQ(mul0_v2, mul0_v2)
  1241  	ADDQ(acc4_v2, acc4_v2)
  1242  	ADCQ(acc5_v2, acc5_v2)
  1243  	ADCQ(acc6_v2, acc6_v2)
  1244  	ADCQ(acc7_v2, acc7_v2)
  1245  	ADCQ(I8(0), mul0_v2)
  1246  	MOVQ(acc4_v2, t0_v2)
  1247  	MOVQ(acc5_v2, t1_v2)
  1248  	MOVQ(acc6_v2, t2_v2)
  1249  	MOVQ(acc7_v2, t3_v2)
  1250  	SUBQ(I8(-1), t0_v2)
  1251  	p256const0 := p256const0_DATA()
  1252  	SBBQ(p256const0, t1_v2)
  1253  	SBBQ(I8(0), t2_v2)
  1254  	p256const1 := p256const1_DATA()
  1255  	SBBQ(p256const1, t3_v2)
  1256  	SBBQ(I8(0), mul0_v2)
  1257  	CMOVQCS(acc4_v2, t0_v2)
  1258  	CMOVQCS(acc5_v2, t1_v2)
  1259  	CMOVQCS(acc6_v2, t2_v2)
  1260  	CMOVQCS(acc7_v2, t3_v2)
  1261  }
  1262  
  1263  func p256AddInline() {
  1264  	XORQ(mul0_v2, mul0_v2)
  1265  	ADDQ(t0_v2, acc4_v2)
  1266  	ADCQ(t1_v2, acc5_v2)
  1267  	ADCQ(t2_v2, acc6_v2)
  1268  	ADCQ(t3_v2, acc7_v2)
  1269  	ADCQ(I8(0), mul0_v2)
  1270  	MOVQ(acc4_v2, t0_v2)
  1271  	MOVQ(acc5_v2, t1_v2)
  1272  	MOVQ(acc6_v2, t2_v2)
  1273  	MOVQ(acc7_v2, t3_v2)
  1274  	SUBQ(I8(-1), t0_v2)
  1275  	p256const0 := p256const0_DATA()
  1276  	SBBQ(p256const0, t1_v2)
  1277  	SBBQ(I8(0), t2_v2)
  1278  	p256const1 := p256const1_DATA()
  1279  	SBBQ(p256const1, t3_v2)
  1280  	SBBQ(I8(0), mul0_v2)
  1281  	CMOVQCS(acc4_v2, t0_v2)
  1282  	CMOVQCS(acc5_v2, t1_v2)
  1283  	CMOVQCS(acc6_v2, t2_v2)
  1284  	CMOVQCS(acc7_v2, t3_v2)
  1285  }
  1286  
  1287  /* ---------------------------------------*/
  1288  
  1289  type MemFunc func(off int) Mem
  1290  
  1291  func LDacc(src MemFunc) {
  1292  	MOVQ(src(8*0), acc4_v2)
  1293  	MOVQ(src(8*1), acc5_v2)
  1294  	MOVQ(src(8*2), acc6_v2)
  1295  	MOVQ(src(8*3), acc7_v2)
  1296  }
  1297  
  1298  func LDt(src MemFunc) {
  1299  	MOVQ(src(8*0), t0_v2)
  1300  	MOVQ(src(8*1), t1_v2)
  1301  	MOVQ(src(8*2), t2_v2)
  1302  	MOVQ(src(8*3), t3_v2)
  1303  }
  1304  
  1305  func ST(dst MemFunc) {
  1306  	MOVQ(acc4_v2, dst(8*0))
  1307  	MOVQ(acc5_v2, dst(8*1))
  1308  	MOVQ(acc6_v2, dst(8*2))
  1309  	MOVQ(acc7_v2, dst(8*3))
  1310  }
  1311  
  1312  func STt(dst MemFunc) {
  1313  	MOVQ(t0_v2, dst(8*0))
  1314  	MOVQ(t1_v2, dst(8*1))
  1315  	MOVQ(t2_v2, dst(8*2))
  1316  	MOVQ(t3_v2, dst(8*3))
  1317  }
  1318  
  1319  func acc2t() {
  1320  	MOVQ(acc4_v2, t0_v2)
  1321  	MOVQ(acc5_v2, t1_v2)
  1322  	MOVQ(acc6_v2, t2_v2)
  1323  	MOVQ(acc7_v2, t3_v2)
  1324  }
  1325  
  1326  func t2acc() {
  1327  	MOVQ(t0_v2, acc4_v2)
  1328  	MOVQ(t1_v2, acc5_v2)
  1329  	MOVQ(t2_v2, acc6_v2)
  1330  	MOVQ(t3_v2, acc7_v2)
  1331  }
  1332  
  1333  /* ---------------------------------------*/
  1334  
  1335  // These functions exist as #define macros in the reference implementation.
  1336  //
  1337  // In the reference assembly, these macros are later undefined and redefined.
  1338  // They are implemented here as versioned functions.
  1339  
  1340  func x1in_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*0 + off) }
  1341  func y1in_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*1 + off) }
  1342  func z1in_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*2 + off) }
  1343  func x2in_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*3 + off) }
  1344  func y2in_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*4 + off) }
  1345  func xout_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*5 + off) }
  1346  func yout_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*6 + off) }
  1347  func zout_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*7 + off) }
  1348  func s2_v1(off int) Mem    { return Mem{Base: SP}.Offset(32*8 + off) }
  1349  func z1sqr_v1(off int) Mem { return Mem{Base: SP}.Offset(32*9 + off) }
  1350  func h_v1(off int) Mem     { return Mem{Base: SP}.Offset(32*10 + off) }
  1351  func r_v1(off int) Mem     { return Mem{Base: SP}.Offset(32*11 + off) }
  1352  func hsqr_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*12 + off) }
  1353  func rsqr_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*13 + off) }
  1354  func hcub_v1(off int) Mem  { return Mem{Base: SP}.Offset(32*14 + off) }
  1355  
  1356  var (
  1357  	rptr_v1      Mem = Mem{Base: SP}.Offset(32*15 + 0)
  1358  	sel_save_v1      = Mem{Base: SP}.Offset(32*15 + 8)
  1359  	zero_save_v1     = Mem{Base: SP}.Offset(32*15 + 8 + 4)
  1360  )
  1361  
  1362  // Implements:
  1363  //
  1364  //	func p256PointAddAffineAsm(res, in1 *P256Point, in2 *p256AffinePoint, sign, sel, zero int)
  1365  func p256PointAddAffineAsm() {
  1366  	Implement("p256PointAddAffineAsm")
  1367  	AllocLocal(512)
  1368  
  1369  	Load(Param("res"), RAX)
  1370  	Load(Param("in1"), RBX)
  1371  	Load(Param("in2"), RCX)
  1372  	Load(Param("sign"), RDX)
  1373  	Load(Param("sel"), t1_v2)
  1374  	Load(Param("zero"), t2_v2)
  1375  
  1376  	MOVOU(Mem{Base: BX}.Offset(16*0), X0)
  1377  	MOVOU(Mem{Base: BX}.Offset(16*1), X1)
  1378  	MOVOU(Mem{Base: BX}.Offset(16*2), X2)
  1379  	MOVOU(Mem{Base: BX}.Offset(16*3), X3)
  1380  	MOVOU(Mem{Base: BX}.Offset(16*4), X4)
  1381  	MOVOU(Mem{Base: BX}.Offset(16*5), X5)
  1382  
  1383  	MOVOU(X0, x1in_v1(16*0))
  1384  	MOVOU(X1, x1in_v1(16*1))
  1385  	MOVOU(X2, y1in_v1(16*0))
  1386  	MOVOU(X3, y1in_v1(16*1))
  1387  	MOVOU(X4, z1in_v1(16*0))
  1388  	MOVOU(X5, z1in_v1(16*1))
  1389  
  1390  	MOVOU(Mem{Base: CX}.Offset(16*0), X0)
  1391  	MOVOU(Mem{Base: CX}.Offset(16*1), X1)
  1392  
  1393  	MOVOU(X0, x2in_v1(16*0))
  1394  	MOVOU(X1, x2in_v1(16*1))
  1395  
  1396  	Comment("Store pointer to result")
  1397  	MOVQ(mul0_v2, rptr_v1)
  1398  
  1399  	// Hack to get Avo to emit:
  1400  	// 	MOVL t1, sel_save_v1
  1401  	Instruction(&ir.Instruction{
  1402  		Opcode:   "MOVL",
  1403  		Operands: []Op{t1_v2, sel_save_v1},
  1404  	})
  1405  
  1406  	// Hack to get Avo to emit:
  1407  	// 	MOVL t2_v2, zero_save_v1
  1408  	Instruction(&ir.Instruction{
  1409  		Opcode:   "MOVL",
  1410  		Operands: []Op{t2_v2, zero_save_v1},
  1411  	})
  1412  
  1413  	Comment("Negate y2in based on sign")
  1414  	MOVQ(Mem{Base: CX}.Offset(16*2+8*0), acc4_v2)
  1415  	MOVQ(Mem{Base: CX}.Offset(16*2+8*1), acc5_v2)
  1416  	MOVQ(Mem{Base: CX}.Offset(16*2+8*2), acc6_v2)
  1417  	MOVQ(Mem{Base: CX}.Offset(16*2+8*3), acc7_v2)
  1418  	MOVQ(I32(-1), acc0_v2)
  1419  	p256const0 := p256const0_DATA()
  1420  	MOVQ(p256const0, acc1_v2)
  1421  	MOVQ(U32(0), acc2_v2)
  1422  	p256const1 := p256const1_DATA()
  1423  	MOVQ(p256const1, acc3_v2)
  1424  	XORQ(mul0_v2, mul0_v2)
  1425  
  1426  	Comment("Speculatively subtract")
  1427  	SUBQ(acc4_v2, acc0_v2)
  1428  	SBBQ(acc5_v2, acc1_v2)
  1429  	SBBQ(acc6_v2, acc2_v2)
  1430  	SBBQ(acc7_v2, acc3_v2)
  1431  	SBBQ(Imm(0), mul0_v2)
  1432  	MOVQ(acc0_v2, t0_v2)
  1433  	MOVQ(acc1_v2, t1_v2)
  1434  	MOVQ(acc2_v2, t2_v2)
  1435  	MOVQ(acc3_v2, t3_v2)
  1436  
  1437  	Comment("Add in case the operand was > p256")
  1438  	ADDQ(I8(-1), acc0_v2)
  1439  	ADCQ(p256const0, acc1_v2)
  1440  	ADCQ(Imm(0), acc2_v2)
  1441  	ADCQ(p256const1, acc3_v2)
  1442  	ADCQ(Imm(0), mul0_v2)
  1443  	CMOVQNE(t0_v2, acc0_v2)
  1444  	CMOVQNE(t1_v2, acc1_v2)
  1445  	CMOVQNE(t2_v2, acc2_v2)
  1446  	CMOVQNE(t3_v2, acc3_v2)
  1447  
  1448  	Comment("If condition is 0, keep original value")
  1449  	TESTQ(RDX, RDX)
  1450  	CMOVQEQ(acc4_v2, acc0_v2)
  1451  	CMOVQEQ(acc5_v2, acc1_v2)
  1452  	CMOVQEQ(acc6_v2, acc2_v2)
  1453  	CMOVQEQ(acc7_v2, acc3_v2)
  1454  
  1455  	Comment("Store result")
  1456  	MOVQ(acc0_v2, y2in_v1(8*0))
  1457  	MOVQ(acc1_v2, y2in_v1(8*1))
  1458  	MOVQ(acc2_v2, y2in_v1(8*2))
  1459  	MOVQ(acc3_v2, y2in_v1(8*3))
  1460  
  1461  	Comment("Begin point add")
  1462  	LDacc(z1in_v1)
  1463  	CALL(LabelRef("p256SqrInternal(SB)")) //                  z1ˆ2
  1464  	ST(z1sqr_v1)
  1465  
  1466  	LDt(x2in_v1)
  1467  	CALL(LabelRef("p256MulInternal(SB)")) //             x2 * z1ˆ2
  1468  
  1469  	LDt(x1in_v1)
  1470  	CALL(LabelRef("p256SubInternal(SB)")) //          h = u2 - u1)
  1471  	ST(h_v1)
  1472  
  1473  	LDt(z1in_v1)
  1474  	CALL(LabelRef("p256MulInternal(SB)")) //           z3 = h * z1
  1475  	ST(zout_v1)
  1476  
  1477  	LDacc(z1sqr_v1)
  1478  	CALL(LabelRef("p256MulInternal(SB)")) //                  z1ˆ3
  1479  
  1480  	LDt(y2in_v1)
  1481  	CALL(LabelRef("p256MulInternal(SB)")) //        s2 = y2 * z1ˆ3
  1482  	ST(s2_v1)
  1483  
  1484  	LDt(y1in_v1)
  1485  	CALL(LabelRef("p256SubInternal(SB)")) //          r = s2 - s1)
  1486  	ST(r_v1)
  1487  
  1488  	CALL(LabelRef("p256SqrInternal(SB)")) //            rsqr = rˆ2
  1489  	ST(rsqr_v1)
  1490  
  1491  	LDacc(h_v1)
  1492  	CALL(LabelRef("p256SqrInternal(SB)")) //            hsqr = hˆ2
  1493  	ST(hsqr_v1)
  1494  
  1495  	LDt(h_v1)
  1496  	CALL(LabelRef("p256MulInternal(SB)")) //            hcub = hˆ3
  1497  	ST(hcub_v1)
  1498  
  1499  	LDt(y1in_v1)
  1500  	CALL(LabelRef("p256MulInternal(SB)")) //             y1 * hˆ3
  1501  	ST(s2_v1)
  1502  
  1503  	LDacc(x1in_v1)
  1504  	LDt(hsqr_v1)
  1505  	CALL(LabelRef("p256MulInternal(SB)")) //             u1 * hˆ2
  1506  	ST(h_v1)
  1507  
  1508  	p256MulBy2Inline() //                    u1 * hˆ2 * 2, inline
  1509  	LDacc(rsqr_v1)
  1510  	CALL(LabelRef("p256SubInternal(SB)")) //  rˆ2 - u1 * hˆ2 * 2)
  1511  
  1512  	LDt(hcub_v1)
  1513  	CALL(LabelRef("p256SubInternal(SB)"))
  1514  	ST(xout_v1)
  1515  
  1516  	MOVQ(acc4_v2, t0_v2)
  1517  	MOVQ(acc5_v2, t1_v2)
  1518  	MOVQ(acc6_v2, t2_v2)
  1519  	MOVQ(acc7_v2, t3_v2)
  1520  	LDacc(h_v1)
  1521  	CALL(LabelRef("p256SubInternal(SB)"))
  1522  
  1523  	LDt(r_v1)
  1524  	CALL(LabelRef("p256MulInternal(SB)"))
  1525  
  1526  	LDt(s2_v1)
  1527  	CALL(LabelRef("p256SubInternal(SB)"))
  1528  	ST(yout_v1)
  1529  
  1530  	Comment("Load stored values from stack")
  1531  	MOVQ(rptr_v1, RAX)
  1532  	MOVL(sel_save_v1, EBX)
  1533  	MOVL(zero_save_v1, ECX)
  1534  
  1535  	Comment("The result is not valid if (sel == 0), conditional choose")
  1536  	MOVOU(xout_v1(16*0), X0)
  1537  	MOVOU(xout_v1(16*1), X1)
  1538  	MOVOU(yout_v1(16*0), X2)
  1539  	MOVOU(yout_v1(16*1), X3)
  1540  	MOVOU(zout_v1(16*0), X4)
  1541  	MOVOU(zout_v1(16*1), X5)
  1542  
  1543  	// Hack to get Avo to emit:
  1544  	// 	MOVL BX, X6
  1545  	Instruction(&ir.Instruction{
  1546  		Opcode:   "MOVL",
  1547  		Operands: []Op{EBX, X6},
  1548  	})
  1549  
  1550  	// Hack to get Avo to emit:
  1551  	// 	MOVL CX, X7
  1552  	Instruction(&ir.Instruction{
  1553  		Opcode:   "MOVL",
  1554  		Operands: []Op{ECX, X7},
  1555  	})
  1556  
  1557  	PXOR(X8, X8)
  1558  	PCMPEQL(X9, X9)
  1559  
  1560  	PSHUFD(Imm(0), X6, X6)
  1561  	PSHUFD(Imm(0), X7, X7)
  1562  
  1563  	PCMPEQL(X8, X6)
  1564  	PCMPEQL(X8, X7)
  1565  
  1566  	MOVOU(X6, X15)
  1567  	PANDN(X9, X15)
  1568  
  1569  	MOVOU(x1in_v1(16*0), X9)
  1570  	MOVOU(x1in_v1(16*1), X10)
  1571  	MOVOU(y1in_v1(16*0), X11)
  1572  	MOVOU(y1in_v1(16*1), X12)
  1573  	MOVOU(z1in_v1(16*0), X13)
  1574  	MOVOU(z1in_v1(16*1), X14)
  1575  
  1576  	PAND(X15, X0)
  1577  	PAND(X15, X1)
  1578  	PAND(X15, X2)
  1579  	PAND(X15, X3)
  1580  	PAND(X15, X4)
  1581  	PAND(X15, X5)
  1582  
  1583  	PAND(X6, X9)
  1584  	PAND(X6, X10)
  1585  	PAND(X6, X11)
  1586  	PAND(X6, X12)
  1587  	PAND(X6, X13)
  1588  	PAND(X6, X14)
  1589  
  1590  	PXOR(X9, X0)
  1591  	PXOR(X10, X1)
  1592  	PXOR(X11, X2)
  1593  	PXOR(X12, X3)
  1594  	PXOR(X13, X4)
  1595  	PXOR(X14, X5)
  1596  
  1597  	Comment("Similarly if zero == 0")
  1598  	PCMPEQL(X9, X9)
  1599  	MOVOU(X7, X15)
  1600  	PANDN(X9, X15)
  1601  
  1602  	MOVOU(x2in_v1(16*0), X9)
  1603  	MOVOU(x2in_v1(16*1), X10)
  1604  	MOVOU(y2in_v1(16*0), X11)
  1605  	MOVOU(y2in_v1(16*1), X12)
  1606  	p256one := p256one_DATA()
  1607  	MOVOU(p256one.Offset(0x00), X13)
  1608  	MOVOU(p256one.Offset(0x10), X14)
  1609  
  1610  	PAND(X15, X0)
  1611  	PAND(X15, X1)
  1612  	PAND(X15, X2)
  1613  	PAND(X15, X3)
  1614  	PAND(X15, X4)
  1615  	PAND(X15, X5)
  1616  
  1617  	PAND(X7, X9)
  1618  	PAND(X7, X10)
  1619  	PAND(X7, X11)
  1620  	PAND(X7, X12)
  1621  	PAND(X7, X13)
  1622  	PAND(X7, X14)
  1623  
  1624  	PXOR(X9, X0)
  1625  	PXOR(X10, X1)
  1626  	PXOR(X11, X2)
  1627  	PXOR(X12, X3)
  1628  	PXOR(X13, X4)
  1629  	PXOR(X14, X5)
  1630  
  1631  	Comment("Finally output the result")
  1632  	MOVOU(X0, Mem{Base: AX}.Offset(16*0))
  1633  	MOVOU(X1, Mem{Base: AX}.Offset(16*1))
  1634  	MOVOU(X2, Mem{Base: AX}.Offset(16*2))
  1635  	MOVOU(X3, Mem{Base: AX}.Offset(16*3))
  1636  	MOVOU(X4, Mem{Base: AX}.Offset(16*4))
  1637  	MOVOU(X5, Mem{Base: AX}.Offset(16*5))
  1638  	MOVQ(U32(0), rptr_v1)
  1639  
  1640  	RET()
  1641  }
  1642  
  1643  // p256IsZero returns 1 in AX if [acc4..acc7] represents zero and zero
  1644  // otherwise. It writes to [acc4..acc7], t0 and t1.
  1645  func p256IsZero() {
  1646  	Function("p256IsZero")
  1647  	Attributes(NOSPLIT)
  1648  
  1649  	Comment("AX contains a flag that is set if the input is zero.")
  1650  	XORQ(RAX, RAX)
  1651  	MOVQ(U32(1), t1_v2)
  1652  
  1653  	Comment("Check whether [acc4..acc7] are all zero.")
  1654  	MOVQ(acc4_v2, t0_v2)
  1655  	ORQ(acc5_v2, t0_v2)
  1656  	ORQ(acc6_v2, t0_v2)
  1657  	ORQ(acc7_v2, t0_v2)
  1658  
  1659  	Comment("Set the zero flag if so. (CMOV of a constant to a register doesn't")
  1660  	Comment("appear to be supported in Go. Thus t1 = 1.)")
  1661  	CMOVQEQ(t1_v2, RAX)
  1662  
  1663  	Comment("XOR [acc4..acc7] with P and compare with zero again.")
  1664  	XORQ(I8(-1), acc4_v2)
  1665  	p256const0 := p256const0_DATA()
  1666  	XORQ(p256const0, acc5_v2)
  1667  	p256const1 := p256const1_DATA()
  1668  	XORQ(p256const1, acc7_v2)
  1669  	ORQ(acc5_v2, acc4_v2)
  1670  	ORQ(acc6_v2, acc4_v2)
  1671  	ORQ(acc7_v2, acc4_v2)
  1672  
  1673  	Comment("Set the zero flag if so.")
  1674  	CMOVQEQ(t1_v2, RAX)
  1675  	RET()
  1676  }
  1677  
  1678  func x1in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*0 + off) }
  1679  func y1in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*1 + off) }
  1680  func z1in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*2 + off) }
  1681  func x2in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*3 + off) }
  1682  func y2in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*4 + off) }
  1683  func z2in_v2(off int) Mem { return Mem{Base: SP}.Offset(32*5 + off) }
  1684  
  1685  func xout_v2(off int) Mem { return Mem{Base: SP}.Offset(32*6 + off) }
  1686  func yout_v2(off int) Mem { return Mem{Base: SP}.Offset(32*7 + off) }
  1687  func zout_v2(off int) Mem { return Mem{Base: SP}.Offset(32*8 + off) }
  1688  
  1689  func u1_v2(off int) Mem    { return Mem{Base: SP}.Offset(32*9 + off) }
  1690  func u2_v2(off int) Mem    { return Mem{Base: SP}.Offset(32*10 + off) }
  1691  func s1_v2(off int) Mem    { return Mem{Base: SP}.Offset(32*11 + off) }
  1692  func s2_v2(off int) Mem    { return Mem{Base: SP}.Offset(32*12 + off) }
  1693  func z1sqr_v2(off int) Mem { return Mem{Base: SP}.Offset(32*13 + off) }
  1694  func z2sqr_v2(off int) Mem { return Mem{Base: SP}.Offset(32*14 + off) }
  1695  func h_v2(off int) Mem     { return Mem{Base: SP}.Offset(32*15 + off) }
  1696  func r_v2(off int) Mem     { return Mem{Base: SP}.Offset(32*16 + off) }
  1697  func hsqr_v2(off int) Mem  { return Mem{Base: SP}.Offset(32*17 + off) }
  1698  func rsqr_v2(off int) Mem  { return Mem{Base: SP}.Offset(32*18 + off) }
  1699  func hcub_v2(off int) Mem  { return Mem{Base: SP}.Offset(32*19 + off) }
  1700  
  1701  var (
  1702  	rptr_v2      Mem = Mem{Base: SP}.Offset(32 * 20)
  1703  	points_eq_v2     = Mem{Base: SP}.Offset(32*20 + 8)
  1704  )
  1705  
  1706  // Implements:
  1707  //
  1708  //	func p256PointAddAsm(res, in1, in2 *P256Point) int
  1709  //
  1710  // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
  1711  func p256PointAddAsm() {
  1712  	Implement("p256PointAddAsm")
  1713  	AllocLocal(680)
  1714  
  1715  	Comment("Move input to stack in order to free registers")
  1716  	Load(Param("res"), RAX)
  1717  	Load(Param("in1"), RBX)
  1718  	Load(Param("in2"), RCX)
  1719  
  1720  	MOVOU(Mem{Base: BX}.Offset(16*0), X0)
  1721  	MOVOU(Mem{Base: BX}.Offset(16*1), X1)
  1722  	MOVOU(Mem{Base: BX}.Offset(16*2), X2)
  1723  	MOVOU(Mem{Base: BX}.Offset(16*3), X3)
  1724  	MOVOU(Mem{Base: BX}.Offset(16*4), X4)
  1725  	MOVOU(Mem{Base: BX}.Offset(16*5), X5)
  1726  
  1727  	MOVOU(X0, x1in_v2(16*0))
  1728  	MOVOU(X1, x1in_v2(16*1))
  1729  	MOVOU(X2, y1in_v2(16*0))
  1730  	MOVOU(X3, y1in_v2(16*1))
  1731  	MOVOU(X4, z1in_v2(16*0))
  1732  	MOVOU(X5, z1in_v2(16*1))
  1733  
  1734  	MOVOU(Mem{Base: CX}.Offset(16*0), X0)
  1735  	MOVOU(Mem{Base: CX}.Offset(16*1), X1)
  1736  	MOVOU(Mem{Base: CX}.Offset(16*2), X2)
  1737  	MOVOU(Mem{Base: CX}.Offset(16*3), X3)
  1738  	MOVOU(Mem{Base: CX}.Offset(16*4), X4)
  1739  	MOVOU(Mem{Base: CX}.Offset(16*5), X5)
  1740  
  1741  	MOVOU(X0, x2in_v2(16*0))
  1742  	MOVOU(X1, x2in_v2(16*1))
  1743  	MOVOU(X2, y2in_v2(16*0))
  1744  	MOVOU(X3, y2in_v2(16*1))
  1745  	MOVOU(X4, z2in_v2(16*0))
  1746  	MOVOU(X5, z2in_v2(16*1))
  1747  
  1748  	Comment("Store pointer to result")
  1749  	MOVQ(RAX, rptr_v2)
  1750  
  1751  	Comment("Begin point add")
  1752  	LDacc(z2in_v2)
  1753  	CALL(LabelRef("p256SqrInternal(SB)")) //               z2ˆ2
  1754  	ST(z2sqr_v2)
  1755  	LDt(z2in_v2)
  1756  	CALL(LabelRef("p256MulInternal(SB)")) //               z2ˆ3
  1757  	LDt(y1in_v2)
  1758  	CALL(LabelRef("p256MulInternal(SB)")) //       s1 = z2ˆ3*y1
  1759  	ST(s1_v2)
  1760  
  1761  	LDacc(z1in_v2)
  1762  	CALL(LabelRef("p256SqrInternal(SB)")) //               z1ˆ2
  1763  	ST(z1sqr_v2)
  1764  	LDt(z1in_v2)
  1765  	CALL(LabelRef("p256MulInternal(SB)")) //               z1ˆ3
  1766  	LDt(y2in_v2)
  1767  	CALL(LabelRef("p256MulInternal(SB)")) //       s2 = z1ˆ3*y2
  1768  	ST(s2_v2)
  1769  
  1770  	LDt(s1_v2)
  1771  	CALL(LabelRef("p256SubInternal(SB)")) //        r = s2 - s1
  1772  	ST(r_v2)
  1773  	CALL(LabelRef("p256IsZero(SB)"))
  1774  	MOVQ(RAX, points_eq_v2)
  1775  
  1776  	LDacc(z2sqr_v2)
  1777  	LDt(x1in_v2)
  1778  	CALL(LabelRef("p256MulInternal(SB)")) //     u1 = x1 * z2ˆ2
  1779  	ST(u1_v2)
  1780  	LDacc(z1sqr_v2)
  1781  	LDt(x2in_v2)
  1782  	CALL(LabelRef("p256MulInternal(SB)")) //     u2 = x2 * z1ˆ2
  1783  	ST(u2_v2)
  1784  
  1785  	LDt(u1_v2)
  1786  	CALL(LabelRef("p256SubInternal(SB)")) //        h = u2 - u1
  1787  	ST(h_v2)
  1788  	CALL(LabelRef("p256IsZero(SB)"))
  1789  	ANDQ(points_eq_v2, RAX)
  1790  	MOVQ(RAX, points_eq_v2)
  1791  
  1792  	LDacc(r_v2)
  1793  	CALL(LabelRef("p256SqrInternal(SB)")) //         rsqr = rˆ2
  1794  	ST(rsqr_v2)
  1795  
  1796  	LDacc(h_v2)
  1797  	CALL(LabelRef("p256SqrInternal(SB)")) //         hsqr = hˆ2
  1798  	ST(hsqr_v2)
  1799  
  1800  	LDt(h_v2)
  1801  	CALL(LabelRef("p256MulInternal(SB)")) //         hcub = hˆ3
  1802  	ST(hcub_v2)
  1803  
  1804  	LDt(s1_v2)
  1805  	CALL(LabelRef("p256MulInternal(SB)"))
  1806  	ST(s2_v2)
  1807  
  1808  	LDacc(z1in_v2)
  1809  	LDt(z2in_v2)
  1810  	CALL(LabelRef("p256MulInternal(SB)")) //            z1 * z2
  1811  	LDt(h_v2)
  1812  	CALL(LabelRef("p256MulInternal(SB)")) //        z1 * z2 * h
  1813  	ST(zout_v2)
  1814  
  1815  	LDacc(hsqr_v2)
  1816  	LDt(u1_v2)
  1817  	CALL(LabelRef("p256MulInternal(SB)")) //           hˆ2 * u1
  1818  	ST(u2_v2)
  1819  
  1820  	p256MulBy2Inline() //                  u1 * hˆ2 * 2, inline
  1821  	LDacc(rsqr_v2)
  1822  	CALL(LabelRef("p256SubInternal(SB)")) // rˆ2 - u1 * hˆ2 * 2
  1823  
  1824  	LDt(hcub_v2)
  1825  	CALL(LabelRef("p256SubInternal(SB)"))
  1826  	ST(xout_v2)
  1827  
  1828  	MOVQ(acc4_v2, t0_v2)
  1829  	MOVQ(acc5_v2, t1_v2)
  1830  	MOVQ(acc6_v2, t2_v2)
  1831  	MOVQ(acc7_v2, t3_v2)
  1832  	LDacc(u2_v2)
  1833  	CALL(LabelRef("p256SubInternal(SB)"))
  1834  
  1835  	LDt(r_v2)
  1836  	CALL(LabelRef("p256MulInternal(SB)"))
  1837  
  1838  	LDt(s2_v2)
  1839  	CALL(LabelRef("p256SubInternal(SB)"))
  1840  	ST(yout_v2)
  1841  
  1842  	MOVOU(xout_v2(16*0), X0)
  1843  	MOVOU(xout_v2(16*1), X1)
  1844  	MOVOU(yout_v2(16*0), X2)
  1845  	MOVOU(yout_v2(16*1), X3)
  1846  	MOVOU(zout_v2(16*0), X4)
  1847  	MOVOU(zout_v2(16*1), X5)
  1848  
  1849  	Comment("Finally output the result")
  1850  	MOVQ(rptr_v2, RAX)
  1851  	MOVQ(U32(0), rptr_v2)
  1852  	MOVOU(X0, Mem{Base: AX}.Offset(16*0))
  1853  	MOVOU(X1, Mem{Base: AX}.Offset(16*1))
  1854  	MOVOU(X2, Mem{Base: AX}.Offset(16*2))
  1855  	MOVOU(X3, Mem{Base: AX}.Offset(16*3))
  1856  	MOVOU(X4, Mem{Base: AX}.Offset(16*4))
  1857  	MOVOU(X5, Mem{Base: AX}.Offset(16*5))
  1858  
  1859  	MOVQ(points_eq_v2, RAX)
  1860  	ret := NewParamAddr("ret", 24)
  1861  	MOVQ(RAX, ret)
  1862  
  1863  	RET()
  1864  }
  1865  
  1866  func x(off int) Mem { return Mem{Base: SP}.Offset(32*0 + off) }
  1867  func y(off int) Mem { return Mem{Base: SP}.Offset(32*1 + off) }
  1868  func z(off int) Mem { return Mem{Base: SP}.Offset(32*2 + off) }
  1869  
  1870  func s(off int) Mem    { return Mem{Base: SP}.Offset(32*3 + off) }
  1871  func m(off int) Mem    { return Mem{Base: SP}.Offset(32*4 + off) }
  1872  func zsqr(off int) Mem { return Mem{Base: SP}.Offset(32*5 + off) }
  1873  func tmp(off int) Mem  { return Mem{Base: SP}.Offset(32*6 + off) }
  1874  
  1875  var rptr_v3 = Mem{Base: SP}.Offset(32 * 7)
  1876  
  1877  // Implements:
  1878  //
  1879  //	func p256PointDoubleAsm(res, in *P256Point)
  1880  func p256PointDoubleAsm() {
  1881  	Implement("p256PointDoubleAsm")
  1882  	Attributes(NOSPLIT)
  1883  	AllocLocal(256)
  1884  
  1885  	Load(Param("res"), RAX)
  1886  	Load(Param("in"), RBX)
  1887  
  1888  	MOVOU(Mem{Base: BX}.Offset(16*0), X0)
  1889  	MOVOU(Mem{Base: BX}.Offset(16*1), X1)
  1890  	MOVOU(Mem{Base: BX}.Offset(16*2), X2)
  1891  	MOVOU(Mem{Base: BX}.Offset(16*3), X3)
  1892  	MOVOU(Mem{Base: BX}.Offset(16*4), X4)
  1893  	MOVOU(Mem{Base: BX}.Offset(16*5), X5)
  1894  
  1895  	MOVOU(X0, x(16*0))
  1896  	MOVOU(X1, x(16*1))
  1897  	MOVOU(X2, y(16*0))
  1898  	MOVOU(X3, y(16*1))
  1899  	MOVOU(X4, z(16*0))
  1900  	MOVOU(X5, z(16*1))
  1901  
  1902  	Comment("Store pointer to result")
  1903  	MOVQ(RAX, rptr_v3)
  1904  
  1905  	Comment("Begin point double")
  1906  	LDacc(z)
  1907  	CALL(LabelRef("p256SqrInternal(SB)"))
  1908  	ST(zsqr)
  1909  
  1910  	LDt(x)
  1911  	p256AddInline()
  1912  	STt(m)
  1913  
  1914  	LDacc(z)
  1915  	LDt(y)
  1916  	CALL(LabelRef("p256MulInternal(SB)"))
  1917  	p256MulBy2Inline()
  1918  	MOVQ(rptr_v3, RAX)
  1919  
  1920  	Comment("Store z")
  1921  	MOVQ(t0_v2, Mem{Base: AX}.Offset(16*4+8*0))
  1922  	MOVQ(t1_v2, Mem{Base: AX}.Offset(16*4+8*1))
  1923  	MOVQ(t2_v2, Mem{Base: AX}.Offset(16*4+8*2))
  1924  	MOVQ(t3_v2, Mem{Base: AX}.Offset(16*4+8*3))
  1925  
  1926  	LDacc(x)
  1927  	LDt(zsqr)
  1928  	CALL(LabelRef("p256SubInternal(SB)"))
  1929  	LDt(m)
  1930  	CALL(LabelRef("p256MulInternal(SB)"))
  1931  	ST(m)
  1932  
  1933  	Comment("Multiply by 3")
  1934  	p256MulBy2Inline()
  1935  	LDacc(m)
  1936  	p256AddInline()
  1937  	STt(m)
  1938  	Comment("////////////////////////")
  1939  	LDacc(y)
  1940  	p256MulBy2Inline()
  1941  	t2acc()
  1942  	CALL(LabelRef("p256SqrInternal(SB)"))
  1943  	ST(s)
  1944  	CALL(LabelRef("p256SqrInternal(SB)"))
  1945  
  1946  	Comment("Divide by 2")
  1947  	XORQ(mul0_v2, mul0_v2)
  1948  	MOVQ(acc4_v2, t0_v2)
  1949  	MOVQ(acc5_v2, t1_v2)
  1950  	MOVQ(acc6_v2, t2_v2)
  1951  	MOVQ(acc7_v2, t3_v2)
  1952  
  1953  	ADDQ(I8(-1), acc4_v2)
  1954  	p256const0 := p256const0_DATA()
  1955  	ADCQ(p256const0, acc5_v2)
  1956  	ADCQ(Imm(0), acc6_v2)
  1957  	p256const1 := p256const1_DATA()
  1958  	ADCQ(p256const1, acc7_v2)
  1959  	ADCQ(Imm(0), mul0_v2)
  1960  	TESTQ(U32(1), t0_v2)
  1961  
  1962  	CMOVQEQ(t0_v2, acc4_v2)
  1963  	CMOVQEQ(t1_v2, acc5_v2)
  1964  	CMOVQEQ(t2_v2, acc6_v2)
  1965  	CMOVQEQ(t3_v2, acc7_v2)
  1966  	ANDQ(t0_v2, mul0_v2)
  1967  
  1968  	SHRQ(Imm(1), acc5_v2, acc4_v2)
  1969  	SHRQ(Imm(1), acc6_v2, acc5_v2)
  1970  	SHRQ(Imm(1), acc7_v2, acc6_v2)
  1971  	SHRQ(Imm(1), mul0_v2, acc7_v2)
  1972  	ST(y)
  1973  	Comment("/////////////////////////")
  1974  	LDacc(x)
  1975  	LDt(s)
  1976  	CALL(LabelRef("p256MulInternal(SB)"))
  1977  	ST(s)
  1978  	p256MulBy2Inline()
  1979  	STt(tmp)
  1980  
  1981  	LDacc(m)
  1982  	CALL(LabelRef("p256SqrInternal(SB)"))
  1983  	LDt(tmp)
  1984  	CALL(LabelRef("p256SubInternal(SB)"))
  1985  
  1986  	MOVQ(rptr_v3, RAX)
  1987  
  1988  	Comment("Store x")
  1989  	MOVQ(acc4_v2, Mem{Base: AX}.Offset(16*0+8*0))
  1990  	MOVQ(acc5_v2, Mem{Base: AX}.Offset(16*0+8*1))
  1991  	MOVQ(acc6_v2, Mem{Base: AX}.Offset(16*0+8*2))
  1992  	MOVQ(acc7_v2, Mem{Base: AX}.Offset(16*0+8*3))
  1993  
  1994  	acc2t()
  1995  	LDacc(s)
  1996  	CALL(LabelRef("p256SubInternal(SB)"))
  1997  
  1998  	LDt(m)
  1999  	CALL(LabelRef("p256MulInternal(SB)"))
  2000  
  2001  	LDt(y)
  2002  	CALL(LabelRef("p256SubInternal(SB)"))
  2003  	MOVQ(rptr_v3, RAX)
  2004  
  2005  	Comment("Store y")
  2006  	MOVQ(acc4_v2, Mem{Base: AX}.Offset(16*2+8*0))
  2007  	MOVQ(acc5_v2, Mem{Base: AX}.Offset(16*2+8*1))
  2008  	MOVQ(acc6_v2, Mem{Base: AX}.Offset(16*2+8*2))
  2009  	MOVQ(acc7_v2, Mem{Base: AX}.Offset(16*2+8*3))
  2010  	Comment("///////////////////////")
  2011  	MOVQ(U32(0), rptr_v3)
  2012  
  2013  	RET()
  2014  }
  2015  
  2016  // #----------------------------DATA SECTION-----------------------------------##
  2017  
  2018  // Pointers for memoizing Data section symbols
  2019  var p256const0_ptr, p256const1_ptr, p256one_ptr *Mem
  2020  
  2021  func p256const0_DATA() Mem {
  2022  	if p256const0_ptr != nil {
  2023  		return *p256const0_ptr
  2024  	}
  2025  
  2026  	p256const0 := GLOBL("p256const0", 8)
  2027  	p256const0_ptr = &p256const0
  2028  	DATA(0, U64(0x00000000ffffffff))
  2029  	return p256const0
  2030  }
  2031  
  2032  func p256const1_DATA() Mem {
  2033  	if p256const1_ptr != nil {
  2034  		return *p256const1_ptr
  2035  	}
  2036  
  2037  	p256const1 := GLOBL("p256const1", 8)
  2038  	p256const1_ptr = &p256const1
  2039  	DATA(0, U64(0xffffffff00000001))
  2040  	return p256const1
  2041  }
  2042  
  2043  var p256oneConstants = [4]uint64{
  2044  	0x0000000000000001,
  2045  	0xffffffff00000000,
  2046  	0xffffffffffffffff,
  2047  	0x00000000fffffffe,
  2048  }
  2049  
  2050  func p256one_DATA() Mem {
  2051  	if p256one_ptr != nil {
  2052  		return *p256one_ptr
  2053  	}
  2054  
  2055  	p256one := GLOBL("p256one", 8)
  2056  	p256one_ptr = &p256one
  2057  
  2058  	for i, k := range p256oneConstants {
  2059  		DATA(i*8, U64(k))
  2060  	}
  2061  
  2062  	return p256one
  2063  }
  2064  
  2065  const ThatPeskyUnicodeDot = "\u00b7"
  2066  
  2067  // removePeskyUnicodeDot strips the dot from the relevant TEXT directives such that they
  2068  // can exist as internal assembly functions
  2069  //
  2070  // Avo v0.6.0 does not support the generation of internal assembly functions. Go's unicode
  2071  // dot tells the compiler to link a TEXT symbol to a function in the current Go package
  2072  // (or another package if specified). Avo unconditionally prepends the unicode dot to all
  2073  // TEXT symbols, making it impossible to emit an internal function without this hack.
  2074  //
  2075  // There is a pending PR to add internal functions to Avo:
  2076  // https://github.com/mmcloughlin/avo/pull/443
  2077  //
  2078  // If merged it should allow the usage of InternalFunction("NAME") for the specified functions
  2079  func removePeskyUnicodeDot(internalFunctions []string, target string) {
  2080  	bytes, err := os.ReadFile(target)
  2081  	if err != nil {
  2082  		panic(err)
  2083  	}
  2084  
  2085  	content := string(bytes)
  2086  
  2087  	for _, from := range internalFunctions {
  2088  		to := strings.ReplaceAll(from, ThatPeskyUnicodeDot, "")
  2089  		content = strings.ReplaceAll(content, from, to)
  2090  	}
  2091  
  2092  	err = os.WriteFile(target, []byte(content), 0644)
  2093  	if err != nil {
  2094  		panic(err)
  2095  	}
  2096  }
  2097  

View as plain text