Skip to content
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

Implement LLVM intrinsics for Div and Mod so that / and % work "normally" on the GBA #8

Closed
Lokathor opened this issue Nov 15, 2018 · 7 comments

Comments

@Lokathor
Copy link
Member

Lokathor commented Nov 15, 2018

So, if we implement the correct special function, then we can make code like

let a = x / y;

Will suddenly magically work on the GBA.

#[no_mangle] extern "aapcs" fn __aeabi_uidiv(num: u32: denom: u32) -> u32
#[no_mangle] extern "aapcs" fn __aeabi_idiv(num: i32: denom: i32) -> u32

Question

Do we want division to magically work like that?

Personally, I think that division is so damn costly on the GBA that I want it to be called as a special function or even as a macro (which makes it look a little weird) just so that people remember that they're doing a weird and costly operation.

@Lokathor
Copy link
Member Author

Upon further chats on the discord, I'm convinced that it'll be fine to make normal division work via special intrinsic magic, so we'll mark this as Enhancement

@Lokathor
Copy link
Member Author

So, due to reasons that no one can seem to figure out, LLVM just doesn't wanna play nice with the intrinsics here. It inserts calls to count zeroes and even if we try to implement that then it says it can't find it and no one was sure what was up.

So we'll put in the GBA BIOS call for i32/i32 divMod for now:

/// BIOS Call: Div (GBA SWI 0x06).
///
/// Gives both the DIV and MOD output of `numerator / denominator`.
///
/// # Panics
///
/// If `denominator` is 0.
#[inline]
pub fn div_modulus(numerator: i32, denominator: i32) -> (i32, i32) {
  assert!(denominator != 0);
  let div_out: i32;
  let mod_out: i32;
  unsafe {
    asm!(/* assembly template */ "swi 0x06"
        :/* output operands */ "={r0}"(div_out), "={r1}"(mod_out)
        :/* input operands */ "{r0}"(numerator), "{r1}"(denominator)
        :/* clobbers */ "r3"
        :/* options */
    );
  }
  (div_out, mod_out)
}

And we'll have to get back to mapping that (and anything else) into LLVM intrinsic stuff later.

@Lokathor Lokathor changed the title Div and Mod Implement LLVM intrinsics for Div and Mod so that / and % work "normally" on the GBA Nov 15, 2018
@Lokathor
Copy link
Member Author

Commented on the rustc issue for this

rust-lang/compiler-builtins#260

Hopefully we can get this done easily enough

@Lokathor
Copy link
Member Author

Put in the start of a PR: rust-lang/compiler-builtins#267

@Lokathor
Copy link
Member Author

Also we now have software versions for u32/u32 and i32/i32, so we can avoid the BIOS calls entirely, which should save us a big pile of overhead.

@Lokathor Lokathor self-assigned this Feb 5, 2019
@Lokathor Lokathor added this to the v0.4 milestone Feb 5, 2019
@Lokathor
Copy link
Member Author

Lokathor commented Feb 9, 2019

Oh yeah, the PR was merged and also the update made its way all the way to rustc

now that we can count leading zeroes, we still need division

@Lokathor Lokathor removed their assignment Oct 11, 2019
@Lokathor
Copy link
Member Author

Lokathor commented Apr 9, 2021

I think we did this forever ago.

@Lokathor Lokathor closed this as completed Apr 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant