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