1 个不稳定版本
0.2.0 | 2022年7月30日 |
---|
#641 在 嵌入式开发
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
。传递一个仅用作u8
的i32
看起来可能很愚蠢,但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.0
或 MIT
。