use core::arch::global_asm;
macro_rules! cfg_global_asm {
{@inner, [$($x:tt)*], } => {
global_asm!{$($x)*}
};
(@inner, [$($x:tt)*], #[cfg($meta:meta)] { $($y:tt)* } $($rest:tt)*) => {
#[cfg($meta)]
cfg_global_asm!{@inner, [$($x)*], $($y)* $($rest)*}
#[cfg(not($meta))]
cfg_global_asm!{@inner, [$($x)*], $($rest)*}
};
(@inner, [$($x:tt)*], #[cfg($meta:meta)] $asm:literal, $($rest:tt)*) => {
#[cfg($meta)]
cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*}
#[cfg(not($meta))]
cfg_global_asm!{@inner, [$($x)*], $($rest)*}
};
{@inner, [$($x:tt)*], $asm:literal, $($rest:tt)*} => {
cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*}
};
{$($asms:tt)*} => {
cfg_global_asm!{@inner, [], $($asms)*}
};
}
riscv_rt_macros::llvm_arch_patch!();
cfg_global_asm!(
".section .init, \"ax\"
.global _start
_start:",
#[cfg(target_arch = "riscv32")]
"lui ra, %hi(_abs_start)
jr %lo(_abs_start)(ra)",
#[cfg(target_arch = "riscv64")]
".option push
.option norelax // to prevent an unsupported R_RISCV_ALIGN relocation from being generated
1:
auipc ra, %pcrel_hi(1f)
ld ra, %pcrel_lo(1b)(ra)
jr ra
.align 3
1:
.dword _abs_start
.option pop",
"
_abs_start:
.option norelax
.cfi_startproc
.cfi_undefined ra",
#[cfg(all(feature = "s-mode", not(feature = "no-xie-xip")))]
"csrw sie, 0
csrw sip, 0",
#[cfg(not(feature = "s-mode"))]
{
#[cfg(not(feature = "no-xie-xip"))]
"csrw mie, 0
csrw mip, 0",
#[cfg(not(feature = "no-mhartid"))]
"csrr a0, mhartid",
#[cfg(feature = "no-mhartid")]
"li a0, 0",
}
#[cfg(not(feature = "no-xtvec"))]
{
"la t0, _pre_init_trap",
#[cfg(feature = "s-mode")]
"csrw stvec, t0",
#[cfg(not(feature = "s-mode"))]
"csrw mtvec, t0",
}
#[cfg(not(feature = "single-hart"))]
"lui t0, %hi(_max_hart_id)
add t0, t0, %lo(_max_hart_id)
bgeu t0, a0, 1f
la t0, abort // If hart_id > _max_hart_id, jump to abort
jr t0
1:", #[cfg(any(feature = "pre-init", not(feature = "single-hart")))]
{
"mv s0, a0
mv s1, a1",
#[cfg(riscvi)]
"mv s2, a2",
#[cfg(not(riscvi))]
"mv a5, a2", }
".option push
.option norelax
la gp, __global_pointer$
.option pop",
#[cfg(not(feature = "single-hart"))]
{
"mv t2, a0
lui t1, %hi(_hart_stack_size)
add t1, t1, %lo(_hart_stack_size)",
#[cfg(riscvm)]
"mul t0, t2, t1",
#[cfg(not(riscvm))]
"mv t0, x0
beqz t2, 2f // skip if hart ID is 0
1:
add t0, t0, t1
addi t2, t2, -1
bnez t2, 1b
2: ",
}
"la t1, _stack_start",
#[cfg(not(feature = "single-hart"))]
"sub t1, t1, t0",
"andi sp, t1, -16",
#[cfg(not(feature = "single-hart"))]
"call _mp_hook
beqz a0, 4f",
#[cfg(feature = "pre-init")]
"call __pre_init",
"// Copy .data from flash to RAM
la t0, __sdata
la a3, __edata
la t1, __sidata
bgeu t0, a3, 2f
1: ",
#[cfg(target_arch = "riscv32")]
"lw t2, 0(t1)
addi t1, t1, 4
sw t2, 0(t0)
addi t0, t0, 4
bltu t0, a3, 1b",
#[cfg(target_arch = "riscv64")]
"ld t2, 0(t1)
addi t1, t1, 8
sd t2, 0(t0)
addi t0, t0, 8
bltu t0, a3, 1b",
"
2: // Zero out .bss
la t0, __sbss
la t2, __ebss
bgeu t0, t2, 4f
3: ",
#[cfg(target_arch = "riscv32")]
"sw zero, 0(t0)
addi t0, t0, 4
bltu t0, t2, 3b",
#[cfg(target_arch = "riscv64")]
"sd zero, 0(t0)
addi t0, t0, 8
bltu t0, t2, 3b",
"
4:",
#[cfg(any(riscvf, riscvd))]
{
"
li t0, 0x4000 // bit 14 is FS most significant bit
li t2, 0x2000 // bit 13 is FS least significant bit
",
#[cfg(feature = "s-mode")]
"csrrc x0, sstatus, t0
csrrs x0, sstatus, t2",
#[cfg(not(feature = "s-mode"))]
"csrrc x0, mstatus, t0
csrrs x0, mstatus, t2",
"fscsr x0",
}
#[cfg(any(feature = "pre-init", not(feature = "single-hart")))]
{ "mv a0, s0
mv a1, s1",
#[cfg(riscvi)]
"mv a2, s2",
#[cfg(not(riscvi))]
"mv a2, a5", }
"mv s0, sp
la t0, _start_rust
jr t0
.cfi_endproc",
#[cfg(not(feature = "single-hart"))]
".global _default_mp_hook
_default_mp_hook:
beqz a0, 2f // if hartid is 0, return true
1: wfi // Otherwise, wait for interrupt in a loop
j 1b
2: li a0, 1
ret",
);
riscv_rt_macros::default_start_trap!();
#[cfg(feature = "v-trap")]
riscv_rt_macros::vectored_interrupt_trap!();
#[rustfmt::skip]
global_asm!(
".section .text.abort
.balign 4
.global _default_abort
_default_abort: // make sure there is an abort symbol when linking
j _default_abort"
);