]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.boringcrypto] all: merge master into dev.boringcrypto
authorHeschi Kreinick <heschi@google.com>
Mon, 8 Nov 2021 19:46:41 +0000 (14:46 -0500)
committerHeschi Kreinick <heschi@google.com>
Mon, 8 Nov 2021 19:46:41 +0000 (14:46 -0500)
Change-Id: If0a6a3d0abf15d9584ce572510b5bb31872d432f

90 files changed:
doc/go1.18.html
src/bufio/bufio_test.go
src/bytes/bytes.go
src/bytes/example_test.go
src/cmd/compile/internal/inline/inl.go
src/cmd/compile/internal/ssa/expand_calls.go
src/cmd/compile/internal/ssa/stmtlines_test.go
src/cmd/compile/internal/typecheck/crawler.go
src/cmd/compile/internal/typecheck/iimport.go
src/cmd/dist/test.go
src/cmd/go/internal/modload/init.go
src/cmd/go/internal/modload/modfile.go
src/cmd/go/testdata/script/gcflags_patterns.txt
src/cmd/internal/sys/supported.go
src/cmd/link/internal/ld/config.go
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ppc64/asm.go
src/crypto/aes/asm_ppc64le.s
src/crypto/elliptic/elliptic.go
src/crypto/elliptic/elliptic_test.go
src/crypto/elliptic/internal/fiat/Dockerfile
src/crypto/elliptic/internal/fiat/README
src/crypto/elliptic/internal/fiat/fiat_test.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/generate.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p224.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p224_fiat64.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p224_invert.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p384.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p384_fiat64.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p384_invert.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p521.go
src/crypto/elliptic/internal/fiat/p521_fiat64.go
src/crypto/elliptic/internal/fiat/p521_invert.go [new file with mode: 0644]
src/crypto/elliptic/internal/fiat/p521_test.go [deleted file]
src/crypto/elliptic/internal/nistec/nistec_test.go [new file with mode: 0644]
src/crypto/elliptic/internal/nistec/p224.go [new file with mode: 0644]
src/crypto/elliptic/internal/nistec/p384.go [new file with mode: 0644]
src/crypto/elliptic/internal/nistec/p521.go
src/crypto/elliptic/internal/nistec/p521_test.go [deleted file]
src/crypto/elliptic/p224.go
src/crypto/elliptic/p224_test.go
src/crypto/elliptic/p256.go
src/crypto/elliptic/p256_test.go
src/crypto/elliptic/p384.go [new file with mode: 0644]
src/crypto/elliptic/p521.go
src/crypto/tls/common.go
src/crypto/tls/handshake_client.go
src/crypto/tls/handshake_server.go
src/crypto/tls/handshake_server_test.go
src/crypto/tls/handshake_server_tls13.go
src/crypto/tls/handshake_test.go
src/crypto/x509/verify_test.go
src/crypto/x509/x509.go
src/crypto/x509/x509_test.go
src/debug/elf/elf.go
src/debug/plan9obj/file.go
src/errors/wrap_test.go
src/internal/poll/fd_windows.go
src/net/http/export_test.go
src/net/http/main_test.go
src/net/http/serve_test.go
src/net/http/server.go
src/net/http/transport.go
src/net/netip/netip.go
src/net/netip/netip_test.go
src/net/udpsock_test.go
src/runtime/chan_test.go
src/runtime/export_test.go
src/runtime/extern.go
src/runtime/lockrank.go
src/runtime/mem_linux.go
src/runtime/mgcpacer.go
src/runtime/mgcscavenge.go
src/runtime/mgcscavenge_test.go
src/runtime/mheap.go
src/runtime/mpagealloc.go
src/runtime/mstats.go
src/runtime/runtime1.go
src/runtime/stack.go
src/runtime/traceback_test.go
src/strings/strings.go
src/syscall/mkall.sh
src/time/example_test.go
src/time/tick.go
src/time/tick_test.go
src/time/time.go
src/time/time_test.go
src/unicode/utf8/example_test.go
src/unicode/utf8/utf8_test.go
test/fixedbugs/issue49378.go [new file with mode: 0644]

index 385a1ae804c26815d86c0134d000d664fb7ede90..55a1de3bd8fd90847de3ca6f350422cc1ef42013 100644 (file)
@@ -31,19 +31,30 @@ Do not send CLs removing the interior tags from such phrases.
 
 <h2 id="ports">Ports</h2>
 
-<p id="freebsd">
+<h3 id="freebsd">FreeBSD</h3>
+
+<p>
   Go 1.18 is the last release that is supported on FreeBSD 11.x, which has
   already reached end-of-life. Go 1.19 will require FreeBSD 12.2+ or FreeBSD
   13.0+.
   FreeBSD 13.0+ will require a kernel with the COMPAT_FREEBSD12 option set (this is the default).
 </p>
 
-<h2 id="tools">Tools</h2>
+<h3 id="ppc64">PPC64</h3>
 
-<p>
-  TODO: complete this section, or delete if not needed
+<p><!-- CL 353969 -->
+  TODO: <a href="https://golang.org/cl/353969">https://golang.org/cl/353969</a>: internal/buildcfg: enable register ABI for PPC64
+</p>
+
+<h3 id="riscv">RISC-V</h3>
+
+<p><!-- golang.org/issue/47100, CL 334872 -->
+  The 64-bit RISC-V architecture on Linux (the <code>linux/riscv64</code> port)
+  now supports the <code>c-archive</code> and <code>c-shared</code> build modes.
 </p>
 
+<h2 id="tools">Tools</h2>
+
 <h3 id="go-command">Go command</h3>
 
 <p><!-- golang.org/issue/43684 -->
@@ -103,8 +114,8 @@ Do not send CLs removing the interior tags from such phrases.
   <code>go</code> <code>mod</code> <code>download</code> <code>all</code>.
 </p>
 
-<p>
-  TODO: complete this section, or delete if not needed
+<p><!-- CL 349595 -->
+  TODO: <a href="https://golang.org/cl/349595">https://golang.org/cl/349595</a>: https://golang.org/cl/349595: cmd/go: add GOAMD64 environment variable
 </p>
 
 <h3 id="gofmt"><code>gofmt</code></h3>
@@ -115,7 +126,6 @@ Do not send CLs removing the interior tags from such phrases.
   multiple CPUs, <code>gofmt</code> should now be significantly faster.
 </p>
 
-
 <h2 id="runtime">Runtime</h2>
 
 <p>
@@ -124,24 +134,30 @@ Do not send CLs removing the interior tags from such phrases.
 
 <h2 id="compiler">Compiler</h2>
 
-<p>
-  TODO: complete this section, or delete if not needed
+<p><!-- CL 298611 -->
+  TODO: <a href="https://golang.org/cl/298611">https://golang.org/cl/298611</a>: https://golang.org/cl/298611: cmd/compile: add -asan option
+</p>
+
+<p><!-- CL 352057 -->
+  TODO: <a href="https://golang.org/cl/352057">https://golang.org/cl/352057</a>: https://golang.org/cl/352057: cmd/compile, runtime: track argument stack slot liveness
 </p>
 
 <h2 id="linker">Linker</h2>
 
-<p>
-  TODO: complete this section, or delete if not needed
+<p><!-- CL 298610 -->
+  TODO: <a href="https://golang.org/cl/298610">https://golang.org/cl/298610</a>: https://golang.org/cl/298610: cmd/link: add -asan option
 </p>
 
 <h2 id="library">Core library</h2>
 
-<h3>TODO</h3>
-<p>
-  TODO: complete this section
+<h3 id="constraints">New <code>constraints</code> package</h3>
+
+<p><!-- CL 349709 -->
+  TODO: <a href="https://golang.org/cl/349709">https://golang.org/cl/349709</a>: constraints: new package
 </p>
 
 <h3 id="netip">New <code>net/netip</code> package</h3>
+
 <p>
   The new <a href="/pkg/net/netip/"><code>net/netip</code></a>
   package defines a new IP address type, <a href="/pkg/net/netip/#Addr"><code>Addr</code></a>.
@@ -163,6 +179,12 @@ Do not send CLs removing the interior tags from such phrases.
   <code>*net.UDPAddr</code> values.
 </p>
 
+<h3>TODO</h3>
+
+<p>
+  TODO: complete this section
+</p>
+
 <h3 id="minor_library_changes">Minor changes to the library</h3>
 
 <p>
@@ -175,6 +197,26 @@ Do not send CLs removing the interior tags from such phrases.
   TODO: complete this section
 </p>
 
+<dl id="bufio"><dt><a href="/pkg/bufio/">bufio</a></dt>
+  <dd>
+    <p><!-- CL 345569 -->
+      TODO: <a href="https://golang.org/cl/345569">https://golang.org/cl/345569</a>: add Writer.AvailableBuffer
+    </p>
+
+    <p><!-- CL 345570 -->
+      TODO: <a href="https://golang.org/cl/345570">https://golang.org/cl/345570</a>: make Reader.Reset and Writer.Reset work on the zero value
+    </p>
+  </dd>
+</dl><!-- bufio -->
+
+<dl id="crypto/tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
+  <dd>
+    <p><!-- CL 325250 -->
+      TODO: <a href="https://golang.org/cl/325250">https://golang.org/cl/325250</a>: add Conn.NetConn method
+    </p>
+  </dd>
+</dl><!-- crypto/tls -->
+
 <dl id="debug/buildinfo"><dt><a href="/pkg/debug/buildinfo">debug/buildinfo</a></dt>
   <dd>
     <p><!-- golang.org/issue/39301 -->
@@ -201,9 +243,33 @@ Do not send CLs removing the interior tags from such phrases.
   </dd>
 </dl><!-- image/draw -->
 
+<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
+  <dd>
+    <p><!-- CL 340261 -->
+      TODO: <a href="https://golang.org/cl/340261">https://golang.org/cl/340261</a>: deprecate (net.Error).Temporary
+    </p>
+  </dd>
+</dl><!-- net -->
+
+<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
+  <dd>
+    <p><!-- CL 338590 -->
+      TODO: <a href="https://golang.org/cl/338590">https://golang.org/cl/338590</a>: add Cookie.Valid method
+    </p>
+  </dd>
+</dl><!-- net/http -->
+
+<dl id="os/user"><dt><a href="/pkg/os/user/">os/user</a></dt>
+  <dd>
+    <p><!-- CL 330753 -->
+      TODO: <a href="https://golang.org/cl/330753">https://golang.org/cl/330753</a>: implement go native GroupIds
+    </p>
+  </dd>
+</dl><!-- os/user -->
+
 <dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
   <dd>
-    <p><!-- CL 356049, 320929 -->
+    <p><!-- CL 356049, CL 320929 -->
       The new
       <a href="/pkg/reflect/#Value.SetIterKey"><code>Value.SetIterKey</code></a>
       and <a href="/pkg/reflect/#Value.SetIterValue"><code>Value.SetIterValue</code></a>
@@ -211,8 +277,7 @@ Do not send CLs removing the interior tags from such phrases.
       <code>Value.Set(iter.Key())</code> and <code>Value.Set(iter.Value())</code> but
       do fewer allocations.
     </p>
-  </dd>
-  <dd>
+
     <p><!-- CL 350691 -->
       The new
       <a href="/pkg/reflect/#Value.UnsafePointer"><code>Value.UnsafePointer</code></a>
@@ -221,9 +286,69 @@ Do not send CLs removing the interior tags from such phrases.
       and <a href="/pkg/reflect/#Value.Pointer"><code>Value.Pointer</code></a>
       to eliminate the need to perform uintptr to unsafe.Pointer conversions at the callsite (as unsafe.Pointer rules require).
     </p>
+
+    <p><!-- CL 321889 -->
+      TODO: <a href="https://golang.org/cl/321889">https://golang.org/cl/321889</a>: allocate hiter as part of MapIter
+    </p>
+
+    <p><!-- CL 321891 -->
+      TODO: <a href="https://golang.org/cl/321891">https://golang.org/cl/321891</a>: add MapIter.Reset
+    </p>
+
+    <p><!-- CL 345486 -->
+      TODO: <a href="https://golang.org/cl/345486">https://golang.org/cl/345486</a>: optimize for maps with string keys
+    </p>
+
+    <p><!-- CL 352131 -->
+      TODO: <a href="https://golang.org/cl/352131">https://golang.org/cl/352131</a>: add Value.{CanInt, CanUint, CanFloat, CanComplex}
+    </p>
+
+    <p><!-- CL 357962 -->
+      TODO: <a href="https://golang.org/cl/357962">https://golang.org/cl/357962</a>: add FieldByIndexErr
+    </p>
   </dd>
 </dl><!-- reflect -->
 
+<dl id="regexp"><dt><a href="/pkg/regexp/">regexp</a></dt>
+  <dd>
+    <p><!-- CL 354569 -->
+      TODO: <a href="https://golang.org/cl/354569">https://golang.org/cl/354569</a>: document and implement that invalid UTF-8 bytes are the same as U+FFFD
+    </p>
+  </dd>
+</dl><!-- regexp -->
+
+<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
+  <dd>
+    <p><!-- CL 343877 -->
+      TODO: <a href="https://golang.org/cl/343877">https://golang.org/cl/343877</a>: reject surrogate halves in Unquote
+    </p>
+  </dd>
+</dl><!-- strconv -->
+
+<dl id="strings"><dt><a href="/pkg/strings/">strings</a></dt>
+  <dd>
+    <p><!-- CL 345849 -->
+      TODO: <a href="https://golang.org/cl/345849">https://golang.org/cl/345849</a>: add Clone function
+    </p>
+  </dd>
+</dl><!-- strings -->
+
+<dl id="strings,bytes"><dt><a href="/pkg/strings,bytes/">strings,bytes</a></dt>
+  <dd>
+    <p><!-- CL 332771 -->
+      TODO: <a href="https://golang.org/cl/332771">https://golang.org/cl/332771</a>: avoid allocations in Trim/TrimLeft/TrimRight
+    </p>
+  </dd>
+</dl><!-- strings,bytes -->
+
+<dl id="sync"><dt><a href="/pkg/sync/">sync</a></dt>
+  <dd>
+    <p><!-- CL 319769 -->
+      TODO: <a href="https://golang.org/cl/319769">https://golang.org/cl/319769</a>: add Mutex.TryLock, RWMutex.TryLock, RWMutex.TryRLock
+    </p>
+  </dd>
+</dl><!-- sync -->
+
 <dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
   <dd>
     <p><!-- CL 336550 -->
@@ -238,5 +363,45 @@ Do not send CLs removing the interior tags from such phrases.
       <a href="/pkg/syscall/?GOOS=windows#Syscall18"><code>Syscall18</code></a> are
       deprecated in favor of <a href="/pkg/syscall/?GOOS=windows#SyscallN"><code>SyscallN</code></a>.
     </p>
+
+    <p><!-- CL 355570 -->
+      TODO: <a href="https://golang.org/cl/355570">https://golang.org/cl/355570</a>: add support for SysProcAttr.Pdeathsig on FreeBSD
+    </p>
   </dd>
 </dl><!-- syscall -->
+
+<dl id="syscall/js"><dt><a href="/pkg/syscall/js/">syscall/js</a></dt>
+  <dd>
+    <p><!-- CL 356430 -->
+      TODO: <a href="https://golang.org/cl/356430">https://golang.org/cl/356430</a>: remove Wrapper interface
+    </p>
+  </dd>
+</dl><!-- syscall/js -->
+
+<dl id="testing"><dt><a href="/pkg/testing/">testing</a></dt>
+  <dd>
+    <p><!-- CL 343883 -->
+      TODO: <a href="https://golang.org/cl/343883">https://golang.org/cl/343883</a>: increase alternation precedence
+    </p>
+
+    <p><!-- CL 356669 -->
+      TODO: <a href="https://golang.org/cl/356669">https://golang.org/cl/356669</a>: skip extra -count iterations if there are no tests
+    </p>
+  </dd>
+</dl><!-- testing -->
+
+<dl id="text/template"><dt><a href="/pkg/text/template/">text/template</a></dt>
+  <dd>
+    <p><!-- CL 321490 -->
+      TODO: <a href="https://golang.org/cl/321490">https://golang.org/cl/321490</a>: implement short-circuit and, or
+    </p>
+  </dd>
+</dl><!-- text/template -->
+
+<dl id="unicode/utf8"><dt><a href="/pkg/unicode/utf8/">unicode/utf8</a></dt>
+  <dd>
+    <p><!-- CL 345571 -->
+      TODO: <a href="https://golang.org/cl/345571">https://golang.org/cl/345571</a>: add AppendRune
+    </p>
+  </dd>
+</dl><!-- unicode/utf8 -->
index 66b3e700531a98a8c876013ba951039ea434c721..4dddfa9085cc4a99aacb5702dfa7f497c82cb48c 100644 (file)
@@ -1520,7 +1520,7 @@ func TestReaderDiscard(t *testing.T) {
                        wantBuffered: 0,
                },
                // Any error from filling shouldn't show up until we
-               // get past the valid bytes. Here we return we return 5 valid bytes at the same time
+               // get past the valid bytes. Here we return 5 valid bytes at the same time
                // as an error, but test that we don't see the error from Discard.
                {
                        name: "fill error, discard less",
index 9e6b68eaf4ea3e8145a350647dd1bc7e0f14b720..6fdaa49c7344921da2d1c987d714a61884935157 100644 (file)
@@ -746,7 +746,8 @@ func isSeparator(r rune) bool {
 // Title treats s as UTF-8-encoded bytes and returns a copy with all Unicode letters that begin
 // words mapped to their title case.
 //
-// BUG(rsc): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
+// Deprecated: The rule Title uses for word boundaries does not handle Unicode
+// punctuation properly. Use golang.org/x/text/cases instead.
 func Title(s []byte) []byte {
        // Use a closure here to remember state.
        // Hackish but effective. Depends on Map scanning in order and calling
index d04b088fabbc4b683dd372d0acac9f3bacdf796d..54a7aa6ae6c04960ce88f6b0d9cabbc01b46acbe 100644 (file)
@@ -37,6 +37,16 @@ func ExampleBuffer_Bytes() {
        // Output: hello world
 }
 
+func ExampleBuffer_Cap() {
+       buf1 := bytes.NewBuffer(make([]byte, 10))
+       buf2 := bytes.NewBuffer(make([]byte, 0, 10))
+       fmt.Println(buf1.Cap())
+       fmt.Println(buf2.Cap())
+       // Output:
+       // 10
+       // 10
+}
+
 func ExampleBuffer_Grow() {
        var b bytes.Buffer
        b.Grow(64)
@@ -67,6 +77,39 @@ func ExampleBuffer_Next() {
        // e
 }
 
+func ExampleBuffer_Read() {
+       var b bytes.Buffer
+       b.Grow(64)
+       b.Write([]byte("abcde"))
+       rdbuf := make([]byte, 1)
+       n, err := b.Read(rdbuf)
+       if err != nil {
+               panic(err)
+       }
+       fmt.Println(n)
+       fmt.Println(b.String())
+       fmt.Println(string(rdbuf))
+       // Output
+       // 1
+       // bcde
+       // a
+}
+
+func ExampleBuffer_ReadByte() {
+       var b bytes.Buffer
+       b.Grow(64)
+       b.Write([]byte("abcde"))
+       c, err := b.ReadByte()
+       if err != nil {
+               panic(err)
+       }
+       fmt.Println(c)
+       fmt.Println(b.String())
+       // Output
+       // 97
+       // bcde
+}
+
 func ExampleCompare() {
        // Interpret Compare's result by comparing it to zero.
        var a, b []byte
index b764aed534db7ffcf93aa18e1dad1a6c23e1036b..47b895f7e3fcebe6aada70c85f294b6f0835b2d4 100644 (file)
@@ -309,7 +309,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
                        break
                }
 
-               if fn := inlCallee(n.X); fn != nil && fn.Inl != nil {
+               if fn := inlCallee(n.X); fn != nil && typecheck.HaveInlineBody(fn) {
                        v.budget -= fn.Inl.Cost
                        break
                }
@@ -585,7 +585,7 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No
                if ir.IsIntrinsicCall(call) {
                        break
                }
-               if fn := inlCallee(call.X); fn != nil && fn.Inl != nil {
+               if fn := inlCallee(call.X); fn != nil && typecheck.HaveInlineBody(fn) {
                        n = mkinlcall(call, fn, maxCost, inlMap, edit)
                }
        }
index 91ff9f87f93107e81dac562a63898845505b4041..a3cea855f2fa456a31e18ae0560d9d773ca5f689 100644 (file)
@@ -954,11 +954,11 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value,
                elt := t.Elem()
                if source.Type != t && t.NumElem() == 1 && elt.Size() == t.Size() && t.Size() == x.regSize {
                        t = removeTrivialWrapperTypes(t)
-                       source.Type = t
                        // it could be a leaf type, but the "leaf" could be complex64 (for example)
                        return x.storeArgOrLoad(pos, b, source, mem, t, storeOffset, loadRegOffset, storeRc)
                }
                eltRO := x.regWidth(elt)
+               source.Type = t
                for i := int64(0); i < t.NumElem(); i++ {
                        sel := source.Block.NewValue1I(pos, OpArraySelect, elt, i, source)
                        mem = x.storeArgOrLoad(pos, b, sel, mem, elt, storeOffset+i*elt.Size(), loadRegOffset, storeRc.at(t, 0))
@@ -988,11 +988,11 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value,
                        // v139 is later stored as an intVal == struct{val *big.Int} which naively requires the fields of
                        // of a *uint8, which does not succeed.
                        t = removeTrivialWrapperTypes(t)
-                       source.Type = t
                        // it could be a leaf type, but the "leaf" could be complex64 (for example)
                        return x.storeArgOrLoad(pos, b, source, mem, t, storeOffset, loadRegOffset, storeRc)
                }
 
+               source.Type = t
                for i := 0; i < t.NumFields(); i++ {
                        fld := t.Field(i)
                        sel := source.Block.NewValue1I(pos, OpStructSelect, fld.Type, int64(i), source)
index 90dd261c557fec7d5603cd7b3d3c5520f9382a19..088f9802e6484f849667b54f2edea84863f8cbdb 100644 (file)
@@ -89,6 +89,9 @@ func TestStmtLines(t *testing.T) {
                if pkgname == "runtime" {
                        continue
                }
+               if pkgname == "crypto/elliptic/internal/fiat" {
+                       continue // golang.org/issue/49372
+               }
                if e.Val(dwarf.AttrStmtList) == nil {
                        continue
                }
index ae2b3b1df4e1ca8d95692533071e71128cf6d325..ae6542d071976ffc0a80457364c8f2138a4e203e 100644 (file)
@@ -207,7 +207,7 @@ func (p *crawler) markInlBody(n *ir.Name) {
        if fn == nil {
                base.Fatalf("markInlBody: missing Func on %v", n)
        }
-       if fn.Inl == nil {
+       if !HaveInlineBody(fn) {
                return
        }
 
index 7c6c23e73714515a322c25c20c2672223d398236..26bc838ed99f8293679f3d3d452b175ac8ca4740 100644 (file)
@@ -81,6 +81,27 @@ func ImportBody(fn *ir.Func) {
        inimport = false
 }
 
+// HaveInlineBody reports whether we have fn's inline body available
+// for inlining.
+func HaveInlineBody(fn *ir.Func) bool {
+       if fn.Inl == nil {
+               return false
+       }
+
+       // Unified IR is much more conservative about pruning unreachable
+       // methods (at the cost of increased build artifact size).
+       if base.Debug.Unified != 0 {
+               return true
+       }
+
+       if fn.Inl.Body != nil {
+               return true
+       }
+
+       _, ok := inlineImporter[fn.Nname.Sym()]
+       return ok
+}
+
 func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset) *importReader {
        x, ok := importers[sym]
        if !ok {
index 14b48351db1070f7a88f869ad623cb6955dddb0d..98e30a158fc628b0fd3facae184099b2ee3fb1a1 100644 (file)
@@ -1013,7 +1013,7 @@ func (t *tester) internalLink() bool {
 func (t *tester) internalLinkPIE() bool {
        switch goos + "-" + goarch {
        case "darwin-amd64", "darwin-arm64",
-               "linux-amd64", "linux-arm64",
+               "linux-amd64", "linux-arm64", "linux-ppc64le",
                "android-arm64",
                "windows-amd64", "windows-386", "windows-arm":
                return true
index 0602aee0cccd63300d90d92256fda9bcf2912af4..9aef5a7c33e5684c90bb6b64c7fc0ff109459fb7 100644 (file)
@@ -968,7 +968,7 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile
                        for _, r := range modFiles[i].Replace {
                                if replacedByWorkFile[r.Old.Path] {
                                        continue
-                               } else if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] {
+                               } else if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] && prev != r.New {
                                        base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v\nuse \"go mod editwork -replace %v=[override]\" to resolve", r.Old, prev, r.New, r.Old)
                                }
                                curModuleReplaces[r.Old] = true
index 1672d563b794bf844665bff28965c7e4930826c4..a7e92222a1ecf188223fe6e667fdc0c527b356bb 100644 (file)
@@ -378,7 +378,7 @@ func canonicalizeReplacePath(r module.Version, modRoot string) module.Version {
                return r
        }
        abs := filepath.Join(modRoot, r.Path)
-       if rel, err := filepath.Rel(workFilePath, abs); err == nil {
+       if rel, err := filepath.Rel(filepath.Dir(workFilePath), abs); err == nil {
                return module.Version{Path: rel, Version: r.Version}
        }
        // We couldn't make the version's path relative to the workspace's path,
index 5b81e9481ad4dde1f7ba32a253c81d6ea4fa63db..24ec5aa11b01deaa9d6b6075a3f700623e995c9e 100644 (file)
@@ -58,8 +58,7 @@ go build -n -ldflags=-X=math.pi=3
 stderr 'link.* -X=math.pi=3'
 
 # -ldflags applies to current directory even if GOPATH is funny
-[windows] cd $WORK/GoPath/src/my/cmd/prog
-[darwin] cd $WORK/GoPath/src/my/cmd/prog
+[!case-sensitive] cd $WORK/GoPath/src/my/cmd/prog
 go build -n -ldflags=-X=math.pi=3
 stderr 'link.* -X=math.pi=3'
 
index c6a78a51eb1aaf805bc3e2aefcbe87e793f70e2a..f25aaabddd60ea8c044bc7f8ae5a6068d8796f0e 100644 (file)
@@ -158,7 +158,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool {
 func InternalLinkPIESupported(goos, goarch string) bool {
        switch goos + "/" + goarch {
        case "darwin/amd64", "darwin/arm64",
-               "linux/amd64", "linux/arm64",
+               "linux/amd64", "linux/arm64", "linux/ppc64le",
                "android/arm64",
                "windows-amd64", "windows-386", "windows-arm":
                return true
index 2d7e1bff68a11afda5c65b2aacdb72b0067308fe..33ab7c3df36777db19d10ef74a46588394704701 100644 (file)
@@ -225,7 +225,8 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) {
                return true, "buildmode=c-shared"
        case BuildModePIE:
                switch buildcfg.GOOS + "/" + buildcfg.GOARCH {
-               case "linux/amd64", "linux/arm64", "android/arm64":
+               case "android/arm64":
+               case "linux/amd64", "linux/arm64", "linux/ppc64le":
                case "windows/386", "windows/amd64", "windows/arm", "windows/arm64":
                case "darwin/amd64", "darwin/arm64":
                default:
index 0513a0d10b567b9fbc48043b98d2070dbfb5c7cf..4d85977d43a84669e848cdecc07dbc07fbb8f9fe 100644 (file)
@@ -227,6 +227,8 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
                                        // DWARF info between the compiler and linker.
                                        continue
                                }
+                       } else if target.IsPPC64() && target.IsPIE() && ldr.SymName(rs) == ".TOC." {
+                               // This is a TOC relative relocation generated from a go object. It is safe to resolve.
                        } else {
                                st.err.errorUnresolved(ldr, s, rs)
                                continue
index 62b319d19648d30a69410785dc3d00df58b6c991..d2b140b45dee9a30c68479608038d99605e9f91a 100644 (file)
@@ -321,6 +321,11 @@ func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s lo
                        rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64)))
                        rela.AddUint64(target.Arch, uint64(r.Add()))
                        su.SetRelocType(rIdx, objabi.ElfRelocOffset) // ignore during relocsym
+               } else if target.IsPIE() && target.IsInternal() {
+                       // For internal linking PIE, this R_ADDR relocation cannot
+                       // be resolved statically. We need to generate a dynamic
+                       // relocation. Let the code below handle it.
+                       break
                }
                return true
 
@@ -383,12 +388,94 @@ func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s lo
        }
 
        // Handle references to ELF symbols from our own object files.
-       if targType != sym.SDYNIMPORT {
+       relocs := ldr.Relocs(s)
+       r = relocs.At(rIdx)
+
+       switch r.Type() {
+       case objabi.R_ADDR:
+               if ldr.SymType(s) == sym.STEXT {
+                       log.Fatalf("R_ADDR relocation in text symbol %s is unsupported\n", ldr.SymName(s))
+               }
+               if target.IsPIE() && target.IsInternal() {
+                       // When internally linking, generate dynamic relocations
+                       // for all typical R_ADDR relocations. The exception
+                       // are those R_ADDR that are created as part of generating
+                       // the dynamic relocations and must be resolved statically.
+                       //
+                       // There are three phases relevant to understanding this:
+                       //
+                       //      dodata()  // we are here
+                       //      address() // symbol address assignment
+                       //      reloc()   // resolution of static R_ADDR relocs
+                       //
+                       // At this point symbol addresses have not been
+                       // assigned yet (as the final size of the .rela section
+                       // will affect the addresses), and so we cannot write
+                       // the Elf64_Rela.r_offset now. Instead we delay it
+                       // until after the 'address' phase of the linker is
+                       // complete. We do this via Addaddrplus, which creates
+                       // a new R_ADDR relocation which will be resolved in
+                       // the 'reloc' phase.
+                       //
+                       // These synthetic static R_ADDR relocs must be skipped
+                       // now, or else we will be caught in an infinite loop
+                       // of generating synthetic relocs for our synthetic
+                       // relocs.
+                       //
+                       // Furthermore, the rela sections contain dynamic
+                       // relocations with R_ADDR relocations on
+                       // Elf64_Rela.r_offset. This field should contain the
+                       // symbol offset as determined by reloc(), not the
+                       // final dynamically linked address as a dynamic
+                       // relocation would provide.
+                       switch ldr.SymName(s) {
+                       case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
+                               return false
+                       }
+               } else {
+                       // Either internally linking a static executable,
+                       // in which case we can resolve these relocations
+                       // statically in the 'reloc' phase, or externally
+                       // linking, in which case the relocation will be
+                       // prepared in the 'reloc' phase and passed to the
+                       // external linker in the 'asmb' phase.
+                       if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA {
+                               break
+                       }
+               }
+               // Generate R_PPC64_RELATIVE relocations for best
+               // efficiency in the dynamic linker.
+               //
+               // As noted above, symbol addresses have not been
+               // assigned yet, so we can't generate the final reloc
+               // entry yet. We ultimately want:
+               //
+               // r_offset = s + r.Off
+               // r_info = R_PPC64_RELATIVE
+               // r_addend = targ + r.Add
+               //
+               // The dynamic linker will set *offset = base address +
+               // addend.
+               //
+               // AddAddrPlus is used for r_offset and r_addend to
+               // generate new R_ADDR relocations that will update
+               // these fields in the 'reloc' phase.
+               rela := ldr.MakeSymbolUpdater(syms.Rela)
+               rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
+               if r.Siz() == 8 {
+                       rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_PPC64_RELATIVE)))
+               } else {
+                       ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
+               }
+               rela.AddAddrPlus(target.Arch, targ, int64(r.Add()))
+
+               // Not mark r done here. So we still apply it statically,
+               // so in the file content we'll also have the right offset
+               // to the relocation target. So it can be examined statically
+               // (e.g. go version).
                return true
        }
 
-       // TODO(austin): Translate our relocations to ELF
-
        return false
 }
 
@@ -542,35 +629,40 @@ func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 {
 }
 
 // archreloctoc relocates a TOC relative symbol.
-// If the symbol pointed by this TOC relative symbol is in .data or .bss, the
-// default load instruction can be changed to an addi instruction and the
-// symbol address can be used directly.
-// This code is for AIX only.
 func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
        rs := r.Sym()
-       if target.IsLinux() {
-               ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
-       }
        var o1, o2 uint32
-
-       o1 = uint32(val >> 32)
-       o2 = uint32(val)
-
-       if !strings.HasPrefix(ldr.SymName(rs), "TOC.") {
-               ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
-       }
        var t int64
        useAddi := false
-       relocs := ldr.Relocs(rs)
-       tarSym := relocs.At(0).Sym()
-
-       if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata {
-               t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC)
-               // change ld to addi in the second instruction
-               o2 = (o2 & 0x03FF0000) | 0xE<<26
-               useAddi = true
+
+       if target.IsBigEndian() {
+               o1 = uint32(val >> 32)
+               o2 = uint32(val)
+       } else {
+               o1 = uint32(val)
+               o2 = uint32(val >> 32)
+       }
+
+       // On AIX, TOC data accesses are always made indirectly against R2 (a sequence of addis+ld+load/store). If the
+       // The target of the load is known, the sequence can be written into addis+addi+load/store. On Linux,
+       // TOC data accesses are always made directly against R2 (e.g addis+load/store).
+       if target.IsAIX() {
+               if !strings.HasPrefix(ldr.SymName(rs), "TOC.") {
+                       ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
+               }
+               relocs := ldr.Relocs(rs)
+               tarSym := relocs.At(0).Sym()
+
+               if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata {
+                       t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC)
+                       // change ld to addi in the second instruction
+                       o2 = (o2 & 0x03FF0000) | 0xE<<26
+                       useAddi = true
+               } else {
+                       t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC)
+               }
        } else {
-               t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC)
+               t = ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s)
        }
 
        if t != int64(int32(t)) {
@@ -593,15 +685,20 @@ func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r lo
                        }
                        o2 |= uint32(t) & 0xFFFC
                }
+       case objabi.R_ADDRPOWER_TOCREL:
+               o2 |= uint32(t) & 0xffff
        default:
                return -1
        }
 
-       return int64(o1)<<32 | int64(o2)
+       if target.IsBigEndian() {
+               return int64(o1)<<32 | int64(o2)
+       }
+       return int64(o2)<<32 | int64(o1)
 }
 
 // archrelocaddr relocates a symbol address.
-// This code is for AIX only.
+// This code is for linux only.
 func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
        rs := r.Sym()
        if target.IsAIX() {
@@ -860,6 +957,18 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
 
                t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
 
+               tgtName := ldr.SymName(rs)
+
+               // If we are linking PIE or shared code, all golang generated object files have an extra 2 instruction prologue
+               // to regenerate the TOC pointer from R12.  The exception are two special case functions tested below.  Note,
+               // local call offsets for externally generated objects are accounted for when converting into golang relocs.
+               if !ldr.IsExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" {
+                       // Furthermore, only apply the offset if the target looks like the start of a function call.
+                       if r.Add() == 0 && ldr.SymType(rs) == sym.STEXT {
+                               t += 8
+                       }
+               }
+
                if t&3 != 0 {
                        ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
                }
@@ -872,6 +981,62 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
        case objabi.R_POWER_TOC: // S + A - .TOC.
                return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true
 
+       case objabi.R_ADDRPOWER_PCREL: // S + A - P
+               t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
+               ha := uint16(((t + 0x8000) >> 16) & 0xFFFF)
+               l := uint16(t)
+               if target.IsBigEndian() {
+                       val |= int64(l)
+                       val |= int64(ha) << 32
+               } else {
+                       val |= int64(ha)
+                       val |= int64(l) << 32
+               }
+               return val, nExtReloc, true
+
+       case objabi.R_POWER_TLS:
+               const OP_ADD = 31<<26 | 266<<1
+               const MASK_OP_ADD = 0x3F<<26 | 0x1FF<<1
+               if val&MASK_OP_ADD != OP_ADD {
+                       ldr.Errorf(s, "R_POWER_TLS reloc only supports XO form ADD, not %08X", val)
+               }
+               // Verify RB is R13 in ADD RA,RB,RT.
+               if (val>>11)&0x1F != 13 {
+                       // If external linking is made to support this, it may expect the linker to rewrite RB.
+                       ldr.Errorf(s, "R_POWER_TLS reloc requires R13 in RB (%08X).", uint32(val))
+               }
+               return val, nExtReloc, true
+
+       case objabi.R_POWER_TLS_IE:
+               // Convert TLS_IE relocation to TLS_LE if supported.
+               if !(target.IsPIE() && target.IsElf()) {
+                       log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s))
+               }
+
+               // We are an ELF binary, we can safely convert to TLS_LE from:
+               // addis to, r2, x@got@tprel@ha
+               // ld to, to, x@got@tprel@l(to)
+               //
+               // to TLS_LE by converting to:
+               // addis to, r0, x@tprel@ha
+               // addi to, to, x@tprel@l(to)
+
+               const OP_ADDI = 14 << 26
+               const OP_MASK = 0x3F << 26
+               const OP_RA_MASK = 0x1F << 16
+               uval := uint64(val)
+               // convert r2 to r0, and ld to addi
+               if target.IsBigEndian() {
+                       uval = uval &^ (OP_RA_MASK << 32)
+                       uval = (uval &^ OP_MASK) | OP_ADDI
+               } else {
+                       uval = uval &^ (OP_RA_MASK)
+                       uval = (uval &^ (OP_MASK << 32)) | (OP_ADDI << 32)
+               }
+               val = int64(uval)
+               // Treat this like an R_POWER_TLS_LE relocation now.
+               fallthrough
+
        case objabi.R_POWER_TLS_LE:
                // The thread pointer points 0x7000 bytes after the start of the
                // thread local storage area as documented in section "3.7.2 TLS
index a69cb78c8b56a8bead4b8516d407b4b2d728cf31..f3a96a3a1705bb9c392700a8a59f904f29d1f40f 100644 (file)
@@ -13,8 +13,8 @@
 // Original code can be found at the link below:
 // https://github.com/dot-asm/cryptogams/blob/master/ppc/aesp8-ppc.pl
 
-// I changed some function names in order to be more likely to go standards.
-// For instance, function aes_p8_set_{en,de}crypt_key become
+// Some function names were changed to be consistent with Go function
+// names. For instance, function aes_p8_set_{en,de}crypt_key become
 // set{En,De}cryptKeyAsm. I also split setEncryptKeyAsm in two parts
 // and a new session was created (doEncryptKeyAsm). This was necessary to
 // avoid arguments overwriting when setDecryptKeyAsm calls setEncryptKeyAsm.
 #define BLK_ROUNDS R6
 #define BLK_IDX    R7
 
-DATA  ยทrcon+0x00(SB)/8, $0x0100000001000000 // RCON
-DATA  ยทrcon+0x08(SB)/8, $0x0100000001000000 // RCON
-DATA  ยทrcon+0x10(SB)/8, $0x1b0000001b000000
-DATA  ยทrcon+0x18(SB)/8, $0x1b0000001b000000
-DATA  ยทrcon+0x20(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK
-DATA  ยทrcon+0x28(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK
-DATA  ยทrcon+0x30(SB)/8, $0x0000000000000000
-DATA  ยทrcon+0x38(SB)/8, $0x0000000000000000
+DATA ยทrcon+0x00(SB)/8, $0x0100000001000000 // RCON
+DATA ยทrcon+0x08(SB)/8, $0x0100000001000000 // RCON
+DATA ยทrcon+0x10(SB)/8, $0x1b0000001b000000
+DATA ยทrcon+0x18(SB)/8, $0x1b0000001b000000
+DATA ยทrcon+0x20(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK
+DATA ยทrcon+0x28(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK
+DATA ยทrcon+0x30(SB)/8, $0x0000000000000000
+DATA ยทrcon+0x38(SB)/8, $0x0000000000000000
 GLOBL ยทrcon(SB), RODATA, $64
 
 // func setEncryptKeyAsm(key *byte, keylen int, enc *uint32) int
-TEXT ยทsetEncryptKeyAsm(SB),NOSPLIT|NOFRAME,$0
+TEXT ยทsetEncryptKeyAsm(SB), NOSPLIT|NOFRAME, $0
        // Load the arguments inside the registers
-       MOVD key+0(FP), INP
-       MOVD keylen+8(FP), BITS
-       MOVD enc+16(FP), OUT
-       JMP ยทdoEncryptKeyAsm(SB)
+       MOVD    key+0(FP), INP
+       MOVD    keylen+8(FP), BITS
+       MOVD    enc+16(FP), OUT
+       JMP     ยทdoEncryptKeyAsm(SB)
 
 // This text is used both setEncryptKeyAsm and setDecryptKeyAsm
-TEXT ยทdoEncryptKeyAsm(SB),NOSPLIT|NOFRAME,$0
+TEXT ยทdoEncryptKeyAsm(SB), NOSPLIT|NOFRAME, $0
        // Do not change R10 since it's storing the LR value in setDecryptKeyAsm
 
        // Check arguments
-       MOVD $-1, PTR                  // li    6,-1       exit code to -1 (255)
-       CMPU INP, $0                   // cmpldi r3,0      input key pointer set?
-       BC 0x0E, 2, enc_key_abort      // beq-  .Lenc_key_abort
-       CMPU OUT, $0                   // cmpldi r5,0      output key pointer set?
-       BC 0x0E, 2, enc_key_abort      // beq-  .Lenc_key_abort
-       MOVD $-2, PTR                  // li    6,-2       exit code to -2 (254)
-       CMPW BITS, $128                // cmpwi 4,128      greater or equal to 128
-       BC 0x0E, 0, enc_key_abort      // blt-  .Lenc_key_abort
-       CMPW BITS, $256                // cmpwi 4,256      lesser or equal to 256
-       BC 0x0E, 1, enc_key_abort      // bgt-  .Lenc_key_abort
-       ANDCC $0x3f, BITS, TEMP        // andi. 0,4,0x3f   multiple of 64
-       BC 0x06, 2, enc_key_abort      // bne-  .Lenc_key_abort
-
-       MOVD $ยทrcon(SB), PTR           // PTR point to rcon addr
+       MOVD    $-1, PTR               // li    6,-1       exit code to -1 (255)
+       CMPU    INP, $0                // cmpldi r3,0      input key pointer set?
+       BC      0x0E, 2, enc_key_abort // beq-  .Lenc_key_abort
+       CMPU    OUT, $0                // cmpldi r5,0      output key pointer set?
+       BC      0x0E, 2, enc_key_abort // beq-  .Lenc_key_abort
+       MOVD    $-2, PTR               // li    6,-2       exit code to -2 (254)
+       CMPW    BITS, $128             // cmpwi 4,128      greater or equal to 128
+       BC      0x0E, 0, enc_key_abort // blt-  .Lenc_key_abort
+       CMPW    BITS, $256             // cmpwi 4,256      lesser or equal to 256
+       BC      0x0E, 1, enc_key_abort // bgt-  .Lenc_key_abort
+       ANDCC   $0x3f, BITS, TEMP      // andi. 0,4,0x3f   multiple of 64
+       BC      0x06, 2, enc_key_abort // bne-  .Lenc_key_abort
+
+       MOVD    $ยทrcon(SB), PTR // PTR point to rcon addr
 
        // Get key from memory and write aligned into VR
-       NEG INP, R9                    // neg   9,3        R9 is ~INP + 1
-       LVX (INP)(R0), IN0             // lvx   1,0,3      Load key inside IN0
-       ADD $15, INP, INP              // addi  3,3,15     Add 15B to INP addr
-       LVSR (R9)(R0), KEY             // lvsr  3,0,9
-       MOVD $0x20, R8                 // li    8,0x20     R8 = 32
-       CMPW BITS, $192                // cmpwi 4,192      Key size == 192?
-       LVX (INP)(R0), IN1             // lvx   2,0,3
-       VSPLTISB $0x0f, MASK           // vspltisb 5,0x0f  0x0f0f0f0f... mask
-       LVX (PTR)(R0), RCON            // lvx   4,0,6      Load first 16 bytes into RCON
-       VXOR KEY, MASK, KEY            // vxor  3,3,5      Adjust for byte swap
-       LVX (PTR)(R8), MASK            // lvx   5,8,6
-       ADD $0x10, PTR, PTR            // addi  6,6,0x10   PTR to next 16 bytes of RCON
-       VPERM IN0, IN1, KEY, IN0       // vperm 1,1,2,3    Align
-       MOVD $8, CNT                   // li    7,8        CNT = 8
-       VXOR ZERO, ZERO, ZERO          // vxor  0,0,0      Zero to be zero :)
-       MOVD CNT, CTR                  // mtctr 7          Set the counter to 8 (rounds)
-
-       LVSL (OUT)(R0), OUTPERM        // lvsl  8,0,5
-       VSPLTISB $-1, OUTMASK          // vspltisb      9,-1
-       LVX (OUT)(R0), OUTHEAD         // lvx   10,0,5
-       VPERM OUTMASK, ZERO, OUTPERM, OUTMASK  // vperm 9,9,0,8
-
-       BLT loop128                    // blt   .Loop128
-       ADD $8, INP, INP               // addi  3,3,8
-       BEQ l192                       // beq   .L192
-       ADD $8, INP, INP               // addi  3,3,8
-       JMP l256                       // b     .L256
+       NEG     INP, R9            // neg   9,3        R9 is ~INP + 1
+       LVX     (INP)(R0), IN0     // lvx   1,0,3      Load key inside IN0
+       ADD     $15, INP, INP      // addi  3,3,15     Add 15B to INP addr
+       LVSR    (R9)(R0), KEY      // lvsr  3,0,9
+       MOVD    $0x20, R8          // li    8,0x20     R8 = 32
+       CMPW    BITS, $192         // cmpwi 4,192      Key size == 192?
+       LVX     (INP)(R0), IN1     // lvx   2,0,3
+       VSPLTISB        $0x0f, MASK// vspltisb 5,0x0f  0x0f0f0f0f... mask
+       LVX     (PTR)(R0), RCON    // lvx   4,0,6      Load first 16 bytes into RCON
+       VXOR    KEY, MASK, KEY     // vxor  3,3,5      Adjust for byte swap
+       LVX     (PTR)(R8), MASK    // lvx   5,8,6
+       ADD     $0x10, PTR, PTR    // addi  6,6,0x10   PTR to next 16 bytes of RCON
+       VPERM   IN0, IN1, KEY, IN0 // vperm 1,1,2,3    Align
+       MOVD    $8, CNT            // li    7,8        CNT = 8
+       VXOR    ZERO, ZERO, ZERO   // vxor  0,0,0      Zero to be zero :)
+       MOVD    CNT, CTR           // mtctr 7          Set the counter to 8 (rounds)
+
+       LVSL    (OUT)(R0), OUTPERM              // lvsl  8,0,5
+       VSPLTISB        $-1, OUTMASK                    // vspltisb      9,-1
+       LVX     (OUT)(R0), OUTHEAD              // lvx   10,0,5
+       VPERM   OUTMASK, ZERO, OUTPERM, OUTMASK // vperm 9,9,0,8
+
+       BLT     loop128      // blt   .Loop128
+       ADD     $8, INP, INP // addi  3,3,8
+       BEQ     l192         // beq   .L192
+       ADD     $8, INP, INP // addi  3,3,8
+       JMP     l256         // b     .L256
 
 loop128:
        // Key schedule (Round 1 to 8)
-       VPERM IN0, IN0, MASK, KEY      // vperm 3,1,1,5         Rotate-n-splat
-       VSLDOI $12, ZERO, IN0, TMP     // vsldoi 6,0,1,12
-       VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8    Rotate
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       VCIPHERLAST KEY, RCON, KEY     // vcipherlast 3,3,4
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5        Write to output
-       ADD $16, OUT, OUT              // addi 5,5,16       Point to the next round
-
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VADDUWM RCON, RCON, RCON       // vadduwm 4,4,4
-       VXOR IN0, KEY, IN0             // vxor 1,1,3
-       BC 0x10, 0, loop128            // bdnz .Loop128
-
-       LVX (PTR)(R0), RCON            // lvx 4,0,6     Last two round keys
+       VPERM   IN0, IN0, MASK, KEY              // vperm 3,1,1,5         Rotate-n-splat
+       VSLDOI  $12, ZERO, IN0, TMP              // vsldoi 6,0,1,12
+       VPERM   IN0, IN0, OUTPERM, OUTTAIL       // vperm 11,1,1,8    Rotate
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       VCIPHERLAST     KEY, RCON, KEY           // vcipherlast 3,3,4
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5        Write to output
+       ADD     $16, OUT, OUT                    // addi 5,5,16       Point to the next round
+
+       VXOR    IN0, TMP, IN0       // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0       // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0       // vxor 1,1,6
+       VADDUWM RCON, RCON, RCON    // vadduwm 4,4,4
+       VXOR    IN0, KEY, IN0       // vxor 1,1,3
+       BC      0x10, 0, loop128    // bdnz .Loop128
+
+       LVX     (PTR)(R0), RCON // lvx 4,0,6     Last two round keys
 
        // Key schedule (Round 9)
-       VPERM IN0, IN0, MASK, KEY      // vperm 3,1,1,5   Rotate-n-spat
-       VSLDOI $12, ZERO, IN0, TMP     // vsldoi 6,0,1,12
-       VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8  Rotate
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       VCIPHERLAST KEY, RCON, KEY     // vcipherlast 3,3,4
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5   Round 9
-       ADD $16, OUT, OUT              // addi 5,5,16
+       VPERM   IN0, IN0, MASK, KEY              // vperm 3,1,1,5   Rotate-n-spat
+       VSLDOI  $12, ZERO, IN0, TMP              // vsldoi 6,0,1,12
+       VPERM   IN0, IN0, OUTPERM, OUTTAIL       // vperm 11,1,1,8  Rotate
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       VCIPHERLAST     KEY, RCON, KEY           // vcipherlast 3,3,4
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5   Round 9
+       ADD     $16, OUT, OUT                    // addi 5,5,16
 
        // Key schedule (Round 10)
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VADDUWM RCON, RCON, RCON       // vadduwm 4,4,4
-       VXOR IN0, KEY, IN0             // vxor 1,1,3
-
-       VPERM IN0, IN0, MASK, KEY      // vperm 3,1,1,5   Rotate-n-splat
-       VSLDOI $12, ZERO, IN0, TMP     // vsldoi 6,0,1,12
-       VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8  Rotate
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       VCIPHERLAST KEY, RCON, KEY     // vcipherlast 3,3,4
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5    Round 10
-       ADD $16, OUT, OUT              // addi 5,5,16
+       VXOR    IN0, TMP, IN0       // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0       // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0       // vxor 1,1,6
+       VADDUWM RCON, RCON, RCON    // vadduwm 4,4,4
+       VXOR    IN0, KEY, IN0       // vxor 1,1,3
+
+       VPERM   IN0, IN0, MASK, KEY              // vperm 3,1,1,5   Rotate-n-splat
+       VSLDOI  $12, ZERO, IN0, TMP              // vsldoi 6,0,1,12
+       VPERM   IN0, IN0, OUTPERM, OUTTAIL       // vperm 11,1,1,8  Rotate
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       VCIPHERLAST     KEY, RCON, KEY           // vcipherlast 3,3,4
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5    Round 10
+       ADD     $16, OUT, OUT                    // addi 5,5,16
 
        // Key schedule (Round 11)
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VXOR IN0, KEY, IN0             // vxor 1,1,3
-       VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5  Round 11
-
-       ADD $15, OUT, INP              // addi  3,5,15
-       ADD $0x50, OUT, OUT            // addi  5,5,0x50
-
-       MOVD $10, ROUNDS               // li    8,10
-       JMP done                       // b     .Ldone
+       VXOR    IN0, TMP, IN0                    // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP              // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0                    // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP              // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0                    // vxor 1,1,6
+       VXOR    IN0, KEY, IN0                    // vxor 1,1,3
+       VPERM   IN0, IN0, OUTPERM, OUTTAIL       // vperm 11,1,1,8
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5  Round 11
+
+       ADD     $15, OUT, INP   // addi  3,5,15
+       ADD     $0x50, OUT, OUT // addi  5,5,0x50
+
+       MOVD    $10, ROUNDS // li    8,10
+       JMP     done        // b     .Ldone
 
 l192:
-       LVX (INP)(R0), TMP             // lvx 6,0,3
-       MOVD $4, CNT                   // li 7,4
-       VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5
-       ADD $16, OUT, OUT              // addi 5,5,16
-       VPERM IN1, TMP, KEY, IN1       // vperm 2,2,6,3
-       VSPLTISB $8, KEY               // vspltisb 3,8
-       MOVD CNT, CTR                  // mtctr 7
-       VSUBUBM MASK, KEY, MASK        // vsububm 5,5,3
+       LVX     (INP)(R0), TMP                   // lvx 6,0,3
+       MOVD    $4, CNT                          // li 7,4
+       VPERM   IN0, IN0, OUTPERM, OUTTAIL       // vperm 11,1,1,8
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5
+       ADD     $16, OUT, OUT                    // addi 5,5,16
+       VPERM   IN1, TMP, KEY, IN1               // vperm 2,2,6,3
+       VSPLTISB        $8, KEY                  // vspltisb 3,8
+       MOVD    CNT, CTR                         // mtctr 7
+       VSUBUBM MASK, KEY, MASK                  // vsububm 5,5,3
 
 loop192:
-       VPERM IN1, IN1, MASK, KEY      // vperm 3,2,2,5
-       VSLDOI $12, ZERO, IN0, TMP     // vsldoi 6,0,1,12
-       VCIPHERLAST KEY, RCON, KEY     // vcipherlast 3,3,4
-
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-
-       VSLDOI $8, ZERO, IN1, STAGE    // vsldoi 7,0,2,8
-       VSPLTW $3, IN0, TMP            // vspltw 6,1,3
-       VXOR TMP, IN1, TMP             // vxor 6,6,2
-       VSLDOI $12, ZERO, IN1, IN1     // vsldoi 2,0,2,12
-       VADDUWM RCON, RCON, RCON       // vadduwm 4,4,4
-       VXOR IN1, TMP, IN1             // vxor 2,2,6
-       VXOR IN0, KEY, IN0             // vxor 1,1,3
-       VXOR IN1, KEY, IN1             // vxor 2,2,3
-       VSLDOI $8, STAGE, IN0, STAGE   // vsldoi 7,7,1,8
-
-       VPERM IN1, IN1, MASK, KEY      // vperm 3,2,2,5
-       VSLDOI $12, ZERO, IN0, TMP     // vsldoi 6,0,1,12
-       VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       VCIPHERLAST KEY, RCON, KEY     // vcipherlast 3,3,4
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5
-       ADD $16, OUT, OUT              // addi 5,5,16
-
-       VSLDOI $8, IN0, IN1, STAGE     // vsldoi 7,1,2,8
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5
-       ADD $16, OUT, OUT              // addi 5,5,16
-
-       VSPLTW $3, IN0, TMP            // vspltw 6,1,3
-       VXOR TMP, IN1, TMP             // vxor 6,6,2
-       VSLDOI $12, ZERO, IN1, IN1     // vsldoi 2,0,2,12
-       VADDUWM RCON, RCON, RCON       // vadduwm 4,4,4
-       VXOR IN1, TMP, IN1             // vxor 2,2,6
-       VXOR IN0, KEY, IN0             // vxor 1,1,3
-       VXOR IN1, KEY, IN1             // vxor 2,2,3
-       VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5
-       ADD $15, OUT, INP              // addi 3,5,15
-       ADD $16, OUT, OUT              // addi 5,5,16
-       BC 0x10, 0, loop192           // bdnz .Loop192
-
-       MOVD $12, ROUNDS               // li 8,12
-       ADD $0x20, OUT, OUT            // addi 5,5,0x20
-       JMP done                       // b .Ldone
+       VPERM   IN1, IN1, MASK, KEY // vperm 3,2,2,5
+       VSLDOI  $12, ZERO, IN0, TMP // vsldoi 6,0,1,12
+       VCIPHERLAST     KEY, RCON, KEY      // vcipherlast 3,3,4
+
+       VXOR    IN0, TMP, IN0       // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0       // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0       // vxor 1,1,6
+
+       VSLDOI  $8, ZERO, IN1, STAGE  // vsldoi 7,0,2,8
+       VSPLTW  $3, IN0, TMP          // vspltw 6,1,3
+       VXOR    TMP, IN1, TMP         // vxor 6,6,2
+       VSLDOI  $12, ZERO, IN1, IN1   // vsldoi 2,0,2,12
+       VADDUWM RCON, RCON, RCON      // vadduwm 4,4,4
+       VXOR    IN1, TMP, IN1         // vxor 2,2,6
+       VXOR    IN0, KEY, IN0         // vxor 1,1,3
+       VXOR    IN1, KEY, IN1         // vxor 2,2,3
+       VSLDOI  $8, STAGE, IN0, STAGE // vsldoi 7,7,1,8
+
+       VPERM   IN1, IN1, MASK, KEY              // vperm 3,2,2,5
+       VSLDOI  $12, ZERO, IN0, TMP              // vsldoi 6,0,1,12
+       VPERM   STAGE, STAGE, OUTPERM, OUTTAIL   // vperm 11,7,7,8
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       VCIPHERLAST     KEY, RCON, KEY           // vcipherlast 3,3,4
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5
+       ADD     $16, OUT, OUT                    // addi 5,5,16
+
+       VSLDOI  $8, IN0, IN1, STAGE              // vsldoi 7,1,2,8
+       VXOR    IN0, TMP, IN0                    // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP              // vsldoi 6,0,6,12
+       VPERM   STAGE, STAGE, OUTPERM, OUTTAIL   // vperm 11,7,7,8
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       VXOR    IN0, TMP, IN0                    // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP              // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0                    // vxor 1,1,6
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5
+       ADD     $16, OUT, OUT                    // addi 5,5,16
+
+       VSPLTW  $3, IN0, TMP                     // vspltw 6,1,3
+       VXOR    TMP, IN1, TMP                    // vxor 6,6,2
+       VSLDOI  $12, ZERO, IN1, IN1              // vsldoi 2,0,2,12
+       VADDUWM RCON, RCON, RCON                 // vadduwm 4,4,4
+       VXOR    IN1, TMP, IN1                    // vxor 2,2,6
+       VXOR    IN0, KEY, IN0                    // vxor 1,1,3
+       VXOR    IN1, KEY, IN1                    // vxor 2,2,3
+       VPERM   IN0, IN0, OUTPERM, OUTTAIL       // vperm 11,1,1,8
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5
+       ADD     $15, OUT, INP                    // addi 3,5,15
+       ADD     $16, OUT, OUT                    // addi 5,5,16
+       BC      0x10, 0, loop192                 // bdnz .Loop192
+
+       MOVD    $12, ROUNDS     // li 8,12
+       ADD     $0x20, OUT, OUT // addi 5,5,0x20
+       BR      done            // b .Ldone
 
 l256:
-       LVX (INP)(R0), TMP             // lvx 6,0,3
-       MOVD $7, CNT                   // li 7,7
-       MOVD $14, ROUNDS               // li 8,14
-       VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5
-       ADD $16, OUT, OUT              // addi 5,5,16
-       VPERM IN1, TMP, KEY, IN1       // vperm 2,2,6,3
-       MOVD CNT, CTR                  // mtctr 7
+       LVX     (INP)(R0), TMP                   // lvx 6,0,3
+       MOVD    $7, CNT                          // li 7,7
+       MOVD    $14, ROUNDS                      // li 8,14
+       VPERM   IN0, IN0, OUTPERM, OUTTAIL       // vperm 11,1,1,8
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5
+       ADD     $16, OUT, OUT                    // addi 5,5,16
+       VPERM   IN1, TMP, KEY, IN1               // vperm 2,2,6,3
+       MOVD    CNT, CTR                         // mtctr 7
 
 loop256:
-       VPERM IN1, IN1, MASK, KEY      // vperm 3,2,2,5
-       VSLDOI $12, ZERO, IN0, TMP     // vsldoi 6,0,1,12
-       VPERM IN1, IN1, OUTPERM, OUTTAIL // vperm 11,2,2,8
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       VCIPHERLAST KEY, RCON, KEY     // vcipherlast 3,3,4
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5
-       ADD $16, OUT, OUT              // addi 5,5,16
-
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN0, TMP, IN0             // vxor 1,1,6
-       VADDUWM RCON, RCON, RCON       // vadduwm 4,4,4
-       VXOR IN0, KEY, IN0             // vxor 1,1,3
-       VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8
-       VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
-       VOR OUTTAIL, OUTTAIL, OUTHEAD  // vor 10,11,11
-       STVX STAGE, (OUT+R0)           // stvx 7,0,5
-       ADD $15, OUT, INP              // addi 3,5,15
-       ADD $16, OUT, OUT              // addi 5,5,16
-       BC 0x12, 0, done               // bdz .Ldone
-
-       VSPLTW $3, IN0, KEY            // vspltw 3,1,3
-       VSLDOI $12, ZERO, IN1, TMP     // vsldoi 6,0,2,12
-       VSBOX KEY, KEY                 // vsbox 3,3
-
-       VXOR IN1, TMP, IN1             // vxor 2,2,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN1, TMP, IN1             // vxor 2,2,6
-       VSLDOI $12, ZERO, TMP, TMP     // vsldoi 6,0,6,12
-       VXOR IN1, TMP, IN1             // vxor 2,2,6
-
-       VXOR IN1, KEY, IN1             // vxor 2,2,3
-       JMP loop256                    // b .Loop256
+       VPERM   IN1, IN1, MASK, KEY              // vperm 3,2,2,5
+       VSLDOI  $12, ZERO, IN0, TMP              // vsldoi 6,0,1,12
+       VPERM   IN1, IN1, OUTPERM, OUTTAIL       // vperm 11,2,2,8
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       VCIPHERLAST     KEY, RCON, KEY           // vcipherlast 3,3,4
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5
+       ADD     $16, OUT, OUT                    // addi 5,5,16
+
+       VXOR    IN0, TMP, IN0                    // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP              // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0                    // vxor 1,1,6
+       VSLDOI  $12, ZERO, TMP, TMP              // vsldoi 6,0,6,12
+       VXOR    IN0, TMP, IN0                    // vxor 1,1,6
+       VADDUWM RCON, RCON, RCON                 // vadduwm 4,4,4
+       VXOR    IN0, KEY, IN0                    // vxor 1,1,3
+       VPERM   IN0, IN0, OUTPERM, OUTTAIL       // vperm 11,1,1,8
+       VSEL    OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9
+       VOR     OUTTAIL, OUTTAIL, OUTHEAD        // vor 10,11,11
+       STVX    STAGE, (OUT+R0)                  // stvx 7,0,5
+       ADD     $15, OUT, INP                    // addi 3,5,15
+       ADD     $16, OUT, OUT                    // addi 5,5,16
+       BC      0x12, 0, done                    // bdz .Ldone
+
+       VSPLTW  $3, IN0, KEY        // vspltw 3,1,3
+       VSLDOI  $12, ZERO, IN1, TMP // vsldoi 6,0,2,12
+       VSBOX   KEY, KEY            // vsbox 3,3
+
+       VXOR    IN1, TMP, IN1       // vxor 2,2,6
+       VSLDOI  $12, ZERO, TMP, TMP // vsldoi 6,0,6,12
+       VXOR    IN1, TMP, IN1       // vxor 2,2,6
+       VSLDOI  $12, ZERO, TMP, TMP // vsldoi 6,0,6,12
+       VXOR    IN1, TMP, IN1       // vxor 2,2,6
+
+       VXOR    IN1, KEY, IN1 // vxor 2,2,3
+       JMP     loop256       // b .Loop256
 
 done:
-       LVX (INP)(R0), IN1             // lvx   2,0,3
-       VSEL OUTHEAD, IN1, OUTMASK, IN1 // vsel 2,10,2,9
-       STVX IN1, (INP+R0)             // stvx  2,0,3
-       MOVD $0, PTR                   // li    6,0    set PTR to 0 (exit code 0)
-       MOVW ROUNDS, 0(OUT)            // stw   8,0(5)
+       LVX     (INP)(R0), IN1             // lvx   2,0,3
+       VSEL    OUTHEAD, IN1, OUTMASK, IN1 // vsel 2,10,2,9
+       STVX    IN1, (INP+R0)              // stvx  2,0,3
+       MOVD    $0, PTR                    // li    6,0    set PTR to 0 (exit code 0)
+       MOVW    ROUNDS, 0(OUT)             // stw   8,0(5)
 
 enc_key_abort:
-       MOVD PTR, INP                  // mr    3,6    set exit code with PTR value
-       MOVD INP, ret+24(FP)           // Put return value into the FP
-       RET                            // blr
+       MOVD    PTR, INP        // mr    3,6    set exit code with PTR value
+       MOVD    INP, ret+24(FP) // Put return value into the FP
+       RET                  // blr
 
 // func setDecryptKeyAsm(key *byte, keylen int, dec *uint32) int
-TEXT ยทsetDecryptKeyAsm(SB),NOSPLIT|NOFRAME,$0
+TEXT ยทsetDecryptKeyAsm(SB), NOSPLIT|NOFRAME, $0
        // Load the arguments inside the registers
-       MOVD key+0(FP), INP
-       MOVD keylen+8(FP), BITS
-       MOVD dec+16(FP), OUT
+       MOVD    key+0(FP), INP
+       MOVD    keylen+8(FP), BITS
+       MOVD    dec+16(FP), OUT
 
-       MOVD LR, R10                   // mflr 10
-       CALL ยทdoEncryptKeyAsm(SB)
-       MOVD R10, LR                   // mtlr 10
+       MOVD    LR, R10              // mflr 10
+       CALL    ยทdoEncryptKeyAsm(SB)
+       MOVD    R10, LR              // mtlr 10
 
-       CMPW INP, $0                   // cmpwi 3,0  exit 0 = ok
-       BC 0x06, 2, dec_key_abort      // bne- .Ldec_key_abort
+       CMPW    INP, $0                // cmpwi 3,0  exit 0 = ok
+       BC      0x06, 2, dec_key_abort // bne- .Ldec_key_abort
 
        // doEncryptKeyAsm set ROUNDS (R8) with the proper value for each mode
-       SLW $4, ROUNDS, CNT            // slwi 7,8,4
-       SUB $240, OUT, INP             // subi 3,5,240
-       SRW $1, ROUNDS, ROUNDS         // srwi 8,8,1
-       ADD R7, INP, OUT               // add 5,3,7
-       MOVD ROUNDS, CTR               // mtctr 8
+       SLW     $4, ROUNDS, CNT    // slwi 7,8,4
+       SUB     $240, OUT, INP     // subi 3,5,240
+       SRW     $1, ROUNDS, ROUNDS // srwi 8,8,1
+       ADD     R7, INP, OUT       // add 5,3,7
+       MOVD    ROUNDS, CTR        // mtctr 8
 
-// dec_key will invert the key sequence in order to be used for decrypt
+       // dec_key will invert the key sequence in order to be used for decrypt
 dec_key:
-       MOVWZ 0(INP), TEMP             // lwz 0, 0(3)
-       MOVWZ 4(INP), R6               // lwz 6, 4(3)
-       MOVWZ 8(INP), R7               // lwz 7, 8(3)
-       MOVWZ 12(INP), R8              // lwz 8, 12(3)
-       ADD $16, INP, INP              // addi 3,3,16
-       MOVWZ 0(OUT), R9               // lwz 9, 0(5)
-       MOVWZ 4(OUT), R10              // lwz 10,4(5)
-       MOVWZ 8(OUT), R11              // lwz 11,8(5)
-       MOVWZ 12(OUT), R12             // lwz 12,12(5)
-       MOVW TEMP, 0(OUT)              // stw 0, 0(5)
-       MOVW R6, 4(OUT)                // stw 6, 4(5)
-       MOVW R7, 8(OUT)                // stw 7, 8(5)
-       MOVW R8, 12(OUT)               // stw 8, 12(5)
-       SUB $16, OUT, OUT              // subi 5,5,16
-       MOVW R9, -16(INP)              // stw 9, -16(3)
-       MOVW R10, -12(INP)             // stw 10,-12(3)
-       MOVW R11, -8(INP)              // stw 11,-8(3)
-       MOVW R12, -4(INP)              // stw 12,-4(3)
-       BC 0x10, 0, dec_key            // bdnz .Ldeckey
-
-       XOR R3, R3, R3                 // xor 3,3,3      Clean R3
+       MOVWZ   0(INP), TEMP     // lwz 0, 0(3)
+       MOVWZ   4(INP), R6       // lwz 6, 4(3)
+       MOVWZ   8(INP), R7       // lwz 7, 8(3)
+       MOVWZ   12(INP), R8      // lwz 8, 12(3)
+       ADD     $16, INP, INP    // addi 3,3,16
+       MOVWZ   0(OUT), R9       // lwz 9, 0(5)
+       MOVWZ   4(OUT), R10      // lwz 10,4(5)
+       MOVWZ   8(OUT), R11      // lwz 11,8(5)
+       MOVWZ   12(OUT), R12     // lwz 12,12(5)
+       MOVW    TEMP, 0(OUT)     // stw 0, 0(5)
+       MOVW    R6, 4(OUT)       // stw 6, 4(5)
+       MOVW    R7, 8(OUT)       // stw 7, 8(5)
+       MOVW    R8, 12(OUT)      // stw 8, 12(5)
+       SUB     $16, OUT, OUT    // subi 5,5,16
+       MOVW    R9, -16(INP)     // stw 9, -16(3)
+       MOVW    R10, -12(INP)    // stw 10,-12(3)
+       MOVW    R11, -8(INP)     // stw 11,-8(3)
+       MOVW    R12, -4(INP)     // stw 12,-4(3)
+       BC      0x10, 0, dec_key // bdnz .Ldeckey
+
+       XOR     R3, R3, R3 // xor 3,3,3      Clean R3
 
 dec_key_abort:
-       MOVD R3, ret+24(FP)            // Put return value into the FP
-       RET                            // blr
-
+       MOVD    R3, ret+24(FP) // Put return value into the FP
+       RET                 // blr
 
 // func encryptBlockAsm(dst, src *byte, enc *uint32)
-TEXT ยทencryptBlockAsm(SB),NOSPLIT|NOFRAME,$0
+TEXT ยทencryptBlockAsm(SB), NOSPLIT|NOFRAME, $0
        // Load the arguments inside the registers
-       MOVD dst+0(FP), BLK_OUT
-       MOVD src+8(FP), BLK_INP
-       MOVD enc+16(FP), BLK_KEY
-
-       MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5)
-       MOVD $15, BLK_IDX              // li 7,15
-
-       LVX (BLK_INP)(R0), ZERO        // lvx 0,0,3
-       NEG BLK_OUT, R11               // neg 11,4
-       LVX (BLK_INP)(BLK_IDX), IN0    // lvx 1,7,3
-       LVSL (BLK_INP)(R0), IN1        // lvsl 2,0,3
-       VSPLTISB $0x0f, RCON           // vspltisb 4,0x0f
-       LVSR (R11)(R0), KEY            // lvsr 3,0,11
-       VXOR IN1, RCON, IN1            // vxor 2,2,4
-       MOVD $16, BLK_IDX              // li 7,16
-       VPERM ZERO, IN0, IN1, ZERO     // vperm 0,0,1,2
-       LVX (BLK_KEY)(R0), IN0         // lvx 1,0,5
-       LVSR (BLK_KEY)(R0), MASK       // lvsr 5,0,5
-       SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1
-       LVX (BLK_KEY)(BLK_IDX), IN1    // lvx 2,7,5
-       ADD $16, BLK_IDX, BLK_IDX      // addi 7,7,16
-       SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1
-       VPERM IN1, IN0, MASK, IN0      // vperm 1,2,1,5
-
-       VXOR ZERO, IN0, ZERO           // vxor 0,0,1
-       LVX (BLK_KEY)(BLK_IDX), IN0    // lvx 1,7,5
-       ADD $16, BLK_IDX, BLK_IDX      // addi 7,7,16
-       MOVD BLK_ROUNDS, CTR           // mtctr 6
+       MOVD    dst+0(FP), BLK_OUT
+       MOVD    src+8(FP), BLK_INP
+       MOVD    enc+16(FP), BLK_KEY
+
+       MOVWZ   240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5)
+       MOVD    $15, BLK_IDX             // li 7,15
+
+       LVX     (BLK_INP)(R0), ZERO        // lvx 0,0,3
+       NEG     BLK_OUT, R11               // neg 11,4
+       LVX     (BLK_INP)(BLK_IDX), IN0    // lvx 1,7,3
+       LVSL    (BLK_INP)(R0), IN1         // lvsl 2,0,3
+       VSPLTISB        $0x0f, RCON        // vspltisb 4,0x0f
+       LVSR    (R11)(R0), KEY             // lvsr 3,0,11
+       VXOR    IN1, RCON, IN1             // vxor 2,2,4
+       MOVD    $16, BLK_IDX               // li 7,16
+       VPERM   ZERO, IN0, IN1, ZERO       // vperm 0,0,1,2
+       LVX     (BLK_KEY)(R0), IN0         // lvx 1,0,5
+       LVSR    (BLK_KEY)(R0), MASK        // lvsr 5,0,5
+       SRW     $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1
+       LVX     (BLK_KEY)(BLK_IDX), IN1    // lvx 2,7,5
+       ADD     $16, BLK_IDX, BLK_IDX      // addi 7,7,16
+       SUB     $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1
+       VPERM   IN1, IN0, MASK, IN0        // vperm 1,2,1,5
+
+       VXOR    ZERO, IN0, ZERO         // vxor 0,0,1
+       LVX     (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5
+       ADD     $16, BLK_IDX, BLK_IDX   // addi 7,7,16
+       MOVD    BLK_ROUNDS, CTR         // mtctr 6
 
 loop_enc:
-       VPERM IN0, IN1, MASK, IN1      // vperm 2,1,2,5
-       VCIPHER ZERO, IN1, ZERO        // vcipher 0,0,2
-       LVX (BLK_KEY)(BLK_IDX), IN1    // lvx 2,7,5
-       ADD $16, BLK_IDX, BLK_IDX      // addi 7,7,16
-       VPERM IN1, IN0, MASK, IN0      // vperm 1,2,1,5
-       VCIPHER ZERO, IN0, ZERO        // vcipher 0,0,1
-       LVX (BLK_KEY)(BLK_IDX), IN0    // lvx 1,7,5
-       ADD $16, BLK_IDX, BLK_IDX      // addi 7,7,16
-       BC 0x10, 0, loop_enc           // bdnz .Loop_enc
-
-       VPERM IN0, IN1, MASK, IN1      // vperm 2,1,2,5
-       VCIPHER ZERO, IN1, ZERO        // vcipher 0,0,2
-       LVX (BLK_KEY)(BLK_IDX), IN1    // lvx 2,7,5
-       VPERM IN1, IN0, MASK, IN0      // vperm 1,2,1,5
-       VCIPHERLAST ZERO, IN0, ZERO    // vcipherlast 0,0,1
-
-       VSPLTISB $-1, IN1              // vspltisb 2,-1
-       VXOR IN0, IN0, IN0             // vxor 1,1,1
-       MOVD $15, BLK_IDX              // li 7,15
-       VPERM IN1, IN0, KEY, IN1       // vperm 2,2,1,3
-       VXOR KEY, RCON, KEY            // vxor 3,3,4
-       LVX (BLK_OUT)(R0), IN0         // lvx 1,0,4
-       VPERM ZERO, ZERO, KEY, ZERO    // vperm 0,0,0,3
-       VSEL IN0, ZERO, IN1, IN0       // vsel 1,1,0,2
-       LVX (BLK_OUT)(BLK_IDX), RCON   // lvx 4,7,4
-       STVX IN0, (BLK_OUT+R0)         // stvx 1,0,4
-       VSEL ZERO, RCON, IN1, ZERO     // vsel 0,0,4,2
-       STVX ZERO, (BLK_OUT+BLK_IDX)   // stvx 0,7,4
-
-       RET                            // blr
-
+       VPERM   IN0, IN1, MASK, IN1     // vperm 2,1,2,5
+       VCIPHER ZERO, IN1, ZERO         // vcipher 0,0,2
+       LVX     (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5
+       ADD     $16, BLK_IDX, BLK_IDX   // addi 7,7,16
+       VPERM   IN1, IN0, MASK, IN0     // vperm 1,2,1,5
+       VCIPHER ZERO, IN0, ZERO         // vcipher 0,0,1
+       LVX     (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5
+       ADD     $16, BLK_IDX, BLK_IDX   // addi 7,7,16
+       BC      0x10, 0, loop_enc       // bdnz .Loop_enc
+
+       VPERM   IN0, IN1, MASK, IN1     // vperm 2,1,2,5
+       VCIPHER ZERO, IN1, ZERO         // vcipher 0,0,2
+       LVX     (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5
+       VPERM   IN1, IN0, MASK, IN0     // vperm 1,2,1,5
+       VCIPHERLAST     ZERO, IN0, ZERO // vcipherlast 0,0,1
+
+       VSPLTISB        $-1, IN1         // vspltisb 2,-1
+       VXOR    IN0, IN0, IN0            // vxor 1,1,1
+       MOVD    $15, BLK_IDX             // li 7,15
+       VPERM   IN1, IN0, KEY, IN1       // vperm 2,2,1,3
+       VXOR    KEY, RCON, KEY           // vxor 3,3,4
+       LVX     (BLK_OUT)(R0), IN0       // lvx 1,0,4
+       VPERM   ZERO, ZERO, KEY, ZERO    // vperm 0,0,0,3
+       VSEL    IN0, ZERO, IN1, IN0      // vsel 1,1,0,2
+       LVX     (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4
+       STVX    IN0, (BLK_OUT+R0)        // stvx 1,0,4
+       VSEL    ZERO, RCON, IN1, ZERO    // vsel 0,0,4,2
+       STVX    ZERO, (BLK_OUT+BLK_IDX)  // stvx 0,7,4
+
+       RET // blr
 
 // func decryptBlockAsm(dst, src *byte, dec *uint32)
-TEXT ยทdecryptBlockAsm(SB),NOSPLIT|NOFRAME,$0
+TEXT ยทdecryptBlockAsm(SB), NOSPLIT|NOFRAME, $0
        // Load the arguments inside the registers
-       MOVD dst+0(FP), BLK_OUT
-       MOVD src+8(FP), BLK_INP
-       MOVD dec+16(FP), BLK_KEY
-
-       MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5)
-       MOVD $15, BLK_IDX              // li 7,15
-
-       LVX (BLK_INP)(R0), ZERO        // lvx 0,0,3
-       NEG BLK_OUT, R11               // neg 11,4
-       LVX (BLK_INP)(BLK_IDX), IN0    // lvx 1,7,3
-       LVSL (BLK_INP)(R0), IN1        // lvsl 2,0,3
-       VSPLTISB $0x0f, RCON           // vspltisb 4,0x0f
-       LVSR (R11)(R0), KEY            // lvsr 3,0,11
-       VXOR IN1, RCON, IN1            // vxor 2,2,4
-       MOVD $16, BLK_IDX              // li 7,16
-       VPERM ZERO, IN0, IN1, ZERO     // vperm 0,0,1,2
-       LVX (BLK_KEY)(R0), IN0         // lvx 1,0,5
-       LVSR (BLK_KEY)(R0), MASK       // lvsr 5,0,5
-       SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1
-       LVX (BLK_KEY)(BLK_IDX), IN1    // lvx 2,7,5
-       ADD $16, BLK_IDX, BLK_IDX      // addi 7,7,16
-       SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1
-       VPERM IN1, IN0, MASK, IN0      // vperm 1,2,1,5
-
-       VXOR ZERO, IN0, ZERO           // vxor 0,0,1
-       LVX (BLK_KEY)(BLK_IDX), IN0    // lvx 1,7,5
-       ADD $16, BLK_IDX, BLK_IDX      // addi 7,7,16
-       MOVD BLK_ROUNDS, CTR           // mtctr 6
+       MOVD    dst+0(FP), BLK_OUT
+       MOVD    src+8(FP), BLK_INP
+       MOVD    dec+16(FP), BLK_KEY
+
+       MOVWZ   240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5)
+       MOVD    $15, BLK_IDX             // li 7,15
+
+       LVX     (BLK_INP)(R0), ZERO        // lvx 0,0,3
+       NEG     BLK_OUT, R11               // neg 11,4
+       LVX     (BLK_INP)(BLK_IDX), IN0    // lvx 1,7,3
+       LVSL    (BLK_INP)(R0), IN1         // lvsl 2,0,3
+       VSPLTISB        $0x0f, RCON        // vspltisb 4,0x0f
+       LVSR    (R11)(R0), KEY             // lvsr 3,0,11
+       VXOR    IN1, RCON, IN1             // vxor 2,2,4
+       MOVD    $16, BLK_IDX               // li 7,16
+       VPERM   ZERO, IN0, IN1, ZERO       // vperm 0,0,1,2
+       LVX     (BLK_KEY)(R0), IN0         // lvx 1,0,5
+       LVSR    (BLK_KEY)(R0), MASK        // lvsr 5,0,5
+       SRW     $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1
+       LVX     (BLK_KEY)(BLK_IDX), IN1    // lvx 2,7,5
+       ADD     $16, BLK_IDX, BLK_IDX      // addi 7,7,16
+       SUB     $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1
+       VPERM   IN1, IN0, MASK, IN0        // vperm 1,2,1,5
+
+       VXOR    ZERO, IN0, ZERO         // vxor 0,0,1
+       LVX     (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5
+       ADD     $16, BLK_IDX, BLK_IDX   // addi 7,7,16
+       MOVD    BLK_ROUNDS, CTR         // mtctr 6
 
 loop_dec:
-       VPERM IN0, IN1, MASK, IN1      // vperm 2,1,2,5
-       VNCIPHER ZERO, IN1, ZERO       // vncipher 0,0,2
-       LVX (BLK_KEY)(BLK_IDX), IN1    // lvx 2,7,5
-       ADD $16, BLK_IDX, BLK_IDX      // addi 7,7,16
-       VPERM IN1, IN0, MASK, IN0      // vperm 1,2,1,5
-       VNCIPHER ZERO, IN0, ZERO       // vncipher 0,0,1
-       LVX (BLK_KEY)(BLK_IDX), IN0    // lvx 1,7,5
-       ADD $16, BLK_IDX, BLK_IDX      // addi 7,7,16
-       BC 0x10, 0, loop_dec           // bdnz .Loop_dec
-
-       VPERM IN0, IN1, MASK, IN1      // vperm 2,1,2,5
-       VNCIPHER ZERO, IN1, ZERO       // vncipher 0,0,2
-       LVX (BLK_KEY)(BLK_IDX), IN1    // lvx 2,7,5
-       VPERM IN1, IN0, MASK, IN0      // vperm 1,2,1,5
-       VNCIPHERLAST ZERO, IN0, ZERO   // vncipherlast 0,0,1
-
-       VSPLTISB $-1, IN1              // vspltisb 2,-1
-       VXOR IN0, IN0, IN0             // vxor 1,1,1
-       MOVD $15, BLK_IDX              // li 7,15
-       VPERM IN1, IN0, KEY, IN1       // vperm 2,2,1,3
-       VXOR KEY, RCON, KEY            // vxor 3,3,4
-       LVX (BLK_OUT)(R0), IN0         // lvx 1,0,4
-       VPERM ZERO, ZERO, KEY, ZERO    // vperm 0,0,0,3
-       VSEL IN0, ZERO, IN1, IN0       // vsel 1,1,0,2
-       LVX (BLK_OUT)(BLK_IDX), RCON   // lvx 4,7,4
-       STVX IN0, (BLK_OUT+R0)         // stvx 1,0,4
-       VSEL ZERO, RCON, IN1, ZERO     // vsel 0,0,4,2
-       STVX ZERO, (BLK_OUT+BLK_IDX)   // stvx 0,7,4
-
-       RET                            // blr
+       VPERM   IN0, IN1, MASK, IN1     // vperm 2,1,2,5
+       VNCIPHER        ZERO, IN1, ZERO // vncipher 0,0,2
+       LVX     (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5
+       ADD     $16, BLK_IDX, BLK_IDX   // addi 7,7,16
+       VPERM   IN1, IN0, MASK, IN0     // vperm 1,2,1,5
+       VNCIPHER        ZERO, IN0, ZERO // vncipher 0,0,1
+       LVX     (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5
+       ADD     $16, BLK_IDX, BLK_IDX   // addi 7,7,16
+       BC      0x10, 0, loop_dec       // bdnz .Loop_dec
+
+       VPERM   IN0, IN1, MASK, IN1     // vperm 2,1,2,5
+       VNCIPHER        ZERO, IN1, ZERO // vncipher 0,0,2
+       LVX     (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5
+       VPERM   IN1, IN0, MASK, IN0     // vperm 1,2,1,5
+       VNCIPHERLAST    ZERO, IN0, ZERO // vncipherlast 0,0,1
+
+       VSPLTISB        $-1, IN1         // vspltisb 2,-1
+       VXOR    IN0, IN0, IN0            // vxor 1,1,1
+       MOVD    $15, BLK_IDX             // li 7,15
+       VPERM   IN1, IN0, KEY, IN1       // vperm 2,2,1,3
+       VXOR    KEY, RCON, KEY           // vxor 3,3,4
+       LVX     (BLK_OUT)(R0), IN0       // lvx 1,0,4
+       VPERM   ZERO, ZERO, KEY, ZERO    // vperm 0,0,0,3
+       VSEL    IN0, ZERO, IN1, IN0      // vsel 1,1,0,2
+       LVX     (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4
+       STVX    IN0, (BLK_OUT+R0)        // stvx 1,0,4
+       VSEL    ZERO, RCON, IN1, ZERO    // vsel 0,0,4,2
+       STVX    ZERO, (BLK_OUT+BLK_IDX)  // stvx 0,7,4
+
+       RET // blr
+
index cdde0c4e607b2f7c6f6a7295538496833b0155c7..d06a284154659643d181ee20835c9ffbb319d92b 100644 (file)
@@ -85,7 +85,7 @@ func (curve *CurveParams) polynomial(x *big.Int) *big.Int {
 func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
        // If there is a dedicated constant-time implementation for this curve operation,
        // use that instead of the generic one.
-       if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+       if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok {
                return specific.IsOnCurve(x, y)
        }
 
@@ -128,7 +128,7 @@ func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.
 func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
        // If there is a dedicated constant-time implementation for this curve operation,
        // use that instead of the generic one.
-       if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+       if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok {
                return specific.Add(x1, y1, x2, y2)
        }
 
@@ -218,7 +218,7 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
 func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
        // If there is a dedicated constant-time implementation for this curve operation,
        // use that instead of the generic one.
-       if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+       if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok {
                return specific.Double(x1, y1)
        }
 
@@ -290,7 +290,7 @@ func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
 func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
        // If there is a dedicated constant-time implementation for this curve operation,
        // use that instead of the generic one.
-       if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok {
+       if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok {
                return specific.ScalarMult(Bx, By, k)
        }
 
@@ -313,7 +313,7 @@ func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.
 func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
        // If there is a dedicated constant-time implementation for this curve operation,
        // use that instead of the generic one.
-       if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok {
+       if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok {
                return specific.ScalarBaseMult(k)
        }
 
@@ -431,7 +431,6 @@ func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int) {
 }
 
 var initonce sync.Once
-var p384 *CurveParams
 
 func initAll() {
        initP224()
@@ -440,15 +439,16 @@ func initAll() {
        initP521()
 }
 
-func initP384() {
-       // See FIPS 186-3, section D.2.4
-       p384 = &CurveParams{Name: "P-384"}
-       p384.P, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10)
-       p384.N, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643", 10)
-       p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16)
-       p384.Gx, _ = new(big.Int).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16)
-       p384.Gy, _ = new(big.Int).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16)
-       p384.BitSize = 384
+// P224 returns a Curve which implements NIST P-224 (FIPS 186-3, section D.2.2),
+// also known as secp224r1. The CurveParams.Name of this Curve is "P-224".
+//
+// Multiple invocations of this function will return the same value, so it can
+// be used for equality checks and switch statements.
+//
+// The cryptographic operations are implemented using constant-time algorithms.
+func P224() Curve {
+       initonce.Do(initAll)
+       return p224
 }
 
 // P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3),
@@ -470,7 +470,7 @@ func P256() Curve {
 // Multiple invocations of this function will return the same value, so it can
 // be used for equality checks and switch statements.
 //
-// The cryptographic operations do not use constant-time algorithms.
+// The cryptographic operations are implemented using constant-time algorithms.
 func P384() Curve {
        initonce.Do(initAll)
        return p384
index d30a6939a4e35c5382d15c52d78b03de2a3cf884..f5b36f75ca0439a28d90c8cd2c75557252089c53 100644 (file)
@@ -14,9 +14,8 @@ import (
 
 // genericParamsForCurve returns the dereferenced CurveParams for
 // the specified curve. This is used to avoid the logic for
-// upgrading a curve to it's specific implementation, forcing
-// usage of the generic implementation. This is only relevant
-// for the P224, P256, and P521 curves.
+// upgrading a curve to its specific implementation, forcing
+// usage of the generic implementation.
 func genericParamsForCurve(c Curve) *CurveParams {
        d := *(c.Params())
        return &d
index 7b5ece0e30f482066b4c1bf808b49d8e3020fc80..2877e0b2c125036d3e7313a2bee52eca0fcc6195 100644 (file)
@@ -4,9 +4,9 @@
 
 FROM coqorg/coq:8.13.2
 
-RUN git clone https://github.com/mit-plv/fiat-crypto
-RUN cd fiat-crypto && git checkout c076f3550bea2bb7f4cb5766a32594b9e67694f2
-RUN cd fiat-crypto && git submodule update --init --recursive
+RUN git clone https://github.com/mit-plv/fiat-crypto && cd fiat-crypto && \
+    git checkout 23d2dbc4ab897d14bde4404f70cd6991635f9c01 && \
+    git submodule update --init --recursive
 RUN cd fiat-crypto && eval $(opam env) && make -j4 standalone-ocaml SKIP_BEDROCK2=1
 
-ENTRYPOINT ["fiat-crypto/src/ExtractionOCaml/unsaturated_solinas"]
+ENV PATH /home/coq/fiat-crypto/src/ExtractionOCaml:$PATH
index 171f57a32742f85391482ea1672f1ad68fe83aeb..916ebc14ce8ad607516e88aad231bc246ae577d0 100644 (file)
@@ -1,17 +1,12 @@
 The code in this package was autogenerated by the fiat-crypto project
-at commit c076f3550 from a formally verified model.
-
-    docker build -t fiat-crypto:c076f3550 .
-    docker run fiat-crypto:c076f3550 --lang Go --no-wide-int --cmovznz-by-mul \
-        --internal-static --public-function-case camelCase --public-type-case camelCase \
-        --private-function-case camelCase --private-type-case camelCase \
-        --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' \
-        --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' \
-        --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' \
-        carry_mul carry_square carry add sub to_bytes from_bytes selectznz \
-        > p521_fiat64.go
-
-It comes under the following license.
+at version v0.0.9 from a formally verified model, and by the addchain
+project at a recent tip version.
+
+    docker build -t fiat-crypto:v0.0.9 .
+    go install github.com/mmcloughlin/addchain/cmd/addchain@v0.3.1-0.20211027081849-6a7d3decbe08
+    ../../../../../bin/go run generate.go
+
+fiat-crypto code comes under the following license.
 
     Copyright (c) 2015-2020 The fiat-crypto Authors. All rights reserved.
 
diff --git a/src/crypto/elliptic/internal/fiat/fiat_test.go b/src/crypto/elliptic/internal/fiat/fiat_test.go
new file mode 100644 (file)
index 0000000..9ecd863
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package fiat_test
+
+import (
+       "crypto/elliptic/internal/fiat"
+       "testing"
+)
+
+func BenchmarkMul(b *testing.B) {
+       b.Run("P224", func(b *testing.B) {
+               v := new(fiat.P224Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Mul(v, v)
+               }
+       })
+       b.Run("P384", func(b *testing.B) {
+               v := new(fiat.P384Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Mul(v, v)
+               }
+       })
+       b.Run("P521", func(b *testing.B) {
+               v := new(fiat.P521Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Mul(v, v)
+               }
+       })
+}
+
+func BenchmarkSquare(b *testing.B) {
+       b.Run("P224", func(b *testing.B) {
+               v := new(fiat.P224Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Square(v)
+               }
+       })
+       b.Run("P384", func(b *testing.B) {
+               v := new(fiat.P384Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Square(v)
+               }
+       })
+       b.Run("P521", func(b *testing.B) {
+               v := new(fiat.P521Element).One()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       v.Square(v)
+               }
+       })
+}
diff --git a/src/crypto/elliptic/internal/fiat/generate.go b/src/crypto/elliptic/internal/fiat/generate.go
new file mode 100644 (file)
index 0000000..fd8509d
--- /dev/null
@@ -0,0 +1,330 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build ignore
+
+package main
+
+import (
+       "bytes"
+       "go/format"
+       "io"
+       "log"
+       "os"
+       "os/exec"
+       "text/template"
+)
+
+var curves = []struct {
+       Element  string
+       Prime    string
+       Prefix   string
+       FiatType string
+       BytesLen int
+}{
+       {
+               Element:  "P224Element",
+               Prime:    "2^224 - 2^96 + 1",
+               Prefix:   "p224",
+               FiatType: "[4]uint64",
+               BytesLen: 28,
+       },
+       // The 32-bit pure Go P-256 in crypto/elliptic is still faster than the
+       // autogenerated code here, regrettably.
+       // {
+       //  Element:  "P256Element",
+       //  Prime:    "2^256 - 2^224 + 2^192 + 2^96 - 1",
+       //  Prefix:   "p256",
+       //  FiatType: "[4]uint64",
+       //  BytesLen: 32,
+       // },
+       {
+               Element:  "P384Element",
+               Prime:    "2^384 - 2^128 - 2^96 + 2^32 - 1",
+               Prefix:   "p384",
+               FiatType: "[6]uint64",
+               BytesLen: 48,
+       },
+       // Note that unsaturated_solinas would be about 2x faster than
+       // word_by_word_montgomery for P-521, but this curve is used rarely enough
+       // that it's not worth carrying unsaturated_solinas support for it.
+       {
+               Element:  "P521Element",
+               Prime:    "2^521 - 1",
+               Prefix:   "p521",
+               FiatType: "[9]uint64",
+               BytesLen: 66,
+       },
+}
+
+func main() {
+       t := template.Must(template.New("montgomery").Parse(tmplWrapper))
+
+       tmplAddchainFile, err := os.CreateTemp("", "addchain-template")
+       if err != nil {
+               log.Fatal(err)
+       }
+       defer os.Remove(tmplAddchainFile.Name())
+       if _, err := io.WriteString(tmplAddchainFile, tmplAddchain); err != nil {
+               log.Fatal(err)
+       }
+       if err := tmplAddchainFile.Close(); err != nil {
+               log.Fatal(err)
+       }
+
+       for _, c := range curves {
+               log.Printf("Generating %s.go...", c.Prefix)
+               f, err := os.Create(c.Prefix + ".go")
+               if err != nil {
+                       log.Fatal(err)
+               }
+               if err := t.Execute(f, c); err != nil {
+                       log.Fatal(err)
+               }
+               if err := f.Close(); err != nil {
+                       log.Fatal(err)
+               }
+
+               log.Printf("Generating %s_fiat64.go...", c.Prefix)
+               cmd := exec.Command("docker", "run", "--rm", "--entrypoint", "word_by_word_montgomery",
+                       "fiat-crypto:v0.0.9", "--lang", "Go", "--no-wide-int", "--cmovznz-by-mul",
+                       "--relax-primitive-carry-to-bitwidth", "32,64", "--internal-static",
+                       "--public-function-case", "camelCase", "--public-type-case", "camelCase",
+                       "--private-function-case", "camelCase", "--private-type-case", "camelCase",
+                       "--doc-text-before-function-name", "", "--doc-newline-before-package-declaration",
+                       "--doc-prepend-header", "Code generated by Fiat Cryptography. DO NOT EDIT.",
+                       "--package-name", "fiat", "--no-prefix-fiat", c.Prefix, "64", c.Prime,
+                       "mul", "square", "add", "sub", "one", "from_montgomery", "to_montgomery",
+                       "selectznz", "to_bytes", "from_bytes")
+               cmd.Stderr = os.Stderr
+               out, err := cmd.Output()
+               if err != nil {
+                       log.Fatal(err)
+               }
+               out, err = format.Source(out)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               if err := os.WriteFile(c.Prefix+"_fiat64.go", out, 0644); err != nil {
+                       log.Fatal(err)
+               }
+
+               log.Printf("Generating %s_invert.go...", c.Prefix)
+               f, err = os.CreateTemp("", "addchain-"+c.Prefix)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               defer os.Remove(f.Name())
+               cmd = exec.Command("addchain", "search", c.Prime+" - 2")
+               cmd.Stderr = os.Stderr
+               cmd.Stdout = f
+               if err := cmd.Run(); err != nil {
+                       log.Fatal(err)
+               }
+               if err := f.Close(); err != nil {
+                       log.Fatal(err)
+               }
+               cmd = exec.Command("addchain", "gen", "-tmpl", tmplAddchainFile.Name(), f.Name())
+               cmd.Stderr = os.Stderr
+               out, err = cmd.Output()
+               if err != nil {
+                       log.Fatal(err)
+               }
+               out = bytes.Replace(out, []byte("Element"), []byte(c.Element), -1)
+               out, err = format.Source(out)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               if err := os.WriteFile(c.Prefix+"_invert.go", out, 0644); err != nil {
+                       log.Fatal(err)
+               }
+       }
+}
+
+const tmplWrapper = `// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by generate.go. DO NOT EDIT.
+
+package fiat
+
+import (
+       "crypto/subtle"
+       "errors"
+)
+
+// {{ .Element }} is an integer modulo {{ .Prime }}.
+//
+// The zero value is a valid zero element.
+type {{ .Element }} struct {
+       // Values are represented internally always in the Montgomery domain, and
+       // converted in Bytes and SetBytes.
+       x {{ .Prefix }}MontgomeryDomainFieldElement
+}
+
+const {{ .Prefix }}ElementLen = {{ .BytesLen }}
+
+type {{ .Prefix }}UntypedFieldElement = {{ .FiatType }}
+
+// One sets e = 1, and returns e.
+func (e *{{ .Element }}) One() *{{ .Element }} {
+       {{ .Prefix }}SetOne(&e.x)
+       return e
+}
+
+// Equal returns 1 if e == t, and zero otherwise.
+func (e *{{ .Element }}) Equal(t *{{ .Element }}) int {
+       eBytes := e.Bytes()
+       tBytes := t.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, tBytes)
+}
+
+var {{ .Prefix }}ZeroEncoding = new({{ .Element }}).Bytes()
+
+// IsZero returns 1 if e == 0, and zero otherwise.
+func (e *{{ .Element }}) IsZero() int {
+       eBytes := e.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, {{ .Prefix }}ZeroEncoding)
+}
+
+// Set sets e = t, and returns e.
+func (e *{{ .Element }}) Set(t *{{ .Element }}) *{{ .Element }} {
+       e.x = t.x
+       return e
+}
+
+// Bytes returns the {{ .BytesLen }}-byte big-endian encoding of e.
+func (e *{{ .Element }}) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [{{ .Prefix }}ElementLen]byte
+       return e.bytes(&out)
+}
+
+func (e *{{ .Element }}) bytes(out *[{{ .Prefix }}ElementLen]byte) []byte {
+       var tmp {{ .Prefix }}NonMontgomeryDomainFieldElement
+       {{ .Prefix }}FromMontgomery(&tmp, &e.x)
+       {{ .Prefix }}ToBytes(out, (*{{ .Prefix }}UntypedFieldElement)(&tmp))
+       {{ .Prefix }}InvertEndianness(out[:])
+       return out[:]
+}
+
+// {{ .Prefix }}MinusOneEncoding is the encoding of -1 mod p, so p - 1, the
+// highest canonical encoding. It is used by SetBytes to check for non-canonical
+// encodings such as p + k, 2p + k, etc.
+var {{ .Prefix }}MinusOneEncoding = new({{ .Element }}).Sub(
+       new({{ .Element }}), new({{ .Element }}).One()).Bytes()
+
+// SetBytes sets e = v, where v is a big-endian {{ .BytesLen }}-byte encoding, and returns e.
+// If v is not {{ .BytesLen }} bytes or it encodes a value higher than {{ .Prime }},
+// SetBytes returns nil and an error, and e is unchanged.
+func (e *{{ .Element }}) SetBytes(v []byte) (*{{ .Element }}, error) {
+       if len(v) != {{ .Prefix }}ElementLen {
+               return nil, errors.New("invalid {{ .Element }} encoding")
+       }
+       for i := range v {
+               if v[i] < {{ .Prefix }}MinusOneEncoding[i] {
+                       break
+               }
+               if v[i] > {{ .Prefix }}MinusOneEncoding[i] {
+                       return nil, errors.New("invalid {{ .Element }} encoding")
+               }
+       }
+       var in [{{ .Prefix }}ElementLen]byte
+       copy(in[:], v)
+       {{ .Prefix }}InvertEndianness(in[:])
+       var tmp {{ .Prefix }}NonMontgomeryDomainFieldElement
+       {{ .Prefix }}FromBytes((*{{ .Prefix }}UntypedFieldElement)(&tmp), &in)
+       {{ .Prefix }}ToMontgomery(&e.x, &tmp)
+       return e, nil
+}
+
+// Add sets e = t1 + t2, and returns e.
+func (e *{{ .Element }}) Add(t1, t2 *{{ .Element }}) *{{ .Element }} {
+       {{ .Prefix }}Add(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Sub sets e = t1 - t2, and returns e.
+func (e *{{ .Element }}) Sub(t1, t2 *{{ .Element }}) *{{ .Element }} {
+       {{ .Prefix }}Sub(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Mul sets e = t1 * t2, and returns e.
+func (e *{{ .Element }}) Mul(t1, t2 *{{ .Element }}) *{{ .Element }} {
+       {{ .Prefix }}Mul(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Square sets e = t * t, and returns e.
+func (e *{{ .Element }}) Square(t *{{ .Element }}) *{{ .Element }} {
+       {{ .Prefix }}Square(&e.x, &t.x)
+       return e
+}
+
+// Select sets v to a if cond == 1, and to b if cond == 0.
+func (v *{{ .Element }}) Select(a, b *{{ .Element }}, cond int) *{{ .Element }} {
+       {{ .Prefix }}Selectznz((*{{ .Prefix }}UntypedFieldElement)(&v.x), {{ .Prefix }}Uint1(cond),
+               (*{{ .Prefix }}UntypedFieldElement)(&b.x), (*{{ .Prefix }}UntypedFieldElement)(&a.x))
+       return v
+}
+
+func {{ .Prefix }}InvertEndianness(v []byte) {
+       for i := 0; i < len(v)/2; i++ {
+               v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
+       }
+}
+`
+
+const tmplAddchain = `// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by {{ .Meta.Name }}. DO NOT EDIT.
+
+package fiat
+
+// Invert sets e = 1/x, and returns e.
+//
+// If x == 0, Invert returns e = 0.
+func (e *Element) Invert(x *Element) *Element {
+       // Inversion is implemented as exponentiation with exponent p โˆ’ 2.
+       // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the
+       // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}.
+       //
+       {{- range lines (format .Script) }}
+       //      {{ . }}
+       {{- end }}
+       //
+
+       var z = new(Element).Set(e)
+       {{- range .Program.Temporaries }}
+       var {{ . }} = new(Element)
+       {{- end }}
+       {{ range $i := .Program.Instructions -}}
+       {{- with add $i.Op }}
+       {{ $i.Output }}.Mul({{ .X }}, {{ .Y }})
+       {{- end -}}
+
+       {{- with double $i.Op }}
+       {{ $i.Output }}.Square({{ .X }})
+       {{- end -}}
+
+       {{- with shift $i.Op -}}
+       {{- $first := 0 -}}
+       {{- if ne $i.Output.Identifier .X.Identifier }}
+       {{ $i.Output }}.Square({{ .X }})
+       {{- $first = 1 -}}
+       {{- end }}
+       for s := {{ $first }}; s < {{ .S }}; s++ {
+               {{ $i.Output }}.Square({{ $i.Output }})
+       }
+       {{- end -}}
+       {{- end }}
+
+       return e.Set(z)
+}
+`
diff --git a/src/crypto/elliptic/internal/fiat/p224.go b/src/crypto/elliptic/internal/fiat/p224.go
new file mode 100644 (file)
index 0000000..4dddeb0
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by generate.go. DO NOT EDIT.
+
+package fiat
+
+import (
+       "crypto/subtle"
+       "errors"
+)
+
+// P224Element is an integer modulo 2^224 - 2^96 + 1.
+//
+// The zero value is a valid zero element.
+type P224Element struct {
+       // Values are represented internally always in the Montgomery domain, and
+       // converted in Bytes and SetBytes.
+       x p224MontgomeryDomainFieldElement
+}
+
+const p224ElementLen = 28
+
+type p224UntypedFieldElement = [4]uint64
+
+// One sets e = 1, and returns e.
+func (e *P224Element) One() *P224Element {
+       p224SetOne(&e.x)
+       return e
+}
+
+// Equal returns 1 if e == t, and zero otherwise.
+func (e *P224Element) Equal(t *P224Element) int {
+       eBytes := e.Bytes()
+       tBytes := t.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, tBytes)
+}
+
+var p224ZeroEncoding = new(P224Element).Bytes()
+
+// IsZero returns 1 if e == 0, and zero otherwise.
+func (e *P224Element) IsZero() int {
+       eBytes := e.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, p224ZeroEncoding)
+}
+
+// Set sets e = t, and returns e.
+func (e *P224Element) Set(t *P224Element) *P224Element {
+       e.x = t.x
+       return e
+}
+
+// Bytes returns the 28-byte big-endian encoding of e.
+func (e *P224Element) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [p224ElementLen]byte
+       return e.bytes(&out)
+}
+
+func (e *P224Element) bytes(out *[p224ElementLen]byte) []byte {
+       var tmp p224NonMontgomeryDomainFieldElement
+       p224FromMontgomery(&tmp, &e.x)
+       p224ToBytes(out, (*p224UntypedFieldElement)(&tmp))
+       p224InvertEndianness(out[:])
+       return out[:]
+}
+
+// p224MinusOneEncoding is the encoding of -1 mod p, so p - 1, the
+// highest canonical encoding. It is used by SetBytes to check for non-canonical
+// encodings such as p + k, 2p + k, etc.
+var p224MinusOneEncoding = new(P224Element).Sub(
+       new(P224Element), new(P224Element).One()).Bytes()
+
+// SetBytes sets e = v, where v is a big-endian 28-byte encoding, and returns e.
+// If v is not 28 bytes or it encodes a value higher than 2^224 - 2^96 + 1,
+// SetBytes returns nil and an error, and e is unchanged.
+func (e *P224Element) SetBytes(v []byte) (*P224Element, error) {
+       if len(v) != p224ElementLen {
+               return nil, errors.New("invalid P224Element encoding")
+       }
+       for i := range v {
+               if v[i] < p224MinusOneEncoding[i] {
+                       break
+               }
+               if v[i] > p224MinusOneEncoding[i] {
+                       return nil, errors.New("invalid P224Element encoding")
+               }
+       }
+       var in [p224ElementLen]byte
+       copy(in[:], v)
+       p224InvertEndianness(in[:])
+       var tmp p224NonMontgomeryDomainFieldElement
+       p224FromBytes((*p224UntypedFieldElement)(&tmp), &in)
+       p224ToMontgomery(&e.x, &tmp)
+       return e, nil
+}
+
+// Add sets e = t1 + t2, and returns e.
+func (e *P224Element) Add(t1, t2 *P224Element) *P224Element {
+       p224Add(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Sub sets e = t1 - t2, and returns e.
+func (e *P224Element) Sub(t1, t2 *P224Element) *P224Element {
+       p224Sub(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Mul sets e = t1 * t2, and returns e.
+func (e *P224Element) Mul(t1, t2 *P224Element) *P224Element {
+       p224Mul(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Square sets e = t * t, and returns e.
+func (e *P224Element) Square(t *P224Element) *P224Element {
+       p224Square(&e.x, &t.x)
+       return e
+}
+
+// Select sets v to a if cond == 1, and to b if cond == 0.
+func (v *P224Element) Select(a, b *P224Element, cond int) *P224Element {
+       p224Selectznz((*p224UntypedFieldElement)(&v.x), p224Uint1(cond),
+               (*p224UntypedFieldElement)(&b.x), (*p224UntypedFieldElement)(&a.x))
+       return v
+}
+
+func p224InvertEndianness(v []byte) {
+       for i := 0; i < len(v)/2; i++ {
+               v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
+       }
+}
diff --git a/src/crypto/elliptic/internal/fiat/p224_fiat64.go b/src/crypto/elliptic/internal/fiat/p224_fiat64.go
new file mode 100644 (file)
index 0000000..4ece3e9
--- /dev/null
@@ -0,0 +1,1429 @@
+// Code generated by Fiat Cryptography. DO NOT EDIT.
+//
+// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p224 64 '2^224 - 2^96 + 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes
+//
+// curve description: p224
+//
+// machine_wordsize = 64 (from "64")
+//
+// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes
+//
+// m = 0xffffffffffffffffffffffffffffffff000000000000000000000001 (from "2^224 - 2^96 + 1")
+//
+//
+//
+// NOTE: In addition to the bounds specified above each function, all
+//
+//   functions synthesized for this Montgomery arithmetic require the
+//
+//   input to be strictly less than the prime modulus (m), and also
+//
+//   require the input to be in the unique saturated representation.
+//
+//   All functions also ensure that these two properties are true of
+//
+//   return values.
+//
+//
+//
+// Computed values:
+//
+//   eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192)
+//
+//   bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216)
+//
+//   twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in
+//
+//                            if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256
+
+package fiat
+
+import "math/bits"
+
+type p224Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
+type p224Int1 int64   // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
+
+// The type p224MontgomeryDomainFieldElement is a field element in the Montgomery domain.
+//
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p224MontgomeryDomainFieldElement [4]uint64
+
+// The type p224NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain.
+//
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p224NonMontgomeryDomainFieldElement [4]uint64
+
+// p224CmovznzU64 is a single-word conditional move.
+//
+// Postconditions:
+//   out1 = (if arg1 = 0 then arg2 else arg3)
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [0x0 ~> 0xffffffffffffffff]
+//   arg3: [0x0 ~> 0xffffffffffffffff]
+// Output Bounds:
+//   out1: [0x0 ~> 0xffffffffffffffff]
+func p224CmovznzU64(out1 *uint64, arg1 p224Uint1, arg2 uint64, arg3 uint64) {
+       x1 := (uint64(arg1) * 0xffffffffffffffff)
+       x2 := ((x1 & arg3) | ((^x1) & arg2))
+       *out1 = x2
+}
+
+// p224Mul multiplies two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+//   0 โ‰ค eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p224Mul(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[0]
+       var x5 uint64
+       var x6 uint64
+       x6, x5 = bits.Mul64(x4, arg2[3])
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x4, arg2[2])
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x4, arg2[1])
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x4, arg2[0])
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Add64(x12, x9, uint64(0x0))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16)))
+       x19 := (uint64(p224Uint1(x18)) + x6)
+       var x20 uint64
+       _, x20 = bits.Mul64(x11, 0xffffffffffffffff)
+       var x22 uint64
+       var x23 uint64
+       x23, x22 = bits.Mul64(x20, 0xffffffff)
+       var x24 uint64
+       var x25 uint64
+       x25, x24 = bits.Mul64(x20, 0xffffffffffffffff)
+       var x26 uint64
+       var x27 uint64
+       x27, x26 = bits.Mul64(x20, 0xffffffff00000000)
+       var x28 uint64
+       var x29 uint64
+       x28, x29 = bits.Add64(x27, x24, uint64(0x0))
+       var x30 uint64
+       var x31 uint64
+       x30, x31 = bits.Add64(x25, x22, uint64(p224Uint1(x29)))
+       x32 := (uint64(p224Uint1(x31)) + x23)
+       var x34 uint64
+       _, x34 = bits.Add64(x11, x20, uint64(0x0))
+       var x35 uint64
+       var x36 uint64
+       x35, x36 = bits.Add64(x13, x26, uint64(p224Uint1(x34)))
+       var x37 uint64
+       var x38 uint64
+       x37, x38 = bits.Add64(x15, x28, uint64(p224Uint1(x36)))
+       var x39 uint64
+       var x40 uint64
+       x39, x40 = bits.Add64(x17, x30, uint64(p224Uint1(x38)))
+       var x41 uint64
+       var x42 uint64
+       x41, x42 = bits.Add64(x19, x32, uint64(p224Uint1(x40)))
+       var x43 uint64
+       var x44 uint64
+       x44, x43 = bits.Mul64(x1, arg2[3])
+       var x45 uint64
+       var x46 uint64
+       x46, x45 = bits.Mul64(x1, arg2[2])
+       var x47 uint64
+       var x48 uint64
+       x48, x47 = bits.Mul64(x1, arg2[1])
+       var x49 uint64
+       var x50 uint64
+       x50, x49 = bits.Mul64(x1, arg2[0])
+       var x51 uint64
+       var x52 uint64
+       x51, x52 = bits.Add64(x50, x47, uint64(0x0))
+       var x53 uint64
+       var x54 uint64
+       x53, x54 = bits.Add64(x48, x45, uint64(p224Uint1(x52)))
+       var x55 uint64
+       var x56 uint64
+       x55, x56 = bits.Add64(x46, x43, uint64(p224Uint1(x54)))
+       x57 := (uint64(p224Uint1(x56)) + x44)
+       var x58 uint64
+       var x59 uint64
+       x58, x59 = bits.Add64(x35, x49, uint64(0x0))
+       var x60 uint64
+       var x61 uint64
+       x60, x61 = bits.Add64(x37, x51, uint64(p224Uint1(x59)))
+       var x62 uint64
+       var x63 uint64
+       x62, x63 = bits.Add64(x39, x53, uint64(p224Uint1(x61)))
+       var x64 uint64
+       var x65 uint64
+       x64, x65 = bits.Add64(x41, x55, uint64(p224Uint1(x63)))
+       var x66 uint64
+       var x67 uint64
+       x66, x67 = bits.Add64(uint64(p224Uint1(x42)), x57, uint64(p224Uint1(x65)))
+       var x68 uint64
+       _, x68 = bits.Mul64(x58, 0xffffffffffffffff)
+       var x70 uint64
+       var x71 uint64
+       x71, x70 = bits.Mul64(x68, 0xffffffff)
+       var x72 uint64
+       var x73 uint64
+       x73, x72 = bits.Mul64(x68, 0xffffffffffffffff)
+       var x74 uint64
+       var x75 uint64
+       x75, x74 = bits.Mul64(x68, 0xffffffff00000000)
+       var x76 uint64
+       var x77 uint64
+       x76, x77 = bits.Add64(x75, x72, uint64(0x0))
+       var x78 uint64
+       var x79 uint64
+       x78, x79 = bits.Add64(x73, x70, uint64(p224Uint1(x77)))
+       x80 := (uint64(p224Uint1(x79)) + x71)
+       var x82 uint64
+       _, x82 = bits.Add64(x58, x68, uint64(0x0))
+       var x83 uint64
+       var x84 uint64
+       x83, x84 = bits.Add64(x60, x74, uint64(p224Uint1(x82)))
+       var x85 uint64
+       var x86 uint64
+       x85, x86 = bits.Add64(x62, x76, uint64(p224Uint1(x84)))
+       var x87 uint64
+       var x88 uint64
+       x87, x88 = bits.Add64(x64, x78, uint64(p224Uint1(x86)))
+       var x89 uint64
+       var x90 uint64
+       x89, x90 = bits.Add64(x66, x80, uint64(p224Uint1(x88)))
+       x91 := (uint64(p224Uint1(x90)) + uint64(p224Uint1(x67)))
+       var x92 uint64
+       var x93 uint64
+       x93, x92 = bits.Mul64(x2, arg2[3])
+       var x94 uint64
+       var x95 uint64
+       x95, x94 = bits.Mul64(x2, arg2[2])
+       var x96 uint64
+       var x97 uint64
+       x97, x96 = bits.Mul64(x2, arg2[1])
+       var x98 uint64
+       var x99 uint64
+       x99, x98 = bits.Mul64(x2, arg2[0])
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x99, x96, uint64(0x0))
+       var x102 uint64
+       var x103 uint64
+       x102, x103 = bits.Add64(x97, x94, uint64(p224Uint1(x101)))
+       var x104 uint64
+       var x105 uint64
+       x104, x105 = bits.Add64(x95, x92, uint64(p224Uint1(x103)))
+       x106 := (uint64(p224Uint1(x105)) + x93)
+       var x107 uint64
+       var x108 uint64
+       x107, x108 = bits.Add64(x83, x98, uint64(0x0))
+       var x109 uint64
+       var x110 uint64
+       x109, x110 = bits.Add64(x85, x100, uint64(p224Uint1(x108)))
+       var x111 uint64
+       var x112 uint64
+       x111, x112 = bits.Add64(x87, x102, uint64(p224Uint1(x110)))
+       var x113 uint64
+       var x114 uint64
+       x113, x114 = bits.Add64(x89, x104, uint64(p224Uint1(x112)))
+       var x115 uint64
+       var x116 uint64
+       x115, x116 = bits.Add64(x91, x106, uint64(p224Uint1(x114)))
+       var x117 uint64
+       _, x117 = bits.Mul64(x107, 0xffffffffffffffff)
+       var x119 uint64
+       var x120 uint64
+       x120, x119 = bits.Mul64(x117, 0xffffffff)
+       var x121 uint64
+       var x122 uint64
+       x122, x121 = bits.Mul64(x117, 0xffffffffffffffff)
+       var x123 uint64
+       var x124 uint64
+       x124, x123 = bits.Mul64(x117, 0xffffffff00000000)
+       var x125 uint64
+       var x126 uint64
+       x125, x126 = bits.Add64(x124, x121, uint64(0x0))
+       var x127 uint64
+       var x128 uint64
+       x127, x128 = bits.Add64(x122, x119, uint64(p224Uint1(x126)))
+       x129 := (uint64(p224Uint1(x128)) + x120)
+       var x131 uint64
+       _, x131 = bits.Add64(x107, x117, uint64(0x0))
+       var x132 uint64
+       var x133 uint64
+       x132, x133 = bits.Add64(x109, x123, uint64(p224Uint1(x131)))
+       var x134 uint64
+       var x135 uint64
+       x134, x135 = bits.Add64(x111, x125, uint64(p224Uint1(x133)))
+       var x136 uint64
+       var x137 uint64
+       x136, x137 = bits.Add64(x113, x127, uint64(p224Uint1(x135)))
+       var x138 uint64
+       var x139 uint64
+       x138, x139 = bits.Add64(x115, x129, uint64(p224Uint1(x137)))
+       x140 := (uint64(p224Uint1(x139)) + uint64(p224Uint1(x116)))
+       var x141 uint64
+       var x142 uint64
+       x142, x141 = bits.Mul64(x3, arg2[3])
+       var x143 uint64
+       var x144 uint64
+       x144, x143 = bits.Mul64(x3, arg2[2])
+       var x145 uint64
+       var x146 uint64
+       x146, x145 = bits.Mul64(x3, arg2[1])
+       var x147 uint64
+       var x148 uint64
+       x148, x147 = bits.Mul64(x3, arg2[0])
+       var x149 uint64
+       var x150 uint64
+       x149, x150 = bits.Add64(x148, x145, uint64(0x0))
+       var x151 uint64
+       var x152 uint64
+       x151, x152 = bits.Add64(x146, x143, uint64(p224Uint1(x150)))
+       var x153 uint64
+       var x154 uint64
+       x153, x154 = bits.Add64(x144, x141, uint64(p224Uint1(x152)))
+       x155 := (uint64(p224Uint1(x154)) + x142)
+       var x156 uint64
+       var x157 uint64
+       x156, x157 = bits.Add64(x132, x147, uint64(0x0))
+       var x158 uint64
+       var x159 uint64
+       x158, x159 = bits.Add64(x134, x149, uint64(p224Uint1(x157)))
+       var x160 uint64
+       var x161 uint64
+       x160, x161 = bits.Add64(x136, x151, uint64(p224Uint1(x159)))
+       var x162 uint64
+       var x163 uint64
+       x162, x163 = bits.Add64(x138, x153, uint64(p224Uint1(x161)))
+       var x164 uint64
+       var x165 uint64
+       x164, x165 = bits.Add64(x140, x155, uint64(p224Uint1(x163)))
+       var x166 uint64
+       _, x166 = bits.Mul64(x156, 0xffffffffffffffff)
+       var x168 uint64
+       var x169 uint64
+       x169, x168 = bits.Mul64(x166, 0xffffffff)
+       var x170 uint64
+       var x171 uint64
+       x171, x170 = bits.Mul64(x166, 0xffffffffffffffff)
+       var x172 uint64
+       var x173 uint64
+       x173, x172 = bits.Mul64(x166, 0xffffffff00000000)
+       var x174 uint64
+       var x175 uint64
+       x174, x175 = bits.Add64(x173, x170, uint64(0x0))
+       var x176 uint64
+       var x177 uint64
+       x176, x177 = bits.Add64(x171, x168, uint64(p224Uint1(x175)))
+       x178 := (uint64(p224Uint1(x177)) + x169)
+       var x180 uint64
+       _, x180 = bits.Add64(x156, x166, uint64(0x0))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x158, x172, uint64(p224Uint1(x180)))
+       var x183 uint64
+       var x184 uint64
+       x183, x184 = bits.Add64(x160, x174, uint64(p224Uint1(x182)))
+       var x185 uint64
+       var x186 uint64
+       x185, x186 = bits.Add64(x162, x176, uint64(p224Uint1(x184)))
+       var x187 uint64
+       var x188 uint64
+       x187, x188 = bits.Add64(x164, x178, uint64(p224Uint1(x186)))
+       x189 := (uint64(p224Uint1(x188)) + uint64(p224Uint1(x165)))
+       var x190 uint64
+       var x191 uint64
+       x190, x191 = bits.Sub64(x181, uint64(0x1), uint64(0x0))
+       var x192 uint64
+       var x193 uint64
+       x192, x193 = bits.Sub64(x183, 0xffffffff00000000, uint64(p224Uint1(x191)))
+       var x194 uint64
+       var x195 uint64
+       x194, x195 = bits.Sub64(x185, 0xffffffffffffffff, uint64(p224Uint1(x193)))
+       var x196 uint64
+       var x197 uint64
+       x196, x197 = bits.Sub64(x187, 0xffffffff, uint64(p224Uint1(x195)))
+       var x199 uint64
+       _, x199 = bits.Sub64(x189, uint64(0x0), uint64(p224Uint1(x197)))
+       var x200 uint64
+       p224CmovznzU64(&x200, p224Uint1(x199), x190, x181)
+       var x201 uint64
+       p224CmovznzU64(&x201, p224Uint1(x199), x192, x183)
+       var x202 uint64
+       p224CmovznzU64(&x202, p224Uint1(x199), x194, x185)
+       var x203 uint64
+       p224CmovznzU64(&x203, p224Uint1(x199), x196, x187)
+       out1[0] = x200
+       out1[1] = x201
+       out1[2] = x202
+       out1[3] = x203
+}
+
+// p224Square squares a field element in the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p224Square(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[0]
+       var x5 uint64
+       var x6 uint64
+       x6, x5 = bits.Mul64(x4, arg1[3])
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x4, arg1[2])
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x4, arg1[1])
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x4, arg1[0])
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Add64(x12, x9, uint64(0x0))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16)))
+       x19 := (uint64(p224Uint1(x18)) + x6)
+       var x20 uint64
+       _, x20 = bits.Mul64(x11, 0xffffffffffffffff)
+       var x22 uint64
+       var x23 uint64
+       x23, x22 = bits.Mul64(x20, 0xffffffff)
+       var x24 uint64
+       var x25 uint64
+       x25, x24 = bits.Mul64(x20, 0xffffffffffffffff)
+       var x26 uint64
+       var x27 uint64
+       x27, x26 = bits.Mul64(x20, 0xffffffff00000000)
+       var x28 uint64
+       var x29 uint64
+       x28, x29 = bits.Add64(x27, x24, uint64(0x0))
+       var x30 uint64
+       var x31 uint64
+       x30, x31 = bits.Add64(x25, x22, uint64(p224Uint1(x29)))
+       x32 := (uint64(p224Uint1(x31)) + x23)
+       var x34 uint64
+       _, x34 = bits.Add64(x11, x20, uint64(0x0))
+       var x35 uint64
+       var x36 uint64
+       x35, x36 = bits.Add64(x13, x26, uint64(p224Uint1(x34)))
+       var x37 uint64
+       var x38 uint64
+       x37, x38 = bits.Add64(x15, x28, uint64(p224Uint1(x36)))
+       var x39 uint64
+       var x40 uint64
+       x39, x40 = bits.Add64(x17, x30, uint64(p224Uint1(x38)))
+       var x41 uint64
+       var x42 uint64
+       x41, x42 = bits.Add64(x19, x32, uint64(p224Uint1(x40)))
+       var x43 uint64
+       var x44 uint64
+       x44, x43 = bits.Mul64(x1, arg1[3])
+       var x45 uint64
+       var x46 uint64
+       x46, x45 = bits.Mul64(x1, arg1[2])
+       var x47 uint64
+       var x48 uint64
+       x48, x47 = bits.Mul64(x1, arg1[1])
+       var x49 uint64
+       var x50 uint64
+       x50, x49 = bits.Mul64(x1, arg1[0])
+       var x51 uint64
+       var x52 uint64
+       x51, x52 = bits.Add64(x50, x47, uint64(0x0))
+       var x53 uint64
+       var x54 uint64
+       x53, x54 = bits.Add64(x48, x45, uint64(p224Uint1(x52)))
+       var x55 uint64
+       var x56 uint64
+       x55, x56 = bits.Add64(x46, x43, uint64(p224Uint1(x54)))
+       x57 := (uint64(p224Uint1(x56)) + x44)
+       var x58 uint64
+       var x59 uint64
+       x58, x59 = bits.Add64(x35, x49, uint64(0x0))
+       var x60 uint64
+       var x61 uint64
+       x60, x61 = bits.Add64(x37, x51, uint64(p224Uint1(x59)))
+       var x62 uint64
+       var x63 uint64
+       x62, x63 = bits.Add64(x39, x53, uint64(p224Uint1(x61)))
+       var x64 uint64
+       var x65 uint64
+       x64, x65 = bits.Add64(x41, x55, uint64(p224Uint1(x63)))
+       var x66 uint64
+       var x67 uint64
+       x66, x67 = bits.Add64(uint64(p224Uint1(x42)), x57, uint64(p224Uint1(x65)))
+       var x68 uint64
+       _, x68 = bits.Mul64(x58, 0xffffffffffffffff)
+       var x70 uint64
+       var x71 uint64
+       x71, x70 = bits.Mul64(x68, 0xffffffff)
+       var x72 uint64
+       var x73 uint64
+       x73, x72 = bits.Mul64(x68, 0xffffffffffffffff)
+       var x74 uint64
+       var x75 uint64
+       x75, x74 = bits.Mul64(x68, 0xffffffff00000000)
+       var x76 uint64
+       var x77 uint64
+       x76, x77 = bits.Add64(x75, x72, uint64(0x0))
+       var x78 uint64
+       var x79 uint64
+       x78, x79 = bits.Add64(x73, x70, uint64(p224Uint1(x77)))
+       x80 := (uint64(p224Uint1(x79)) + x71)
+       var x82 uint64
+       _, x82 = bits.Add64(x58, x68, uint64(0x0))
+       var x83 uint64
+       var x84 uint64
+       x83, x84 = bits.Add64(x60, x74, uint64(p224Uint1(x82)))
+       var x85 uint64
+       var x86 uint64
+       x85, x86 = bits.Add64(x62, x76, uint64(p224Uint1(x84)))
+       var x87 uint64
+       var x88 uint64
+       x87, x88 = bits.Add64(x64, x78, uint64(p224Uint1(x86)))
+       var x89 uint64
+       var x90 uint64
+       x89, x90 = bits.Add64(x66, x80, uint64(p224Uint1(x88)))
+       x91 := (uint64(p224Uint1(x90)) + uint64(p224Uint1(x67)))
+       var x92 uint64
+       var x93 uint64
+       x93, x92 = bits.Mul64(x2, arg1[3])
+       var x94 uint64
+       var x95 uint64
+       x95, x94 = bits.Mul64(x2, arg1[2])
+       var x96 uint64
+       var x97 uint64
+       x97, x96 = bits.Mul64(x2, arg1[1])
+       var x98 uint64
+       var x99 uint64
+       x99, x98 = bits.Mul64(x2, arg1[0])
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x99, x96, uint64(0x0))
+       var x102 uint64
+       var x103 uint64
+       x102, x103 = bits.Add64(x97, x94, uint64(p224Uint1(x101)))
+       var x104 uint64
+       var x105 uint64
+       x104, x105 = bits.Add64(x95, x92, uint64(p224Uint1(x103)))
+       x106 := (uint64(p224Uint1(x105)) + x93)
+       var x107 uint64
+       var x108 uint64
+       x107, x108 = bits.Add64(x83, x98, uint64(0x0))
+       var x109 uint64
+       var x110 uint64
+       x109, x110 = bits.Add64(x85, x100, uint64(p224Uint1(x108)))
+       var x111 uint64
+       var x112 uint64
+       x111, x112 = bits.Add64(x87, x102, uint64(p224Uint1(x110)))
+       var x113 uint64
+       var x114 uint64
+       x113, x114 = bits.Add64(x89, x104, uint64(p224Uint1(x112)))
+       var x115 uint64
+       var x116 uint64
+       x115, x116 = bits.Add64(x91, x106, uint64(p224Uint1(x114)))
+       var x117 uint64
+       _, x117 = bits.Mul64(x107, 0xffffffffffffffff)
+       var x119 uint64
+       var x120 uint64
+       x120, x119 = bits.Mul64(x117, 0xffffffff)
+       var x121 uint64
+       var x122 uint64
+       x122, x121 = bits.Mul64(x117, 0xffffffffffffffff)
+       var x123 uint64
+       var x124 uint64
+       x124, x123 = bits.Mul64(x117, 0xffffffff00000000)
+       var x125 uint64
+       var x126 uint64
+       x125, x126 = bits.Add64(x124, x121, uint64(0x0))
+       var x127 uint64
+       var x128 uint64
+       x127, x128 = bits.Add64(x122, x119, uint64(p224Uint1(x126)))
+       x129 := (uint64(p224Uint1(x128)) + x120)
+       var x131 uint64
+       _, x131 = bits.Add64(x107, x117, uint64(0x0))
+       var x132 uint64
+       var x133 uint64
+       x132, x133 = bits.Add64(x109, x123, uint64(p224Uint1(x131)))
+       var x134 uint64
+       var x135 uint64
+       x134, x135 = bits.Add64(x111, x125, uint64(p224Uint1(x133)))
+       var x136 uint64
+       var x137 uint64
+       x136, x137 = bits.Add64(x113, x127, uint64(p224Uint1(x135)))
+       var x138 uint64
+       var x139 uint64
+       x138, x139 = bits.Add64(x115, x129, uint64(p224Uint1(x137)))
+       x140 := (uint64(p224Uint1(x139)) + uint64(p224Uint1(x116)))
+       var x141 uint64
+       var x142 uint64
+       x142, x141 = bits.Mul64(x3, arg1[3])
+       var x143 uint64
+       var x144 uint64
+       x144, x143 = bits.Mul64(x3, arg1[2])
+       var x145 uint64
+       var x146 uint64
+       x146, x145 = bits.Mul64(x3, arg1[1])
+       var x147 uint64
+       var x148 uint64
+       x148, x147 = bits.Mul64(x3, arg1[0])
+       var x149 uint64
+       var x150 uint64
+       x149, x150 = bits.Add64(x148, x145, uint64(0x0))
+       var x151 uint64
+       var x152 uint64
+       x151, x152 = bits.Add64(x146, x143, uint64(p224Uint1(x150)))
+       var x153 uint64
+       var x154 uint64
+       x153, x154 = bits.Add64(x144, x141, uint64(p224Uint1(x152)))
+       x155 := (uint64(p224Uint1(x154)) + x142)
+       var x156 uint64
+       var x157 uint64
+       x156, x157 = bits.Add64(x132, x147, uint64(0x0))
+       var x158 uint64
+       var x159 uint64
+       x158, x159 = bits.Add64(x134, x149, uint64(p224Uint1(x157)))
+       var x160 uint64
+       var x161 uint64
+       x160, x161 = bits.Add64(x136, x151, uint64(p224Uint1(x159)))
+       var x162 uint64
+       var x163 uint64
+       x162, x163 = bits.Add64(x138, x153, uint64(p224Uint1(x161)))
+       var x164 uint64
+       var x165 uint64
+       x164, x165 = bits.Add64(x140, x155, uint64(p224Uint1(x163)))
+       var x166 uint64
+       _, x166 = bits.Mul64(x156, 0xffffffffffffffff)
+       var x168 uint64
+       var x169 uint64
+       x169, x168 = bits.Mul64(x166, 0xffffffff)
+       var x170 uint64
+       var x171 uint64
+       x171, x170 = bits.Mul64(x166, 0xffffffffffffffff)
+       var x172 uint64
+       var x173 uint64
+       x173, x172 = bits.Mul64(x166, 0xffffffff00000000)
+       var x174 uint64
+       var x175 uint64
+       x174, x175 = bits.Add64(x173, x170, uint64(0x0))
+       var x176 uint64
+       var x177 uint64
+       x176, x177 = bits.Add64(x171, x168, uint64(p224Uint1(x175)))
+       x178 := (uint64(p224Uint1(x177)) + x169)
+       var x180 uint64
+       _, x180 = bits.Add64(x156, x166, uint64(0x0))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x158, x172, uint64(p224Uint1(x180)))
+       var x183 uint64
+       var x184 uint64
+       x183, x184 = bits.Add64(x160, x174, uint64(p224Uint1(x182)))
+       var x185 uint64
+       var x186 uint64
+       x185, x186 = bits.Add64(x162, x176, uint64(p224Uint1(x184)))
+       var x187 uint64
+       var x188 uint64
+       x187, x188 = bits.Add64(x164, x178, uint64(p224Uint1(x186)))
+       x189 := (uint64(p224Uint1(x188)) + uint64(p224Uint1(x165)))
+       var x190 uint64
+       var x191 uint64
+       x190, x191 = bits.Sub64(x181, uint64(0x1), uint64(0x0))
+       var x192 uint64
+       var x193 uint64
+       x192, x193 = bits.Sub64(x183, 0xffffffff00000000, uint64(p224Uint1(x191)))
+       var x194 uint64
+       var x195 uint64
+       x194, x195 = bits.Sub64(x185, 0xffffffffffffffff, uint64(p224Uint1(x193)))
+       var x196 uint64
+       var x197 uint64
+       x196, x197 = bits.Sub64(x187, 0xffffffff, uint64(p224Uint1(x195)))
+       var x199 uint64
+       _, x199 = bits.Sub64(x189, uint64(0x0), uint64(p224Uint1(x197)))
+       var x200 uint64
+       p224CmovznzU64(&x200, p224Uint1(x199), x190, x181)
+       var x201 uint64
+       p224CmovznzU64(&x201, p224Uint1(x199), x192, x183)
+       var x202 uint64
+       p224CmovznzU64(&x202, p224Uint1(x199), x194, x185)
+       var x203 uint64
+       p224CmovznzU64(&x203, p224Uint1(x199), x196, x187)
+       out1[0] = x200
+       out1[1] = x201
+       out1[2] = x202
+       out1[3] = x203
+}
+
+// p224Add adds two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+//   0 โ‰ค eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p224Add(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p224Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p224Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p224Uint1(x6)))
+       var x9 uint64
+       var x10 uint64
+       x9, x10 = bits.Sub64(x1, uint64(0x1), uint64(0x0))
+       var x11 uint64
+       var x12 uint64
+       x11, x12 = bits.Sub64(x3, 0xffffffff00000000, uint64(p224Uint1(x10)))
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Sub64(x5, 0xffffffffffffffff, uint64(p224Uint1(x12)))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Sub64(x7, 0xffffffff, uint64(p224Uint1(x14)))
+       var x18 uint64
+       _, x18 = bits.Sub64(uint64(p224Uint1(x8)), uint64(0x0), uint64(p224Uint1(x16)))
+       var x19 uint64
+       p224CmovznzU64(&x19, p224Uint1(x18), x9, x1)
+       var x20 uint64
+       p224CmovznzU64(&x20, p224Uint1(x18), x11, x3)
+       var x21 uint64
+       p224CmovznzU64(&x21, p224Uint1(x18), x13, x5)
+       var x22 uint64
+       p224CmovznzU64(&x22, p224Uint1(x18), x15, x7)
+       out1[0] = x19
+       out1[1] = x20
+       out1[2] = x21
+       out1[3] = x22
+}
+
+// p224Sub subtracts two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+//   0 โ‰ค eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p224Sub(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p224Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p224Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p224Uint1(x6)))
+       var x9 uint64
+       p224CmovznzU64(&x9, p224Uint1(x8), uint64(0x0), 0xffffffffffffffff)
+       var x10 uint64
+       var x11 uint64
+       x10, x11 = bits.Add64(x1, uint64((p224Uint1(x9) & 0x1)), uint64(0x0))
+       var x12 uint64
+       var x13 uint64
+       x12, x13 = bits.Add64(x3, (x9 & 0xffffffff00000000), uint64(p224Uint1(x11)))
+       var x14 uint64
+       var x15 uint64
+       x14, x15 = bits.Add64(x5, x9, uint64(p224Uint1(x13)))
+       var x16 uint64
+       x16, _ = bits.Add64(x7, (x9 & 0xffffffff), uint64(p224Uint1(x15)))
+       out1[0] = x10
+       out1[1] = x12
+       out1[2] = x14
+       out1[3] = x16
+}
+
+// p224SetOne returns the field element one in the Montgomery domain.
+//
+// Postconditions:
+//   eval (from_montgomery out1) mod m = 1 mod m
+//   0 โ‰ค eval out1 < m
+//
+func p224SetOne(out1 *p224MontgomeryDomainFieldElement) {
+       out1[0] = 0xffffffff00000000
+       out1[1] = 0xffffffffffffffff
+       out1[2] = uint64(0x0)
+       out1[3] = uint64(0x0)
+}
+
+// p224FromMontgomery translates a field element out of the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+// Postconditions:
+//   eval out1 mod m = (eval arg1 * ((2^64)โปยน mod m)^4) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p224FromMontgomery(out1 *p224NonMontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement) {
+       x1 := arg1[0]
+       var x2 uint64
+       _, x2 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x4 uint64
+       var x5 uint64
+       x5, x4 = bits.Mul64(x2, 0xffffffff)
+       var x6 uint64
+       var x7 uint64
+       x7, x6 = bits.Mul64(x2, 0xffffffffffffffff)
+       var x8 uint64
+       var x9 uint64
+       x9, x8 = bits.Mul64(x2, 0xffffffff00000000)
+       var x10 uint64
+       var x11 uint64
+       x10, x11 = bits.Add64(x9, x6, uint64(0x0))
+       var x12 uint64
+       var x13 uint64
+       x12, x13 = bits.Add64(x7, x4, uint64(p224Uint1(x11)))
+       var x15 uint64
+       _, x15 = bits.Add64(x1, x2, uint64(0x0))
+       var x16 uint64
+       var x17 uint64
+       x16, x17 = bits.Add64(uint64(0x0), x8, uint64(p224Uint1(x15)))
+       var x18 uint64
+       var x19 uint64
+       x18, x19 = bits.Add64(uint64(0x0), x10, uint64(p224Uint1(x17)))
+       var x20 uint64
+       var x21 uint64
+       x20, x21 = bits.Add64(uint64(0x0), x12, uint64(p224Uint1(x19)))
+       var x22 uint64
+       var x23 uint64
+       x22, x23 = bits.Add64(x16, arg1[1], uint64(0x0))
+       var x24 uint64
+       var x25 uint64
+       x24, x25 = bits.Add64(x18, uint64(0x0), uint64(p224Uint1(x23)))
+       var x26 uint64
+       var x27 uint64
+       x26, x27 = bits.Add64(x20, uint64(0x0), uint64(p224Uint1(x25)))
+       var x28 uint64
+       _, x28 = bits.Mul64(x22, 0xffffffffffffffff)
+       var x30 uint64
+       var x31 uint64
+       x31, x30 = bits.Mul64(x28, 0xffffffff)
+       var x32 uint64
+       var x33 uint64
+       x33, x32 = bits.Mul64(x28, 0xffffffffffffffff)
+       var x34 uint64
+       var x35 uint64
+       x35, x34 = bits.Mul64(x28, 0xffffffff00000000)
+       var x36 uint64
+       var x37 uint64
+       x36, x37 = bits.Add64(x35, x32, uint64(0x0))
+       var x38 uint64
+       var x39 uint64
+       x38, x39 = bits.Add64(x33, x30, uint64(p224Uint1(x37)))
+       var x41 uint64
+       _, x41 = bits.Add64(x22, x28, uint64(0x0))
+       var x42 uint64
+       var x43 uint64
+       x42, x43 = bits.Add64(x24, x34, uint64(p224Uint1(x41)))
+       var x44 uint64
+       var x45 uint64
+       x44, x45 = bits.Add64(x26, x36, uint64(p224Uint1(x43)))
+       var x46 uint64
+       var x47 uint64
+       x46, x47 = bits.Add64((uint64(p224Uint1(x27)) + (uint64(p224Uint1(x21)) + (uint64(p224Uint1(x13)) + x5))), x38, uint64(p224Uint1(x45)))
+       var x48 uint64
+       var x49 uint64
+       x48, x49 = bits.Add64(x42, arg1[2], uint64(0x0))
+       var x50 uint64
+       var x51 uint64
+       x50, x51 = bits.Add64(x44, uint64(0x0), uint64(p224Uint1(x49)))
+       var x52 uint64
+       var x53 uint64
+       x52, x53 = bits.Add64(x46, uint64(0x0), uint64(p224Uint1(x51)))
+       var x54 uint64
+       _, x54 = bits.Mul64(x48, 0xffffffffffffffff)
+       var x56 uint64
+       var x57 uint64
+       x57, x56 = bits.Mul64(x54, 0xffffffff)
+       var x58 uint64
+       var x59 uint64
+       x59, x58 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x60 uint64
+       var x61 uint64
+       x61, x60 = bits.Mul64(x54, 0xffffffff00000000)
+       var x62 uint64
+       var x63 uint64
+       x62, x63 = bits.Add64(x61, x58, uint64(0x0))
+       var x64 uint64
+       var x65 uint64
+       x64, x65 = bits.Add64(x59, x56, uint64(p224Uint1(x63)))
+       var x67 uint64
+       _, x67 = bits.Add64(x48, x54, uint64(0x0))
+       var x68 uint64
+       var x69 uint64
+       x68, x69 = bits.Add64(x50, x60, uint64(p224Uint1(x67)))
+       var x70 uint64
+       var x71 uint64
+       x70, x71 = bits.Add64(x52, x62, uint64(p224Uint1(x69)))
+       var x72 uint64
+       var x73 uint64
+       x72, x73 = bits.Add64((uint64(p224Uint1(x53)) + (uint64(p224Uint1(x47)) + (uint64(p224Uint1(x39)) + x31))), x64, uint64(p224Uint1(x71)))
+       var x74 uint64
+       var x75 uint64
+       x74, x75 = bits.Add64(x68, arg1[3], uint64(0x0))
+       var x76 uint64
+       var x77 uint64
+       x76, x77 = bits.Add64(x70, uint64(0x0), uint64(p224Uint1(x75)))
+       var x78 uint64
+       var x79 uint64
+       x78, x79 = bits.Add64(x72, uint64(0x0), uint64(p224Uint1(x77)))
+       var x80 uint64
+       _, x80 = bits.Mul64(x74, 0xffffffffffffffff)
+       var x82 uint64
+       var x83 uint64
+       x83, x82 = bits.Mul64(x80, 0xffffffff)
+       var x84 uint64
+       var x85 uint64
+       x85, x84 = bits.Mul64(x80, 0xffffffffffffffff)
+       var x86 uint64
+       var x87 uint64
+       x87, x86 = bits.Mul64(x80, 0xffffffff00000000)
+       var x88 uint64
+       var x89 uint64
+       x88, x89 = bits.Add64(x87, x84, uint64(0x0))
+       var x90 uint64
+       var x91 uint64
+       x90, x91 = bits.Add64(x85, x82, uint64(p224Uint1(x89)))
+       var x93 uint64
+       _, x93 = bits.Add64(x74, x80, uint64(0x0))
+       var x94 uint64
+       var x95 uint64
+       x94, x95 = bits.Add64(x76, x86, uint64(p224Uint1(x93)))
+       var x96 uint64
+       var x97 uint64
+       x96, x97 = bits.Add64(x78, x88, uint64(p224Uint1(x95)))
+       var x98 uint64
+       var x99 uint64
+       x98, x99 = bits.Add64((uint64(p224Uint1(x79)) + (uint64(p224Uint1(x73)) + (uint64(p224Uint1(x65)) + x57))), x90, uint64(p224Uint1(x97)))
+       x100 := (uint64(p224Uint1(x99)) + (uint64(p224Uint1(x91)) + x83))
+       var x101 uint64
+       var x102 uint64
+       x101, x102 = bits.Sub64(x94, uint64(0x1), uint64(0x0))
+       var x103 uint64
+       var x104 uint64
+       x103, x104 = bits.Sub64(x96, 0xffffffff00000000, uint64(p224Uint1(x102)))
+       var x105 uint64
+       var x106 uint64
+       x105, x106 = bits.Sub64(x98, 0xffffffffffffffff, uint64(p224Uint1(x104)))
+       var x107 uint64
+       var x108 uint64
+       x107, x108 = bits.Sub64(x100, 0xffffffff, uint64(p224Uint1(x106)))
+       var x110 uint64
+       _, x110 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p224Uint1(x108)))
+       var x111 uint64
+       p224CmovznzU64(&x111, p224Uint1(x110), x101, x94)
+       var x112 uint64
+       p224CmovznzU64(&x112, p224Uint1(x110), x103, x96)
+       var x113 uint64
+       p224CmovznzU64(&x113, p224Uint1(x110), x105, x98)
+       var x114 uint64
+       p224CmovznzU64(&x114, p224Uint1(x110), x107, x100)
+       out1[0] = x111
+       out1[1] = x112
+       out1[2] = x113
+       out1[3] = x114
+}
+
+// p224ToMontgomery translates a field element into the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = eval arg1 mod m
+//   0 โ‰ค eval out1 < m
+//
+func p224ToMontgomery(out1 *p224MontgomeryDomainFieldElement, arg1 *p224NonMontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[0]
+       var x5 uint64
+       var x6 uint64
+       x6, x5 = bits.Mul64(x4, 0xffffffff)
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x4, 0xfffffffe00000000)
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x4, 0xffffffff00000000)
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x4, 0xffffffff00000001)
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Add64(x12, x9, uint64(0x0))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16)))
+       var x19 uint64
+       _, x19 = bits.Mul64(x11, 0xffffffffffffffff)
+       var x21 uint64
+       var x22 uint64
+       x22, x21 = bits.Mul64(x19, 0xffffffff)
+       var x23 uint64
+       var x24 uint64
+       x24, x23 = bits.Mul64(x19, 0xffffffffffffffff)
+       var x25 uint64
+       var x26 uint64
+       x26, x25 = bits.Mul64(x19, 0xffffffff00000000)
+       var x27 uint64
+       var x28 uint64
+       x27, x28 = bits.Add64(x26, x23, uint64(0x0))
+       var x29 uint64
+       var x30 uint64
+       x29, x30 = bits.Add64(x24, x21, uint64(p224Uint1(x28)))
+       var x32 uint64
+       _, x32 = bits.Add64(x11, x19, uint64(0x0))
+       var x33 uint64
+       var x34 uint64
+       x33, x34 = bits.Add64(x13, x25, uint64(p224Uint1(x32)))
+       var x35 uint64
+       var x36 uint64
+       x35, x36 = bits.Add64(x15, x27, uint64(p224Uint1(x34)))
+       var x37 uint64
+       var x38 uint64
+       x37, x38 = bits.Add64(x17, x29, uint64(p224Uint1(x36)))
+       var x39 uint64
+       var x40 uint64
+       x40, x39 = bits.Mul64(x1, 0xffffffff)
+       var x41 uint64
+       var x42 uint64
+       x42, x41 = bits.Mul64(x1, 0xfffffffe00000000)
+       var x43 uint64
+       var x44 uint64
+       x44, x43 = bits.Mul64(x1, 0xffffffff00000000)
+       var x45 uint64
+       var x46 uint64
+       x46, x45 = bits.Mul64(x1, 0xffffffff00000001)
+       var x47 uint64
+       var x48 uint64
+       x47, x48 = bits.Add64(x46, x43, uint64(0x0))
+       var x49 uint64
+       var x50 uint64
+       x49, x50 = bits.Add64(x44, x41, uint64(p224Uint1(x48)))
+       var x51 uint64
+       var x52 uint64
+       x51, x52 = bits.Add64(x42, x39, uint64(p224Uint1(x50)))
+       var x53 uint64
+       var x54 uint64
+       x53, x54 = bits.Add64(x33, x45, uint64(0x0))
+       var x55 uint64
+       var x56 uint64
+       x55, x56 = bits.Add64(x35, x47, uint64(p224Uint1(x54)))
+       var x57 uint64
+       var x58 uint64
+       x57, x58 = bits.Add64(x37, x49, uint64(p224Uint1(x56)))
+       var x59 uint64
+       var x60 uint64
+       x59, x60 = bits.Add64(((uint64(p224Uint1(x38)) + (uint64(p224Uint1(x18)) + x6)) + (uint64(p224Uint1(x30)) + x22)), x51, uint64(p224Uint1(x58)))
+       var x61 uint64
+       _, x61 = bits.Mul64(x53, 0xffffffffffffffff)
+       var x63 uint64
+       var x64 uint64
+       x64, x63 = bits.Mul64(x61, 0xffffffff)
+       var x65 uint64
+       var x66 uint64
+       x66, x65 = bits.Mul64(x61, 0xffffffffffffffff)
+       var x67 uint64
+       var x68 uint64
+       x68, x67 = bits.Mul64(x61, 0xffffffff00000000)
+       var x69 uint64
+       var x70 uint64
+       x69, x70 = bits.Add64(x68, x65, uint64(0x0))
+       var x71 uint64
+       var x72 uint64
+       x71, x72 = bits.Add64(x66, x63, uint64(p224Uint1(x70)))
+       var x74 uint64
+       _, x74 = bits.Add64(x53, x61, uint64(0x0))
+       var x75 uint64
+       var x76 uint64
+       x75, x76 = bits.Add64(x55, x67, uint64(p224Uint1(x74)))
+       var x77 uint64
+       var x78 uint64
+       x77, x78 = bits.Add64(x57, x69, uint64(p224Uint1(x76)))
+       var x79 uint64
+       var x80 uint64
+       x79, x80 = bits.Add64(x59, x71, uint64(p224Uint1(x78)))
+       var x81 uint64
+       var x82 uint64
+       x82, x81 = bits.Mul64(x2, 0xffffffff)
+       var x83 uint64
+       var x84 uint64
+       x84, x83 = bits.Mul64(x2, 0xfffffffe00000000)
+       var x85 uint64
+       var x86 uint64
+       x86, x85 = bits.Mul64(x2, 0xffffffff00000000)
+       var x87 uint64
+       var x88 uint64
+       x88, x87 = bits.Mul64(x2, 0xffffffff00000001)
+       var x89 uint64
+       var x90 uint64
+       x89, x90 = bits.Add64(x88, x85, uint64(0x0))
+       var x91 uint64
+       var x92 uint64
+       x91, x92 = bits.Add64(x86, x83, uint64(p224Uint1(x90)))
+       var x93 uint64
+       var x94 uint64
+       x93, x94 = bits.Add64(x84, x81, uint64(p224Uint1(x92)))
+       var x95 uint64
+       var x96 uint64
+       x95, x96 = bits.Add64(x75, x87, uint64(0x0))
+       var x97 uint64
+       var x98 uint64
+       x97, x98 = bits.Add64(x77, x89, uint64(p224Uint1(x96)))
+       var x99 uint64
+       var x100 uint64
+       x99, x100 = bits.Add64(x79, x91, uint64(p224Uint1(x98)))
+       var x101 uint64
+       var x102 uint64
+       x101, x102 = bits.Add64(((uint64(p224Uint1(x80)) + (uint64(p224Uint1(x60)) + (uint64(p224Uint1(x52)) + x40))) + (uint64(p224Uint1(x72)) + x64)), x93, uint64(p224Uint1(x100)))
+       var x103 uint64
+       _, x103 = bits.Mul64(x95, 0xffffffffffffffff)
+       var x105 uint64
+       var x106 uint64
+       x106, x105 = bits.Mul64(x103, 0xffffffff)
+       var x107 uint64
+       var x108 uint64
+       x108, x107 = bits.Mul64(x103, 0xffffffffffffffff)
+       var x109 uint64
+       var x110 uint64
+       x110, x109 = bits.Mul64(x103, 0xffffffff00000000)
+       var x111 uint64
+       var x112 uint64
+       x111, x112 = bits.Add64(x110, x107, uint64(0x0))
+       var x113 uint64
+       var x114 uint64
+       x113, x114 = bits.Add64(x108, x105, uint64(p224Uint1(x112)))
+       var x116 uint64
+       _, x116 = bits.Add64(x95, x103, uint64(0x0))
+       var x117 uint64
+       var x118 uint64
+       x117, x118 = bits.Add64(x97, x109, uint64(p224Uint1(x116)))
+       var x119 uint64
+       var x120 uint64
+       x119, x120 = bits.Add64(x99, x111, uint64(p224Uint1(x118)))
+       var x121 uint64
+       var x122 uint64
+       x121, x122 = bits.Add64(x101, x113, uint64(p224Uint1(x120)))
+       var x123 uint64
+       var x124 uint64
+       x124, x123 = bits.Mul64(x3, 0xffffffff)
+       var x125 uint64
+       var x126 uint64
+       x126, x125 = bits.Mul64(x3, 0xfffffffe00000000)
+       var x127 uint64
+       var x128 uint64
+       x128, x127 = bits.Mul64(x3, 0xffffffff00000000)
+       var x129 uint64
+       var x130 uint64
+       x130, x129 = bits.Mul64(x3, 0xffffffff00000001)
+       var x131 uint64
+       var x132 uint64
+       x131, x132 = bits.Add64(x130, x127, uint64(0x0))
+       var x133 uint64
+       var x134 uint64
+       x133, x134 = bits.Add64(x128, x125, uint64(p224Uint1(x132)))
+       var x135 uint64
+       var x136 uint64
+       x135, x136 = bits.Add64(x126, x123, uint64(p224Uint1(x134)))
+       var x137 uint64
+       var x138 uint64
+       x137, x138 = bits.Add64(x117, x129, uint64(0x0))
+       var x139 uint64
+       var x140 uint64
+       x139, x140 = bits.Add64(x119, x131, uint64(p224Uint1(x138)))
+       var x141 uint64
+       var x142 uint64
+       x141, x142 = bits.Add64(x121, x133, uint64(p224Uint1(x140)))
+       var x143 uint64
+       var x144 uint64
+       x143, x144 = bits.Add64(((uint64(p224Uint1(x122)) + (uint64(p224Uint1(x102)) + (uint64(p224Uint1(x94)) + x82))) + (uint64(p224Uint1(x114)) + x106)), x135, uint64(p224Uint1(x142)))
+       var x145 uint64
+       _, x145 = bits.Mul64(x137, 0xffffffffffffffff)
+       var x147 uint64
+       var x148 uint64
+       x148, x147 = bits.Mul64(x145, 0xffffffff)
+       var x149 uint64
+       var x150 uint64
+       x150, x149 = bits.Mul64(x145, 0xffffffffffffffff)
+       var x151 uint64
+       var x152 uint64
+       x152, x151 = bits.Mul64(x145, 0xffffffff00000000)
+       var x153 uint64
+       var x154 uint64
+       x153, x154 = bits.Add64(x152, x149, uint64(0x0))
+       var x155 uint64
+       var x156 uint64
+       x155, x156 = bits.Add64(x150, x147, uint64(p224Uint1(x154)))
+       var x158 uint64
+       _, x158 = bits.Add64(x137, x145, uint64(0x0))
+       var x159 uint64
+       var x160 uint64
+       x159, x160 = bits.Add64(x139, x151, uint64(p224Uint1(x158)))
+       var x161 uint64
+       var x162 uint64
+       x161, x162 = bits.Add64(x141, x153, uint64(p224Uint1(x160)))
+       var x163 uint64
+       var x164 uint64
+       x163, x164 = bits.Add64(x143, x155, uint64(p224Uint1(x162)))
+       x165 := ((uint64(p224Uint1(x164)) + (uint64(p224Uint1(x144)) + (uint64(p224Uint1(x136)) + x124))) + (uint64(p224Uint1(x156)) + x148))
+       var x166 uint64
+       var x167 uint64
+       x166, x167 = bits.Sub64(x159, uint64(0x1), uint64(0x0))
+       var x168 uint64
+       var x169 uint64
+       x168, x169 = bits.Sub64(x161, 0xffffffff00000000, uint64(p224Uint1(x167)))
+       var x170 uint64
+       var x171 uint64
+       x170, x171 = bits.Sub64(x163, 0xffffffffffffffff, uint64(p224Uint1(x169)))
+       var x172 uint64
+       var x173 uint64
+       x172, x173 = bits.Sub64(x165, 0xffffffff, uint64(p224Uint1(x171)))
+       var x175 uint64
+       _, x175 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p224Uint1(x173)))
+       var x176 uint64
+       p224CmovznzU64(&x176, p224Uint1(x175), x166, x159)
+       var x177 uint64
+       p224CmovznzU64(&x177, p224Uint1(x175), x168, x161)
+       var x178 uint64
+       p224CmovznzU64(&x178, p224Uint1(x175), x170, x163)
+       var x179 uint64
+       p224CmovznzU64(&x179, p224Uint1(x175), x172, x165)
+       out1[0] = x176
+       out1[1] = x177
+       out1[2] = x178
+       out1[3] = x179
+}
+
+// p224Selectznz is a multi-limb conditional select.
+//
+// Postconditions:
+//   eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+//   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+func p224Selectznz(out1 *[4]uint64, arg1 p224Uint1, arg2 *[4]uint64, arg3 *[4]uint64) {
+       var x1 uint64
+       p224CmovznzU64(&x1, arg1, arg2[0], arg3[0])
+       var x2 uint64
+       p224CmovznzU64(&x2, arg1, arg2[1], arg3[1])
+       var x3 uint64
+       p224CmovznzU64(&x3, arg1, arg2[2], arg3[2])
+       var x4 uint64
+       p224CmovznzU64(&x4, arg1, arg2[3], arg3[3])
+       out1[0] = x1
+       out1[1] = x2
+       out1[2] = x3
+       out1[3] = x4
+}
+
+// p224ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+// Postconditions:
+//   out1 = map (ฮป x, โŒŠ((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)โŒ‹) [0..27]
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+func p224ToBytes(out1 *[28]uint8, arg1 *[4]uint64) {
+       x1 := arg1[3]
+       x2 := arg1[2]
+       x3 := arg1[1]
+       x4 := arg1[0]
+       x5 := (uint8(x4) & 0xff)
+       x6 := (x4 >> 8)
+       x7 := (uint8(x6) & 0xff)
+       x8 := (x6 >> 8)
+       x9 := (uint8(x8) & 0xff)
+       x10 := (x8 >> 8)
+       x11 := (uint8(x10) & 0xff)
+       x12 := (x10 >> 8)
+       x13 := (uint8(x12) & 0xff)
+       x14 := (x12 >> 8)
+       x15 := (uint8(x14) & 0xff)
+       x16 := (x14 >> 8)
+       x17 := (uint8(x16) & 0xff)
+       x18 := uint8((x16 >> 8))
+       x19 := (uint8(x3) & 0xff)
+       x20 := (x3 >> 8)
+       x21 := (uint8(x20) & 0xff)
+       x22 := (x20 >> 8)
+       x23 := (uint8(x22) & 0xff)
+       x24 := (x22 >> 8)
+       x25 := (uint8(x24) & 0xff)
+       x26 := (x24 >> 8)
+       x27 := (uint8(x26) & 0xff)
+       x28 := (x26 >> 8)
+       x29 := (uint8(x28) & 0xff)
+       x30 := (x28 >> 8)
+       x31 := (uint8(x30) & 0xff)
+       x32 := uint8((x30 >> 8))
+       x33 := (uint8(x2) & 0xff)
+       x34 := (x2 >> 8)
+       x35 := (uint8(x34) & 0xff)
+       x36 := (x34 >> 8)
+       x37 := (uint8(x36) & 0xff)
+       x38 := (x36 >> 8)
+       x39 := (uint8(x38) & 0xff)
+       x40 := (x38 >> 8)
+       x41 := (uint8(x40) & 0xff)
+       x42 := (x40 >> 8)
+       x43 := (uint8(x42) & 0xff)
+       x44 := (x42 >> 8)
+       x45 := (uint8(x44) & 0xff)
+       x46 := uint8((x44 >> 8))
+       x47 := (uint8(x1) & 0xff)
+       x48 := (x1 >> 8)
+       x49 := (uint8(x48) & 0xff)
+       x50 := (x48 >> 8)
+       x51 := (uint8(x50) & 0xff)
+       x52 := uint8((x50 >> 8))
+       out1[0] = x5
+       out1[1] = x7
+       out1[2] = x9
+       out1[3] = x11
+       out1[4] = x13
+       out1[5] = x15
+       out1[6] = x17
+       out1[7] = x18
+       out1[8] = x19
+       out1[9] = x21
+       out1[10] = x23
+       out1[11] = x25
+       out1[12] = x27
+       out1[13] = x29
+       out1[14] = x31
+       out1[15] = x32
+       out1[16] = x33
+       out1[17] = x35
+       out1[18] = x37
+       out1[19] = x39
+       out1[20] = x41
+       out1[21] = x43
+       out1[22] = x45
+       out1[23] = x46
+       out1[24] = x47
+       out1[25] = x49
+       out1[26] = x51
+       out1[27] = x52
+}
+
+// p224FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order.
+//
+// Preconditions:
+//   0 โ‰ค bytes_eval arg1 < m
+// Postconditions:
+//   eval out1 mod m = bytes_eval arg1 mod m
+//   0 โ‰ค eval out1 < m
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffff]]
+func p224FromBytes(out1 *[4]uint64, arg1 *[28]uint8) {
+       x1 := (uint64(arg1[27]) << 24)
+       x2 := (uint64(arg1[26]) << 16)
+       x3 := (uint64(arg1[25]) << 8)
+       x4 := arg1[24]
+       x5 := (uint64(arg1[23]) << 56)
+       x6 := (uint64(arg1[22]) << 48)
+       x7 := (uint64(arg1[21]) << 40)
+       x8 := (uint64(arg1[20]) << 32)
+       x9 := (uint64(arg1[19]) << 24)
+       x10 := (uint64(arg1[18]) << 16)
+       x11 := (uint64(arg1[17]) << 8)
+       x12 := arg1[16]
+       x13 := (uint64(arg1[15]) << 56)
+       x14 := (uint64(arg1[14]) << 48)
+       x15 := (uint64(arg1[13]) << 40)
+       x16 := (uint64(arg1[12]) << 32)
+       x17 := (uint64(arg1[11]) << 24)
+       x18 := (uint64(arg1[10]) << 16)
+       x19 := (uint64(arg1[9]) << 8)
+       x20 := arg1[8]
+       x21 := (uint64(arg1[7]) << 56)
+       x22 := (uint64(arg1[6]) << 48)
+       x23 := (uint64(arg1[5]) << 40)
+       x24 := (uint64(arg1[4]) << 32)
+       x25 := (uint64(arg1[3]) << 24)
+       x26 := (uint64(arg1[2]) << 16)
+       x27 := (uint64(arg1[1]) << 8)
+       x28 := arg1[0]
+       x29 := (x27 + uint64(x28))
+       x30 := (x26 + x29)
+       x31 := (x25 + x30)
+       x32 := (x24 + x31)
+       x33 := (x23 + x32)
+       x34 := (x22 + x33)
+       x35 := (x21 + x34)
+       x36 := (x19 + uint64(x20))
+       x37 := (x18 + x36)
+       x38 := (x17 + x37)
+       x39 := (x16 + x38)
+       x40 := (x15 + x39)
+       x41 := (x14 + x40)
+       x42 := (x13 + x41)
+       x43 := (x11 + uint64(x12))
+       x44 := (x10 + x43)
+       x45 := (x9 + x44)
+       x46 := (x8 + x45)
+       x47 := (x7 + x46)
+       x48 := (x6 + x47)
+       x49 := (x5 + x48)
+       x50 := (x3 + uint64(x4))
+       x51 := (x2 + x50)
+       x52 := (x1 + x51)
+       out1[0] = x35
+       out1[1] = x42
+       out1[2] = x49
+       out1[3] = x52
+}
diff --git a/src/crypto/elliptic/internal/fiat/p224_invert.go b/src/crypto/elliptic/internal/fiat/p224_invert.go
new file mode 100644 (file)
index 0000000..4163ed0
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by addchain. DO NOT EDIT.
+
+package fiat
+
+// Invert sets e = 1/x, and returns e.
+//
+// If x == 0, Invert returns e = 0.
+func (e *P224Element) Invert(x *P224Element) *P224Element {
+       // Inversion is implemented as exponentiation with exponent p โˆ’ 2.
+       // The sequence of 11 multiplications and 223 squarings is derived from the
+       // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0.
+       //
+       //      _10     = 2*1
+       //      _11     = 1 + _10
+       //      _110    = 2*_11
+       //      _111    = 1 + _110
+       //      _111000 = _111 << 3
+       //      _111111 = _111 + _111000
+       //      x12     = _111111 << 6 + _111111
+       //      x14     = x12 << 2 + _11
+       //      x17     = x14 << 3 + _111
+       //      x31     = x17 << 14 + x14
+       //      x48     = x31 << 17 + x17
+       //      x96     = x48 << 48 + x48
+       //      x127    = x96 << 31 + x31
+       //      return    x127 << 97 + x96
+       //
+
+       var z = new(P224Element).Set(e)
+       var t0 = new(P224Element)
+       var t1 = new(P224Element)
+       var t2 = new(P224Element)
+
+       z.Square(x)
+       t0.Mul(x, z)
+       z.Square(t0)
+       z.Mul(x, z)
+       t1.Square(z)
+       for s := 1; s < 3; s++ {
+               t1.Square(t1)
+       }
+       t1.Mul(z, t1)
+       t2.Square(t1)
+       for s := 1; s < 6; s++ {
+               t2.Square(t2)
+       }
+       t1.Mul(t1, t2)
+       for s := 0; s < 2; s++ {
+               t1.Square(t1)
+       }
+       t0.Mul(t0, t1)
+       t1.Square(t0)
+       for s := 1; s < 3; s++ {
+               t1.Square(t1)
+       }
+       z.Mul(z, t1)
+       t1.Square(z)
+       for s := 1; s < 14; s++ {
+               t1.Square(t1)
+       }
+       t0.Mul(t0, t1)
+       t1.Square(t0)
+       for s := 1; s < 17; s++ {
+               t1.Square(t1)
+       }
+       z.Mul(z, t1)
+       t1.Square(z)
+       for s := 1; s < 48; s++ {
+               t1.Square(t1)
+       }
+       z.Mul(z, t1)
+       t1.Square(z)
+       for s := 1; s < 31; s++ {
+               t1.Square(t1)
+       }
+       t0.Mul(t0, t1)
+       for s := 0; s < 97; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+
+       return e.Set(z)
+}
diff --git a/src/crypto/elliptic/internal/fiat/p384.go b/src/crypto/elliptic/internal/fiat/p384.go
new file mode 100644 (file)
index 0000000..5474d77
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by generate.go. DO NOT EDIT.
+
+package fiat
+
+import (
+       "crypto/subtle"
+       "errors"
+)
+
+// P384Element is an integer modulo 2^384 - 2^128 - 2^96 + 2^32 - 1.
+//
+// The zero value is a valid zero element.
+type P384Element struct {
+       // Values are represented internally always in the Montgomery domain, and
+       // converted in Bytes and SetBytes.
+       x p384MontgomeryDomainFieldElement
+}
+
+const p384ElementLen = 48
+
+type p384UntypedFieldElement = [6]uint64
+
+// One sets e = 1, and returns e.
+func (e *P384Element) One() *P384Element {
+       p384SetOne(&e.x)
+       return e
+}
+
+// Equal returns 1 if e == t, and zero otherwise.
+func (e *P384Element) Equal(t *P384Element) int {
+       eBytes := e.Bytes()
+       tBytes := t.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, tBytes)
+}
+
+var p384ZeroEncoding = new(P384Element).Bytes()
+
+// IsZero returns 1 if e == 0, and zero otherwise.
+func (e *P384Element) IsZero() int {
+       eBytes := e.Bytes()
+       return subtle.ConstantTimeCompare(eBytes, p384ZeroEncoding)
+}
+
+// Set sets e = t, and returns e.
+func (e *P384Element) Set(t *P384Element) *P384Element {
+       e.x = t.x
+       return e
+}
+
+// Bytes returns the 48-byte big-endian encoding of e.
+func (e *P384Element) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [p384ElementLen]byte
+       return e.bytes(&out)
+}
+
+func (e *P384Element) bytes(out *[p384ElementLen]byte) []byte {
+       var tmp p384NonMontgomeryDomainFieldElement
+       p384FromMontgomery(&tmp, &e.x)
+       p384ToBytes(out, (*p384UntypedFieldElement)(&tmp))
+       p384InvertEndianness(out[:])
+       return out[:]
+}
+
+// p384MinusOneEncoding is the encoding of -1 mod p, so p - 1, the
+// highest canonical encoding. It is used by SetBytes to check for non-canonical
+// encodings such as p + k, 2p + k, etc.
+var p384MinusOneEncoding = new(P384Element).Sub(
+       new(P384Element), new(P384Element).One()).Bytes()
+
+// SetBytes sets e = v, where v is a big-endian 48-byte encoding, and returns e.
+// If v is not 48 bytes or it encodes a value higher than 2^384 - 2^128 - 2^96 + 2^32 - 1,
+// SetBytes returns nil and an error, and e is unchanged.
+func (e *P384Element) SetBytes(v []byte) (*P384Element, error) {
+       if len(v) != p384ElementLen {
+               return nil, errors.New("invalid P384Element encoding")
+       }
+       for i := range v {
+               if v[i] < p384MinusOneEncoding[i] {
+                       break
+               }
+               if v[i] > p384MinusOneEncoding[i] {
+                       return nil, errors.New("invalid P384Element encoding")
+               }
+       }
+       var in [p384ElementLen]byte
+       copy(in[:], v)
+       p384InvertEndianness(in[:])
+       var tmp p384NonMontgomeryDomainFieldElement
+       p384FromBytes((*p384UntypedFieldElement)(&tmp), &in)
+       p384ToMontgomery(&e.x, &tmp)
+       return e, nil
+}
+
+// Add sets e = t1 + t2, and returns e.
+func (e *P384Element) Add(t1, t2 *P384Element) *P384Element {
+       p384Add(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Sub sets e = t1 - t2, and returns e.
+func (e *P384Element) Sub(t1, t2 *P384Element) *P384Element {
+       p384Sub(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Mul sets e = t1 * t2, and returns e.
+func (e *P384Element) Mul(t1, t2 *P384Element) *P384Element {
+       p384Mul(&e.x, &t1.x, &t2.x)
+       return e
+}
+
+// Square sets e = t * t, and returns e.
+func (e *P384Element) Square(t *P384Element) *P384Element {
+       p384Square(&e.x, &t.x)
+       return e
+}
+
+// Select sets v to a if cond == 1, and to b if cond == 0.
+func (v *P384Element) Select(a, b *P384Element, cond int) *P384Element {
+       p384Selectznz((*p384UntypedFieldElement)(&v.x), p384Uint1(cond),
+               (*p384UntypedFieldElement)(&b.x), (*p384UntypedFieldElement)(&a.x))
+       return v
+}
+
+func p384InvertEndianness(v []byte) {
+       for i := 0; i < len(v)/2; i++ {
+               v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
+       }
+}
diff --git a/src/crypto/elliptic/internal/fiat/p384_fiat64.go b/src/crypto/elliptic/internal/fiat/p384_fiat64.go
new file mode 100644 (file)
index 0000000..493bed4
--- /dev/null
@@ -0,0 +1,3004 @@
+// Code generated by Fiat Cryptography. DO NOT EDIT.
+//
+// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p384 64 '2^384 - 2^128 - 2^96 + 2^32 - 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes
+//
+// curve description: p384
+//
+// machine_wordsize = 64 (from "64")
+//
+// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes
+//
+// m = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff (from "2^384 - 2^128 - 2^96 + 2^32 - 1")
+//
+//
+//
+// NOTE: In addition to the bounds specified above each function, all
+//
+//   functions synthesized for this Montgomery arithmetic require the
+//
+//   input to be strictly less than the prime modulus (m), and also
+//
+//   require the input to be in the unique saturated representation.
+//
+//   All functions also ensure that these two properties are true of
+//
+//   return values.
+//
+//
+//
+// Computed values:
+//
+//   eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140)
+//
+//   bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178)
+//
+//   twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) in
+//
+//                            if x1 & (2^384-1) < 2^383 then x1 & (2^384-1) else (x1 & (2^384-1)) - 2^384
+
+package fiat
+
+import "math/bits"
+
+type p384Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
+type p384Int1 int64   // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
+
+// The type p384MontgomeryDomainFieldElement is a field element in the Montgomery domain.
+//
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p384MontgomeryDomainFieldElement [6]uint64
+
+// The type p384NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain.
+//
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p384NonMontgomeryDomainFieldElement [6]uint64
+
+// p384CmovznzU64 is a single-word conditional move.
+//
+// Postconditions:
+//   out1 = (if arg1 = 0 then arg2 else arg3)
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [0x0 ~> 0xffffffffffffffff]
+//   arg3: [0x0 ~> 0xffffffffffffffff]
+// Output Bounds:
+//   out1: [0x0 ~> 0xffffffffffffffff]
+func p384CmovznzU64(out1 *uint64, arg1 p384Uint1, arg2 uint64, arg3 uint64) {
+       x1 := (uint64(arg1) * 0xffffffffffffffff)
+       x2 := ((x1 & arg3) | ((^x1) & arg2))
+       *out1 = x2
+}
+
+// p384Mul multiplies two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+//   0 โ‰ค eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p384Mul(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[4]
+       x5 := arg1[5]
+       x6 := arg1[0]
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x6, arg2[5])
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x6, arg2[4])
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x6, arg2[3])
+       var x13 uint64
+       var x14 uint64
+       x14, x13 = bits.Mul64(x6, arg2[2])
+       var x15 uint64
+       var x16 uint64
+       x16, x15 = bits.Mul64(x6, arg2[1])
+       var x17 uint64
+       var x18 uint64
+       x18, x17 = bits.Mul64(x6, arg2[0])
+       var x19 uint64
+       var x20 uint64
+       x19, x20 = bits.Add64(x18, x15, uint64(0x0))
+       var x21 uint64
+       var x22 uint64
+       x21, x22 = bits.Add64(x16, x13, uint64(p384Uint1(x20)))
+       var x23 uint64
+       var x24 uint64
+       x23, x24 = bits.Add64(x14, x11, uint64(p384Uint1(x22)))
+       var x25 uint64
+       var x26 uint64
+       x25, x26 = bits.Add64(x12, x9, uint64(p384Uint1(x24)))
+       var x27 uint64
+       var x28 uint64
+       x27, x28 = bits.Add64(x10, x7, uint64(p384Uint1(x26)))
+       x29 := (uint64(p384Uint1(x28)) + x8)
+       var x30 uint64
+       _, x30 = bits.Mul64(x17, 0x100000001)
+       var x32 uint64
+       var x33 uint64
+       x33, x32 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x34 uint64
+       var x35 uint64
+       x35, x34 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x36 uint64
+       var x37 uint64
+       x37, x36 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x38 uint64
+       var x39 uint64
+       x39, x38 = bits.Mul64(x30, 0xfffffffffffffffe)
+       var x40 uint64
+       var x41 uint64
+       x41, x40 = bits.Mul64(x30, 0xffffffff00000000)
+       var x42 uint64
+       var x43 uint64
+       x43, x42 = bits.Mul64(x30, 0xffffffff)
+       var x44 uint64
+       var x45 uint64
+       x44, x45 = bits.Add64(x43, x40, uint64(0x0))
+       var x46 uint64
+       var x47 uint64
+       x46, x47 = bits.Add64(x41, x38, uint64(p384Uint1(x45)))
+       var x48 uint64
+       var x49 uint64
+       x48, x49 = bits.Add64(x39, x36, uint64(p384Uint1(x47)))
+       var x50 uint64
+       var x51 uint64
+       x50, x51 = bits.Add64(x37, x34, uint64(p384Uint1(x49)))
+       var x52 uint64
+       var x53 uint64
+       x52, x53 = bits.Add64(x35, x32, uint64(p384Uint1(x51)))
+       x54 := (uint64(p384Uint1(x53)) + x33)
+       var x56 uint64
+       _, x56 = bits.Add64(x17, x42, uint64(0x0))
+       var x57 uint64
+       var x58 uint64
+       x57, x58 = bits.Add64(x19, x44, uint64(p384Uint1(x56)))
+       var x59 uint64
+       var x60 uint64
+       x59, x60 = bits.Add64(x21, x46, uint64(p384Uint1(x58)))
+       var x61 uint64
+       var x62 uint64
+       x61, x62 = bits.Add64(x23, x48, uint64(p384Uint1(x60)))
+       var x63 uint64
+       var x64 uint64
+       x63, x64 = bits.Add64(x25, x50, uint64(p384Uint1(x62)))
+       var x65 uint64
+       var x66 uint64
+       x65, x66 = bits.Add64(x27, x52, uint64(p384Uint1(x64)))
+       var x67 uint64
+       var x68 uint64
+       x67, x68 = bits.Add64(x29, x54, uint64(p384Uint1(x66)))
+       var x69 uint64
+       var x70 uint64
+       x70, x69 = bits.Mul64(x1, arg2[5])
+       var x71 uint64
+       var x72 uint64
+       x72, x71 = bits.Mul64(x1, arg2[4])
+       var x73 uint64
+       var x74 uint64
+       x74, x73 = bits.Mul64(x1, arg2[3])
+       var x75 uint64
+       var x76 uint64
+       x76, x75 = bits.Mul64(x1, arg2[2])
+       var x77 uint64
+       var x78 uint64
+       x78, x77 = bits.Mul64(x1, arg2[1])
+       var x79 uint64
+       var x80 uint64
+       x80, x79 = bits.Mul64(x1, arg2[0])
+       var x81 uint64
+       var x82 uint64
+       x81, x82 = bits.Add64(x80, x77, uint64(0x0))
+       var x83 uint64
+       var x84 uint64
+       x83, x84 = bits.Add64(x78, x75, uint64(p384Uint1(x82)))
+       var x85 uint64
+       var x86 uint64
+       x85, x86 = bits.Add64(x76, x73, uint64(p384Uint1(x84)))
+       var x87 uint64
+       var x88 uint64
+       x87, x88 = bits.Add64(x74, x71, uint64(p384Uint1(x86)))
+       var x89 uint64
+       var x90 uint64
+       x89, x90 = bits.Add64(x72, x69, uint64(p384Uint1(x88)))
+       x91 := (uint64(p384Uint1(x90)) + x70)
+       var x92 uint64
+       var x93 uint64
+       x92, x93 = bits.Add64(x57, x79, uint64(0x0))
+       var x94 uint64
+       var x95 uint64
+       x94, x95 = bits.Add64(x59, x81, uint64(p384Uint1(x93)))
+       var x96 uint64
+       var x97 uint64
+       x96, x97 = bits.Add64(x61, x83, uint64(p384Uint1(x95)))
+       var x98 uint64
+       var x99 uint64
+       x98, x99 = bits.Add64(x63, x85, uint64(p384Uint1(x97)))
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x65, x87, uint64(p384Uint1(x99)))
+       var x102 uint64
+       var x103 uint64
+       x102, x103 = bits.Add64(x67, x89, uint64(p384Uint1(x101)))
+       var x104 uint64
+       var x105 uint64
+       x104, x105 = bits.Add64(uint64(p384Uint1(x68)), x91, uint64(p384Uint1(x103)))
+       var x106 uint64
+       _, x106 = bits.Mul64(x92, 0x100000001)
+       var x108 uint64
+       var x109 uint64
+       x109, x108 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x110 uint64
+       var x111 uint64
+       x111, x110 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x112 uint64
+       var x113 uint64
+       x113, x112 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x114 uint64
+       var x115 uint64
+       x115, x114 = bits.Mul64(x106, 0xfffffffffffffffe)
+       var x116 uint64
+       var x117 uint64
+       x117, x116 = bits.Mul64(x106, 0xffffffff00000000)
+       var x118 uint64
+       var x119 uint64
+       x119, x118 = bits.Mul64(x106, 0xffffffff)
+       var x120 uint64
+       var x121 uint64
+       x120, x121 = bits.Add64(x119, x116, uint64(0x0))
+       var x122 uint64
+       var x123 uint64
+       x122, x123 = bits.Add64(x117, x114, uint64(p384Uint1(x121)))
+       var x124 uint64
+       var x125 uint64
+       x124, x125 = bits.Add64(x115, x112, uint64(p384Uint1(x123)))
+       var x126 uint64
+       var x127 uint64
+       x126, x127 = bits.Add64(x113, x110, uint64(p384Uint1(x125)))
+       var x128 uint64
+       var x129 uint64
+       x128, x129 = bits.Add64(x111, x108, uint64(p384Uint1(x127)))
+       x130 := (uint64(p384Uint1(x129)) + x109)
+       var x132 uint64
+       _, x132 = bits.Add64(x92, x118, uint64(0x0))
+       var x133 uint64
+       var x134 uint64
+       x133, x134 = bits.Add64(x94, x120, uint64(p384Uint1(x132)))
+       var x135 uint64
+       var x136 uint64
+       x135, x136 = bits.Add64(x96, x122, uint64(p384Uint1(x134)))
+       var x137 uint64
+       var x138 uint64
+       x137, x138 = bits.Add64(x98, x124, uint64(p384Uint1(x136)))
+       var x139 uint64
+       var x140 uint64
+       x139, x140 = bits.Add64(x100, x126, uint64(p384Uint1(x138)))
+       var x141 uint64
+       var x142 uint64
+       x141, x142 = bits.Add64(x102, x128, uint64(p384Uint1(x140)))
+       var x143 uint64
+       var x144 uint64
+       x143, x144 = bits.Add64(x104, x130, uint64(p384Uint1(x142)))
+       x145 := (uint64(p384Uint1(x144)) + uint64(p384Uint1(x105)))
+       var x146 uint64
+       var x147 uint64
+       x147, x146 = bits.Mul64(x2, arg2[5])
+       var x148 uint64
+       var x149 uint64
+       x149, x148 = bits.Mul64(x2, arg2[4])
+       var x150 uint64
+       var x151 uint64
+       x151, x150 = bits.Mul64(x2, arg2[3])
+       var x152 uint64
+       var x153 uint64
+       x153, x152 = bits.Mul64(x2, arg2[2])
+       var x154 uint64
+       var x155 uint64
+       x155, x154 = bits.Mul64(x2, arg2[1])
+       var x156 uint64
+       var x157 uint64
+       x157, x156 = bits.Mul64(x2, arg2[0])
+       var x158 uint64
+       var x159 uint64
+       x158, x159 = bits.Add64(x157, x154, uint64(0x0))
+       var x160 uint64
+       var x161 uint64
+       x160, x161 = bits.Add64(x155, x152, uint64(p384Uint1(x159)))
+       var x162 uint64
+       var x163 uint64
+       x162, x163 = bits.Add64(x153, x150, uint64(p384Uint1(x161)))
+       var x164 uint64
+       var x165 uint64
+       x164, x165 = bits.Add64(x151, x148, uint64(p384Uint1(x163)))
+       var x166 uint64
+       var x167 uint64
+       x166, x167 = bits.Add64(x149, x146, uint64(p384Uint1(x165)))
+       x168 := (uint64(p384Uint1(x167)) + x147)
+       var x169 uint64
+       var x170 uint64
+       x169, x170 = bits.Add64(x133, x156, uint64(0x0))
+       var x171 uint64
+       var x172 uint64
+       x171, x172 = bits.Add64(x135, x158, uint64(p384Uint1(x170)))
+       var x173 uint64
+       var x174 uint64
+       x173, x174 = bits.Add64(x137, x160, uint64(p384Uint1(x172)))
+       var x175 uint64
+       var x176 uint64
+       x175, x176 = bits.Add64(x139, x162, uint64(p384Uint1(x174)))
+       var x177 uint64
+       var x178 uint64
+       x177, x178 = bits.Add64(x141, x164, uint64(p384Uint1(x176)))
+       var x179 uint64
+       var x180 uint64
+       x179, x180 = bits.Add64(x143, x166, uint64(p384Uint1(x178)))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x145, x168, uint64(p384Uint1(x180)))
+       var x183 uint64
+       _, x183 = bits.Mul64(x169, 0x100000001)
+       var x185 uint64
+       var x186 uint64
+       x186, x185 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x187 uint64
+       var x188 uint64
+       x188, x187 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x189 uint64
+       var x190 uint64
+       x190, x189 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x191 uint64
+       var x192 uint64
+       x192, x191 = bits.Mul64(x183, 0xfffffffffffffffe)
+       var x193 uint64
+       var x194 uint64
+       x194, x193 = bits.Mul64(x183, 0xffffffff00000000)
+       var x195 uint64
+       var x196 uint64
+       x196, x195 = bits.Mul64(x183, 0xffffffff)
+       var x197 uint64
+       var x198 uint64
+       x197, x198 = bits.Add64(x196, x193, uint64(0x0))
+       var x199 uint64
+       var x200 uint64
+       x199, x200 = bits.Add64(x194, x191, uint64(p384Uint1(x198)))
+       var x201 uint64
+       var x202 uint64
+       x201, x202 = bits.Add64(x192, x189, uint64(p384Uint1(x200)))
+       var x203 uint64
+       var x204 uint64
+       x203, x204 = bits.Add64(x190, x187, uint64(p384Uint1(x202)))
+       var x205 uint64
+       var x206 uint64
+       x205, x206 = bits.Add64(x188, x185, uint64(p384Uint1(x204)))
+       x207 := (uint64(p384Uint1(x206)) + x186)
+       var x209 uint64
+       _, x209 = bits.Add64(x169, x195, uint64(0x0))
+       var x210 uint64
+       var x211 uint64
+       x210, x211 = bits.Add64(x171, x197, uint64(p384Uint1(x209)))
+       var x212 uint64
+       var x213 uint64
+       x212, x213 = bits.Add64(x173, x199, uint64(p384Uint1(x211)))
+       var x214 uint64
+       var x215 uint64
+       x214, x215 = bits.Add64(x175, x201, uint64(p384Uint1(x213)))
+       var x216 uint64
+       var x217 uint64
+       x216, x217 = bits.Add64(x177, x203, uint64(p384Uint1(x215)))
+       var x218 uint64
+       var x219 uint64
+       x218, x219 = bits.Add64(x179, x205, uint64(p384Uint1(x217)))
+       var x220 uint64
+       var x221 uint64
+       x220, x221 = bits.Add64(x181, x207, uint64(p384Uint1(x219)))
+       x222 := (uint64(p384Uint1(x221)) + uint64(p384Uint1(x182)))
+       var x223 uint64
+       var x224 uint64
+       x224, x223 = bits.Mul64(x3, arg2[5])
+       var x225 uint64
+       var x226 uint64
+       x226, x225 = bits.Mul64(x3, arg2[4])
+       var x227 uint64
+       var x228 uint64
+       x228, x227 = bits.Mul64(x3, arg2[3])
+       var x229 uint64
+       var x230 uint64
+       x230, x229 = bits.Mul64(x3, arg2[2])
+       var x231 uint64
+       var x232 uint64
+       x232, x231 = bits.Mul64(x3, arg2[1])
+       var x233 uint64
+       var x234 uint64
+       x234, x233 = bits.Mul64(x3, arg2[0])
+       var x235 uint64
+       var x236 uint64
+       x235, x236 = bits.Add64(x234, x231, uint64(0x0))
+       var x237 uint64
+       var x238 uint64
+       x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236)))
+       var x239 uint64
+       var x240 uint64
+       x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238)))
+       var x241 uint64
+       var x242 uint64
+       x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240)))
+       var x243 uint64
+       var x244 uint64
+       x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242)))
+       x245 := (uint64(p384Uint1(x244)) + x224)
+       var x246 uint64
+       var x247 uint64
+       x246, x247 = bits.Add64(x210, x233, uint64(0x0))
+       var x248 uint64
+       var x249 uint64
+       x248, x249 = bits.Add64(x212, x235, uint64(p384Uint1(x247)))
+       var x250 uint64
+       var x251 uint64
+       x250, x251 = bits.Add64(x214, x237, uint64(p384Uint1(x249)))
+       var x252 uint64
+       var x253 uint64
+       x252, x253 = bits.Add64(x216, x239, uint64(p384Uint1(x251)))
+       var x254 uint64
+       var x255 uint64
+       x254, x255 = bits.Add64(x218, x241, uint64(p384Uint1(x253)))
+       var x256 uint64
+       var x257 uint64
+       x256, x257 = bits.Add64(x220, x243, uint64(p384Uint1(x255)))
+       var x258 uint64
+       var x259 uint64
+       x258, x259 = bits.Add64(x222, x245, uint64(p384Uint1(x257)))
+       var x260 uint64
+       _, x260 = bits.Mul64(x246, 0x100000001)
+       var x262 uint64
+       var x263 uint64
+       x263, x262 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x264 uint64
+       var x265 uint64
+       x265, x264 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x266 uint64
+       var x267 uint64
+       x267, x266 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x268 uint64
+       var x269 uint64
+       x269, x268 = bits.Mul64(x260, 0xfffffffffffffffe)
+       var x270 uint64
+       var x271 uint64
+       x271, x270 = bits.Mul64(x260, 0xffffffff00000000)
+       var x272 uint64
+       var x273 uint64
+       x273, x272 = bits.Mul64(x260, 0xffffffff)
+       var x274 uint64
+       var x275 uint64
+       x274, x275 = bits.Add64(x273, x270, uint64(0x0))
+       var x276 uint64
+       var x277 uint64
+       x276, x277 = bits.Add64(x271, x268, uint64(p384Uint1(x275)))
+       var x278 uint64
+       var x279 uint64
+       x278, x279 = bits.Add64(x269, x266, uint64(p384Uint1(x277)))
+       var x280 uint64
+       var x281 uint64
+       x280, x281 = bits.Add64(x267, x264, uint64(p384Uint1(x279)))
+       var x282 uint64
+       var x283 uint64
+       x282, x283 = bits.Add64(x265, x262, uint64(p384Uint1(x281)))
+       x284 := (uint64(p384Uint1(x283)) + x263)
+       var x286 uint64
+       _, x286 = bits.Add64(x246, x272, uint64(0x0))
+       var x287 uint64
+       var x288 uint64
+       x287, x288 = bits.Add64(x248, x274, uint64(p384Uint1(x286)))
+       var x289 uint64
+       var x290 uint64
+       x289, x290 = bits.Add64(x250, x276, uint64(p384Uint1(x288)))
+       var x291 uint64
+       var x292 uint64
+       x291, x292 = bits.Add64(x252, x278, uint64(p384Uint1(x290)))
+       var x293 uint64
+       var x294 uint64
+       x293, x294 = bits.Add64(x254, x280, uint64(p384Uint1(x292)))
+       var x295 uint64
+       var x296 uint64
+       x295, x296 = bits.Add64(x256, x282, uint64(p384Uint1(x294)))
+       var x297 uint64
+       var x298 uint64
+       x297, x298 = bits.Add64(x258, x284, uint64(p384Uint1(x296)))
+       x299 := (uint64(p384Uint1(x298)) + uint64(p384Uint1(x259)))
+       var x300 uint64
+       var x301 uint64
+       x301, x300 = bits.Mul64(x4, arg2[5])
+       var x302 uint64
+       var x303 uint64
+       x303, x302 = bits.Mul64(x4, arg2[4])
+       var x304 uint64
+       var x305 uint64
+       x305, x304 = bits.Mul64(x4, arg2[3])
+       var x306 uint64
+       var x307 uint64
+       x307, x306 = bits.Mul64(x4, arg2[2])
+       var x308 uint64
+       var x309 uint64
+       x309, x308 = bits.Mul64(x4, arg2[1])
+       var x310 uint64
+       var x311 uint64
+       x311, x310 = bits.Mul64(x4, arg2[0])
+       var x312 uint64
+       var x313 uint64
+       x312, x313 = bits.Add64(x311, x308, uint64(0x0))
+       var x314 uint64
+       var x315 uint64
+       x314, x315 = bits.Add64(x309, x306, uint64(p384Uint1(x313)))
+       var x316 uint64
+       var x317 uint64
+       x316, x317 = bits.Add64(x307, x304, uint64(p384Uint1(x315)))
+       var x318 uint64
+       var x319 uint64
+       x318, x319 = bits.Add64(x305, x302, uint64(p384Uint1(x317)))
+       var x320 uint64
+       var x321 uint64
+       x320, x321 = bits.Add64(x303, x300, uint64(p384Uint1(x319)))
+       x322 := (uint64(p384Uint1(x321)) + x301)
+       var x323 uint64
+       var x324 uint64
+       x323, x324 = bits.Add64(x287, x310, uint64(0x0))
+       var x325 uint64
+       var x326 uint64
+       x325, x326 = bits.Add64(x289, x312, uint64(p384Uint1(x324)))
+       var x327 uint64
+       var x328 uint64
+       x327, x328 = bits.Add64(x291, x314, uint64(p384Uint1(x326)))
+       var x329 uint64
+       var x330 uint64
+       x329, x330 = bits.Add64(x293, x316, uint64(p384Uint1(x328)))
+       var x331 uint64
+       var x332 uint64
+       x331, x332 = bits.Add64(x295, x318, uint64(p384Uint1(x330)))
+       var x333 uint64
+       var x334 uint64
+       x333, x334 = bits.Add64(x297, x320, uint64(p384Uint1(x332)))
+       var x335 uint64
+       var x336 uint64
+       x335, x336 = bits.Add64(x299, x322, uint64(p384Uint1(x334)))
+       var x337 uint64
+       _, x337 = bits.Mul64(x323, 0x100000001)
+       var x339 uint64
+       var x340 uint64
+       x340, x339 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x341 uint64
+       var x342 uint64
+       x342, x341 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x343 uint64
+       var x344 uint64
+       x344, x343 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x345 uint64
+       var x346 uint64
+       x346, x345 = bits.Mul64(x337, 0xfffffffffffffffe)
+       var x347 uint64
+       var x348 uint64
+       x348, x347 = bits.Mul64(x337, 0xffffffff00000000)
+       var x349 uint64
+       var x350 uint64
+       x350, x349 = bits.Mul64(x337, 0xffffffff)
+       var x351 uint64
+       var x352 uint64
+       x351, x352 = bits.Add64(x350, x347, uint64(0x0))
+       var x353 uint64
+       var x354 uint64
+       x353, x354 = bits.Add64(x348, x345, uint64(p384Uint1(x352)))
+       var x355 uint64
+       var x356 uint64
+       x355, x356 = bits.Add64(x346, x343, uint64(p384Uint1(x354)))
+       var x357 uint64
+       var x358 uint64
+       x357, x358 = bits.Add64(x344, x341, uint64(p384Uint1(x356)))
+       var x359 uint64
+       var x360 uint64
+       x359, x360 = bits.Add64(x342, x339, uint64(p384Uint1(x358)))
+       x361 := (uint64(p384Uint1(x360)) + x340)
+       var x363 uint64
+       _, x363 = bits.Add64(x323, x349, uint64(0x0))
+       var x364 uint64
+       var x365 uint64
+       x364, x365 = bits.Add64(x325, x351, uint64(p384Uint1(x363)))
+       var x366 uint64
+       var x367 uint64
+       x366, x367 = bits.Add64(x327, x353, uint64(p384Uint1(x365)))
+       var x368 uint64
+       var x369 uint64
+       x368, x369 = bits.Add64(x329, x355, uint64(p384Uint1(x367)))
+       var x370 uint64
+       var x371 uint64
+       x370, x371 = bits.Add64(x331, x357, uint64(p384Uint1(x369)))
+       var x372 uint64
+       var x373 uint64
+       x372, x373 = bits.Add64(x333, x359, uint64(p384Uint1(x371)))
+       var x374 uint64
+       var x375 uint64
+       x374, x375 = bits.Add64(x335, x361, uint64(p384Uint1(x373)))
+       x376 := (uint64(p384Uint1(x375)) + uint64(p384Uint1(x336)))
+       var x377 uint64
+       var x378 uint64
+       x378, x377 = bits.Mul64(x5, arg2[5])
+       var x379 uint64
+       var x380 uint64
+       x380, x379 = bits.Mul64(x5, arg2[4])
+       var x381 uint64
+       var x382 uint64
+       x382, x381 = bits.Mul64(x5, arg2[3])
+       var x383 uint64
+       var x384 uint64
+       x384, x383 = bits.Mul64(x5, arg2[2])
+       var x385 uint64
+       var x386 uint64
+       x386, x385 = bits.Mul64(x5, arg2[1])
+       var x387 uint64
+       var x388 uint64
+       x388, x387 = bits.Mul64(x5, arg2[0])
+       var x389 uint64
+       var x390 uint64
+       x389, x390 = bits.Add64(x388, x385, uint64(0x0))
+       var x391 uint64
+       var x392 uint64
+       x391, x392 = bits.Add64(x386, x383, uint64(p384Uint1(x390)))
+       var x393 uint64
+       var x394 uint64
+       x393, x394 = bits.Add64(x384, x381, uint64(p384Uint1(x392)))
+       var x395 uint64
+       var x396 uint64
+       x395, x396 = bits.Add64(x382, x379, uint64(p384Uint1(x394)))
+       var x397 uint64
+       var x398 uint64
+       x397, x398 = bits.Add64(x380, x377, uint64(p384Uint1(x396)))
+       x399 := (uint64(p384Uint1(x398)) + x378)
+       var x400 uint64
+       var x401 uint64
+       x400, x401 = bits.Add64(x364, x387, uint64(0x0))
+       var x402 uint64
+       var x403 uint64
+       x402, x403 = bits.Add64(x366, x389, uint64(p384Uint1(x401)))
+       var x404 uint64
+       var x405 uint64
+       x404, x405 = bits.Add64(x368, x391, uint64(p384Uint1(x403)))
+       var x406 uint64
+       var x407 uint64
+       x406, x407 = bits.Add64(x370, x393, uint64(p384Uint1(x405)))
+       var x408 uint64
+       var x409 uint64
+       x408, x409 = bits.Add64(x372, x395, uint64(p384Uint1(x407)))
+       var x410 uint64
+       var x411 uint64
+       x410, x411 = bits.Add64(x374, x397, uint64(p384Uint1(x409)))
+       var x412 uint64
+       var x413 uint64
+       x412, x413 = bits.Add64(x376, x399, uint64(p384Uint1(x411)))
+       var x414 uint64
+       _, x414 = bits.Mul64(x400, 0x100000001)
+       var x416 uint64
+       var x417 uint64
+       x417, x416 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x418 uint64
+       var x419 uint64
+       x419, x418 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x420 uint64
+       var x421 uint64
+       x421, x420 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x422 uint64
+       var x423 uint64
+       x423, x422 = bits.Mul64(x414, 0xfffffffffffffffe)
+       var x424 uint64
+       var x425 uint64
+       x425, x424 = bits.Mul64(x414, 0xffffffff00000000)
+       var x426 uint64
+       var x427 uint64
+       x427, x426 = bits.Mul64(x414, 0xffffffff)
+       var x428 uint64
+       var x429 uint64
+       x428, x429 = bits.Add64(x427, x424, uint64(0x0))
+       var x430 uint64
+       var x431 uint64
+       x430, x431 = bits.Add64(x425, x422, uint64(p384Uint1(x429)))
+       var x432 uint64
+       var x433 uint64
+       x432, x433 = bits.Add64(x423, x420, uint64(p384Uint1(x431)))
+       var x434 uint64
+       var x435 uint64
+       x434, x435 = bits.Add64(x421, x418, uint64(p384Uint1(x433)))
+       var x436 uint64
+       var x437 uint64
+       x436, x437 = bits.Add64(x419, x416, uint64(p384Uint1(x435)))
+       x438 := (uint64(p384Uint1(x437)) + x417)
+       var x440 uint64
+       _, x440 = bits.Add64(x400, x426, uint64(0x0))
+       var x441 uint64
+       var x442 uint64
+       x441, x442 = bits.Add64(x402, x428, uint64(p384Uint1(x440)))
+       var x443 uint64
+       var x444 uint64
+       x443, x444 = bits.Add64(x404, x430, uint64(p384Uint1(x442)))
+       var x445 uint64
+       var x446 uint64
+       x445, x446 = bits.Add64(x406, x432, uint64(p384Uint1(x444)))
+       var x447 uint64
+       var x448 uint64
+       x447, x448 = bits.Add64(x408, x434, uint64(p384Uint1(x446)))
+       var x449 uint64
+       var x450 uint64
+       x449, x450 = bits.Add64(x410, x436, uint64(p384Uint1(x448)))
+       var x451 uint64
+       var x452 uint64
+       x451, x452 = bits.Add64(x412, x438, uint64(p384Uint1(x450)))
+       x453 := (uint64(p384Uint1(x452)) + uint64(p384Uint1(x413)))
+       var x454 uint64
+       var x455 uint64
+       x454, x455 = bits.Sub64(x441, 0xffffffff, uint64(0x0))
+       var x456 uint64
+       var x457 uint64
+       x456, x457 = bits.Sub64(x443, 0xffffffff00000000, uint64(p384Uint1(x455)))
+       var x458 uint64
+       var x459 uint64
+       x458, x459 = bits.Sub64(x445, 0xfffffffffffffffe, uint64(p384Uint1(x457)))
+       var x460 uint64
+       var x461 uint64
+       x460, x461 = bits.Sub64(x447, 0xffffffffffffffff, uint64(p384Uint1(x459)))
+       var x462 uint64
+       var x463 uint64
+       x462, x463 = bits.Sub64(x449, 0xffffffffffffffff, uint64(p384Uint1(x461)))
+       var x464 uint64
+       var x465 uint64
+       x464, x465 = bits.Sub64(x451, 0xffffffffffffffff, uint64(p384Uint1(x463)))
+       var x467 uint64
+       _, x467 = bits.Sub64(x453, uint64(0x0), uint64(p384Uint1(x465)))
+       var x468 uint64
+       p384CmovznzU64(&x468, p384Uint1(x467), x454, x441)
+       var x469 uint64
+       p384CmovznzU64(&x469, p384Uint1(x467), x456, x443)
+       var x470 uint64
+       p384CmovznzU64(&x470, p384Uint1(x467), x458, x445)
+       var x471 uint64
+       p384CmovznzU64(&x471, p384Uint1(x467), x460, x447)
+       var x472 uint64
+       p384CmovznzU64(&x472, p384Uint1(x467), x462, x449)
+       var x473 uint64
+       p384CmovznzU64(&x473, p384Uint1(x467), x464, x451)
+       out1[0] = x468
+       out1[1] = x469
+       out1[2] = x470
+       out1[3] = x471
+       out1[4] = x472
+       out1[5] = x473
+}
+
+// p384Square squares a field element in the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p384Square(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[4]
+       x5 := arg1[5]
+       x6 := arg1[0]
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x6, arg1[5])
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x6, arg1[4])
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x6, arg1[3])
+       var x13 uint64
+       var x14 uint64
+       x14, x13 = bits.Mul64(x6, arg1[2])
+       var x15 uint64
+       var x16 uint64
+       x16, x15 = bits.Mul64(x6, arg1[1])
+       var x17 uint64
+       var x18 uint64
+       x18, x17 = bits.Mul64(x6, arg1[0])
+       var x19 uint64
+       var x20 uint64
+       x19, x20 = bits.Add64(x18, x15, uint64(0x0))
+       var x21 uint64
+       var x22 uint64
+       x21, x22 = bits.Add64(x16, x13, uint64(p384Uint1(x20)))
+       var x23 uint64
+       var x24 uint64
+       x23, x24 = bits.Add64(x14, x11, uint64(p384Uint1(x22)))
+       var x25 uint64
+       var x26 uint64
+       x25, x26 = bits.Add64(x12, x9, uint64(p384Uint1(x24)))
+       var x27 uint64
+       var x28 uint64
+       x27, x28 = bits.Add64(x10, x7, uint64(p384Uint1(x26)))
+       x29 := (uint64(p384Uint1(x28)) + x8)
+       var x30 uint64
+       _, x30 = bits.Mul64(x17, 0x100000001)
+       var x32 uint64
+       var x33 uint64
+       x33, x32 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x34 uint64
+       var x35 uint64
+       x35, x34 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x36 uint64
+       var x37 uint64
+       x37, x36 = bits.Mul64(x30, 0xffffffffffffffff)
+       var x38 uint64
+       var x39 uint64
+       x39, x38 = bits.Mul64(x30, 0xfffffffffffffffe)
+       var x40 uint64
+       var x41 uint64
+       x41, x40 = bits.Mul64(x30, 0xffffffff00000000)
+       var x42 uint64
+       var x43 uint64
+       x43, x42 = bits.Mul64(x30, 0xffffffff)
+       var x44 uint64
+       var x45 uint64
+       x44, x45 = bits.Add64(x43, x40, uint64(0x0))
+       var x46 uint64
+       var x47 uint64
+       x46, x47 = bits.Add64(x41, x38, uint64(p384Uint1(x45)))
+       var x48 uint64
+       var x49 uint64
+       x48, x49 = bits.Add64(x39, x36, uint64(p384Uint1(x47)))
+       var x50 uint64
+       var x51 uint64
+       x50, x51 = bits.Add64(x37, x34, uint64(p384Uint1(x49)))
+       var x52 uint64
+       var x53 uint64
+       x52, x53 = bits.Add64(x35, x32, uint64(p384Uint1(x51)))
+       x54 := (uint64(p384Uint1(x53)) + x33)
+       var x56 uint64
+       _, x56 = bits.Add64(x17, x42, uint64(0x0))
+       var x57 uint64
+       var x58 uint64
+       x57, x58 = bits.Add64(x19, x44, uint64(p384Uint1(x56)))
+       var x59 uint64
+       var x60 uint64
+       x59, x60 = bits.Add64(x21, x46, uint64(p384Uint1(x58)))
+       var x61 uint64
+       var x62 uint64
+       x61, x62 = bits.Add64(x23, x48, uint64(p384Uint1(x60)))
+       var x63 uint64
+       var x64 uint64
+       x63, x64 = bits.Add64(x25, x50, uint64(p384Uint1(x62)))
+       var x65 uint64
+       var x66 uint64
+       x65, x66 = bits.Add64(x27, x52, uint64(p384Uint1(x64)))
+       var x67 uint64
+       var x68 uint64
+       x67, x68 = bits.Add64(x29, x54, uint64(p384Uint1(x66)))
+       var x69 uint64
+       var x70 uint64
+       x70, x69 = bits.Mul64(x1, arg1[5])
+       var x71 uint64
+       var x72 uint64
+       x72, x71 = bits.Mul64(x1, arg1[4])
+       var x73 uint64
+       var x74 uint64
+       x74, x73 = bits.Mul64(x1, arg1[3])
+       var x75 uint64
+       var x76 uint64
+       x76, x75 = bits.Mul64(x1, arg1[2])
+       var x77 uint64
+       var x78 uint64
+       x78, x77 = bits.Mul64(x1, arg1[1])
+       var x79 uint64
+       var x80 uint64
+       x80, x79 = bits.Mul64(x1, arg1[0])
+       var x81 uint64
+       var x82 uint64
+       x81, x82 = bits.Add64(x80, x77, uint64(0x0))
+       var x83 uint64
+       var x84 uint64
+       x83, x84 = bits.Add64(x78, x75, uint64(p384Uint1(x82)))
+       var x85 uint64
+       var x86 uint64
+       x85, x86 = bits.Add64(x76, x73, uint64(p384Uint1(x84)))
+       var x87 uint64
+       var x88 uint64
+       x87, x88 = bits.Add64(x74, x71, uint64(p384Uint1(x86)))
+       var x89 uint64
+       var x90 uint64
+       x89, x90 = bits.Add64(x72, x69, uint64(p384Uint1(x88)))
+       x91 := (uint64(p384Uint1(x90)) + x70)
+       var x92 uint64
+       var x93 uint64
+       x92, x93 = bits.Add64(x57, x79, uint64(0x0))
+       var x94 uint64
+       var x95 uint64
+       x94, x95 = bits.Add64(x59, x81, uint64(p384Uint1(x93)))
+       var x96 uint64
+       var x97 uint64
+       x96, x97 = bits.Add64(x61, x83, uint64(p384Uint1(x95)))
+       var x98 uint64
+       var x99 uint64
+       x98, x99 = bits.Add64(x63, x85, uint64(p384Uint1(x97)))
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x65, x87, uint64(p384Uint1(x99)))
+       var x102 uint64
+       var x103 uint64
+       x102, x103 = bits.Add64(x67, x89, uint64(p384Uint1(x101)))
+       var x104 uint64
+       var x105 uint64
+       x104, x105 = bits.Add64(uint64(p384Uint1(x68)), x91, uint64(p384Uint1(x103)))
+       var x106 uint64
+       _, x106 = bits.Mul64(x92, 0x100000001)
+       var x108 uint64
+       var x109 uint64
+       x109, x108 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x110 uint64
+       var x111 uint64
+       x111, x110 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x112 uint64
+       var x113 uint64
+       x113, x112 = bits.Mul64(x106, 0xffffffffffffffff)
+       var x114 uint64
+       var x115 uint64
+       x115, x114 = bits.Mul64(x106, 0xfffffffffffffffe)
+       var x116 uint64
+       var x117 uint64
+       x117, x116 = bits.Mul64(x106, 0xffffffff00000000)
+       var x118 uint64
+       var x119 uint64
+       x119, x118 = bits.Mul64(x106, 0xffffffff)
+       var x120 uint64
+       var x121 uint64
+       x120, x121 = bits.Add64(x119, x116, uint64(0x0))
+       var x122 uint64
+       var x123 uint64
+       x122, x123 = bits.Add64(x117, x114, uint64(p384Uint1(x121)))
+       var x124 uint64
+       var x125 uint64
+       x124, x125 = bits.Add64(x115, x112, uint64(p384Uint1(x123)))
+       var x126 uint64
+       var x127 uint64
+       x126, x127 = bits.Add64(x113, x110, uint64(p384Uint1(x125)))
+       var x128 uint64
+       var x129 uint64
+       x128, x129 = bits.Add64(x111, x108, uint64(p384Uint1(x127)))
+       x130 := (uint64(p384Uint1(x129)) + x109)
+       var x132 uint64
+       _, x132 = bits.Add64(x92, x118, uint64(0x0))
+       var x133 uint64
+       var x134 uint64
+       x133, x134 = bits.Add64(x94, x120, uint64(p384Uint1(x132)))
+       var x135 uint64
+       var x136 uint64
+       x135, x136 = bits.Add64(x96, x122, uint64(p384Uint1(x134)))
+       var x137 uint64
+       var x138 uint64
+       x137, x138 = bits.Add64(x98, x124, uint64(p384Uint1(x136)))
+       var x139 uint64
+       var x140 uint64
+       x139, x140 = bits.Add64(x100, x126, uint64(p384Uint1(x138)))
+       var x141 uint64
+       var x142 uint64
+       x141, x142 = bits.Add64(x102, x128, uint64(p384Uint1(x140)))
+       var x143 uint64
+       var x144 uint64
+       x143, x144 = bits.Add64(x104, x130, uint64(p384Uint1(x142)))
+       x145 := (uint64(p384Uint1(x144)) + uint64(p384Uint1(x105)))
+       var x146 uint64
+       var x147 uint64
+       x147, x146 = bits.Mul64(x2, arg1[5])
+       var x148 uint64
+       var x149 uint64
+       x149, x148 = bits.Mul64(x2, arg1[4])
+       var x150 uint64
+       var x151 uint64
+       x151, x150 = bits.Mul64(x2, arg1[3])
+       var x152 uint64
+       var x153 uint64
+       x153, x152 = bits.Mul64(x2, arg1[2])
+       var x154 uint64
+       var x155 uint64
+       x155, x154 = bits.Mul64(x2, arg1[1])
+       var x156 uint64
+       var x157 uint64
+       x157, x156 = bits.Mul64(x2, arg1[0])
+       var x158 uint64
+       var x159 uint64
+       x158, x159 = bits.Add64(x157, x154, uint64(0x0))
+       var x160 uint64
+       var x161 uint64
+       x160, x161 = bits.Add64(x155, x152, uint64(p384Uint1(x159)))
+       var x162 uint64
+       var x163 uint64
+       x162, x163 = bits.Add64(x153, x150, uint64(p384Uint1(x161)))
+       var x164 uint64
+       var x165 uint64
+       x164, x165 = bits.Add64(x151, x148, uint64(p384Uint1(x163)))
+       var x166 uint64
+       var x167 uint64
+       x166, x167 = bits.Add64(x149, x146, uint64(p384Uint1(x165)))
+       x168 := (uint64(p384Uint1(x167)) + x147)
+       var x169 uint64
+       var x170 uint64
+       x169, x170 = bits.Add64(x133, x156, uint64(0x0))
+       var x171 uint64
+       var x172 uint64
+       x171, x172 = bits.Add64(x135, x158, uint64(p384Uint1(x170)))
+       var x173 uint64
+       var x174 uint64
+       x173, x174 = bits.Add64(x137, x160, uint64(p384Uint1(x172)))
+       var x175 uint64
+       var x176 uint64
+       x175, x176 = bits.Add64(x139, x162, uint64(p384Uint1(x174)))
+       var x177 uint64
+       var x178 uint64
+       x177, x178 = bits.Add64(x141, x164, uint64(p384Uint1(x176)))
+       var x179 uint64
+       var x180 uint64
+       x179, x180 = bits.Add64(x143, x166, uint64(p384Uint1(x178)))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x145, x168, uint64(p384Uint1(x180)))
+       var x183 uint64
+       _, x183 = bits.Mul64(x169, 0x100000001)
+       var x185 uint64
+       var x186 uint64
+       x186, x185 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x187 uint64
+       var x188 uint64
+       x188, x187 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x189 uint64
+       var x190 uint64
+       x190, x189 = bits.Mul64(x183, 0xffffffffffffffff)
+       var x191 uint64
+       var x192 uint64
+       x192, x191 = bits.Mul64(x183, 0xfffffffffffffffe)
+       var x193 uint64
+       var x194 uint64
+       x194, x193 = bits.Mul64(x183, 0xffffffff00000000)
+       var x195 uint64
+       var x196 uint64
+       x196, x195 = bits.Mul64(x183, 0xffffffff)
+       var x197 uint64
+       var x198 uint64
+       x197, x198 = bits.Add64(x196, x193, uint64(0x0))
+       var x199 uint64
+       var x200 uint64
+       x199, x200 = bits.Add64(x194, x191, uint64(p384Uint1(x198)))
+       var x201 uint64
+       var x202 uint64
+       x201, x202 = bits.Add64(x192, x189, uint64(p384Uint1(x200)))
+       var x203 uint64
+       var x204 uint64
+       x203, x204 = bits.Add64(x190, x187, uint64(p384Uint1(x202)))
+       var x205 uint64
+       var x206 uint64
+       x205, x206 = bits.Add64(x188, x185, uint64(p384Uint1(x204)))
+       x207 := (uint64(p384Uint1(x206)) + x186)
+       var x209 uint64
+       _, x209 = bits.Add64(x169, x195, uint64(0x0))
+       var x210 uint64
+       var x211 uint64
+       x210, x211 = bits.Add64(x171, x197, uint64(p384Uint1(x209)))
+       var x212 uint64
+       var x213 uint64
+       x212, x213 = bits.Add64(x173, x199, uint64(p384Uint1(x211)))
+       var x214 uint64
+       var x215 uint64
+       x214, x215 = bits.Add64(x175, x201, uint64(p384Uint1(x213)))
+       var x216 uint64
+       var x217 uint64
+       x216, x217 = bits.Add64(x177, x203, uint64(p384Uint1(x215)))
+       var x218 uint64
+       var x219 uint64
+       x218, x219 = bits.Add64(x179, x205, uint64(p384Uint1(x217)))
+       var x220 uint64
+       var x221 uint64
+       x220, x221 = bits.Add64(x181, x207, uint64(p384Uint1(x219)))
+       x222 := (uint64(p384Uint1(x221)) + uint64(p384Uint1(x182)))
+       var x223 uint64
+       var x224 uint64
+       x224, x223 = bits.Mul64(x3, arg1[5])
+       var x225 uint64
+       var x226 uint64
+       x226, x225 = bits.Mul64(x3, arg1[4])
+       var x227 uint64
+       var x228 uint64
+       x228, x227 = bits.Mul64(x3, arg1[3])
+       var x229 uint64
+       var x230 uint64
+       x230, x229 = bits.Mul64(x3, arg1[2])
+       var x231 uint64
+       var x232 uint64
+       x232, x231 = bits.Mul64(x3, arg1[1])
+       var x233 uint64
+       var x234 uint64
+       x234, x233 = bits.Mul64(x3, arg1[0])
+       var x235 uint64
+       var x236 uint64
+       x235, x236 = bits.Add64(x234, x231, uint64(0x0))
+       var x237 uint64
+       var x238 uint64
+       x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236)))
+       var x239 uint64
+       var x240 uint64
+       x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238)))
+       var x241 uint64
+       var x242 uint64
+       x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240)))
+       var x243 uint64
+       var x244 uint64
+       x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242)))
+       x245 := (uint64(p384Uint1(x244)) + x224)
+       var x246 uint64
+       var x247 uint64
+       x246, x247 = bits.Add64(x210, x233, uint64(0x0))
+       var x248 uint64
+       var x249 uint64
+       x248, x249 = bits.Add64(x212, x235, uint64(p384Uint1(x247)))
+       var x250 uint64
+       var x251 uint64
+       x250, x251 = bits.Add64(x214, x237, uint64(p384Uint1(x249)))
+       var x252 uint64
+       var x253 uint64
+       x252, x253 = bits.Add64(x216, x239, uint64(p384Uint1(x251)))
+       var x254 uint64
+       var x255 uint64
+       x254, x255 = bits.Add64(x218, x241, uint64(p384Uint1(x253)))
+       var x256 uint64
+       var x257 uint64
+       x256, x257 = bits.Add64(x220, x243, uint64(p384Uint1(x255)))
+       var x258 uint64
+       var x259 uint64
+       x258, x259 = bits.Add64(x222, x245, uint64(p384Uint1(x257)))
+       var x260 uint64
+       _, x260 = bits.Mul64(x246, 0x100000001)
+       var x262 uint64
+       var x263 uint64
+       x263, x262 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x264 uint64
+       var x265 uint64
+       x265, x264 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x266 uint64
+       var x267 uint64
+       x267, x266 = bits.Mul64(x260, 0xffffffffffffffff)
+       var x268 uint64
+       var x269 uint64
+       x269, x268 = bits.Mul64(x260, 0xfffffffffffffffe)
+       var x270 uint64
+       var x271 uint64
+       x271, x270 = bits.Mul64(x260, 0xffffffff00000000)
+       var x272 uint64
+       var x273 uint64
+       x273, x272 = bits.Mul64(x260, 0xffffffff)
+       var x274 uint64
+       var x275 uint64
+       x274, x275 = bits.Add64(x273, x270, uint64(0x0))
+       var x276 uint64
+       var x277 uint64
+       x276, x277 = bits.Add64(x271, x268, uint64(p384Uint1(x275)))
+       var x278 uint64
+       var x279 uint64
+       x278, x279 = bits.Add64(x269, x266, uint64(p384Uint1(x277)))
+       var x280 uint64
+       var x281 uint64
+       x280, x281 = bits.Add64(x267, x264, uint64(p384Uint1(x279)))
+       var x282 uint64
+       var x283 uint64
+       x282, x283 = bits.Add64(x265, x262, uint64(p384Uint1(x281)))
+       x284 := (uint64(p384Uint1(x283)) + x263)
+       var x286 uint64
+       _, x286 = bits.Add64(x246, x272, uint64(0x0))
+       var x287 uint64
+       var x288 uint64
+       x287, x288 = bits.Add64(x248, x274, uint64(p384Uint1(x286)))
+       var x289 uint64
+       var x290 uint64
+       x289, x290 = bits.Add64(x250, x276, uint64(p384Uint1(x288)))
+       var x291 uint64
+       var x292 uint64
+       x291, x292 = bits.Add64(x252, x278, uint64(p384Uint1(x290)))
+       var x293 uint64
+       var x294 uint64
+       x293, x294 = bits.Add64(x254, x280, uint64(p384Uint1(x292)))
+       var x295 uint64
+       var x296 uint64
+       x295, x296 = bits.Add64(x256, x282, uint64(p384Uint1(x294)))
+       var x297 uint64
+       var x298 uint64
+       x297, x298 = bits.Add64(x258, x284, uint64(p384Uint1(x296)))
+       x299 := (uint64(p384Uint1(x298)) + uint64(p384Uint1(x259)))
+       var x300 uint64
+       var x301 uint64
+       x301, x300 = bits.Mul64(x4, arg1[5])
+       var x302 uint64
+       var x303 uint64
+       x303, x302 = bits.Mul64(x4, arg1[4])
+       var x304 uint64
+       var x305 uint64
+       x305, x304 = bits.Mul64(x4, arg1[3])
+       var x306 uint64
+       var x307 uint64
+       x307, x306 = bits.Mul64(x4, arg1[2])
+       var x308 uint64
+       var x309 uint64
+       x309, x308 = bits.Mul64(x4, arg1[1])
+       var x310 uint64
+       var x311 uint64
+       x311, x310 = bits.Mul64(x4, arg1[0])
+       var x312 uint64
+       var x313 uint64
+       x312, x313 = bits.Add64(x311, x308, uint64(0x0))
+       var x314 uint64
+       var x315 uint64
+       x314, x315 = bits.Add64(x309, x306, uint64(p384Uint1(x313)))
+       var x316 uint64
+       var x317 uint64
+       x316, x317 = bits.Add64(x307, x304, uint64(p384Uint1(x315)))
+       var x318 uint64
+       var x319 uint64
+       x318, x319 = bits.Add64(x305, x302, uint64(p384Uint1(x317)))
+       var x320 uint64
+       var x321 uint64
+       x320, x321 = bits.Add64(x303, x300, uint64(p384Uint1(x319)))
+       x322 := (uint64(p384Uint1(x321)) + x301)
+       var x323 uint64
+       var x324 uint64
+       x323, x324 = bits.Add64(x287, x310, uint64(0x0))
+       var x325 uint64
+       var x326 uint64
+       x325, x326 = bits.Add64(x289, x312, uint64(p384Uint1(x324)))
+       var x327 uint64
+       var x328 uint64
+       x327, x328 = bits.Add64(x291, x314, uint64(p384Uint1(x326)))
+       var x329 uint64
+       var x330 uint64
+       x329, x330 = bits.Add64(x293, x316, uint64(p384Uint1(x328)))
+       var x331 uint64
+       var x332 uint64
+       x331, x332 = bits.Add64(x295, x318, uint64(p384Uint1(x330)))
+       var x333 uint64
+       var x334 uint64
+       x333, x334 = bits.Add64(x297, x320, uint64(p384Uint1(x332)))
+       var x335 uint64
+       var x336 uint64
+       x335, x336 = bits.Add64(x299, x322, uint64(p384Uint1(x334)))
+       var x337 uint64
+       _, x337 = bits.Mul64(x323, 0x100000001)
+       var x339 uint64
+       var x340 uint64
+       x340, x339 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x341 uint64
+       var x342 uint64
+       x342, x341 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x343 uint64
+       var x344 uint64
+       x344, x343 = bits.Mul64(x337, 0xffffffffffffffff)
+       var x345 uint64
+       var x346 uint64
+       x346, x345 = bits.Mul64(x337, 0xfffffffffffffffe)
+       var x347 uint64
+       var x348 uint64
+       x348, x347 = bits.Mul64(x337, 0xffffffff00000000)
+       var x349 uint64
+       var x350 uint64
+       x350, x349 = bits.Mul64(x337, 0xffffffff)
+       var x351 uint64
+       var x352 uint64
+       x351, x352 = bits.Add64(x350, x347, uint64(0x0))
+       var x353 uint64
+       var x354 uint64
+       x353, x354 = bits.Add64(x348, x345, uint64(p384Uint1(x352)))
+       var x355 uint64
+       var x356 uint64
+       x355, x356 = bits.Add64(x346, x343, uint64(p384Uint1(x354)))
+       var x357 uint64
+       var x358 uint64
+       x357, x358 = bits.Add64(x344, x341, uint64(p384Uint1(x356)))
+       var x359 uint64
+       var x360 uint64
+       x359, x360 = bits.Add64(x342, x339, uint64(p384Uint1(x358)))
+       x361 := (uint64(p384Uint1(x360)) + x340)
+       var x363 uint64
+       _, x363 = bits.Add64(x323, x349, uint64(0x0))
+       var x364 uint64
+       var x365 uint64
+       x364, x365 = bits.Add64(x325, x351, uint64(p384Uint1(x363)))
+       var x366 uint64
+       var x367 uint64
+       x366, x367 = bits.Add64(x327, x353, uint64(p384Uint1(x365)))
+       var x368 uint64
+       var x369 uint64
+       x368, x369 = bits.Add64(x329, x355, uint64(p384Uint1(x367)))
+       var x370 uint64
+       var x371 uint64
+       x370, x371 = bits.Add64(x331, x357, uint64(p384Uint1(x369)))
+       var x372 uint64
+       var x373 uint64
+       x372, x373 = bits.Add64(x333, x359, uint64(p384Uint1(x371)))
+       var x374 uint64
+       var x375 uint64
+       x374, x375 = bits.Add64(x335, x361, uint64(p384Uint1(x373)))
+       x376 := (uint64(p384Uint1(x375)) + uint64(p384Uint1(x336)))
+       var x377 uint64
+       var x378 uint64
+       x378, x377 = bits.Mul64(x5, arg1[5])
+       var x379 uint64
+       var x380 uint64
+       x380, x379 = bits.Mul64(x5, arg1[4])
+       var x381 uint64
+       var x382 uint64
+       x382, x381 = bits.Mul64(x5, arg1[3])
+       var x383 uint64
+       var x384 uint64
+       x384, x383 = bits.Mul64(x5, arg1[2])
+       var x385 uint64
+       var x386 uint64
+       x386, x385 = bits.Mul64(x5, arg1[1])
+       var x387 uint64
+       var x388 uint64
+       x388, x387 = bits.Mul64(x5, arg1[0])
+       var x389 uint64
+       var x390 uint64
+       x389, x390 = bits.Add64(x388, x385, uint64(0x0))
+       var x391 uint64
+       var x392 uint64
+       x391, x392 = bits.Add64(x386, x383, uint64(p384Uint1(x390)))
+       var x393 uint64
+       var x394 uint64
+       x393, x394 = bits.Add64(x384, x381, uint64(p384Uint1(x392)))
+       var x395 uint64
+       var x396 uint64
+       x395, x396 = bits.Add64(x382, x379, uint64(p384Uint1(x394)))
+       var x397 uint64
+       var x398 uint64
+       x397, x398 = bits.Add64(x380, x377, uint64(p384Uint1(x396)))
+       x399 := (uint64(p384Uint1(x398)) + x378)
+       var x400 uint64
+       var x401 uint64
+       x400, x401 = bits.Add64(x364, x387, uint64(0x0))
+       var x402 uint64
+       var x403 uint64
+       x402, x403 = bits.Add64(x366, x389, uint64(p384Uint1(x401)))
+       var x404 uint64
+       var x405 uint64
+       x404, x405 = bits.Add64(x368, x391, uint64(p384Uint1(x403)))
+       var x406 uint64
+       var x407 uint64
+       x406, x407 = bits.Add64(x370, x393, uint64(p384Uint1(x405)))
+       var x408 uint64
+       var x409 uint64
+       x408, x409 = bits.Add64(x372, x395, uint64(p384Uint1(x407)))
+       var x410 uint64
+       var x411 uint64
+       x410, x411 = bits.Add64(x374, x397, uint64(p384Uint1(x409)))
+       var x412 uint64
+       var x413 uint64
+       x412, x413 = bits.Add64(x376, x399, uint64(p384Uint1(x411)))
+       var x414 uint64
+       _, x414 = bits.Mul64(x400, 0x100000001)
+       var x416 uint64
+       var x417 uint64
+       x417, x416 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x418 uint64
+       var x419 uint64
+       x419, x418 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x420 uint64
+       var x421 uint64
+       x421, x420 = bits.Mul64(x414, 0xffffffffffffffff)
+       var x422 uint64
+       var x423 uint64
+       x423, x422 = bits.Mul64(x414, 0xfffffffffffffffe)
+       var x424 uint64
+       var x425 uint64
+       x425, x424 = bits.Mul64(x414, 0xffffffff00000000)
+       var x426 uint64
+       var x427 uint64
+       x427, x426 = bits.Mul64(x414, 0xffffffff)
+       var x428 uint64
+       var x429 uint64
+       x428, x429 = bits.Add64(x427, x424, uint64(0x0))
+       var x430 uint64
+       var x431 uint64
+       x430, x431 = bits.Add64(x425, x422, uint64(p384Uint1(x429)))
+       var x432 uint64
+       var x433 uint64
+       x432, x433 = bits.Add64(x423, x420, uint64(p384Uint1(x431)))
+       var x434 uint64
+       var x435 uint64
+       x434, x435 = bits.Add64(x421, x418, uint64(p384Uint1(x433)))
+       var x436 uint64
+       var x437 uint64
+       x436, x437 = bits.Add64(x419, x416, uint64(p384Uint1(x435)))
+       x438 := (uint64(p384Uint1(x437)) + x417)
+       var x440 uint64
+       _, x440 = bits.Add64(x400, x426, uint64(0x0))
+       var x441 uint64
+       var x442 uint64
+       x441, x442 = bits.Add64(x402, x428, uint64(p384Uint1(x440)))
+       var x443 uint64
+       var x444 uint64
+       x443, x444 = bits.Add64(x404, x430, uint64(p384Uint1(x442)))
+       var x445 uint64
+       var x446 uint64
+       x445, x446 = bits.Add64(x406, x432, uint64(p384Uint1(x444)))
+       var x447 uint64
+       var x448 uint64
+       x447, x448 = bits.Add64(x408, x434, uint64(p384Uint1(x446)))
+       var x449 uint64
+       var x450 uint64
+       x449, x450 = bits.Add64(x410, x436, uint64(p384Uint1(x448)))
+       var x451 uint64
+       var x452 uint64
+       x451, x452 = bits.Add64(x412, x438, uint64(p384Uint1(x450)))
+       x453 := (uint64(p384Uint1(x452)) + uint64(p384Uint1(x413)))
+       var x454 uint64
+       var x455 uint64
+       x454, x455 = bits.Sub64(x441, 0xffffffff, uint64(0x0))
+       var x456 uint64
+       var x457 uint64
+       x456, x457 = bits.Sub64(x443, 0xffffffff00000000, uint64(p384Uint1(x455)))
+       var x458 uint64
+       var x459 uint64
+       x458, x459 = bits.Sub64(x445, 0xfffffffffffffffe, uint64(p384Uint1(x457)))
+       var x460 uint64
+       var x461 uint64
+       x460, x461 = bits.Sub64(x447, 0xffffffffffffffff, uint64(p384Uint1(x459)))
+       var x462 uint64
+       var x463 uint64
+       x462, x463 = bits.Sub64(x449, 0xffffffffffffffff, uint64(p384Uint1(x461)))
+       var x464 uint64
+       var x465 uint64
+       x464, x465 = bits.Sub64(x451, 0xffffffffffffffff, uint64(p384Uint1(x463)))
+       var x467 uint64
+       _, x467 = bits.Sub64(x453, uint64(0x0), uint64(p384Uint1(x465)))
+       var x468 uint64
+       p384CmovznzU64(&x468, p384Uint1(x467), x454, x441)
+       var x469 uint64
+       p384CmovznzU64(&x469, p384Uint1(x467), x456, x443)
+       var x470 uint64
+       p384CmovznzU64(&x470, p384Uint1(x467), x458, x445)
+       var x471 uint64
+       p384CmovznzU64(&x471, p384Uint1(x467), x460, x447)
+       var x472 uint64
+       p384CmovznzU64(&x472, p384Uint1(x467), x462, x449)
+       var x473 uint64
+       p384CmovznzU64(&x473, p384Uint1(x467), x464, x451)
+       out1[0] = x468
+       out1[1] = x469
+       out1[2] = x470
+       out1[3] = x471
+       out1[4] = x472
+       out1[5] = x473
+}
+
+// p384Add adds two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+//   0 โ‰ค eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p384Add(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p384Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p384Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p384Uint1(x6)))
+       var x9 uint64
+       var x10 uint64
+       x9, x10 = bits.Add64(arg1[4], arg2[4], uint64(p384Uint1(x8)))
+       var x11 uint64
+       var x12 uint64
+       x11, x12 = bits.Add64(arg1[5], arg2[5], uint64(p384Uint1(x10)))
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Sub64(x1, 0xffffffff, uint64(0x0))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Sub64(x3, 0xffffffff00000000, uint64(p384Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Sub64(x5, 0xfffffffffffffffe, uint64(p384Uint1(x16)))
+       var x19 uint64
+       var x20 uint64
+       x19, x20 = bits.Sub64(x7, 0xffffffffffffffff, uint64(p384Uint1(x18)))
+       var x21 uint64
+       var x22 uint64
+       x21, x22 = bits.Sub64(x9, 0xffffffffffffffff, uint64(p384Uint1(x20)))
+       var x23 uint64
+       var x24 uint64
+       x23, x24 = bits.Sub64(x11, 0xffffffffffffffff, uint64(p384Uint1(x22)))
+       var x26 uint64
+       _, x26 = bits.Sub64(uint64(p384Uint1(x12)), uint64(0x0), uint64(p384Uint1(x24)))
+       var x27 uint64
+       p384CmovznzU64(&x27, p384Uint1(x26), x13, x1)
+       var x28 uint64
+       p384CmovznzU64(&x28, p384Uint1(x26), x15, x3)
+       var x29 uint64
+       p384CmovznzU64(&x29, p384Uint1(x26), x17, x5)
+       var x30 uint64
+       p384CmovznzU64(&x30, p384Uint1(x26), x19, x7)
+       var x31 uint64
+       p384CmovznzU64(&x31, p384Uint1(x26), x21, x9)
+       var x32 uint64
+       p384CmovznzU64(&x32, p384Uint1(x26), x23, x11)
+       out1[0] = x27
+       out1[1] = x28
+       out1[2] = x29
+       out1[3] = x30
+       out1[4] = x31
+       out1[5] = x32
+}
+
+// p384Sub subtracts two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+//   0 โ‰ค eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p384Sub(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p384Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p384Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p384Uint1(x6)))
+       var x9 uint64
+       var x10 uint64
+       x9, x10 = bits.Sub64(arg1[4], arg2[4], uint64(p384Uint1(x8)))
+       var x11 uint64
+       var x12 uint64
+       x11, x12 = bits.Sub64(arg1[5], arg2[5], uint64(p384Uint1(x10)))
+       var x13 uint64
+       p384CmovznzU64(&x13, p384Uint1(x12), uint64(0x0), 0xffffffffffffffff)
+       var x14 uint64
+       var x15 uint64
+       x14, x15 = bits.Add64(x1, (x13 & 0xffffffff), uint64(0x0))
+       var x16 uint64
+       var x17 uint64
+       x16, x17 = bits.Add64(x3, (x13 & 0xffffffff00000000), uint64(p384Uint1(x15)))
+       var x18 uint64
+       var x19 uint64
+       x18, x19 = bits.Add64(x5, (x13 & 0xfffffffffffffffe), uint64(p384Uint1(x17)))
+       var x20 uint64
+       var x21 uint64
+       x20, x21 = bits.Add64(x7, x13, uint64(p384Uint1(x19)))
+       var x22 uint64
+       var x23 uint64
+       x22, x23 = bits.Add64(x9, x13, uint64(p384Uint1(x21)))
+       var x24 uint64
+       x24, _ = bits.Add64(x11, x13, uint64(p384Uint1(x23)))
+       out1[0] = x14
+       out1[1] = x16
+       out1[2] = x18
+       out1[3] = x20
+       out1[4] = x22
+       out1[5] = x24
+}
+
+// p384SetOne returns the field element one in the Montgomery domain.
+//
+// Postconditions:
+//   eval (from_montgomery out1) mod m = 1 mod m
+//   0 โ‰ค eval out1 < m
+//
+func p384SetOne(out1 *p384MontgomeryDomainFieldElement) {
+       out1[0] = 0xffffffff00000001
+       out1[1] = 0xffffffff
+       out1[2] = uint64(0x1)
+       out1[3] = uint64(0x0)
+       out1[4] = uint64(0x0)
+       out1[5] = uint64(0x0)
+}
+
+// p384FromMontgomery translates a field element out of the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+// Postconditions:
+//   eval out1 mod m = (eval arg1 * ((2^64)โปยน mod m)^6) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p384FromMontgomery(out1 *p384NonMontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement) {
+       x1 := arg1[0]
+       var x2 uint64
+       _, x2 = bits.Mul64(x1, 0x100000001)
+       var x4 uint64
+       var x5 uint64
+       x5, x4 = bits.Mul64(x2, 0xffffffffffffffff)
+       var x6 uint64
+       var x7 uint64
+       x7, x6 = bits.Mul64(x2, 0xffffffffffffffff)
+       var x8 uint64
+       var x9 uint64
+       x9, x8 = bits.Mul64(x2, 0xffffffffffffffff)
+       var x10 uint64
+       var x11 uint64
+       x11, x10 = bits.Mul64(x2, 0xfffffffffffffffe)
+       var x12 uint64
+       var x13 uint64
+       x13, x12 = bits.Mul64(x2, 0xffffffff00000000)
+       var x14 uint64
+       var x15 uint64
+       x15, x14 = bits.Mul64(x2, 0xffffffff)
+       var x16 uint64
+       var x17 uint64
+       x16, x17 = bits.Add64(x15, x12, uint64(0x0))
+       var x18 uint64
+       var x19 uint64
+       x18, x19 = bits.Add64(x13, x10, uint64(p384Uint1(x17)))
+       var x20 uint64
+       var x21 uint64
+       x20, x21 = bits.Add64(x11, x8, uint64(p384Uint1(x19)))
+       var x22 uint64
+       var x23 uint64
+       x22, x23 = bits.Add64(x9, x6, uint64(p384Uint1(x21)))
+       var x24 uint64
+       var x25 uint64
+       x24, x25 = bits.Add64(x7, x4, uint64(p384Uint1(x23)))
+       var x27 uint64
+       _, x27 = bits.Add64(x1, x14, uint64(0x0))
+       var x28 uint64
+       var x29 uint64
+       x28, x29 = bits.Add64(uint64(0x0), x16, uint64(p384Uint1(x27)))
+       var x30 uint64
+       var x31 uint64
+       x30, x31 = bits.Add64(uint64(0x0), x18, uint64(p384Uint1(x29)))
+       var x32 uint64
+       var x33 uint64
+       x32, x33 = bits.Add64(uint64(0x0), x20, uint64(p384Uint1(x31)))
+       var x34 uint64
+       var x35 uint64
+       x34, x35 = bits.Add64(uint64(0x0), x22, uint64(p384Uint1(x33)))
+       var x36 uint64
+       var x37 uint64
+       x36, x37 = bits.Add64(uint64(0x0), x24, uint64(p384Uint1(x35)))
+       var x38 uint64
+       var x39 uint64
+       x38, x39 = bits.Add64(uint64(0x0), (uint64(p384Uint1(x25)) + x5), uint64(p384Uint1(x37)))
+       var x40 uint64
+       var x41 uint64
+       x40, x41 = bits.Add64(x28, arg1[1], uint64(0x0))
+       var x42 uint64
+       var x43 uint64
+       x42, x43 = bits.Add64(x30, uint64(0x0), uint64(p384Uint1(x41)))
+       var x44 uint64
+       var x45 uint64
+       x44, x45 = bits.Add64(x32, uint64(0x0), uint64(p384Uint1(x43)))
+       var x46 uint64
+       var x47 uint64
+       x46, x47 = bits.Add64(x34, uint64(0x0), uint64(p384Uint1(x45)))
+       var x48 uint64
+       var x49 uint64
+       x48, x49 = bits.Add64(x36, uint64(0x0), uint64(p384Uint1(x47)))
+       var x50 uint64
+       var x51 uint64
+       x50, x51 = bits.Add64(x38, uint64(0x0), uint64(p384Uint1(x49)))
+       var x52 uint64
+       _, x52 = bits.Mul64(x40, 0x100000001)
+       var x54 uint64
+       var x55 uint64
+       x55, x54 = bits.Mul64(x52, 0xffffffffffffffff)
+       var x56 uint64
+       var x57 uint64
+       x57, x56 = bits.Mul64(x52, 0xffffffffffffffff)
+       var x58 uint64
+       var x59 uint64
+       x59, x58 = bits.Mul64(x52, 0xffffffffffffffff)
+       var x60 uint64
+       var x61 uint64
+       x61, x60 = bits.Mul64(x52, 0xfffffffffffffffe)
+       var x62 uint64
+       var x63 uint64
+       x63, x62 = bits.Mul64(x52, 0xffffffff00000000)
+       var x64 uint64
+       var x65 uint64
+       x65, x64 = bits.Mul64(x52, 0xffffffff)
+       var x66 uint64
+       var x67 uint64
+       x66, x67 = bits.Add64(x65, x62, uint64(0x0))
+       var x68 uint64
+       var x69 uint64
+       x68, x69 = bits.Add64(x63, x60, uint64(p384Uint1(x67)))
+       var x70 uint64
+       var x71 uint64
+       x70, x71 = bits.Add64(x61, x58, uint64(p384Uint1(x69)))
+       var x72 uint64
+       var x73 uint64
+       x72, x73 = bits.Add64(x59, x56, uint64(p384Uint1(x71)))
+       var x74 uint64
+       var x75 uint64
+       x74, x75 = bits.Add64(x57, x54, uint64(p384Uint1(x73)))
+       var x77 uint64
+       _, x77 = bits.Add64(x40, x64, uint64(0x0))
+       var x78 uint64
+       var x79 uint64
+       x78, x79 = bits.Add64(x42, x66, uint64(p384Uint1(x77)))
+       var x80 uint64
+       var x81 uint64
+       x80, x81 = bits.Add64(x44, x68, uint64(p384Uint1(x79)))
+       var x82 uint64
+       var x83 uint64
+       x82, x83 = bits.Add64(x46, x70, uint64(p384Uint1(x81)))
+       var x84 uint64
+       var x85 uint64
+       x84, x85 = bits.Add64(x48, x72, uint64(p384Uint1(x83)))
+       var x86 uint64
+       var x87 uint64
+       x86, x87 = bits.Add64(x50, x74, uint64(p384Uint1(x85)))
+       var x88 uint64
+       var x89 uint64
+       x88, x89 = bits.Add64((uint64(p384Uint1(x51)) + uint64(p384Uint1(x39))), (uint64(p384Uint1(x75)) + x55), uint64(p384Uint1(x87)))
+       var x90 uint64
+       var x91 uint64
+       x90, x91 = bits.Add64(x78, arg1[2], uint64(0x0))
+       var x92 uint64
+       var x93 uint64
+       x92, x93 = bits.Add64(x80, uint64(0x0), uint64(p384Uint1(x91)))
+       var x94 uint64
+       var x95 uint64
+       x94, x95 = bits.Add64(x82, uint64(0x0), uint64(p384Uint1(x93)))
+       var x96 uint64
+       var x97 uint64
+       x96, x97 = bits.Add64(x84, uint64(0x0), uint64(p384Uint1(x95)))
+       var x98 uint64
+       var x99 uint64
+       x98, x99 = bits.Add64(x86, uint64(0x0), uint64(p384Uint1(x97)))
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x88, uint64(0x0), uint64(p384Uint1(x99)))
+       var x102 uint64
+       _, x102 = bits.Mul64(x90, 0x100000001)
+       var x104 uint64
+       var x105 uint64
+       x105, x104 = bits.Mul64(x102, 0xffffffffffffffff)
+       var x106 uint64
+       var x107 uint64
+       x107, x106 = bits.Mul64(x102, 0xffffffffffffffff)
+       var x108 uint64
+       var x109 uint64
+       x109, x108 = bits.Mul64(x102, 0xffffffffffffffff)
+       var x110 uint64
+       var x111 uint64
+       x111, x110 = bits.Mul64(x102, 0xfffffffffffffffe)
+       var x112 uint64
+       var x113 uint64
+       x113, x112 = bits.Mul64(x102, 0xffffffff00000000)
+       var x114 uint64
+       var x115 uint64
+       x115, x114 = bits.Mul64(x102, 0xffffffff)
+       var x116 uint64
+       var x117 uint64
+       x116, x117 = bits.Add64(x115, x112, uint64(0x0))
+       var x118 uint64
+       var x119 uint64
+       x118, x119 = bits.Add64(x113, x110, uint64(p384Uint1(x117)))
+       var x120 uint64
+       var x121 uint64
+       x120, x121 = bits.Add64(x111, x108, uint64(p384Uint1(x119)))
+       var x122 uint64
+       var x123 uint64
+       x122, x123 = bits.Add64(x109, x106, uint64(p384Uint1(x121)))
+       var x124 uint64
+       var x125 uint64
+       x124, x125 = bits.Add64(x107, x104, uint64(p384Uint1(x123)))
+       var x127 uint64
+       _, x127 = bits.Add64(x90, x114, uint64(0x0))
+       var x128 uint64
+       var x129 uint64
+       x128, x129 = bits.Add64(x92, x116, uint64(p384Uint1(x127)))
+       var x130 uint64
+       var x131 uint64
+       x130, x131 = bits.Add64(x94, x118, uint64(p384Uint1(x129)))
+       var x132 uint64
+       var x133 uint64
+       x132, x133 = bits.Add64(x96, x120, uint64(p384Uint1(x131)))
+       var x134 uint64
+       var x135 uint64
+       x134, x135 = bits.Add64(x98, x122, uint64(p384Uint1(x133)))
+       var x136 uint64
+       var x137 uint64
+       x136, x137 = bits.Add64(x100, x124, uint64(p384Uint1(x135)))
+       var x138 uint64
+       var x139 uint64
+       x138, x139 = bits.Add64((uint64(p384Uint1(x101)) + uint64(p384Uint1(x89))), (uint64(p384Uint1(x125)) + x105), uint64(p384Uint1(x137)))
+       var x140 uint64
+       var x141 uint64
+       x140, x141 = bits.Add64(x128, arg1[3], uint64(0x0))
+       var x142 uint64
+       var x143 uint64
+       x142, x143 = bits.Add64(x130, uint64(0x0), uint64(p384Uint1(x141)))
+       var x144 uint64
+       var x145 uint64
+       x144, x145 = bits.Add64(x132, uint64(0x0), uint64(p384Uint1(x143)))
+       var x146 uint64
+       var x147 uint64
+       x146, x147 = bits.Add64(x134, uint64(0x0), uint64(p384Uint1(x145)))
+       var x148 uint64
+       var x149 uint64
+       x148, x149 = bits.Add64(x136, uint64(0x0), uint64(p384Uint1(x147)))
+       var x150 uint64
+       var x151 uint64
+       x150, x151 = bits.Add64(x138, uint64(0x0), uint64(p384Uint1(x149)))
+       var x152 uint64
+       _, x152 = bits.Mul64(x140, 0x100000001)
+       var x154 uint64
+       var x155 uint64
+       x155, x154 = bits.Mul64(x152, 0xffffffffffffffff)
+       var x156 uint64
+       var x157 uint64
+       x157, x156 = bits.Mul64(x152, 0xffffffffffffffff)
+       var x158 uint64
+       var x159 uint64
+       x159, x158 = bits.Mul64(x152, 0xffffffffffffffff)
+       var x160 uint64
+       var x161 uint64
+       x161, x160 = bits.Mul64(x152, 0xfffffffffffffffe)
+       var x162 uint64
+       var x163 uint64
+       x163, x162 = bits.Mul64(x152, 0xffffffff00000000)
+       var x164 uint64
+       var x165 uint64
+       x165, x164 = bits.Mul64(x152, 0xffffffff)
+       var x166 uint64
+       var x167 uint64
+       x166, x167 = bits.Add64(x165, x162, uint64(0x0))
+       var x168 uint64
+       var x169 uint64
+       x168, x169 = bits.Add64(x163, x160, uint64(p384Uint1(x167)))
+       var x170 uint64
+       var x171 uint64
+       x170, x171 = bits.Add64(x161, x158, uint64(p384Uint1(x169)))
+       var x172 uint64
+       var x173 uint64
+       x172, x173 = bits.Add64(x159, x156, uint64(p384Uint1(x171)))
+       var x174 uint64
+       var x175 uint64
+       x174, x175 = bits.Add64(x157, x154, uint64(p384Uint1(x173)))
+       var x177 uint64
+       _, x177 = bits.Add64(x140, x164, uint64(0x0))
+       var x178 uint64
+       var x179 uint64
+       x178, x179 = bits.Add64(x142, x166, uint64(p384Uint1(x177)))
+       var x180 uint64
+       var x181 uint64
+       x180, x181 = bits.Add64(x144, x168, uint64(p384Uint1(x179)))
+       var x182 uint64
+       var x183 uint64
+       x182, x183 = bits.Add64(x146, x170, uint64(p384Uint1(x181)))
+       var x184 uint64
+       var x185 uint64
+       x184, x185 = bits.Add64(x148, x172, uint64(p384Uint1(x183)))
+       var x186 uint64
+       var x187 uint64
+       x186, x187 = bits.Add64(x150, x174, uint64(p384Uint1(x185)))
+       var x188 uint64
+       var x189 uint64
+       x188, x189 = bits.Add64((uint64(p384Uint1(x151)) + uint64(p384Uint1(x139))), (uint64(p384Uint1(x175)) + x155), uint64(p384Uint1(x187)))
+       var x190 uint64
+       var x191 uint64
+       x190, x191 = bits.Add64(x178, arg1[4], uint64(0x0))
+       var x192 uint64
+       var x193 uint64
+       x192, x193 = bits.Add64(x180, uint64(0x0), uint64(p384Uint1(x191)))
+       var x194 uint64
+       var x195 uint64
+       x194, x195 = bits.Add64(x182, uint64(0x0), uint64(p384Uint1(x193)))
+       var x196 uint64
+       var x197 uint64
+       x196, x197 = bits.Add64(x184, uint64(0x0), uint64(p384Uint1(x195)))
+       var x198 uint64
+       var x199 uint64
+       x198, x199 = bits.Add64(x186, uint64(0x0), uint64(p384Uint1(x197)))
+       var x200 uint64
+       var x201 uint64
+       x200, x201 = bits.Add64(x188, uint64(0x0), uint64(p384Uint1(x199)))
+       var x202 uint64
+       _, x202 = bits.Mul64(x190, 0x100000001)
+       var x204 uint64
+       var x205 uint64
+       x205, x204 = bits.Mul64(x202, 0xffffffffffffffff)
+       var x206 uint64
+       var x207 uint64
+       x207, x206 = bits.Mul64(x202, 0xffffffffffffffff)
+       var x208 uint64
+       var x209 uint64
+       x209, x208 = bits.Mul64(x202, 0xffffffffffffffff)
+       var x210 uint64
+       var x211 uint64
+       x211, x210 = bits.Mul64(x202, 0xfffffffffffffffe)
+       var x212 uint64
+       var x213 uint64
+       x213, x212 = bits.Mul64(x202, 0xffffffff00000000)
+       var x214 uint64
+       var x215 uint64
+       x215, x214 = bits.Mul64(x202, 0xffffffff)
+       var x216 uint64
+       var x217 uint64
+       x216, x217 = bits.Add64(x215, x212, uint64(0x0))
+       var x218 uint64
+       var x219 uint64
+       x218, x219 = bits.Add64(x213, x210, uint64(p384Uint1(x217)))
+       var x220 uint64
+       var x221 uint64
+       x220, x221 = bits.Add64(x211, x208, uint64(p384Uint1(x219)))
+       var x222 uint64
+       var x223 uint64
+       x222, x223 = bits.Add64(x209, x206, uint64(p384Uint1(x221)))
+       var x224 uint64
+       var x225 uint64
+       x224, x225 = bits.Add64(x207, x204, uint64(p384Uint1(x223)))
+       var x227 uint64
+       _, x227 = bits.Add64(x190, x214, uint64(0x0))
+       var x228 uint64
+       var x229 uint64
+       x228, x229 = bits.Add64(x192, x216, uint64(p384Uint1(x227)))
+       var x230 uint64
+       var x231 uint64
+       x230, x231 = bits.Add64(x194, x218, uint64(p384Uint1(x229)))
+       var x232 uint64
+       var x233 uint64
+       x232, x233 = bits.Add64(x196, x220, uint64(p384Uint1(x231)))
+       var x234 uint64
+       var x235 uint64
+       x234, x235 = bits.Add64(x198, x222, uint64(p384Uint1(x233)))
+       var x236 uint64
+       var x237 uint64
+       x236, x237 = bits.Add64(x200, x224, uint64(p384Uint1(x235)))
+       var x238 uint64
+       var x239 uint64
+       x238, x239 = bits.Add64((uint64(p384Uint1(x201)) + uint64(p384Uint1(x189))), (uint64(p384Uint1(x225)) + x205), uint64(p384Uint1(x237)))
+       var x240 uint64
+       var x241 uint64
+       x240, x241 = bits.Add64(x228, arg1[5], uint64(0x0))
+       var x242 uint64
+       var x243 uint64
+       x242, x243 = bits.Add64(x230, uint64(0x0), uint64(p384Uint1(x241)))
+       var x244 uint64
+       var x245 uint64
+       x244, x245 = bits.Add64(x232, uint64(0x0), uint64(p384Uint1(x243)))
+       var x246 uint64
+       var x247 uint64
+       x246, x247 = bits.Add64(x234, uint64(0x0), uint64(p384Uint1(x245)))
+       var x248 uint64
+       var x249 uint64
+       x248, x249 = bits.Add64(x236, uint64(0x0), uint64(p384Uint1(x247)))
+       var x250 uint64
+       var x251 uint64
+       x250, x251 = bits.Add64(x238, uint64(0x0), uint64(p384Uint1(x249)))
+       var x252 uint64
+       _, x252 = bits.Mul64(x240, 0x100000001)
+       var x254 uint64
+       var x255 uint64
+       x255, x254 = bits.Mul64(x252, 0xffffffffffffffff)
+       var x256 uint64
+       var x257 uint64
+       x257, x256 = bits.Mul64(x252, 0xffffffffffffffff)
+       var x258 uint64
+       var x259 uint64
+       x259, x258 = bits.Mul64(x252, 0xffffffffffffffff)
+       var x260 uint64
+       var x261 uint64
+       x261, x260 = bits.Mul64(x252, 0xfffffffffffffffe)
+       var x262 uint64
+       var x263 uint64
+       x263, x262 = bits.Mul64(x252, 0xffffffff00000000)
+       var x264 uint64
+       var x265 uint64
+       x265, x264 = bits.Mul64(x252, 0xffffffff)
+       var x266 uint64
+       var x267 uint64
+       x266, x267 = bits.Add64(x265, x262, uint64(0x0))
+       var x268 uint64
+       var x269 uint64
+       x268, x269 = bits.Add64(x263, x260, uint64(p384Uint1(x267)))
+       var x270 uint64
+       var x271 uint64
+       x270, x271 = bits.Add64(x261, x258, uint64(p384Uint1(x269)))
+       var x272 uint64
+       var x273 uint64
+       x272, x273 = bits.Add64(x259, x256, uint64(p384Uint1(x271)))
+       var x274 uint64
+       var x275 uint64
+       x274, x275 = bits.Add64(x257, x254, uint64(p384Uint1(x273)))
+       var x277 uint64
+       _, x277 = bits.Add64(x240, x264, uint64(0x0))
+       var x278 uint64
+       var x279 uint64
+       x278, x279 = bits.Add64(x242, x266, uint64(p384Uint1(x277)))
+       var x280 uint64
+       var x281 uint64
+       x280, x281 = bits.Add64(x244, x268, uint64(p384Uint1(x279)))
+       var x282 uint64
+       var x283 uint64
+       x282, x283 = bits.Add64(x246, x270, uint64(p384Uint1(x281)))
+       var x284 uint64
+       var x285 uint64
+       x284, x285 = bits.Add64(x248, x272, uint64(p384Uint1(x283)))
+       var x286 uint64
+       var x287 uint64
+       x286, x287 = bits.Add64(x250, x274, uint64(p384Uint1(x285)))
+       var x288 uint64
+       var x289 uint64
+       x288, x289 = bits.Add64((uint64(p384Uint1(x251)) + uint64(p384Uint1(x239))), (uint64(p384Uint1(x275)) + x255), uint64(p384Uint1(x287)))
+       var x290 uint64
+       var x291 uint64
+       x290, x291 = bits.Sub64(x278, 0xffffffff, uint64(0x0))
+       var x292 uint64
+       var x293 uint64
+       x292, x293 = bits.Sub64(x280, 0xffffffff00000000, uint64(p384Uint1(x291)))
+       var x294 uint64
+       var x295 uint64
+       x294, x295 = bits.Sub64(x282, 0xfffffffffffffffe, uint64(p384Uint1(x293)))
+       var x296 uint64
+       var x297 uint64
+       x296, x297 = bits.Sub64(x284, 0xffffffffffffffff, uint64(p384Uint1(x295)))
+       var x298 uint64
+       var x299 uint64
+       x298, x299 = bits.Sub64(x286, 0xffffffffffffffff, uint64(p384Uint1(x297)))
+       var x300 uint64
+       var x301 uint64
+       x300, x301 = bits.Sub64(x288, 0xffffffffffffffff, uint64(p384Uint1(x299)))
+       var x303 uint64
+       _, x303 = bits.Sub64(uint64(p384Uint1(x289)), uint64(0x0), uint64(p384Uint1(x301)))
+       var x304 uint64
+       p384CmovznzU64(&x304, p384Uint1(x303), x290, x278)
+       var x305 uint64
+       p384CmovznzU64(&x305, p384Uint1(x303), x292, x280)
+       var x306 uint64
+       p384CmovznzU64(&x306, p384Uint1(x303), x294, x282)
+       var x307 uint64
+       p384CmovznzU64(&x307, p384Uint1(x303), x296, x284)
+       var x308 uint64
+       p384CmovznzU64(&x308, p384Uint1(x303), x298, x286)
+       var x309 uint64
+       p384CmovznzU64(&x309, p384Uint1(x303), x300, x288)
+       out1[0] = x304
+       out1[1] = x305
+       out1[2] = x306
+       out1[3] = x307
+       out1[4] = x308
+       out1[5] = x309
+}
+
+// p384ToMontgomery translates a field element into the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = eval arg1 mod m
+//   0 โ‰ค eval out1 < m
+//
+func p384ToMontgomery(out1 *p384MontgomeryDomainFieldElement, arg1 *p384NonMontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[4]
+       x5 := arg1[5]
+       x6 := arg1[0]
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x6, 0x200000000)
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x6, 0xfffffffe00000000)
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x6, 0x200000000)
+       var x13 uint64
+       var x14 uint64
+       x14, x13 = bits.Mul64(x6, 0xfffffffe00000001)
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Add64(x14, x11, uint64(0x0))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Add64(x12, x9, uint64(p384Uint1(x16)))
+       var x19 uint64
+       var x20 uint64
+       x19, x20 = bits.Add64(x10, x7, uint64(p384Uint1(x18)))
+       var x21 uint64
+       var x22 uint64
+       x21, x22 = bits.Add64(x8, x6, uint64(p384Uint1(x20)))
+       var x23 uint64
+       _, x23 = bits.Mul64(x13, 0x100000001)
+       var x25 uint64
+       var x26 uint64
+       x26, x25 = bits.Mul64(x23, 0xffffffffffffffff)
+       var x27 uint64
+       var x28 uint64
+       x28, x27 = bits.Mul64(x23, 0xffffffffffffffff)
+       var x29 uint64
+       var x30 uint64
+       x30, x29 = bits.Mul64(x23, 0xffffffffffffffff)
+       var x31 uint64
+       var x32 uint64
+       x32, x31 = bits.Mul64(x23, 0xfffffffffffffffe)
+       var x33 uint64
+       var x34 uint64
+       x34, x33 = bits.Mul64(x23, 0xffffffff00000000)
+       var x35 uint64
+       var x36 uint64
+       x36, x35 = bits.Mul64(x23, 0xffffffff)
+       var x37 uint64
+       var x38 uint64
+       x37, x38 = bits.Add64(x36, x33, uint64(0x0))
+       var x39 uint64
+       var x40 uint64
+       x39, x40 = bits.Add64(x34, x31, uint64(p384Uint1(x38)))
+       var x41 uint64
+       var x42 uint64
+       x41, x42 = bits.Add64(x32, x29, uint64(p384Uint1(x40)))
+       var x43 uint64
+       var x44 uint64
+       x43, x44 = bits.Add64(x30, x27, uint64(p384Uint1(x42)))
+       var x45 uint64
+       var x46 uint64
+       x45, x46 = bits.Add64(x28, x25, uint64(p384Uint1(x44)))
+       var x48 uint64
+       _, x48 = bits.Add64(x13, x35, uint64(0x0))
+       var x49 uint64
+       var x50 uint64
+       x49, x50 = bits.Add64(x15, x37, uint64(p384Uint1(x48)))
+       var x51 uint64
+       var x52 uint64
+       x51, x52 = bits.Add64(x17, x39, uint64(p384Uint1(x50)))
+       var x53 uint64
+       var x54 uint64
+       x53, x54 = bits.Add64(x19, x41, uint64(p384Uint1(x52)))
+       var x55 uint64
+       var x56 uint64
+       x55, x56 = bits.Add64(x21, x43, uint64(p384Uint1(x54)))
+       var x57 uint64
+       var x58 uint64
+       x57, x58 = bits.Add64(uint64(p384Uint1(x22)), x45, uint64(p384Uint1(x56)))
+       var x59 uint64
+       var x60 uint64
+       x59, x60 = bits.Add64(uint64(0x0), (uint64(p384Uint1(x46)) + x26), uint64(p384Uint1(x58)))
+       var x61 uint64
+       var x62 uint64
+       x62, x61 = bits.Mul64(x1, 0x200000000)
+       var x63 uint64
+       var x64 uint64
+       x64, x63 = bits.Mul64(x1, 0xfffffffe00000000)
+       var x65 uint64
+       var x66 uint64
+       x66, x65 = bits.Mul64(x1, 0x200000000)
+       var x67 uint64
+       var x68 uint64
+       x68, x67 = bits.Mul64(x1, 0xfffffffe00000001)
+       var x69 uint64
+       var x70 uint64
+       x69, x70 = bits.Add64(x68, x65, uint64(0x0))
+       var x71 uint64
+       var x72 uint64
+       x71, x72 = bits.Add64(x66, x63, uint64(p384Uint1(x70)))
+       var x73 uint64
+       var x74 uint64
+       x73, x74 = bits.Add64(x64, x61, uint64(p384Uint1(x72)))
+       var x75 uint64
+       var x76 uint64
+       x75, x76 = bits.Add64(x62, x1, uint64(p384Uint1(x74)))
+       var x77 uint64
+       var x78 uint64
+       x77, x78 = bits.Add64(x49, x67, uint64(0x0))
+       var x79 uint64
+       var x80 uint64
+       x79, x80 = bits.Add64(x51, x69, uint64(p384Uint1(x78)))
+       var x81 uint64
+       var x82 uint64
+       x81, x82 = bits.Add64(x53, x71, uint64(p384Uint1(x80)))
+       var x83 uint64
+       var x84 uint64
+       x83, x84 = bits.Add64(x55, x73, uint64(p384Uint1(x82)))
+       var x85 uint64
+       var x86 uint64
+       x85, x86 = bits.Add64(x57, x75, uint64(p384Uint1(x84)))
+       var x87 uint64
+       var x88 uint64
+       x87, x88 = bits.Add64(x59, uint64(p384Uint1(x76)), uint64(p384Uint1(x86)))
+       var x89 uint64
+       _, x89 = bits.Mul64(x77, 0x100000001)
+       var x91 uint64
+       var x92 uint64
+       x92, x91 = bits.Mul64(x89, 0xffffffffffffffff)
+       var x93 uint64
+       var x94 uint64
+       x94, x93 = bits.Mul64(x89, 0xffffffffffffffff)
+       var x95 uint64
+       var x96 uint64
+       x96, x95 = bits.Mul64(x89, 0xffffffffffffffff)
+       var x97 uint64
+       var x98 uint64
+       x98, x97 = bits.Mul64(x89, 0xfffffffffffffffe)
+       var x99 uint64
+       var x100 uint64
+       x100, x99 = bits.Mul64(x89, 0xffffffff00000000)
+       var x101 uint64
+       var x102 uint64
+       x102, x101 = bits.Mul64(x89, 0xffffffff)
+       var x103 uint64
+       var x104 uint64
+       x103, x104 = bits.Add64(x102, x99, uint64(0x0))
+       var x105 uint64
+       var x106 uint64
+       x105, x106 = bits.Add64(x100, x97, uint64(p384Uint1(x104)))
+       var x107 uint64
+       var x108 uint64
+       x107, x108 = bits.Add64(x98, x95, uint64(p384Uint1(x106)))
+       var x109 uint64
+       var x110 uint64
+       x109, x110 = bits.Add64(x96, x93, uint64(p384Uint1(x108)))
+       var x111 uint64
+       var x112 uint64
+       x111, x112 = bits.Add64(x94, x91, uint64(p384Uint1(x110)))
+       var x114 uint64
+       _, x114 = bits.Add64(x77, x101, uint64(0x0))
+       var x115 uint64
+       var x116 uint64
+       x115, x116 = bits.Add64(x79, x103, uint64(p384Uint1(x114)))
+       var x117 uint64
+       var x118 uint64
+       x117, x118 = bits.Add64(x81, x105, uint64(p384Uint1(x116)))
+       var x119 uint64
+       var x120 uint64
+       x119, x120 = bits.Add64(x83, x107, uint64(p384Uint1(x118)))
+       var x121 uint64
+       var x122 uint64
+       x121, x122 = bits.Add64(x85, x109, uint64(p384Uint1(x120)))
+       var x123 uint64
+       var x124 uint64
+       x123, x124 = bits.Add64(x87, x111, uint64(p384Uint1(x122)))
+       var x125 uint64
+       var x126 uint64
+       x125, x126 = bits.Add64((uint64(p384Uint1(x88)) + uint64(p384Uint1(x60))), (uint64(p384Uint1(x112)) + x92), uint64(p384Uint1(x124)))
+       var x127 uint64
+       var x128 uint64
+       x128, x127 = bits.Mul64(x2, 0x200000000)
+       var x129 uint64
+       var x130 uint64
+       x130, x129 = bits.Mul64(x2, 0xfffffffe00000000)
+       var x131 uint64
+       var x132 uint64
+       x132, x131 = bits.Mul64(x2, 0x200000000)
+       var x133 uint64
+       var x134 uint64
+       x134, x133 = bits.Mul64(x2, 0xfffffffe00000001)
+       var x135 uint64
+       var x136 uint64
+       x135, x136 = bits.Add64(x134, x131, uint64(0x0))
+       var x137 uint64
+       var x138 uint64
+       x137, x138 = bits.Add64(x132, x129, uint64(p384Uint1(x136)))
+       var x139 uint64
+       var x140 uint64
+       x139, x140 = bits.Add64(x130, x127, uint64(p384Uint1(x138)))
+       var x141 uint64
+       var x142 uint64
+       x141, x142 = bits.Add64(x128, x2, uint64(p384Uint1(x140)))
+       var x143 uint64
+       var x144 uint64
+       x143, x144 = bits.Add64(x115, x133, uint64(0x0))
+       var x145 uint64
+       var x146 uint64
+       x145, x146 = bits.Add64(x117, x135, uint64(p384Uint1(x144)))
+       var x147 uint64
+       var x148 uint64
+       x147, x148 = bits.Add64(x119, x137, uint64(p384Uint1(x146)))
+       var x149 uint64
+       var x150 uint64
+       x149, x150 = bits.Add64(x121, x139, uint64(p384Uint1(x148)))
+       var x151 uint64
+       var x152 uint64
+       x151, x152 = bits.Add64(x123, x141, uint64(p384Uint1(x150)))
+       var x153 uint64
+       var x154 uint64
+       x153, x154 = bits.Add64(x125, uint64(p384Uint1(x142)), uint64(p384Uint1(x152)))
+       var x155 uint64
+       _, x155 = bits.Mul64(x143, 0x100000001)
+       var x157 uint64
+       var x158 uint64
+       x158, x157 = bits.Mul64(x155, 0xffffffffffffffff)
+       var x159 uint64
+       var x160 uint64
+       x160, x159 = bits.Mul64(x155, 0xffffffffffffffff)
+       var x161 uint64
+       var x162 uint64
+       x162, x161 = bits.Mul64(x155, 0xffffffffffffffff)
+       var x163 uint64
+       var x164 uint64
+       x164, x163 = bits.Mul64(x155, 0xfffffffffffffffe)
+       var x165 uint64
+       var x166 uint64
+       x166, x165 = bits.Mul64(x155, 0xffffffff00000000)
+       var x167 uint64
+       var x168 uint64
+       x168, x167 = bits.Mul64(x155, 0xffffffff)
+       var x169 uint64
+       var x170 uint64
+       x169, x170 = bits.Add64(x168, x165, uint64(0x0))
+       var x171 uint64
+       var x172 uint64
+       x171, x172 = bits.Add64(x166, x163, uint64(p384Uint1(x170)))
+       var x173 uint64
+       var x174 uint64
+       x173, x174 = bits.Add64(x164, x161, uint64(p384Uint1(x172)))
+       var x175 uint64
+       var x176 uint64
+       x175, x176 = bits.Add64(x162, x159, uint64(p384Uint1(x174)))
+       var x177 uint64
+       var x178 uint64
+       x177, x178 = bits.Add64(x160, x157, uint64(p384Uint1(x176)))
+       var x180 uint64
+       _, x180 = bits.Add64(x143, x167, uint64(0x0))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x145, x169, uint64(p384Uint1(x180)))
+       var x183 uint64
+       var x184 uint64
+       x183, x184 = bits.Add64(x147, x171, uint64(p384Uint1(x182)))
+       var x185 uint64
+       var x186 uint64
+       x185, x186 = bits.Add64(x149, x173, uint64(p384Uint1(x184)))
+       var x187 uint64
+       var x188 uint64
+       x187, x188 = bits.Add64(x151, x175, uint64(p384Uint1(x186)))
+       var x189 uint64
+       var x190 uint64
+       x189, x190 = bits.Add64(x153, x177, uint64(p384Uint1(x188)))
+       var x191 uint64
+       var x192 uint64
+       x191, x192 = bits.Add64((uint64(p384Uint1(x154)) + uint64(p384Uint1(x126))), (uint64(p384Uint1(x178)) + x158), uint64(p384Uint1(x190)))
+       var x193 uint64
+       var x194 uint64
+       x194, x193 = bits.Mul64(x3, 0x200000000)
+       var x195 uint64
+       var x196 uint64
+       x196, x195 = bits.Mul64(x3, 0xfffffffe00000000)
+       var x197 uint64
+       var x198 uint64
+       x198, x197 = bits.Mul64(x3, 0x200000000)
+       var x199 uint64
+       var x200 uint64
+       x200, x199 = bits.Mul64(x3, 0xfffffffe00000001)
+       var x201 uint64
+       var x202 uint64
+       x201, x202 = bits.Add64(x200, x197, uint64(0x0))
+       var x203 uint64
+       var x204 uint64
+       x203, x204 = bits.Add64(x198, x195, uint64(p384Uint1(x202)))
+       var x205 uint64
+       var x206 uint64
+       x205, x206 = bits.Add64(x196, x193, uint64(p384Uint1(x204)))
+       var x207 uint64
+       var x208 uint64
+       x207, x208 = bits.Add64(x194, x3, uint64(p384Uint1(x206)))
+       var x209 uint64
+       var x210 uint64
+       x209, x210 = bits.Add64(x181, x199, uint64(0x0))
+       var x211 uint64
+       var x212 uint64
+       x211, x212 = bits.Add64(x183, x201, uint64(p384Uint1(x210)))
+       var x213 uint64
+       var x214 uint64
+       x213, x214 = bits.Add64(x185, x203, uint64(p384Uint1(x212)))
+       var x215 uint64
+       var x216 uint64
+       x215, x216 = bits.Add64(x187, x205, uint64(p384Uint1(x214)))
+       var x217 uint64
+       var x218 uint64
+       x217, x218 = bits.Add64(x189, x207, uint64(p384Uint1(x216)))
+       var x219 uint64
+       var x220 uint64
+       x219, x220 = bits.Add64(x191, uint64(p384Uint1(x208)), uint64(p384Uint1(x218)))
+       var x221 uint64
+       _, x221 = bits.Mul64(x209, 0x100000001)
+       var x223 uint64
+       var x224 uint64
+       x224, x223 = bits.Mul64(x221, 0xffffffffffffffff)
+       var x225 uint64
+       var x226 uint64
+       x226, x225 = bits.Mul64(x221, 0xffffffffffffffff)
+       var x227 uint64
+       var x228 uint64
+       x228, x227 = bits.Mul64(x221, 0xffffffffffffffff)
+       var x229 uint64
+       var x230 uint64
+       x230, x229 = bits.Mul64(x221, 0xfffffffffffffffe)
+       var x231 uint64
+       var x232 uint64
+       x232, x231 = bits.Mul64(x221, 0xffffffff00000000)
+       var x233 uint64
+       var x234 uint64
+       x234, x233 = bits.Mul64(x221, 0xffffffff)
+       var x235 uint64
+       var x236 uint64
+       x235, x236 = bits.Add64(x234, x231, uint64(0x0))
+       var x237 uint64
+       var x238 uint64
+       x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236)))
+       var x239 uint64
+       var x240 uint64
+       x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238)))
+       var x241 uint64
+       var x242 uint64
+       x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240)))
+       var x243 uint64
+       var x244 uint64
+       x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242)))
+       var x246 uint64
+       _, x246 = bits.Add64(x209, x233, uint64(0x0))
+       var x247 uint64
+       var x248 uint64
+       x247, x248 = bits.Add64(x211, x235, uint64(p384Uint1(x246)))
+       var x249 uint64
+       var x250 uint64
+       x249, x250 = bits.Add64(x213, x237, uint64(p384Uint1(x248)))
+       var x251 uint64
+       var x252 uint64
+       x251, x252 = bits.Add64(x215, x239, uint64(p384Uint1(x250)))
+       var x253 uint64
+       var x254 uint64
+       x253, x254 = bits.Add64(x217, x241, uint64(p384Uint1(x252)))
+       var x255 uint64
+       var x256 uint64
+       x255, x256 = bits.Add64(x219, x243, uint64(p384Uint1(x254)))
+       var x257 uint64
+       var x258 uint64
+       x257, x258 = bits.Add64((uint64(p384Uint1(x220)) + uint64(p384Uint1(x192))), (uint64(p384Uint1(x244)) + x224), uint64(p384Uint1(x256)))
+       var x259 uint64
+       var x260 uint64
+       x260, x259 = bits.Mul64(x4, 0x200000000)
+       var x261 uint64
+       var x262 uint64
+       x262, x261 = bits.Mul64(x4, 0xfffffffe00000000)
+       var x263 uint64
+       var x264 uint64
+       x264, x263 = bits.Mul64(x4, 0x200000000)
+       var x265 uint64
+       var x266 uint64
+       x266, x265 = bits.Mul64(x4, 0xfffffffe00000001)
+       var x267 uint64
+       var x268 uint64
+       x267, x268 = bits.Add64(x266, x263, uint64(0x0))
+       var x269 uint64
+       var x270 uint64
+       x269, x270 = bits.Add64(x264, x261, uint64(p384Uint1(x268)))
+       var x271 uint64
+       var x272 uint64
+       x271, x272 = bits.Add64(x262, x259, uint64(p384Uint1(x270)))
+       var x273 uint64
+       var x274 uint64
+       x273, x274 = bits.Add64(x260, x4, uint64(p384Uint1(x272)))
+       var x275 uint64
+       var x276 uint64
+       x275, x276 = bits.Add64(x247, x265, uint64(0x0))
+       var x277 uint64
+       var x278 uint64
+       x277, x278 = bits.Add64(x249, x267, uint64(p384Uint1(x276)))
+       var x279 uint64
+       var x280 uint64
+       x279, x280 = bits.Add64(x251, x269, uint64(p384Uint1(x278)))
+       var x281 uint64
+       var x282 uint64
+       x281, x282 = bits.Add64(x253, x271, uint64(p384Uint1(x280)))
+       var x283 uint64
+       var x284 uint64
+       x283, x284 = bits.Add64(x255, x273, uint64(p384Uint1(x282)))
+       var x285 uint64
+       var x286 uint64
+       x285, x286 = bits.Add64(x257, uint64(p384Uint1(x274)), uint64(p384Uint1(x284)))
+       var x287 uint64
+       _, x287 = bits.Mul64(x275, 0x100000001)
+       var x289 uint64
+       var x290 uint64
+       x290, x289 = bits.Mul64(x287, 0xffffffffffffffff)
+       var x291 uint64
+       var x292 uint64
+       x292, x291 = bits.Mul64(x287, 0xffffffffffffffff)
+       var x293 uint64
+       var x294 uint64
+       x294, x293 = bits.Mul64(x287, 0xffffffffffffffff)
+       var x295 uint64
+       var x296 uint64
+       x296, x295 = bits.Mul64(x287, 0xfffffffffffffffe)
+       var x297 uint64
+       var x298 uint64
+       x298, x297 = bits.Mul64(x287, 0xffffffff00000000)
+       var x299 uint64
+       var x300 uint64
+       x300, x299 = bits.Mul64(x287, 0xffffffff)
+       var x301 uint64
+       var x302 uint64
+       x301, x302 = bits.Add64(x300, x297, uint64(0x0))
+       var x303 uint64
+       var x304 uint64
+       x303, x304 = bits.Add64(x298, x295, uint64(p384Uint1(x302)))
+       var x305 uint64
+       var x306 uint64
+       x305, x306 = bits.Add64(x296, x293, uint64(p384Uint1(x304)))
+       var x307 uint64
+       var x308 uint64
+       x307, x308 = bits.Add64(x294, x291, uint64(p384Uint1(x306)))
+       var x309 uint64
+       var x310 uint64
+       x309, x310 = bits.Add64(x292, x289, uint64(p384Uint1(x308)))
+       var x312 uint64
+       _, x312 = bits.Add64(x275, x299, uint64(0x0))
+       var x313 uint64
+       var x314 uint64
+       x313, x314 = bits.Add64(x277, x301, uint64(p384Uint1(x312)))
+       var x315 uint64
+       var x316 uint64
+       x315, x316 = bits.Add64(x279, x303, uint64(p384Uint1(x314)))
+       var x317 uint64
+       var x318 uint64
+       x317, x318 = bits.Add64(x281, x305, uint64(p384Uint1(x316)))
+       var x319 uint64
+       var x320 uint64
+       x319, x320 = bits.Add64(x283, x307, uint64(p384Uint1(x318)))
+       var x321 uint64
+       var x322 uint64
+       x321, x322 = bits.Add64(x285, x309, uint64(p384Uint1(x320)))
+       var x323 uint64
+       var x324 uint64
+       x323, x324 = bits.Add64((uint64(p384Uint1(x286)) + uint64(p384Uint1(x258))), (uint64(p384Uint1(x310)) + x290), uint64(p384Uint1(x322)))
+       var x325 uint64
+       var x326 uint64
+       x326, x325 = bits.Mul64(x5, 0x200000000)
+       var x327 uint64
+       var x328 uint64
+       x328, x327 = bits.Mul64(x5, 0xfffffffe00000000)
+       var x329 uint64
+       var x330 uint64
+       x330, x329 = bits.Mul64(x5, 0x200000000)
+       var x331 uint64
+       var x332 uint64
+       x332, x331 = bits.Mul64(x5, 0xfffffffe00000001)
+       var x333 uint64
+       var x334 uint64
+       x333, x334 = bits.Add64(x332, x329, uint64(0x0))
+       var x335 uint64
+       var x336 uint64
+       x335, x336 = bits.Add64(x330, x327, uint64(p384Uint1(x334)))
+       var x337 uint64
+       var x338 uint64
+       x337, x338 = bits.Add64(x328, x325, uint64(p384Uint1(x336)))
+       var x339 uint64
+       var x340 uint64
+       x339, x340 = bits.Add64(x326, x5, uint64(p384Uint1(x338)))
+       var x341 uint64
+       var x342 uint64
+       x341, x342 = bits.Add64(x313, x331, uint64(0x0))
+       var x343 uint64
+       var x344 uint64
+       x343, x344 = bits.Add64(x315, x333, uint64(p384Uint1(x342)))
+       var x345 uint64
+       var x346 uint64
+       x345, x346 = bits.Add64(x317, x335, uint64(p384Uint1(x344)))
+       var x347 uint64
+       var x348 uint64
+       x347, x348 = bits.Add64(x319, x337, uint64(p384Uint1(x346)))
+       var x349 uint64
+       var x350 uint64
+       x349, x350 = bits.Add64(x321, x339, uint64(p384Uint1(x348)))
+       var x351 uint64
+       var x352 uint64
+       x351, x352 = bits.Add64(x323, uint64(p384Uint1(x340)), uint64(p384Uint1(x350)))
+       var x353 uint64
+       _, x353 = bits.Mul64(x341, 0x100000001)
+       var x355 uint64
+       var x356 uint64
+       x356, x355 = bits.Mul64(x353, 0xffffffffffffffff)
+       var x357 uint64
+       var x358 uint64
+       x358, x357 = bits.Mul64(x353, 0xffffffffffffffff)
+       var x359 uint64
+       var x360 uint64
+       x360, x359 = bits.Mul64(x353, 0xffffffffffffffff)
+       var x361 uint64
+       var x362 uint64
+       x362, x361 = bits.Mul64(x353, 0xfffffffffffffffe)
+       var x363 uint64
+       var x364 uint64
+       x364, x363 = bits.Mul64(x353, 0xffffffff00000000)
+       var x365 uint64
+       var x366 uint64
+       x366, x365 = bits.Mul64(x353, 0xffffffff)
+       var x367 uint64
+       var x368 uint64
+       x367, x368 = bits.Add64(x366, x363, uint64(0x0))
+       var x369 uint64
+       var x370 uint64
+       x369, x370 = bits.Add64(x364, x361, uint64(p384Uint1(x368)))
+       var x371 uint64
+       var x372 uint64
+       x371, x372 = bits.Add64(x362, x359, uint64(p384Uint1(x370)))
+       var x373 uint64
+       var x374 uint64
+       x373, x374 = bits.Add64(x360, x357, uint64(p384Uint1(x372)))
+       var x375 uint64
+       var x376 uint64
+       x375, x376 = bits.Add64(x358, x355, uint64(p384Uint1(x374)))
+       var x378 uint64
+       _, x378 = bits.Add64(x341, x365, uint64(0x0))
+       var x379 uint64
+       var x380 uint64
+       x379, x380 = bits.Add64(x343, x367, uint64(p384Uint1(x378)))
+       var x381 uint64
+       var x382 uint64
+       x381, x382 = bits.Add64(x345, x369, uint64(p384Uint1(x380)))
+       var x383 uint64
+       var x384 uint64
+       x383, x384 = bits.Add64(x347, x371, uint64(p384Uint1(x382)))
+       var x385 uint64
+       var x386 uint64
+       x385, x386 = bits.Add64(x349, x373, uint64(p384Uint1(x384)))
+       var x387 uint64
+       var x388 uint64
+       x387, x388 = bits.Add64(x351, x375, uint64(p384Uint1(x386)))
+       var x389 uint64
+       var x390 uint64
+       x389, x390 = bits.Add64((uint64(p384Uint1(x352)) + uint64(p384Uint1(x324))), (uint64(p384Uint1(x376)) + x356), uint64(p384Uint1(x388)))
+       var x391 uint64
+       var x392 uint64
+       x391, x392 = bits.Sub64(x379, 0xffffffff, uint64(0x0))
+       var x393 uint64
+       var x394 uint64
+       x393, x394 = bits.Sub64(x381, 0xffffffff00000000, uint64(p384Uint1(x392)))
+       var x395 uint64
+       var x396 uint64
+       x395, x396 = bits.Sub64(x383, 0xfffffffffffffffe, uint64(p384Uint1(x394)))
+       var x397 uint64
+       var x398 uint64
+       x397, x398 = bits.Sub64(x385, 0xffffffffffffffff, uint64(p384Uint1(x396)))
+       var x399 uint64
+       var x400 uint64
+       x399, x400 = bits.Sub64(x387, 0xffffffffffffffff, uint64(p384Uint1(x398)))
+       var x401 uint64
+       var x402 uint64
+       x401, x402 = bits.Sub64(x389, 0xffffffffffffffff, uint64(p384Uint1(x400)))
+       var x404 uint64
+       _, x404 = bits.Sub64(uint64(p384Uint1(x390)), uint64(0x0), uint64(p384Uint1(x402)))
+       var x405 uint64
+       p384CmovznzU64(&x405, p384Uint1(x404), x391, x379)
+       var x406 uint64
+       p384CmovznzU64(&x406, p384Uint1(x404), x393, x381)
+       var x407 uint64
+       p384CmovznzU64(&x407, p384Uint1(x404), x395, x383)
+       var x408 uint64
+       p384CmovznzU64(&x408, p384Uint1(x404), x397, x385)
+       var x409 uint64
+       p384CmovznzU64(&x409, p384Uint1(x404), x399, x387)
+       var x410 uint64
+       p384CmovznzU64(&x410, p384Uint1(x404), x401, x389)
+       out1[0] = x405
+       out1[1] = x406
+       out1[2] = x407
+       out1[3] = x408
+       out1[4] = x409
+       out1[5] = x410
+}
+
+// p384Selectznz is a multi-limb conditional select.
+//
+// Postconditions:
+//   eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
+//
+// Input Bounds:
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+//   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+func p384Selectznz(out1 *[6]uint64, arg1 p384Uint1, arg2 *[6]uint64, arg3 *[6]uint64) {
+       var x1 uint64
+       p384CmovznzU64(&x1, arg1, arg2[0], arg3[0])
+       var x2 uint64
+       p384CmovznzU64(&x2, arg1, arg2[1], arg3[1])
+       var x3 uint64
+       p384CmovznzU64(&x3, arg1, arg2[2], arg3[2])
+       var x4 uint64
+       p384CmovznzU64(&x4, arg1, arg2[3], arg3[3])
+       var x5 uint64
+       p384CmovznzU64(&x5, arg1, arg2[4], arg3[4])
+       var x6 uint64
+       p384CmovznzU64(&x6, arg1, arg2[5], arg3[5])
+       out1[0] = x1
+       out1[1] = x2
+       out1[2] = x3
+       out1[3] = x4
+       out1[4] = x5
+       out1[5] = x6
+}
+
+// p384ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+// Postconditions:
+//   out1 = map (ฮป x, โŒŠ((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)โŒ‹) [0..47]
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+func p384ToBytes(out1 *[48]uint8, arg1 *[6]uint64) {
+       x1 := arg1[5]
+       x2 := arg1[4]
+       x3 := arg1[3]
+       x4 := arg1[2]
+       x5 := arg1[1]
+       x6 := arg1[0]
+       x7 := (uint8(x6) & 0xff)
+       x8 := (x6 >> 8)
+       x9 := (uint8(x8) & 0xff)
+       x10 := (x8 >> 8)
+       x11 := (uint8(x10) & 0xff)
+       x12 := (x10 >> 8)
+       x13 := (uint8(x12) & 0xff)
+       x14 := (x12 >> 8)
+       x15 := (uint8(x14) & 0xff)
+       x16 := (x14 >> 8)
+       x17 := (uint8(x16) & 0xff)
+       x18 := (x16 >> 8)
+       x19 := (uint8(x18) & 0xff)
+       x20 := uint8((x18 >> 8))
+       x21 := (uint8(x5) & 0xff)
+       x22 := (x5 >> 8)
+       x23 := (uint8(x22) & 0xff)
+       x24 := (x22 >> 8)
+       x25 := (uint8(x24) & 0xff)
+       x26 := (x24 >> 8)
+       x27 := (uint8(x26) & 0xff)
+       x28 := (x26 >> 8)
+       x29 := (uint8(x28) & 0xff)
+       x30 := (x28 >> 8)
+       x31 := (uint8(x30) & 0xff)
+       x32 := (x30 >> 8)
+       x33 := (uint8(x32) & 0xff)
+       x34 := uint8((x32 >> 8))
+       x35 := (uint8(x4) & 0xff)
+       x36 := (x4 >> 8)
+       x37 := (uint8(x36) & 0xff)
+       x38 := (x36 >> 8)
+       x39 := (uint8(x38) & 0xff)
+       x40 := (x38 >> 8)
+       x41 := (uint8(x40) & 0xff)
+       x42 := (x40 >> 8)
+       x43 := (uint8(x42) & 0xff)
+       x44 := (x42 >> 8)
+       x45 := (uint8(x44) & 0xff)
+       x46 := (x44 >> 8)
+       x47 := (uint8(x46) & 0xff)
+       x48 := uint8((x46 >> 8))
+       x49 := (uint8(x3) & 0xff)
+       x50 := (x3 >> 8)
+       x51 := (uint8(x50) & 0xff)
+       x52 := (x50 >> 8)
+       x53 := (uint8(x52) & 0xff)
+       x54 := (x52 >> 8)
+       x55 := (uint8(x54) & 0xff)
+       x56 := (x54 >> 8)
+       x57 := (uint8(x56) & 0xff)
+       x58 := (x56 >> 8)
+       x59 := (uint8(x58) & 0xff)
+       x60 := (x58 >> 8)
+       x61 := (uint8(x60) & 0xff)
+       x62 := uint8((x60 >> 8))
+       x63 := (uint8(x2) & 0xff)
+       x64 := (x2 >> 8)
+       x65 := (uint8(x64) & 0xff)
+       x66 := (x64 >> 8)
+       x67 := (uint8(x66) & 0xff)
+       x68 := (x66 >> 8)
+       x69 := (uint8(x68) & 0xff)
+       x70 := (x68 >> 8)
+       x71 := (uint8(x70) & 0xff)
+       x72 := (x70 >> 8)
+       x73 := (uint8(x72) & 0xff)
+       x74 := (x72 >> 8)
+       x75 := (uint8(x74) & 0xff)
+       x76 := uint8((x74 >> 8))
+       x77 := (uint8(x1) & 0xff)
+       x78 := (x1 >> 8)
+       x79 := (uint8(x78) & 0xff)
+       x80 := (x78 >> 8)
+       x81 := (uint8(x80) & 0xff)
+       x82 := (x80 >> 8)
+       x83 := (uint8(x82) & 0xff)
+       x84 := (x82 >> 8)
+       x85 := (uint8(x84) & 0xff)
+       x86 := (x84 >> 8)
+       x87 := (uint8(x86) & 0xff)
+       x88 := (x86 >> 8)
+       x89 := (uint8(x88) & 0xff)
+       x90 := uint8((x88 >> 8))
+       out1[0] = x7
+       out1[1] = x9
+       out1[2] = x11
+       out1[3] = x13
+       out1[4] = x15
+       out1[5] = x17
+       out1[6] = x19
+       out1[7] = x20
+       out1[8] = x21
+       out1[9] = x23
+       out1[10] = x25
+       out1[11] = x27
+       out1[12] = x29
+       out1[13] = x31
+       out1[14] = x33
+       out1[15] = x34
+       out1[16] = x35
+       out1[17] = x37
+       out1[18] = x39
+       out1[19] = x41
+       out1[20] = x43
+       out1[21] = x45
+       out1[22] = x47
+       out1[23] = x48
+       out1[24] = x49
+       out1[25] = x51
+       out1[26] = x53
+       out1[27] = x55
+       out1[28] = x57
+       out1[29] = x59
+       out1[30] = x61
+       out1[31] = x62
+       out1[32] = x63
+       out1[33] = x65
+       out1[34] = x67
+       out1[35] = x69
+       out1[36] = x71
+       out1[37] = x73
+       out1[38] = x75
+       out1[39] = x76
+       out1[40] = x77
+       out1[41] = x79
+       out1[42] = x81
+       out1[43] = x83
+       out1[44] = x85
+       out1[45] = x87
+       out1[46] = x89
+       out1[47] = x90
+}
+
+// p384FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order.
+//
+// Preconditions:
+//   0 โ‰ค bytes_eval arg1 < m
+// Postconditions:
+//   eval out1 mod m = bytes_eval arg1 mod m
+//   0 โ‰ค eval out1 < m
+//
+// Input Bounds:
+//   arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+// Output Bounds:
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+func p384FromBytes(out1 *[6]uint64, arg1 *[48]uint8) {
+       x1 := (uint64(arg1[47]) << 56)
+       x2 := (uint64(arg1[46]) << 48)
+       x3 := (uint64(arg1[45]) << 40)
+       x4 := (uint64(arg1[44]) << 32)
+       x5 := (uint64(arg1[43]) << 24)
+       x6 := (uint64(arg1[42]) << 16)
+       x7 := (uint64(arg1[41]) << 8)
+       x8 := arg1[40]
+       x9 := (uint64(arg1[39]) << 56)
+       x10 := (uint64(arg1[38]) << 48)
+       x11 := (uint64(arg1[37]) << 40)
+       x12 := (uint64(arg1[36]) << 32)
+       x13 := (uint64(arg1[35]) << 24)
+       x14 := (uint64(arg1[34]) << 16)
+       x15 := (uint64(arg1[33]) << 8)
+       x16 := arg1[32]
+       x17 := (uint64(arg1[31]) << 56)
+       x18 := (uint64(arg1[30]) << 48)
+       x19 := (uint64(arg1[29]) << 40)
+       x20 := (uint64(arg1[28]) << 32)
+       x21 := (uint64(arg1[27]) << 24)
+       x22 := (uint64(arg1[26]) << 16)
+       x23 := (uint64(arg1[25]) << 8)
+       x24 := arg1[24]
+       x25 := (uint64(arg1[23]) << 56)
+       x26 := (uint64(arg1[22]) << 48)
+       x27 := (uint64(arg1[21]) << 40)
+       x28 := (uint64(arg1[20]) << 32)
+       x29 := (uint64(arg1[19]) << 24)
+       x30 := (uint64(arg1[18]) << 16)
+       x31 := (uint64(arg1[17]) << 8)
+       x32 := arg1[16]
+       x33 := (uint64(arg1[15]) << 56)
+       x34 := (uint64(arg1[14]) << 48)
+       x35 := (uint64(arg1[13]) << 40)
+       x36 := (uint64(arg1[12]) << 32)
+       x37 := (uint64(arg1[11]) << 24)
+       x38 := (uint64(arg1[10]) << 16)
+       x39 := (uint64(arg1[9]) << 8)
+       x40 := arg1[8]
+       x41 := (uint64(arg1[7]) << 56)
+       x42 := (uint64(arg1[6]) << 48)
+       x43 := (uint64(arg1[5]) << 40)
+       x44 := (uint64(arg1[4]) << 32)
+       x45 := (uint64(arg1[3]) << 24)
+       x46 := (uint64(arg1[2]) << 16)
+       x47 := (uint64(arg1[1]) << 8)
+       x48 := arg1[0]
+       x49 := (x47 + uint64(x48))
+       x50 := (x46 + x49)
+       x51 := (x45 + x50)
+       x52 := (x44 + x51)
+       x53 := (x43 + x52)
+       x54 := (x42 + x53)
+       x55 := (x41 + x54)
+       x56 := (x39 + uint64(x40))
+       x57 := (x38 + x56)
+       x58 := (x37 + x57)
+       x59 := (x36 + x58)
+       x60 := (x35 + x59)
+       x61 := (x34 + x60)
+       x62 := (x33 + x61)
+       x63 := (x31 + uint64(x32))
+       x64 := (x30 + x63)
+       x65 := (x29 + x64)
+       x66 := (x28 + x65)
+       x67 := (x27 + x66)
+       x68 := (x26 + x67)
+       x69 := (x25 + x68)
+       x70 := (x23 + uint64(x24))
+       x71 := (x22 + x70)
+       x72 := (x21 + x71)
+       x73 := (x20 + x72)
+       x74 := (x19 + x73)
+       x75 := (x18 + x74)
+       x76 := (x17 + x75)
+       x77 := (x15 + uint64(x16))
+       x78 := (x14 + x77)
+       x79 := (x13 + x78)
+       x80 := (x12 + x79)
+       x81 := (x11 + x80)
+       x82 := (x10 + x81)
+       x83 := (x9 + x82)
+       x84 := (x7 + uint64(x8))
+       x85 := (x6 + x84)
+       x86 := (x5 + x85)
+       x87 := (x4 + x86)
+       x88 := (x3 + x87)
+       x89 := (x2 + x88)
+       x90 := (x1 + x89)
+       out1[0] = x55
+       out1[1] = x62
+       out1[2] = x69
+       out1[3] = x76
+       out1[4] = x83
+       out1[5] = x90
+}
diff --git a/src/crypto/elliptic/internal/fiat/p384_invert.go b/src/crypto/elliptic/internal/fiat/p384_invert.go
new file mode 100644 (file)
index 0000000..24169e9
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by addchain. DO NOT EDIT.
+
+package fiat
+
+// Invert sets e = 1/x, and returns e.
+//
+// If x == 0, Invert returns e = 0.
+func (e *P384Element) Invert(x *P384Element) *P384Element {
+       // Inversion is implemented as exponentiation with exponent p โˆ’ 2.
+       // The sequence of 15 multiplications and 383 squarings is derived from the
+       // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0.
+       //
+       //      _10     = 2*1
+       //      _11     = 1 + _10
+       //      _110    = 2*_11
+       //      _111    = 1 + _110
+       //      _111000 = _111 << 3
+       //      _111111 = _111 + _111000
+       //      x12     = _111111 << 6 + _111111
+       //      x24     = x12 << 12 + x12
+       //      x30     = x24 << 6 + _111111
+       //      x31     = 2*x30 + 1
+       //      x32     = 2*x31 + 1
+       //      x63     = x32 << 31 + x31
+       //      x126    = x63 << 63 + x63
+       //      x252    = x126 << 126 + x126
+       //      x255    = x252 << 3 + _111
+       //      i397    = ((x255 << 33 + x32) << 94 + x30) << 2
+       //      return    1 + i397
+       //
+
+       var z = new(P384Element).Set(e)
+       var t0 = new(P384Element)
+       var t1 = new(P384Element)
+       var t2 = new(P384Element)
+       var t3 = new(P384Element)
+
+       z.Square(x)
+       z.Mul(x, z)
+       z.Square(z)
+       t1.Mul(x, z)
+       z.Square(t1)
+       for s := 1; s < 3; s++ {
+               z.Square(z)
+       }
+       z.Mul(t1, z)
+       t0.Square(z)
+       for s := 1; s < 6; s++ {
+               t0.Square(t0)
+       }
+       t0.Mul(z, t0)
+       t2.Square(t0)
+       for s := 1; s < 12; s++ {
+               t2.Square(t2)
+       }
+       t0.Mul(t0, t2)
+       for s := 0; s < 6; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       t2.Mul(x, t0)
+       t0.Square(t2)
+       t0.Mul(x, t0)
+       t3.Square(t0)
+       for s := 1; s < 31; s++ {
+               t3.Square(t3)
+       }
+       t2.Mul(t2, t3)
+       t3.Square(t2)
+       for s := 1; s < 63; s++ {
+               t3.Square(t3)
+       }
+       t2.Mul(t2, t3)
+       t3.Square(t2)
+       for s := 1; s < 126; s++ {
+               t3.Square(t3)
+       }
+       t2.Mul(t2, t3)
+       for s := 0; s < 3; s++ {
+               t2.Square(t2)
+       }
+       t1.Mul(t1, t2)
+       for s := 0; s < 33; s++ {
+               t1.Square(t1)
+       }
+       t0.Mul(t0, t1)
+       for s := 0; s < 94; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       for s := 0; s < 2; s++ {
+               z.Square(z)
+       }
+       z.Mul(x, z)
+
+       return e.Set(z)
+}
index 647c3f914f7b7f04c8f372acc95c6a1484c5c365..3d12117e496a661872cbc49a2b88fc4b4b184009 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package fiat implements prime order fields using formally verified algorithms
-// from the Fiat Cryptography project.
+// Code generated by generate.go. DO NOT EDIT.
+
 package fiat
 
 import (
@@ -15,20 +15,18 @@ import (
 //
 // The zero value is a valid zero element.
 type P521Element struct {
-       // This element has the following bounds, which are tighter than
-       // the output bounds of some operations. Those operations must be
-       // followed by a carry.
-       //
-       // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000],
-       // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000],
-       // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]
-       x [9]uint64
+       // Values are represented internally always in the Montgomery domain, and
+       // converted in Bytes and SetBytes.
+       x p521MontgomeryDomainFieldElement
 }
 
+const p521ElementLen = 66
+
+type p521UntypedFieldElement = [9]uint64
+
 // One sets e = 1, and returns e.
 func (e *P521Element) One() *P521Element {
-       *e = P521Element{}
-       e.x[0] = 1
+       p521SetOne(&e.x)
        return e
 }
 
@@ -57,153 +55,81 @@ func (e *P521Element) Set(t *P521Element) *P521Element {
 func (e *P521Element) Bytes() []byte {
        // This function is outlined to make the allocations inline in the caller
        // rather than happen on the heap.
-       var out [66]byte
+       var out [p521ElementLen]byte
        return e.bytes(&out)
 }
 
-func (e *P521Element) bytes(out *[66]byte) []byte {
-       p521ToBytes(out, &e.x)
-       invertEndianness(out[:])
+func (e *P521Element) bytes(out *[p521ElementLen]byte) []byte {
+       var tmp p521NonMontgomeryDomainFieldElement
+       p521FromMontgomery(&tmp, &e.x)
+       p521ToBytes(out, (*p521UntypedFieldElement)(&tmp))
+       p521InvertEndianness(out[:])
        return out[:]
 }
 
-// SetBytes sets e = v, where v is a big-endian 66-byte encoding, and returns
-// e. If v is not 66 bytes or it encodes a value higher than 2^521 - 1, SetBytes
-// returns nil and an error, and e is unchanged.
+// p521MinusOneEncoding is the encoding of -1 mod p, so p - 1, the
+// highest canonical encoding. It is used by SetBytes to check for non-canonical
+// encodings such as p + k, 2p + k, etc.
+var p521MinusOneEncoding = new(P521Element).Sub(
+       new(P521Element), new(P521Element).One()).Bytes()
+
+// SetBytes sets e = v, where v is a big-endian 66-byte encoding, and returns e.
+// If v is not 66 bytes or it encodes a value higher than 2^521 - 1,
+// SetBytes returns nil and an error, and e is unchanged.
 func (e *P521Element) SetBytes(v []byte) (*P521Element, error) {
-       if len(v) != 66 || v[0] > 1 {
-               return nil, errors.New("invalid P-521 field encoding")
+       if len(v) != p521ElementLen {
+               return nil, errors.New("invalid P521Element encoding")
+       }
+       for i := range v {
+               if v[i] < p521MinusOneEncoding[i] {
+                       break
+               }
+               if v[i] > p521MinusOneEncoding[i] {
+                       return nil, errors.New("invalid P521Element encoding")
+               }
        }
-       var in [66]byte
+       var in [p521ElementLen]byte
        copy(in[:], v)
-       invertEndianness(in[:])
-       p521FromBytes(&e.x, &in)
+       p521InvertEndianness(in[:])
+       var tmp p521NonMontgomeryDomainFieldElement
+       p521FromBytes((*p521UntypedFieldElement)(&tmp), &in)
+       p521ToMontgomery(&e.x, &tmp)
        return e, nil
 }
 
-func invertEndianness(v []byte) {
-       for i := 0; i < len(v)/2; i++ {
-               v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
-       }
-}
-
 // Add sets e = t1 + t2, and returns e.
 func (e *P521Element) Add(t1, t2 *P521Element) *P521Element {
        p521Add(&e.x, &t1.x, &t2.x)
-       p521Carry(&e.x, &e.x)
        return e
 }
 
 // Sub sets e = t1 - t2, and returns e.
 func (e *P521Element) Sub(t1, t2 *P521Element) *P521Element {
        p521Sub(&e.x, &t1.x, &t2.x)
-       p521Carry(&e.x, &e.x)
        return e
 }
 
 // Mul sets e = t1 * t2, and returns e.
 func (e *P521Element) Mul(t1, t2 *P521Element) *P521Element {
-       p521CarryMul(&e.x, &t1.x, &t2.x)
+       p521Mul(&e.x, &t1.x, &t2.x)
        return e
 }
 
 // Square sets e = t * t, and returns e.
 func (e *P521Element) Square(t *P521Element) *P521Element {
-       p521CarrySquare(&e.x, &t.x)
+       p521Square(&e.x, &t.x)
        return e
 }
 
-// Select sets e to a if cond == 1, and to b if cond == 0.
+// Select sets v to a if cond == 1, and to b if cond == 0.
 func (v *P521Element) Select(a, b *P521Element, cond int) *P521Element {
-       p521Selectznz(&v.x, p521Uint1(cond), &b.x, &a.x)
+       p521Selectznz((*p521UntypedFieldElement)(&v.x), p521Uint1(cond),
+               (*p521UntypedFieldElement)(&b.x), (*p521UntypedFieldElement)(&a.x))
        return v
 }
 
-// Invert sets e = 1/t, and returns e.
-//
-// If t == 0, Invert returns e = 0.
-func (e *P521Element) Invert(t *P521Element) *P521Element {
-       // Inversion is implemented as exponentiation with exponent p โˆ’ 2.
-       // The sequence of multiplications and squarings was generated with
-       // github.com/mmcloughlin/addchain v0.2.0.
-
-       var t1, t2 = new(P521Element), new(P521Element)
-
-       // _10 = 2 * 1
-       t1.Square(t)
-
-       // _11 = 1 + _10
-       t1.Mul(t, t1)
-
-       // _1100 = _11 << 2
-       t2.Square(t1)
-       t2.Square(t2)
-
-       // _1111 = _11 + _1100
-       t1.Mul(t1, t2)
-
-       // _11110000 = _1111 << 4
-       t2.Square(t1)
-       for i := 0; i < 3; i++ {
-               t2.Square(t2)
-       }
-
-       // _11111111 = _1111 + _11110000
-       t1.Mul(t1, t2)
-
-       // x16 = _11111111<<8 + _11111111
-       t2.Square(t1)
-       for i := 0; i < 7; i++ {
-               t2.Square(t2)
-       }
-       t1.Mul(t1, t2)
-
-       // x32 = x16<<16 + x16
-       t2.Square(t1)
-       for i := 0; i < 15; i++ {
-               t2.Square(t2)
-       }
-       t1.Mul(t1, t2)
-
-       // x64 = x32<<32 + x32
-       t2.Square(t1)
-       for i := 0; i < 31; i++ {
-               t2.Square(t2)
-       }
-       t1.Mul(t1, t2)
-
-       // x65 = 2*x64 + 1
-       t2.Square(t1)
-       t2.Mul(t2, t)
-
-       // x129 = x65<<64 + x64
-       for i := 0; i < 64; i++ {
-               t2.Square(t2)
-       }
-       t1.Mul(t1, t2)
-
-       // x130 = 2*x129 + 1
-       t2.Square(t1)
-       t2.Mul(t2, t)
-
-       // x259 = x130<<129 + x129
-       for i := 0; i < 129; i++ {
-               t2.Square(t2)
-       }
-       t1.Mul(t1, t2)
-
-       // x260 = 2*x259 + 1
-       t2.Square(t1)
-       t2.Mul(t2, t)
-
-       // x519 = x260<<259 + x259
-       for i := 0; i < 259; i++ {
-               t2.Square(t2)
+func p521InvertEndianness(v []byte) {
+       for i := 0; i < len(v)/2; i++ {
+               v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
        }
-       t1.Mul(t1, t2)
-
-       // return x519<<2 + 1
-       t1.Square(t1)
-       t1.Square(t1)
-       return e.Mul(t1, t)
 }
index f86283b587eb9a03d28b27459edc314e5c2560cb..9f4f290f4cae2de70cb802f79b48ce7b702470f5 100644 (file)
 // Code generated by Fiat Cryptography. DO NOT EDIT.
 //
-// Autogenerated: 'fiat-crypto/src/ExtractionOCaml/unsaturated_solinas' --lang Go --no-wide-int --cmovznz-by-mul --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' carry_mul carry_square carry add sub to_bytes from_bytes selectznz
+// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p521 64 '2^521 - 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes
 //
 // curve description: p521
 //
 // machine_wordsize = 64 (from "64")
 //
-// requested operations: carry_mul, carry_square, carry, add, sub, to_bytes, from_bytes, selectznz
+// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes
 //
-// n = 9 (from "9")
+// m = 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff (from "2^521 - 1")
 //
-// s-c = 2^521 - [(1, 1)] (from "2^521 - 1")
 //
-// tight_bounds_multiplier = 1 (from "")
 //
+// NOTE: In addition to the bounds specified above each function, all
 //
+//   functions synthesized for this Montgomery arithmetic require the
 //
-// Computed values:
+//   input to be strictly less than the prime modulus (m), and also
+//
+//   require the input to be in the unique saturated representation.
+//
+//   All functions also ensure that these two properties are true of
+//
+//   return values.
 //
-//   carry_chain = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1]
 //
-//   eval z = z[0] + (z[1] << 58) + (z[2] << 116) + (z[3] << 174) + (z[4] << 232) + (z[5] << 0x122) + (z[6] << 0x15c) + (z[7] << 0x196) + (z[8] << 0x1d0)
+//
+// Computed values:
+//
+//   eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) + (z[6] << 0x180) + (z[7] << 0x1c0) + (z[8] << 2^9)
 //
 //   bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178) + (z[48] << 0x180) + (z[49] << 0x188) + (z[50] << 0x190) + (z[51] << 0x198) + (z[52] << 0x1a0) + (z[53] << 0x1a8) + (z[54] << 0x1b0) + (z[55] << 0x1b8) + (z[56] << 0x1c0) + (z[57] << 0x1c8) + (z[58] << 0x1d0) + (z[59] << 0x1d8) + (z[60] << 0x1e0) + (z[61] << 0x1e8) + (z[62] << 0x1f0) + (z[63] << 0x1f8) + (z[64] << 2^9) + (z[65] << 0x208)
 //
-//   balance = [0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x3fffffffffffffe]
+//   twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) + (z[6] << 0x180) + (z[7] << 0x1c0) + (z[8] << 2^9) in
+//
+//                            if x1 & (2^576-1) < 2^575 then x1 & (2^576-1) else (x1 & (2^576-1)) - 2^576
 
 package fiat
 
 import "math/bits"
 
-type p521Uint1 uint8
-type p521Int1 int8
-
-// p521AddcarryxU64 is a thin wrapper around bits.Add64 that uses p521Uint1 rather than uint64
-func p521AddcarryxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) {
-       sum, carryOut := bits.Add64(x, y, uint64(carry))
-       return sum, p521Uint1(carryOut)
-}
-
-// p521SubborrowxU64 is a thin wrapper around bits.Sub64 that uses p521Uint1 rather than uint64
-func p521SubborrowxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) {
-       sum, carryOut := bits.Sub64(x, y, uint64(carry))
-       return sum, p521Uint1(carryOut)
-}
-
-// p521AddcarryxU58 is an addition with carry.
-//
-// Postconditions:
-//   out1 = (arg1 + arg2 + arg3) mod 2^58
-//   out2 = โŒŠ(arg1 + arg2 + arg3) / 2^58โŒ‹
-//
-// Input Bounds:
-//   arg1: [0x0 ~> 0x1]
-//   arg2: [0x0 ~> 0x3ffffffffffffff]
-//   arg3: [0x0 ~> 0x3ffffffffffffff]
-// Output Bounds:
-//   out1: [0x0 ~> 0x3ffffffffffffff]
-//   out2: [0x0 ~> 0x1]
-func p521AddcarryxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
-       x1 := ((uint64(arg1) + arg2) + arg3)
-       x2 := (x1 & 0x3ffffffffffffff)
-       x3 := p521Uint1((x1 >> 58))
-       *out1 = x2
-       *out2 = x3
-}
-
-// p521SubborrowxU58 is a subtraction with borrow.
-//
-// Postconditions:
-//   out1 = (-arg1 + arg2 + -arg3) mod 2^58
-//   out2 = -โŒŠ(-arg1 + arg2 + -arg3) / 2^58โŒ‹
-//
-// Input Bounds:
-//   arg1: [0x0 ~> 0x1]
-//   arg2: [0x0 ~> 0x3ffffffffffffff]
-//   arg3: [0x0 ~> 0x3ffffffffffffff]
-// Output Bounds:
-//   out1: [0x0 ~> 0x3ffffffffffffff]
-//   out2: [0x0 ~> 0x1]
-func p521SubborrowxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
-       x1 := ((int64(arg2) - int64(arg1)) - int64(arg3))
-       x2 := p521Int1((x1 >> 58))
-       x3 := (uint64(x1) & 0x3ffffffffffffff)
-       *out1 = x3
-       *out2 = (0x0 - p521Uint1(x2))
-}
+type p521Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
+type p521Int1 int64   // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927
 
-// p521AddcarryxU57 is an addition with carry.
-//
-// Postconditions:
-//   out1 = (arg1 + arg2 + arg3) mod 2^57
-//   out2 = โŒŠ(arg1 + arg2 + arg3) / 2^57โŒ‹
+// The type p521MontgomeryDomainFieldElement is a field element in the Montgomery domain.
 //
-// Input Bounds:
-//   arg1: [0x0 ~> 0x1]
-//   arg2: [0x0 ~> 0x1ffffffffffffff]
-//   arg3: [0x0 ~> 0x1ffffffffffffff]
-// Output Bounds:
-//   out1: [0x0 ~> 0x1ffffffffffffff]
-//   out2: [0x0 ~> 0x1]
-func p521AddcarryxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
-       x1 := ((uint64(arg1) + arg2) + arg3)
-       x2 := (x1 & 0x1ffffffffffffff)
-       x3 := p521Uint1((x1 >> 57))
-       *out1 = x2
-       *out2 = x3
-}
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p521MontgomeryDomainFieldElement [9]uint64
 
-// p521SubborrowxU57 is a subtraction with borrow.
+// The type p521NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain.
 //
-// Postconditions:
-//   out1 = (-arg1 + arg2 + -arg3) mod 2^57
-//   out2 = -โŒŠ(-arg1 + arg2 + -arg3) / 2^57โŒ‹
-//
-// Input Bounds:
-//   arg1: [0x0 ~> 0x1]
-//   arg2: [0x0 ~> 0x1ffffffffffffff]
-//   arg3: [0x0 ~> 0x1ffffffffffffff]
-// Output Bounds:
-//   out1: [0x0 ~> 0x1ffffffffffffff]
-//   out2: [0x0 ~> 0x1]
-func p521SubborrowxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
-       x1 := ((int64(arg2) - int64(arg1)) - int64(arg3))
-       x2 := p521Int1((x1 >> 57))
-       x3 := (uint64(x1) & 0x1ffffffffffffff)
-       *out1 = x3
-       *out2 = (0x0 - p521Uint1(x2))
-}
+// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+type p521NonMontgomeryDomainFieldElement [9]uint64
 
 // p521CmovznzU64 is a single-word conditional move.
 //
@@ -146,1229 +70,5083 @@ func p521CmovznzU64(out1 *uint64, arg1 p521Uint1, arg2 uint64, arg3 uint64) {
        *out1 = x2
 }
 
-// p521CarryMul multiplies two field elements and reduces the result.
+// p521Mul multiplies two field elements in the Montgomery domain.
 //
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+//   0 โ‰ค eval arg2 < m
 // Postconditions:
-//   eval out1 mod m = (eval arg1 * eval arg2) mod m
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
+//   0 โ‰ค eval out1 < m
 //
-// Input Bounds:
-//   arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-//   arg2: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-// Output Bounds:
-//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-func p521CarryMul(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
-       var x1 uint64
-       var x2 uint64
-       x2, x1 = bits.Mul64(arg1[8], (arg2[8] * 0x2))
-       var x3 uint64
-       var x4 uint64
-       x4, x3 = bits.Mul64(arg1[8], (arg2[7] * 0x2))
-       var x5 uint64
-       var x6 uint64
-       x6, x5 = bits.Mul64(arg1[8], (arg2[6] * 0x2))
-       var x7 uint64
-       var x8 uint64
-       x8, x7 = bits.Mul64(arg1[8], (arg2[5] * 0x2))
-       var x9 uint64
+func p521Mul(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[4]
+       x5 := arg1[5]
+       x6 := arg1[6]
+       x7 := arg1[7]
+       x8 := arg1[8]
+       x9 := arg1[0]
        var x10 uint64
-       x10, x9 = bits.Mul64(arg1[8], (arg2[4] * 0x2))
        var x11 uint64
+       x11, x10 = bits.Mul64(x9, arg2[8])
        var x12 uint64
-       x12, x11 = bits.Mul64(arg1[8], (arg2[3] * 0x2))
        var x13 uint64
+       x13, x12 = bits.Mul64(x9, arg2[7])
        var x14 uint64
-       x14, x13 = bits.Mul64(arg1[8], (arg2[2] * 0x2))
        var x15 uint64
+       x15, x14 = bits.Mul64(x9, arg2[6])
        var x16 uint64
-       x16, x15 = bits.Mul64(arg1[8], (arg2[1] * 0x2))
        var x17 uint64
+       x17, x16 = bits.Mul64(x9, arg2[5])
        var x18 uint64
-       x18, x17 = bits.Mul64(arg1[7], (arg2[8] * 0x2))
        var x19 uint64
+       x19, x18 = bits.Mul64(x9, arg2[4])
        var x20 uint64
-       x20, x19 = bits.Mul64(arg1[7], (arg2[7] * 0x2))
        var x21 uint64
+       x21, x20 = bits.Mul64(x9, arg2[3])
        var x22 uint64
-       x22, x21 = bits.Mul64(arg1[7], (arg2[6] * 0x2))
        var x23 uint64
+       x23, x22 = bits.Mul64(x9, arg2[2])
        var x24 uint64
-       x24, x23 = bits.Mul64(arg1[7], (arg2[5] * 0x2))
        var x25 uint64
+       x25, x24 = bits.Mul64(x9, arg2[1])
        var x26 uint64
-       x26, x25 = bits.Mul64(arg1[7], (arg2[4] * 0x2))
        var x27 uint64
+       x27, x26 = bits.Mul64(x9, arg2[0])
        var x28 uint64
-       x28, x27 = bits.Mul64(arg1[7], (arg2[3] * 0x2))
        var x29 uint64
+       x28, x29 = bits.Add64(x27, x24, uint64(0x0))
        var x30 uint64
-       x30, x29 = bits.Mul64(arg1[7], (arg2[2] * 0x2))
        var x31 uint64
+       x30, x31 = bits.Add64(x25, x22, uint64(p521Uint1(x29)))
        var x32 uint64
-       x32, x31 = bits.Mul64(arg1[6], (arg2[8] * 0x2))
        var x33 uint64
+       x32, x33 = bits.Add64(x23, x20, uint64(p521Uint1(x31)))
        var x34 uint64
-       x34, x33 = bits.Mul64(arg1[6], (arg2[7] * 0x2))
        var x35 uint64
+       x34, x35 = bits.Add64(x21, x18, uint64(p521Uint1(x33)))
        var x36 uint64
-       x36, x35 = bits.Mul64(arg1[6], (arg2[6] * 0x2))
        var x37 uint64
+       x36, x37 = bits.Add64(x19, x16, uint64(p521Uint1(x35)))
        var x38 uint64
-       x38, x37 = bits.Mul64(arg1[6], (arg2[5] * 0x2))
        var x39 uint64
+       x38, x39 = bits.Add64(x17, x14, uint64(p521Uint1(x37)))
        var x40 uint64
-       x40, x39 = bits.Mul64(arg1[6], (arg2[4] * 0x2))
        var x41 uint64
+       x40, x41 = bits.Add64(x15, x12, uint64(p521Uint1(x39)))
        var x42 uint64
-       x42, x41 = bits.Mul64(arg1[6], (arg2[3] * 0x2))
        var x43 uint64
-       var x44 uint64
-       x44, x43 = bits.Mul64(arg1[5], (arg2[8] * 0x2))
+       x42, x43 = bits.Add64(x13, x10, uint64(p521Uint1(x41)))
+       x44 := (uint64(p521Uint1(x43)) + x11)
        var x45 uint64
        var x46 uint64
-       x46, x45 = bits.Mul64(arg1[5], (arg2[7] * 0x2))
+       x46, x45 = bits.Mul64(x26, 0x1ff)
        var x47 uint64
        var x48 uint64
-       x48, x47 = bits.Mul64(arg1[5], (arg2[6] * 0x2))
+       x48, x47 = bits.Mul64(x26, 0xffffffffffffffff)
        var x49 uint64
        var x50 uint64
-       x50, x49 = bits.Mul64(arg1[5], (arg2[5] * 0x2))
+       x50, x49 = bits.Mul64(x26, 0xffffffffffffffff)
        var x51 uint64
        var x52 uint64
-       x52, x51 = bits.Mul64(arg1[5], (arg2[4] * 0x2))
+       x52, x51 = bits.Mul64(x26, 0xffffffffffffffff)
        var x53 uint64
        var x54 uint64
-       x54, x53 = bits.Mul64(arg1[4], (arg2[8] * 0x2))
+       x54, x53 = bits.Mul64(x26, 0xffffffffffffffff)
        var x55 uint64
        var x56 uint64
-       x56, x55 = bits.Mul64(arg1[4], (arg2[7] * 0x2))
+       x56, x55 = bits.Mul64(x26, 0xffffffffffffffff)
        var x57 uint64
        var x58 uint64
-       x58, x57 = bits.Mul64(arg1[4], (arg2[6] * 0x2))
+       x58, x57 = bits.Mul64(x26, 0xffffffffffffffff)
        var x59 uint64
        var x60 uint64
-       x60, x59 = bits.Mul64(arg1[4], (arg2[5] * 0x2))
+       x60, x59 = bits.Mul64(x26, 0xffffffffffffffff)
        var x61 uint64
        var x62 uint64
-       x62, x61 = bits.Mul64(arg1[3], (arg2[8] * 0x2))
+       x62, x61 = bits.Mul64(x26, 0xffffffffffffffff)
        var x63 uint64
        var x64 uint64
-       x64, x63 = bits.Mul64(arg1[3], (arg2[7] * 0x2))
+       x63, x64 = bits.Add64(x62, x59, uint64(0x0))
        var x65 uint64
        var x66 uint64
-       x66, x65 = bits.Mul64(arg1[3], (arg2[6] * 0x2))
+       x65, x66 = bits.Add64(x60, x57, uint64(p521Uint1(x64)))
        var x67 uint64
        var x68 uint64
-       x68, x67 = bits.Mul64(arg1[2], (arg2[8] * 0x2))
+       x67, x68 = bits.Add64(x58, x55, uint64(p521Uint1(x66)))
        var x69 uint64
        var x70 uint64
-       x70, x69 = bits.Mul64(arg1[2], (arg2[7] * 0x2))
+       x69, x70 = bits.Add64(x56, x53, uint64(p521Uint1(x68)))
        var x71 uint64
        var x72 uint64
-       x72, x71 = bits.Mul64(arg1[1], (arg2[8] * 0x2))
+       x71, x72 = bits.Add64(x54, x51, uint64(p521Uint1(x70)))
        var x73 uint64
        var x74 uint64
-       x74, x73 = bits.Mul64(arg1[8], arg2[0])
+       x73, x74 = bits.Add64(x52, x49, uint64(p521Uint1(x72)))
        var x75 uint64
        var x76 uint64
-       x76, x75 = bits.Mul64(arg1[7], arg2[1])
+       x75, x76 = bits.Add64(x50, x47, uint64(p521Uint1(x74)))
        var x77 uint64
        var x78 uint64
-       x78, x77 = bits.Mul64(arg1[7], arg2[0])
-       var x79 uint64
-       var x80 uint64
-       x80, x79 = bits.Mul64(arg1[6], arg2[2])
+       x77, x78 = bits.Add64(x48, x45, uint64(p521Uint1(x76)))
+       x79 := (uint64(p521Uint1(x78)) + x46)
        var x81 uint64
+       _, x81 = bits.Add64(x26, x61, uint64(0x0))
        var x82 uint64
-       x82, x81 = bits.Mul64(arg1[6], arg2[1])
        var x83 uint64
+       x82, x83 = bits.Add64(x28, x63, uint64(p521Uint1(x81)))
        var x84 uint64
-       x84, x83 = bits.Mul64(arg1[6], arg2[0])
        var x85 uint64
+       x84, x85 = bits.Add64(x30, x65, uint64(p521Uint1(x83)))
        var x86 uint64
-       x86, x85 = bits.Mul64(arg1[5], arg2[3])
        var x87 uint64
+       x86, x87 = bits.Add64(x32, x67, uint64(p521Uint1(x85)))
        var x88 uint64
-       x88, x87 = bits.Mul64(arg1[5], arg2[2])
        var x89 uint64
+       x88, x89 = bits.Add64(x34, x69, uint64(p521Uint1(x87)))
        var x90 uint64
-       x90, x89 = bits.Mul64(arg1[5], arg2[1])
        var x91 uint64
+       x90, x91 = bits.Add64(x36, x71, uint64(p521Uint1(x89)))
        var x92 uint64
-       x92, x91 = bits.Mul64(arg1[5], arg2[0])
        var x93 uint64
+       x92, x93 = bits.Add64(x38, x73, uint64(p521Uint1(x91)))
        var x94 uint64
-       x94, x93 = bits.Mul64(arg1[4], arg2[4])
        var x95 uint64
+       x94, x95 = bits.Add64(x40, x75, uint64(p521Uint1(x93)))
        var x96 uint64
-       x96, x95 = bits.Mul64(arg1[4], arg2[3])
        var x97 uint64
+       x96, x97 = bits.Add64(x42, x77, uint64(p521Uint1(x95)))
        var x98 uint64
-       x98, x97 = bits.Mul64(arg1[4], arg2[2])
        var x99 uint64
+       x98, x99 = bits.Add64(x44, x79, uint64(p521Uint1(x97)))
        var x100 uint64
-       x100, x99 = bits.Mul64(arg1[4], arg2[1])
        var x101 uint64
+       x101, x100 = bits.Mul64(x1, arg2[8])
        var x102 uint64
-       x102, x101 = bits.Mul64(arg1[4], arg2[0])
        var x103 uint64
+       x103, x102 = bits.Mul64(x1, arg2[7])
        var x104 uint64
-       x104, x103 = bits.Mul64(arg1[3], arg2[5])
        var x105 uint64
+       x105, x104 = bits.Mul64(x1, arg2[6])
        var x106 uint64
-       x106, x105 = bits.Mul64(arg1[3], arg2[4])
        var x107 uint64
+       x107, x106 = bits.Mul64(x1, arg2[5])
        var x108 uint64
-       x108, x107 = bits.Mul64(arg1[3], arg2[3])
        var x109 uint64
+       x109, x108 = bits.Mul64(x1, arg2[4])
        var x110 uint64
-       x110, x109 = bits.Mul64(arg1[3], arg2[2])
        var x111 uint64
+       x111, x110 = bits.Mul64(x1, arg2[3])
        var x112 uint64
-       x112, x111 = bits.Mul64(arg1[3], arg2[1])
        var x113 uint64
+       x113, x112 = bits.Mul64(x1, arg2[2])
        var x114 uint64
-       x114, x113 = bits.Mul64(arg1[3], arg2[0])
        var x115 uint64
+       x115, x114 = bits.Mul64(x1, arg2[1])
        var x116 uint64
-       x116, x115 = bits.Mul64(arg1[2], arg2[6])
        var x117 uint64
+       x117, x116 = bits.Mul64(x1, arg2[0])
        var x118 uint64
-       x118, x117 = bits.Mul64(arg1[2], arg2[5])
        var x119 uint64
+       x118, x119 = bits.Add64(x117, x114, uint64(0x0))
        var x120 uint64
-       x120, x119 = bits.Mul64(arg1[2], arg2[4])
        var x121 uint64
+       x120, x121 = bits.Add64(x115, x112, uint64(p521Uint1(x119)))
        var x122 uint64
-       x122, x121 = bits.Mul64(arg1[2], arg2[3])
        var x123 uint64
+       x122, x123 = bits.Add64(x113, x110, uint64(p521Uint1(x121)))
        var x124 uint64
-       x124, x123 = bits.Mul64(arg1[2], arg2[2])
        var x125 uint64
+       x124, x125 = bits.Add64(x111, x108, uint64(p521Uint1(x123)))
        var x126 uint64
-       x126, x125 = bits.Mul64(arg1[2], arg2[1])
        var x127 uint64
+       x126, x127 = bits.Add64(x109, x106, uint64(p521Uint1(x125)))
        var x128 uint64
-       x128, x127 = bits.Mul64(arg1[2], arg2[0])
        var x129 uint64
+       x128, x129 = bits.Add64(x107, x104, uint64(p521Uint1(x127)))
        var x130 uint64
-       x130, x129 = bits.Mul64(arg1[1], arg2[7])
        var x131 uint64
+       x130, x131 = bits.Add64(x105, x102, uint64(p521Uint1(x129)))
        var x132 uint64
-       x132, x131 = bits.Mul64(arg1[1], arg2[6])
        var x133 uint64
-       var x134 uint64
-       x134, x133 = bits.Mul64(arg1[1], arg2[5])
+       x132, x133 = bits.Add64(x103, x100, uint64(p521Uint1(x131)))
+       x134 := (uint64(p521Uint1(x133)) + x101)
        var x135 uint64
        var x136 uint64
-       x136, x135 = bits.Mul64(arg1[1], arg2[4])
+       x135, x136 = bits.Add64(x82, x116, uint64(0x0))
        var x137 uint64
        var x138 uint64
-       x138, x137 = bits.Mul64(arg1[1], arg2[3])
+       x137, x138 = bits.Add64(x84, x118, uint64(p521Uint1(x136)))
        var x139 uint64
        var x140 uint64
-       x140, x139 = bits.Mul64(arg1[1], arg2[2])
+       x139, x140 = bits.Add64(x86, x120, uint64(p521Uint1(x138)))
        var x141 uint64
        var x142 uint64
-       x142, x141 = bits.Mul64(arg1[1], arg2[1])
+       x141, x142 = bits.Add64(x88, x122, uint64(p521Uint1(x140)))
        var x143 uint64
        var x144 uint64
-       x144, x143 = bits.Mul64(arg1[1], arg2[0])
+       x143, x144 = bits.Add64(x90, x124, uint64(p521Uint1(x142)))
        var x145 uint64
        var x146 uint64
-       x146, x145 = bits.Mul64(arg1[0], arg2[8])
+       x145, x146 = bits.Add64(x92, x126, uint64(p521Uint1(x144)))
        var x147 uint64
        var x148 uint64
-       x148, x147 = bits.Mul64(arg1[0], arg2[7])
+       x147, x148 = bits.Add64(x94, x128, uint64(p521Uint1(x146)))
        var x149 uint64
        var x150 uint64
-       x150, x149 = bits.Mul64(arg1[0], arg2[6])
+       x149, x150 = bits.Add64(x96, x130, uint64(p521Uint1(x148)))
        var x151 uint64
        var x152 uint64
-       x152, x151 = bits.Mul64(arg1[0], arg2[5])
+       x151, x152 = bits.Add64(x98, x132, uint64(p521Uint1(x150)))
        var x153 uint64
        var x154 uint64
-       x154, x153 = bits.Mul64(arg1[0], arg2[4])
+       x153, x154 = bits.Add64(uint64(p521Uint1(x99)), x134, uint64(p521Uint1(x152)))
        var x155 uint64
        var x156 uint64
-       x156, x155 = bits.Mul64(arg1[0], arg2[3])
+       x156, x155 = bits.Mul64(x135, 0x1ff)
        var x157 uint64
        var x158 uint64
-       x158, x157 = bits.Mul64(arg1[0], arg2[2])
+       x158, x157 = bits.Mul64(x135, 0xffffffffffffffff)
        var x159 uint64
        var x160 uint64
-       x160, x159 = bits.Mul64(arg1[0], arg2[1])
+       x160, x159 = bits.Mul64(x135, 0xffffffffffffffff)
        var x161 uint64
        var x162 uint64
-       x162, x161 = bits.Mul64(arg1[0], arg2[0])
+       x162, x161 = bits.Mul64(x135, 0xffffffffffffffff)
        var x163 uint64
-       var x164 p521Uint1
-       x163, x164 = p521AddcarryxU64(x29, x15, 0x0)
+       var x164 uint64
+       x164, x163 = bits.Mul64(x135, 0xffffffffffffffff)
        var x165 uint64
-       x165, _ = p521AddcarryxU64(x30, x16, x164)
+       var x166 uint64
+       x166, x165 = bits.Mul64(x135, 0xffffffffffffffff)
        var x167 uint64
-       var x168 p521Uint1
-       x167, x168 = p521AddcarryxU64(x41, x163, 0x0)
+       var x168 uint64
+       x168, x167 = bits.Mul64(x135, 0xffffffffffffffff)
        var x169 uint64
-       x169, _ = p521AddcarryxU64(x42, x165, x168)
+       var x170 uint64
+       x170, x169 = bits.Mul64(x135, 0xffffffffffffffff)
        var x171 uint64
-       var x172 p521Uint1
-       x171, x172 = p521AddcarryxU64(x51, x167, 0x0)
+       var x172 uint64
+       x172, x171 = bits.Mul64(x135, 0xffffffffffffffff)
        var x173 uint64
-       x173, _ = p521AddcarryxU64(x52, x169, x172)
+       var x174 uint64
+       x173, x174 = bits.Add64(x172, x169, uint64(0x0))
        var x175 uint64
-       var x176 p521Uint1
-       x175, x176 = p521AddcarryxU64(x59, x171, 0x0)
+       var x176 uint64
+       x175, x176 = bits.Add64(x170, x167, uint64(p521Uint1(x174)))
        var x177 uint64
-       x177, _ = p521AddcarryxU64(x60, x173, x176)
+       var x178 uint64
+       x177, x178 = bits.Add64(x168, x165, uint64(p521Uint1(x176)))
        var x179 uint64
-       var x180 p521Uint1
-       x179, x180 = p521AddcarryxU64(x65, x175, 0x0)
+       var x180 uint64
+       x179, x180 = bits.Add64(x166, x163, uint64(p521Uint1(x178)))
        var x181 uint64
-       x181, _ = p521AddcarryxU64(x66, x177, x180)
+       var x182 uint64
+       x181, x182 = bits.Add64(x164, x161, uint64(p521Uint1(x180)))
        var x183 uint64
-       var x184 p521Uint1
-       x183, x184 = p521AddcarryxU64(x69, x179, 0x0)
+       var x184 uint64
+       x183, x184 = bits.Add64(x162, x159, uint64(p521Uint1(x182)))
        var x185 uint64
-       x185, _ = p521AddcarryxU64(x70, x181, x184)
+       var x186 uint64
+       x185, x186 = bits.Add64(x160, x157, uint64(p521Uint1(x184)))
        var x187 uint64
-       var x188 p521Uint1
-       x187, x188 = p521AddcarryxU64(x71, x183, 0x0)
-       var x189 uint64
-       x189, _ = p521AddcarryxU64(x72, x185, x188)
+       var x188 uint64
+       x187, x188 = bits.Add64(x158, x155, uint64(p521Uint1(x186)))
+       x189 := (uint64(p521Uint1(x188)) + x156)
        var x191 uint64
-       var x192 p521Uint1
-       x191, x192 = p521AddcarryxU64(x161, x187, 0x0)
+       _, x191 = bits.Add64(x135, x171, uint64(0x0))
+       var x192 uint64
        var x193 uint64
-       x193, _ = p521AddcarryxU64(x162, x189, x192)
-       x195 := ((x191 >> 58) | ((x193 << 6) & 0xffffffffffffffff))
-       x196 := (x193 >> 58)
-       x197 := (x191 & 0x3ffffffffffffff)
+       x192, x193 = bits.Add64(x137, x173, uint64(p521Uint1(x191)))
+       var x194 uint64
+       var x195 uint64
+       x194, x195 = bits.Add64(x139, x175, uint64(p521Uint1(x193)))
+       var x196 uint64
+       var x197 uint64
+       x196, x197 = bits.Add64(x141, x177, uint64(p521Uint1(x195)))
        var x198 uint64
-       var x199 p521Uint1
-       x198, x199 = p521AddcarryxU64(x75, x73, 0x0)
+       var x199 uint64
+       x198, x199 = bits.Add64(x143, x179, uint64(p521Uint1(x197)))
        var x200 uint64
-       x200, _ = p521AddcarryxU64(x76, x74, x199)
+       var x201 uint64
+       x200, x201 = bits.Add64(x145, x181, uint64(p521Uint1(x199)))
        var x202 uint64
-       var x203 p521Uint1
-       x202, x203 = p521AddcarryxU64(x79, x198, 0x0)
+       var x203 uint64
+       x202, x203 = bits.Add64(x147, x183, uint64(p521Uint1(x201)))
        var x204 uint64
-       x204, _ = p521AddcarryxU64(x80, x200, x203)
+       var x205 uint64
+       x204, x205 = bits.Add64(x149, x185, uint64(p521Uint1(x203)))
        var x206 uint64
-       var x207 p521Uint1
-       x206, x207 = p521AddcarryxU64(x85, x202, 0x0)
+       var x207 uint64
+       x206, x207 = bits.Add64(x151, x187, uint64(p521Uint1(x205)))
        var x208 uint64
-       x208, _ = p521AddcarryxU64(x86, x204, x207)
-       var x210 uint64
-       var x211 p521Uint1
-       x210, x211 = p521AddcarryxU64(x93, x206, 0x0)
+       var x209 uint64
+       x208, x209 = bits.Add64(x153, x189, uint64(p521Uint1(x207)))
+       x210 := (uint64(p521Uint1(x209)) + uint64(p521Uint1(x154)))
+       var x211 uint64
        var x212 uint64
-       x212, _ = p521AddcarryxU64(x94, x208, x211)
+       x212, x211 = bits.Mul64(x2, arg2[8])
+       var x213 uint64
        var x214 uint64
-       var x215 p521Uint1
-       x214, x215 = p521AddcarryxU64(x103, x210, 0x0)
+       x214, x213 = bits.Mul64(x2, arg2[7])
+       var x215 uint64
        var x216 uint64
-       x216, _ = p521AddcarryxU64(x104, x212, x215)
+       x216, x215 = bits.Mul64(x2, arg2[6])
+       var x217 uint64
        var x218 uint64
-       var x219 p521Uint1
-       x218, x219 = p521AddcarryxU64(x115, x214, 0x0)
+       x218, x217 = bits.Mul64(x2, arg2[5])
+       var x219 uint64
        var x220 uint64
-       x220, _ = p521AddcarryxU64(x116, x216, x219)
+       x220, x219 = bits.Mul64(x2, arg2[4])
+       var x221 uint64
        var x222 uint64
-       var x223 p521Uint1
-       x222, x223 = p521AddcarryxU64(x129, x218, 0x0)
+       x222, x221 = bits.Mul64(x2, arg2[3])
+       var x223 uint64
        var x224 uint64
-       x224, _ = p521AddcarryxU64(x130, x220, x223)
+       x224, x223 = bits.Mul64(x2, arg2[2])
+       var x225 uint64
        var x226 uint64
-       var x227 p521Uint1
-       x226, x227 = p521AddcarryxU64(x145, x222, 0x0)
+       x226, x225 = bits.Mul64(x2, arg2[1])
+       var x227 uint64
        var x228 uint64
-       x228, _ = p521AddcarryxU64(x146, x224, x227)
+       x228, x227 = bits.Mul64(x2, arg2[0])
+       var x229 uint64
        var x230 uint64
-       var x231 p521Uint1
-       x230, x231 = p521AddcarryxU64(x77, x1, 0x0)
+       x229, x230 = bits.Add64(x228, x225, uint64(0x0))
+       var x231 uint64
        var x232 uint64
-       x232, _ = p521AddcarryxU64(x78, x2, x231)
+       x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230)))
+       var x233 uint64
        var x234 uint64
-       var x235 p521Uint1
-       x234, x235 = p521AddcarryxU64(x81, x230, 0x0)
+       x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232)))
+       var x235 uint64
        var x236 uint64
-       x236, _ = p521AddcarryxU64(x82, x232, x235)
+       x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234)))
+       var x237 uint64
        var x238 uint64
-       var x239 p521Uint1
-       x238, x239 = p521AddcarryxU64(x87, x234, 0x0)
+       x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236)))
+       var x239 uint64
        var x240 uint64
-       x240, _ = p521AddcarryxU64(x88, x236, x239)
+       x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238)))
+       var x241 uint64
        var x242 uint64
-       var x243 p521Uint1
-       x242, x243 = p521AddcarryxU64(x95, x238, 0x0)
+       x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240)))
+       var x243 uint64
        var x244 uint64
-       x244, _ = p521AddcarryxU64(x96, x240, x243)
+       x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242)))
+       x245 := (uint64(p521Uint1(x244)) + x212)
        var x246 uint64
-       var x247 p521Uint1
-       x246, x247 = p521AddcarryxU64(x105, x242, 0x0)
+       var x247 uint64
+       x246, x247 = bits.Add64(x192, x227, uint64(0x0))
        var x248 uint64
-       x248, _ = p521AddcarryxU64(x106, x244, x247)
+       var x249 uint64
+       x248, x249 = bits.Add64(x194, x229, uint64(p521Uint1(x247)))
        var x250 uint64
-       var x251 p521Uint1
-       x250, x251 = p521AddcarryxU64(x117, x246, 0x0)
+       var x251 uint64
+       x250, x251 = bits.Add64(x196, x231, uint64(p521Uint1(x249)))
        var x252 uint64
-       x252, _ = p521AddcarryxU64(x118, x248, x251)
+       var x253 uint64
+       x252, x253 = bits.Add64(x198, x233, uint64(p521Uint1(x251)))
        var x254 uint64
-       var x255 p521Uint1
-       x254, x255 = p521AddcarryxU64(x131, x250, 0x0)
+       var x255 uint64
+       x254, x255 = bits.Add64(x200, x235, uint64(p521Uint1(x253)))
        var x256 uint64
-       x256, _ = p521AddcarryxU64(x132, x252, x255)
+       var x257 uint64
+       x256, x257 = bits.Add64(x202, x237, uint64(p521Uint1(x255)))
        var x258 uint64
-       var x259 p521Uint1
-       x258, x259 = p521AddcarryxU64(x147, x254, 0x0)
+       var x259 uint64
+       x258, x259 = bits.Add64(x204, x239, uint64(p521Uint1(x257)))
        var x260 uint64
-       x260, _ = p521AddcarryxU64(x148, x256, x259)
+       var x261 uint64
+       x260, x261 = bits.Add64(x206, x241, uint64(p521Uint1(x259)))
        var x262 uint64
-       var x263 p521Uint1
-       x262, x263 = p521AddcarryxU64(x17, x3, 0x0)
+       var x263 uint64
+       x262, x263 = bits.Add64(x208, x243, uint64(p521Uint1(x261)))
        var x264 uint64
-       x264, _ = p521AddcarryxU64(x18, x4, x263)
+       var x265 uint64
+       x264, x265 = bits.Add64(x210, x245, uint64(p521Uint1(x263)))
        var x266 uint64
-       var x267 p521Uint1
-       x266, x267 = p521AddcarryxU64(x83, x262, 0x0)
+       var x267 uint64
+       x267, x266 = bits.Mul64(x246, 0x1ff)
        var x268 uint64
-       x268, _ = p521AddcarryxU64(x84, x264, x267)
+       var x269 uint64
+       x269, x268 = bits.Mul64(x246, 0xffffffffffffffff)
        var x270 uint64
-       var x271 p521Uint1
-       x270, x271 = p521AddcarryxU64(x89, x266, 0x0)
+       var x271 uint64
+       x271, x270 = bits.Mul64(x246, 0xffffffffffffffff)
        var x272 uint64
-       x272, _ = p521AddcarryxU64(x90, x268, x271)
+       var x273 uint64
+       x273, x272 = bits.Mul64(x246, 0xffffffffffffffff)
        var x274 uint64
-       var x275 p521Uint1
-       x274, x275 = p521AddcarryxU64(x97, x270, 0x0)
+       var x275 uint64
+       x275, x274 = bits.Mul64(x246, 0xffffffffffffffff)
        var x276 uint64
-       x276, _ = p521AddcarryxU64(x98, x272, x275)
+       var x277 uint64
+       x277, x276 = bits.Mul64(x246, 0xffffffffffffffff)
        var x278 uint64
-       var x279 p521Uint1
-       x278, x279 = p521AddcarryxU64(x107, x274, 0x0)
+       var x279 uint64
+       x279, x278 = bits.Mul64(x246, 0xffffffffffffffff)
        var x280 uint64
-       x280, _ = p521AddcarryxU64(x108, x276, x279)
+       var x281 uint64
+       x281, x280 = bits.Mul64(x246, 0xffffffffffffffff)
        var x282 uint64
-       var x283 p521Uint1
-       x282, x283 = p521AddcarryxU64(x119, x278, 0x0)
+       var x283 uint64
+       x283, x282 = bits.Mul64(x246, 0xffffffffffffffff)
        var x284 uint64
-       x284, _ = p521AddcarryxU64(x120, x280, x283)
+       var x285 uint64
+       x284, x285 = bits.Add64(x283, x280, uint64(0x0))
        var x286 uint64
-       var x287 p521Uint1
-       x286, x287 = p521AddcarryxU64(x133, x282, 0x0)
+       var x287 uint64
+       x286, x287 = bits.Add64(x281, x278, uint64(p521Uint1(x285)))
        var x288 uint64
-       x288, _ = p521AddcarryxU64(x134, x284, x287)
+       var x289 uint64
+       x288, x289 = bits.Add64(x279, x276, uint64(p521Uint1(x287)))
        var x290 uint64
-       var x291 p521Uint1
-       x290, x291 = p521AddcarryxU64(x149, x286, 0x0)
+       var x291 uint64
+       x290, x291 = bits.Add64(x277, x274, uint64(p521Uint1(x289)))
        var x292 uint64
-       x292, _ = p521AddcarryxU64(x150, x288, x291)
+       var x293 uint64
+       x292, x293 = bits.Add64(x275, x272, uint64(p521Uint1(x291)))
        var x294 uint64
-       var x295 p521Uint1
-       x294, x295 = p521AddcarryxU64(x19, x5, 0x0)
+       var x295 uint64
+       x294, x295 = bits.Add64(x273, x270, uint64(p521Uint1(x293)))
        var x296 uint64
-       x296, _ = p521AddcarryxU64(x20, x6, x295)
+       var x297 uint64
+       x296, x297 = bits.Add64(x271, x268, uint64(p521Uint1(x295)))
        var x298 uint64
-       var x299 p521Uint1
-       x298, x299 = p521AddcarryxU64(x31, x294, 0x0)
-       var x300 uint64
-       x300, _ = p521AddcarryxU64(x32, x296, x299)
+       var x299 uint64
+       x298, x299 = bits.Add64(x269, x266, uint64(p521Uint1(x297)))
+       x300 := (uint64(p521Uint1(x299)) + x267)
        var x302 uint64
-       var x303 p521Uint1
-       x302, x303 = p521AddcarryxU64(x91, x298, 0x0)
+       _, x302 = bits.Add64(x246, x282, uint64(0x0))
+       var x303 uint64
        var x304 uint64
-       x304, _ = p521AddcarryxU64(x92, x300, x303)
+       x303, x304 = bits.Add64(x248, x284, uint64(p521Uint1(x302)))
+       var x305 uint64
        var x306 uint64
-       var x307 p521Uint1
-       x306, x307 = p521AddcarryxU64(x99, x302, 0x0)
+       x305, x306 = bits.Add64(x250, x286, uint64(p521Uint1(x304)))
+       var x307 uint64
        var x308 uint64
-       x308, _ = p521AddcarryxU64(x100, x304, x307)
+       x307, x308 = bits.Add64(x252, x288, uint64(p521Uint1(x306)))
+       var x309 uint64
        var x310 uint64
-       var x311 p521Uint1
-       x310, x311 = p521AddcarryxU64(x109, x306, 0x0)
+       x309, x310 = bits.Add64(x254, x290, uint64(p521Uint1(x308)))
+       var x311 uint64
        var x312 uint64
-       x312, _ = p521AddcarryxU64(x110, x308, x311)
+       x311, x312 = bits.Add64(x256, x292, uint64(p521Uint1(x310)))
+       var x313 uint64
        var x314 uint64
-       var x315 p521Uint1
-       x314, x315 = p521AddcarryxU64(x121, x310, 0x0)
+       x313, x314 = bits.Add64(x258, x294, uint64(p521Uint1(x312)))
+       var x315 uint64
        var x316 uint64
-       x316, _ = p521AddcarryxU64(x122, x312, x315)
+       x315, x316 = bits.Add64(x260, x296, uint64(p521Uint1(x314)))
+       var x317 uint64
        var x318 uint64
-       var x319 p521Uint1
-       x318, x319 = p521AddcarryxU64(x135, x314, 0x0)
+       x317, x318 = bits.Add64(x262, x298, uint64(p521Uint1(x316)))
+       var x319 uint64
        var x320 uint64
-       x320, _ = p521AddcarryxU64(x136, x316, x319)
+       x319, x320 = bits.Add64(x264, x300, uint64(p521Uint1(x318)))
+       x321 := (uint64(p521Uint1(x320)) + uint64(p521Uint1(x265)))
        var x322 uint64
-       var x323 p521Uint1
-       x322, x323 = p521AddcarryxU64(x151, x318, 0x0)
+       var x323 uint64
+       x323, x322 = bits.Mul64(x3, arg2[8])
        var x324 uint64
-       x324, _ = p521AddcarryxU64(x152, x320, x323)
+       var x325 uint64
+       x325, x324 = bits.Mul64(x3, arg2[7])
        var x326 uint64
-       var x327 p521Uint1
-       x326, x327 = p521AddcarryxU64(x21, x7, 0x0)
+       var x327 uint64
+       x327, x326 = bits.Mul64(x3, arg2[6])
        var x328 uint64
-       x328, _ = p521AddcarryxU64(x22, x8, x327)
+       var x329 uint64
+       x329, x328 = bits.Mul64(x3, arg2[5])
        var x330 uint64
-       var x331 p521Uint1
-       x330, x331 = p521AddcarryxU64(x33, x326, 0x0)
+       var x331 uint64
+       x331, x330 = bits.Mul64(x3, arg2[4])
        var x332 uint64
-       x332, _ = p521AddcarryxU64(x34, x328, x331)
+       var x333 uint64
+       x333, x332 = bits.Mul64(x3, arg2[3])
        var x334 uint64
-       var x335 p521Uint1
-       x334, x335 = p521AddcarryxU64(x43, x330, 0x0)
+       var x335 uint64
+       x335, x334 = bits.Mul64(x3, arg2[2])
        var x336 uint64
-       x336, _ = p521AddcarryxU64(x44, x332, x335)
+       var x337 uint64
+       x337, x336 = bits.Mul64(x3, arg2[1])
        var x338 uint64
-       var x339 p521Uint1
-       x338, x339 = p521AddcarryxU64(x101, x334, 0x0)
+       var x339 uint64
+       x339, x338 = bits.Mul64(x3, arg2[0])
        var x340 uint64
-       x340, _ = p521AddcarryxU64(x102, x336, x339)
+       var x341 uint64
+       x340, x341 = bits.Add64(x339, x336, uint64(0x0))
        var x342 uint64
-       var x343 p521Uint1
-       x342, x343 = p521AddcarryxU64(x111, x338, 0x0)
+       var x343 uint64
+       x342, x343 = bits.Add64(x337, x334, uint64(p521Uint1(x341)))
        var x344 uint64
-       x344, _ = p521AddcarryxU64(x112, x340, x343)
+       var x345 uint64
+       x344, x345 = bits.Add64(x335, x332, uint64(p521Uint1(x343)))
        var x346 uint64
-       var x347 p521Uint1
-       x346, x347 = p521AddcarryxU64(x123, x342, 0x0)
+       var x347 uint64
+       x346, x347 = bits.Add64(x333, x330, uint64(p521Uint1(x345)))
        var x348 uint64
-       x348, _ = p521AddcarryxU64(x124, x344, x347)
+       var x349 uint64
+       x348, x349 = bits.Add64(x331, x328, uint64(p521Uint1(x347)))
        var x350 uint64
-       var x351 p521Uint1
-       x350, x351 = p521AddcarryxU64(x137, x346, 0x0)
+       var x351 uint64
+       x350, x351 = bits.Add64(x329, x326, uint64(p521Uint1(x349)))
        var x352 uint64
-       x352, _ = p521AddcarryxU64(x138, x348, x351)
+       var x353 uint64
+       x352, x353 = bits.Add64(x327, x324, uint64(p521Uint1(x351)))
        var x354 uint64
-       var x355 p521Uint1
-       x354, x355 = p521AddcarryxU64(x153, x350, 0x0)
-       var x356 uint64
-       x356, _ = p521AddcarryxU64(x154, x352, x355)
+       var x355 uint64
+       x354, x355 = bits.Add64(x325, x322, uint64(p521Uint1(x353)))
+       x356 := (uint64(p521Uint1(x355)) + x323)
+       var x357 uint64
        var x358 uint64
-       var x359 p521Uint1
-       x358, x359 = p521AddcarryxU64(x23, x9, 0x0)
+       x357, x358 = bits.Add64(x303, x338, uint64(0x0))
+       var x359 uint64
        var x360 uint64
-       x360, _ = p521AddcarryxU64(x24, x10, x359)
+       x359, x360 = bits.Add64(x305, x340, uint64(p521Uint1(x358)))
+       var x361 uint64
        var x362 uint64
-       var x363 p521Uint1
-       x362, x363 = p521AddcarryxU64(x35, x358, 0x0)
+       x361, x362 = bits.Add64(x307, x342, uint64(p521Uint1(x360)))
+       var x363 uint64
        var x364 uint64
-       x364, _ = p521AddcarryxU64(x36, x360, x363)
+       x363, x364 = bits.Add64(x309, x344, uint64(p521Uint1(x362)))
+       var x365 uint64
        var x366 uint64
-       var x367 p521Uint1
-       x366, x367 = p521AddcarryxU64(x45, x362, 0x0)
+       x365, x366 = bits.Add64(x311, x346, uint64(p521Uint1(x364)))
+       var x367 uint64
        var x368 uint64
-       x368, _ = p521AddcarryxU64(x46, x364, x367)
+       x367, x368 = bits.Add64(x313, x348, uint64(p521Uint1(x366)))
+       var x369 uint64
        var x370 uint64
-       var x371 p521Uint1
-       x370, x371 = p521AddcarryxU64(x53, x366, 0x0)
+       x369, x370 = bits.Add64(x315, x350, uint64(p521Uint1(x368)))
+       var x371 uint64
        var x372 uint64
-       x372, _ = p521AddcarryxU64(x54, x368, x371)
+       x371, x372 = bits.Add64(x317, x352, uint64(p521Uint1(x370)))
+       var x373 uint64
        var x374 uint64
-       var x375 p521Uint1
-       x374, x375 = p521AddcarryxU64(x113, x370, 0x0)
+       x373, x374 = bits.Add64(x319, x354, uint64(p521Uint1(x372)))
+       var x375 uint64
        var x376 uint64
-       x376, _ = p521AddcarryxU64(x114, x372, x375)
+       x375, x376 = bits.Add64(x321, x356, uint64(p521Uint1(x374)))
+       var x377 uint64
        var x378 uint64
-       var x379 p521Uint1
-       x378, x379 = p521AddcarryxU64(x125, x374, 0x0)
+       x378, x377 = bits.Mul64(x357, 0x1ff)
+       var x379 uint64
        var x380 uint64
-       x380, _ = p521AddcarryxU64(x126, x376, x379)
+       x380, x379 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x381 uint64
        var x382 uint64
-       var x383 p521Uint1
-       x382, x383 = p521AddcarryxU64(x139, x378, 0x0)
+       x382, x381 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x383 uint64
        var x384 uint64
-       x384, _ = p521AddcarryxU64(x140, x380, x383)
+       x384, x383 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x385 uint64
        var x386 uint64
-       var x387 p521Uint1
-       x386, x387 = p521AddcarryxU64(x155, x382, 0x0)
+       x386, x385 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x387 uint64
        var x388 uint64
-       x388, _ = p521AddcarryxU64(x156, x384, x387)
+       x388, x387 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x389 uint64
        var x390 uint64
-       var x391 p521Uint1
-       x390, x391 = p521AddcarryxU64(x25, x11, 0x0)
+       x390, x389 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x391 uint64
        var x392 uint64
-       x392, _ = p521AddcarryxU64(x26, x12, x391)
+       x392, x391 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x393 uint64
        var x394 uint64
-       var x395 p521Uint1
-       x394, x395 = p521AddcarryxU64(x37, x390, 0x0)
+       x394, x393 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x395 uint64
        var x396 uint64
-       x396, _ = p521AddcarryxU64(x38, x392, x395)
+       x395, x396 = bits.Add64(x394, x391, uint64(0x0))
+       var x397 uint64
        var x398 uint64
-       var x399 p521Uint1
-       x398, x399 = p521AddcarryxU64(x47, x394, 0x0)
+       x397, x398 = bits.Add64(x392, x389, uint64(p521Uint1(x396)))
+       var x399 uint64
        var x400 uint64
-       x400, _ = p521AddcarryxU64(x48, x396, x399)
+       x399, x400 = bits.Add64(x390, x387, uint64(p521Uint1(x398)))
+       var x401 uint64
        var x402 uint64
-       var x403 p521Uint1
-       x402, x403 = p521AddcarryxU64(x55, x398, 0x0)
+       x401, x402 = bits.Add64(x388, x385, uint64(p521Uint1(x400)))
+       var x403 uint64
        var x404 uint64
-       x404, _ = p521AddcarryxU64(x56, x400, x403)
+       x403, x404 = bits.Add64(x386, x383, uint64(p521Uint1(x402)))
+       var x405 uint64
        var x406 uint64
-       var x407 p521Uint1
-       x406, x407 = p521AddcarryxU64(x61, x402, 0x0)
+       x405, x406 = bits.Add64(x384, x381, uint64(p521Uint1(x404)))
+       var x407 uint64
        var x408 uint64
-       x408, _ = p521AddcarryxU64(x62, x404, x407)
+       x407, x408 = bits.Add64(x382, x379, uint64(p521Uint1(x406)))
+       var x409 uint64
        var x410 uint64
-       var x411 p521Uint1
-       x410, x411 = p521AddcarryxU64(x127, x406, 0x0)
-       var x412 uint64
-       x412, _ = p521AddcarryxU64(x128, x408, x411)
+       x409, x410 = bits.Add64(x380, x377, uint64(p521Uint1(x408)))
+       x411 := (uint64(p521Uint1(x410)) + x378)
+       var x413 uint64
+       _, x413 = bits.Add64(x357, x393, uint64(0x0))
        var x414 uint64
-       var x415 p521Uint1
-       x414, x415 = p521AddcarryxU64(x141, x410, 0x0)
+       var x415 uint64
+       x414, x415 = bits.Add64(x359, x395, uint64(p521Uint1(x413)))
        var x416 uint64
-       x416, _ = p521AddcarryxU64(x142, x412, x415)
+       var x417 uint64
+       x416, x417 = bits.Add64(x361, x397, uint64(p521Uint1(x415)))
        var x418 uint64
-       var x419 p521Uint1
-       x418, x419 = p521AddcarryxU64(x157, x414, 0x0)
+       var x419 uint64
+       x418, x419 = bits.Add64(x363, x399, uint64(p521Uint1(x417)))
        var x420 uint64
-       x420, _ = p521AddcarryxU64(x158, x416, x419)
+       var x421 uint64
+       x420, x421 = bits.Add64(x365, x401, uint64(p521Uint1(x419)))
        var x422 uint64
-       var x423 p521Uint1
-       x422, x423 = p521AddcarryxU64(x27, x13, 0x0)
+       var x423 uint64
+       x422, x423 = bits.Add64(x367, x403, uint64(p521Uint1(x421)))
        var x424 uint64
-       x424, _ = p521AddcarryxU64(x28, x14, x423)
+       var x425 uint64
+       x424, x425 = bits.Add64(x369, x405, uint64(p521Uint1(x423)))
        var x426 uint64
-       var x427 p521Uint1
-       x426, x427 = p521AddcarryxU64(x39, x422, 0x0)
+       var x427 uint64
+       x426, x427 = bits.Add64(x371, x407, uint64(p521Uint1(x425)))
        var x428 uint64
-       x428, _ = p521AddcarryxU64(x40, x424, x427)
+       var x429 uint64
+       x428, x429 = bits.Add64(x373, x409, uint64(p521Uint1(x427)))
        var x430 uint64
-       var x431 p521Uint1
-       x430, x431 = p521AddcarryxU64(x49, x426, 0x0)
-       var x432 uint64
-       x432, _ = p521AddcarryxU64(x50, x428, x431)
+       var x431 uint64
+       x430, x431 = bits.Add64(x375, x411, uint64(p521Uint1(x429)))
+       x432 := (uint64(p521Uint1(x431)) + uint64(p521Uint1(x376)))
+       var x433 uint64
        var x434 uint64
-       var x435 p521Uint1
-       x434, x435 = p521AddcarryxU64(x57, x430, 0x0)
+       x434, x433 = bits.Mul64(x4, arg2[8])
+       var x435 uint64
        var x436 uint64
-       x436, _ = p521AddcarryxU64(x58, x432, x435)
+       x436, x435 = bits.Mul64(x4, arg2[7])
+       var x437 uint64
        var x438 uint64
-       var x439 p521Uint1
-       x438, x439 = p521AddcarryxU64(x63, x434, 0x0)
+       x438, x437 = bits.Mul64(x4, arg2[6])
+       var x439 uint64
        var x440 uint64
-       x440, _ = p521AddcarryxU64(x64, x436, x439)
+       x440, x439 = bits.Mul64(x4, arg2[5])
+       var x441 uint64
        var x442 uint64
-       var x443 p521Uint1
-       x442, x443 = p521AddcarryxU64(x67, x438, 0x0)
+       x442, x441 = bits.Mul64(x4, arg2[4])
+       var x443 uint64
        var x444 uint64
-       x444, _ = p521AddcarryxU64(x68, x440, x443)
+       x444, x443 = bits.Mul64(x4, arg2[3])
+       var x445 uint64
        var x446 uint64
-       var x447 p521Uint1
-       x446, x447 = p521AddcarryxU64(x143, x442, 0x0)
+       x446, x445 = bits.Mul64(x4, arg2[2])
+       var x447 uint64
        var x448 uint64
-       x448, _ = p521AddcarryxU64(x144, x444, x447)
+       x448, x447 = bits.Mul64(x4, arg2[1])
+       var x449 uint64
        var x450 uint64
-       var x451 p521Uint1
-       x450, x451 = p521AddcarryxU64(x159, x446, 0x0)
+       x450, x449 = bits.Mul64(x4, arg2[0])
+       var x451 uint64
        var x452 uint64
-       x452, _ = p521AddcarryxU64(x160, x448, x451)
+       x451, x452 = bits.Add64(x450, x447, uint64(0x0))
+       var x453 uint64
        var x454 uint64
-       var x455 p521Uint1
-       x454, x455 = p521AddcarryxU64(x195, x450, 0x0)
+       x453, x454 = bits.Add64(x448, x445, uint64(p521Uint1(x452)))
+       var x455 uint64
        var x456 uint64
-       x456, _ = p521AddcarryxU64(x196, x452, x455)
-       x458 := ((x454 >> 58) | ((x456 << 6) & 0xffffffffffffffff))
-       x459 := (x456 >> 58)
-       x460 := (x454 & 0x3ffffffffffffff)
+       x455, x456 = bits.Add64(x446, x443, uint64(p521Uint1(x454)))
+       var x457 uint64
+       var x458 uint64
+       x457, x458 = bits.Add64(x444, x441, uint64(p521Uint1(x456)))
+       var x459 uint64
+       var x460 uint64
+       x459, x460 = bits.Add64(x442, x439, uint64(p521Uint1(x458)))
        var x461 uint64
-       var x462 p521Uint1
-       x461, x462 = p521AddcarryxU64(x458, x418, 0x0)
+       var x462 uint64
+       x461, x462 = bits.Add64(x440, x437, uint64(p521Uint1(x460)))
        var x463 uint64
-       x463, _ = p521AddcarryxU64(x459, x420, x462)
-       x465 := ((x461 >> 58) | ((x463 << 6) & 0xffffffffffffffff))
-       x466 := (x463 >> 58)
-       x467 := (x461 & 0x3ffffffffffffff)
+       var x464 uint64
+       x463, x464 = bits.Add64(x438, x435, uint64(p521Uint1(x462)))
+       var x465 uint64
+       var x466 uint64
+       x465, x466 = bits.Add64(x436, x433, uint64(p521Uint1(x464)))
+       x467 := (uint64(p521Uint1(x466)) + x434)
        var x468 uint64
-       var x469 p521Uint1
-       x468, x469 = p521AddcarryxU64(x465, x386, 0x0)
+       var x469 uint64
+       x468, x469 = bits.Add64(x414, x449, uint64(0x0))
        var x470 uint64
-       x470, _ = p521AddcarryxU64(x466, x388, x469)
-       x472 := ((x468 >> 58) | ((x470 << 6) & 0xffffffffffffffff))
-       x473 := (x470 >> 58)
-       x474 := (x468 & 0x3ffffffffffffff)
+       var x471 uint64
+       x470, x471 = bits.Add64(x416, x451, uint64(p521Uint1(x469)))
+       var x472 uint64
+       var x473 uint64
+       x472, x473 = bits.Add64(x418, x453, uint64(p521Uint1(x471)))
+       var x474 uint64
        var x475 uint64
-       var x476 p521Uint1
-       x475, x476 = p521AddcarryxU64(x472, x354, 0x0)
+       x474, x475 = bits.Add64(x420, x455, uint64(p521Uint1(x473)))
+       var x476 uint64
        var x477 uint64
-       x477, _ = p521AddcarryxU64(x473, x356, x476)
-       x479 := ((x475 >> 58) | ((x477 << 6) & 0xffffffffffffffff))
-       x480 := (x477 >> 58)
-       x481 := (x475 & 0x3ffffffffffffff)
+       x476, x477 = bits.Add64(x422, x457, uint64(p521Uint1(x475)))
+       var x478 uint64
+       var x479 uint64
+       x478, x479 = bits.Add64(x424, x459, uint64(p521Uint1(x477)))
+       var x480 uint64
+       var x481 uint64
+       x480, x481 = bits.Add64(x426, x461, uint64(p521Uint1(x479)))
        var x482 uint64
-       var x483 p521Uint1
-       x482, x483 = p521AddcarryxU64(x479, x322, 0x0)
+       var x483 uint64
+       x482, x483 = bits.Add64(x428, x463, uint64(p521Uint1(x481)))
        var x484 uint64
-       x484, _ = p521AddcarryxU64(x480, x324, x483)
-       x486 := ((x482 >> 58) | ((x484 << 6) & 0xffffffffffffffff))
-       x487 := (x484 >> 58)
-       x488 := (x482 & 0x3ffffffffffffff)
+       var x485 uint64
+       x484, x485 = bits.Add64(x430, x465, uint64(p521Uint1(x483)))
+       var x486 uint64
+       var x487 uint64
+       x486, x487 = bits.Add64(x432, x467, uint64(p521Uint1(x485)))
+       var x488 uint64
        var x489 uint64
-       var x490 p521Uint1
-       x489, x490 = p521AddcarryxU64(x486, x290, 0x0)
+       x489, x488 = bits.Mul64(x468, 0x1ff)
+       var x490 uint64
        var x491 uint64
-       x491, _ = p521AddcarryxU64(x487, x292, x490)
-       x493 := ((x489 >> 58) | ((x491 << 6) & 0xffffffffffffffff))
-       x494 := (x491 >> 58)
-       x495 := (x489 & 0x3ffffffffffffff)
+       x491, x490 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x492 uint64
+       var x493 uint64
+       x493, x492 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x494 uint64
+       var x495 uint64
+       x495, x494 = bits.Mul64(x468, 0xffffffffffffffff)
        var x496 uint64
-       var x497 p521Uint1
-       x496, x497 = p521AddcarryxU64(x493, x258, 0x0)
+       var x497 uint64
+       x497, x496 = bits.Mul64(x468, 0xffffffffffffffff)
        var x498 uint64
-       x498, _ = p521AddcarryxU64(x494, x260, x497)
-       x500 := ((x496 >> 58) | ((x498 << 6) & 0xffffffffffffffff))
-       x501 := (x498 >> 58)
-       x502 := (x496 & 0x3ffffffffffffff)
+       var x499 uint64
+       x499, x498 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x500 uint64
+       var x501 uint64
+       x501, x500 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x502 uint64
        var x503 uint64
-       var x504 p521Uint1
-       x503, x504 = p521AddcarryxU64(x500, x226, 0x0)
+       x503, x502 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x504 uint64
        var x505 uint64
-       x505, _ = p521AddcarryxU64(x501, x228, x504)
-       x507 := ((x503 >> 57) | ((x505 << 7) & 0xffffffffffffffff))
-       x508 := (x505 >> 57)
-       x509 := (x503 & 0x1ffffffffffffff)
+       x505, x504 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x506 uint64
+       var x507 uint64
+       x506, x507 = bits.Add64(x505, x502, uint64(0x0))
+       var x508 uint64
+       var x509 uint64
+       x508, x509 = bits.Add64(x503, x500, uint64(p521Uint1(x507)))
        var x510 uint64
-       var x511 p521Uint1
-       x510, x511 = p521AddcarryxU64(x197, x507, 0x0)
-       x512 := (uint64(x511) + x508)
-       x513 := ((x510 >> 58) | ((x512 << 6) & 0xffffffffffffffff))
-       x514 := (x510 & 0x3ffffffffffffff)
-       x515 := (x513 + x460)
-       x516 := p521Uint1((x515 >> 58))
-       x517 := (x515 & 0x3ffffffffffffff)
-       x518 := (uint64(x516) + x467)
-       out1[0] = x514
-       out1[1] = x517
-       out1[2] = x518
-       out1[3] = x474
-       out1[4] = x481
-       out1[5] = x488
-       out1[6] = x495
-       out1[7] = x502
-       out1[8] = x509
+       var x511 uint64
+       x510, x511 = bits.Add64(x501, x498, uint64(p521Uint1(x509)))
+       var x512 uint64
+       var x513 uint64
+       x512, x513 = bits.Add64(x499, x496, uint64(p521Uint1(x511)))
+       var x514 uint64
+       var x515 uint64
+       x514, x515 = bits.Add64(x497, x494, uint64(p521Uint1(x513)))
+       var x516 uint64
+       var x517 uint64
+       x516, x517 = bits.Add64(x495, x492, uint64(p521Uint1(x515)))
+       var x518 uint64
+       var x519 uint64
+       x518, x519 = bits.Add64(x493, x490, uint64(p521Uint1(x517)))
+       var x520 uint64
+       var x521 uint64
+       x520, x521 = bits.Add64(x491, x488, uint64(p521Uint1(x519)))
+       x522 := (uint64(p521Uint1(x521)) + x489)
+       var x524 uint64
+       _, x524 = bits.Add64(x468, x504, uint64(0x0))
+       var x525 uint64
+       var x526 uint64
+       x525, x526 = bits.Add64(x470, x506, uint64(p521Uint1(x524)))
+       var x527 uint64
+       var x528 uint64
+       x527, x528 = bits.Add64(x472, x508, uint64(p521Uint1(x526)))
+       var x529 uint64
+       var x530 uint64
+       x529, x530 = bits.Add64(x474, x510, uint64(p521Uint1(x528)))
+       var x531 uint64
+       var x532 uint64
+       x531, x532 = bits.Add64(x476, x512, uint64(p521Uint1(x530)))
+       var x533 uint64
+       var x534 uint64
+       x533, x534 = bits.Add64(x478, x514, uint64(p521Uint1(x532)))
+       var x535 uint64
+       var x536 uint64
+       x535, x536 = bits.Add64(x480, x516, uint64(p521Uint1(x534)))
+       var x537 uint64
+       var x538 uint64
+       x537, x538 = bits.Add64(x482, x518, uint64(p521Uint1(x536)))
+       var x539 uint64
+       var x540 uint64
+       x539, x540 = bits.Add64(x484, x520, uint64(p521Uint1(x538)))
+       var x541 uint64
+       var x542 uint64
+       x541, x542 = bits.Add64(x486, x522, uint64(p521Uint1(x540)))
+       x543 := (uint64(p521Uint1(x542)) + uint64(p521Uint1(x487)))
+       var x544 uint64
+       var x545 uint64
+       x545, x544 = bits.Mul64(x5, arg2[8])
+       var x546 uint64
+       var x547 uint64
+       x547, x546 = bits.Mul64(x5, arg2[7])
+       var x548 uint64
+       var x549 uint64
+       x549, x548 = bits.Mul64(x5, arg2[6])
+       var x550 uint64
+       var x551 uint64
+       x551, x550 = bits.Mul64(x5, arg2[5])
+       var x552 uint64
+       var x553 uint64
+       x553, x552 = bits.Mul64(x5, arg2[4])
+       var x554 uint64
+       var x555 uint64
+       x555, x554 = bits.Mul64(x5, arg2[3])
+       var x556 uint64
+       var x557 uint64
+       x557, x556 = bits.Mul64(x5, arg2[2])
+       var x558 uint64
+       var x559 uint64
+       x559, x558 = bits.Mul64(x5, arg2[1])
+       var x560 uint64
+       var x561 uint64
+       x561, x560 = bits.Mul64(x5, arg2[0])
+       var x562 uint64
+       var x563 uint64
+       x562, x563 = bits.Add64(x561, x558, uint64(0x0))
+       var x564 uint64
+       var x565 uint64
+       x564, x565 = bits.Add64(x559, x556, uint64(p521Uint1(x563)))
+       var x566 uint64
+       var x567 uint64
+       x566, x567 = bits.Add64(x557, x554, uint64(p521Uint1(x565)))
+       var x568 uint64
+       var x569 uint64
+       x568, x569 = bits.Add64(x555, x552, uint64(p521Uint1(x567)))
+       var x570 uint64
+       var x571 uint64
+       x570, x571 = bits.Add64(x553, x550, uint64(p521Uint1(x569)))
+       var x572 uint64
+       var x573 uint64
+       x572, x573 = bits.Add64(x551, x548, uint64(p521Uint1(x571)))
+       var x574 uint64
+       var x575 uint64
+       x574, x575 = bits.Add64(x549, x546, uint64(p521Uint1(x573)))
+       var x576 uint64
+       var x577 uint64
+       x576, x577 = bits.Add64(x547, x544, uint64(p521Uint1(x575)))
+       x578 := (uint64(p521Uint1(x577)) + x545)
+       var x579 uint64
+       var x580 uint64
+       x579, x580 = bits.Add64(x525, x560, uint64(0x0))
+       var x581 uint64
+       var x582 uint64
+       x581, x582 = bits.Add64(x527, x562, uint64(p521Uint1(x580)))
+       var x583 uint64
+       var x584 uint64
+       x583, x584 = bits.Add64(x529, x564, uint64(p521Uint1(x582)))
+       var x585 uint64
+       var x586 uint64
+       x585, x586 = bits.Add64(x531, x566, uint64(p521Uint1(x584)))
+       var x587 uint64
+       var x588 uint64
+       x587, x588 = bits.Add64(x533, x568, uint64(p521Uint1(x586)))
+       var x589 uint64
+       var x590 uint64
+       x589, x590 = bits.Add64(x535, x570, uint64(p521Uint1(x588)))
+       var x591 uint64
+       var x592 uint64
+       x591, x592 = bits.Add64(x537, x572, uint64(p521Uint1(x590)))
+       var x593 uint64
+       var x594 uint64
+       x593, x594 = bits.Add64(x539, x574, uint64(p521Uint1(x592)))
+       var x595 uint64
+       var x596 uint64
+       x595, x596 = bits.Add64(x541, x576, uint64(p521Uint1(x594)))
+       var x597 uint64
+       var x598 uint64
+       x597, x598 = bits.Add64(x543, x578, uint64(p521Uint1(x596)))
+       var x599 uint64
+       var x600 uint64
+       x600, x599 = bits.Mul64(x579, 0x1ff)
+       var x601 uint64
+       var x602 uint64
+       x602, x601 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x603 uint64
+       var x604 uint64
+       x604, x603 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x605 uint64
+       var x606 uint64
+       x606, x605 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x607 uint64
+       var x608 uint64
+       x608, x607 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x609 uint64
+       var x610 uint64
+       x610, x609 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x611 uint64
+       var x612 uint64
+       x612, x611 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x613 uint64
+       var x614 uint64
+       x614, x613 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x615 uint64
+       var x616 uint64
+       x616, x615 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x617 uint64
+       var x618 uint64
+       x617, x618 = bits.Add64(x616, x613, uint64(0x0))
+       var x619 uint64
+       var x620 uint64
+       x619, x620 = bits.Add64(x614, x611, uint64(p521Uint1(x618)))
+       var x621 uint64
+       var x622 uint64
+       x621, x622 = bits.Add64(x612, x609, uint64(p521Uint1(x620)))
+       var x623 uint64
+       var x624 uint64
+       x623, x624 = bits.Add64(x610, x607, uint64(p521Uint1(x622)))
+       var x625 uint64
+       var x626 uint64
+       x625, x626 = bits.Add64(x608, x605, uint64(p521Uint1(x624)))
+       var x627 uint64
+       var x628 uint64
+       x627, x628 = bits.Add64(x606, x603, uint64(p521Uint1(x626)))
+       var x629 uint64
+       var x630 uint64
+       x629, x630 = bits.Add64(x604, x601, uint64(p521Uint1(x628)))
+       var x631 uint64
+       var x632 uint64
+       x631, x632 = bits.Add64(x602, x599, uint64(p521Uint1(x630)))
+       x633 := (uint64(p521Uint1(x632)) + x600)
+       var x635 uint64
+       _, x635 = bits.Add64(x579, x615, uint64(0x0))
+       var x636 uint64
+       var x637 uint64
+       x636, x637 = bits.Add64(x581, x617, uint64(p521Uint1(x635)))
+       var x638 uint64
+       var x639 uint64
+       x638, x639 = bits.Add64(x583, x619, uint64(p521Uint1(x637)))
+       var x640 uint64
+       var x641 uint64
+       x640, x641 = bits.Add64(x585, x621, uint64(p521Uint1(x639)))
+       var x642 uint64
+       var x643 uint64
+       x642, x643 = bits.Add64(x587, x623, uint64(p521Uint1(x641)))
+       var x644 uint64
+       var x645 uint64
+       x644, x645 = bits.Add64(x589, x625, uint64(p521Uint1(x643)))
+       var x646 uint64
+       var x647 uint64
+       x646, x647 = bits.Add64(x591, x627, uint64(p521Uint1(x645)))
+       var x648 uint64
+       var x649 uint64
+       x648, x649 = bits.Add64(x593, x629, uint64(p521Uint1(x647)))
+       var x650 uint64
+       var x651 uint64
+       x650, x651 = bits.Add64(x595, x631, uint64(p521Uint1(x649)))
+       var x652 uint64
+       var x653 uint64
+       x652, x653 = bits.Add64(x597, x633, uint64(p521Uint1(x651)))
+       x654 := (uint64(p521Uint1(x653)) + uint64(p521Uint1(x598)))
+       var x655 uint64
+       var x656 uint64
+       x656, x655 = bits.Mul64(x6, arg2[8])
+       var x657 uint64
+       var x658 uint64
+       x658, x657 = bits.Mul64(x6, arg2[7])
+       var x659 uint64
+       var x660 uint64
+       x660, x659 = bits.Mul64(x6, arg2[6])
+       var x661 uint64
+       var x662 uint64
+       x662, x661 = bits.Mul64(x6, arg2[5])
+       var x663 uint64
+       var x664 uint64
+       x664, x663 = bits.Mul64(x6, arg2[4])
+       var x665 uint64
+       var x666 uint64
+       x666, x665 = bits.Mul64(x6, arg2[3])
+       var x667 uint64
+       var x668 uint64
+       x668, x667 = bits.Mul64(x6, arg2[2])
+       var x669 uint64
+       var x670 uint64
+       x670, x669 = bits.Mul64(x6, arg2[1])
+       var x671 uint64
+       var x672 uint64
+       x672, x671 = bits.Mul64(x6, arg2[0])
+       var x673 uint64
+       var x674 uint64
+       x673, x674 = bits.Add64(x672, x669, uint64(0x0))
+       var x675 uint64
+       var x676 uint64
+       x675, x676 = bits.Add64(x670, x667, uint64(p521Uint1(x674)))
+       var x677 uint64
+       var x678 uint64
+       x677, x678 = bits.Add64(x668, x665, uint64(p521Uint1(x676)))
+       var x679 uint64
+       var x680 uint64
+       x679, x680 = bits.Add64(x666, x663, uint64(p521Uint1(x678)))
+       var x681 uint64
+       var x682 uint64
+       x681, x682 = bits.Add64(x664, x661, uint64(p521Uint1(x680)))
+       var x683 uint64
+       var x684 uint64
+       x683, x684 = bits.Add64(x662, x659, uint64(p521Uint1(x682)))
+       var x685 uint64
+       var x686 uint64
+       x685, x686 = bits.Add64(x660, x657, uint64(p521Uint1(x684)))
+       var x687 uint64
+       var x688 uint64
+       x687, x688 = bits.Add64(x658, x655, uint64(p521Uint1(x686)))
+       x689 := (uint64(p521Uint1(x688)) + x656)
+       var x690 uint64
+       var x691 uint64
+       x690, x691 = bits.Add64(x636, x671, uint64(0x0))
+       var x692 uint64
+       var x693 uint64
+       x692, x693 = bits.Add64(x638, x673, uint64(p521Uint1(x691)))
+       var x694 uint64
+       var x695 uint64
+       x694, x695 = bits.Add64(x640, x675, uint64(p521Uint1(x693)))
+       var x696 uint64
+       var x697 uint64
+       x696, x697 = bits.Add64(x642, x677, uint64(p521Uint1(x695)))
+       var x698 uint64
+       var x699 uint64
+       x698, x699 = bits.Add64(x644, x679, uint64(p521Uint1(x697)))
+       var x700 uint64
+       var x701 uint64
+       x700, x701 = bits.Add64(x646, x681, uint64(p521Uint1(x699)))
+       var x702 uint64
+       var x703 uint64
+       x702, x703 = bits.Add64(x648, x683, uint64(p521Uint1(x701)))
+       var x704 uint64
+       var x705 uint64
+       x704, x705 = bits.Add64(x650, x685, uint64(p521Uint1(x703)))
+       var x706 uint64
+       var x707 uint64
+       x706, x707 = bits.Add64(x652, x687, uint64(p521Uint1(x705)))
+       var x708 uint64
+       var x709 uint64
+       x708, x709 = bits.Add64(x654, x689, uint64(p521Uint1(x707)))
+       var x710 uint64
+       var x711 uint64
+       x711, x710 = bits.Mul64(x690, 0x1ff)
+       var x712 uint64
+       var x713 uint64
+       x713, x712 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x714 uint64
+       var x715 uint64
+       x715, x714 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x716 uint64
+       var x717 uint64
+       x717, x716 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x718 uint64
+       var x719 uint64
+       x719, x718 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x720 uint64
+       var x721 uint64
+       x721, x720 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x722 uint64
+       var x723 uint64
+       x723, x722 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x724 uint64
+       var x725 uint64
+       x725, x724 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x726 uint64
+       var x727 uint64
+       x727, x726 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x728 uint64
+       var x729 uint64
+       x728, x729 = bits.Add64(x727, x724, uint64(0x0))
+       var x730 uint64
+       var x731 uint64
+       x730, x731 = bits.Add64(x725, x722, uint64(p521Uint1(x729)))
+       var x732 uint64
+       var x733 uint64
+       x732, x733 = bits.Add64(x723, x720, uint64(p521Uint1(x731)))
+       var x734 uint64
+       var x735 uint64
+       x734, x735 = bits.Add64(x721, x718, uint64(p521Uint1(x733)))
+       var x736 uint64
+       var x737 uint64
+       x736, x737 = bits.Add64(x719, x716, uint64(p521Uint1(x735)))
+       var x738 uint64
+       var x739 uint64
+       x738, x739 = bits.Add64(x717, x714, uint64(p521Uint1(x737)))
+       var x740 uint64
+       var x741 uint64
+       x740, x741 = bits.Add64(x715, x712, uint64(p521Uint1(x739)))
+       var x742 uint64
+       var x743 uint64
+       x742, x743 = bits.Add64(x713, x710, uint64(p521Uint1(x741)))
+       x744 := (uint64(p521Uint1(x743)) + x711)
+       var x746 uint64
+       _, x746 = bits.Add64(x690, x726, uint64(0x0))
+       var x747 uint64
+       var x748 uint64
+       x747, x748 = bits.Add64(x692, x728, uint64(p521Uint1(x746)))
+       var x749 uint64
+       var x750 uint64
+       x749, x750 = bits.Add64(x694, x730, uint64(p521Uint1(x748)))
+       var x751 uint64
+       var x752 uint64
+       x751, x752 = bits.Add64(x696, x732, uint64(p521Uint1(x750)))
+       var x753 uint64
+       var x754 uint64
+       x753, x754 = bits.Add64(x698, x734, uint64(p521Uint1(x752)))
+       var x755 uint64
+       var x756 uint64
+       x755, x756 = bits.Add64(x700, x736, uint64(p521Uint1(x754)))
+       var x757 uint64
+       var x758 uint64
+       x757, x758 = bits.Add64(x702, x738, uint64(p521Uint1(x756)))
+       var x759 uint64
+       var x760 uint64
+       x759, x760 = bits.Add64(x704, x740, uint64(p521Uint1(x758)))
+       var x761 uint64
+       var x762 uint64
+       x761, x762 = bits.Add64(x706, x742, uint64(p521Uint1(x760)))
+       var x763 uint64
+       var x764 uint64
+       x763, x764 = bits.Add64(x708, x744, uint64(p521Uint1(x762)))
+       x765 := (uint64(p521Uint1(x764)) + uint64(p521Uint1(x709)))
+       var x766 uint64
+       var x767 uint64
+       x767, x766 = bits.Mul64(x7, arg2[8])
+       var x768 uint64
+       var x769 uint64
+       x769, x768 = bits.Mul64(x7, arg2[7])
+       var x770 uint64
+       var x771 uint64
+       x771, x770 = bits.Mul64(x7, arg2[6])
+       var x772 uint64
+       var x773 uint64
+       x773, x772 = bits.Mul64(x7, arg2[5])
+       var x774 uint64
+       var x775 uint64
+       x775, x774 = bits.Mul64(x7, arg2[4])
+       var x776 uint64
+       var x777 uint64
+       x777, x776 = bits.Mul64(x7, arg2[3])
+       var x778 uint64
+       var x779 uint64
+       x779, x778 = bits.Mul64(x7, arg2[2])
+       var x780 uint64
+       var x781 uint64
+       x781, x780 = bits.Mul64(x7, arg2[1])
+       var x782 uint64
+       var x783 uint64
+       x783, x782 = bits.Mul64(x7, arg2[0])
+       var x784 uint64
+       var x785 uint64
+       x784, x785 = bits.Add64(x783, x780, uint64(0x0))
+       var x786 uint64
+       var x787 uint64
+       x786, x787 = bits.Add64(x781, x778, uint64(p521Uint1(x785)))
+       var x788 uint64
+       var x789 uint64
+       x788, x789 = bits.Add64(x779, x776, uint64(p521Uint1(x787)))
+       var x790 uint64
+       var x791 uint64
+       x790, x791 = bits.Add64(x777, x774, uint64(p521Uint1(x789)))
+       var x792 uint64
+       var x793 uint64
+       x792, x793 = bits.Add64(x775, x772, uint64(p521Uint1(x791)))
+       var x794 uint64
+       var x795 uint64
+       x794, x795 = bits.Add64(x773, x770, uint64(p521Uint1(x793)))
+       var x796 uint64
+       var x797 uint64
+       x796, x797 = bits.Add64(x771, x768, uint64(p521Uint1(x795)))
+       var x798 uint64
+       var x799 uint64
+       x798, x799 = bits.Add64(x769, x766, uint64(p521Uint1(x797)))
+       x800 := (uint64(p521Uint1(x799)) + x767)
+       var x801 uint64
+       var x802 uint64
+       x801, x802 = bits.Add64(x747, x782, uint64(0x0))
+       var x803 uint64
+       var x804 uint64
+       x803, x804 = bits.Add64(x749, x784, uint64(p521Uint1(x802)))
+       var x805 uint64
+       var x806 uint64
+       x805, x806 = bits.Add64(x751, x786, uint64(p521Uint1(x804)))
+       var x807 uint64
+       var x808 uint64
+       x807, x808 = bits.Add64(x753, x788, uint64(p521Uint1(x806)))
+       var x809 uint64
+       var x810 uint64
+       x809, x810 = bits.Add64(x755, x790, uint64(p521Uint1(x808)))
+       var x811 uint64
+       var x812 uint64
+       x811, x812 = bits.Add64(x757, x792, uint64(p521Uint1(x810)))
+       var x813 uint64
+       var x814 uint64
+       x813, x814 = bits.Add64(x759, x794, uint64(p521Uint1(x812)))
+       var x815 uint64
+       var x816 uint64
+       x815, x816 = bits.Add64(x761, x796, uint64(p521Uint1(x814)))
+       var x817 uint64
+       var x818 uint64
+       x817, x818 = bits.Add64(x763, x798, uint64(p521Uint1(x816)))
+       var x819 uint64
+       var x820 uint64
+       x819, x820 = bits.Add64(x765, x800, uint64(p521Uint1(x818)))
+       var x821 uint64
+       var x822 uint64
+       x822, x821 = bits.Mul64(x801, 0x1ff)
+       var x823 uint64
+       var x824 uint64
+       x824, x823 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x825 uint64
+       var x826 uint64
+       x826, x825 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x827 uint64
+       var x828 uint64
+       x828, x827 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x829 uint64
+       var x830 uint64
+       x830, x829 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x831 uint64
+       var x832 uint64
+       x832, x831 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x833 uint64
+       var x834 uint64
+       x834, x833 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x835 uint64
+       var x836 uint64
+       x836, x835 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x837 uint64
+       var x838 uint64
+       x838, x837 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x839 uint64
+       var x840 uint64
+       x839, x840 = bits.Add64(x838, x835, uint64(0x0))
+       var x841 uint64
+       var x842 uint64
+       x841, x842 = bits.Add64(x836, x833, uint64(p521Uint1(x840)))
+       var x843 uint64
+       var x844 uint64
+       x843, x844 = bits.Add64(x834, x831, uint64(p521Uint1(x842)))
+       var x845 uint64
+       var x846 uint64
+       x845, x846 = bits.Add64(x832, x829, uint64(p521Uint1(x844)))
+       var x847 uint64
+       var x848 uint64
+       x847, x848 = bits.Add64(x830, x827, uint64(p521Uint1(x846)))
+       var x849 uint64
+       var x850 uint64
+       x849, x850 = bits.Add64(x828, x825, uint64(p521Uint1(x848)))
+       var x851 uint64
+       var x852 uint64
+       x851, x852 = bits.Add64(x826, x823, uint64(p521Uint1(x850)))
+       var x853 uint64
+       var x854 uint64
+       x853, x854 = bits.Add64(x824, x821, uint64(p521Uint1(x852)))
+       x855 := (uint64(p521Uint1(x854)) + x822)
+       var x857 uint64
+       _, x857 = bits.Add64(x801, x837, uint64(0x0))
+       var x858 uint64
+       var x859 uint64
+       x858, x859 = bits.Add64(x803, x839, uint64(p521Uint1(x857)))
+       var x860 uint64
+       var x861 uint64
+       x860, x861 = bits.Add64(x805, x841, uint64(p521Uint1(x859)))
+       var x862 uint64
+       var x863 uint64
+       x862, x863 = bits.Add64(x807, x843, uint64(p521Uint1(x861)))
+       var x864 uint64
+       var x865 uint64
+       x864, x865 = bits.Add64(x809, x845, uint64(p521Uint1(x863)))
+       var x866 uint64
+       var x867 uint64
+       x866, x867 = bits.Add64(x811, x847, uint64(p521Uint1(x865)))
+       var x868 uint64
+       var x869 uint64
+       x868, x869 = bits.Add64(x813, x849, uint64(p521Uint1(x867)))
+       var x870 uint64
+       var x871 uint64
+       x870, x871 = bits.Add64(x815, x851, uint64(p521Uint1(x869)))
+       var x872 uint64
+       var x873 uint64
+       x872, x873 = bits.Add64(x817, x853, uint64(p521Uint1(x871)))
+       var x874 uint64
+       var x875 uint64
+       x874, x875 = bits.Add64(x819, x855, uint64(p521Uint1(x873)))
+       x876 := (uint64(p521Uint1(x875)) + uint64(p521Uint1(x820)))
+       var x877 uint64
+       var x878 uint64
+       x878, x877 = bits.Mul64(x8, arg2[8])
+       var x879 uint64
+       var x880 uint64
+       x880, x879 = bits.Mul64(x8, arg2[7])
+       var x881 uint64
+       var x882 uint64
+       x882, x881 = bits.Mul64(x8, arg2[6])
+       var x883 uint64
+       var x884 uint64
+       x884, x883 = bits.Mul64(x8, arg2[5])
+       var x885 uint64
+       var x886 uint64
+       x886, x885 = bits.Mul64(x8, arg2[4])
+       var x887 uint64
+       var x888 uint64
+       x888, x887 = bits.Mul64(x8, arg2[3])
+       var x889 uint64
+       var x890 uint64
+       x890, x889 = bits.Mul64(x8, arg2[2])
+       var x891 uint64
+       var x892 uint64
+       x892, x891 = bits.Mul64(x8, arg2[1])
+       var x893 uint64
+       var x894 uint64
+       x894, x893 = bits.Mul64(x8, arg2[0])
+       var x895 uint64
+       var x896 uint64
+       x895, x896 = bits.Add64(x894, x891, uint64(0x0))
+       var x897 uint64
+       var x898 uint64
+       x897, x898 = bits.Add64(x892, x889, uint64(p521Uint1(x896)))
+       var x899 uint64
+       var x900 uint64
+       x899, x900 = bits.Add64(x890, x887, uint64(p521Uint1(x898)))
+       var x901 uint64
+       var x902 uint64
+       x901, x902 = bits.Add64(x888, x885, uint64(p521Uint1(x900)))
+       var x903 uint64
+       var x904 uint64
+       x903, x904 = bits.Add64(x886, x883, uint64(p521Uint1(x902)))
+       var x905 uint64
+       var x906 uint64
+       x905, x906 = bits.Add64(x884, x881, uint64(p521Uint1(x904)))
+       var x907 uint64
+       var x908 uint64
+       x907, x908 = bits.Add64(x882, x879, uint64(p521Uint1(x906)))
+       var x909 uint64
+       var x910 uint64
+       x909, x910 = bits.Add64(x880, x877, uint64(p521Uint1(x908)))
+       x911 := (uint64(p521Uint1(x910)) + x878)
+       var x912 uint64
+       var x913 uint64
+       x912, x913 = bits.Add64(x858, x893, uint64(0x0))
+       var x914 uint64
+       var x915 uint64
+       x914, x915 = bits.Add64(x860, x895, uint64(p521Uint1(x913)))
+       var x916 uint64
+       var x917 uint64
+       x916, x917 = bits.Add64(x862, x897, uint64(p521Uint1(x915)))
+       var x918 uint64
+       var x919 uint64
+       x918, x919 = bits.Add64(x864, x899, uint64(p521Uint1(x917)))
+       var x920 uint64
+       var x921 uint64
+       x920, x921 = bits.Add64(x866, x901, uint64(p521Uint1(x919)))
+       var x922 uint64
+       var x923 uint64
+       x922, x923 = bits.Add64(x868, x903, uint64(p521Uint1(x921)))
+       var x924 uint64
+       var x925 uint64
+       x924, x925 = bits.Add64(x870, x905, uint64(p521Uint1(x923)))
+       var x926 uint64
+       var x927 uint64
+       x926, x927 = bits.Add64(x872, x907, uint64(p521Uint1(x925)))
+       var x928 uint64
+       var x929 uint64
+       x928, x929 = bits.Add64(x874, x909, uint64(p521Uint1(x927)))
+       var x930 uint64
+       var x931 uint64
+       x930, x931 = bits.Add64(x876, x911, uint64(p521Uint1(x929)))
+       var x932 uint64
+       var x933 uint64
+       x933, x932 = bits.Mul64(x912, 0x1ff)
+       var x934 uint64
+       var x935 uint64
+       x935, x934 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x936 uint64
+       var x937 uint64
+       x937, x936 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x938 uint64
+       var x939 uint64
+       x939, x938 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x940 uint64
+       var x941 uint64
+       x941, x940 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x942 uint64
+       var x943 uint64
+       x943, x942 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x944 uint64
+       var x945 uint64
+       x945, x944 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x946 uint64
+       var x947 uint64
+       x947, x946 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x948 uint64
+       var x949 uint64
+       x949, x948 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x950 uint64
+       var x951 uint64
+       x950, x951 = bits.Add64(x949, x946, uint64(0x0))
+       var x952 uint64
+       var x953 uint64
+       x952, x953 = bits.Add64(x947, x944, uint64(p521Uint1(x951)))
+       var x954 uint64
+       var x955 uint64
+       x954, x955 = bits.Add64(x945, x942, uint64(p521Uint1(x953)))
+       var x956 uint64
+       var x957 uint64
+       x956, x957 = bits.Add64(x943, x940, uint64(p521Uint1(x955)))
+       var x958 uint64
+       var x959 uint64
+       x958, x959 = bits.Add64(x941, x938, uint64(p521Uint1(x957)))
+       var x960 uint64
+       var x961 uint64
+       x960, x961 = bits.Add64(x939, x936, uint64(p521Uint1(x959)))
+       var x962 uint64
+       var x963 uint64
+       x962, x963 = bits.Add64(x937, x934, uint64(p521Uint1(x961)))
+       var x964 uint64
+       var x965 uint64
+       x964, x965 = bits.Add64(x935, x932, uint64(p521Uint1(x963)))
+       x966 := (uint64(p521Uint1(x965)) + x933)
+       var x968 uint64
+       _, x968 = bits.Add64(x912, x948, uint64(0x0))
+       var x969 uint64
+       var x970 uint64
+       x969, x970 = bits.Add64(x914, x950, uint64(p521Uint1(x968)))
+       var x971 uint64
+       var x972 uint64
+       x971, x972 = bits.Add64(x916, x952, uint64(p521Uint1(x970)))
+       var x973 uint64
+       var x974 uint64
+       x973, x974 = bits.Add64(x918, x954, uint64(p521Uint1(x972)))
+       var x975 uint64
+       var x976 uint64
+       x975, x976 = bits.Add64(x920, x956, uint64(p521Uint1(x974)))
+       var x977 uint64
+       var x978 uint64
+       x977, x978 = bits.Add64(x922, x958, uint64(p521Uint1(x976)))
+       var x979 uint64
+       var x980 uint64
+       x979, x980 = bits.Add64(x924, x960, uint64(p521Uint1(x978)))
+       var x981 uint64
+       var x982 uint64
+       x981, x982 = bits.Add64(x926, x962, uint64(p521Uint1(x980)))
+       var x983 uint64
+       var x984 uint64
+       x983, x984 = bits.Add64(x928, x964, uint64(p521Uint1(x982)))
+       var x985 uint64
+       var x986 uint64
+       x985, x986 = bits.Add64(x930, x966, uint64(p521Uint1(x984)))
+       x987 := (uint64(p521Uint1(x986)) + uint64(p521Uint1(x931)))
+       var x988 uint64
+       var x989 uint64
+       x988, x989 = bits.Sub64(x969, 0xffffffffffffffff, uint64(0x0))
+       var x990 uint64
+       var x991 uint64
+       x990, x991 = bits.Sub64(x971, 0xffffffffffffffff, uint64(p521Uint1(x989)))
+       var x992 uint64
+       var x993 uint64
+       x992, x993 = bits.Sub64(x973, 0xffffffffffffffff, uint64(p521Uint1(x991)))
+       var x994 uint64
+       var x995 uint64
+       x994, x995 = bits.Sub64(x975, 0xffffffffffffffff, uint64(p521Uint1(x993)))
+       var x996 uint64
+       var x997 uint64
+       x996, x997 = bits.Sub64(x977, 0xffffffffffffffff, uint64(p521Uint1(x995)))
+       var x998 uint64
+       var x999 uint64
+       x998, x999 = bits.Sub64(x979, 0xffffffffffffffff, uint64(p521Uint1(x997)))
+       var x1000 uint64
+       var x1001 uint64
+       x1000, x1001 = bits.Sub64(x981, 0xffffffffffffffff, uint64(p521Uint1(x999)))
+       var x1002 uint64
+       var x1003 uint64
+       x1002, x1003 = bits.Sub64(x983, 0xffffffffffffffff, uint64(p521Uint1(x1001)))
+       var x1004 uint64
+       var x1005 uint64
+       x1004, x1005 = bits.Sub64(x985, 0x1ff, uint64(p521Uint1(x1003)))
+       var x1007 uint64
+       _, x1007 = bits.Sub64(x987, uint64(0x0), uint64(p521Uint1(x1005)))
+       var x1008 uint64
+       p521CmovznzU64(&x1008, p521Uint1(x1007), x988, x969)
+       var x1009 uint64
+       p521CmovznzU64(&x1009, p521Uint1(x1007), x990, x971)
+       var x1010 uint64
+       p521CmovznzU64(&x1010, p521Uint1(x1007), x992, x973)
+       var x1011 uint64
+       p521CmovznzU64(&x1011, p521Uint1(x1007), x994, x975)
+       var x1012 uint64
+       p521CmovznzU64(&x1012, p521Uint1(x1007), x996, x977)
+       var x1013 uint64
+       p521CmovznzU64(&x1013, p521Uint1(x1007), x998, x979)
+       var x1014 uint64
+       p521CmovznzU64(&x1014, p521Uint1(x1007), x1000, x981)
+       var x1015 uint64
+       p521CmovznzU64(&x1015, p521Uint1(x1007), x1002, x983)
+       var x1016 uint64
+       p521CmovznzU64(&x1016, p521Uint1(x1007), x1004, x985)
+       out1[0] = x1008
+       out1[1] = x1009
+       out1[2] = x1010
+       out1[3] = x1011
+       out1[4] = x1012
+       out1[5] = x1013
+       out1[6] = x1014
+       out1[7] = x1015
+       out1[8] = x1016
 }
 
-// p521CarrySquare squares a field element and reduces the result.
+// p521Square squares a field element in the Montgomery domain.
 //
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
 // Postconditions:
-//   eval out1 mod m = (eval arg1 * eval arg1) mod m
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m
+//   0 โ‰ค eval out1 < m
 //
-// Input Bounds:
-//   arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-// Output Bounds:
-//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-func p521CarrySquare(out1 *[9]uint64, arg1 *[9]uint64) {
-       x1 := arg1[8]
-       x2 := (x1 * 0x2)
-       x3 := (arg1[8] * 0x2)
-       x4 := arg1[7]
-       x5 := (x4 * 0x2)
-       x6 := (arg1[7] * 0x2)
-       x7 := arg1[6]
-       x8 := (x7 * 0x2)
-       x9 := (arg1[6] * 0x2)
-       x10 := arg1[5]
-       x11 := (x10 * 0x2)
-       x12 := (arg1[5] * 0x2)
-       x13 := (arg1[4] * 0x2)
-       x14 := (arg1[3] * 0x2)
-       x15 := (arg1[2] * 0x2)
-       x16 := (arg1[1] * 0x2)
+func p521Square(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement) {
+       x1 := arg1[1]
+       x2 := arg1[2]
+       x3 := arg1[3]
+       x4 := arg1[4]
+       x5 := arg1[5]
+       x6 := arg1[6]
+       x7 := arg1[7]
+       x8 := arg1[8]
+       x9 := arg1[0]
+       var x10 uint64
+       var x11 uint64
+       x11, x10 = bits.Mul64(x9, arg1[8])
+       var x12 uint64
+       var x13 uint64
+       x13, x12 = bits.Mul64(x9, arg1[7])
+       var x14 uint64
+       var x15 uint64
+       x15, x14 = bits.Mul64(x9, arg1[6])
+       var x16 uint64
        var x17 uint64
+       x17, x16 = bits.Mul64(x9, arg1[5])
        var x18 uint64
-       x18, x17 = bits.Mul64(arg1[8], (x1 * 0x2))
        var x19 uint64
+       x19, x18 = bits.Mul64(x9, arg1[4])
        var x20 uint64
-       x20, x19 = bits.Mul64(arg1[7], (x2 * 0x2))
        var x21 uint64
+       x21, x20 = bits.Mul64(x9, arg1[3])
        var x22 uint64
-       x22, x21 = bits.Mul64(arg1[7], (x4 * 0x2))
        var x23 uint64
+       x23, x22 = bits.Mul64(x9, arg1[2])
        var x24 uint64
-       x24, x23 = bits.Mul64(arg1[6], (x2 * 0x2))
        var x25 uint64
+       x25, x24 = bits.Mul64(x9, arg1[1])
        var x26 uint64
-       x26, x25 = bits.Mul64(arg1[6], (x5 * 0x2))
        var x27 uint64
+       x27, x26 = bits.Mul64(x9, arg1[0])
        var x28 uint64
-       x28, x27 = bits.Mul64(arg1[6], (x7 * 0x2))
        var x29 uint64
+       x28, x29 = bits.Add64(x27, x24, uint64(0x0))
        var x30 uint64
-       x30, x29 = bits.Mul64(arg1[5], (x2 * 0x2))
        var x31 uint64
+       x30, x31 = bits.Add64(x25, x22, uint64(p521Uint1(x29)))
        var x32 uint64
-       x32, x31 = bits.Mul64(arg1[5], (x5 * 0x2))
        var x33 uint64
+       x32, x33 = bits.Add64(x23, x20, uint64(p521Uint1(x31)))
        var x34 uint64
-       x34, x33 = bits.Mul64(arg1[5], (x8 * 0x2))
        var x35 uint64
+       x34, x35 = bits.Add64(x21, x18, uint64(p521Uint1(x33)))
        var x36 uint64
-       x36, x35 = bits.Mul64(arg1[5], (x10 * 0x2))
        var x37 uint64
+       x36, x37 = bits.Add64(x19, x16, uint64(p521Uint1(x35)))
        var x38 uint64
-       x38, x37 = bits.Mul64(arg1[4], (x2 * 0x2))
        var x39 uint64
+       x38, x39 = bits.Add64(x17, x14, uint64(p521Uint1(x37)))
        var x40 uint64
-       x40, x39 = bits.Mul64(arg1[4], (x5 * 0x2))
        var x41 uint64
+       x40, x41 = bits.Add64(x15, x12, uint64(p521Uint1(x39)))
        var x42 uint64
-       x42, x41 = bits.Mul64(arg1[4], (x8 * 0x2))
        var x43 uint64
-       var x44 uint64
-       x44, x43 = bits.Mul64(arg1[4], (x11 * 0x2))
+       x42, x43 = bits.Add64(x13, x10, uint64(p521Uint1(x41)))
+       x44 := (uint64(p521Uint1(x43)) + x11)
        var x45 uint64
        var x46 uint64
-       x46, x45 = bits.Mul64(arg1[4], arg1[4])
+       x46, x45 = bits.Mul64(x26, 0x1ff)
        var x47 uint64
        var x48 uint64
-       x48, x47 = bits.Mul64(arg1[3], (x2 * 0x2))
+       x48, x47 = bits.Mul64(x26, 0xffffffffffffffff)
        var x49 uint64
        var x50 uint64
-       x50, x49 = bits.Mul64(arg1[3], (x5 * 0x2))
+       x50, x49 = bits.Mul64(x26, 0xffffffffffffffff)
        var x51 uint64
        var x52 uint64
-       x52, x51 = bits.Mul64(arg1[3], (x8 * 0x2))
+       x52, x51 = bits.Mul64(x26, 0xffffffffffffffff)
        var x53 uint64
        var x54 uint64
-       x54, x53 = bits.Mul64(arg1[3], x12)
+       x54, x53 = bits.Mul64(x26, 0xffffffffffffffff)
        var x55 uint64
        var x56 uint64
-       x56, x55 = bits.Mul64(arg1[3], x13)
+       x56, x55 = bits.Mul64(x26, 0xffffffffffffffff)
        var x57 uint64
        var x58 uint64
-       x58, x57 = bits.Mul64(arg1[3], arg1[3])
+       x58, x57 = bits.Mul64(x26, 0xffffffffffffffff)
        var x59 uint64
        var x60 uint64
-       x60, x59 = bits.Mul64(arg1[2], (x2 * 0x2))
+       x60, x59 = bits.Mul64(x26, 0xffffffffffffffff)
        var x61 uint64
        var x62 uint64
-       x62, x61 = bits.Mul64(arg1[2], (x5 * 0x2))
+       x62, x61 = bits.Mul64(x26, 0xffffffffffffffff)
        var x63 uint64
        var x64 uint64
-       x64, x63 = bits.Mul64(arg1[2], x9)
+       x63, x64 = bits.Add64(x62, x59, uint64(0x0))
        var x65 uint64
        var x66 uint64
-       x66, x65 = bits.Mul64(arg1[2], x12)
+       x65, x66 = bits.Add64(x60, x57, uint64(p521Uint1(x64)))
        var x67 uint64
        var x68 uint64
-       x68, x67 = bits.Mul64(arg1[2], x13)
+       x67, x68 = bits.Add64(x58, x55, uint64(p521Uint1(x66)))
        var x69 uint64
        var x70 uint64
-       x70, x69 = bits.Mul64(arg1[2], x14)
+       x69, x70 = bits.Add64(x56, x53, uint64(p521Uint1(x68)))
        var x71 uint64
        var x72 uint64
-       x72, x71 = bits.Mul64(arg1[2], arg1[2])
+       x71, x72 = bits.Add64(x54, x51, uint64(p521Uint1(x70)))
        var x73 uint64
        var x74 uint64
-       x74, x73 = bits.Mul64(arg1[1], (x2 * 0x2))
+       x73, x74 = bits.Add64(x52, x49, uint64(p521Uint1(x72)))
        var x75 uint64
        var x76 uint64
-       x76, x75 = bits.Mul64(arg1[1], x6)
+       x75, x76 = bits.Add64(x50, x47, uint64(p521Uint1(x74)))
        var x77 uint64
        var x78 uint64
-       x78, x77 = bits.Mul64(arg1[1], x9)
-       var x79 uint64
-       var x80 uint64
-       x80, x79 = bits.Mul64(arg1[1], x12)
+       x77, x78 = bits.Add64(x48, x45, uint64(p521Uint1(x76)))
+       x79 := (uint64(p521Uint1(x78)) + x46)
        var x81 uint64
+       _, x81 = bits.Add64(x26, x61, uint64(0x0))
        var x82 uint64
-       x82, x81 = bits.Mul64(arg1[1], x13)
        var x83 uint64
+       x82, x83 = bits.Add64(x28, x63, uint64(p521Uint1(x81)))
        var x84 uint64
-       x84, x83 = bits.Mul64(arg1[1], x14)
        var x85 uint64
+       x84, x85 = bits.Add64(x30, x65, uint64(p521Uint1(x83)))
        var x86 uint64
-       x86, x85 = bits.Mul64(arg1[1], x15)
        var x87 uint64
+       x86, x87 = bits.Add64(x32, x67, uint64(p521Uint1(x85)))
        var x88 uint64
-       x88, x87 = bits.Mul64(arg1[1], arg1[1])
        var x89 uint64
+       x88, x89 = bits.Add64(x34, x69, uint64(p521Uint1(x87)))
        var x90 uint64
-       x90, x89 = bits.Mul64(arg1[0], x3)
        var x91 uint64
+       x90, x91 = bits.Add64(x36, x71, uint64(p521Uint1(x89)))
        var x92 uint64
-       x92, x91 = bits.Mul64(arg1[0], x6)
        var x93 uint64
+       x92, x93 = bits.Add64(x38, x73, uint64(p521Uint1(x91)))
        var x94 uint64
-       x94, x93 = bits.Mul64(arg1[0], x9)
        var x95 uint64
+       x94, x95 = bits.Add64(x40, x75, uint64(p521Uint1(x93)))
        var x96 uint64
-       x96, x95 = bits.Mul64(arg1[0], x12)
        var x97 uint64
+       x96, x97 = bits.Add64(x42, x77, uint64(p521Uint1(x95)))
        var x98 uint64
-       x98, x97 = bits.Mul64(arg1[0], x13)
        var x99 uint64
+       x98, x99 = bits.Add64(x44, x79, uint64(p521Uint1(x97)))
        var x100 uint64
-       x100, x99 = bits.Mul64(arg1[0], x14)
        var x101 uint64
+       x101, x100 = bits.Mul64(x1, arg1[8])
        var x102 uint64
-       x102, x101 = bits.Mul64(arg1[0], x15)
        var x103 uint64
+       x103, x102 = bits.Mul64(x1, arg1[7])
        var x104 uint64
-       x104, x103 = bits.Mul64(arg1[0], x16)
        var x105 uint64
+       x105, x104 = bits.Mul64(x1, arg1[6])
        var x106 uint64
-       x106, x105 = bits.Mul64(arg1[0], arg1[0])
        var x107 uint64
-       var x108 p521Uint1
-       x107, x108 = p521AddcarryxU64(x51, x43, 0x0)
+       x107, x106 = bits.Mul64(x1, arg1[5])
+       var x108 uint64
        var x109 uint64
-       x109, _ = p521AddcarryxU64(x52, x44, x108)
+       x109, x108 = bits.Mul64(x1, arg1[4])
+       var x110 uint64
        var x111 uint64
-       var x112 p521Uint1
-       x111, x112 = p521AddcarryxU64(x61, x107, 0x0)
+       x111, x110 = bits.Mul64(x1, arg1[3])
+       var x112 uint64
        var x113 uint64
-       x113, _ = p521AddcarryxU64(x62, x109, x112)
+       x113, x112 = bits.Mul64(x1, arg1[2])
+       var x114 uint64
        var x115 uint64
-       var x116 p521Uint1
-       x115, x116 = p521AddcarryxU64(x73, x111, 0x0)
+       x115, x114 = bits.Mul64(x1, arg1[1])
+       var x116 uint64
        var x117 uint64
-       x117, _ = p521AddcarryxU64(x74, x113, x116)
+       x117, x116 = bits.Mul64(x1, arg1[0])
+       var x118 uint64
        var x119 uint64
-       var x120 p521Uint1
-       x119, x120 = p521AddcarryxU64(x105, x115, 0x0)
+       x118, x119 = bits.Add64(x117, x114, uint64(0x0))
+       var x120 uint64
        var x121 uint64
-       x121, _ = p521AddcarryxU64(x106, x117, x120)
-       x123 := ((x119 >> 58) | ((x121 << 6) & 0xffffffffffffffff))
-       x124 := (x121 >> 58)
-       x125 := (x119 & 0x3ffffffffffffff)
+       x120, x121 = bits.Add64(x115, x112, uint64(p521Uint1(x119)))
+       var x122 uint64
+       var x123 uint64
+       x122, x123 = bits.Add64(x113, x110, uint64(p521Uint1(x121)))
+       var x124 uint64
+       var x125 uint64
+       x124, x125 = bits.Add64(x111, x108, uint64(p521Uint1(x123)))
        var x126 uint64
-       var x127 p521Uint1
-       x126, x127 = p521AddcarryxU64(x53, x45, 0x0)
+       var x127 uint64
+       x126, x127 = bits.Add64(x109, x106, uint64(p521Uint1(x125)))
        var x128 uint64
-       x128, _ = p521AddcarryxU64(x54, x46, x127)
+       var x129 uint64
+       x128, x129 = bits.Add64(x107, x104, uint64(p521Uint1(x127)))
        var x130 uint64
-       var x131 p521Uint1
-       x130, x131 = p521AddcarryxU64(x63, x126, 0x0)
+       var x131 uint64
+       x130, x131 = bits.Add64(x105, x102, uint64(p521Uint1(x129)))
        var x132 uint64
-       x132, _ = p521AddcarryxU64(x64, x128, x131)
-       var x134 uint64
-       var x135 p521Uint1
-       x134, x135 = p521AddcarryxU64(x75, x130, 0x0)
+       var x133 uint64
+       x132, x133 = bits.Add64(x103, x100, uint64(p521Uint1(x131)))
+       x134 := (uint64(p521Uint1(x133)) + x101)
+       var x135 uint64
        var x136 uint64
-       x136, _ = p521AddcarryxU64(x76, x132, x135)
+       x135, x136 = bits.Add64(x82, x116, uint64(0x0))
+       var x137 uint64
        var x138 uint64
-       var x139 p521Uint1
-       x138, x139 = p521AddcarryxU64(x89, x134, 0x0)
+       x137, x138 = bits.Add64(x84, x118, uint64(p521Uint1(x136)))
+       var x139 uint64
        var x140 uint64
-       x140, _ = p521AddcarryxU64(x90, x136, x139)
+       x139, x140 = bits.Add64(x86, x120, uint64(p521Uint1(x138)))
+       var x141 uint64
        var x142 uint64
-       var x143 p521Uint1
-       x142, x143 = p521AddcarryxU64(x55, x17, 0x0)
+       x141, x142 = bits.Add64(x88, x122, uint64(p521Uint1(x140)))
+       var x143 uint64
        var x144 uint64
-       x144, _ = p521AddcarryxU64(x56, x18, x143)
+       x143, x144 = bits.Add64(x90, x124, uint64(p521Uint1(x142)))
+       var x145 uint64
        var x146 uint64
-       var x147 p521Uint1
-       x146, x147 = p521AddcarryxU64(x65, x142, 0x0)
+       x145, x146 = bits.Add64(x92, x126, uint64(p521Uint1(x144)))
+       var x147 uint64
        var x148 uint64
-       x148, _ = p521AddcarryxU64(x66, x144, x147)
+       x147, x148 = bits.Add64(x94, x128, uint64(p521Uint1(x146)))
+       var x149 uint64
        var x150 uint64
-       var x151 p521Uint1
-       x150, x151 = p521AddcarryxU64(x77, x146, 0x0)
+       x149, x150 = bits.Add64(x96, x130, uint64(p521Uint1(x148)))
+       var x151 uint64
        var x152 uint64
-       x152, _ = p521AddcarryxU64(x78, x148, x151)
+       x151, x152 = bits.Add64(x98, x132, uint64(p521Uint1(x150)))
+       var x153 uint64
        var x154 uint64
-       var x155 p521Uint1
-       x154, x155 = p521AddcarryxU64(x91, x150, 0x0)
+       x153, x154 = bits.Add64(uint64(p521Uint1(x99)), x134, uint64(p521Uint1(x152)))
+       var x155 uint64
        var x156 uint64
-       x156, _ = p521AddcarryxU64(x92, x152, x155)
+       x156, x155 = bits.Mul64(x135, 0x1ff)
+       var x157 uint64
        var x158 uint64
-       var x159 p521Uint1
-       x158, x159 = p521AddcarryxU64(x57, x19, 0x0)
+       x158, x157 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x159 uint64
        var x160 uint64
-       x160, _ = p521AddcarryxU64(x58, x20, x159)
+       x160, x159 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x161 uint64
        var x162 uint64
-       var x163 p521Uint1
-       x162, x163 = p521AddcarryxU64(x67, x158, 0x0)
+       x162, x161 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x163 uint64
        var x164 uint64
-       x164, _ = p521AddcarryxU64(x68, x160, x163)
+       x164, x163 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x165 uint64
        var x166 uint64
-       var x167 p521Uint1
-       x166, x167 = p521AddcarryxU64(x79, x162, 0x0)
+       x166, x165 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x167 uint64
        var x168 uint64
-       x168, _ = p521AddcarryxU64(x80, x164, x167)
+       x168, x167 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x169 uint64
        var x170 uint64
-       var x171 p521Uint1
-       x170, x171 = p521AddcarryxU64(x93, x166, 0x0)
+       x170, x169 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x171 uint64
        var x172 uint64
-       x172, _ = p521AddcarryxU64(x94, x168, x171)
+       x172, x171 = bits.Mul64(x135, 0xffffffffffffffff)
+       var x173 uint64
        var x174 uint64
-       var x175 p521Uint1
-       x174, x175 = p521AddcarryxU64(x23, x21, 0x0)
+       x173, x174 = bits.Add64(x172, x169, uint64(0x0))
+       var x175 uint64
        var x176 uint64
-       x176, _ = p521AddcarryxU64(x24, x22, x175)
+       x175, x176 = bits.Add64(x170, x167, uint64(p521Uint1(x174)))
+       var x177 uint64
        var x178 uint64
-       var x179 p521Uint1
-       x178, x179 = p521AddcarryxU64(x69, x174, 0x0)
+       x177, x178 = bits.Add64(x168, x165, uint64(p521Uint1(x176)))
+       var x179 uint64
        var x180 uint64
-       x180, _ = p521AddcarryxU64(x70, x176, x179)
+       x179, x180 = bits.Add64(x166, x163, uint64(p521Uint1(x178)))
+       var x181 uint64
        var x182 uint64
-       var x183 p521Uint1
-       x182, x183 = p521AddcarryxU64(x81, x178, 0x0)
+       x181, x182 = bits.Add64(x164, x161, uint64(p521Uint1(x180)))
+       var x183 uint64
        var x184 uint64
-       x184, _ = p521AddcarryxU64(x82, x180, x183)
+       x183, x184 = bits.Add64(x162, x159, uint64(p521Uint1(x182)))
+       var x185 uint64
        var x186 uint64
-       var x187 p521Uint1
-       x186, x187 = p521AddcarryxU64(x95, x182, 0x0)
+       x185, x186 = bits.Add64(x160, x157, uint64(p521Uint1(x184)))
+       var x187 uint64
        var x188 uint64
-       x188, _ = p521AddcarryxU64(x96, x184, x187)
-       var x190 uint64
-       var x191 p521Uint1
-       x190, x191 = p521AddcarryxU64(x29, x25, 0x0)
+       x187, x188 = bits.Add64(x158, x155, uint64(p521Uint1(x186)))
+       x189 := (uint64(p521Uint1(x188)) + x156)
+       var x191 uint64
+       _, x191 = bits.Add64(x135, x171, uint64(0x0))
        var x192 uint64
-       x192, _ = p521AddcarryxU64(x30, x26, x191)
+       var x193 uint64
+       x192, x193 = bits.Add64(x137, x173, uint64(p521Uint1(x191)))
        var x194 uint64
-       var x195 p521Uint1
-       x194, x195 = p521AddcarryxU64(x71, x190, 0x0)
+       var x195 uint64
+       x194, x195 = bits.Add64(x139, x175, uint64(p521Uint1(x193)))
        var x196 uint64
-       x196, _ = p521AddcarryxU64(x72, x192, x195)
+       var x197 uint64
+       x196, x197 = bits.Add64(x141, x177, uint64(p521Uint1(x195)))
        var x198 uint64
-       var x199 p521Uint1
-       x198, x199 = p521AddcarryxU64(x83, x194, 0x0)
+       var x199 uint64
+       x198, x199 = bits.Add64(x143, x179, uint64(p521Uint1(x197)))
        var x200 uint64
-       x200, _ = p521AddcarryxU64(x84, x196, x199)
+       var x201 uint64
+       x200, x201 = bits.Add64(x145, x181, uint64(p521Uint1(x199)))
        var x202 uint64
-       var x203 p521Uint1
-       x202, x203 = p521AddcarryxU64(x97, x198, 0x0)
+       var x203 uint64
+       x202, x203 = bits.Add64(x147, x183, uint64(p521Uint1(x201)))
        var x204 uint64
-       x204, _ = p521AddcarryxU64(x98, x200, x203)
+       var x205 uint64
+       x204, x205 = bits.Add64(x149, x185, uint64(p521Uint1(x203)))
        var x206 uint64
-       var x207 p521Uint1
-       x206, x207 = p521AddcarryxU64(x31, x27, 0x0)
+       var x207 uint64
+       x206, x207 = bits.Add64(x151, x187, uint64(p521Uint1(x205)))
        var x208 uint64
-       x208, _ = p521AddcarryxU64(x32, x28, x207)
-       var x210 uint64
-       var x211 p521Uint1
-       x210, x211 = p521AddcarryxU64(x37, x206, 0x0)
+       var x209 uint64
+       x208, x209 = bits.Add64(x153, x189, uint64(p521Uint1(x207)))
+       x210 := (uint64(p521Uint1(x209)) + uint64(p521Uint1(x154)))
+       var x211 uint64
        var x212 uint64
-       x212, _ = p521AddcarryxU64(x38, x208, x211)
+       x212, x211 = bits.Mul64(x2, arg1[8])
+       var x213 uint64
        var x214 uint64
-       var x215 p521Uint1
-       x214, x215 = p521AddcarryxU64(x85, x210, 0x0)
+       x214, x213 = bits.Mul64(x2, arg1[7])
+       var x215 uint64
        var x216 uint64
-       x216, _ = p521AddcarryxU64(x86, x212, x215)
+       x216, x215 = bits.Mul64(x2, arg1[6])
+       var x217 uint64
        var x218 uint64
-       var x219 p521Uint1
-       x218, x219 = p521AddcarryxU64(x99, x214, 0x0)
+       x218, x217 = bits.Mul64(x2, arg1[5])
+       var x219 uint64
        var x220 uint64
-       x220, _ = p521AddcarryxU64(x100, x216, x219)
+       x220, x219 = bits.Mul64(x2, arg1[4])
+       var x221 uint64
        var x222 uint64
-       var x223 p521Uint1
-       x222, x223 = p521AddcarryxU64(x39, x33, 0x0)
+       x222, x221 = bits.Mul64(x2, arg1[3])
+       var x223 uint64
        var x224 uint64
-       x224, _ = p521AddcarryxU64(x40, x34, x223)
+       x224, x223 = bits.Mul64(x2, arg1[2])
+       var x225 uint64
        var x226 uint64
-       var x227 p521Uint1
-       x226, x227 = p521AddcarryxU64(x47, x222, 0x0)
+       x226, x225 = bits.Mul64(x2, arg1[1])
+       var x227 uint64
        var x228 uint64
-       x228, _ = p521AddcarryxU64(x48, x224, x227)
+       x228, x227 = bits.Mul64(x2, arg1[0])
+       var x229 uint64
        var x230 uint64
-       var x231 p521Uint1
-       x230, x231 = p521AddcarryxU64(x87, x226, 0x0)
+       x229, x230 = bits.Add64(x228, x225, uint64(0x0))
+       var x231 uint64
        var x232 uint64
-       x232, _ = p521AddcarryxU64(x88, x228, x231)
+       x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230)))
+       var x233 uint64
        var x234 uint64
-       var x235 p521Uint1
-       x234, x235 = p521AddcarryxU64(x101, x230, 0x0)
+       x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232)))
+       var x235 uint64
        var x236 uint64
-       x236, _ = p521AddcarryxU64(x102, x232, x235)
+       x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234)))
+       var x237 uint64
        var x238 uint64
-       var x239 p521Uint1
-       x238, x239 = p521AddcarryxU64(x41, x35, 0x0)
+       x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236)))
+       var x239 uint64
        var x240 uint64
-       x240, _ = p521AddcarryxU64(x42, x36, x239)
+       x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238)))
+       var x241 uint64
        var x242 uint64
-       var x243 p521Uint1
-       x242, x243 = p521AddcarryxU64(x49, x238, 0x0)
+       x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240)))
+       var x243 uint64
        var x244 uint64
-       x244, _ = p521AddcarryxU64(x50, x240, x243)
+       x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242)))
+       x245 := (uint64(p521Uint1(x244)) + x212)
        var x246 uint64
-       var x247 p521Uint1
-       x246, x247 = p521AddcarryxU64(x59, x242, 0x0)
+       var x247 uint64
+       x246, x247 = bits.Add64(x192, x227, uint64(0x0))
        var x248 uint64
-       x248, _ = p521AddcarryxU64(x60, x244, x247)
+       var x249 uint64
+       x248, x249 = bits.Add64(x194, x229, uint64(p521Uint1(x247)))
        var x250 uint64
-       var x251 p521Uint1
-       x250, x251 = p521AddcarryxU64(x103, x246, 0x0)
+       var x251 uint64
+       x250, x251 = bits.Add64(x196, x231, uint64(p521Uint1(x249)))
        var x252 uint64
-       x252, _ = p521AddcarryxU64(x104, x248, x251)
+       var x253 uint64
+       x252, x253 = bits.Add64(x198, x233, uint64(p521Uint1(x251)))
        var x254 uint64
-       var x255 p521Uint1
-       x254, x255 = p521AddcarryxU64(x123, x250, 0x0)
+       var x255 uint64
+       x254, x255 = bits.Add64(x200, x235, uint64(p521Uint1(x253)))
        var x256 uint64
-       x256, _ = p521AddcarryxU64(x124, x252, x255)
-       x258 := ((x254 >> 58) | ((x256 << 6) & 0xffffffffffffffff))
-       x259 := (x256 >> 58)
-       x260 := (x254 & 0x3ffffffffffffff)
+       var x257 uint64
+       x256, x257 = bits.Add64(x202, x237, uint64(p521Uint1(x255)))
+       var x258 uint64
+       var x259 uint64
+       x258, x259 = bits.Add64(x204, x239, uint64(p521Uint1(x257)))
+       var x260 uint64
        var x261 uint64
-       var x262 p521Uint1
-       x261, x262 = p521AddcarryxU64(x258, x234, 0x0)
+       x260, x261 = bits.Add64(x206, x241, uint64(p521Uint1(x259)))
+       var x262 uint64
        var x263 uint64
-       x263, _ = p521AddcarryxU64(x259, x236, x262)
-       x265 := ((x261 >> 58) | ((x263 << 6) & 0xffffffffffffffff))
-       x266 := (x263 >> 58)
-       x267 := (x261 & 0x3ffffffffffffff)
+       x262, x263 = bits.Add64(x208, x243, uint64(p521Uint1(x261)))
+       var x264 uint64
+       var x265 uint64
+       x264, x265 = bits.Add64(x210, x245, uint64(p521Uint1(x263)))
+       var x266 uint64
+       var x267 uint64
+       x267, x266 = bits.Mul64(x246, 0x1ff)
        var x268 uint64
-       var x269 p521Uint1
-       x268, x269 = p521AddcarryxU64(x265, x218, 0x0)
+       var x269 uint64
+       x269, x268 = bits.Mul64(x246, 0xffffffffffffffff)
        var x270 uint64
-       x270, _ = p521AddcarryxU64(x266, x220, x269)
-       x272 := ((x268 >> 58) | ((x270 << 6) & 0xffffffffffffffff))
-       x273 := (x270 >> 58)
-       x274 := (x268 & 0x3ffffffffffffff)
+       var x271 uint64
+       x271, x270 = bits.Mul64(x246, 0xffffffffffffffff)
+       var x272 uint64
+       var x273 uint64
+       x273, x272 = bits.Mul64(x246, 0xffffffffffffffff)
+       var x274 uint64
        var x275 uint64
-       var x276 p521Uint1
-       x275, x276 = p521AddcarryxU64(x272, x202, 0x0)
+       x275, x274 = bits.Mul64(x246, 0xffffffffffffffff)
+       var x276 uint64
        var x277 uint64
-       x277, _ = p521AddcarryxU64(x273, x204, x276)
-       x279 := ((x275 >> 58) | ((x277 << 6) & 0xffffffffffffffff))
-       x280 := (x277 >> 58)
-       x281 := (x275 & 0x3ffffffffffffff)
+       x277, x276 = bits.Mul64(x246, 0xffffffffffffffff)
+       var x278 uint64
+       var x279 uint64
+       x279, x278 = bits.Mul64(x246, 0xffffffffffffffff)
+       var x280 uint64
+       var x281 uint64
+       x281, x280 = bits.Mul64(x246, 0xffffffffffffffff)
        var x282 uint64
-       var x283 p521Uint1
-       x282, x283 = p521AddcarryxU64(x279, x186, 0x0)
+       var x283 uint64
+       x283, x282 = bits.Mul64(x246, 0xffffffffffffffff)
        var x284 uint64
-       x284, _ = p521AddcarryxU64(x280, x188, x283)
-       x286 := ((x282 >> 58) | ((x284 << 6) & 0xffffffffffffffff))
-       x287 := (x284 >> 58)
-       x288 := (x282 & 0x3ffffffffffffff)
+       var x285 uint64
+       x284, x285 = bits.Add64(x283, x280, uint64(0x0))
+       var x286 uint64
+       var x287 uint64
+       x286, x287 = bits.Add64(x281, x278, uint64(p521Uint1(x285)))
+       var x288 uint64
        var x289 uint64
-       var x290 p521Uint1
-       x289, x290 = p521AddcarryxU64(x286, x170, 0x0)
+       x288, x289 = bits.Add64(x279, x276, uint64(p521Uint1(x287)))
+       var x290 uint64
        var x291 uint64
-       x291, _ = p521AddcarryxU64(x287, x172, x290)
-       x293 := ((x289 >> 58) | ((x291 << 6) & 0xffffffffffffffff))
-       x294 := (x291 >> 58)
-       x295 := (x289 & 0x3ffffffffffffff)
+       x290, x291 = bits.Add64(x277, x274, uint64(p521Uint1(x289)))
+       var x292 uint64
+       var x293 uint64
+       x292, x293 = bits.Add64(x275, x272, uint64(p521Uint1(x291)))
+       var x294 uint64
+       var x295 uint64
+       x294, x295 = bits.Add64(x273, x270, uint64(p521Uint1(x293)))
        var x296 uint64
-       var x297 p521Uint1
-       x296, x297 = p521AddcarryxU64(x293, x154, 0x0)
+       var x297 uint64
+       x296, x297 = bits.Add64(x271, x268, uint64(p521Uint1(x295)))
        var x298 uint64
-       x298, _ = p521AddcarryxU64(x294, x156, x297)
-       x300 := ((x296 >> 58) | ((x298 << 6) & 0xffffffffffffffff))
-       x301 := (x298 >> 58)
-       x302 := (x296 & 0x3ffffffffffffff)
+       var x299 uint64
+       x298, x299 = bits.Add64(x269, x266, uint64(p521Uint1(x297)))
+       x300 := (uint64(p521Uint1(x299)) + x267)
+       var x302 uint64
+       _, x302 = bits.Add64(x246, x282, uint64(0x0))
        var x303 uint64
-       var x304 p521Uint1
-       x303, x304 = p521AddcarryxU64(x300, x138, 0x0)
+       var x304 uint64
+       x303, x304 = bits.Add64(x248, x284, uint64(p521Uint1(x302)))
        var x305 uint64
-       x305, _ = p521AddcarryxU64(x301, x140, x304)
-       x307 := ((x303 >> 57) | ((x305 << 7) & 0xffffffffffffffff))
-       x308 := (x305 >> 57)
-       x309 := (x303 & 0x1ffffffffffffff)
+       var x306 uint64
+       x305, x306 = bits.Add64(x250, x286, uint64(p521Uint1(x304)))
+       var x307 uint64
+       var x308 uint64
+       x307, x308 = bits.Add64(x252, x288, uint64(p521Uint1(x306)))
+       var x309 uint64
        var x310 uint64
-       var x311 p521Uint1
-       x310, x311 = p521AddcarryxU64(x125, x307, 0x0)
-       x312 := (uint64(x311) + x308)
-       x313 := ((x310 >> 58) | ((x312 << 6) & 0xffffffffffffffff))
-       x314 := (x310 & 0x3ffffffffffffff)
-       x315 := (x313 + x260)
-       x316 := p521Uint1((x315 >> 58))
-       x317 := (x315 & 0x3ffffffffffffff)
-       x318 := (uint64(x316) + x267)
-       out1[0] = x314
-       out1[1] = x317
-       out1[2] = x318
-       out1[3] = x274
-       out1[4] = x281
-       out1[5] = x288
-       out1[6] = x295
-       out1[7] = x302
-       out1[8] = x309
+       x309, x310 = bits.Add64(x254, x290, uint64(p521Uint1(x308)))
+       var x311 uint64
+       var x312 uint64
+       x311, x312 = bits.Add64(x256, x292, uint64(p521Uint1(x310)))
+       var x313 uint64
+       var x314 uint64
+       x313, x314 = bits.Add64(x258, x294, uint64(p521Uint1(x312)))
+       var x315 uint64
+       var x316 uint64
+       x315, x316 = bits.Add64(x260, x296, uint64(p521Uint1(x314)))
+       var x317 uint64
+       var x318 uint64
+       x317, x318 = bits.Add64(x262, x298, uint64(p521Uint1(x316)))
+       var x319 uint64
+       var x320 uint64
+       x319, x320 = bits.Add64(x264, x300, uint64(p521Uint1(x318)))
+       x321 := (uint64(p521Uint1(x320)) + uint64(p521Uint1(x265)))
+       var x322 uint64
+       var x323 uint64
+       x323, x322 = bits.Mul64(x3, arg1[8])
+       var x324 uint64
+       var x325 uint64
+       x325, x324 = bits.Mul64(x3, arg1[7])
+       var x326 uint64
+       var x327 uint64
+       x327, x326 = bits.Mul64(x3, arg1[6])
+       var x328 uint64
+       var x329 uint64
+       x329, x328 = bits.Mul64(x3, arg1[5])
+       var x330 uint64
+       var x331 uint64
+       x331, x330 = bits.Mul64(x3, arg1[4])
+       var x332 uint64
+       var x333 uint64
+       x333, x332 = bits.Mul64(x3, arg1[3])
+       var x334 uint64
+       var x335 uint64
+       x335, x334 = bits.Mul64(x3, arg1[2])
+       var x336 uint64
+       var x337 uint64
+       x337, x336 = bits.Mul64(x3, arg1[1])
+       var x338 uint64
+       var x339 uint64
+       x339, x338 = bits.Mul64(x3, arg1[0])
+       var x340 uint64
+       var x341 uint64
+       x340, x341 = bits.Add64(x339, x336, uint64(0x0))
+       var x342 uint64
+       var x343 uint64
+       x342, x343 = bits.Add64(x337, x334, uint64(p521Uint1(x341)))
+       var x344 uint64
+       var x345 uint64
+       x344, x345 = bits.Add64(x335, x332, uint64(p521Uint1(x343)))
+       var x346 uint64
+       var x347 uint64
+       x346, x347 = bits.Add64(x333, x330, uint64(p521Uint1(x345)))
+       var x348 uint64
+       var x349 uint64
+       x348, x349 = bits.Add64(x331, x328, uint64(p521Uint1(x347)))
+       var x350 uint64
+       var x351 uint64
+       x350, x351 = bits.Add64(x329, x326, uint64(p521Uint1(x349)))
+       var x352 uint64
+       var x353 uint64
+       x352, x353 = bits.Add64(x327, x324, uint64(p521Uint1(x351)))
+       var x354 uint64
+       var x355 uint64
+       x354, x355 = bits.Add64(x325, x322, uint64(p521Uint1(x353)))
+       x356 := (uint64(p521Uint1(x355)) + x323)
+       var x357 uint64
+       var x358 uint64
+       x357, x358 = bits.Add64(x303, x338, uint64(0x0))
+       var x359 uint64
+       var x360 uint64
+       x359, x360 = bits.Add64(x305, x340, uint64(p521Uint1(x358)))
+       var x361 uint64
+       var x362 uint64
+       x361, x362 = bits.Add64(x307, x342, uint64(p521Uint1(x360)))
+       var x363 uint64
+       var x364 uint64
+       x363, x364 = bits.Add64(x309, x344, uint64(p521Uint1(x362)))
+       var x365 uint64
+       var x366 uint64
+       x365, x366 = bits.Add64(x311, x346, uint64(p521Uint1(x364)))
+       var x367 uint64
+       var x368 uint64
+       x367, x368 = bits.Add64(x313, x348, uint64(p521Uint1(x366)))
+       var x369 uint64
+       var x370 uint64
+       x369, x370 = bits.Add64(x315, x350, uint64(p521Uint1(x368)))
+       var x371 uint64
+       var x372 uint64
+       x371, x372 = bits.Add64(x317, x352, uint64(p521Uint1(x370)))
+       var x373 uint64
+       var x374 uint64
+       x373, x374 = bits.Add64(x319, x354, uint64(p521Uint1(x372)))
+       var x375 uint64
+       var x376 uint64
+       x375, x376 = bits.Add64(x321, x356, uint64(p521Uint1(x374)))
+       var x377 uint64
+       var x378 uint64
+       x378, x377 = bits.Mul64(x357, 0x1ff)
+       var x379 uint64
+       var x380 uint64
+       x380, x379 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x381 uint64
+       var x382 uint64
+       x382, x381 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x383 uint64
+       var x384 uint64
+       x384, x383 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x385 uint64
+       var x386 uint64
+       x386, x385 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x387 uint64
+       var x388 uint64
+       x388, x387 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x389 uint64
+       var x390 uint64
+       x390, x389 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x391 uint64
+       var x392 uint64
+       x392, x391 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x393 uint64
+       var x394 uint64
+       x394, x393 = bits.Mul64(x357, 0xffffffffffffffff)
+       var x395 uint64
+       var x396 uint64
+       x395, x396 = bits.Add64(x394, x391, uint64(0x0))
+       var x397 uint64
+       var x398 uint64
+       x397, x398 = bits.Add64(x392, x389, uint64(p521Uint1(x396)))
+       var x399 uint64
+       var x400 uint64
+       x399, x400 = bits.Add64(x390, x387, uint64(p521Uint1(x398)))
+       var x401 uint64
+       var x402 uint64
+       x401, x402 = bits.Add64(x388, x385, uint64(p521Uint1(x400)))
+       var x403 uint64
+       var x404 uint64
+       x403, x404 = bits.Add64(x386, x383, uint64(p521Uint1(x402)))
+       var x405 uint64
+       var x406 uint64
+       x405, x406 = bits.Add64(x384, x381, uint64(p521Uint1(x404)))
+       var x407 uint64
+       var x408 uint64
+       x407, x408 = bits.Add64(x382, x379, uint64(p521Uint1(x406)))
+       var x409 uint64
+       var x410 uint64
+       x409, x410 = bits.Add64(x380, x377, uint64(p521Uint1(x408)))
+       x411 := (uint64(p521Uint1(x410)) + x378)
+       var x413 uint64
+       _, x413 = bits.Add64(x357, x393, uint64(0x0))
+       var x414 uint64
+       var x415 uint64
+       x414, x415 = bits.Add64(x359, x395, uint64(p521Uint1(x413)))
+       var x416 uint64
+       var x417 uint64
+       x416, x417 = bits.Add64(x361, x397, uint64(p521Uint1(x415)))
+       var x418 uint64
+       var x419 uint64
+       x418, x419 = bits.Add64(x363, x399, uint64(p521Uint1(x417)))
+       var x420 uint64
+       var x421 uint64
+       x420, x421 = bits.Add64(x365, x401, uint64(p521Uint1(x419)))
+       var x422 uint64
+       var x423 uint64
+       x422, x423 = bits.Add64(x367, x403, uint64(p521Uint1(x421)))
+       var x424 uint64
+       var x425 uint64
+       x424, x425 = bits.Add64(x369, x405, uint64(p521Uint1(x423)))
+       var x426 uint64
+       var x427 uint64
+       x426, x427 = bits.Add64(x371, x407, uint64(p521Uint1(x425)))
+       var x428 uint64
+       var x429 uint64
+       x428, x429 = bits.Add64(x373, x409, uint64(p521Uint1(x427)))
+       var x430 uint64
+       var x431 uint64
+       x430, x431 = bits.Add64(x375, x411, uint64(p521Uint1(x429)))
+       x432 := (uint64(p521Uint1(x431)) + uint64(p521Uint1(x376)))
+       var x433 uint64
+       var x434 uint64
+       x434, x433 = bits.Mul64(x4, arg1[8])
+       var x435 uint64
+       var x436 uint64
+       x436, x435 = bits.Mul64(x4, arg1[7])
+       var x437 uint64
+       var x438 uint64
+       x438, x437 = bits.Mul64(x4, arg1[6])
+       var x439 uint64
+       var x440 uint64
+       x440, x439 = bits.Mul64(x4, arg1[5])
+       var x441 uint64
+       var x442 uint64
+       x442, x441 = bits.Mul64(x4, arg1[4])
+       var x443 uint64
+       var x444 uint64
+       x444, x443 = bits.Mul64(x4, arg1[3])
+       var x445 uint64
+       var x446 uint64
+       x446, x445 = bits.Mul64(x4, arg1[2])
+       var x447 uint64
+       var x448 uint64
+       x448, x447 = bits.Mul64(x4, arg1[1])
+       var x449 uint64
+       var x450 uint64
+       x450, x449 = bits.Mul64(x4, arg1[0])
+       var x451 uint64
+       var x452 uint64
+       x451, x452 = bits.Add64(x450, x447, uint64(0x0))
+       var x453 uint64
+       var x454 uint64
+       x453, x454 = bits.Add64(x448, x445, uint64(p521Uint1(x452)))
+       var x455 uint64
+       var x456 uint64
+       x455, x456 = bits.Add64(x446, x443, uint64(p521Uint1(x454)))
+       var x457 uint64
+       var x458 uint64
+       x457, x458 = bits.Add64(x444, x441, uint64(p521Uint1(x456)))
+       var x459 uint64
+       var x460 uint64
+       x459, x460 = bits.Add64(x442, x439, uint64(p521Uint1(x458)))
+       var x461 uint64
+       var x462 uint64
+       x461, x462 = bits.Add64(x440, x437, uint64(p521Uint1(x460)))
+       var x463 uint64
+       var x464 uint64
+       x463, x464 = bits.Add64(x438, x435, uint64(p521Uint1(x462)))
+       var x465 uint64
+       var x466 uint64
+       x465, x466 = bits.Add64(x436, x433, uint64(p521Uint1(x464)))
+       x467 := (uint64(p521Uint1(x466)) + x434)
+       var x468 uint64
+       var x469 uint64
+       x468, x469 = bits.Add64(x414, x449, uint64(0x0))
+       var x470 uint64
+       var x471 uint64
+       x470, x471 = bits.Add64(x416, x451, uint64(p521Uint1(x469)))
+       var x472 uint64
+       var x473 uint64
+       x472, x473 = bits.Add64(x418, x453, uint64(p521Uint1(x471)))
+       var x474 uint64
+       var x475 uint64
+       x474, x475 = bits.Add64(x420, x455, uint64(p521Uint1(x473)))
+       var x476 uint64
+       var x477 uint64
+       x476, x477 = bits.Add64(x422, x457, uint64(p521Uint1(x475)))
+       var x478 uint64
+       var x479 uint64
+       x478, x479 = bits.Add64(x424, x459, uint64(p521Uint1(x477)))
+       var x480 uint64
+       var x481 uint64
+       x480, x481 = bits.Add64(x426, x461, uint64(p521Uint1(x479)))
+       var x482 uint64
+       var x483 uint64
+       x482, x483 = bits.Add64(x428, x463, uint64(p521Uint1(x481)))
+       var x484 uint64
+       var x485 uint64
+       x484, x485 = bits.Add64(x430, x465, uint64(p521Uint1(x483)))
+       var x486 uint64
+       var x487 uint64
+       x486, x487 = bits.Add64(x432, x467, uint64(p521Uint1(x485)))
+       var x488 uint64
+       var x489 uint64
+       x489, x488 = bits.Mul64(x468, 0x1ff)
+       var x490 uint64
+       var x491 uint64
+       x491, x490 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x492 uint64
+       var x493 uint64
+       x493, x492 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x494 uint64
+       var x495 uint64
+       x495, x494 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x496 uint64
+       var x497 uint64
+       x497, x496 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x498 uint64
+       var x499 uint64
+       x499, x498 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x500 uint64
+       var x501 uint64
+       x501, x500 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x502 uint64
+       var x503 uint64
+       x503, x502 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x504 uint64
+       var x505 uint64
+       x505, x504 = bits.Mul64(x468, 0xffffffffffffffff)
+       var x506 uint64
+       var x507 uint64
+       x506, x507 = bits.Add64(x505, x502, uint64(0x0))
+       var x508 uint64
+       var x509 uint64
+       x508, x509 = bits.Add64(x503, x500, uint64(p521Uint1(x507)))
+       var x510 uint64
+       var x511 uint64
+       x510, x511 = bits.Add64(x501, x498, uint64(p521Uint1(x509)))
+       var x512 uint64
+       var x513 uint64
+       x512, x513 = bits.Add64(x499, x496, uint64(p521Uint1(x511)))
+       var x514 uint64
+       var x515 uint64
+       x514, x515 = bits.Add64(x497, x494, uint64(p521Uint1(x513)))
+       var x516 uint64
+       var x517 uint64
+       x516, x517 = bits.Add64(x495, x492, uint64(p521Uint1(x515)))
+       var x518 uint64
+       var x519 uint64
+       x518, x519 = bits.Add64(x493, x490, uint64(p521Uint1(x517)))
+       var x520 uint64
+       var x521 uint64
+       x520, x521 = bits.Add64(x491, x488, uint64(p521Uint1(x519)))
+       x522 := (uint64(p521Uint1(x521)) + x489)
+       var x524 uint64
+       _, x524 = bits.Add64(x468, x504, uint64(0x0))
+       var x525 uint64
+       var x526 uint64
+       x525, x526 = bits.Add64(x470, x506, uint64(p521Uint1(x524)))
+       var x527 uint64
+       var x528 uint64
+       x527, x528 = bits.Add64(x472, x508, uint64(p521Uint1(x526)))
+       var x529 uint64
+       var x530 uint64
+       x529, x530 = bits.Add64(x474, x510, uint64(p521Uint1(x528)))
+       var x531 uint64
+       var x532 uint64
+       x531, x532 = bits.Add64(x476, x512, uint64(p521Uint1(x530)))
+       var x533 uint64
+       var x534 uint64
+       x533, x534 = bits.Add64(x478, x514, uint64(p521Uint1(x532)))
+       var x535 uint64
+       var x536 uint64
+       x535, x536 = bits.Add64(x480, x516, uint64(p521Uint1(x534)))
+       var x537 uint64
+       var x538 uint64
+       x537, x538 = bits.Add64(x482, x518, uint64(p521Uint1(x536)))
+       var x539 uint64
+       var x540 uint64
+       x539, x540 = bits.Add64(x484, x520, uint64(p521Uint1(x538)))
+       var x541 uint64
+       var x542 uint64
+       x541, x542 = bits.Add64(x486, x522, uint64(p521Uint1(x540)))
+       x543 := (uint64(p521Uint1(x542)) + uint64(p521Uint1(x487)))
+       var x544 uint64
+       var x545 uint64
+       x545, x544 = bits.Mul64(x5, arg1[8])
+       var x546 uint64
+       var x547 uint64
+       x547, x546 = bits.Mul64(x5, arg1[7])
+       var x548 uint64
+       var x549 uint64
+       x549, x548 = bits.Mul64(x5, arg1[6])
+       var x550 uint64
+       var x551 uint64
+       x551, x550 = bits.Mul64(x5, arg1[5])
+       var x552 uint64
+       var x553 uint64
+       x553, x552 = bits.Mul64(x5, arg1[4])
+       var x554 uint64
+       var x555 uint64
+       x555, x554 = bits.Mul64(x5, arg1[3])
+       var x556 uint64
+       var x557 uint64
+       x557, x556 = bits.Mul64(x5, arg1[2])
+       var x558 uint64
+       var x559 uint64
+       x559, x558 = bits.Mul64(x5, arg1[1])
+       var x560 uint64
+       var x561 uint64
+       x561, x560 = bits.Mul64(x5, arg1[0])
+       var x562 uint64
+       var x563 uint64
+       x562, x563 = bits.Add64(x561, x558, uint64(0x0))
+       var x564 uint64
+       var x565 uint64
+       x564, x565 = bits.Add64(x559, x556, uint64(p521Uint1(x563)))
+       var x566 uint64
+       var x567 uint64
+       x566, x567 = bits.Add64(x557, x554, uint64(p521Uint1(x565)))
+       var x568 uint64
+       var x569 uint64
+       x568, x569 = bits.Add64(x555, x552, uint64(p521Uint1(x567)))
+       var x570 uint64
+       var x571 uint64
+       x570, x571 = bits.Add64(x553, x550, uint64(p521Uint1(x569)))
+       var x572 uint64
+       var x573 uint64
+       x572, x573 = bits.Add64(x551, x548, uint64(p521Uint1(x571)))
+       var x574 uint64
+       var x575 uint64
+       x574, x575 = bits.Add64(x549, x546, uint64(p521Uint1(x573)))
+       var x576 uint64
+       var x577 uint64
+       x576, x577 = bits.Add64(x547, x544, uint64(p521Uint1(x575)))
+       x578 := (uint64(p521Uint1(x577)) + x545)
+       var x579 uint64
+       var x580 uint64
+       x579, x580 = bits.Add64(x525, x560, uint64(0x0))
+       var x581 uint64
+       var x582 uint64
+       x581, x582 = bits.Add64(x527, x562, uint64(p521Uint1(x580)))
+       var x583 uint64
+       var x584 uint64
+       x583, x584 = bits.Add64(x529, x564, uint64(p521Uint1(x582)))
+       var x585 uint64
+       var x586 uint64
+       x585, x586 = bits.Add64(x531, x566, uint64(p521Uint1(x584)))
+       var x587 uint64
+       var x588 uint64
+       x587, x588 = bits.Add64(x533, x568, uint64(p521Uint1(x586)))
+       var x589 uint64
+       var x590 uint64
+       x589, x590 = bits.Add64(x535, x570, uint64(p521Uint1(x588)))
+       var x591 uint64
+       var x592 uint64
+       x591, x592 = bits.Add64(x537, x572, uint64(p521Uint1(x590)))
+       var x593 uint64
+       var x594 uint64
+       x593, x594 = bits.Add64(x539, x574, uint64(p521Uint1(x592)))
+       var x595 uint64
+       var x596 uint64
+       x595, x596 = bits.Add64(x541, x576, uint64(p521Uint1(x594)))
+       var x597 uint64
+       var x598 uint64
+       x597, x598 = bits.Add64(x543, x578, uint64(p521Uint1(x596)))
+       var x599 uint64
+       var x600 uint64
+       x600, x599 = bits.Mul64(x579, 0x1ff)
+       var x601 uint64
+       var x602 uint64
+       x602, x601 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x603 uint64
+       var x604 uint64
+       x604, x603 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x605 uint64
+       var x606 uint64
+       x606, x605 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x607 uint64
+       var x608 uint64
+       x608, x607 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x609 uint64
+       var x610 uint64
+       x610, x609 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x611 uint64
+       var x612 uint64
+       x612, x611 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x613 uint64
+       var x614 uint64
+       x614, x613 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x615 uint64
+       var x616 uint64
+       x616, x615 = bits.Mul64(x579, 0xffffffffffffffff)
+       var x617 uint64
+       var x618 uint64
+       x617, x618 = bits.Add64(x616, x613, uint64(0x0))
+       var x619 uint64
+       var x620 uint64
+       x619, x620 = bits.Add64(x614, x611, uint64(p521Uint1(x618)))
+       var x621 uint64
+       var x622 uint64
+       x621, x622 = bits.Add64(x612, x609, uint64(p521Uint1(x620)))
+       var x623 uint64
+       var x624 uint64
+       x623, x624 = bits.Add64(x610, x607, uint64(p521Uint1(x622)))
+       var x625 uint64
+       var x626 uint64
+       x625, x626 = bits.Add64(x608, x605, uint64(p521Uint1(x624)))
+       var x627 uint64
+       var x628 uint64
+       x627, x628 = bits.Add64(x606, x603, uint64(p521Uint1(x626)))
+       var x629 uint64
+       var x630 uint64
+       x629, x630 = bits.Add64(x604, x601, uint64(p521Uint1(x628)))
+       var x631 uint64
+       var x632 uint64
+       x631, x632 = bits.Add64(x602, x599, uint64(p521Uint1(x630)))
+       x633 := (uint64(p521Uint1(x632)) + x600)
+       var x635 uint64
+       _, x635 = bits.Add64(x579, x615, uint64(0x0))
+       var x636 uint64
+       var x637 uint64
+       x636, x637 = bits.Add64(x581, x617, uint64(p521Uint1(x635)))
+       var x638 uint64
+       var x639 uint64
+       x638, x639 = bits.Add64(x583, x619, uint64(p521Uint1(x637)))
+       var x640 uint64
+       var x641 uint64
+       x640, x641 = bits.Add64(x585, x621, uint64(p521Uint1(x639)))
+       var x642 uint64
+       var x643 uint64
+       x642, x643 = bits.Add64(x587, x623, uint64(p521Uint1(x641)))
+       var x644 uint64
+       var x645 uint64
+       x644, x645 = bits.Add64(x589, x625, uint64(p521Uint1(x643)))
+       var x646 uint64
+       var x647 uint64
+       x646, x647 = bits.Add64(x591, x627, uint64(p521Uint1(x645)))
+       var x648 uint64
+       var x649 uint64
+       x648, x649 = bits.Add64(x593, x629, uint64(p521Uint1(x647)))
+       var x650 uint64
+       var x651 uint64
+       x650, x651 = bits.Add64(x595, x631, uint64(p521Uint1(x649)))
+       var x652 uint64
+       var x653 uint64
+       x652, x653 = bits.Add64(x597, x633, uint64(p521Uint1(x651)))
+       x654 := (uint64(p521Uint1(x653)) + uint64(p521Uint1(x598)))
+       var x655 uint64
+       var x656 uint64
+       x656, x655 = bits.Mul64(x6, arg1[8])
+       var x657 uint64
+       var x658 uint64
+       x658, x657 = bits.Mul64(x6, arg1[7])
+       var x659 uint64
+       var x660 uint64
+       x660, x659 = bits.Mul64(x6, arg1[6])
+       var x661 uint64
+       var x662 uint64
+       x662, x661 = bits.Mul64(x6, arg1[5])
+       var x663 uint64
+       var x664 uint64
+       x664, x663 = bits.Mul64(x6, arg1[4])
+       var x665 uint64
+       var x666 uint64
+       x666, x665 = bits.Mul64(x6, arg1[3])
+       var x667 uint64
+       var x668 uint64
+       x668, x667 = bits.Mul64(x6, arg1[2])
+       var x669 uint64
+       var x670 uint64
+       x670, x669 = bits.Mul64(x6, arg1[1])
+       var x671 uint64
+       var x672 uint64
+       x672, x671 = bits.Mul64(x6, arg1[0])
+       var x673 uint64
+       var x674 uint64
+       x673, x674 = bits.Add64(x672, x669, uint64(0x0))
+       var x675 uint64
+       var x676 uint64
+       x675, x676 = bits.Add64(x670, x667, uint64(p521Uint1(x674)))
+       var x677 uint64
+       var x678 uint64
+       x677, x678 = bits.Add64(x668, x665, uint64(p521Uint1(x676)))
+       var x679 uint64
+       var x680 uint64
+       x679, x680 = bits.Add64(x666, x663, uint64(p521Uint1(x678)))
+       var x681 uint64
+       var x682 uint64
+       x681, x682 = bits.Add64(x664, x661, uint64(p521Uint1(x680)))
+       var x683 uint64
+       var x684 uint64
+       x683, x684 = bits.Add64(x662, x659, uint64(p521Uint1(x682)))
+       var x685 uint64
+       var x686 uint64
+       x685, x686 = bits.Add64(x660, x657, uint64(p521Uint1(x684)))
+       var x687 uint64
+       var x688 uint64
+       x687, x688 = bits.Add64(x658, x655, uint64(p521Uint1(x686)))
+       x689 := (uint64(p521Uint1(x688)) + x656)
+       var x690 uint64
+       var x691 uint64
+       x690, x691 = bits.Add64(x636, x671, uint64(0x0))
+       var x692 uint64
+       var x693 uint64
+       x692, x693 = bits.Add64(x638, x673, uint64(p521Uint1(x691)))
+       var x694 uint64
+       var x695 uint64
+       x694, x695 = bits.Add64(x640, x675, uint64(p521Uint1(x693)))
+       var x696 uint64
+       var x697 uint64
+       x696, x697 = bits.Add64(x642, x677, uint64(p521Uint1(x695)))
+       var x698 uint64
+       var x699 uint64
+       x698, x699 = bits.Add64(x644, x679, uint64(p521Uint1(x697)))
+       var x700 uint64
+       var x701 uint64
+       x700, x701 = bits.Add64(x646, x681, uint64(p521Uint1(x699)))
+       var x702 uint64
+       var x703 uint64
+       x702, x703 = bits.Add64(x648, x683, uint64(p521Uint1(x701)))
+       var x704 uint64
+       var x705 uint64
+       x704, x705 = bits.Add64(x650, x685, uint64(p521Uint1(x703)))
+       var x706 uint64
+       var x707 uint64
+       x706, x707 = bits.Add64(x652, x687, uint64(p521Uint1(x705)))
+       var x708 uint64
+       var x709 uint64
+       x708, x709 = bits.Add64(x654, x689, uint64(p521Uint1(x707)))
+       var x710 uint64
+       var x711 uint64
+       x711, x710 = bits.Mul64(x690, 0x1ff)
+       var x712 uint64
+       var x713 uint64
+       x713, x712 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x714 uint64
+       var x715 uint64
+       x715, x714 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x716 uint64
+       var x717 uint64
+       x717, x716 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x718 uint64
+       var x719 uint64
+       x719, x718 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x720 uint64
+       var x721 uint64
+       x721, x720 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x722 uint64
+       var x723 uint64
+       x723, x722 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x724 uint64
+       var x725 uint64
+       x725, x724 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x726 uint64
+       var x727 uint64
+       x727, x726 = bits.Mul64(x690, 0xffffffffffffffff)
+       var x728 uint64
+       var x729 uint64
+       x728, x729 = bits.Add64(x727, x724, uint64(0x0))
+       var x730 uint64
+       var x731 uint64
+       x730, x731 = bits.Add64(x725, x722, uint64(p521Uint1(x729)))
+       var x732 uint64
+       var x733 uint64
+       x732, x733 = bits.Add64(x723, x720, uint64(p521Uint1(x731)))
+       var x734 uint64
+       var x735 uint64
+       x734, x735 = bits.Add64(x721, x718, uint64(p521Uint1(x733)))
+       var x736 uint64
+       var x737 uint64
+       x736, x737 = bits.Add64(x719, x716, uint64(p521Uint1(x735)))
+       var x738 uint64
+       var x739 uint64
+       x738, x739 = bits.Add64(x717, x714, uint64(p521Uint1(x737)))
+       var x740 uint64
+       var x741 uint64
+       x740, x741 = bits.Add64(x715, x712, uint64(p521Uint1(x739)))
+       var x742 uint64
+       var x743 uint64
+       x742, x743 = bits.Add64(x713, x710, uint64(p521Uint1(x741)))
+       x744 := (uint64(p521Uint1(x743)) + x711)
+       var x746 uint64
+       _, x746 = bits.Add64(x690, x726, uint64(0x0))
+       var x747 uint64
+       var x748 uint64
+       x747, x748 = bits.Add64(x692, x728, uint64(p521Uint1(x746)))
+       var x749 uint64
+       var x750 uint64
+       x749, x750 = bits.Add64(x694, x730, uint64(p521Uint1(x748)))
+       var x751 uint64
+       var x752 uint64
+       x751, x752 = bits.Add64(x696, x732, uint64(p521Uint1(x750)))
+       var x753 uint64
+       var x754 uint64
+       x753, x754 = bits.Add64(x698, x734, uint64(p521Uint1(x752)))
+       var x755 uint64
+       var x756 uint64
+       x755, x756 = bits.Add64(x700, x736, uint64(p521Uint1(x754)))
+       var x757 uint64
+       var x758 uint64
+       x757, x758 = bits.Add64(x702, x738, uint64(p521Uint1(x756)))
+       var x759 uint64
+       var x760 uint64
+       x759, x760 = bits.Add64(x704, x740, uint64(p521Uint1(x758)))
+       var x761 uint64
+       var x762 uint64
+       x761, x762 = bits.Add64(x706, x742, uint64(p521Uint1(x760)))
+       var x763 uint64
+       var x764 uint64
+       x763, x764 = bits.Add64(x708, x744, uint64(p521Uint1(x762)))
+       x765 := (uint64(p521Uint1(x764)) + uint64(p521Uint1(x709)))
+       var x766 uint64
+       var x767 uint64
+       x767, x766 = bits.Mul64(x7, arg1[8])
+       var x768 uint64
+       var x769 uint64
+       x769, x768 = bits.Mul64(x7, arg1[7])
+       var x770 uint64
+       var x771 uint64
+       x771, x770 = bits.Mul64(x7, arg1[6])
+       var x772 uint64
+       var x773 uint64
+       x773, x772 = bits.Mul64(x7, arg1[5])
+       var x774 uint64
+       var x775 uint64
+       x775, x774 = bits.Mul64(x7, arg1[4])
+       var x776 uint64
+       var x777 uint64
+       x777, x776 = bits.Mul64(x7, arg1[3])
+       var x778 uint64
+       var x779 uint64
+       x779, x778 = bits.Mul64(x7, arg1[2])
+       var x780 uint64
+       var x781 uint64
+       x781, x780 = bits.Mul64(x7, arg1[1])
+       var x782 uint64
+       var x783 uint64
+       x783, x782 = bits.Mul64(x7, arg1[0])
+       var x784 uint64
+       var x785 uint64
+       x784, x785 = bits.Add64(x783, x780, uint64(0x0))
+       var x786 uint64
+       var x787 uint64
+       x786, x787 = bits.Add64(x781, x778, uint64(p521Uint1(x785)))
+       var x788 uint64
+       var x789 uint64
+       x788, x789 = bits.Add64(x779, x776, uint64(p521Uint1(x787)))
+       var x790 uint64
+       var x791 uint64
+       x790, x791 = bits.Add64(x777, x774, uint64(p521Uint1(x789)))
+       var x792 uint64
+       var x793 uint64
+       x792, x793 = bits.Add64(x775, x772, uint64(p521Uint1(x791)))
+       var x794 uint64
+       var x795 uint64
+       x794, x795 = bits.Add64(x773, x770, uint64(p521Uint1(x793)))
+       var x796 uint64
+       var x797 uint64
+       x796, x797 = bits.Add64(x771, x768, uint64(p521Uint1(x795)))
+       var x798 uint64
+       var x799 uint64
+       x798, x799 = bits.Add64(x769, x766, uint64(p521Uint1(x797)))
+       x800 := (uint64(p521Uint1(x799)) + x767)
+       var x801 uint64
+       var x802 uint64
+       x801, x802 = bits.Add64(x747, x782, uint64(0x0))
+       var x803 uint64
+       var x804 uint64
+       x803, x804 = bits.Add64(x749, x784, uint64(p521Uint1(x802)))
+       var x805 uint64
+       var x806 uint64
+       x805, x806 = bits.Add64(x751, x786, uint64(p521Uint1(x804)))
+       var x807 uint64
+       var x808 uint64
+       x807, x808 = bits.Add64(x753, x788, uint64(p521Uint1(x806)))
+       var x809 uint64
+       var x810 uint64
+       x809, x810 = bits.Add64(x755, x790, uint64(p521Uint1(x808)))
+       var x811 uint64
+       var x812 uint64
+       x811, x812 = bits.Add64(x757, x792, uint64(p521Uint1(x810)))
+       var x813 uint64
+       var x814 uint64
+       x813, x814 = bits.Add64(x759, x794, uint64(p521Uint1(x812)))
+       var x815 uint64
+       var x816 uint64
+       x815, x816 = bits.Add64(x761, x796, uint64(p521Uint1(x814)))
+       var x817 uint64
+       var x818 uint64
+       x817, x818 = bits.Add64(x763, x798, uint64(p521Uint1(x816)))
+       var x819 uint64
+       var x820 uint64
+       x819, x820 = bits.Add64(x765, x800, uint64(p521Uint1(x818)))
+       var x821 uint64
+       var x822 uint64
+       x822, x821 = bits.Mul64(x801, 0x1ff)
+       var x823 uint64
+       var x824 uint64
+       x824, x823 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x825 uint64
+       var x826 uint64
+       x826, x825 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x827 uint64
+       var x828 uint64
+       x828, x827 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x829 uint64
+       var x830 uint64
+       x830, x829 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x831 uint64
+       var x832 uint64
+       x832, x831 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x833 uint64
+       var x834 uint64
+       x834, x833 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x835 uint64
+       var x836 uint64
+       x836, x835 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x837 uint64
+       var x838 uint64
+       x838, x837 = bits.Mul64(x801, 0xffffffffffffffff)
+       var x839 uint64
+       var x840 uint64
+       x839, x840 = bits.Add64(x838, x835, uint64(0x0))
+       var x841 uint64
+       var x842 uint64
+       x841, x842 = bits.Add64(x836, x833, uint64(p521Uint1(x840)))
+       var x843 uint64
+       var x844 uint64
+       x843, x844 = bits.Add64(x834, x831, uint64(p521Uint1(x842)))
+       var x845 uint64
+       var x846 uint64
+       x845, x846 = bits.Add64(x832, x829, uint64(p521Uint1(x844)))
+       var x847 uint64
+       var x848 uint64
+       x847, x848 = bits.Add64(x830, x827, uint64(p521Uint1(x846)))
+       var x849 uint64
+       var x850 uint64
+       x849, x850 = bits.Add64(x828, x825, uint64(p521Uint1(x848)))
+       var x851 uint64
+       var x852 uint64
+       x851, x852 = bits.Add64(x826, x823, uint64(p521Uint1(x850)))
+       var x853 uint64
+       var x854 uint64
+       x853, x854 = bits.Add64(x824, x821, uint64(p521Uint1(x852)))
+       x855 := (uint64(p521Uint1(x854)) + x822)
+       var x857 uint64
+       _, x857 = bits.Add64(x801, x837, uint64(0x0))
+       var x858 uint64
+       var x859 uint64
+       x858, x859 = bits.Add64(x803, x839, uint64(p521Uint1(x857)))
+       var x860 uint64
+       var x861 uint64
+       x860, x861 = bits.Add64(x805, x841, uint64(p521Uint1(x859)))
+       var x862 uint64
+       var x863 uint64
+       x862, x863 = bits.Add64(x807, x843, uint64(p521Uint1(x861)))
+       var x864 uint64
+       var x865 uint64
+       x864, x865 = bits.Add64(x809, x845, uint64(p521Uint1(x863)))
+       var x866 uint64
+       var x867 uint64
+       x866, x867 = bits.Add64(x811, x847, uint64(p521Uint1(x865)))
+       var x868 uint64
+       var x869 uint64
+       x868, x869 = bits.Add64(x813, x849, uint64(p521Uint1(x867)))
+       var x870 uint64
+       var x871 uint64
+       x870, x871 = bits.Add64(x815, x851, uint64(p521Uint1(x869)))
+       var x872 uint64
+       var x873 uint64
+       x872, x873 = bits.Add64(x817, x853, uint64(p521Uint1(x871)))
+       var x874 uint64
+       var x875 uint64
+       x874, x875 = bits.Add64(x819, x855, uint64(p521Uint1(x873)))
+       x876 := (uint64(p521Uint1(x875)) + uint64(p521Uint1(x820)))
+       var x877 uint64
+       var x878 uint64
+       x878, x877 = bits.Mul64(x8, arg1[8])
+       var x879 uint64
+       var x880 uint64
+       x880, x879 = bits.Mul64(x8, arg1[7])
+       var x881 uint64
+       var x882 uint64
+       x882, x881 = bits.Mul64(x8, arg1[6])
+       var x883 uint64
+       var x884 uint64
+       x884, x883 = bits.Mul64(x8, arg1[5])
+       var x885 uint64
+       var x886 uint64
+       x886, x885 = bits.Mul64(x8, arg1[4])
+       var x887 uint64
+       var x888 uint64
+       x888, x887 = bits.Mul64(x8, arg1[3])
+       var x889 uint64
+       var x890 uint64
+       x890, x889 = bits.Mul64(x8, arg1[2])
+       var x891 uint64
+       var x892 uint64
+       x892, x891 = bits.Mul64(x8, arg1[1])
+       var x893 uint64
+       var x894 uint64
+       x894, x893 = bits.Mul64(x8, arg1[0])
+       var x895 uint64
+       var x896 uint64
+       x895, x896 = bits.Add64(x894, x891, uint64(0x0))
+       var x897 uint64
+       var x898 uint64
+       x897, x898 = bits.Add64(x892, x889, uint64(p521Uint1(x896)))
+       var x899 uint64
+       var x900 uint64
+       x899, x900 = bits.Add64(x890, x887, uint64(p521Uint1(x898)))
+       var x901 uint64
+       var x902 uint64
+       x901, x902 = bits.Add64(x888, x885, uint64(p521Uint1(x900)))
+       var x903 uint64
+       var x904 uint64
+       x903, x904 = bits.Add64(x886, x883, uint64(p521Uint1(x902)))
+       var x905 uint64
+       var x906 uint64
+       x905, x906 = bits.Add64(x884, x881, uint64(p521Uint1(x904)))
+       var x907 uint64
+       var x908 uint64
+       x907, x908 = bits.Add64(x882, x879, uint64(p521Uint1(x906)))
+       var x909 uint64
+       var x910 uint64
+       x909, x910 = bits.Add64(x880, x877, uint64(p521Uint1(x908)))
+       x911 := (uint64(p521Uint1(x910)) + x878)
+       var x912 uint64
+       var x913 uint64
+       x912, x913 = bits.Add64(x858, x893, uint64(0x0))
+       var x914 uint64
+       var x915 uint64
+       x914, x915 = bits.Add64(x860, x895, uint64(p521Uint1(x913)))
+       var x916 uint64
+       var x917 uint64
+       x916, x917 = bits.Add64(x862, x897, uint64(p521Uint1(x915)))
+       var x918 uint64
+       var x919 uint64
+       x918, x919 = bits.Add64(x864, x899, uint64(p521Uint1(x917)))
+       var x920 uint64
+       var x921 uint64
+       x920, x921 = bits.Add64(x866, x901, uint64(p521Uint1(x919)))
+       var x922 uint64
+       var x923 uint64
+       x922, x923 = bits.Add64(x868, x903, uint64(p521Uint1(x921)))
+       var x924 uint64
+       var x925 uint64
+       x924, x925 = bits.Add64(x870, x905, uint64(p521Uint1(x923)))
+       var x926 uint64
+       var x927 uint64
+       x926, x927 = bits.Add64(x872, x907, uint64(p521Uint1(x925)))
+       var x928 uint64
+       var x929 uint64
+       x928, x929 = bits.Add64(x874, x909, uint64(p521Uint1(x927)))
+       var x930 uint64
+       var x931 uint64
+       x930, x931 = bits.Add64(x876, x911, uint64(p521Uint1(x929)))
+       var x932 uint64
+       var x933 uint64
+       x933, x932 = bits.Mul64(x912, 0x1ff)
+       var x934 uint64
+       var x935 uint64
+       x935, x934 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x936 uint64
+       var x937 uint64
+       x937, x936 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x938 uint64
+       var x939 uint64
+       x939, x938 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x940 uint64
+       var x941 uint64
+       x941, x940 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x942 uint64
+       var x943 uint64
+       x943, x942 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x944 uint64
+       var x945 uint64
+       x945, x944 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x946 uint64
+       var x947 uint64
+       x947, x946 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x948 uint64
+       var x949 uint64
+       x949, x948 = bits.Mul64(x912, 0xffffffffffffffff)
+       var x950 uint64
+       var x951 uint64
+       x950, x951 = bits.Add64(x949, x946, uint64(0x0))
+       var x952 uint64
+       var x953 uint64
+       x952, x953 = bits.Add64(x947, x944, uint64(p521Uint1(x951)))
+       var x954 uint64
+       var x955 uint64
+       x954, x955 = bits.Add64(x945, x942, uint64(p521Uint1(x953)))
+       var x956 uint64
+       var x957 uint64
+       x956, x957 = bits.Add64(x943, x940, uint64(p521Uint1(x955)))
+       var x958 uint64
+       var x959 uint64
+       x958, x959 = bits.Add64(x941, x938, uint64(p521Uint1(x957)))
+       var x960 uint64
+       var x961 uint64
+       x960, x961 = bits.Add64(x939, x936, uint64(p521Uint1(x959)))
+       var x962 uint64
+       var x963 uint64
+       x962, x963 = bits.Add64(x937, x934, uint64(p521Uint1(x961)))
+       var x964 uint64
+       var x965 uint64
+       x964, x965 = bits.Add64(x935, x932, uint64(p521Uint1(x963)))
+       x966 := (uint64(p521Uint1(x965)) + x933)
+       var x968 uint64
+       _, x968 = bits.Add64(x912, x948, uint64(0x0))
+       var x969 uint64
+       var x970 uint64
+       x969, x970 = bits.Add64(x914, x950, uint64(p521Uint1(x968)))
+       var x971 uint64
+       var x972 uint64
+       x971, x972 = bits.Add64(x916, x952, uint64(p521Uint1(x970)))
+       var x973 uint64
+       var x974 uint64
+       x973, x974 = bits.Add64(x918, x954, uint64(p521Uint1(x972)))
+       var x975 uint64
+       var x976 uint64
+       x975, x976 = bits.Add64(x920, x956, uint64(p521Uint1(x974)))
+       var x977 uint64
+       var x978 uint64
+       x977, x978 = bits.Add64(x922, x958, uint64(p521Uint1(x976)))
+       var x979 uint64
+       var x980 uint64
+       x979, x980 = bits.Add64(x924, x960, uint64(p521Uint1(x978)))
+       var x981 uint64
+       var x982 uint64
+       x981, x982 = bits.Add64(x926, x962, uint64(p521Uint1(x980)))
+       var x983 uint64
+       var x984 uint64
+       x983, x984 = bits.Add64(x928, x964, uint64(p521Uint1(x982)))
+       var x985 uint64
+       var x986 uint64
+       x985, x986 = bits.Add64(x930, x966, uint64(p521Uint1(x984)))
+       x987 := (uint64(p521Uint1(x986)) + uint64(p521Uint1(x931)))
+       var x988 uint64
+       var x989 uint64
+       x988, x989 = bits.Sub64(x969, 0xffffffffffffffff, uint64(0x0))
+       var x990 uint64
+       var x991 uint64
+       x990, x991 = bits.Sub64(x971, 0xffffffffffffffff, uint64(p521Uint1(x989)))
+       var x992 uint64
+       var x993 uint64
+       x992, x993 = bits.Sub64(x973, 0xffffffffffffffff, uint64(p521Uint1(x991)))
+       var x994 uint64
+       var x995 uint64
+       x994, x995 = bits.Sub64(x975, 0xffffffffffffffff, uint64(p521Uint1(x993)))
+       var x996 uint64
+       var x997 uint64
+       x996, x997 = bits.Sub64(x977, 0xffffffffffffffff, uint64(p521Uint1(x995)))
+       var x998 uint64
+       var x999 uint64
+       x998, x999 = bits.Sub64(x979, 0xffffffffffffffff, uint64(p521Uint1(x997)))
+       var x1000 uint64
+       var x1001 uint64
+       x1000, x1001 = bits.Sub64(x981, 0xffffffffffffffff, uint64(p521Uint1(x999)))
+       var x1002 uint64
+       var x1003 uint64
+       x1002, x1003 = bits.Sub64(x983, 0xffffffffffffffff, uint64(p521Uint1(x1001)))
+       var x1004 uint64
+       var x1005 uint64
+       x1004, x1005 = bits.Sub64(x985, 0x1ff, uint64(p521Uint1(x1003)))
+       var x1007 uint64
+       _, x1007 = bits.Sub64(x987, uint64(0x0), uint64(p521Uint1(x1005)))
+       var x1008 uint64
+       p521CmovznzU64(&x1008, p521Uint1(x1007), x988, x969)
+       var x1009 uint64
+       p521CmovznzU64(&x1009, p521Uint1(x1007), x990, x971)
+       var x1010 uint64
+       p521CmovznzU64(&x1010, p521Uint1(x1007), x992, x973)
+       var x1011 uint64
+       p521CmovznzU64(&x1011, p521Uint1(x1007), x994, x975)
+       var x1012 uint64
+       p521CmovznzU64(&x1012, p521Uint1(x1007), x996, x977)
+       var x1013 uint64
+       p521CmovznzU64(&x1013, p521Uint1(x1007), x998, x979)
+       var x1014 uint64
+       p521CmovznzU64(&x1014, p521Uint1(x1007), x1000, x981)
+       var x1015 uint64
+       p521CmovznzU64(&x1015, p521Uint1(x1007), x1002, x983)
+       var x1016 uint64
+       p521CmovznzU64(&x1016, p521Uint1(x1007), x1004, x985)
+       out1[0] = x1008
+       out1[1] = x1009
+       out1[2] = x1010
+       out1[3] = x1011
+       out1[4] = x1012
+       out1[5] = x1013
+       out1[6] = x1014
+       out1[7] = x1015
+       out1[8] = x1016
 }
 
-// p521Carry reduces a field element.
+// p521Add adds two field elements in the Montgomery domain.
 //
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+//   0 โ‰ค eval arg2 < m
 // Postconditions:
-//   eval out1 mod m = eval arg1 mod m
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
+//   0 โ‰ค eval out1 < m
 //
-// Input Bounds:
-//   arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-// Output Bounds:
-//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-func p521Carry(out1 *[9]uint64, arg1 *[9]uint64) {
-       x1 := arg1[0]
-       x2 := ((x1 >> 58) + arg1[1])
-       x3 := ((x2 >> 58) + arg1[2])
-       x4 := ((x3 >> 58) + arg1[3])
-       x5 := ((x4 >> 58) + arg1[4])
-       x6 := ((x5 >> 58) + arg1[5])
-       x7 := ((x6 >> 58) + arg1[6])
-       x8 := ((x7 >> 58) + arg1[7])
-       x9 := ((x8 >> 58) + arg1[8])
-       x10 := ((x1 & 0x3ffffffffffffff) + (x9 >> 57))
-       x11 := (uint64(p521Uint1((x10 >> 58))) + (x2 & 0x3ffffffffffffff))
-       x12 := (x10 & 0x3ffffffffffffff)
-       x13 := (x11 & 0x3ffffffffffffff)
-       x14 := (uint64(p521Uint1((x11 >> 58))) + (x3 & 0x3ffffffffffffff))
-       x15 := (x4 & 0x3ffffffffffffff)
-       x16 := (x5 & 0x3ffffffffffffff)
-       x17 := (x6 & 0x3ffffffffffffff)
-       x18 := (x7 & 0x3ffffffffffffff)
-       x19 := (x8 & 0x3ffffffffffffff)
-       x20 := (x9 & 0x1ffffffffffffff)
-       out1[0] = x12
-       out1[1] = x13
-       out1[2] = x14
-       out1[3] = x15
-       out1[4] = x16
-       out1[5] = x17
-       out1[6] = x18
-       out1[7] = x19
-       out1[8] = x20
-}
+func p521Add(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p521Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p521Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p521Uint1(x6)))
+       var x9 uint64
+       var x10 uint64
+       x9, x10 = bits.Add64(arg1[4], arg2[4], uint64(p521Uint1(x8)))
+       var x11 uint64
+       var x12 uint64
+       x11, x12 = bits.Add64(arg1[5], arg2[5], uint64(p521Uint1(x10)))
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Add64(arg1[6], arg2[6], uint64(p521Uint1(x12)))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Add64(arg1[7], arg2[7], uint64(p521Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Add64(arg1[8], arg2[8], uint64(p521Uint1(x16)))
+       var x19 uint64
+       var x20 uint64
+       x19, x20 = bits.Sub64(x1, 0xffffffffffffffff, uint64(0x0))
+       var x21 uint64
+       var x22 uint64
+       x21, x22 = bits.Sub64(x3, 0xffffffffffffffff, uint64(p521Uint1(x20)))
+       var x23 uint64
+       var x24 uint64
+       x23, x24 = bits.Sub64(x5, 0xffffffffffffffff, uint64(p521Uint1(x22)))
+       var x25 uint64
+       var x26 uint64
+       x25, x26 = bits.Sub64(x7, 0xffffffffffffffff, uint64(p521Uint1(x24)))
+       var x27 uint64
+       var x28 uint64
+       x27, x28 = bits.Sub64(x9, 0xffffffffffffffff, uint64(p521Uint1(x26)))
+       var x29 uint64
+       var x30 uint64
+       x29, x30 = bits.Sub64(x11, 0xffffffffffffffff, uint64(p521Uint1(x28)))
+       var x31 uint64
+       var x32 uint64
+       x31, x32 = bits.Sub64(x13, 0xffffffffffffffff, uint64(p521Uint1(x30)))
+       var x33 uint64
+       var x34 uint64
+       x33, x34 = bits.Sub64(x15, 0xffffffffffffffff, uint64(p521Uint1(x32)))
+       var x35 uint64
+       var x36 uint64
+       x35, x36 = bits.Sub64(x17, 0x1ff, uint64(p521Uint1(x34)))
+       var x38 uint64
+       _, x38 = bits.Sub64(uint64(p521Uint1(x18)), uint64(0x0), uint64(p521Uint1(x36)))
+       var x39 uint64
+       p521CmovznzU64(&x39, p521Uint1(x38), x19, x1)
+       var x40 uint64
+       p521CmovznzU64(&x40, p521Uint1(x38), x21, x3)
+       var x41 uint64
+       p521CmovznzU64(&x41, p521Uint1(x38), x23, x5)
+       var x42 uint64
+       p521CmovznzU64(&x42, p521Uint1(x38), x25, x7)
+       var x43 uint64
+       p521CmovznzU64(&x43, p521Uint1(x38), x27, x9)
+       var x44 uint64
+       p521CmovznzU64(&x44, p521Uint1(x38), x29, x11)
+       var x45 uint64
+       p521CmovznzU64(&x45, p521Uint1(x38), x31, x13)
+       var x46 uint64
+       p521CmovznzU64(&x46, p521Uint1(x38), x33, x15)
+       var x47 uint64
+       p521CmovznzU64(&x47, p521Uint1(x38), x35, x17)
+       out1[0] = x39
+       out1[1] = x40
+       out1[2] = x41
+       out1[3] = x42
+       out1[4] = x43
+       out1[5] = x44
+       out1[6] = x45
+       out1[7] = x46
+       out1[8] = x47
+}
+
+// p521Sub subtracts two field elements in the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+//   0 โ‰ค eval arg2 < m
+// Postconditions:
+//   eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p521Sub(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0))
+       var x3 uint64
+       var x4 uint64
+       x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p521Uint1(x2)))
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p521Uint1(x4)))
+       var x7 uint64
+       var x8 uint64
+       x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p521Uint1(x6)))
+       var x9 uint64
+       var x10 uint64
+       x9, x10 = bits.Sub64(arg1[4], arg2[4], uint64(p521Uint1(x8)))
+       var x11 uint64
+       var x12 uint64
+       x11, x12 = bits.Sub64(arg1[5], arg2[5], uint64(p521Uint1(x10)))
+       var x13 uint64
+       var x14 uint64
+       x13, x14 = bits.Sub64(arg1[6], arg2[6], uint64(p521Uint1(x12)))
+       var x15 uint64
+       var x16 uint64
+       x15, x16 = bits.Sub64(arg1[7], arg2[7], uint64(p521Uint1(x14)))
+       var x17 uint64
+       var x18 uint64
+       x17, x18 = bits.Sub64(arg1[8], arg2[8], uint64(p521Uint1(x16)))
+       var x19 uint64
+       p521CmovznzU64(&x19, p521Uint1(x18), uint64(0x0), 0xffffffffffffffff)
+       var x20 uint64
+       var x21 uint64
+       x20, x21 = bits.Add64(x1, x19, uint64(0x0))
+       var x22 uint64
+       var x23 uint64
+       x22, x23 = bits.Add64(x3, x19, uint64(p521Uint1(x21)))
+       var x24 uint64
+       var x25 uint64
+       x24, x25 = bits.Add64(x5, x19, uint64(p521Uint1(x23)))
+       var x26 uint64
+       var x27 uint64
+       x26, x27 = bits.Add64(x7, x19, uint64(p521Uint1(x25)))
+       var x28 uint64
+       var x29 uint64
+       x28, x29 = bits.Add64(x9, x19, uint64(p521Uint1(x27)))
+       var x30 uint64
+       var x31 uint64
+       x30, x31 = bits.Add64(x11, x19, uint64(p521Uint1(x29)))
+       var x32 uint64
+       var x33 uint64
+       x32, x33 = bits.Add64(x13, x19, uint64(p521Uint1(x31)))
+       var x34 uint64
+       var x35 uint64
+       x34, x35 = bits.Add64(x15, x19, uint64(p521Uint1(x33)))
+       var x36 uint64
+       x36, _ = bits.Add64(x17, (x19 & 0x1ff), uint64(p521Uint1(x35)))
+       out1[0] = x20
+       out1[1] = x22
+       out1[2] = x24
+       out1[3] = x26
+       out1[4] = x28
+       out1[5] = x30
+       out1[6] = x32
+       out1[7] = x34
+       out1[8] = x36
+}
+
+// p521SetOne returns the field element one in the Montgomery domain.
+//
+// Postconditions:
+//   eval (from_montgomery out1) mod m = 1 mod m
+//   0 โ‰ค eval out1 < m
+//
+func p521SetOne(out1 *p521MontgomeryDomainFieldElement) {
+       out1[0] = 0x80000000000000
+       out1[1] = uint64(0x0)
+       out1[2] = uint64(0x0)
+       out1[3] = uint64(0x0)
+       out1[4] = uint64(0x0)
+       out1[5] = uint64(0x0)
+       out1[6] = uint64(0x0)
+       out1[7] = uint64(0x0)
+       out1[8] = uint64(0x0)
+}
+
+// p521FromMontgomery translates a field element out of the Montgomery domain.
+//
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
+// Postconditions:
+//   eval out1 mod m = (eval arg1 * ((2^64)โปยน mod m)^9) mod m
+//   0 โ‰ค eval out1 < m
+//
+func p521FromMontgomery(out1 *p521NonMontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement) {
+       x1 := arg1[0]
+       var x2 uint64
+       var x3 uint64
+       x3, x2 = bits.Mul64(x1, 0x1ff)
+       var x4 uint64
+       var x5 uint64
+       x5, x4 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x6 uint64
+       var x7 uint64
+       x7, x6 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x8 uint64
+       var x9 uint64
+       x9, x8 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x10 uint64
+       var x11 uint64
+       x11, x10 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x12 uint64
+       var x13 uint64
+       x13, x12 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x14 uint64
+       var x15 uint64
+       x15, x14 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x16 uint64
+       var x17 uint64
+       x17, x16 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x18 uint64
+       var x19 uint64
+       x19, x18 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x20 uint64
+       var x21 uint64
+       x20, x21 = bits.Add64(x19, x16, uint64(0x0))
+       var x22 uint64
+       var x23 uint64
+       x22, x23 = bits.Add64(x17, x14, uint64(p521Uint1(x21)))
+       var x24 uint64
+       var x25 uint64
+       x24, x25 = bits.Add64(x15, x12, uint64(p521Uint1(x23)))
+       var x26 uint64
+       var x27 uint64
+       x26, x27 = bits.Add64(x13, x10, uint64(p521Uint1(x25)))
+       var x28 uint64
+       var x29 uint64
+       x28, x29 = bits.Add64(x11, x8, uint64(p521Uint1(x27)))
+       var x30 uint64
+       var x31 uint64
+       x30, x31 = bits.Add64(x9, x6, uint64(p521Uint1(x29)))
+       var x32 uint64
+       var x33 uint64
+       x32, x33 = bits.Add64(x7, x4, uint64(p521Uint1(x31)))
+       var x34 uint64
+       var x35 uint64
+       x34, x35 = bits.Add64(x5, x2, uint64(p521Uint1(x33)))
+       var x37 uint64
+       _, x37 = bits.Add64(x1, x18, uint64(0x0))
+       var x38 uint64
+       var x39 uint64
+       x38, x39 = bits.Add64(uint64(0x0), x20, uint64(p521Uint1(x37)))
+       var x40 uint64
+       var x41 uint64
+       x40, x41 = bits.Add64(uint64(0x0), x22, uint64(p521Uint1(x39)))
+       var x42 uint64
+       var x43 uint64
+       x42, x43 = bits.Add64(uint64(0x0), x24, uint64(p521Uint1(x41)))
+       var x44 uint64
+       var x45 uint64
+       x44, x45 = bits.Add64(uint64(0x0), x26, uint64(p521Uint1(x43)))
+       var x46 uint64
+       var x47 uint64
+       x46, x47 = bits.Add64(uint64(0x0), x28, uint64(p521Uint1(x45)))
+       var x48 uint64
+       var x49 uint64
+       x48, x49 = bits.Add64(uint64(0x0), x30, uint64(p521Uint1(x47)))
+       var x50 uint64
+       var x51 uint64
+       x50, x51 = bits.Add64(uint64(0x0), x32, uint64(p521Uint1(x49)))
+       var x52 uint64
+       var x53 uint64
+       x52, x53 = bits.Add64(uint64(0x0), x34, uint64(p521Uint1(x51)))
+       var x54 uint64
+       var x55 uint64
+       x54, x55 = bits.Add64(x38, arg1[1], uint64(0x0))
+       var x56 uint64
+       var x57 uint64
+       x56, x57 = bits.Add64(x40, uint64(0x0), uint64(p521Uint1(x55)))
+       var x58 uint64
+       var x59 uint64
+       x58, x59 = bits.Add64(x42, uint64(0x0), uint64(p521Uint1(x57)))
+       var x60 uint64
+       var x61 uint64
+       x60, x61 = bits.Add64(x44, uint64(0x0), uint64(p521Uint1(x59)))
+       var x62 uint64
+       var x63 uint64
+       x62, x63 = bits.Add64(x46, uint64(0x0), uint64(p521Uint1(x61)))
+       var x64 uint64
+       var x65 uint64
+       x64, x65 = bits.Add64(x48, uint64(0x0), uint64(p521Uint1(x63)))
+       var x66 uint64
+       var x67 uint64
+       x66, x67 = bits.Add64(x50, uint64(0x0), uint64(p521Uint1(x65)))
+       var x68 uint64
+       var x69 uint64
+       x68, x69 = bits.Add64(x52, uint64(0x0), uint64(p521Uint1(x67)))
+       var x70 uint64
+       var x71 uint64
+       x71, x70 = bits.Mul64(x54, 0x1ff)
+       var x72 uint64
+       var x73 uint64
+       x73, x72 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x74 uint64
+       var x75 uint64
+       x75, x74 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x76 uint64
+       var x77 uint64
+       x77, x76 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x78 uint64
+       var x79 uint64
+       x79, x78 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x80 uint64
+       var x81 uint64
+       x81, x80 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x82 uint64
+       var x83 uint64
+       x83, x82 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x84 uint64
+       var x85 uint64
+       x85, x84 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x86 uint64
+       var x87 uint64
+       x87, x86 = bits.Mul64(x54, 0xffffffffffffffff)
+       var x88 uint64
+       var x89 uint64
+       x88, x89 = bits.Add64(x87, x84, uint64(0x0))
+       var x90 uint64
+       var x91 uint64
+       x90, x91 = bits.Add64(x85, x82, uint64(p521Uint1(x89)))
+       var x92 uint64
+       var x93 uint64
+       x92, x93 = bits.Add64(x83, x80, uint64(p521Uint1(x91)))
+       var x94 uint64
+       var x95 uint64
+       x94, x95 = bits.Add64(x81, x78, uint64(p521Uint1(x93)))
+       var x96 uint64
+       var x97 uint64
+       x96, x97 = bits.Add64(x79, x76, uint64(p521Uint1(x95)))
+       var x98 uint64
+       var x99 uint64
+       x98, x99 = bits.Add64(x77, x74, uint64(p521Uint1(x97)))
+       var x100 uint64
+       var x101 uint64
+       x100, x101 = bits.Add64(x75, x72, uint64(p521Uint1(x99)))
+       var x102 uint64
+       var x103 uint64
+       x102, x103 = bits.Add64(x73, x70, uint64(p521Uint1(x101)))
+       var x105 uint64
+       _, x105 = bits.Add64(x54, x86, uint64(0x0))
+       var x106 uint64
+       var x107 uint64
+       x106, x107 = bits.Add64(x56, x88, uint64(p521Uint1(x105)))
+       var x108 uint64
+       var x109 uint64
+       x108, x109 = bits.Add64(x58, x90, uint64(p521Uint1(x107)))
+       var x110 uint64
+       var x111 uint64
+       x110, x111 = bits.Add64(x60, x92, uint64(p521Uint1(x109)))
+       var x112 uint64
+       var x113 uint64
+       x112, x113 = bits.Add64(x62, x94, uint64(p521Uint1(x111)))
+       var x114 uint64
+       var x115 uint64
+       x114, x115 = bits.Add64(x64, x96, uint64(p521Uint1(x113)))
+       var x116 uint64
+       var x117 uint64
+       x116, x117 = bits.Add64(x66, x98, uint64(p521Uint1(x115)))
+       var x118 uint64
+       var x119 uint64
+       x118, x119 = bits.Add64(x68, x100, uint64(p521Uint1(x117)))
+       var x120 uint64
+       var x121 uint64
+       x120, x121 = bits.Add64((uint64(p521Uint1(x69)) + (uint64(p521Uint1(x53)) + (uint64(p521Uint1(x35)) + x3))), x102, uint64(p521Uint1(x119)))
+       var x122 uint64
+       var x123 uint64
+       x122, x123 = bits.Add64(x106, arg1[2], uint64(0x0))
+       var x124 uint64
+       var x125 uint64
+       x124, x125 = bits.Add64(x108, uint64(0x0), uint64(p521Uint1(x123)))
+       var x126 uint64
+       var x127 uint64
+       x126, x127 = bits.Add64(x110, uint64(0x0), uint64(p521Uint1(x125)))
+       var x128 uint64
+       var x129 uint64
+       x128, x129 = bits.Add64(x112, uint64(0x0), uint64(p521Uint1(x127)))
+       var x130 uint64
+       var x131 uint64
+       x130, x131 = bits.Add64(x114, uint64(0x0), uint64(p521Uint1(x129)))
+       var x132 uint64
+       var x133 uint64
+       x132, x133 = bits.Add64(x116, uint64(0x0), uint64(p521Uint1(x131)))
+       var x134 uint64
+       var x135 uint64
+       x134, x135 = bits.Add64(x118, uint64(0x0), uint64(p521Uint1(x133)))
+       var x136 uint64
+       var x137 uint64
+       x136, x137 = bits.Add64(x120, uint64(0x0), uint64(p521Uint1(x135)))
+       var x138 uint64
+       var x139 uint64
+       x139, x138 = bits.Mul64(x122, 0x1ff)
+       var x140 uint64
+       var x141 uint64
+       x141, x140 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x142 uint64
+       var x143 uint64
+       x143, x142 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x144 uint64
+       var x145 uint64
+       x145, x144 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x146 uint64
+       var x147 uint64
+       x147, x146 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x148 uint64
+       var x149 uint64
+       x149, x148 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x150 uint64
+       var x151 uint64
+       x151, x150 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x152 uint64
+       var x153 uint64
+       x153, x152 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x154 uint64
+       var x155 uint64
+       x155, x154 = bits.Mul64(x122, 0xffffffffffffffff)
+       var x156 uint64
+       var x157 uint64
+       x156, x157 = bits.Add64(x155, x152, uint64(0x0))
+       var x158 uint64
+       var x159 uint64
+       x158, x159 = bits.Add64(x153, x150, uint64(p521Uint1(x157)))
+       var x160 uint64
+       var x161 uint64
+       x160, x161 = bits.Add64(x151, x148, uint64(p521Uint1(x159)))
+       var x162 uint64
+       var x163 uint64
+       x162, x163 = bits.Add64(x149, x146, uint64(p521Uint1(x161)))
+       var x164 uint64
+       var x165 uint64
+       x164, x165 = bits.Add64(x147, x144, uint64(p521Uint1(x163)))
+       var x166 uint64
+       var x167 uint64
+       x166, x167 = bits.Add64(x145, x142, uint64(p521Uint1(x165)))
+       var x168 uint64
+       var x169 uint64
+       x168, x169 = bits.Add64(x143, x140, uint64(p521Uint1(x167)))
+       var x170 uint64
+       var x171 uint64
+       x170, x171 = bits.Add64(x141, x138, uint64(p521Uint1(x169)))
+       var x173 uint64
+       _, x173 = bits.Add64(x122, x154, uint64(0x0))
+       var x174 uint64
+       var x175 uint64
+       x174, x175 = bits.Add64(x124, x156, uint64(p521Uint1(x173)))
+       var x176 uint64
+       var x177 uint64
+       x176, x177 = bits.Add64(x126, x158, uint64(p521Uint1(x175)))
+       var x178 uint64
+       var x179 uint64
+       x178, x179 = bits.Add64(x128, x160, uint64(p521Uint1(x177)))
+       var x180 uint64
+       var x181 uint64
+       x180, x181 = bits.Add64(x130, x162, uint64(p521Uint1(x179)))
+       var x182 uint64
+       var x183 uint64
+       x182, x183 = bits.Add64(x132, x164, uint64(p521Uint1(x181)))
+       var x184 uint64
+       var x185 uint64
+       x184, x185 = bits.Add64(x134, x166, uint64(p521Uint1(x183)))
+       var x186 uint64
+       var x187 uint64
+       x186, x187 = bits.Add64(x136, x168, uint64(p521Uint1(x185)))
+       var x188 uint64
+       var x189 uint64
+       x188, x189 = bits.Add64((uint64(p521Uint1(x137)) + (uint64(p521Uint1(x121)) + (uint64(p521Uint1(x103)) + x71))), x170, uint64(p521Uint1(x187)))
+       var x190 uint64
+       var x191 uint64
+       x190, x191 = bits.Add64(x174, arg1[3], uint64(0x0))
+       var x192 uint64
+       var x193 uint64
+       x192, x193 = bits.Add64(x176, uint64(0x0), uint64(p521Uint1(x191)))
+       var x194 uint64
+       var x195 uint64
+       x194, x195 = bits.Add64(x178, uint64(0x0), uint64(p521Uint1(x193)))
+       var x196 uint64
+       var x197 uint64
+       x196, x197 = bits.Add64(x180, uint64(0x0), uint64(p521Uint1(x195)))
+       var x198 uint64
+       var x199 uint64
+       x198, x199 = bits.Add64(x182, uint64(0x0), uint64(p521Uint1(x197)))
+       var x200 uint64
+       var x201 uint64
+       x200, x201 = bits.Add64(x184, uint64(0x0), uint64(p521Uint1(x199)))
+       var x202 uint64
+       var x203 uint64
+       x202, x203 = bits.Add64(x186, uint64(0x0), uint64(p521Uint1(x201)))
+       var x204 uint64
+       var x205 uint64
+       x204, x205 = bits.Add64(x188, uint64(0x0), uint64(p521Uint1(x203)))
+       var x206 uint64
+       var x207 uint64
+       x207, x206 = bits.Mul64(x190, 0x1ff)
+       var x208 uint64
+       var x209 uint64
+       x209, x208 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x210 uint64
+       var x211 uint64
+       x211, x210 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x212 uint64
+       var x213 uint64
+       x213, x212 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x214 uint64
+       var x215 uint64
+       x215, x214 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x216 uint64
+       var x217 uint64
+       x217, x216 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x218 uint64
+       var x219 uint64
+       x219, x218 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x220 uint64
+       var x221 uint64
+       x221, x220 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x222 uint64
+       var x223 uint64
+       x223, x222 = bits.Mul64(x190, 0xffffffffffffffff)
+       var x224 uint64
+       var x225 uint64
+       x224, x225 = bits.Add64(x223, x220, uint64(0x0))
+       var x226 uint64
+       var x227 uint64
+       x226, x227 = bits.Add64(x221, x218, uint64(p521Uint1(x225)))
+       var x228 uint64
+       var x229 uint64
+       x228, x229 = bits.Add64(x219, x216, uint64(p521Uint1(x227)))
+       var x230 uint64
+       var x231 uint64
+       x230, x231 = bits.Add64(x217, x214, uint64(p521Uint1(x229)))
+       var x232 uint64
+       var x233 uint64
+       x232, x233 = bits.Add64(x215, x212, uint64(p521Uint1(x231)))
+       var x234 uint64
+       var x235 uint64
+       x234, x235 = bits.Add64(x213, x210, uint64(p521Uint1(x233)))
+       var x236 uint64
+       var x237 uint64
+       x236, x237 = bits.Add64(x211, x208, uint64(p521Uint1(x235)))
+       var x238 uint64
+       var x239 uint64
+       x238, x239 = bits.Add64(x209, x206, uint64(p521Uint1(x237)))
+       var x241 uint64
+       _, x241 = bits.Add64(x190, x222, uint64(0x0))
+       var x242 uint64
+       var x243 uint64
+       x242, x243 = bits.Add64(x192, x224, uint64(p521Uint1(x241)))
+       var x244 uint64
+       var x245 uint64
+       x244, x245 = bits.Add64(x194, x226, uint64(p521Uint1(x243)))
+       var x246 uint64
+       var x247 uint64
+       x246, x247 = bits.Add64(x196, x228, uint64(p521Uint1(x245)))
+       var x248 uint64
+       var x249 uint64
+       x248, x249 = bits.Add64(x198, x230, uint64(p521Uint1(x247)))
+       var x250 uint64
+       var x251 uint64
+       x250, x251 = bits.Add64(x200, x232, uint64(p521Uint1(x249)))
+       var x252 uint64
+       var x253 uint64
+       x252, x253 = bits.Add64(x202, x234, uint64(p521Uint1(x251)))
+       var x254 uint64
+       var x255 uint64
+       x254, x255 = bits.Add64(x204, x236, uint64(p521Uint1(x253)))
+       var x256 uint64
+       var x257 uint64
+       x256, x257 = bits.Add64((uint64(p521Uint1(x205)) + (uint64(p521Uint1(x189)) + (uint64(p521Uint1(x171)) + x139))), x238, uint64(p521Uint1(x255)))
+       var x258 uint64
+       var x259 uint64
+       x258, x259 = bits.Add64(x242, arg1[4], uint64(0x0))
+       var x260 uint64
+       var x261 uint64
+       x260, x261 = bits.Add64(x244, uint64(0x0), uint64(p521Uint1(x259)))
+       var x262 uint64
+       var x263 uint64
+       x262, x263 = bits.Add64(x246, uint64(0x0), uint64(p521Uint1(x261)))
+       var x264 uint64
+       var x265 uint64
+       x264, x265 = bits.Add64(x248, uint64(0x0), uint64(p521Uint1(x263)))
+       var x266 uint64
+       var x267 uint64
+       x266, x267 = bits.Add64(x250, uint64(0x0), uint64(p521Uint1(x265)))
+       var x268 uint64
+       var x269 uint64
+       x268, x269 = bits.Add64(x252, uint64(0x0), uint64(p521Uint1(x267)))
+       var x270 uint64
+       var x271 uint64
+       x270, x271 = bits.Add64(x254, uint64(0x0), uint64(p521Uint1(x269)))
+       var x272 uint64
+       var x273 uint64
+       x272, x273 = bits.Add64(x256, uint64(0x0), uint64(p521Uint1(x271)))
+       var x274 uint64
+       var x275 uint64
+       x275, x274 = bits.Mul64(x258, 0x1ff)
+       var x276 uint64
+       var x277 uint64
+       x277, x276 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x278 uint64
+       var x279 uint64
+       x279, x278 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x280 uint64
+       var x281 uint64
+       x281, x280 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x282 uint64
+       var x283 uint64
+       x283, x282 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x284 uint64
+       var x285 uint64
+       x285, x284 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x286 uint64
+       var x287 uint64
+       x287, x286 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x288 uint64
+       var x289 uint64
+       x289, x288 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x290 uint64
+       var x291 uint64
+       x291, x290 = bits.Mul64(x258, 0xffffffffffffffff)
+       var x292 uint64
+       var x293 uint64
+       x292, x293 = bits.Add64(x291, x288, uint64(0x0))
+       var x294 uint64
+       var x295 uint64
+       x294, x295 = bits.Add64(x289, x286, uint64(p521Uint1(x293)))
+       var x296 uint64
+       var x297 uint64
+       x296, x297 = bits.Add64(x287, x284, uint64(p521Uint1(x295)))
+       var x298 uint64
+       var x299 uint64
+       x298, x299 = bits.Add64(x285, x282, uint64(p521Uint1(x297)))
+       var x300 uint64
+       var x301 uint64
+       x300, x301 = bits.Add64(x283, x280, uint64(p521Uint1(x299)))
+       var x302 uint64
+       var x303 uint64
+       x302, x303 = bits.Add64(x281, x278, uint64(p521Uint1(x301)))
+       var x304 uint64
+       var x305 uint64
+       x304, x305 = bits.Add64(x279, x276, uint64(p521Uint1(x303)))
+       var x306 uint64
+       var x307 uint64
+       x306, x307 = bits.Add64(x277, x274, uint64(p521Uint1(x305)))
+       var x309 uint64
+       _, x309 = bits.Add64(x258, x290, uint64(0x0))
+       var x310 uint64
+       var x311 uint64
+       x310, x311 = bits.Add64(x260, x292, uint64(p521Uint1(x309)))
+       var x312 uint64
+       var x313 uint64
+       x312, x313 = bits.Add64(x262, x294, uint64(p521Uint1(x311)))
+       var x314 uint64
+       var x315 uint64
+       x314, x315 = bits.Add64(x264, x296, uint64(p521Uint1(x313)))
+       var x316 uint64
+       var x317 uint64
+       x316, x317 = bits.Add64(x266, x298, uint64(p521Uint1(x315)))
+       var x318 uint64
+       var x319 uint64
+       x318, x319 = bits.Add64(x268, x300, uint64(p521Uint1(x317)))
+       var x320 uint64
+       var x321 uint64
+       x320, x321 = bits.Add64(x270, x302, uint64(p521Uint1(x319)))
+       var x322 uint64
+       var x323 uint64
+       x322, x323 = bits.Add64(x272, x304, uint64(p521Uint1(x321)))
+       var x324 uint64
+       var x325 uint64
+       x324, x325 = bits.Add64((uint64(p521Uint1(x273)) + (uint64(p521Uint1(x257)) + (uint64(p521Uint1(x239)) + x207))), x306, uint64(p521Uint1(x323)))
+       var x326 uint64
+       var x327 uint64
+       x326, x327 = bits.Add64(x310, arg1[5], uint64(0x0))
+       var x328 uint64
+       var x329 uint64
+       x328, x329 = bits.Add64(x312, uint64(0x0), uint64(p521Uint1(x327)))
+       var x330 uint64
+       var x331 uint64
+       x330, x331 = bits.Add64(x314, uint64(0x0), uint64(p521Uint1(x329)))
+       var x332 uint64
+       var x333 uint64
+       x332, x333 = bits.Add64(x316, uint64(0x0), uint64(p521Uint1(x331)))
+       var x334 uint64
+       var x335 uint64
+       x334, x335 = bits.Add64(x318, uint64(0x0), uint64(p521Uint1(x333)))
+       var x336 uint64
+       var x337 uint64
+       x336, x337 = bits.Add64(x320, uint64(0x0), uint64(p521Uint1(x335)))
+       var x338 uint64
+       var x339 uint64
+       x338, x339 = bits.Add64(x322, uint64(0x0), uint64(p521Uint1(x337)))
+       var x340 uint64
+       var x341 uint64
+       x340, x341 = bits.Add64(x324, uint64(0x0), uint64(p521Uint1(x339)))
+       var x342 uint64
+       var x343 uint64
+       x343, x342 = bits.Mul64(x326, 0x1ff)
+       var x344 uint64
+       var x345 uint64
+       x345, x344 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x346 uint64
+       var x347 uint64
+       x347, x346 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x348 uint64
+       var x349 uint64
+       x349, x348 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x350 uint64
+       var x351 uint64
+       x351, x350 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x352 uint64
+       var x353 uint64
+       x353, x352 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x354 uint64
+       var x355 uint64
+       x355, x354 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x356 uint64
+       var x357 uint64
+       x357, x356 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x358 uint64
+       var x359 uint64
+       x359, x358 = bits.Mul64(x326, 0xffffffffffffffff)
+       var x360 uint64
+       var x361 uint64
+       x360, x361 = bits.Add64(x359, x356, uint64(0x0))
+       var x362 uint64
+       var x363 uint64
+       x362, x363 = bits.Add64(x357, x354, uint64(p521Uint1(x361)))
+       var x364 uint64
+       var x365 uint64
+       x364, x365 = bits.Add64(x355, x352, uint64(p521Uint1(x363)))
+       var x366 uint64
+       var x367 uint64
+       x366, x367 = bits.Add64(x353, x350, uint64(p521Uint1(x365)))
+       var x368 uint64
+       var x369 uint64
+       x368, x369 = bits.Add64(x351, x348, uint64(p521Uint1(x367)))
+       var x370 uint64
+       var x371 uint64
+       x370, x371 = bits.Add64(x349, x346, uint64(p521Uint1(x369)))
+       var x372 uint64
+       var x373 uint64
+       x372, x373 = bits.Add64(x347, x344, uint64(p521Uint1(x371)))
+       var x374 uint64
+       var x375 uint64
+       x374, x375 = bits.Add64(x345, x342, uint64(p521Uint1(x373)))
+       var x377 uint64
+       _, x377 = bits.Add64(x326, x358, uint64(0x0))
+       var x378 uint64
+       var x379 uint64
+       x378, x379 = bits.Add64(x328, x360, uint64(p521Uint1(x377)))
+       var x380 uint64
+       var x381 uint64
+       x380, x381 = bits.Add64(x330, x362, uint64(p521Uint1(x379)))
+       var x382 uint64
+       var x383 uint64
+       x382, x383 = bits.Add64(x332, x364, uint64(p521Uint1(x381)))
+       var x384 uint64
+       var x385 uint64
+       x384, x385 = bits.Add64(x334, x366, uint64(p521Uint1(x383)))
+       var x386 uint64
+       var x387 uint64
+       x386, x387 = bits.Add64(x336, x368, uint64(p521Uint1(x385)))
+       var x388 uint64
+       var x389 uint64
+       x388, x389 = bits.Add64(x338, x370, uint64(p521Uint1(x387)))
+       var x390 uint64
+       var x391 uint64
+       x390, x391 = bits.Add64(x340, x372, uint64(p521Uint1(x389)))
+       var x392 uint64
+       var x393 uint64
+       x392, x393 = bits.Add64((uint64(p521Uint1(x341)) + (uint64(p521Uint1(x325)) + (uint64(p521Uint1(x307)) + x275))), x374, uint64(p521Uint1(x391)))
+       var x394 uint64
+       var x395 uint64
+       x394, x395 = bits.Add64(x378, arg1[6], uint64(0x0))
+       var x396 uint64
+       var x397 uint64
+       x396, x397 = bits.Add64(x380, uint64(0x0), uint64(p521Uint1(x395)))
+       var x398 uint64
+       var x399 uint64
+       x398, x399 = bits.Add64(x382, uint64(0x0), uint64(p521Uint1(x397)))
+       var x400 uint64
+       var x401 uint64
+       x400, x401 = bits.Add64(x384, uint64(0x0), uint64(p521Uint1(x399)))
+       var x402 uint64
+       var x403 uint64
+       x402, x403 = bits.Add64(x386, uint64(0x0), uint64(p521Uint1(x401)))
+       var x404 uint64
+       var x405 uint64
+       x404, x405 = bits.Add64(x388, uint64(0x0), uint64(p521Uint1(x403)))
+       var x406 uint64
+       var x407 uint64
+       x406, x407 = bits.Add64(x390, uint64(0x0), uint64(p521Uint1(x405)))
+       var x408 uint64
+       var x409 uint64
+       x408, x409 = bits.Add64(x392, uint64(0x0), uint64(p521Uint1(x407)))
+       var x410 uint64
+       var x411 uint64
+       x411, x410 = bits.Mul64(x394, 0x1ff)
+       var x412 uint64
+       var x413 uint64
+       x413, x412 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x414 uint64
+       var x415 uint64
+       x415, x414 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x416 uint64
+       var x417 uint64
+       x417, x416 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x418 uint64
+       var x419 uint64
+       x419, x418 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x420 uint64
+       var x421 uint64
+       x421, x420 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x422 uint64
+       var x423 uint64
+       x423, x422 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x424 uint64
+       var x425 uint64
+       x425, x424 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x426 uint64
+       var x427 uint64
+       x427, x426 = bits.Mul64(x394, 0xffffffffffffffff)
+       var x428 uint64
+       var x429 uint64
+       x428, x429 = bits.Add64(x427, x424, uint64(0x0))
+       var x430 uint64
+       var x431 uint64
+       x430, x431 = bits.Add64(x425, x422, uint64(p521Uint1(x429)))
+       var x432 uint64
+       var x433 uint64
+       x432, x433 = bits.Add64(x423, x420, uint64(p521Uint1(x431)))
+       var x434 uint64
+       var x435 uint64
+       x434, x435 = bits.Add64(x421, x418, uint64(p521Uint1(x433)))
+       var x436 uint64
+       var x437 uint64
+       x436, x437 = bits.Add64(x419, x416, uint64(p521Uint1(x435)))
+       var x438 uint64
+       var x439 uint64
+       x438, x439 = bits.Add64(x417, x414, uint64(p521Uint1(x437)))
+       var x440 uint64
+       var x441 uint64
+       x440, x441 = bits.Add64(x415, x412, uint64(p521Uint1(x439)))
+       var x442 uint64
+       var x443 uint64
+       x442, x443 = bits.Add64(x413, x410, uint64(p521Uint1(x441)))
+       var x445 uint64
+       _, x445 = bits.Add64(x394, x426, uint64(0x0))
+       var x446 uint64
+       var x447 uint64
+       x446, x447 = bits.Add64(x396, x428, uint64(p521Uint1(x445)))
+       var x448 uint64
+       var x449 uint64
+       x448, x449 = bits.Add64(x398, x430, uint64(p521Uint1(x447)))
+       var x450 uint64
+       var x451 uint64
+       x450, x451 = bits.Add64(x400, x432, uint64(p521Uint1(x449)))
+       var x452 uint64
+       var x453 uint64
+       x452, x453 = bits.Add64(x402, x434, uint64(p521Uint1(x451)))
+       var x454 uint64
+       var x455 uint64
+       x454, x455 = bits.Add64(x404, x436, uint64(p521Uint1(x453)))
+       var x456 uint64
+       var x457 uint64
+       x456, x457 = bits.Add64(x406, x438, uint64(p521Uint1(x455)))
+       var x458 uint64
+       var x459 uint64
+       x458, x459 = bits.Add64(x408, x440, uint64(p521Uint1(x457)))
+       var x460 uint64
+       var x461 uint64
+       x460, x461 = bits.Add64((uint64(p521Uint1(x409)) + (uint64(p521Uint1(x393)) + (uint64(p521Uint1(x375)) + x343))), x442, uint64(p521Uint1(x459)))
+       var x462 uint64
+       var x463 uint64
+       x462, x463 = bits.Add64(x446, arg1[7], uint64(0x0))
+       var x464 uint64
+       var x465 uint64
+       x464, x465 = bits.Add64(x448, uint64(0x0), uint64(p521Uint1(x463)))
+       var x466 uint64
+       var x467 uint64
+       x466, x467 = bits.Add64(x450, uint64(0x0), uint64(p521Uint1(x465)))
+       var x468 uint64
+       var x469 uint64
+       x468, x469 = bits.Add64(x452, uint64(0x0), uint64(p521Uint1(x467)))
+       var x470 uint64
+       var x471 uint64
+       x470, x471 = bits.Add64(x454, uint64(0x0), uint64(p521Uint1(x469)))
+       var x472 uint64
+       var x473 uint64
+       x472, x473 = bits.Add64(x456, uint64(0x0), uint64(p521Uint1(x471)))
+       var x474 uint64
+       var x475 uint64
+       x474, x475 = bits.Add64(x458, uint64(0x0), uint64(p521Uint1(x473)))
+       var x476 uint64
+       var x477 uint64
+       x476, x477 = bits.Add64(x460, uint64(0x0), uint64(p521Uint1(x475)))
+       var x478 uint64
+       var x479 uint64
+       x479, x478 = bits.Mul64(x462, 0x1ff)
+       var x480 uint64
+       var x481 uint64
+       x481, x480 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x482 uint64
+       var x483 uint64
+       x483, x482 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x484 uint64
+       var x485 uint64
+       x485, x484 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x486 uint64
+       var x487 uint64
+       x487, x486 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x488 uint64
+       var x489 uint64
+       x489, x488 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x490 uint64
+       var x491 uint64
+       x491, x490 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x492 uint64
+       var x493 uint64
+       x493, x492 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x494 uint64
+       var x495 uint64
+       x495, x494 = bits.Mul64(x462, 0xffffffffffffffff)
+       var x496 uint64
+       var x497 uint64
+       x496, x497 = bits.Add64(x495, x492, uint64(0x0))
+       var x498 uint64
+       var x499 uint64
+       x498, x499 = bits.Add64(x493, x490, uint64(p521Uint1(x497)))
+       var x500 uint64
+       var x501 uint64
+       x500, x501 = bits.Add64(x491, x488, uint64(p521Uint1(x499)))
+       var x502 uint64
+       var x503 uint64
+       x502, x503 = bits.Add64(x489, x486, uint64(p521Uint1(x501)))
+       var x504 uint64
+       var x505 uint64
+       x504, x505 = bits.Add64(x487, x484, uint64(p521Uint1(x503)))
+       var x506 uint64
+       var x507 uint64
+       x506, x507 = bits.Add64(x485, x482, uint64(p521Uint1(x505)))
+       var x508 uint64
+       var x509 uint64
+       x508, x509 = bits.Add64(x483, x480, uint64(p521Uint1(x507)))
+       var x510 uint64
+       var x511 uint64
+       x510, x511 = bits.Add64(x481, x478, uint64(p521Uint1(x509)))
+       var x513 uint64
+       _, x513 = bits.Add64(x462, x494, uint64(0x0))
+       var x514 uint64
+       var x515 uint64
+       x514, x515 = bits.Add64(x464, x496, uint64(p521Uint1(x513)))
+       var x516 uint64
+       var x517 uint64
+       x516, x517 = bits.Add64(x466, x498, uint64(p521Uint1(x515)))
+       var x518 uint64
+       var x519 uint64
+       x518, x519 = bits.Add64(x468, x500, uint64(p521Uint1(x517)))
+       var x520 uint64
+       var x521 uint64
+       x520, x521 = bits.Add64(x470, x502, uint64(p521Uint1(x519)))
+       var x522 uint64
+       var x523 uint64
+       x522, x523 = bits.Add64(x472, x504, uint64(p521Uint1(x521)))
+       var x524 uint64
+       var x525 uint64
+       x524, x525 = bits.Add64(x474, x506, uint64(p521Uint1(x523)))
+       var x526 uint64
+       var x527 uint64
+       x526, x527 = bits.Add64(x476, x508, uint64(p521Uint1(x525)))
+       var x528 uint64
+       var x529 uint64
+       x528, x529 = bits.Add64((uint64(p521Uint1(x477)) + (uint64(p521Uint1(x461)) + (uint64(p521Uint1(x443)) + x411))), x510, uint64(p521Uint1(x527)))
+       var x530 uint64
+       var x531 uint64
+       x530, x531 = bits.Add64(x514, arg1[8], uint64(0x0))
+       var x532 uint64
+       var x533 uint64
+       x532, x533 = bits.Add64(x516, uint64(0x0), uint64(p521Uint1(x531)))
+       var x534 uint64
+       var x535 uint64
+       x534, x535 = bits.Add64(x518, uint64(0x0), uint64(p521Uint1(x533)))
+       var x536 uint64
+       var x537 uint64
+       x536, x537 = bits.Add64(x520, uint64(0x0), uint64(p521Uint1(x535)))
+       var x538 uint64
+       var x539 uint64
+       x538, x539 = bits.Add64(x522, uint64(0x0), uint64(p521Uint1(x537)))
+       var x540 uint64
+       var x541 uint64
+       x540, x541 = bits.Add64(x524, uint64(0x0), uint64(p521Uint1(x539)))
+       var x542 uint64
+       var x543 uint64
+       x542, x543 = bits.Add64(x526, uint64(0x0), uint64(p521Uint1(x541)))
+       var x544 uint64
+       var x545 uint64
+       x544, x545 = bits.Add64(x528, uint64(0x0), uint64(p521Uint1(x543)))
+       var x546 uint64
+       var x547 uint64
+       x547, x546 = bits.Mul64(x530, 0x1ff)
+       var x548 uint64
+       var x549 uint64
+       x549, x548 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x550 uint64
+       var x551 uint64
+       x551, x550 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x552 uint64
+       var x553 uint64
+       x553, x552 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x554 uint64
+       var x555 uint64
+       x555, x554 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x556 uint64
+       var x557 uint64
+       x557, x556 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x558 uint64
+       var x559 uint64
+       x559, x558 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x560 uint64
+       var x561 uint64
+       x561, x560 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x562 uint64
+       var x563 uint64
+       x563, x562 = bits.Mul64(x530, 0xffffffffffffffff)
+       var x564 uint64
+       var x565 uint64
+       x564, x565 = bits.Add64(x563, x560, uint64(0x0))
+       var x566 uint64
+       var x567 uint64
+       x566, x567 = bits.Add64(x561, x558, uint64(p521Uint1(x565)))
+       var x568 uint64
+       var x569 uint64
+       x568, x569 = bits.Add64(x559, x556, uint64(p521Uint1(x567)))
+       var x570 uint64
+       var x571 uint64
+       x570, x571 = bits.Add64(x557, x554, uint64(p521Uint1(x569)))
+       var x572 uint64
+       var x573 uint64
+       x572, x573 = bits.Add64(x555, x552, uint64(p521Uint1(x571)))
+       var x574 uint64
+       var x575 uint64
+       x574, x575 = bits.Add64(x553, x550, uint64(p521Uint1(x573)))
+       var x576 uint64
+       var x577 uint64
+       x576, x577 = bits.Add64(x551, x548, uint64(p521Uint1(x575)))
+       var x578 uint64
+       var x579 uint64
+       x578, x579 = bits.Add64(x549, x546, uint64(p521Uint1(x577)))
+       var x581 uint64
+       _, x581 = bits.Add64(x530, x562, uint64(0x0))
+       var x582 uint64
+       var x583 uint64
+       x582, x583 = bits.Add64(x532, x564, uint64(p521Uint1(x581)))
+       var x584 uint64
+       var x585 uint64
+       x584, x585 = bits.Add64(x534, x566, uint64(p521Uint1(x583)))
+       var x586 uint64
+       var x587 uint64
+       x586, x587 = bits.Add64(x536, x568, uint64(p521Uint1(x585)))
+       var x588 uint64
+       var x589 uint64
+       x588, x589 = bits.Add64(x538, x570, uint64(p521Uint1(x587)))
+       var x590 uint64
+       var x591 uint64
+       x590, x591 = bits.Add64(x540, x572, uint64(p521Uint1(x589)))
+       var x592 uint64
+       var x593 uint64
+       x592, x593 = bits.Add64(x542, x574, uint64(p521Uint1(x591)))
+       var x594 uint64
+       var x595 uint64
+       x594, x595 = bits.Add64(x544, x576, uint64(p521Uint1(x593)))
+       var x596 uint64
+       var x597 uint64
+       x596, x597 = bits.Add64((uint64(p521Uint1(x545)) + (uint64(p521Uint1(x529)) + (uint64(p521Uint1(x511)) + x479))), x578, uint64(p521Uint1(x595)))
+       x598 := (uint64(p521Uint1(x597)) + (uint64(p521Uint1(x579)) + x547))
+       var x599 uint64
+       var x600 uint64
+       x599, x600 = bits.Sub64(x582, 0xffffffffffffffff, uint64(0x0))
+       var x601 uint64
+       var x602 uint64
+       x601, x602 = bits.Sub64(x584, 0xffffffffffffffff, uint64(p521Uint1(x600)))
+       var x603 uint64
+       var x604 uint64
+       x603, x604 = bits.Sub64(x586, 0xffffffffffffffff, uint64(p521Uint1(x602)))
+       var x605 uint64
+       var x606 uint64
+       x605, x606 = bits.Sub64(x588, 0xffffffffffffffff, uint64(p521Uint1(x604)))
+       var x607 uint64
+       var x608 uint64
+       x607, x608 = bits.Sub64(x590, 0xffffffffffffffff, uint64(p521Uint1(x606)))
+       var x609 uint64
+       var x610 uint64
+       x609, x610 = bits.Sub64(x592, 0xffffffffffffffff, uint64(p521Uint1(x608)))
+       var x611 uint64
+       var x612 uint64
+       x611, x612 = bits.Sub64(x594, 0xffffffffffffffff, uint64(p521Uint1(x610)))
+       var x613 uint64
+       var x614 uint64
+       x613, x614 = bits.Sub64(x596, 0xffffffffffffffff, uint64(p521Uint1(x612)))
+       var x615 uint64
+       var x616 uint64
+       x615, x616 = bits.Sub64(x598, 0x1ff, uint64(p521Uint1(x614)))
+       var x618 uint64
+       _, x618 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p521Uint1(x616)))
+       var x619 uint64
+       p521CmovznzU64(&x619, p521Uint1(x618), x599, x582)
+       var x620 uint64
+       p521CmovznzU64(&x620, p521Uint1(x618), x601, x584)
+       var x621 uint64
+       p521CmovznzU64(&x621, p521Uint1(x618), x603, x586)
+       var x622 uint64
+       p521CmovznzU64(&x622, p521Uint1(x618), x605, x588)
+       var x623 uint64
+       p521CmovznzU64(&x623, p521Uint1(x618), x607, x590)
+       var x624 uint64
+       p521CmovznzU64(&x624, p521Uint1(x618), x609, x592)
+       var x625 uint64
+       p521CmovznzU64(&x625, p521Uint1(x618), x611, x594)
+       var x626 uint64
+       p521CmovznzU64(&x626, p521Uint1(x618), x613, x596)
+       var x627 uint64
+       p521CmovznzU64(&x627, p521Uint1(x618), x615, x598)
+       out1[0] = x619
+       out1[1] = x620
+       out1[2] = x621
+       out1[3] = x622
+       out1[4] = x623
+       out1[5] = x624
+       out1[6] = x625
+       out1[7] = x626
+       out1[8] = x627
+}
 
-// p521Add adds two field elements.
+// p521ToMontgomery translates a field element into the Montgomery domain.
 //
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
 // Postconditions:
-//   eval out1 mod m = (eval arg1 + eval arg2) mod m
+//   eval (from_montgomery out1) mod m = eval arg1 mod m
+//   0 โ‰ค eval out1 < m
 //
-// Input Bounds:
-//   arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-//   arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-// Output Bounds:
-//   out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-func p521Add(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
-       x1 := (arg1[0] + arg2[0])
-       x2 := (arg1[1] + arg2[1])
-       x3 := (arg1[2] + arg2[2])
-       x4 := (arg1[3] + arg2[3])
-       x5 := (arg1[4] + arg2[4])
-       x6 := (arg1[5] + arg2[5])
-       x7 := (arg1[6] + arg2[6])
-       x8 := (arg1[7] + arg2[7])
-       x9 := (arg1[8] + arg2[8])
-       out1[0] = x1
-       out1[1] = x2
-       out1[2] = x3
-       out1[3] = x4
-       out1[4] = x5
-       out1[5] = x6
-       out1[6] = x7
-       out1[7] = x8
-       out1[8] = x9
+func p521ToMontgomery(out1 *p521MontgomeryDomainFieldElement, arg1 *p521NonMontgomeryDomainFieldElement) {
+       var x1 uint64
+       var x2 uint64
+       x2, x1 = bits.Mul64(arg1[0], 0x400000000000)
+       var x3 uint64
+       var x4 uint64
+       x4, x3 = bits.Mul64(arg1[1], 0x400000000000)
+       var x5 uint64
+       var x6 uint64
+       x5, x6 = bits.Add64(x2, x3, uint64(0x0))
+       var x7 uint64
+       var x8 uint64
+       x8, x7 = bits.Mul64(x1, 0x1ff)
+       var x9 uint64
+       var x10 uint64
+       x10, x9 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x11 uint64
+       var x12 uint64
+       x12, x11 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x13 uint64
+       var x14 uint64
+       x14, x13 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x15 uint64
+       var x16 uint64
+       x16, x15 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x17 uint64
+       var x18 uint64
+       x18, x17 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x19 uint64
+       var x20 uint64
+       x20, x19 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x21 uint64
+       var x22 uint64
+       x22, x21 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x23 uint64
+       var x24 uint64
+       x24, x23 = bits.Mul64(x1, 0xffffffffffffffff)
+       var x25 uint64
+       var x26 uint64
+       x25, x26 = bits.Add64(x24, x21, uint64(0x0))
+       var x27 uint64
+       var x28 uint64
+       x27, x28 = bits.Add64(x22, x19, uint64(p521Uint1(x26)))
+       var x29 uint64
+       var x30 uint64
+       x29, x30 = bits.Add64(x20, x17, uint64(p521Uint1(x28)))
+       var x31 uint64
+       var x32 uint64
+       x31, x32 = bits.Add64(x18, x15, uint64(p521Uint1(x30)))
+       var x33 uint64
+       var x34 uint64
+       x33, x34 = bits.Add64(x16, x13, uint64(p521Uint1(x32)))
+       var x35 uint64
+       var x36 uint64
+       x35, x36 = bits.Add64(x14, x11, uint64(p521Uint1(x34)))
+       var x37 uint64
+       var x38 uint64
+       x37, x38 = bits.Add64(x12, x9, uint64(p521Uint1(x36)))
+       var x39 uint64
+       var x40 uint64
+       x39, x40 = bits.Add64(x10, x7, uint64(p521Uint1(x38)))
+       var x42 uint64
+       _, x42 = bits.Add64(x1, x23, uint64(0x0))
+       var x43 uint64
+       var x44 uint64
+       x43, x44 = bits.Add64(x5, x25, uint64(p521Uint1(x42)))
+       var x45 uint64
+       var x46 uint64
+       x45, x46 = bits.Add64((uint64(p521Uint1(x6)) + x4), x27, uint64(p521Uint1(x44)))
+       var x47 uint64
+       var x48 uint64
+       x47, x48 = bits.Add64(uint64(0x0), x29, uint64(p521Uint1(x46)))
+       var x49 uint64
+       var x50 uint64
+       x49, x50 = bits.Add64(uint64(0x0), x31, uint64(p521Uint1(x48)))
+       var x51 uint64
+       var x52 uint64
+       x51, x52 = bits.Add64(uint64(0x0), x33, uint64(p521Uint1(x50)))
+       var x53 uint64
+       var x54 uint64
+       x53, x54 = bits.Add64(uint64(0x0), x35, uint64(p521Uint1(x52)))
+       var x55 uint64
+       var x56 uint64
+       x55, x56 = bits.Add64(uint64(0x0), x37, uint64(p521Uint1(x54)))
+       var x57 uint64
+       var x58 uint64
+       x57, x58 = bits.Add64(uint64(0x0), x39, uint64(p521Uint1(x56)))
+       var x59 uint64
+       var x60 uint64
+       x60, x59 = bits.Mul64(arg1[2], 0x400000000000)
+       var x61 uint64
+       var x62 uint64
+       x61, x62 = bits.Add64(x45, x59, uint64(0x0))
+       var x63 uint64
+       var x64 uint64
+       x63, x64 = bits.Add64(x47, x60, uint64(p521Uint1(x62)))
+       var x65 uint64
+       var x66 uint64
+       x65, x66 = bits.Add64(x49, uint64(0x0), uint64(p521Uint1(x64)))
+       var x67 uint64
+       var x68 uint64
+       x67, x68 = bits.Add64(x51, uint64(0x0), uint64(p521Uint1(x66)))
+       var x69 uint64
+       var x70 uint64
+       x69, x70 = bits.Add64(x53, uint64(0x0), uint64(p521Uint1(x68)))
+       var x71 uint64
+       var x72 uint64
+       x71, x72 = bits.Add64(x55, uint64(0x0), uint64(p521Uint1(x70)))
+       var x73 uint64
+       var x74 uint64
+       x73, x74 = bits.Add64(x57, uint64(0x0), uint64(p521Uint1(x72)))
+       var x75 uint64
+       var x76 uint64
+       x76, x75 = bits.Mul64(x43, 0x1ff)
+       var x77 uint64
+       var x78 uint64
+       x78, x77 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x79 uint64
+       var x80 uint64
+       x80, x79 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x81 uint64
+       var x82 uint64
+       x82, x81 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x83 uint64
+       var x84 uint64
+       x84, x83 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x85 uint64
+       var x86 uint64
+       x86, x85 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x87 uint64
+       var x88 uint64
+       x88, x87 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x89 uint64
+       var x90 uint64
+       x90, x89 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x91 uint64
+       var x92 uint64
+       x92, x91 = bits.Mul64(x43, 0xffffffffffffffff)
+       var x93 uint64
+       var x94 uint64
+       x93, x94 = bits.Add64(x92, x89, uint64(0x0))
+       var x95 uint64
+       var x96 uint64
+       x95, x96 = bits.Add64(x90, x87, uint64(p521Uint1(x94)))
+       var x97 uint64
+       var x98 uint64
+       x97, x98 = bits.Add64(x88, x85, uint64(p521Uint1(x96)))
+       var x99 uint64
+       var x100 uint64
+       x99, x100 = bits.Add64(x86, x83, uint64(p521Uint1(x98)))
+       var x101 uint64
+       var x102 uint64
+       x101, x102 = bits.Add64(x84, x81, uint64(p521Uint1(x100)))
+       var x103 uint64
+       var x104 uint64
+       x103, x104 = bits.Add64(x82, x79, uint64(p521Uint1(x102)))
+       var x105 uint64
+       var x106 uint64
+       x105, x106 = bits.Add64(x80, x77, uint64(p521Uint1(x104)))
+       var x107 uint64
+       var x108 uint64
+       x107, x108 = bits.Add64(x78, x75, uint64(p521Uint1(x106)))
+       var x110 uint64
+       _, x110 = bits.Add64(x43, x91, uint64(0x0))
+       var x111 uint64
+       var x112 uint64
+       x111, x112 = bits.Add64(x61, x93, uint64(p521Uint1(x110)))
+       var x113 uint64
+       var x114 uint64
+       x113, x114 = bits.Add64(x63, x95, uint64(p521Uint1(x112)))
+       var x115 uint64
+       var x116 uint64
+       x115, x116 = bits.Add64(x65, x97, uint64(p521Uint1(x114)))
+       var x117 uint64
+       var x118 uint64
+       x117, x118 = bits.Add64(x67, x99, uint64(p521Uint1(x116)))
+       var x119 uint64
+       var x120 uint64
+       x119, x120 = bits.Add64(x69, x101, uint64(p521Uint1(x118)))
+       var x121 uint64
+       var x122 uint64
+       x121, x122 = bits.Add64(x71, x103, uint64(p521Uint1(x120)))
+       var x123 uint64
+       var x124 uint64
+       x123, x124 = bits.Add64(x73, x105, uint64(p521Uint1(x122)))
+       var x125 uint64
+       var x126 uint64
+       x125, x126 = bits.Add64((uint64(p521Uint1(x74)) + (uint64(p521Uint1(x58)) + (uint64(p521Uint1(x40)) + x8))), x107, uint64(p521Uint1(x124)))
+       var x127 uint64
+       var x128 uint64
+       x128, x127 = bits.Mul64(arg1[3], 0x400000000000)
+       var x129 uint64
+       var x130 uint64
+       x129, x130 = bits.Add64(x113, x127, uint64(0x0))
+       var x131 uint64
+       var x132 uint64
+       x131, x132 = bits.Add64(x115, x128, uint64(p521Uint1(x130)))
+       var x133 uint64
+       var x134 uint64
+       x133, x134 = bits.Add64(x117, uint64(0x0), uint64(p521Uint1(x132)))
+       var x135 uint64
+       var x136 uint64
+       x135, x136 = bits.Add64(x119, uint64(0x0), uint64(p521Uint1(x134)))
+       var x137 uint64
+       var x138 uint64
+       x137, x138 = bits.Add64(x121, uint64(0x0), uint64(p521Uint1(x136)))
+       var x139 uint64
+       var x140 uint64
+       x139, x140 = bits.Add64(x123, uint64(0x0), uint64(p521Uint1(x138)))
+       var x141 uint64
+       var x142 uint64
+       x141, x142 = bits.Add64(x125, uint64(0x0), uint64(p521Uint1(x140)))
+       var x143 uint64
+       var x144 uint64
+       x144, x143 = bits.Mul64(x111, 0x1ff)
+       var x145 uint64
+       var x146 uint64
+       x146, x145 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x147 uint64
+       var x148 uint64
+       x148, x147 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x149 uint64
+       var x150 uint64
+       x150, x149 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x151 uint64
+       var x152 uint64
+       x152, x151 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x153 uint64
+       var x154 uint64
+       x154, x153 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x155 uint64
+       var x156 uint64
+       x156, x155 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x157 uint64
+       var x158 uint64
+       x158, x157 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x159 uint64
+       var x160 uint64
+       x160, x159 = bits.Mul64(x111, 0xffffffffffffffff)
+       var x161 uint64
+       var x162 uint64
+       x161, x162 = bits.Add64(x160, x157, uint64(0x0))
+       var x163 uint64
+       var x164 uint64
+       x163, x164 = bits.Add64(x158, x155, uint64(p521Uint1(x162)))
+       var x165 uint64
+       var x166 uint64
+       x165, x166 = bits.Add64(x156, x153, uint64(p521Uint1(x164)))
+       var x167 uint64
+       var x168 uint64
+       x167, x168 = bits.Add64(x154, x151, uint64(p521Uint1(x166)))
+       var x169 uint64
+       var x170 uint64
+       x169, x170 = bits.Add64(x152, x149, uint64(p521Uint1(x168)))
+       var x171 uint64
+       var x172 uint64
+       x171, x172 = bits.Add64(x150, x147, uint64(p521Uint1(x170)))
+       var x173 uint64
+       var x174 uint64
+       x173, x174 = bits.Add64(x148, x145, uint64(p521Uint1(x172)))
+       var x175 uint64
+       var x176 uint64
+       x175, x176 = bits.Add64(x146, x143, uint64(p521Uint1(x174)))
+       var x178 uint64
+       _, x178 = bits.Add64(x111, x159, uint64(0x0))
+       var x179 uint64
+       var x180 uint64
+       x179, x180 = bits.Add64(x129, x161, uint64(p521Uint1(x178)))
+       var x181 uint64
+       var x182 uint64
+       x181, x182 = bits.Add64(x131, x163, uint64(p521Uint1(x180)))
+       var x183 uint64
+       var x184 uint64
+       x183, x184 = bits.Add64(x133, x165, uint64(p521Uint1(x182)))
+       var x185 uint64
+       var x186 uint64
+       x185, x186 = bits.Add64(x135, x167, uint64(p521Uint1(x184)))
+       var x187 uint64
+       var x188 uint64
+       x187, x188 = bits.Add64(x137, x169, uint64(p521Uint1(x186)))
+       var x189 uint64
+       var x190 uint64
+       x189, x190 = bits.Add64(x139, x171, uint64(p521Uint1(x188)))
+       var x191 uint64
+       var x192 uint64
+       x191, x192 = bits.Add64(x141, x173, uint64(p521Uint1(x190)))
+       var x193 uint64
+       var x194 uint64
+       x193, x194 = bits.Add64((uint64(p521Uint1(x142)) + (uint64(p521Uint1(x126)) + (uint64(p521Uint1(x108)) + x76))), x175, uint64(p521Uint1(x192)))
+       var x195 uint64
+       var x196 uint64
+       x196, x195 = bits.Mul64(arg1[4], 0x400000000000)
+       var x197 uint64
+       var x198 uint64
+       x197, x198 = bits.Add64(x181, x195, uint64(0x0))
+       var x199 uint64
+       var x200 uint64
+       x199, x200 = bits.Add64(x183, x196, uint64(p521Uint1(x198)))
+       var x201 uint64
+       var x202 uint64
+       x201, x202 = bits.Add64(x185, uint64(0x0), uint64(p521Uint1(x200)))
+       var x203 uint64
+       var x204 uint64
+       x203, x204 = bits.Add64(x187, uint64(0x0), uint64(p521Uint1(x202)))
+       var x205 uint64
+       var x206 uint64
+       x205, x206 = bits.Add64(x189, uint64(0x0), uint64(p521Uint1(x204)))
+       var x207 uint64
+       var x208 uint64
+       x207, x208 = bits.Add64(x191, uint64(0x0), uint64(p521Uint1(x206)))
+       var x209 uint64
+       var x210 uint64
+       x209, x210 = bits.Add64(x193, uint64(0x0), uint64(p521Uint1(x208)))
+       var x211 uint64
+       var x212 uint64
+       x212, x211 = bits.Mul64(x179, 0x1ff)
+       var x213 uint64
+       var x214 uint64
+       x214, x213 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x215 uint64
+       var x216 uint64
+       x216, x215 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x217 uint64
+       var x218 uint64
+       x218, x217 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x219 uint64
+       var x220 uint64
+       x220, x219 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x221 uint64
+       var x222 uint64
+       x222, x221 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x223 uint64
+       var x224 uint64
+       x224, x223 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x225 uint64
+       var x226 uint64
+       x226, x225 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x227 uint64
+       var x228 uint64
+       x228, x227 = bits.Mul64(x179, 0xffffffffffffffff)
+       var x229 uint64
+       var x230 uint64
+       x229, x230 = bits.Add64(x228, x225, uint64(0x0))
+       var x231 uint64
+       var x232 uint64
+       x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230)))
+       var x233 uint64
+       var x234 uint64
+       x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232)))
+       var x235 uint64
+       var x236 uint64
+       x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234)))
+       var x237 uint64
+       var x238 uint64
+       x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236)))
+       var x239 uint64
+       var x240 uint64
+       x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238)))
+       var x241 uint64
+       var x242 uint64
+       x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240)))
+       var x243 uint64
+       var x244 uint64
+       x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242)))
+       var x246 uint64
+       _, x246 = bits.Add64(x179, x227, uint64(0x0))
+       var x247 uint64
+       var x248 uint64
+       x247, x248 = bits.Add64(x197, x229, uint64(p521Uint1(x246)))
+       var x249 uint64
+       var x250 uint64
+       x249, x250 = bits.Add64(x199, x231, uint64(p521Uint1(x248)))
+       var x251 uint64
+       var x252 uint64
+       x251, x252 = bits.Add64(x201, x233, uint64(p521Uint1(x250)))
+       var x253 uint64
+       var x254 uint64
+       x253, x254 = bits.Add64(x203, x235, uint64(p521Uint1(x252)))
+       var x255 uint64
+       var x256 uint64
+       x255, x256 = bits.Add64(x205, x237, uint64(p521Uint1(x254)))
+       var x257 uint64
+       var x258 uint64
+       x257, x258 = bits.Add64(x207, x239, uint64(p521Uint1(x256)))
+       var x259 uint64
+       var x260 uint64
+       x259, x260 = bits.Add64(x209, x241, uint64(p521Uint1(x258)))
+       var x261 uint64
+       var x262 uint64
+       x261, x262 = bits.Add64((uint64(p521Uint1(x210)) + (uint64(p521Uint1(x194)) + (uint64(p521Uint1(x176)) + x144))), x243, uint64(p521Uint1(x260)))
+       var x263 uint64
+       var x264 uint64
+       x264, x263 = bits.Mul64(arg1[5], 0x400000000000)
+       var x265 uint64
+       var x266 uint64
+       x265, x266 = bits.Add64(x249, x263, uint64(0x0))
+       var x267 uint64
+       var x268 uint64
+       x267, x268 = bits.Add64(x251, x264, uint64(p521Uint1(x266)))
+       var x269 uint64
+       var x270 uint64
+       x269, x270 = bits.Add64(x253, uint64(0x0), uint64(p521Uint1(x268)))
+       var x271 uint64
+       var x272 uint64
+       x271, x272 = bits.Add64(x255, uint64(0x0), uint64(p521Uint1(x270)))
+       var x273 uint64
+       var x274 uint64
+       x273, x274 = bits.Add64(x257, uint64(0x0), uint64(p521Uint1(x272)))
+       var x275 uint64
+       var x276 uint64
+       x275, x276 = bits.Add64(x259, uint64(0x0), uint64(p521Uint1(x274)))
+       var x277 uint64
+       var x278 uint64
+       x277, x278 = bits.Add64(x261, uint64(0x0), uint64(p521Uint1(x276)))
+       var x279 uint64
+       var x280 uint64
+       x280, x279 = bits.Mul64(x247, 0x1ff)
+       var x281 uint64
+       var x282 uint64
+       x282, x281 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x283 uint64
+       var x284 uint64
+       x284, x283 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x285 uint64
+       var x286 uint64
+       x286, x285 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x287 uint64
+       var x288 uint64
+       x288, x287 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x289 uint64
+       var x290 uint64
+       x290, x289 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x291 uint64
+       var x292 uint64
+       x292, x291 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x293 uint64
+       var x294 uint64
+       x294, x293 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x295 uint64
+       var x296 uint64
+       x296, x295 = bits.Mul64(x247, 0xffffffffffffffff)
+       var x297 uint64
+       var x298 uint64
+       x297, x298 = bits.Add64(x296, x293, uint64(0x0))
+       var x299 uint64
+       var x300 uint64
+       x299, x300 = bits.Add64(x294, x291, uint64(p521Uint1(x298)))
+       var x301 uint64
+       var x302 uint64
+       x301, x302 = bits.Add64(x292, x289, uint64(p521Uint1(x300)))
+       var x303 uint64
+       var x304 uint64
+       x303, x304 = bits.Add64(x290, x287, uint64(p521Uint1(x302)))
+       var x305 uint64
+       var x306 uint64
+       x305, x306 = bits.Add64(x288, x285, uint64(p521Uint1(x304)))
+       var x307 uint64
+       var x308 uint64
+       x307, x308 = bits.Add64(x286, x283, uint64(p521Uint1(x306)))
+       var x309 uint64
+       var x310 uint64
+       x309, x310 = bits.Add64(x284, x281, uint64(p521Uint1(x308)))
+       var x311 uint64
+       var x312 uint64
+       x311, x312 = bits.Add64(x282, x279, uint64(p521Uint1(x310)))
+       var x314 uint64
+       _, x314 = bits.Add64(x247, x295, uint64(0x0))
+       var x315 uint64
+       var x316 uint64
+       x315, x316 = bits.Add64(x265, x297, uint64(p521Uint1(x314)))
+       var x317 uint64
+       var x318 uint64
+       x317, x318 = bits.Add64(x267, x299, uint64(p521Uint1(x316)))
+       var x319 uint64
+       var x320 uint64
+       x319, x320 = bits.Add64(x269, x301, uint64(p521Uint1(x318)))
+       var x321 uint64
+       var x322 uint64
+       x321, x322 = bits.Add64(x271, x303, uint64(p521Uint1(x320)))
+       var x323 uint64
+       var x324 uint64
+       x323, x324 = bits.Add64(x273, x305, uint64(p521Uint1(x322)))
+       var x325 uint64
+       var x326 uint64
+       x325, x326 = bits.Add64(x275, x307, uint64(p521Uint1(x324)))
+       var x327 uint64
+       var x328 uint64
+       x327, x328 = bits.Add64(x277, x309, uint64(p521Uint1(x326)))
+       var x329 uint64
+       var x330 uint64
+       x329, x330 = bits.Add64((uint64(p521Uint1(x278)) + (uint64(p521Uint1(x262)) + (uint64(p521Uint1(x244)) + x212))), x311, uint64(p521Uint1(x328)))
+       var x331 uint64
+       var x332 uint64
+       x332, x331 = bits.Mul64(arg1[6], 0x400000000000)
+       var x333 uint64
+       var x334 uint64
+       x333, x334 = bits.Add64(x317, x331, uint64(0x0))
+       var x335 uint64
+       var x336 uint64
+       x335, x336 = bits.Add64(x319, x332, uint64(p521Uint1(x334)))
+       var x337 uint64
+       var x338 uint64
+       x337, x338 = bits.Add64(x321, uint64(0x0), uint64(p521Uint1(x336)))
+       var x339 uint64
+       var x340 uint64
+       x339, x340 = bits.Add64(x323, uint64(0x0), uint64(p521Uint1(x338)))
+       var x341 uint64
+       var x342 uint64
+       x341, x342 = bits.Add64(x325, uint64(0x0), uint64(p521Uint1(x340)))
+       var x343 uint64
+       var x344 uint64
+       x343, x344 = bits.Add64(x327, uint64(0x0), uint64(p521Uint1(x342)))
+       var x345 uint64
+       var x346 uint64
+       x345, x346 = bits.Add64(x329, uint64(0x0), uint64(p521Uint1(x344)))
+       var x347 uint64
+       var x348 uint64
+       x348, x347 = bits.Mul64(x315, 0x1ff)
+       var x349 uint64
+       var x350 uint64
+       x350, x349 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x351 uint64
+       var x352 uint64
+       x352, x351 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x353 uint64
+       var x354 uint64
+       x354, x353 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x355 uint64
+       var x356 uint64
+       x356, x355 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x357 uint64
+       var x358 uint64
+       x358, x357 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x359 uint64
+       var x360 uint64
+       x360, x359 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x361 uint64
+       var x362 uint64
+       x362, x361 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x363 uint64
+       var x364 uint64
+       x364, x363 = bits.Mul64(x315, 0xffffffffffffffff)
+       var x365 uint64
+       var x366 uint64
+       x365, x366 = bits.Add64(x364, x361, uint64(0x0))
+       var x367 uint64
+       var x368 uint64
+       x367, x368 = bits.Add64(x362, x359, uint64(p521Uint1(x366)))
+       var x369 uint64
+       var x370 uint64
+       x369, x370 = bits.Add64(x360, x357, uint64(p521Uint1(x368)))
+       var x371 uint64
+       var x372 uint64
+       x371, x372 = bits.Add64(x358, x355, uint64(p521Uint1(x370)))
+       var x373 uint64
+       var x374 uint64
+       x373, x374 = bits.Add64(x356, x353, uint64(p521Uint1(x372)))
+       var x375 uint64
+       var x376 uint64
+       x375, x376 = bits.Add64(x354, x351, uint64(p521Uint1(x374)))
+       var x377 uint64
+       var x378 uint64
+       x377, x378 = bits.Add64(x352, x349, uint64(p521Uint1(x376)))
+       var x379 uint64
+       var x380 uint64
+       x379, x380 = bits.Add64(x350, x347, uint64(p521Uint1(x378)))
+       var x382 uint64
+       _, x382 = bits.Add64(x315, x363, uint64(0x0))
+       var x383 uint64
+       var x384 uint64
+       x383, x384 = bits.Add64(x333, x365, uint64(p521Uint1(x382)))
+       var x385 uint64
+       var x386 uint64
+       x385, x386 = bits.Add64(x335, x367, uint64(p521Uint1(x384)))
+       var x387 uint64
+       var x388 uint64
+       x387, x388 = bits.Add64(x337, x369, uint64(p521Uint1(x386)))
+       var x389 uint64
+       var x390 uint64
+       x389, x390 = bits.Add64(x339, x371, uint64(p521Uint1(x388)))
+       var x391 uint64
+       var x392 uint64
+       x391, x392 = bits.Add64(x341, x373, uint64(p521Uint1(x390)))
+       var x393 uint64
+       var x394 uint64
+       x393, x394 = bits.Add64(x343, x375, uint64(p521Uint1(x392)))
+       var x395 uint64
+       var x396 uint64
+       x395, x396 = bits.Add64(x345, x377, uint64(p521Uint1(x394)))
+       var x397 uint64
+       var x398 uint64
+       x397, x398 = bits.Add64((uint64(p521Uint1(x346)) + (uint64(p521Uint1(x330)) + (uint64(p521Uint1(x312)) + x280))), x379, uint64(p521Uint1(x396)))
+       var x399 uint64
+       var x400 uint64
+       x400, x399 = bits.Mul64(arg1[7], 0x400000000000)
+       var x401 uint64
+       var x402 uint64
+       x401, x402 = bits.Add64(x385, x399, uint64(0x0))
+       var x403 uint64
+       var x404 uint64
+       x403, x404 = bits.Add64(x387, x400, uint64(p521Uint1(x402)))
+       var x405 uint64
+       var x406 uint64
+       x405, x406 = bits.Add64(x389, uint64(0x0), uint64(p521Uint1(x404)))
+       var x407 uint64
+       var x408 uint64
+       x407, x408 = bits.Add64(x391, uint64(0x0), uint64(p521Uint1(x406)))
+       var x409 uint64
+       var x410 uint64
+       x409, x410 = bits.Add64(x393, uint64(0x0), uint64(p521Uint1(x408)))
+       var x411 uint64
+       var x412 uint64
+       x411, x412 = bits.Add64(x395, uint64(0x0), uint64(p521Uint1(x410)))
+       var x413 uint64
+       var x414 uint64
+       x413, x414 = bits.Add64(x397, uint64(0x0), uint64(p521Uint1(x412)))
+       var x415 uint64
+       var x416 uint64
+       x416, x415 = bits.Mul64(x383, 0x1ff)
+       var x417 uint64
+       var x418 uint64
+       x418, x417 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x419 uint64
+       var x420 uint64
+       x420, x419 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x421 uint64
+       var x422 uint64
+       x422, x421 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x423 uint64
+       var x424 uint64
+       x424, x423 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x425 uint64
+       var x426 uint64
+       x426, x425 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x427 uint64
+       var x428 uint64
+       x428, x427 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x429 uint64
+       var x430 uint64
+       x430, x429 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x431 uint64
+       var x432 uint64
+       x432, x431 = bits.Mul64(x383, 0xffffffffffffffff)
+       var x433 uint64
+       var x434 uint64
+       x433, x434 = bits.Add64(x432, x429, uint64(0x0))
+       var x435 uint64
+       var x436 uint64
+       x435, x436 = bits.Add64(x430, x427, uint64(p521Uint1(x434)))
+       var x437 uint64
+       var x438 uint64
+       x437, x438 = bits.Add64(x428, x425, uint64(p521Uint1(x436)))
+       var x439 uint64
+       var x440 uint64
+       x439, x440 = bits.Add64(x426, x423, uint64(p521Uint1(x438)))
+       var x441 uint64
+       var x442 uint64
+       x441, x442 = bits.Add64(x424, x421, uint64(p521Uint1(x440)))
+       var x443 uint64
+       var x444 uint64
+       x443, x444 = bits.Add64(x422, x419, uint64(p521Uint1(x442)))
+       var x445 uint64
+       var x446 uint64
+       x445, x446 = bits.Add64(x420, x417, uint64(p521Uint1(x444)))
+       var x447 uint64
+       var x448 uint64
+       x447, x448 = bits.Add64(x418, x415, uint64(p521Uint1(x446)))
+       var x450 uint64
+       _, x450 = bits.Add64(x383, x431, uint64(0x0))
+       var x451 uint64
+       var x452 uint64
+       x451, x452 = bits.Add64(x401, x433, uint64(p521Uint1(x450)))
+       var x453 uint64
+       var x454 uint64
+       x453, x454 = bits.Add64(x403, x435, uint64(p521Uint1(x452)))
+       var x455 uint64
+       var x456 uint64
+       x455, x456 = bits.Add64(x405, x437, uint64(p521Uint1(x454)))
+       var x457 uint64
+       var x458 uint64
+       x457, x458 = bits.Add64(x407, x439, uint64(p521Uint1(x456)))
+       var x459 uint64
+       var x460 uint64
+       x459, x460 = bits.Add64(x409, x441, uint64(p521Uint1(x458)))
+       var x461 uint64
+       var x462 uint64
+       x461, x462 = bits.Add64(x411, x443, uint64(p521Uint1(x460)))
+       var x463 uint64
+       var x464 uint64
+       x463, x464 = bits.Add64(x413, x445, uint64(p521Uint1(x462)))
+       var x465 uint64
+       var x466 uint64
+       x465, x466 = bits.Add64((uint64(p521Uint1(x414)) + (uint64(p521Uint1(x398)) + (uint64(p521Uint1(x380)) + x348))), x447, uint64(p521Uint1(x464)))
+       var x467 uint64
+       var x468 uint64
+       x468, x467 = bits.Mul64(arg1[8], 0x400000000000)
+       var x469 uint64
+       var x470 uint64
+       x469, x470 = bits.Add64(x453, x467, uint64(0x0))
+       var x471 uint64
+       var x472 uint64
+       x471, x472 = bits.Add64(x455, x468, uint64(p521Uint1(x470)))
+       var x473 uint64
+       var x474 uint64
+       x473, x474 = bits.Add64(x457, uint64(0x0), uint64(p521Uint1(x472)))
+       var x475 uint64
+       var x476 uint64
+       x475, x476 = bits.Add64(x459, uint64(0x0), uint64(p521Uint1(x474)))
+       var x477 uint64
+       var x478 uint64
+       x477, x478 = bits.Add64(x461, uint64(0x0), uint64(p521Uint1(x476)))
+       var x479 uint64
+       var x480 uint64
+       x479, x480 = bits.Add64(x463, uint64(0x0), uint64(p521Uint1(x478)))
+       var x481 uint64
+       var x482 uint64
+       x481, x482 = bits.Add64(x465, uint64(0x0), uint64(p521Uint1(x480)))
+       var x483 uint64
+       var x484 uint64
+       x484, x483 = bits.Mul64(x451, 0x1ff)
+       var x485 uint64
+       var x486 uint64
+       x486, x485 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x487 uint64
+       var x488 uint64
+       x488, x487 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x489 uint64
+       var x490 uint64
+       x490, x489 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x491 uint64
+       var x492 uint64
+       x492, x491 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x493 uint64
+       var x494 uint64
+       x494, x493 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x495 uint64
+       var x496 uint64
+       x496, x495 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x497 uint64
+       var x498 uint64
+       x498, x497 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x499 uint64
+       var x500 uint64
+       x500, x499 = bits.Mul64(x451, 0xffffffffffffffff)
+       var x501 uint64
+       var x502 uint64
+       x501, x502 = bits.Add64(x500, x497, uint64(0x0))
+       var x503 uint64
+       var x504 uint64
+       x503, x504 = bits.Add64(x498, x495, uint64(p521Uint1(x502)))
+       var x505 uint64
+       var x506 uint64
+       x505, x506 = bits.Add64(x496, x493, uint64(p521Uint1(x504)))
+       var x507 uint64
+       var x508 uint64
+       x507, x508 = bits.Add64(x494, x491, uint64(p521Uint1(x506)))
+       var x509 uint64
+       var x510 uint64
+       x509, x510 = bits.Add64(x492, x489, uint64(p521Uint1(x508)))
+       var x511 uint64
+       var x512 uint64
+       x511, x512 = bits.Add64(x490, x487, uint64(p521Uint1(x510)))
+       var x513 uint64
+       var x514 uint64
+       x513, x514 = bits.Add64(x488, x485, uint64(p521Uint1(x512)))
+       var x515 uint64
+       var x516 uint64
+       x515, x516 = bits.Add64(x486, x483, uint64(p521Uint1(x514)))
+       var x518 uint64
+       _, x518 = bits.Add64(x451, x499, uint64(0x0))
+       var x519 uint64
+       var x520 uint64
+       x519, x520 = bits.Add64(x469, x501, uint64(p521Uint1(x518)))
+       var x521 uint64
+       var x522 uint64
+       x521, x522 = bits.Add64(x471, x503, uint64(p521Uint1(x520)))
+       var x523 uint64
+       var x524 uint64
+       x523, x524 = bits.Add64(x473, x505, uint64(p521Uint1(x522)))
+       var x525 uint64
+       var x526 uint64
+       x525, x526 = bits.Add64(x475, x507, uint64(p521Uint1(x524)))
+       var x527 uint64
+       var x528 uint64
+       x527, x528 = bits.Add64(x477, x509, uint64(p521Uint1(x526)))
+       var x529 uint64
+       var x530 uint64
+       x529, x530 = bits.Add64(x479, x511, uint64(p521Uint1(x528)))
+       var x531 uint64
+       var x532 uint64
+       x531, x532 = bits.Add64(x481, x513, uint64(p521Uint1(x530)))
+       var x533 uint64
+       var x534 uint64
+       x533, x534 = bits.Add64((uint64(p521Uint1(x482)) + (uint64(p521Uint1(x466)) + (uint64(p521Uint1(x448)) + x416))), x515, uint64(p521Uint1(x532)))
+       x535 := (uint64(p521Uint1(x534)) + (uint64(p521Uint1(x516)) + x484))
+       var x536 uint64
+       var x537 uint64
+       x536, x537 = bits.Sub64(x519, 0xffffffffffffffff, uint64(0x0))
+       var x538 uint64
+       var x539 uint64
+       x538, x539 = bits.Sub64(x521, 0xffffffffffffffff, uint64(p521Uint1(x537)))
+       var x540 uint64
+       var x541 uint64
+       x540, x541 = bits.Sub64(x523, 0xffffffffffffffff, uint64(p521Uint1(x539)))
+       var x542 uint64
+       var x543 uint64
+       x542, x543 = bits.Sub64(x525, 0xffffffffffffffff, uint64(p521Uint1(x541)))
+       var x544 uint64
+       var x545 uint64
+       x544, x545 = bits.Sub64(x527, 0xffffffffffffffff, uint64(p521Uint1(x543)))
+       var x546 uint64
+       var x547 uint64
+       x546, x547 = bits.Sub64(x529, 0xffffffffffffffff, uint64(p521Uint1(x545)))
+       var x548 uint64
+       var x549 uint64
+       x548, x549 = bits.Sub64(x531, 0xffffffffffffffff, uint64(p521Uint1(x547)))
+       var x550 uint64
+       var x551 uint64
+       x550, x551 = bits.Sub64(x533, 0xffffffffffffffff, uint64(p521Uint1(x549)))
+       var x552 uint64
+       var x553 uint64
+       x552, x553 = bits.Sub64(x535, 0x1ff, uint64(p521Uint1(x551)))
+       var x555 uint64
+       _, x555 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p521Uint1(x553)))
+       var x556 uint64
+       p521CmovznzU64(&x556, p521Uint1(x555), x536, x519)
+       var x557 uint64
+       p521CmovznzU64(&x557, p521Uint1(x555), x538, x521)
+       var x558 uint64
+       p521CmovznzU64(&x558, p521Uint1(x555), x540, x523)
+       var x559 uint64
+       p521CmovznzU64(&x559, p521Uint1(x555), x542, x525)
+       var x560 uint64
+       p521CmovznzU64(&x560, p521Uint1(x555), x544, x527)
+       var x561 uint64
+       p521CmovznzU64(&x561, p521Uint1(x555), x546, x529)
+       var x562 uint64
+       p521CmovznzU64(&x562, p521Uint1(x555), x548, x531)
+       var x563 uint64
+       p521CmovznzU64(&x563, p521Uint1(x555), x550, x533)
+       var x564 uint64
+       p521CmovznzU64(&x564, p521Uint1(x555), x552, x535)
+       out1[0] = x556
+       out1[1] = x557
+       out1[2] = x558
+       out1[3] = x559
+       out1[4] = x560
+       out1[5] = x561
+       out1[6] = x562
+       out1[7] = x563
+       out1[8] = x564
 }
 
-// p521Sub subtracts two field elements.
+// p521Selectznz is a multi-limb conditional select.
 //
 // Postconditions:
-//   eval out1 mod m = (eval arg1 - eval arg2) mod m
+//   eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
 //
 // Input Bounds:
-//   arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
-//   arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+//   arg1: [0x0 ~> 0x1]
+//   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+//   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
 // Output Bounds:
-//   out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]]
-func p521Sub(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
-       x1 := ((0x7fffffffffffffe + arg1[0]) - arg2[0])
-       x2 := ((0x7fffffffffffffe + arg1[1]) - arg2[1])
-       x3 := ((0x7fffffffffffffe + arg1[2]) - arg2[2])
-       x4 := ((0x7fffffffffffffe + arg1[3]) - arg2[3])
-       x5 := ((0x7fffffffffffffe + arg1[4]) - arg2[4])
-       x6 := ((0x7fffffffffffffe + arg1[5]) - arg2[5])
-       x7 := ((0x7fffffffffffffe + arg1[6]) - arg2[6])
-       x8 := ((0x7fffffffffffffe + arg1[7]) - arg2[7])
-       x9 := ((0x3fffffffffffffe + arg1[8]) - arg2[8])
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+func p521Selectznz(out1 *[9]uint64, arg1 p521Uint1, arg2 *[9]uint64, arg3 *[9]uint64) {
+       var x1 uint64
+       p521CmovznzU64(&x1, arg1, arg2[0], arg3[0])
+       var x2 uint64
+       p521CmovznzU64(&x2, arg1, arg2[1], arg3[1])
+       var x3 uint64
+       p521CmovznzU64(&x3, arg1, arg2[2], arg3[2])
+       var x4 uint64
+       p521CmovznzU64(&x4, arg1, arg2[3], arg3[3])
+       var x5 uint64
+       p521CmovznzU64(&x5, arg1, arg2[4], arg3[4])
+       var x6 uint64
+       p521CmovznzU64(&x6, arg1, arg2[5], arg3[5])
+       var x7 uint64
+       p521CmovznzU64(&x7, arg1, arg2[6], arg3[6])
+       var x8 uint64
+       p521CmovznzU64(&x8, arg1, arg2[7], arg3[7])
+       var x9 uint64
+       p521CmovznzU64(&x9, arg1, arg2[8], arg3[8])
        out1[0] = x1
        out1[1] = x2
        out1[2] = x3
@@ -1380,346 +5158,280 @@ func p521Sub(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) {
        out1[8] = x9
 }
 
-// p521ToBytes serializes a field element to bytes in little-endian order.
+// p521ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order.
 //
+// Preconditions:
+//   0 โ‰ค eval arg1 < m
 // Postconditions:
 //   out1 = map (ฮป x, โŒŠ((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)โŒ‹) [0..65]
 //
 // Input Bounds:
-//   arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+//   arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1ff]]
 // Output Bounds:
 //   out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]]
 func p521ToBytes(out1 *[66]uint8, arg1 *[9]uint64) {
-       var x1 uint64
-       var x2 p521Uint1
-       p521SubborrowxU58(&x1, &x2, 0x0, arg1[0], 0x3ffffffffffffff)
-       var x3 uint64
-       var x4 p521Uint1
-       p521SubborrowxU58(&x3, &x4, x2, arg1[1], 0x3ffffffffffffff)
-       var x5 uint64
-       var x6 p521Uint1
-       p521SubborrowxU58(&x5, &x6, x4, arg1[2], 0x3ffffffffffffff)
-       var x7 uint64
-       var x8 p521Uint1
-       p521SubborrowxU58(&x7, &x8, x6, arg1[3], 0x3ffffffffffffff)
-       var x9 uint64
-       var x10 p521Uint1
-       p521SubborrowxU58(&x9, &x10, x8, arg1[4], 0x3ffffffffffffff)
-       var x11 uint64
-       var x12 p521Uint1
-       p521SubborrowxU58(&x11, &x12, x10, arg1[5], 0x3ffffffffffffff)
-       var x13 uint64
-       var x14 p521Uint1
-       p521SubborrowxU58(&x13, &x14, x12, arg1[6], 0x3ffffffffffffff)
-       var x15 uint64
-       var x16 p521Uint1
-       p521SubborrowxU58(&x15, &x16, x14, arg1[7], 0x3ffffffffffffff)
-       var x17 uint64
-       var x18 p521Uint1
-       p521SubborrowxU57(&x17, &x18, x16, arg1[8], 0x1ffffffffffffff)
-       var x19 uint64
-       p521CmovznzU64(&x19, x18, uint64(0x0), 0xffffffffffffffff)
-       var x20 uint64
-       var x21 p521Uint1
-       p521AddcarryxU58(&x20, &x21, 0x0, x1, (x19 & 0x3ffffffffffffff))
-       var x22 uint64
-       var x23 p521Uint1
-       p521AddcarryxU58(&x22, &x23, x21, x3, (x19 & 0x3ffffffffffffff))
-       var x24 uint64
-       var x25 p521Uint1
-       p521AddcarryxU58(&x24, &x25, x23, x5, (x19 & 0x3ffffffffffffff))
-       var x26 uint64
-       var x27 p521Uint1
-       p521AddcarryxU58(&x26, &x27, x25, x7, (x19 & 0x3ffffffffffffff))
-       var x28 uint64
-       var x29 p521Uint1
-       p521AddcarryxU58(&x28, &x29, x27, x9, (x19 & 0x3ffffffffffffff))
-       var x30 uint64
-       var x31 p521Uint1
-       p521AddcarryxU58(&x30, &x31, x29, x11, (x19 & 0x3ffffffffffffff))
-       var x32 uint64
-       var x33 p521Uint1
-       p521AddcarryxU58(&x32, &x33, x31, x13, (x19 & 0x3ffffffffffffff))
-       var x34 uint64
-       var x35 p521Uint1
-       p521AddcarryxU58(&x34, &x35, x33, x15, (x19 & 0x3ffffffffffffff))
-       var x36 uint64
-       var x37 p521Uint1
-       p521AddcarryxU57(&x36, &x37, x35, x17, (x19 & 0x1ffffffffffffff))
-       x38 := (x34 << 6)
-       x39 := (x32 << 4)
-       x40 := (x30 << 2)
-       x41 := (x26 << 6)
-       x42 := (x24 << 4)
-       x43 := (x22 << 2)
-       x44 := (uint8(x20) & 0xff)
-       x45 := (x20 >> 8)
+       x1 := arg1[8]
+       x2 := arg1[7]
+       x3 := arg1[6]
+       x4 := arg1[5]
+       x5 := arg1[4]
+       x6 := arg1[3]
+       x7 := arg1[2]
+       x8 := arg1[1]
+       x9 := arg1[0]
+       x10 := (uint8(x9) & 0xff)
+       x11 := (x9 >> 8)
+       x12 := (uint8(x11) & 0xff)
+       x13 := (x11 >> 8)
+       x14 := (uint8(x13) & 0xff)
+       x15 := (x13 >> 8)
+       x16 := (uint8(x15) & 0xff)
+       x17 := (x15 >> 8)
+       x18 := (uint8(x17) & 0xff)
+       x19 := (x17 >> 8)
+       x20 := (uint8(x19) & 0xff)
+       x21 := (x19 >> 8)
+       x22 := (uint8(x21) & 0xff)
+       x23 := uint8((x21 >> 8))
+       x24 := (uint8(x8) & 0xff)
+       x25 := (x8 >> 8)
+       x26 := (uint8(x25) & 0xff)
+       x27 := (x25 >> 8)
+       x28 := (uint8(x27) & 0xff)
+       x29 := (x27 >> 8)
+       x30 := (uint8(x29) & 0xff)
+       x31 := (x29 >> 8)
+       x32 := (uint8(x31) & 0xff)
+       x33 := (x31 >> 8)
+       x34 := (uint8(x33) & 0xff)
+       x35 := (x33 >> 8)
+       x36 := (uint8(x35) & 0xff)
+       x37 := uint8((x35 >> 8))
+       x38 := (uint8(x7) & 0xff)
+       x39 := (x7 >> 8)
+       x40 := (uint8(x39) & 0xff)
+       x41 := (x39 >> 8)
+       x42 := (uint8(x41) & 0xff)
+       x43 := (x41 >> 8)
+       x44 := (uint8(x43) & 0xff)
+       x45 := (x43 >> 8)
        x46 := (uint8(x45) & 0xff)
        x47 := (x45 >> 8)
        x48 := (uint8(x47) & 0xff)
        x49 := (x47 >> 8)
        x50 := (uint8(x49) & 0xff)
-       x51 := (x49 >> 8)
-       x52 := (uint8(x51) & 0xff)
-       x53 := (x51 >> 8)
+       x51 := uint8((x49 >> 8))
+       x52 := (uint8(x6) & 0xff)
+       x53 := (x6 >> 8)
        x54 := (uint8(x53) & 0xff)
        x55 := (x53 >> 8)
        x56 := (uint8(x55) & 0xff)
-       x57 := uint8((x55 >> 8))
-       x58 := (x43 + uint64(x57))
-       x59 := (uint8(x58) & 0xff)
-       x60 := (x58 >> 8)
-       x61 := (uint8(x60) & 0xff)
-       x62 := (x60 >> 8)
-       x63 := (uint8(x62) & 0xff)
-       x64 := (x62 >> 8)
-       x65 := (uint8(x64) & 0xff)
-       x66 := (x64 >> 8)
-       x67 := (uint8(x66) & 0xff)
-       x68 := (x66 >> 8)
-       x69 := (uint8(x68) & 0xff)
-       x70 := (x68 >> 8)
-       x71 := (uint8(x70) & 0xff)
-       x72 := uint8((x70 >> 8))
-       x73 := (x42 + uint64(x72))
+       x57 := (x55 >> 8)
+       x58 := (uint8(x57) & 0xff)
+       x59 := (x57 >> 8)
+       x60 := (uint8(x59) & 0xff)
+       x61 := (x59 >> 8)
+       x62 := (uint8(x61) & 0xff)
+       x63 := (x61 >> 8)
+       x64 := (uint8(x63) & 0xff)
+       x65 := uint8((x63 >> 8))
+       x66 := (uint8(x5) & 0xff)
+       x67 := (x5 >> 8)
+       x68 := (uint8(x67) & 0xff)
+       x69 := (x67 >> 8)
+       x70 := (uint8(x69) & 0xff)
+       x71 := (x69 >> 8)
+       x72 := (uint8(x71) & 0xff)
+       x73 := (x71 >> 8)
        x74 := (uint8(x73) & 0xff)
        x75 := (x73 >> 8)
        x76 := (uint8(x75) & 0xff)
        x77 := (x75 >> 8)
        x78 := (uint8(x77) & 0xff)
-       x79 := (x77 >> 8)
-       x80 := (uint8(x79) & 0xff)
-       x81 := (x79 >> 8)
+       x79 := uint8((x77 >> 8))
+       x80 := (uint8(x4) & 0xff)
+       x81 := (x4 >> 8)
        x82 := (uint8(x81) & 0xff)
        x83 := (x81 >> 8)
        x84 := (uint8(x83) & 0xff)
        x85 := (x83 >> 8)
        x86 := (uint8(x85) & 0xff)
-       x87 := uint8((x85 >> 8))
-       x88 := (x41 + uint64(x87))
-       x89 := (uint8(x88) & 0xff)
-       x90 := (x88 >> 8)
-       x91 := (uint8(x90) & 0xff)
-       x92 := (x90 >> 8)
-       x93 := (uint8(x92) & 0xff)
-       x94 := (x92 >> 8)
-       x95 := (uint8(x94) & 0xff)
-       x96 := (x94 >> 8)
-       x97 := (uint8(x96) & 0xff)
-       x98 := (x96 >> 8)
-       x99 := (uint8(x98) & 0xff)
-       x100 := (x98 >> 8)
-       x101 := (uint8(x100) & 0xff)
-       x102 := uint8((x100 >> 8))
-       x103 := (uint8(x28) & 0xff)
-       x104 := (x28 >> 8)
-       x105 := (uint8(x104) & 0xff)
-       x106 := (x104 >> 8)
-       x107 := (uint8(x106) & 0xff)
-       x108 := (x106 >> 8)
-       x109 := (uint8(x108) & 0xff)
-       x110 := (x108 >> 8)
-       x111 := (uint8(x110) & 0xff)
-       x112 := (x110 >> 8)
-       x113 := (uint8(x112) & 0xff)
-       x114 := (x112 >> 8)
-       x115 := (uint8(x114) & 0xff)
-       x116 := uint8((x114 >> 8))
-       x117 := (x40 + uint64(x116))
+       x87 := (x85 >> 8)
+       x88 := (uint8(x87) & 0xff)
+       x89 := (x87 >> 8)
+       x90 := (uint8(x89) & 0xff)
+       x91 := (x89 >> 8)
+       x92 := (uint8(x91) & 0xff)
+       x93 := uint8((x91 >> 8))
+       x94 := (uint8(x3) & 0xff)
+       x95 := (x3 >> 8)
+       x96 := (uint8(x95) & 0xff)
+       x97 := (x95 >> 8)
+       x98 := (uint8(x97) & 0xff)
+       x99 := (x97 >> 8)
+       x100 := (uint8(x99) & 0xff)
+       x101 := (x99 >> 8)
+       x102 := (uint8(x101) & 0xff)
+       x103 := (x101 >> 8)
+       x104 := (uint8(x103) & 0xff)
+       x105 := (x103 >> 8)
+       x106 := (uint8(x105) & 0xff)
+       x107 := uint8((x105 >> 8))
+       x108 := (uint8(x2) & 0xff)
+       x109 := (x2 >> 8)
+       x110 := (uint8(x109) & 0xff)
+       x111 := (x109 >> 8)
+       x112 := (uint8(x111) & 0xff)
+       x113 := (x111 >> 8)
+       x114 := (uint8(x113) & 0xff)
+       x115 := (x113 >> 8)
+       x116 := (uint8(x115) & 0xff)
+       x117 := (x115 >> 8)
        x118 := (uint8(x117) & 0xff)
        x119 := (x117 >> 8)
        x120 := (uint8(x119) & 0xff)
-       x121 := (x119 >> 8)
-       x122 := (uint8(x121) & 0xff)
-       x123 := (x121 >> 8)
-       x124 := (uint8(x123) & 0xff)
-       x125 := (x123 >> 8)
-       x126 := (uint8(x125) & 0xff)
-       x127 := (x125 >> 8)
-       x128 := (uint8(x127) & 0xff)
-       x129 := (x127 >> 8)
-       x130 := (uint8(x129) & 0xff)
-       x131 := uint8((x129 >> 8))
-       x132 := (x39 + uint64(x131))
-       x133 := (uint8(x132) & 0xff)
-       x134 := (x132 >> 8)
-       x135 := (uint8(x134) & 0xff)
-       x136 := (x134 >> 8)
-       x137 := (uint8(x136) & 0xff)
-       x138 := (x136 >> 8)
-       x139 := (uint8(x138) & 0xff)
-       x140 := (x138 >> 8)
-       x141 := (uint8(x140) & 0xff)
-       x142 := (x140 >> 8)
-       x143 := (uint8(x142) & 0xff)
-       x144 := (x142 >> 8)
-       x145 := (uint8(x144) & 0xff)
-       x146 := uint8((x144 >> 8))
-       x147 := (x38 + uint64(x146))
-       x148 := (uint8(x147) & 0xff)
-       x149 := (x147 >> 8)
-       x150 := (uint8(x149) & 0xff)
-       x151 := (x149 >> 8)
-       x152 := (uint8(x151) & 0xff)
-       x153 := (x151 >> 8)
-       x154 := (uint8(x153) & 0xff)
-       x155 := (x153 >> 8)
-       x156 := (uint8(x155) & 0xff)
-       x157 := (x155 >> 8)
-       x158 := (uint8(x157) & 0xff)
-       x159 := (x157 >> 8)
-       x160 := (uint8(x159) & 0xff)
-       x161 := uint8((x159 >> 8))
-       x162 := (uint8(x36) & 0xff)
-       x163 := (x36 >> 8)
-       x164 := (uint8(x163) & 0xff)
-       x165 := (x163 >> 8)
-       x166 := (uint8(x165) & 0xff)
-       x167 := (x165 >> 8)
-       x168 := (uint8(x167) & 0xff)
-       x169 := (x167 >> 8)
-       x170 := (uint8(x169) & 0xff)
-       x171 := (x169 >> 8)
-       x172 := (uint8(x171) & 0xff)
-       x173 := (x171 >> 8)
-       x174 := (uint8(x173) & 0xff)
-       x175 := p521Uint1((x173 >> 8))
-       out1[0] = x44
-       out1[1] = x46
-       out1[2] = x48
-       out1[3] = x50
-       out1[4] = x52
-       out1[5] = x54
-       out1[6] = x56
-       out1[7] = x59
-       out1[8] = x61
-       out1[9] = x63
-       out1[10] = x65
-       out1[11] = x67
-       out1[12] = x69
-       out1[13] = x71
-       out1[14] = x74
-       out1[15] = x76
-       out1[16] = x78
-       out1[17] = x80
-       out1[18] = x82
-       out1[19] = x84
-       out1[20] = x86
-       out1[21] = x89
-       out1[22] = x91
-       out1[23] = x93
-       out1[24] = x95
-       out1[25] = x97
-       out1[26] = x99
-       out1[27] = x101
-       out1[28] = x102
-       out1[29] = x103
-       out1[30] = x105
-       out1[31] = x107
-       out1[32] = x109
-       out1[33] = x111
-       out1[34] = x113
-       out1[35] = x115
-       out1[36] = x118
-       out1[37] = x120
-       out1[38] = x122
-       out1[39] = x124
-       out1[40] = x126
-       out1[41] = x128
-       out1[42] = x130
-       out1[43] = x133
-       out1[44] = x135
-       out1[45] = x137
-       out1[46] = x139
-       out1[47] = x141
-       out1[48] = x143
-       out1[49] = x145
-       out1[50] = x148
-       out1[51] = x150
-       out1[52] = x152
-       out1[53] = x154
-       out1[54] = x156
-       out1[55] = x158
-       out1[56] = x160
-       out1[57] = x161
-       out1[58] = x162
-       out1[59] = x164
-       out1[60] = x166
-       out1[61] = x168
-       out1[62] = x170
-       out1[63] = x172
-       out1[64] = x174
-       out1[65] = uint8(x175)
+       x121 := uint8((x119 >> 8))
+       x122 := (uint8(x1) & 0xff)
+       x123 := p521Uint1((x1 >> 8))
+       out1[0] = x10
+       out1[1] = x12
+       out1[2] = x14
+       out1[3] = x16
+       out1[4] = x18
+       out1[5] = x20
+       out1[6] = x22
+       out1[7] = x23
+       out1[8] = x24
+       out1[9] = x26
+       out1[10] = x28
+       out1[11] = x30
+       out1[12] = x32
+       out1[13] = x34
+       out1[14] = x36
+       out1[15] = x37
+       out1[16] = x38
+       out1[17] = x40
+       out1[18] = x42
+       out1[19] = x44
+       out1[20] = x46
+       out1[21] = x48
+       out1[22] = x50
+       out1[23] = x51
+       out1[24] = x52
+       out1[25] = x54
+       out1[26] = x56
+       out1[27] = x58
+       out1[28] = x60
+       out1[29] = x62
+       out1[30] = x64
+       out1[31] = x65
+       out1[32] = x66
+       out1[33] = x68
+       out1[34] = x70
+       out1[35] = x72
+       out1[36] = x74
+       out1[37] = x76
+       out1[38] = x78
+       out1[39] = x79
+       out1[40] = x80
+       out1[41] = x82
+       out1[42] = x84
+       out1[43] = x86
+       out1[44] = x88
+       out1[45] = x90
+       out1[46] = x92
+       out1[47] = x93
+       out1[48] = x94
+       out1[49] = x96
+       out1[50] = x98
+       out1[51] = x100
+       out1[52] = x102
+       out1[53] = x104
+       out1[54] = x106
+       out1[55] = x107
+       out1[56] = x108
+       out1[57] = x110
+       out1[58] = x112
+       out1[59] = x114
+       out1[60] = x116
+       out1[61] = x118
+       out1[62] = x120
+       out1[63] = x121
+       out1[64] = x122
+       out1[65] = uint8(x123)
 }
 
-// p521FromBytes deserializes a field element from bytes in little-endian order.
+// p521FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order.
 //
+// Preconditions:
+//   0 โ‰ค bytes_eval arg1 < m
 // Postconditions:
 //   eval out1 mod m = bytes_eval arg1 mod m
+//   0 โ‰ค eval out1 < m
 //
 // Input Bounds:
 //   arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]]
 // Output Bounds:
-//   out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]]
+//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1ff]]
 func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) {
-       x1 := (uint64(p521Uint1(arg1[65])) << 56)
-       x2 := (uint64(arg1[64]) << 48)
-       x3 := (uint64(arg1[63]) << 40)
-       x4 := (uint64(arg1[62]) << 32)
-       x5 := (uint64(arg1[61]) << 24)
-       x6 := (uint64(arg1[60]) << 16)
-       x7 := (uint64(arg1[59]) << 8)
-       x8 := arg1[58]
-       x9 := (uint64(arg1[57]) << 50)
-       x10 := (uint64(arg1[56]) << 42)
-       x11 := (uint64(arg1[55]) << 34)
-       x12 := (uint64(arg1[54]) << 26)
-       x13 := (uint64(arg1[53]) << 18)
-       x14 := (uint64(arg1[52]) << 10)
-       x15 := (uint64(arg1[51]) << 2)
-       x16 := (uint64(arg1[50]) << 52)
-       x17 := (uint64(arg1[49]) << 44)
-       x18 := (uint64(arg1[48]) << 36)
-       x19 := (uint64(arg1[47]) << 28)
-       x20 := (uint64(arg1[46]) << 20)
-       x21 := (uint64(arg1[45]) << 12)
-       x22 := (uint64(arg1[44]) << 4)
-       x23 := (uint64(arg1[43]) << 54)
-       x24 := (uint64(arg1[42]) << 46)
-       x25 := (uint64(arg1[41]) << 38)
-       x26 := (uint64(arg1[40]) << 30)
-       x27 := (uint64(arg1[39]) << 22)
-       x28 := (uint64(arg1[38]) << 14)
-       x29 := (uint64(arg1[37]) << 6)
-       x30 := (uint64(arg1[36]) << 56)
-       x31 := (uint64(arg1[35]) << 48)
-       x32 := (uint64(arg1[34]) << 40)
-       x33 := (uint64(arg1[33]) << 32)
-       x34 := (uint64(arg1[32]) << 24)
-       x35 := (uint64(arg1[31]) << 16)
-       x36 := (uint64(arg1[30]) << 8)
-       x37 := arg1[29]
-       x38 := (uint64(arg1[28]) << 50)
-       x39 := (uint64(arg1[27]) << 42)
-       x40 := (uint64(arg1[26]) << 34)
-       x41 := (uint64(arg1[25]) << 26)
-       x42 := (uint64(arg1[24]) << 18)
-       x43 := (uint64(arg1[23]) << 10)
-       x44 := (uint64(arg1[22]) << 2)
-       x45 := (uint64(arg1[21]) << 52)
-       x46 := (uint64(arg1[20]) << 44)
-       x47 := (uint64(arg1[19]) << 36)
-       x48 := (uint64(arg1[18]) << 28)
-       x49 := (uint64(arg1[17]) << 20)
-       x50 := (uint64(arg1[16]) << 12)
-       x51 := (uint64(arg1[15]) << 4)
-       x52 := (uint64(arg1[14]) << 54)
-       x53 := (uint64(arg1[13]) << 46)
-       x54 := (uint64(arg1[12]) << 38)
-       x55 := (uint64(arg1[11]) << 30)
-       x56 := (uint64(arg1[10]) << 22)
-       x57 := (uint64(arg1[9]) << 14)
-       x58 := (uint64(arg1[8]) << 6)
+       x1 := (uint64(p521Uint1(arg1[65])) << 8)
+       x2 := arg1[64]
+       x3 := (uint64(arg1[63]) << 56)
+       x4 := (uint64(arg1[62]) << 48)
+       x5 := (uint64(arg1[61]) << 40)
+       x6 := (uint64(arg1[60]) << 32)
+       x7 := (uint64(arg1[59]) << 24)
+       x8 := (uint64(arg1[58]) << 16)
+       x9 := (uint64(arg1[57]) << 8)
+       x10 := arg1[56]
+       x11 := (uint64(arg1[55]) << 56)
+       x12 := (uint64(arg1[54]) << 48)
+       x13 := (uint64(arg1[53]) << 40)
+       x14 := (uint64(arg1[52]) << 32)
+       x15 := (uint64(arg1[51]) << 24)
+       x16 := (uint64(arg1[50]) << 16)
+       x17 := (uint64(arg1[49]) << 8)
+       x18 := arg1[48]
+       x19 := (uint64(arg1[47]) << 56)
+       x20 := (uint64(arg1[46]) << 48)
+       x21 := (uint64(arg1[45]) << 40)
+       x22 := (uint64(arg1[44]) << 32)
+       x23 := (uint64(arg1[43]) << 24)
+       x24 := (uint64(arg1[42]) << 16)
+       x25 := (uint64(arg1[41]) << 8)
+       x26 := arg1[40]
+       x27 := (uint64(arg1[39]) << 56)
+       x28 := (uint64(arg1[38]) << 48)
+       x29 := (uint64(arg1[37]) << 40)
+       x30 := (uint64(arg1[36]) << 32)
+       x31 := (uint64(arg1[35]) << 24)
+       x32 := (uint64(arg1[34]) << 16)
+       x33 := (uint64(arg1[33]) << 8)
+       x34 := arg1[32]
+       x35 := (uint64(arg1[31]) << 56)
+       x36 := (uint64(arg1[30]) << 48)
+       x37 := (uint64(arg1[29]) << 40)
+       x38 := (uint64(arg1[28]) << 32)
+       x39 := (uint64(arg1[27]) << 24)
+       x40 := (uint64(arg1[26]) << 16)
+       x41 := (uint64(arg1[25]) << 8)
+       x42 := arg1[24]
+       x43 := (uint64(arg1[23]) << 56)
+       x44 := (uint64(arg1[22]) << 48)
+       x45 := (uint64(arg1[21]) << 40)
+       x46 := (uint64(arg1[20]) << 32)
+       x47 := (uint64(arg1[19]) << 24)
+       x48 := (uint64(arg1[18]) << 16)
+       x49 := (uint64(arg1[17]) << 8)
+       x50 := arg1[16]
+       x51 := (uint64(arg1[15]) << 56)
+       x52 := (uint64(arg1[14]) << 48)
+       x53 := (uint64(arg1[13]) << 40)
+       x54 := (uint64(arg1[12]) << 32)
+       x55 := (uint64(arg1[11]) << 24)
+       x56 := (uint64(arg1[10]) << 16)
+       x57 := (uint64(arg1[9]) << 8)
+       x58 := arg1[8]
        x59 := (uint64(arg1[7]) << 56)
        x60 := (uint64(arg1[6]) << 48)
        x61 := (uint64(arg1[5]) << 40)
@@ -1735,122 +5447,63 @@ func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) {
        x71 := (x61 + x70)
        x72 := (x60 + x71)
        x73 := (x59 + x72)
-       x74 := (x73 & 0x3ffffffffffffff)
-       x75 := uint8((x73 >> 58))
-       x76 := (x58 + uint64(x75))
-       x77 := (x57 + x76)
-       x78 := (x56 + x77)
-       x79 := (x55 + x78)
-       x80 := (x54 + x79)
-       x81 := (x53 + x80)
-       x82 := (x52 + x81)
-       x83 := (x82 & 0x3ffffffffffffff)
-       x84 := uint8((x82 >> 58))
-       x85 := (x51 + uint64(x84))
-       x86 := (x50 + x85)
-       x87 := (x49 + x86)
-       x88 := (x48 + x87)
-       x89 := (x47 + x88)
-       x90 := (x46 + x89)
-       x91 := (x45 + x90)
-       x92 := (x91 & 0x3ffffffffffffff)
-       x93 := uint8((x91 >> 58))
-       x94 := (x44 + uint64(x93))
-       x95 := (x43 + x94)
-       x96 := (x42 + x95)
-       x97 := (x41 + x96)
-       x98 := (x40 + x97)
-       x99 := (x39 + x98)
-       x100 := (x38 + x99)
-       x101 := (x36 + uint64(x37))
-       x102 := (x35 + x101)
-       x103 := (x34 + x102)
-       x104 := (x33 + x103)
-       x105 := (x32 + x104)
-       x106 := (x31 + x105)
-       x107 := (x30 + x106)
-       x108 := (x107 & 0x3ffffffffffffff)
-       x109 := uint8((x107 >> 58))
-       x110 := (x29 + uint64(x109))
-       x111 := (x28 + x110)
-       x112 := (x27 + x111)
-       x113 := (x26 + x112)
-       x114 := (x25 + x113)
-       x115 := (x24 + x114)
-       x116 := (x23 + x115)
-       x117 := (x116 & 0x3ffffffffffffff)
-       x118 := uint8((x116 >> 58))
-       x119 := (x22 + uint64(x118))
-       x120 := (x21 + x119)
-       x121 := (x20 + x120)
-       x122 := (x19 + x121)
-       x123 := (x18 + x122)
-       x124 := (x17 + x123)
-       x125 := (x16 + x124)
-       x126 := (x125 & 0x3ffffffffffffff)
-       x127 := uint8((x125 >> 58))
-       x128 := (x15 + uint64(x127))
-       x129 := (x14 + x128)
-       x130 := (x13 + x129)
-       x131 := (x12 + x130)
-       x132 := (x11 + x131)
-       x133 := (x10 + x132)
-       x134 := (x9 + x133)
-       x135 := (x7 + uint64(x8))
-       x136 := (x6 + x135)
-       x137 := (x5 + x136)
-       x138 := (x4 + x137)
-       x139 := (x3 + x138)
-       x140 := (x2 + x139)
-       x141 := (x1 + x140)
-       out1[0] = x74
-       out1[1] = x83
-       out1[2] = x92
-       out1[3] = x100
-       out1[4] = x108
-       out1[5] = x117
-       out1[6] = x126
-       out1[7] = x134
-       out1[8] = x141
-}
-
-// p521Selectznz is a multi-limb conditional select.
-//
-// Postconditions:
-//   eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
-//
-// Input Bounds:
-//   arg1: [0x0 ~> 0x1]
-//   arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
-//   arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
-// Output Bounds:
-//   out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
-func p521Selectznz(out1 *[9]uint64, arg1 p521Uint1, arg2 *[9]uint64, arg3 *[9]uint64) {
-       var x1 uint64
-       p521CmovznzU64(&x1, arg1, arg2[0], arg3[0])
-       var x2 uint64
-       p521CmovznzU64(&x2, arg1, arg2[1], arg3[1])
-       var x3 uint64
-       p521CmovznzU64(&x3, arg1, arg2[2], arg3[2])
-       var x4 uint64
-       p521CmovznzU64(&x4, arg1, arg2[3], arg3[3])
-       var x5 uint64
-       p521CmovznzU64(&x5, arg1, arg2[4], arg3[4])
-       var x6 uint64
-       p521CmovznzU64(&x6, arg1, arg2[5], arg3[5])
-       var x7 uint64
-       p521CmovznzU64(&x7, arg1, arg2[6], arg3[6])
-       var x8 uint64
-       p521CmovznzU64(&x8, arg1, arg2[7], arg3[7])
-       var x9 uint64
-       p521CmovznzU64(&x9, arg1, arg2[8], arg3[8])
-       out1[0] = x1
-       out1[1] = x2
-       out1[2] = x3
-       out1[3] = x4
-       out1[4] = x5
-       out1[5] = x6
-       out1[6] = x7
-       out1[7] = x8
-       out1[8] = x9
+       x74 := (x57 + uint64(x58))
+       x75 := (x56 + x74)
+       x76 := (x55 + x75)
+       x77 := (x54 + x76)
+       x78 := (x53 + x77)
+       x79 := (x52 + x78)
+       x80 := (x51 + x79)
+       x81 := (x49 + uint64(x50))
+       x82 := (x48 + x81)
+       x83 := (x47 + x82)
+       x84 := (x46 + x83)
+       x85 := (x45 + x84)
+       x86 := (x44 + x85)
+       x87 := (x43 + x86)
+       x88 := (x41 + uint64(x42))
+       x89 := (x40 + x88)
+       x90 := (x39 + x89)
+       x91 := (x38 + x90)
+       x92 := (x37 + x91)
+       x93 := (x36 + x92)
+       x94 := (x35 + x93)
+       x95 := (x33 + uint64(x34))
+       x96 := (x32 + x95)
+       x97 := (x31 + x96)
+       x98 := (x30 + x97)
+       x99 := (x29 + x98)
+       x100 := (x28 + x99)
+       x101 := (x27 + x100)
+       x102 := (x25 + uint64(x26))
+       x103 := (x24 + x102)
+       x104 := (x23 + x103)
+       x105 := (x22 + x104)
+       x106 := (x21 + x105)
+       x107 := (x20 + x106)
+       x108 := (x19 + x107)
+       x109 := (x17 + uint64(x18))
+       x110 := (x16 + x109)
+       x111 := (x15 + x110)
+       x112 := (x14 + x111)
+       x113 := (x13 + x112)
+       x114 := (x12 + x113)
+       x115 := (x11 + x114)
+       x116 := (x9 + uint64(x10))
+       x117 := (x8 + x116)
+       x118 := (x7 + x117)
+       x119 := (x6 + x118)
+       x120 := (x5 + x119)
+       x121 := (x4 + x120)
+       x122 := (x3 + x121)
+       x123 := (x1 + uint64(x2))
+       out1[0] = x73
+       out1[1] = x80
+       out1[2] = x87
+       out1[3] = x94
+       out1[4] = x101
+       out1[5] = x108
+       out1[6] = x115
+       out1[7] = x122
+       out1[8] = x123
 }
diff --git a/src/crypto/elliptic/internal/fiat/p521_invert.go b/src/crypto/elliptic/internal/fiat/p521_invert.go
new file mode 100644 (file)
index 0000000..407711a
--- /dev/null
@@ -0,0 +1,89 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by addchain. DO NOT EDIT.
+
+package fiat
+
+// Invert sets e = 1/x, and returns e.
+//
+// If x == 0, Invert returns e = 0.
+func (e *P521Element) Invert(x *P521Element) *P521Element {
+       // Inversion is implemented as exponentiation with exponent p โˆ’ 2.
+       // The sequence of 13 multiplications and 520 squarings is derived from the
+       // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0.
+       //
+       //      _10       = 2*1
+       //      _11       = 1 + _10
+       //      _1100     = _11 << 2
+       //      _1111     = _11 + _1100
+       //      _11110000 = _1111 << 4
+       //      _11111111 = _1111 + _11110000
+       //      x16       = _11111111 << 8 + _11111111
+       //      x32       = x16 << 16 + x16
+       //      x64       = x32 << 32 + x32
+       //      x65       = 2*x64 + 1
+       //      x129      = x65 << 64 + x64
+       //      x130      = 2*x129 + 1
+       //      x259      = x130 << 129 + x129
+       //      x260      = 2*x259 + 1
+       //      x519      = x260 << 259 + x259
+       //      return      x519 << 2 + 1
+       //
+
+       var z = new(P521Element).Set(e)
+       var t0 = new(P521Element)
+
+       z.Square(x)
+       z.Mul(x, z)
+       t0.Square(z)
+       for s := 1; s < 2; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       for s := 1; s < 4; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       for s := 1; s < 8; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       for s := 1; s < 16; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       for s := 1; s < 32; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       t0.Mul(x, t0)
+       for s := 0; s < 64; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       t0.Mul(x, t0)
+       for s := 0; s < 129; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       t0.Square(z)
+       t0.Mul(x, t0)
+       for s := 0; s < 259; s++ {
+               t0.Square(t0)
+       }
+       z.Mul(z, t0)
+       for s := 0; s < 2; s++ {
+               z.Square(z)
+       }
+       z.Mul(x, z)
+
+       return e.Set(z)
+}
diff --git a/src/crypto/elliptic/internal/fiat/p521_test.go b/src/crypto/elliptic/internal/fiat/p521_test.go
deleted file mode 100644 (file)
index 2b374fa..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package fiat_test
-
-import (
-       "crypto/elliptic/internal/fiat"
-       "crypto/rand"
-       "testing"
-)
-
-func p521Random(t *testing.T) *fiat.P521Element {
-       buf := make([]byte, 66)
-       if _, err := rand.Read(buf); err != nil {
-               t.Fatal(err)
-       }
-       buf[0] &= 1
-       e, err := new(fiat.P521Element).SetBytes(buf)
-       if err != nil {
-               t.Fatal(err)
-       }
-       return e
-}
-
-func TestP521Invert(t *testing.T) {
-       a := p521Random(t)
-       inv := new(fiat.P521Element).Invert(a)
-       one := new(fiat.P521Element).Mul(a, inv)
-       if new(fiat.P521Element).One().Equal(one) != 1 {
-               t.Errorf("a * 1/a != 1; got %x for %x", one.Bytes(), a.Bytes())
-       }
-       inv.Invert(new(fiat.P521Element))
-       if new(fiat.P521Element).Equal(inv) != 1 {
-               t.Errorf("1/0 != 0; got %x", inv.Bytes())
-       }
-}
diff --git a/src/crypto/elliptic/internal/nistec/nistec_test.go b/src/crypto/elliptic/internal/nistec/nistec_test.go
new file mode 100644 (file)
index 0000000..4eae998
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package nistec_test
+
+import (
+       "crypto/elliptic/internal/nistec"
+       "math/rand"
+       "os"
+       "strings"
+       "testing"
+)
+
+func TestAllocations(t *testing.T) {
+       if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") {
+               t.Skip("skipping allocations test without relevant optimizations")
+       }
+       t.Run("P224", func(t *testing.T) {
+               if allocs := testing.AllocsPerRun(100, func() {
+                       p := nistec.NewP224Generator()
+                       scalar := make([]byte, 66)
+                       rand.Read(scalar)
+                       p.ScalarMult(p, scalar)
+                       out := p.Bytes()
+                       if _, err := p.SetBytes(out); err != nil {
+                               t.Fatal(err)
+                       }
+               }); allocs > 0 {
+                       t.Errorf("expected zero allocations, got %0.1f", allocs)
+               }
+       })
+       t.Run("P384", func(t *testing.T) {
+               if allocs := testing.AllocsPerRun(100, func() {
+                       p := nistec.NewP384Generator()
+                       scalar := make([]byte, 66)
+                       rand.Read(scalar)
+                       p.ScalarMult(p, scalar)
+                       out := p.Bytes()
+                       if _, err := p.SetBytes(out); err != nil {
+                               t.Fatal(err)
+                       }
+               }); allocs > 0 {
+                       t.Errorf("expected zero allocations, got %0.1f", allocs)
+               }
+       })
+       t.Run("P521", func(t *testing.T) {
+               if allocs := testing.AllocsPerRun(100, func() {
+                       p := nistec.NewP521Generator()
+                       scalar := make([]byte, 66)
+                       rand.Read(scalar)
+                       p.ScalarMult(p, scalar)
+                       out := p.Bytes()
+                       if _, err := p.SetBytes(out); err != nil {
+                               t.Fatal(err)
+                       }
+               }); allocs > 0 {
+                       t.Errorf("expected zero allocations, got %0.1f", allocs)
+               }
+       })
+}
+
+func BenchmarkScalarMult(b *testing.B) {
+       b.Run("P224", func(b *testing.B) {
+               scalar := make([]byte, 66)
+               rand.Read(scalar)
+               p := nistec.NewP224Generator()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       p.ScalarMult(p, scalar)
+               }
+       })
+       b.Run("P384", func(b *testing.B) {
+               scalar := make([]byte, 66)
+               rand.Read(scalar)
+               p := nistec.NewP384Generator()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       p.ScalarMult(p, scalar)
+               }
+       })
+       b.Run("P521", func(b *testing.B) {
+               scalar := make([]byte, 66)
+               rand.Read(scalar)
+               p := nistec.NewP521Generator()
+               b.ReportAllocs()
+               b.ResetTimer()
+               for i := 0; i < b.N; i++ {
+                       p.ScalarMult(p, scalar)
+               }
+       })
+}
diff --git a/src/crypto/elliptic/internal/nistec/p224.go b/src/crypto/elliptic/internal/nistec/p224.go
new file mode 100644 (file)
index 0000000..74dbc18
--- /dev/null
@@ -0,0 +1,293 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package nistec
+
+import (
+       "crypto/elliptic/internal/fiat"
+       "crypto/subtle"
+       "errors"
+)
+
+var p224B, _ = new(fiat.P224Element).SetBytes([]byte{0xb4, 0x05, 0x0a, 0x85,
+       0x0c, 0x04, 0xb3, 0xab, 0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7,
+       0xd7, 0xbf, 0xd8, 0xba, 0x27, 0x0b, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4})
+
+var p224G, _ = NewP224Point().SetBytes([]byte{0x04,
+       0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9,
+       0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6,
+       0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb,
+       0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64,
+       0x44, 0xd5, 0x81, 0x99, 0x85, 0x0, 0x7e, 0x34})
+
+const p224ElementLength = 28
+
+// P224Point is a P-224 point. The zero value is NOT valid.
+type P224Point struct {
+       // The point is represented in projective coordinates (X:Y:Z),
+       // where x = X/Z and y = Y/Z.
+       x, y, z *fiat.P224Element
+}
+
+// NewP224Point returns a new P224Point representing the point at infinity point.
+func NewP224Point() *P224Point {
+       return &P224Point{
+               x: new(fiat.P224Element),
+               y: new(fiat.P224Element).One(),
+               z: new(fiat.P224Element),
+       }
+}
+
+// NewP224Generator returns a new P224Point set to the canonical generator.
+func NewP224Generator() *P224Point {
+       return (&P224Point{
+               x: new(fiat.P224Element),
+               y: new(fiat.P224Element),
+               z: new(fiat.P224Element),
+       }).Set(p224G)
+}
+
+// Set sets p = q and returns p.
+func (p *P224Point) Set(q *P224Point) *P224Point {
+       p.x.Set(q.x)
+       p.y.Set(q.y)
+       p.z.Set(q.z)
+       return p
+}
+
+// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in
+// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on
+// the curve, it returns nil and an error, and the receiver is unchanged.
+// Otherwise, it returns p.
+func (p *P224Point) SetBytes(b []byte) (*P224Point, error) {
+       switch {
+       // Point at infinity.
+       case len(b) == 1 && b[0] == 0:
+               return p.Set(NewP224Point()), nil
+
+       // Uncompressed form.
+       case len(b) == 1+2*p224ElementLength && b[0] == 4:
+               x, err := new(fiat.P224Element).SetBytes(b[1 : 1+p224ElementLength])
+               if err != nil {
+                       return nil, err
+               }
+               y, err := new(fiat.P224Element).SetBytes(b[1+p224ElementLength:])
+               if err != nil {
+                       return nil, err
+               }
+               if err := p224CheckOnCurve(x, y); err != nil {
+                       return nil, err
+               }
+               p.x.Set(x)
+               p.y.Set(y)
+               p.z.One()
+               return p, nil
+
+       // Compressed form
+       case len(b) == 1+p224ElementLength && b[0] == 0:
+               return nil, errors.New("unimplemented") // TODO(filippo)
+
+       default:
+               return nil, errors.New("invalid P224 point encoding")
+       }
+}
+
+func p224CheckOnCurve(x, y *fiat.P224Element) error {
+       // xยณ - 3x + b.
+       x3 := new(fiat.P224Element).Square(x)
+       x3.Mul(x3, x)
+
+       threeX := new(fiat.P224Element).Add(x, x)
+       threeX.Add(threeX, x)
+
+       x3.Sub(x3, threeX)
+       x3.Add(x3, p224B)
+
+       // yยฒ = xยณ - 3x + b
+       y2 := new(fiat.P224Element).Square(y)
+
+       if x3.Equal(y2) != 1 {
+               return errors.New("P224 point not on curve")
+       }
+       return nil
+}
+
+// Bytes returns the uncompressed or infinity encoding of p, as specified in
+// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at
+// infinity is shorter than all other encodings.
+func (p *P224Point) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [133]byte
+       return p.bytes(&out)
+}
+
+func (p *P224Point) bytes(out *[133]byte) []byte {
+       if p.z.IsZero() == 1 {
+               return append(out[:0], 0)
+       }
+
+       zinv := new(fiat.P224Element).Invert(p.z)
+       xx := new(fiat.P224Element).Mul(p.x, zinv)
+       yy := new(fiat.P224Element).Mul(p.y, zinv)
+
+       buf := append(out[:0], 4)
+       buf = append(buf, xx.Bytes()...)
+       buf = append(buf, yy.Bytes()...)
+       return buf
+}
+
+// Add sets q = p1 + p2, and returns q. The points may overlap.
+func (q *P224Point) Add(p1, p2 *P224Point) *P224Point {
+       // Complete addition formula for a = -3 from "Complete addition formulas for
+       // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), ยงA.2.
+
+       t0 := new(fiat.P224Element).Mul(p1.x, p2.x) // t0 := X1 * X2
+       t1 := new(fiat.P224Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2
+       t2 := new(fiat.P224Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2
+       t3 := new(fiat.P224Element).Add(p1.x, p1.y) // t3 := X1 + Y1
+       t4 := new(fiat.P224Element).Add(p2.x, p2.y) // t4 := X2 + Y2
+       t3.Mul(t3, t4)                              // t3 := t3 * t4
+       t4.Add(t0, t1)                              // t4 := t0 + t1
+       t3.Sub(t3, t4)                              // t3 := t3 - t4
+       t4.Add(p1.y, p1.z)                          // t4 := Y1 + Z1
+       x3 := new(fiat.P224Element).Add(p2.y, p2.z) // X3 := Y2 + Z2
+       t4.Mul(t4, x3)                              // t4 := t4 * X3
+       x3.Add(t1, t2)                              // X3 := t1 + t2
+       t4.Sub(t4, x3)                              // t4 := t4 - X3
+       x3.Add(p1.x, p1.z)                          // X3 := X1 + Z1
+       y3 := new(fiat.P224Element).Add(p2.x, p2.z) // Y3 := X2 + Z2
+       x3.Mul(x3, y3)                              // X3 := X3 * Y3
+       y3.Add(t0, t2)                              // Y3 := t0 + t2
+       y3.Sub(x3, y3)                              // Y3 := X3 - Y3
+       z3 := new(fiat.P224Element).Mul(p224B, t2)  // Z3 := b * t2
+       x3.Sub(y3, z3)                              // X3 := Y3 - Z3
+       z3.Add(x3, x3)                              // Z3 := X3 + X3
+       x3.Add(x3, z3)                              // X3 := X3 + Z3
+       z3.Sub(t1, x3)                              // Z3 := t1 - X3
+       x3.Add(t1, x3)                              // X3 := t1 + X3
+       y3.Mul(p224B, y3)                           // Y3 := b * Y3
+       t1.Add(t2, t2)                              // t1 := t2 + t2
+       t2.Add(t1, t2)                              // t2 := t1 + t2
+       y3.Sub(y3, t2)                              // Y3 := Y3 - t2
+       y3.Sub(y3, t0)                              // Y3 := Y3 - t0
+       t1.Add(y3, y3)                              // t1 := Y3 + Y3
+       y3.Add(t1, y3)                              // Y3 := t1 + Y3
+       t1.Add(t0, t0)                              // t1 := t0 + t0
+       t0.Add(t1, t0)                              // t0 := t1 + t0
+       t0.Sub(t0, t2)                              // t0 := t0 - t2
+       t1.Mul(t4, y3)                              // t1 := t4 * Y3
+       t2.Mul(t0, y3)                              // t2 := t0 * Y3
+       y3.Mul(x3, z3)                              // Y3 := X3 * Z3
+       y3.Add(y3, t2)                              // Y3 := Y3 + t2
+       x3.Mul(t3, x3)                              // X3 := t3 * X3
+       x3.Sub(x3, t1)                              // X3 := X3 - t1
+       z3.Mul(t4, z3)                              // Z3 := t4 * Z3
+       t1.Mul(t3, t0)                              // t1 := t3 * t0
+       z3.Add(z3, t1)                              // Z3 := Z3 + t1
+
+       q.x.Set(x3)
+       q.y.Set(y3)
+       q.z.Set(z3)
+       return q
+}
+
+// Double sets q = p + p, and returns q. The points may overlap.
+func (q *P224Point) Double(p *P224Point) *P224Point {
+       // Complete addition formula for a = -3 from "Complete addition formulas for
+       // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), ยงA.2.
+
+       t0 := new(fiat.P224Element).Square(p.x)    // t0 := X ^ 2
+       t1 := new(fiat.P224Element).Square(p.y)    // t1 := Y ^ 2
+       t2 := new(fiat.P224Element).Square(p.z)    // t2 := Z ^ 2
+       t3 := new(fiat.P224Element).Mul(p.x, p.y)  // t3 := X * Y
+       t3.Add(t3, t3)                             // t3 := t3 + t3
+       z3 := new(fiat.P224Element).Mul(p.x, p.z)  // Z3 := X * Z
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+       y3 := new(fiat.P224Element).Mul(p224B, t2) // Y3 := b * t2
+       y3.Sub(y3, z3)                             // Y3 := Y3 - Z3
+       x3 := new(fiat.P224Element).Add(y3, y3)    // X3 := Y3 + Y3
+       y3.Add(x3, y3)                             // Y3 := X3 + Y3
+       x3.Sub(t1, y3)                             // X3 := t1 - Y3
+       y3.Add(t1, y3)                             // Y3 := t1 + Y3
+       y3.Mul(x3, y3)                             // Y3 := X3 * Y3
+       x3.Mul(x3, t3)                             // X3 := X3 * t3
+       t3.Add(t2, t2)                             // t3 := t2 + t2
+       t2.Add(t2, t3)                             // t2 := t2 + t3
+       z3.Mul(p224B, z3)                          // Z3 := b * Z3
+       z3.Sub(z3, t2)                             // Z3 := Z3 - t2
+       z3.Sub(z3, t0)                             // Z3 := Z3 - t0
+       t3.Add(z3, z3)                             // t3 := Z3 + Z3
+       z3.Add(z3, t3)                             // Z3 := Z3 + t3
+       t3.Add(t0, t0)                             // t3 := t0 + t0
+       t0.Add(t3, t0)                             // t0 := t3 + t0
+       t0.Sub(t0, t2)                             // t0 := t0 - t2
+       t0.Mul(t0, z3)                             // t0 := t0 * Z3
+       y3.Add(y3, t0)                             // Y3 := Y3 + t0
+       t0.Mul(p.y, p.z)                           // t0 := Y * Z
+       t0.Add(t0, t0)                             // t0 := t0 + t0
+       z3.Mul(t0, z3)                             // Z3 := t0 * Z3
+       x3.Sub(x3, z3)                             // X3 := X3 - Z3
+       z3.Mul(t0, t1)                             // Z3 := t0 * t1
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+
+       q.x.Set(x3)
+       q.y.Set(y3)
+       q.z.Set(z3)
+       return q
+}
+
+// Select sets q to p1 if cond == 1, and to p2 if cond == 0.
+func (q *P224Point) Select(p1, p2 *P224Point, cond int) *P224Point {
+       q.x.Select(p1.x, p2.x, cond)
+       q.y.Select(p1.y, p2.y, cond)
+       q.z.Select(p1.z, p2.z, cond)
+       return q
+}
+
+// ScalarMult sets p = scalar * q, and returns p.
+func (p *P224Point) ScalarMult(q *P224Point, scalar []byte) *P224Point {
+       // table holds the first 16 multiples of q. The explicit newP224Point calls
+       // get inlined, letting the allocations live on the stack.
+       var table = [16]*P224Point{
+               NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
+               NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
+               NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
+               NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
+       }
+       for i := 1; i < 16; i++ {
+               table[i].Add(table[i-1], q)
+       }
+
+       // Instead of doing the classic double-and-add chain, we do it with a
+       // four-bit window: we double four times, and then add [0-15]P.
+       t := NewP224Point()
+       p.Set(NewP224Point())
+       for _, byte := range scalar {
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+
+               for i := uint8(0); i < 16; i++ {
+                       cond := subtle.ConstantTimeByteEq(byte>>4, i)
+                       t.Select(table[i], t, cond)
+               }
+               p.Add(p, t)
+
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+
+               for i := uint8(0); i < 16; i++ {
+                       cond := subtle.ConstantTimeByteEq(byte&0b1111, i)
+                       t.Select(table[i], t, cond)
+               }
+               p.Add(p, t)
+       }
+
+       return p
+}
diff --git a/src/crypto/elliptic/internal/nistec/p384.go b/src/crypto/elliptic/internal/nistec/p384.go
new file mode 100644 (file)
index 0000000..24a166d
--- /dev/null
@@ -0,0 +1,298 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package nistec
+
+import (
+       "crypto/elliptic/internal/fiat"
+       "crypto/subtle"
+       "errors"
+)
+
+var p384B, _ = new(fiat.P384Element).SetBytes([]byte{
+       0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x05, 0x6b,
+       0xe3, 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12,
+       0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d,
+       0x8a, 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef})
+
+var p384G, _ = NewP384Point().SetBytes([]byte{0x4,
+       0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, 0x1e,
+       0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98,
+       0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x02, 0xf2, 0x5d,
+       0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7,
+       0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
+       0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
+       0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
+       0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f})
+
+const p384ElementLength = 48
+
+// P384Point is a P-384 point. The zero value is NOT valid.
+type P384Point struct {
+       // The point is represented in projective coordinates (X:Y:Z),
+       // where x = X/Z and y = Y/Z.
+       x, y, z *fiat.P384Element
+}
+
+// NewP384Point returns a new P384Point representing the point at infinity point.
+func NewP384Point() *P384Point {
+       return &P384Point{
+               x: new(fiat.P384Element),
+               y: new(fiat.P384Element).One(),
+               z: new(fiat.P384Element),
+       }
+}
+
+// NewP384Generator returns a new P384Point set to the canonical generator.
+func NewP384Generator() *P384Point {
+       return (&P384Point{
+               x: new(fiat.P384Element),
+               y: new(fiat.P384Element),
+               z: new(fiat.P384Element),
+       }).Set(p384G)
+}
+
+// Set sets p = q and returns p.
+func (p *P384Point) Set(q *P384Point) *P384Point {
+       p.x.Set(q.x)
+       p.y.Set(q.y)
+       p.z.Set(q.z)
+       return p
+}
+
+// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in
+// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on
+// the curve, it returns nil and an error, and the receiver is unchanged.
+// Otherwise, it returns p.
+func (p *P384Point) SetBytes(b []byte) (*P384Point, error) {
+       switch {
+       // Point at infinity.
+       case len(b) == 1 && b[0] == 0:
+               return p.Set(NewP384Point()), nil
+
+       // Uncompressed form.
+       case len(b) == 1+2*p384ElementLength && b[0] == 4:
+               x, err := new(fiat.P384Element).SetBytes(b[1 : 1+p384ElementLength])
+               if err != nil {
+                       return nil, err
+               }
+               y, err := new(fiat.P384Element).SetBytes(b[1+p384ElementLength:])
+               if err != nil {
+                       return nil, err
+               }
+               if err := p384CheckOnCurve(x, y); err != nil {
+                       return nil, err
+               }
+               p.x.Set(x)
+               p.y.Set(y)
+               p.z.One()
+               return p, nil
+
+       // Compressed form
+       case len(b) == 1+p384ElementLength && b[0] == 0:
+               return nil, errors.New("unimplemented") // TODO(filippo)
+
+       default:
+               return nil, errors.New("invalid P384 point encoding")
+       }
+}
+
+func p384CheckOnCurve(x, y *fiat.P384Element) error {
+       // xยณ - 3x + b.
+       x3 := new(fiat.P384Element).Square(x)
+       x3.Mul(x3, x)
+
+       threeX := new(fiat.P384Element).Add(x, x)
+       threeX.Add(threeX, x)
+
+       x3.Sub(x3, threeX)
+       x3.Add(x3, p384B)
+
+       // yยฒ = xยณ - 3x + b
+       y2 := new(fiat.P384Element).Square(y)
+
+       if x3.Equal(y2) != 1 {
+               return errors.New("P384 point not on curve")
+       }
+       return nil
+}
+
+// Bytes returns the uncompressed or infinity encoding of p, as specified in
+// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at
+// infinity is shorter than all other encodings.
+func (p *P384Point) Bytes() []byte {
+       // This function is outlined to make the allocations inline in the caller
+       // rather than happen on the heap.
+       var out [133]byte
+       return p.bytes(&out)
+}
+
+func (p *P384Point) bytes(out *[133]byte) []byte {
+       if p.z.IsZero() == 1 {
+               return append(out[:0], 0)
+       }
+
+       zinv := new(fiat.P384Element).Invert(p.z)
+       xx := new(fiat.P384Element).Mul(p.x, zinv)
+       yy := new(fiat.P384Element).Mul(p.y, zinv)
+
+       buf := append(out[:0], 4)
+       buf = append(buf, xx.Bytes()...)
+       buf = append(buf, yy.Bytes()...)
+       return buf
+}
+
+// Add sets q = p1 + p2, and returns q. The points may overlap.
+func (q *P384Point) Add(p1, p2 *P384Point) *P384Point {
+       // Complete addition formula for a = -3 from "Complete addition formulas for
+       // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), ยงA.2.
+
+       t0 := new(fiat.P384Element).Mul(p1.x, p2.x) // t0 := X1 * X2
+       t1 := new(fiat.P384Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2
+       t2 := new(fiat.P384Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2
+       t3 := new(fiat.P384Element).Add(p1.x, p1.y) // t3 := X1 + Y1
+       t4 := new(fiat.P384Element).Add(p2.x, p2.y) // t4 := X2 + Y2
+       t3.Mul(t3, t4)                              // t3 := t3 * t4
+       t4.Add(t0, t1)                              // t4 := t0 + t1
+       t3.Sub(t3, t4)                              // t3 := t3 - t4
+       t4.Add(p1.y, p1.z)                          // t4 := Y1 + Z1
+       x3 := new(fiat.P384Element).Add(p2.y, p2.z) // X3 := Y2 + Z2
+       t4.Mul(t4, x3)                              // t4 := t4 * X3
+       x3.Add(t1, t2)                              // X3 := t1 + t2
+       t4.Sub(t4, x3)                              // t4 := t4 - X3
+       x3.Add(p1.x, p1.z)                          // X3 := X1 + Z1
+       y3 := new(fiat.P384Element).Add(p2.x, p2.z) // Y3 := X2 + Z2
+       x3.Mul(x3, y3)                              // X3 := X3 * Y3
+       y3.Add(t0, t2)                              // Y3 := t0 + t2
+       y3.Sub(x3, y3)                              // Y3 := X3 - Y3
+       z3 := new(fiat.P384Element).Mul(p384B, t2)  // Z3 := b * t2
+       x3.Sub(y3, z3)                              // X3 := Y3 - Z3
+       z3.Add(x3, x3)                              // Z3 := X3 + X3
+       x3.Add(x3, z3)                              // X3 := X3 + Z3
+       z3.Sub(t1, x3)                              // Z3 := t1 - X3
+       x3.Add(t1, x3)                              // X3 := t1 + X3
+       y3.Mul(p384B, y3)                           // Y3 := b * Y3
+       t1.Add(t2, t2)                              // t1 := t2 + t2
+       t2.Add(t1, t2)                              // t2 := t1 + t2
+       y3.Sub(y3, t2)                              // Y3 := Y3 - t2
+       y3.Sub(y3, t0)                              // Y3 := Y3 - t0
+       t1.Add(y3, y3)                              // t1 := Y3 + Y3
+       y3.Add(t1, y3)                              // Y3 := t1 + Y3
+       t1.Add(t0, t0)                              // t1 := t0 + t0
+       t0.Add(t1, t0)                              // t0 := t1 + t0
+       t0.Sub(t0, t2)                              // t0 := t0 - t2
+       t1.Mul(t4, y3)                              // t1 := t4 * Y3
+       t2.Mul(t0, y3)                              // t2 := t0 * Y3
+       y3.Mul(x3, z3)                              // Y3 := X3 * Z3
+       y3.Add(y3, t2)                              // Y3 := Y3 + t2
+       x3.Mul(t3, x3)                              // X3 := t3 * X3
+       x3.Sub(x3, t1)                              // X3 := X3 - t1
+       z3.Mul(t4, z3)                              // Z3 := t4 * Z3
+       t1.Mul(t3, t0)                              // t1 := t3 * t0
+       z3.Add(z3, t1)                              // Z3 := Z3 + t1
+
+       q.x.Set(x3)
+       q.y.Set(y3)
+       q.z.Set(z3)
+       return q
+}
+
+// Double sets q = p + p, and returns q. The points may overlap.
+func (q *P384Point) Double(p *P384Point) *P384Point {
+       // Complete addition formula for a = -3 from "Complete addition formulas for
+       // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), ยงA.2.
+
+       t0 := new(fiat.P384Element).Square(p.x)    // t0 := X ^ 2
+       t1 := new(fiat.P384Element).Square(p.y)    // t1 := Y ^ 2
+       t2 := new(fiat.P384Element).Square(p.z)    // t2 := Z ^ 2
+       t3 := new(fiat.P384Element).Mul(p.x, p.y)  // t3 := X * Y
+       t3.Add(t3, t3)                             // t3 := t3 + t3
+       z3 := new(fiat.P384Element).Mul(p.x, p.z)  // Z3 := X * Z
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+       y3 := new(fiat.P384Element).Mul(p384B, t2) // Y3 := b * t2
+       y3.Sub(y3, z3)                             // Y3 := Y3 - Z3
+       x3 := new(fiat.P384Element).Add(y3, y3)    // X3 := Y3 + Y3
+       y3.Add(x3, y3)                             // Y3 := X3 + Y3
+       x3.Sub(t1, y3)                             // X3 := t1 - Y3
+       y3.Add(t1, y3)                             // Y3 := t1 + Y3
+       y3.Mul(x3, y3)                             // Y3 := X3 * Y3
+       x3.Mul(x3, t3)                             // X3 := X3 * t3
+       t3.Add(t2, t2)                             // t3 := t2 + t2
+       t2.Add(t2, t3)                             // t2 := t2 + t3
+       z3.Mul(p384B, z3)                          // Z3 := b * Z3
+       z3.Sub(z3, t2)                             // Z3 := Z3 - t2
+       z3.Sub(z3, t0)                             // Z3 := Z3 - t0
+       t3.Add(z3, z3)                             // t3 := Z3 + Z3
+       z3.Add(z3, t3)                             // Z3 := Z3 + t3
+       t3.Add(t0, t0)                             // t3 := t0 + t0
+       t0.Add(t3, t0)                             // t0 := t3 + t0
+       t0.Sub(t0, t2)                             // t0 := t0 - t2
+       t0.Mul(t0, z3)                             // t0 := t0 * Z3
+       y3.Add(y3, t0)                             // Y3 := Y3 + t0
+       t0.Mul(p.y, p.z)                           // t0 := Y * Z
+       t0.Add(t0, t0)                             // t0 := t0 + t0
+       z3.Mul(t0, z3)                             // Z3 := t0 * Z3
+       x3.Sub(x3, z3)                             // X3 := X3 - Z3
+       z3.Mul(t0, t1)                             // Z3 := t0 * t1
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+       z3.Add(z3, z3)                             // Z3 := Z3 + Z3
+
+       q.x.Set(x3)
+       q.y.Set(y3)
+       q.z.Set(z3)
+       return q
+}
+
+// Select sets q to p1 if cond == 1, and to p2 if cond == 0.
+func (q *P384Point) Select(p1, p2 *P384Point, cond int) *P384Point {
+       q.x.Select(p1.x, p2.x, cond)
+       q.y.Select(p1.y, p2.y, cond)
+       q.z.Select(p1.z, p2.z, cond)
+       return q
+}
+
+// ScalarMult sets p = scalar * q, and returns p.
+func (p *P384Point) ScalarMult(q *P384Point, scalar []byte) *P384Point {
+       // table holds the first 16 multiples of q. The explicit newP384Point calls
+       // get inlined, letting the allocations live on the stack.
+       var table = [16]*P384Point{
+               NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(),
+               NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(),
+               NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(),
+               NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(),
+       }
+       for i := 1; i < 16; i++ {
+               table[i].Add(table[i-1], q)
+       }
+
+       // Instead of doing the classic double-and-add chain, we do it with a
+       // four-bit window: we double four times, and then add [0-15]P.
+       t := NewP384Point()
+       p.Set(NewP384Point())
+       for _, byte := range scalar {
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+
+               for i := uint8(0); i < 16; i++ {
+                       cond := subtle.ConstantTimeByteEq(byte>>4, i)
+                       t.Select(table[i], t, cond)
+               }
+               p.Add(p, t)
+
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+               p.Double(p)
+
+               for i := uint8(0); i < 16; i++ {
+                       cond := subtle.ConstantTimeByteEq(byte&0b1111, i)
+                       t.Select(table[i], t, cond)
+               }
+               p.Add(p, t)
+       }
+
+       return p
+}
index e5b4e46d4b6ae39e5cd1a2e3c911460353534581..cdbd195cf436a4bcd660e1f3c36845a839d0781f 100644 (file)
@@ -58,7 +58,11 @@ func NewP521Point() *P521Point {
 
 // NewP521Generator returns a new P521Point set to the canonical generator.
 func NewP521Generator() *P521Point {
-       return NewP521Point().Set(p521G)
+       return (&P521Point{
+               x: new(fiat.P521Element),
+               y: new(fiat.P521Element),
+               z: new(fiat.P521Element),
+       }).Set(p521G)
 }
 
 // Set sets p = q and returns p.
diff --git a/src/crypto/elliptic/internal/nistec/p521_test.go b/src/crypto/elliptic/internal/nistec/p521_test.go
deleted file mode 100644 (file)
index e62c1cb..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package nistec_test
-
-import (
-       "crypto/elliptic/internal/nistec"
-       "math/rand"
-       "os"
-       "strings"
-       "testing"
-)
-
-func TestP521Allocations(t *testing.T) {
-       if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") {
-               t.Skip("skipping allocations test without relevant optimizations")
-       }
-       if allocs := testing.AllocsPerRun(100, func() {
-               p := nistec.NewP521Generator()
-               scalar := make([]byte, 66)
-               rand.Read(scalar)
-               p.ScalarMult(p, scalar)
-               out := p.Bytes()
-               if _, err := p.SetBytes(out); err != nil {
-                       t.Fatal(err)
-               }
-       }); allocs > 0 {
-               t.Errorf("expected zero allocations, got %0.1f", allocs)
-       }
-}
-
-func BenchmarkScalarMult(b *testing.B) {
-       b.Run("P521", func(b *testing.B) {
-               scalar := make([]byte, 66)
-               rand.Read(scalar)
-               p := nistec.NewP521Generator()
-               b.ReportAllocs()
-               b.ResetTimer()
-               for i := 0; i < b.N; i++ {
-                       p.ScalarMult(p, scalar)
-               }
-       })
-}
index 34079d14b12496c7ba375e7a1452ff0b67d1816e..a8533b85ff4c35f471374eed02752e6c22776f4e 100644 (file)
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
 package elliptic
 
-// This is a constant-time, 32-bit implementation of P224. See FIPS 186-3,
-// section D.2.2.
-//
-// See https://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
-
 import (
-       "encoding/binary"
+       "crypto/elliptic/internal/nistec"
+       "crypto/rand"
        "math/big"
-       "math/bits"
 )
 
-var p224 p224Curve
-
-type p224Curve struct {
-       *CurveParams
-       gx, gy, b p224FieldElement
-}
-
-func initP224() {
-       // See FIPS 186-3, section D.2.2
-       p224.CurveParams = &CurveParams{Name: "P-224"}
-       p224.P, _ = new(big.Int).SetString("26959946667150639794667015087019630673557916260026308143510066298881", 10)
-       p224.N, _ = new(big.Int).SetString("26959946667150639794667015087019625940457807714424391721682722368061", 10)
-       p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16)
-       p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16)
-       p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16)
-       p224.BitSize = 224
-
-       p224FromBig(&p224.gx, p224.Gx)
-       p224FromBig(&p224.gy, p224.Gy)
-       p224FromBig(&p224.b, p224.B)
-}
-
-// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2).
-//
-// The cryptographic operations are implemented using constant-time algorithms.
-func P224() Curve {
-       initonce.Do(initAll)
-       return p224
-}
-
-func (curve p224Curve) Params() *CurveParams {
-       return curve.CurveParams
-}
-
-func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool {
-       if bigX.BitLen() > 224 || bigY.BitLen() > 224 {
-               return false
-       }
-
-       var x, y p224FieldElement
-       p224FromBig(&x, bigX)
-       p224FromBig(&y, bigY)
-
-       // yยฒ = xยณ - 3x + b
-       var tmp p224LargeFieldElement
-       var x3 p224FieldElement
-       p224Square(&x3, &x, &tmp)
-       p224Mul(&x3, &x3, &x, &tmp)
-
-       for i := 0; i < 8; i++ {
-               x[i] *= 3
-       }
-       p224Sub(&x3, &x3, &x)
-       p224Reduce(&x3)
-       p224Add(&x3, &x3, &curve.b)
-       p224Contract(&x3, &x3)
-
-       p224Square(&y, &y, &tmp)
-       p224Contract(&y, &y)
-
-       for i := 0; i < 8; i++ {
-               if y[i] != x3[i] {
-                       return false
-               }
-       }
-       return true
-}
-
-func (p224Curve) Add(bigX1, bigY1, bigX2, bigY2 *big.Int) (x, y *big.Int) {
-       var x1, y1, z1, x2, y2, z2, x3, y3, z3 p224FieldElement
-
-       p224FromBig(&x1, bigX1)
-       p224FromBig(&y1, bigY1)
-       if bigX1.Sign() != 0 || bigY1.Sign() != 0 {
-               z1[0] = 1
-       }
-       p224FromBig(&x2, bigX2)
-       p224FromBig(&y2, bigY2)
-       if bigX2.Sign() != 0 || bigY2.Sign() != 0 {
-               z2[0] = 1
-       }
-
-       p224AddJacobian(&x3, &y3, &z3, &x1, &y1, &z1, &x2, &y2, &z2)
-       return p224ToAffine(&x3, &y3, &z3)
-}
-
-func (p224Curve) Double(bigX1, bigY1 *big.Int) (x, y *big.Int) {
-       var x1, y1, z1, x2, y2, z2 p224FieldElement
-
-       p224FromBig(&x1, bigX1)
-       p224FromBig(&y1, bigY1)
-       z1[0] = 1
-
-       p224DoubleJacobian(&x2, &y2, &z2, &x1, &y1, &z1)
-       return p224ToAffine(&x2, &y2, &z2)
-}
-
-func (p224Curve) ScalarMult(bigX1, bigY1 *big.Int, scalar []byte) (x, y *big.Int) {
-       var x1, y1, z1, x2, y2, z2 p224FieldElement
-
-       p224FromBig(&x1, bigX1)
-       p224FromBig(&y1, bigY1)
-       z1[0] = 1
-
-       p224ScalarMult(&x2, &y2, &z2, &x1, &y1, &z1, scalar)
-       return p224ToAffine(&x2, &y2, &z2)
-}
-
-func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
-       var z1, x2, y2, z2 p224FieldElement
-
-       z1[0] = 1
-       p224ScalarMult(&x2, &y2, &z2, &curve.gx, &curve.gy, &z1, scalar)
-       return p224ToAffine(&x2, &y2, &z2)
-}
-
-// Field element functions.
-//
-// The field that we're dealing with is โ„ค/pโ„ค where p = 2**224 - 2**96 + 1.
-//
-// Field elements are represented by a FieldElement, which is a typedef to an
-// array of 8 uint32's. The value of a FieldElement, a, is:
-//   a[0] + 2**28ยทa[1] + 2**56ยทa[1] + ... + 2**196ยทa[7]
-//
-// Using 28-bit limbs means that there's only 4 bits of headroom, which is less
-// than we would really like. But it has the useful feature that we hit 2**224
-// exactly, making the reflections during a reduce much nicer.
-type p224FieldElement [8]uint32
-
-// p224P is the order of the field, represented as a p224FieldElement.
-var p224P = p224FieldElement{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
-
-// p224IsZero returns 1 if a == 0 mod p and 0 otherwise.
+// p224Curve is a Curve implementation based on nistec.P224Point.
 //
-// a[i] < 2**29
-func p224IsZero(a *p224FieldElement) uint32 {
-       var minimal p224FieldElement
-       p224Contract(&minimal, a)
-
-       var acc uint32
-       for _, v := range minimal {
-               acc |= v
-       }
-       mask := ^maskIsNotZero(acc)
-
-       return 1 & mask
-}
-
-// p224Add computes *out = a+b
+// It's a wrapper that exposes the big.Int-based Curve interface and encodes the
+// legacy idiosyncrasies it requires, such as invalid and infinity point
+// handling.
 //
-// a[i] + b[i] < 2**32
-func p224Add(out, a, b *p224FieldElement) {
-       for i := 0; i < 8; i++ {
-               out[i] = a[i] + b[i]
-       }
-}
-
-const two31p3 = 1<<31 + 1<<3
-const two31m3 = 1<<31 - 1<<3
-const two31m15m3 = 1<<31 - 1<<15 - 1<<3
-
-// p224ZeroModP31 is 0 mod p where bit 31 is set in all limbs so that we can
-// subtract smaller amounts without underflow. See the section "Subtraction" in
-// [1] for reasoning.
-//
-// To calculate this value, start by adding 2ยณยน to the lowest limb and
-// subtracting 2ยณ from the next one to compensate. Repeat for each next limb,
-// ending up with 2ยณยน - 2ยณ in each of them, and a carry of -2ยณ. Apply the
-// reduction identity, and we need to subtract 2ยณ * 2โนโถ - 2ยณ = 2ยนโต * 2โธโด - 2ยณ so
-// we subtract 2ยนโต from the 4th limb and add 2ยณ to the first limb.
-var p224ZeroModP31 = []uint32{two31p3, two31m3, two31m3, two31m15m3, two31m3, two31m3, two31m3, two31m3}
-
-// p224Sub computes *out = a-b
-//
-// a[i], b[i] < 2**30
-// out[i] < 2**32
-func p224Sub(out, a, b *p224FieldElement) {
-       for i := 0; i < 8; i++ {
-               out[i] = a[i] + p224ZeroModP31[i] - b[i]
-       }
-}
-
-// LargeFieldElement also represents an element of the field. The limbs are
-// still spaced 28-bits apart and in little-endian order. So the limbs are at
-// 0, 28, 56, ..., 392 bits, each 64-bits wide.
-type p224LargeFieldElement [15]uint64
-
-const two63p35 = 1<<63 + 1<<35
-const two63m35 = 1<<63 - 1<<35
-const two63m35m19 = 1<<63 - 1<<35 - 1<<19
-
-// p224ZeroModP63 is 0 mod p where bit 63 is set in all limbs. See the section
-// "Subtraction" in [1] for why.
-var p224ZeroModP63 = [8]uint64{two63p35, two63m35, two63m35, two63m35, two63m35m19, two63m35, two63m35, two63m35}
-
-const bottom12Bits = 0xfff
-const bottom28Bits = 0xfffffff
-
-// p224Mul computes *out = a*b
-//
-// a[i] < 2**29, b[i] < 2**30 (or vice versa)
-// out[i] < 2**29
-func p224Mul(out, a, b *p224FieldElement, tmp *p224LargeFieldElement) {
-       for i := range tmp {
-               tmp[i] = 0
-       }
-
-       for i := 0; i < 8; i++ {
-               for j := 0; j < 8; j++ {
-                       tmp[i+j] += uint64(a[i]) * uint64(b[j])
-               }
-       }
-
-       p224ReduceLarge(out, tmp)
-}
-
-// Square computes *out = a*a
-//
-// a[i] < 2**29
-// out[i] < 2**29
-func p224Square(out, a *p224FieldElement, tmp *p224LargeFieldElement) {
-       for i := range tmp {
-               tmp[i] = 0
-       }
-
-       for i := 0; i < 8; i++ {
-               for j := 0; j <= i; j++ {
-                       r := uint64(a[i]) * uint64(a[j])
-                       if i == j {
-                               tmp[i+j] += r
-                       } else {
-                               tmp[i+j] += r * 2
-                       }
-               }
-       }
-
-       p224ReduceLarge(out, tmp)
+// To interact with the nistec package, points are encoded into and decoded from
+// properly formatted byte slices. All big.Int use is limited to this package.
+// Encoding and decoding is 1/1000th of the runtime of a scalar multiplication,
+// so the overhead is acceptable.
+type p224Curve struct {
+       params *CurveParams
 }
 
-// ReduceLarge converts a p224LargeFieldElement to a p224FieldElement.
-//
-// in[i] < 2**62
-// out[i] < 2**29
-func p224ReduceLarge(out *p224FieldElement, in *p224LargeFieldElement) {
-       for i := 0; i < 8; i++ {
-               in[i] += p224ZeroModP63[i]
-       }
-
-       // Eliminate the coefficients at 2**224 and greater by applying the
-       // reduction identity.
-       //
-       //   a + top * 2ยฒยฒโด = a + top * 2โนโถ - top
-       //
-       // Since top here is in[8..14], both the subtraction at offset 0 and the
-       // addition at offset 96 (3 * 28 + 16) span multiple limbs. The subtraction
-       // can't underflow because of the p224ZeroModP63 addition above, while the
-       // addition can't overflow because of the 62 bit input bounds.
-       for i := 14; i >= 8; i-- {
-               in[i-8] -= in[i]
-               in[i-5] += (in[i] & 0xffff) << 12
-               in[i-4] += in[i] >> 16
-       }
-       in[8] = 0
-       // in[0..7] < 2**64
-       // in[9..14] discarded
-
-       // Run a carry chain and light reduction. Keep [0] large so we can do the
-       // subtraction safely. As the values become small enough, we start to store
-       // them in out and use 32-bit operations.
-       for i := 1; i < 8; i++ {
-               in[i+1] += in[i] >> 28
-               out[i] = uint32(in[i] & bottom28Bits)
-       }
-       in[0] -= in[8]
-       out[3] += uint32(in[8]&0xffff) << 12
-       out[4] += uint32(in[8] >> 16)
-       // in[0] < 2**64
-       // out[3] < 2**29
-       // out[4] < 2**29
-       // out[1,2,5..7] < 2**28
-
-       // Carry the overflow of [0] into the short 28 bit limbs.
-       out[0] = uint32(in[0] & bottom28Bits)
-       out[1] += uint32((in[0] >> 28) & bottom28Bits)
-       out[2] += uint32(in[0] >> 56)
-       // out[0] < 2**28
-       // out[1..4] < 2**29
-       // out[5..7] < 2**28
-}
+var p224 p224Curve
+var _ Curve = p224
 
-// Reduce reduces the coefficients of a to smaller bounds.
-//
-// On entry: a[i] < 2**31 + 2**30
-// On exit: a[i] < 2**29
-func p224Reduce(a *p224FieldElement) {
-       for i := 0; i < 7; i++ {
-               a[i+1] += a[i] >> 28
-               a[i] &= bottom28Bits
+func initP224() {
+       p224.params = &CurveParams{
+               Name:    "P-224",
+               BitSize: 224,
+               // FIPS 186-4, section D.1.2.2
+               P:  bigFromDecimal("26959946667150639794667015087019630673557916260026308143510066298881"),
+               N:  bigFromDecimal("26959946667150639794667015087019625940457807714424391721682722368061"),
+               B:  bigFromHex("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"),
+               Gx: bigFromHex("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"),
+               Gy: bigFromHex("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"),
        }
-       top := a[7] >> 28
-       a[7] &= bottom28Bits
-
-       a[0] -= top
-       a[3] += top << 12
-
-       // We may have just made a[0] negative but if we did top must have been not
-       // zero, so a[3] is not zero, so we can carry down to a[0]. (Note that we
-       // don't actually check if a[0] went negative, like in p224Contract, nor we
-       // try to stop the carry at a[1] or a[2], because here we can afford to go
-       // above 28 bits, so instead we carry all the way down from a[3].)
-       mask := maskIsNotZero(top)
-       a[3] -= 1 & mask
-       a[2] += mask & (1<<28 - 1)
-       a[1] += mask & (1<<28 - 1)
-       a[0] += mask & (1 << 28)
 }
 
-// p224Invert calculates *out = in**-1 by using Fermat's little theorem and
-// computing in**(p-2) = in**(2**224 - 2**96 - 1).
-func p224Invert(out, in *p224FieldElement) {
-       var f1, f2, f3, f4 p224FieldElement
-       var c p224LargeFieldElement
-
-       p224Square(&f1, in, &c)    // 2
-       p224Mul(&f1, &f1, in, &c)  // 2**2 - 1
-       p224Square(&f1, &f1, &c)   // 2**3 - 2
-       p224Mul(&f1, &f1, in, &c)  // 2**3 - 1
-       p224Square(&f2, &f1, &c)   // 2**4 - 2
-       p224Square(&f2, &f2, &c)   // 2**5 - 4
-       p224Square(&f2, &f2, &c)   // 2**6 - 8
-       p224Mul(&f1, &f1, &f2, &c) // 2**6 - 1
-       p224Square(&f2, &f1, &c)   // 2**7 - 2
-       for i := 0; i < 5; i++ {   // 2**12 - 2**6
-               p224Square(&f2, &f2, &c)
-       }
-       p224Mul(&f2, &f2, &f1, &c) // 2**12 - 1
-       p224Square(&f3, &f2, &c)   // 2**13 - 2
-       for i := 0; i < 11; i++ {  // 2**24 - 2**12
-               p224Square(&f3, &f3, &c)
-       }
-       p224Mul(&f2, &f3, &f2, &c) // 2**24 - 1
-       p224Square(&f3, &f2, &c)   // 2**25 - 2
-       for i := 0; i < 23; i++ {  // 2**48 - 2**24
-               p224Square(&f3, &f3, &c)
-       }
-       p224Mul(&f3, &f3, &f2, &c) // 2**48 - 1
-       p224Square(&f4, &f3, &c)   // 2**49 - 2
-       for i := 0; i < 47; i++ {  // 2**96 - 2**48
-               p224Square(&f4, &f4, &c)
-       }
-       p224Mul(&f3, &f3, &f4, &c) // 2**96 - 1
-       p224Square(&f4, &f3, &c)   // 2**97 - 2
-       for i := 0; i < 23; i++ {  // 2**120 - 2**24
-               p224Square(&f4, &f4, &c)
-       }
-       p224Mul(&f2, &f4, &f2, &c) // 2**120 - 1
-       for i := 0; i < 6; i++ {   // 2**126 - 2**6
-               p224Square(&f2, &f2, &c)
-       }
-       p224Mul(&f1, &f1, &f2, &c) // 2**126 - 1
-       p224Square(&f1, &f1, &c)   // 2**127 - 2
-       p224Mul(&f1, &f1, in, &c)  // 2**127 - 1
-       for i := 0; i < 97; i++ {  // 2**224 - 2**97
-               p224Square(&f1, &f1, &c)
-       }
-       p224Mul(out, &f1, &f3, &c) // 2**224 - 2**96 - 1
+func (curve p224Curve) Params() *CurveParams {
+       return curve.params
 }
 
-// p224Contract converts a FieldElement to its unique, minimal form.
-//
-// On entry, in[i] < 2**29
-// On exit, out[i] < 2**28 and out < p
-func p224Contract(out, in *p224FieldElement) {
-       copy(out[:], in[:])
-
-       // First, carry the bits above 28 to the higher limb.
-       for i := 0; i < 7; i++ {
-               out[i+1] += out[i] >> 28
-               out[i] &= bottom28Bits
-       }
-       top := out[7] >> 28
-       out[7] &= bottom28Bits
-
-       // Use the reduction identity to carry the overflow.
-       //
-       //   a + top * 2ยฒยฒโด = a + top * 2โนโถ - top
-       out[0] -= top
-       out[3] += top << 12
-
-       // We may just have made out[0] negative. So we carry down. If we made
-       // out[0] negative then we know that out[3] is sufficiently positive
-       // because we just added to it.
-       for i := 0; i < 3; i++ {
-               mask := maskIsNegative(out[i])
-               out[i] += (1 << 28) & mask
-               out[i+1] -= 1 & mask
-       }
-
-       // We might have pushed out[3] over 2**28 so we perform another, partial,
-       // carry chain; carry the overflow according to the reduction identity; and
-       // carry down in case we made out[0] negative.
-       for i := 3; i < 7; i++ {
-               out[i+1] += out[i] >> 28
-               out[i] &= bottom28Bits
-       }
-       top = out[7] >> 28
-       out[7] &= bottom28Bits
-
-       out[0] -= top
-       out[3] += top << 12
-
-       for i := 0; i < 3; i++ {
-               mask := maskIsNegative(out[i])
-               out[i] += (1 << 28) & mask
-               out[i+1] -= 1 & mask
-       }
-
-       // There are two cases to consider for out[3]:
-       //   1) The first time that we eliminated top, we didn't push out[3] over
-       //      2**28. In this case, the partial carry chain didn't change any values
-       //      and top is now zero.
-       //   2) We did push out[3] over 2**28 the first time that we eliminated top.
-       //      The first value of top was in [0..2], therefore, after overflowing
-       //      and being reduced by the second carry chain, out[3] <= 2<<12 - 1.
-       // In both cases, out[3] cannot have overflowed when we eliminated top for
-       // the second time.
-
-       // Now we need to subtract p if the value is >= p. To check, we subtract p
-       // with a borrow chain and look at the final borrow bit.
-       var b uint32
-       for i := 0; i < len(out); i++ {
-               _, b = bits.Sub32(out[i], p224P[i], b)
-       }
-       mask := ^maskIsNotZero(b)
-
-       out[0] -= 1 & mask
-       out[3] -= 0xffff000 & mask
-       out[4] -= 0xfffffff & mask
-       out[5] -= 0xfffffff & mask
-       out[6] -= 0xfffffff & mask
-       out[7] -= 0xfffffff & mask
-
-       // Do one final carry down, in case we made out[0] negative. One of
-       // out[0..3] needs to be positive and able to absorb the -1 or the value
-       // would have been < p, and the subtraction wouldn't have happened.
-       for i := 0; i < 3; i++ {
-               mask := maskIsNegative(out[i])
-               out[i] += (1 << 28) & mask
-               out[i+1] -= 1 & mask
+func (curve p224Curve) IsOnCurve(x, y *big.Int) bool {
+       // IsOnCurve is documented to reject (0, 0), the conventional point at
+       // infinity, which however is accepted by p224PointFromAffine.
+       if x.Sign() == 0 && y.Sign() == 0 {
+               return false
        }
+       _, ok := p224PointFromAffine(x, y)
+       return ok
 }
 
-// maskIsNegative returns 0xffffffff if the most significant bit of v is set,
-// and 0 otherwise.
-func maskIsNegative(v uint32) uint32 { return uint32(int32(v) >> 31) }
-
-// maskIfNegative returns 0xffffffff if v is not zero, and 0 otherwise.
-func maskIsNotZero(v uint32) uint32 {
-       v |= v >> 16
-       v |= v >> 8
-       v |= v >> 4
-       v |= v >> 2
-       v |= v >> 1
-       return uint32(int32(v<<31) >> 31)
-}
-
-// Group element functions.
-//
-// These functions deal with group elements. The group is an elliptic curve
-// group with a = -3 defined in FIPS 186-3, section D.2.2.
-
-// p224AddJacobian computes *out = a+b where a != b.
-func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
-       // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-p224Add-2007-bl
-       var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement
-       var c p224LargeFieldElement
-
-       z1IsZero := p224IsZero(z1)
-       z2IsZero := p224IsZero(z2)
-
-       // Z1Z1 = Z1ยฒ
-       p224Square(&z1z1, z1, &c)
-       // Z2Z2 = Z2ยฒ
-       p224Square(&z2z2, z2, &c)
-       // U1 = X1*Z2Z2
-       p224Mul(&u1, x1, &z2z2, &c)
-       // U2 = X2*Z1Z1
-       p224Mul(&u2, x2, &z1z1, &c)
-       // S1 = Y1*Z2*Z2Z2
-       p224Mul(&s1, z2, &z2z2, &c)
-       p224Mul(&s1, y1, &s1, &c)
-       // S2 = Y2*Z1*Z1Z1
-       p224Mul(&s2, z1, &z1z1, &c)
-       p224Mul(&s2, y2, &s2, &c)
-       // H = U2-U1
-       p224Sub(&h, &u2, &u1)
-       p224Reduce(&h)
-       xEqual := p224IsZero(&h)
-       // I = (2*H)ยฒ
-       for j := 0; j < 8; j++ {
-               i[j] = h[j] << 1
-       }
-       p224Reduce(&i)
-       p224Square(&i, &i, &c)
-       // J = H*I
-       p224Mul(&j, &h, &i, &c)
-       // r = 2*(S2-S1)
-       p224Sub(&r, &s2, &s1)
-       p224Reduce(&r)
-       yEqual := p224IsZero(&r)
-       if xEqual == 1 && yEqual == 1 && z1IsZero == 0 && z2IsZero == 0 {
-               p224DoubleJacobian(x3, y3, z3, x1, y1, z1)
-               return
-       }
-       for i := 0; i < 8; i++ {
-               r[i] <<= 1
+func p224PointFromAffine(x, y *big.Int) (p *nistec.P224Point, ok bool) {
+       // (0, 0) is by convention the point at infinity, which can't be represented
+       // in affine coordinates. Marshal incorrectly encodes it as an uncompressed
+       // point, which SetBytes would correctly reject. See Issue 37294.
+       if x.Sign() == 0 && y.Sign() == 0 {
+               return nistec.NewP224Point(), true
        }
-       p224Reduce(&r)
-       // V = U1*I
-       p224Mul(&v, &u1, &i, &c)
-       // Z3 = ((Z1+Z2)ยฒ-Z1Z1-Z2Z2)*H
-       p224Add(&z1z1, &z1z1, &z2z2)
-       p224Add(&z2z2, z1, z2)
-       p224Reduce(&z2z2)
-       p224Square(&z2z2, &z2z2, &c)
-       p224Sub(z3, &z2z2, &z1z1)
-       p224Reduce(z3)
-       p224Mul(z3, z3, &h, &c)
-       // X3 = rยฒ-J-2*V
-       for i := 0; i < 8; i++ {
-               z1z1[i] = v[i] << 1
+       if x.BitLen() > 224 || y.BitLen() > 224 {
+               return nil, false
        }
-       p224Add(&z1z1, &j, &z1z1)
-       p224Reduce(&z1z1)
-       p224Square(x3, &r, &c)
-       p224Sub(x3, x3, &z1z1)
-       p224Reduce(x3)
-       // Y3 = r*(V-X3)-2*S1*J
-       for i := 0; i < 8; i++ {
-               s1[i] <<= 1
+       p, err := nistec.NewP224Point().SetBytes(Marshal(P224(), x, y))
+       if err != nil {
+               return nil, false
        }
-       p224Mul(&s1, &s1, &j, &c)
-       p224Sub(&z1z1, &v, x3)
-       p224Reduce(&z1z1)
-       p224Mul(&z1z1, &z1z1, &r, &c)
-       p224Sub(y3, &z1z1, &s1)
-       p224Reduce(y3)
-
-       p224CopyConditional(x3, x2, z1IsZero)
-       p224CopyConditional(x3, x1, z2IsZero)
-       p224CopyConditional(y3, y2, z1IsZero)
-       p224CopyConditional(y3, y1, z2IsZero)
-       p224CopyConditional(z3, z2, z1IsZero)
-       p224CopyConditional(z3, z1, z2IsZero)
+       return p, true
 }
 
-// p224DoubleJacobian computes *out = a+a.
-func p224DoubleJacobian(x3, y3, z3, x1, y1, z1 *p224FieldElement) {
-       var delta, gamma, beta, alpha, t p224FieldElement
-       var c p224LargeFieldElement
-
-       p224Square(&delta, z1, &c)
-       p224Square(&gamma, y1, &c)
-       p224Mul(&beta, x1, &gamma, &c)
-
-       // alpha = 3*(X1-delta)*(X1+delta)
-       p224Add(&t, x1, &delta)
-       for i := 0; i < 8; i++ {
-               t[i] += t[i] << 1
-       }
-       p224Reduce(&t)
-       p224Sub(&alpha, x1, &delta)
-       p224Reduce(&alpha)
-       p224Mul(&alpha, &alpha, &t, &c)
-
-       // Z3 = (Y1+Z1)ยฒ-gamma-delta
-       p224Add(z3, y1, z1)
-       p224Reduce(z3)
-       p224Square(z3, z3, &c)
-       p224Sub(z3, z3, &gamma)
-       p224Reduce(z3)
-       p224Sub(z3, z3, &delta)
-       p224Reduce(z3)
-
-       // X3 = alphaยฒ-8*beta
-       for i := 0; i < 8; i++ {
-               delta[i] = beta[i] << 3
-       }
-       p224Reduce(&delta)
-       p224Square(x3, &alpha, &c)
-       p224Sub(x3, x3, &delta)
-       p224Reduce(x3)
-
-       // Y3 = alpha*(4*beta-X3)-8*gammaยฒ
-       for i := 0; i < 8; i++ {
-               beta[i] <<= 2
+func p224PointToAffine(p *nistec.P224Point) (x, y *big.Int) {
+       out := p.Bytes()
+       if len(out) == 1 && out[0] == 0 {
+               // This is the correct encoding of the point at infinity, which
+               // Unmarshal does not support. See Issue 37294.
+               return new(big.Int), new(big.Int)
        }
-       p224Sub(&beta, &beta, x3)
-       p224Reduce(&beta)
-       p224Square(&gamma, &gamma, &c)
-       for i := 0; i < 8; i++ {
-               gamma[i] <<= 3
+       x, y = Unmarshal(P224(), out)
+       if x == nil {
+               panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding")
        }
-       p224Reduce(&gamma)
-       p224Mul(y3, &alpha, &beta, &c)
-       p224Sub(y3, y3, &gamma)
-       p224Reduce(y3)
+       return x, y
 }
 
-// p224CopyConditional sets *out = *in in constant time if control is not zero.
-func p224CopyConditional(out, in *p224FieldElement, control uint32) {
-       mask := maskIsNotZero(control)
-       for i := 0; i < 8; i++ {
-               out[i] ^= (out[i] ^ in[i]) & mask
+// p224RandomPoint returns a random point on the curve. It's used when Add,
+// Double, or ScalarMult are fed a point not on the curve, which is undefined
+// behavior. Originally, we used to do the math on it anyway (which allows
+// invalid curve attacks) and relied on the caller and Unmarshal to avoid this
+// happening in the first place. Now, we just can't construct a nistec.P224Point
+// for an invalid pair of coordinates, because that API is safer. If we panic,
+// we risk introducing a DoS. If we return nil, we risk a panic. If we return
+// the input, ecdsa.Verify might fail open. The safest course seems to be to
+// return a valid, random point, which hopefully won't help the attacker.
+func p224RandomPoint() (x, y *big.Int) {
+       _, x, y, err := GenerateKey(P224(), rand.Reader)
+       if err != nil {
+               panic("crypto/elliptic: failed to generate random point")
        }
+       return x, y
 }
 
-func p224ScalarMult(outX, outY, outZ, inX, inY, inZ *p224FieldElement, scalar []byte) {
-       var xx, yy, zz p224FieldElement
-       for i := 0; i < 8; i++ {
-               outX[i] = 0
-               outY[i] = 0
-               outZ[i] = 0
+func (p224Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+       p1, ok := p224PointFromAffine(x1, y1)
+       if !ok {
+               return p224RandomPoint()
        }
-
-       for _, byte := range scalar {
-               for bitNum := uint(0); bitNum < 8; bitNum++ {
-                       p224DoubleJacobian(outX, outY, outZ, outX, outY, outZ)
-                       bit := uint32((byte >> (7 - bitNum)) & 1)
-                       p224AddJacobian(&xx, &yy, &zz, inX, inY, inZ, outX, outY, outZ)
-                       p224CopyConditional(outX, &xx, bit)
-                       p224CopyConditional(outY, &yy, bit)
-                       p224CopyConditional(outZ, &zz, bit)
-               }
+       p2, ok := p224PointFromAffine(x2, y2)
+       if !ok {
+               return p224RandomPoint()
        }
+       return p224PointToAffine(p1.Add(p1, p2))
 }
 
-// p224ToAffine converts from Jacobian to affine form.
-func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) {
-       var zinv, zinvsq, outx, outy p224FieldElement
-       var tmp p224LargeFieldElement
-
-       if isPointAtInfinity := p224IsZero(z); isPointAtInfinity == 1 {
-               return new(big.Int), new(big.Int)
+func (p224Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+       p, ok := p224PointFromAffine(x1, y1)
+       if !ok {
+               return p224RandomPoint()
        }
-
-       p224Invert(&zinv, z)
-       p224Square(&zinvsq, &zinv, &tmp)
-       p224Mul(x, x, &zinvsq, &tmp)
-       p224Mul(&zinvsq, &zinvsq, &zinv, &tmp)
-       p224Mul(y, y, &zinvsq, &tmp)
-
-       p224Contract(&outx, x)
-       p224Contract(&outy, y)
-       return p224ToBig(&outx), p224ToBig(&outy)
+       return p224PointToAffine(p.Double(p))
 }
 
-// get28BitsFromEnd returns the least-significant 28 bits from buf>>shift,
-// where buf is interpreted as a big-endian number. shift must be at most
-// 4 bits higher than a multiple of 8.
-func get28BitsFromEnd(buf []byte, shift int) uint32 {
-       buf = buf[:len(buf)-shift/8]
-       shift = shift % 8
-       if shift > 4 {
-               panic("misuse of get28BitsFromEnd")
+func (p224Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
+       p, ok := p224PointFromAffine(Bx, By)
+       if !ok {
+               return p224RandomPoint()
        }
-
-       ret := binary.BigEndian.Uint32(buf[len(buf)-4:])
-       ret >>= shift
-       ret &= bottom28Bits
-       return ret
+       return p224PointToAffine(p.ScalarMult(p, scalar))
 }
 
-// p224FromBig sets *out = *in.
-func p224FromBig(out *p224FieldElement, in *big.Int) {
-       bytes := in.FillBytes(make([]byte, 224/8))
-       for i := range out {
-               out[i] = get28BitsFromEnd(bytes, 28*i)
-       }
-}
-
-// p224ToBig returns in as a big.Int.
-func p224ToBig(in *p224FieldElement) *big.Int {
-       var buf [28]byte
-       buf[27] = byte(in[0])
-       buf[26] = byte(in[0] >> 8)
-       buf[25] = byte(in[0] >> 16)
-       buf[24] = byte(((in[0] >> 24) & 0x0f) | (in[1]<<4)&0xf0)
-
-       buf[23] = byte(in[1] >> 4)
-       buf[22] = byte(in[1] >> 12)
-       buf[21] = byte(in[1] >> 20)
-
-       buf[20] = byte(in[2])
-       buf[19] = byte(in[2] >> 8)
-       buf[18] = byte(in[2] >> 16)
-       buf[17] = byte(((in[2] >> 24) & 0x0f) | (in[3]<<4)&0xf0)
-
-       buf[16] = byte(in[3] >> 4)
-       buf[15] = byte(in[3] >> 12)
-       buf[14] = byte(in[3] >> 20)
-
-       buf[13] = byte(in[4])
-       buf[12] = byte(in[4] >> 8)
-       buf[11] = byte(in[4] >> 16)
-       buf[10] = byte(((in[4] >> 24) & 0x0f) | (in[5]<<4)&0xf0)
-
-       buf[9] = byte(in[5] >> 4)
-       buf[8] = byte(in[5] >> 12)
-       buf[7] = byte(in[5] >> 20)
-
-       buf[6] = byte(in[6])
-       buf[5] = byte(in[6] >> 8)
-       buf[4] = byte(in[6] >> 16)
-       buf[3] = byte(((in[6] >> 24) & 0x0f) | (in[7]<<4)&0xf0)
-
-       buf[2] = byte(in[7] >> 4)
-       buf[1] = byte(in[7] >> 12)
-       buf[0] = byte(in[7] >> 20)
-
-       return new(big.Int).SetBytes(buf[:])
+func (p224Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) {
+       p := nistec.NewP224Generator()
+       return p224PointToAffine(p.ScalarMult(p, scalar))
 }
index 3e0c78b0f9c0de2993efbb83832ff3cde161f75b..7971f631bf2a31b433d8c1bb0056c7cc59db9d02 100644 (file)
@@ -8,313 +8,9 @@ import (
        "encoding/hex"
        "fmt"
        "math/big"
-       "math/bits"
-       "math/rand"
-       "reflect"
        "testing"
-       "testing/quick"
 )
 
-var toFromBigTests = []string{
-       "0",
-       "1",
-       "23",
-       "b70e0cb46bb4bf7f321390b94a03c1d356c01122343280d6105c1d21",
-       "706a46d476dcb76798e6046d89474788d164c18032d268fd10704fa6",
-}
-
-func p224AlternativeToBig(in *p224FieldElement) *big.Int {
-       ret := new(big.Int)
-       tmp := new(big.Int)
-
-       for i := len(in) - 1; i >= 0; i-- {
-               ret.Lsh(ret, 28)
-               tmp.SetInt64(int64(in[i]))
-               ret.Add(ret, tmp)
-       }
-       ret.Mod(ret, P224().Params().P)
-       return ret
-}
-
-func TestP224ToFromBig(t *testing.T) {
-       for i, test := range toFromBigTests {
-               n, _ := new(big.Int).SetString(test, 16)
-               var x p224FieldElement
-               p224FromBig(&x, n)
-               m := p224ToBig(&x)
-               if n.Cmp(m) != 0 {
-                       t.Errorf("#%d: %x != %x", i, n, m)
-               }
-               q := p224AlternativeToBig(&x)
-               if n.Cmp(q) != 0 {
-                       t.Errorf("#%d: %x != %x (alternative)", i, n, q)
-               }
-       }
-}
-
-// quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks)
-// times. The default value of -quickchecks is 100.
-var quickCheckConfig32 = &quick.Config{MaxCountScale: 32}
-
-// weirdLimbs can be combined to generate a range of edge-case field elements.
-var weirdLimbs = [...]uint32{
-       0, 1, (1 << 29) - 1,
-       (1 << 12), (1 << 12) - 1,
-       (1 << 28), (1 << 28) - 1,
-}
-
-func generateLimb(rand *rand.Rand) uint32 {
-       const bottom29Bits = 0x1fffffff
-       n := rand.Intn(len(weirdLimbs) + 3)
-       switch n {
-       case len(weirdLimbs):
-               // Random value.
-               return uint32(rand.Int31n(1 << 29))
-       case len(weirdLimbs) + 1:
-               // Sum of two values.
-               k := generateLimb(rand) + generateLimb(rand)
-               return k & bottom29Bits
-       case len(weirdLimbs) + 2:
-               // Difference of two values.
-               k := generateLimb(rand) - generateLimb(rand)
-               return k & bottom29Bits
-       default:
-               return weirdLimbs[n]
-       }
-}
-
-func (p224FieldElement) Generate(rand *rand.Rand, size int) reflect.Value {
-       return reflect.ValueOf(p224FieldElement{
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-               generateLimb(rand),
-       })
-}
-
-func isInBounds(x *p224FieldElement) bool {
-       return bits.Len32(x[0]) <= 29 &&
-               bits.Len32(x[1]) <= 29 &&
-               bits.Len32(x[2]) <= 29 &&
-               bits.Len32(x[3]) <= 29 &&
-               bits.Len32(x[4]) <= 29 &&
-               bits.Len32(x[5]) <= 29 &&
-               bits.Len32(x[6]) <= 29 &&
-               bits.Len32(x[7]) <= 29
-}
-
-func TestP224Mul(t *testing.T) {
-       mulMatchesBigInt := func(a, b, out p224FieldElement) bool {
-               var tmp p224LargeFieldElement
-               p224Mul(&out, &a, &b, &tmp)
-
-               exp := new(big.Int).Mul(p224AlternativeToBig(&a), p224AlternativeToBig(&b))
-               exp.Mod(exp, P224().Params().P)
-               got := p224AlternativeToBig(&out)
-               if exp.Cmp(got) != 0 || !isInBounds(&out) {
-                       t.Logf("a = %x", a)
-                       t.Logf("b = %x", b)
-                       t.Logf("p224Mul(a, b) = %x = %v", out, got)
-                       t.Logf("a * b = %v", exp)
-                       return false
-               }
-
-               return true
-       }
-
-       a := p224FieldElement{0xfffffff, 0xfffffff, 0xf00ffff, 0x20f, 0x0, 0x0, 0x0, 0x0}
-       b := p224FieldElement{1, 0, 0, 0, 0, 0, 0, 0}
-       if !mulMatchesBigInt(a, b, p224FieldElement{}) {
-               t.Fail()
-       }
-
-       if err := quick.Check(mulMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224Square(t *testing.T) {
-       squareMatchesBigInt := func(a, out p224FieldElement) bool {
-               var tmp p224LargeFieldElement
-               p224Square(&out, &a, &tmp)
-
-               exp := p224AlternativeToBig(&a)
-               exp.Mul(exp, exp)
-               exp.Mod(exp, P224().Params().P)
-               got := p224AlternativeToBig(&out)
-               if exp.Cmp(got) != 0 || !isInBounds(&out) {
-                       t.Logf("a = %x", a)
-                       t.Logf("p224Square(a, b) = %x = %v", out, got)
-                       t.Logf("a * a = %v", exp)
-                       return false
-               }
-
-               return true
-       }
-
-       if err := quick.Check(squareMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224Add(t *testing.T) {
-       addMatchesBigInt := func(a, b, out p224FieldElement) bool {
-               p224Add(&out, &a, &b)
-
-               exp := new(big.Int).Add(p224AlternativeToBig(&a), p224AlternativeToBig(&b))
-               exp.Mod(exp, P224().Params().P)
-               got := p224AlternativeToBig(&out)
-               if exp.Cmp(got) != 0 {
-                       t.Logf("a = %x", a)
-                       t.Logf("b = %x", b)
-                       t.Logf("p224Add(a, b) = %x = %v", out, got)
-                       t.Logf("a + b = %v", exp)
-                       return false
-               }
-
-               return true
-       }
-
-       if err := quick.Check(addMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224Reduce(t *testing.T) {
-       reduceMatchesBigInt := func(a p224FieldElement) bool {
-               out := a
-               // TODO: generate higher values for functions like p224Reduce that are
-               // expected to work with higher input bounds.
-               p224Reduce(&out)
-
-               exp := p224AlternativeToBig(&a)
-               got := p224AlternativeToBig(&out)
-               if exp.Cmp(got) != 0 || !isInBounds(&out) {
-                       t.Logf("a = %x = %v", a, exp)
-                       t.Logf("p224Reduce(a) = %x = %v", out, got)
-                       return false
-               }
-
-               return true
-       }
-
-       if err := quick.Check(reduceMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224Contract(t *testing.T) {
-       contractMatchesBigInt := func(a, out p224FieldElement) bool {
-               p224Contract(&out, &a)
-
-               exp := p224AlternativeToBig(&a)
-               got := p224AlternativeToBig(&out)
-               if exp.Cmp(got) != 0 {
-                       t.Logf("a = %x = %v", a, exp)
-                       t.Logf("p224Contract(a) = %x = %v", out, got)
-                       return false
-               }
-
-               // Check that out < P.
-               for i := range p224P {
-                       k := 8 - i - 1
-                       if out[k] > p224P[k] {
-                               t.Logf("p224Contract(a) = %x", out)
-                               return false
-                       }
-                       if out[k] < p224P[k] {
-                               return true
-                       }
-               }
-               t.Logf("p224Contract(a) = %x", out)
-               return false
-       }
-
-       if !contractMatchesBigInt(p224P, p224FieldElement{}) {
-               t.Error("p224Contract(p) is broken")
-       }
-       pMinus1 := p224FieldElement{0, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
-       if !contractMatchesBigInt(pMinus1, p224FieldElement{}) {
-               t.Error("p224Contract(p - 1) is broken")
-       }
-       // Check that we can handle input above p, but lowest limb zero.
-       a := p224FieldElement{0, 1, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
-       if !contractMatchesBigInt(a, p224FieldElement{}) {
-               t.Error("p224Contract(p + 2ยฒโธ) is broken")
-       }
-       // Check that we can handle input above p, but lowest three limbs zero.
-       b := p224FieldElement{0, 0, 0, 0xffff001, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
-       if !contractMatchesBigInt(b, p224FieldElement{}) {
-               t.Error("p224Contract(p + 2โธโด) is broken")
-       }
-
-       if err := quick.Check(contractMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224IsZero(t *testing.T) {
-       if got := p224IsZero(&p224FieldElement{}); got != 1 {
-               t.Errorf("p224IsZero(0) = %d, expected 1", got)
-       }
-       if got := p224IsZero(&p224P); got != 1 {
-               t.Errorf("p224IsZero(p) = %d, expected 1", got)
-       }
-       if got := p224IsZero(&p224FieldElement{1}); got != 0 {
-               t.Errorf("p224IsZero(1) = %d, expected 0", got)
-       }
-
-       isZeroMatchesBigInt := func(a p224FieldElement) bool {
-               isZero := p224IsZero(&a)
-
-               big := p224AlternativeToBig(&a)
-               if big.Sign() == 0 && isZero != 1 {
-                       return false
-               }
-               if big.Sign() != 0 && isZero != 0 {
-                       return false
-               }
-               return true
-       }
-
-       if err := quick.Check(isZeroMatchesBigInt, quickCheckConfig32); err != nil {
-               t.Error(err)
-       }
-}
-
-func TestP224Invert(t *testing.T) {
-       var out p224FieldElement
-
-       p224Invert(&out, &p224FieldElement{})
-       if got := p224IsZero(&out); got != 1 {
-               t.Errorf("p224Invert(0) = %x, expected 0", out)
-       }
-
-       p224Invert(&out, &p224P)
-       if got := p224IsZero(&out); got != 1 {
-               t.Errorf("p224Invert(p) = %x, expected 0", out)
-       }
-
-       p224Invert(&out, &p224FieldElement{1})
-       p224Contract(&out, &out)
-       if out != (p224FieldElement{1}) {
-               t.Errorf("p224Invert(1) = %x, expected 1", out)
-       }
-
-       var tmp p224LargeFieldElement
-       a := p224FieldElement{1, 2, 3, 4, 5, 6, 7, 8}
-       p224Invert(&out, &a)
-       p224Mul(&out, &out, &a, &tmp)
-       p224Contract(&out, &out)
-       if out != (p224FieldElement{1}) {
-               t.Errorf("p224Invert(a) * a = %x, expected 1", out)
-       }
-}
-
 type baseMultTest struct {
        k    string
        x, y string
@@ -602,7 +298,7 @@ func TestP224BaseMult(t *testing.T) {
 
 func TestP224GenericBaseMult(t *testing.T) {
        // We use the P224 CurveParams directly in order to test the generic implementation.
-       p224 := P224().Params()
+       p224 := genericParamsForCurve(P224())
        for i, e := range p224BaseMultTests {
                k, ok := new(big.Int).SetString(e.k, 10)
                if !ok {
index 7747de7a50bb3855800576f391f8b9c3678a81f4..7ff7e335487509e54a11cc5c6720e80103bd0d1c 100644 (file)
@@ -209,6 +209,8 @@ var p256Precomputed = [p256Limbs * 2 * 15 * 2]uint32{
 
 // Field element operations:
 
+const bottom28Bits = 0xfffffff
+
 // nonZeroToAllOnes returns:
 //   0xffffffff for 0 < x <= 2**31
 //   0 for x == 0 or x > 2**31.
@@ -269,6 +271,7 @@ const (
        two30m2    = 1<<30 - 1<<2
        two30p13m2 = 1<<30 + 1<<13 - 1<<2
        two31m2    = 1<<31 - 1<<2
+       two31m3    = 1<<31 - 1<<3
        two31p24m2 = 1<<31 + 1<<24 - 1<<2
        two30m27m2 = 1<<30 - 1<<27 - 1<<2
 )
index 1435f5e1a58a8f9a7f1a9cffe7d5ca03f08f79c7..c6862d95476c6fb8d40b247dfad1aa1fba531fac 100644 (file)
@@ -34,7 +34,7 @@ var p256MultTests = []scalarMultTest{
 
 func TestP256BaseMult(t *testing.T) {
        p256 := P256()
-       p256Generic := p256.Params()
+       p256Generic := genericParamsForCurve(p256)
 
        scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1)
        for _, e := range p224BaseMultTests {
@@ -60,23 +60,6 @@ func TestP256BaseMult(t *testing.T) {
 
 func TestP256Mult(t *testing.T) {
        p256 := P256()
-       p256Generic := p256.Params()
-
-       for i, e := range p224BaseMultTests {
-               x, _ := new(big.Int).SetString(e.x, 16)
-               y, _ := new(big.Int).SetString(e.y, 16)
-               k, _ := new(big.Int).SetString(e.k, 10)
-
-               xx, yy := p256.ScalarMult(x, y, k.Bytes())
-               xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes())
-               if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 {
-                       t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2)
-               }
-               if testing.Short() && i > 5 {
-                       break
-               }
-       }
-
        for i, e := range p256MultTests {
                x, _ := new(big.Int).SetString(e.xIn, 16)
                y, _ := new(big.Int).SetString(e.yIn, 16)
diff --git a/src/crypto/elliptic/p384.go b/src/crypto/elliptic/p384.go
new file mode 100644 (file)
index 0000000..0fb7471
--- /dev/null
@@ -0,0 +1,141 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package elliptic
+
+import (
+       "crypto/elliptic/internal/nistec"
+       "crypto/rand"
+       "math/big"
+)
+
+// p384Curve is a Curve implementation based on nistec.P384Point.
+//
+// It's a wrapper that exposes the big.Int-based Curve interface and encodes the
+// legacy idiosyncrasies it requires, such as invalid and infinity point
+// handling.
+//
+// To interact with the nistec package, points are encoded into and decoded from
+// properly formatted byte slices. All big.Int use is limited to this package.
+// Encoding and decoding is 1/1000th of the runtime of a scalar multiplication,
+// so the overhead is acceptable.
+type p384Curve struct {
+       params *CurveParams
+}
+
+var p384 p384Curve
+var _ Curve = p384
+
+func initP384() {
+       p384.params = &CurveParams{
+               Name:    "P-384",
+               BitSize: 384,
+               // FIPS 186-4, section D.1.2.4
+               P: bigFromDecimal("394020061963944792122790401001436138050797392704654" +
+                       "46667948293404245721771496870329047266088258938001861606973112319"),
+               N: bigFromDecimal("394020061963944792122790401001436138050797392704654" +
+                       "46667946905279627659399113263569398956308152294913554433653942643"),
+               B: bigFromHex("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088" +
+                       "f5013875ac656398d8a2ed19d2a85c8edd3ec2aef"),
+               Gx: bigFromHex("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741" +
+                       "e082542a385502f25dbf55296c3a545e3872760ab7"),
+               Gy: bigFromHex("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da31" +
+                       "13b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"),
+       }
+}
+
+func (curve p384Curve) Params() *CurveParams {
+       return curve.params
+}
+
+func (curve p384Curve) IsOnCurve(x, y *big.Int) bool {
+       // IsOnCurve is documented to reject (0, 0), the conventional point at
+       // infinity, which however is accepted by p384PointFromAffine.
+       if x.Sign() == 0 && y.Sign() == 0 {
+               return false
+       }
+       _, ok := p384PointFromAffine(x, y)
+       return ok
+}
+
+func p384PointFromAffine(x, y *big.Int) (p *nistec.P384Point, ok bool) {
+       // (0, 0) is by convention the point at infinity, which can't be represented
+       // in affine coordinates. Marshal incorrectly encodes it as an uncompressed
+       // point, which SetBytes would correctly reject. See Issue 37294.
+       if x.Sign() == 0 && y.Sign() == 0 {
+               return nistec.NewP384Point(), true
+       }
+       if x.BitLen() > 384 || y.BitLen() > 384 {
+               return nil, false
+       }
+       p, err := nistec.NewP384Point().SetBytes(Marshal(P384(), x, y))
+       if err != nil {
+               return nil, false
+       }
+       return p, true
+}
+
+func p384PointToAffine(p *nistec.P384Point) (x, y *big.Int) {
+       out := p.Bytes()
+       if len(out) == 1 && out[0] == 0 {
+               // This is the correct encoding of the point at infinity, which
+               // Unmarshal does not support. See Issue 37294.
+               return new(big.Int), new(big.Int)
+       }
+       x, y = Unmarshal(P384(), out)
+       if x == nil {
+               panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding")
+       }
+       return x, y
+}
+
+// p384RandomPoint returns a random point on the curve. It's used when Add,
+// Double, or ScalarMult are fed a point not on the curve, which is undefined
+// behavior. Originally, we used to do the math on it anyway (which allows
+// invalid curve attacks) and relied on the caller and Unmarshal to avoid this
+// happening in the first place. Now, we just can't construct a nistec.P384Point
+// for an invalid pair of coordinates, because that API is safer. If we panic,
+// we risk introducing a DoS. If we return nil, we risk a panic. If we return
+// the input, ecdsa.Verify might fail open. The safest course seems to be to
+// return a valid, random point, which hopefully won't help the attacker.
+func p384RandomPoint() (x, y *big.Int) {
+       _, x, y, err := GenerateKey(P384(), rand.Reader)
+       if err != nil {
+               panic("crypto/elliptic: failed to generate random point")
+       }
+       return x, y
+}
+
+func (p384Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+       p1, ok := p384PointFromAffine(x1, y1)
+       if !ok {
+               return p384RandomPoint()
+       }
+       p2, ok := p384PointFromAffine(x2, y2)
+       if !ok {
+               return p384RandomPoint()
+       }
+       return p384PointToAffine(p1.Add(p1, p2))
+}
+
+func (p384Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+       p, ok := p384PointFromAffine(x1, y1)
+       if !ok {
+               return p384RandomPoint()
+       }
+       return p384PointToAffine(p.Double(p))
+}
+
+func (p384Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
+       p, ok := p384PointFromAffine(Bx, By)
+       if !ok {
+               return p384RandomPoint()
+       }
+       return p384PointToAffine(p.ScalarMult(p, scalar))
+}
+
+func (p384Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) {
+       p := nistec.NewP384Generator()
+       return p384PointToAffine(p.ScalarMult(p, scalar))
+}
index e64007dfe35aad3a17906a054953a6d68280be88..6c9eed30e536cd715a28bfe6a7e50bf2183172fd 100644 (file)
@@ -112,7 +112,7 @@ func p521RandomPoint() (x, y *big.Int) {
        return x, y
 }
 
-func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+func (p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
        p1, ok := p521PointFromAffine(x1, y1)
        if !ok {
                return p521RandomPoint()
@@ -124,7 +124,7 @@ func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
        return p521PointToAffine(p1.Add(p1, p2))
 }
 
-func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+func (p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
        p, ok := p521PointFromAffine(x1, y1)
        if !ok {
                return p521RandomPoint()
@@ -132,7 +132,7 @@ func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
        return p521PointToAffine(p.Double(p))
 }
 
-func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
+func (p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
        p, ok := p521PointFromAffine(Bx, By)
        if !ok {
                return p521RandomPoint()
@@ -140,7 +140,7 @@ func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *bi
        return p521PointToAffine(p.ScalarMult(p, scalar))
 }
 
-func (curve p521Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) {
+func (p521Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) {
        p := nistec.NewP521Generator()
        return p521PointToAffine(p.ScalarMult(p, scalar))
 }
index 0da93677b52a6d2aec3386995e2eb7569e708810..d17cac30eb49cd48007410c875c6bc4d81978baa 100644 (file)
@@ -18,6 +18,7 @@ import (
        "crypto/x509"
        "errors"
        "fmt"
+       "internal/godebug"
        "io"
        "net"
        "strings"
@@ -682,11 +683,20 @@ type Config struct {
        ClientSessionCache ClientSessionCache
 
        // MinVersion contains the minimum TLS version that is acceptable.
-       // If zero, TLS 1.0 is currently taken as the minimum.
+       //
+       // By default, TLS 1.2 is currently used as the minimum when acting as a
+       // client, and TLS 1.0 when acting as a server. TLS 1.0 is the minimum
+       // supported by this package, both as a client and as a server.
+       //
+       // The client-side default can temporarily be reverted to TLS 1.0 by
+       // including the value "x509sha1=1" in the GODEBUG environment variable.
+       // Note that this option will be removed in Go 1.19 (but it will still be
+       // possible to set this field to VersionTLS10 explicitly).
        MinVersion uint16
 
        // MaxVersion contains the maximum TLS version that is acceptable.
-       // If zero, the maximum version supported by this package is used,
+       //
+       // By default, the maximum version supported by this package is used,
        // which is currently TLS 1.3.
        MaxVersion uint16
 
@@ -967,12 +977,24 @@ var supportedVersions = []uint16{
        VersionTLS10,
 }
 
-func (c *Config) supportedVersions() []uint16 {
+// debugEnableTLS10 enables TLS 1.0. See issue 45428.
+var debugEnableTLS10 = godebug.Get("tls10default") == "1"
+
+// roleClient and roleServer are meant to call supportedVersions and parents
+// with more readability at the callsite.
+const roleClient = true
+const roleServer = false
+
+func (c *Config) supportedVersions(isClient bool) []uint16 {
        versions := make([]uint16, 0, len(supportedVersions))
        for _, v := range supportedVersions {
                if needFIPS() && (v < fipsMinVersion(c) || v > fipsMaxVersion(c)) {
                        continue
                }
+               if (c == nil || c.MinVersion == 0) && !debugEnableTLS10 &&
+                       isClient && v < VersionTLS12 {
+                       continue
+               }
                if c != nil && c.MinVersion != 0 && v < c.MinVersion {
                        continue
                }
@@ -984,8 +1006,8 @@ func (c *Config) supportedVersions() []uint16 {
        return versions
 }
 
-func (c *Config) maxSupportedVersion() uint16 {
-       supportedVersions := c.supportedVersions()
+func (c *Config) maxSupportedVersion(isClient bool) uint16 {
+       supportedVersions := c.supportedVersions(isClient)
        if len(supportedVersions) == 0 {
                return 0
        }
@@ -1029,8 +1051,8 @@ func (c *Config) supportsCurve(curve CurveID) bool {
 
 // mutualVersion returns the protocol version to use given the advertised
 // versions of the peer. Priority is given to the peer preference order.
-func (c *Config) mutualVersion(peerVersions []uint16) (uint16, bool) {
-       supportedVersions := c.supportedVersions()
+func (c *Config) mutualVersion(isClient bool, peerVersions []uint16) (uint16, bool) {
+       supportedVersions := c.supportedVersions(isClient)
        for _, peerVersion := range peerVersions {
                for _, v := range supportedVersions {
                        if v == peerVersion {
@@ -1109,7 +1131,7 @@ func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error {
        if config == nil {
                config = &Config{}
        }
-       vers, ok := config.mutualVersion(chi.SupportedVersions)
+       vers, ok := config.mutualVersion(roleServer, chi.SupportedVersions)
        if !ok {
                return errors.New("no mutually supported protocol versions")
        }
index cd1b3b1d126c0cab68a911bf58f0be23f17a1a6b..c368c6cd584b539a38569c925dfe31639a24c940 100644 (file)
@@ -52,12 +52,12 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
                return nil, nil, errors.New("tls: NextProtos values too large")
        }
 
-       supportedVersions := config.supportedVersions()
+       supportedVersions := config.supportedVersions(roleClient)
        if len(supportedVersions) == 0 {
                return nil, nil, errors.New("tls: no supported versions satisfy MinVersion and MaxVersion")
        }
 
-       clientHelloVersion := config.maxSupportedVersion()
+       clientHelloVersion := config.maxSupportedVersion(roleClient)
        // The version at the beginning of the ClientHello was capped at TLS 1.2
        // for compatibility reasons. The supported_versions extension is used
        // to negotiate versions now. See RFC 8446, Section 4.2.1.
@@ -197,7 +197,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) {
        // If we are negotiating a protocol version that's lower than what we
        // support, check for the server downgrade canaries.
        // See RFC 8446, Section 4.1.3.
-       maxVers := c.config.maxSupportedVersion()
+       maxVers := c.config.maxSupportedVersion(roleClient)
        tls12Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS12
        tls11Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS11
        if maxVers == VersionTLS13 && c.vers <= VersionTLS12 && (tls12Downgrade || tls11Downgrade) ||
@@ -365,7 +365,7 @@ func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error {
                peerVersion = serverHello.supportedVersion
        }
 
-       vers, ok := c.config.mutualVersion([]uint16{peerVersion})
+       vers, ok := c.config.mutualVersion(roleClient, []uint16{peerVersion})
        if !ok {
                c.sendAlert(alertProtocolVersion)
                return fmt.Errorf("tls: server selected unsupported protocol version %x", peerVersion)
index 497e196a856dcef64a610cb75c1ea1e1ef24ce91..be6424889105cfbba8ff2e1afbac0f1403f6d6d6 100644 (file)
@@ -156,7 +156,7 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) {
        if len(clientHello.supportedVersions) == 0 {
                clientVersions = supportedVersionsFromMax(clientHello.vers)
        }
-       c.vers, ok = c.config.mutualVersion(clientVersions)
+       c.vers, ok = c.config.mutualVersion(roleServer, clientVersions)
        if !ok {
                c.sendAlert(alertProtocolVersion)
                return nil, fmt.Errorf("tls: client offered only unsupported versions: %x", clientVersions)
@@ -191,7 +191,7 @@ func (hs *serverHandshakeState) processClientHello() error {
        hs.hello.random = make([]byte, 32)
        serverRandom := hs.hello.random
        // Downgrade protection canaries. See RFC 8446, Section 4.1.3.
-       maxVers := c.config.maxSupportedVersion()
+       maxVers := c.config.maxSupportedVersion(roleServer)
        if maxVers >= VersionTLS12 && c.vers < maxVers || testingOnlyForceDowngradeCanary {
                if c.vers == VersionTLS12 {
                        copy(serverRandom[24:], downgradeCanaryTLS12)
@@ -354,7 +354,7 @@ func (hs *serverHandshakeState) pickCipherSuite() error {
        for _, id := range hs.clientHello.cipherSuites {
                if id == TLS_FALLBACK_SCSV {
                        // The client is doing a fallback connection. See RFC 7507.
-                       if hs.clientHello.vers < c.config.maxSupportedVersion() {
+                       if hs.clientHello.vers < c.config.maxSupportedVersion(roleServer) {
                                c.sendAlert(alertInappropriateFallback)
                                return errors.New("tls: client using inappropriate protocol fallback")
                        }
index f61b4c88efaf1d270c00d9bafc7831e4db6bf124..5fb2ebbbb3aa4673b18d3bd7d615c8e2d4c1a8bd 100644 (file)
@@ -385,13 +385,30 @@ func TestVersion(t *testing.T) {
        }
        clientConfig := &Config{
                InsecureSkipVerify: true,
+               MinVersion:         VersionTLS10,
        }
        state, _, err := testHandshake(t, clientConfig, serverConfig)
        if err != nil {
                t.Fatalf("handshake failed: %s", err)
        }
        if state.Version != VersionTLS11 {
-               t.Fatalf("Incorrect version %x, should be %x", state.Version, VersionTLS11)
+               t.Fatalf("incorrect version %x, should be %x", state.Version, VersionTLS11)
+       }
+
+       clientConfig.MinVersion = 0
+       _, _, err = testHandshake(t, clientConfig, serverConfig)
+       if err == nil {
+               t.Fatalf("expected failure to connect with TLS 1.0/1.1")
+       }
+
+       defer func(old bool) { debugEnableTLS10 = old }(debugEnableTLS10)
+       debugEnableTLS10 = true
+       _, _, err = testHandshake(t, clientConfig, serverConfig)
+       if err != nil {
+               t.Fatalf("handshake failed: %s", err)
+       }
+       if state.Version != VersionTLS11 {
+               t.Fatalf("incorrect version %x, should be %x", state.Version, VersionTLS11)
        }
 }
 
@@ -472,6 +489,7 @@ func testCrossVersionResume(t *testing.T, version uint16) {
                InsecureSkipVerify: true,
                ClientSessionCache: NewLRUClientSessionCache(1),
                ServerName:         "servername",
+               MinVersion:         VersionTLS10,
        }
 
        // Establish a session at TLS 1.1.
index 109ff7a01d4606fda81bd8289e72383f0cf72710..09674764e2cf8c0ef2a0e6393ae704793985fa52 100644 (file)
@@ -114,7 +114,7 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error {
                if id == TLS_FALLBACK_SCSV {
                        // Use c.vers instead of max(supported_versions) because an attacker
                        // could defeat this by adding an arbitrary high version otherwise.
-                       if c.vers < c.config.maxSupportedVersion() {
+                       if c.vers < c.config.maxSupportedVersion(roleServer) {
                                c.sendAlert(alertInappropriateFallback)
                                return errors.New("tls: client using inappropriate protocol fallback")
                        }
index 90ac9bd11ee2ae31d1ec654f1f9776cf5c7ed834..bacc8b7d4fed57805ff3eb920abab998f62c113e 100644 (file)
@@ -363,6 +363,8 @@ func runMain(m *testing.M) int {
                Certificates:       make([]Certificate, 2),
                InsecureSkipVerify: true,
                CipherSuites:       allCipherSuites(),
+               MinVersion:         VersionTLS10,
+               MaxVersion:         VersionTLS13,
        }
        testConfig.Certificates[0].Certificate = [][]byte{testRSACertificate}
        testConfig.Certificates[0].PrivateKey = testRSAPrivateKey
index df78abd77e30c90f8c02fddea8c1403a60f2ea38..b9b71f4c1e52ddfaaaf8c7fb8031d11917681f24 100644 (file)
@@ -534,6 +534,10 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) {
 }
 
 func TestGoVerify(t *testing.T) {
+       // Temporarily enable SHA-1 verification since a number of test chains
+       // require it. TODO(filippo): regenerate test chains.
+       defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1)
+       debugAllowSHA1 = true
        for _, test := range verifyTests {
                t.Run(test.name, func(t *testing.T) {
                        testVerify(t, test, false)
index 4304ab54e1a7052f7a7c40e6eb589900db7c56e9..b5c2b22cd746e414acc81c72337a7195cf1cbdfb 100644 (file)
@@ -18,6 +18,7 @@ import (
        "encoding/pem"
        "errors"
        "fmt"
+       "internal/godebug"
        "io"
        "math/big"
        "net"
@@ -181,15 +182,15 @@ type SignatureAlgorithm int
 const (
        UnknownSignatureAlgorithm SignatureAlgorithm = iota
 
-       MD2WithRSA // Unsupported.
-       MD5WithRSA // Only supported for signing, not verification.
-       SHA1WithRSA
+       MD2WithRSA  // Unsupported.
+       MD5WithRSA  // Only supported for signing, not verification.
+       SHA1WithRSA // Only supported for signing, not verification.
        SHA256WithRSA
        SHA384WithRSA
        SHA512WithRSA
        DSAWithSHA1   // Unsupported.
        DSAWithSHA256 // Unsupported.
-       ECDSAWithSHA1
+       ECDSAWithSHA1 // Only supported for signing, not verification.
        ECDSAWithSHA256
        ECDSAWithSHA384
        ECDSAWithSHA512
@@ -729,11 +730,23 @@ type Certificate struct {
 // involves algorithms that are not currently implemented.
 var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented")
 
-// An InsecureAlgorithmError
+// debugAllowSHA1 allows SHA-1 signatures. See issue 41682.
+var debugAllowSHA1 = godebug.Get("x509sha1") == "1"
+
+// An InsecureAlgorithmError indicates that the SignatureAlgorithm used to
+// generate the signature is not secure, and the signature has been rejected.
+//
+// To temporarily restore support for SHA-1 signatures, include the value
+// "x509sha1=1" in the GODEBUG environment variable. Note that this option will
+// be removed in Go 1.19.
 type InsecureAlgorithmError SignatureAlgorithm
 
 func (e InsecureAlgorithmError) Error() string {
-       return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e))
+       var override string
+       if SignatureAlgorithm(e) == SHA1WithRSA || SignatureAlgorithm(e) == ECDSAWithSHA1 {
+               override = " (temporarily override with GODEBUG=x509sha1=1)"
+       }
+       return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) + override
 }
 
 // ConstraintViolationError results when a requested usage is not permitted by
@@ -825,6 +838,11 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey
                }
        case crypto.MD5:
                return InsecureAlgorithmError(algo)
+       case crypto.SHA1:
+               if !debugAllowSHA1 {
+                       return InsecureAlgorithmError(algo)
+               }
+               fallthrough
        default:
                if !hashType.Available() {
                        return ErrUnsupportedAlgorithm
@@ -1579,9 +1597,12 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
        }
 
        // Check the signature to ensure the crypto.Signer behaved correctly.
-       // We skip this check if the signature algorithm is MD5WithRSA as we
-       // only support this algorithm for signing, and not verification.
-       if sigAlg := getSignatureAlgorithmFromAI(signatureAlgorithm); sigAlg != MD5WithRSA {
+       sigAlg := getSignatureAlgorithmFromAI(signatureAlgorithm)
+       switch sigAlg {
+       case MD5WithRSA, SHA1WithRSA, ECDSAWithSHA1:
+               // We skip the check if the signature algorithm is only supported for
+               // signing, not verification.
+       default:
                if err := checkSignature(sigAlg, c.Raw, signature, key.Public()); err != nil {
                        return nil, fmt.Errorf("x509: signature over certificate returned by signer is invalid: %w", err)
                }
index a4053abf41d4160c6d8112164fabb5ba2bef51e4..affab3789d5f9fbd5472918e2f9369a0f26ef79c 100644 (file)
@@ -585,10 +585,10 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
                checkSig  bool
                sigAlgo   SignatureAlgorithm
        }{
-               {"RSA/RSA", &testPrivateKey.PublicKey, testPrivateKey, true, SHA1WithRSA},
+               {"RSA/RSA", &testPrivateKey.PublicKey, testPrivateKey, true, SHA384WithRSA},
                {"RSA/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384},
                {"ECDSA/RSA", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSA},
-               {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA1},
+               {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA256},
                {"RSAPSS/RSAPSS", &testPrivateKey.PublicKey, testPrivateKey, true, SHA256WithRSAPSS},
                {"ECDSA/RSAPSS", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSAPSS},
                {"RSAPSS/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384},
@@ -886,7 +886,6 @@ var ecdsaTests = []struct {
        sigAlgo SignatureAlgorithm
        pemCert string
 }{
-       {ECDSAWithSHA1, ecdsaSHA1CertPem},
        {ECDSAWithSHA256, ecdsaSHA256p256CertPem},
        {ECDSAWithSHA256, ecdsaSHA256p384CertPem},
        {ECDSAWithSHA384, ecdsaSHA384p521CertPem},
@@ -1389,10 +1388,10 @@ func TestCreateCertificateRequest(t *testing.T) {
                priv    interface{}
                sigAlgo SignatureAlgorithm
        }{
-               {"RSA", testPrivateKey, SHA1WithRSA},
-               {"ECDSA-256", ecdsa256Priv, ECDSAWithSHA1},
-               {"ECDSA-384", ecdsa384Priv, ECDSAWithSHA1},
-               {"ECDSA-521", ecdsa521Priv, ECDSAWithSHA1},
+               {"RSA", testPrivateKey, SHA256WithRSA},
+               {"ECDSA-256", ecdsa256Priv, ECDSAWithSHA256},
+               {"ECDSA-384", ecdsa384Priv, ECDSAWithSHA256},
+               {"ECDSA-521", ecdsa521Priv, ECDSAWithSHA256},
                {"Ed25519", ed25519Priv, PureEd25519},
        }
 
@@ -1783,6 +1782,9 @@ func TestInsecureAlgorithmErrorString(t *testing.T) {
                sa   SignatureAlgorithm
                want string
        }{
+               {MD5WithRSA, "x509: cannot verify signature: insecure algorithm MD5-RSA"},
+               {SHA1WithRSA, "x509: cannot verify signature: insecure algorithm SHA1-RSA (temporarily override with GODEBUG=x509sha1=1)"},
+               {ECDSAWithSHA1, "x509: cannot verify signature: insecure algorithm ECDSA-SHA1 (temporarily override with GODEBUG=x509sha1=1)"},
                {MD2WithRSA, "x509: cannot verify signature: insecure algorithm MD2-RSA"},
                {-1, "x509: cannot verify signature: insecure algorithm -1"},
                {0, "x509: cannot verify signature: insecure algorithm 0"},
@@ -1846,6 +1848,30 @@ func TestMD5(t *testing.T) {
        }
 }
 
+func TestSHA1(t *testing.T) {
+       pemBlock, _ := pem.Decode([]byte(ecdsaSHA1CertPem))
+       cert, err := ParseCertificate(pemBlock.Bytes)
+       if err != nil {
+               t.Fatalf("failed to parse certificate: %s", err)
+       }
+       if sa := cert.SignatureAlgorithm; sa != ECDSAWithSHA1 {
+               t.Errorf("signature algorithm is %v, want %v", sa, ECDSAWithSHA1)
+       }
+       if err = cert.CheckSignatureFrom(cert); err == nil {
+               t.Fatalf("certificate verification succeeded incorrectly")
+       }
+       if _, ok := err.(InsecureAlgorithmError); !ok {
+               t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err)
+       }
+
+       defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1)
+       debugAllowSHA1 = true
+
+       if err = cert.CheckSignatureFrom(cert); err != nil {
+               t.Fatalf("SHA-1 certificate did not verify with GODEBUG=x509sha1=1: %v", err)
+       }
+}
+
 // certMissingRSANULL contains an RSA public key where the AlgorithmIdentifier
 // parameters are omitted rather than being an ASN.1 NULL.
 const certMissingRSANULL = `
@@ -2897,19 +2923,31 @@ func TestCreateCertificateBrokenSigner(t *testing.T) {
        }
 }
 
-func TestCreateCertificateMD5(t *testing.T) {
-       template := &Certificate{
-               SerialNumber:       big.NewInt(10),
-               DNSNames:           []string{"example.com"},
-               SignatureAlgorithm: MD5WithRSA,
-       }
-       k, err := rsa.GenerateKey(rand.Reader, 1024)
+func TestCreateCertificateLegacy(t *testing.T) {
+       ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
        if err != nil {
-               t.Fatalf("failed to generate test key: %s", err)
+               t.Fatalf("Failed to generate ECDSA key: %s", err)
        }
-       _, err = CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()})
-       if err != nil {
-               t.Fatalf("CreateCertificate failed when SignatureAlgorithm = MD5WithRSA: %s", err)
+
+       for _, sigAlg := range []SignatureAlgorithm{
+               MD5WithRSA, SHA1WithRSA, ECDSAWithSHA1,
+       } {
+               template := &Certificate{
+                       SerialNumber:       big.NewInt(10),
+                       DNSNames:           []string{"example.com"},
+                       SignatureAlgorithm: sigAlg,
+               }
+               var k crypto.Signer
+               switch sigAlg {
+               case MD5WithRSA, SHA1WithRSA:
+                       k = testPrivateKey
+               case ECDSAWithSHA1:
+                       k = ecdsaPriv
+               }
+               _, err := CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()})
+               if err != nil {
+                       t.Fatalf("CreateCertificate failed when SignatureAlgorithm = %v: %s", sigAlg, err)
+               }
        }
 }
 
@@ -3131,7 +3169,6 @@ func TestParseCertificateRawEquals(t *testing.T) {
        if !bytes.Equal(p.Bytes, cert.Raw) {
                t.Fatalf("unexpected Certificate.Raw\ngot: %x\nwant: %x\n", cert.Raw, p.Bytes)
        }
-       fmt.Printf("in:  %x\nout: %x\n", p.Bytes, cert.Raw)
 }
 
 // mismatchingSigAlgIDPEM contains a certificate where the Certificate
index 9f8399d4d3cef70a68bdb126b4a5c59f1be127d8..4c51bc4de2a16a0c7b061b864711390196d3a377 100644 (file)
@@ -2349,6 +2349,7 @@ const (
        R_PPC64_GOT16_HI           R_PPC64 = 16 // R_POWERPC_GOT16_HI
        R_PPC64_GOT16_HA           R_PPC64 = 17 // R_POWERPC_GOT16_HA
        R_PPC64_JMP_SLOT           R_PPC64 = 21 // R_POWERPC_JMP_SLOT
+       R_PPC64_RELATIVE           R_PPC64 = 22 // R_POWERPC_RELATIVE
        R_PPC64_REL32              R_PPC64 = 26 // R_POWERPC_REL32
        R_PPC64_ADDR64             R_PPC64 = 38
        R_PPC64_ADDR16_HIGHER      R_PPC64 = 39
@@ -2457,6 +2458,7 @@ var rppc64Strings = []intName{
        {16, "R_PPC64_GOT16_HI"},
        {17, "R_PPC64_GOT16_HA"},
        {21, "R_PPC64_JMP_SLOT"},
+       {22, "R_PPC64_RELATIVE"},
        {26, "R_PPC64_REL32"},
        {38, "R_PPC64_ADDR64"},
        {39, "R_PPC64_ADDR16_HIGHER"},
index 314608da6108331b37adfc190a0d166dfd882662..c054635148d10aee6010da24c7e4aaecf582d046 100644 (file)
@@ -301,11 +301,15 @@ func newTable(symtab []byte, ptrsz int) ([]Sym, error) {
        return syms, nil
 }
 
+// ErrNoSymbols is returned by File.Symbols if there is no such section
+// in the File.
+var ErrNoSymbols = errors.New("no symbol section")
+
 // Symbols returns the symbol table for f.
 func (f *File) Symbols() ([]Sym, error) {
        symtabSection := f.Section("syms")
        if symtabSection == nil {
-               return nil, errors.New("no symbol section")
+               return nil, ErrNoSymbols
        }
 
        symtab, err := symtabSection.Data()
index 6f66e99c4a20cc7778bc3229697cfbf63fa747a3..a22fee2f04412e4d772ea8969f2df9c5dd033249 100644 (file)
@@ -265,3 +265,13 @@ func ExampleAs() {
        // Output:
        // Failed at path: non-existing
 }
+
+func ExampleUnwrap() {
+       err1 := errors.New("error1")
+       err2 := fmt.Errorf("error2: [%w]", err1)
+       fmt.Println(err2)
+       fmt.Println(errors.Unwrap(err2))
+       // Output
+       // error2: [error1]
+       // error1
+}
index 0d8bf879921d2bcab93894bc8898a359373455c1..1ca281b2a4a0613825705b5386108480595d3e22 100644 (file)
@@ -593,7 +593,7 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
        return n, sa, nil
 }
 
-// ReadFrom wraps the recvfrom network call for IPv4.
+// ReadFromInet4 wraps the recvfrom network call for IPv4.
 func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
        if len(buf) == 0 {
                return 0, nil
@@ -622,7 +622,7 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error)
        return n, err
 }
 
-// ReadFrom wraps the recvfrom network call for IPv6.
+// ReadFromInet6 wraps the recvfrom network call for IPv6.
 func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
        if len(buf) == 0 {
                return 0, nil
index 096a6d382a8afab3ea3e8ce7cb231524994ce02c..a849327f4528b430cac53046168f4a4a9440aaf2 100644 (file)
@@ -88,12 +88,7 @@ func SetPendingDialHooks(before, after func()) {
 
 func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn }
 
-func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
-       ctx, cancel := context.WithCancel(context.Background())
-       go func() {
-               <-ch
-               cancel()
-       }()
+func NewTestTimeoutHandler(handler Handler, ctx context.Context) Handler {
        return &timeoutHandler{
                handler:     handler,
                testContext: ctx,
index 632a308a5ce2eb0da306356e80d026e77689d054..27872b4e7a40f10409e85bc83e9d5dd96240f2a4 100644 (file)
@@ -43,7 +43,7 @@ func interestingGoroutines() (gs []string) {
                        // These only show up with GOTRACEBACK=2; Issue 5005 (comment 28)
                        strings.Contains(stack, "runtime.goexit") ||
                        strings.Contains(stack, "created by runtime.gc") ||
-                       strings.Contains(stack, "net/http_test.interestingGoroutines") ||
+                       strings.Contains(stack, "interestingGoroutines") ||
                        strings.Contains(stack, "runtime.MHeap_Scavenger") {
                        continue
                }
index a98d6c313f86cba5f0e86c4339cca146cb96cf22..e8fb77446c3d45668dcfda36026971abe21c49ac 100644 (file)
@@ -2274,6 +2274,18 @@ func TestRequestBodyTimeoutClosesConnection(t *testing.T) {
        }
 }
 
+// cancelableTimeoutContext overwrites the error message to DeadlineExceeded
+type cancelableTimeoutContext struct {
+       context.Context
+}
+
+func (c cancelableTimeoutContext) Err() error {
+       if c.Context.Err() != nil {
+               return context.DeadlineExceeded
+       }
+       return nil
+}
+
 func TestTimeoutHandler_h1(t *testing.T) { testTimeoutHandler(t, h1Mode) }
 func TestTimeoutHandler_h2(t *testing.T) { testTimeoutHandler(t, h2Mode) }
 func testTimeoutHandler(t *testing.T, h2 bool) {
@@ -2286,8 +2298,9 @@ func testTimeoutHandler(t *testing.T, h2 bool) {
                _, werr := w.Write([]byte("hi"))
                writeErrors <- werr
        })
-       timeout := make(chan time.Time, 1) // write to this to force timeouts
-       cst := newClientServerTest(t, h2, NewTestTimeoutHandler(sayHi, timeout))
+       ctx, cancel := context.WithCancel(context.Background())
+       h := NewTestTimeoutHandler(sayHi, cancelableTimeoutContext{ctx})
+       cst := newClientServerTest(t, h2, h)
        defer cst.close()
 
        // Succeed without timing out:
@@ -2308,7 +2321,8 @@ func testTimeoutHandler(t *testing.T, h2 bool) {
        }
 
        // Times out:
-       timeout <- time.Time{}
+       cancel()
+
        res, err = cst.c.Get(cst.ts.URL)
        if err != nil {
                t.Error(err)
@@ -2429,8 +2443,9 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) {
                _, werr := w.Write([]byte("hi"))
                writeErrors <- werr
        })
-       timeout := make(chan time.Time, 1) // write to this to force timeouts
-       cst := newClientServerTest(t, h1Mode, NewTestTimeoutHandler(sayHi, timeout))
+       ctx, cancel := context.WithCancel(context.Background())
+       h := NewTestTimeoutHandler(sayHi, cancelableTimeoutContext{ctx})
+       cst := newClientServerTest(t, h1Mode, h)
        defer cst.close()
 
        // Succeed without timing out:
@@ -2451,7 +2466,8 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) {
        }
 
        // Times out:
-       timeout <- time.Time{}
+       cancel()
+
        res, err = cst.c.Get(cst.ts.URL)
        if err != nil {
                t.Error(err)
@@ -2501,6 +2517,41 @@ func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) {
        }
 }
 
+func TestTimeoutHandlerContextCanceled(t *testing.T) {
+       setParallel(t)
+       defer afterTest(t)
+       sendHi := make(chan bool, 1)
+       writeErrors := make(chan error, 1)
+       sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
+               w.Header().Set("Content-Type", "text/plain")
+               <-sendHi
+               _, werr := w.Write([]byte("hi"))
+               writeErrors <- werr
+       })
+       ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour)
+       h := NewTestTimeoutHandler(sayHi, ctx)
+       cancel()
+       cst := newClientServerTest(t, h1Mode, h)
+       defer cst.close()
+
+       // Succeed without timing out:
+       sendHi <- true
+       res, err := cst.c.Get(cst.ts.URL)
+       if err != nil {
+               t.Error(err)
+       }
+       if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
+               t.Errorf("got res.StatusCode %d; expected %d", g, e)
+       }
+       body, _ := io.ReadAll(res.Body)
+       if g, e := string(body), ""; g != e {
+               t.Errorf("got body %q; expected %q", g, e)
+       }
+       if g, e := <-writeErrors, context.Canceled; g != e {
+               t.Errorf("got unexpected Write error on first request: %v", g)
+       }
+}
+
 // https://golang.org/issue/15948
 func TestTimeoutHandlerEmptyResponse(t *testing.T) {
        setParallel(t)
index 91fad68694b51659b579ee8eef7e1360ce44a0f6..08fd478ed9e48d69fa7170bce998fe4d5ad6fcec 100644 (file)
@@ -3391,9 +3391,15 @@ func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
        case <-ctx.Done():
                tw.mu.Lock()
                defer tw.mu.Unlock()
-               w.WriteHeader(StatusServiceUnavailable)
-               io.WriteString(w, h.errorBody())
-               tw.timedOut = true
+               switch err := ctx.Err(); err {
+               case context.DeadlineExceeded:
+                       w.WriteHeader(StatusServiceUnavailable)
+                       io.WriteString(w, h.errorBody())
+                       tw.err = ErrHandlerTimeout
+               default:
+                       w.WriteHeader(StatusServiceUnavailable)
+                       tw.err = err
+               }
        }
 }
 
@@ -3404,7 +3410,7 @@ type timeoutWriter struct {
        req  *Request
 
        mu          sync.Mutex
-       timedOut    bool
+       err         error
        wroteHeader bool
        code        int
 }
@@ -3424,8 +3430,8 @@ func (tw *timeoutWriter) Header() Header { return tw.h }
 func (tw *timeoutWriter) Write(p []byte) (int, error) {
        tw.mu.Lock()
        defer tw.mu.Unlock()
-       if tw.timedOut {
-               return 0, ErrHandlerTimeout
+       if tw.err != nil {
+               return 0, tw.err
        }
        if !tw.wroteHeader {
                tw.writeHeaderLocked(StatusOK)
@@ -3437,7 +3443,7 @@ func (tw *timeoutWriter) writeHeaderLocked(code int) {
        checkWriteHeaderCode(code)
 
        switch {
-       case tw.timedOut:
+       case tw.err != nil:
                return
        case tw.wroteHeader:
                if tw.req != nil {
index 05a16591369f777a91836813bcddc951966511c8..f2d2f7928049ded2acc3b6fe76d47f5781d10707 100644 (file)
@@ -2481,7 +2481,7 @@ type requestAndChan struct {
        callerGone <-chan struct{} // closed when roundTrip caller has returned
 }
 
-// A writeRequest is sent by the readLoop's goroutine to the
+// A writeRequest is sent by the caller's goroutine to the
 // writeLoop's goroutine to write a request while the read loop
 // concurrently waits on both the write response and the server's
 // reply.
index 02a4aa04525072b59fa2e0d95ce11c210f092b21..8cde6ef3d20e85c2b318ced05c997b58c3969dfa 100644 (file)
@@ -155,9 +155,14 @@ func (err parseAddrError) Error() string {
 func parseIPv4(s string) (ip Addr, err error) {
        var fields [4]uint8
        var val, pos int
+       var digLen int // number of digits in current octet
        for i := 0; i < len(s); i++ {
                if s[i] >= '0' && s[i] <= '9' {
+                       if digLen == 1 && val == 0 {
+                               return Addr{}, parseAddrError{in: s, msg: "IPv4 field has octet with leading zero"}
+                       }
                        val = val*10 + int(s[i]) - '0'
+                       digLen++
                        if val > 255 {
                                return Addr{}, parseAddrError{in: s, msg: "IPv4 field has value >255"}
                        }
@@ -175,6 +180,7 @@ func parseIPv4(s string) (ip Addr, err error) {
                        fields[pos] = uint8(val)
                        pos++
                        val = 0
+                       digLen = 0
                } else {
                        return Addr{}, parseAddrError{in: s, msg: "unexpected character", at: s[i:]}
                }
@@ -692,21 +698,19 @@ const (
 // IPv6 addresses with zones are returned without their zone (use the
 // Zone method to get it).
 // The ip zero value returns all zeroes.
-func (ip Addr) As16() [16]byte {
-       var ret [16]byte
-       bePutUint64(ret[:8], ip.addr.hi)
-       bePutUint64(ret[8:], ip.addr.lo)
-       return ret
+func (ip Addr) As16() (a16 [16]byte) {
+       bePutUint64(a16[:8], ip.addr.hi)
+       bePutUint64(a16[8:], ip.addr.lo)
+       return a16
 }
 
 // As4 returns an IPv4 or IPv4-in-IPv6 address in its 4-byte representation.
 // If ip is the zero Addr or an IPv6 address, As4 panics.
 // Note that 0.0.0.0 is not the zero Addr.
-func (ip Addr) As4() [4]byte {
+func (ip Addr) As4() (a4 [4]byte) {
        if ip.z == z4 || ip.Is4In6() {
-               var ret [4]byte
-               bePutUint32(ret[:], uint32(ip.addr.lo))
-               return ret
+               bePutUint32(a4[:], uint32(ip.addr.lo))
+               return a4
        }
        if ip.z == z0 {
                panic("As4 called on IP zero value")
index 5d935c8fd37b7b555004f81801bcc1da02ff1228..c39b1ec201efeaa9752b3c546b1d28a031093944 100644 (file)
@@ -29,9 +29,10 @@ var (
 
 func TestParseAddr(t *testing.T) {
        var validIPs = []struct {
-               in  string
-               ip  Addr   // output of ParseAddr()
-               str string // output of String(). If "", use in.
+               in      string
+               ip      Addr   // output of ParseAddr()
+               str     string // output of String(). If "", use in.
+               wantErr string
        }{
                // Basic zero IPv4 address.
                {
@@ -45,15 +46,18 @@ func TestParseAddr(t *testing.T) {
                },
                // IPv4 address in windows-style "print all the digits" form.
                {
-                       in:  "010.000.015.001",
-                       ip:  MkAddr(Mk128(0, 0xffff0a000f01), Z4),
-                       str: "10.0.15.1",
+                       in:      "010.000.015.001",
+                       wantErr: `ParseAddr("010.000.015.001"): IPv4 field has octet with leading zero`,
                },
                // IPv4 address with a silly amount of leading zeros.
                {
-                       in:  "000001.00000002.00000003.000000004",
-                       ip:  MkAddr(Mk128(0, 0xffff01020304), Z4),
-                       str: "1.2.3.4",
+                       in:      "000001.00000002.00000003.000000004",
+                       wantErr: `ParseAddr("000001.00000002.00000003.000000004"): IPv4 field has octet with leading zero`,
+               },
+               // 4-in-6 with octet with leading zero
+               {
+                       in:      "::ffff:1.2.03.4",
+                       wantErr: `ParseAddr("::ffff:1.2.03.4"): ParseAddr("1.2.03.4"): IPv4 field has octet with leading zero (at "1.2.03.4")`,
                },
                // Basic zero IPv6 address.
                {
@@ -121,10 +125,16 @@ func TestParseAddr(t *testing.T) {
                t.Run(test.in, func(t *testing.T) {
                        got, err := ParseAddr(test.in)
                        if err != nil {
+                               if err.Error() == test.wantErr {
+                                       return
+                               }
                                t.Fatal(err)
                        }
+                       if test.wantErr != "" {
+                               t.Fatalf("wanted error %q; got none", test.wantErr)
+                       }
                        if got != test.ip {
-                               t.Errorf("ParseAddr(%q) got %#v, want %#v", test.in, got, test.ip)
+                               t.Errorf("got %#v, want %#v", got, test.ip)
                        }
 
                        // Check that ParseAddr is a pure function.
@@ -963,7 +973,7 @@ func TestIs4In6(t *testing.T) {
                {mustIP("::ffff:192.0.2.128"), true, mustIP("192.0.2.128")},
                {mustIP("::ffff:192.0.2.128%eth0"), true, mustIP("192.0.2.128")},
                {mustIP("::fffe:c000:0280"), false, mustIP("::fffe:c000:0280")},
-               {mustIP("::ffff:127.001.002.003"), true, mustIP("127.1.2.3")},
+               {mustIP("::ffff:127.1.2.3"), true, mustIP("127.1.2.3")},
                {mustIP("::ffff:7f01:0203"), true, mustIP("127.1.2.3")},
                {mustIP("0:0:0:0:0000:ffff:127.1.2.3"), true, mustIP("127.1.2.3")},
                {mustIP("0:0:0:0:000000:ffff:127.1.2.3"), true, mustIP("127.1.2.3")},
@@ -1796,3 +1806,12 @@ func TestInvalidAddrPortString(t *testing.T) {
                }
        }
 }
+
+var sink16 [16]byte
+
+func BenchmarkAs16(b *testing.B) {
+       addr := MustParseAddr("1::10")
+       for i := 0; i < b.N; i++ {
+               sink16 = addr.As16()
+       }
+}
index 518c66c33147a3b5944fd35ee6bf46575eb4fd8c..9fe74f47a2bbb297c8b750269dcc32e0462d6d41 100644 (file)
@@ -475,6 +475,17 @@ func TestUDPReadTimeout(t *testing.T) {
 }
 
 func TestAllocs(t *testing.T) {
+       switch runtime.GOOS {
+       case "plan9":
+               // Plan9 wasn't optimized.
+               t.Skipf("skipping on %v", runtime.GOOS)
+       }
+       builder := os.Getenv("GO_BUILDER_NAME")
+       switch builder {
+       case "linux-amd64-noopt":
+               // Optimizations are required to remove the allocs.
+               t.Skipf("skipping on %v", builder)
+       }
        conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
        if err != nil {
                t.Fatal(err)
index c9ce3ac643184f99a6776aa2b81971b9ddcf992d..355267c5e3a7332792510416f46f1b61eaa690d1 100644 (file)
@@ -624,6 +624,10 @@ func TestShrinkStackDuringBlockedSend(t *testing.T) {
 }
 
 func TestNoShrinkStackWhileParking(t *testing.T) {
+       if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" {
+               testenv.SkipFlaky(t, 49382)
+       }
+
        // The goal of this test is to trigger a "racy sudog adjustment"
        // throw. Basically, there's a window between when a goroutine
        // becomes available for preemption for stack scanning (and thus,
index 5149252c83746395c2fde9287dbf93acd68d53f2..b2e64f14ad381d5616e2adc67d6a766b0520da0b 100644 (file)
@@ -796,21 +796,17 @@ func (p *PageAlloc) Free(base, npages uintptr) {
                // None of the tests need any higher-level locking, so we just
                // take the lock internally.
                lock(pp.mheapLock)
-               pp.free(base, npages)
+               pp.free(base, npages, true)
                unlock(pp.mheapLock)
        })
 }
 func (p *PageAlloc) Bounds() (ChunkIdx, ChunkIdx) {
        return ChunkIdx((*pageAlloc)(p).start), ChunkIdx((*pageAlloc)(p).end)
 }
-func (p *PageAlloc) Scavenge(nbytes uintptr, mayUnlock bool) (r uintptr) {
+func (p *PageAlloc) Scavenge(nbytes uintptr) (r uintptr) {
        pp := (*pageAlloc)(p)
        systemstack(func() {
-               // None of the tests need any higher-level locking, so we just
-               // take the lock internally.
-               lock(pp.mheapLock)
-               r = pp.scavenge(nbytes, mayUnlock)
-               unlock(pp.mheapLock)
+               r = pp.scavenge(nbytes)
        })
        return
 }
index b2003ba54318ded5e5f835ebdfb80d56e2f8b307..f1f6ea51231fed11952c2c11be34c25e8ea9d327 100644 (file)
@@ -78,6 +78,11 @@ It is a comma-separated list of name=val pairs setting these named variables:
        If the line ends with "(forced)", this GC was forced by a
        runtime.GC() call.
 
+       harddecommit: setting harddecommit=1 causes memory that is returned to the OS to
+       also have protections removed on it. This is the only mode of operation on Windows,
+       but is helpful in debugging scavenger-related issues on other platforms. Currently,
+       only supported on Linux.
+
        inittrace: setting inittrace=1 causes the runtime to emit a single line to standard
        error for each package with init work, summarizing the execution time and memory
        allocation. No information is printed for inits executed as part of plugin loading
index dde9f7c21a7f3aa0f6d1ab5a61128e890e56238e..4a16bc0ddb6e7c091fd95b0163230971461d8276 100644 (file)
@@ -51,9 +51,9 @@ const (
        lockRankItab
        lockRankReflectOffs
        lockRankHchan // Multiple hchans acquired in lock order in syncadjustsudogs()
+       lockRankTraceBuf
        lockRankFin
        lockRankNotifyList
-       lockRankTraceBuf
        lockRankTraceStrings
        lockRankMspanSpecial
        lockRankProf
@@ -80,6 +80,7 @@ const (
 
        // Memory-related leaf locks
        lockRankGlobalAlloc
+       lockRankPageAllocScav
 
        // Other leaf locks
        lockRankGFree
@@ -131,9 +132,9 @@ var lockNames = []string{
        lockRankReflectOffs: "reflectOffs",
 
        lockRankHchan:         "hchan",
+       lockRankTraceBuf:      "traceBuf",
        lockRankFin:           "fin",
        lockRankNotifyList:    "notifyList",
-       lockRankTraceBuf:      "traceBuf",
        lockRankTraceStrings:  "traceStrings",
        lockRankMspanSpecial:  "mspanSpecial",
        lockRankProf:          "prof",
@@ -157,7 +158,8 @@ var lockNames = []string{
        lockRankMheap:        "mheap",
        lockRankMheapSpecial: "mheapSpecial",
 
-       lockRankGlobalAlloc: "globalAlloc.mutex",
+       lockRankGlobalAlloc:   "globalAlloc.mutex",
+       lockRankPageAllocScav: "pageAlloc.scav.lock",
 
        lockRankGFree:     "gFree",
        lockRankHchanLeaf: "hchanLeaf",
@@ -208,31 +210,32 @@ var lockPartialOrder [][]lockRank = [][]lockRank{
        lockRankItab:          {},
        lockRankReflectOffs:   {lockRankItab},
        lockRankHchan:         {lockRankScavenge, lockRankSweep, lockRankHchan},
-       lockRankFin:           {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan},
-       lockRankNotifyList:    {},
        lockRankTraceBuf:      {lockRankSysmon, lockRankScavenge},
+       lockRankFin:           {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllg, lockRankTimers, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf},
+       lockRankNotifyList:    {},
        lockRankTraceStrings:  {lockRankTraceBuf},
-       lockRankMspanSpecial:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
-       lockRankProf:          {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
-       lockRankGcBitsArenas:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
+       lockRankMspanSpecial:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
+       lockRankProf:          {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
+       lockRankGcBitsArenas:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
        lockRankRoot:          {},
        lockRankTrace:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot},
-       lockRankTraceStackTab: {lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankTrace},
+       lockRankTraceStackTab: {lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankRoot, lockRankTrace},
        lockRankNetpollInit:   {lockRankTimers},
 
        lockRankRwmutexW: {},
        lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW},
 
-       lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
-       lockRankGscan:        {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine},
-       lockRankStackpool:    {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan},
-       lockRankStackLarge:   {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan},
-       lockRankDefer:        {},
-       lockRankSudog:        {lockRankHchan, lockRankNotifyList},
-       lockRankWbufSpans:    {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog},
-       lockRankMheap:        {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans},
-       lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
-       lockRankGlobalAlloc:  {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial},
+       lockRankSpanSetSpine:  {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
+       lockRankGscan:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine},
+       lockRankStackpool:     {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan},
+       lockRankStackLarge:    {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan},
+       lockRankDefer:         {},
+       lockRankSudog:         {lockRankHchan, lockRankNotifyList},
+       lockRankWbufSpans:     {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog},
+       lockRankMheap:         {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans},
+       lockRankMheapSpecial:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
+       lockRankGlobalAlloc:   {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial},
+       lockRankPageAllocScav: {lockRankMheap},
 
        lockRankGFree:     {lockRankSched},
        lockRankHchanLeaf: {lockRankGscan, lockRankHchanLeaf},
index 34368510911b4dea0a578ad7e43600adfc36bb8d..f8f9c531701f97ac9682315aa648f7a4b2871cb1 100644 (file)
@@ -114,9 +114,29 @@ func sysUnused(v unsafe.Pointer, n uintptr) {
                atomic.Store(&adviseUnused, _MADV_DONTNEED)
                madvise(v, n, _MADV_DONTNEED)
        }
+
+       if debug.harddecommit > 0 {
+               p, err := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
+               if p != v || err != 0 {
+                       throw("runtime: cannot disable permissions in address space")
+               }
+       }
 }
 
 func sysUsed(v unsafe.Pointer, n uintptr) {
+       if debug.harddecommit > 0 {
+               p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
+               if err == _ENOMEM {
+                       throw("runtime: out of memory")
+               }
+               if p != v || err != 0 {
+                       throw("runtime: cannot remap pages in address space")
+               }
+               return
+
+               // Don't do the sysHugePage optimization in hard decommit mode.
+               // We're breaking up pages everywhere, there's no point.
+       }
        // Partially undo the NOHUGEPAGE marks from sysUnused
        // for whole huge pages between v and v+n. This may
        // leave huge pages off at the end points v and v+n
index 230e78b000d544e38cf461d67493882eee5e37c6..5b699cb298381e8eb63a8c779790b3236153a19c 100644 (file)
@@ -349,9 +349,6 @@ func (c *gcControllerState) init(gcPercent int32) {
                        kp: 0.9,
                        ti: 4.0,
 
-                       // An update is done once per GC cycle.
-                       period: 1,
-
                        // Set a high reset time in GC cycles.
                        // This is inversely proportional to the rate at which we
                        // accumulate error from clipping. By making this very high
@@ -677,8 +674,9 @@ func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) floa
                        (float64(scanWork) * (1 - utilization))
 
                // Update cons/mark controller.
+               // Period for this is 1 GC cycle.
                oldConsMark := c.consMark
-               c.consMark = c.consMarkController.next(c.consMark, currentConsMark)
+               c.consMark = c.consMarkController.next(c.consMark, currentConsMark, 1.0)
 
                if debug.gcpacertrace > 0 {
                        printlock()
@@ -1259,10 +1257,7 @@ func readGOGC() int32 {
 type piController struct {
        kp float64 // Proportional constant.
        ti float64 // Integral time constant.
-       tt float64 // Reset time in GC cyles.
-
-       // Period in GC cycles between updates.
-       period float64
+       tt float64 // Reset time.
 
        min, max float64 // Output boundaries.
 
@@ -1271,7 +1266,7 @@ type piController struct {
        errIntegral float64 // Integral of the error from t=0 to now.
 }
 
-func (c *piController) next(input, setpoint float64) float64 {
+func (c *piController) next(input, setpoint, period float64) float64 {
        // Compute the raw output value.
        prop := c.kp * (setpoint - input)
        rawOutput := prop + c.errIntegral
@@ -1286,7 +1281,7 @@ func (c *piController) next(input, setpoint float64) float64 {
 
        // Update the controller's state.
        if c.ti != 0 && c.tt != 0 {
-               c.errIntegral += (c.kp*c.period/c.ti)*(setpoint-input) + (c.period/c.tt)*(output-rawOutput)
+               c.errIntegral += (c.kp*period/c.ti)*(setpoint-input) + (period/c.tt)*(output-rawOutput)
        }
        return output
 }
index 4edeb8739e7e3d9009cbc026f527e21a9406b9f2..4a7f2465fd1d749b9a2803e9b4c2741bf6a60238 100644 (file)
@@ -270,49 +270,80 @@ func bgscavenge(c chan int) {
        c <- 1
        goparkunlock(&scavenge.lock, waitReasonGCScavengeWait, traceEvGoBlock, 1)
 
-       // Exponentially-weighted moving average of the fraction of time this
-       // goroutine spends scavenging (that is, percent of a single CPU).
-       // It represents a measure of scheduling overheads which might extend
-       // the sleep or the critical time beyond what's expected. Assume no
-       // overhead to begin with.
-       //
-       // TODO(mknyszek): Consider making this based on total CPU time of the
-       // application (i.e. scavengePercent * GOMAXPROCS). This isn't really
-       // feasible now because the scavenger acquires the heap lock over the
-       // scavenging operation, which means scavenging effectively blocks
-       // allocators and isn't scalable. However, given a scalable allocator,
-       // it makes sense to also make the scavenger scale with it; if you're
-       // allocating more frequently, then presumably you're also generating
-       // more work for the scavenger.
-       const idealFraction = scavengePercent / 100.0
-       scavengeEWMA := float64(idealFraction)
+       // idealFraction is the ideal % of overall application CPU time that we
+       // spend scavenging.
+       idealFraction := float64(scavengePercent) / 100.0
 
+       // Input: fraction of CPU time used.
+       // Setpoint: idealFraction.
+       // Output: ratio of critical time to sleep time (determines sleep time).
+       //
+       // The output of this controller is somewhat indirect to what we actually
+       // want to achieve: how much time to sleep for. The reason for this definition
+       // is to ensure that the controller's outputs have a direct relationship with
+       // its inputs (as opposed to an inverse relationship), making it somewhat
+       // easier to reason about for tuning purposes.
+       critSleepController := piController{
+               // Tuned loosely via Ziegler-Nichols process.
+               kp: 0.3375,
+               ti: 3.2e6,
+               tt: 1e9, // 1 second reset time.
+
+               // These ranges seem wide, but we want to give the controller plenty of
+               // room to hunt for the optimal value.
+               min: 0.001,  // 1:1000
+               max: 1000.0, // 1000:1
+       }
+       // It doesn't really matter what value we start at, but we can't be zero, because
+       // that'll cause divide-by-zero issues.
+       critSleepRatio := 0.001
        for {
                released := uintptr(0)
-
-               // Time in scavenging critical section.
                crit := float64(0)
 
-               // Run on the system stack since we grab the heap lock,
-               // and a stack growth with the heap lock means a deadlock.
-               systemstack(func() {
-                       lock(&mheap_.lock)
-
+               // Spend at least 1 ms scavenging, otherwise the corresponding
+               // sleep time to maintain our desired utilization is too low to
+               // be reliable.
+               const minCritTime = 1e6
+               for crit < minCritTime {
                        // If background scavenging is disabled or if there's no work to do just park.
                        retained, goal := heapRetained(), atomic.Load64(&mheap_.scavengeGoal)
                        if retained <= goal {
-                               unlock(&mheap_.lock)
-                               return
+                               break
                        }
 
-                       // Scavenge one page, and measure the amount of time spent scavenging.
+                       // scavengeQuantum is the amount of memory we try to scavenge
+                       // in one go. A smaller value means the scavenger is more responsive
+                       // to the scheduler in case of e.g. preemption. A larger value means
+                       // that the overheads of scavenging are better amortized, so better
+                       // scavenging throughput.
+                       //
+                       // The current value is chosen assuming a cost of ~10ยตs/physical page
+                       // (this is somewhat pessimistic), which implies a worst-case latency of
+                       // about 160ยตs for 4 KiB physical pages. The current value is biased
+                       // toward latency over throughput.
+                       const scavengeQuantum = 64 << 10
+
+                       // Accumulate the amount of time spent scavenging.
                        start := nanotime()
-                       released = mheap_.pages.scavenge(physPageSize, true)
-                       mheap_.pages.scav.released += released
-                       crit = float64(nanotime() - start)
+                       released = mheap_.pages.scavenge(scavengeQuantum)
+                       atomic.Xadduintptr(&mheap_.pages.scav.released, released)
+                       end := nanotime()
 
-                       unlock(&mheap_.lock)
-               })
+                       // On some platforms we may see end >= start if the time it takes to scavenge
+                       // memory is less than the minimum granularity of its clock (e.g. Windows) or
+                       // due to clock bugs.
+                       //
+                       // In this case, just assume scavenging takes 10 ยตs per regular physical page
+                       // (determined empirically), and conservatively ignore the impact of huge pages
+                       // on timing.
+                       const approxCritNSPerPhysicalPage = 10e3
+                       if end <= start {
+                               crit += approxCritNSPerPhysicalPage * float64(released/physPageSize)
+                       } else {
+                               crit += float64(end - start)
+                       }
+               }
 
                if released == 0 {
                        lock(&scavenge.lock)
@@ -329,18 +360,13 @@ func bgscavenge(c chan int) {
                        throw("released less than one physical page of memory")
                }
 
-               // On some platforms we may see crit as zero if the time it takes to scavenge
-               // memory is less than the minimum granularity of its clock (e.g. Windows).
-               // In this case, just assume scavenging takes 10 ยตs per regular physical page
-               // (determined empirically), and conservatively ignore the impact of huge pages
-               // on timing.
-               //
-               // We shouldn't ever see a crit value less than zero unless there's a bug of
-               // some kind, either on our side or in the platform we're running on, but be
-               // defensive in that case as well.
-               const approxCritNSPerPhysicalPage = 10e3
-               if crit <= 0 {
-                       crit = approxCritNSPerPhysicalPage * float64(released/physPageSize)
+               if crit < minCritTime {
+                       // This means there wasn't enough work to actually fill up minCritTime.
+                       // That's fine; we shouldn't try to do anything with this information
+                       // because it's going result in a short enough sleep request that things
+                       // will get messy. Just assume we did at least this much work.
+                       // All this means is that we'll sleep longer than we otherwise would have.
+                       crit = minCritTime
                }
 
                // Multiply the critical time by 1 + the ratio of the costs of using
@@ -351,41 +377,19 @@ func bgscavenge(c chan int) {
                // because of the additional overheads of using scavenged memory.
                crit *= 1 + scavengeCostRatio
 
-               // If we spent more than 10 ms (for example, if the OS scheduled us away, or someone
-               // put their machine to sleep) in the critical section, bound the time we use to
-               // calculate at 10 ms to avoid letting the sleep time get arbitrarily high.
-               const maxCrit = 10e6
-               if crit > maxCrit {
-                       crit = maxCrit
-               }
+               // Go to sleep for our current sleepNS.
+               slept := scavengeSleep(int64(crit / critSleepRatio))
 
-               // Compute the amount of time to sleep, assuming we want to use at most
-               // scavengePercent of CPU time. Take into account scheduling overheads
-               // that may extend the length of our sleep by multiplying by how far
-               // off we are from the ideal ratio. For example, if we're sleeping too
-               // much, then scavengeEMWA < idealFraction, so we'll adjust the sleep time
-               // down.
-               adjust := scavengeEWMA / idealFraction
-               sleepTime := int64(adjust * crit / (scavengePercent / 100.0))
-
-               // Go to sleep.
-               slept := scavengeSleep(sleepTime)
-
-               // Compute the new ratio.
-               fraction := crit / (crit + float64(slept))
-
-               // Set a lower bound on the fraction.
-               // Due to OS-related anomalies we may "sleep" for an inordinate amount
-               // of time. Let's avoid letting the ratio get out of hand by bounding
-               // the sleep time we use in our EWMA.
-               const minFraction = 1.0 / 1000.0
-               if fraction < minFraction {
-                       fraction = minFraction
-               }
+               // Calculate the CPU time spent.
+               //
+               // This may be slightly inaccurate with respect to GOMAXPROCS, but we're
+               // recomputing this often enough relative to GOMAXPROCS changes in general
+               // (it only changes when the world is stopped, and not during a GC) that
+               // that small inaccuracy is in the noise.
+               cpuFraction := float64(crit) / ((float64(slept) + crit) * float64(gomaxprocs))
 
-               // Update scavengeEWMA by merging in the new crit/slept ratio.
-               const alpha = 0.5
-               scavengeEWMA = alpha*fraction + (1-alpha)*scavengeEWMA
+               // Update the critSleepRatio, adjusting until we reach our ideal fraction.
+               critSleepRatio = critSleepController.next(cpuFraction, idealFraction, float64(slept)+crit)
        }
 }
 
@@ -395,16 +399,7 @@ func bgscavenge(c chan int) {
 // back to the top of the heap.
 //
 // Returns the amount of memory scavenged in bytes.
-//
-// p.mheapLock must be held, but may be temporarily released if
-// mayUnlock == true.
-//
-// Must run on the system stack because p.mheapLock must be held.
-//
-//go:systemstack
-func (p *pageAlloc) scavenge(nbytes uintptr, mayUnlock bool) uintptr {
-       assertLockHeld(p.mheapLock)
-
+func (p *pageAlloc) scavenge(nbytes uintptr) uintptr {
        var (
                addrs addrRange
                gen   uint32
@@ -416,9 +411,11 @@ func (p *pageAlloc) scavenge(nbytes uintptr, mayUnlock bool) uintptr {
                                break
                        }
                }
-               r, a := p.scavengeOne(addrs, nbytes-released, mayUnlock)
-               released += r
-               addrs = a
+               systemstack(func() {
+                       r, a := p.scavengeOne(addrs, nbytes-released)
+                       released += r
+                       addrs = a
+               })
        }
        // Only unreserve the space which hasn't been scavenged or searched
        // to ensure we always make progress.
@@ -456,8 +453,9 @@ func printScavTrace(gen uint32, released uintptr, forced bool) {
 func (p *pageAlloc) scavengeStartGen() {
        assertLockHeld(p.mheapLock)
 
+       lock(&p.scav.lock)
        if debug.scavtrace > 0 {
-               printScavTrace(p.scav.gen, p.scav.released, false)
+               printScavTrace(p.scav.gen, atomic.Loaduintptr(&p.scav.released), false)
        }
        p.inUse.cloneInto(&p.scav.inUse)
 
@@ -487,9 +485,10 @@ func (p *pageAlloc) scavengeStartGen() {
        // arena in size, so virtually every heap has the scavenger on.
        p.scav.reservationBytes = alignUp(p.inUse.totalBytes, pallocChunkBytes) / scavengeReservationShards
        p.scav.gen++
-       p.scav.released = 0
+       atomic.Storeuintptr(&p.scav.released, 0)
        p.scav.freeHWM = minOffAddr
        p.scav.scavLWM = maxOffAddr
+       unlock(&p.scav.lock)
 }
 
 // scavengeReserve reserves a contiguous range of the address space
@@ -498,14 +497,9 @@ func (p *pageAlloc) scavengeStartGen() {
 // first.
 //
 // Returns the reserved range and the scavenge generation number for it.
-//
-// p.mheapLock must be held.
-//
-// Must run on the system stack because p.mheapLock must be held.
-//
-//go:systemstack
 func (p *pageAlloc) scavengeReserve() (addrRange, uint32) {
-       assertLockHeld(p.mheapLock)
+       lock(&p.scav.lock)
+       gen := p.scav.gen
 
        // Start by reserving the minimum.
        r := p.scav.inUse.removeLast(p.scav.reservationBytes)
@@ -513,7 +507,8 @@ func (p *pageAlloc) scavengeReserve() (addrRange, uint32) {
        // Return early if the size is zero; we don't want to use
        // the bogus address below.
        if r.size() == 0 {
-               return r, p.scav.gen
+               unlock(&p.scav.lock)
+               return r, gen
        }
 
        // The scavenger requires that base be aligned to a
@@ -524,28 +519,26 @@ func (p *pageAlloc) scavengeReserve() (addrRange, uint32) {
 
        // Remove from inUse however much extra we just pulled out.
        p.scav.inUse.removeGreaterEqual(newBase)
+       unlock(&p.scav.lock)
+
        r.base = offAddr{newBase}
-       return r, p.scav.gen
+       return r, gen
 }
 
 // scavengeUnreserve returns an unscavenged portion of a range that was
 // previously reserved with scavengeReserve.
-//
-// p.mheapLock must be held.
-//
-// Must run on the system stack because p.mheapLock must be held.
-//
-//go:systemstack
 func (p *pageAlloc) scavengeUnreserve(r addrRange, gen uint32) {
-       assertLockHeld(p.mheapLock)
-
-       if r.size() == 0 || gen != p.scav.gen {
+       if r.size() == 0 {
                return
        }
        if r.base.addr()%pallocChunkBytes != 0 {
                throw("unreserving unaligned region")
        }
-       p.scav.inUse.add(r)
+       lock(&p.scav.lock)
+       if gen == p.scav.gen {
+               p.scav.inUse.add(r)
+       }
+       unlock(&p.scav.lock)
 }
 
 // scavengeOne walks over address range work until it finds
@@ -559,15 +552,10 @@ func (p *pageAlloc) scavengeUnreserve(r addrRange, gen uint32) {
 //
 // work's base address must be aligned to pallocChunkBytes.
 //
-// p.mheapLock must be held, but may be temporarily released if
-// mayUnlock == true.
-//
-// Must run on the system stack because p.mheapLock must be held.
+// Must run on the systemstack because it acquires p.mheapLock.
 //
 //go:systemstack
-func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (uintptr, addrRange) {
-       assertLockHeld(p.mheapLock)
-
+func (p *pageAlloc) scavengeOne(work addrRange, max uintptr) (uintptr, addrRange) {
        // Defensively check if we've received an empty address range.
        // If so, just return.
        if work.size() == 0 {
@@ -599,40 +587,12 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui
                minPages = 1
        }
 
-       // Helpers for locking and unlocking only if mayUnlock == true.
-       lockHeap := func() {
-               if mayUnlock {
-                       lock(p.mheapLock)
-               }
-       }
-       unlockHeap := func() {
-               if mayUnlock {
-                       unlock(p.mheapLock)
-               }
-       }
-
-       // Fast path: check the chunk containing the top-most address in work,
-       // starting at that address's page index in the chunk.
-       //
-       // Note that work.end() is exclusive, so get the chunk we care about
-       // by subtracting 1.
-       maxAddr := work.limit.addr() - 1
-       maxChunk := chunkIndex(maxAddr)
-       if p.summary[len(p.summary)-1][maxChunk].max() >= uint(minPages) {
-               // We only bother looking for a candidate if there at least
-               // minPages free pages at all.
-               base, npages := p.chunkOf(maxChunk).findScavengeCandidate(chunkPageIndex(maxAddr), minPages, maxPages)
-
-               // If we found something, scavenge it and return!
-               if npages != 0 {
-                       work.limit = offAddr{p.scavengeRangeLocked(maxChunk, base, npages)}
-
-                       assertLockHeld(p.mheapLock) // Must be locked on return.
-                       return uintptr(npages) * pageSize, work
-               }
+       // Fast path: check the chunk containing the top-most address in work.
+       if r, w := p.scavengeOneFast(work, minPages, maxPages); r != 0 {
+               return r, w
+       } else {
+               work = w
        }
-       // Update the limit to reflect the fact that we checked maxChunk already.
-       work.limit = offAddr{chunkBase(maxChunk)}
 
        // findCandidate finds the next scavenge candidate in work optimistically.
        //
@@ -671,37 +631,61 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui
        // looking for any free and unscavenged page. If we think we see something,
        // lock and verify it!
        for work.size() != 0 {
-               unlockHeap()
 
                // Search for the candidate.
                candidateChunkIdx, ok := findCandidate(work)
-
-               // Lock the heap. We need to do this now if we found a candidate or not.
-               // If we did, we'll verify it. If not, we need to lock before returning
-               // anyway.
-               lockHeap()
-
                if !ok {
                        // We didn't find a candidate, so we're done.
                        work.limit = work.base
                        break
                }
 
+               // Lock, so we can verify what we found.
+               lock(p.mheapLock)
+
                // Find, verify, and scavenge if we can.
                chunk := p.chunkOf(candidateChunkIdx)
                base, npages := chunk.findScavengeCandidate(pallocChunkPages-1, minPages, maxPages)
                if npages > 0 {
                        work.limit = offAddr{p.scavengeRangeLocked(candidateChunkIdx, base, npages)}
-
-                       assertLockHeld(p.mheapLock) // Must be locked on return.
+                       unlock(p.mheapLock)
                        return uintptr(npages) * pageSize, work
                }
+               unlock(p.mheapLock)
 
                // We were fooled, so let's continue from where we left off.
                work.limit = offAddr{chunkBase(candidateChunkIdx)}
        }
+       return 0, work
+}
+
+// scavengeOneFast is the fast path for scavengeOne, which just checks the top
+// chunk of work for some pages to scavenge.
+//
+// Must run on the system stack because it acquires the heap lock.
+//
+//go:systemstack
+func (p *pageAlloc) scavengeOneFast(work addrRange, minPages, maxPages uintptr) (uintptr, addrRange) {
+       maxAddr := work.limit.addr() - 1
+       maxChunk := chunkIndex(maxAddr)
 
-       assertLockHeld(p.mheapLock) // Must be locked on return.
+       lock(p.mheapLock)
+       if p.summary[len(p.summary)-1][maxChunk].max() >= uint(minPages) {
+               // We only bother looking for a candidate if there at least
+               // minPages free pages at all.
+               base, npages := p.chunkOf(maxChunk).findScavengeCandidate(chunkPageIndex(maxAddr), minPages, maxPages)
+
+               // If we found something, scavenge it and return!
+               if npages != 0 {
+                       work.limit = offAddr{p.scavengeRangeLocked(maxChunk, base, npages)}
+                       unlock(p.mheapLock)
+                       return uintptr(npages) * pageSize, work
+               }
+       }
+       unlock(p.mheapLock)
+
+       // Update the limit to reflect the fact that we checked maxChunk already.
+       work.limit = offAddr{chunkBase(maxChunk)}
        return 0, work
 }
 
@@ -712,38 +696,57 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui
 //
 // Returns the base address of the scavenged region.
 //
-// p.mheapLock must be held.
+// p.mheapLock must be held. Unlocks p.mheapLock but reacquires
+// it before returning. Must be run on the systemstack as a result.
+//
+//go:systemstack
 func (p *pageAlloc) scavengeRangeLocked(ci chunkIdx, base, npages uint) uintptr {
        assertLockHeld(p.mheapLock)
 
-       p.chunkOf(ci).scavenged.setRange(base, npages)
-
        // Compute the full address for the start of the range.
        addr := chunkBase(ci) + uintptr(base)*pageSize
 
+       // Mark the range we're about to scavenge as allocated, because
+       // we don't want any allocating goroutines to grab it while
+       // the scavenging is in progress.
+       if scav := p.allocRange(addr, uintptr(npages)); scav != 0 {
+               throw("double scavenge")
+       }
+
+       // With that done, it's safe to unlock.
+       unlock(p.mheapLock)
+
        // Update the scavenge low watermark.
+       lock(&p.scav.lock)
        if oAddr := (offAddr{addr}); oAddr.lessThan(p.scav.scavLWM) {
                p.scav.scavLWM = oAddr
        }
+       unlock(&p.scav.lock)
 
-       // Only perform the actual scavenging if we're not in a test.
-       // It's dangerous to do so otherwise.
-       if p.test {
-               return addr
-       }
-       sysUnused(unsafe.Pointer(addr), uintptr(npages)*pageSize)
+       if !p.test {
+               // Only perform the actual scavenging if we're not in a test.
+               // It's dangerous to do so otherwise.
+               sysUnused(unsafe.Pointer(addr), uintptr(npages)*pageSize)
 
-       // Update global accounting only when not in test, otherwise
-       // the runtime's accounting will be wrong.
-       nbytes := int64(npages) * pageSize
-       atomic.Xadd64(&memstats.heap_released, nbytes)
+               // Update global accounting only when not in test, otherwise
+               // the runtime's accounting will be wrong.
+               nbytes := int64(npages) * pageSize
+               atomic.Xadd64(&memstats.heap_released, nbytes)
 
-       // Update consistent accounting too.
-       stats := memstats.heapStats.acquire()
-       atomic.Xaddint64(&stats.committed, -nbytes)
-       atomic.Xaddint64(&stats.released, nbytes)
-       memstats.heapStats.release()
+               // Update consistent accounting too.
+               stats := memstats.heapStats.acquire()
+               atomic.Xaddint64(&stats.committed, -nbytes)
+               atomic.Xaddint64(&stats.released, nbytes)
+               memstats.heapStats.release()
+       }
+
+       // Relock the heap, because now we need to make these pages
+       // available allocation. Free them back to the page allocator.
+       lock(p.mheapLock)
+       p.free(addr, uintptr(npages), true)
 
+       // Mark the range as scavenged.
+       p.chunkOf(ci).scavenged.setRange(base, npages)
        return addr
 }
 
index 3b12a2e1e631524e4ea267025214f34966fa42a0..b186cad2f40b13193076b584ab889b291b13e1c9 100644 (file)
@@ -430,12 +430,12 @@ func TestPageAllocScavenge(t *testing.T) {
        }
        for name, v := range tests {
                v := v
-               runTest := func(t *testing.T, mayUnlock bool) {
+               t.Run(name, func(t *testing.T) {
                        b := NewPageAlloc(v.beforeAlloc, v.beforeScav)
                        defer FreePageAlloc(b)
 
                        for iter, h := range v.expect {
-                               if got := b.Scavenge(h.request, mayUnlock); got != h.expect {
+                               if got := b.Scavenge(h.request); got != h.expect {
                                        t.Fatalf("bad scavenge #%d: want %d, got %d", iter+1, h.expect, got)
                                }
                        }
@@ -443,12 +443,6 @@ func TestPageAllocScavenge(t *testing.T) {
                        defer FreePageAlloc(want)
 
                        checkPageAlloc(t, want, b)
-               }
-               t.Run(name, func(t *testing.T) {
-                       runTest(t, false)
-               })
-               t.Run(name+"MayUnlock", func(t *testing.T) {
-                       runTest(t, true)
                })
        }
 }
index f2f6e7f4cf7f154d4f5dc561ce4defbd0f334a10..ecbd0a3a492a33fede00394babd9b813de530e11 100644 (file)
@@ -80,7 +80,7 @@ type mheap struct {
        // access (since that may free the backing store).
        allspans []*mspan // all spans out there
 
-       _ uint32 // align uint64 fields on 32-bit for atomics
+       // _ uint32 // align uint64 fields on 32-bit for atomics
 
        // Proportional sweep
        //
@@ -1120,6 +1120,7 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass
        // Function-global state.
        gp := getg()
        base, scav := uintptr(0), uintptr(0)
+       growth := uintptr(0)
 
        // On some platforms we need to provide physical page aligned stack
        // allocations. Where the page size is less than the physical page
@@ -1165,7 +1166,9 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass
                // Try to acquire a base address.
                base, scav = h.pages.alloc(npages)
                if base == 0 {
-                       if !h.grow(npages) {
+                       var ok bool
+                       growth, ok = h.grow(npages)
+                       if !ok {
                                unlock(&h.lock)
                                return nil
                        }
@@ -1189,16 +1192,35 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass
                // Return memory around the aligned allocation.
                spaceBefore := base - allocBase
                if spaceBefore > 0 {
-                       h.pages.free(allocBase, spaceBefore/pageSize)
+                       h.pages.free(allocBase, spaceBefore/pageSize, false)
                }
                spaceAfter := (allocPages-npages)*pageSize - spaceBefore
                if spaceAfter > 0 {
-                       h.pages.free(base+npages*pageSize, spaceAfter/pageSize)
+                       h.pages.free(base+npages*pageSize, spaceAfter/pageSize, false)
                }
        }
 
        unlock(&h.lock)
 
+       if growth > 0 {
+               // We just caused a heap growth, so scavenge down what will soon be used.
+               // By scavenging inline we deal with the failure to allocate out of
+               // memory fragments by scavenging the memory fragments that are least
+               // likely to be re-used.
+               scavengeGoal := atomic.Load64(&h.scavengeGoal)
+               if retained := heapRetained(); retained+uint64(growth) > scavengeGoal {
+                       // The scavenging algorithm requires the heap lock to be dropped so it
+                       // can acquire it only sparingly. This is a potentially expensive operation
+                       // so it frees up other goroutines to allocate in the meanwhile. In fact,
+                       // they can make use of the growth we just created.
+                       todo := growth
+                       if overage := uintptr(retained + uint64(growth) - scavengeGoal); todo > overage {
+                               todo = overage
+                       }
+                       h.pages.scavenge(todo)
+               }
+       }
+
 HaveSpan:
        // At this point, both s != nil and base != 0, and the heap
        // lock is no longer held. Initialize the span.
@@ -1311,10 +1333,10 @@ HaveSpan:
 }
 
 // Try to add at least npage pages of memory to the heap,
-// returning whether it worked.
+// returning how much the heap grew by and whether it worked.
 //
 // h.lock must be held.
-func (h *mheap) grow(npage uintptr) bool {
+func (h *mheap) grow(npage uintptr) (uintptr, bool) {
        assertLockHeld(&h.lock)
 
        // We must grow the heap in whole palloc chunks.
@@ -1336,7 +1358,7 @@ func (h *mheap) grow(npage uintptr) bool {
                av, asize := h.sysAlloc(ask)
                if av == nil {
                        print("runtime: out of memory: cannot allocate ", ask, "-byte block (", memstats.heap_sys, " in use)\n")
-                       return false
+                       return 0, false
                }
 
                if uintptr(av) == h.curArena.end {
@@ -1396,20 +1418,7 @@ func (h *mheap) grow(npage uintptr) bool {
        // space ready for allocation.
        h.pages.grow(v, nBase-v)
        totalGrowth += nBase - v
-
-       // We just caused a heap growth, so scavenge down what will soon be used.
-       // By scavenging inline we deal with the failure to allocate out of
-       // memory fragments by scavenging the memory fragments that are least
-       // likely to be re-used.
-       scavengeGoal := atomic.Load64(&h.scavengeGoal)
-       if retained := heapRetained(); retained+uint64(totalGrowth) > scavengeGoal {
-               todo := totalGrowth
-               if overage := uintptr(retained + uint64(totalGrowth) - scavengeGoal); todo > overage {
-                       todo = overage
-               }
-               h.pages.scavenge(todo, false)
-       }
-       return true
+       return totalGrowth, true
 }
 
 // Free the span back into the heap.
@@ -1499,7 +1508,7 @@ func (h *mheap) freeSpanLocked(s *mspan, typ spanAllocType) {
        memstats.heapStats.release()
 
        // Mark the space as free.
-       h.pages.free(s.base(), s.npages)
+       h.pages.free(s.base(), s.npages, false)
 
        // Free the span structure. We no longer have a use for it.
        s.state.set(mSpanDead)
@@ -1515,13 +1524,19 @@ func (h *mheap) scavengeAll() {
        // the mheap API.
        gp := getg()
        gp.m.mallocing++
+
        lock(&h.lock)
        // Start a new scavenge generation so we have a chance to walk
        // over the whole heap.
        h.pages.scavengeStartGen()
-       released := h.pages.scavenge(^uintptr(0), false)
-       gen := h.pages.scav.gen
        unlock(&h.lock)
+
+       released := h.pages.scavenge(^uintptr(0))
+
+       lock(&h.pages.scav.lock)
+       gen := h.pages.scav.gen
+       unlock(&h.pages.scav.lock)
+
        gp.m.mallocing--
 
        if debug.scavtrace > 0 {
index 862882cd82472388ec93aa6662c2c4d9b1662e33..2725e3b7c7b59b4d7f8d3ab36b823533c82d4454 100644 (file)
@@ -226,6 +226,8 @@ type pageAlloc struct {
        // are currently available. Otherwise one might iterate over unused
        // ranges.
        //
+       // Protected by mheapLock.
+       //
        // TODO(mknyszek): Consider changing the definition of the bitmap
        // such that 1 means free and 0 means in-use so that summaries and
        // the bitmaps align better on zero-values.
@@ -261,29 +263,41 @@ type pageAlloc struct {
        inUse addrRanges
 
        // scav stores the scavenger state.
-       //
-       // All fields are protected by mheapLock.
        scav struct {
+               lock mutex
+
                // inUse is a slice of ranges of address space which have not
                // yet been looked at by the scavenger.
+               //
+               // Protected by lock.
                inUse addrRanges
 
                // gen is the scavenge generation number.
+               //
+               // Protected by lock.
                gen uint32
 
                // reservationBytes is how large of a reservation should be made
                // in bytes of address space for each scavenge iteration.
+               //
+               // Protected by lock.
                reservationBytes uintptr
 
                // released is the amount of memory released this generation.
+               //
+               // Updated atomically.
                released uintptr
 
                // scavLWM is the lowest (offset) address that the scavenger reached this
                // scavenge generation.
+               //
+               // Protected by lock.
                scavLWM offAddr
 
                // freeHWM is the highest (offset) address of a page that was freed to
                // the page allocator this scavenge generation.
+               //
+               // Protected by mheapLock.
                freeHWM offAddr
        }
 
@@ -864,17 +878,19 @@ Found:
 // Must run on the system stack because p.mheapLock must be held.
 //
 //go:systemstack
-func (p *pageAlloc) free(base, npages uintptr) {
+func (p *pageAlloc) free(base, npages uintptr, scavenged bool) {
        assertLockHeld(p.mheapLock)
 
        // If we're freeing pages below the p.searchAddr, update searchAddr.
        if b := (offAddr{base}); b.lessThan(p.searchAddr) {
                p.searchAddr = b
        }
-       // Update the free high watermark for the scavenger.
        limit := base + npages*pageSize - 1
-       if offLimit := (offAddr{limit}); p.scav.freeHWM.lessThan(offLimit) {
-               p.scav.freeHWM = offLimit
+       if !scavenged {
+               // Update the free high watermark for the scavenger.
+               if offLimit := (offAddr{limit}); p.scav.freeHWM.lessThan(offLimit) {
+                       p.scav.freeHWM = offLimit
+               }
        }
        if npages == 1 {
                // Fast path: we're clearing a single bit, and we know exactly
index 341ba9a9365c2eef81ad998d5ab173785f3d2f0d..c2303e5b8ec0617f9777f63248e4a8d5e797af2c 100644 (file)
@@ -790,7 +790,15 @@ type consistentHeapStats struct {
 //
 // The caller's P must not change between acquire and
 // release. This also means that the caller should not
-// acquire a P or release its P in between.
+// acquire a P or release its P in between. A P also must
+// not acquire a given consistentHeapStats if it hasn't
+// yet released it.
+//
+// nosplit because a stack growth in this function could
+// lead to a stack allocation that could reenter the
+// function.
+//
+//go:nosplit
 func (m *consistentHeapStats) acquire() *heapStatsDelta {
        if pp := getg().m.p.ptr(); pp != nil {
                seq := atomic.Xadd(&pp.statsSeq, 1)
@@ -814,6 +822,12 @@ func (m *consistentHeapStats) acquire() *heapStatsDelta {
 // The caller's P must not change between acquire and
 // release. This also means that the caller should not
 // acquire a P or release its P in between.
+//
+// nosplit because a stack growth in this function could
+// lead to a stack allocation that causes another acquire
+// before this operation has completed.
+//
+//go:nosplit
 func (m *consistentHeapStats) release() {
        if pp := getg().m.p.ptr(); pp != nil {
                seq := atomic.Xadd(&pp.statsSeq, 1)
index b6c3cbfff4806d2600730a6ebe77153598ed3f58..65e1e0eebca1c1ded1e54c6fad41a5fb6b0cfa29 100644 (file)
@@ -315,6 +315,7 @@ var debug struct {
        schedtrace         int32
        tracebackancestors int32
        asyncpreemptoff    int32
+       harddecommit       int32
 
        // debug.malloc is used as a combined debug check
        // in the malloc function and should be set
@@ -344,6 +345,7 @@ var dbgvars = []dbgVar{
        {"tracebackancestors", &debug.tracebackancestors},
        {"asyncpreemptoff", &debug.asyncpreemptoff},
        {"inittrace", &debug.inittrace},
+       {"harddecommit", &debug.harddecommit},
 }
 
 func parsedebugvars() {
index 7d9ae1e9d24dc3f7a9d03a63991772d1d6cef1af..25a6f5bbb465ad83e53c29f91c7137b08673bcbd 100644 (file)
@@ -1002,7 +1002,7 @@ func newstack() {
        // NOTE: stackguard0 may change underfoot, if another thread
        // is about to try to preempt gp. Read it just once and use that same
        // value now and below.
-       preempt := atomic.Loaduintptr(&gp.stackguard0) == stackPreempt
+       stackguard0 := atomic.Loaduintptr(&gp.stackguard0)
 
        // Be conservative about where we preempt.
        // We are interested in preempting user Go code, not runtime code.
@@ -1016,6 +1016,7 @@ func newstack() {
        // If the GC is in some way dependent on this goroutine (for example,
        // it needs a lock held by the goroutine), that small preemption turns
        // into a real deadlock.
+       preempt := stackguard0 == stackPreempt
        if preempt {
                if !canPreemptM(thisg.m) {
                        // Let the goroutine keep running for now.
@@ -1083,7 +1084,7 @@ func newstack() {
                }
        }
 
-       if gp.stackguard0 == stackForceMove {
+       if stackguard0 == stackForceMove {
                // Forced stack movement used for debugging.
                // Don't double the stack (or we may quickly run out
                // if this is done repeatedly).
index 0333b85c56c75287e762241b8cb48ca57f111e66..7d8b04e14b732e2b1615f115cf563d92d9f1c4dd 100644 (file)
@@ -353,6 +353,9 @@ func testTracebackArgs8d(a testArgsType8d) int {
        return n
 }
 
+// nosplit to avoid preemption or morestack spilling registers.
+//
+//go:nosplit
 //go:noinline
 func testTracebackArgs9(a int64, b int32, c int16, d int8, x [2]int, y int) int {
        if a < 0 {
@@ -366,6 +369,9 @@ func testTracebackArgs9(a int64, b int32, c int16, d int8, x [2]int, y int) int
        return n
 }
 
+// nosplit to avoid preemption or morestack spilling registers.
+//
+//go:nosplit
 //go:noinline
 func testTracebackArgs10(a, b, c, d, e int32) int {
        // no use of any args
@@ -373,8 +379,10 @@ func testTracebackArgs10(a, b, c, d, e int32) int {
 }
 
 // norace to avoid race instrumentation changing spill locations.
+// nosplit to avoid preemption or morestack spilling registers.
 //
 //go:norace
+//go:nosplit
 //go:noinline
 func testTracebackArgs11a(a, b, c int32) int {
        if a < 0 {
@@ -387,8 +395,10 @@ func testTracebackArgs11a(a, b, c int32) int {
 }
 
 // norace to avoid race instrumentation changing spill locations.
+// nosplit to avoid preemption or morestack spilling registers.
 //
 //go:norace
+//go:nosplit
 //go:noinline
 func testTracebackArgs11b(a, b, c, d int32) int {
        var x int32
index bc734048c3fc2223cf57b2bdf9f739d1dcb62e19..c5a29e95f6dd5ac7602e9544fc1c8ffdc73bc865 100644 (file)
@@ -706,7 +706,8 @@ func isSeparator(r rune) bool {
 // Title returns a copy of the string s with all Unicode letters that begin words
 // mapped to their Unicode title case.
 //
-// BUG(rsc): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
+// Deprecated: The rule Title uses for word boundaries does not handle Unicode
+// punctuation properly. Use golang.org/x/text/cases instead.
 func Title(s string) string {
        // Use a closure here to remember state.
        // Hackish but effective. Depends on Map scanning in order and calling
index dffb52864bad59de3f1c033c3c8ce98e6f3c7add..5fc91d381584297e61226399a327c9d0e1a72245 100755 (executable)
@@ -283,7 +283,7 @@ netbsd_arm64)
        mktypes="GOARCH=$GOARCH go tool cgo -godefs"
        ;;
 openbsd_386)
-       GOOSARCH_in="syscall_openbsd1.go syscall_openbsd_$GOARCH.go"
+       GOOSARCH_in="syscall_openbsd_libc.go syscall_openbsd_$GOARCH.go"
        mkerrors="$mkerrors -m32"
        mksyscall="./mksyscall.pl -l32 -openbsd -libc"
        mksysctl="./mksysctl_openbsd.pl"
index 0afb18aba6b4e5beb9233d54156966cb66cccfca..ec2259b1bae5e2af3454dd94731377cabcc2483b 100644 (file)
@@ -344,6 +344,23 @@ func ExampleTime_Format_pad() {
 
 }
 
+func ExampleTime_GoString() {
+       t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+       fmt.Println(t.GoString())
+       t = t.Add(1 * time.Minute)
+       fmt.Println(t.GoString())
+       t = t.AddDate(0, 1, 0)
+       fmt.Println(t.GoString())
+       t, _ = time.Parse("Jan 2, 2006 at 3:04pm (MST)", "Feb 3, 2013 at 7:54pm (UTC)")
+       fmt.Println(t.GoString())
+
+       // Output:
+       // time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+       // time.Date(2009, time.November, 10, 23, 1, 0, 0, time.UTC)
+       // time.Date(2009, time.December, 10, 23, 1, 0, 0, time.UTC)
+       // time.Date(2013, time.February, 3, 19, 54, 0, 0, time.UTC)
+}
+
 func ExampleParse() {
        // See the example for Time.Format for a thorough description of how
        // to define the layout string to parse a time.Time value; Parse and
@@ -401,6 +418,39 @@ func ExampleParseInLocation() {
        // 2012-07-09 00:00:00 +0200 CEST
 }
 
+func ExampleUnix() {
+       unixTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+       fmt.Println(unixTime.Unix())
+       t := time.Unix(unixTime.Unix(), 0).UTC()
+       fmt.Println(t)
+
+       // Output:
+       // 1257894000
+       // 2009-11-10 23:00:00 +0000 UTC
+}
+
+func ExampleUnixMicro() {
+       umt := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+       fmt.Println(umt.UnixMicro())
+       t := time.UnixMicro(umt.UnixMicro()).UTC()
+       fmt.Println(t)
+
+       // Output:
+       // 1257894000000000
+       // 2009-11-10 23:00:00 +0000 UTC
+}
+
+func ExampleUnixMilli() {
+       umt := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+       fmt.Println(umt.UnixMilli())
+       t := time.UnixMilli(umt.UnixMilli()).UTC()
+       fmt.Println(t)
+
+       // Output:
+       // 1257894000000
+       // 2009-11-10 23:00:00 +0000 UTC
+}
+
 func ExampleTime_Unix() {
        // 1 billion seconds of Unix, three ways.
        fmt.Println(time.Unix(1e9, 0).UTC())     // 1e9 seconds
index f9522b0b754ad6c2566b0e04cb45fd856a7857b5..babf865aeb086bafbe85eecefd290db1ecf1acc6 100644 (file)
@@ -48,8 +48,12 @@ func (t *Ticker) Stop() {
 }
 
 // Reset stops a ticker and resets its period to the specified duration.
-// The next tick will arrive after the new period elapses.
+// The next tick will arrive after the new period elapses. The duration d
+// must be greater than zero; if not, Reset will panic.
 func (t *Ticker) Reset(d Duration) {
+       if d <= 0 {
+               panic("non-positive interval for Ticker.Reset")
+       }
        if t.r.f == nil {
                panic("time: Reset called on uninitialized Ticker")
        }
index d8cd59228f0fd47adf01273d384fd48a876f44c4..f539091869fcaf2f06bde50954608d2a229ee79c 100644 (file)
@@ -134,6 +134,17 @@ func TestNewTickerLtZeroDuration(t *testing.T) {
        NewTicker(-1)
 }
 
+// Test that Ticker.Reset panics when given a duration less than zero.
+func TestTickerResetLtZeroDuration(t *testing.T) {
+       defer func() {
+               if err := recover(); err == nil {
+                       t.Errorf("Ticker.Reset(0) should have panicked")
+               }
+       }()
+       tk := NewTicker(Second)
+       tk.Reset(0)
+}
+
 func BenchmarkTicker(b *testing.B) {
        benchmark(b, func(n int) {
                ticker := NewTicker(Nanosecond)
index edf0c6261026ddf6e6599b302870a691f694adca..8046ff508b6b4fc7a77258e23e241da8d1c40389 100644 (file)
@@ -1433,17 +1433,17 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T
 
        unix := int64(abs) + (absoluteToInternal + internalToUnix)
 
-       // Look for zone offset for t, so we can adjust to UTC.
-       // The lookup function expects UTC, so we pass t in the
+       // Look for zone offset for expected time, so we can adjust to UTC.
+       // The lookup function expects UTC, so first we pass unix in the
        // hope that it will not be too close to a zone transition,
        // and then adjust if it is.
        _, offset, start, end, _ := loc.lookup(unix)
        if offset != 0 {
-               switch utc := unix - int64(offset); {
-               case utc < start:
-                       _, offset, _, _, _ = loc.lookup(start - 1)
-               case utc >= end:
-                       _, offset, _, _, _ = loc.lookup(end)
+               utc := unix - int64(offset)
+               // If utc is valid for the time zone we found, then we have the right offset.
+               // If not, we get the correct offset by looking up utc in the location.
+               if utc < start || utc >= end {
+                       _, offset, _, _, _ = loc.lookup(utc)
                }
                unix -= int64(offset)
        }
index 5007b6e723128a0827afb8af853e0a6e9086f10c..6a4049617cb640703835d7b36c82eaae4682f099 100644 (file)
@@ -1616,3 +1616,45 @@ func TestTimeAddSecOverflow(t *testing.T) {
                }
        }
 }
+
+// Issue 49284: time: ParseInLocation incorrectly because of Daylight Saving Time
+func TestTimeWithZoneTransition(t *testing.T) {
+       ForceZipFileForTesting(true)
+       defer ForceZipFileForTesting(false)
+
+       loc, err := LoadLocation("Asia/Shanghai")
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       tests := [...]struct {
+               give Time
+               want Time
+       }{
+               // 14 Apr 1991 - Daylight Saving Time Started
+               // When time of "Asia/Shanghai" was about to reach
+               // Sunday, 14 April 1991, 02:00:00 clocks were turned forward 1 hour to
+               // Sunday, 14 April 1991, 03:00:00 local daylight time instead.
+               // The UTC time was 13 April 1991, 18:00:00
+               0: {Date(1991, April, 13, 17, 50, 0, 0, loc), Date(1991, April, 13, 9, 50, 0, 0, UTC)},
+               1: {Date(1991, April, 13, 18, 0, 0, 0, loc), Date(1991, April, 13, 10, 0, 0, 0, UTC)},
+               2: {Date(1991, April, 14, 1, 50, 0, 0, loc), Date(1991, April, 13, 17, 50, 0, 0, UTC)},
+               3: {Date(1991, April, 14, 3, 0, 0, 0, loc), Date(1991, April, 13, 18, 0, 0, 0, UTC)},
+
+               // 15 Sep 1991 - Daylight Saving Time Ended
+               // When local daylight time of "Asia/Shanghai" was about to reach
+               // Sunday, 15 September 1991, 02:00:00 clocks were turned backward 1 hour to
+               // Sunday, 15 September 1991, 01:00:00 local standard time instead.
+               // The UTC time was 14 September 1991, 17:00:00
+               4: {Date(1991, September, 14, 16, 50, 0, 0, loc), Date(1991, September, 14, 7, 50, 0, 0, UTC)},
+               5: {Date(1991, September, 14, 17, 0, 0, 0, loc), Date(1991, September, 14, 8, 0, 0, 0, UTC)},
+               6: {Date(1991, September, 15, 0, 50, 0, 0, loc), Date(1991, September, 14, 15, 50, 0, 0, UTC)},
+               7: {Date(1991, September, 15, 2, 00, 0, 0, loc), Date(1991, September, 14, 18, 00, 0, 0, UTC)},
+       }
+
+       for i, tt := range tests {
+               if !tt.give.Equal(tt.want) {
+                       t.Errorf("#%d:: %#v is not equal to %#v", i, tt.give.Format(RFC3339), tt.want.Format(RFC3339))
+               }
+       }
+}
index 5cd931d24279ff27eb4a1343dc9a306998f32020..fe434c94767c08d560e224fcdf0fec80f95f39e0 100644 (file)
@@ -214,3 +214,13 @@ func ExampleValidString() {
        // true
        // false
 }
+
+func ExampleAppendRune() {
+       buf1 := utf8.AppendRune(nil, 0x10000)
+       buf2 := utf8.AppendRune([]byte("init"), 0x10000)
+       fmt.Println(string(buf1))
+       fmt.Println(string(buf2))
+       // Output:
+       // ๐€€
+       // init๐€€
+}
index a60040ecfde8db8853d59b62d30375a960b91993..e9be4d2d636eec84bcb8dc9efe55047a83bf2fd3 100644 (file)
@@ -133,7 +133,7 @@ func TestAppendRune(t *testing.T) {
                        t.Errorf("AppendRune(nil, %#04x) = %s, want %s", m.r, buf, m.str)
                }
                if buf := AppendRune([]byte("init"), m.r); string(buf) != "init"+m.str {
-                       t.Errorf("AppendRune(nil, %#04x) = %s, want %s", m.r, buf, "init"+m.str)
+                       t.Errorf("AppendRune(init, %#04x) = %s, want %s", m.r, buf, "init"+m.str)
                }
        }
 }
diff --git a/test/fixedbugs/issue49378.go b/test/fixedbugs/issue49378.go
new file mode 100644 (file)
index 0000000..70f466c
--- /dev/null
@@ -0,0 +1,25 @@
+// compile
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(i int) {
+       var s1 struct {
+               s struct{ s struct{ i int } }
+       }
+       var s2, s3 struct {
+               a struct{ i int }
+               b int
+       }
+       func() {
+               i = 1 + 2*i + s3.a.i + func() int {
+                       s2.a, s2.b = s3.a, s3.b
+                       return 0
+               }() + func(*int) int {
+                       return s1.s.s.i
+               }(new(int))
+       }()
+}