Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/bios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![no_std]
#![feature(asm, global_asm, isa_attribute)]
#![feature(isa_attribute)]

//! This crate helps you write GBA ROMs.
//!
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/mmio_addresses/mode3.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::prelude::Color;

use core::arch::asm;
use voladdress::*;

pub const WIDTH: usize = 240;
Expand Down
3 changes: 2 additions & 1 deletion src/save/asm_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"));

Expand Down
2 changes: 2 additions & 0 deletions src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

use crate::prelude::*;

use core::arch::asm;

mod locks;
mod statics;

Expand Down
126 changes: 65 additions & 61 deletions src/sync/statics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::sync::with_irqs_disabled;
use core::{
arch::asm,
cell::UnsafeCell,
mem::{align_of, size_of, MaybeUninit},
ptr,
Expand All @@ -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!(
Expand Down Expand Up @@ -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.
Expand Down