提交 7c665018 编写于 作者: J Jiaxun Yang

[libcpu] Refine MIPS common code

MIPS common code was highly duplicated, This commit
is a attempt to clean-up and refine these code.

The context and exception handle flow is mostly identical
with Linux, but a notable difference is that when FPU enabled,
we save FP registers in stackframe unconditionally.
Signed-off-by: NJiaxun Yang <jiaxun.yang@flygoat.com>
上级 44123368
......@@ -13,6 +13,7 @@ list = os.listdir(cwd)
group = group + SConscript(os.path.join('common', 'SConscript'))
# cpu porting code files
group = group + SConscript(os.path.join(rtconfig.CPU, 'SConscript'))
if rtconfig.CPU != 'common':
group = group + SConscript(os.path.join(rtconfig.CPU, 'SConscript'))
Return('group')
menu "RT-Thread MIPS CPU"
config RT_USING_FPU
bool "Using Float Point Unit"
default n
help
Using Float Point Unit in code.
endmenu
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
* Assembly Macros For MIPS
*
* Copyright (C) 1995, 1996, 1997, 1999, 2001 by Ralf Baechle
* Copyright (C) 1999 by Silicon Graphics, Inc.
* Copyright (C) 2001 MIPS Technologies, Inc.
* Copyright (C) 2002 Maciej W. Rozycki
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* Some useful macros for MIPS assembler code
* SPDX-License-Identifier: Apache-2.0
*
* Some of the routines below contain useless nops that will be optimized
* away by gas in -O mode. These nops are however required to fill delay
* slots in noreorder mode.
* Change Logs:
* Date Author Notes
* 2019-12-04 Jiaxun Yang Initial version
*/
#ifndef __ASM_H__
#define __ASM_H__
......@@ -21,94 +18,94 @@
* LEAF - declare leaf routine
*/
#define LEAF(symbol) \
.globl symbol; \
.align 2; \
.type symbol,@function; \
.ent symbol,0; \
.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; \
.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
.end function; \
.size function,.-function
/*
* EXPORT - export definition of symbol
*/
#define EXPORT(symbol) \
.globl symbol; \
.globl symbol; \
symbol:
/*
* FEXPORT - export definition of a function symbol
*/
#define FEXPORT(symbol) \
.globl symbol; \
.type symbol,@function; \
.globl symbol; \
.type symbol,@function; \
symbol:
/*
* Global data declaration with size.
*/
#define EXPORTS(name,sz) \
.globl name; \
.type name,@object; \
.size 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; \
.weakext name; \
.type name,@object; \
.size name,sz; \
name:
/*
* Global data reference with size.
*/
#define IMPORT(name, size) \
.extern name,size
.extern name,size
/*
* Global zeroed data.
*/
#define BSS(name,size) \
.type name,@object; \
.comm name,size
.type name,@object; \
.comm name,size
/*
* Local zeroed data.
*/
#define LBSS(name,size) \
.lcomm name,size
.lcomm name,size
/*
* ABS - export absolute symbol
*/
#define ABS(symbol,value) \
.globl symbol; \
.globl symbol; \
symbol = value
#define TEXT(msg) \
.pushsection .data; \
.pushsection .data; \
8: .asciiz msg; \
.popsection;
.popsection;
#define ENTRY(name) \
......
/*
* Copyright (c) 2006-2019, 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_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
sw sp, 0(a0) /* store sp in preempted tasks TCB */
lw 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:
lw 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:
la t0, rt_thread_switch_interrupt_flag
lw t1, 0(t0)
nop
bnez t1, _reswitch
nop
li t1, 0x01 /* set rt_thread_switch_interrupt_flag to 1 */
sw t1, 0(t0)
la t0, rt_interrupt_from_thread /* set rt_interrupt_from_thread */
sw a0, 0(t0)
_reswitch:
la t0, rt_interrupt_to_thread /* set rt_interrupt_to_thread */
sw 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 */
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
*/
la k0, rt_thread_switch_interrupt_flag
lw k1, 0(k0)
beqz k1, spurious_interrupt
nop
sw zero, 0(k0) /* clear flag */
nop
/*
* switch to the new thread
*/
la k0, rt_interrupt_from_thread
lw k1, 0(k0)
nop
sw sp, 0(k1) /* store sp in preempted task TCB */
la k0, rt_interrupt_to_thread
lw k1, 0(k0)
nop
lw sp, 0(k1) /* get new task stack pointer */
j spurious_interrupt
nop
spurious_interrupt:
RESTORE_ALL_AND_RET
.set reorder
/*
* Copyright (c) 2006-2019, 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>
.section ".start", "ax"
.set noreorder
/* the program entry */
.globl _rtthread_entry
_rtthread_entry:
#ifndef RT_USING_SELF_BOOT
.globl _start
_start:
#endif
la ra, _rtthread_entry
/* disable interrupt */
mtc0 zero, CP0_CAUSE
mtc0 zero, CP0_STATUS # Set CPU to disable interrupt.
ehb
/* setup stack pointer */
la sp, _system_stack
la gp, _gp
bal rt_cpu_early_init
nop
/* clear bss */
la t0, __bss_start
la t1, __bss_end
_clr_bss_loop:
sw zero, 0(t0)
bne t0, t1, _clr_bss_loop
addiu t0, t0, 4
/* jump to RT-Thread RTOS */
jal rtthread_startup
nop
/* restart, never die */
j _start
nop
/*
* Copyright (c) 2006-2019, 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_uint32_t __ebase_entry;
rt_uint32_t rt_interrupt_from_thread;
rt_uint32_t rt_interrupt_to_thread;
rt_uint32_t rt_thread_switch_interrupt_flag;
rt_base_t rt_hw_interrupt_disable(void)
{
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 31
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 = sys_exception_handlers[n];
if ((n == 0) || (n > RT_EXCEPTION_MAX) || (!func))
{
return 0;
}
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%08x, CAUSE: 0x%08x\n", read_c0_epc(), read_c0_cause());
rt_kprintf("ST0: 0x%08x ",regs->cp0_status);
rt_kprintf("ErrorPC: 0x%08x\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_uint32_t ebase = (rt_uint32_t)&__ebase_entry;
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_uint32_t cause, exccode;
exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE;
if (exccode == 0) {
rt_uint32_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));
}
/*@}*/
/*
* File : cpu.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2010, RT-Thread Development Team
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2010-05-17 swkyer first version
* 2019-12-04 Jiaxun Yang Initial version
*/
#ifndef __EXCEPTION_H__
#define __EXCEPTION_H__
#include "ptrace.h"
/*
* important register numbers
*/
#define REG_EPC 37
#define REG_FP 72
#define REG_SP 29
/*
* Stack layout for the GDB exception handler
* Derived from the stack layout described in asm-mips/stackframe.h
*
* The first PTRSIZE*6 bytes are argument save space for C subroutines.
*/
#define NUMREGS 90
#define GDB_FR_REG0 (PTRSIZE*6) /* 0 */
#define GDB_FR_REG1 ((GDB_FR_REG0) + LONGSIZE) /* 1 */
#define GDB_FR_REG2 ((GDB_FR_REG1) + LONGSIZE) /* 2 */
#define GDB_FR_REG3 ((GDB_FR_REG2) + LONGSIZE) /* 3 */
#define GDB_FR_REG4 ((GDB_FR_REG3) + LONGSIZE) /* 4 */
#define GDB_FR_REG5 ((GDB_FR_REG4) + LONGSIZE) /* 5 */
#define GDB_FR_REG6 ((GDB_FR_REG5) + LONGSIZE) /* 6 */
#define GDB_FR_REG7 ((GDB_FR_REG6) + LONGSIZE) /* 7 */
#define GDB_FR_REG8 ((GDB_FR_REG7) + LONGSIZE) /* 8 */
#define GDB_FR_REG9 ((GDB_FR_REG8) + LONGSIZE) /* 9 */
#define GDB_FR_REG10 ((GDB_FR_REG9) + LONGSIZE) /* 10 */
#define GDB_FR_REG11 ((GDB_FR_REG10) + LONGSIZE) /* 11 */
#define GDB_FR_REG12 ((GDB_FR_REG11) + LONGSIZE) /* 12 */
#define GDB_FR_REG13 ((GDB_FR_REG12) + LONGSIZE) /* 13 */
#define GDB_FR_REG14 ((GDB_FR_REG13) + LONGSIZE) /* 14 */
#define GDB_FR_REG15 ((GDB_FR_REG14) + LONGSIZE) /* 15 */
#define GDB_FR_REG16 ((GDB_FR_REG15) + LONGSIZE) /* 16 */
#define GDB_FR_REG17 ((GDB_FR_REG16) + LONGSIZE) /* 17 */
#define GDB_FR_REG18 ((GDB_FR_REG17) + LONGSIZE) /* 18 */
#define GDB_FR_REG19 ((GDB_FR_REG18) + LONGSIZE) /* 19 */
#define GDB_FR_REG20 ((GDB_FR_REG19) + LONGSIZE) /* 20 */
#define GDB_FR_REG21 ((GDB_FR_REG20) + LONGSIZE) /* 21 */
#define GDB_FR_REG22 ((GDB_FR_REG21) + LONGSIZE) /* 22 */
#define GDB_FR_REG23 ((GDB_FR_REG22) + LONGSIZE) /* 23 */
#define GDB_FR_REG24 ((GDB_FR_REG23) + LONGSIZE) /* 24 */
#define GDB_FR_REG25 ((GDB_FR_REG24) + LONGSIZE) /* 25 */
#define GDB_FR_REG26 ((GDB_FR_REG25) + LONGSIZE) /* 26 */
#define GDB_FR_REG27 ((GDB_FR_REG26) + LONGSIZE) /* 27 */
#define GDB_FR_REG28 ((GDB_FR_REG27) + LONGSIZE) /* 28 */
#define GDB_FR_REG29 ((GDB_FR_REG28) + LONGSIZE) /* 29 */
#define GDB_FR_REG30 ((GDB_FR_REG29) + LONGSIZE) /* 30 */
#define GDB_FR_REG31 ((GDB_FR_REG30) + LONGSIZE) /* 31 */
/*
* Saved special registers
*/
#define GDB_FR_STATUS ((GDB_FR_REG31) + LONGSIZE) /* 32 */
#define GDB_FR_LO ((GDB_FR_STATUS) + LONGSIZE) /* 33 */
#define GDB_FR_HI ((GDB_FR_LO) + LONGSIZE) /* 34 */
#define GDB_FR_BADVADDR ((GDB_FR_HI) + LONGSIZE) /* 35 */
#define GDB_FR_CAUSE ((GDB_FR_BADVADDR) + LONGSIZE) /* 36 */
#define GDB_FR_EPC ((GDB_FR_CAUSE) + LONGSIZE) /* 37 */
///*
// * Saved floating point registers
// */
//#define GDB_FR_FPR0 ((GDB_FR_EPC) + LONGSIZE) /* 38 */
//#define GDB_FR_FPR1 ((GDB_FR_FPR0) + LONGSIZE) /* 39 */
//#define GDB_FR_FPR2 ((GDB_FR_FPR1) + LONGSIZE) /* 40 */
//#define GDB_FR_FPR3 ((GDB_FR_FPR2) + LONGSIZE) /* 41 */
//#define GDB_FR_FPR4 ((GDB_FR_FPR3) + LONGSIZE) /* 42 */
//#define GDB_FR_FPR5 ((GDB_FR_FPR4) + LONGSIZE) /* 43 */
//#define GDB_FR_FPR6 ((GDB_FR_FPR5) + LONGSIZE) /* 44 */
//#define GDB_FR_FPR7 ((GDB_FR_FPR6) + LONGSIZE) /* 45 */
//#define GDB_FR_FPR8 ((GDB_FR_FPR7) + LONGSIZE) /* 46 */
//#define GDB_FR_FPR9 ((GDB_FR_FPR8) + LONGSIZE) /* 47 */
//#define GDB_FR_FPR10 ((GDB_FR_FPR9) + LONGSIZE) /* 48 */
//#define GDB_FR_FPR11 ((GDB_FR_FPR10) + LONGSIZE) /* 49 */
//#define GDB_FR_FPR12 ((GDB_FR_FPR11) + LONGSIZE) /* 50 */
//#define GDB_FR_FPR13 ((GDB_FR_FPR12) + LONGSIZE) /* 51 */
//#define GDB_FR_FPR14 ((GDB_FR_FPR13) + LONGSIZE) /* 52 */
//#define GDB_FR_FPR15 ((GDB_FR_FPR14) + LONGSIZE) /* 53 */
//#define GDB_FR_FPR16 ((GDB_FR_FPR15) + LONGSIZE) /* 54 */
//#define GDB_FR_FPR17 ((GDB_FR_FPR16) + LONGSIZE) /* 55 */
//#define GDB_FR_FPR18 ((GDB_FR_FPR17) + LONGSIZE) /* 56 */
//#define GDB_FR_FPR19 ((GDB_FR_FPR18) + LONGSIZE) /* 57 */
//#define GDB_FR_FPR20 ((GDB_FR_FPR19) + LONGSIZE) /* 58 */
//#define GDB_FR_FPR21 ((GDB_FR_FPR20) + LONGSIZE) /* 59 */
//#define GDB_FR_FPR22 ((GDB_FR_FPR21) + LONGSIZE) /* 60 */
//#define GDB_FR_FPR23 ((GDB_FR_FPR22) + LONGSIZE) /* 61 */
//#define GDB_FR_FPR24 ((GDB_FR_FPR23) + LONGSIZE) /* 62 */
//#define GDB_FR_FPR25 ((GDB_FR_FPR24) + LONGSIZE) /* 63 */
//#define GDB_FR_FPR26 ((GDB_FR_FPR25) + LONGSIZE) /* 64 */
//#define GDB_FR_FPR27 ((GDB_FR_FPR26) + LONGSIZE) /* 65 */
//#define GDB_FR_FPR28 ((GDB_FR_FPR27) + LONGSIZE) /* 66 */
//#define GDB_FR_FPR29 ((GDB_FR_FPR28) + LONGSIZE) /* 67 */
//#define GDB_FR_FPR30 ((GDB_FR_FPR29) + LONGSIZE) /* 68 */
//#define GDB_FR_FPR31 ((GDB_FR_FPR30) + LONGSIZE) /* 69 */
//
//#define GDB_FR_FSR ((GDB_FR_FPR31) + LONGSIZE) /* 70 */
//#define GDB_FR_FIR ((GDB_FR_FSR) + LONGSIZE) /* 71 */
//#define GDB_FR_FRP ((GDB_FR_FIR) + LONGSIZE) /* 72 */
//
//#define GDB_FR_DUMMY ((GDB_FR_FRP) + LONGSIZE) /* 73, unused ??? */
//
///*
// * Again, CP0 registers
// */
//#define GDB_FR_CP0_INDEX ((GDB_FR_DUMMY) + LONGSIZE) /* 74 */
#define GDB_FR_FRP ((GDB_FR_EPC) + LONGSIZE) /* 72 */
#define GDB_FR_CP0_INDEX ((GDB_FR_FRP) + LONGSIZE) /* 74 */
#define GDB_FR_CP0_RANDOM ((GDB_FR_CP0_INDEX) + LONGSIZE) /* 75 */
#define GDB_FR_CP0_ENTRYLO0 ((GDB_FR_CP0_RANDOM) + LONGSIZE)/* 76 */
#define GDB_FR_CP0_ENTRYLO1 ((GDB_FR_CP0_ENTRYLO0) + LONGSIZE)/* 77 */
#define GDB_FR_CP0_CONTEXT ((GDB_FR_CP0_ENTRYLO1) + LONGSIZE)/* 78 */
#define GDB_FR_CP0_PAGEMASK ((GDB_FR_CP0_CONTEXT) + LONGSIZE)/* 79 */
#define GDB_FR_CP0_WIRED ((GDB_FR_CP0_PAGEMASK) + LONGSIZE)/* 80 */
#define GDB_FR_CP0_REG7 ((GDB_FR_CP0_WIRED) + LONGSIZE) /* 81 */
#define GDB_FR_CP0_REG8 ((GDB_FR_CP0_REG7) + LONGSIZE) /* 82 */
#define GDB_FR_CP0_REG9 ((GDB_FR_CP0_REG8) + LONGSIZE) /* 83 */
#define GDB_FR_CP0_ENTRYHI ((GDB_FR_CP0_REG9) + LONGSIZE) /* 84 */
#define GDB_FR_CP0_REG11 ((GDB_FR_CP0_ENTRYHI) + LONGSIZE)/* 85 */
#define GDB_FR_CP0_REG12 ((GDB_FR_CP0_REG11) + LONGSIZE) /* 86 */
#define GDB_FR_CP0_REG13 ((GDB_FR_CP0_REG12) + LONGSIZE) /* 87 */
#define GDB_FR_CP0_REG14 ((GDB_FR_CP0_REG13) + LONGSIZE) /* 88 */
#define GDB_FR_CP0_PRID ((GDB_FR_CP0_REG14) + LONGSIZE) /* 89 */
#define GDB_FR_SIZE ((((GDB_FR_CP0_PRID) + LONGSIZE) + (PTRSIZE-1)) & ~(PTRSIZE-1))
/*
* This is the same as above, but for the high-level
* part of the INT stub.
*/
typedef struct pt_regs_s
{
/* Saved main processor registers. */
rt_base_t regs[32];
/* Saved special registers. */
rt_base_t cp0_status;
rt_base_t hi;
rt_base_t lo;
rt_base_t cp0_badvaddr;
rt_base_t cp0_cause;
rt_base_t cp0_epc;
} pt_regs_t;
#ifndef __ASSEMBLY__
typedef void (* exception_func_t)(pt_regs_t *regs);
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);
void install_default_execpt_handle(void);
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__ */
/*
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-12-04 Jiaxun Yang Initial version
*/
.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
/* 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
la $k0, mips_irq_handle
jr $k0
nop
.set reorder
/* interrupt handler */
_irq_handler:
.set noreorder
la $k0, mips_irq_handle
jr $k0
nop
.set reorder
......@@ -12,14 +12,12 @@
#define _COMMON_MIPS_H_
#include "mips_cfg.h"
#include "ptrace.h"
#include "mips_types.h"
#include "mips_asm.h"
#include "mips_def.h"
#include "asm.h"
#include "mips_regs.h"
#include "mips_addrspace.h"
#include "mips_cache.h"
#include "mips_context.h"
#include "mips_excpt.h"
#include "exception.h"
#endif /* _COMMON_MIPS_H_ */
/*
* File : mips_addrspace.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
* Copyright (c) 2006-2019, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016912 Urey the first version
* 2019-12-04 Jiaxun Yang Initial version
*/
#ifndef _MIPS_ADDRSPACE_H_
......@@ -108,11 +94,11 @@
* 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
#define KUSEGBASE 0x00000000
#define KSEG0BASE 0x80000000
#define KSEG1BASE 0xa0000000
#define KSEG2BASE 0xc0000000
#define KSEG3BASE 0xe0000000
#define CKUSEG 0x00000000
#define CKSEG0 0x80000000
......@@ -147,14 +133,6 @@
* Returns the uncached address of a sdram address
*/
#ifndef __ASSEMBLY__
#if defined(CONFIG_SOC_AU1X00) || defined(CONFIG_TB0229)
/* We use a 36 bit physical address map here and
cannot access physical memory directly from core */
#define UNCACHED_SDRAM(a) (((unsigned long)(a)) | 0x20000000)
#else /* !CONFIG_SOC_AU1X00 */
#define UNCACHED_SDRAM(a) CKSEG1ADDR(a)
#endif /* CONFIG_SOC_AU1X00 */
#endif /* __ASSEMBLY__ */
/*
* The ultimate limited of the 64-bit MIPS architecture: 2 bits for selecting
......@@ -162,46 +140,19 @@
* R8000 implements most with its 48-bit physical address space.
*/
#define TO_PHYS_MASK _CONST64_(0x07ffffffffffffff) /* 2^^59 - 1 */
#ifndef CONFIG_CPU_R8000
/*
* The R8000 doesn't have the 32-bit compat spaces so we don't define them
* in order to catch bugs in the source code.
*/
#define COMPAT_K1BASE32 _CONST64_(0xffffffffa0000000)
#define PHYS_TO_COMPATK1(x) ((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */
#endif
#define KDM_TO_PHYS(x) (_ACAST64_ (x) & TO_PHYS_MASK)
#define PHYS_TO_K0(x) (_ACAST64_ (x) | CAC_BASE)
#endif
#ifndef __ASSEMBLY__
/*
* Change virtual addresses to physical addresses and vv.
* These are trivial on the 1:1 Linux/MIPS mapping
*/
static inline phys_addr_t virt_to_phys(volatile void * address)
{
#ifndef CONFIG_64BIT
return CPHYSADDR(address);
#else
return XPHYSADDR(address);
#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
}
static inline void * phys_to_virt(unsigned long address)
{
#ifndef CONFIG_64BIT
return (void *)KSEG0ADDR(address);
#else
return (void *)CKSEG0ADDR(address);
#endif
}
#endif
#endif /* _MIPS_ADDRSPACE_H_ */
/*
* File : mips_asm.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 201697 Urey the first version
*/
#ifndef _MIPS_ASM_H_
#define _MIPS_ASM_H_
/* ********************************************************************* */
/* Interface macro & data definition */
#ifdef __ASSEMBLY__
/******** ASSEMBLER SPECIFIC DEFINITIONS ********/
#ifdef __ghs__
#define ALIGN(x) .##align (1 << (x))
#else
#define ALIGN(x) .##align (x)
#endif
#ifdef __ghs__
#define SET_MIPS3()
#define SET_MIPS0()
#define SET_PUSH()
#define SET_POP()
#else
#define SET_MIPS3() .##set mips3
#define SET_MIPS0() .##set mips0
#define SET_PUSH() .##set push
#define SET_POP() .##set pop
#endif
/* Different assemblers have different requirements for how to
* indicate that the next section is bss :
*
* Some use : .bss
* Others use : .section bss
*
* We select which to use based on _BSS_OLD_, which may be defined
* in makefile.
*/
#ifdef _BSS_OLD_
#define BSS .##section bss
#else
#define BSS .##bss
#endif
#define LEAF(name)\
.##text;\
.##globl name;\
.##ent name;\
name:
#define SLEAF(name)\
.##text;\
.##ent name;\
name:
#ifdef __ghs__
#define END(name)\
.##end name
#else
#define END(name)\
.##size name,.-name;\
.##end name
#endif
#define EXTERN(name)
#else
#define U64 unsigned long long
#define U32 unsigned int
#define U16 unsigned short
#define U8 unsigned char
#define S64 signed long long
#define S32 int
#define S16 short int
#define S8 signed char
//#define bool U8
#ifndef _SIZE_T_
#define _SIZE_T_
#ifdef __ghs__
typedef unsigned int size_t;
#else
typedef unsigned long size_t;
#endif
#endif
/* Sets the result on bPort */
#define BIT_SET(bPort,bBitMask) (bPort |= bBitMask)
#define BIT_CLR(bPort,bBitMask) (bPort &= ~bBitMask)
/* Returns the result */
#define GET_BIT_SET(bPort,bBitMask) (bPort | bBitMask)
#define GET_BIT_CLR(bPort,bBitMask) (bPort & ~bBitMask)
/* Returns 0 if the condition is False & a non-zero value if it is True */
#define TEST_BIT_SET(bPort,bBitMask) (bPort & bBitMask)
#define TEST_BIT_CLR(bPort,bBitMask) ((~bPort) & bBitMask)
/* Split union definitions */
typedef union tunSU16
{
U16 hwHW;
struct tst2U8
{
U8 bB0;
U8 bB1;
}st2U8;
}tunSU16;
typedef union tunSU32
{
U32 wW;
struct tst2U16
{
U16 hwHW0;
U16 hwHW1;
}st2U16;
struct tst4U8
{
U8 bB0;
U8 bB1;
U8 bB2;
U8 bB3;
}st4U8;
}tunSU32;
#endif /* #ifdef __ASSEMBLY__ */
/******** DEFINITIONS FOR BOTH ASSEMBLER AND C ********/
#define NO_ERR 0x00000000 /* operation completed successfully */
#define ERR 0xffffffff /* operation completed not successfully */
#define False 0
#define True !False
#ifndef NULL
#define NULL ((void *)0)
#endif//NULL
#ifndef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#endif//MIN
#ifndef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif//MAX
#define MAXUINT(w) (\
((w) == sizeof(U8)) ? 0xFFU :\
((w) == sizeof(U16)) ? 0xFFFFU :\
((w) == sizeof(U32)) ? 0xFFFFFFFFU : 0\
)
#define MAXINT(w) (\
((w) == sizeof(S8)) ? 0x7F :\
((w) == sizeof(S16)) ? 0x7FFF :\
((w) == sizeof(S32)) ? 0x7FFFFFFF : 0\
)
#define MSK(n) ((1 << (n)) - 1)
#define KUSEG_MSK 0x80000000
#define KSEG_MSK 0xE0000000
#define KUSEGBASE 0x00000000
#define KSEG0BASE 0x80000000
#define KSEG1BASE 0xA0000000
#define KSSEGBASE 0xC0000000
#define KSEG3BASE 0xE0000000
/* Below macros perform the following functions :
*
* KSEG0 : Converts KSEG0/1 or physical addr (below 0.5GB) to KSEG0.
* KSEG1 : Converts KSEG0/1 or physical addr (below 0.5GB) to KSEG1.
* PHYS : Converts KSEG0/1 or physical addr (below 0.5GB) to physical address.
* KSSEG : Not relevant for converting, but used for determining range.
* KSEG3 : Not relevant for converting, but used for determining range.
* KUSEG : Not relevant for converting, but used for determining range.
* KSEG0A : Same as KSEG0 but operates on register rather than constant.
* KSEG1A : Same as KSEG1 but operates on register rather than constant.
* PHYSA : Same as PHYS but operates on register rather than constant.
* CACHED : Alias for KSEG0 macro .
* (Note that KSEG0 cache attribute is determined by K0
* field of Config register, but this is typically cached).
* UNCACHED : Alias for KSEG1 macro .
*/
#ifdef __ASSEMBLY__
#define KSEG0(addr) (((addr) & ~KSEG_MSK) | KSEG0BASE)
#define KSEG1(addr) (((addr) & ~KSEG_MSK) | KSEG1BASE)
#define KSSEG(addr) (((addr) & ~KSEG_MSK) | KSSEGBASE)
#define KSEG3(addr) (((addr) & ~KSEG_MSK) | KSEG3BASE)
#define KUSEG(addr) (((addr) & ~KUSEG_MSK) | KUSEGBASE)
#define PHYS(addr) ( (addr) & ~KSEG_MSK)
#define KSEG0A(reg) and reg, ~KSEG_MSK; or reg, KSEG0BASE
#define KSEG1A(reg) and reg, ~KSEG_MSK; or reg, KSEG1BASE
#define PHYSA(reg) and reg, ~KSEG_MSK
#else
#define KSEG0(addr) (((U32)(addr) & ~KSEG_MSK) | KSEG0BASE)
#define KSEG1(addr) (((U32)(addr) & ~KSEG_MSK) | KSEG1BASE)
#define KSSEG(addr) (((U32)(addr) & ~KSEG_MSK) | KSSEGBASE)
#define KSEG3(addr) (((U32)(addr) & ~KSEG_MSK) | KSEG3BASE)
#define KUSEG(addr) (((U32)(addr) & ~KUSEG_MSK) | KUSEGBASE)
#define PHYS(addr) ((U32)(addr) & ~KSEG_MSK)
#endif
#define CACHED(addr) KSEG0(addr)
#define UNCACHED(addr) KSEG1(addr)
#ifdef __ASSEMBLY__
/* Macroes to access variables at constant addresses
* Compensates for signed 16 bit displacement
* Typical use: li a0, HIKSEG1(ATLAS_ASCIIWORD)
* sw v1, LO_OFFS(ATLAS_ASCIIWORD)(a0)
*/
#define HIKSEG0(addr) ((KSEG0(addr) + 0x8000) & 0xffff0000)
#define HIKSEG1(addr) ((KSEG1(addr) + 0x8000) & 0xffff0000)
#define HI_PART(addr) (((addr) + 0x8000) & 0xffff0000)
#define LO_OFFS(addr) ((addr) & 0xffff)
#endif
/* Most/Least significant 32 bit from 64 bit double word */
#define HI32(data64) ((U32)(data64 >> 32))
#define LO32(data64) ((U32)(data64 & 0xFFFFFFFF))
#if ((!defined(__ASSEMBLY__)) && (!defined(__LANGUAGE_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
/* Register field mapping */
#define REGFIELD(reg, rfld) (((reg) & rfld##_MSK) >> rfld##_SHF)
/* absolute register address, access */
#define REGA(addr) REG32(addr)
/* physical register address, access: base address + offsett */
#define REGP(base,phys) REG32( (U32)(base) + (phys) )
/* relative register address, access: base address + offsett */
#define REG(base,offs) REG32( (U32)(base) + offs##_##OFS )
/* relative register address, access: base address + offsett */
#define REG_8(base,offs) REG8( (U32)(base) + offs##_##OFS )
/* relative register address, access: base address + offsett */
#define REG_16(base,offs) REG16( (U32)(base) + offs##_##OFS )
/* relative register address, access: base address + offsett */
#define REG_64(base,offs) REG64( (U32)(base) + offs##_##OFS )
/**************************************
* Macroes not used by YAMON any more
* (kept for backwards compatibility)
*/
/* register read field */
#define REGARD(addr,fld) ((REGA(addr) & addr##_##fld##_##MSK) \
>> addr##_##fld##_##SHF)
/* register write numeric field value */
#define REGAWRI(addr,fld,intval) ((REGA(addr) & ~(addr##_##fld##_##MSK))\
| ((intval) << addr##_##fld##_##SHF))
/* register write enumerated field value */
#define REGAWRE(addr,fld,enumval) ((REGA(addr) & ~(addr##_##fld##_##MSK))\
| ((addr##_##fld##_##enumval) << addr##_##fld##_##SHF))
/* Examples:
*
* exccode = REGARD(CPU_CAUSE,EXC);
*
* REGA(SDR_CONTROL) = REGAWRI(OSG_CONTROL,TMO,17)
* | REGAWRE(OSG_CONTROL,DTYPE,PC1);
*/
/* register read field */
#define REGRD(base,offs,fld) ((REG(base,offs) & offs##_##fld##_##MSK) \
>> offs##_##fld##_##SHF)
/* register write numeric field value */
#define REGWRI(base,offs,fld,intval)((REG(base,offs)& ~(offs##_##fld##_##MSK))\
| (((intval) << offs##_##fld##_##SHF) & offs##_##fld##_##MSK))
/* register write enumerated field value */
#define REGWRE(base,offs,fld,enumval)((REG(base,offs) & ~(offs##_##fld##_##MSK))\
| ((offs##_##fld##_##enumval) << offs##_##fld##_##SHF))
/* physical register read field */
#define REGPRD(base,phys,fld) ((REGP(base,phys) & phys##_##fld##_##MSK) \
>> phys##_##fld##_##SHF)
/* physical register write numeric field value */
#define REGPWRI(base,phys,fld,intval)((REGP(base,phys)& ~(phys##_##fld##_##MSK))\
| ((intval) << phys##_##fld##_##SHF))
/* physical register write enumerated field value */
#define REGPWRE(base,phys,fld,enumval)((REGP(base,phys) & ~(phys##_##fld##_##MSK))\
| ((phys##_##fld##_##enumval) << phys##_##fld##_##SHF))
/*
* End of macroes not used by YAMON any more
*********************************************/
/* Endian related macros */
#define SWAP_BYTEADDR32( addr ) ( (addr) ^ 0x3 )
#define SWAP_U16ADDR32( addr ) ( (addr) ^ 0x2 )
/* Set byte address to little endian format */
#ifdef EL
#define SWAP_BYTEADDR_EL(addr) addr
#else
#define SWAP_BYTEADDR_EL(addr) SWAP_BYTEADDR32( addr )
#endif
/* Set byte address to big endian format */
#ifdef EB
#define SWAP_BYTEADDR_EB(addr) addr
#else
#define SWAP_BYTEADDR_EB(addr) SWAP_BYTEADDR32( addr )
#endif
/* Set U16 address to little endian format */
#ifdef EL
#define SWAP_U16ADDR_EL(addr) addr
#else
#define SWAP_U16ADDR_EL(addr) SWAP_U16ADDR32( addr )
#endif
/* Set U16 address to big endian format */
#ifdef EB
#define SWAP_U16ADDR_EB(addr) addr
#else
#define SWAP_U16ADDR_EB(addr) SWAP_U16ADDR32( addr )
#endif
#ifdef EL
#define REGW32LE(addr, data) REG32(addr) = (data)
#define REGR32LE(addr, data) (data) = REG32(addr)
#else
#define REGW32LE(addr, data) REG32(addr) = SWAPEND32(data)
#define REGR32LE(addr, data) (data) = REG32(addr), (data) = SWAPEND32(data)
#endif
/* Set of 'LE'-macros, convert by BE: */
#ifdef EL
#define CPU_TO_LE32( value ) (value)
#define LE32_TO_CPU( value ) (value)
#define CPU_TO_LE16( value ) (value)
#define LE16_TO_CPU( value ) (value)
#else
#define CPU_TO_LE32( value ) ( ( ((U32)value) << 24) | \
((0x0000FF00UL & ((U32)value)) << 8) | \
((0x00FF0000UL & ((U32)value)) >> 8) | \
( ((U32)value) >> 24) )
#define LE32_TO_CPU( value ) CPU_TO_LE32( value )
#define CPU_TO_LE16( value ) ( ((U16)(((U16)value) << 8)) | \
((U16)(((U16)value) >> 8)) )
#define LE16_TO_CPU( value ) CPU_TO_LE16( value )
#endif
/* Set of 'BE'-macros, convert by LE: */
#ifdef EB
#define CPU_TO_BE32( value ) (value)
#define BE32_TO_CPU( value ) (value)
#define CPU_TO_BE16( value ) (value)
#define BE16_TO_CPU( value ) (value)
#else
#define CPU_TO_BE32( value ) ( ( ((U32)value) << 24) | \
((0x0000FF00UL & ((U32)value)) << 8) | \
((0x00FF0000UL & ((U32)value)) >> 8) | \
( ((U32)value) >> 24) )
#define BE32_TO_CPU( value ) CPU_TO_BE32( value )
#define CPU_TO_BE16( value ) ( ((U16)(((U16)value) << 8)) | \
((U16)(((U16)value) >> 8)) )
#define BE16_TO_CPU( value ) CPU_TO_BE16( value )
#endif
/* Control characters */
#define CTRL_A ('A'-0x40)
#define CTRL_B ('B'-0x40)
#define CTRL_C ('C'-0x40)
#define CTRL_D ('D'-0x40)
#define CTRL_E ('E'-0x40)
#define CTRL_F ('F'-0x40)
#define CTRL_H ('H'-0x40)
#define CTRL_K ('K'-0x40)
#define CTRL_N ('N'-0x40)
#define CTRL_P ('P'-0x40)
#define CTRL_U ('U'-0x40)
#define BACKSPACE 0x08
#define DEL 0x7F
#define TAB 0x09
#define CR 0x0D /* Enter Key */
#define LF 0x0A
#define ESC 0x1B
#define SP 0x20
#define CSI 0x9B
/* DEF2STR(x) converts #define symbol to string */
#define DEF2STR1(x) #x
#define DEF2STR(x) DEF2STR1(x)
#endif /* _MIPS_ASM_H_ */
......@@ -19,7 +19,7 @@
*
* Change Logs:
* Date Author Notes
* 201697 Urey the first version
* 2016-09-07 Urey the first version
*/
#include <rtthread.h>
......
......@@ -19,7 +19,7 @@
*
* Change Logs:
* Date Author Notes
* 2016910 Urey the first version
* 2016-09-07 Urey the first version
*/
#ifndef _MIPS_CACHE_H_
......@@ -38,11 +38,7 @@
#define INDEX_LOAD_TAG_D 0x05
#define INDEX_STORE_TAG_I 0x08
#define INDEX_STORE_TAG_D 0x09
#if defined(CONFIG_CPU_LOONGSON2)
#define HIT_INVALIDATE_I 0x00
#else
#define HIT_INVALIDATE_I 0x10
#endif
#define HIT_INVALIDATE_D 0x11
#define HIT_WRITEBACK_INV_D 0x15
......
......@@ -19,7 +19,7 @@
*
* Change Logs:
* Date Author Notes
* 2016Äê9ÔÂ10ÈÕ Urey the first version
* 2016-09-07 Urey the first version
*/
#ifndef _MIPS_CFG_H_
......@@ -30,12 +30,12 @@
typedef struct mips32_core_cfg
{
uint16_t icache_line_size;
// uint16_t icache_lines_per_way;
// uint16_t icache_ways;
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_lines_per_way;
uint16_t dcache_ways;
uint16_t dcache_size;
uint16_t max_tlb_entries; /* number of tlb entry */
......
/*
* File : mips_context_asm.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 201697 Urey the first version
*/
#ifndef _MIPS_CONTEXT_ASM_H_
#define _MIPS_CONTEXT_ASM_H_
#define CONTEXT_SIZE ( STK_CTX_SIZE + FPU_ADJ )
#ifdef __mips_hard_float
#define FPU_ADJ (32 * 4 + 8) /* FP0-FP31 + CP1_STATUS */
#define FPU_CTX ( CONTEXT_SIZE - FPU_ADJ )
#else
#define FPU_ADJ 0
#endif
#ifdef __ASSEMBLY__
#ifdef __mips_hard_float
.global _fpctx_save
.global _fpctx_load
#endif
.macro SAVE_CONTEXT
.set push
.set noat
.set noreorder
.set volatile
//save SP
move k1, sp
move k0, sp
subu sp, k1, CONTEXT_SIZE
sw k0, (29 * 4)(sp)
//save REG
sw $0, ( 0 * 4)(sp)
sw $1, ( 1 * 4)(sp)
sw $2, ( 2 * 4)(sp)
sw $3, ( 3 * 4)(sp)
sw $4, ( 4 * 4)(sp)
sw $5, ( 5 * 4)(sp)
sw $6, ( 6 * 4)(sp)
sw $7, ( 7 * 4)(sp)
sw $8, ( 8 * 4)(sp)
sw $9, ( 9 * 4)(sp)
sw $10, (10 * 4)(sp)
sw $11, (11 * 4)(sp)
sw $12, (12 * 4)(sp)
sw $13, (13 * 4)(sp)
sw $14, (14 * 4)(sp)
sw $15, (15 * 4)(sp)
sw $16, (16 * 4)(sp)
sw $17, (17 * 4)(sp)
sw $18, (18 * 4)(sp)
sw $19, (19 * 4)(sp)
sw $20, (20 * 4)(sp)
sw $21, (21 * 4)(sp)
sw $22, (22 * 4)(sp)
sw $23, (23 * 4)(sp)
sw $24, (24 * 4)(sp)
sw $25, (25 * 4)(sp)
/* K0 K1 */
sw $28, (28 * 4)(sp)
/* SP */
sw $30, (30 * 4)(sp)
sw $31, (31 * 4)(sp)
/* STATUS CAUSE EPC.... */
mfc0 $2, CP0_STATUS
sw $2, STK_OFFSET_SR(sp)
mfc0 $2, CP0_CAUSE
sw $2, STK_OFFSET_CAUSE(sp)
mfc0 $2, CP0_BADVADDR
sw $2, STK_OFFSET_BADVADDR(sp)
MFC0 $2, CP0_EPC
sw $2, STK_OFFSET_EPC(sp)
mfhi $2
sw $2, STK_OFFSET_HI(sp)
mflo $2
sw $2, STK_OFFSET_LO(sp)
#ifdef __mips_hard_float
add a0, sp,STK_CTX_SIZE
mfc0 t0, CP0_STATUS
.set push
.set at
or t0, M_StatusCU1
.set push
mtc0 t0, CP0_STATUS
cfc1 t0, CP1_STATUS
sw t0 , 0x00(a0)
swc1 $f0,(0x04 * 1)(a0)
swc1 $f1,(0x04 * 2)(a0)
swc1 $f2,(0x04 * 3)(a0)
swc1 $f3,(0x04 * 4)(a0)
swc1 $f4,(0x04 * 5)(a0)
swc1 $f5,(0x04 * 6)(a0)
swc1 $f6,(0x04 * 7)(a0)
swc1 $f7,(0x04 * 8)(a0)
swc1 $f8,(0x04 * 9)(a0)
swc1 $f9,(0x04 * 10)(a0)
swc1 $f10,(0x04 * 11)(a0)
swc1 $f11,(0x04 * 12)(a0)
swc1 $f12,(0x04 * 13)(a0)
swc1 $f13,(0x04 * 14)(a0)
swc1 $f14,(0x04 * 15)(a0)
swc1 $f15,(0x04 * 16)(a0)
swc1 $f16,(0x04 * 17)(a0)
swc1 $f17,(0x04 * 18)(a0)
swc1 $f18,(0x04 * 19)(a0)
swc1 $f19,(0x04 * 20)(a0)
swc1 $f20,(0x04 * 21)(a0)
swc1 $f21,(0x04 * 22)(a0)
swc1 $f22,(0x04 * 23)(a0)
swc1 $f23,(0x04 * 24)(a0)
swc1 $f24,(0x04 * 25)(a0)
swc1 $f25,(0x04 * 26)(a0)
swc1 $f26,(0x04 * 27)(a0)
swc1 $f27,(0x04 * 28)(a0)
swc1 $f28,(0x04 * 29)(a0)
swc1 $f29,(0x04 * 30)(a0)
swc1 $f30,(0x04 * 31)(a0)
swc1 $f31,(0x04 * 32)(a0)
nop
#endif
//restore a0
lw a0, (REG_A0 * 4)(sp)
.set pop
.endm
.macro RESTORE_CONTEXT
.set push
.set noat
.set noreorder
.set volatile
#ifdef __mips_hard_float
add a0, sp,STK_CTX_SIZE
mfc0 t0, CP0_STATUS
.set push
.set at
or t0, M_StatusCU1
.set noat
mtc0 t0, CP0_STATUS
lw t0 , 0x00(a0)
lwc1 $f0,(0x04 * 1)(a0)
lwc1 $f1,(0x04 * 2)(a0)
lwc1 $f2,(0x04 * 3)(a0)
lwc1 $f3,(0x04 * 4)(a0)
lwc1 $f4,(0x04 * 5)(a0)
lwc1 $f5,(0x04 * 6)(a0)
lwc1 $f6,(0x04 * 7)(a0)
lwc1 $f7,(0x04 * 8)(a0)
lwc1 $f8,(0x04 * 9)(a0)
lwc1 $f9,(0x04 * 10)(a0)
lwc1 $f10,(0x04 * 11)(a0)
lwc1 $f11,(0x04 * 12)(a0)
lwc1 $f12,(0x04 * 13)(a0)
lwc1 $f13,(0x04 * 14)(a0)
lwc1 $f14,(0x04 * 15)(a0)
lwc1 $f15,(0x04 * 16)(a0)
lwc1 $f16,(0x04 * 17)(a0)
lwc1 $f17,(0x04 * 18)(a0)
lwc1 $f18,(0x04 * 19)(a0)
lwc1 $f19,(0x04 * 20)(a0)
lwc1 $f20,(0x04 * 21)(a0)
lwc1 $f21,(0x04 * 22)(a0)
lwc1 $f22,(0x04 * 23)(a0)
lwc1 $f23,(0x04 * 24)(a0)
lwc1 $f24,(0x04 * 25)(a0)
lwc1 $f25,(0x04 * 26)(a0)
lwc1 $f26,(0x04 * 27)(a0)
lwc1 $f27,(0x04 * 28)(a0)
lwc1 $f28,(0x04 * 29)(a0)
lwc1 $f29,(0x04 * 30)(a0)
lwc1 $f30,(0x04 * 31)(a0)
lwc1 $f31,(0x04 * 32)(a0)
ctc1 t0, CP1_STATUS ;/* restore fpp status reg */
nop
#endif
/* ͨüĴ */
/* ZERO */
lw $1, ( 1 * 4)(sp)
/* V0 */
lw $3, ( 3 * 4)(sp)
lw $4, ( 4 * 4)(sp)
lw $5, ( 5 * 4)(sp)
lw $6, ( 6 * 4)(sp)
lw $7, ( 7 * 4)(sp)
lw $8, ( 8 * 4)(sp)
lw $9, ( 9 * 4)(sp)
lw $10, (10 * 4)(sp)
lw $11, (11 * 4)(sp)
lw $12, (12 * 4)(sp)
lw $13, (13 * 4)(sp)
lw $14, (14 * 4)(sp)
lw $15, (15 * 4)(sp)
lw $16, (16 * 4)(sp)
lw $17, (17 * 4)(sp)
lw $18, (18 * 4)(sp)
lw $19, (19 * 4)(sp)
lw $20, (20 * 4)(sp)
lw $21, (21 * 4)(sp)
lw $22, (22 * 4)(sp)
lw $23, (23 * 4)(sp)
lw $24, (24 * 4)(sp)
lw $25, (25 * 4)(sp)
lw $26, (26 * 4)(sp)
lw $27, (27 * 4)(sp)
lw $28, (28 * 4)(sp)
/* SP */
lw $30, (30 * 4)(sp)
lw $31, (31 * 4)(sp)
/* STATUS CAUSE EPC.... */
lw $2, STK_OFFSET_HI(sp)
mthi $2
lw $2, STK_OFFSET_LO(sp)
mtlo $2
lw $2, STK_OFFSET_SR(sp)
mtc0 $2, CP0_STATUS
lw $2, STK_OFFSET_BADVADDR(sp)
mtc0 $2, CP0_BADVADDR
lw $2, STK_OFFSET_CAUSE(sp)
mtc0 $2, CP0_CAUSE
lw $2, STK_OFFSET_EPC(sp)
MTC0 $2, CP0_EPC
//restore $2
lw $2, ( 2 * 4)(sp)
//restore sp
lw $29, (29 * 4)(sp)
eret
nop
.set pop
.endm
#endif
#endif /* _MIPS_CONTEXT_ASM_H_ */
此差异已折叠。
/*
* File : mips_excpt.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2016Äê9ÔÂ7ÈÕ Urey the first version
*/
#ifndef _MIPS_EXCPT_H_
#define _MIPS_EXCPT_H_
#include "mips_regs.h"
#ifndef __ASSEMBLY__
typedef void (* exception_func_t)(mips_reg_ctx *regs);
//extern exception_func_t mips_exception_handlers[];
int rt_hw_exception_init(void);
exception_func_t rt_set_except_vector(int n, exception_func_t func);
void install_default_execpt_handle(void);
#endif /* __ASSEMBLY__ */
#endif /* _MIPS_EXCPT_H_ */
/*
* Copyright (c) 2006-2019, 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
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
inline void rt_hw_fpu_init(void){} /* Do nothing */
#endif
#endif
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册