1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * MIPS Macros File: mipsmacros.h 5 * 6 * Macros to deal with various mips-related things. 7 * 8 * Author: Mitch Lichtenberg (mpl@broadcom.com) 9 * 10 ********************************************************************* 11 * 12 * Copyright 2000,2001,2002,2003 13 * Broadcom Corporation. All rights reserved. 14 * 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. 21 * 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. 25 * 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. 31 * 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 ********************************************************************* */ 46 47/* ********************************************************************* 48 * 32/64-bit macros 49 ********************************************************************* */ 50 51#ifdef __long64 52#define _VECT_ .dword 53#define _LONG_ .dword 54#define SR sd 55#define LR ld 56#define ADD dadd 57#define SUB dsub 58#define MFC0 dmfc0 59#define MTC0 dmtc0 60#define REGSIZE 8 61#define BPWSIZE 3 /* bits per word size */ 62#define _TBLIDX(x) ((x)*REGSIZE) 63#else 64#define _VECT_ .word 65#define _LONG_ .word 66#define SR sw 67#define LR lw 68#define ADD add 69#define SUB sub 70#define MFC0 mfc0 71#define MTC0 mtc0 72#define REGSIZE 4 73#define BPWSIZE 2 74#define _TBLIDX(x) ((x)*REGSIZE) 75#endif 76 77 78/* ********************************************************************* 79 * NORMAL_VECTOR(addr,vecname,vecdest) 80 * NORMAL_XVECTOR(addr,vecname,vecdest,code) 81 * 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. 85 * 86 * Input parameters: 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 91 * 92 * Return value: 93 * nothing 94 ********************************************************************* */ 95 96 97#define NORMAL_VECTOR(addr,vecname,vecdest) \ 98 .globl vecname ; \ 99 .org addr ; \ 100vecname: b vecdest ; \ 101 nop; 102 103#define NORMAL_XVECTOR(addr,vecname,vecdest,code) \ 104 .globl vecname ; \ 105 .org addr ; \ 106vecname: b vecdest ; \ 107 li k0,code ; \ 108 nop; 109 110 111/* ********************************************************************* 112 * Evil macros for bi-endian support. 113 * 114 * The magic here is in the instruction encoded as 0x10000014. 115 * 116 * This instruction in big-endian is: "b .+0x54" 117 * this instruction in little-endian is: "bne zero,zero,.+0x44" 118 * 119 * So, depending on what the system endianness is, it will either 120 * branch to .+0x54 or not branch at all. 121 * 122 * the instructions that follow are: 123 * 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) 132 * 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. 138 * 139 * the instructions at the vectors will either jump to the 140 * big-endian or little-endian code based on system endianness. 141 * 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. 147 * 148 * More information about how this works can be found in the 149 * CFE Manual. 150 ********************************************************************* */ 151 152#define __SWAPW(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8)) 153 154#define BIENDIAN_VECTOR(addr,vecname,vecdest) \ 155 .globl vecname ; \ 156 .org addr ; \ 157vecname: .word 0x10000014 ; \ 158 .word 0 ; \ 159 .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \ 160 .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \ 161 .word 0x08004003 ; \ 162 .word 0 ; \ 163 .org ((addr) + 0x54) ; \ 164 b vecdest ; \ 165 nop; 166 167#define BIENDIAN_XVECTOR(addr,vecname,vecdest,code) \ 168 .globl vecname ; \ 169 .org addr ; \ 170vecname: .word 0x10000014 ; \ 171 .word 0 ; \ 172 .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \ 173 .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \ 174 .word 0x08004003 ; \ 175 .word 0 ; \ 176 .org ((addr) + 0x54) ; \ 177 b vecdest ; \ 178 li k0,code ; \ 179 nop; 180 181 182 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 ********************************************************************* */ 189 190#if CFG_BIENDIAN && defined(__MIPSEB) 191#define DECLARE_VECTOR BIENDIAN_VECTOR 192#define DECLARE_XVECTOR BIENDIAN_XVECTOR 193#else 194#define DECLARE_VECTOR NORMAL_VECTOR 195#define DECLARE_XVECTOR NORMAL_XVECTOR 196#endif 197 198 199 200/* ********************************************************************* 201 * LOADREL(reg,label) 202 * 203 * Load the address of a label, but do it in a position-independent 204 * way. 205 * 206 * Input parameters: 207 * reg - register to load 208 * label - label whose address to load 209 * 210 * Return value: 211 * ra is trashed! 212 ********************************************************************* */ 213 214#if CFG_EMBEDDED_PIC 215#define LOADREL(reg,label) \ 216 .set noreorder ; \ 217 bal 1f ; \ 218 nop ; \ 2191: nop ; \ 220 .set reorder ; \ 221 la reg,label-1b ; \ 222 addu reg,ra 223#else 224#define LOADREL(reg,label) \ 225 .set noreorder ; \ 226 bal 1f ; \ 227 nop ; \ 2281: nop ; \ 229 .set reorder ; \ 230 la reg,1b ; \ 231 subu ra,reg ; \ 232 la reg,label ; \ 233 addu reg,ra ; 234#endif 235 236 237 238/* ********************************************************************* 239 * JUMPREL(reg) 240 * 241 * Jump relative to the current PC. 242 * 243 * Input parameters: 244 * reg - contains linked address to fix up 245 * 246 * Return value: 247 * ra is trashed! 248 ********************************************************************* */ 249 250#if CFG_EMBEDDED_PIC 251#define JUMPREL1(reg) \ 252 or reg,K1BASE ; \ 253 jalr reg 254#define JUMPREL(reg) \ 255 jalr reg 256#else 257#define __JUMPREL(reg) \ 258 .set noreorder ; \ 259 bal 1f ; \ 260 nop ; \ 2611: nop ; \ 262 addu ra,reg ; \ 263 la reg,1b ; \ 264 subu reg,ra,reg ; \ 265 .set reorder 266#define JUMPREL1(reg) \ 267 __JUMPREL(reg) ; \ 268 or reg,K1BASE ; \ 269 jalr reg 270#define JUMPREL(reg) \ 271 __JUMPREL(reg) ; \ 272 jalr reg 273#endif 274 275/* ********************************************************************* 276 * CALLINIT_KSEG1(label,table,offset) 277 * CALLINIT_KSEG0(label,table,offset) 278 * 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. 283 * 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. 288 * 289 * Input parameters: 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 293 * 294 * Return value: 295 * k1,ra is trashed. 296 ********************************************************************* */ 297 298 299#define CALLINIT_KSEG0(table,tableoffset) \ 300 LOADREL(k1,table) ; \ 301 LR k1,tableoffset(k1) ; \ 302 JUMPREL(k1) 303#if CFG_RUNFROMKSEG0 304/* Cached PIC code - call indirect through table */ 305#define CALLINIT_KSEG1(table,tableoffset) \ 306 LOADREL(k1,table) ; \ 307 or k1,K1BASE ; \ 308 LR k1,tableoffset(k1) ; \ 309 JUMPREL1(k1) 310#else 311/* Uncached PIC code - call indirect through table, always same KSEG */ 312#define CALLINIT_KSEG1 CALLINIT_KSEG0 313#endif 314 315/* 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. 321 */ 322 323#if CFG_EMBEDDED_PIC 324#define CALLINIT_RELOC(table,tableoffset) \ 325 LOADREL(k1,table) ; \ 326 LR k1,tableoffset(k1) ; \ 327 beq gp,zero,123f ; \ 328 LR k0,mem_textreloc ; \ 329 ADD k1,k1,k0 ; \ 330123: jal k1 331#else 332#define CALLINIT_RELOC CALLINIT_KSEG0 333#endif 334 335 336 337/* ********************************************************************* 338 * SPIN_LOCK(lock,reg1,reg2) 339 * 340 * Acquire a spin lock. 341 * 342 * Input parameters: 343 * lock - symbol (address) of lock to acquire 344 * reg1,reg2 - registers we can use to acquire lock 345 * 346 * Return value: 347 * nothing (lock acquired) 348 ********************************************************************* */ 349 350#define SPIN_LOCK(lock,reg1,reg2) \ 351 la reg1,lock ; \ 3521: sync ; \ 353 ll reg2,0(reg1) ; \ 354 bne reg2,zero,1b ; \ 355 li reg2,1 ; \ 356 sc reg2,0(reg1) ; \ 357 beq reg2,zero,1b ; \ 358 nop 359 360/* ********************************************************************* 361 * SPIN_UNLOCK(lock,reg1) 362 * 363 * Release a spin lock. 364 * 365 * Input parameters: 366 * lock - symbol (address) of lock to release 367 * reg1 - a register we can use 368 * 369 * Return value: 370 * nothing (lock released) 371 ********************************************************************* */ 372 373 374#define SPIN_UNLOCK(lock,reg1) \ 375 la reg1,lock ; \ 376 sw zero,0(reg1) 377 378 379/* ********************************************************************* 380 * SETCCAMODE(treg,mode) 381 * 382 * Set cacheability mode. For some of the pass1 workarounds we 383 * do this alot, so here's a handy macro. 384 * 385 * Input parameters: 386 * treg - temporary register we can use 387 * mode - new mode (K_CFG_K0COH_xxx) 388 * 389 * Return value: 390 * nothing 391 ********************************************************************* */ 392 393#define SETCCAMODE(treg,mode) \ 394 mfc0 treg,C0_CONFIG ; \ 395 srl treg,treg,3 ; \ 396 sll treg,treg,3 ; \ 397 or treg,treg,mode ; \ 398 mtc0 treg,C0_CONFIG ; \ 399 HAZARD 400 401 402/* ********************************************************************* 403 * Declare variables 404 ********************************************************************* */ 405 406#define DECLARE_LONG(x) \ 407 .global x ; \ 408x: _LONG_ 0 409 410 411 412 413/* 414 * end 415 */ 416