Source file src/math/big/internal/asmgen/add.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package asmgen
     6  
     7  // addOrSubVV generates addVV or subVV,
     8  // which do z, c = x ± y.
     9  // The caller guarantees that len(z) == len(x) == len(y).
    10  func addOrSubVV(a *Asm, name string) {
    11  	f := a.Func("func " + name + "(z, x, y []Word) (c Word)")
    12  
    13  	add := a.Add
    14  	which := AddCarry
    15  	if name == "subVV" {
    16  		add = a.Sub
    17  		which = SubCarry
    18  	}
    19  
    20  	n := f.Arg("z_len")
    21  	p := f.Pipe()
    22  	p.SetHint("y", HintMemOK) // allow y to be used from memory on x86
    23  	p.Start(n, 1, 4)
    24  	var c Reg
    25  	if !a.Arch.CarrySafeLoop {
    26  		// Carry smashed by loop tests; allocate and save in register
    27  		// around unrolled blocks.
    28  		c = a.Reg()
    29  		a.Mov(a.Imm(0), c)
    30  		a.EOL("clear saved carry")
    31  		p.AtUnrollStart(func() { a.RestoreCarry(c); a.Free(c) })
    32  		p.AtUnrollEnd(func() { a.Unfree(c); a.SaveCarry(c) })
    33  	} else {
    34  		// Carry preserved by loop; clear now, ahead of loop
    35  		// (but after Start, which may have modified it).
    36  		a.ClearCarry(which)
    37  	}
    38  	p.Loop(func(in, out [][]Reg) {
    39  		for i, x := range in[0] {
    40  			y := in[1][i]
    41  			add(y, x, x, SetCarry|UseCarry)
    42  		}
    43  		p.StoreN(in[:1])
    44  	})
    45  	p.Done()
    46  
    47  	// Copy carry to output.
    48  	if c.Valid() {
    49  		a.ConvertCarry(which, c)
    50  	} else {
    51  		c = a.RegHint(HintCarry)
    52  		a.SaveConvertCarry(which, c)
    53  	}
    54  	f.StoreArg(c, "c")
    55  	a.Free(c)
    56  	a.Ret()
    57  }
    58  

View as plain text