1
- #[ cfg( not( all( feature = "c" , target_arch = "x86" ) ) ) ]
2
1
use int:: LargeInt ;
3
2
use int:: Int ;
4
3
5
4
macro_rules! mul {
6
- ( $intrinsic: ident: $ty: ty) => {
5
+ ( $intrinsic: ident: $ty: ty, $tyh : ty ) => {
7
6
/// Returns `a * b`
8
7
#[ cfg_attr( not( test) , no_mangle) ]
9
8
pub extern "C" fn $intrinsic( a: $ty, b: $ty) -> $ty {
@@ -14,31 +13,36 @@ macro_rules! mul {
14
13
low &= lower_mask;
15
14
t += ( a. low( ) >> half_bits) . wrapping_mul( b. low( ) & lower_mask) ;
16
15
low += ( t & lower_mask) << half_bits;
17
- let mut high = t >> half_bits;
16
+ let mut high = ( t >> half_bits) as $tyh ;
18
17
t = low >> half_bits;
19
18
low &= lower_mask;
20
19
t += ( b. low( ) >> half_bits) . wrapping_mul( a. low( ) & lower_mask) ;
21
20
low += ( t & lower_mask) << half_bits;
22
- high += t >> half_bits;
23
- high += ( a. low( ) >> half_bits) . wrapping_mul( b. low( ) >> half_bits) ;
24
- high = high. wrapping_add( a. high( ) . wrapping_mul( b. low( ) ) . wrapping_add( a. low( ) . wrapping_mul( b. high( ) ) ) ) ;
21
+ high += ( t >> half_bits) as $tyh;
22
+ high += ( a. low( ) >> half_bits) . wrapping_mul( b. low( ) >> half_bits) as $tyh;
23
+ high = high. wrapping_add( a. high( ) . wrapping_mul( b. low( ) as $tyh) )
24
+ . wrapping_add( ( a. low( ) as $tyh) . wrapping_mul( b. high( ) ) ) ;
25
25
<$ty>:: from_parts( low, high)
26
26
}
27
27
}
28
28
}
29
29
30
30
macro_rules! mulo {
31
31
( $intrinsic: ident: $ty: ty) => {
32
+ // Default is "C" ABI
33
+ mulo!( $intrinsic: $ty, "C" , |i| { i } , $ty) ;
34
+ } ;
35
+ ( $intrinsic: ident: $ty: ty, $abi: tt, $conv: expr, $rty: ty) => {
32
36
/// Returns `a * b` and sets `*overflow = 1` if `a * b` overflows
33
37
#[ cfg_attr( not( test) , no_mangle) ]
34
- pub extern "C" fn $intrinsic( a: $ty, b: $ty, overflow: & mut i32 ) -> $ty {
38
+ pub extern $abi fn $intrinsic( a: $ty, b: $ty, overflow: & mut i32 ) -> $rty {
35
39
* overflow = 0 ;
36
40
let result = a. wrapping_mul( b) ;
37
41
if a == <$ty>:: min_value( ) {
38
42
if b != 0 && b != 1 {
39
43
* overflow = 1 ;
40
44
}
41
- return result;
45
+ return ( $conv ) ( result) ;
42
46
}
43
47
if b == <$ty>:: min_value( ) {
44
48
if a != 0 && a != 1 {
@@ -52,7 +56,7 @@ macro_rules! mulo {
52
56
let sb = b >> ( <$ty>:: bits( ) - 1 ) ;
53
57
let abs_b = ( b ^ sb) - sb;
54
58
if abs_a < 2 || abs_b < 2 {
55
- return result;
59
+ return ( $conv ) ( result) ;
56
60
}
57
61
if sa == sb {
58
62
if abs_a > <$ty>:: max_value( ) / abs_b {
@@ -63,17 +67,31 @@ macro_rules! mulo {
63
67
* overflow = 1 ;
64
68
}
65
69
}
66
- result
70
+ ( $conv ) ( result)
67
71
}
68
72
}
69
73
}
70
74
71
75
#[ cfg( not( all( feature = "c" , target_arch = "x86" ) ) ) ]
72
- mul ! ( __muldi3: u64 ) ;
76
+ mul ! ( __muldi3: u64 , u32 ) ;
77
+
78
+ #[ cfg( stage0) ]
79
+ mul ! ( __multi3: u64 , u32 ) ;
80
+ #[ cfg( not( stage0) ) ]
81
+ mul ! ( __multi3: i128 , i64 ) ;
73
82
74
83
mulo ! ( __mulosi4: i32 ) ;
75
84
mulo ! ( __mulodi4: i64 ) ;
76
85
86
+ #[ cfg( stage0) ]
87
+ mulo ! ( __muloti4: i64 ) ;
88
+ #[ cfg( not( stage0) ) ]
89
+ #[ cfg( all( windows, target_pointer_width="64" ) ) ]
90
+ mulo ! ( __muloti4: i128 , "unadjusted" , super :: conv, super :: U64x2 ) ;
91
+ #[ cfg( not( stage0) ) ]
92
+ #[ cfg( not( all( windows, target_pointer_width="64" ) ) ) ]
93
+ mulo ! ( __muloti4: i128 ) ;
94
+
77
95
#[ cfg( test) ]
78
96
mod tests {
79
97
use qc:: { I32 , I64 , U64 } ;
0 commit comments