// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module bits

// mul_64 returns the 128-bit product of x and y: (hi, lo) = x * y
// with the product bits' upper half returned in hi and the lower
// half returned in lo.
//
// This function's execution time does not depend on the inputs.
@[inline]
pub fn mul_64(x u64, y u64) (u64, u64) {
	mut hi := u64(0)
	mut lo := u64(0)
	$if arm64 && !tinyc {
		asm arm64 {
			mul lo, x, y
			umulh hi, x, y
			; =&r (hi)
			  =&r (lo)
			; r (x)
			  r (y)
			; cc
		}
		return hi, lo
	}
	// cross compile
	return mul_64_default(x, y)
}

// mul_add_64 returns the 128-bit result of x * y + z: (hi, lo) = x * y + z
// with the result bits' upper half returned in hi and the lower
// half returned in lo.
@[inline]
pub fn mul_add_64(x u64, y u64, z u64) (u64, u64) {
	mut hi := u64(0)
	mut lo := u64(0)
	$if arm64 && !tinyc {
		asm arm64 {
			mul lo, x, y
			umulh hi, x, y
			adds lo, lo, z
			adc hi, hi, xzr
			; =&r (hi)
			  =&r (lo)
			; r (x)
			  r (y)
			  r (z)
			; cc
		}
		return hi, lo
	}
	// cross compile
	return mul_add_64_default(x, y, z)
}
