#![no_std]

use cfg_if::cfg_if;

/// Returns an absolute address to the given symbol
#[macro_export]
macro_rules! absolute_address {
    ($sym:expr) => {{
        let mut _x: usize;
        #[cfg(target_arch = "aarch64")]
        unsafe {
            core::arch::asm!("ldr {0}, ={1}", out(reg) _x, sym $sym);
        }
        #[cfg(target_arch = "x86_64")]
        unsafe {
            core::arch::asm!("movabsq ${1}, {0}", out(reg) _x, sym $sym, options(att_syntax));
        }
        _x
    }};
}

cfg_if! {
    if #[cfg(any(test, not(target_os = "none")))] {
        extern crate kernel_arch_hosted as imp;
    } else if #[cfg(target_arch = "aarch64")] {
        extern crate kernel_arch_aarch64 as imp;
    } else if #[cfg(target_arch = "x86_64")] {
        extern crate kernel_arch_x86_64 as imp;
    } else if #[cfg(target_arch = "riscv64")] {
        extern crate kernel_arch_riscv64 as imp;
    } else {
        compile_error!("Unsupported architecture");
    }
}

pub use imp::{ArchitectureImpl, KernelTableManagerImpl, ProcessAddressSpaceImpl, TaskContextImpl};

pub use kernel_arch_interface::{guard, mem, sync, task, util, Architecture, KERNEL_VIRT_OFFSET};

pub type CpuImpl<S> = kernel_arch_interface::cpu::CpuImpl<ArchitectureImpl, S>;
pub type LocalCpuImpl<'a, S> = kernel_arch_interface::cpu::LocalCpuImpl<'a, ArchitectureImpl, S>;
