mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
Entirely remove the need for binutils
This commit is contained in:
parent
2012f2ec35
commit
5ab0176ddb
71
agb/build.rs
71
agb/build.rs
|
@ -1,76 +1,5 @@
|
|||
use std::path;
|
||||
|
||||
fn main() {
|
||||
let asm = &[
|
||||
"src/crt0.s",
|
||||
"src/interrupt_handler.s",
|
||||
"src/sound/mixer/mixer.s",
|
||||
"src/agbabi/memset.s",
|
||||
"src/agbabi/memcpy.s",
|
||||
"src/save/asm_routines.s",
|
||||
];
|
||||
|
||||
println!("cargo:rerun-if-changed=gba.ld");
|
||||
println!("cargo:rerun-if-changed=gba_mb.ld");
|
||||
println!("cargo:rerun-if-changed=src/asm_include.s");
|
||||
println!("cargo:rerun-if-changed=src/agbabi/macros.inc");
|
||||
println!("cargo:rerun-if-changed=gfx/test_logo.png");
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR environment variable must be specified");
|
||||
let mut o_files = vec![];
|
||||
|
||||
for &a in asm.iter() {
|
||||
println!("cargo:rerun-if-changed={a}");
|
||||
let filename = path::Path::new(a);
|
||||
let filename = filename.with_extension("o");
|
||||
let filename = filename
|
||||
.file_name()
|
||||
.expect("should have filename")
|
||||
.to_str()
|
||||
.expect("Please make it valid utf-8");
|
||||
|
||||
let out_file_path = format!("{out_dir}/{filename}");
|
||||
|
||||
let out = std::process::Command::new("arm-none-eabi-as")
|
||||
.arg("-mthumb-interwork")
|
||||
.arg("-mcpu=arm7tdmi")
|
||||
.arg("-g")
|
||||
.args(["-o", out_file_path.as_str()])
|
||||
.arg(a)
|
||||
.output()
|
||||
.unwrap_or_else(|_| panic!("failed to compile {a}"));
|
||||
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"{}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
for warning_line in String::from_utf8_lossy(&out.stderr).split('\n') {
|
||||
if !warning_line.is_empty() {
|
||||
println!("cargo:warning={warning_line}");
|
||||
}
|
||||
}
|
||||
|
||||
o_files.push(out_file_path);
|
||||
}
|
||||
|
||||
let archive = format!("{out_dir}/agb.a");
|
||||
let _ = std::fs::remove_file(&archive);
|
||||
let ar_out = std::process::Command::new("arm-none-eabi-ar")
|
||||
.arg("-crs")
|
||||
.arg(&archive)
|
||||
.args(&o_files)
|
||||
.output()
|
||||
.expect("Failed to create static library");
|
||||
|
||||
assert!(
|
||||
ar_out.status.success(),
|
||||
"{}",
|
||||
String::from_utf8_lossy(&ar_out.stderr)
|
||||
);
|
||||
|
||||
println!("cargo:rustc-link-search={out_dir}");
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(rom);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(ewram);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -32,14 +32,14 @@ __aeabi_memcpy:
|
|||
joaobapt_test r3
|
||||
|
||||
// Copy byte head to align
|
||||
ldrmib r3, [r1], #1
|
||||
strmib r3, [r0], #1
|
||||
ldrbmi r3, [r1], #1
|
||||
strbmi r3, [r0], #1
|
||||
submi r2, r2, #1
|
||||
// r0, r1 are now half aligned
|
||||
|
||||
// Copy half head to align
|
||||
ldrcsh r3, [r1], #2
|
||||
strcsh r3, [r0], #2
|
||||
ldrhcs r3, [r1], #2
|
||||
strhcs r3, [r0], #2
|
||||
subcs r2, r2, #2
|
||||
// r0, r1 are now word aligned
|
||||
|
||||
|
@ -51,13 +51,13 @@ __aeabi_memcpy4:
|
|||
blt .Lcopy_words
|
||||
|
||||
// Word aligned, 32-byte copy
|
||||
push {r4-r10}
|
||||
push {{r4-r10}}
|
||||
.Lloop_32:
|
||||
subs r2, r2, #32
|
||||
ldmgeia r1!, {r3-r10}
|
||||
stmgeia r0!, {r3-r10}
|
||||
ldmiage r1!, {{r3-r10}}
|
||||
stmiage r0!, {{r3-r10}}
|
||||
bgt .Lloop_32
|
||||
pop {r4-r10}
|
||||
pop {{r4-r10}}
|
||||
bxeq lr
|
||||
|
||||
// < 32 bytes remaining to be copied
|
||||
|
@ -77,40 +77,40 @@ __aeabi_memcpy4:
|
|||
// This test still works when r2 is negative
|
||||
joaobapt_test r2
|
||||
// Copy half
|
||||
ldrcsh r3, [r1], #2
|
||||
strcsh r3, [r0], #2
|
||||
ldrhcs r3, [r1], #2
|
||||
strhcs r3, [r0], #2
|
||||
// Copy byte
|
||||
ldrmib r3, [r1]
|
||||
strmib r3, [r0]
|
||||
ldrbmi r3, [r1]
|
||||
strbmi r3, [r0]
|
||||
bx lr
|
||||
|
||||
.Lcopy_halves:
|
||||
// Copy byte head to align
|
||||
tst r0, #1
|
||||
ldrneb r3, [r1], #1
|
||||
strneb r3, [r0], #1
|
||||
ldrbne r3, [r1], #1
|
||||
strbne r3, [r0], #1
|
||||
subne r2, r2, #1
|
||||
// r0, r1 are now half aligned
|
||||
|
||||
.global __agbabi_memcpy2
|
||||
__agbabi_memcpy2:
|
||||
subs r2, r2, #2
|
||||
ldrgeh r3, [r1], #2
|
||||
strgeh r3, [r0], #2
|
||||
ldrhge r3, [r1], #2
|
||||
strhge r3, [r0], #2
|
||||
bgt __agbabi_memcpy2
|
||||
bxeq lr
|
||||
|
||||
// Copy byte tail
|
||||
adds r2, r2, #1
|
||||
ldreqb r3, [r1]
|
||||
streqb r3, [r0]
|
||||
ldrbeq r3, [r1]
|
||||
strbeq r3, [r0]
|
||||
bx lr
|
||||
|
||||
.global __agbabi_memcpy1
|
||||
__agbabi_memcpy1:
|
||||
subs r2, r2, #1
|
||||
ldrgeb r3, [r1], #1
|
||||
strgeb r3, [r0], #1
|
||||
ldrbge r3, [r1], #1
|
||||
strbge r3, [r0], #1
|
||||
bgt __agbabi_memcpy1
|
||||
bx lr
|
||||
|
||||
|
@ -118,7 +118,7 @@ __agbabi_memcpy1:
|
|||
.align 2
|
||||
.global memcpy
|
||||
memcpy:
|
||||
push {r0, lr}
|
||||
push {{r0, lr}}
|
||||
bl __aeabi_memcpy
|
||||
pop {r0, lr}
|
||||
pop {{r0, lr}}
|
||||
bx lr
|
||||
|
|
|
@ -40,9 +40,9 @@ __aeabi_memset:
|
|||
// JoaoBapt carry & sign bit test
|
||||
movs r1, r1, lsl #31
|
||||
// Set byte and half
|
||||
strmib r2, [r0], #1
|
||||
strcsb r2, [r0], #1
|
||||
strcsb r2, [r0]
|
||||
strbmi r2, [r0], #1
|
||||
strbcs r2, [r0], #1
|
||||
strbcs r2, [r0]
|
||||
bx lr
|
||||
|
||||
.LskipShortHead:
|
||||
|
@ -50,9 +50,9 @@ __aeabi_memset:
|
|||
// JoaoBapt carry & sign bit test
|
||||
movs r3, r3, lsl #31
|
||||
// Set half and byte head
|
||||
strmib r2, [r0], #1
|
||||
strbmi r2, [r0], #1
|
||||
submi r1, r1, #1
|
||||
strcsh r2, [r0], #2
|
||||
strhcs r2, [r0], #2
|
||||
subcs r1, r1, #2
|
||||
b __agbabi_wordset4
|
||||
|
||||
|
@ -79,7 +79,7 @@ __agbabi_wordset4:
|
|||
beq .Lskip32
|
||||
lsl r3, r12, #5
|
||||
sub r1, r1, r3
|
||||
push {r4-r9}
|
||||
push {{r4-r9}}
|
||||
mov r3, r2
|
||||
mov r4, r2
|
||||
mov r5, r2
|
||||
|
@ -88,10 +88,10 @@ __agbabi_wordset4:
|
|||
mov r8, r2
|
||||
mov r9, r2
|
||||
.LsetWords8:
|
||||
stmia r0!, {r2-r9}
|
||||
stmia r0!, {{r2-r9}}
|
||||
subs r12, r12, #1
|
||||
bne .LsetWords8
|
||||
pop {r4-r9}
|
||||
pop {{r4-r9}}
|
||||
.Lskip32:
|
||||
|
||||
// Set words
|
||||
|
@ -104,8 +104,8 @@ __agbabi_wordset4:
|
|||
// Set half and byte tail
|
||||
// JoaoBapt carry & sign bit test
|
||||
movs r3, r1, lsl #31
|
||||
strcsh r2, [r0], #2
|
||||
strmib r2, [r0]
|
||||
strhcs r2, [r0], #2
|
||||
strbmi r2, [r0]
|
||||
bx lr
|
||||
|
||||
.section .iwram.memset, "ax", %progbits
|
||||
|
@ -115,7 +115,7 @@ memset:
|
|||
mov r3, r1
|
||||
mov r1, r2
|
||||
mov r2, r3
|
||||
push {r0, lr}
|
||||
push {{r0, lr}}
|
||||
bl __aeabi_memset
|
||||
pop {r0, lr}
|
||||
pop {{r0, lr}}
|
||||
bx lr
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
use core::arch::global_asm;
|
||||
|
||||
global_asm!(include_str!("memcpy.s"));
|
||||
global_asm!(include_str!("memset.s"));
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
mod memset {
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
.align 2
|
||||
.global \functionName
|
||||
.type \functionName, %function
|
||||
.func \functionName
|
||||
@ .func \functionName
|
||||
\functionName:
|
||||
.endm
|
||||
|
||||
.macro agb_arm_end functionName:req
|
||||
.pool
|
||||
.size \functionName,.-\functionName
|
||||
.endfunc
|
||||
@ .endfunc
|
||||
.endm
|
||||
|
||||
.macro agb_thumb_func functionName:req
|
||||
|
@ -20,12 +20,12 @@
|
|||
.align 1
|
||||
.global \functionName
|
||||
.type \functionName, %function
|
||||
.func \functionName
|
||||
@ .func \functionName
|
||||
\functionName:
|
||||
.endm
|
||||
|
||||
.macro agb_thumb_end functionName:req
|
||||
.pool
|
||||
.size \functionName,.-\functionName
|
||||
.endfunc
|
||||
@ .endfunc
|
||||
.endm
|
||||
|
|
5
agb/src/global_asm.rs
Normal file
5
agb/src/global_asm.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
use core::arch::global_asm;
|
||||
|
||||
global_asm!(include_str!("crt0.s"));
|
||||
global_asm!(include_str!("interrupt_handler.s"));
|
||||
global_asm!(include_str!("sound/mixer/mixer.s"));
|
|
@ -26,10 +26,10 @@ InterruptHandler:
|
|||
|
||||
@ call the rust interrupt handler with r0 set to the triggered interrupts
|
||||
ldr r1, =__RUST_INTERRUPT_HANDLER
|
||||
push {r2, lr}
|
||||
push {{r2, lr}}
|
||||
mov lr, pc
|
||||
bx r1
|
||||
pop {r2, lr}
|
||||
pop {{r2, lr}}
|
||||
|
||||
@ change back to interrupt mode
|
||||
mrs r1, cpsr
|
||||
|
|
|
@ -174,6 +174,7 @@ mod no_game;
|
|||
pub use no_game::no_game;
|
||||
|
||||
pub(crate) mod arena;
|
||||
mod global_asm;
|
||||
|
||||
pub use {agb_alloc::ExternalAllocator, agb_alloc::InternalAllocator};
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ agb_thumb_end agb_rs__WramReadByte
|
|||
@ A routine that compares two memory offsets.
|
||||
@
|
||||
agb_thumb_func agb_rs__WramVerifyBuf
|
||||
push {r4-r5, lr}
|
||||
push {{r4-r5, lr}}
|
||||
movs r5, r0 @ set up r5 to be r0, so we can use it immediately for the return result
|
||||
movs r0, #0 @ set up r0 so the default return result is false
|
||||
|
||||
|
@ -25,14 +25,14 @@ agb_thumb_func agb_rs__WramVerifyBuf
|
|||
ldrb r4, [r1,r2]
|
||||
cmp r3, r4
|
||||
bne 0f
|
||||
sub r2, #1
|
||||
subs r2, #1
|
||||
bpl 1b
|
||||
|
||||
@ Returns from the function successfully
|
||||
movs r0, #1
|
||||
0: @ Jumps to here return the function unsuccessfully, because r0 contains 0 at this point
|
||||
pop {r4-r5}
|
||||
pop {r1}
|
||||
pop {{r4-r5}}
|
||||
pop {{r1}}
|
||||
bx r1
|
||||
agb_thumb_end agb_rs__WramVerifyBuf
|
||||
|
||||
|
@ -43,7 +43,7 @@ agb_thumb_end agb_rs__WramVerifyBuf
|
|||
@ A routine that copies one buffer into another.
|
||||
@
|
||||
agb_thumb_func agb_rs__WramTransferBuf
|
||||
0: sub r2, #1
|
||||
0: subs r2, #1
|
||||
ldrb r3, [r0,r2]
|
||||
strb r3, [r1,r2]
|
||||
bne 0b
|
||||
|
|
|
@ -90,12 +90,16 @@ use crate::sync::{Mutex, RawMutexGuard};
|
|||
use crate::timer::Timer;
|
||||
use core::ops::Range;
|
||||
|
||||
use core::arch::global_asm;
|
||||
|
||||
mod asm_utils;
|
||||
mod eeprom;
|
||||
mod flash;
|
||||
mod sram;
|
||||
mod utils;
|
||||
|
||||
global_asm!(include_str!("asm_routines.s"));
|
||||
|
||||
/// A list of save media types.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
|
||||
#[non_exhaustive]
|
||||
|
|
|
@ -15,7 +15,7 @@ agb_arm_func agb_rs__mixer_add
|
|||
@ stack position 1 - amount to modify the right channel by (u16 fixnum with 4 bits)
|
||||
@
|
||||
@ The sound buffer must be SOUND_BUFFER_SIZE * 2 in size = 176 * 2
|
||||
push {r4-r8}
|
||||
push {{r4-r8}}
|
||||
|
||||
ldr r7, [sp, #20] @ load the right channel modification amount into r7
|
||||
|
||||
|
@ -46,7 +46,7 @@ modifications_fallback:
|
|||
subs r8, r8, #4 @ loop counter
|
||||
bne 1b @ jump back if we're done with the loop
|
||||
|
||||
pop {r4-r8}
|
||||
pop {{r4-r8}}
|
||||
bx lr
|
||||
|
||||
same_modification:
|
||||
|
@ -88,7 +88,7 @@ same_modification:
|
|||
subs r8, r8, #4 @ loop counter
|
||||
bne 1b @ jump back if we're done with the loop
|
||||
|
||||
pop {r4-r8}
|
||||
pop {{r4-r8}}
|
||||
bx lr
|
||||
|
||||
agb_arm_end agb_rs__mixer_add
|
||||
|
@ -100,7 +100,7 @@ agb_arm_func agb_rs__mixer_add_stereo
|
|||
@ r2 - volume to play the sound at
|
||||
@
|
||||
@ The sound buffer must be SOUND_BUFFER_SIZE * 2 in size = 176 * 2
|
||||
push {r4-r9}
|
||||
push {{r4-r9}}
|
||||
|
||||
mov r9, r2
|
||||
ldr r5, =0x00000FFF
|
||||
|
@ -140,7 +140,7 @@ agb_arm_func agb_rs__mixer_add_stereo
|
|||
subs r8, r8, #4 @ loop counter
|
||||
bne 1b @ jump back if we're done with the loop
|
||||
|
||||
pop {r4-r9}
|
||||
pop {{r4-r9}}
|
||||
bx lr
|
||||
|
||||
agb_arm_end agb_rs__mixer_add_stereo
|
||||
|
@ -150,7 +150,7 @@ agb_arm_func agb_rs__mixer_collapse
|
|||
@ r0 = target buffer (i8)
|
||||
@ r1 = input buffer (i16) of fixnums with 4 bits of precision (read in sets of i16 in an i32)
|
||||
|
||||
push {r4-r11}
|
||||
push {{r4-r11}}
|
||||
|
||||
CONST_0 .req r7
|
||||
CONST_FF .req r8
|
||||
|
@ -228,6 +228,6 @@ SWAP_SIGN .req r11
|
|||
subs r2, r2, #16 @ r2 -= 16
|
||||
bne 1b @ loop if not 0
|
||||
|
||||
pop {r4-r11}
|
||||
pop {{r4-r11}}
|
||||
bx lr
|
||||
agb_arm_end agb_rs__mixer_collapse
|
||||
|
|
|
@ -15,8 +15,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(rom);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(ewram);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(rom);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(ewram);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(rom);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(ewram);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(rom);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(ewram);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(rom);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(rom);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(ewram);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(rom);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ MEMORY {
|
|||
|
||||
__text_start = ORIGIN(ewram);
|
||||
|
||||
INPUT (agb.a)
|
||||
|
||||
SECTIONS {
|
||||
. = __text_start;
|
||||
|
||||
|
|
Loading…
Reference in a new issue