原始版本

This commit is contained in:
冯佳
2025-06-19 21:56:46 +08:00
parent fe98e5f010
commit a4841450cf
4152 changed files with 1910684 additions and 0 deletions

View 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

View 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')

View 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__ */

View 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

View 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

View 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));
}
/*@}*/

View 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__ */

View 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

View 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_ */

View 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__ */

View 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_ */

View 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) ;
}
}

View 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_ */

View 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_ */

View 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

File diff suppressed because it is too large Load Diff

View 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_ */

View 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

View 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;
}

View 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__ */