diff options
Diffstat (limited to 'cfe/cfe/arch/mips/common/include/mipsmacros.h')
-rwxr-xr-x | cfe/cfe/arch/mips/common/include/mipsmacros.h | 376 |
1 files changed, 376 insertions, 0 deletions
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 + */ |