polkavm_common/
operation.rs

1// This is mostly here so that we can share the implementation between the interpreter and the optimizer.
2
3#[inline]
4pub const fn divu(lhs: u32, rhs: u32) -> u32 {
5    if rhs == 0 {
6        u32::MAX
7    } else {
8        lhs / rhs
9    }
10}
11
12#[inline]
13pub const fn divu64(lhs: u64, rhs: u64) -> u64 {
14    if rhs == 0 {
15        u64::MAX
16    } else {
17        lhs / rhs
18    }
19}
20
21#[inline]
22pub const fn remu(lhs: u32, rhs: u32) -> u32 {
23    if rhs == 0 {
24        lhs
25    } else {
26        lhs % rhs
27    }
28}
29
30#[inline]
31pub const fn remu64(lhs: u64, rhs: u64) -> u64 {
32    if rhs == 0 {
33        lhs
34    } else {
35        lhs % rhs
36    }
37}
38
39#[inline]
40pub const fn div(lhs: i32, rhs: i32) -> i32 {
41    if rhs == 0 {
42        -1
43    } else if lhs == i32::MIN && rhs == -1 {
44        lhs
45    } else {
46        lhs / rhs
47    }
48}
49
50#[inline]
51pub const fn div64(lhs: i64, rhs: i64) -> i64 {
52    if rhs == 0 {
53        -1
54    } else if lhs == i64::MIN && rhs == -1 {
55        lhs
56    } else {
57        lhs / rhs
58    }
59}
60
61#[inline]
62pub const fn rem(lhs: i32, rhs: i32) -> i32 {
63    if rhs == 0 {
64        lhs
65    } else if lhs == i32::MIN && rhs == -1 {
66        0
67    } else {
68        lhs % rhs
69    }
70}
71
72#[inline]
73pub const fn rem64(lhs: i64, rhs: i64) -> i64 {
74    if rhs == 0 {
75        lhs
76    } else if lhs == i64::MIN && rhs == -1 {
77        0
78    } else {
79        lhs % rhs
80    }
81}
82
83#[inline]
84pub const fn mulh(lhs: i32, rhs: i32) -> i32 {
85    ((lhs as i64).wrapping_mul(rhs as i64) >> 32) as i32
86}
87
88#[inline]
89pub const fn mulh64(lhs: i64, rhs: i64) -> i64 {
90    ((lhs as i128).wrapping_mul(rhs as i128) >> 64) as i64
91}
92
93#[inline]
94pub const fn mulhsu(lhs: i32, rhs: u32) -> i32 {
95    ((lhs as i64).wrapping_mul(rhs as i64) >> 32) as i32
96}
97
98#[inline]
99pub const fn mulhsu64(lhs: i64, rhs: u64) -> i64 {
100    ((lhs as i128).wrapping_mul(rhs as i128) >> 64) as i64
101}
102
103#[inline]
104pub const fn mulhu(lhs: u32, rhs: u32) -> u32 {
105    ((lhs as i64).wrapping_mul(rhs as i64) >> 32) as u32
106}
107
108#[inline]
109pub const fn mulhu64(lhs: u64, rhs: u64) -> u64 {
110    ((lhs as i128).wrapping_mul(rhs as i128) >> 64) as u64
111}
112
113#[test]
114fn test_div_rem() {
115    assert_eq!(divu(10, 2), 5);
116    assert_eq!(divu(10, 0), u32::MAX);
117
118    assert_eq!(divu64(10, 2), 5);
119    assert_eq!(divu64(10, 0), u64::MAX);
120
121    assert_eq!(div(10, 2), 5);
122    assert_eq!(div(10, 0), -1);
123    assert_eq!(div(i32::MIN, -1), i32::MIN);
124
125    assert_eq!(div64(10, 2), 5);
126    assert_eq!(div64(10, 0), -1);
127    assert_eq!(div64(i64::MIN, -1), i64::MIN);
128
129    assert_eq!(remu(10, 9), 1);
130    assert_eq!(remu(10, 5), 0);
131    assert_eq!(remu(10, 0), 10);
132
133    assert_eq!(remu64(10, 9), 1);
134    assert_eq!(remu64(10, 5), 0);
135    assert_eq!(remu64(10, 0), 10);
136
137    assert_eq!(rem(10, 9), 1);
138    assert_eq!(rem(10, 5), 0);
139    assert_eq!(rem(10, 0), 10);
140    assert_eq!(rem(i32::MIN, -1), 0);
141
142    assert_eq!(rem64(10, 9), 1);
143    assert_eq!(rem64(10, 5), 0);
144    assert_eq!(rem64(10, 0), 10);
145    assert_eq!(rem64(i64::MIN, -1), 0);
146}