Skip to content
Open
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
14 changes: 6 additions & 8 deletions aarch32-rt/src/arch_v4/abort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ core::arch::global_asm!(
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp2


// Called from the vector table when we have an undefined exception.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _data_abort_handler(addr: usize);`
.section .text._asm_default_data_abort_handler
.pushsection .text._asm_default_data_abort_handler
.arm
.global _asm_default_data_abort_handler
.type _asm_default_data_abort_handler, %function
Expand All @@ -18,8 +17,7 @@ core::arch::global_asm!(
push {{ r12 }} // Save preserved register R12 - can now use it
mrs r12, spsr // grab SPSR
push {{ r12 }} // save SPSR value
mov r12, sp // align SP down to eight byte boundary using R12
and r12, r12, 7 //
and r12, sp, 7 // align SP down to eight byte boundary using R12
sub sp, r12 // SP now aligned - only push 64-bit values from here
push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding)
"#,
Expand All @@ -38,6 +36,7 @@ core::arch::global_asm!(
pop {{ r12 }} // restore R12
movs pc, lr // return from exception
.size _asm_default_data_abort_handler, . - _asm_default_data_abort_handler
.popsection
"#
);

Expand All @@ -46,11 +45,10 @@ core::arch::global_asm!(
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp2


// Called from the vector table when we have a prefetch abort.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _prefetch_abort_handler(addr: usize);`
.section .text._asm_default_prefetch_abort_handler
.pushsection .text._asm_default_prefetch_abort_handler
.arm
.global _asm_default_prefetch_abort_handler
.type _asm_default_prefetch_abort_handler, %function
Expand All @@ -59,8 +57,7 @@ core::arch::global_asm!(
push {{ r12 }} // Save preserved register R12 - can now use it
mrs r12, spsr // grab SPSR
push {{ r12 }} // save SPSR value
mov r12, sp // align SP down to eight byte boundary using R12
and r12, r12, 7 //
and r12, sp, 7 // align SP down to eight byte boundary using R12
sub sp, r12 // SP now aligned - only push 64-bit values from here
push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding)
"#,
Expand All @@ -79,5 +76,6 @@ core::arch::global_asm!(
pop {{ r12 }} // restore R12
movs pc, lr // return from exception
.size _asm_default_prefetch_abort_handler, . - _asm_default_prefetch_abort_handler
.popsection
"#,
);
9 changes: 6 additions & 3 deletions aarch32-rt/src/arch_v4/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ core::arch::global_asm!(
// Called from the vector table when we have an interrupt.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _irq_handler();`
.section .text._asm_default_irq_handler
//
// See https://developer.arm.com/documentation/dui0203/j/handling-processor-exceptions/armv6-and-earlier--armv7-a-and-armv7-r-profiles/interrupt-handlers
// for details on how we need to save LR_irq, SPSR_irq and LR_sys.
.pushsection .text._asm_default_irq_handler
.arm
.global _asm_default_irq_handler
.type _asm_default_irq_handler, %function
Expand All @@ -22,8 +25,7 @@ core::arch::global_asm!(
push {{ lr }} // save it to IRQ stack using LR
msr cpsr_c, {sys_mode} // switch to system mode so we can handle another interrupt (because if we interrupt irq mode we trash our own shadow registers)
push {{ lr }} // Save LR of system mode before using it for stack alignment
mov lr, sp // align SP down to eight byte boundary using LR
and lr, lr, 7 //
and lr, sp, 7 // align SP down to eight byte boundary using LR
sub sp, lr // SP now aligned - only push 64-bit values from here
push {{ r0-r3, r12, lr }} // push alignment amount (in LR) and preserved registers
"#,
Expand All @@ -41,6 +43,7 @@ core::arch::global_asm!(
msr spsr, lr //
ldmfd sp!, {{ pc }}^ // return from exception (^ => restore SPSR to CPSR)
.size _asm_default_irq_handler, . - _asm_default_irq_handler
.popsection
"#,
// sys mode with IRQ masked
sys_mode = const {
Expand Down
7 changes: 3 additions & 4 deletions aarch32-rt/src/arch_v4/svc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,18 @@ core::arch::global_asm!(
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp2


// Called from the vector table when we have an software interrupt.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _svc_handler(arg: u32, frame: &Frame) -> u32;`
.section .text._asm_default_svc_handler
.pushsection .text._asm_default_svc_handler
.arm
.global _asm_default_svc_handler
.type _asm_default_svc_handler, %function
_asm_default_svc_handler:
push {{ r12, lr }} // save LR and R12 - can now use R12 (but leave LR alone for SVC code lookup)
mrs r12, spsr // grab SPSR using R12
push {{ r12 }} // save SPSR value
mov r12, sp // align SP down to eight byte boundary using R12
and r12, r12, 7 //
and r12, sp, 7 // align SP down to eight byte boundary using R12
sub sp, r12 // SP now aligned - only push 64-bit values from here
push {{ r0-r6, r12 }} // push alignment amount, and stacked SVC argument registers (must be even number of regs for alignment)
mov r12, sp // save SP for integer frame
Expand Down Expand Up @@ -49,6 +47,7 @@ core::arch::global_asm!(
msr spsr, lr //
ldmfd sp!, {{ r12, pc }}^ // restore R12 and return from exception (^ => restore SPSR to CPSR)
.size _asm_default_svc_handler, . - _asm_default_svc_handler
.popsection
"#,
t_bit = const { crate::Cpsr::new_with_raw_value(0).with_t(true).raw_value() },
);
8 changes: 4 additions & 4 deletions aarch32-rt/src/arch_v4/undefined.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ core::arch::global_asm!(
r#"
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp2

// Called from the vector table when we have an undefined exception.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _undefined_handler(addr: usize) -> usize;`
// or
// `extern "C" fn _undefined_handler(addr: usize) -> !;`
.section .text._asm_default_undefined_handler
.pushsection .text._asm_default_undefined_handler
.arm
.global _asm_default_undefined_handler
.type _asm_default_undefined_handler, %function
Expand All @@ -23,8 +23,7 @@ core::arch::global_asm!(
ite eq // Adjust LR to point to faulting instruction - see p.1206 of the ARMv7-A architecture manual.
subeq lr, lr, #4 // Subtract 4 in Arm Mode
subne lr, lr, #2 // Subtract 2 in Thumb Mode
mov r12, sp // align SP down to eight byte boundary using R12
and r12, r12, 7 //
and r12, sp, 7 // align SP down to eight byte boundary using R12
sub sp, r12 // SP now aligned - only push 64-bit values from here
push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding)
"#,
Expand All @@ -43,6 +42,7 @@ core::arch::global_asm!(
pop {{ r12 }} // restore R12
movs pc, lr // return from exception (movs => restore SPSR to CPSR)
.size _asm_default_undefined_handler, . - _asm_default_undefined_handler
.popsection
"#,
t_bit = const { crate::Cpsr::new_with_raw_value(0).with_t(true).raw_value() },
);
17 changes: 9 additions & 8 deletions aarch32-rt/src/arch_v7/abort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ core::arch::global_asm!(
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp3

.section .text._asm_default_data_abort_handler

// Called from the vector table when we have an undefined exception.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _data_abort_handler(addr: usize);`
.pushsection .text._asm_default_data_abort_handler
.arm
.global _asm_default_data_abort_handler
.type _asm_default_data_abort_handler, %function
_asm_default_data_abort_handler:
sub lr, lr, #8 // Subtract 8 from LR, see p.1214 of the ARMv7-A architecture manual.
srsfd sp!, #{abt_mode} // store return state to ABT stack
push {{ r12 }} // Save preserved register R12 - can now use it
mov r12, sp // align SP down to eight byte boundary using R12
and r12, r12, 7 //
and r12, sp, 7 // align SP down to eight byte boundary using R12
sub sp, r12 // SP now aligned - only push 64-bit values from here
push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding)
"#,
Expand All @@ -35,6 +35,7 @@ core::arch::global_asm!(
str lr, [sp] // overwrite the saved LR with the one from the C handler
rfefd sp! // return from exception
.size _asm_default_data_abort_handler, . - _asm_default_data_abort_handler
.popsection
"#,
abt_mode = const crate::ProcessorMode::Abt as u8,
);
Expand All @@ -43,20 +44,19 @@ core::arch::global_asm!(
r#"
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp3
.section .text._asm_default_prefetch_abort_handler


// Called from the vector table when we have a prefetch abort.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _prefetch_abort_handler(addr: usize);`
.global _asm_default_prefetch_abort_handler
.pushsection .text._asm_default_prefetch_abort_handler
.arm
.global _asm_default_prefetch_abort_handler
.type _asm_default_prefetch_abort_handler, %function
_asm_default_prefetch_abort_handler:
sub lr, lr, #4 // Subtract 8 from LR, see p.1212 of the ARMv7-A architecture manual.
srsfd sp!, #{abt_mode} // store return state to ABT stack
push {{ r12 }} // save R12 - can now use it
mov r12, sp // align SP down to eight byte boundary using R12
and r12, r12, 7 //
and r12, sp, 7 // align SP down to eight byte boundary using R12
sub sp, r12 // SP now aligned - only push 64-bit values from here
push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding)
"#,
Expand All @@ -74,6 +74,7 @@ core::arch::global_asm!(
str lr, [sp] // overwrite the saved LR with the one from the C handler
rfefd sp! // return from exception
.size _asm_default_prefetch_abort_handler, . - _asm_default_prefetch_abort_handler
.popsection
"#,
abt_mode = const crate::ProcessorMode::Abt as u8,
);
11 changes: 7 additions & 4 deletions aarch32-rt/src/arch_v7/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@ core::arch::global_asm!(
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp3

.section .text._asm_default_irq_handler

// Called from the vector table when we have an interrupt.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _irq_handler();`
//
// See https://developer.arm.com/documentation/dui0203/j/handling-processor-exceptions/armv6-and-earlier--armv7-a-and-armv7-r-profiles/interrupt-handlers
// for details on how we need to save LR_irq, SPSR_irq and LR_sys.
.pushsection .text._asm_default_irq_handler
.arm
.global _asm_default_irq_handler
.type _asm_default_irq_handler, %function
_asm_default_irq_handler:
sub lr, lr, 4 // make sure we jump back to the right place
srsfd sp!, #{sys_mode} // store return state to SYS stack
cps #{sys_mode} // switch to system mode so we can handle another interrupt (because if we interrupt irq mode we trash our own shadow registers)
push {{ lr }} // save adjusted LR to SYS stack
mov lr, sp // align SP down to eight byte boundary using LR
and lr, lr, 7 //
and lr, sp, 7 // align SP down to eight byte boundary using LR
sub sp, lr // SP now aligned - only push 64-bit values from here
push {{ r0-r3, r12, lr }} // push alignment amount (in LR) and preserved registers
"#,
Expand All @@ -34,6 +36,7 @@ core::arch::global_asm!(
pop {{ lr }} // restore adjusted LR
rfefd sp! // return from exception
.size _asm_default_irq_handler, . - _asm_default_irq_handler
.popsection
"#,
sys_mode = const crate::ProcessorMode::Sys as u8,
);
8 changes: 4 additions & 4 deletions aarch32-rt/src/arch_v7/svc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@ core::arch::global_asm!(
r#"
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp3

// Called from the vector table when we have an software interrupt.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _svc_handler(arg: u32, frame: &Frame) -> u32;`
.section .text._asm_default_svc_handler
.pushsection .text._asm_default_svc_handler
.arm
.global _asm_default_svc_handler
.type _asm_default_svc_handler, %function
_asm_default_svc_handler:
srsfd sp!, #{svc_mode} // store return state to SVC stack
push {{ r12, lr }} // save LR and R12 - can now use R12 (but leave LR alone for SVC code lookup)
mov r12, sp // align SP down to eight byte boundary using R12
and r12, r12, 7 //
and r12, sp, 7 // align SP down to eight byte boundary using R12
sub sp, r12 // SP now aligned - only push 64-bit values from here
push {{ r0-r6, r12 }} // push alignment amount, and stacked SVC argument registers (must be even number of regs for alignment)
mov r12, sp // save SP for integer frame
Expand All @@ -42,6 +41,7 @@ core::arch::global_asm!(
pop {{ r12, lr }} // restore R12 and LR
rfefd sp! // return from exception
.size _asm_default_svc_handler, . - _asm_default_svc_handler
.popsection
"#,
svc_mode = const crate::ProcessorMode::Svc as u8,
t_bit = const { crate::Cpsr::new_with_raw_value(0).with_t(true).raw_value() },
Expand Down
7 changes: 4 additions & 3 deletions aarch32-rt/src/arch_v7/undefined.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ core::arch::global_asm!(
// `extern "C" fn _undefined_handler(addr: usize) -> usize;`
// or
// `extern "C" fn _undefined_handler(addr: usize) -> !;`
.section .text._asm_default_undefined_handler
.pushsection .text._asm_default_undefined_handler
.arm
.global _asm_default_undefined_handler
.type _asm_default_undefined_handler, %function
_asm_default_undefined_handler:
Expand All @@ -22,8 +23,7 @@ core::arch::global_asm!(
ite eq // Adjust LR to point to faulting instruction - see p.1206 of the ARMv7-A architecture manual.
subeq lr, lr, #4 // Subtract 4 in Arm Mode
subne lr, lr, #2 // Subtract 2 in Thumb Mode
mov r12, sp // align SP down to eight byte boundary using R12
and r12, r12, 7 //
and r12, sp, 7 // align SP down to eight byte boundary using R12
sub sp, r12 // SP now aligned - only push 64-bit values from here
push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding)
"#,
Expand All @@ -41,6 +41,7 @@ core::arch::global_asm!(
str lr, [sp] // overwrite the saved LR with the one from the C handler
rfefd sp! // return from exception
.size _asm_default_undefined_handler, . - _asm_default_undefined_handler
.popsection
"#,
und_mode = const crate::ProcessorMode::Und as u8,
t_bit = const { crate::Cpsr::new_with_raw_value(0).with_t(true).raw_value() },
Expand Down
Loading