#pragma once
#include <rt/arch/coprocessor.h>
#include <rt/arch/cpsr.h>
#include <rt/arch/mode.h>
#include <vic.h>
#define BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
struct context
{
#if RT_ARM_FP
uint32_t fpexc;
#endif
uint32_t r4, r5, r6, r7, r8, r9, r10, r11;
uint32_t r0, r1, r2, r3, r12, lr, pc, psr;
};
static void profile_context_init(struct context *ctx)
{
ctx->psr = MODE_SYS | (BIG_ENDIAN ? CPSR_E : 0) |
((((uintptr_t)rt_task_entry & 1) != 0) ? CPSR_T : 0);
#if RT_ARM_FP
ctx->fpexc = 0;
#endif }
void rt_task_drop_privilege(void)
{
__asm__("dsb; cps %0" : : "i"(MODE_USR) : "memory");
}
static inline uint32_t cpsr_mode(void)
{
uint32_t cpsr;
__asm__ __volatile__("mrs %0, cpsr" : "=r"(cpsr));
return cpsr & MODE_MASK;
}
static inline uint32_t spsr_mode(void)
{
uint32_t spsr;
__asm__ __volatile__("mrs %0, spsr" : "=r"(spsr));
return spsr & MODE_MASK;
}
static inline bool mode_is_exception(uint32_t mode)
{
return (MODE_USR < mode) && (mode < MODE_SYS);
}
bool rt_interrupt_is_active(void)
{
return mode_is_exception(cpsr_mode());
}
void rt_syscall_0(enum rt_syscall syscall)
{
register enum rt_syscall r0 __asm__("r0") = syscall;
__asm__ __volatile__("svc 0"
: "+r"(r0)
:
: "r1", "r2", "r3", "r12", "lr", "memory");
}
void rt_syscall_1(enum rt_syscall syscall, uintptr_t arg0)
{
register enum rt_syscall r0 __asm__("r0") = syscall;
register uintptr_t r1 __asm__("r1") = arg0;
__asm__ __volatile__("svc 0"
: "+r"(r0), "+r"(r1)
:
: "r2", "r3", "r12", "lr", "memory");
}
void rt_syscall_2(enum rt_syscall syscall, uintptr_t arg0, uintptr_t arg1)
{
register enum rt_syscall r0 __asm__("r0") = syscall;
register uintptr_t r1 __asm__("r1") = arg0;
register uintptr_t r2 __asm__("r2") = arg1;
__asm__ __volatile__("svc 0"
: "+r"(r0), "+r"(r1), "+r"(r2)
:
: "r3", "r12", "lr", "memory");
}
void rt_syscall_3(enum rt_syscall syscall, uintptr_t arg0, uintptr_t arg1,
uintptr_t arg2)
{
register enum rt_syscall r0 __asm__("r0") = syscall;
register uintptr_t r1 __asm__("r1") = arg0;
register uintptr_t r2 __asm__("r2") = arg1;
register uintptr_t r3 __asm__("r3") = arg2;
__asm__ __volatile__("svc 0"
: "+r"(r0), "+r"(r1), "+r"(r2), "+r"(r3)
:
: "r12", "lr", "memory");
}
void rt_syscall_pend(void)
{
vic_syscall_pend();
}
__attribute__((weak)) void rt_cycle_init(void)
{
#if RT_CYCLE_ENABLE
pmcr_oreq(PMCR_E | PMCR_C);
pmcntenset_oreq(PMCNTEN_C);
pmuserenr_set(PMUSERENR_EN);
__asm__("isb" :::);
#endif
}
__attribute__((weak)) uint32_t rt_cycle(void)
{
#if RT_CYCLE_ENABLE
return pmccntr();
#else
return 0;
#endif
}
void rt_tls_set(void *tls)
{
tpidruro_set((uintptr_t)tls);
}