Using asm and global_asm from core::arch module. (#157)

* Using asm and global_asm from core::arch module.

* Commenting out some broken code with higher registers.
This commit is contained in:
Matt L 2022-01-01 23:54:46 -05:00 committed by GitHub
parent 42e2836507
commit 093146fd8a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 65 deletions

View file

@ -11,6 +11,8 @@
#[allow(unused)]
use crate::prelude::*;
use core::arch::asm;
/// (`swi 0x00`) Performs a "soft reset" of the device.
///
/// Loads `r14` based on the `u8` value at `0x0300_7FFA`:

View file

@ -1,5 +1,5 @@
#![no_std]
#![feature(asm, global_asm, isa_attribute)]
#![feature(isa_attribute)]
//! This crate helps you write GBA ROMs.
//!
@ -31,11 +31,11 @@ pub mod prelude {
#[cfg(target_arch = "arm")]
pub use crate::mmio_addresses::*;
#[cfg(target_arch = "arm")]
pub use crate::random::*;
#[cfg(target_arch = "arm")]
pub use crate::save::*;
#[cfg(target_arch = "arm")]
pub use crate::sync::*;
#[cfg(target_arch = "arm")]
pub use crate::random::*;
}
pub mod mmio_types;

View file

@ -1,5 +1,6 @@
use crate::prelude::Color;
use core::arch::asm;
use voladdress::*;
pub const WIDTH: usize = 240;

View file

@ -2,8 +2,9 @@
//! WRAM. Both flash media and battery-backed SRAM require reads to be
//! performed via code in WRAM and cannot be accessed by DMA.
#![cfg_attr(not(target_arch = "arm"), allow(unused_variables, non_snake_case))]
use core::arch::global_asm;
#[cfg_attr(not(target_arch = "arm"), allow(unused_variables, non_snake_case))]
#[cfg(target_arch = "arm")]
global_asm!(include_str!("asm_routines.s"));

View file

@ -2,6 +2,8 @@
use crate::prelude::*;
use core::arch::asm;
mod locks;
mod statics;

View file

@ -2,6 +2,7 @@
use crate::sync::with_irqs_disabled;
use core::{
arch::asm,
cell::UnsafeCell,
mem::{align_of, size_of, MaybeUninit},
ptr,
@ -20,8 +21,10 @@ unsafe fn transfer<T: Copy>(dst: *mut T, src: *const T) {
// We can do an 4-byte aligned transfer up to 16 bytes.
transfer_align4_thumb(dst, src);
} else if size <= 36 && align % 4 == 0 {
// We can do the same up to 36 bytes, but we need to switch to ARM.
transfer_align4_arm(dst, src);
// // We can do the same up to 36 bytes, but we need to switch to ARM.
// transfer_align4_arm(dst, src);
// TODO(rust-console/gba#158) Cannot optimize larger transfers for now.
with_irqs_disabled(|| ptr::write_volatile(dst, ptr::read_volatile(src)));
} else if size <= 2 && align % 2 == 0 {
// We can do a 2-byte aligned transfer up to 2 bytes.
asm!(
@ -82,65 +85,66 @@ unsafe fn transfer_align4_thumb<T: Copy>(mut dst: *mut T, mut src: *const T) {
}
}
#[cfg(target_arch = "arm")]
#[instruction_set(arm::a32)]
#[allow(unused_assignments)]
unsafe fn transfer_align4_arm<T: Copy>(mut dst: *mut T, mut src: *const T) {
let size = size_of::<T>();
if size <= 16 {
unimplemented!("This should be done via transfer_thumb.");
} else if size <= 20 {
// Starting at size == 20, we have to switch to ARM due to lack of
// accessible registers in THUMB mode.
asm!(
"ldmia {0}!, {{r2-r5,r8}}",
"stmia {1}!, {{r2-r5,r8}}",
inout(reg) src, inout(reg) dst,
out("r2") _, out("r3") _, out("r4") _, out("r5") _, out("r8") _,
)
} else if size <= 24 {
asm!(
"push {{r9}}",
"ldmia {0}!, {{r2-r5,r8-r9}}",
"stmia {1}!, {{r2-r5,r8-r9}}",
"pop {{r9}}",
inout(reg) src, inout(reg) dst,
out("r2") _, out("r3") _, out("r4") _, out("r5") _, out("r8") _,
)
} else if size <= 28 {
asm!(
"push {{r9}}",
"ldmia {0}!, {{r2-r5,r8-r10}}",
"stmia {1}!, {{r2-r5,r8-r10}}",
"pop {{r9}}",
inout(reg) src, inout(reg) dst,
out("r2") _, out("r3") _, out("r4") _, out("r5") _, out("r8") _,
out("r10") _,
)
} else if size <= 32 {
asm!(
"push {{r9}}",
"ldmia {0}!, {{r2-r5,r8-r10,r12}}",
"stmia {1}!, {{r2-r5,r8-r10,r12}}",
"pop {{r9}}",
inout(reg) src, inout(reg) dst,
out("r2") _, out("r3") _, out("r4") _, out("r5") _, out("r8") _,
out("r10") _, out("r12") _,
)
} else if size <= 36 {
asm!(
"push {{r9}}",
"ldmia {0}!, {{r2-r5,r8-r10,r12,r14}}",
"stmia {1}!, {{r2-r5,r8-r10,r12,r14}}",
"pop {{r9}}",
inout(reg) src, inout(reg) dst,
out("r2") _, out("r3") _, out("r4") _, out("r5") _, out("r8") _,
out("r10") _, out("r12") _, out("r14") _,
)
} else {
unimplemented!("Copy too large for use of ldmia/stmia.");
}
}
// TODO(rust-console/gba#158) Un-comment out this fn when we can use higher registers.
// #[cfg(target_arch = "arm")]
// #[instruction_set(arm::a32)]
// #[allow(unused_assignments)]
// unsafe fn transfer_align4_arm<T: Copy>(mut dst: *mut T, mut src: *const T) {
// let size = size_of::<T>();
// if size <= 16 {
// unimplemented!("This should be done via transfer_thumb.");
// } else if size <= 20 {
// // Starting at size == 20, we have to switch to ARM due to lack of
// // accessible registers in THUMB mode.
// asm!(
// "ldmia {0}!, {{r2-r5,r8}}",
// "stmia {1}!, {{r2-r5,r8}}",
// inout(reg) src, inout(reg) dst,
// out("r2") _, out("r3") _, out("r4") _, out("r5") _, out("r8") _,
// )
// } else if size <= 24 {
// asm!(
// "push {{r9}}",
// "ldmia {0}!, {{r2-r5,r8-r9}}",
// "stmia {1}!, {{r2-r5,r8-r9}}",
// "pop {{r9}}",
// inout(reg) src, inout(reg) dst,
// out("r2") _, out("r3") _, out("r4") _, out("r5") _, out("r8") _,
// )
// } else if size <= 28 {
// asm!(
// "push {{r9}}",
// "ldmia {0}!, {{r2-r5,r8-r10}}",
// "stmia {1}!, {{r2-r5,r8-r10}}",
// "pop {{r9}}",
// inout(reg) src, inout(reg) dst,
// out("r2") _, out("r3") _, out("r4") _, out("r5") _, out("r8") _,
// out("r10") _,
// )
// } else if size <= 32 {
// asm!(
// "push {{r9}}",
// "ldmia {0}!, {{r2-r5,r8-r10,r12}}",
// "stmia {1}!, {{r2-r5,r8-r10,r12}}",
// "pop {{r9}}",
// inout(reg) src, inout(reg) dst,
// out("r2") _, out("r3") _, out("r4") _, out("r5") _, out("r8") _,
// out("r10") _, out("r12") _,
// )
// } else if size <= 36 {
// asm!(
// "push {{r9}}",
// "ldmia {0}!, {{r2-r5,r8-r10,r12,r14}}",
// "stmia {1}!, {{r2-r5,r8-r10,r12,r14}}",
// "pop {{r9}}",
// inout(reg) src, inout(reg) dst,
// out("r2") _, out("r3") _, out("r4") _, out("r5") _, out("r8") _,
// out("r10") _, out("r12") _, out("r14") _,
// )
// } else {
// unimplemented!("Copy too large for use of ldmia/stmia.");
// }
// }
/// The internal function for swapping the current value of a [`Static`] with
/// another value.