1const P_2EXP63: u64 = 1 << 63;
2const INT32_MAX: u32 = i32::MAX as u32;
3
4pub fn u64_from_i32_imm(imm: i32) -> u64 {
5 let x = imm as u32;
6 if x > INT32_MAX {
7 x as u64 | 0xffffffff00000000
8 } else {
9 x as u64
10 }
11}
12
13pub fn u64_from_u32_imm(imm: u32) -> u64 {
14 if imm > INT32_MAX {
15 imm as u64 | 0xffffffff00000000
16 } else {
17 imm as u64
18 }
19}
20
21pub fn mulh(a: u64, b: u64) -> u64 {
22 ((a as u128).wrapping_mul(b as u128) >> 64) as u64
23}
24
25pub fn smulh(a: u64, b: u64) -> u64 {
26 let v_src = (a as i64) as i128; let v_dst = (b as i64) as i128;
28 (v_src.wrapping_mul(v_dst) >> 64) as u64
29}
30
31pub fn randomx_reciprocal(divisor: u64) -> u64 {
47 assert_ne!(divisor, 0);
48
49 let mut quotient = P_2EXP63 / divisor;
50 let mut remainder = P_2EXP63 % divisor;
51 let mut bsr = 0;
52
53 let mut bit = divisor;
54
55 loop {
56 if bit == 0 {
57 break;
58 }
59 bsr += 1;
60 bit >>= 1;
61 }
62
63 for _ in 0..bsr {
64 if remainder >= divisor.wrapping_sub(remainder) {
65 quotient = quotient.wrapping_mul(2).wrapping_add(1);
66 remainder = remainder.wrapping_mul(2).wrapping_sub(divisor);
67 } else {
68 quotient = quotient.wrapping_mul(2);
69 remainder = remainder.wrapping_mul(2);
70 }
71 }
72 quotient
73}