diff options
author | root <root@lamia.panaceas.james.local> | 2015-12-19 13:13:57 +0000 |
---|---|---|
committer | root <root@lamia.panaceas.james.local> | 2015-12-19 14:18:03 +0000 |
commit | 1a2238d1bddc823df06f67312d96ccf9de2893cc (patch) | |
tree | c58a3944d674a667f133ea5a730f5037e57d3d2e /cfe/cfe/arch/mips/common | |
download | bootloader-1a2238d1bddc823df06f67312d96ccf9de2893cc.tar.gz bootloader-1a2238d1bddc823df06f67312d96ccf9de2893cc.tar.bz2 bootloader-1a2238d1bddc823df06f67312d96ccf9de2893cc.zip |
CFE from danitool [without hostTools dir]: https://mega.nz/#!mwZyFK7a!CPT3BKC8dEw29kubtdYxhB91G9vIIismTkgzQ3iUy3k
Diffstat (limited to 'cfe/cfe/arch/mips/common')
32 files changed, 8345 insertions, 0 deletions
diff --git a/cfe/cfe/arch/mips/common/include/addrspace.h b/cfe/cfe/arch/mips/common/include/addrspace.h new file mode 100644 index 0000000..6330851 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/addrspace.h @@ -0,0 +1,63 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Address space macros File: addrspace.h + * + * Macros to deal with physical, virtual, and uncached addresses. + * for MIPS, these map to the appropriate KSEG0/KSEG1 macros + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "sbmips.h" + +#define PHYSADDR(x) K0_TO_PHYS(x) + +/* If running uncached, force all kernel addresses to be uncached */ +#if CFG_RUNFROMKSEG0 +#define KERNADDR(x) PHYS_TO_K0(x) +#else +#define KERNADDR(x) PHYS_TO_K1(x) +#endif + +#define UNCADDR(x) PHYS_TO_K1(x) + + + diff --git a/cfe/cfe/arch/mips/common/include/disasm.h b/cfe/cfe/arch/mips/common/include/disasm.h new file mode 100644 index 0000000..8a8e7b7 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/disasm.h @@ -0,0 +1,61 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * MIPS disassembler File: disasm.h + * + * MIPS disassembler (used by ui_examcmds.c) + * + * Author: Justin Carlson (carlson@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#ifndef DISASM_H +#define DISASM_H + +/* Returns a pointer to a read-only string containing the intstruction name */ +char *disasm_inst_name(uint32_t inst); + +/* Copies a disassembled version of the instruction into buf, null terminating the +string. Will not exceed buf_size bytes written; if the disassembled string is +longer than buf_size, buf_size-1 bytes of the string will be written and that string +will be null-terminated */ +void disasm_inst(char *buf, int buf_size, uint32_t inst, uint64_t pc); +#endif + + + diff --git a/cfe/cfe/arch/mips/common/include/exception.h b/cfe/cfe/arch/mips/common/include/exception.h new file mode 100644 index 0000000..70e87c2 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/exception.h @@ -0,0 +1,223 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Exception/trap handler defs File: exception.h + * + * This module describes the exception handlers, exception + * trap frames, and dispatch. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#ifdef __ASSEMBLER__ +#define _XAIDX(x) (8*(x)) +#else +#define _XAIDX(x) (x) +#endif + + +/* ********************************************************************* + * Exception vectors from the MIPS specification + ********************************************************************* */ + +#define MIPS_ROM_VEC_RESET 0x0000 +#define MIPS_ROM_VEC_TLBFILL 0x0200 +#define MIPS_ROM_VEC_XTLBFILL 0x0280 +#define MIPS_ROM_VEC_CACHEERR 0x0300 +#define MIPS_ROM_VEC_EXCEPTION 0x0380 +#define MIPS_ROM_VEC_INTERRUPT 0x0400 +#define MIPS_ROM_VEC_EJTAG 0x0480 + +#define MIPS_RAM_VEC_TLBFILL 0x0000 +#define MIPS_RAM_VEC_XTLBFILL 0x0080 +#define MIPS_RAM_VEC_EXCEPTION 0x0180 +#define MIPS_RAM_VEC_INTERRUPT 0x0200 +#define MIPS_RAM_VEC_CACHEERR 0x0100 +#define MIPS_RAM_VEC_END 0x0300 + +#define MIPS_RAM_EXL_VEC_TLBFILL 0x0100 +#define MIPS_RAM_EXL_VEC_XTLBFILL 0x0180 + + +/* ********************************************************************* + * Fixed locations of other low-memory objects. We stuff some + * important data in the spaces between the vectors. + ********************************************************************* */ + +#define CFE_LOCORE_GLOBAL_GP 0x0040 /* our "handle" */ +#define CFE_LOCORE_GLOBAL_SP 0x0048 /* Stack pointer for exceptions */ +#define CFE_LOCORE_GLOBAL_K0TMP 0x0050 /* Used by cache error handler */ +#define CFE_LOCORE_GLOBAL_K1TMP 0x0058 /* Used by cache error handler */ +#define CFE_LOCORE_GLOBAL_RATMP 0x0060 /* Used by cache error handler */ +#define CFE_LOCORE_GLOBAL_GPTMP 0x0068 /* Used by cache error handler */ +#define CFE_LOCORE_GLOBAL_CERRH 0x0070 /* Pointer to cache error handler */ + +#define CFE_LOCORE_GLOBAL_T0TMP 0x0240 /* used by cache error handler */ +#define CFE_LOCORE_GLOBAL_T1TMP 0x0248 /* used by cache error handler */ +#define CFE_LOCORE_GLOBAL_T2TMP 0x0250 /* used by cache error handler */ +#define CFE_LOCORE_GLOBAL_T3TMP 0x0258 /* used by cache error handler */ + +/* ********************************************************************* + * Offsets into our exception handler table. + ********************************************************************* */ + +#define XTYPE_RESET 0 +#define XTYPE_TLBFILL 8 +#define XTYPE_XTLBFILL 16 +#define XTYPE_CACHEERR 24 +#define XTYPE_EXCEPTION 32 +#define XTYPE_INTERRUPT 40 +#define XTYPE_EJTAG 48 + +/* ********************************************************************* + * Exception frame definitions. + ********************************************************************* */ + +/* + * The exception frame is divided up into pieces, representing the different + * parts of the processor that the data comes from: + * + * CP0: Words 0..7 + * Int Regs: Words 8..41 + * FP Regs: Words 42..73 + * Total size: 74 words + */ + +#define EXCEPTION_SIZE _XAIDX(74) + +#define XCP0_BASE 0 +#define XGR_BASE 8 +#define XFR_BASE 42 + +#define _XCP0IDX(x) _XAIDX((x)+XCP0_BASE) +#define XCP0_SR _XCP0IDX(0) +#define XCP0_CAUSE _XCP0IDX(1) +#define XCP0_EPC _XCP0IDX(2) +#define XCP0_VADDR _XCP0IDX(3) +#define XCP0_PRID _XCP0IDX(4) + +#define _XGRIDX(x) _XAIDX((x)+XGR_BASE) +#define XGR_ZERO _XGRIDX(0) +#define XGR_AT _XGRIDX(1) +#define XGR_V0 _XGRIDX(2) +#define XGR_V1 _XGRIDX(3) +#define XGR_A0 _XGRIDX(4) +#define XGR_A1 _XGRIDX(5) +#define XGR_A2 _XGRIDX(6) +#define XGR_A3 _XGRIDX(7) +#define XGR_T0 _XGRIDX(8) +#define XGR_T1 _XGRIDX(9) +#define XGR_T2 _XGRIDX(10) +#define XGR_T3 _XGRIDX(11) +#define XGR_T4 _XGRIDX(12) +#define XGR_T5 _XGRIDX(13) +#define XGR_T6 _XGRIDX(14) +#define XGR_T7 _XGRIDX(15) +#define XGR_S0 _XGRIDX(16) +#define XGR_S1 _XGRIDX(17) +#define XGR_S2 _XGRIDX(18) +#define XGR_S3 _XGRIDX(19) +#define XGR_S4 _XGRIDX(20) +#define XGR_S5 _XGRIDX(21) +#define XGR_S6 _XGRIDX(22) +#define XGR_S7 _XGRIDX(23) +#define XGR_T8 _XGRIDX(24) +#define XGR_T9 _XGRIDX(25) +#define XGR_K0 _XGRIDX(26) +#define XGR_K1 _XGRIDX(27) +#define XGR_GP _XGRIDX(28) +#define XGR_SP _XGRIDX(29) +#define XGR_FP _XGRIDX(30) +#define XGR_RA _XGRIDX(31) +#define XGR_LO _XGRIDX(32) +#define XGR_HI _XGRIDX(33) + + +#define _XFRIDX(x) _XAIDX((x)+XFR_BASE) +#define XR_F0 _XFRIDX(0) +#define XR_F1 _XFRIDX(1) +#define XR_F2 _XFRIDX(2) +#define XR_F3 _XFRIDX(3) +#define XR_F4 _XFRIDX(4) +#define XR_F5 _XFRIDX(5) +#define XR_F6 _XFRIDX(6) +#define XR_F7 _XFRIDX(7) +#define XR_F8 _XFRIDX(8) +#define XR_F9 _XFRIDX(9) +#define XR_F10 _XFRIDX(10) +#define XR_F11 _XFRIDX(11) +#define XR_F12 _XFRIDX(12) +#define XR_F13 _XFRIDX(13) +#define XR_F14 _XFRIDX(14) +#define XR_F15 _XFRIDX(15) +#define XR_F16 _XFRIDX(16) +#define XR_F17 _XFRIDX(17) +#define XR_F18 _XFRIDX(18) +#define XR_F19 _XFRIDX(19) +#define XR_F20 _XFRIDX(20) +#define XR_F21 _XFRIDX(21) +#define XR_F22 _XFRIDX(22) +#define XR_F23 _XFRIDX(23) +#define XR_F24 _XFRIDX(24) +#define XR_F25 _XFRIDX(25) +#define XR_F26 _XFRIDX(26) +#define XR_F27 _XFRIDX(27) +#define XR_F28 _XFRIDX(28) +#define XR_F29 _XFRIDX(29) +#define XR_F30 _XFRIDX(30) +#define XR_F31 _XFRIDX(31) +#define XR_FCR _XFRIDX(32) +#define XR_FID _XFRIDX(33) + + +#ifndef __ASSEMBLER__ +extern void _exc_setvector(int vectype, void *vecaddr); +extern void _exc_crash_sim(void); +extern void _exc_cache_crash_sim(void); +extern void _exc_restart(void); +extern void _exc_clear_sr_exl(void); +extern void _exc_clear_sr_erl(void); +void cfe_exception(int code,uint64_t *info); +void cfe_setup_exceptions(void); +#endif + + + + + diff --git a/cfe/cfe/arch/mips/common/include/exchandler.h b/cfe/cfe/arch/mips/common/include/exchandler.h new file mode 100644 index 0000000..af268f1 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/exchandler.h @@ -0,0 +1,85 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Exception Handler definitions File: exchandler.h + * + * Exception handler functions and constants + * + * Author: Binh Vo (binh@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#ifndef _LIB_SETJMP_H +#include "lib_setjmp.h" +#endif + +#ifndef _LIB_QUEUE_H +#include "lib_queue.h" +#endif + +#define MEM_BYTE 1 +#define MEM_HALFWORD 2 +#define MEM_WORD 3 +#define MEM_QUADWORD 4 + +#define EXC_NORMAL_RETURN 0 +#define EXC_CHAIN_EXC 1 + +typedef struct jmpbuf_s { + queue_t stack; + jmp_buf jmpbuf; +} jmpbuf_t; + +typedef struct exc_handler_s { + int catch_exc; + int chain_exc; + queue_t jmpbuf_stack; +} exc_handler_t; + +extern exc_handler_t exc_handler; + +jmpbuf_t *exc_initialize_block(void); +void exc_cleanup_block(jmpbuf_t *); +void exc_cleanup_handler(jmpbuf_t *, int); +void exc_longjmp_handler(void); +int mem_peek(void*, long, int); +int mem_poke(long, uint64_t, int); + + +#define exc_try(jb) (lib_setjmp(((jb)->jmpbuf))) diff --git a/cfe/cfe/arch/mips/common/include/initdata.h b/cfe/cfe/arch/mips/common/include/initdata.h new file mode 100644 index 0000000..c5fc0d8 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/initdata.h @@ -0,0 +1,68 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Data stored in initialization module File: initdata.h + * + * This file contains data declared by the init module. It also + * contains externs for that data so we can keep the types straight. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#if defined(__ASSEMBLER__) +#define DECLARE_INITVAR(x) \ + .globl x ; \ +x: _LONG_ 0 +#else +#define DECLARE_INITVAR(x) \ + extern long x; +#endif + +DECLARE_INITVAR(mem_textreloc) +DECLARE_INITVAR(mem_textbase) +DECLARE_INITVAR(mem_textsize) +DECLARE_INITVAR(mem_totalsize) +DECLARE_INITVAR(mem_topofmem) +DECLARE_INITVAR(mem_heapstart) +DECLARE_INITVAR(mem_bottomofmem) +DECLARE_INITVAR(mem_datareloc) +DECLARE_INITVAR(cpu_prid) + + diff --git a/cfe/cfe/arch/mips/common/include/lib_hssubr.h b/cfe/cfe/arch/mips/common/include/lib_hssubr.h new file mode 100644 index 0000000..b4df439 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/lib_hssubr.h @@ -0,0 +1,84 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * "Hyperspace" access routines File: lib_hssubr.h + * + * Constants, macros, and definitions for routines to deal with + * hyperspace (beyond 256MB) on MIPS processors. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#ifndef _LIB_HSSUBR_H +#define _LIB_HSSUBR_H + +/* + * If __long64 we can do this via macros. Otherwise, call + * the magic functions. + */ + +#if __long64 + +typedef long hsaddr_t; + +#define hs_write8(a,b) *((volatile uint8_t *) (a)) = (b) +#define hs_write16(a,b) *((volatile uint16_t *) (a)) = (b) +#define hs_write32(a,b) *((volatile uint32_t *) (a)) = (b) +#define hs_write64(a,b) *((volatile uint32_t *) (a)) = (b) +#define hs_read8(a) *((volatile uint8_t *) (a)) +#define hs_read16(a) *((volatile uint16_t *) (a)) +#define hs_read32(a) *((volatile uint32_t *) (a)) +#define hs_read64(a) *((volatile uint64_t *) (a)) + +#else /* not __long64 */ + +typedef long long hsaddr_t; + +extern void hs_write8(hsaddr_t a,uint8_t b); +extern void hs_write16(hsaddr_t a,uint16_t b); +extern void hs_write32(hsaddr_t a,uint32_t b); +extern void hs_write64(hsaddr_t a,uint64_t b); +extern uint8_t hs_read8(hsaddr_t a); +extern uint16_t hs_read16(hsaddr_t a); +extern uint32_t hs_read32(hsaddr_t a); +extern uint64_t hs_read64(hsaddr_t a); +#endif + +#endif diff --git a/cfe/cfe/arch/mips/common/include/lib_physio.h b/cfe/cfe/arch/mips/common/include/lib_physio.h new file mode 100644 index 0000000..00d0093 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/lib_physio.h @@ -0,0 +1,100 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Physical memory peek/poke routines File: lib_physio.h + * + * Little stub routines to allow access to arbitrary physical + * addresses. In most cases this should not be needed, as + * many physical addresses are within kseg1, but this handles + * the cases that are not automagically, so we don't need + * to mess up the code with icky macros and such. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#ifndef _LIB_PHYSIO_H +#define _LIB_PHYSIO_H + +//#ifndef _SB_MIPS_H +//#include "sbmips.h" +//#endif + +/* + * If __long64 we can do this via macros. Otherwise, call + * the magic functions. + */ + +#if __long64 + +typedef long physaddr_t; +#define _PHYSADDR_T_DEFINED_ + +/*#define __UNCADDRX(x) PHYS_TO_XKSEG_UNCACHED(x)*/ +#define __UNCADDRX(x) (((physaddr_t)(x))|0x9000000000000000) + + +#define phys_write8(a,b) *((volatile uint8_t *) __UNCADDRX(a)) = (b) +#define phys_write16(a,b) *((volatile uint16_t *) __UNCADDRX(a)) = (b) +#define phys_write32(a,b) *((volatile uint32_t *) __UNCADDRX(a)) = (b) +#define phys_write64(a,b) *((volatile uint64_t *) __UNCADDRX(a)) = (b) +#define phys_read8(a) *((volatile uint8_t *) __UNCADDRX(a)) +#define phys_read16(a) *((volatile uint16_t *) __UNCADDRX(a)) +#define phys_read32(a) *((volatile uint32_t *) __UNCADDRX(a)) +#define phys_read64(a) *((volatile uint64_t *) __UNCADDRX(a)) + +#else /* not __long64 */ + +#ifdef _MIPSREGS32_ +typedef long physaddr_t; /* 32-bit-only processors can't have >32bit pa's */ +#else +typedef long long physaddr_t; /* Otherwise, they might. */ +#endif + +extern void phys_write8(physaddr_t a,uint8_t b); +extern void phys_write16(physaddr_t a,uint16_t b); +extern void phys_write32(physaddr_t a,uint32_t b); +extern void phys_write64(physaddr_t a,uint64_t b); +extern uint8_t phys_read8(physaddr_t a); +extern uint16_t phys_read16(physaddr_t a); +extern uint32_t phys_read32(physaddr_t a); +extern uint64_t phys_read64(physaddr_t a); +#endif + +#endif diff --git a/cfe/cfe/arch/mips/common/include/lib_setjmp.h b/cfe/cfe/arch/mips/common/include/lib_setjmp.h new file mode 100644 index 0000000..b673222 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/lib_setjmp.h @@ -0,0 +1,81 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * setjmp/longjmp defs File: lib_setjmp.h + * + * Description of the jmp_buf structure for setjmp and longjmp + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +/* + * Note that while lib_setjmp() and lib_longjmp() behave like setjmp() + * and longjmp() normally do, gcc 3.1.x (and later) assumes things about + * how setjmp() and longjmp() should work (even with -fno-builtins). We + * don't want it to do those, so these functions must be named differently. + */ + +#ifdef __ASSEMBLER__ +#define _JBIDX(x) (8*(x)) +#else +#define _JBIDX(x) (x) +#endif + + +#define JMPB_S0 _JBIDX(0) +#define JMPB_S1 _JBIDX(1) +#define JMPB_S2 _JBIDX(2) +#define JMPB_S3 _JBIDX(3) +#define JMPB_S4 _JBIDX(4) +#define JMPB_S5 _JBIDX(5) +#define JMPB_S6 _JBIDX(6) +#define JMPB_S7 _JBIDX(7) +#define JMPB_FP _JBIDX(8) +#define JMPB_SP _JBIDX(9) +#define JMPB_RA _JBIDX(10) + +#define JMPB_SIZE _JBIDX(11) + +#ifndef __ASSEMBLER__ +typedef long long jmp_buf[JMPB_SIZE]; +extern int lib_setjmp(jmp_buf); +extern void lib_longjmp(jmp_buf,int val); +#endif + diff --git a/cfe/cfe/arch/mips/common/include/mipsmacros.h b/cfe/cfe/arch/mips/common/include/mipsmacros.h new file mode 100755 index 0000000..072a5e6 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/mipsmacros.h @@ -0,0 +1,376 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * MIPS Macros File: mipsmacros.h + * + * Macros to deal with various mips-related things. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +/* ********************************************************************* + * 32/64-bit macros + ********************************************************************* */ + +#ifdef __long64 +#define _VECT_ .dword +#define _LONG_ .dword +#define SR sd +#define LR ld +#define ADD dadd +#define SUB dsub +#define MFC0 dmfc0 +#define MTC0 dmtc0 +#define REGSIZE 8 +#define BPWSIZE 3 /* bits per word size */ +#define _TBLIDX(x) ((x)*REGSIZE) +#else +#define _VECT_ .word +#define _LONG_ .word +#define SR sw +#define LR lw +#define ADD add +#define SUB sub +#define MFC0 mfc0 +#define MTC0 mtc0 +#define REGSIZE 4 +#define BPWSIZE 2 +#define _TBLIDX(x) ((x)*REGSIZE) +#endif + + +/* ********************************************************************* + * NORMAL_VECTOR(addr,vecname,vecdest) + * NORMAL_XVECTOR(addr,vecname,vecdest,code) + * + * Declare a trap or dispatch vector. There are two flavors, + * DECLARE_XVECTOR sets up an indentifying code in k0 before + * jumping to the dispatch routine. + * + * Input parameters: + * addr - vector address + * vecname - for label at that address + * vecdest - destination (place vector jumps to) + * code - code to place in k0 before jumping + * + * Return value: + * nothing + ********************************************************************* */ + + +#define NORMAL_VECTOR(addr,vecname,vecdest) \ + .globl vecname ; \ + .org addr ; \ +vecname: b vecdest ; \ + nop; + +#define NORMAL_XVECTOR(addr,vecname,vecdest,code) \ + .globl vecname ; \ + .org addr ; \ +vecname: b vecdest ; \ + li k0,code ; \ + nop; + + +/* ********************************************************************* + * Evil macros for bi-endian support. + * + * The magic here is in the instruction encoded as 0x10000014. + * + * This instruction in big-endian is: "b .+0x54" + * this instruction in little-endian is: "bne zero,zero,.+0x44" + * + * So, depending on what the system endianness is, it will either + * branch to .+0x54 or not branch at all. + * + * the instructions that follow are: + * + * 0x10000014 "magic branch" (either-endian) + * 0x00000000 nop (bds) (either-endian) + * 0xD0BF1A3C lui k0,0xBFD0 (little-endian) + * 0xxxxx5A27 addu k0,vector (little-endian) + * 0x08004003 jr k0 (little-endian) + * 0x00000000 nop (bds) (little-endian) + * ... space up to offset 0x54 + * ......... b vecaddr (big-endian) + * + * The idea is that the big-endian firmware is first, from 0..1MB + * in the flash, and the little-endian firmware is second, + * from 1..2MB in the flash. The little-endian firmware is + * set to load at BFD00000, so that its initial routines will + * work until relocation is completed. + * + * the instructions at the vectors will either jump to the + * big-endian or little-endian code based on system endianness. + * + * The ROM is built by compiling CFE twice, first with + * CFG_BIENDIAN=1 and CFG_LITTLE=0 (big-endian) and again + * with CFG_BIENDIAN=1 and CFG_LITTLE=1. The resulting + * cfe.bin files are located at 0xBFC00000 and 0xBFD00000 + * for big and little-endian versions, respectively. + * + * More information about how this works can be found in the + * CFE Manual. + ********************************************************************* */ + +#define __SWAPW(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8)) + +#define BIENDIAN_VECTOR(addr,vecname,vecdest) \ + .globl vecname ; \ + .org addr ; \ +vecname: .word 0x10000014 ; \ + .word 0 ; \ + .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \ + .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \ + .word 0x08004003 ; \ + .word 0 ; \ + .org ((addr) + 0x54) ; \ + b vecdest ; \ + nop; + +#define BIENDIAN_XVECTOR(addr,vecname,vecdest,code) \ + .globl vecname ; \ + .org addr ; \ +vecname: .word 0x10000014 ; \ + .word 0 ; \ + .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \ + .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \ + .word 0x08004003 ; \ + .word 0 ; \ + .org ((addr) + 0x54) ; \ + b vecdest ; \ + li k0,code ; \ + nop; + + + +/* ********************************************************************* + * Declare the right versions of DECLARE_VECTOR and + * DECLARE_XVECTOR depending on how we're building stuff. + * Generally, we only use the biendian version if we're building + * as CFG_BIENDIAN=1 and we're doing the big-endian MIPS version. + ********************************************************************* */ + +#if (CFG_BIENDIAN) && defined(__MIPSEB) +#define DECLARE_VECTOR BIENDIAN_VECTOR +#define DECLARE_XVECTOR BIENDIAN_XVECTOR +#else +#define DECLARE_VECTOR NORMAL_VECTOR +#define DECLARE_XVECTOR NORMAL_XVECTOR +#endif + + + +/* ********************************************************************* + * LOADREL(reg,label) + * + * Load the address of a label, but do it in a position-independent + * way. + * + * Input parameters: + * reg - register to load + * label - label whose address to load + * + * Return value: + * ra is trashed! + ********************************************************************* */ + +#if (!(CFG_RAMAPP)) +#define LOADREL(reg,label) \ + la reg, label ; \ + la ra, 100f ; \ + sub reg, ra ; \ + .set push ; \ + .set noreorder ; \ + bal 100f ; \ + nop ; \ + .set pop ; \ +100: ; \ + addu reg, ra +#else +#define LOADREL(reg,label) \ + la reg,label +#endif + +#if (CFG_RAMAPP) +#define FIXUP(addr) +#else +#define FIXUP(addr) \ + addu addr, s6 +#endif + + + +/* ********************************************************************* + * CALLINIT_KSEG1(label,table,offset) + * CALLINIT_KSEG0(label,table,offset) + * + * Call an initialization routine (usually in another module). + * If initialization routine lives in KSEG1 it may need + * special fixing if using the cached version of CFE (this is + * the default case). CFE is linked at a KSEG0 address. + * + * Embedded PIC is especially tricky, since the "la" + * instruction expands to calculations involving GP. + * In that case, use our table of offsets to + * load the routine address from a table in memory. + * + * Input parameters: + * label - routine to call if we can call directly + * table - symbol name of table containing routine addresses + * offset - offset within the above table + * + * Return value: + * k1,ra is trashed. + ********************************************************************* */ + + +#if CFG_RUNFROMKSEG0 +/* Cached PIC code - call indirect through table */ +#define CALLINIT_KSEG1(table,tableoffset) \ + LOADREL(k1,table) ; \ + or k1,K1BASE ; \ + LR k1,tableoffset(k1) ; \ + FIXUP (k1); \ + or k1,K1BASE ; \ + jal k1 +#define CALLINIT_KSEG0(table,tableoffset) \ + LOADREL(k1,table) ; \ + LR k1,tableoffset(k1) ; \ + FIXUP (k1); \ + jal k1 +#else +/* Uncached PIC code - call indirect through table, always same KSEG */ +#define CALLINIT_KSEG1(table,tableoffset) \ + LOADREL(k1,table) ; \ + LR k1,tableoffset(k1) ; \ + FIXUP (k1); \ + jal k1 +#define CALLINIT_KSEG0 CALLINIT_KSEG1 +#endif + +/* + * CALLINIT_RELOC is used once CFE's relocation is complete and + * the "mem_textreloc" variable is set up. (yes, this is nasty.) + * If 'gp' is set, we can presume that we've relocated + * and it's safe to read "mem_textreloc", otherwise use the + * address as-is from the table. + */ + +#define CALLINIT_RELOC CALLINIT_KSEG0 + +/* ********************************************************************* + * SPIN_LOCK(lock,reg1,reg2) + * + * Acquire a spin lock. + * + * Input parameters: + * lock - symbol (address) of lock to acquire + * reg1,reg2 - registers we can use to acquire lock + * + * Return value: + * nothing (lock acquired) + ********************************************************************* */ + +#define SPIN_LOCK(lock,reg1,reg2) \ + la reg1,lock ; \ +1: sync ; \ + ll reg2,0(reg1) ; \ + bne reg2,zero,1b ; \ + li reg2,1 ; \ + sc reg2,0(reg1) ; \ + beq reg2,zero,1b ; \ + nop + +/* ********************************************************************* + * SPIN_UNLOCK(lock,reg1) + * + * Release a spin lock. + * + * Input parameters: + * lock - symbol (address) of lock to release + * reg1 - a register we can use + * + * Return value: + * nothing (lock released) + ********************************************************************* */ + + +#define SPIN_UNLOCK(lock,reg1) \ + la reg1,lock ; \ + sw zero,0(reg1) + + +/* ********************************************************************* + * SETCCAMODE(treg,mode) + * + * Set cacheability mode. For some of the pass1 workarounds we + * do this alot, so here's a handy macro. + * + * Input parameters: + * treg - temporary register we can use + * mode - new mode (K_CFG_K0COH_xxx) + * + * Return value: + * nothing + ********************************************************************* */ + +#define SETCCAMODE(treg,mode) \ + mfc0 treg,C0_CONFIG ; \ + srl treg,treg,3 ; \ + sll treg,treg,3 ; \ + or treg,treg,mode ; \ + mtc0 treg,C0_CONFIG ; \ + HAZARD + + +/* ********************************************************************* + * Declare variables + ********************************************************************* */ + +#define DECLARE_LONG(x) \ + .global x ; \ +x: _LONG_ 0 + + + + +/* + * end + */ diff --git a/cfe/cfe/arch/mips/common/include/segtable.h b/cfe/cfe/arch/mips/common/include/segtable.h new file mode 100755 index 0000000..8a003f0 --- /dev/null +++ b/cfe/cfe/arch/mips/common/include/segtable.h @@ -0,0 +1,97 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Segment Table definitions File: segtable.h + * + * The 'segment table' (bad name) is just a list of addresses + * of important stuff used during initialization. We use these + * indirections to make life less complicated during code + * relocation. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#if !defined(__ASSEMBLER__) +#define _TBLIDX(x) (x) /* C handles indexing for us */ +typedef long segtable_t; /* 32 for long32, 64 for long64 */ +#endif + +/* + * Definitions for the segment_table + */ + +#define R_SEG_ETEXT _TBLIDX(0) /* end of text segment */ +#define R_SEG_FDATA _TBLIDX(1) /* Beginning of data segment */ +#define R_SEG_EDATA _TBLIDX(2) /* end of data segment */ +#define R_SEG_END _TBLIDX(3) /* End of BSS */ +#define R_SEG_FTEXT _TBLIDX(4) /* Beginning of text segment */ +#define R_SEG_FBSS _TBLIDX(5) /* Beginning of BSS */ +#define R_SEG_GP _TBLIDX(6) /* Global Pointer */ +#define R_SEG_RELOCSTART _TBLIDX(7) /* Start of reloc table */ +#define R_SEG_RELOCEND _TBLIDX(8) /* End of reloc table */ +#define R_SEG_APIENTRY _TBLIDX(9) /* API Entry address */ + +/* + * Definitions for the init_table + */ + +#define R_INIT_EARLYINIT _TBLIDX(0) /* pointer to board_earlyinit */ +#define R_INIT_SETLEDS _TBLIDX(1) /* pointer to board_setleds */ +#define R_INIT_DRAMINFO _TBLIDX(2) /* pointer to board_draminfo */ +#define R_INIT_CPUINIT _TBLIDX(3) /* pointer tp cpuinit */ +#define R_INIT_ALTCPU_START1 _TBLIDX(4) /* pointer to altcpu_start1 */ +#define R_INIT_ALTCPU_START2 _TBLIDX(5) /* pointer to altcpu_start2 */ +#define R_INIT_ALTCPU_RESET _TBLIDX(6) /* pointer to altcpu_reset */ +#define R_INIT_CPURESTART _TBLIDX(7) /* pointer to cpurestart */ +#define R_INIT_DRAMINIT _TBLIDX(8) /* pointer to draminit */ +#define R_INIT_CACHEOPS _TBLIDX(9) /* pointer to cacheops */ +#define R_INIT_TLBHANDLER _TBLIDX(10) /* pointer to TLB fault handler */ +#define R_INIT_CMDSTART _TBLIDX(11) /* pointer to cfe_main */ +#define R_INIT_CMDRESTART _TBLIDX(12) /* pointer to cfe_cmd_restart */ +#define R_INIT_DOXREQ _TBLIDX(13) /* pointer to cfe_doxreq */ +#define R_INIT_TP1_SWITCH _TBLIDX(14) /* pointer to tp1_switch */ +#define R_INIT_SIZERAM _TBLIDX(15) /* pointer to board_sizeram */ + +/* + * Definitions for the diag_table + */ + +#define R_DIAG_TEST1 _TBLIDX(0) /* after CPU and cache init, before DRAM init */ +#define R_DIAG_TEST2 _TBLIDX(1) /* after DRAM init, before main */ diff --git a/cfe/cfe/arch/mips/common/src/Makefile b/cfe/cfe/arch/mips/common/src/Makefile new file mode 100755 index 0000000..638113d --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/Makefile @@ -0,0 +1,38 @@ + +# +# This is just a Makefile fragment -- it is included by the master +# makefile, cfe.mk +# +# This file should just append object file names to "ALLOBJS", +# but since it is mean to be linked *first*, it will append +# modules to "CRT0OBJS" +# + +ifndef INIT_MIPS +INIT_MIPS = init_mips.o +endif + +ifeq ($(strip ${CFG_RAMAPP}),1) +CRT0OBJS += init_ram.o exception.o +else +CRT0OBJS += $(INIT_MIPS) +endif + +ifeq ($(strip ${CFG_RAMAPP}),1) +ALLOBJS += lib_hssubr.o lib_setjmp.o mips_arena.o exchandler.o +ALLOBJS += dev_flash_all.o dev_flashop_engine.o +ALLOBJS += ui_memtest.o +endif + +makereg : ${TOP}/hosttools/makereg.c + gcc -o makereg ${TOP}/hosttools/makereg.c + +%.inc : %.regdef makereg + ./makereg $< $@ + +ui_soccmds.o : ${CPU_SRC}/ui_soccmds.c ${CPU}_socregs.inc + +vapi.o : ${TOP}/verif/vapi.S sb1250_socregs.inc + + + diff --git a/cfe/cfe/arch/mips/common/src/cfe_ram_cached.lds b/cfe/cfe/arch/mips/common/src/cfe_ram_cached.lds new file mode 100644 index 0000000..4b8ce87 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_ram_cached.lds @@ -0,0 +1,40 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0x9fc00000; /* was 0x9fc00000 */ + .text : +/* AT ( 0xBFC00000 ) */ /* was 0xbfc00000 */ + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + *(.fini) + *(.rodata) + _etext = .; + } + + .data : + { + _fdata = ALIGN(16) ; + *(.data) + CONSTRUCTORS + . = ALIGN(16); + _gp = . + 0x8000; + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_ram_uncached.lds b/cfe/cfe/arch/mips/common/src/cfe_ram_uncached.lds new file mode 100644 index 0000000..4295fe4 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_ram_uncached.lds @@ -0,0 +1,40 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0xbfc00000; /* was 0x9fc00000 */ + .text : +/* AT ( 0xBFC00000 ) */ /* was 0xbfc00000 */ + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + *(.fini) + *(.rodata) + _etext = .; + } + + .data : + { + _fdata = ALIGN(16) ; + *(.data) + CONSTRUCTORS + . = ALIGN(16); + _gp = . + 0x8000; + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_ramapp.lds b/cfe/cfe/arch/mips/common/src/cfe_ramapp.lds new file mode 100755 index 0000000..5a7a377 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_ramapp.lds @@ -0,0 +1,41 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0x80601000; + .text : + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + *(.fini) + *(.rodata) + *(.rodata.str1.4) + *(.gnu.linkonce.r.*) + _etext = .; + } + + .data : + { + _fdata = ALIGN(16) ; + *(.data) + CONSTRUCTORS + . = ALIGN(16); + _gp = . + 0x8000; + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_cached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_cached.lds new file mode 100755 index 0000000..2ca1353 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_rom_cached.lds @@ -0,0 +1,40 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0x80000000; + .text : + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + *(.fini) + *(.rodata) + _etext = .; + } + + .data : + { + _fdata = ALIGN(16) ; + *(.data) + CONSTRUCTORS + . = ALIGN(16); + _gp = . + 0x8000; + *(.sdata) + } + . = ALIGN(16); + _edata = .; + .reginfo : {} + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached.lds new file mode 100644 index 0000000..ee94831 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached.lds @@ -0,0 +1,43 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0x9FC00000; + .text : + AT ( 0xBFC00000 ) + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + *(.fini) + *(.rodata) + _etext = .; + } + .data 0x80001000 : + AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0) + { + _gp = ALIGN(16) + 0x8000; + _fdata = .; + *(.rdata) + *(.data) + CONSTRUCTORS + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds new file mode 100644 index 0000000..78421a4 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds @@ -0,0 +1,49 @@ +/* + * This linker script is exactly the same as cfe_rom_reloc_cached.lds + * except our start address is at BFD00000, 1MB into the + * ROM. We locate the little-endian version of CFE at this address + * in bi-endian ROM support. + */ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0x9FD00000; + .text : + AT ( 0xBFD00000 ) + { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + *(.fini) + *(.rodata) + _etext = .; + } + .data 0x80001000 : + AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0) + { + _gp = ALIGN(16) + 0x8000; + _fdata = .; + *(.rdata) + *(.data) + CONSTRUCTORS + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_uncached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_uncached.lds new file mode 100644 index 0000000..0c62889 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_uncached.lds @@ -0,0 +1,41 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0xBFC00000; + .text : { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + *(.fini) + *(.rodata) + _etext = .; + } + .data 0xA0001000 : + AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0) + { + _gp = ALIGN(16) + 0x8000; + _fdata = .; + *(.rdata) + *(.data) + CONSTRUCTORS + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_uncached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_uncached.lds new file mode 100644 index 0000000..a0362ba --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/cfe_rom_uncached.lds @@ -0,0 +1,39 @@ +OUTPUT_ARCH(mips) +ENTRY(vec_reset) +SECTIONS +{ + . = 0xBFC00000; + .text : { + _ftext = . ; + *(.init) + eprol = .; + *(.text) + *(.fini) + *(.rodata) + _etext = .; + } + + .data 0xA1F00000 : + AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0) + { + _fdata = ALIGN(16) ; + *(.data) + CONSTRUCTORS + . = ALIGN(16); + _gp = . + 0x8000; + *(.sdata) + } + . = ALIGN(16); + _edata = .; + _fbss = .; + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + . = ALIGN(16); + _end = .; +} diff --git a/cfe/cfe/arch/mips/common/src/dev_flash_all.S b/cfe/cfe/arch/mips/common/src/dev_flash_all.S new file mode 100644 index 0000000..6dbb581 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/dev_flash_all.S @@ -0,0 +1,220 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Flash "self-write" module File: flash_write_all.S + * + * This module takes care of the case of writing to the flash + * memory that CFE is currently reading its code from. It is + * assumed that you'll be doing a complete flash update, + * so this code erases the affected sectors, reprograms them, + * and jumps to the boot sector. + * + * Note: this code is written to be position-independent, even + * for non-PIC versions of CFE! It will be copied (with memcpy) + * into the heap for execution. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include "sbmips.h" +#include "dev_flash.h" +#include "mipsmacros.h" + +#define WRITEFLASH(base,offset,value) \ + li t0,value ; \ + sb t0,offset(base) + + +/* ********************************************************************* + * flash_write_all(data,flashbase,size,secsize) + * + * Write bytes to flash, erasing affected sectors first. + * + * Input parameters: + * a0 - data - pointer to data to write + * a1 - flashbase - base (phys addr) of flash area + * a2 - size - number of bytes to write + * a3 - secsize - flash sector size + * + * Return value: + * does not return + ********************************************************************* */ + +#define data a0 +#define flashbase a1 +#define datasize a2 +#define secsize a3 + +#define secidx t4 +#define secptr t5 + +LEAF(flash_write_all) + + /* + * Mask all interrupts. An exception with BEV set would be very bad. + */ + + mfc0 v0,C0_SR # Get current interrupt flag + li v1,M_SR_IE # master interrupt control + not v1 # disable interrupts + and v0,v1 # SR now has IE=0 + mtc0 v0,C0_SR # put back into CP0 + + /* + * Get KSEG1 addr of flash + */ + + or flashbase,K1BASE + + + /* + * Do an "unlock write" sequence (cycles 1-2) + */ + + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* + * send the erase command (cycle 3) + */ + + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3) + + /* + * Do an "unlock write" sequence (cycles 4-5) + */ + + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* + * Send the "erase all" qualifier (cycle 6) + */ + + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_ALL_6) + + /* + * Wait for the erase to complete + */ + +1: lb t0,0(secptr) # get byte + and t0,0xFF # test hi byte + bne t0,0xFF,1b # go till bit is set + + + /* + * Okay, now loop through the bytes and write them to the + * flash. + */ + + move secptr,flashbase + move secidx,datasize + +proglp: + + /* + * Do an "unlock write" sequence + */ + + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* + * Send a program command + */ + WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM) + + /* + * Write a byte + */ + + lbu t0,0(data) + sb t0,0(secptr) # t0 = byte written to flash + + + /* + * Wait for write to complete + */ + +1: lbu t2,0(secptr) # t2 = byte from flash + + and t1,t2,0x80 # done if bit7 of flash + and t0,t0,0x80 # is same as bit7 of data + beq t1,t0,2f + + and t1,t2,0x20 # not done if bit5 + bne t1,0x20,1b # is still set +2: + + /* + * next byte... + */ + + add a0,1 # next source byte + add secptr,1 # next dest byte + sub datasize,1 # one less count + bgt datasize,0,proglp + + /* + * All done, reboot system + */ + + li v0,0xBFC00000 + j v0 + +flash_write_all_end: + nop + +END(flash_write_all) + +/* ********************************************************************* + * Data + ********************************************************************* */ + + .sdata + + .globl flash_write_all_ptr + .globl flash_write_all_len + +flash_write_all_ptr: + _VECT_ flash_write_all +flash_write_all_len: + .word flash_write_all_end-flash_write_all + + diff --git a/cfe/cfe/arch/mips/common/src/dev_flashop_engine.S b/cfe/cfe/arch/mips/common/src/dev_flashop_engine.S new file mode 100644 index 0000000..29ade6a --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/dev_flashop_engine.S @@ -0,0 +1,695 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Flash "self-write" module File: dev_flashop_engine.S + * + * This module takes care of the case of writing to the flash + * memory that CFE is currently reading its code from. + * + * Note: this code is written to be position-independent, even + * for non-PIC versions of CFE! It will be copied (with memcpy) + * into the heap for execution. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include "sbmips.h" +#include "mipsmacros.h" + +#include "bsp_config.h" +#include "dev_newflash.h" + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#define FLASHCMD_8(base,offset,value) \ + li t0,value ; \ + sb t0,offset(base) + +#define FLASHCMD_16(base,offset,value) \ + li t0,value ; \ + sh t0,((offset)<<1)(base) + +#define FLASHCMD_16B(base,offset,value) \ + li t0,value ; \ + sb t0,((offset)<<1)(base) + + +/* ********************************************************************* + * flashop_engine + * + * This routine is written in a PIC method to allow us to do + * flash operations without any help from CFE. We need to do + * this when we're not relocated and want to muck with the + * flash we're running from. + * + * This routine follows some simple instructions in a table, + * so you can batch up the operations in one place. + * + * Input parameters: + * a0 - pointer to instruction list + * + * Return value: + * v0 - 0 if all instructions succeeded + * else less than zero, # of failing instructions + ********************************************************************* */ + + .text + +#define reg_op t3 +#define reg_base t4 +#define reg_dest t5 +#define reg_src t6 +#define reg_cnt t7 + +LEAF(flashop_engine) + +instloop: LR reg_op,FEINST_OP(a0) /* Load instruction */ + LR reg_base,FEINST_BASE(a0) + LR reg_dest,FEINST_DEST(a0) + LR reg_src,FEINST_SRC(a0) + LR reg_cnt,FEINST_CNT(a0) + li v0,0 /* total of result values */ + li v1,0 /* result for this function */ + +#ifdef __long64 + dli t0,0x9000000000000000 /* uncached - XKPHYS */ + or reg_base,t0 /* so we can access flash beyond KSEG */ +#else + or reg_base,K1BASE /* 32-bit, regular KSEG */ +#endif + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + bne reg_op,FEOP_RETURN,99f /* Return to main prog */ + + j ra +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_REBOOT,99f /* restart system */ + + li t0,0xBFC00000 /* jump to boot vector */ + j t0 +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_READ8,99f /* Read, 8-bit mode */ + + ADD reg_src,reg_src,reg_base + +1: lbu t0,0(reg_src) /* Copy user data */ + sb t0,0(reg_dest) + ADD reg_src,1 + add reg_dest,1 + sub reg_cnt,1 + bgt reg_cnt,zero,1b + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_READ16,99f /* Read, 16-bit mode */ + + ADD reg_src,reg_src,reg_base + + li t0,1 /* test bottom bit */ + and t0,t0,reg_src /* t0 == 1 if odd */ + beq t0,zero,1f /* no odd byte to worry about */ + + SUB reg_src,reg_src,t0 /* make even value */ + lh t0,0(reg_src) /* interesting byte is odd */ +#ifdef __MIPSEB + sb t0,0(reg_dest) /* interesting byte in low 8 bits */ +#else + srl t0,t0,8 /* little endian */ + sb t0,0(reg_dest) /* interesting byte is high 8 bits */ +#endif + + ADD reg_src,2 /* advance one word (we made addr even above) */ + add reg_dest,1 /* dest always written by bytes */ + sub reg_cnt,1 + +1: beq reg_cnt,zero,nextinst + + lh t0,0(reg_src) /* Copy user data */ + +#ifdef __MIPSEB + sb t0,1(reg_dest) /* Big endian to memory */ + srl t0,t0,8 /* t0 = 0x1234 -> 0x12 0x34 */ + sb t0,0(reg_dest) +#else + sb t0,0(reg_dest) /* little endian */ + srl t0,t0,8 /* t0 = 0x1234 -> 0x34 0x12 */ + sb t0,1(reg_dest) +#endif + + ADD reg_src,2 + add reg_dest,2 + sub reg_cnt,2 + bgt reg_cnt,1,1b + + beq reg_cnt,zero,nextinst /* no straggler */ + + lh t0,0(reg_src) /* interesting byte is odd */ +#ifdef __MIPSEB + srl t0,t0,8 /* little endian */ + sb t0,0(reg_dest) /* interesting byte in high 8 bits */ +#else + sb t0,0(reg_dest) /* interesting byte is low 8 bits */ +#endif + + b nextinst +/* CFI - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +#if (FLASH_DRIVERS & FLASH_DRIVER_CFI) +99: bne reg_op,FEOP_CFIQUERY8,99f /* CFI Query 8-bit */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_8(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE) + +1: lbu t0,0(reg_src) /* Copy CFI data */ + sb t0,0(reg_dest) + ADD reg_src,1 + add reg_dest,1 + sub reg_cnt,1 + bgt reg_cnt,zero,1b + + FLASHCMD_8(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_CFIQUERY16,99f /* CFI Query 16-bit in word mode */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE) + +1: lh t0,0(reg_src) /* Copy CFI data */ + sh t0,0(reg_dest) + ADD reg_src,2 + add reg_dest,2 + sub reg_cnt,2 + bgt reg_cnt,zero,1b + + FLASHCMD_16(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_CFIQUERY16B,99f /* CFI Query 16-bit in byte mode */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16B(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE) + +1: lb t0,0(reg_src) /* Copy CFI data */ + sb t0,0(reg_dest) + ADD reg_src,1 + add reg_dest,1 + sub reg_cnt,1 + bgt reg_cnt,zero,1b + + FLASHCMD_16B(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT) + + b nextinst +#endif + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_MEMCPY,99f /* Generic memcpy */ + +1: lbu t0,0(reg_src) + sb t0,0(reg_dest) + add reg_src,1 + add reg_dest,1 + sub reg_cnt,1 + bgt reg_cnt,zero,1b + + b nextinst + + +/* AMD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +#if (FLASH_DRIVERS & FLASH_DRIVER_AMD) +99: bne reg_op,FEOP_AMD_ERASE8,99f /* AMD erase (8-bit) */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* send the erase command (cycle 3) */ + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3) + + /* Do an "unlock write" sequence (cycles 4-5) */ + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send the "erase sector" qualifier (cycle 6) */ + + FLASHCMD_8(reg_dest,0,AMD_FLASH_ERASE_SEC_6) + + /* Wait for the erase to complete */ + +1: lb t0,0(reg_dest) # get byte + and t0,0xFF # test hi byte + bne t0,0xFF,1b # go till bit is set + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_ERASE16,99f /* AMD erase (16-bit in word mode) */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* send the erase command (cycle 3) */ + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3) + + /* Do an "unlock write" sequence (cycles 4-5) */ + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send the "erase sector" qualifier (cycle 6) */ + + FLASHCMD_16(reg_dest,0,AMD_FLASH_ERASE_SEC_6) + + /* Wait for the erase to complete */ + +1: lh t0,0(reg_dest) # get word + and t0,0xFF # test byte + bne t0,0xFF,1b # go till erased + + b nextinst + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_ERASE16B,99f /* AMD erase (16-bit in byte mode) */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* send the erase command (cycle 3) */ + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3) + + /* Do an "unlock write" sequence (cycles 4-5) */ + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send the "erase sector" qualifier (cycle 6) */ + + FLASHCMD_16B(reg_dest,0,AMD_FLASH_ERASE_SEC_6) + + /* Wait for the erase to complete */ + +1: lh t0,0(reg_dest) # get word + and t0,0xFF # test byte + bne t0,0xFF,1b # go till erased + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_PGM8,99f /* AMD 8-bit program */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ +11: + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send a program command (cycle 3) */ + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM) + + /* Write a byte (cycle 4) */ + + lbu t0,0(reg_src) + sb t0,0(reg_dest) # t0 = byte written to flash + + /* Wait for write to complete */ + +1: lbu t2,0(reg_dest) # t2 = byte from flash + + and t1,t2,0x80 # done if bit7 of flash + and t0,t0,0x80 # is same as bit7 of data + beq t1,t0,2f + + and t1,t2,0x20 # not done if bit5 + bne t1,0x20,1b # is still set +2: + + /* next byte... */ + + add reg_src,1 # next source byte + ADD reg_dest,1 # next dest byte + sub reg_cnt,1 # one less count + bgt reg_cnt,0,11b + + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_PGM16,99f /* AMD 16-bit program */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ +11: + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send a program command (cycle 3) */ + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM) + + /* Write a byte (cycle 4) */ + + lh t0,0(reg_src) + sh t0,0(reg_dest) # t0 = byte written to flash + + /* Wait for write to complete */ + +1: lh t2,0(reg_dest) # t2 = byte from flash + + and t1,t2,0x80 # done if bit7 of flash + and t0,t0,0x80 # is same as bit7 of data + beq t1,t0,2f + + and t1,t2,0x20 # not done if bit5 + bne t1,0x20,1b # is still set +2: + + /* next byte... */ + + add reg_src,2 # next source word + ADD reg_dest,2 # next dest word + sub reg_cnt,2 # one less count + bgt reg_cnt,0,11b + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_PGM16B,99f /* AMD 16-bit pgm in 8-bit mode */ + + ADD reg_dest,reg_dest,reg_base + + /* Do an "unlock write" sequence (cycles 1-2) */ +11: + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + + /* Send a program command (cycle 3) */ + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM) + + /* Write a byte (cycle 4) */ + + lb t0,0(reg_src) + sb t0,0(reg_dest) # t0 = byte written to flash + + /* Wait for write to complete */ + +1: lb t2,0(reg_dest) # t2 = byte from flash + + and t1,t2,0x80 # done if bit7 of flash + and t0,t0,0x80 # is same as bit7 of data + beq t1,t0,2f + + and t1,t2,0x20 # not done if bit5 + bne t1,0x20,1b # is still set +2: + + /* next byte... */ + + add reg_src,1 # next source word + ADD reg_dest,1 # next dest word + sub reg_cnt,1 # one less count + bgt reg_cnt,0,11b + + b nextinst + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_DEVCODE8,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lbu t0,AMD_FLASH_DEVCODE8(reg_src) + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_DEVCODE16,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lw t0,0(reg_src) +#ifdef __MIPSEB + srl t0,t0,8 /* ((3-AMD_FLASH_DEVCODE16)*8) */ +#else + srl t0,t0,16 /* (AMD_FLASH_DEVCODE16*8) */ +#endif + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_DEVCODE16B,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lw t0,0(reg_src) +#ifdef __MIPSEB +#else + srl t0,t0,16 /* (AMD_FLASH_DEVCODE16B*8)*/ +#endif + + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_MANID8,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lbu t0,AMD_FLASH_MANID(reg_src) + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_MANID16,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lw t0,0(reg_src) +#ifdef __MIPSEB + srl t0,t0,((3-AMD_FLASH_MANID)*8) +#else + srl t0,t0,(AMD_FLASH_MANID*8) +#endif + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_AMD_MANID16B,99f /* AMD 8-bit - Boot Block Location */ + + ADD reg_src,reg_src,reg_base + + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2) + FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL) + + lbu t0,AMD_FLASH_MANID(reg_src) + + sb t0,0(reg_dest) + li t0,AMD_FLASH_RESET + sb t0,0(reg_src) + + b nextinst + +#endif + +/* INTEL - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +#if (FLASH_DRIVERS & FLASH_DRIVER_INTEL) +99: bne reg_op,FEOP_INTEL_ERASE8,99f /* Intel erase 8-bit */ + + ADD reg_dest,reg_dest,reg_base + + FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_BLOCK) + FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_CONFIRM) + +1: lbu t0,0(reg_dest) /* loop till bit 7 is set */ + andi t0,0x80 + beq t0,zero,1b + + FLASHCMD_8(reg_dest,0,INTEL_FLASH_READ_MODE) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_INTEL_ERASE16,99f /* Intel erase 16-bit */ + + ADD reg_dest,reg_dest,reg_base + +/* XXX copy of 8-bit erase, is this right? */ + + FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_BLOCK) + FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_CONFIRM) + +1: lbu t0,0(reg_dest) /* loop till bit 7 is set */ + andi t0,0x80 + beq t0,zero,1b + + FLASHCMD_8(reg_dest,0,INTEL_FLASH_READ_MODE) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_INTEL_PGM8,99f /* Intel 8-bit program */ + + ADD reg_dest,reg_dest,reg_base + +11: FLASHCMD_8(reg_dest,0,INTEL_FLASH_PROGRAM) + + lbu t0,0(reg_src) + sb t0,0(reg_dest) + +1: lbu t0,0(reg_dest) /* loop till bit 7 is set */ + andi t0,0x80 + beq t0,zero,1b + + lbu t0,0(reg_dest) /* contains final result */ + /* If good, bits 1, 3, 4 will not be set */ + + add reg_src,1 + ADD reg_dest,1 + sub reg_cnt,1 + bgt reg_cnt,zero,11b + + FLASHCMD_8(reg_dest,0,INTEL_FLASH_READ_MODE) + + b nextinst +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: bne reg_op,FEOP_INTEL_PGM16,99f /* Intel 16-bit prog */ + + ADD reg_dest,reg_dest,reg_base + +11: FLASHCMD_16(reg_dest,0,INTEL_FLASH_PROGRAM) + + lh t0,0(reg_src) + sh t0,0(reg_dest) + +1: lh t0,0(reg_dest) /* loop till bit 7 is set */ + andi t0,0x80 + beq t0,zero,1b + + lh t0,0(reg_dest) /* contains final result */ + /* If good, bits 1, 3, 4 will not be set */ + + add reg_src,2 + ADD reg_dest,2 + sub reg_cnt,2 + bgt reg_cnt,zero,11b + + FLASHCMD_16(reg_dest,0,INTEL_FLASH_READ_MODE) + + b nextinst +#endif +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +99: li v1,-1 /* invalid command */ + +nextinst: SR v1,FEINST_RESULT(a0) /* store result of instruction */ + ADD v0,v0,v1 /* add to total */ + ADD a0,FEINST_SIZE /* advance to next instr. */ + b instloop + +flashop_engine_end: + nop + +END(flashop_engine) + + .sdata + + .globl flashop_engine_ptr + .globl flashop_engine_len + +flashop_engine_ptr: + _VECT_ flashop_engine +flashop_engine_len: + .word flashop_engine_end-flashop_engine + + + +/* ********************************************************************* + * end + ********************************************************************* */ + + diff --git a/cfe/cfe/arch/mips/common/src/disasm.c b/cfe/cfe/arch/mips/common/src/disasm.c new file mode 100644 index 0000000..1b76fee --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/disasm.c @@ -0,0 +1,2111 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * MIPS disassembler File: disasm.c + * + * MIPS disassembler (used by ui_examcmds.c) + * + * Author: Justin Carlson (carlson@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "lib_types.h" +#include "lib_string.h" +#include "disasm.h" +#include "lib_printf.h" + +#define UINT64_T(x) ((uint64_t) (x)) +#define PF_64 "ll" +#define PF_32 "" +/* These aren't guaranteed to be portable, either */ +#define SEXT_32(bit, val) \ + ((((int32_t)(val))<<(31-(bit)))>>(31-(bit))) +#define SEXT_64(bit, val) \ + ((((int64_t)(val))<<(63-(bit)))>>(63-(bit))) + +#define DATASEG __attribute__ ((section(".text"))) + + +#define REGNAME(r) (&_regnames[(r)*5]) +static const char * const _regnames = + "zero\0" + "AT\0 " + "v0\0 " + "v1\0 " + "a0\0 " + "a1\0 " + "a2\0 " + "a3\0 " + "t0\0 " + "t1\0 " + "t2\0 " + "t3\0 " + "t4\0 " + "t5\0 " + "t6\0 " + "t7\0 " + "s0\0 " + "s1\0 " + "s2\0 " + "s3\0 " + "s4\0 " + "s5\0 " + "s6\0 " + "s7\0 " + "t8\0 " + "t9\0 " + "k0\0 " + "k1\0 " + "gp\0 " + "sp\0 " + "fp\0 " + "ra\0 "; + +#define CP0REGNAME(r) (&_cp0names[(r)*12]) +static const char * const _cp0names = + "C0_INX\0 " + "C0_RAND\0 " + "C0_TLBLO0\0 " + "C0_TLBLO1\0 " + + "C0_CTEXT\0 " + "C0_PGMASK\0 " + "C0_WIRED\0 " + "C0_reserved\0" + + "C0_BADVADDR\0" + "C0_COUNT\0 " + "C0_TLBHI\0 " + "C0_COMPARE\0 " + + "C0_SR\0 " + "C0_CAUSE\0 " + "C0_EPC\0 " + "C0_PRID\0 " + + "C0_CONFIG\0 " + "C0_LLADDR\0 " + "C0_WATCHLO\0 " + "C0_WATCHHI\0 " + + "C0_XCTEXT\0 " + "C0_reserved\0" + "C0_reserved\0" + "C0_reserved\0" + + "C0_reserved\0" + "C0_reserved\0" + "C0_reserved\0" + "C0_reserved\0" + + "C0_TAGLO\0 " + "C0_TAGHI\0 " + "C0_ERREPC\0 " + "C0_reserved\0"; + + + +/* + * MIPS instruction set disassembly module. + */ + +typedef enum { + DC_RD_RS_RT, + DC_RD_RT_RS, + DC_RT_RS_SIMM, + DC_RT_RS_XIMM, + DC_RS_RT_OFS, + DC_RS_OFS, + DC_RD_RT_SA, + DC_RT_UIMM, + DC_RD, + DC_J, + DC_RD_RS, + DC_RS_RT, + DC_RT_RS, + DC_RT_RD_SEL, + DC_RT_CR_SEL, + DC_RS, + DC_RS_SIMM, + DC_RT_OFS_BASE, + DC_FT_OFS_BASE, + DC_FD_IDX_BASE, + DC_FS_IDX_BASE, + DC_FD_FS_FT, + DC_FD_FS_RT, + DC_FD_FS, + DC_PREF_OFS, + DC_PREF_IDX, + DC_CC_OFS, + DC_FD_FS_CC, + DC_RD_RS_CC, + DC_FD_FR_FS_FT, + DC_FD_FS_FT_RS, + DC_CC_FS_FT, + DC_BARE, + DC_RT_FS, + DC_SYSCALL, + DC_BREAK, + DC_VD_VS_VT_VEC, + DC_VD_VS_VT, + DC_VS_VT, + DC_VS_VT_VEC, + DC_VD_VS_VT_RS, + DC_VD_VS_VT_IMM, + DC_VD_VT, + DC_VD, + DC_VS, + DC_DEREF, + DC_OOPS +} DISASM_CLASS; + + + + +/* We're pulling some trickery here. Most of the time, this structure operates + exactly as one would expect. The special case, when type == DC_DREF, + means name points to a byte that is an index into a dereferencing array. */ + +/* + * To make matters worse, the whole module has been coded to reduce the + * number of relocations present, so we don't actually store pointers + * in the dereferencing array. Instead, we store fixed-width strings + * and use digits to represent indicies into the deref array. + * + * This is all to make more things fit in the relocatable version, + * since every initialized pointer goes into our small data segment. + */ + +typedef struct { + char name[15]; + char type; +} disasm_t; + +typedef struct { + const disasm_t *ptr; + int shift; + uint32_t mask; +} disasm_deref_t; + +/* Forward declaration of deref array, we need this for the disasm_t definitions */ + + +extern const disasm_deref_t disasm_deref[]; + +static const disasm_t disasm_normal[64] DATASEG = +{{"$1" , DC_DEREF }, + {"$2" , DC_DEREF }, + {"j" , DC_J }, + {"jal" , DC_J }, + {"beq" , DC_RS_RT_OFS }, + {"bne" , DC_RS_RT_OFS }, + {"blez" , DC_RS_OFS }, + {"bgtz" , DC_RS_OFS }, + {"addi" , DC_RT_RS_SIMM }, + {"addiu" , DC_RT_RS_SIMM }, + {"slti" , DC_RT_RS_SIMM }, + {"sltiu" , DC_RT_RS_SIMM }, + {"andi" , DC_RT_RS_XIMM }, + {"ori" , DC_RT_RS_XIMM }, + {"xori" , DC_RT_RS_XIMM }, + {"lui" , DC_RT_UIMM }, + {"$4" , DC_DEREF }, + {"$6" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"$15" , DC_DEREF }, + {"beql" , DC_RS_RT_OFS }, + {"bnel" , DC_RS_RT_OFS }, + {"blezl" , DC_RS_OFS }, + {"bgtzl" , DC_RS_OFS }, + {"daddi" , DC_RT_RS_SIMM }, + {"daddiu" , DC_RT_RS_SIMM }, + {"ldl" , DC_RT_OFS_BASE }, + {"ldr" , DC_RT_OFS_BASE }, + {"$3" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"$18" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"lb" , DC_RT_OFS_BASE }, + {"lh" , DC_RT_OFS_BASE }, + {"lwl" , DC_RT_OFS_BASE }, + {"lw" , DC_RT_OFS_BASE }, + {"lbu" , DC_RT_OFS_BASE }, + {"lhu" , DC_RT_OFS_BASE }, + {"lwr" , DC_RT_OFS_BASE }, + {"lwu" , DC_RT_OFS_BASE }, + {"sb" , DC_RT_OFS_BASE }, + {"sh" , DC_RT_OFS_BASE }, + {"swl" , DC_RT_OFS_BASE }, + {"sw" , DC_RT_OFS_BASE }, + {"sdl" , DC_RT_OFS_BASE }, + {"sdr" , DC_RT_OFS_BASE }, + {"swr" , DC_RT_OFS_BASE }, + {"cache" , DC_BARE }, + {"ll" , DC_RT_OFS_BASE }, + {"lwc1" , DC_FT_OFS_BASE }, + {"invalid" , DC_BARE }, + {"pref" , DC_PREF_OFS }, + {"lld" , DC_RT_OFS_BASE }, + {"ldc1" , DC_FT_OFS_BASE }, + {"invalid" , DC_BARE }, + {"ld" , DC_RT_OFS_BASE }, + {"sc" , DC_RT_OFS_BASE }, + {"swc1" , DC_FT_OFS_BASE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"scd" , DC_RT_OFS_BASE }, + {"sdc1" , DC_FT_OFS_BASE }, + {"invalid" , DC_BARE }, + {"sd" , DC_RT_OFS_BASE }}; + +static const disasm_t disasm_special[64] DATASEG = +{{"sll" , DC_RD_RT_SA }, + {"$16" , DC_DEREF }, + {"srl" , DC_RD_RT_SA }, + {"sra" , DC_RD_RT_SA }, + {"sllv" , DC_RD_RT_RS }, + {"invalid" , DC_BARE }, + {"srlv" , DC_RD_RT_RS }, + {"srav" , DC_RD_RT_RS }, + {"jr" , DC_RS }, + {"jalr" , DC_RD_RS }, + {"movz" , DC_RD_RS_RT }, + {"movn" , DC_RD_RS_RT }, + {"syscall" , DC_SYSCALL }, + {"break" , DC_BREAK }, + {"invalid" , DC_BARE }, + {"sync" , DC_BARE }, + {"mfhi" , DC_RD }, + {"mthi" , DC_RS }, + {"mflo" , DC_RD }, + {"mtlo" , DC_RS }, + {"dsllv" , DC_RD_RT_RS }, + {"invalid" , DC_BARE }, + {"dsrlv" , DC_RD_RT_RS }, + {"dsrav" , DC_RD_RT_RS }, + {"mult" , DC_RS_RT }, + {"multu" , DC_RS_RT }, + {"div" , DC_RS_RT }, + {"divu" , DC_RS_RT }, + {"dmult" , DC_RS_RT }, + {"dmultu" , DC_RS_RT }, + {"ddiv" , DC_RS_RT }, + {"ddivu" , DC_RS_RT }, + {"add" , DC_RD_RS_RT }, + {"addu" , DC_RD_RS_RT }, + {"sub" , DC_RD_RS_RT }, + {"subu" , DC_RD_RS_RT }, + {"and" , DC_RD_RS_RT }, + {"or" , DC_RD_RS_RT }, + {"xor" , DC_RD_RS_RT }, + {"nor" , DC_RD_RS_RT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"slt" , DC_RD_RS_RT }, + {"sltu" , DC_RD_RS_RT }, + {"dadd" , DC_RD_RS_RT }, + {"daddu" , DC_RD_RS_RT }, + {"dsub" , DC_RD_RS_RT }, + {"dsubu" , DC_RD_RS_RT }, + {"tge" , DC_RS_RT }, + {"tgeu" , DC_RS_RT }, + {"tlt" , DC_RS_RT }, + {"tltu" , DC_RS_RT }, + {"teq" , DC_RS_RT }, + {"invalid" , DC_BARE }, + {"tne" , DC_RS_RT }, + {"invalid" , DC_BARE }, + {"dsll" , DC_RD_RT_SA }, + {"invalid" , DC_BARE }, + {"dsrl" , DC_RD_RT_SA }, + {"dsra" , DC_RD_RT_SA }, + {"dsll32" , DC_RD_RT_SA }, + {"invalid" , DC_BARE }, + {"dsrl32" , DC_RD_RT_SA }, + {"dsra32" , DC_RD_RT_SA }}; + +static const disasm_t disasm_movci[2] DATASEG = +{{"movf" , DC_RD_RS_CC }, + {"movt" , DC_RD_RS_CC }}; + +static const disasm_t disasm_regimm[32] DATASEG = +{{"bltz" , DC_RS_OFS }, + {"bgez" , DC_RS_OFS }, + {"bltzl" , DC_RS_OFS }, + {"bgezl" , DC_RS_OFS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"tgei" , DC_RS_SIMM }, + {"tgeiu" , DC_RS_SIMM }, + {"tlti" , DC_RS_SIMM }, + {"tltiu" , DC_RS_SIMM }, + {"teqi" , DC_RS_SIMM }, + {"invalid" , DC_BARE }, + {"tnei" , DC_RS_SIMM }, + {"invalid" , DC_BARE }, + {"bltzal" , DC_RS_OFS }, + {"bgezal" , DC_RS_OFS }, + {"bltzall" , DC_RS_OFS }, + {"bgezall" , DC_RS_OFS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_spec2[64] DATASEG = +{{"madd" , DC_RS_RT }, + {"maddu" , DC_RS_RT }, + {"mul" , DC_RD_RS_RT }, + {"invalid" , DC_BARE }, + {"msub" , DC_RS_RT }, + {"msubu" , DC_RS_RT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"clz" , DC_RT_RS }, + {"clo" , DC_RT_RS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"dclz" , DC_RT_RS }, + {"dclo" , DC_RT_RS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"sdbbp" , DC_BARE }}; + +static const disasm_t disasm_cop0[32] DATASEG = +{{"mfc0@1" , DC_RT_CR_SEL }, + {"dmfc0@1" , DC_RT_CR_SEL }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"mtc0@1" , DC_RT_CR_SEL }, + {"dmtc0@1" , DC_RT_CR_SEL }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }, + {"$5" , DC_DEREF }}; + +static const disasm_t disasm_cop0_c0[64] DATASEG = +{{"invalid" , DC_BARE }, + {"tlbr" , DC_BARE }, + {"tlbwi" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"tlbwr" , DC_BARE }, + {"invalid" , DC_BARE }, + {"tlbp" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"eret" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"deret" , DC_BARE }, + {"wait" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_cop1[32] DATASEG = +{{"mfc1" , DC_RT_FS }, + {"dmfc1" , DC_RT_FS }, + {"cfc1" , DC_RT_FS }, + {"invalid" , DC_BARE }, + {"mtc1" , DC_RT_FS }, + {"dmtc1" , DC_RT_FS }, + {"ctc1" , DC_RT_FS }, + {"invalid" , DC_BARE }, + {"$17" , DC_DEREF }, + {"$36" , DC_DEREF }, + {"$37" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$7" , DC_DEREF }, + {"$9" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$11" , DC_DEREF }, + {"$12" , DC_DEREF }, + {"$13" , DC_DEREF }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_cop1_bc1[4] DATASEG = +{{"bc1f" , DC_CC_OFS }, + {"bc1t" , DC_CC_OFS }, + {"bc1fl" , DC_CC_OFS }, + {"bc1tl" , DC_CC_OFS }, +}; + +static const disasm_t disasm_cop1_bc1any2[2] DATASEG = +{{"bc1any2f" , DC_CC_OFS }, + {"bc1any2t" , DC_CC_OFS }, +}; + +static const disasm_t disasm_cop1_bc1any4[2] DATASEG = +{{"bc1any4f" , DC_CC_OFS }, + {"bc1any4t" , DC_CC_OFS }, +}; + +static const disasm_t disasm_cop1_s[64] DATASEG = +{{"add.s" , DC_FD_FS_FT }, + {"sub.s" , DC_FD_FS_FT }, + {"mul.s" , DC_FD_FS_FT }, + {"div.s" , DC_FD_FS_FT }, + {"sqrt.s" , DC_FD_FS }, + {"abs.s" , DC_FD_FS }, + {"mov.s" , DC_FD_FS }, + {"neg.s" , DC_FD_FS }, + {"round.l.s" , DC_FD_FS }, + {"trunc.l.s" , DC_FD_FS }, + {"ceil.l.s" , DC_FD_FS }, + {"floor.l.s" , DC_FD_FS }, + {"round.w.s" , DC_FD_FS }, + {"trunc.w.s" , DC_FD_FS }, + {"ceil.w.s" , DC_FD_FS }, + {"floor.w.s" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"$8" , DC_DEREF }, + {"movz.s" , DC_FD_FS_RT }, + {"movn.s" , DC_FD_FS_RT }, + {"invalid" , DC_BARE }, + {"recip.s" , DC_FD_FS }, + {"rsqrt.s" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"recip2.s" , DC_FD_FS_FT }, + {"recip1.s" , DC_FD_FS }, + {"rsqrt1.s" , DC_FD_FS }, + {"rsqrt2.s" , DC_FD_FS_FT }, + {"invalid" , DC_BARE }, + {"cvt.d.s" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.w.s" , DC_FD_FS }, + {"cvt.l.s" , DC_FD_FS }, + {"cvt.ps.s" , DC_FD_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$38" , DC_DEREF }, + {"$39" , DC_DEREF }, + {"$40" , DC_DEREF }, + {"$41" , DC_DEREF }, + {"$42" , DC_DEREF }, + {"$43" , DC_DEREF }, + {"$44" , DC_DEREF }, + {"$45" , DC_DEREF }, + {"$46" , DC_DEREF }, + {"$47" , DC_DEREF }, + {"$48" , DC_DEREF }, + {"$49" , DC_DEREF }, + {"$50" , DC_DEREF }, + {"$51" , DC_DEREF }, + {"$52" , DC_DEREF }, + {"$53" , DC_DEREF }}; + +static const disasm_t disasm_cop1_s_mvcf[2] DATASEG = +{{"movf.s" , DC_FD_FS_CC }, + {"movt.s" , DC_FD_FS_CC }}; + +static const disasm_t disasm_cop1_d[64] DATASEG = +{{"add.d" , DC_FD_FS_FT }, + {"sub.d" , DC_FD_FS_FT }, + {"mul.d" , DC_FD_FS_FT }, + {"div.d" , DC_FD_FS_FT }, + {"sqrt.d" , DC_FD_FS }, + {"abs.d" , DC_FD_FS }, + {"mov.d" , DC_FD_FS }, + {"neg.d" , DC_FD_FS }, + {"round.l.d" , DC_FD_FS }, + {"trunc.l.d" , DC_FD_FS }, + {"ceil.l.d" , DC_FD_FS }, + {"floor.l.d" , DC_FD_FS }, + {"round.w.d" , DC_FD_FS }, + {"trunc.w.d" , DC_FD_FS }, + {"ceil.w.d" , DC_FD_FS }, + {"floor.w.d" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"$10" , DC_DEREF }, + {"movz.d" , DC_FD_FS_RT }, + {"movn.d" , DC_FD_FS_RT }, + {"invalid" , DC_BARE }, + {"recip.d" , DC_FD_FS }, + {"rsqrt.d" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"recip2.d" , DC_FD_FS_FT }, + {"recip1.d" , DC_FD_FS }, + {"rsqrt1.d" , DC_FD_FS }, + {"rsqrt2.d" , DC_FD_FS_FT }, + {"cvt.s.d" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.w.d" , DC_FD_FS }, + {"cvt.l.d" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$54" , DC_DEREF }, + {"$55" , DC_DEREF }, + {"$56" , DC_DEREF }, + {"$57" , DC_DEREF }, + {"$58" , DC_DEREF }, + {"$59" , DC_DEREF }, + {"$60" , DC_DEREF }, + {"$61" , DC_DEREF }, + {"$62" , DC_DEREF }, + {"$63" , DC_DEREF }, + {"$64" , DC_DEREF }, + {"$65" , DC_DEREF }, + {"$66" , DC_DEREF }, + {"$67" , DC_DEREF }, + {"$68" , DC_DEREF }, + {"$69" , DC_DEREF }}; + +static const disasm_t disasm_cop1_d_mvcf[2] DATASEG = +{{"movf.d" , DC_FD_FS_CC }, + {"movt.d" , DC_FD_FS_CC }}; + +static const disasm_t disasm_cop1_w[64] DATASEG = +{{"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.s.w" , DC_FD_FS }, + {"cvt.d.w" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.ps.pw" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_cop1_l[64] DATASEG = +{{"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.s.l" , DC_FD_FS }, + {"cvt.d.l" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_cop1_ps[64] DATASEG = +{{"add.ps" , DC_FD_FS_FT }, + {"sub.ps" , DC_FD_FS_FT }, + {"mul.ps" , DC_FD_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"abs.ps" , DC_FD_FS }, + {"mov.ps" , DC_FD_FS }, + {"neg.ps" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"$14" , DC_DEREF }, + {"movz.ps" , DC_FD_FS_RT }, + {"movn.ps" , DC_FD_FS_RT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"addr.ps" , DC_FD_FS_FT }, + {"invalid" , DC_BARE }, + {"mulr.ps" , DC_FD_FS_FT }, + {"invalid" , DC_BARE }, + {"recip2.ps" , DC_FD_FS_FT }, + {"recip1.ps" , DC_FD_FS }, + {"rsqrt1.ps" , DC_FD_FS }, + {"rsqrt2.ps" , DC_FD_FS_FT }, + {"cvt.s.pu" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.pw.ps" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"cvt.s.pl" , DC_FD_FS }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"pll.ps" , DC_FD_FS_FT }, + {"plu.ps" , DC_FD_FS_FT }, + {"pul.ps" , DC_FD_FS_FT }, + {"puu.ps" , DC_FD_FS_FT }, + {"$70" , DC_DEREF }, + {"$71" , DC_DEREF }, + {"$72" , DC_DEREF }, + {"$73" , DC_DEREF }, + {"$74" , DC_DEREF }, + {"$75" , DC_DEREF }, + {"$76" , DC_DEREF }, + {"$77" , DC_DEREF }, + {"$78" , DC_DEREF }, + {"$79" , DC_DEREF }, + {"$80" , DC_DEREF }, + {"$81" , DC_DEREF }, + {"$82" , DC_DEREF }, + {"$83" , DC_DEREF }, + {"$84" , DC_DEREF }, + {"$85" , DC_DEREF }}; + +static const disasm_t disasm_cop1_c_f_s[2] DATASEG = +{{"c.f.s" , DC_CC_FS_FT }, + {"cabs.f.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_un_s[2] DATASEG = +{{"c.un.s" , DC_CC_FS_FT }, + {"cabs.un.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_eq_s[2] DATASEG = +{{"c.eq.s" , DC_CC_FS_FT }, + {"cabs.eq.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ueq_s[2] DATASEG = +{{"c.ueq.s" , DC_CC_FS_FT }, + {"cabs.ueq.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_olt_s[2] DATASEG = +{{"c.olt.s" , DC_CC_FS_FT }, + {"cabs.olt.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ult_s[2] DATASEG = +{{"c.ult.s" , DC_CC_FS_FT }, + {"cabs.ult.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ole_s[2] DATASEG = +{{"c.ole.s" , DC_CC_FS_FT }, + {"cabs.ole.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ule_s[2] DATASEG = +{{"c.ule.s" , DC_CC_FS_FT }, + {"cabs.ule.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_sf_s[2] DATASEG = +{{"c.sf.s" , DC_CC_FS_FT }, + {"cabs.sf.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngle_s[2] DATASEG = +{{"c.ngle.s" , DC_CC_FS_FT }, + {"cabs.ngle.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_seq_s[2] DATASEG = +{{"c.seq.s" , DC_CC_FS_FT }, + {"cabs.seq.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngl_s[2] DATASEG = +{{"c.ngl.s" , DC_CC_FS_FT }, + {"cabs.ngl.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_lt_s[2] DATASEG = +{{"c.lt.s" , DC_CC_FS_FT }, + {"cabs.lt.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_nge_s[2] DATASEG = +{{"c.nge.s" , DC_CC_FS_FT }, + {"cabs.nge.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_le_s[2] DATASEG = +{{"c.le.s" , DC_CC_FS_FT }, + {"cabs.le.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngt_s[2] DATASEG = +{{"c.ngt.s" , DC_CC_FS_FT }, + {"cabs.ngt.s" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_f_d[2] DATASEG = +{{"c.f.d" , DC_CC_FS_FT }, + {"cabs.f.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_un_d[2] DATASEG = +{{"c.un.d" , DC_CC_FS_FT }, + {"cabs.un.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_eq_d[2] DATASEG = +{{"c.eq.d" , DC_CC_FS_FT }, + {"cabs.eq.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ueq_d[2] DATASEG = +{{"c.ueq.d" , DC_CC_FS_FT }, + {"cabs.ueq.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_olt_d[2] DATASEG = +{{"c.olt.d" , DC_CC_FS_FT }, + {"cabs.olt.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ult_d[2] DATASEG = +{{"c.ult.d" , DC_CC_FS_FT }, + {"cabs.ult.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ole_d[2] DATASEG = +{{"c.ole.d" , DC_CC_FS_FT }, + {"cabs.ole.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ule_d[2] DATASEG = +{{"c.ule.d" , DC_CC_FS_FT }, + {"cabs.ule.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_sf_d[2] DATASEG = +{{"c.sf.d" , DC_CC_FS_FT }, + {"cabs.sf.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngle_d[2] DATASEG = +{{"c.ngle.d" , DC_CC_FS_FT }, + {"cabs.ngle.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_seq_d[2] DATASEG = +{{"c.seq.d" , DC_CC_FS_FT }, + {"cabs.seq.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngl_d[2] DATASEG = +{{"c.ngl.d" , DC_CC_FS_FT }, + {"cabs.ngl.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_lt_d[2] DATASEG = +{{"c.lt.d" , DC_CC_FS_FT }, + {"cabs.lt.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_nge_d[2] DATASEG = +{{"c.nge.d" , DC_CC_FS_FT }, + {"cabs.nge.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_le_d[2] DATASEG = +{{"c.le.d" , DC_CC_FS_FT }, + {"cabs.le.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngt_d[2] DATASEG = +{{"c.ngt.d" , DC_CC_FS_FT }, + {"cabs.ngt.d" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_f_ps[2] DATASEG = +{{"c.f.ps" , DC_CC_FS_FT }, + {"cabs.f.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_un_ps[2] DATASEG = +{{"c.un.ps" , DC_CC_FS_FT }, + {"cabs.un.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_eq_ps[2] DATASEG = +{{"c.eq.ps" , DC_CC_FS_FT }, + {"cabs.eq.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ueq_ps[2] DATASEG = +{{"c.ueq.ps" , DC_CC_FS_FT }, + {"cabs.ueq.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_olt_ps[2] DATASEG = +{{"c.olt.ps" , DC_CC_FS_FT }, + {"cabs.olt.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ult_ps[2] DATASEG = +{{"c.ult.ps" , DC_CC_FS_FT }, + {"cabs.ult.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ole_ps[2] DATASEG = +{{"c.ole.ps" , DC_CC_FS_FT }, + {"cabs.ole.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ule_ps[2] DATASEG = +{{"c.ule.ps" , DC_CC_FS_FT }, + {"cabs.ule.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_sf_ps[2] DATASEG = +{{"c.sf.ps" , DC_CC_FS_FT }, + {"cabs.sf.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngle_ps[2] DATASEG = +{{"c.ngle.ps" , DC_CC_FS_FT }, + {"cabs.ngle.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_seq_ps[2] DATASEG = +{{"c.seq.ps" , DC_CC_FS_FT }, + {"cabs.seq.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngl_ps[2] DATASEG = +{{"c.ngl.ps" , DC_CC_FS_FT }, + {"cabs.ngl.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_lt_ps[2] DATASEG = +{{"c.lt.ps" , DC_CC_FS_FT }, + {"cabs.lt.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_nge_ps[2] DATASEG = +{{"c.nge.ps" , DC_CC_FS_FT }, + {"cabs.nge.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_le_ps[2] DATASEG = +{{"c.le.ps" , DC_CC_FS_FT }, + {"cabs.le.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_c_ngt_ps[2] DATASEG = +{{"c.ngt.ps" , DC_CC_FS_FT }, + {"cabs.ngt.ps" , DC_CC_FS_FT }}; + +static const disasm_t disasm_cop1_ps_mvcf[2] DATASEG = +{{"movf.ps" , DC_FD_FS_CC }, + {"movt.ps" , DC_FD_FS_CC }}; + +static const disasm_t disasm_cop1x[64] DATASEG = +{{"lwxc1" , DC_FD_IDX_BASE }, + {"ldxc1" , DC_FD_IDX_BASE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"luxc1" , DC_FD_IDX_BASE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"swxc1" , DC_FS_IDX_BASE }, + {"sdxc1" , DC_FS_IDX_BASE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"suxc1" , DC_FS_IDX_BASE }, + {"invalid" , DC_BARE }, + {"prefx" , DC_PREF_IDX }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"alnv.ps" , DC_FD_FS_FT_RS }, + {"invalid" , DC_BARE }, + {"madd.s" , DC_FD_FR_FS_FT }, + {"madd.d" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"madd.ps" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"msub.s" , DC_FD_FR_FS_FT }, + {"msub.d" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"msub.ps" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"nmadd.s" , DC_FD_FR_FS_FT }, + {"nmadd.d" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"nmadd.ps" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"nmsub.s" , DC_FD_FR_FS_FT }, + {"nmsub.d" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"invalid" , DC_BARE }, + {"nmsub.ps" , DC_FD_FR_FS_FT }, + {"invalid" , DC_BARE }}; + +static const disasm_t disasm_mdmx[8] DATASEG = +{{ "$20" , DC_DEREF }, + { "$19" , DC_DEREF }, + { "$20" , DC_DEREF }, + { "$33" , DC_DEREF }, + { "$20" , DC_DEREF }, + { "$19" , DC_DEREF }, + { "$20" , DC_DEREF }, + { "$33" , DC_DEREF }, +}; + +static const disasm_t disasm_mdmx_qh[64] DATASEG = +{{ "msgn.qh" , DC_VD_VS_VT_VEC}, + { "c.eq.qh" , DC_VS_VT_VEC }, + { "pickf.qh" , DC_VD_VS_VT_VEC}, + { "pickt.qh" , DC_VD_VS_VT_VEC}, + { "c.lt.qh" , DC_VS_VT_VEC }, + { "c.le.qh" , DC_VS_VT_VEC }, + { "min.qh" , DC_VD_VS_VT_VEC}, + { "max.qh" , DC_VD_VS_VT_VEC}, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "sub.qh" , DC_VD_VS_VT_VEC}, + { "add.qh" , DC_VD_VS_VT_VEC}, + { "and.qh" , DC_VD_VS_VT_VEC}, + { "xor.qh" , DC_VD_VS_VT_VEC}, + { "or.qh" , DC_VD_VS_VT_VEC}, + { "nor.qh" , DC_VD_VS_VT_VEC}, + + { "sll.qh" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "srl.qh" , DC_VD_VS_VT_VEC}, + { "sra.qh" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "alni.ob" , DC_VD_VS_VT_IMM}, + { "alnv.ob" , DC_VD_VS_VT_RS }, + { "alni.qh" , DC_VD_VS_VT_IMM}, + { "alnv.qh" , DC_VD_VS_VT_RS }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$34" , DC_DEREF }, + + { "rzu.qh" , DC_VD_VT }, + { "rnau.qh" , DC_VD_VT }, + { "rneu.qh" , DC_VD_VT }, + { "invalid" , DC_BARE }, + { "rzs.qh" , DC_VD_VT }, + { "rnas.qh" , DC_VD_VT }, + { "rnes.qh" , DC_VD_VT }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "mul.qh" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "$21" , DC_DEREF }, + { "$22" , DC_DEREF }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$23" , DC_DEREF }, + { "$24" , DC_DEREF }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$25" , DC_DEREF }, + { "$26" , DC_DEREF }, +}; + +static const disasm_t disasm_mdmx_ob[64] DATASEG = +{{ "invalid" , DC_BARE }, + { "c.eq.ob" , DC_VS_VT_VEC }, + { "pickf.ob" , DC_VD_VS_VT_VEC}, + { "pickt.ob" , DC_VD_VS_VT_VEC}, + { "c.lt.ob" , DC_VS_VT_VEC }, + { "c.le.ob" , DC_VS_VT_VEC }, + { "min.ob" , DC_VD_VS_VT_VEC}, + { "max.ob" , DC_VD_VS_VT_VEC}, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "sub.ob" , DC_VD_VS_VT_VEC}, + { "add.ob" , DC_VD_VS_VT_VEC}, + { "and.ob" , DC_VD_VS_VT_VEC}, + { "xor.ob" , DC_VD_VS_VT_VEC}, + { "or.ob" , DC_VD_VS_VT_VEC}, + { "nor.ob" , DC_VD_VS_VT_VEC}, + + { "sll.ob" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "srl.ob" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "alni.ob" , DC_VD_VS_VT_IMM}, + { "alnv.ob" , DC_VD_VS_VT_RS }, + { "alni.qh" , DC_VD_VS_VT_IMM}, + { "alnv.qh" , DC_VD_VS_VT_RS }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$35" , DC_DEREF }, + + { "rzu.ob" , DC_VD_VT }, + { "rnau.ob" , DC_VD_VT }, + { "rneu.ob" , DC_VD_VT }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "mul.ob" , DC_VD_VS_VT_VEC}, + { "invalid" , DC_BARE }, + { "$27" , DC_DEREF }, + { "$28" , DC_DEREF }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$29" , DC_DEREF }, + { "$30" , DC_DEREF }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "$31" , DC_DEREF }, + { "$32" , DC_DEREF }, +}; + +static const disasm_t disasm_mdmx_alni[64] DATASEG = +{{ "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "alni.ob" , DC_VD_VS_VT_IMM}, + { "alnv.ob" , DC_VD_VS_VT_RS }, + { "alni.qh" , DC_VD_VS_VT_IMM}, + { "alnv.qh" , DC_VD_VS_VT_RS }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_muls_qh[2] DATASEG = +{{ "muls.qh" , DC_VS_VT_VEC }, + { "mulsl.qh" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_mul_qh[2] DATASEG = +{{ "mula.qh" , DC_VS_VT_VEC }, + { "mull.qh" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_sub_qh[2] DATASEG = +{{ "suba.qh" , DC_VS_VT_VEC }, + { "subl.qh" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_add_qh[2] DATASEG = +{{ "adda.qh" , DC_VS_VT_VEC }, + { "addl.qh" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_wac_qh[4] DATASEG = +{{ "wacl.qh" , DC_VS_VT }, + { "invalid" , DC_BARE }, + { "wach.qh" , DC_VS }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_rac_qh[4] DATASEG = +{{ "racl.qh" , DC_VD }, + { "racm.qh" , DC_VD }, + { "rach.qh" , DC_VD }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_muls_ob[2] DATASEG = +{{ "muls.ob" , DC_VS_VT_VEC }, + { "mulsl.ob" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_mul_ob[2] DATASEG = +{{ "mula.ob" , DC_VS_VT_VEC }, + { "mull.ob" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_sub_ob[2] DATASEG = +{{ "suba.ob" , DC_VS_VT_VEC }, + { "subl.ob" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_add_ob[2] DATASEG = +{{ "adda.ob" , DC_VS_VT_VEC }, + { "addl.ob" , DC_VS_VT_VEC }, +}; + +static const disasm_t disasm_mdmx_wac_ob[4] DATASEG = +{{ "wacl.ob" , DC_VS_VT }, + { "invalid" , DC_BARE }, + { "wach.ob" , DC_VS }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_rac_ob[4] DATASEG = +{{ "racl.ob" , DC_VD }, + { "racm.ob" , DC_VD }, + { "rach.ob" , DC_VD }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_shfl_ob[16] DATASEG = +{{ "shfl.upsl.ob" , DC_VD_VS_VT }, + { "shfl.pach.ob" , DC_VD_VS_VT }, + { "shfl.mixh.ob" , DC_VD_VS_VT }, + { "shfl.mixl.ob" , DC_VD_VS_VT }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, +}; + +static const disasm_t disasm_mdmx_shfl_qh[8] DATASEG = +{{ "shfl.bfla.qh" , DC_VD_VS_VT }, + { "shfl.pach.qh" , DC_VD_VS_VT }, + { "shfl.mixh.qh" , DC_VD_VS_VT }, + { "shfl.mixl.qh" , DC_VD_VS_VT }, + { "shfl.repa.qh" , DC_VD_VS_VT }, + { "shfl.repb.qh" , DC_VD_VS_VT }, + { "invalid" , DC_BARE }, + { "invalid" , DC_BARE }, +}; + + + +const disasm_deref_t disasm_deref[] = +/* Disasm array shft msk */ +{{ disasm_normal , 26, 0x3f }, /* 0 */ + { disasm_special , 0, 0x3f }, /* 1 */ + { disasm_regimm , 16, 0x1f }, /* 2 */ + { disasm_spec2 , 0, 0x3f }, /* 3 */ + { disasm_cop0 , 21, 0x1f }, /* 4 */ + { disasm_cop0_c0 , 0, 0x3f }, /* 5 */ + { disasm_cop1 , 21, 0x1f }, /* 6 */ + { disasm_cop1_s , 0, 0x3f }, /* 7 */ + { disasm_cop1_s_mvcf , 16, 0x1 }, /* 8 */ + { disasm_cop1_d , 0, 0x3f }, /* 9 */ + { disasm_cop1_d_mvcf , 16, 0x1 }, /* 10 */ + { disasm_cop1_w , 0, 0x3f }, /* 11 */ + { disasm_cop1_l , 0, 0x3f }, /* 12 */ + { disasm_cop1_ps , 0, 0x3f }, /* 13 */ + { disasm_cop1_ps_mvcf, 16, 0x1 }, /* 14 */ + { disasm_cop1x , 0, 0x3f }, /* 15 */ + { disasm_movci , 16, 0x1 }, /* 16 */ + { disasm_cop1_bc1 , 16, 0x3 }, /* 17 */ + { disasm_mdmx , 21, 0x7 }, /* 18 */ + { disasm_mdmx_qh , 0, 0x3f }, /* 19 */ + { disasm_mdmx_ob , 0, 0x3f }, /* 20 */ + { disasm_mdmx_muls_qh, 10, 0x1 }, /* 21 */ + { disasm_mdmx_mul_qh , 10, 0x1 }, /* 22 */ + { disasm_mdmx_sub_qh , 10, 0x1 }, /* 23 */ + { disasm_mdmx_add_qh , 10, 0x1 }, /* 24 */ + { disasm_mdmx_wac_qh , 24, 0x3 }, /* 25 */ + { disasm_mdmx_rac_qh , 24, 0x3 }, /* 26 */ + { disasm_mdmx_muls_ob, 10, 0x1 }, /* 27 */ + { disasm_mdmx_mul_ob , 10, 0x1 }, /* 28 */ + { disasm_mdmx_sub_ob , 10, 0x1 }, /* 29 */ + { disasm_mdmx_add_ob , 10, 0x1 }, /* 30 */ + { disasm_mdmx_wac_ob , 24, 0x3 }, /* 31 */ + { disasm_mdmx_rac_ob , 24, 0x3 }, /* 32 */ + { disasm_mdmx_alni , 0, 0x3f }, /* 33 */ + { disasm_mdmx_shfl_ob, 22, 0xf }, /* 34 */ + { disasm_mdmx_shfl_qh, 23, 0x7 }, /* 35 */ + { disasm_cop1_bc1any2, 16, 0x1 }, /* 36 */ + { disasm_cop1_bc1any4, 16, 0x1 }, /* 37 */ + { disasm_cop1_c_f_s , 6, 0x1 }, /* 38 */ + { disasm_cop1_c_un_s , 6, 0x1 }, /* 39 */ + { disasm_cop1_c_eq_s , 6, 0x1 }, /* 40 */ + { disasm_cop1_c_ueq_s, 6, 0x1 }, /* 41 */ + { disasm_cop1_c_olt_s, 6, 0x1 }, /* 42 */ + { disasm_cop1_c_ult_s, 6, 0x1 }, /* 43 */ + { disasm_cop1_c_ole_s, 6, 0x1 }, /* 44 */ + { disasm_cop1_c_ule_s, 6, 0x1 }, /* 45 */ + { disasm_cop1_c_sf_s , 6, 0x1 }, /* 46 */ + { disasm_cop1_c_ngle_s, 6, 0x1 }, /* 47 */ + { disasm_cop1_c_seq_s, 6, 0x1 }, /* 48 */ + { disasm_cop1_c_ngl_s, 6, 0x1 }, /* 49 */ + { disasm_cop1_c_lt_s , 6, 0x1 }, /* 50 */ + { disasm_cop1_c_nge_s, 6, 0x1 }, /* 51 */ + { disasm_cop1_c_le_s , 6, 0x1 }, /* 52 */ + { disasm_cop1_c_ngt_s, 6, 0x1 }, /* 53 */ + { disasm_cop1_c_f_d , 6, 0x1 }, /* 54 */ + { disasm_cop1_c_un_d , 6, 0x1 }, /* 55 */ + { disasm_cop1_c_eq_d , 6, 0x1 }, /* 56 */ + { disasm_cop1_c_ueq_d, 6, 0x1 }, /* 57 */ + { disasm_cop1_c_olt_d, 6, 0x1 }, /* 58 */ + { disasm_cop1_c_ult_d, 6, 0x1 }, /* 59 */ + { disasm_cop1_c_ole_d, 6, 0x1 }, /* 60 */ + { disasm_cop1_c_ule_d, 6, 0x1 }, /* 61 */ + { disasm_cop1_c_sf_d , 6, 0x1 }, /* 62 */ + { disasm_cop1_c_ngle_d, 6, 0x1 }, /* 63 */ + { disasm_cop1_c_seq_d, 6, 0x1 }, /* 64 */ + { disasm_cop1_c_ngl_d, 6, 0x1 }, /* 65 */ + { disasm_cop1_c_lt_d , 6, 0x1 }, /* 66 */ + { disasm_cop1_c_nge_d, 6, 0x1 }, /* 67 */ + { disasm_cop1_c_le_d , 6, 0x1 }, /* 68 */ + { disasm_cop1_c_ngt_d, 6, 0x1 }, /* 69 */ + { disasm_cop1_c_f_ps , 6, 0x1 }, /* 70 */ + { disasm_cop1_c_un_ps, 6, 0x1 }, /* 71 */ + { disasm_cop1_c_eq_ps, 6, 0x1 }, /* 72 */ + { disasm_cop1_c_ueq_ps, 6, 0x1 }, /* 73 */ + { disasm_cop1_c_olt_ps, 6, 0x1 }, /* 74 */ + { disasm_cop1_c_ult_ps, 6, 0x1 }, /* 75 */ + { disasm_cop1_c_ole_ps, 6, 0x1 }, /* 76 */ + { disasm_cop1_c_ule_ps, 6, 0x1 }, /* 77 */ + { disasm_cop1_c_sf_ps, 6, 0x1 }, /* 78 */ + { disasm_cop1_c_ngle_ps, 6, 0x1 }, /* 79 */ + { disasm_cop1_c_seq_ps, 6, 0x1 }, /* 80 */ + { disasm_cop1_c_ngl_ps, 6, 0x1 }, /* 81 */ + { disasm_cop1_c_lt_ps, 6, 0x1 }, /* 82 */ + { disasm_cop1_c_nge_ps, 6, 0x1 }, /* 83 */ + { disasm_cop1_c_le_ps, 6, 0x1 }, /* 84 */ + { disasm_cop1_c_ngt_ps, 6, 0x1 }, /* 85 */ +}; + +#define PREFHINT(x) (&pref_hints[(x)*9]) +static char *pref_hints = + "load \0" + "store \0" + "reserved\0" + "reserved\0" + + "ld_strm \0" + "st_strm \0" + "ld_retn \0" + "st_retn \0" + + "reserved\0" + "reserved\0" + "reserved\0" + "reserved\0" + + "reserved\0" + "reserved\0" + "reserved\0" + "reserved\0" + + "reserved\0" + "reserved\0" + "reserved\0" + "reserved\0" + + "reserved\0" + "reserved\0" + "reserved\0" + "reserved\0" + + "reserved\0" + "wb_inval\0" + "reserved\0" + "reserved\0" + + "reserved\0" + "reserved\0" + "reserved\0" + "reserved\0"; + + +static int snprintf(char *buf,int len,const char *templat,...) +{ + va_list marker; + int count; + + va_start(marker,templat); + count = xvsprintf(buf,templat,marker); + va_end(marker); + + return count; +} + +static const disasm_t *get_disasm_field(uint32_t inst) +{ + const disasm_deref_t *tmp = &disasm_deref[0]; + const disasm_t *rec; + do { + rec = &(tmp->ptr[(inst>>tmp->shift) & tmp->mask]); + tmp = &disasm_deref[atoi(&(rec->name[1]))]; + } while (rec->type == DC_DEREF); + return rec; +} + +char *disasm_inst_name(uint32_t inst) +{ + return (char *)(get_disasm_field(inst)->name); +} + +void disasm_inst(char *buf, int buf_size, uint32_t inst, uint64_t pc) +{ + const disasm_t *tmp; + char instname[32]; + int commentmode = 0; + char *x; + + tmp = get_disasm_field(inst); + + strcpy(instname,(char *) tmp->name); + + if ((x = strchr(instname,'@'))) { + *x++ = 0; + commentmode = atoi(x); + } + + switch (tmp->type) { + case DC_RD_RS_RT: + snprintf(buf, buf_size, "%-8s %s,%s,%s", + instname, + REGNAME((inst>>11) & 0x1f), + REGNAME((inst>>21) & 0x1f), + REGNAME((inst>>16) & 0x1f)); + break; + case DC_RD_RT_RS: + snprintf(buf, buf_size, "%-8s %s,%s,%s", + instname, + REGNAME((inst>>11) & 0x1f), + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_RT_RS_SIMM: + snprintf(buf, buf_size, "%-8s %s,%s,#%" PF_32 "d", + instname, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f), + SEXT_32(15, inst & 0xffff)); + break; + case DC_RT_RS_XIMM: + snprintf(buf, buf_size, "%-8s %s,%s,#0x%" PF_32 "x", + instname, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f), + inst & 0xffff); + break; + case DC_RS_RT_OFS: + snprintf(buf, buf_size, "%-8s %s,%s,0x%" PF_64 "x", + instname, + REGNAME((inst>>21) & 0x1f), + REGNAME((inst>>16) & 0x1f), + pc + 4 + (SEXT_64(15, inst & 0xffff)<<2)); + break; + case DC_RS_OFS: + snprintf(buf, buf_size, "%-8s %s,0x%" PF_64 "x", + instname, + REGNAME((inst>>21) & 0x1f), + pc + 4 + (SEXT_64(16, inst & 0xffff)<<2)); + break; + case DC_RD_RT_SA: + snprintf(buf, buf_size, "%-8s %s,%s,#%d", + instname, + REGNAME((inst>>11) & 0x1f), + REGNAME((inst>>16) & 0x1f), + (inst>>6) & 0x1f); + break; + case DC_RT_UIMM: + snprintf(buf, buf_size, "%-8s %s,#%d", + instname, + REGNAME((inst>>16) & 0x1f), + inst & 0xffff); + break; + case DC_RD: + snprintf(buf, buf_size, "%-8s %s", + instname, + REGNAME((inst>>11) & 0x1f)); + break; + case DC_J: + snprintf(buf, buf_size, "%-8s 0x%" PF_64 "x", + instname, + (pc & UINT64_T(0xfffffffff0000000)) | ((inst & 0x3ffffff)<<2)); + break; + case DC_RD_RS: + snprintf(buf, buf_size, "%-8s %s,%s", + instname, + REGNAME((inst>>11) & 0x1f), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_RS_RT: + snprintf(buf, buf_size, "%-8s %s,%s", + instname, + REGNAME((inst>>21) & 0x1f), + REGNAME((inst>>16) & 0x1f)); + break; + case DC_RT_RS: + snprintf(buf, buf_size, "%-8s %s,%s", + instname, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_RT_RD_SEL: + snprintf(buf, buf_size, "%-8s %s,%s,#%d", + instname, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>11) & 0x1f), + inst & 0x3); + break; + case DC_RT_CR_SEL: + snprintf(buf, buf_size, "%-8s %s,%d,#%d", + instname, + REGNAME((inst>>16) & 0x1f), + (inst>>11) & 0x1f, + inst & 0x3); + break; + case DC_RS: + snprintf(buf, buf_size, "%-8s %s", + instname, + REGNAME((inst>>21) & 0x1f)); + break; + case DC_RS_SIMM: + snprintf(buf, buf_size, "%-8s %s,#%" PF_32 "d", + instname, + REGNAME((inst>>21) & 0x1f), + SEXT_32(15, inst & 0xffff)); + break; + case DC_RT_OFS_BASE: + snprintf(buf, buf_size, "%-8s %s,#%" PF_32 "d(%s)", + instname, + REGNAME((inst>>16) & 0x1f), + SEXT_32(15, inst), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_FT_OFS_BASE: + snprintf(buf, buf_size, "%-8s f%d,#%" PF_32 "d(%s)", + instname, + (inst>>16) & 0x1f, + SEXT_32(15, inst), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_FD_IDX_BASE: + snprintf(buf, buf_size, "%-8s f%d,%s(%s)", + instname, + (inst>>6) & 0x1f, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_FS_IDX_BASE: + snprintf(buf, buf_size, "%-8s f%d,%s(%s)", + instname, + (inst>>11) & 0x1f, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f)); + break; + case DC_FD_FS_FT: + snprintf(buf, buf_size, "%-8s f%d,f%d,f%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_FD_FS_RT: + snprintf(buf, buf_size, "%-8s f%d,f%d,%s", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + REGNAME((inst>>16) & 0x1f)); + break; + case DC_FD_FS: + snprintf(buf, buf_size, "%-8s f%d,f%d", + instname, + (inst>>6)&0x1f, + (inst>>11)&0x1f); + break; + case DC_PREF_OFS: + snprintf(buf, buf_size, "%-8s #%" PF_32 "d(%s) /* %s */", + instname, + SEXT_32(15, inst & 0xffff), + REGNAME((inst>>21) & 0x1f), + PREFHINT((inst>>16) & 0x1f)); + break; + case DC_PREF_IDX: + snprintf(buf, buf_size, "%-8s %s(%s) /* %s */", + instname, + REGNAME((inst>>16) & 0x1f), + REGNAME((inst>>21) & 0x1f), + PREFHINT((inst>>16) & 0x1f)); + break; + case DC_CC_OFS: + snprintf(buf, buf_size, "%-8s %d,0x%" PF_64 "x", + instname, + (inst>>18) & 0x7, + pc + 4 + (SEXT_64(15, inst & 0xffff)<<2)); + break; + case DC_RD_RS_CC: + snprintf(buf, buf_size, "%-8s %s,%s,%d", + instname, + REGNAME((inst>>11) & 0x1f), + REGNAME((inst>>21) & 0x1f), + (inst>>18) & 0x7); + break; + case DC_FD_FS_CC: + snprintf(buf, buf_size, "%-8s f%d,f%d,%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>18) & 0x7); + break; + case DC_FD_FR_FS_FT: + snprintf(buf, buf_size, "%-8s f%d,f%d,f%d,f%d", + instname, + (inst>>6) & 0x1f, + (inst>>21) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_FD_FS_FT_RS: + snprintf(buf, buf_size, "%-8s f%d,f%d,f%d,%s", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + REGNAME((inst>>21) & 0x1f)); + break; + case DC_CC_FS_FT: + snprintf(buf, buf_size, "%-8s %d,f%d,f%d", + instname, + (inst>>8) & 0x7, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_BARE: + snprintf(buf, buf_size, "%-8s", instname); + break; + case DC_RT_FS: + snprintf(buf, buf_size, "%-8s %s,f%d", + instname, + REGNAME((inst>>16) & 0x1f), + (inst>>11) & 0x1f); + break; + case DC_VS: + snprintf(buf, buf_size, "%-8s $v%d", + instname, + (inst>>11) & 0x1f); + break; + case DC_VD: + snprintf(buf, buf_size, "%-8s $v%d", + instname, + (inst>>6) & 0x1f); + break; + case DC_VD_VT: + snprintf(buf, buf_size, "%-8s $v%d,$v%d", + instname, + (inst>>6) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_VD_VS_VT_IMM: + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d,#%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + (inst>>21) & 0x7); + break; + case DC_VD_VS_VT_RS: + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d,%s", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + REGNAME((inst>>21) & 0x1f)); + break; + case DC_VD_VS_VT: + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_VS_VT: + snprintf(buf, buf_size, "%-8s $v%d,$v%d", + instname, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case DC_VS_VT_VEC: + switch((inst>>24) & 0x3) { + case 0: + case 1: + /* element select */ + if ((inst>>21) & 1) { + /* QH */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d[%d]", + instname, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + (inst>>23) & 0x3); + } else { + /* OB */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d[%d]", + instname, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + (inst>>22) & 0x7); + + } + break; + case 2: + /* Vector select */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d", + instname, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case 3: + /* immediate select */ + snprintf(buf, buf_size, "%-8s $v%d,$#%d", + instname, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + } + break; + + case DC_VD_VS_VT_VEC: + switch((inst>>24) & 0x3) { + case 0: + case 1: + /* element select */ + if ((inst>>21) & 1) { + /* QH */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d[%d]", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + (inst>>23) & 0x3); + } else { + /* OB */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d[%d]", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f, + (inst>>22) & 0x7); + + } + break; + case 2: + /* Vector select */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + case 3: + /* immediate select */ + snprintf(buf, buf_size, "%-8s $v%d,$v%d,$#%d", + instname, + (inst>>6) & 0x1f, + (inst>>11) & 0x1f, + (inst>>16) & 0x1f); + break; + } + break; + + case DC_SYSCALL: + snprintf(buf, buf_size, "%-8s #%d", + instname, + (inst>>6) & 0xfffff); + break; + case DC_BREAK: + snprintf(buf, buf_size, "%-8s %d", instname, (inst>>6)&0xfffff); + break; + case DC_OOPS: + snprintf(buf, buf_size, "%s OOPS! FIXME!", instname); + break; + default: + /* Hit something we don't know about...Shouldn't happen. */ + break; + } + + /* + * Handle comment field + */ + + + switch (commentmode) { + case 1: /* CP0 ops */ + if ((inst & 3) == 0) { /* select 0 */ + snprintf(buf + strlen(buf),buf_size-strlen(buf)," /* %s */", + CP0REGNAME((inst >> 11) & 0x1f)); + } + break; + default: + break; + } + + buf[buf_size-1] = 0; + +} diff --git a/cfe/cfe/arch/mips/common/src/exception.S b/cfe/cfe/arch/mips/common/src/exception.S new file mode 100644 index 0000000..8036b35 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/exception.S @@ -0,0 +1,546 @@ +/* ********************************************************************* + * SB1250 Board Support Package + * + * Exception Handler File: exception.S + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "sbmips.h" +#include "exception.h" +#include "mipsmacros.h" +#include "cpu_config.h" /* for definition of HAZARD and ERET */ +#include "bsp_config.h" + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#ifdef _MIPSREGS32_ +#define LREG lw +#define SREG sw +#define SRL srl +#define SLL sll +#else +#define LREG ld +#define SREG sd +#define SRL dsrl +#define SLL dsll +#endif + + +/* ********************************************************************* + * Data + ********************************************************************* */ + + .sdata + + .globl _exc_vectab +_exc_vectab: _LONG_ 0 # XTYPE_RESET + _LONG_ 0 # XTYPE_TLBFILL (not used) + _LONG_ 0 # XTYPE_XTLBFILL + _LONG_ 0 # XTYPE_CACHEERR (not used) + _LONG_ 0 # XTYPE_EXCEPTION + _LONG_ 0 # XTYPE_INTERRUPT + _LONG_ 0 # XTYPE_EJTAG + +/* ********************************************************************* + * Common Data + ********************************************************************* */ + + .bss + + +/* ********************************************************************* + * Code + ********************************************************************* */ + + .text + +#define R_EXC_CERR_TEMPLATE _TBLIDX(0) +#define R_EXC_CERR_TEMPLATE_END _TBLIDX(1) + + .globl _exc_cerr_htable +_exc_cerr_htable: + _LONG_ _exc_cerr_template + _LONG_ _exc_cerr_template_end + + +/* ********************************************************************* + * _exc_cerr_template + * + * This is a template routine for our cache error handler. + * We save a couple of registers in our magic save area, then + * dispatch to code elsewhere in CFE. + * + * This code is copied right to the vector address, so it has + * to be kept tiny! + * + * Input parameters: + * nothing - running uncached, all registers trashed + * + * Return value: + * might return, might not + ********************************************************************* */ + +LEAF(_exc_cerr_template) + + /* + * Magic! When the cache error handler is running, + * we are in a very special state, running uncached + * and with translations turned off. We can use offsets + * from r0(zero) to store registers we need to use + * during the error handler. + */ + + .set push ; .set noreorder + + SR k0,CFE_LOCORE_GLOBAL_K0TMP(zero) + SR k1,CFE_LOCORE_GLOBAL_K1TMP(zero) + SR ra,CFE_LOCORE_GLOBAL_RATMP(zero) + SR gp,CFE_LOCORE_GLOBAL_GPTMP(zero) + + LR k0,CFE_LOCORE_GLOBAL_CERRH(zero) + jal k0 + nop + + LR k0,CFE_LOCORE_GLOBAL_K0TMP(zero) + LR k1,CFE_LOCORE_GLOBAL_K1TMP(zero) + LR ra,CFE_LOCORE_GLOBAL_RATMP(zero) + LR gp,CFE_LOCORE_GLOBAL_GPTMP(zero) + ERET + + .set pop + + /* + * Note: make sure this routine does not exceed 128 bytes + */ + +_exc_cerr_template_end: + +END(_exc_cerr_template) + +/* ********************************************************************* + * _exc_setup_locore(cerrh) + * + * Set global data into the low-memory region. We do this in + * assembly language so it's easier to deal with the 32-bit/64-bit + * issues that arise in the "C" code. + * + * Input parameters: + * a0 - cache error handler + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_exc_setup_locore) + + move t4,ra + + /* + * Save GP for easy re-use, using uncached writes. + */ + + li t0,PHYS_TO_K1(CFE_LOCORE_GLOBAL_GP) + SR gp,0(t0) + + /* + * Initialize cache error handler pointer. Make it + * uncached, since cache error handlers should not + * touch the cache. + */ + + li t1,(K0SIZE-1) + and a0,a0,t1 # keep just physical part + li t1,K1BASE + or a0,a0,t1 # make into an uncached address + + li t0,PHYS_TO_K1(CFE_LOCORE_GLOBAL_CERRH) + SR a0,0(t0) + + /* + * Move the cache error handler into low RAM. + */ + + li t0,PHYS_TO_K1(MIPS_RAM_VEC_CACHEERR) + + LOADREL(t1,_exc_cerr_htable) + LR t2,R_EXC_CERR_TEMPLATE_END(t1) + LR t1,R_EXC_CERR_TEMPLATE(t1) + +1: lw t3,0(t1) # get a word + sw t3,0(t0) # write a word + ADD t0,4 # next word... + ADD t1,4 + blt t1,t2,1b # till done + + /* + * Now do the whole thing again, but with cached writes. + * Writing uncached makes sure the data is actually in memory, + * and writing cached makes sure we write the same + * stuff again when the cache is evicted. + * This way we don't have to bother with cacheops, + * a bonus on the BCM1250 with its funky L2. + */ + + li t0,PHYS_TO_K0(CFE_LOCORE_GLOBAL_GP) + SR gp,0(t0) + + li t0,PHYS_TO_K0(CFE_LOCORE_GLOBAL_CERRH) + SR a0,0(t0) + + li t0,PHYS_TO_K0(MIPS_RAM_VEC_CACHEERR) + + LOADREL(t1,_exc_cerr_htable) + LR t2,R_EXC_CERR_TEMPLATE_END(t1) + LR t1,R_EXC_CERR_TEMPLATE(t1) + +1: lw t3,0(t1) # get a word + sw t3,0(t0) # write a word + ADD t0,4 # next word... + ADD t1,4 + blt t1,t2,1b # till done + + + /* + * done! + */ + + move ra,t4 + j ra + +END(_exc_setup_locore) + + + + +/* ********************************************************************* + * _exc_setvector(xtype,addr) + * + * Set an exception vector address + * + * Input parameters: + * xtype - exception vector type + * addr - routine address + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_exc_setvector) + + la v0,_exc_vectab + srl a0,3 /* convert 8-byte index to array index */ + sll a0,BPWSIZE /* convert back to index appropriate for word size */ + add v0,a0 + SR a1,(v0) + j ra + +END(_exc_setvector) + + +/* ********************************************************************* + * _exc_crash_sim() + * + * Crash the GDB simulator, causing it to exit. + * + * Input parameters: + * nothing + * + * Return value: + * nothing - does not return + ********************************************************************* */ + + +LEAF(_exc_crash_sim) + + li $2,1 + li $3,0xdead + li $4,0 + syscall 0xca +1: b 1b + +END(_exc_crash_sim) + + +/* ********************************************************************* + * _exc_cache_crash_sim() + * + * As _exc_crash_sim, but distinguish cache error exception. + * + * Input parameters: + * nothing + * + * Return value: + * nothing - does not return + ********************************************************************* */ + + +LEAF(_exc_cache_crash_sim) + + li $2,1 + li $3,0xbadc + li $4,0 + syscall 0xca +1: b 1b + +END(_exc_cache_crash_sim) + + +/* ********************************************************************* + * _exc_restart() + * + * Restart the firmware at the boot address + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_exc_restart) + + li t0,0xBFC00000 # ROM restart vector + jr t0 + +END(_exc_restart) + +/* ********************************************************************* + * _exc_entry(k0) + * + * Main exception entry point. + * + * Input parameters: + * k0 - exception type + * + * Return value: + * ... + ********************************************************************* */ + +LEAF(_exc_entry) + + .set noreorder + .set noat + + subu k1,sp,EXCEPTION_SIZE + SRL k1,3 + SLL k1,3 + + SREG zero,XGR_ZERO(k1) + SREG AT,XGR_AT(k1) + + SREG v0,XGR_V0(k1) + SREG v1,XGR_V1(k1) + + SREG a0,XGR_A0(k1) + SREG a1,XGR_A1(k1) + SREG a2,XGR_A2(k1) + SREG a3,XGR_A3(k1) + + SREG t0,XGR_T0(k1) + SREG t1,XGR_T1(k1) + SREG t2,XGR_T2(k1) + SREG t3,XGR_T3(k1) + SREG t4,XGR_T4(k1) + SREG t5,XGR_T5(k1) + SREG t6,XGR_T6(k1) + SREG t7,XGR_T7(k1) + + SREG s0,XGR_S0(k1) + SREG s1,XGR_S1(k1) + SREG s2,XGR_S2(k1) + SREG s3,XGR_S3(k1) + SREG s4,XGR_S4(k1) + SREG s5,XGR_S5(k1) + SREG s6,XGR_S6(k1) + SREG s7,XGR_S7(k1) + + SREG t8,XGR_T8(k1) + SREG t9,XGR_T9(k1) + + SREG gp,XGR_GP(k1) + SREG sp,XGR_SP(k1) + SREG fp,XGR_FP(k1) + SREG ra,XGR_RA(k1) + + mfc0 t0,C0_CAUSE + mfc0 t1,C0_SR + MFC0 t2,C0_BADVADDR + MFC0 t3,C0_EPC + mfc0 t4,C0_PRID + mflo t5 + mfhi t6 + SREG t0,XCP0_CAUSE(k1) + SREG t1,XCP0_SR(k1) + SREG t2,XCP0_VADDR(k1) + SREG t3,XCP0_EPC(k1) + SREG t4,XCP0_PRID(k1) + SREG t5,XGR_LO(k1) + SREG t6,XGR_HI(k1) + +#if CFG_EMBEDDED_PIC + la gp,PHYS_TO_K0(CFE_LOCORE_GLOBAL_GP) + LR gp,0(gp) # get our GP handle from low memory vector +#else + la gp,_gp # Load up GP, not relocated so it's easy +#endif + + move a0,k0 # Pass exception type + move a1,k1 # Pass frame to exception handler + la t0,_exc_vectab # get base of exception vectors + srl k0,3 # convert 8-byte index to array index + sll k0,BPWSIZE # convert back to index appropriate for word size + addu t0,k0 # get vector address + LR t0,(t0) # to call handler + + move sp,k1 # "C" gets fresh stack area + + jalr t0 # Call exception handler + nop + + move k1, sp + LREG AT,XGR_AT(k1) + + LREG t0,XGR_LO(k1) + LREG t1,XGR_HI(k1) + mtlo t0 + mthi t1 + + LREG a0,XGR_A0(k1) + LREG a1,XGR_A1(k1) + LREG a2,XGR_A2(k1) + LREG a3,XGR_A3(k1) + + LREG t0,XGR_T0(k1) + LREG t1,XGR_T1(k1) + LREG t2,XGR_T2(k1) + LREG t3,XGR_T3(k1) + LREG t4,XGR_T4(k1) + LREG t5,XGR_T5(k1) + LREG t6,XGR_T6(k1) + LREG t7,XGR_T7(k1) + + LREG s0,XGR_S0(k1) + LREG s1,XGR_S1(k1) + LREG s2,XGR_S2(k1) + LREG s3,XGR_S3(k1) + LREG s4,XGR_S4(k1) + LREG s5,XGR_S5(k1) + LREG s6,XGR_S6(k1) + LREG s7,XGR_S7(k1) + + LREG t8,XGR_T8(k1) + LREG t9,XGR_T9(k1) + + LREG gp,XGR_GP(k1) + LREG sp,XGR_SP(k1) + LREG fp,XGR_FP(k1) + LREG ra,XGR_RA(k1) + +/* do any CP0 cleanup here */ + + LREG v0,XGR_V0(k1) + LREG v1,XGR_V1(k1) + + ERET + + .set at + .set reorder + + +END(_exc_entry) + + +/* ********************************************************************* + * _exc_clear_sr_exl() + * + * Clear SR(EXL) and return to caller. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_exc_clear_sr_exl) + + mfc0 t0,C0_SR + and t0,t0,~(0x02) # clear SR(EXL). Bit 1 + mtc0 t0,C0_SR + + HAZARD + + j ra + +END(_exc_clear_sr_exl) + +/* ********************************************************************* + * _exc_clear_sr_erl() + * + * Clear SR(ERL) and return to caller. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_exc_clear_sr_erl) + + mfc0 t0,C0_SR + and t0,t0,~(0x04) # clear SR(ERL). Bit 2 + mtc0 t0,C0_SR + + HAZARD + + j ra + +END(_exc_clear_sr_erl) + + +/* ********************************************************************* + * End + ********************************************************************* */ + + diff --git a/cfe/cfe/arch/mips/common/src/exchandler.c b/cfe/cfe/arch/mips/common/src/exchandler.c new file mode 100644 index 0000000..d69b980 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/exchandler.c @@ -0,0 +1,580 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Exception Handler File: exchandler.c + * + * This is the "C" part of the exception handler and the + * associated setup routines. We call these routines from + * the assembly-language exception handler. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "sbmips.h" +#include "lib_types.h" +#include "lib_string.h" +#include "lib_printf.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "exception.h" +#include "cfe.h" +#include "cfe_error.h" +#include "cfe_iocb.h" +#include "exchandler.h" +#include "cpu_config.h" +#include "bsp_config.h" + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +/* + * Temporary until all our CPU packages support a cache error handler + */ + +#ifndef CPUCFG_CERRHANDLER +#define CPUCFG_CERRHANDLER 0xBFC00000 +#else +extern void CPUCFG_CERRHANDLER(void); +#endif + +/* ********************************************************************* + * Globals + ********************************************************************* */ + +exc_handler_t exc_handler; +extern void _exc_entry(void); +extern void _exc_setup_locore(long); +extern void CPUCFG_TLBHANDLER(void); +extern void cfe_flushcache(uint32_t,long,long); +extern uint32_t _getstatus(void); +extern void _setstatus(uint32_t); + +static const char *regnames = "0 ATv0v1a0a1a2a3t0t1t2t3t4t5t6t7" + "s0s1s2s3s4s5s6s7t8t9k0k1gpspfpra"; +static const char *excnames = + "Interrupt" /* 0 */ + "TLBMod " /* 1 */ + "TLBMissRd" /* 2 */ + "TLBMissWr" /* 3 */ + "AddrErrRd" /* 4 */ + "AddrErrWr" /* 5 */ + "BusErrRd " /* 6 */ + "BusErrWr " /* 7 */ + "Syscall " /* 8 */ + "Breakpt " /* 9 */ + "InvOpcode" /* 10 */ + "CoProcUnu" /* 11 */ + "ArithOvfl" /* 12 */ + "TrapExc " /* 13 */ + "VCEI " /* 14 */ + "FPUExc " /* 15 */ + "CP2Exc " /* 16 */ + "Exc17 " /* 17 */ + "Exc18 " /* 18 */ + "Exc19 " /* 19 */ + "Exc20 " /* 20 */ + "Exc21 " /* 21 */ + "Exc22 " /* 22 */ + "Watchpt " /* 23 */ + "Exc24 " /* 24 */ + "Exc25 " /* 25 */ + "Exc26 " /* 26 */ + "Exc27 " /* 27 */ + "Exc28 " /* 28 */ + "Exc29 " /* 29 */ + "Exc30 " /* 30 */ + "VCED "; /* 31 */ + + + +/* ********************************************************************* + * cfe_exception(code,info) + * + * Exception handler. This routine is called when any CPU + * exception that is handled by the assembly-language + * vectors is reached. The usual thing to do here is just to + * reboot. + * + * Input parameters: + * code - exception type + * info - exception stack frame + * + * Return value: + * usually reboots + ********************************************************************* */ + +void cfe_exception(int code,uint64_t *info) +{ + int idx; + + SETLEDS("EXC!"); + + if(exc_handler.catch_exc == 1) { + /*Deal with exception without restarting CFE.*/ + + /*Clear relevant SR bits*/ + _exc_clear_sr_exl(); + _exc_clear_sr_erl(); + + /*Reset flag*/ + exc_handler.catch_exc = 0; + + exc_longjmp_handler(); + } + + +#ifdef _MIPSREGS32_ + xprintf("**Exception %d: EPC=%08X, Cause=%08X (%9s)\n", + code,(uint32_t)info[XCP0_EPC], + (uint32_t)info[XCP0_CAUSE], + excnames + G_CAUSE_EXC((uint32_t)info[XCP0_CAUSE])*9); + xprintf(" RA=%08X, VAddr=%08X\n", + (uint32_t)info[XGR_RA],(uint32_t)info[XCP0_VADDR]); + xprintf("\n"); + for (idx = 0;idx < 32; idx+= 2) { + xprintf(" %2s ($%2d) = %08X %2s ($%2d) = %08X\n", + regnames+(idx*2), + idx,(uint32_t)info[XGR_ZERO+idx], + regnames+((idx+1)*2), + idx+1,(uint32_t)info[XGR_ZERO+idx+1]); + } +#else + xprintf("**Exception %d: EPC=%016llX, Cause=%08X (%9s)\n", + code,info[XCP0_EPC],info[XCP0_CAUSE], + excnames + G_CAUSE_EXC((uint32_t)info[XCP0_CAUSE])*9); + xprintf(" RA=%016llX, VAddr=%016llX\n", + info[XGR_RA],info[XCP0_VADDR]); + xprintf("\n"); + for (idx = 0;idx < 32; idx+= 2) { + xprintf(" %2s ($%2d) = %016llX %2s ($%2d) = %016llX\n", + regnames+(idx*2), + idx,info[XGR_ZERO+idx], + regnames+((idx+1)*2), + idx+1,info[XGR_ZERO+idx+1]); + } +#endif + + xprintf("\n"); + _exc_restart(); +} + +#if (!CFG_BOOTRAM) && (CFG_RUNFROMKSEG0) +/* ********************************************************************* + * exc_setup_hw_vector(vecoffset,target,k0code) + * + * Install a patch of code at the specified offset in low + * KSEG0 memory that will jump to 'target' and load k0 + * with the specified code value. This is used when we + * run with RAM vectors. + * + * Input parameters: + * vecoffset - offset into KSEG0 + * target - location where we should branch when vector is called + * k0code - value to load into K0 before branching + * + * Return value: + * nothing + ********************************************************************* */ + +static void exc_setup_hw_vector(uint32_t vecoffset, + void *target, + uint32_t k0code) +{ + uint32_t *vec; + uint32_t new; + uint32_t lower,upper; + + new = (uint32_t) (intptr_t) target; /* warning: assumes compatibility addresses! */ + + lower = new & 0xffff; + upper = (new >> 16) & 0xffff; + if ((lower & 0x8000) != 0) { + upper++; + } + + /* + * Get a KSEG0 version of the vector offset. + */ + vec = (uint32_t *) PHYS_TO_K0(vecoffset); + + /* + * Patch in the vector. Note that we have to flush + * the L1 Dcache and invalidate the L1 Icache before + * we can use this. + */ + + vec[0] = 0x3c1b0000 | upper; /* lui k1, HIGH(new) */ + vec[1] = 0x277b0000 | lower; /* addiu k1, k1, LOW(new) */ + vec[2] = 0x03600008; /* jr k1 */ + vec[3] = 0x241a0000 | k0code; /* li k0, code */ + +} + + +/* ********************************************************************* + * exc_install_ram_vectors() + * + * Install all of the hardware vectors into low memory, + * flush the cache, and clear the BEV bit so we can start + * using them. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +static void exc_install_ram_vectors(void) +{ + uint32_t *ptr; + int idx; + + /* Debug: blow away the vector area so we can see what we did */ + ptr = (uint32_t *) PHYS_TO_K0(0); + for (idx = 0; idx < 0x1000/sizeof(uint32_t); idx++) *ptr++ = 0; + + /* + * Set up the vectors. The cache error handler is set up + * specially. + */ + + exc_setup_hw_vector(MIPS_RAM_VEC_TLBFILL, CPUCFG_TLBHANDLER,XTYPE_TLBFILL); + exc_setup_hw_vector(MIPS_RAM_VEC_XTLBFILL, _exc_entry,XTYPE_XTLBFILL); + exc_setup_hw_vector(MIPS_RAM_VEC_CACHEERR, _exc_entry,XTYPE_CACHEERR); + exc_setup_hw_vector(MIPS_RAM_VEC_EXCEPTION,_exc_entry,XTYPE_EXCEPTION); + exc_setup_hw_vector(MIPS_RAM_VEC_INTERRUPT,_exc_entry,XTYPE_INTERRUPT); + + /* + * Flush the D-cache and invalidate the I-cache so we can start + * using these vectors. + */ + + cfe_flushcache(CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I,0,0); + + /* + * Write the handle into our low memory space. If we need to save + * other stuff down there, this is a good place to do it. + * This call uses uncached writes - we have not touched the + * memory in the handlers just yet, so they should not be + * in our caches. + */ + + _exc_setup_locore((intptr_t) CPUCFG_CERRHANDLER); + + /* + * Finally, clear BEV so we'll use the vectors in RAM. + */ + + _setstatus(_getstatus() & ~M_SR_BEV); + + /* + * XXX There's a hazard here, but we're not going to worry about + * XXX it. It is unlikely we'll use the vectors any time soon. + */ +} +#endif + +/* ********************************************************************* + * cfe_setup_exceptions() + * + * Set up the exception handlers. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ +void cfe_setup_exceptions(void) +{ + _exc_setvector(XTYPE_TLBFILL, (void *) cfe_exception); + _exc_setvector(XTYPE_XTLBFILL, (void *) cfe_exception); + _exc_setvector(XTYPE_CACHEERR, (void *) _exc_cache_crash_sim); + _exc_setvector(XTYPE_EXCEPTION,(void *) cfe_exception); + _exc_setvector(XTYPE_INTERRUPT,(void *) cfe_exception); + _exc_setvector(XTYPE_EJTAG, (void *) cfe_exception); + + exc_handler.catch_exc = 0; + q_init( &(exc_handler.jmpbuf_stack)); + +#if (!CFG_BOOTRAM) && (CFG_RUNFROMKSEG0) + /* + * Install RAM vectors, and clear the BEV bit in the status + * register. Don't do this if we're running from PromICE RAM + */ + exc_install_ram_vectors(); +#endif +} + + + +/* ********************************************************************* + * exc_initialize_block() + * + * Set up the exception handler. Allow exceptions to be caught. + * Allocate memory for jmpbuf and store it away. + * + * Returns NULL if error in memory allocation. + * + * Input parameters: + * nothing + * + * Return value: + * jmpbuf_t structure, or NULL if no memory + ********************************************************************* */ +jmpbuf_t *exc_initialize_block(void) +{ + jmpbuf_t *jmpbuf_local; + + exc_handler.catch_exc = 1; + + /* Create the jmpbuf_t object */ + jmpbuf_local = (jmpbuf_t *) KMALLOC((sizeof(jmpbuf_t)),0); + + if (jmpbuf_local == NULL) { + return NULL; + } + + q_enqueue( &(exc_handler.jmpbuf_stack), &((*jmpbuf_local).stack)); + + return jmpbuf_local; +} + +/* ********************************************************************* + * exc_cleanup_block(dq_jmpbuf) + * + * Remove dq_jmpbuf from the exception handler stack and free + * the memory. + * + * Input parameters: + * dq_jmpbuf - block to deallocate + * + * Return value: + * nothing + ********************************************************************* */ + +void exc_cleanup_block(jmpbuf_t *dq_jmpbuf) +{ + int count; + + if (dq_jmpbuf == NULL) { + return; + } + + count = q_count( &(exc_handler.jmpbuf_stack)); + + if( count > 0 ) { + q_dequeue( &(*dq_jmpbuf).stack ); + KFREE(dq_jmpbuf); + } +} + +/* ********************************************************************* + * exc_cleanup_handler(dq_jmpbuf,chain_exc) + * + * Clean a block, then chain to the next exception if required. + * + * Input parameters: + * dq_jmpbuf - current exception + * chain_exc - true if we should chain to the next handler + * + * Return value: + * nothing + ********************************************************************* */ + +void exc_cleanup_handler(jmpbuf_t *dq_jmpbuf, int chain_exc) +{ + exc_cleanup_block(dq_jmpbuf); + + if( chain_exc == EXC_CHAIN_EXC ) { + /*Go to next exception on stack */ + exc_longjmp_handler(); + } +} + + + +/* ********************************************************************* + * exc_longjmp_handler() + * + * This routine long jumps to the exception handler on the top + * of the exception stack. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ +void exc_longjmp_handler(void) +{ + int count; + jmpbuf_t *jmpbuf_local; + + count = q_count( &(exc_handler.jmpbuf_stack)); + + if( count > 0 ) { + jmpbuf_local = (jmpbuf_t *) q_getlast(&(exc_handler.jmpbuf_stack)); + + SETLEDS("CFE "); + + lib_longjmp( (*jmpbuf_local).jmpbuf, -1); + } +} + + +/* ********************************************************************* + * mem_peek(d,addr,type) + * + * Read memory of the specified type at the specified address. + * Exceptions are caught in the case of a bad memory reference. + * + * Input parameters: + * d - pointer to where data should be placed + * addr - address to read + * type - type of read to do (MEM_BYTE, etc.) + * + * Return value: + * 0 if ok + * else error code + ********************************************************************* */ + +int mem_peek(void *d, long addr, int type) +{ + + jmpbuf_t *jb; + + jb = exc_initialize_block(); + if( jb == NULL ) { + return CFE_ERR_NOMEM; + } + + if (exc_try(jb) == 0) { + + switch (type) { + case MEM_BYTE: + *(uint8_t *)d = *((volatile uint8_t *) addr); + break; + case MEM_HALFWORD: + *(uint16_t *)d = *((volatile uint16_t *) addr); + break; + case MEM_WORD: + *(uint32_t *)d = *((volatile uint32_t *) addr); + break; + case MEM_QUADWORD: + *(uint64_t *)d = *((volatile uint64_t *) addr); + break; + default: + return CFE_ERR_INV_PARAM; + } + + exc_cleanup_block(jb); + } + else { + /*Exception handler*/ + + exc_cleanup_handler(jb, EXC_NORMAL_RETURN); + return CFE_ERR_GETMEM; + } + + return 0; +} + +/* ********************************************************************* + * Write memory of type at address addr with value val. + * Exceptions are caught, handled (error message) and function + * returns with 0. + * + * 1 success + * 0 failure + ********************************************************************* */ + +int mem_poke(long addr, uint64_t val, int type) +{ + + jmpbuf_t *jb; + + jb = exc_initialize_block(); + if( jb == NULL ) { + return CFE_ERR_NOMEM; + } + + if (exc_try(jb) == 0) { + + switch (type) { + case MEM_BYTE: + *((volatile uint8_t *) addr) = (uint8_t) val; + break; + case MEM_HALFWORD: + *((volatile uint16_t *) addr) = (uint16_t) val; + break; + case MEM_WORD: + *((volatile uint32_t *) addr) = (uint32_t) val; + break; + case MEM_QUADWORD: + *((volatile uint64_t *) addr) = (uint64_t) val; + break; + default: + return CFE_ERR_INV_PARAM; + } + + exc_cleanup_block(jb); + } + else { + /*Exception handler*/ + + exc_cleanup_handler(jb, EXC_NORMAL_RETURN); + return CFE_ERR_SETMEM; + } + + return 0; +} + + + + + + + + + + diff --git a/cfe/cfe/arch/mips/common/src/init_mips.S b/cfe/cfe/arch/mips/common/src/init_mips.S new file mode 100755 index 0000000..3f59539 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/init_mips.S @@ -0,0 +1,683 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * CPU init module File: init_mips.S + * + * This module contains the vectors and lowest-level CPU startup + * functions for CFE. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "sbmips.h" +#include "exception.h" + +#include "bsp_config.h" +#include "cpu_config.h" + +#ifdef _CFE_ +#include "cfe_devfuncs.h" +#else + +#define cfe_command_restart 0 +#endif + +/* BCM63XX specific change. */ +#include "bcm_hwdefs.h" + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#include "mipsmacros.h" + + +/* ********************************************************************* + * SETLEDS(a,b,c,d) + * SETLEDS1(a,b,c,d) + * + * Sets the on-board LED display (if present). Two variants + * of this routine are provided. If you're running KSEG1, + * call the SETLEDS1 variant, else call SETLEDS. + * + * Input parameters: + * a,b,c,d - four ASCII characters (literal constants) + * + * Return value: + * a0,k1,ra trashed + ********************************************************************* */ + +#define SETLEDS(a,b,c,d) \ + li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \ + CALLINIT_KSEG0(init_table,R_INIT_SETLEDS) + +#define SETLEDS1(a,b,c,d) \ + li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \ + CALLINIT_KSEG1(init_table,R_INIT_SETLEDS) + + +/* ********************************************************************* + * Other constants + ********************************************************************* */ + +/* + * This is the size of the stack, rounded to KByte boundaries. + */ + +#ifndef CFG_STACK_SIZE +#error "CFG_STACK_SIZE not defined" +#else +#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023) +#endif + +#ifdef __MIPSEB +#define TEXTSECTION 0x2e746578 # ".tex", big-endian +#else +#define TEXTSECTION 0x7865742e # ".tex", little-endian +#endif + +/* + * Duplicates from cfe_iocb.h -- warning! + */ + +#define CFE_CACHE_FLUSH_D 1 +#define CFE_CACHE_INVAL_I 2 +#define CFE_CACHE_INVAL_D 4 +#define CFE_CACHE_INVAL_L2 8 +#define CFE_CACHE_FLUSH_L2 16 +#define CFE_CACHE_INVAL_RANGE 32 +#define CFE_CACHE_FLUSH_RANGE 64 + + +/* + * To make life easier reading this code, define "KSEGBASE" + * to either K0BASE or K1BASE depending on whether we're running + * uncached. + */ + +#if CFG_RUNFROMKSEG0 +#define KSEGBASE K0BASE +#else +#define KSEGBASE K1BASE +#endif + + +/* ********************************************************************* + * Names of registers used in this module + ********************************************************************* */ + +#define RELOCOFFSET s8 /* $30 (fp) */ +#define TEXTOFFSET t9 /* $25 (t9) */ +#define MEMTOP t8 /* $24 (t8) */ +#define TEXTBASE s7 /* $23 (s7) */ +#undef BOOT_OFFSET +#define BOOT_OFFSET s6 /* $22 (s6) */ + + .sdata + +#include "initdata.h" /* declare variables we use here */ + +#if CFG_MULTI_CPUS + .globl cfe_spinlock +cfe_spinlock: .word 0 +#endif + + .extern _fdata + .extern _edata + .extern _etext + +/* ********************************************************************* + * uninitialized data + ********************************************************************* */ + + .bss + + .comm __junk,4 + +/* ********************************************************************* + * Exception Vectors + ********************************************************************* */ + + .text + + .set noreorder + +/* + * Declare the actual vectors. This expands to code that + * must be at the very beginning of the text segment. + */ + +DECLARE_VECTOR(0x0000,vec_reset,cpu_reset) + + .set reorder + +/* ********************************************************************* + * Some offsets depend on our current configuration + ********************************************************************* */ + +#define RUNTIME_RELOC_START 0 +#define RUNTIME_RELOC_STOP 0 + +/* ********************************************************************* + * Segment Table. + * + * Addresses of data segments and of certain routines we're going + * to call from KSEG1. These are here mostly for the embedded + * PIC case, since we can't count on the 'la' instruction to + * do the expected thing (the assembler expands it into a macro + * for doing GP-relative stuff, and the code is NOT GP-relative. + * So, we (relocatably) get the offset of this table and then + * index within it. + * + * Pointer values in this segment will be relative to KSEG0 for + * cached versions of CFE, so we need to OR in K1BASE in the + * case of calling to a uncached address. + * + * The LOADREL macro handles most of the nastiness here. + ********************************************************************* */ + +#include "segtable.h" +#include "cfe.h" + + .org 0x570 + .byte 'c','f','e','-','v',CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD,BCM63XX_MAJOR,BCM63XX_MINOR # CFE version info for applications + .org 0x580 # move past exception vectors + + /* + * BCM963XX NVRAM Data Storage + */ + + .globl nvram_data_storage +nvram_data_storage: + .word NVRAM_DATA_ID + .space 0x400 + + .globl segment_table +segment_table: + _LONG_ _etext # [ 0] End of text (R_SEG_ETEXT) + _LONG_ _fdata # [ 1] Beginning of data (R_SEG_FDATA) + _LONG_ _edata # [ 2] End of data (R_SEG_EDATA) + _LONG_ _end # [ 3] End of BSS (R_SEG_END) + _LONG_ _ftext # [ 4] Beginning of text (R_SEG_FTEXT) + _LONG_ _fbss # [ 5] Beginning of BSS (R_SEG_FBSS) + _LONG_ _gp # [ 6] Global Pointer (R_SEG_GP) + _LONG_ 0 # [ 7] Beginning of reloc entries + _LONG_ 0 # [ 8] End of reloc entries + _LONG_ 0 # [ 9] R_SEG_APIENTRY + +/* ********************************************************************* + * Init Table. + * + * This is like segment_table except it contains pointers to + * routines used during initialization. It serves both as a + * table for doing PIC stuff and also to separate out + * machine-specific init routines. + * + * The CALLINIT_xxx macros are used to call routines in this table. + ********************************************************************* */ + + + .globl init_table +init_table: + _LONG_ board_earlyinit # [ 0] R_INIT_EARLYINIT + _LONG_ board_setleds # [ 1] R_INIT_SETLEDS + _LONG_ board_draminfo # [ 2] R_INIT_DRAMINFO + _LONG_ CPUCFG_CPUINIT # [ 3] R_INIT_CPUINIT + _LONG_ CPUCFG_ALTCPU_START1 # [ 4] R_INIT_ALTCPU_START1 + _LONG_ CPUCFG_ALTCPU_START2 # [ 5] R_INIT_ALTCPU_START2 + _LONG_ CPUCFG_ALTCPU_RESET # [ 6] R_INIT_ALTCPU_RESET + _LONG_ CPUCFG_CPURESTART # [ 7] R_INIT_CPURESTART + _LONG_ CPUCFG_DRAMINIT # [ 8] R_INIT_DRAMINIT + _LONG_ CPUCFG_CACHEOPS # [ 9] R_INIT_CACHEOPS + _LONG_ CPUCFG_TLBHANDLER # [ 10] R_INIT_TLBHANDLER + _LONG_ cfe_main # [ 11] R_INIT_CMDSTART + _LONG_ cfe_command_restart # [ 12] R_INIT_CMDRESTART + _LONG_ cfe_doxreq # [ 13] R_INIT_DOXREQ + _LONG_ CPUCFG_TP1_SWITCH # [ 14] R_INIT_TP1_SWITCH + _LONG_ cfe_size_ram # [ 15] R_INIT_SIZERAM + +/* ********************************************************************* + * CPU Startup Code + ********************************************************************* */ + +cpu_reset: + + /* + * Start with GP as zero. Nobody should touch + * this or set it to any other value until we're ready + * to use it. This is used to tell when we should start + * using relocated references in the init table, + * so beware! (see CALLINIT_RELOC in mipsmacros.h) + */ + + move gp,zero # start with no GP. + + .set noreorder + bal 1f + nop +1: nop + .set reorder + li BOOT_OFFSET, 0x1fff0000 + and BOOT_OFFSET, ra + +#------------------------------------------------------------------------------ + + /* + * Do low-level board initialization. This is our first + * chance to customize the startup sequence. + */ + move a0, BOOT_OFFSET + + CALLINIT_KSEG1(init_table,R_INIT_EARLYINIT) + + SETLEDS1('H','E','L','O') + + CALLINIT_KSEG1(init_table,R_INIT_CPUINIT) + +#------------------------------------------------------------------------------ + + /* + * Now, switch from KSEG1 to KSEG0 + */ + +#if CFG_RUNFROMKSEG0 + bal cpu_kseg0_switch +#endif + +#------------------------------------------------------------------------------ + /* + * Now running on cpu0 in K0SEG. + */ + +#if CFG_CMT + /* + * Check if the thread switch is required. If we are already + * running on thread 1 this function will do nothing and just return + * If we are running on thread 0 this function will take thread 1 + * out of reset and put thread 0 to sleep waiting for singnal from + * thread 1. + */ + CALLINIT_KSEG0(init_table,R_INIT_TP1_SWITCH) +#endif + +#if CFG_INIT_DRAM + SETLEDS('D','R','A','M') + + CALLINIT_KSEG0(init_table,R_INIT_DRAMINFO) + + move a0,v0 # pass these params + CALLINIT_KSEG0(init_table,R_INIT_DRAMINIT) + CALLINIT_KSEG0(init_table,R_INIT_SIZERAM) + move k0,v0 # Save in k0 for now +#else + li k0,(CFG_DRAM_SIZE * 1024) +#endif + +#------------------------------------------------------------------------------ + +#if CFG_BOOTRAM + b have_ram # No RAM is ok if using emulator RAM +#endif + + bne k0,zero,have_ram + + SETLEDS('R','A','M','X') # die here if no ram + +die1: b die1 + +have_ram: + + /* + * If this is the 64-bit version, turn on the KX bit + * to allow 64-bit accesses. + */ + +#ifdef __long64 + mfc0 t0,C0_SR + or t0,t0,M_SR_KX + mtc0 t0,C0_SR +#endif + +#------------------------------------------------------------------------------ + /* + * K0 contains the RAM size (and therefore the top of RAM + * offset). Start there, and subtract the amount of memory + * we expect to use. If we have more than 256MB of + * physical memory, work backwards from the 256MB + * boundary. + */ + +__CalcMemTop: li MEMTOP,256 # 256MB boundary + bgt k0,MEMTOP,1f # use 256MB if k0 is greater + move MEMTOP,k0 # otherwise keep top +1: sll MEMTOP,20 # make into byte amount + + li RELOCOFFSET,0 # not relocating, no offset + li TEXTOFFSET,0 + + /* + * DRAM is now running, and we're alive in cacheable memory + * on cpu0 in K0SEG. Set up GP. + */ + + LOADREL(a0,segment_table) + LR gp,R_SEG_GP(a0) + add gp,RELOCOFFSET + +#------------------------------------------------------------------------------ + /* + * Zero BSS + */ + + SETLEDS('Z','B','S','S') + + LOADREL(a0,segment_table) +__ZeroBss: + + LR v0,R_SEG_FBSS(a0) + LR v1,R_SEG_END(a0) + ADD v0,RELOCOFFSET # Relocate to actual data segment + ADD v1,RELOCOFFSET + +1: SR zero,0(v0) # Zero one cacheline at a time + SR zero,(REGSIZE*1)(v0) + SR zero,(REGSIZE*2)(v0) + SR zero,(REGSIZE*3)(v0) + add v0,REGSIZE*4 + blt v0,v1,1b + +#------------------------------------------------------------------------------ + /* + * Copy code + */ + + SETLEDS('C','O','D','E') + + LOADREL(a0,segment_table) +__CopyCode: + + LR t1,R_SEG_FTEXT(a0) # destination address + move TEXTBASE,t1 + + LR t2,R_SEG_FTEXT(a0) # Source address + FIXUP (t2); + LR t3,R_SEG_ETEXT(a0) + FIXUP (t3); + +1: LR t4,0(t2) # read one cache line + LR t5,(REGSIZE*1)(t2) + LR t6,(REGSIZE*2)(t2) + LR t7,(REGSIZE*3)(t2) + SR t4,0(t1) # write one cache line + SR t5,(REGSIZE*1)(t1) + SR t6,(REGSIZE*2)(t1) + SR t7,(REGSIZE*3)(t1) + add t1,REGSIZE*4 + add t2,REGSIZE*4 + bltu t2,t3,1b + +#------------------------------------------------------------------------------ + /* + * Copy initialized data + */ + +#if (CFG_BOOTRAM == 0) + + SETLEDS('D','A','T','A') + + LOADREL(a0,segment_table) + +__CopyData: + LR t1,R_SEG_FDATA(a0) + FIXUP (t1); + li t0,15 + add t1,t0 + not t0 + and t1,t0 # t1 = _etext rounded up to 16-byte boundary + + LR t2,R_SEG_FDATA(a0) + LR t3,R_SEG_EDATA(a0) + ADD t2,RELOCOFFSET # Relocate to actual data segment + ADD t3,RELOCOFFSET + +1: LR t4,0(t1) # read one cache line + LR t5,(REGSIZE*1)(t1) + LR t6,(REGSIZE*2)(t1) + LR t7,(REGSIZE*3)(t1) + SR t4,0(t2) # write one cache line + SR t5,(REGSIZE*1)(t2) + SR t6,(REGSIZE*2)(t2) + SR t7,(REGSIZE*3)(t2) + add t1,(REGSIZE*4) + add t2,(REGSIZE*4) + bltu t2,t3,1b + +#endif + +#------------------------------------------------------------------------------ + + /* + * Flush the cache, then switch to relocated code + * We need to flush the cache since we just moved the code and + * it may still live in our L1 DCache. We also need to + * flush L2, since there are some rare times we run + * uncached from DRAM, like when we start/stop a CPU. + * + * In the case of running completely uncached, don't flush the + * cache. It should not have any dirty lines in it, but you + * never know... + */ + +__GoRelo: + +#if CFG_RUNFROMKSEG0 + SETLEDS('L','1','2','F') + + li a0,CFE_CACHE_FLUSH_D | CFE_CACHE_FLUSH_L2 + CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS) + li a0,CFE_CACHE_INVAL_I + CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS) +#endif /* CFG_RUNFROMKSEG0 */ + + la t0,gorelo # Now jump to an address code was compiled for + j t0 # and go there +gorelo: nop + li BOOT_OFFSET, 0 # no longer running at offset + + /* + * Remember total amount of memory. This is *still* in k0 + * after all this time. Hopefully. + */ + +__MemVars: + SR k0,mem_totalsize + SR RELOCOFFSET,mem_datareloc + + move v0,zero + + LOADREL(a0,segment_table) # trashed by l2 cache flush + LR v0,R_SEG_FDATA(a0) + ADD v0,RELOCOFFSET + LR v1,R_SEG_END(a0) + ADD v1,RELOCOFFSET + + SR v0,mem_bottomofmem + SR v1,mem_heapstart + + add v1,(CFG_HEAP_SIZE*1024) # Otherwise + add v1,STACK_SIZE + SR v1,mem_topofmem + + SR TEXTOFFSET,mem_textreloc + + /* At this point it's safe to use the CALLINIT_RELOC macro */ + + LR t1,R_SEG_FTEXT(a0) + FIXUP (t1); + LR t0,R_SEG_ETEXT(a0) + FIXUP (t0); + sub t0,t0,t1 + SR t0,mem_textsize + add t1,TEXTOFFSET + SR t1,mem_textbase + + +#------------------------------------------------------------------------------ + + /* + * Stash away some config register stuff + */ + + mfc0 v0,C0_PRID + SR v0,cpu_prid + + +#------------------------------------------------------------------------------ + + /* + * Set up the "C" stack and jump to the main routine. + */ + + SETLEDS('M','A','I','N') + + LR sp,mem_heapstart + ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8) + li a0,0 # call as "cfe_main(0,0)" + li a1,0 + + CALLINIT_RELOC(init_table,R_INIT_CMDSTART) # should not return + +/* ********************************************************************* + * CFE_LAUNCH + * + * Start the user program. The program is passed a handle + * that must be passed back when calling the firmware. + * + * Parameters passed to the called program are as follows: + * + * a0 - CFE handle + * a1 - entry vector + * a2 - reserved, will be 0 + * a3 - entrypoint signature. + * + * Input parameters: + * a0 - entry vector + * + * Return value: + * does not return + ********************************************************************* */ + +LEAF(cfe_launch) + + sub sp,8 + SR a0,0(sp) + + /* + * This function runs in RAM so BOOT_OFFSET is 0. It is called from + * C which could have modified the BOOT_OFFSET register, s6. + */ + li BOOT_OFFSET, 0 + + + /* + * Mask all interrupts. + */ + mfc0 v0,C0_SR # Get current interrupt flag + li v1,M_SR_IE # master interrupt control + not v1 # disable interrupts + and v0,v1 # SR now has IE=0 + mtc0 v0,C0_SR # put back into CP0 + + + /* + * Flush the D-Cache, since the program we loaded is "data". + * Invalidate the I-Cache, so that addresses in the program + * region will miss and need to be filled from the data we + * just flushed above. + */ + + li a0,CFE_CACHE_FLUSH_D|CFE_CACHE_INVAL_I + CALLINIT_RELOC(init_table,R_INIT_CACHEOPS) + + + /* + * Set things up for launching the program. Pass the + * handle in A0 - apps need to remember that and pass it + * back. + */ + + j RunProgram + +END(cfe_launch) + + /* + * This is a nice place to set a breakpoint. + */ +LEAF(RunProgram) + LR t0,0(sp) # entry point + + j t0 # go for it. +END(RunProgram) + +/* ********************************************************************* + * CPU_KSEG0_SWITCH + * + * Hack the return address so we will come back in KSEG0 + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(cpu_kseg0_switch) + + and ra,(K0SIZE-1) + or ra,K0BASE + jr ra + +END(cpu_kseg0_switch) + +/* ********************************************************************* + * End + ********************************************************************* */ + + diff --git a/cfe/cfe/arch/mips/common/src/init_ram.S b/cfe/cfe/arch/mips/common/src/init_ram.S new file mode 100755 index 0000000..2531700 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/init_ram.S @@ -0,0 +1,889 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * CPU init module File: init_ram.S + * + * This module contains the vectors and lowest-level CPU startup + * functions for CFE. + * + * This is very similar to "init_mips.S" but is used when + * you want to locate CFE in DRAM, loading it like an + * application program. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "sbmips.h" +#include "exception.h" + +#include "bsp_config.h" +#include "cpu_config.h" + +#include "cfe_devfuncs.h" + +/* ********************************************************************* + * Check some stuff + ********************************************************************* */ + +#if CFG_RELOC +#error "RAM version is not compatible with relocation." +#endif +#if !(CFG_RUNFROMKSEG0) +#error "RAM version should be run cached" +#endif + +#if CFG_MULTI_CPUS +#error "Multiple CPUs not compatible with RAM version" +#endif + + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#include "mipsmacros.h" + + +/* ********************************************************************* + * SETLEDS(a,b,c,d) + * + * Sets the on-board LED display (if present). + * + * Input parameters: + * a,b,c,d - four ASCII characters (literal constants) + * + * Return value: + * a0,k1,ra trashed + ********************************************************************* */ + + +#define SETLEDS(a,b,c,d) \ + li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \ + jal board_setleds ; + + +/* ********************************************************************* + * Other constants + ********************************************************************* */ + +/* + * This is the size of the stack, rounded to KByte boundaries. + */ + +#ifndef CFG_STACK_SIZE +#error "CFG_STACK_SIZE not defined" +#else +#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023) +#endif + +/* + * Duplicates from cfe_iocb.h -- warning! + */ + +#define CFE_CACHE_FLUSH_D 1 +#define CFE_CACHE_INVAL_I 2 +#define CFE_CACHE_INVAL_D 4 +#define CFE_CACHE_INVAL_L2 8 +#define CFE_CACHE_FLUSH_L2 16 +#define CFE_CACHE_INVAL_RANGE 32 +#define CFE_CACHE_FLUSH_RANGE 64 + + +/* + * To make life easier reading this code, define "KSEGBASE" + * to either K0BASE or K1BASE depending on whether we're running + * uncached. + */ + +#define KSEGBASE K0BASE /* RAM version always cached */ + + +/* ********************************************************************* + * Names of registers used in this module + ********************************************************************* */ + + .sdata + +#include "initdata.h" /* declare variables we use here */ + +#if CFG_MULTI_CPUS + .globl cfe_spinlock +cfe_spinlock: .word 0 +#endif + + .extern _fdata + .extern _edata + .extern _etext + +/* ********************************************************************* + * uninitialized data + ********************************************************************* */ + + .bss + + .comm __junk,4 + + .text + + .set noreorder + + +/* ********************************************************************* + * CFE Entry Point (used by OS boot loaders and such) + ********************************************************************* */ + + .set noreorder + + .globl vec_reset + +vec_reset: b cpu_reset + nop + + +vec_apientry: b cpu_apientry + nop + .word CFE_EPTSEAL + .word CFE_EPTSEAL + + .set reorder + + +/* ********************************************************************* + * Segment Table. + * + * Addresses of data segments and of certain routines we're going + * to call from KSEG1. These are here mostly for the embedded + * PIC case, since we can't count on the 'la' instruction to + * do the expected thing (the assembler expands it into a macro + * for doing GP-relative stuff, and the code is NOT GP-relative. + * So, we (relocatably) get the offset of this table and then + * index within it. + * + * Pointer values in this segment will be relative to KSEG0 for + * cached versions of CFE, so we need to OR in K1BASE in the + * case of calling to a uncached address. + * + * The LOADREL macro handles most of the nastiness here. + ********************************************************************* */ + + +#include "segtable.h" + + .globl segment_table +segment_table: + _LONG_ _etext # [ 0] End of text (R_SEG_ETEXT) + _LONG_ _fdata # [ 1] Beginning of data (R_SEG_FDATA) + _LONG_ _edata # [ 2] End of data (R_SEG_EDATA) + _LONG_ _end # [ 3] End of BSS (R_SEG_END) + _LONG_ _ftext # [ 4] Beginning of text (R_SEG_FTEXT) + _LONG_ _fbss # [ 5] Beginning of BSS (R_SEG_FBSS) + _LONG_ _gp # [ 6] Global Pointer (R_SEG_GP) + _LONG_ 0 # [ 7] Beginning of reloc entries + _LONG_ 0 # [ 8] End of reloc entries + _LONG_ cpu_apientry # [ 9] R_SEG_APIENTRY + + +/* ********************************************************************* + * Init Table. + * + * This is like segment_table except it contains pointers to + * routines used during initialization. It serves both as a + * table for doing PIC stuff and also to separate out + * machine-specific init routines. + * + * The CALLINIT_xxx macros are used to call routines in this table. + ********************************************************************* */ + + + .globl init_table +init_table: + _LONG_ board_earlyinit # [ 0] R_INIT_EARLYINIT + _LONG_ board_setleds # [ 1] R_INIT_SETLEDS + _LONG_ board_draminfo # [ 2] R_INIT_DRAMINFO + _LONG_ CPUCFG_CPUINIT # [ 3] R_INIT_CPUINIT + _LONG_ CPUCFG_ALTCPU_START1 # [ 4] R_INIT_ALTCPU_START1 + _LONG_ CPUCFG_ALTCPU_START2 # [ 5] R_INIT_ALTCPU_START2 + _LONG_ CPUCFG_ALTCPU_RESET # [ 6] R_INIT_ALTCPU_RESET + _LONG_ CPUCFG_CPURESTART # [ 7] R_INIT_CPURESTART + _LONG_ CPUCFG_DRAMINIT # [ 8] R_INIT_DRAMINIT + _LONG_ CPUCFG_CACHEOPS # [ 9] R_INIT_CACHEOPS + _LONG_ CPUCFG_TLBHANDLER # [ 10] R_INIT_TLBHANDLER + _LONG_ cfe_main # [ 11] R_INIT_CMDSTART + _LONG_ cfe_command_restart # [ 12] R_INIT_CMDRESTART + _LONG_ cfe_doxreq # [ 13] R_INIT_DOXREQ + _LONG_ CPUCFG_TP1_SWITCH # [ 14] R_INIT_TP1_SWITCH + _LONG_ bcmcore_null # [ 15] R_INIT_SIZERAM + +/* ********************************************************************* + * CPU Startup Code + ********************************************************************* */ + + +cpu_reset: + +#------------------------------------------------------------------------------ + + /* + * Do low-level board initialization. This is our first + * chance to customize the startup sequence. + */ + + CALLINIT_KSEG0(init_table,R_INIT_EARLYINIT) + + SETLEDS('H','E','L','O') + +#------------------------------------------------------------------------------ + + /* + * DRAM is now running, and we're alive in cacheable memory + * on cpu0 in K0SEG. Set up GP. + */ + + LOADREL(a0,segment_table) + LR gp,R_SEG_GP(a0) + +#------------------------------------------------------------------------------ + /* + * Zero BSS + */ + + SETLEDS('Z','B','S','S') + + LOADREL(a0,segment_table) +__ZeroBss: + + LR v0,R_SEG_FBSS(a0) + LR v1,R_SEG_END(a0) + +1: SR zero,0(v0) # Zero one cacheline at a time + SR zero,(REGSIZE*1)(v0) + SR zero,(REGSIZE*2)(v0) + SR zero,(REGSIZE*3)(v0) + add v0,REGSIZE*4 + blt v0,v1,1b + + +#------------------------------------------------------------------------------ + + li k0,256 # memory size in megabytes + + +#ifdef __long64 + mfc0 t0,C0_SR + or t0,t0,M_SR_KX + mtc0 t0,C0_SR +#endif + +#------------------------------------------------------------------------------ + + /* + * Remember total amount of memory. This is *still* in k0 + * after all this time. Hopefully. + */ + +__MemVars: + SR k0,mem_totalsize + SR zero,mem_datareloc + + move v0,zero + + LOADREL(a0,segment_table) # trashed by l2 cache flush + LR v0,R_SEG_FTEXT(a0) # bottom = beginning of text + LR v1,R_SEG_END(a0) + + SR v0,mem_bottomofmem + SR v1,mem_heapstart + + add v1,(CFG_HEAP_SIZE*1024) # Otherwise + add v1,STACK_SIZE + SR v1,mem_topofmem + + SR zero,mem_textreloc + + + LR t1,R_SEG_FTEXT(a0) + LR t0,R_SEG_ETEXT(a0) + sub t0,t0,t1 + SR t0,mem_textsize + SR t1,mem_textbase + + +#------------------------------------------------------------------------------ + +#if CFG_MULTI_CPUS + /* + * Let secondary CPU(s) run their idle loops. Set the + * mailbox register to our relocation factor so we can read + * it out of the mailbox register and relocate GP properly. + */ + + move a0,zero + CALLINIT_KSEG0(init_table,R_INIT_ALTCPU_START2) +#endif + + /* + * Stash away some config register stuff + */ + + mfc0 v0,C0_PRID + SR v0,cpu_prid + + +#------------------------------------------------------------------------------ + + /* + * Set up the "C" stack and jump to the main routine. + */ + + SETLEDS('M','A','I','N') + + LR sp,mem_heapstart + ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8) + li a0,0 # call as "cfe_main(0,0)" + li a1,0 + + CALLINIT_KSEG0(init_table,R_INIT_CMDSTART) # should not return + + + /* + * Terminate the simulator. + */ + +crash_sim: li $2,1 + li $4,0 + syscall 0xCA + b cpu_reset + + + +/* ********************************************************************* + * CFE_WARMSTART + * + * Restart the command interpreter + * + * Input parameters: + * A0 - command status + * nothing (GP has already been set up for us) + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(cfe_warmstart) + + SR a0,0(sp) # store on old stack + LOADREL(v0,init_table) + LR v0,R_INIT_CPURESTART(v0) + jal v0 # had better not trash GP or K1 + LR a0,0(sp) + + LR sp,mem_heapstart + ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8) + + /* + * If someone called the API to do a warm start, clear the + * spin lock, since the call will never return. + */ + +#if CFG_MULTI_CPUS + SPIN_UNLOCK(cfe_spinlock,t0) +#endif + + CALLINIT_KSEG0(init_table,R_INIT_CMDRESTART) # should not return + +END(cfe_warmstart) + +/* ********************************************************************* + * CFE_FLUSHCACHE + * + * Perform certain cache operations + * + * Input parameters: + * a0 - flags (CFE_CACHE_xxx flags, or zero for a default) + * a1,a2 - start/end of range for "range invalidate" operations + * (not used otherwise) + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_cfe_flushcache) + + sub sp,32 + SR ra,0(sp) + SR a0,8(sp) + SR s0,16(sp) + SR v1,24(sp) + + + CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS) + + LR v1,24(sp) + LR s0,16(sp) + LR a0,8(sp) + LR ra,0(sp) + add sp,32 + j ra + +END(_cfe_flushcache) + + +/* ********************************************************************* + * CFE_LAUNCH + * + * Start the user program. The program is passed a handle + * that must be passed back when calling the firmware. + * + * Parameters passed to the called program are as follows: + * + * a0 - CFE handle + * a1 - entry vector + * a2 - reserved, will be 0 + * a3 - entrypoint signature. + * + * Input parameters: + * a0 - entry vector + * + * Return value: + * does not return + ********************************************************************* */ + +LEAF(cfe_launch) + + sub sp,8 + SR a0,0(sp) + + /* + * Mask all interrupts. + */ + mfc0 v0,C0_SR # Get current interrupt flag + li v1,M_SR_IE # master interrupt control + not v1 # disable interrupts + and v0,v1 # SR now has IE=0 + mtc0 v0,C0_SR # put back into CP0 + + /* + * Flush the D-Cache, since the program we loaded is "data". + * Invalidate the I-Cache, so that addresses in the program + * region will miss and need to be filled from the data we + * just flushed above. + */ + + li a0,CFE_CACHE_FLUSH_D|CFE_CACHE_INVAL_I + CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS) + + /* + * Set things up for launching the program. Pass the + * handle in A0 - apps need to remember that and pass it + * back. + */ + + j RunProgram + +END(cfe_launch) + + /* + * This is a nice place to set a breakpoint. + */ +LEAF(RunProgram) + + LOADREL(a2,segment_table) + LR a2,R_SEG_APIENTRY(a2) # A2 = code entry + move t0,a0 # + move a1,zero # A1 = 0 + move a0,gp # A0 = handle + li a3,CFE_EPTSEAL # A3 = entrypoint signature + LR t0,0(sp) # entry point + j t0 # go for it. +END(RunProgram) + + + + +/* ********************************************************************* + * CFE_LEDS + * + * Set the on-board LEDs. + * + * Input parameters: + * a0 - LEDs + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(cfe_leds) + + j board_setleds # jump to BSP routine + +END(cfe_leds) + +/* ********************************************************************* + * TLB Fill Exeption Handler + ********************************************************************* */ + +cpu_tlbfill: + move k0,ra # Save, we're about to trash + LOADREL(k1,init_table) # Load offset of init table + LR k1,R_INIT_TLBHANDLER(k1) # Get entry from table + move ra,k0 # restore trashed ra + j k1 # Dispatch to handler + +/* ********************************************************************* + * XTLB Fill Exception Handler + ********************************************************************* */ + +cpu_xtlbfill: + j _exc_entry + +/* ********************************************************************* + * Cache Error Exception Handler + ********************************************************************* */ + +cpu_cacheerr: + j _exc_entry + + +/* ********************************************************************* + * General Exception Handler + ********************************************************************* */ + +cpu_exception: + j _exc_entry + + +/* ********************************************************************* + * General Interrupt Handler + ********************************************************************* */ + +cpu_interrupt: + j _exc_entry + + +/* ********************************************************************* + * EJTAG Debug Exception Handler + ********************************************************************* */ + +cpu_ejtag: + j cpu_reset + +/* ********************************************************************* + * cpu_apientry(handle,iocb) + * + * API entry point for external apps. + * + * Input parameters: + * a0 - firmware handle (used to determine the location of + * our relocated data) + * a1 - pointer to IOCB to execute + * + * Return value: + * v0 - return code, 0 if ok + ********************************************************************* */ + +#define _regidx(x) ((x)*8) + +#define CAE_SRSAVE _regidx(0) +#define CAE_GPSAVE _regidx(1) +#define CAE_RASAVE _regidx(2) +#define CAE_S0SAVE _regidx(3) +#define CAE_S1SAVE _regidx(4) +#define CAE_S2SAVE _regidx(5) +#define CAE_S3SAVE _regidx(6) +#define CAE_S4SAVE _regidx(7) +#define CAE_S5SAVE _regidx(8) +#define CAE_S6SAVE _regidx(9) +#define CAE_S7SAVE _regidx(10) + +#define CAE_STKSIZE _regidx(11) + +LEAF(cpu_apientry) + + sub sp,CAE_STKSIZE # Make room for our stuff + + mfc0 v0,C0_SR # Get current interrupt flag + SR v0,CAE_SRSAVE(sp) # save on stack + li t0,M_SR_IE # master interrupt control + not t0 # disable interrupts + and v0,t0 # SR now has IE=0 + mtc0 v0,C0_SR # put back into CP0 + + SR gp,CAE_GPSAVE(sp) # save GP + SR ra,CAE_RASAVE(sp) # and old RA + + SR s0,CAE_S0SAVE(sp) + SR s1,CAE_S1SAVE(sp) + SR s2,CAE_S2SAVE(sp) + SR s3,CAE_S3SAVE(sp) + SR s4,CAE_S4SAVE(sp) + SR s5,CAE_S5SAVE(sp) + SR s6,CAE_S6SAVE(sp) + SR s7,CAE_S7SAVE(sp) + + move gp,a0 # set up new GP + move a0,a1 # A0 points at IOCB + + +#if CFG_MULTI_CPUS + SPIN_LOCK(cfe_spinlock,t0,t1) +#endif + + CALLINIT_KSEG0(init_table,R_INIT_DOXREQ) # should not return + +#if CFG_MULTI_CPUS + SPIN_UNLOCK(cfe_spinlock,t0) +#endif + + # + # Restore the saved registers. + # + + LR s7,CAE_S7SAVE(sp) + LR s6,CAE_S6SAVE(sp) + LR s5,CAE_S5SAVE(sp) + LR s4,CAE_S4SAVE(sp) + LR s3,CAE_S3SAVE(sp) + LR s2,CAE_S2SAVE(sp) + LR s1,CAE_S1SAVE(sp) + LR s0,CAE_S0SAVE(sp) + + LR ra,CAE_RASAVE(sp) # unwind the stack + LR gp,CAE_GPSAVE(sp) + + LR t0,CAE_SRSAVE(sp) # old interrupt mask + + add sp,CAE_STKSIZE # restore old stack pointer + + mtc0 t0,C0_SR # restore interrupts + j ra + nop + +END(cpu_apientry) + + +/* ********************************************************************* + * CPU_KSEG0_SWITCH + * + * Hack the return address so we will come back in KSEG0 + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(cpu_kseg0_switch) + + and ra,(K0SIZE-1) + or ra,K0BASE + jr ra + +END(cpu_kseg0_switch) + + + + +/* ********************************************************************* + * _GETSTATUS() + * + * Read the STATUS register into v0 + * + * Input parameters: + * nothing + * + * Return value: + * v0 - Status register + ********************************************************************* */ + +LEAF(_getstatus) + + mfc0 v0,C0_SR + j ra +END(_getstatus) + + +/* ********************************************************************* + * _SETSTATUS() + * + * Set the STATUS register to the value in a0 + * + * Input parameters: + * nothing + * + * Return value: + * v0 - Status register + ********************************************************************* */ + +LEAF(_setstatus) + + mtc0 a0,C0_SR + j ra +END(_setstatus) + +/* ********************************************************************* + * _GETCAUSE() + * + * Read the CAUSE register into v0 + * + * Input parameters: + * nothing + * + * Return value: + * v0 - Cause register + ********************************************************************* */ + +LEAF(_getcause) + + mfc0 v0,C0_CAUSE + j ra +END(_getcause) + + +/* ********************************************************************* + * _GETTICKS() + * + * Read the COUNT register into v0 + * + * Input parameters: + * nothing + * + * Return value: + * v0 - count register + ********************************************************************* */ + +LEAF(_getticks) + + mfc0 v0,C0_COUNT + j ra +END(_getticks) + + +/* ********************************************************************* + * _SETALARM(ticks) + * + * Set the C0_Compare register from a0 + * + * Input parameters: + * a0 - compare register + * + * Return value: + * none + ********************************************************************* */ + +LEAF(_setalarm) + + mtc0 a0,C0_COMPARE + j ra +END(_setalarm) + + +/* ********************************************************************* + * _SETCONTEXT() + * + * Set the CONTEXT register. + * + * Input parameters: + * a0 - context + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_setcontext) + + mtc0 a0,C0_CTEXT + j ra +END(_setcontext) + +/* ********************************************************************* + * _GETSEGTBL() + * + * Return the address of the segment table. We use this + * to display the startup messages. + * + * You can't just address the table from C because it lives + * in the text segment. + * + * Input parameters: + * nothing + * + * Return value: + * address of table + ********************************************************************* */ + + +LEAF(_getsegtbl) + move t0,ra + LOADREL(v0,segment_table) + move ra,t0 + j ra +END(_getsegtbl) + + +/* ********************************************************************* + * _wbflush() + * + * Flush the write buffer. This is probably not necessary + * on SiByte CPUs, but we have it for completeness. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +LEAF(_wbflush) + + sync /* drain the buffers */ + la t0,__junk /* do an uncached read to force it out */ + or t0,K1BASE + lw zero,0(t0) + j ra + +END(_wbflush) + + +/* ********************************************************************* + * End + ********************************************************************* */ + + diff --git a/cfe/cfe/arch/mips/common/src/lib_hssubr.S b/cfe/cfe/arch/mips/common/src/lib_hssubr.S new file mode 100644 index 0000000..07085e3 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/lib_hssubr.S @@ -0,0 +1,194 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Hyperspace Subroutines File: lib_hssubr.S + * + * Little stub routines to allow access to KXSEG from 32-bit progs. + * + * Author: Mitch Lichtenberg (mitch@sibyte.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "sbmips.h" +#include "mipsmacros.h" +#include "cpu_config.h" /* for definition of HAZARD */ + + +/* ********************************************************************* + * hs_read8 - read 8-bit bytes + ********************************************************************* */ + + +LEAF(hs_read8) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + lbu v0,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_read8) + +/* ********************************************************************* + * hs_read16 - read 16-bit shorts + ********************************************************************* */ + +LEAF(hs_read16) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + lhu v0,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_read16) + +/* ********************************************************************* + * hs_read32 - read 32-bit ints + ********************************************************************* */ + +LEAF(hs_read32) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + lw v0,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_read32) + +/* ********************************************************************* + * hs_read64 - read 64-bit longs + ********************************************************************* */ + +LEAF(hs_read64) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + ld v0,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_read64) + +/* ********************************************************************* + * hs_write8 - write 8-bit bytes + ********************************************************************* */ + +LEAF(hs_write8) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + sb a1,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_write8) + +/* ********************************************************************* + * hs_write16 - write 16-bit shorts + ********************************************************************* */ + +LEAF(hs_write16) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + sh a1,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_write16) + +/* ********************************************************************* + * hs_write32 - write 32-bit longs + ********************************************************************* */ + +LEAF(hs_write32) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + sw a1,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_write32) + +/* ********************************************************************* + * hs_write64 - write 64-bit longs + ********************************************************************* */ + +LEAF(hs_write64) + mfc0 t2,C0_SR + or t1,t2,M_SR_KX + mtc0 t1,C0_SR + HAZARD + + sd a1,(a0) + + mtc0 t2,C0_SR + HAZARD + j ra +END(hs_write64) + + +/* ********************************************************************* + * End + ********************************************************************* */ + diff --git a/cfe/cfe/arch/mips/common/src/lib_physio.S b/cfe/cfe/arch/mips/common/src/lib_physio.S new file mode 100644 index 0000000..7f57fea --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/lib_physio.S @@ -0,0 +1,173 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Physical memory peek/poke routines File: lib_physio.S + * + * Little stub routines to allow access to arbitrary physical + * addresses. In most cases this should not be needed, as + * many physical addresses are within kseg1, but this handles + * the cases that are not automagically, so we don't need + * to mess up the code with icky macros and such. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "sbmips.h" +#include "mipsmacros.h" +#include "cpu_config.h" /* for definition of HAZARD */ + + +/* ********************************************************************* + * PHYSOP(inst,a) + * + * Macro to construct code for doing the physical I/O + * We try to avoid messing with KX or doing 64-bit stuff + * unless necessary. + * + * Input parameters: + * INST - instruction name to run + * A - register containing arg or return value + * + * Return value: + * nothing + ********************************************************************* */ + + + +#ifdef _MIPSREGS32_ +#define PHYSOP(INST,A) \ + or a0,a0,K1BASE ; \ + INST A,0(a0) ; \ + j ra ; +#else +#define PHYSOP(INST,A) \ + lui t0,0x2000 ; \ + bgeu a0,t0,1f ; \ + or a0,a0,K1BASE ; \ + INST A,0(a0) ; \ + j ra ; \ +1: lui t0,0x9000 ; \ + dsll t0,t0,32 ; \ + or a0,a0,t0 ; \ + mfc0 t1,C0_SR ; \ + and t0,t1,M_SR_KX ; \ + beq t0,zero,1f ; \ + INST A,0(a0) ; \ + j ra ; \ +1: or t0,t1,M_SR_KX ; \ + mtc0 t0,C0_SR ; \ + HAZARD ; \ + INST A,0(a0) ; \ + mtc0 t1,C0_SR ; \ + HAZARD ; \ + j ra ; +#endif + + +/* ********************************************************************* + * phys_read8 - read 8-bit bytes + ********************************************************************* */ + + +LEAF(phys_read8) +PHYSOP(lbu,v0) +END(phys_read8) + +/* ********************************************************************* + * phys_read16 - read 16-bit shorts + ********************************************************************* */ + +LEAF(phys_read16) +PHYSOP(lh,v0) +END(phys_read16) + +/* ********************************************************************* + * phys_read32 - read 32-bit ints + ********************************************************************* */ + +LEAF(phys_read32) +PHYSOP(lw,v0) +END(phys_read32) + +/* ********************************************************************* + * phys_read64 - read 64-bit longs + ********************************************************************* */ + +LEAF(phys_read64) +PHYSOP(ld,v0) +END(phys_read64) + +/* ********************************************************************* + * phys_write8 - write 8-bit bytes + ********************************************************************* */ + +LEAF(phys_write8) +PHYSOP(sb,a1) +END(phys_write8) + +/* ********************************************************************* + * phys_write16 - write 16-bit shorts + ********************************************************************* */ + +LEAF(phys_write16) +PHYSOP(sh,a1) +END(phys_write16) + +/* ********************************************************************* + * phys_write32 - write 32-bit longs + ********************************************************************* */ + +LEAF(phys_write32) +PHYSOP(sw,a1) +END(phys_write32) + +/* ********************************************************************* + * phys_write64 - write 64-bit longs + ********************************************************************* */ + +LEAF(phys_write64) +PHYSOP(sd,a1) +END(phys_write64) + + +/* ********************************************************************* + * End + ********************************************************************* */ + diff --git a/cfe/cfe/arch/mips/common/src/lib_setjmp.S b/cfe/cfe/arch/mips/common/src/lib_setjmp.S new file mode 100644 index 0000000..b8c82b3 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/lib_setjmp.S @@ -0,0 +1,94 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Simple setjmp/longjmp File: lib_setjmp.S + * + * A very simple SETJMP and LONGJMP + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + + + +#include "sbmips.h" +#include "lib_setjmp.h" + +#ifdef _MIPSREGS32_ +#define SREG sw +#define LREG lw +#else +#define SREG sd +#define LREG ld +#endif + +LEAF(lib_setjmp) + + SREG s0,JMPB_S0(a0) + SREG s1,JMPB_S1(a0) + SREG s2,JMPB_S2(a0) + SREG s3,JMPB_S3(a0) + SREG s4,JMPB_S4(a0) + SREG s5,JMPB_S5(a0) + SREG s6,JMPB_S6(a0) + SREG s7,JMPB_S7(a0) + SREG fp,JMPB_FP(a0) + SREG sp,JMPB_SP(a0) + SREG ra,JMPB_RA(a0) + move v0,zero + j ra + +END(lib_setjmp) + +LEAF(lib_longjmp) + LREG s0,JMPB_S0(a0) + LREG s1,JMPB_S1(a0) + LREG s2,JMPB_S2(a0) + LREG s3,JMPB_S3(a0) + LREG s4,JMPB_S4(a0) + LREG s5,JMPB_S5(a0) + LREG s6,JMPB_S6(a0) + LREG s7,JMPB_S7(a0) + LREG fp,JMPB_FP(a0) + LREG sp,JMPB_SP(a0) + LREG ra,JMPB_RA(a0) + move v0,a1 + jr ra +END(lib_longjmp) + diff --git a/cfe/cfe/arch/mips/common/src/mips_arena.c b/cfe/cfe/arch/mips/common/src/mips_arena.c new file mode 100644 index 0000000..d96fee6 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/mips_arena.c @@ -0,0 +1,186 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Physical Memory (arena) manager File: sb1250_arena.c + * + * This module describes the physical memory available to the + * firmware. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "lib_printf.h" +#include "lib_arena.h" + +#include "cfe_error.h" + +#include "cfe.h" +#include "cfe_mem.h" + +#include "initdata.h" + +#define _NOPROTOS_ +#include "cfe_boot.h" +#undef _NOPROTOS_ + +#include "cpu_config.h" + +#include "addrspace.h" + +/* ********************************************************************* + * Constants + ********************************************************************* */ + + +#define MEG (1024*1024) +#define KB 1024 +#define PAGESIZE 4096 +#define CFE_BOOTAREA_SIZE (256*KB) +#define CFE_BOOTAREA_ADDR 0x20000000 + + +/* ********************************************************************* + * Globals + ********************************************************************* */ + +extern arena_t cfe_arena; +uint64_t *cfe_pagetable = NULL; + +extern void CPUCFG_PAGETBLINIT(uint64_t *ptaddr,unsigned int ptstart); + +void cfe_bootarea_init(void); +extern void _setcontext(int64_t); + + +/* ********************************************************************* + * CFE_BOOTAREA_INIT() + * + * Initialize the page table and map our boot program area. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +void cfe_bootarea_init(void) +{ + unsigned char *pte; + int64_t pte_int; + unsigned int addr = 16*MEG; + unsigned int topmem; + unsigned int topcfe; + unsigned int botcfe; + unsigned int beforecfe; + unsigned int aftercfe; + + /* + * Calculate the location where the boot area will + * live. It lives either above or below the + * firmware, depending on where there's more space. + */ + + /* + * The firmware will always be loaded in the first + * 256M. Calculate the top of that region. The bottom + * of that region is always the beginning of our + * data segment. + */ + if (mem_totalsize > (uint64_t)256) { + topmem = 256*MEG; + } + else { + topmem = (unsigned int) (mem_totalsize << 20); + } + botcfe = (unsigned int) K1_TO_PHYS(mem_bottomofmem); + topcfe = (unsigned int) K1_TO_PHYS(mem_topofmem); + + beforecfe = botcfe; + aftercfe = topmem-topcfe; + + if (beforecfe > aftercfe) { + botcfe -= (PAGESIZE-1); + botcfe &= ~(PAGESIZE-1); /* round down to page boundary */ + addr = botcfe - CFE_BOOTAREA_SIZE; /* this is the address */ + } + else { + topcfe += (PAGESIZE-1); /* round *up* to a page address */ + topcfe &= ~(PAGESIZE-1); + addr = topcfe; + } + + mem_bootarea_start = addr; + mem_bootarea_size = CFE_BOOTAREA_SIZE; + + /* + * Allocate the page table + */ + + pte = KMALLOC(1024,1024); + +#ifdef __long64 + pte_int = (int64_t) pte; +#else + pte_int = (int64_t) ((int) pte); +#endif + + /* + * Set the CP0 CONTEXT register to point at the page table + */ + + pte_int <<= 13; + cfe_pagetable = (uint64_t *) pte; + + _setcontext(pte_int); + + + /* + * Initialize page table entries + */ + + CPUCFG_PAGETBLINIT(cfe_pagetable,addr); + + +} + diff --git a/cfe/cfe/arch/mips/common/src/tools.mk b/cfe/cfe/arch/mips/common/src/tools.mk new file mode 100755 index 0000000..d195de9 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/tools.mk @@ -0,0 +1,83 @@ +# +# Basic compiler options and preprocessor flags +# + +CFLAGS += -g -c -ffreestanding +CFLAGS += -O1 -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes + +# +# Tools locations +# + +ifndef TOOLS +TOOLS=/opt/toolchains/uclibc-crosstools-gcc-4.4.2-1/usr/bin/mips-linux- +endif + +GCC ?= $(TOOLS)gcc +GLD ?= $(TOOLS)ld +AR ?= $(TOOLS)ar +OBJDUMP ?= $(TOOLS)objdump +OBJCOPY ?= $(TOOLS)objcopy +RANLIB ?= $(TOOLS)ranlib + +# +# Check for 64-bit mode +# + +ifeq ($(strip ${CFG_MLONG64}),1) + CFLAGS += -mlong64 -D__long64 +endif + +# +# Figure out which linker script to use +# + +ifeq ($(strip ${CFG_RAMAPP}),1) + CFLAGS += -DCFG_RAMAPP=1 + LDFLAGS = -g --script ${ARCH_SRC}/cfe_ramapp.lds + CFLAGS += -DCFG_RUNFROMKSEG0=1 +else + ifeq ($(strip ${CFG_RELOC}),0) + ifeq ($(strip ${CFG_BOOTRAM}),1) + CFLAGS += -DCFG_BOOTRAM=1 + ROMRAM = ram + else + CFLAGS += -DCFG_BOOTRAM=0 + ROMRAM = rom + endif + ifeq ($(strip ${CFG_UNCACHED}),1) + CFLAGS += -DCFG_RUNFROMKSEG0=0 + LDFLAGS = -g --script ${ARCH_SRC}/cfe_${ROMRAM}_uncached.lds + else + CFLAGS += -DCFG_RUNFROMKSEG0=1 + LDFLAGS = -g --script ${ARCH_SRC}/cfe_${ROMRAM}_cached.lds + endif + else + CFLAGS += -membedded-pic -mlong-calls -DCFG_EMBEDDED_PIC=1 + ifeq ($(strip ${CFG_UNCACHED}),1) + CFLAGS += -DCFG_RUNFROMKSEG0=0 + LDFLAGS = -g --script ${ARCH_SRC}/cfe_rom_reloc_uncached.lds --embedded-relocs + else + CFLAGS += -DCFG_RUNFROMKSEG0=1 + ifeq ($(strip ${CFG_TEXTAT1MB}),1) + LDFLAGS = -g --script ${ARCH_SRC}/cfe_rom_reloc_cached_biendian.lds --embedded-relocs + else + LDFLAGS = -g --script ${ARCH_SRC}/cfe_rom_reloc_cached.lds --embedded-relocs + endif + endif + endif +endif +# +# Determine target endianness +# + +ifeq ($(strip ${CFG_LITTLE}),1) + ENDIAN = -EL + CFLAGS += -EL + LDFLAGS += -EL +else + ENDIAN = -EB + CFLAGS += -EB + LDFLAGS += -EB +endif + diff --git a/cfe/cfe/arch/mips/common/src/ui_memtest.c b/cfe/cfe/arch/mips/common/src/ui_memtest.c new file mode 100644 index 0000000..5388fd8 --- /dev/null +++ b/cfe/cfe/arch/mips/common/src/ui_memtest.c @@ -0,0 +1,282 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Test commands File: ui_memtest.c + * + * A simple memory test + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "sbmips.h" + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "lib_printf.h" + +#include "cfe_iocb.h" +#include "cfe_device.h" +#include "cfe_console.h" +#include "cfe_devfuncs.h" + +#include "cfe_error.h" + +#include "ui_command.h" +#include "cfe.h" + +#include "bsp_config.h" + +#include "cfe_mem.h" + + +#ifdef __long64 +static int ui_cmd_memorytest(ui_cmdline_t *cmd,int argc,char *argv[]); +#endif + +#ifndef _SB_MAKE64 +#define _SB_MAKE64(x) ((uint64_t)(x)) +#endif +#ifndef _SB_MAKEMASK +#define _SB_MAKEMASK(v,n) (_SB_MAKE64((_SB_MAKE64(1)<<(v))-1) << _SB_MAKE64(n)) +#endif +#ifndef _SB_MAKEMASK1 +#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n)) +#endif + + +int ui_init_memtestcmds(void); + +int ui_init_memtestcmds(void) +{ +#ifdef __long64 + cmd_addcmd("memorytest", + ui_cmd_memorytest, + NULL, + "Tests all available memory", + "", + "-loop;Loop forever or until keypress|" + "-stoponerror;Stop if error occurs while looping|" + "-cca=*;Use specified cacheability attribute|" + "-arena=*;Test only specified arena index"); +#endif + return 0; +} + + +#ifdef __long64 +/* extensive memory tests */ + +static void inline uacwrite(volatile long *srcadr,long *dstadr) +{ +__asm __volatile ("ld $8, 0(%0) ; " + "ld $9, 8(%0) ; " + "ld $10, 16(%0) ; " + "ld $11, 24(%0) ; " + "sync ; " + "sd $8, 0(%1) ; " + "sd $9, 8(%1) ; " + "sd $10, 16(%1) ; " + "sd $11, 24(%1) ; " + "sync" :: "r"(srcadr),"r"(dstadr) : "$8","$9","$10","$11"); +} + + +#define TEST_DATA_LEN 4 +#define CACHE_LINE_LEN 32 + +static int ui_cmd_memorytest(ui_cmdline_t *cmd,int argc,char *argv[]) +{ + + static volatile long test_data[TEST_DATA_LEN] = { + 0xaaaaaaaaaaaaaaaa, 0x5555555555555555, 0xcccccccccccccccc, 0x3333333333333333, /* one cache line */ + }; + int arena, exitLoop; + int error; + int arena_type; + uint64_t arena_start, arena_size; + long phys_addr, offset, mem_base, cache_mem_base, i; + long *dst_adr, *cache_dst_adr; + long cda,tda; + int forever; + int passcnt; + int stoponerr = 0; + int cca = K_CALG_UNCACHED_ACCEL; + int arenanum = -1; + char *x; + + arena = 0; + exitLoop = 0; + offset = 0; + mem_base = 0; + passcnt = 0; + error = 0; + + forever = cmd_sw_isset(cmd,"-loop"); + stoponerr = cmd_sw_isset(cmd,"-stoponerror"); + if (cmd_sw_value(cmd,"-cca",&x)) cca = atoi(x); + if (cmd_sw_value(cmd,"-arena",&x)) arenanum = atoi(x); + + printf("Available memory arenas:\n"); + while (cfe_arena_enum(arena, &arena_type, &arena_start, &arena_size, FALSE) == 0) { + phys_addr = (long) arena_start; /* actual physical address */ + mem_base = PHYS_TO_XKPHYS(cca, phys_addr); /* virtual address */ + xprintf("phys = %016llX, virt = %016llX, size = %016llX\n", phys_addr, mem_base, arena_size); + arena++; + } + + printf("\nTesting memory.\n"); + do { + + passcnt++; + if (forever) { + if (console_status()) break; + printf("***** Iteration %d *****\n",passcnt); + } + + arena = 0; + exitLoop = 0; + error = 0; + + while (cfe_arena_enum(arena, &arena_type, &arena_start, &arena_size, FALSE) == 0) { + + if ((arenanum >= 0) && (arena != arenanum)) { + arena++; + continue; + } + + test_data[0] = 0xAAAAAAAAAAAAAAAA; + test_data[1] = 0x5555555555555555; + test_data[2] = 0xCCCCCCCCCCCCCCCC; + test_data[3] = 0x3333333333333333; + + phys_addr = (long) arena_start; /* actual physical address */ + mem_base = PHYS_TO_XKPHYS(cca, phys_addr); /* virtual address */ + cache_mem_base = PHYS_TO_K0(phys_addr); + + xprintf("\n"); + xprintf("Testing: phys = %016llX, virt = %016llX, size = %016llX\n", phys_addr, mem_base, arena_size); + + xprintf("Writing: a/5/c/3\n"); + + for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { + dst_adr = (long*)(mem_base+offset); + uacwrite(test_data, dst_adr); + } + + xprintf("Reading: a/5/c/3\n"); + + for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { + dst_adr = (long*)(mem_base+offset); + cache_dst_adr = (long*)(mem_base+offset); + for (i = 0; i < TEST_DATA_LEN; i++) { + cda = cache_dst_adr[i]; + tda = test_data[i]; + if (cda != tda) { + xprintf("mem[%016llX] %016llX != %016llX\n", + mem_base+offset+(i*8), cda, tda); + exitLoop = 1; + } + } + if (exitLoop) break; + } + + + if (exitLoop) { + exitLoop = 0; + error++; + arena++; + continue; + } + + xprintf("Writing: address|5555/inv/aaaa|address\n"); + exitLoop = 0; + + for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { + dst_adr = (long*)(mem_base+offset); + test_data[0] = ((long)dst_adr<<32)|0x55555555; + test_data[1] = ~test_data[0]; + test_data[2] = 0xaaaaaaaa00000000|((long)dst_adr & 0xffffffff); + test_data[3] = ~test_data[2]; + uacwrite(test_data, dst_adr); + } + + xprintf("Reading: address|5555/inv/aaaa|address\n"); + + for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { + dst_adr = (long*)(mem_base+offset); + test_data[0] = ((long)dst_adr<<32)|0x55555555; + test_data[1] = ~test_data[0]; + test_data[2] = 0xaaaaaaaa00000000|((long)dst_adr & 0xffffffff); + test_data[3] = ~test_data[2]; + cache_dst_adr = (long*)(mem_base+offset); + for (i = 0; i < TEST_DATA_LEN; i++) { + cda = cache_dst_adr[i]; + tda = test_data[i]; + if (cda != tda) { + xprintf("mem[%016llX] %016llX != %016llX\n", + mem_base+offset+(i*8),cda,tda); + exitLoop = 1; + } + } + if (exitLoop) break; + } + + if (exitLoop) { + error++; + exitLoop = 0; + if (stoponerr) forever = 0; + } + + arena++; + } + } while (forever); + + if (error) printf("Failing address: %016llX\n",mem_base+offset); + + return error ? -1 : 0; +} + +#endif + + + + |