| 1 | // Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved. |
| 2 | // Use of this source code is governed by an MIT license |
| 3 | // that can be found in the LICENSE file. |
| 4 | module bits |
| 5 | |
| 6 | // mul_64 returns the 128-bit product of x and y: (hi, lo) = x * y |
| 7 | // with the product bits' upper half returned in hi and the lower |
| 8 | // half returned in lo. |
| 9 | // |
| 10 | // This function's execution time does not depend on the inputs. |
| 11 | @[inline] |
| 12 | pub fn mul_64(x u64, y u64) (u64, u64) { |
| 13 | mut hi := u64(0) |
| 14 | mut lo := u64(0) |
| 15 | $if arm64 && !tinyc { |
| 16 | asm arm64 { |
| 17 | mul lo, x, y |
| 18 | umulh hi, x, y |
| 19 | ; =&r (hi) |
| 20 | =&r (lo) |
| 21 | ; r (x) |
| 22 | r (y) |
| 23 | ; cc |
| 24 | } |
| 25 | return hi, lo |
| 26 | } |
| 27 | // cross compile |
| 28 | return mul_64_default(x, y) |
| 29 | } |
| 30 | |
| 31 | // mul_add_64 returns the 128-bit result of x * y + z: (hi, lo) = x * y + z |
| 32 | // with the result bits' upper half returned in hi and the lower |
| 33 | // half returned in lo. |
| 34 | @[inline] |
| 35 | pub fn mul_add_64(x u64, y u64, z u64) (u64, u64) { |
| 36 | mut hi := u64(0) |
| 37 | mut lo := u64(0) |
| 38 | $if arm64 && !tinyc { |
| 39 | asm arm64 { |
| 40 | mul lo, x, y |
| 41 | umulh hi, x, y |
| 42 | adds lo, lo, z |
| 43 | adc hi, hi, xzr |
| 44 | ; =&r (hi) |
| 45 | =&r (lo) |
| 46 | ; r (x) |
| 47 | r (y) |
| 48 | r (z) |
| 49 | ; cc |
| 50 | } |
| 51 | return hi, lo |
| 52 | } |
| 53 | // cross compile |
| 54 | return mul_add_64_default(x, y, z) |
| 55 | } |
| 56 | |