On 14/04/2025 21:46, Russell King (Oracle) wrote:
On Mon, Apr 14, 2025 at 09:21:42PM +0200, Christian Schrefl wrote:
Hi Miguel,
On 14.04.25 8:14 PM, Miguel Ojeda wrote:
Hi Jocelyn, Christian,
I started build-testing arm 32-bit within my other usual routine
tests, and I hit:
ld.lld: error: undefined symbol: __aeabi_uldivmod
>>> referenced by drm_panic_qr.rs:417 (drivers/gpu/drm/drm_panic_qr.rs:417)
>>> drivers/gpu/drm/drm_panic_qr.o:(<drm_panic_qr::SegmentIterator
as core::iter::traits::iterator::Iterator>::next) in archive vmlinux.a
which comes from both these `u64` by `u64`:
let out = (self.carry / pow) as u16;
self.carry = self.carry % pow;
Christian: I guess we can offer a set of `div64` functions using the C
ones, at least for the time being, and eventually wire the actual
operator with some support from upstream Rust. Or do you have
something else in mind? (i.e. I think you have been discussing
intrinsics lately)
I think using the C implementations is fine. Not sure how much the
FFI is going to matter for performance, but it should be rare enough
that is shouldn't matter (and hopefully we will get cross lang LTO
or something similar at some point).
We could also just implement the intrinsic(s) ourselves, but then
the u64 divisions would be implicit which is probably undesired.
We could also rename the intrinsics so they are only usable from
specific crates.
I think we need the opinion of the some arm people here.
CC Russell King and Linus Walleij.
The kernel has had the general position that u64 by u64 division is
silly and isn't supported. Several 32-bit architectures including
32-bit ARM don't support it.
For this case, the u64 divisor "pow" is a power of 10, so can have only
a limited number of values. (17, and 9 of them can be used as u32).
Normally when the divisor is known at build time the compiler can
replace the division by a multiplication and some bit shift.
so for 32bits machine, the match can be rewritten with constants, a bit
like this:
1..9 => {
let out = (self.carry / u32::pow(10, self.carry_len));
10 => {
let out = (self.carry / 10_000_000_000);
...
}
11 => {
let out = (self.carry / 100_000_000_000);
...
}
Would that fix this problem?
Best Regards,
--
Jocelyn