1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * MIPS Macros File: mipsmacros.h
6 * Macros to deal with various mips-related things.
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
47 /* *********************************************************************
49 ********************************************************************* */
61 #define BPWSIZE 3 /* bits per word size */
62 #define _TBLIDX(x) ((x)*REGSIZE)
74 #define _TBLIDX(x) ((x)*REGSIZE)
78 /* *********************************************************************
79 * NORMAL_VECTOR(addr,vecname,vecdest)
80 * NORMAL_XVECTOR(addr,vecname,vecdest,code)
82 * Declare a trap or dispatch vector. There are two flavors,
83 * DECLARE_XVECTOR sets up an indentifying code in k0 before
84 * jumping to the dispatch routine.
87 * addr - vector address
88 * vecname - for label at that address
89 * vecdest - destination (place vector jumps to)
90 * code - code to place in k0 before jumping
94 ********************************************************************* */
97 #define NORMAL_VECTOR(addr,vecname,vecdest) \
100 vecname: b vecdest ; \
103 #define NORMAL_XVECTOR(addr,vecname,vecdest,code) \
106 vecname: b vecdest ; \
111 /* *********************************************************************
112 * Evil macros for bi-endian support.
114 * The magic here is in the instruction encoded as 0x10000014.
116 * This instruction in big-endian is: "b .+0x54"
117 * this instruction in little-endian is: "bne zero,zero,.+0x44"
119 * So, depending on what the system endianness is, it will either
120 * branch to .+0x54 or not branch at all.
122 * the instructions that follow are:
124 * 0x10000014 "magic branch" (either-endian)
125 * 0x00000000 nop (bds) (either-endian)
126 * 0xD0BF1A3C lui k0,0xBFD0 (little-endian)
127 * 0xxxxx5A27 addu k0,vector (little-endian)
128 * 0x08004003 jr k0 (little-endian)
129 * 0x00000000 nop (bds) (little-endian)
130 * ... space up to offset 0x54
131 * ......... b vecaddr (big-endian)
133 * The idea is that the big-endian firmware is first, from 0..1MB
134 * in the flash, and the little-endian firmware is second,
135 * from 1..2MB in the flash. The little-endian firmware is
136 * set to load at BFD00000, so that its initial routines will
137 * work until relocation is completed.
139 * the instructions at the vectors will either jump to the
140 * big-endian or little-endian code based on system endianness.
142 * The ROM is built by compiling CFE twice, first with
143 * CFG_BIENDIAN=1 and CFG_LITTLE=0 (big-endian) and again
144 * with CFG_BIENDIAN=1 and CFG_LITTLE=1. The resulting
145 * cfe.bin files are located at 0xBFC00000 and 0xBFD00000
146 * for big and little-endian versions, respectively.
148 * More information about how this works can be found in the
150 ********************************************************************* */
152 #define __SWAPW(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8))
154 #define BIENDIAN_VECTOR(addr,vecname,vecdest) \
157 vecname: .word 0x10000014 ; \
159 .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \
160 .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \
163 .org ((addr) + 0x54) ; \
167 #define BIENDIAN_XVECTOR(addr,vecname,vecdest,code) \
170 vecname: .word 0x10000014 ; \
172 .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \
173 .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \
176 .org ((addr) + 0x54) ; \
183 /* *********************************************************************
184 * Declare the right versions of DECLARE_VECTOR and
185 * DECLARE_XVECTOR depending on how we're building stuff.
186 * Generally, we only use the biendian version if we're building
187 * as CFG_BIENDIAN=1 and we're doing the big-endian MIPS version.
188 ********************************************************************* */
190 #if CFG_BIENDIAN && defined(__MIPSEB)
191 #define DECLARE_VECTOR BIENDIAN_VECTOR
192 #define DECLARE_XVECTOR BIENDIAN_XVECTOR
194 #define DECLARE_VECTOR NORMAL_VECTOR
195 #define DECLARE_XVECTOR NORMAL_XVECTOR
200 /* *********************************************************************
203 * Load the address of a label, but do it in a position-independent
207 * reg - register to load
208 * label - label whose address to load
212 ********************************************************************* */
215 #define LOADREL(reg,label) \
224 #define LOADREL(reg,label) \
238 /* *********************************************************************
241 * Jump relative to the current PC.
244 * reg - contains linked address to fix up
248 ********************************************************************* */
251 #define JUMPREL1(reg) \
254 #define JUMPREL(reg) \
257 #define __JUMPREL(reg) \
266 #define JUMPREL1(reg) \
270 #define JUMPREL(reg) \
275 /* *********************************************************************
276 * CALLINIT_KSEG1(label,table,offset)
277 * CALLINIT_KSEG0(label,table,offset)
279 * Call an initialization routine (usually in another module).
280 * If initialization routine lives in KSEG1 it may need
281 * special fixing if using the cached version of CFE (this is
282 * the default case). CFE is linked at a KSEG0 address.
284 * Embedded PIC is especially tricky, since the "la"
285 * instruction expands to calculations involving GP.
286 * In that case, use our table of offsets to
287 * load the routine address from a table in memory.
290 * label - routine to call if we can call directly
291 * table - symbol name of table containing routine addresses
292 * offset - offset within the above table
296 ********************************************************************* */
299 #define CALLINIT_KSEG0(table,tableoffset) \
300 LOADREL(k1,table) ; \
301 LR k1,tableoffset(k1) ; \
304 /* Cached PIC code - call indirect through table */
305 #define CALLINIT_KSEG1(table,tableoffset) \
306 LOADREL(k1,table) ; \
308 LR k1,tableoffset(k1) ; \
311 /* Uncached PIC code - call indirect through table, always same KSEG */
312 #define CALLINIT_KSEG1 CALLINIT_KSEG0
316 * CALLINIT_RELOC is used once CFE's relocation is complete and
317 * the "mem_textreloc" variable is set up. (yes, this is nasty.)
318 * If 'gp' is set, we can presume that we've relocated
319 * and it's safe to read "mem_textreloc", otherwise use the
320 * address as-is from the table.
324 #define CALLINIT_RELOC(table,tableoffset) \
325 LOADREL(k1,table) ; \
326 LR k1,tableoffset(k1) ; \
328 LR k0,mem_textreloc ; \
332 #define CALLINIT_RELOC CALLINIT_KSEG0
337 /* *********************************************************************
338 * SPIN_LOCK(lock,reg1,reg2)
340 * Acquire a spin lock.
343 * lock - symbol (address) of lock to acquire
344 * reg1,reg2 - registers we can use to acquire lock
347 * nothing (lock acquired)
348 ********************************************************************* */
350 #define SPIN_LOCK(lock,reg1,reg2) \
360 /* *********************************************************************
361 * SPIN_UNLOCK(lock,reg1)
363 * Release a spin lock.
366 * lock - symbol (address) of lock to release
367 * reg1 - a register we can use
370 * nothing (lock released)
371 ********************************************************************* */
374 #define SPIN_UNLOCK(lock,reg1) \
379 /* *********************************************************************
380 * SETCCAMODE(treg,mode)
382 * Set cacheability mode. For some of the pass1 workarounds we
383 * do this alot, so here's a handy macro.
386 * treg - temporary register we can use
387 * mode - new mode (K_CFG_K0COH_xxx)
391 ********************************************************************* */
393 #define SETCCAMODE(treg,mode) \
394 mfc0 treg,C0_CONFIG ; \
397 or treg,treg,mode ; \
398 mtc0 treg,C0_CONFIG ; \
402 /* *********************************************************************
404 ********************************************************************* */
406 #define DECLARE_LONG(x) \