Skip to content

Commit

Permalink
fix: Add #[avr_skip] for bit shifts
Browse files Browse the repository at this point in the history
This commit follows the same logic as:

- rust-lang#462
- rust-lang#466

I've tested the changes by preparing a simple program:

```rust
fn calc() -> ... {
    let x = hint::black_box(4u...); // 4u8, 4u16, 4u32, 4u64, 4u128 + signed
    let y = hint::black_box(1u32);

    // x >> y
    // x << y
}

fn main() -> ! {
    let dp = arduino_hal::Peripherals::take().unwrap();
    let pins = arduino_hal::pins!(dp);
    let mut serial = arduino_hal::default_serial!(dp, pins, 57600);

    for b in calc().to_le_bytes() {
        _ = ufmt::uwrite!(&mut serial, "{} ", b);
    }

    _ = ufmt::uwriteln!(&mut serial, "");

    loop {
        //
    }
}
```

... switching types & operators in `calc()`, and observing the results;
what I ended up with was:

```
 u32 << u32 - ok
 u64 << u32 - ok
u128 << u32 - error (undefined reference to `__ashlti3')
 i32 >> u32 - ok
 i64 >> u32 - ok
i128 >> u32 - error (undefined reference to `__ashrti3')
 u32 >> u32 - ok
 u64 >> u32 - ok
u128 >> u32 - error (undefined reference to `__lshrti3')

(where "ok" = compiles and returns correct results)
```

As with multiplication and division, so do in here 128-bit operations
not work, because avr-gcc's standard library doesn't provide them (at
the same time, requiring that specific calling convention, making it
pretty difficult for compiler-builtins to jump in).

I think 128-bit operations non-working on an 8-bit controller is an
acceptable trade-off - :innocent: - and so the entire fix in here is
just about skipping those functions.
  • Loading branch information
Patryk27 committed Dec 25, 2022
1 parent 23a74de commit c9f5280
Showing 1 changed file with 9 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/int/shift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,47 +69,56 @@ impl Lshr for u64 {}
impl Lshr for u128 {}

intrinsics! {
#[avr_skip]
#[maybe_use_optimized_c_shim]
pub extern "C" fn __ashlsi3(a: u32, b: u32) -> u32 {
a.ashl(b)
}

#[avr_skip]
#[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_llsl]
pub extern "C" fn __ashldi3(a: u64, b: u32) -> u64 {
a.ashl(b)
}

#[avr_skip]
pub extern "C" fn __ashlti3(a: u128, b: u32) -> u128 {
a.ashl(b)
}

#[avr_skip]
#[maybe_use_optimized_c_shim]
pub extern "C" fn __ashrsi3(a: i32, b: u32) -> i32 {
a.ashr(b)
}

#[avr_skip]
#[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_lasr]
pub extern "C" fn __ashrdi3(a: i64, b: u32) -> i64 {
a.ashr(b)
}

#[avr_skip]
pub extern "C" fn __ashrti3(a: i128, b: u32) -> i128 {
a.ashr(b)
}

#[avr_skip]
#[maybe_use_optimized_c_shim]
pub extern "C" fn __lshrsi3(a: u32, b: u32) -> u32 {
a.lshr(b)
}

#[avr_skip]
#[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_llsr]
pub extern "C" fn __lshrdi3(a: u64, b: u32) -> u64 {
a.lshr(b)
}

#[avr_skip]
pub extern "C" fn __lshrti3(a: u128, b: u32) -> u128 {
a.lshr(b)
}
Expand Down

0 comments on commit c9f5280

Please sign in to comment.