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 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#ifndef _MIPSMACROS_H 48#define _MIPSMACROS_H 49 50/* ********************************************************************* 51 * 32/64-bit macros 52 ********************************************************************* */ 53 54#if ((CPUCFG_REGS32+CPUCFG_REGS64) != 1) 55#error "You must define exactly ONE of CPUCFG_REGS32,CPUCFG_REGS64 in cpu_config.h" 56#endif 57 58#if ((CFG_RELOC) && defined(__long64)) 59#error "Relocation is not compatible with 64-bit pointer types" 60#endif 61 62/* 63 * These macros are used when we know we're dealing with 64-bit 64 * pointers. Normally CFE is a 32-bit app, but there are a few 65 * cases where we explicitly deal with pointers that are greater 66 * than the word size, like the dump/examine commands, the flashop 67 * engine, etc. 68 */ 69 70/* 71 * CPUCFG_REGS64 tells us that our architecture has 64-bit 72 * registers. We define macros that expand to 64-bit ops 73 * regardless of the setting of __long64. 74 * 75 * These macros are used in cases where we really care whether 76 * the registers are 64 bits wide or not. Places like exception 77 * handlers and other code that needs to see the entire register 78 * even though we're in a 32-bit app. 79 * 80 * One special case is when we're dealing with 64-bit pointers. We 81 * need 64-bit ALU ops to add/subtract these even if they are 82 * pointing at 32-bit data. 83 */ 84#if CPUCFG_REGS64 85#define ADDPTR daddu 86#define SUBPTR dsubu 87#define LDPTR ld 88#define STPTR sd 89#define LREG ld 90#define SREG sd 91#define MFC0 dmfc0 92#define MTC0 dmtc0 93#define SRL dsrl 94#define SLL dsll 95#else 96#define ADDPTR addu 97#define SUBPTR subu 98#define LDPTR lw 99#define STPTR sw 100#define LREG lw 101#define SREG sw 102#define MFC0 mfc0 103#define MTC0 mtc0 104#define SRL srl 105#define SLL sll 106#endif 107 108#ifdef __long64 109/* 110 * CFE is normally a 32-bit application. It's still possible to build 111 * a 64-bit version, but only for non-relocating cases. 112 * 113 * These macros are used to make the size of a pointer transparent (mostly). 114 * So, when you load/store something on the stack, we use the right instruction 115 * to save either 32 bits or all 64 bits. Since CFE is mostly 32-bit nowadays, 116 * these macros will mostly be the 32-bit variants. 117 */ 118#define _VECT_ .dword 119#define _LONG_ .dword 120#define SR sd 121#define LR ld 122#define LA dla 123#define ADD dadd 124#define SUB dsub 125#define REGSIZE 8 126#define BPWSIZE 3 /* bits per word size */ 127#define _TBLIDX(x) ((x)*REGSIZE) 128#else 129#define _VECT_ .word 130#define _LONG_ .word 131#define SR sw 132#define LR lw 133#define LA la 134#define ADD add 135#define SUB sub 136#define REGSIZE 4 137#define BPWSIZE 2 138#define _TBLIDX(x) ((x)*REGSIZE) 139#endif 140 141 142/* ********************************************************************* 143 * NORMAL_VECTOR(addr,vecname,vecdest) 144 * NORMAL_XVECTOR(addr,vecname,vecdest,code) 145 * 146 * Declare a trap or dispatch vector. There are two flavors, 147 * DECLARE_XVECTOR sets up an indentifying code in k0 before 148 * jumping to the dispatch routine. 149 * 150 * Input parameters: 151 * addr - vector address 152 * vecname - for label at that address 153 * vecdest - destination (place vector jumps to) 154 * code - code to place in k0 before jumping 155 * 156 * Return value: 157 * nothing 158 ********************************************************************* */ 159 160 161#define NORMAL_VECTOR(addr,vecname,vecdest) \ 162 .globl vecname ; \ 163 .org addr ; \ 164vecname: b vecdest ; \ 165 nop; 166 167#define NORMAL_XVECTOR(addr,vecname,vecdest,code) \ 168 .globl vecname ; \ 169 .org addr ; \ 170vecname: b vecdest ; \ 171 li k0,code ; \ 172 nop; 173 174 175/* ********************************************************************* 176 * Evil macros for bi-endian support. 177 * 178 * The magic here is in the instruction encoded as 0x10000014. 179 * 180 * This instruction in big-endian is: "b .+0x54" 181 * this instruction in little-endian is: "bne zero,zero,.+0x44" 182 * 183 * So, depending on what the system endianness is, it will either 184 * branch to .+0x54 or not branch at all. 185 * 186 * the instructions that follow are: 187 * 188 * 0x10000014 "magic branch" (either-endian) 189 * 0x00000000 nop (bds) (either-endian) 190 * 0xD0BF1A3C lui k0,0xBFD0 (little-endian) 191 * 0xxxxx5A27 addu k0,vector (little-endian) 192 * 0x08004003 jr k0 (little-endian) 193 * 0x00000000 nop (bds) (little-endian) 194 * ... space up to offset 0x54 195 * ......... b vecaddr (big-endian) 196 * 197 * The idea is that the big-endian firmware is first, from 0..1MB 198 * in the flash, and the little-endian firmware is second, 199 * from 1..2MB in the flash. The little-endian firmware is 200 * set to load at BFD00000, so that its initial routines will 201 * work until relocation is completed. 202 * 203 * the instructions at the vectors will either jump to the 204 * big-endian or little-endian code based on system endianness. 205 * 206 * The ROM is built by compiling CFE twice, first with 207 * CFG_BIENDIAN=1 and CFG_LITTLE=0 (big-endian) and again 208 * with CFG_BIENDIAN=1 and CFG_LITTLE=1. The resulting 209 * cfe.bin files are located at 0xBFC00000 and 0xBFD00000 210 * for big and little-endian versions, respectively. 211 * 212 * More information about how this works can be found in the 213 * CFE Manual. 214 ********************************************************************* */ 215 216#define __SWAPW(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8)) 217 218#define BIENDIAN_VECTOR(addr,vecname,vecdest) \ 219 .globl vecname ; \ 220 .org addr ; \ 221vecname: .word 0x10000014 ; \ 222 .word 0 ; \ 223 .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \ 224 .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \ 225 .word 0x08004003 ; \ 226 .word 0 ; \ 227 .org ((addr) + 0x54) ; \ 228 b vecdest ; \ 229 nop; 230 231#define BIENDIAN_XVECTOR(addr,vecname,vecdest,code) \ 232 .globl vecname ; \ 233 .org addr ; \ 234vecname: .word 0x10000014 ; \ 235 .word 0 ; \ 236 .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \ 237 .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \ 238 .word 0x08004003 ; \ 239 .word 0 ; \ 240 .org ((addr) + 0x54) ; \ 241 b vecdest ; \ 242 li k0,code ; \ 243 nop; 244 245 246 247/* ********************************************************************* 248 * Declare the right versions of DECLARE_VECTOR and 249 * DECLARE_XVECTOR depending on how we're building stuff. 250 * Generally, we only use the biendian version if we're building 251 * as CFG_BIENDIAN=1 and we're doing the big-endian MIPS version. 252 ********************************************************************* */ 253 254#if (CFG_BIENDIAN) && defined(__MIPSEB) 255#define DECLARE_VECTOR BIENDIAN_VECTOR 256#define DECLARE_XVECTOR BIENDIAN_XVECTOR 257#else 258#define DECLARE_VECTOR NORMAL_VECTOR 259#define DECLARE_XVECTOR NORMAL_XVECTOR 260#endif 261 262 263 264/* ********************************************************************* 265 * LDADDR(reg,label) 266 * 267 * Load the address of a symbol via the GOT. We use this in 268 * relocated (SVR4 PIC) mode, when we aren't sure that gp is loaded 269 * correctly or not. We get our GP value from low memory 270 * (assume it's set up), make the reference, and restore GP to 271 * its old value. Note: this macro uses the k0 register. 272 * 273 * Input parameters: 274 * reg - register to load 275 * label - address (symbol) to load into register 276 ********************************************************************* */ 277 278#if CFG_RELOC 279#define LDADDR(reg,label) \ 280 move k0,gp ; \ 281 li gp,PHYS_TO_K1(CFE_LOCORE_GLOBAL_GP) ; \ 282 LR gp,0(gp) ; \ 283 la reg,label ; \ 284 move gp,k0 285#else 286#define LDADDR(reg,label) \ 287 LA reg,label 288#endif 289 290 291 292/* ********************************************************************* 293 * Subroutine Linkage Macros 294 * 295 * We deal with the differences between non-PIC and SVR4 PIC here. 296 * 297 * The JAL_KSEG1 macro variant makes sure the target address 298 * is in KSEG1 for calling routines while running uncached, 299 * even if the target address was linked to a cached 300 * address (typical for init code). 301 ********************************************************************* */ 302 303 304/* 305 * Subroutine linkage varies among the relocation methods 306 * we support. In particular, SVR4 PIC will not allow 307 * a direct branch or call to an external routine, so 308 * we have these macros here for generating code that 309 * the linker will be happy with. Note that 310 * 'k1' is used in the SVR4 PIC case. 311 */ 312 313#if (CFG_RELOC) 314#define JMP(x) la t9,x ; j t9 /* use PIC linkage */ 315#define JAL(x) la t9,x ; jalr t9 316#else 317#define JMP(x) j x /* Standard JAL ok */ 318#define JAL(x) jal x 319#endif 320 321#define JAL_KSEG1(x) LA t9,x ; or t9,K1BASE ; jalr t9 322 323 324/* ********************************************************************* 325 * SPIN_LOCK(lock,reg1,reg2) 326 * 327 * Acquire a spin lock. 328 * 329 * Input parameters: 330 * lock - symbol (address) of lock to acquire 331 * reg1,reg2 - registers we can use to acquire lock 332 * 333 * Return value: 334 * nothing (lock acquired) 335 ********************************************************************* */ 336 337#define SPIN_LOCK(lock,reg1,reg2) \ 338 LA reg1,lock ; \ 3391: ll reg2,0(reg1) ; \ 340 bne reg2,zero,1b ; \ 341 li reg2,1 ; \ 342 sc reg2,0(reg1) ; \ 343 beq reg2,zero,1b ; \ 344 nop 345 346/* ********************************************************************* 347 * SPIN_UNLOCK(lock,reg1) 348 * 349 * Release a spin lock. 350 * 351 * Input parameters: 352 * lock - symbol (address) of lock to release 353 * reg1 - a register we can use 354 * 355 * Return value: 356 * nothing (lock released) 357 ********************************************************************* */ 358 359 360#define SPIN_UNLOCK(lock,reg1) \ 361 LA reg1,lock ; \ 362 sw zero,0(reg1) 363 364 365/* ********************************************************************* 366 * SETCCAMODE(treg,mode) 367 * 368 * Set cacheability mode. For some of the pass1 workarounds we 369 * do this alot, so here's a handy macro. 370 * 371 * Input parameters: 372 * treg - temporary register we can use 373 * mode - new mode (K_CFG_K0COH_xxx) 374 * 375 * Return value: 376 * nothing 377 ********************************************************************* */ 378 379#define SETCCAMODE(treg,mode) \ 380 mfc0 treg,C0_CONFIG ; \ 381 srl treg,treg,3 ; \ 382 sll treg,treg,3 ; \ 383 or treg,treg,mode ; \ 384 mtc0 treg,C0_CONFIG ; \ 385 HAZARD 386 387 388/* ********************************************************************* 389 * Declare variables 390 ********************************************************************* */ 391 392#define DECLARE_LONG(x) \ 393 .global x ; \ 394x: _LONG_ 0 395 396 397 398 399/* 400 * end 401 */ 402 403#endif 404 405