forked from M-Labs/zynq-rs
1
0
Fork 0
zynq-rs/src/cortex_a9/regs.rs

150 lines
3.6 KiB
Rust
Raw Normal View History

use crate::register_bit;
use crate::regs::{RegisterR, RegisterW, RegisterRW};
2019-05-05 20:56:23 +08:00
macro_rules! def_reg_r {
($name:tt, $type: ty, $asm_instr:tt) => {
impl RegisterR for $name {
type R = $type;
2019-05-05 20:56:23 +08:00
#[inline(always)]
fn read(&self) -> Self::R {
let mut value: u32;
2019-05-05 20:56:23 +08:00
unsafe { asm!($asm_instr : "=r" (value) ::: "volatile") }
value.into()
2019-05-05 20:56:23 +08:00
}
}
}
}
macro_rules! def_reg_w {
2019-05-05 20:56:23 +08:00
($name:ty, $type:ty, $asm_instr:tt) => {
impl RegisterW for $name {
type W = $type;
2019-05-05 20:56:23 +08:00
#[inline(always)]
fn write(&mut self, value: Self::W) {
let value: u32 = value.into();
2019-05-05 20:56:23 +08:00
unsafe { asm!($asm_instr :: "r" (value) :: "volatile") }
}
fn zeroed() -> Self::W {
0u32.into()
}
}
}
}
macro_rules! wrap_reg {
($mod_name: ident) => {
pub mod $mod_name {
pub struct Read {
pub inner: u32,
}
impl From<u32> for Read {
fn from(value: u32) -> Self {
Read { inner: value }
}
}
pub struct Write {
pub inner: u32,
}
impl From<u32> for Write {
fn from(value: u32) -> Self {
Write { inner: value }
}
}
impl Into<u32> for Write {
fn into(self) -> u32 {
self.inner
}
}
2019-05-05 20:56:23 +08:00
}
}
}
2019-05-27 07:44:24 +08:00
/// Stack Pointer
2019-05-05 20:56:23 +08:00
pub struct SP;
def_reg_r!(SP, u32, "mov $0, sp");
def_reg_w!(SP, u32, "mov sp, $0");
2019-05-05 20:56:23 +08:00
2019-05-27 07:44:24 +08:00
/// Link register (function call return address)
pub struct LR;
def_reg_r!(LR, u32, "mov $0, lr");
def_reg_w!(LR, u32, "mov lr, $0");
2019-05-27 07:44:24 +08:00
2019-05-05 20:56:23 +08:00
pub struct MPIDR;
def_reg_r!(MPIDR, u32, "mrc p15, 0, $0, c0, c0, 5");
2019-05-24 01:05:06 +08:00
pub struct DFAR;
def_reg_r!(DFAR, u32, "mrc p15, 0, $0, c6, c0, 0");
pub struct DFSR;
def_reg_r!(DFSR, u32, "mrc p15, 0, $0, c5, c0, 0");
pub struct SCTLR;
wrap_reg!(sctlr);
def_reg_r!(SCTLR, sctlr::Read, "mrc p15, 0, $0, c1, c0, 0");
def_reg_w!(SCTLR, sctlr::Write, "mcr p15, 0, $0, c1, c0, 0");
register_bit!(sctlr,
/// Enables MMU
m, 0);
register_bit!(sctlr,
/// Strict Alignment Checking
a, 1);
register_bit!(sctlr,
/// Data Caching
c, 2);
register_bit!(sctlr, sw, 10);
register_bit!(sctlr, z, 11);
register_bit!(sctlr, i, 12);
register_bit!(sctlr, v, 13);
register_bit!(sctlr, ha, 17);
register_bit!(sctlr, ee, 25);
register_bit!(sctlr,
/// (read-only)
nmfi, 27);
register_bit!(sctlr, unaligned, 22);
register_bit!(sctlr,
/// TEX Remap Enable
tre, 28);
register_bit!(sctlr,
/// Access Flag Enable
afe, 29);
register_bit!(sctlr,
/// Thumb Exception Enable
te, 30);
2019-05-24 01:05:06 +08:00
/// Invalidate TLBs
#[inline(always)]
2019-05-24 01:05:06 +08:00
pub fn tlbiall() {
unsafe {
asm!("mcr p15, 0, $0, c8, c7, 0" :: "r" (0) :: "volatile");
}
}
/// Invalidate I-Cache
#[inline(always)]
2019-05-24 01:05:06 +08:00
pub fn iciallu() {
unsafe {
asm!("mcr p15, 0, $0, c7, c5, 0" :: "r" (0) :: "volatile");
}
}
/// Invalidate Branch Predictor Array
#[inline(always)]
2019-05-24 01:05:06 +08:00
pub fn bpiall() {
unsafe {
asm!("mcr p15, 0, $0, c7, c5, 6" :: "r" (0) :: "volatile");
}
}
/// Invalidate D-Cache
#[inline(always)]
2019-05-24 01:05:06 +08:00
pub fn dccisw() {
// TODO: $0 is r11 at what value?
unsafe {
asm!("mcr p15, 0, $0, c7, c5, 6" :: "r" (0) :: "volatile");
}
}