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 remu(lhs: u32, rhs: u32) -> u32 {
14    if rhs == 0 {
15        lhs
16    } else {
17        lhs % rhs
18    }
19}
20
21#[inline]
22pub const fn div(lhs: i32, rhs: i32) -> i32 {
23    if rhs == 0 {
24        -1
25    } else if lhs == i32::MIN && rhs == -1 {
26        lhs
27    } else {
28        lhs / rhs
29    }
30}
31
32#[inline]
33pub const fn rem(lhs: i32, rhs: i32) -> i32 {
34    if rhs == 0 {
35        lhs
36    } else if lhs == i32::MIN && rhs == -1 {
37        0
38    } else {
39        lhs % rhs
40    }
41}
42
43#[inline]
44pub const fn mulh(lhs: i32, rhs: i32) -> i32 {
45    ((lhs as i64).wrapping_mul(rhs as i64) >> 32) as i32
46}
47
48#[inline]
49pub const fn mulhsu(lhs: i32, rhs: u32) -> i32 {
50    ((lhs as i64).wrapping_mul(rhs as i64) >> 32) as i32
51}
52
53#[inline]
54pub const fn mulhu(lhs: u32, rhs: u32) -> u32 {
55    ((lhs as i64).wrapping_mul(rhs as i64) >> 32) as u32
56}
57
58#[test]
59fn test_div_rem() {
60    assert_eq!(divu(10, 2), 5);
61    assert_eq!(divu(10, 0), u32::MAX);
62
63    assert_eq!(div(10, 2), 5);
64    assert_eq!(div(10, 0), -1);
65    assert_eq!(div(i32::MIN, -1), i32::MIN);
66
67    assert_eq!(remu(10, 9), 1);
68    assert_eq!(remu(10, 5), 0);
69    assert_eq!(remu(10, 0), 10);
70
71    assert_eq!(rem(10, 9), 1);
72    assert_eq!(rem(10, 5), 0);
73    assert_eq!(rem(10, 0), 10);
74    assert_eq!(rem(i32::MIN, -1), 0);
75}