p256_asm.mx raw

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