-
Notifications
You must be signed in to change notification settings - Fork 221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Native support for AVR instrinsics #711
Comments
Thanks for filing this. I don't think we are blocked on LLVM having support for the calling convention, instead we should be able to use naked functions to translate the cc like we do for aeabi intrinsics Lines 21 to 35 in cb06005
I'm not positive how this would interact with the clobbers, however. |
Oh, sure, that seems like a good idea 🙂 |
Separately you may be interested in getting AVR asm to stable. This isn't a blocker for this crate but it may be useful in user code rust-lang/rust#93335 |
Also, do you know if there is a version of these symbols in assembly that don't come from libgcc? Some of these are probably easy enough that we could provide our own assembly implementations, but we need to be careful with licensing. |
I'm aware only of the libgcc implementation, unfortunately. |
After rust-lang/rust#131651 merges it should be possible to fix the AVRTiny asm convention, at which point I think we will be okay to start using AVR assembly in this repo. The |
@Patryk27 do you happen to know which intrinsics we are actually missing? Testing with the below: #![no_std]
#[unsafe(no_mangle)]
pub fn call_umulhisi3(a: &u16, b: &u16, r: &mut u32) {
*r = *a as u32 * *b as u32;
}
#[unsafe(no_mangle)]
pub fn call_mulhisi3(a: &i16, b: &i16, r: &mut i32) {
*r = *a as i32 * *b as i32;
}
#[unsafe(no_mangle)]
pub fn call_udivmodqi4(a: &u8, b: &u8, r1: &mut u8, r2: &mut u8) {
(*r1, *r2) = (*a / *b, *a % *b);
}
#[unsafe(no_mangle)]
pub fn call_divmodqi4(a: &i8, b: &i8, r1: &mut i8, r2: &mut i8) {
(*r1, *r2) = (*a / *b, *a % *b);
}
#[unsafe(no_mangle)]
pub fn call_udivmodhi4(a: &u16, b: &u16, r1: &mut u16, r2: &mut u16) {
(*r1, *r2) = (*a / *b, *a % *b);
}
#[unsafe(no_mangle)]
pub fn call_divmodhi4(a: &i16, b: &i16, r1: &mut i16, r2: &mut i16) {
(*r1, *r2) = (*a / *b, *a % *b);
} On the atmega328p target-cpu (unsure whether this makes a difference), the only intrinsics from the list at https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention are the 8- and 16-bit integer division |
Status: was a little bit busy previous week, I'll take a look at those intrinsics and your example in a couple of days 🙂 |
You're right - it seems that the only Funny Intrinsics™ used at the moment are I have tried to summon #[inline(never)]
pub fn fun(a: &u16, b: &u16, x: &mut u16, y: &mut u16) {
(*x, *y) = a.widening_mul(*b);
} ... but even this causes LLVM to go with 16b->32b extension followed by 32b x 32b multiplication (aka All of those observations match the intrinsics actually hardcoded into the codegen: ... which confirms that we'd only have to provide Curiously enough, some time ago I thought that ABI conflicts were the reason why f32 is broken on AVR: ... but since they don't have special ABI, it must be a codegen bug, actually (this particular investigation will follow on Rahix/avr-hal#641). |
Alright, there is another kind of ABI mismatch happening, though! Context:
tl;dr intrinsics like those: compiler-builtins/src/float/cmp.rs Line 114 in 7bec089
... should (most likely?) return Edit: actually, it's not even
Should be easy to implement with a regular cfg-guarded type alias. |
It seems there's an ABI difference in regards to 32-bit division and remainder as well. Instead of compiler-builtins' ... and that's what also came out when I was running avr-tester's random-math test-suite on compiler-builtins without any Now that I have a deeper understanding of how the pieces come together, I see a light out of the tunnel - I'm preparing a pull request that gets rid of all/most |
Ok, it seems that implementing #[cfg(target_arch = "avr")]
intrinsics! {
#[maybe_use_optimized_c_shim]
pub extern "C" fn __udivmodsi4(n: u32, d: u32) -> u64 {
let (div, rem) = u32_div_rem(n, d);
((rem as u64) << 32) | (div as u64)
}
} ... yields a working intrinsic! Unfortunately we can't go with the simpler |
At the moment compiler-builtins isn't useful for AVR, because that platform uses a custom calling convention for intrinsics - supporting AVR here would require:
There are no ongoing plans to do so yet, but over rust-lang/rust#131651 it was pointed out it would be nice to have some kind of message of this issue left, so here we go 🙂
The text was updated successfully, but these errors were encountered: