From e94adf07ca3021d693003cf282f2914ef5cdac98 Mon Sep 17 00:00:00 2001 From: "bernard.xiong" Date: Wed, 14 Jul 2010 09:51:49 +0000 Subject: [PATCH] add init Jz47xx porting. git-svn-id: https://rt-thread.googlecode.com/svn/trunk@792 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- libcpu/mips/common/asm.h | 220 +++++++++++ libcpu/mips/common/cache.c | 114 ++++++ libcpu/mips/common/cache.h | 232 ++++++++++++ libcpu/mips/common/exception.h | 168 +++++++++ libcpu/mips/common/mips.inc | 51 +++ libcpu/mips/common/mipscfg.h | 32 ++ libcpu/mips/common/mipsregs.h | 616 +++++++++++++++++++++++++++++++ libcpu/mips/common/stackframe.h | 228 ++++++++++++ libcpu/mips/jz47xx/cache_gcc.S | 42 +++ libcpu/mips/jz47xx/context_gcc.S | 146 ++++++++ libcpu/mips/jz47xx/cpu.c | 36 ++ libcpu/mips/jz47xx/exception.c | 57 +++ libcpu/mips/jz47xx/interrupt.c | 116 ++++++ libcpu/mips/jz47xx/interrupt.h | 28 ++ libcpu/mips/jz47xx/jz4755.h | 4 + libcpu/mips/jz47xx/jz47xx.h | 96 +++++ libcpu/mips/jz47xx/mipscfg.c | 82 ++++ libcpu/mips/jz47xx/stack.c | 94 +++++ libcpu/mips/jz47xx/start_gcc.S | 177 +++++++++ 19 files changed, 2539 insertions(+) create mode 100644 libcpu/mips/common/asm.h create mode 100644 libcpu/mips/common/cache.c create mode 100644 libcpu/mips/common/cache.h create mode 100644 libcpu/mips/common/exception.h create mode 100644 libcpu/mips/common/mips.inc create mode 100644 libcpu/mips/common/mipscfg.h create mode 100644 libcpu/mips/common/mipsregs.h create mode 100644 libcpu/mips/common/stackframe.h create mode 100644 libcpu/mips/jz47xx/cache_gcc.S create mode 100644 libcpu/mips/jz47xx/context_gcc.S create mode 100644 libcpu/mips/jz47xx/cpu.c create mode 100644 libcpu/mips/jz47xx/exception.c create mode 100644 libcpu/mips/jz47xx/interrupt.c create mode 100644 libcpu/mips/jz47xx/interrupt.h create mode 100644 libcpu/mips/jz47xx/jz4755.h create mode 100644 libcpu/mips/jz47xx/jz47xx.h create mode 100644 libcpu/mips/jz47xx/mipscfg.c create mode 100644 libcpu/mips/jz47xx/stack.c create mode 100644 libcpu/mips/jz47xx/start_gcc.S diff --git a/libcpu/mips/common/asm.h b/libcpu/mips/common/asm.h new file mode 100644 index 0000000000..7a4fb81398 --- /dev/null +++ b/libcpu/mips/common/asm.h @@ -0,0 +1,220 @@ +/* + * 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. + * + * 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 + * + * Some useful macros for MIPS assembler code + * + * 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. + */ +#ifndef __ASM_H__ +#define __ASM_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 + */ + +/* + * 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 + + +#define SSNOP sll zero, zero, 1 + +#endif /* end of __ASM_H__ */ diff --git a/libcpu/mips/common/cache.c b/libcpu/mips/common/cache.c new file mode 100644 index 0000000000..de9a112f50 --- /dev/null +++ b/libcpu/mips/common/cache.c @@ -0,0 +1,114 @@ +/* + * File : cache.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2010, 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 + * + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + */ +#include +#include "mipscfg.h" +#include "cache.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 > icache_size) + { + blast_icache16(); + } + else + { + rt_ubase_t ic_lsize = cpu_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 = cpu_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 = cpu_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 >= dcache_size) + { + blast_dcache16(); + } + else + { + rt_ubase_t dc_lsize = cpu_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; + } + } +} diff --git a/libcpu/mips/common/cache.h b/libcpu/mips/common/cache.h new file mode 100644 index 0000000000..579be8ff9b --- /dev/null +++ b/libcpu/mips/common/cache.h @@ -0,0 +1,232 @@ +/* + * Cache operations for the cache instruction. + * + * 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. + * + * (C) Copyright 1996, 97, 99, 2002, 03 Ralf Baechle + * (C) Copyright 1999 Silicon Graphics, Inc. + */ +#ifndef __CACHE_H__ +#define __CACHE_H__ + + +#define KUSEG 0x00000000 +#define KSEG0 0x80000000 +#define KSEG1 0xa0000000 +#define KSEG2 0xc0000000 +#define KSEG3 0xe0000000 + +/* + * 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 +#define Hit_Writeback_I 0x18 +#define Hit_Writeback_D 0x19 + +/* + *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 +/* + * R4000-specific cacheops + */ +#define Create_Dirty_Excl_D 0x0d +#define Fill 0x14 + +/* + * 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 + +/* + * R1000-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 + + +#ifndef __ASSEMBLER__ + +#ifndef dcache_size +#define dcache_size (g_mips_core.dcache_ways * g_mips_core.dcache_lines_per_way * g_mips_core.dcache_line_size) +#endif + +#ifndef icache_size +#define icache_size (g_mips_core.dcache_ways * g_mips_core.dcache_lines_per_way * g_mips_core.dcache_line_size) +#endif + +#ifndef cpu_dcache_line_size +#define cpu_dcache_line_size() g_mips_core.icache_line_size +#endif + +#ifndef cpu_icache_line_size +#define cpu_icache_line_size() g_mips_core.icache_line_size +#endif + +#define cache_op(op, addr) \ + __asm__ __volatile__( \ + " .set noreorder \n" \ + " .set mips3\n\t \n" \ + " cache %0, %1 \n" \ + " .set mips0 \n" \ + " .set reorder" \ + : \ + : "i" (op), "m" (*(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 = KSEG0; + rt_ubase_t end = start + dcache_size; + rt_ubase_t addr; + + for (addr = start; addr < end; addr += 0x200) + cache16_unroll32(addr, Index_Writeback_Inv_D); +} + +static inline void inv_dcache16(void) +{ + rt_ubase_t start = KSEG0; + rt_ubase_t end = start + dcache_size; + rt_ubase_t addr; + + for (addr = start; addr < end; addr += 0x200) + cache16_unroll32(addr, Hit_Invalidate_D); +} + +static inline void blast_icache16(void) +{ + rt_ubase_t start = KSEG0; + rt_ubase_t end = start + icache_size; + rt_ubase_t addr; + + for (addr = start; addr < end; addr += 0x200) + 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); + +#endif /*end of __ASSEMBLER__ */ + +#endif /* end of __CACHE_H__ */ diff --git a/libcpu/mips/common/exception.h b/libcpu/mips/common/exception.h new file mode 100644 index 0000000000..07ffcd7a29 --- /dev/null +++ b/libcpu/mips/common/exception.h @@ -0,0 +1,168 @@ +/* + * File : cpu.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2010, 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 + * + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + */ +#ifndef __EXCEPTION_H__ +#define __EXCEPTION_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; + +typedef void (* exception_func_t)(pt_regs_t *regs); + +extern exception_func_t sys_exception_handlers[33]; +exception_func_t rt_set_except_vector(int n, exception_func_t func); +void install_default_execpt_handle(void); + +#endif /* end of __EXCEPTION_H__ */ diff --git a/libcpu/mips/common/mips.inc b/libcpu/mips/common/mips.inc new file mode 100644 index 0000000000..59388fd7f1 --- /dev/null +++ b/libcpu/mips/common/mips.inc @@ -0,0 +1,51 @@ +/* + * File : mips.inc + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2010, 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 + * + * Change Logs: + * Date Author Notes + * 2010-05-17 sangwei first version + */ +#ifndef __MIPS_INC__ +#define __MIPS_INC__ + +#define zero $0 +#define at $1 +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define ra $31 + + +#endif /* end of __MIPS_INC__ */ diff --git a/libcpu/mips/common/mipscfg.h b/libcpu/mips/common/mipscfg.h new file mode 100644 index 0000000000..1e64d99db9 --- /dev/null +++ b/libcpu/mips/common/mipscfg.h @@ -0,0 +1,32 @@ +/* + * File : mipscfg.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2010, 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 + * + * Change Logs: + * Date Author Notes + * 2010-05-27 swkyer first version + */ +#ifndef __MIPSCFG_H__ +#define __MIPSCFG_H__ + + +typedef struct mips32_core_cfg +{ + rt_uint16_t icache_line_size; + rt_uint16_t icache_lines_per_way; + rt_uint16_t icache_ways; + rt_uint16_t dcache_line_size; + rt_uint16_t dcache_lines_per_way; + rt_uint16_t dcache_ways; + + rt_uint16_t max_tlb_entries; /* number of tlb entry */ +} mips32_core_cfg_t; + +extern mips32_core_cfg_t g_mips_core; + +#endif /* end of __MIPSCFG_H__ */ diff --git a/libcpu/mips/common/mipsregs.h b/libcpu/mips/common/mipsregs.h new file mode 100644 index 0000000000..d29b59d237 --- /dev/null +++ b/libcpu/mips/common/mipsregs.h @@ -0,0 +1,616 @@ +/* + * 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. + * + * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. + * Modified for further R[236]000 support by Paul M. Antoine, 1996. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000, 07 MIPS Technologies, Inc. + * Copyright (C) 2003, 2004 Maciej W. Rozycki + * + * Change Logs: + * Date Author Notes + * + */ +#ifndef __MIPSREGS_H__ +#define __MIPSREGS_H__ + +/* + * The following macros are especially useful for __asm__ + * inline assembler. + */ +#ifndef __STR +#define __STR(x) #x +#endif +#ifndef STR +#define STR(x) __STR(x) +#endif + +/* + * Configure language + */ +#ifdef __ASSEMBLY__ +#define _ULCAST_ +#else +#define _ULCAST_ (unsigned long) +#endif + +/* + * Coprocessor 0 register names + */ +#define CP0_INDEX $0 +#define CP0_RANDOM $1 +#define CP0_ENTRYLO0 $2 +#define CP0_ENTRYLO1 $3 +#define CP0_CONF $3 +#define CP0_CONTEXT $4 +#define CP0_PAGEMASK $5 +#define CP0_WIRED $6 +#define CP0_INFO $7 +#define CP0_BADVADDR $8 +#define CP0_COUNT $9 +#define CP0_ENTRYHI $10 +#define CP0_COMPARE $11 +#define CP0_STATUS $12 +#define CP0_CAUSE $13 +#define CP0_EPC $14 +#define CP0_PRID $15 +#define CP0_CONFIG $16 +#define CP0_LLADDR $17 +#define CP0_WATCHLO $18 +#define CP0_WATCHHI $19 +#define CP0_XCONTEXT $20 +#define CP0_FRAMEMASK $21 +#define CP0_DIAGNOSTIC $22 +#define CP0_DEBUG $23 +#define CP0_DEPC $24 +#define CP0_PERFORMANCE $25 +#define CP0_ECC $26 +#define CP0_CACHEERR $27 +#define CP0_TAGLO $28 +#define CP0_TAGHI $29 +#define CP0_ERROREPC $30 +#define CP0_DESAVE $31 + +/* + * R4640/R4650 cp0 register names. These registers are listed + * here only for completeness; without MMU these CPUs are not useable + * by Linux. A future ELKS port might take make Linux run on them + * though ... + */ +#define CP0_IBASE $0 +#define CP0_IBOUND $1 +#define CP0_DBASE $2 +#define CP0_DBOUND $3 +#define CP0_CALG $17 +#define CP0_IWATCH $18 +#define CP0_DWATCH $19 + +/* + * Coprocessor 0 Set 1 register names + */ +#define CP0_S1_DERRADDR0 $26 +#define CP0_S1_DERRADDR1 $27 +#define CP0_S1_INTCONTROL $20 + +/* + * Coprocessor 0 Set 2 register names + */ +#define CP0_S2_SRSCTL $12 /* MIPSR2 */ + +/* + * Coprocessor 0 Set 3 register names + */ +#define CP0_S3_SRSMAP $12 /* MIPSR2 */ + +/* + * TX39 Series + */ +#define CP0_TX39_CACHE $7 + +/* + * Coprocessor 1 (FPU) register names + */ +#define CP1_REVISION $0 +#define CP1_STATUS $31 + + +/* + * R4x00 interrupt enable / cause bits + */ +#define IE_SW0 (_ULCAST_(1) << 8) +#define IE_SW1 (_ULCAST_(1) << 9) +#define IE_IRQ0 (_ULCAST_(1) << 10) +#define IE_IRQ1 (_ULCAST_(1) << 11) +#define IE_IRQ2 (_ULCAST_(1) << 12) +#define IE_IRQ3 (_ULCAST_(1) << 13) +#define IE_IRQ4 (_ULCAST_(1) << 14) +#define IE_IRQ5 (_ULCAST_(1) << 15) + +/* + * R4x00 interrupt cause bits + */ +#define C_SW0 (_ULCAST_(1) << 8) +#define C_SW1 (_ULCAST_(1) << 9) +#define C_IRQ0 (_ULCAST_(1) << 10) +#define C_IRQ1 (_ULCAST_(1) << 11) +#define C_IRQ2 (_ULCAST_(1) << 12) +#define C_IRQ3 (_ULCAST_(1) << 13) +#define C_IRQ4 (_ULCAST_(1) << 14) +#define C_IRQ5 (_ULCAST_(1) << 15) + +/* + * Bitfields in the R4xx0 cp0 status register + */ +#define ST0_IE 0x00000001 +#define ST0_EXL 0x00000002 +#define ST0_ERL 0x00000004 +#define ST0_KSU 0x00000018 +# define KSU_USER 0x00000010 +# define KSU_SUPERVISOR 0x00000008 +# define KSU_KERNEL 0x00000000 +#define ST0_UX 0x00000020 +#define ST0_SX 0x00000040 +#define ST0_KX 0x00000080 +#define ST0_DE 0x00010000 +#define ST0_CE 0x00020000 + +/* + * Setting c0_status.co enables Hit_Writeback and Hit_Writeback_Invalidate + * cacheops in userspace. This bit exists only on RM7000 and RM9000 + * processors. + */ +#define ST0_CO 0x08000000 + +/* + * Bitfields in the R[23]000 cp0 status register. + */ +#define ST0_IEC 0x00000001 +#define ST0_KUC 0x00000002 +#define ST0_IEP 0x00000004 +#define ST0_KUP 0x00000008 +#define ST0_IEO 0x00000010 +#define ST0_KUO 0x00000020 +/* bits 6 & 7 are reserved on R[23]000 */ +#define ST0_ISC 0x00010000 +#define ST0_SWC 0x00020000 +#define ST0_CM 0x00080000 + +/* + * Bits specific to the R4640/R4650 + */ +#define ST0_UM (_ULCAST_(1) << 4) +#define ST0_IL (_ULCAST_(1) << 23) +#define ST0_DL (_ULCAST_(1) << 24) + +/* + * Enable the MIPS DSP ASE + */ +#define ST0_MX 0x01000000 + +/* + * Bitfields in the TX39 family CP0 Configuration Register 3 + */ +#define TX39_CONF_ICS_SHIFT 19 +#define TX39_CONF_ICS_MASK 0x00380000 +#define TX39_CONF_ICS_1KB 0x00000000 +#define TX39_CONF_ICS_2KB 0x00080000 +#define TX39_CONF_ICS_4KB 0x00100000 +#define TX39_CONF_ICS_8KB 0x00180000 +#define TX39_CONF_ICS_16KB 0x00200000 + +#define TX39_CONF_DCS_SHIFT 16 +#define TX39_CONF_DCS_MASK 0x00070000 +#define TX39_CONF_DCS_1KB 0x00000000 +#define TX39_CONF_DCS_2KB 0x00010000 +#define TX39_CONF_DCS_4KB 0x00020000 +#define TX39_CONF_DCS_8KB 0x00030000 +#define TX39_CONF_DCS_16KB 0x00040000 + +#define TX39_CONF_CWFON 0x00004000 +#define TX39_CONF_WBON 0x00002000 +#define TX39_CONF_RF_SHIFT 10 +#define TX39_CONF_RF_MASK 0x00000c00 +#define TX39_CONF_DOZE 0x00000200 +#define TX39_CONF_HALT 0x00000100 +#define TX39_CONF_LOCK 0x00000080 +#define TX39_CONF_ICE 0x00000020 +#define TX39_CONF_DCE 0x00000010 +#define TX39_CONF_IRSIZE_SHIFT 2 +#define TX39_CONF_IRSIZE_MASK 0x0000000c +#define TX39_CONF_DRSIZE_SHIFT 0 +#define TX39_CONF_DRSIZE_MASK 0x00000003 + +/* + * Status register bits available in all MIPS CPUs. + */ +#define ST0_IM 0x0000ff00 +#define STATUSB_IP0 8 +#define STATUSF_IP0 (_ULCAST_(1) << 8) +#define STATUSB_IP1 9 +#define STATUSF_IP1 (_ULCAST_(1) << 9) +#define STATUSB_IP2 10 +#define STATUSF_IP2 (_ULCAST_(1) << 10) +#define STATUSB_IP3 11 +#define STATUSF_IP3 (_ULCAST_(1) << 11) +#define STATUSB_IP4 12 +#define STATUSF_IP4 (_ULCAST_(1) << 12) +#define STATUSB_IP5 13 +#define STATUSF_IP5 (_ULCAST_(1) << 13) +#define STATUSB_IP6 14 +#define STATUSF_IP6 (_ULCAST_(1) << 14) +#define STATUSB_IP7 15 +#define STATUSF_IP7 (_ULCAST_(1) << 15) +#define STATUSB_IP8 0 +#define STATUSF_IP8 (_ULCAST_(1) << 0) +#define STATUSB_IP9 1 +#define STATUSF_IP9 (_ULCAST_(1) << 1) +#define STATUSB_IP10 2 +#define STATUSF_IP10 (_ULCAST_(1) << 2) +#define STATUSB_IP11 3 +#define STATUSF_IP11 (_ULCAST_(1) << 3) +#define STATUSB_IP12 4 +#define STATUSF_IP12 (_ULCAST_(1) << 4) +#define STATUSB_IP13 5 +#define STATUSF_IP13 (_ULCAST_(1) << 5) +#define STATUSB_IP14 6 +#define STATUSF_IP14 (_ULCAST_(1) << 6) +#define STATUSB_IP15 7 +#define STATUSF_IP15 (_ULCAST_(1) << 7) +#define ST0_CH 0x00040000 +#define ST0_SR 0x00100000 +#define ST0_TS 0x00200000 +#define ST0_BEV 0x00400000 +#define ST0_RE 0x02000000 +#define ST0_FR 0x04000000 +#define ST0_CU 0xf0000000 +#define ST0_CU0 0x10000000 +#define ST0_CU1 0x20000000 +#define ST0_CU2 0x40000000 +#define ST0_CU3 0x80000000 +#define ST0_XX 0x80000000 /* MIPS IV naming */ + +/* + * Bitfields and bit numbers in the coprocessor 0 cause register. + * + * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. + */ +#define CAUSEB_EXCCODE 2 +#define CAUSEF_EXCCODE (_ULCAST_(31) << 2) +#define CAUSEB_IP 8 +#define CAUSEF_IP (_ULCAST_(255) << 8) +#define CAUSEB_IP0 8 +#define CAUSEF_IP0 (_ULCAST_(1) << 8) +#define CAUSEB_IP1 9 +#define CAUSEF_IP1 (_ULCAST_(1) << 9) +#define CAUSEB_IP2 10 +#define CAUSEF_IP2 (_ULCAST_(1) << 10) +#define CAUSEB_IP3 11 +#define CAUSEF_IP3 (_ULCAST_(1) << 11) +#define CAUSEB_IP4 12 +#define CAUSEF_IP4 (_ULCAST_(1) << 12) +#define CAUSEB_IP5 13 +#define CAUSEF_IP5 (_ULCAST_(1) << 13) +#define CAUSEB_IP6 14 +#define CAUSEF_IP6 (_ULCAST_(1) << 14) +#define CAUSEB_IP7 15 +#define CAUSEF_IP7 (_ULCAST_(1) << 15) +#define CAUSEB_IV 23 +#define CAUSEF_IV (_ULCAST_(1) << 23) +#define CAUSEB_CE 28 +#define CAUSEF_CE (_ULCAST_(3) << 28) +#define CAUSEB_BD 31 +#define CAUSEF_BD (_ULCAST_(1) << 31) + +/* + * Bits in the coprocessor 0 config register. + */ +/* Generic bits. */ +#define CONF_CM_CACHABLE_NO_WA 0 +#define CONF_CM_CACHABLE_WA 1 +#define CONF_CM_UNCACHED 2 +#define CONF_CM_CACHABLE_NONCOHERENT 3 +#define CONF_CM_CACHABLE_CE 4 +#define CONF_CM_CACHABLE_COW 5 +#define CONF_CM_CACHABLE_CUW 6 +#define CONF_CM_CACHABLE_ACCELERATED 7 +#define CONF_CM_CMASK 7 +#define CONF_BE (_ULCAST_(1) << 15) + +/* Bits common to various processors. */ +#define CONF_CU (_ULCAST_(1) << 3) +#define CONF_DB (_ULCAST_(1) << 4) +#define CONF_IB (_ULCAST_(1) << 5) +#define CONF_DC (_ULCAST_(7) << 6) +#define CONF_IC (_ULCAST_(7) << 9) +#define CONF_EB (_ULCAST_(1) << 13) +#define CONF_EM (_ULCAST_(1) << 14) +#define CONF_SM (_ULCAST_(1) << 16) +#define CONF_SC (_ULCAST_(1) << 17) +#define CONF_EW (_ULCAST_(3) << 18) +#define CONF_EP (_ULCAST_(15)<< 24) +#define CONF_EC (_ULCAST_(7) << 28) +#define CONF_CM (_ULCAST_(1) << 31) + +/* Bits specific to the R4xx0. */ +#define R4K_CONF_SW (_ULCAST_(1) << 20) +#define R4K_CONF_SS (_ULCAST_(1) << 21) +#define R4K_CONF_SB (_ULCAST_(3) << 22) + +/* Bits specific to the R5000. */ +#define R5K_CONF_SE (_ULCAST_(1) << 12) +#define R5K_CONF_SS (_ULCAST_(3) << 20) + +/* Bits specific to the RM7000. */ +#define RM7K_CONF_SE (_ULCAST_(1) << 3) +#define RM7K_CONF_TE (_ULCAST_(1) << 12) +#define RM7K_CONF_CLK (_ULCAST_(1) << 16) +#define RM7K_CONF_TC (_ULCAST_(1) << 17) +#define RM7K_CONF_SI (_ULCAST_(3) << 20) +#define RM7K_CONF_SC (_ULCAST_(1) << 31) + +/* Bits specific to the R10000. */ +#define R10K_CONF_DN (_ULCAST_(3) << 3) +#define R10K_CONF_CT (_ULCAST_(1) << 5) +#define R10K_CONF_PE (_ULCAST_(1) << 6) +#define R10K_CONF_PM (_ULCAST_(3) << 7) +#define R10K_CONF_EC (_ULCAST_(15)<< 9) +#define R10K_CONF_SB (_ULCAST_(1) << 13) +#define R10K_CONF_SK (_ULCAST_(1) << 14) +#define R10K_CONF_SS (_ULCAST_(7) << 16) +#define R10K_CONF_SC (_ULCAST_(7) << 19) +#define R10K_CONF_DC (_ULCAST_(7) << 26) +#define R10K_CONF_IC (_ULCAST_(7) << 29) + +/* Bits specific to the VR41xx. */ +#define VR41_CONF_CS (_ULCAST_(1) << 12) +#define VR41_CONF_M16 (_ULCAST_(1) << 20) +#define VR41_CONF_AD (_ULCAST_(1) << 23) + +/* Bits specific to the R30xx. */ +#define R30XX_CONF_FDM (_ULCAST_(1) << 19) +#define R30XX_CONF_REV (_ULCAST_(1) << 22) +#define R30XX_CONF_AC (_ULCAST_(1) << 23) +#define R30XX_CONF_RF (_ULCAST_(1) << 24) +#define R30XX_CONF_HALT (_ULCAST_(1) << 25) +#define R30XX_CONF_FPINT (_ULCAST_(7) << 26) +#define R30XX_CONF_DBR (_ULCAST_(1) << 29) +#define R30XX_CONF_SB (_ULCAST_(1) << 30) +#define R30XX_CONF_LOCK (_ULCAST_(1) << 31) + +/* Bits specific to the TX49. */ +#define TX49_CONF_DC (_ULCAST_(1) << 16) +#define TX49_CONF_IC (_ULCAST_(1) << 17) /* conflict with CONF_SC */ +#define TX49_CONF_HALT (_ULCAST_(1) << 18) +#define TX49_CONF_CWFON (_ULCAST_(1) << 27) + +/* Bits specific to the MIPS32/64 PRA. */ +#define MIPS_CONF_MT (_ULCAST_(7) << 7) +#define MIPS_CONF_AR (_ULCAST_(7) << 10) +#define MIPS_CONF_AT (_ULCAST_(3) << 13) +#define MIPS_CONF_M (_ULCAST_(1) << 31) + +/* + * Bits in the MIPS32/64 PRA coprocessor 0 config registers 1 and above. + */ +#define MIPS_CONF1_FP (_ULCAST_(1) << 0) +#define MIPS_CONF1_EP (_ULCAST_(1) << 1) +#define MIPS_CONF1_CA (_ULCAST_(1) << 2) +#define MIPS_CONF1_WR (_ULCAST_(1) << 3) +#define MIPS_CONF1_PC (_ULCAST_(1) << 4) +#define MIPS_CONF1_MD (_ULCAST_(1) << 5) +#define MIPS_CONF1_C2 (_ULCAST_(1) << 6) +#define MIPS_CONF1_DA (_ULCAST_(7) << 7) +#define MIPS_CONF1_DL (_ULCAST_(7) << 10) +#define MIPS_CONF1_DS (_ULCAST_(7) << 13) +#define MIPS_CONF1_IA (_ULCAST_(7) << 16) +#define MIPS_CONF1_IL (_ULCAST_(7) << 19) +#define MIPS_CONF1_IS (_ULCAST_(7) << 22) +#define MIPS_CONF1_TLBS (_ULCAST_(63)<< 25) + +#define MIPS_CONF2_SA (_ULCAST_(15)<< 0) +#define MIPS_CONF2_SL (_ULCAST_(15)<< 4) +#define MIPS_CONF2_SS (_ULCAST_(15)<< 8) +#define MIPS_CONF2_SU (_ULCAST_(15)<< 12) +#define MIPS_CONF2_TA (_ULCAST_(15)<< 16) +#define MIPS_CONF2_TL (_ULCAST_(15)<< 20) +#define MIPS_CONF2_TS (_ULCAST_(15)<< 24) +#define MIPS_CONF2_TU (_ULCAST_(7) << 28) + +#define MIPS_CONF3_TL (_ULCAST_(1) << 0) +#define MIPS_CONF3_SM (_ULCAST_(1) << 1) +#define MIPS_CONF3_MT (_ULCAST_(1) << 2) +#define MIPS_CONF3_SP (_ULCAST_(1) << 4) +#define MIPS_CONF3_VINT (_ULCAST_(1) << 5) +#define MIPS_CONF3_VEIC (_ULCAST_(1) << 6) +#define MIPS_CONF3_LPA (_ULCAST_(1) << 7) +#define MIPS_CONF3_DSP (_ULCAST_(1) << 10) + +/* + * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register. + */ +#define MIPS_FPIR_S (_ULCAST_(1) << 16) +#define MIPS_FPIR_D (_ULCAST_(1) << 17) +#define MIPS_FPIR_PS (_ULCAST_(1) << 18) +#define MIPS_FPIR_3D (_ULCAST_(1) << 19) +#define MIPS_FPIR_W (_ULCAST_(1) << 20) +#define MIPS_FPIR_L (_ULCAST_(1) << 21) +#define MIPS_FPIR_F64 (_ULCAST_(1) << 22) + +/* + * R10000 performance counter definitions. + * + * FIXME: The R10000 performance counter opens a nice way to implement CPU + * time accounting with a precission of one cycle. I don't have + * R10000 silicon but just a manual, so ... + */ + +/* + * Events counted by counter #0 + */ +#define CE0_CYCLES 0 +#define CE0_INSN_ISSUED 1 +#define CE0_LPSC_ISSUED 2 +#define CE0_S_ISSUED 3 +#define CE0_SC_ISSUED 4 +#define CE0_SC_FAILED 5 +#define CE0_BRANCH_DECODED 6 +#define CE0_QW_WB_SECONDARY 7 +#define CE0_CORRECTED_ECC_ERRORS 8 +#define CE0_ICACHE_MISSES 9 +#define CE0_SCACHE_I_MISSES 10 +#define CE0_SCACHE_I_WAY_MISSPREDICTED 11 +#define CE0_EXT_INTERVENTIONS_REQ 12 +#define CE0_EXT_INVALIDATE_REQ 13 +#define CE0_VIRTUAL_COHERENCY_COND 14 +#define CE0_INSN_GRADUATED 15 + +/* + * Events counted by counter #1 + */ +#define CE1_CYCLES 0 +#define CE1_INSN_GRADUATED 1 +#define CE1_LPSC_GRADUATED 2 +#define CE1_S_GRADUATED 3 +#define CE1_SC_GRADUATED 4 +#define CE1_FP_INSN_GRADUATED 5 +#define CE1_QW_WB_PRIMARY 6 +#define CE1_TLB_REFILL 7 +#define CE1_BRANCH_MISSPREDICTED 8 +#define CE1_DCACHE_MISS 9 +#define CE1_SCACHE_D_MISSES 10 +#define CE1_SCACHE_D_WAY_MISSPREDICTED 11 +#define CE1_EXT_INTERVENTION_HITS 12 +#define CE1_EXT_INVALIDATE_REQ 13 +#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS 14 +#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS 15 + +/* + * These flags define in which privilege mode the counters count events + */ +#define CEB_USER 8 /* Count events in user mode, EXL = ERL = 0 */ +#define CEB_SUPERVISOR 4 /* Count events in supvervisor mode EXL = ERL = 0 */ +#define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */ +#define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */ + + +#ifndef __ASSEMBLY__ + +/* + * Macros to access the system control coprocessor + */ +#define __read_32bit_c0_register(source, sel) \ +({ int __res; \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __write_32bit_c0_register(register, sel, value) \ +do { \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mtc0\t%z0, " #register "\n\t" \ + : : "Jr" ((unsigned int)(value))); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mtc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "Jr" ((unsigned int)(value))); \ +} while (0) + +#define read_c0_index() __read_32bit_c0_register($0, 0) +#define write_c0_index(val) __write_32bit_c0_register($0, 0, val) + +#define read_c0_random() __read_32bit_c0_register($1, 0) +#define write_c0_random(val) __write_32bit_c0_register($1, 0, val) + +#define read_c0_entrylo0() __read_32bit_c0_register($2, 0) +#define write_c0_entrylo0(val) __write_32bit_c0_register($2, 0, val) + +#define read_c0_entrylo1() __read_32bit_c0_register($3, 0) +#define write_c0_entrylo1(val) __write_32bit_c0_register($3, 0, val) + +#define read_c0_conf() __read_32bit_c0_register($3, 0) +#define write_c0_conf(val) __write_32bit_c0_register($3, 0, val) + +#define read_c0_context() __read_32bit_c0_register($4, 0) +#define write_c0_context(val) __write_32bit_c0_register($4, 0, val) + +#define read_c0_userlocal() __read_32bit_c0_register($4, 2) +#define write_c0_userlocal(val) __write_32bit_c0_register($4, 2, val) + +#define read_c0_pagemask() __read_32bit_c0_register($5, 0) +#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val) + +#define read_c0_wired() __read_32bit_c0_register($6, 0) +#define write_c0_wired(val) __write_32bit_c0_register($6, 0, val) + +#define read_c0_info() __read_32bit_c0_register($7, 0) + +#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */ +#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val) + +#define read_c0_badvaddr() __read_32bit_c0_register($8, 0) +#define write_c0_badvaddr(val) __write_32bit_c0_register($8, 0, val) + +#define read_c0_count() __read_32bit_c0_register($9, 0) +#define write_c0_count(val) __write_32bit_c0_register($9, 0, val) + +#define read_c0_count2() __read_32bit_c0_register($9, 6) /* pnx8550 */ +#define write_c0_count2(val) __write_32bit_c0_register($9, 6, val) + +#define read_c0_count3() __read_32bit_c0_register($9, 7) /* pnx8550 */ +#define write_c0_count3(val) __write_32bit_c0_register($9, 7, val) + +#define read_c0_entryhi() __read_32bit_c0_register($10, 0) +#define write_c0_entryhi(val) __write_32bit_c0_register($10, 0, val) + +#define read_c0_compare() __read_32bit_c0_register($11, 0) +#define write_c0_compare(val) __write_32bit_c0_register($11, 0, val) + +#define read_c0_compare2() __read_32bit_c0_register($11, 6) /* pnx8550 */ +#define write_c0_compare2(val) __write_32bit_c0_register($11, 6, val) + +#define read_c0_compare3() __read_32bit_c0_register($11, 7) /* pnx8550 */ +#define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val) + +#define read_c0_status() __read_32bit_c0_register($12, 0) +#define write_c0_status(val) __write_32bit_c0_register($12, 0, val) + +#define read_c0_cause() __read_32bit_c0_register($13, 0) +#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) + +#define read_c0_epc() __read_32bit_c0_register($14, 0) +#define write_c0_epc(val) __write_32bit_c0_register($14, 0, val) + +#define read_c0_prid() __read_32bit_c0_register($15, 0) + +#define read_c0_ebase() __read_32bit_c0_register($15, 1) +#define write_c0_ebase(val) __write_32bit_c0_register($15, 1, val) + +#define read_c0_config() __read_32bit_c0_register($16, 0) +#define read_c0_config1() __read_32bit_c0_register($16, 1) +#define read_c0_config2() __read_32bit_c0_register($16, 2) +#define read_c0_config3() __read_32bit_c0_register($16, 3) +#define write_c0_config(val) __write_32bit_c0_register($16, 0, val) +#define write_c0_config1(val) __write_32bit_c0_register($16, 1, val) +#define write_c0_config2(val) __write_32bit_c0_register($16, 2, val) +#define write_c0_config3(val) __write_32bit_c0_register($16, 3, val) + + +#endif /* end of __ASSEMBLY__ */ + +#endif /* end of __MIPSREGS_H__ */ + diff --git a/libcpu/mips/common/stackframe.h b/libcpu/mips/common/stackframe.h new file mode 100644 index 0000000000..ab4eccb2bc --- /dev/null +++ b/libcpu/mips/common/stackframe.h @@ -0,0 +1,228 @@ +/* + * 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. + * + * Copyright (C) 1994, 95, 96, 99, 2001 Ralf Baechle + * Copyright (C) 1994, 1995, 1996 Paul M. Antoine. + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2007 Maciej W. Rozycki + */ +#ifndef __STACKFRAME_H__ +#define __STACKFRAME_H__ + +#include "asm.h" +#include "mipsregs.h" + +/* + * Stack layout for the INT 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 PT_R0 (PTRSIZE*6) /* 0 */ +#define PT_R0 (0) /* 0 */ +#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) + LONGSIZE) /* 33 */ +#define PT_LO ((PT_HI) + LONGSIZE) /* 34 */ +#define PT_BADVADDR ((PT_LO) + LONGSIZE) /* 35 */ +#define PT_CAUSE ((PT_BADVADDR) + LONGSIZE) /* 36 */ +#define PT_EPC ((PT_CAUSE) + LONGSIZE) /* 37 */ + +#define PT_SIZE ((((PT_EPC) + LONGSIZE) + (PTRSIZE-1)) & ~(PTRSIZE-1)) + + + .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) + LONG_S v1, PT_HI(sp) + mflo v1 + LONG_S $10, PT_R10(sp) + LONG_S $11, PT_R11(sp) + LONG_S 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 get_saved_sp + nop + .endm + + .macro SAVE_SOME + .set push + .set noat + .set reorder + move k1, sp +8: 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_STATIC + .endm + + .macro RESTORE_AT + .set push + .set noat + LONG_L $1, PT_R1(sp) + .set pop + .endm + + .macro RESTORE_TEMP + LONG_L $24, PT_LO(sp) + LONG_L $8, PT_R8(sp) + LONG_L $9, PT_R9(sp) + mtlo $24 + LONG_L $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 + + .macro RESTORE_SOME + .set push + .set reorder + .set noat + LONG_L v0, PT_STATUS(sp) + 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) + .set mips3 + eret + .set mips0 + .endm + + + .macro RESTORE_SP + LONG_L sp, PT_R29(sp) + .endm + + .macro RESTORE_ALL + RESTORE_TEMP + RESTORE_STATIC + RESTORE_AT + RESTORE_SOME + RESTORE_SP + .endm + + .macro RESTORE_ALL_AND_RET + RESTORE_TEMP + RESTORE_STATIC + RESTORE_AT + RESTORE_SOME + RESTORE_SP_AND_RET + .endm + +#endif /* end of __STACKFRAME_H__ */ + diff --git a/libcpu/mips/jz47xx/cache_gcc.S b/libcpu/mips/jz47xx/cache_gcc.S new file mode 100644 index 0000000000..3b1e430753 --- /dev/null +++ b/libcpu/mips/jz47xx/cache_gcc.S @@ -0,0 +1,42 @@ +/* + * File : cache_init.S + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + */ +#include "../common/mips.inc" +#include "../common/mipsregs.h" +#include "../common/stackframe.h" + + .text + .set noreorder + + .globl cache_init + .ent cache_init +cache_init: + .set noreorder + mtc0 zero, CP0_TAGLO + move t0, a0 // cache total size + move t1, a1 // cache line size + li t2, 0x80000000 + addu t3, t0, t2 + +_cache_init_loop: + cache 8, 0(t2) // icache_index_store_tag + cache 9, 0(t2) // dcache_index_store_tag + addu t2, t1 + bne t2, t3, _cache_init_loop + nop + + mfc0 t0, CP0_CONFIG + li t1, 0x7 + not t1 + and t0, t0, t1 + or t0, 0x3 // cacheable, noncoherent, write-back, write allocate + mtc0 t0, CP0_CONFIG + + jr ra + nop + + .set reorder + .end cache_init diff --git a/libcpu/mips/jz47xx/context_gcc.S b/libcpu/mips/jz47xx/context_gcc.S new file mode 100644 index 0000000000..539c014554 --- /dev/null +++ b/libcpu/mips/jz47xx/context_gcc.S @@ -0,0 +1,146 @@ +/* + * File : context_gcc.S + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + */ +#include "../common/mips.inc" +#include "../common/stackframe.h" +#include "jz47xx.h" + + .section ".text", "ax" + .set noreorder + +/* + * rt_base_t rt_hw_interrupt_disable() + */ + .globl rt_hw_interrupt_disable +rt_hw_interrupt_disable: + mfc0 v0, CP0_STATUS + and v1, v0, 0xfffffffe + mtc0 v1, CP0_STATUS + jr ra + nop + +/* + * void rt_hw_interrupt_enable(rt_base_t level) + */ + .globl rt_hw_interrupt_enable +rt_hw_interrupt_enable: + mtc0 a0, CP0_STATUS + jr ra + nop + +/* + * 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_interrput_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_interrput_flag + lw t1, 0(t0) + nop + bnez t1, _reswitch + nop + li t1, 0x01 /* set rt_thread_switch_interrput_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 mips_irq_handle +mips_irq_handle: + SAVE_ALL + + mfc0 t0, CP0_CAUSE + mfc0 t1, CP0_STATUS + and t0, t1 + + andi t0, 0xff00 + beqz t0, spurious_interrupt + nop + + /* switch to kernel stack */ + move k0, sp + li sp, SYSTEM_STACK + addiu sp, sp, -4 + sw k0, 0(sp) + +1: + jal rt_interrupt_enter + nop + jal rt_interrupt_dispatch + nop + jal rt_interrupt_leave + nop + + /* switch sp back to thread's context */ + lw k0, 0(sp) + nop + move sp, k0 + + /* + * if rt_thread_switch_interrput_flag set, jump to + * rt_hw_context_switch_interrupt_do and don't return + */ + la k0, rt_thread_switch_interrput_flag + lw k1, 0(k0) + beqz k1, spurious_interrupt + nop + + /* + * switch to the new thread + */ + sw zero, 0(k0) /* clear flag */ + la k0, rt_interrupt_from_thread + lw k1, 0(k0) + nop + sw sp, 0(k1) /* store sp in preempted tasks's TCB */ + la k0, rt_interrupt_to_thread + lw k1, 0(k0) + nop + lw sp, 0(k1) /* get new task's stack pointer */ + j spurious_interrupt + nop + +spurious_interrupt: + RESTORE_ALL_AND_RET + + .set reorder diff --git a/libcpu/mips/jz47xx/cpu.c b/libcpu/mips/jz47xx/cpu.c new file mode 100644 index 0000000000..bb6cd22c53 --- /dev/null +++ b/libcpu/mips/jz47xx/cpu.c @@ -0,0 +1,36 @@ +/* + * File : cpu.c + * Change Logs: + * Date Author Notes + * 2010-07-09 Bernard first version + */ +#include + + +/** + * @addtogroup Jz47xx + */ +/*@{*/ + +/** + * this function will reset CPU + * + */ +void rt_hw_cpu_reset() +{ + /* open the watch-dog */ +} + +/** + * this function will shutdown CPU + * + */ +void rt_hw_cpu_shutdown() +{ + rt_kprintf("shutdown...\n"); + + while (1); +} + +/*@}*/ + diff --git a/libcpu/mips/jz47xx/exception.c b/libcpu/mips/jz47xx/exception.c new file mode 100644 index 0000000000..5bbe0b8f00 --- /dev/null +++ b/libcpu/mips/jz47xx/exception.c @@ -0,0 +1,57 @@ +/* + * File : exception.c + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + */ +#include +#include +#include "../common/exception.h" + +/** + * @addtogroup Jz47xx + */ +/*@{*/ + +/** + * exception handle table + */ +exception_func_t sys_exception_handlers[33]; + +/** + * 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 > 32) || (!func)) + { + return 0; + } + + sys_exception_handlers[n] = func; + + return old_handler; +} + +void tlbmiss_handle(rt_uint32_t epc) +{ + rt_kprintf("tlb-miss happens, epc: 0x%08x\n", epc); +} + +static void unhandled_exception_handle(pt_regs_t *regs) +{ + rt_kprintf("exception happens, epc: 0x%08x\n", regs->cp0_epc); +} + +void install_default_execpt_handle(void) +{ + rt_int32_t i; + + for (i=0; i<33; i++) + sys_exception_handlers[i] = (exception_func_t)unhandled_exception_handle; +} + +/*@}*/ + diff --git a/libcpu/mips/jz47xx/interrupt.c b/libcpu/mips/jz47xx/interrupt.c new file mode 100644 index 0000000000..b8567bfdc9 --- /dev/null +++ b/libcpu/mips/jz47xx/interrupt.c @@ -0,0 +1,116 @@ +/* + * File : interrupt.c + * + * Change Logs: + * Date Author Notes + * 2010-07-09 Bernard first version + */ +#include +#include "jz47xx.h" +#include "interrupt.h" + +#define JZ47XX_MAX_INTR 32 + +extern rt_uint32_t rt_interrupt_nest; +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrput_flag; + +static rt_isr_handler_t irq_handle_table[JZ47XX_MAX_INTR]; + +extern rt_uint32_t cp0_get_cause(void); +extern rt_uint32_t cp0_get_status(void); +extern void disable_cp0_counter(void); +extern void enable_cp0_counter(void); + +/** + * @addtogroup Jz47xx + */ +/*@{*/ + +void rt_hw_interrupt_handler(int vector) +{ + rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init() +{ + rt_int32_t index; + + for (index = 0; index < JZ47XX_MAX_INTR; index ++) + { + irq_handle_table[index] = (rt_isr_handler_t)rt_hw_interrupt_handler; + } + + /* init interrupt nest, and context in thread sp */ + rt_interrupt_nest = 0; + rt_interrupt_from_thread = 0; + rt_interrupt_to_thread = 0; + rt_thread_switch_interrput_flag = 0; +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + /* mask interrupt */ + INTC_IMSR = 1 << vector; +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + INTC_IMCR = 1 << vector; +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +void rt_hw_interrupt_install(int vector, rt_isr_handler_t new_handler, rt_isr_handler_t *old_handler) +{ + if (vector >= 0 && vector < JZ47XX_MAX_INTR) + { + if (old_handler != RT_NULL) + *old_handler = irq_handle_table[vector]; + if (new_handler != RT_NULL) + irq_handle_table[vector] = (rt_isr_handler_t)new_handler; + } +} + +void rt_interrupt_dispatch(void *ptreg) +{ + int i; + rt_uint32_t pending; + rt_isr_handler_t irq_func; + + /* the hardware interrupt */ + pending = INTC_IPR; + if (!pending) return; + + for (i = 0; i < JZ47XX_MAX_INTR; i++) + { + if ((pending & (1< +#include "../common/mipsregs.h" +#include "../common/mipscfg.h" + +mips32_core_cfg_t g_mips_core = +{ + 16, /* icache_line_size */ + 256, /* icache_lines_per_way */ + 4, /* icache_ways */ + 16, /* dcache_line_size */ + 256, /* dcache_lines_per_way */ + 4, /* dcache_ways */ + 16, /* max_tlb_entries */ +}; + +static rt_uint16_t m_pow(rt_uint16_t b, rt_uint16_t n) +{ + rt_uint16_t rets = 1; + + while (n--) + rets *= b; + + return rets; +} + +static rt_uint16_t m_log2(rt_uint16_t b) +{ + rt_uint16_t rets = 0; + + while (b != 1) + { + b /= 2; + rets++; + } + + return rets; +} + +/** + * read core attribute + */ +void mips32_cfg_init(void) +{ + rt_uint16_t val; + rt_uint32_t cp0_config1; + + cp0_config1 = read_c0_config(); + if (cp0_config1 & 0x80000000) + { + cp0_config1 = read_c0_config1(); + + val = (cp0_config1 & (7<<22))>>22; + g_mips_core.icache_lines_per_way = 64 * m_pow(2, val); + val = (cp0_config1 & (7<<19))>>19; + g_mips_core.icache_line_size = 2 * m_pow(2, val); + val = (cp0_config1 & (7<<16))>>16; + g_mips_core.icache_ways = val + 1; + + val = (cp0_config1 & (7<<13))>>13; + g_mips_core.dcache_lines_per_way = 64 * m_pow(2, val); + val = (cp0_config1 & (7<<10))>>10; + g_mips_core.dcache_line_size = 2 * m_pow(2, val); + val = (cp0_config1 & (7<<7))>>7; + g_mips_core.dcache_ways = val + 1; + + val = (cp0_config1 & (0x3F<<25))>>25; + g_mips_core.max_tlb_entries = val + 1; + } +} diff --git a/libcpu/mips/jz47xx/stack.c b/libcpu/mips/jz47xx/stack.c new file mode 100644 index 0000000000..c1576072b1 --- /dev/null +++ b/libcpu/mips/jz47xx/stack.c @@ -0,0 +1,94 @@ +/* + * File : stack.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, 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 + * + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + * 2010-07-07 Bernard porting to Jz47xx + */ +#include + +/** + * @addtogroup Jz47xx + */ +/*@{*/ + +extern rt_uint32_t cp0_get_cause(void); +extern rt_uint32_t cp0_get_status(void); +extern rt_uint32_t cp0_get_hi(void); +extern rt_uint32_t cp0_get_lo(void); + +/** + * This function will initialize thread stack + * + * @param tentry the entry of thread + * @param parameter the parameter of entry + * @param stack_addr the beginning stack address + * @param texit the function will be called when thread exit + * + * @return stack address + */ +rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit) +{ + rt_uint32_t *stk; + static rt_uint32_t g_sr = 0; + + if (g_sr == 0) + { + g_sr = cp0_get_status(); + g_sr &= 0xfffffffe; + g_sr |= 0x8403; + } + + /** Start at stack top */ + stk = (rt_uint32_t *)stack_addr; + *(stk) = (rt_uint32_t) tentry; /* pc: Entry Point */ + *(--stk) = (rt_uint32_t) 0xeeee; /* c0_cause */ + *(--stk) = (rt_uint32_t) 0xffff; /* c0_badvaddr */ + *(--stk) = (rt_uint32_t) cp0_get_lo(); /* lo */ + *(--stk) = (rt_uint32_t) cp0_get_hi(); /* hi */ + *(--stk) = (rt_uint32_t) g_sr; /* C0_SR: HW2 = En, IE = En */ + *(--stk) = (rt_uint32_t) texit; /* ra */ + *(--stk) = (rt_uint32_t) 0x0000001e; /* s8 */ + *(--stk) = (rt_uint32_t) stack_addr; /* sp */ + *(--stk) = (rt_uint32_t) 0x0000001c; /* gp */ + *(--stk) = (rt_uint32_t) 0x0000001b; /* k1 */ + *(--stk) = (rt_uint32_t) 0x0000001a; /* k0 */ + *(--stk) = (rt_uint32_t) 0x00000019; /* t9 */ + *(--stk) = (rt_uint32_t) 0x00000018; /* t8 */ + *(--stk) = (rt_uint32_t) 0x00000017; /* s7 */ + *(--stk) = (rt_uint32_t) 0x00000016; /* s6 */ + *(--stk) = (rt_uint32_t) 0x00000015; /* s5 */ + *(--stk) = (rt_uint32_t) 0x00000014; /* s4 */ + *(--stk) = (rt_uint32_t) 0x00000013; /* s3 */ + *(--stk) = (rt_uint32_t) 0x00000012; /* s2 */ + *(--stk) = (rt_uint32_t) 0x00000011; /* s1 */ + *(--stk) = (rt_uint32_t) 0x00000010; /* s0 */ + *(--stk) = (rt_uint32_t) 0x0000000f; /* t7 */ + *(--stk) = (rt_uint32_t) 0x0000000e; /* t6 */ + *(--stk) = (rt_uint32_t) 0x0000000d; /* t5 */ + *(--stk) = (rt_uint32_t) 0x0000000c; /* t4 */ + *(--stk) = (rt_uint32_t) 0x0000000b; /* t3 */ + *(--stk) = (rt_uint32_t) 0x0000000a; /* t2 */ + *(--stk) = (rt_uint32_t) 0x00000009; /* t1 */ + *(--stk) = (rt_uint32_t) 0x00000008; /* t0 */ + *(--stk) = (rt_uint32_t) 0x00000007; /* a3 */ + *(--stk) = (rt_uint32_t) 0x00000006; /* a2 */ + *(--stk) = (rt_uint32_t) 0x00000005; /* a1 */ + *(--stk) = (rt_uint32_t) parameter; /* a0 */ + *(--stk) = (rt_uint32_t) 0x00000003; /* v1 */ + *(--stk) = (rt_uint32_t) 0x00000002; /* v0 */ + *(--stk) = (rt_uint32_t) 0x00000001; /* at */ + *(--stk) = (rt_uint32_t) 0x00000000; /* zero */ + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} + +/*@}*/ diff --git a/libcpu/mips/jz47xx/start_gcc.S b/libcpu/mips/jz47xx/start_gcc.S new file mode 100644 index 0000000000..b3c051283b --- /dev/null +++ b/libcpu/mips/jz47xx/start_gcc.S @@ -0,0 +1,177 @@ +/* + * File : start_gcc.S + * Change Logs: + * Date Author Notes + * 2010-05-17 swkyer first version + */ +#include "../common/mips.inc" +#include "../common/stackframe.h" +#include "jz47xx.h" + + .section ".start", "ax" + .set noreorder + + .extern sys_exception_handlers + .extern tlbmiss_handle + + .globl _entry + /* exception entry */ +_entry: +.org 0x0 + .set noreorder + mfc0 t0, $14 + jal tlbmiss_handle + move a0, t0 + j _sys_dead /* TLB Miss, should never happen */ + nop + .set reorder + + /* + * void config_tick_timer(uint32_t perio) + */ + .globl config_tick_timer +config_tick_timer: + mfc0 t0, $9 /* count */ + nop + addu t1, t0, a0 + mtc0 t1, $11 /* compare */ + jr ra + nop + + .globl cp0_get_cause +cp0_get_cause: + mfc0 v0, CP0_CAUSE + jr ra + nop + + .globl cp0_get_status +cp0_get_status: + mfc0 v0, CP0_STATUS + jr ra + nop + + .globl cp0_get_hi +cp0_get_hi: + mfhi v0 + jr ra + nop + + .globl cp0_get_lo +cp0_get_lo: + mflo v0 + jr ra + nop + +.org 0x100 + .set noreorder + j _sys_dead /* cache error exception handle */ + nop + .set reorder + + + .globl disable_cp0_counter +disable_cp0_counter: + .set noreorder + mfc0 t0, CP0_CAUSE + lui t1, 0x0800 + or t0, t1 + mtc0 t0, CP0_CAUSE + jr ra + nop + .set reorder + + .globl enable_cp0_counter +enable_cp0_counter: + .set noreorder + mfc0 t0, CP0_CAUSE + lui t1, 0x0800 + not t2, t1 + and t0, t0, t2 + mtc0 t0, CP0_CAUSE + jr ra + nop + .set reorder + + // general exception handle +.org 0x180 +_gen_exp_handle: + .set noreorder + mfc0 k1, CP0_CAUSE + andi k1, k1, 0x7c + srl k1, k1, 2 + lw k0, sys_exception_handlers(k1) + jr k0 + nop + .set reorder + + /* error happens */ +_sys_dead: + .set noreorder + jal rt_hw_cpu_reset + nop + /* should never return here */ + j _sys_dead + nop + .set reorder + + + .globl mips_irq_handle + /* interrupt handle */ +.org 0x200 +_irq_handle: + .set noreorder + la k0, mips_irq_handle + jr k0 + nop + .set reorder + + + /* the REAL program entry */ + .extern mips32_cfg_init + .extern r4k_cache_init + .extern install_default_execpt_handle + .globl _start +.org 0x400 +_start: + .set noreorder + la ra, _start + + /* init cp0 registers. */ + li t0, 0x0040FC00 + mtc0 t0, CP0_STATUS + + li t1, 0x00800000 + mtc0 t1, CP0_CAUSE + + /* setup stack pointer */ + li sp, SYSTEM_STACK + la gp, _gp + + /* 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 + + /* read core config */ + jal mips32_cfg_init + nop + + /* initialize cache */ + jal r4k_cache_init + nop + + /* setup default exception handle */ + jal install_default_execpt_handle + nop + + /* jump to RT-Thread RTOS */ + jal rtthread_startup + nop + + /* restart, never die */ + j _start + nop + .set reorder