#arm7tdmi #armv4t #thumbv4t

无std arm7tdmi_aeabi

将aeabi函数放入代码中的宏

1 个不稳定版本

0.2.0 2022年7月30日

#641嵌入式开发

CC0-1.0 OR Apache-2.0 OR MIT

35KB
537

arm7tdmi_aeabi

根据ARM的AEABI实现运行时支持函数。所有函数都针对ARM7TDMI CPU进行了优化。它们也应该与任何较新的ARM CPU一起工作,但由于指令流水线差异,它们可能无法达到最佳性能。

这些函数旨在支持在GBA上进行的Rust开发,但它们是用汇编语言编写的,因此应该可以与任何语言以及任何ARMv4T或更晚期的设备一起使用。

当前支持

目前代码使用略不同的名称,以便可以编译到测试中而不会与每个符号的系统版本冲突。

目前提供的以下函数

extern "C" {
  pub fn libc_memcpy(d: *mut u8, s: *const u8, bytes: usize) -> *mut u8;
  pub fn aeabi_memcpy(d: *mut u8, s: *const u8, bytes: usize);
  pub fn aeabi_memcpy4(d: *mut u8, s: *const u8, bytes: usize);
  pub fn aeabi_memcpy8(d: *mut u8, s: *const u8, bytes: usize);
  pub fn gba_memcpy_sram(d: *mut u8, s: *const u8, bytes: usize);

  pub fn libc_memmove(d: *mut u8, s: *const u8, bytes: usize) -> *mut u8;
  pub fn aeabi_memmove(d: *mut u8, s: *const u8, bytes: usize);
  pub fn aeabi_memmove4(d: *mut u8, s: *const u8, bytes: usize);
  pub fn aeabi_memmove8(d: *mut u8, s: *const u8, bytes: usize);

  pub fn libc_memset(d: *mut u8, val: i32, bytes: usize) -> *mut u8;
  pub fn aeabi_memset(d: *mut u8, bytes: usize, val: i32);
  pub fn aeabi_memset4(d: *mut u8, bytes: usize, val: i32);
  pub fn aeabi_memset8(d: *mut u8, bytes: usize, val: i32);

  pub fn aeabi_memclr(d: *mut u8, bytes: usize);
  pub fn aeabi_memclr4(d: *mut u8, bytes: usize);
  pub fn aeabi_memclr8(d: *mut u8, bytes: usize);

  pub fn aeabi_uread4(address: *const u32) -> u32;
  pub fn aeabi_uread8(address: *const u64) -> u64;
  pub fn aeabi_uwrite4(value: u32, address: *mut u32) -> u32;
  pub fn aeabi_uwrite8(value: u64, address: *mut u64) -> u64;

  pub fn aeabi_idiv(n: i32, d: i32) -> i32;
  pub fn aeabi_uidiv(n: u32, d: u32) -> u32;
  pub fn aeabi_idivmod(n: i32, d: i32) -> u64;
  pub fn aeabi_uidivmod(n: u32, d: u32) -> u64;
}
  • "内存复制"函数假定是独占区域。 gba_memcpy_sram 函数不属于AEABI,但它允许执行一次只访问一个字节的复制。这使得它与GBA的SRAM一起使用是安全的。
  • "内存移动"函数允许重叠区域。
  • "内存设置"函数会将所有字节的值设置为 val as u8。传递一个仅用作 u8i32 看起来可能很愚蠢,但 memset 早于 C中的函数原型,因此就是这样工作的。注意,libc和aeabi版本已交换了参数顺序。在Rust中这不是什么大问题,编译器会在你混淆时捕获它。
  • "内存清除"函数与"内存设置"类似,但设置的值隐式为0,这允许对对齐版本进行轻微优化。
  • "未对齐读取"函数返回读取的值。
  • "未对齐写入"函数返回写入的值。

以4或8结尾的函数要求输入指针必须对齐到那么多。 bytes 值不需要是对齐要求的偶数倍。

所有 libc_ 函数都将它们传递的原始目标指针作为它们的返回值。所有 aeabi_ 函数根本不返回任何内容(这更有效,因此当可能时请使用它们)。

使用

遗憾的是,crate 无法指定它们希望依赖项代码使用的链接部分。由于我的主要用途是将此汇编放在 GBA 的特殊部分,以便代码在运行时位于 RAM 中,我无法简单地将其发布到 crates.io,然后将其用作常规依赖项,并使其位于我想要的位置。或者,我可以这样做,但这样就没有其他人可以在那个特定的 GBA 上下文之外使用它,这也不太好。

将来,这个 crate 将作为一个接受部分名称并发出正确内容的 global_asm! 的 proc-macro 发布。在此之前,如果您想使用这些函数,只需将这些文件作为供应商集成到您的项目中即可。

测试

使用 cross 通常是测试此 crate 的最简单方法。

cross test --target arm-unknown-linux-gnueabi

或者,如果您正在 ARM 设备(例如:运行 32 位操作系统的 rpi)上运行,那么您可能可以本地测试。

许可证

此处所有代码均在 CCO 下发布。

或者(如果您真的想使用标准 Rust 项目许可证),也可以使用 Apache-2.0MIT

无运行时依赖项