Source file src/crypto/internal/fips140/bigmod/nat_wasm.go

     1  // Copyright 2024 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build !purego
     6  
     7  package bigmod
     8  
     9  import "unsafe"
    10  
    11  // The generic implementation relies on 64x64->128 bit multiplication and
    12  // 64-bit add-with-carry, which are compiler intrinsics on many architectures.
    13  // Wasm doesn't support those. Here we implement it with 32x32->64 bit
    14  // operations, which is more efficient on Wasm.
    15  
    16  func idx(x *uint, i uintptr) *uint {
    17  	return (*uint)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + i*8))
    18  }
    19  
    20  func addMulVVWWasm(z, x *uint, y uint, n uintptr) (carry uint) {
    21  	const mask32 = 1<<32 - 1
    22  	y0 := y & mask32
    23  	y1 := y >> 32
    24  	for i := range n {
    25  		xi := *idx(x, i)
    26  		x0 := xi & mask32
    27  		x1 := xi >> 32
    28  		zi := *idx(z, i)
    29  		z0 := zi & mask32
    30  		z1 := zi >> 32
    31  		c0 := carry & mask32
    32  		c1 := carry >> 32
    33  
    34  		w00 := x0*y0 + z0 + c0
    35  		l00 := w00 & mask32
    36  		h00 := w00 >> 32
    37  
    38  		w01 := x0*y1 + z1 + h00
    39  		l01 := w01 & mask32
    40  		h01 := w01 >> 32
    41  
    42  		w10 := x1*y0 + c1 + l01
    43  		h10 := w10 >> 32
    44  
    45  		carry = x1*y1 + h10 + h01
    46  		*idx(z, i) = w10<<32 + l00
    47  	}
    48  	return carry
    49  }
    50  
    51  func addMulVVW1024(z, x *uint, y uint) (c uint) {
    52  	return addMulVVWWasm(z, x, y, 1024/_W)
    53  }
    54  
    55  func addMulVVW1536(z, x *uint, y uint) (c uint) {
    56  	return addMulVVWWasm(z, x, y, 1536/_W)
    57  }
    58  
    59  func addMulVVW2048(z, x *uint, y uint) (c uint) {
    60  	return addMulVVWWasm(z, x, y, 2048/_W)
    61  }
    62  

View as plain text