原始版本
This commit is contained in:
9
RT_Thread/libcpu/mips/common/Kconfig
Normal file
9
RT_Thread/libcpu/mips/common/Kconfig
Normal file
@ -0,0 +1,9 @@
|
||||
menu "RT-Thread MIPS CPU"
|
||||
|
||||
config RT_USING_FPU
|
||||
bool "Using Float Point Unit"
|
||||
default n
|
||||
help
|
||||
Using Float Point Unit in code.
|
||||
|
||||
endmenu
|
||||
13
RT_Thread/libcpu/mips/common/SConscript
Normal file
13
RT_Thread/libcpu/mips/common/SConscript
Normal file
@ -0,0 +1,13 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
306
RT_Thread/libcpu/mips/common/asm.h
Normal file
306
RT_Thread/libcpu/mips/common/asm.h
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Assembly Macros For MIPS
|
||||
*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __ASM_H__
|
||||
#define __ASM_H__
|
||||
|
||||
#include <rtconfig.h>
|
||||
/*
|
||||
* LEAF - declare leaf routine
|
||||
*/
|
||||
#define LEAF(symbol) \
|
||||
.globl symbol; \
|
||||
.align 2; \
|
||||
.type symbol,@function; \
|
||||
.ent symbol,0; \
|
||||
symbol: .frame sp,0,ra
|
||||
|
||||
/*
|
||||
* NESTED - declare nested routine entry point
|
||||
*/
|
||||
#define NESTED(symbol, framesize, rpc) \
|
||||
.globl symbol; \
|
||||
.align 2; \
|
||||
.type symbol,@function; \
|
||||
.ent symbol,0; \
|
||||
symbol: .frame sp, framesize, rpc
|
||||
|
||||
/*
|
||||
* END - mark end of function
|
||||
*/
|
||||
#define END(function) \
|
||||
.end function; \
|
||||
.size function,.-function
|
||||
|
||||
/*
|
||||
* EXPORT - export definition of symbol
|
||||
*/
|
||||
#define EXPORT(symbol) \
|
||||
.globl symbol; \
|
||||
symbol:
|
||||
|
||||
/*
|
||||
* FEXPORT - export definition of a function symbol
|
||||
*/
|
||||
#define FEXPORT(symbol) \
|
||||
.globl symbol; \
|
||||
.type symbol,@function; \
|
||||
symbol:
|
||||
|
||||
/*
|
||||
* Global data declaration with size.
|
||||
*/
|
||||
#define EXPORTS(name,sz) \
|
||||
.globl name; \
|
||||
.type name,@object; \
|
||||
.size name,sz; \
|
||||
name:
|
||||
|
||||
/*
|
||||
* Weak data declaration with size.
|
||||
*/
|
||||
#define WEXPORT(name,sz) \
|
||||
.weakext name; \
|
||||
.type name,@object; \
|
||||
.size name,sz; \
|
||||
name:
|
||||
|
||||
/*
|
||||
* Global data reference with size.
|
||||
*/
|
||||
#define IMPORT(name, size) \
|
||||
.extern name,size
|
||||
|
||||
/*
|
||||
* Global zeroed data.
|
||||
*/
|
||||
#define BSS(name,size) \
|
||||
.type name,@object; \
|
||||
.comm name,size
|
||||
|
||||
/*
|
||||
* Local zeroed data.
|
||||
*/
|
||||
#define LBSS(name,size) \
|
||||
.lcomm name,size
|
||||
|
||||
|
||||
/*
|
||||
* ABS - export absolute symbol
|
||||
*/
|
||||
#define ABS(symbol,value) \
|
||||
.globl symbol; \
|
||||
symbol = value
|
||||
|
||||
|
||||
#define TEXT(msg) \
|
||||
.pushsection .data; \
|
||||
8: .asciiz msg; \
|
||||
.popsection;
|
||||
|
||||
|
||||
#define ENTRY(name) \
|
||||
.globl name; \
|
||||
.align 2; \
|
||||
.ent name,0; \
|
||||
name##:
|
||||
|
||||
/*
|
||||
* Macros to handle different pointer/register sizes for 32/64-bit code
|
||||
*/
|
||||
#if defined ARCH_MIPS64
|
||||
/*
|
||||
* Size of a register
|
||||
*/
|
||||
#define SZREG 8
|
||||
|
||||
/*
|
||||
* Use the following macros in assemblercode to load/store registers,
|
||||
* pointers etc.
|
||||
*/
|
||||
#define REG_S sd
|
||||
#define REG_L ld
|
||||
#define REG_SUBU dsubu
|
||||
#define REG_ADDU daddu
|
||||
|
||||
/*
|
||||
* How to add/sub/load/store/shift C int variables.
|
||||
*/
|
||||
#define INT_ADD dadd
|
||||
#define INT_ADDU daddu
|
||||
#define INT_ADDI daddi
|
||||
#define INT_ADDIU daddiu
|
||||
#define INT_SUB dsub
|
||||
#define INT_SUBU dsubu
|
||||
#define INT_L ld
|
||||
#define INT_S sd
|
||||
#define INT_SLL dsll
|
||||
#define INT_SLLV dsllv
|
||||
#define INT_SRL dsrl
|
||||
#define INT_SRLV dsrlv
|
||||
#define INT_SRA dsra
|
||||
#define INT_SRAV dsrav
|
||||
|
||||
/*
|
||||
* Use the following macros in assemblercode to load/store registers,
|
||||
* pointers etc.
|
||||
*/
|
||||
#define LONG_ADD dadd
|
||||
#define LONG_ADDU daddu
|
||||
#define LONG_ADDI daddi
|
||||
#define LONG_ADDIU daddiu
|
||||
#define LONG_SUB dsub
|
||||
#define LONG_SUBU dsubu
|
||||
#define LONG_L ld
|
||||
#define LONG_S sd
|
||||
#define LONG_SP sdp
|
||||
#define LONG_SLL dsll
|
||||
#define LONG_SLLV dsllv
|
||||
#define LONG_SRL dsrl
|
||||
#define LONG_SRLV dsrlv
|
||||
#define LONG_SRA dsra
|
||||
#define LONG_SRAV dsrav
|
||||
|
||||
#define LONG .dword
|
||||
#define LONGSIZE 8
|
||||
#define LONGMASK 7
|
||||
#define LONGLOG 3
|
||||
|
||||
/*
|
||||
* How to add/sub/load/store/shift pointers.
|
||||
*/
|
||||
#define PTR_ADD dadd
|
||||
#define PTR_ADDU daddu
|
||||
#define PTR_ADDI daddi
|
||||
#define PTR_ADDIU daddiu
|
||||
#define PTR_SUB dsub
|
||||
#define PTR_SUBU dsubu
|
||||
#define PTR_L ld
|
||||
#define PTR_S sd
|
||||
#define PTR_LA dla
|
||||
#define PTR_LI dli
|
||||
#define PTR_SLL dsll
|
||||
#define PTR_SLLV dsllv
|
||||
#define PTR_SRL dsrl
|
||||
#define PTR_SRLV dsrlv
|
||||
#define PTR_SRA dsra
|
||||
#define PTR_SRAV dsrav
|
||||
|
||||
#define PTR_SCALESHIFT 3
|
||||
|
||||
#define PTR .dword
|
||||
#define PTRSIZE 8
|
||||
#define PTRLOG 3
|
||||
|
||||
#define MFC0 dmfc0
|
||||
#define MTC0 dmtc0
|
||||
|
||||
#else
|
||||
/*
|
||||
* Size of a register
|
||||
*/
|
||||
#define SZREG 4
|
||||
|
||||
|
||||
/*
|
||||
* Use the following macros in assemblercode to load/store registers,
|
||||
* pointers etc.
|
||||
*/
|
||||
#define REG_S sw
|
||||
#define REG_L lw
|
||||
#define REG_SUBU subu
|
||||
#define REG_ADDU addu
|
||||
|
||||
|
||||
/*
|
||||
* How to add/sub/load/store/shift C int variables.
|
||||
*/
|
||||
#define INT_ADD add
|
||||
#define INT_ADDU addu
|
||||
#define INT_ADDI addi
|
||||
#define INT_ADDIU addiu
|
||||
#define INT_SUB sub
|
||||
#define INT_SUBU subu
|
||||
#define INT_L lw
|
||||
#define INT_S sw
|
||||
#define INT_SLL sll
|
||||
#define INT_SLLV sllv
|
||||
#define INT_SRL srl
|
||||
#define INT_SRLV srlv
|
||||
#define INT_SRA sra
|
||||
#define INT_SRAV srav
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* How to add/sub/load/store/shift C long variables.
|
||||
*/
|
||||
#define LONG_ADD add
|
||||
#define LONG_ADDU addu
|
||||
#define LONG_ADDI addi
|
||||
#define LONG_ADDIU addiu
|
||||
#define LONG_SUB sub
|
||||
#define LONG_SUBU subu
|
||||
#define LONG_L lw
|
||||
#define LONG_S sw
|
||||
#define LONG_SLL sll
|
||||
#define LONG_SLLV sllv
|
||||
#define LONG_SRL srl
|
||||
#define LONG_SRLV srlv
|
||||
#define LONG_SRA sra
|
||||
#define LONG_SRAV srav
|
||||
|
||||
#define LONG .word
|
||||
#define LONGSIZE 4
|
||||
#define LONGMASK 3
|
||||
#define LONGLOG 2
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* How to add/sub/load/store/shift pointers.
|
||||
*/
|
||||
#define PTR_ADD add
|
||||
#define PTR_ADDU addu
|
||||
#define PTR_ADDI addi
|
||||
#define PTR_ADDIU addiu
|
||||
#define PTR_SUB sub
|
||||
#define PTR_SUBU subu
|
||||
#define PTR_L lw
|
||||
#define PTR_S sw
|
||||
#define PTR_LA la
|
||||
#define PTR_SLL sll
|
||||
#define PTR_SLLV sllv
|
||||
#define PTR_SRL srl
|
||||
#define PTR_SRLV srlv
|
||||
#define PTR_SRA sra
|
||||
#define PTR_SRAV srav
|
||||
|
||||
#define PTR_SCALESHIFT 2
|
||||
|
||||
#define PTR .word
|
||||
#define PTRSIZE 4
|
||||
#define PTRLOG 2
|
||||
|
||||
|
||||
/*
|
||||
* Some cp0 registers were extended to 64bit for MIPS III.
|
||||
*/
|
||||
#define MFC0 mfc0
|
||||
#define MTC0 mtc0
|
||||
|
||||
#endif
|
||||
|
||||
#define SSNOP sll zero, zero, 1
|
||||
|
||||
#endif /* end of __ASM_H__ */
|
||||
124
RT_Thread/libcpu/mips/common/context_gcc.S
Normal file
124
RT_Thread/libcpu/mips/common/context_gcc.S
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
* 2020-07-26 lizhirui Fixed some problems
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#define __ASSEMBLY__
|
||||
#endif
|
||||
|
||||
#include "mips_regs.h"
|
||||
#include "stackframe.h"
|
||||
|
||||
.section ".text", "ax"
|
||||
.set noreorder
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)
|
||||
* a0 --> from
|
||||
* a1 --> to
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
MTC0 ra, CP0_EPC
|
||||
SAVE_ALL
|
||||
|
||||
REG_S sp, 0(a0) /* store sp in preempted tasks TCB */
|
||||
REG_L sp, 0(a1) /* get new task stack pointer */
|
||||
|
||||
RESTORE_ALL_AND_RET
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_to(rt_uint32 to)/*
|
||||
* a0 --> to
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
REG_L sp, 0(a0) /* get new task stack pointer */
|
||||
RESTORE_ALL_AND_RET
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/*
|
||||
*/
|
||||
.globl rt_thread_switch_interrupt_flag
|
||||
.globl rt_interrupt_from_thread
|
||||
.globl rt_interrupt_to_thread
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
PTR_LA t0, rt_thread_switch_interrupt_flag
|
||||
REG_L t1, 0(t0)
|
||||
nop
|
||||
bnez t1, _reswitch
|
||||
nop
|
||||
li t1, 0x01 /* set rt_thread_switch_interrupt_flag to 1 */
|
||||
LONG_S t1, 0(t0)
|
||||
PTR_LA t0, rt_interrupt_from_thread /* set rt_interrupt_from_thread */
|
||||
LONG_S a0, 0(t0)
|
||||
_reswitch:
|
||||
PTR_LA t0, rt_interrupt_to_thread /* set rt_interrupt_to_thread */
|
||||
LONG_S a1, 0(t0)
|
||||
jr ra
|
||||
nop
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt_do(rt_base_t flag)
|
||||
*/
|
||||
.globl rt_interrupt_enter
|
||||
.globl rt_interrupt_leave
|
||||
.globl rt_general_exc_dispatch
|
||||
.globl mips_irq_handle
|
||||
mips_irq_handle:
|
||||
SAVE_ALL
|
||||
|
||||
/* let k0 keep the current context sp */
|
||||
move k0, sp
|
||||
/* switch to kernel stack */
|
||||
PTR_LA sp, _system_stack
|
||||
|
||||
jal rt_interrupt_enter
|
||||
nop
|
||||
/* Get Old SP from k0 as paremeter in a0 */
|
||||
move a0, k0
|
||||
jal rt_general_exc_dispatch
|
||||
nop
|
||||
jal rt_interrupt_leave
|
||||
nop
|
||||
|
||||
/* switch sp back to thread context */
|
||||
move sp, k0
|
||||
|
||||
/*
|
||||
* if rt_thread_switch_interrupt_flag set, jump to
|
||||
* rt_hw_context_switch_interrupt_do and do not return
|
||||
*/
|
||||
PTR_LA k0, rt_thread_switch_interrupt_flag
|
||||
LONG_L k1, 0(k0)
|
||||
beqz k1, spurious_interrupt
|
||||
nop
|
||||
LONG_S zero, 0(k0) /* clear flag */
|
||||
nop
|
||||
|
||||
/*
|
||||
* switch to the new thread
|
||||
*/
|
||||
PTR_LA k0, rt_interrupt_from_thread
|
||||
LONG_L k1, 0(k0)
|
||||
nop
|
||||
LONG_S sp, 0(k1) /* store sp in preempted task TCB */
|
||||
|
||||
PTR_LA k0, rt_interrupt_to_thread
|
||||
LONG_L k1, 0(k0)
|
||||
nop
|
||||
LONG_L sp, 0(k1) /* get new task stack pointer */
|
||||
j spurious_interrupt
|
||||
nop
|
||||
|
||||
spurious_interrupt:
|
||||
RESTORE_ALL_AND_RET
|
||||
.set reorder
|
||||
64
RT_Thread/libcpu/mips/common/entry_gcc.S
Normal file
64
RT_Thread/libcpu/mips/common/entry_gcc.S
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#define __ASSEMBLY__
|
||||
#endif
|
||||
|
||||
#include <mips.h>
|
||||
#include <rtconfig.h>
|
||||
|
||||
#include "asm.h"
|
||||
#include <rtconfig.h>
|
||||
|
||||
.section ".start", "ax"
|
||||
.set noreorder
|
||||
|
||||
/* the program entry */
|
||||
.globl _rtthread_entry
|
||||
_rtthread_entry:
|
||||
#ifndef RT_USING_SELF_BOOT
|
||||
.globl _start
|
||||
_start:
|
||||
#endif
|
||||
PTR_LA ra, _rtthread_entry
|
||||
|
||||
/* disable interrupt */
|
||||
MTC0 zero, CP0_CAUSE
|
||||
MTC0 zero, CP0_STATUS # Set CPU to disable interrupt.
|
||||
ehb
|
||||
|
||||
#ifdef ARCH_MIPS64
|
||||
dli t0, ST0_KX
|
||||
MTC0 t0, CP0_STATUS
|
||||
#endif
|
||||
|
||||
/* setup stack pointer */
|
||||
PTR_LA sp, _system_stack
|
||||
PTR_LA gp, _gp
|
||||
|
||||
bal rt_cpu_early_init
|
||||
nop
|
||||
|
||||
/* clear bss */
|
||||
PTR_LA t0, __bss_start
|
||||
PTR_LA t1, __bss_end
|
||||
|
||||
_clr_bss_loop:
|
||||
sw zero, 0(t0)
|
||||
bne t1, t0, _clr_bss_loop
|
||||
addu t0, 4
|
||||
/* jump to RT-Thread RTOS */
|
||||
jal rtthread_startup
|
||||
nop
|
||||
|
||||
/* restart, never die */
|
||||
j _start
|
||||
nop
|
||||
212
RT_Thread/libcpu/mips/common/exception.c
Normal file
212
RT_Thread/libcpu/mips/common/exception.c
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include "exception.h"
|
||||
#include "mips_regs.h"
|
||||
|
||||
/**
|
||||
* @addtogroup MIPS
|
||||
*/
|
||||
|
||||
/*@{*/
|
||||
|
||||
extern rt_ubase_t __ebase_entry;
|
||||
rt_ubase_t rt_interrupt_from_thread;
|
||||
rt_ubase_t rt_interrupt_to_thread;
|
||||
rt_ubase_t rt_thread_switch_interrupt_flag;
|
||||
|
||||
const char *exception_name[] = {
|
||||
"Interrupt",
|
||||
"(X)TLB Modify Exception",
|
||||
"(X)TLB Read/Fetch Exception",
|
||||
"(X)TLB Write Exception",
|
||||
"Address Read/Fetch Exception",
|
||||
"Address Write Exception",
|
||||
"",
|
||||
"",
|
||||
"Syscall",
|
||||
"Breakpoint",
|
||||
"Reversed Instruction Exception",
|
||||
"Coprocessor Unit Invalid",
|
||||
"Overflow",
|
||||
"Trap",
|
||||
"FPU Exception in Vector Instruction",
|
||||
"FPU Exception",
|
||||
"Loongson Custom Exception",
|
||||
"",
|
||||
"",
|
||||
"(X)TLB Read Denied Exception",
|
||||
"(X)TLB Execute Denied Exception",
|
||||
"Vector Module Disabled Exception",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"Cache Error Exception",
|
||||
""
|
||||
};
|
||||
|
||||
rt_base_t rt_hw_interrupt_disable(void)
|
||||
{
|
||||
register rt_base_t status = read_c0_status();
|
||||
clear_c0_status(ST0_IE);
|
||||
return status;
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_enable(rt_base_t level)
|
||||
{
|
||||
write_c0_status(level);
|
||||
}
|
||||
|
||||
/**
|
||||
* exception handle table
|
||||
*/
|
||||
#define RT_EXCEPTION_MAX 32
|
||||
exception_func_t sys_exception_handlers[RT_EXCEPTION_MAX];
|
||||
|
||||
/**
|
||||
* setup the exception handle
|
||||
*/
|
||||
exception_func_t rt_set_except_vector(int n, exception_func_t func)
|
||||
{
|
||||
exception_func_t old_handler;
|
||||
|
||||
if ((n < 0) || (n >= RT_EXCEPTION_MAX) || (!func))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
old_handler = sys_exception_handlers[n];
|
||||
sys_exception_handlers[n] = func;
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
void mips_dump_regs(struct pt_regs *regs)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 32 / 4; i++)
|
||||
{
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
int reg = 4 * i + j;
|
||||
rt_kprintf("%d: 0x%08x, ", reg, regs->regs[reg]);
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void tlb_refill_handler(void)
|
||||
{
|
||||
rt_kprintf("TLB-Miss Happens, EPC: 0x%08x\n", read_c0_epc());
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
void cache_error_handler(void)
|
||||
{
|
||||
rt_kprintf("Cache Exception Happens, EPC: 0x%08x\n", read_c0_epc());
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
static void unhandled_exception_handle(struct pt_regs *regs)
|
||||
{
|
||||
rt_kprintf("Unknown Exception, EPC: 0x%p, CAUSE: 0x%08x\n", read_c0_epc(), read_c0_cause());
|
||||
rt_kprintf("Exception Name:%s\n",exception_name[(read_c0_cause() >> 2) & 0x1f]);
|
||||
#ifdef SOC_LS2K1000
|
||||
rt_kprintf("ExeCode = 0x%08x,BadAddr = 0x%p\n",(read_c0_cause() >> 2) & 0x1f,mmu_tlb_get_bad_vaddr());
|
||||
#else
|
||||
rt_kprintf("ExeCode = 0x%08x\n",(read_c0_cause() >> 2) & 0x1f);
|
||||
#endif
|
||||
rt_kprintf("ST0: 0x%08x ",regs->cp0_status);
|
||||
rt_kprintf("ErrorPC: 0x%p\n",read_c0_errorepc());
|
||||
mips_dump_regs(regs);
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
static void install_default_exception_handler(void)
|
||||
{
|
||||
rt_int32_t i;
|
||||
|
||||
for (i = 0; i < RT_EXCEPTION_MAX; i++)
|
||||
sys_exception_handlers[i] =
|
||||
(exception_func_t)unhandled_exception_handle;
|
||||
}
|
||||
|
||||
int rt_hw_exception_init(void)
|
||||
{
|
||||
rt_ubase_t ebase = (rt_ubase_t)&__ebase_entry;
|
||||
#ifdef ARCH_MIPS64
|
||||
ebase |= 0xffffffff00000000;
|
||||
#endif
|
||||
write_c0_ebase(ebase);
|
||||
clear_c0_status(ST0_BEV | ST0_ERL | ST0_EXL);
|
||||
clear_c0_status(ST0_IM | ST0_IE);
|
||||
set_c0_status(ST0_CU0);
|
||||
/* install the default exception handler */
|
||||
install_default_exception_handler();
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
void rt_general_exc_dispatch(struct pt_regs *regs)
|
||||
{
|
||||
rt_ubase_t cause, exccode;
|
||||
cause = read_c0_cause();
|
||||
exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE;
|
||||
|
||||
if (exccode == 0)
|
||||
{
|
||||
rt_ubase_t status, pending;
|
||||
|
||||
status = read_c0_status();
|
||||
pending = (cause & CAUSEF_IP) & (status & ST0_IM);
|
||||
if (pending & CAUSEF_IP0)
|
||||
rt_do_mips_cpu_irq(0);
|
||||
if (pending & CAUSEF_IP1)
|
||||
rt_do_mips_cpu_irq(1);
|
||||
if (pending & CAUSEF_IP2)
|
||||
rt_do_mips_cpu_irq(2);
|
||||
if (pending & CAUSEF_IP3)
|
||||
rt_do_mips_cpu_irq(3);
|
||||
if (pending & CAUSEF_IP4)
|
||||
rt_do_mips_cpu_irq(4);
|
||||
if (pending & CAUSEF_IP5)
|
||||
rt_do_mips_cpu_irq(5);
|
||||
if (pending & CAUSEF_IP6)
|
||||
rt_do_mips_cpu_irq(6);
|
||||
if (pending & CAUSEF_IP7)
|
||||
rt_do_mips_cpu_irq(7);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sys_exception_handlers[exccode])
|
||||
sys_exception_handlers[exccode](regs);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mask means disable the interrupt */
|
||||
void mips_mask_cpu_irq(rt_uint32_t irq)
|
||||
{
|
||||
clear_c0_status(1 << (STATUSB_IP0 + irq));
|
||||
}
|
||||
|
||||
/* Unmask means enable the interrupt */
|
||||
void mips_unmask_cpu_irq(rt_uint32_t irq)
|
||||
{
|
||||
set_c0_status(1 << (STATUSB_IP0 + irq));
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
28
RT_Thread/libcpu/mips/common/exception.h
Normal file
28
RT_Thread/libcpu/mips/common/exception.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
*/
|
||||
|
||||
#ifndef __EXCEPTION_H__
|
||||
#define __EXCEPTION_H__
|
||||
|
||||
#include "ptrace.h"
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef void (* exception_func_t)(struct pt_regs *regs);
|
||||
|
||||
extern int rt_hw_exception_init(void);
|
||||
extern exception_func_t sys_exception_handlers[];
|
||||
extern void rt_do_mips_cpu_irq(rt_uint32_t ip);
|
||||
exception_func_t rt_set_except_vector(int n, exception_func_t func);
|
||||
extern void mips_mask_cpu_irq(rt_uint32_t irq);
|
||||
extern void mips_unmask_cpu_irq(rt_uint32_t irq);
|
||||
#endif
|
||||
|
||||
#endif /* end of __EXCEPTION_H__ */
|
||||
70
RT_Thread/libcpu/mips/common/exception_gcc.S
Normal file
70
RT_Thread/libcpu/mips/common/exception_gcc.S
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
* 2020-07-26 lizhirui Add xtlb exception entry
|
||||
*/
|
||||
#ifndef __ASSEMBLY__
|
||||
#define __ASSEMBLY__
|
||||
#endif
|
||||
|
||||
#include <mips.h>
|
||||
|
||||
.section ".exc_vectors", "ax"
|
||||
.extern tlb_refill_handler
|
||||
.extern cache_error_handler
|
||||
.extern mips_irq_handle
|
||||
|
||||
/* 0x0 - TLB refill handler */
|
||||
.global tlb_refill_exception
|
||||
.type tlb_refill_exception,@function
|
||||
ebase_start:
|
||||
tlb_refill_exception:
|
||||
b _general_exception_handler
|
||||
nop
|
||||
|
||||
/* 0x080 - XTLB refill handler */
|
||||
.org ebase_start + 0x080
|
||||
b _general_exception_handler
|
||||
nop
|
||||
|
||||
/* 0x100 - Cache error handler */
|
||||
.org ebase_start + 0x100
|
||||
j cache_error_handler
|
||||
nop
|
||||
|
||||
/* 0x180 - Exception/Interrupt handler */
|
||||
.global general_exception
|
||||
.type general_exception,@function
|
||||
.org ebase_start + 0x180
|
||||
general_exception:
|
||||
b _general_exception_handler
|
||||
nop
|
||||
|
||||
/* 0x200 - Special Exception Interrupt handler (when IV is set in CP0_CAUSE) */
|
||||
.global irq_exception
|
||||
.type irq_exception,@function
|
||||
.org ebase_start + 0x200
|
||||
irq_exception:
|
||||
b _general_exception_handler
|
||||
nop
|
||||
|
||||
/* general exception handler */
|
||||
_general_exception_handler:
|
||||
.set noreorder
|
||||
PTR_LA k0, mips_irq_handle
|
||||
jr k0
|
||||
nop
|
||||
.set reorder
|
||||
|
||||
/* interrupt handler */
|
||||
_irq_handler:
|
||||
.set noreorder
|
||||
PTR_LA k0, mips_irq_handle
|
||||
jr k0
|
||||
nop
|
||||
.set reorder
|
||||
23
RT_Thread/libcpu/mips/common/mips.h
Normal file
23
RT_Thread/libcpu/mips/common/mips.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2016-09-07 Urey first version
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_MIPS_H_
|
||||
#define _COMMON_MIPS_H_
|
||||
|
||||
#include "mips_cfg.h"
|
||||
#include "ptrace.h"
|
||||
#include "mips_types.h"
|
||||
#include "asm.h"
|
||||
#include "mips_regs.h"
|
||||
#include "mips_addrspace.h"
|
||||
#include "mips_cache.h"
|
||||
#include "exception.h"
|
||||
|
||||
#endif /* _COMMON_MIPS_H_ */
|
||||
49
RT_Thread/libcpu/mips/common/mips.inc
Normal file
49
RT_Thread/libcpu/mips/common/mips.inc
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-05-17 sangwei first version
|
||||
*/
|
||||
|
||||
#ifndef __MIPS_INC__
|
||||
#define __MIPS_INC__
|
||||
|
||||
#define zero $0 /* wired zero */
|
||||
// #define at $1
|
||||
#define v0 $2 /* return value */
|
||||
#define v1 $3
|
||||
#define a0 $4 /* argument registers */
|
||||
#define a1 $5
|
||||
#define a2 $6
|
||||
#define a3 $7
|
||||
#define t0 $8 /* caller saved */
|
||||
#define t1 $9
|
||||
#define t2 $10
|
||||
#define t3 $11
|
||||
#define t4 $12
|
||||
#define t5 $13
|
||||
#define t6 $14
|
||||
#define t7 $15
|
||||
#define s0 $16 /* callee saved */
|
||||
#define s1 $17
|
||||
#define s2 $18
|
||||
#define s3 $19
|
||||
#define s4 $20
|
||||
#define s5 $21
|
||||
#define s6 $22
|
||||
#define s7 $23
|
||||
#define t8 $24 /* caller saved */
|
||||
#define t9 $25
|
||||
#define jp $25 /* PIC jump register */
|
||||
#define k0 $26 /* kernel scratch */
|
||||
#define k1 $27
|
||||
#define gp $28 /* global pointer */
|
||||
#define sp $29 /* stack pointer */
|
||||
#define fp $30 /* frame pointer */
|
||||
#define s8 $30 /* same like fp! */
|
||||
#define ra $31 /* return address */
|
||||
|
||||
#endif /* end of __MIPS_INC__ */
|
||||
165
RT_Thread/libcpu/mips/common/mips_addrspace.h
Normal file
165
RT_Thread/libcpu/mips/common/mips_addrspace.h
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_ADDRSPACE_H_
|
||||
#define _MIPS_ADDRSPACE_H_
|
||||
|
||||
|
||||
/*
|
||||
* Configure language
|
||||
*/
|
||||
#ifdef __ASSEMBLY__
|
||||
#define _ATYPE_
|
||||
#define _ATYPE32_
|
||||
#define _ATYPE64_
|
||||
#define _CONST64_(x) x
|
||||
#else
|
||||
#define _ATYPE_ __PTRDIFF_TYPE__
|
||||
#define _ATYPE32_ int
|
||||
#define _ATYPE64_ __s64
|
||||
#ifdef ARCH_MIPS64
|
||||
#define _CONST64_(x) x ## L
|
||||
#else
|
||||
#define _CONST64_(x) x ## LL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 32-bit MIPS address spaces
|
||||
*/
|
||||
#ifdef __ASSEMBLY__
|
||||
#define _ACAST32_
|
||||
#define _ACAST64_
|
||||
#else
|
||||
#define _ACAST32_ (_ATYPE_)(_ATYPE32_) /* widen if necessary */
|
||||
#define _ACAST64_ (_ATYPE64_) /* do _not_ narrow */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns the kernel segment base of a given address
|
||||
*/
|
||||
#define KSEGX(a) ((_ACAST32_ (a)) & 0xe0000000)
|
||||
|
||||
/*
|
||||
* Returns the physical address of a CKSEGx / XKPHYS address
|
||||
*/
|
||||
#define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff)
|
||||
#define XPHYSADDR(a) ((_ACAST64_(a)) & \
|
||||
_CONST64_(0x000000ffffffffff))
|
||||
|
||||
#ifdef ARCH_MIPS64
|
||||
|
||||
/*
|
||||
* Memory segments (64bit kernel mode addresses)
|
||||
* The compatibility segments use the full 64-bit sign extended value. Note
|
||||
* the R8000 doesn't have them so don't reference these in generic MIPS code.
|
||||
*/
|
||||
#define XKUSEG _CONST64_(0x0000000000000000)
|
||||
#define XKSSEG _CONST64_(0x4000000000000000)
|
||||
#define XKPHYS _CONST64_(0x8000000000000000)
|
||||
#define XKSEG _CONST64_(0xc000000000000000)
|
||||
#define CKSEG0 _CONST64_(0xffffffff80000000)
|
||||
#define CKSEG1 _CONST64_(0xffffffffa0000000)
|
||||
#define CKSSEG _CONST64_(0xffffffffc0000000)
|
||||
#define CKSEG3 _CONST64_(0xffffffffe0000000)
|
||||
|
||||
#define CKSEG0ADDR(a) (CPHYSADDR(a) | CKSEG0)
|
||||
#define CKSEG1ADDR(a) (CPHYSADDR(a) | CKSEG1)
|
||||
#define CKSEG2ADDR(a) (CPHYSADDR(a) | CKSEG2)
|
||||
#define CKSEG3ADDR(a) (CPHYSADDR(a) | CKSEG3)
|
||||
|
||||
#define KUSEGBASE 0xffffffff00000000
|
||||
#define KSEG0BASE 0xffffffff80000000
|
||||
#define KSEG1BASE 0xffffffffa0000000
|
||||
#define KSEG2BASE 0xffffffffc0000000
|
||||
#define KSEG3BASE 0xffffffffe0000000
|
||||
|
||||
#else
|
||||
|
||||
#define CKSEG0ADDR(a) (CPHYSADDR(a) | KSEG0BASE)
|
||||
#define CKSEG1ADDR(a) (CPHYSADDR(a) | KSEG1BASE)
|
||||
#define CKSEG2ADDR(a) (CPHYSADDR(a) | KSEG2BASE)
|
||||
#define CKSEG3ADDR(a) (CPHYSADDR(a) | KSEG3BASE)
|
||||
|
||||
/*
|
||||
* Map an address to a certain kernel segment
|
||||
*/
|
||||
#define KSEG0ADDR(a) (CPHYSADDR(a) | KSEG0BASE)
|
||||
#define KSEG1ADDR(a) (CPHYSADDR(a) | KSEG1BASE)
|
||||
#define KSEG2ADDR(a) (CPHYSADDR(a) | KSEG2BASE)
|
||||
#define KSEG3ADDR(a) (CPHYSADDR(a) | KSEG3BASE)
|
||||
|
||||
#define CKUSEG 0x00000000
|
||||
#define CKSEG0 0x80000000
|
||||
#define CKSEG1 0xa0000000
|
||||
#define CKSEG2 0xc0000000
|
||||
#define CKSEG3 0xe0000000
|
||||
|
||||
/*
|
||||
* Memory segments (32bit kernel mode addresses)
|
||||
* These are the traditional names used in the 32-bit universe.
|
||||
*/
|
||||
#define KUSEGBASE 0x00000000
|
||||
#define KSEG0BASE 0x80000000
|
||||
#define KSEG1BASE 0xa0000000
|
||||
#define KSEG2BASE 0xc0000000
|
||||
#define KSEG3BASE 0xe0000000
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Cache modes for XKPHYS address conversion macros
|
||||
*/
|
||||
#define K_CALG_COH_EXCL1_NOL2 0
|
||||
#define K_CALG_COH_SHRL1_NOL2 1
|
||||
#define K_CALG_UNCACHED 2
|
||||
#define K_CALG_NONCOHERENT 3
|
||||
#define K_CALG_COH_EXCL 4
|
||||
#define K_CALG_COH_SHAREABLE 5
|
||||
#define K_CALG_NOTUSED 6
|
||||
#define K_CALG_UNCACHED_ACCEL 7
|
||||
|
||||
/*
|
||||
* 64-bit address conversions
|
||||
*/
|
||||
#define PHYS_TO_XKSEG_UNCACHED(p) PHYS_TO_XKPHYS(K_CALG_UNCACHED, (p))
|
||||
#define PHYS_TO_XKSEG_CACHED(p) PHYS_TO_XKPHYS(K_CALG_COH_SHAREABLE, (p))
|
||||
#define XKPHYS_TO_PHYS(p) ((p) & TO_PHYS_MASK)
|
||||
#define PHYS_TO_XKPHYS(cm, a) (_CONST64_(0x8000000000000000) | \
|
||||
(_CONST64_(cm) << 59) | (a))
|
||||
|
||||
/*
|
||||
* Returns the uncached address of a sdram address
|
||||
*/
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* The ultimate limited of the 64-bit MIPS architecture: 2 bits for selecting
|
||||
* the region, 3 bits for the CCA mode. This leaves 59 bits of which the
|
||||
* R8000 implements most with its 48-bit physical address space.
|
||||
*/
|
||||
#define TO_PHYS_MASK _CONST64_(0x07ffffffffffffff) /* 2^^59 - 1 */
|
||||
#define COMPAT_K1BASE32 _CONST64_(0xffffffffa0000000)
|
||||
#define PHYS_TO_COMPATK1(x) ((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */
|
||||
|
||||
#define KDM_TO_PHYS(x) (_ACAST64_ (x) & TO_PHYS_MASK)
|
||||
#define PHYS_TO_K0(x) (_ACAST64_ (x) | CAC_BASE)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#define REG8( addr ) (*(volatile u8 *) (addr))
|
||||
#define REG16( addr ) (*(volatile u16 *)(addr))
|
||||
#define REG32( addr ) (*(volatile u32 *)(addr))
|
||||
#define REG64( addr ) (*(volatile u64 *)(addr))
|
||||
#endif
|
||||
|
||||
#endif /* _MIPS_ADDRSPACE_H_ */
|
||||
139
RT_Thread/libcpu/mips/common/mips_cache.c
Normal file
139
RT_Thread/libcpu/mips/common/mips_cache.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2016-09-07 Urey the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "mips.h"
|
||||
|
||||
extern void cache_init(rt_ubase_t cache_size, rt_ubase_t cache_line_size);
|
||||
void r4k_cache_init(void)
|
||||
{
|
||||
// cache_init(dcache_size, cpu_dcache_line_size);
|
||||
}
|
||||
|
||||
void r4k_cache_flush_all(void)
|
||||
{
|
||||
blast_dcache16();
|
||||
blast_icache16();
|
||||
}
|
||||
|
||||
|
||||
void r4k_icache_flush_all(void)
|
||||
{
|
||||
blast_icache16();
|
||||
}
|
||||
|
||||
void r4k_icache_flush_range(rt_ubase_t addr, rt_ubase_t size)
|
||||
{
|
||||
rt_ubase_t end, a;
|
||||
|
||||
if (size > g_mips_core.icache_size)
|
||||
{
|
||||
blast_icache16();
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_ubase_t ic_lsize = g_mips_core.icache_line_size;
|
||||
|
||||
a = addr & ~(ic_lsize - 1);
|
||||
end = ((addr + size) - 1) & ~(ic_lsize - 1);
|
||||
while (1)
|
||||
{
|
||||
flush_icache_line(a);
|
||||
if (a == end)
|
||||
break;
|
||||
a += ic_lsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void r4k_icache_lock_range(rt_ubase_t addr, rt_ubase_t size)
|
||||
{
|
||||
rt_ubase_t end, a;
|
||||
rt_ubase_t ic_lsize = g_mips_core.icache_line_size;
|
||||
|
||||
a = addr & ~(ic_lsize - 1);
|
||||
end = ((addr + size) - 1) & ~(ic_lsize - 1);
|
||||
while (1)
|
||||
{
|
||||
lock_icache_line(a);
|
||||
if (a == end)
|
||||
break;
|
||||
a += ic_lsize;
|
||||
}
|
||||
}
|
||||
|
||||
void r4k_dcache_inv(rt_ubase_t addr, rt_ubase_t size)
|
||||
{
|
||||
rt_ubase_t end, a;
|
||||
rt_ubase_t dc_lsize = g_mips_core.dcache_line_size;
|
||||
|
||||
a = addr & ~(dc_lsize - 1);
|
||||
end = ((addr + size) - 1) & ~(dc_lsize - 1);
|
||||
while (1)
|
||||
{
|
||||
invalidate_dcache_line(a);
|
||||
if (a == end)
|
||||
break;
|
||||
a += dc_lsize;
|
||||
}
|
||||
}
|
||||
|
||||
void r4k_dcache_wback_inv(rt_ubase_t addr, rt_ubase_t size)
|
||||
{
|
||||
rt_ubase_t end, a;
|
||||
|
||||
if (size >= g_mips_core.dcache_size)
|
||||
{
|
||||
blast_dcache16();
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_ubase_t dc_lsize = g_mips_core.dcache_line_size;
|
||||
|
||||
a = addr & ~(dc_lsize - 1);
|
||||
end = ((addr + size) - 1) & ~(dc_lsize - 1);
|
||||
while (1)
|
||||
{
|
||||
flush_dcache_line(a);
|
||||
if (a == end)
|
||||
break;
|
||||
a += dc_lsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define dma_cache_wback_inv(start,size) \
|
||||
do { (void) (start); (void) (size); } while (0)
|
||||
#define dma_cache_wback(start,size) \
|
||||
do { (void) (start); (void) (size); } while (0)
|
||||
#define dma_cache_inv(start,size) \
|
||||
do { (void) (start); (void) (size); } while (0)
|
||||
|
||||
|
||||
void r4k_dma_cache_sync(rt_ubase_t addr, rt_size_t size, enum dma_data_direction direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case DMA_TO_DEVICE:
|
||||
r4k_dcache_wback_inv(addr, size);
|
||||
break;
|
||||
|
||||
case DMA_FROM_DEVICE:
|
||||
r4k_dcache_wback_inv(addr, size);
|
||||
break;
|
||||
|
||||
case DMA_BIDIRECTIONAL:
|
||||
dma_cache_wback_inv(addr, size);
|
||||
break;
|
||||
default:
|
||||
RT_ASSERT(0) ;
|
||||
}
|
||||
}
|
||||
|
||||
216
RT_Thread/libcpu/mips/common/mips_cache.h
Normal file
216
RT_Thread/libcpu/mips/common/mips_cache.h
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2016-09-07 Urey the first version
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_CACHE_H_
|
||||
#define _MIPS_CACHE_H_
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <rtdef.h>
|
||||
#include <mips_cfg.h>
|
||||
|
||||
/*
|
||||
* Cache Operations available on all MIPS processors with R4000-style caches
|
||||
*/
|
||||
#define INDEX_INVALIDATE_I 0x00
|
||||
#define INDEX_WRITEBACK_INV_D 0x01
|
||||
#define INDEX_LOAD_TAG_I 0x04
|
||||
#define INDEX_LOAD_TAG_D 0x05
|
||||
#define INDEX_STORE_TAG_I 0x08
|
||||
#define INDEX_STORE_TAG_D 0x09
|
||||
#define HIT_INVALIDATE_I 0x10
|
||||
#define HIT_INVALIDATE_D 0x11
|
||||
#define HIT_WRITEBACK_INV_D 0x15
|
||||
|
||||
/*
|
||||
*The lock state is cleared by executing an Index
|
||||
Invalidate, Index Writeback Invalidate, Hit
|
||||
Invalidate, or Hit Writeback Invalidate
|
||||
operation to the locked line, or via an Index
|
||||
Store Tag operation with the lock bit reset in
|
||||
the TagLo register.
|
||||
*/
|
||||
#define FETCH_AND_LOCK_I 0x1c
|
||||
#define FETCH_AND_LOCK_D 0x1d
|
||||
|
||||
|
||||
enum dma_data_direction
|
||||
{
|
||||
DMA_BIDIRECTIONAL = 0,
|
||||
DMA_TO_DEVICE = 1,
|
||||
DMA_FROM_DEVICE = 2,
|
||||
DMA_NONE = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* R4000-specific cacheops
|
||||
*/
|
||||
#define CREATE_DIRTY_EXCL_D 0x0d
|
||||
#define FILL 0x14
|
||||
#define HIT_WRITEBACK_I 0x18
|
||||
#define HIT_WRITEBACK_D 0x19
|
||||
|
||||
/*
|
||||
* R4000SC and R4400SC-specific cacheops
|
||||
*/
|
||||
#define INDEX_INVALIDATE_SI 0x02
|
||||
#define INDEX_WRITEBACK_INV_SD 0x03
|
||||
#define INDEX_LOAD_TAG_SI 0x06
|
||||
#define INDEX_LOAD_TAG_SD 0x07
|
||||
#define INDEX_STORE_TAG_SI 0x0A
|
||||
#define INDEX_STORE_TAG_SD 0x0B
|
||||
#define CREATE_DIRTY_EXCL_SD 0x0f
|
||||
#define HIT_INVALIDATE_SI 0x12
|
||||
#define HIT_INVALIDATE_SD 0x13
|
||||
#define HIT_WRITEBACK_INV_SD 0x17
|
||||
#define HIT_WRITEBACK_SD 0x1b
|
||||
#define HIT_SET_VIRTUAL_SI 0x1e
|
||||
#define HIT_SET_VIRTUAL_SD 0x1f
|
||||
|
||||
/*
|
||||
* R5000-specific cacheops
|
||||
*/
|
||||
#define R5K_PAGE_INVALIDATE_S 0x17
|
||||
|
||||
/*
|
||||
* RM7000-specific cacheops
|
||||
*/
|
||||
#define PAGE_INVALIDATE_T 0x16
|
||||
|
||||
/*
|
||||
* R10000-specific cacheops
|
||||
*
|
||||
* Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused.
|
||||
* Most of the _S cacheops are identical to the R4000SC _SD cacheops.
|
||||
*/
|
||||
#define INDEX_WRITEBACK_INV_S 0x03
|
||||
#define INDEX_LOAD_TAG_S 0x07
|
||||
#define INDEX_STORE_TAG_S 0x0B
|
||||
#define HIT_INVALIDATE_S 0x13
|
||||
#define CACHE_BARRIER 0x14
|
||||
#define HIT_WRITEBACK_INV_S 0x17
|
||||
#define INDEX_LOAD_DATA_I 0x18
|
||||
#define INDEX_LOAD_DATA_D 0x19
|
||||
#define INDEX_LOAD_DATA_S 0x1b
|
||||
#define INDEX_STORE_DATA_I 0x1c
|
||||
#define INDEX_STORE_DATA_D 0x1d
|
||||
#define INDEX_STORE_DATA_S 0x1f
|
||||
|
||||
#define cache_op(op, addr) \
|
||||
__asm__ __volatile__( \
|
||||
".set push\n" \
|
||||
".set noreorder\n" \
|
||||
".set mips3\n" \
|
||||
"cache %0, %1\n" \
|
||||
".set pop\n" \
|
||||
: \
|
||||
: "i" (op), "R" (*(unsigned char *)(addr)))
|
||||
|
||||
#define cache16_unroll32(base, op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set noreorder \n" \
|
||||
" .set mips3 \n" \
|
||||
" cache %1, 0x000(%0); cache %1, 0x010(%0) \n" \
|
||||
" cache %1, 0x020(%0); cache %1, 0x030(%0) \n" \
|
||||
" cache %1, 0x040(%0); cache %1, 0x050(%0) \n" \
|
||||
" cache %1, 0x060(%0); cache %1, 0x070(%0) \n" \
|
||||
" cache %1, 0x080(%0); cache %1, 0x090(%0) \n" \
|
||||
" cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) \n" \
|
||||
" cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) \n" \
|
||||
" cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) \n" \
|
||||
" cache %1, 0x100(%0); cache %1, 0x110(%0) \n" \
|
||||
" cache %1, 0x120(%0); cache %1, 0x130(%0) \n" \
|
||||
" cache %1, 0x140(%0); cache %1, 0x150(%0) \n" \
|
||||
" cache %1, 0x160(%0); cache %1, 0x170(%0) \n" \
|
||||
" cache %1, 0x180(%0); cache %1, 0x190(%0) \n" \
|
||||
" cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) \n" \
|
||||
" cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) \n" \
|
||||
" cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) \n" \
|
||||
" .set mips0 \n" \
|
||||
" .set reorder \n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
|
||||
|
||||
static inline void flush_icache_line_indexed(rt_ubase_t addr)
|
||||
{
|
||||
cache_op(INDEX_INVALIDATE_I, addr);
|
||||
}
|
||||
|
||||
static inline void flush_dcache_line_indexed(rt_ubase_t addr)
|
||||
{
|
||||
cache_op(INDEX_WRITEBACK_INV_D, addr);
|
||||
}
|
||||
|
||||
static inline void flush_icache_line(rt_ubase_t addr)
|
||||
{
|
||||
cache_op(HIT_INVALIDATE_I, addr);
|
||||
}
|
||||
|
||||
static inline void lock_icache_line(rt_ubase_t addr)
|
||||
{
|
||||
cache_op(FETCH_AND_LOCK_I, addr);
|
||||
}
|
||||
|
||||
static inline void lock_dcache_line(rt_ubase_t addr)
|
||||
{
|
||||
cache_op(FETCH_AND_LOCK_D, addr);
|
||||
}
|
||||
|
||||
static inline void flush_dcache_line(rt_ubase_t addr)
|
||||
{
|
||||
cache_op(HIT_WRITEBACK_INV_D, addr);
|
||||
}
|
||||
|
||||
static inline void invalidate_dcache_line(rt_ubase_t addr)
|
||||
{
|
||||
cache_op(HIT_INVALIDATE_D, addr);
|
||||
}
|
||||
static inline void blast_dcache16(void)
|
||||
{
|
||||
rt_ubase_t start = KSEG0BASE;
|
||||
rt_ubase_t end = start + g_mips_core.dcache_size;
|
||||
rt_ubase_t addr;
|
||||
|
||||
for (addr = start; addr < end; addr += g_mips_core.dcache_line_size)
|
||||
cache16_unroll32(addr, INDEX_WRITEBACK_INV_D);
|
||||
}
|
||||
|
||||
static inline void inv_dcache16(void)
|
||||
{
|
||||
rt_ubase_t start = KSEG0BASE;
|
||||
rt_ubase_t end = start + g_mips_core.dcache_size;
|
||||
rt_ubase_t addr;
|
||||
|
||||
for (addr = start; addr < end; addr += g_mips_core.dcache_line_size)
|
||||
cache16_unroll32(addr, HIT_INVALIDATE_D);
|
||||
}
|
||||
|
||||
static inline void blast_icache16(void)
|
||||
{
|
||||
rt_ubase_t start = KSEG0BASE;
|
||||
rt_ubase_t end = start + g_mips_core.icache_size;
|
||||
rt_ubase_t addr;
|
||||
|
||||
for (addr = start; addr < end; addr += g_mips_core.icache_line_size)
|
||||
cache16_unroll32(addr, INDEX_INVALIDATE_I);
|
||||
}
|
||||
|
||||
void r4k_cache_init(void);
|
||||
void r4k_cache_flush_all(void);
|
||||
void r4k_icache_flush_all(void);
|
||||
void r4k_icache_flush_range(rt_ubase_t addr, rt_ubase_t size);
|
||||
void r4k_icache_lock_range(rt_ubase_t addr, rt_ubase_t size);
|
||||
void r4k_dcache_inv(rt_ubase_t addr, rt_ubase_t size);
|
||||
void r4k_dcache_wback_inv(rt_ubase_t addr, rt_ubase_t size);
|
||||
void r4k_dma_cache_sync(rt_ubase_t addr, rt_size_t size, enum dma_data_direction direction);
|
||||
#endif
|
||||
|
||||
#endif /* _MIPS_CACHE_H_ */
|
||||
34
RT_Thread/libcpu/mips/common/mips_cfg.h
Normal file
34
RT_Thread/libcpu/mips/common/mips_cfg.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2016-09-07 Urey the first version
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_CFG_H_
|
||||
#define _MIPS_CFG_H_
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <stdint.h>
|
||||
typedef struct mips32_core_cfg
|
||||
{
|
||||
uint16_t icache_line_size;
|
||||
uint16_t icache_lines_per_way;
|
||||
uint16_t icache_ways;
|
||||
uint16_t icache_size;
|
||||
uint16_t dcache_line_size;
|
||||
uint16_t dcache_lines_per_way;
|
||||
uint16_t dcache_ways;
|
||||
uint16_t dcache_size;
|
||||
|
||||
uint16_t max_tlb_entries; /* number of tlb entry */
|
||||
} mips32_core_cfg_t;
|
||||
|
||||
extern mips32_core_cfg_t g_mips_core;
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _MIPS_CFG_H_ */
|
||||
46
RT_Thread/libcpu/mips/common/mips_fpu.h
Normal file
46
RT_Thread/libcpu/mips/common/mips_fpu.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_FPU_H_
|
||||
#define _MIPS_FPU_H_
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <mips_regs.h>
|
||||
/**
|
||||
* init hardware FPU
|
||||
*/
|
||||
#ifdef RT_USING_FPU
|
||||
rt_inline void rt_hw_fpu_init(void)
|
||||
{
|
||||
rt_uint32_t c0_status = 0;
|
||||
rt_uint32_t c1_status = 0;
|
||||
|
||||
/* Enable CU1 */
|
||||
c0_status = read_c0_status();
|
||||
c0_status |= (ST0_CU1 | ST0_FR);
|
||||
write_c0_status(c0_status);
|
||||
|
||||
/* FCSR Configs */
|
||||
c1_status = read_c1_status();
|
||||
c1_status |= (FPU_CSR_FS | FPU_CSR_FO | FPU_CSR_FN); /* Set FS, FO, FN */
|
||||
c1_status &= ~(FPU_CSR_ALL_E); /* Disable exception */
|
||||
c1_status = (c1_status & (~FPU_CSR_RM)) | FPU_CSR_RN; /* Set RN */
|
||||
write_c1_status(c1_status);
|
||||
|
||||
return ;
|
||||
}
|
||||
#else
|
||||
rt_inline void rt_hw_fpu_init(void){} /* Do nothing */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1146
RT_Thread/libcpu/mips/common/mips_regs.h
Normal file
1146
RT_Thread/libcpu/mips/common/mips_regs.h
Normal file
File diff suppressed because it is too large
Load Diff
91
RT_Thread/libcpu/mips/common/mips_types.h
Normal file
91
RT_Thread/libcpu/mips/common/mips_types.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2016-09-07 Urey the first version
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_TYPES_H_
|
||||
#define _MIPS_TYPES_H_
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef unsigned short umode_t;
|
||||
|
||||
/*
|
||||
* __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
|
||||
* header files exported to user space
|
||||
*/
|
||||
|
||||
typedef __signed__ char __s8;
|
||||
typedef unsigned char __u8;
|
||||
|
||||
typedef __signed__ short __s16;
|
||||
typedef unsigned short __u16;
|
||||
|
||||
typedef __signed__ int __s32;
|
||||
typedef unsigned int __u32;
|
||||
|
||||
#if (_MIPS_SZLONG == 64)
|
||||
|
||||
typedef __signed__ long __s64;
|
||||
typedef unsigned long __u64;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(__GNUC__)
|
||||
__extension__ typedef __signed__ long long __s64;
|
||||
__extension__ typedef unsigned long long __u64;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These aren't exported outside the kernel to avoid name space clashes
|
||||
*/
|
||||
|
||||
#define BITS_PER_LONG _MIPS_SZLONG
|
||||
|
||||
|
||||
typedef __signed char s8;
|
||||
typedef unsigned char u8;
|
||||
|
||||
typedef __signed short s16;
|
||||
typedef unsigned short u16;
|
||||
|
||||
typedef __signed int s32;
|
||||
typedef unsigned int u32;
|
||||
|
||||
#if (_MIPS_SZLONG == 64)
|
||||
|
||||
typedef __signed__ long s64;
|
||||
typedef unsigned long u64;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
typedef __signed__ long long s64;
|
||||
typedef unsigned long long u64;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef u32 dma_addr_t;
|
||||
|
||||
typedef u32 phys_addr_t;
|
||||
typedef u32 phys_size_t;
|
||||
|
||||
|
||||
/*
|
||||
* Don't use phys_t. You've been warned.
|
||||
*/
|
||||
|
||||
typedef unsigned long phys_t;
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
||||
#endif /* _MIPS_TYPES_H_ */
|
||||
145
RT_Thread/libcpu/mips/common/ptrace.h
Normal file
145
RT_Thread/libcpu/mips/common/ptrace.h
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_PTRACE_H
|
||||
#define _MIPS_PTRACE_H
|
||||
|
||||
#include "asm.h"
|
||||
#include "mips_regs.h"
|
||||
|
||||
#define HI_LO_SIZE 4
|
||||
|
||||
#define FP_REG_SIZE 8
|
||||
#define NUM_FPU_REGS 16
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <rtthread.h>
|
||||
|
||||
struct mips_fpu_struct {
|
||||
rt_uint64_t fpr[NUM_FPU_REGS];
|
||||
rt_uint32_t fcr31;
|
||||
rt_uint32_t pad;
|
||||
};
|
||||
|
||||
struct pt_regs {
|
||||
#ifndef ARCH_MIPS64
|
||||
/* Only O32 Need This! */
|
||||
/* Pad bytes for argument save space on the stack. */
|
||||
rt_uint32_t pad0[8];
|
||||
|
||||
/* Saved main processor registers. */
|
||||
rt_uint32_t regs[32];
|
||||
|
||||
/* Saved special registers. */
|
||||
rt_uint32_t cp0_status;
|
||||
rt_uint32_t hi;
|
||||
rt_uint32_t lo;
|
||||
rt_uint32_t cp0_badvaddr;
|
||||
rt_uint32_t cp0_cause;
|
||||
rt_uint32_t cp0_epc;
|
||||
#else
|
||||
/* Saved main processor registers. */
|
||||
unsigned long regs[32];
|
||||
|
||||
/* Saved special registers. */
|
||||
rt_uint32_t cp0_status;
|
||||
rt_uint32_t hi;
|
||||
rt_uint32_t lo;
|
||||
unsigned long cp0_badvaddr;
|
||||
rt_uint32_t cp0_cause;
|
||||
unsigned long cp0_epc;
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
/* FPU Registers */
|
||||
/* Unlike Linux Kernel, we save these registers unconditionally,
|
||||
* so it should be a part of pt_regs */
|
||||
struct mips_fpu_struct fpu;
|
||||
#endif
|
||||
} __attribute__((aligned(8)));
|
||||
#endif
|
||||
|
||||
/* Note: For call stack o32 ABI has 0x8 shadowsoace Here */
|
||||
#ifdef ARCH_MIPS64
|
||||
#define PT_R0 (0x0 * LONGSIZE) /* 0 */
|
||||
#else
|
||||
#define PT_R0 (0x8 * LONGSIZE) /* 0 */
|
||||
#endif
|
||||
#define PT_R1 ((PT_R0) + LONGSIZE) /* 1 */
|
||||
#define PT_R2 ((PT_R1) + LONGSIZE) /* 2 */
|
||||
#define PT_R3 ((PT_R2) + LONGSIZE) /* 3 */
|
||||
#define PT_R4 ((PT_R3) + LONGSIZE) /* 4 */
|
||||
#define PT_R5 ((PT_R4) + LONGSIZE) /* 5 */
|
||||
#define PT_R6 ((PT_R5) + LONGSIZE) /* 6 */
|
||||
#define PT_R7 ((PT_R6) + LONGSIZE) /* 7 */
|
||||
#define PT_R8 ((PT_R7) + LONGSIZE) /* 8 */
|
||||
#define PT_R9 ((PT_R8) + LONGSIZE) /* 9 */
|
||||
#define PT_R10 ((PT_R9) + LONGSIZE) /* 10 */
|
||||
#define PT_R11 ((PT_R10) + LONGSIZE) /* 11 */
|
||||
#define PT_R12 ((PT_R11) + LONGSIZE) /* 12 */
|
||||
#define PT_R13 ((PT_R12) + LONGSIZE) /* 13 */
|
||||
#define PT_R14 ((PT_R13) + LONGSIZE) /* 14 */
|
||||
#define PT_R15 ((PT_R14) + LONGSIZE) /* 15 */
|
||||
#define PT_R16 ((PT_R15) + LONGSIZE) /* 16 */
|
||||
#define PT_R17 ((PT_R16) + LONGSIZE) /* 17 */
|
||||
#define PT_R18 ((PT_R17) + LONGSIZE) /* 18 */
|
||||
#define PT_R19 ((PT_R18) + LONGSIZE) /* 19 */
|
||||
#define PT_R20 ((PT_R19) + LONGSIZE) /* 20 */
|
||||
#define PT_R21 ((PT_R20) + LONGSIZE) /* 21 */
|
||||
#define PT_R22 ((PT_R21) + LONGSIZE) /* 22 */
|
||||
#define PT_R23 ((PT_R22) + LONGSIZE) /* 23 */
|
||||
#define PT_R24 ((PT_R23) + LONGSIZE) /* 24 */
|
||||
#define PT_R25 ((PT_R24) + LONGSIZE) /* 25 */
|
||||
#define PT_R26 ((PT_R25) + LONGSIZE) /* 26 */
|
||||
#define PT_R27 ((PT_R26) + LONGSIZE) /* 27 */
|
||||
#define PT_R28 ((PT_R27) + LONGSIZE) /* 28 */
|
||||
#define PT_R29 ((PT_R28) + LONGSIZE) /* 29 */
|
||||
#define PT_R30 ((PT_R29) + LONGSIZE) /* 30 */
|
||||
#define PT_R31 ((PT_R30) + LONGSIZE) /* 31 */
|
||||
|
||||
/*
|
||||
* Saved special registers
|
||||
*/
|
||||
#define PT_STATUS ((PT_R31) + LONGSIZE) /* 32 */
|
||||
#define PT_HI ((PT_STATUS) + HI_LO_SIZE) /* 33 */
|
||||
#define PT_LO ((PT_HI) + HI_LO_SIZE) /* 34 */
|
||||
#define PT_BADVADDR ((PT_LO) + LONGSIZE) /* 35 */
|
||||
#define PT_CAUSE ((PT_BADVADDR) + LONGSIZE) /* 36 */
|
||||
#define PT_EPC ((PT_CAUSE) + LONGSIZE) /* 37 */
|
||||
|
||||
#define PT_REG_END ((PT_EPC) + LONGSIZE) /* Align already ensured manually */
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
#define PT_FPU_R0 (PT_REG_END)
|
||||
#define PT_FPU_R2 ((PT_FPU_R0) + FP_REG_SIZE)
|
||||
#define PT_FPU_R4 ((PT_FPU_R2) + FP_REG_SIZE)
|
||||
#define PT_FPU_R6 ((PT_FPU_R4) + FP_REG_SIZE)
|
||||
#define PT_FPU_R8 ((PT_FPU_R6) + FP_REG_SIZE)
|
||||
#define PT_FPU_R10 ((PT_FPU_R8) + FP_REG_SIZE)
|
||||
#define PT_FPU_R12 ((PT_FPU_R10) + FP_REG_SIZE)
|
||||
#define PT_FPU_R14 ((PT_FPU_R12) + FP_REG_SIZE)
|
||||
#define PT_FPU_R16 ((PT_FPU_R14) + FP_REG_SIZE)
|
||||
#define PT_FPU_R18 ((PT_FPU_R16) + FP_REG_SIZE)
|
||||
#define PT_FPU_R20 ((PT_FPU_R18) + FP_REG_SIZE)
|
||||
#define PT_FPU_R22 ((PT_FPU_R20) + FP_REG_SIZE)
|
||||
#define PT_FPU_R24 ((PT_FPU_R22) + FP_REG_SIZE)
|
||||
#define PT_FPU_R26 ((PT_FPU_R24) + FP_REG_SIZE)
|
||||
#define PT_FPU_R28 ((PT_FPU_R26) + FP_REG_SIZE)
|
||||
#define PT_FPU_R30 ((PT_FPU_R28) + FP_REG_SIZE)
|
||||
#define PT_FPU_FCSR31 ((PT_FPU_R30) + FP_REG_SIZE)
|
||||
#define PT_FPU_PAD0 ((PT_FPU_FCSR31) + 4)
|
||||
|
||||
#define PT_FPU_END ((PT_FPU_PAD0) + 4)
|
||||
#define PT_SIZE PT_FPU_END
|
||||
#else
|
||||
#define PT_SIZE PT_REG_END
|
||||
#endif
|
||||
|
||||
#endif
|
||||
61
RT_Thread/libcpu/mips/common/stack.c
Normal file
61
RT_Thread/libcpu/mips/common/stack.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "mips.h"
|
||||
|
||||
register rt_uint32_t $GP __asm__ ("$28");
|
||||
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit)
|
||||
{
|
||||
static rt_ubase_t wSR=0;
|
||||
static rt_ubase_t wGP;
|
||||
rt_uint8_t *stk;
|
||||
|
||||
struct pt_regs *pt;
|
||||
|
||||
rt_uint32_t i;
|
||||
|
||||
/* Get stack aligned */
|
||||
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stack_addr, 8);
|
||||
stk -= sizeof(struct pt_regs);
|
||||
pt = (struct pt_regs*)stk;
|
||||
|
||||
#ifndef ARCH_MIPS64
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
pt->pad0[i] = 0xdeadbeef;
|
||||
}
|
||||
#endif
|
||||
/* Fill Stack register numbers */
|
||||
for (i = 0; i < 32; ++i)
|
||||
{
|
||||
pt->regs[i] = 0xdeadbeef;
|
||||
}
|
||||
|
||||
pt->regs[REG_SP] = (rt_ubase_t)stk;
|
||||
pt->regs[REG_A0] = (rt_ubase_t)parameter;
|
||||
pt->regs[REG_GP] = (rt_ubase_t)$GP;
|
||||
pt->regs[REG_FP] = (rt_ubase_t)0x0;
|
||||
pt->regs[REG_RA] = (rt_ubase_t)texit;
|
||||
|
||||
pt->hi = 0x0;
|
||||
pt->lo = 0x0;
|
||||
pt->cp0_status = (ST0_IE | ST0_CU0 | ST0_IM);
|
||||
#ifdef RT_USING_FPU
|
||||
pt->cp0_status |= (ST0_CU1 | ST0_FR);
|
||||
#endif
|
||||
pt->cp0_cause = read_c0_cause();
|
||||
pt->cp0_epc = (rt_ubase_t)tentry;
|
||||
pt->cp0_badvaddr = 0x0;
|
||||
|
||||
return stk;
|
||||
}
|
||||
256
RT_Thread/libcpu/mips/common/stackframe.h
Normal file
256
RT_Thread/libcpu/mips/common/stackframe.h
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-12-04 Jiaxun Yang Initial version
|
||||
*/
|
||||
|
||||
#ifndef __STACKFRAME_H__
|
||||
#define __STACKFRAME_H__
|
||||
|
||||
#include "asm.h"
|
||||
#include "mips_regs.h"
|
||||
#include "ptrace.h"
|
||||
|
||||
/* You MUST ensure FP is enabled before SAVE_FPU! */
|
||||
.macro SAVE_FPU
|
||||
.set push
|
||||
.set noreorder
|
||||
#ifdef RT_USING_FPU
|
||||
/* Ensure CU1 (FPU) is enabled */
|
||||
MFC0 v1, CP0_STATUS
|
||||
lui t1, %hi(ST0_CU1)
|
||||
addiu t1, t1, %lo(ST0_CU1)
|
||||
or v1, v1, t1
|
||||
MTC0 v1, CP0_STATUS
|
||||
SSNOP
|
||||
cfc1 v1, fcr31
|
||||
/* Store as delay slot */
|
||||
s.d $f0, PT_FPU_R0(sp)
|
||||
s.d $f2, PT_FPU_R2(sp)
|
||||
s.d $f4, PT_FPU_R4(sp)
|
||||
s.d $f6, PT_FPU_R6(sp)
|
||||
s.d $f8, PT_FPU_R8(sp)
|
||||
s.d $f10, PT_FPU_R10(sp)
|
||||
s.d $f12, PT_FPU_R12(sp)
|
||||
s.d $f14, PT_FPU_R14(sp)
|
||||
s.d $f16, PT_FPU_R16(sp)
|
||||
s.d $f18, PT_FPU_R18(sp)
|
||||
s.d $f20, PT_FPU_R20(sp)
|
||||
s.d $f22, PT_FPU_R22(sp)
|
||||
s.d $f24, PT_FPU_R24(sp)
|
||||
s.d $f26, PT_FPU_R26(sp)
|
||||
s.d $f28, PT_FPU_R28(sp)
|
||||
s.d $f30, PT_FPU_R30(sp)
|
||||
LONG_S v1, PT_FPU_FCSR31(sp)
|
||||
#endif
|
||||
.set reorder
|
||||
.set pop
|
||||
.endm
|
||||
|
||||
.macro SAVE_AT
|
||||
.set push
|
||||
.set noat
|
||||
LONG_S $1, PT_R1(sp)
|
||||
.set pop
|
||||
.endm
|
||||
|
||||
.macro SAVE_TEMP
|
||||
mfhi v1
|
||||
LONG_S $8, PT_R8(sp)
|
||||
LONG_S $9, PT_R9(sp)
|
||||
sw v1, PT_HI(sp)
|
||||
mflo v1
|
||||
LONG_S $10, PT_R10(sp)
|
||||
LONG_S $11, PT_R11(sp)
|
||||
sw v1, PT_LO(sp)
|
||||
LONG_S $12, PT_R12(sp)
|
||||
LONG_S $13, PT_R13(sp)
|
||||
LONG_S $14, PT_R14(sp)
|
||||
LONG_S $15, PT_R15(sp)
|
||||
LONG_S $24, PT_R24(sp)
|
||||
.endm
|
||||
|
||||
.macro SAVE_STATIC
|
||||
LONG_S $16, PT_R16(sp)
|
||||
LONG_S $17, PT_R17(sp)
|
||||
LONG_S $18, PT_R18(sp)
|
||||
LONG_S $19, PT_R19(sp)
|
||||
LONG_S $20, PT_R20(sp)
|
||||
LONG_S $21, PT_R21(sp)
|
||||
LONG_S $22, PT_R22(sp)
|
||||
LONG_S $23, PT_R23(sp)
|
||||
LONG_S $30, PT_R30(sp)
|
||||
.endm
|
||||
|
||||
.macro SAVE_SOME
|
||||
.set push
|
||||
.set noat
|
||||
.set reorder
|
||||
move k1, sp
|
||||
move k0, sp
|
||||
PTR_SUBU sp, k1, PT_SIZE
|
||||
LONG_S k0, PT_R29(sp)
|
||||
LONG_S $3, PT_R3(sp)
|
||||
LONG_S $0, PT_R0(sp)
|
||||
MFC0 v1, CP0_STATUS
|
||||
LONG_S $2, PT_R2(sp)
|
||||
LONG_S v1, PT_STATUS(sp)
|
||||
LONG_S $4, PT_R4(sp)
|
||||
MFC0 v1, CP0_CAUSE
|
||||
LONG_S $5, PT_R5(sp)
|
||||
LONG_S v1, PT_CAUSE(sp)
|
||||
LONG_S $6, PT_R6(sp)
|
||||
MFC0 v1, CP0_EPC
|
||||
LONG_S $7, PT_R7(sp)
|
||||
LONG_S v1, PT_EPC(sp)
|
||||
LONG_S $25, PT_R25(sp)
|
||||
LONG_S $28, PT_R28(sp)
|
||||
LONG_S $31, PT_R31(sp)
|
||||
.set pop
|
||||
.endm
|
||||
|
||||
.macro SAVE_ALL
|
||||
SAVE_SOME
|
||||
SAVE_AT
|
||||
SAVE_TEMP
|
||||
SAVE_FPU
|
||||
SAVE_STATIC
|
||||
.endm
|
||||
|
||||
.macro RESTORE_FPU
|
||||
.set push
|
||||
.set noreorder
|
||||
#ifdef RT_USING_FPU
|
||||
/* Ensure CU1 (FPU) is enabled */
|
||||
MFC0 v1, CP0_STATUS
|
||||
lui t1, %hi(ST0_CU1)
|
||||
addiu t1, t1, %lo(ST0_CU1)
|
||||
or v1, v1, t1
|
||||
MTC0 v1, CP0_STATUS
|
||||
SSNOP
|
||||
LONG_L v1, PT_FPU_FCSR31(sp)
|
||||
ctc1 v1, fcr31
|
||||
l.d $f0, PT_FPU_R0(sp)
|
||||
l.d $f2, PT_FPU_R2(sp)
|
||||
l.d $f4, PT_FPU_R4(sp)
|
||||
l.d $f6, PT_FPU_R6(sp)
|
||||
l.d $f8, PT_FPU_R8(sp)
|
||||
l.d $f10, PT_FPU_R10(sp)
|
||||
l.d $f12, PT_FPU_R12(sp)
|
||||
l.d $f14, PT_FPU_R14(sp)
|
||||
l.d $f16, PT_FPU_R16(sp)
|
||||
l.d $f18, PT_FPU_R18(sp)
|
||||
l.d $f20, PT_FPU_R20(sp)
|
||||
l.d $f22, PT_FPU_R22(sp)
|
||||
l.d $f24, PT_FPU_R24(sp)
|
||||
l.d $f26, PT_FPU_R26(sp)
|
||||
l.d $f28, PT_FPU_R28(sp)
|
||||
l.d $f30, PT_FPU_R30(sp)
|
||||
#endif
|
||||
.set reorder
|
||||
.set pop
|
||||
.endm
|
||||
|
||||
.macro RESTORE_AT
|
||||
.set push
|
||||
.set noat
|
||||
LONG_L $1, PT_R1(sp)
|
||||
.set pop
|
||||
.endm
|
||||
|
||||
.macro RESTORE_TEMP
|
||||
lw $24, PT_LO(sp)
|
||||
LONG_L $8, PT_R8(sp)
|
||||
LONG_L $9, PT_R9(sp)
|
||||
mtlo $24
|
||||
lw $24, PT_HI(sp)
|
||||
LONG_L $10, PT_R10(sp)
|
||||
LONG_L $11, PT_R11(sp)
|
||||
mthi $24
|
||||
LONG_L $12, PT_R12(sp)
|
||||
LONG_L $13, PT_R13(sp)
|
||||
LONG_L $14, PT_R14(sp)
|
||||
LONG_L $15, PT_R15(sp)
|
||||
LONG_L $24, PT_R24(sp)
|
||||
.endm
|
||||
|
||||
.macro RESTORE_STATIC
|
||||
LONG_L $16, PT_R16(sp)
|
||||
LONG_L $17, PT_R17(sp)
|
||||
LONG_L $18, PT_R18(sp)
|
||||
LONG_L $19, PT_R19(sp)
|
||||
LONG_L $20, PT_R20(sp)
|
||||
LONG_L $21, PT_R21(sp)
|
||||
LONG_L $22, PT_R22(sp)
|
||||
LONG_L $23, PT_R23(sp)
|
||||
LONG_L $30, PT_R30(sp)
|
||||
.endm
|
||||
|
||||
#define STATMASK 0x1f
|
||||
|
||||
.macro RESTORE_SOME
|
||||
.set push
|
||||
.set reorder
|
||||
.set noat
|
||||
mfc0 a0, CP0_STATUS
|
||||
ori a0, STATMASK
|
||||
xori a0, STATMASK
|
||||
mtc0 a0, CP0_STATUS
|
||||
li v1, (ST0_CU1 | ST0_FR | ST0_IM)
|
||||
and a0, v1, a0
|
||||
LONG_L v0, PT_STATUS(sp)
|
||||
li v1, ~(ST0_CU1 | ST0_FR | ST0_IM)
|
||||
and v0, v1
|
||||
or v0, a0
|
||||
li v1, (ST0_KX | ST0_SX | ST0_UX)
|
||||
or v0, v1
|
||||
mtc0 v0, CP0_STATUS
|
||||
LONG_L v1, PT_EPC(sp)
|
||||
MTC0 v1, CP0_EPC
|
||||
LONG_L $31, PT_R31(sp)
|
||||
LONG_L $28, PT_R28(sp)
|
||||
LONG_L $25, PT_R25(sp)
|
||||
LONG_L $7, PT_R7(sp)
|
||||
LONG_L $6, PT_R6(sp)
|
||||
LONG_L $5, PT_R5(sp)
|
||||
LONG_L $4, PT_R4(sp)
|
||||
LONG_L $3, PT_R3(sp)
|
||||
LONG_L $2, PT_R2(sp)
|
||||
.set pop
|
||||
.endm
|
||||
|
||||
.macro RESTORE_SP_AND_RET
|
||||
LONG_L sp, PT_R29(sp)
|
||||
eret
|
||||
nop
|
||||
.endm
|
||||
|
||||
|
||||
.macro RESTORE_SP
|
||||
LONG_L sp, PT_R29(sp)
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ALL
|
||||
RESTORE_TEMP
|
||||
RESTORE_FPU
|
||||
RESTORE_STATIC
|
||||
RESTORE_AT
|
||||
RESTORE_SOME
|
||||
RESTORE_SP
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ALL_AND_RET
|
||||
RESTORE_TEMP
|
||||
RESTORE_FPU
|
||||
RESTORE_STATIC
|
||||
RESTORE_AT
|
||||
RESTORE_SOME
|
||||
RESTORE_SP_AND_RET
|
||||
.endm
|
||||
|
||||
#endif /* end of __STACKFRAME_H__ */
|
||||
|
||||
Reference in New Issue
Block a user