| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- use core::arch::naked_asm;
- use eonix_hal_traits::context::RawTaskContext;
- #[repr(C)]
- #[derive(Debug)]
- pub struct TaskContext {
- sx: [u64; 9],
- sp: u64,
- ra: u64,
- fp: u64,
- crmd: usize,
- }
- impl RawTaskContext for TaskContext {
- fn new() -> Self {
- Self::new()
- }
- fn set_program_counter(&mut self, pc: usize) {
- self.ra = pc as u64;
- }
- fn set_stack_pointer(&mut self, sp: usize) {
- self.sp = sp as u64;
- }
- fn is_interrupt_enabled(&self) -> bool {
- self.crmd & (1 << 2) != 0
- }
- fn set_interrupt_enabled(&mut self, is_enabled: bool) {
- if is_enabled {
- self.crmd = self.crmd | (1 << 2);
- } else {
- self.crmd = self.crmd & !(1 << 2);
- }
- }
- fn call(&mut self, func: unsafe extern "C" fn(usize) -> !, arg: usize) {
- self.sx[0] = func as u64;
- self.sx[1] = arg as u64;
- self.set_program_counter(Self::do_call as usize);
- }
- #[unsafe(naked)]
- unsafe extern "C" fn switch(from: &mut Self, to: &mut Self) {
- // Input arguments `from` and `to` will be in `a0` (x10) and `a1` (x11).
- naked_asm!(
- // Save current task's callee-saved registers to `from` context
- "st.d $s0, $a0, 0",
- "st.d $s1, $a0, 8",
- "st.d $s2, $a0, 16",
- "st.d $s3, $a0, 24",
- "st.d $s4, $a0, 32",
- "st.d $s5, $a0, 40",
- "st.d $s6, $a0, 48",
- "st.d $s7, $a0, 56",
- "st.d $s8, $a0, 64",
- "st.d $sp, $a0, 72",
- "st.d $ra, $a0, 80",
- "st.d $fp, $a0, 88",
- "csrrd $t0, 0", // CRMD
- "st.d $t0, $a0, 96",
- "",
- "ld.d $s0, $a1, 0",
- "ld.d $s1, $a1, 8",
- "ld.d $s2, $a1, 16",
- "ld.d $s3, $a1, 24",
- "ld.d $s4, $a1, 32",
- "ld.d $s5, $a1, 40",
- "ld.d $s6, $a1, 48",
- "ld.d $s7, $a1, 56",
- "ld.d $s8, $a1, 64",
- "ld.d $sp, $a1, 72",
- "ld.d $ra, $a1, 80",
- "ld.d $fp, $a1, 88",
- "ld.d $t0, $a1, 96",
- "csrwr $t0, 0", // CRMD
- "ret",
- );
- }
- }
- impl TaskContext {
- pub const fn new() -> Self {
- Self {
- sx: [0; 9],
- sp: 0,
- ra: 0,
- fp: 0,
- crmd: 1 << 4, // PG = 1
- }
- }
- #[unsafe(naked)]
- /// Maximum of 5 arguments supported.
- unsafe extern "C" fn do_call() -> ! {
- naked_asm!(
- "move $a0, $s1", // Args
- "move $a1, $s2",
- "move $a2, $s3",
- "move $a3, $s4",
- "move $a4, $s5",
- "move $fp, $zero", // Set frame pointer to 0.
- "move $ra, $zero",
- "jirl $zero, $s0, 0",
- );
- }
- }
|