Skip to content

Commit 45dc402

Browse files
committed
Support thumbv4t-none-eabi and thumbv5te-none-eabi
1 parent 4469cf4 commit 45dc402

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+803
-131
lines changed

.cargo/config.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,11 @@ runner = "qemu-system-arm -machine versatileab -cpu arm926 -semihosting -nograph
2222
[target.armv4t-none-eabi]
2323
runner = "qemu-system-arm -machine versatileab -cpu pxa250 -semihosting -nographic -audio none -kernel"
2424

25+
[target.thumbv5te-none-eabi]
26+
runner = "qemu-system-arm -machine versatileab -cpu arm926 -semihosting -nographic -audio none -kernel"
27+
28+
[target.thumbv4t-none-eabi]
29+
runner = "qemu-system-arm -machine versatileab -cpu pxa250 -semihosting -nographic -audio none -kernel"
30+
2531
[unstable]
2632
build-std = ["core", "alloc"]

aarch32-cpu/src/asmv4.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//! Simple assembly routines for ARMv4
2+
3+
/// Emit an NOP instruction
4+
#[cfg_attr(not(feature = "check-asm"), inline)]
5+
pub fn nop() {
6+
unsafe { core::arch::asm!("nop", options(nomem, nostack, preserves_flags)) }
7+
}
8+
9+
/// Mask IRQ
10+
#[cfg_attr(not(feature = "check-asm"), inline)]
11+
#[instruction_set(arm::a32)]
12+
pub fn irq_disable() {
13+
unsafe {
14+
core::arch::asm!(r#"
15+
mrs {0}, cpsr
16+
orr {0}, {flag}
17+
msr cpsr, {0}
18+
"#,
19+
in(reg) 0,
20+
flag = const {
21+
crate::register::Cpsr::new_with_raw_value(0)
22+
.with_i(true)
23+
.raw_value()
24+
},
25+
options(nomem, nostack, preserves_flags));
26+
};
27+
}
28+
29+
/// Unmask IRQ
30+
#[cfg_attr(not(feature = "check-asm"), inline)]
31+
#[instruction_set(arm::a32)]
32+
pub fn irq_enable() {
33+
unsafe {
34+
core::arch::asm!(r#"
35+
mrs {0}, cpsr
36+
bic {0}, #{flag}
37+
msr cpsr, {0}
38+
"#,
39+
in(reg) 0,
40+
flag = const {
41+
crate::register::Cpsr::new_with_raw_value(0)
42+
.with_i(true)
43+
.raw_value()
44+
},
45+
options(nomem, nostack, preserves_flags));
46+
};
47+
}
48+
49+
/// Which core are we?
50+
///
51+
/// Return the bottom 24-bits of the MPIDR
52+
#[cfg_attr(not(feature = "check-asm"), inline)]
53+
#[instruction_set(arm::a32)]
54+
pub fn core_id() -> u32 {
55+
let r: u32;
56+
unsafe {
57+
core::arch::asm!("MRC p15, 0, {}, c0, c0, 5", out(reg) r, options(nomem, nostack, preserves_flags));
58+
}
59+
r & 0x00FF_FFFF
60+
}
61+
62+
#[no_mangle]
63+
pub extern "C" fn __sync_synchronize() {
64+
// we don't have a barrier instruction - the linux kernel just uses an empty inline asm block
65+
unsafe {
66+
core::arch::asm!("");
67+
}
68+
}
Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
//! Simple assembly routines
1+
//! Simple assembly routines for ARMv7
22
33
/// Data Memory Barrier
44
///
55
/// Ensures that all explicit memory accesses that appear in program order before the `DMB`
66
/// instruction are observed before any explicit memory accesses that appear in program order
77
/// after the `DMB` instruction.
88
#[cfg_attr(not(feature = "check-asm"), inline)]
9-
#[cfg(any(
10-
arm_architecture = "v7-r",
11-
arm_architecture = "v7-a",
12-
arm_architecture = "v8-r"
13-
))]
149
pub fn dmb() {
1510
use core::sync::atomic::{compiler_fence, Ordering};
1611
compiler_fence(Ordering::SeqCst);
@@ -28,11 +23,6 @@ pub fn dmb() {
2823
/// * any explicit memory access made before this instruction is complete
2924
/// * all cache and branch predictor maintenance operations before this instruction complete
3025
#[cfg_attr(not(feature = "check-asm"), inline)]
31-
#[cfg(any(
32-
arm_architecture = "v7-r",
33-
arm_architecture = "v7-a",
34-
arm_architecture = "v8-r"
35-
))]
3626
pub fn dsb() {
3727
use core::sync::atomic::{compiler_fence, Ordering};
3828
compiler_fence(Ordering::SeqCst);
@@ -47,11 +37,6 @@ pub fn dsb() {
4737
/// Flushes the pipeline in the processor, so that all instructions following the `ISB` are fetched
4838
/// from cache or memory, after the instruction has been completed.
4939
#[cfg_attr(not(feature = "check-asm"), inline)]
50-
#[cfg(any(
51-
arm_architecture = "v7-r",
52-
arm_architecture = "v7-a",
53-
arm_architecture = "v8-r"
54-
))]
5540
pub fn isb() {
5641
use core::sync::atomic::{compiler_fence, Ordering};
5742
compiler_fence(Ordering::SeqCst);
@@ -69,39 +54,40 @@ pub fn nop() {
6954

7055
/// Emit an WFI instruction
7156
#[cfg_attr(not(feature = "check-asm"), inline)]
72-
#[cfg(any(
73-
arm_architecture = "v7-r",
74-
arm_architecture = "v7-a",
75-
arm_architecture = "v8-r"
76-
))]
7757
pub fn wfi() {
7858
unsafe { core::arch::asm!("wfi", options(nomem, nostack, preserves_flags)) }
7959
}
8060

8161
/// Emit an WFE instruction
8262
#[cfg_attr(not(feature = "check-asm"), inline)]
83-
#[cfg(any(
84-
arm_architecture = "v7-r",
85-
arm_architecture = "v7-a",
86-
arm_architecture = "v8-r"
87-
))]
8863
pub fn wfe() {
8964
unsafe { core::arch::asm!("wfe", options(nomem, nostack, preserves_flags)) }
9065
}
9166

9267
/// Emit an SEV instruction
9368
#[cfg_attr(not(feature = "check-asm"), inline)]
94-
#[cfg(any(
95-
arm_architecture = "v7-r",
96-
arm_architecture = "v7-a",
97-
arm_architecture = "v8-r"
98-
))]
9969
pub fn sev() {
10070
unsafe {
10171
core::arch::asm!("sev");
10272
}
10373
}
10474

75+
/// Mask IRQ
76+
#[cfg_attr(not(feature = "check-asm"), inline)]
77+
pub fn irq_disable() {
78+
unsafe {
79+
core::arch::asm!("cpsid i");
80+
}
81+
}
82+
83+
/// Unmask IRQ
84+
#[cfg_attr(not(feature = "check-asm"), inline)]
85+
pub fn irq_enable() {
86+
unsafe {
87+
core::arch::asm!("cpsie i");
88+
}
89+
}
90+
10591
/// Which core are we?
10692
///
10793
/// Return the bottom 24-bits of the MPIDR
@@ -113,12 +99,3 @@ pub fn core_id() -> u32 {
11399
}
114100
r & 0x00FF_FFFF
115101
}
116-
117-
#[cfg(any(arm_architecture = "v4t", arm_architecture = "v5te"))]
118-
#[no_mangle]
119-
pub extern "C" fn __sync_synchronize() {
120-
// we don't have a barrier instruction - the linux kernel just uses an empty inline asm block
121-
unsafe {
122-
core::arch::asm!("");
123-
}
124-
}

aarch32-cpu/src/interrupt.rs

Lines changed: 2 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
1414
pub unsafe fn enable() {
1515
// Ensure no preceeding memory accesses are reordered to after interrupts are enabled.
1616
compiler_fence(Ordering::SeqCst);
17-
// Safety: A Data Store Barrier is OK to call anywhere, and we're
18-
// atomically setting a bit in a special register, and we're in an unsafe
19-
// function that places restrictions on when you can call it
20-
#[cfg(any(
21-
arm_architecture = "v7-r",
22-
arm_architecture = "v7-a",
23-
arm_architecture = "v8-r"
24-
))]
25-
unsafe {
26-
core::arch::asm!(
27-
r#"
28-
dsb
29-
cpsie i
30-
"#,
31-
options(nomem, nostack, preserves_flags)
32-
);
33-
};
34-
#[cfg(all(
35-
target_arch = "arm",
36-
not(any(
37-
arm_architecture = "v7-r",
38-
arm_architecture = "v7-a",
39-
arm_architecture = "v8-r"
40-
))
41-
))]
42-
unsafe {
43-
core::arch::asm!(r#"
44-
mrs {0}, cpsr
45-
orr {0}, #0xC0
46-
msr cpsr, {0}
47-
"#,
48-
in(reg) 0,
49-
options(nomem, nostack, preserves_flags));
50-
};
17+
crate::asm::irq_enable();
5118
}
5219

5320
/// Disable IRQ
@@ -56,40 +23,7 @@ pub unsafe fn enable() {
5623
/// * Doesn't disable FIQ.
5724
#[inline]
5825
pub fn disable() {
59-
// Safety: A Data Store Barrier is OK to call anywhere, and we're
60-
// atomically setting a bit in a special register, and we're in an unsafe
61-
// function that places restrictions on when you can call it
62-
#[cfg(any(
63-
arm_architecture = "v7-r",
64-
arm_architecture = "v7-a",
65-
arm_architecture = "v8-r"
66-
))]
67-
unsafe {
68-
core::arch::asm!(
69-
r#"
70-
cpsid i
71-
dsb
72-
"#,
73-
options(nomem, nostack, preserves_flags)
74-
);
75-
};
76-
#[cfg(all(
77-
target_arch = "arm",
78-
not(any(
79-
arm_architecture = "v7-r",
80-
arm_architecture = "v7-a",
81-
arm_architecture = "v8-r"
82-
))
83-
))]
84-
unsafe {
85-
core::arch::asm!(r#"
86-
mrs {0}, cpsr
87-
bic {0}, #0xC0
88-
msr cpsr, {0}
89-
"#,
90-
in(reg) 0,
91-
options(nomem, nostack, preserves_flags));
92-
};
26+
crate::asm::irq_disable();
9327
// Ensure no subsequent memory accesses are reordered to before interrupts are disabled.
9428
compiler_fence(Ordering::SeqCst);
9529
}

aarch32-cpu/src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,22 @@
33

44
mod critical_section;
55

6-
#[cfg(any(doc, target_arch = "arm"))]
6+
#[cfg(any(
7+
doc,
8+
arm_architecture = "v7-a",
9+
arm_architecture = "v7-r",
10+
arm_architecture = "v8-r"
11+
))]
12+
#[path = "asmv7.rs"]
13+
pub mod asm;
14+
15+
#[cfg(not(any(
16+
doc,
17+
arm_architecture = "v7-a",
18+
arm_architecture = "v7-r",
19+
arm_architecture = "v8-r"
20+
)))]
21+
#[path = "asmv4.rs"]
722
pub mod asm;
823

924
pub mod cache;

aarch32-cpu/src/register/cpsr.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,14 @@ pub struct Cpsr {
7070

7171
impl Cpsr {
7272
/// Read CPSR (*Current Program Status Register*)
73-
#[inline]
73+
///
74+
/// On Armv4T and Armv5TE this will be an Arm function, even on the
75+
/// `thumb*` targets, as Thumb-1 cannot do an MRS.
76+
#[cfg_attr(not(feature = "check-asm"), inline)]
77+
#[cfg_attr(
78+
any(arm_architecture = "v4t", arm_architecture = "v5te"),
79+
instruction_set(arm::a32)
80+
)]
7481
pub fn read() -> Self {
7582
let r: u32;
7683
// Safety: Reading this register has no side-effects and is atomic
@@ -96,7 +103,14 @@ impl Cpsr {
96103
///
97104
/// You almost certainly want to follow this with an [ISB](crate::asm::isb)
98105
/// instruction.
99-
#[inline]
106+
///
107+
/// On Armv4T and Armv5TE this will be an Arm function, even on the
108+
/// `thumb*` targets, as Thumb-1 cannot do an MSR.
109+
#[cfg_attr(not(feature = "check-asm"), inline)]
110+
#[cfg_attr(
111+
any(arm_architecture = "v4t", arm_architecture = "v5te"),
112+
instruction_set(arm::a32)
113+
)]
100114
pub unsafe fn write(_value: Self) {
101115
// Safety: This is risky, but we're in an unsafe function
102116
#[cfg(target_arch = "arm")]

aarch32-cpu/src/register/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,11 @@ pub trait SysRegRead: SysReg {
223223
///
224224
/// You need to read the Architecture Reference Manual because this read
225225
/// may have side-effects.
226-
#[inline]
226+
#[cfg_attr(not(feature = "check-asm"), inline)]
227+
#[cfg_attr(
228+
any(arm_architecture = "v4t", arm_architecture = "v5te"),
229+
instruction_set(arm::a32)
230+
)]
227231
unsafe fn read_raw() -> u32 {
228232
let r: u32;
229233
#[cfg(target_arch = "arm")]
@@ -255,7 +259,11 @@ pub trait SysRegWrite: SysReg {
255259
///
256260
/// You need to read the Architecture Reference Manual to verify that you are
257261
/// writing valid data here.
258-
#[inline]
262+
#[cfg_attr(not(feature = "check-asm"), inline)]
263+
#[cfg_attr(
264+
any(arm_architecture = "v4t", arm_architecture = "v5te"),
265+
instruction_set(arm::a32)
266+
)]
259267
unsafe fn write_raw(_value: u32) {
260268
#[cfg(target_arch = "arm")]
261269
unsafe {

aarch32-rt/src/arch_v4/abort.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ core::arch::global_asm!(
1111
// Saves state and calls a C-compatible handler like
1212
// `extern "C" fn _data_abort_handler(addr: usize);`
1313
.global _asm_default_data_abort_handler
14+
.arm
1415
.type _asm_default_data_abort_handler, %function
1516
_asm_default_data_abort_handler:
1617
// Subtract 8 from the stored LR, see p.1214 of the ARMv7-A architecture manual.
@@ -44,6 +45,7 @@ core::arch::global_asm!(
4445
// Saves state and calls a C-compatible handler like
4546
// `extern "C" fn _prefetch_abort_handler(addr: usize);`
4647
.global _asm_default_prefetch_abort_handler
48+
.arm
4749
.type _asm_default_prefetch_abort_handler, %function
4850
_asm_default_prefetch_abort_handler:
4951
// Subtract 4 from the stored LR, see p.1212 of the ARMv7-A architecture manual.

aarch32-rt/src/arch_v4/interrupt.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ core::arch::global_asm!(
1414
// Saves state and calls a C-compatible handler like
1515
// `extern "C" fn _irq_handler();`
1616
.global _asm_default_irq_handler
17+
.arm
1718
.type _asm_default_irq_handler, %function
1819
_asm_default_irq_handler:
1920
// make sure we jump back to the right place

aarch32-rt/src/arch_v4/svc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ core::arch::global_asm!(
1212
// Saves state and calls a C-compatible handler like
1313
// `extern "C" fn _svc_handler(svc: u32);`
1414
.global _asm_default_svc_handler
15+
.arm
1516
.type _asm_default_svc_handler, %function
1617
_asm_default_svc_handler:
1718
stmfd sp!, {{ r0, lr }}

0 commit comments

Comments
 (0)