RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / arch / mips / common / src / init_mips.S
blob94e3d66ef7e078b5ceed3ef144eb359be5041d3d
1 /*  *********************************************************************
2     *  Broadcom Common Firmware Environment (CFE)
3     *
4     *  CPU init module                          File: init_mips.S
5     *
6     *  This module contains the vectors and lowest-level CPU startup
7     *  functions for CFE.
8     *
9     *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
10     *
11     *********************************************************************
12     *
13     *  Copyright 2000,2001,2002,2003
14     *  Broadcom Corporation. All rights reserved.
15     *
16     *  This software is furnished under license and may be used and
17     *  copied only in accordance with the following terms and
18     *  conditions.  Subject to these conditions, you may download,
19     *  copy, install, use, modify and distribute modified or unmodified
20     *  copies of this software in source and/or binary form.  No title
21     *  or ownership is transferred hereby.
22     *
23     *  1) Any source code used, modified or distributed must reproduce
24     *     and retain this copyright notice and list of conditions
25     *     as they appear in the source file.
26     *
27     *  2) No right is granted to use any trade name, trademark, or
28     *     logo of Broadcom Corporation.  The "Broadcom Corporation"
29     *     name may not be used to endorse or promote products derived
30     *     from this software without the prior written permission of
31     *     Broadcom Corporation.
32     *
33     *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34     *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35     *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36     *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37     *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38     *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39     *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40     *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41     *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42     *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43     *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44     *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45     *     THE POSSIBILITY OF SUCH DAMAGE.
46     ********************************************************************* */
49 #include "sbmips.h"
50 #include "exception.h"
52 #include "bsp_config.h"
53 #include "cpu_config.h"
55 #ifdef _CFE_
56 #include "cfe_devfuncs.h"
57 #else
59 #if CFG_BIENDIAN && defined(__MIPSEB)
60 #define CFE_EPTSEAL_REV 0x31454643
61 #endif
62 #define CFE_EPTSEAL 0x43464531
64 #define cfe_command_restart 0
65 #endif
67 #if CFG_VAPI                /* haul in SB1250-specfic stuff only for VAPI */
68 #include "sb1250_defs.h"
69 #include "sb1250_regs.h"
70 #include "sb1250_scd.h"
71 #endif
73 /*  *********************************************************************
74     *  Macros
75     ********************************************************************* */
77 #include "mipsmacros.h"
80 /*  *********************************************************************
81     *  SETLEDS(a,b,c,d)
82     *  SETLEDS1(a,b,c,d)
83     *
84     *  Sets the on-board LED display (if present).  Two variants
85     *  of this routine are provided.  If you're running KSEG1,
86     *  call the SETLEDS1 variant, else call SETLEDS.
87     *
88     *  Input parameters:
89     *      a,b,c,d - four ASCII characters (literal constants)
90     *
91     *  Return value:
92     *      a0,k1,ra trashed
93     ********************************************************************* */
95 #define SETLEDS(a,b,c,d)                     \
96         li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
97         CALLINIT_KSEG0(init_table,R_INIT_SETLEDS)
99 #define SETLEDS1(a,b,c,d)                     \
100         li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
101         CALLINIT_KSEG1(init_table,R_INIT_SETLEDS)
103 /*  *********************************************************************
104     *  Other constants
105     ********************************************************************* */
108  * This is the size of the stack, rounded to KByte boundaries.
109  */
111 #ifndef CFG_STACK_SIZE
112 #error "CFG_STACK_SIZE not defined"
113 #else
114 #define STACK_SIZE      ((CFG_STACK_SIZE+1023) & ~1023)
115 #endif
117 #ifdef __MIPSEB
118 #define TEXTSECTION     0x2e746578              # ".tex", big-endian
119 #else
120 #define TEXTSECTION     0x7865742e              # ".tex", little-endian
121 #endif
124  * Duplicates from cfe_iocb.h -- warning!
125  */
127 #define CFE_CACHE_FLUSH_D       1
128 #define CFE_CACHE_INVAL_I       2
129 #define CFE_CACHE_INVAL_D       4
130 #define CFE_CACHE_INVAL_L2      8
131 #define CFE_CACHE_FLUSH_L2      16
132 #define CFE_CACHE_INVAL_RANGE   32
133 #define CFE_CACHE_FLUSH_RANGE   64
137  * To make life easier reading this code, define "KSEGBASE"
138  * to either K0BASE or K1BASE depending on whether we're running
139  * uncached.
140  */
142 #if CFG_RUNFROMKSEG0
143 #define KSEGBASE        K0BASE
144 #else
145 #define KSEGBASE        K1BASE
146 #endif
149 /*  *********************************************************************
150     *  Names of registers used in this module
151     ********************************************************************* */
153 #define RELOCOFFSET     s8                      /* $30 (fp) */
154 #define TEXTOFFSET      t9                      /* $25 (t9) */
155 #define MEMTOP          t8                      /* $24 (t8) */
156 #define TEXTBASE        s7                      /* $23 (s7) */
158                 .sdata
160 #include "initdata.h"           /* declare variables we use here */
162 #if CFG_MULTI_CPUS
163                 .globl  cfe_spinlock
164 cfe_spinlock:   .word   0
165 #endif
167                 .extern _ftext
168                 .extern _etext
169                 .extern _fdata
170                 .extern _edata
171                 .extern _fbss
172                 .extern _end
174 /*  *********************************************************************
175     *  uninitialized data
176     ********************************************************************* */
178                 .bss
180                 .comm   __junk,4
182 /*  *********************************************************************
183     *  Exception Vectors
184     ********************************************************************* */
186                 .text
188                 .set noreorder
191  * If we're building a bi-endian version, this is the base
192  * address that we can expect to find the little-endian version
193  * of the firmware.
195  * Warning: If you change this, you must also change
196  * the linker script (arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds)
197  * and the mkflashimage program (hosttools/mkflashimage.c)
198  */
200 #define BIENDIAN_LE_BASE        0xBFD00000
203  * Declare the actual vectors.  This expands to code that
204  * must be at the very beginning of the text segment.
205  */
207 DECLARE_VECTOR(0x0000,vec_reset,cpu_reset)
208 DECLARE_VECTOR(0x0200,vec_tlbfill,cpu_tlbfill)
209 DECLARE_XVECTOR(0x0280,vec_xtlbfill,cpu_xtlbfill,XTYPE_XTLBFILL)
210 DECLARE_VECTOR(0x0300,vec_cacheerr,cpu_cacheerr)
211 DECLARE_XVECTOR(0x0380,vec_exception,cpu_exception,XTYPE_EXCEPTION)
212 DECLARE_XVECTOR(0x0400,vec_interrupt,cpu_interrupt,XTYPE_INTERRUPT)
213 DECLARE_XVECTOR(0x0480,vec_ejtag,cpu_ejtag,XTYPE_EJTAG)
217  * New location of CFE seal.  Will eventually phase out the seal at
218  * offset 0x508
219  */
220                 .org    0x4E0
221 cfe_seal:       .word   CFE_EPTSEAL
222                 .word   CFE_EPTSEAL
224 #if CFG_BIENDIAN && defined(__MIPSEB)
225                 .org    0x4E8
226 cfe_seal_rev:   .word   CFE_EPTSEAL_REV
227                 .word   CFE_EPTSEAL_REV
228 #endif
230                 .set reorder
232 /*  *********************************************************************
233     *  CFE Entry Point (used by OS boot loaders and such)
234     ********************************************************************* */
236                 .set  noreorder
238 DECLARE_VECTOR(0x0500,vec_apientry,cpu_apientry)
239 #if !CFG_BIENDIAN
240                 .org    0x508
241                 .word   CFE_EPTSEAL
242                 .word   CFE_EPTSEAL
243 #endif
245 /*  *********************************************************************
246     *  Verification APIs (if present)   [SB1250-specific]
247     ********************************************************************* */
249 #if CFG_VAPI
250 #if CFG_EMBEDDED_PIC
251 #error "CFG_VAPI is not compatible with relocatable code"
252 #endif
253 #include "vapi.h"
255  * Vector should be 16 bytes long
256  */
257 #define VAPI_VECTOR(l,x) \
258                 .extern x ; \
259                 .org (l & 0xFFFF) ; \
260                 j       x ; \
261                 nop ;  \
262                 .word   VAPI_EPTSEAL ; \
263                 .word   VAPI_EPTSEAL
265 VAPI_VECTOR(VAPI_FUNC_EXIT,vapi_exit)
266 VAPI_VECTOR(VAPI_FUNC_DUMPGPRS,vapi_dumpgprs)
267 VAPI_VECTOR(VAPI_FUNC_SETLOG,vapi_setlog)
268 VAPI_VECTOR(VAPI_FUNC_LOGVALUE,vapi_logsingle)
269 VAPI_VECTOR(VAPI_FUNC_LOGDATA,vapi_logdata)
270 VAPI_VECTOR(VAPI_FUNC_LOGTRACE,vapi_logtrace)
271 VAPI_VECTOR(VAPI_FUNC_LOGSOC,vapi_savesoc)
272 VAPI_VECTOR(VAPI_FUNC_LOGGPRS,vapi_loggprs)
273 VAPI_VECTOR(VAPI_FUNC_DUMPSTRING,vapi_puts)
274 VAPI_VECTOR(VAPI_FUNC_SETLEDS,vapi_setleds)
275 VAPI_VECTOR(VAPI_FUNC_LOGFPRS,vapi_logfprs)
276 #endif
279                 .set   reorder
281 /*  *********************************************************************
282     *  Some offsets depend on our current configuration
283     ********************************************************************* */
285 #if CFG_EMBEDDED_PIC
286 #define RUNTIME_RELOC_START     __runtime_reloc_start
287 #define RUNTIME_RELOC_STOP      __runtime_reloc_stop
288 #else
289 #define RUNTIME_RELOC_START     0
290 #define RUNTIME_RELOC_STOP      0
291 #endif
294 /*  *********************************************************************
295     *  Segment Table.
296     *
297     *  Addresses of data segments and of certain routines we're going
298     *  to call from KSEG1.  These are here mostly for the embedded
299     *  PIC case, since we can't count on the 'la' instruction to
300     *  do the expected thing (the assembler expands it into a macro
301     *  for doing GP-relative stuff, and the code is NOT GP-relative.
302     *  So, we (relocatably) get the offset of this table and then
303     *  index within it.
304     *
305     *  Pointer values in this segment will be relative to KSEG0 for
306     *  cached versions of CFE, so we need to OR in K1BASE in the
307     *  case of calling to a uncached address.
308     *
309     *  The LOADREL macro handles most of the nastiness here.
310     ********************************************************************* */
313 #include "segtable.h"
315 #if CFG_VAPI
316                 .org    0x600                   # move past exception vectors
317 #else
318                 .org    0x580                   # move past exception vectors
319 #endif
321 #if CFG_EMBEDDED_NVRAM
322                 .org    0x1000
323                 .globl  embedded_nvram
324 embedded_nvram: .fill   0x400,4,~(0x48534c46)
325         .long   0x4c5a4d41              # LZMA NVRAM Supported
327 #endif
329                 .globl segment_table
330 segment_table:
331                 _LONG_  _etext                  # [  0] End of text (R_SEG_ETEXT)
332                 _LONG_  _fdata                  # [  1] Beginning of data (R_SEG_FDATA)
333                 _LONG_  _edata                  # [  2] End of data (R_SEG_EDATA)
334                 _LONG_  _end                    # [  3] End of BSS (R_SEG_END)
335                 _LONG_  _ftext                  # [  4] Beginning of text (R_SEG_FTEXT)
336                 _LONG_  _fbss                   # [  5] Beginning of BSS (R_SEG_FBSS)
337                 _LONG_  _gp                     # [  6] Global Pointer (R_SEG_GP)
338                 _LONG_  RUNTIME_RELOC_START     # [  7] Beginning of reloc entries
339                 _LONG_  RUNTIME_RELOC_STOP      # [  8] End of reloc entries
340                 _LONG_  cpu_apientry            # [  9] R_SEG_APIENTRY
342 /*  *********************************************************************
343     *  Init Table.
344     *
345     *  This is like segment_table except it contains pointers to
346     *  routines used during initialization.  It serves both as a
347     *  table for doing PIC stuff and also to separate out
348     *  machine-specific init routines.
349     *
350     *  The CALLINIT_xxx macros are used to call routines in this table.
351     ********************************************************************* */
354                 .globl  init_table
355 init_table:
356                 _LONG_  board_earlyinit         # [  0] R_INIT_EARLYINIT
357                 _LONG_  board_setleds           # [  1] R_INIT_SETLEDS
358                 _LONG_  board_draminfo          # [  2] R_INIT_DRAMINFO
359                 _LONG_  CPUCFG_CPUINIT          # [  3] R_INIT_CPUINIT
360                 _LONG_  CPUCFG_ALTCPU_START1    # [  4] R_INIT_ALTCPU_START1
361                 _LONG_  CPUCFG_ALTCPU_START2    # [  5] R_INIT_ALTCPU_START2
362                 _LONG_  CPUCFG_ALTCPU_RESET     # [  6] R_INIT_ALTCPU_RESET
363                 _LONG_  CPUCFG_CPURESTART       # [  7] R_INIT_CPURESTART
364                 _LONG_  CPUCFG_DRAMINIT         # [  8] R_INIT_DRAMINIT
365                 _LONG_  CPUCFG_CACHEOPS         # [  9] R_INIT_CACHEOPS
366                 _LONG_  CPUCFG_TLBHANDLER       # [ 10] R_INIT_TLBHANDLER
367                 _LONG_  cfe_main                # [ 11] R_INIT_CMDSTART
368                 _LONG_  cfe_command_restart     # [ 12] R_INIT_CMDRESTART
369                 _LONG_  cfe_doxreq              # [ 13] R_INIT_DOXREQ
372 #if !CFG_MINIMAL_SIZE
373                 .globl  diag_table
374 diag_table:     _LONG_  CPUCFG_DIAG_TEST1       # [ 0 ] R_DIAG_TEST1
375                 _LONG_  CPUCFG_DIAG_TEST2       # [ 1 ] R_DIAG_TEST2
376 #endif
378 /*  *********************************************************************
379     *  CPU Startup Code
380     ********************************************************************* */
382 cpu_reset:
384         /*
385          * Start with GP as zero.  Nobody should touch
386          * this or set it to any other value until we're ready
387          * to use it.  This is used to tell when we should start
388          * using relocated references in the init table,
389          * so beware!  (see CALLINIT_RELOC in mipsmacros.h)
390          */
392                 move    gp,zero                 # start with no GP.
394 #if CFG_VAPI
395         /*
396          * VAPI works by using the SCD to reset just the core.
397          * Look for a special signature in the mailbox register
398          * on CPU0 - if present, jump to the start of the diag.
399          * Of course, you need a real 12500 to do this.
400          */
402                 li      k0,PHYS_TO_K1(A_IMR_REGISTER(0,R_IMR_MAILBOX_CPU))
403                 ld      k0,0(k0)
404                 dli     k1,VAPI_MAGIC_NUMBER_MC
405                 beq     k0,k1,vapi_runmc
406                 dli     k1,VAPI_MAGIC_NUMBER_UNC
407                 beq     k0,k1,vapi_rununc
408                 dli     k1,VAPI_MAGIC_NUMBER
409                 bne     k0,k1,vapi_skip
411         /*
412          * The only CP0 init we do is to set K0 to cacheable
413          */
415                 mfc0    k0,C0_CONFIG            # get current CONFIG register
416                 srl     k0,k0,3                 # strip out K0 bits
417                 sll     k0,k0,3                 # k0 bits now zero
418                 or      k0,k0,K_CFG_K0COH_COHERENT # K0 is cacheable.
419                 mtc0    k0,C0_CONFIG
421         /*
422          * Set any required defeature bits (for VAPI diagnostics only)
423          * they get cleared by the soft reset.
424          */
426                 jal     sb1250_reset_defeature  /* in sb1250_l1cache.S */
428         /*
429          * Jump to the diagnostic.  Two variants, one for cached
430          * and one for uncached.
431          */
433                 li      k0,VAPI_DIAG_ENTRY
434                 j       k0
436 vapi_rununc:    li      k0,VAPI_DIAG_ENTRY_UNC
437                 j       k0
439 vapi_runmc:     li      k0,VAPI_DIAG_ENTRY_MC
440                 j       k0
442 vapi_skip:
443 #endif
445         /*
446          * Test the CAUSE and STATUS registers for why we
447          * are here.  Cold reset, Warm reset, and NMI all
448          * use this vector.
449          */
453         /*
454          * Test to see if we're on the secondary CPU.  If so,
455          * go do the initialization for that CPU.
456          */
458 #if CFG_MULTI_CPUS
459                 CALLINIT_KSEG1(init_table,R_INIT_ALTCPU_RESET)
460                 /* does not return if on CPU1 */
461 #endif
463 #------------------------------------------------------------------------------
465         /*
466          * Do low-level board initialization.  This is our first
467          * chance to customize the startup sequence.
468          */
470                 CALLINIT_KSEG1(init_table,R_INIT_EARLYINIT)
472                 SETLEDS1('H','E','L','O')
474                 CALLINIT_KSEG1(init_table,R_INIT_CPUINIT)
476         /*
477          * Run some diagnostics
478          */
480 #if !CFG_MINIMAL_SIZE
481                 SETLEDS1('T','S','T','1')
483                 CALLINIT_KSEG1(diag_table,R_DIAG_TEST1)
484 #endif
487 #------------------------------------------------------------------------------
488 #if CFG_MULTI_CPUS
489         /*
490          * Spin up secondary CPU core(s)
491          */
493                 CALLINIT_KSEG1(init_table,R_INIT_ALTCPU_START1)
494 #endif
496         /*
497          * Now, switch from KSEG1 to KSEG0
498          */
501 #if CFG_RUNFROMKSEG0
502                 bal     cpu_kseg0_switch
503 #endif
505 #------------------------------------------------------------------------------
506         /*
507          * Now running on cpu0 in K0SEG.
508          */
510 #if CFG_INIT_DRAM
511                 SETLEDS('D','R','A','M')
513                 CALLINIT_KSEG0(init_table,R_INIT_DRAMINFO)
515                 move   a0,v0            # pass these params
516                 CALLINIT_KSEG0(init_table,R_INIT_DRAMINIT)
517                 srl     k0,v0,10        # board_draminit returns memsize in bytes
518 #else
519                 li      k0,CFG_DRAM_SIZE
520 #endif
522 #ifdef CFE_CAPMEM
523                 li      k0,CFE_CAPMEM
524 #endif
526                 /* Check if we are already in RAM */
527                 bal     1f
528                 nop
529 1:              li      t0,0x1fffffff
530                 and     t0,t0,ra
531                 li      t1,0x1fc00000
532                 blt     t0,t1,zbss
533                 nop
535                 SETLEDS('C','O','P','Y')
537 #if !CFG_EMBEDDED_PIC
538 #if !CFG_XIP
539                 /* Copy self to RAM */
540                 LOADREL(a0,_ftext)
541                 la      a1,_ftext
542 #else
543                 /* Copy data only to RAM */
544                 LOADREL(a0,_etext)
545                 la      a1,_fdata
546 #endif
547                 la      a2,_edata
548                 sub     a2,a2,a1
549 1:              LR      t0,0(a0)
550                 SR      t0,0(a1)
551                 add     a0,4
552                 add     a1,4
553                 sub     a2,4
554                 bnez    a2,1b
555                 nop
557 zbss:
558                 /* Zero BSS */
559                 SETLEDS('Z','B','S','S')
561                 la      a0,_fbss
562                 la      a1,_end
563                 sub     a1,a1,a0
565 1:              SR      zero,0(a0)
566                 add     a0,4
567                 sub     a1,4
568                 bnez    a1,1b
569                 nop
571                 SETLEDS(' ','D','$','F')
573                 /* Flush the D cache */
574                 CALLINIT_KSEG0(cacheops_table,_TBLIDX(0))
576                 SETLEDS(' ','I','$','I')
578                 /* and invalidate the I cache */
579                 CALLINIT_KSEG0(cacheops_table,_TBLIDX(1))
581                 SETLEDS(' ','J','S','R')
583                 /* Jump to self in RAM  */
584                 la      a0,have_ram
585                 jr      a0
586                 nop
588                 .globl  cacheops_table
589 cacheops_table: _LONG_  bcmcore_l1cache_flush_d # [ 0 ] DCACHE_FULSH
590                 _LONG_  bcmcore_l1cache_inval_i # [ 1 ] ICACHE_INVAL
591 #endif
593 #------------------------------------------------------------------------------
595 #if CFG_BOOTRAM
596                 b      have_ram                 # No RAM is ok if using emulator RAM
597 #endif
599                 bne    k0,zero,have_ram
601                 SETLEDS('R','A','M','X')        # die here if no ram
603 die1:           b      die1
605 have_ram:
607          /*
608           * If this is the 64-bit version, turn on the KX bit
609           * to allow 64-bit accesses.
610           */
612 #ifdef __long64
613                 mfc0    t0,C0_SR
614                 or      t0,t0,M_SR_KX
615                 mtc0    t0,C0_SR
616 #endif
618 #------------------------------------------------------------------------------
619         /*
620          * K0 contains the RAM size (and therefore the top of RAM
621          * offset).  Start there, and subtract the amount of memory
622          * we expect to use.  If we have more than 256MB of
623          * physical memory, work backwards from the 256MB
624          * boundary.
625          */
627 __CalcMemTop:   li      MEMTOP,0x40000          # 256MB boundary
628                 bgt     k0,MEMTOP,1f            # use 256MB if k0 is greater
629                 move    MEMTOP,k0               # otherwise keep top
630 1:              sll     MEMTOP,10               # make into byte amount
633 #if CFG_EMBEDDED_PIC
634         /*
635          * Calculate the data relocation amount.  Store in FP
636          * for now.  We'll call this register RELOCOFFSET.
637          *
638          * Also calculate a similar offset for relocating code
639          * if we're doing that.  Call this TEXTOFFSET (t9).
640          */
642                 LOADREL(a0,segment_table)       # we'll need this.
644                 LR      t1,R_SEG_ETEXT(a0)
645                 LR      t0,R_SEG_FTEXT(a0)
646                 sub     t1,t1,t0                # T1 = text size
647                 sub     t3,MEMTOP,t1            # reserve room for code
648                 li      t2,~31                  # round down to cache-line boundary
649                 and     t3,t2
650                 move    TEXTBASE,t3             # TEXTBASE is current mem top
651                 sub     TEXTBASE,64             # Reserve top 64 bytes
654  * If you're debugging the relocation stuff, you can uncomment this
655  * line to force CFE to be relocated to a specific address.  Sure
656  * makes life easier when setting breakpoints!
658  *              li      TEXTBASE,0x3C00000
659  */
661                 li      t2,KSEGBASE
662                 add     TEXTBASE,t2             # offset is in K0SEG.
663                 sub     TEXTOFFSET,TEXTBASE,t0  # TEXTOFFSET is distance to move
665 __RelocOffset:
667                 li      t0,((CFG_HEAP_SIZE*1024)+STACK_SIZE) # t0 = size of heap + stack
668                 LR      t1,R_SEG_END(a0)
669                 LR      t2,R_SEG_FDATA(a0)
670                 sub     t1,t2                   # t1 = data + bss
671                 add     t0,t1                   # t0 = total
672                 li      t1,31                   # round to 32-byte boundary
673                 add     t0,t1
674                 not     t1
675                 and     t0,t1                   # t0 = total size rounded up
677                 sub     t1,TEXTBASE,t0          # t1 = TEXTBASE - total size
679         /*
680          * t1 now contains the place where we would like to put our
681          * data segment, BSS, and heap.  Calculate the difference between that
682          * and where our data segment currently resides.
683          */
685                 LR      t0,R_SEG_FDATA(a0)              # beginning of data
686                 subu    RELOCOFFSET,t1,t0       # offset = distance to move segment
688                 li      t0,31                   # round *down* to a cache line
689                 not     t0
690                 and     RELOCOFFSET,t0
691 #else /* */
692                 li      RELOCOFFSET,0           # not relocating, no offset
693                 li      TEXTOFFSET,0
694 #endif
696         /*
697          * DRAM is now running, and we're alive in cacheable memory
698          * on cpu0 in K0SEG.  Set up GP.
699          */
701                 LOADREL(a0,segment_table)
702                 LR      gp,R_SEG_GP(a0)
703                 add     gp,RELOCOFFSET
705 #if CFG_EMBEDDED_PIC
706 #------------------------------------------------------------------------------
707         /*
708          * Zero BSS
709          */
711                 SETLEDS('Z','B','S','S')
713                 LOADREL(a0,segment_table)
714 __ZeroBss:
716                 LR      v0,R_SEG_FBSS(a0)
717                 LR      v1,R_SEG_END(a0)
718                 ADD     v0,RELOCOFFSET          # Relocate to actual data segment
719                 ADD     v1,RELOCOFFSET
721 1:              SR      zero,0(v0)              # Zero one cacheline at a time
722                 SR      zero,(REGSIZE*1)(v0)
723                 SR      zero,(REGSIZE*2)(v0)
724                 SR      zero,(REGSIZE*3)(v0)
725                 add     v0,REGSIZE*4
726                 blt     v0,v1,1b
728 #------------------------------------------------------------------------------
729         /*
730          * Copy code
731          */
733                 SETLEDS('C','O','D','E')
735                 LOADREL(a0,segment_table)
736 __CopyCode:
738                 move    t1,TEXTBASE             # destination address
740                 LR      t2,R_SEG_FTEXT(a0)              # Source address
741                 LR      t3,R_SEG_ETEXT(a0)
743 1:              LR      t4,0(t2)        # read one cache line
744                 LR      t5,(REGSIZE*1)(t2)
745                 LR      t6,(REGSIZE*2)(t2)
746                 LR      t7,(REGSIZE*3)(t2)
747                 SR      t4,0(t1)        # write one cache line
748                 SR      t5,(REGSIZE*1)(t1)
749                 SR      t6,(REGSIZE*2)(t1)
750                 SR      t7,(REGSIZE*3)(t1)
751                 add     t1,REGSIZE*4
752                 add     t2,REGSIZE*4
753                 bltu    t2,t3,1b
754 #endif
756 #------------------------------------------------------------------------------
757         /*
758          * Copy initialized data
759          */
761 #if (CFG_BOOTRAM == 0)
763                 SETLEDS('D','A','T','A')
765                 LOADREL(a0,segment_table)
767 __CopyData:
768                 LR      t1,R_SEG_ETEXT(a0)
769                 li      t0,15
770                 add     t1,t0
771                 not     t0
772                 and     t1,t0           # t1 = _etext rounded up to 16-byte boundary
774                 LR      t2,R_SEG_FDATA(a0)
775                 LR      t3,R_SEG_EDATA(a0)
776                 ADD     t2,RELOCOFFSET  # Relocate to actual data segment
777                 ADD     t3,RELOCOFFSET
779 1:              LR      t4,0(t1)        # read one cache line
780                 LR      t5,(REGSIZE*1)(t1)
781                 LR      t6,(REGSIZE*2)(t1)
782                 LR      t7,(REGSIZE*3)(t1)
783                 SR      t4,0(t2)        # write one cache line
784                 SR      t5,(REGSIZE*1)(t2)
785                 SR      t6,(REGSIZE*2)(t2)
786                 SR      t7,(REGSIZE*3)(t2)
787                 add     t1,(REGSIZE*4)
788                 add     t2,(REGSIZE*4)
789                 bltu    t2,t3,1b
791 #endif
793 #------------------------------------------------------------------------------
795 #if CFG_EMBEDDED_PIC
797         /*
798          * Walk through relocation table and do the data segment
799          * fixups.  Each entry in this table is in the following
800          * format:
801          *
802          *    <offset> <segment-name>
803          *    4 bytes   8 bytes
804          *
805          * The 'offset' represents the distance into the segment where
806          * a fixup needs to be applied, and the 'segment-name'
807          * is the name of the section where the offset is located.
808          * The basic idea is that you would expect that code and
809          * data are moved by different amounts, so places where
810          * the data segment references the text segment you need
811          * apply the offset that the text segment was moved, not data.
812          */
814 __RelocAll:
815                 SETLEDS('R','E','L','O')
817                 LOADREL(a0,segment_table)
819                 LR      a1,R_SEG_FDATA(a0)              # beginning of data segment
820                 add     a1,RELOCOFFSET          # relocate it.
822                 LR      v0,R_SEG_RELOCSTART(a0) # relocs start here
823                 LR      v1,R_SEG_RELOCEND(a0)   # and end here
824                 li      t2,TEXTSECTION          # marker for text sections
826         #
827         # The bottom bit in the offset will be set if we want to
828         # handle a MIPS_64 relocation.   Of course, this bit is not really
829         # part of the relocation offset.
830         #
831                 li      t4,1                    # Make the mask that we
832                 not     t4                      # need to mask off bottom bit
834 reloclp:        lw      t0,4(v0)                # Get section name
835                 beq     t0,t2,textreloc         # skip if for text section
837 # - - - - -  - - - - -  - - - - -  - - - - -  - - - - -  - - - - -  - - - - -  - - - - -
839                 lw      t0,0(v0)                # T0 = relocation offset
840                 and     t1,t0,1                 # test MIPS_64 reloc bit (t1=0 for 32-bit)
841                 and     t0,t4                   # clear MIPS_64 reloc bit
842                 add     t0,a1                   # Add offset to start of data segment
844                 beq     t1,zero,reloc32         # go if doing a 32-bit reloc
846 reloc64:        ld      t1,(t0)                 # Get word from data segment
847                 add     t1,RELOCOFFSET          # Add relocation offset
848                 sd      t1,(t0)                 # Put it back
849                 b       skipreloc               # next...
851 reloc32:        lw      t1,(t0)                 # Get word from data segment
852                 add     t1,RELOCOFFSET          # Add relocation offset
853                 sw      t1,(t0)                 # Put it back
854                 b       skipreloc
856 # - - - - -  - - - - -  - - - - -  - - - - -  - - - - -  - - - - -  - - - - -  - - - - -
858 textreloc:
859                 lw      t0,0(v0)                # T0 = relocation offset
860                 and     t1,t0,1                 # test MIPS_64 reloc bit (t1=0 for 32-bit)
861                 and     t0,t4                   # clear MIPS_64 reloc bit
862                 add     t0,a1                   # Add offset to start of data segment
864                 beq     t1,zero,treloc32        # go if doing a 32-bit reloc
866 treloc64:       ld      t1,(t0)                 # Get word from data segment
867                 add     t1,TEXTOFFSET           # Add relocation offset
868                 sd      t1,(t0)                 # Put it back
869                 b       skipreloc               # next...
871 treloc32:       lw      t1,(t0)                 # Get word from data segment
872                 add     t1,TEXTOFFSET           # Add relocation offset
873                 sw      t1,(t0)                 # Put it back
874                 b       skipreloc
876 skipreloc:      add     v0,12                   # Go to next relocation entry
877                 blt     v0,v1,reloclp
878 #endif
881 #------------------------------------------------------------------------------
883 #if CFG_EMBEDDED_PIC
884         /*
885          * Flush the cache, then switch to relocated code
886          * We need to flush the cache since we just moved the code and
887          * it may still live in our L1 DCache.  We also need to
888          * flush L2, since there are some rare times we run
889          * uncached from DRAM, like when we start/stop a CPU.
890          *
891          * In the case of running completely uncached, don't flush the
892          * cache.  It should not have any dirty lines in it, but you
893          * never know...
894          */
896 __GoRelo:
898 #if CFG_RUNFROMKSEG0
899                 SETLEDS('L','1','2','F')
901                 li      a0,CFE_CACHE_FLUSH_D | CFE_CACHE_FLUSH_L2
902                 CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
903                 li      a0,CFE_CACHE_INVAL_I
904                 CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
905 #endif /* CFG_RUNFROMKSEG0 */
907                 LOADREL(t0,gorelo)              # get offset of next instr
908                 add     t0,TEXTOFFSET           # add in our relocation
909                 j       t0                      # and go there
910 gorelo:         nop
912 #endif
913         /*
914          * Remember total amount of memory.  This is *still* in k0
915          * after all this time.  Hopefully.
916          */
918 __MemVars:
919                 SR      k0,mem_totalsize
920                 SR      RELOCOFFSET,mem_datareloc
922                 move    v0,zero
924                 LOADREL(a0,segment_table)       # trashed by l2 cache flush
925 #if CFG_EMBEDDED_PIC
926                 LR      v0,R_SEG_FDATA(a0)
927                 ADD     v0,RELOCOFFSET
928 #else
929                 LR      v0,R_SEG_FTEXT(a0)
930                 ADD     v0,TEXTOFFSET
931 #endif
932                 LR      v1,R_SEG_END(a0)
933                 ADD     v1,RELOCOFFSET
935                 SR      v0,mem_bottomofmem
936                 SR      v1,mem_heapstart
938 #if CFG_EMBEDDED_PIC
939                 move    t0,MEMTOP               # relocated code means top of memory
940                 add     t0,KSEGBASE             # is *after* code.
941                 SR      t0,mem_topofmem
943 //              SR      gp,-8(t0)               # Store handle at top of memory
944 //              SR      zero,-16(t0)            # Zero out the other handles
945 //              SR      zero,-24(t0)            # in our special place.
946 //              SR      zero,-32(t0)            #
947 //              SR      zero,-48(t0)            #
948 //              SR      zero,-64(t0)            #
949 #else
950                 add     v1,(CFG_HEAP_SIZE*1024) # Otherwise
951                 add     v1,STACK_SIZE
952                 SR      v1,mem_topofmem
953 #endif
955                 SR      TEXTOFFSET,mem_textreloc
957                 /* At this point it's safe to use the CALLINIT_RELOC macro */
960                 LR      t1,R_SEG_FTEXT(a0)
961                 LR      t0,R_SEG_ETEXT(a0)
962                 sub     t0,t0,t1
963                 SR      t0,mem_textsize
964                 add     t1,TEXTOFFSET
965                 SR      t1,mem_textbase
968 #------------------------------------------------------------------------------
970 #if CFG_MULTI_CPUS
971         /*
972          * Let secondary CPU(s) run their idle loops.  Set the
973          * mailbox register to our relocation factor so we can read
974          * it out of the mailbox register and relocate GP properly.
975          */
977                 move    a0,RELOCOFFSET
978                 CALLINIT_RELOC(init_table,R_INIT_ALTCPU_START2)
979 #endif
981 #ifdef _SB1250_PASS1_WORKAROUNDS_
982         /*
983          * Okay, it's safe now to be coherent.
984          * Flush the D cache to invalidate all the lines we have,
985          * then change the config register back.
986          */
987                 li      a0,CFE_CACHE_FLUSH_D
988                 CALLINIT_RELOC(init_table,R_INIT_CACHEOPS)
989                 SETCCAMODE(v0,K_CFG_K0COH_COHERENT) /* cacheable coherent */
990 #endif
992         /*
993          * Stash away some config register stuff
994          */
996                 mfc0    v0,C0_PRID
997                 SR      v0,cpu_prid
1000 #------------------------------------------------------------------------------
1002         /*
1003          * Set up the "C" stack and jump to the main routine.
1004          */
1006                 SETLEDS('M','A','I','N')
1008                 LR      sp,mem_heapstart
1009                 ADD     sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
1010                 li      a0,0                    # call as "cfe_main(0,0)"
1011                 li      a1,0
1013                 CALLINIT_RELOC(init_table,R_INIT_CMDSTART)  # should not return
1016         /*
1017          * Terminate the simulator.
1018          */
1020 crash_sim:      li $2,1
1021                 li $4,0
1022                 syscall 0xCA
1023                 b       cpu_reset
1027 #ifdef _CFE_
1028 /*  *********************************************************************
1029     *  CFE_WARMSTART
1030     *
1031     *  Restart the command interpreter
1032     *
1033     *  Input parameters:
1034     *      A0 - command status
1035     *      nothing (GP has already been set up for us)
1036     *
1037     *  Return value:
1038     *      nothing
1039     ********************************************************************* */
1041 LEAF(cfe_warmstart)
1043                 SR      a0,0(sp)                # store on old stack
1044                 LOADREL(v0,init_table)
1045                 LR      v0,R_INIT_CPURESTART(v0)
1046 #if CFG_EMBEDDED_PIC
1047                 LR      t0,mem_textreloc        # relocate table entry
1048                 ADD     v0,v0,t0
1049 #endif
1051                 jal     v0                      # had better not trash GP or K1
1053          /*
1054           * If this is the 64-bit version, turn on the KX bit
1055           * to allow 64-bit accesses.  Do after calling the cpu
1056           * init routine, but before touching the stack, which
1057           * *could* be a 64-bit address.
1058           */
1060 #ifdef __long64
1061                 mfc0    t0,C0_SR
1062                 or      t0,t0,M_SR_KX
1063                 mtc0    t0,C0_SR
1064                 HAZARD
1065 #endif
1067                 LR      a0,0(sp)
1069                 LR      sp,mem_heapstart
1070                 ADD     sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
1072         /*
1073          * If someone called the API to do a warm start, clear the
1074          * spin lock, since the call will never return.
1075          */
1077 #if CFG_MULTI_CPUS
1078                 SPIN_UNLOCK(cfe_spinlock,t0)
1079 #endif
1081                 CALLINIT_RELOC(init_table,R_INIT_CMDRESTART)  # should not return
1083 END(cfe_warmstart)
1084 #endif
1086 /*  *********************************************************************
1087     *  CFE_FLUSHCACHE
1088     *
1089     *  Perform certain cache operations
1090     *
1091     *  Input parameters:
1092     *      a0 - flags (CFE_CACHE_xxx flags, or zero for a default)
1093     *      a1,a2 - start/end of range for "range invalidate" operations
1094     *      (not used otherwise)
1095     *
1096     *  Return value:
1097     *      nothing
1098     ********************************************************************* */
1100 LEAF(_cfe_flushcache)
1102                 sub     sp,56
1103                 SR      ra,0(sp)
1104                 SR      a0,8(sp)
1105                 SR      s0,16(sp)
1106                 SR      v1,24(sp)
1107                 SR      s1,32(sp)
1108                 SR      s2,40(sp)
1109                 SR      s3,48(sp)
1110                 SR      s4,56(sp)
1113                 CALLINIT_RELOC(init_table,R_INIT_CACHEOPS)
1115                 LR      s4,56(sp)
1116                 LR      s3,48(sp)
1117                 LR      s2,40(sp)
1118                 LR      s1,32(sp)
1119                 LR      v1,24(sp)
1120                 LR      s0,16(sp)
1121                 LR      a0,8(sp)
1122                 LR      ra,0(sp)
1123                 add     sp,56
1124                 j       ra
1126 END(_cfe_flushcache)
1129 /*  *********************************************************************
1130     *  CFE_LAUNCH
1131     *
1132     *  Start the user program.  The program is passed a handle
1133     *  that must be passed back when calling the firmware.
1134     *
1135     *  Parameters passed to the called program are as follows:
1136     *
1137     *      a0 - CFE handle
1138     *      a1 - entry vector
1139     *      a2 - reserved, will be 0
1140     *      a3 - entrypoint signature.
1141     *
1142     *  Input parameters:
1143     *      a0 - entry vector
1144     *
1145     *  Return value:
1146     *      does not return
1147     ********************************************************************* */
1149 LEAF(cfe_launch)
1151                 sub     sp,8
1152                 SR      a0,0(sp)
1155         /*
1156          * Mask all interrupts.
1157          */
1158                 mfc0    v0,C0_SR                # Get current interrupt flag
1159                 li      v1,M_SR_IE              # master interrupt control
1160                 not     v1                      # disable interrupts
1161                 and     v0,v1                   # SR now has IE=0
1162                 mtc0    v0,C0_SR                # put back into CP0
1165         /*
1166          * Flush the D-Cache, since the program we loaded is "data".
1167          * Invalidate the I-Cache, so that addresses in the program
1168          * region will miss and need to be filled from the data we
1169          * just flushed above.
1170          */
1172                 li      a0,CFE_CACHE_FLUSH_D|CFE_CACHE_INVAL_I
1173                 CALLINIT_RELOC(init_table,R_INIT_CACHEOPS)
1176         /*
1177          * Set things up for launching the program.  Pass the
1178          * handle in A0 - apps need to remember that and pass it
1179          * back.
1180          */
1182                 j       RunProgram
1184 END(cfe_launch)
1186         /*
1187          * This is a nice place to set a breakpoint.
1188          */
1189 LEAF(RunProgram)
1191                 LOADREL(a2,segment_table)
1192                 LR      a2,R_SEG_APIENTRY(a2) # A2 = code entry
1194 #if CFG_EMBEDDED_PIC
1195                 LR      t1,mem_textreloc        # relocate table entry
1196                 ADD     a2,a2,t1
1197 #endif
1198                 move    t0,a0           #
1199                 move    a1,zero         # A1 = 0
1200                 move    a0,gp           # A0 = handle
1201                 li      a3,CFE_EPTSEAL  # A3 = entrypoint signature
1202                 LR      t0,0(sp)        # entry point
1204                 j       t0              # go for it.
1205 END(RunProgram)
1210 /*  *********************************************************************
1211     *  CFE_LEDS
1212     *
1213     *  Set the on-board LEDs.
1214     *
1215     *  Input parameters:
1216     *      a0 - LEDs
1217     *
1218     *  Return value:
1219     *      nothing
1220     ********************************************************************* */
1222 LEAF(cfe_leds)
1224 #if CFG_EMBEDDED_PIC
1225                 move    t1,ra                   # LOADREL trashes ra!
1226                 LOADREL(t0,init_table)
1227                 move    ra,t1
1228                 LR      t0,R_INIT_SETLEDS(t0)
1229                 jr      t0
1230 #else
1231                 j       board_setleds           # jump to BSP routine
1232 #endif
1234 END(cfe_leds)
1236 /*  *********************************************************************
1237     *  TLB Fill Exeption Handler
1238     ********************************************************************* */
1240 cpu_tlbfill:
1241                 move    k0,ra                   # Save, we're about to trash
1242                 LOADREL(k1,init_table)          # Load offset of init table
1243                 LR      k1,R_INIT_TLBHANDLER(k1) # Get entry from table
1244                 move    ra,k0                   # restore trashed ra
1245                 j       k1                      # Dispatch to handler
1247 /*  *********************************************************************
1248     *  XTLB Fill Exception Handler
1249     ********************************************************************* */
1251 cpu_xtlbfill:
1252                 j       _exc_entry
1254 /*  *********************************************************************
1255     *  Cache Error Exception Handler
1256     ********************************************************************* */
1258 cpu_cacheerr:
1260 #if defined(_CSWARM_) || defined(_SWARM_) || defined(_BCM91120C_) || defined(_PTSWARM_)
1261 #define LED_CHAR0       (32+8*3)
1262 #define LED_CHAR1       (32+8*2)
1263 #define LED_CHAR2       (32+8*1)
1264 #define LED_CHAR3       (32+8*0)
1265 #if defined(_PTSWARM_)
1266                 li    k0,0xBB0A0000          /* address of LEDs */
1267 #else
1268                 li    k0,0xB00A0000          /* address of LEDs */
1269 #endif
1270                 li    k1,'C'
1271                 sb    k1,LED_CHAR0(k0)
1272                 li    k1,'e'
1273                 sb    k1,LED_CHAR1(k0)
1274                 li    k1,'r'
1275                 sb    k1,LED_CHAR2(k0)
1276                 li    k1,'2'
1277                 sb    k1,LED_CHAR3(k0)
1279                 SETLEDS1('C','e','r','2')
1280 #endif
1282 cpu_cache_death:        b       cpu_cache_death
1286 /*  *********************************************************************
1287     *  General Exception Handler
1288     ********************************************************************* */
1290 cpu_exception:
1291                 j       _exc_entry
1294 /*  *********************************************************************
1295     *  General Interrupt Handler
1296     ********************************************************************* */
1298 cpu_interrupt:
1299                 j       _exc_entry
1302 /*  *********************************************************************
1303     *  EJTAG Debug Exception Handler
1304     ********************************************************************* */
1306 cpu_ejtag:
1307                 .set push
1308                 .set mips64
1309                 deret
1310                 .set pop
1311                 j       cpu_reset
1313 /*  *********************************************************************
1314     *  cpu_apientry(handle,iocb)
1315     *
1316     *  API entry point for external apps.
1317     *
1318     *  Input parameters:
1319     *      a0 - firmware handle (used to determine the location of
1320     *           our relocated data)
1321     *      a1 - pointer to IOCB to execute
1322     *
1323     *  Return value:
1324     *      v0 - return code, 0 if ok
1325     ********************************************************************* */
1327 #define _regidx(x)    ((x)*8)
1329 #define CAE_SRSAVE     _regidx(0)
1330 #define CAE_GPSAVE     _regidx(1)
1331 #define CAE_RASAVE     _regidx(2)
1332 #define CAE_S0SAVE     _regidx(3)
1333 #define CAE_S1SAVE     _regidx(4)
1334 #define CAE_S2SAVE     _regidx(5)
1335 #define CAE_S3SAVE     _regidx(6)
1336 #define CAE_S4SAVE     _regidx(7)
1337 #define CAE_S5SAVE     _regidx(8)
1338 #define CAE_S6SAVE     _regidx(9)
1339 #define CAE_S7SAVE     _regidx(10)
1340 #define CAE_K0SAVE     _regidx(11)
1341 #define CAE_K1SAVE     _regidx(12)
1343 #define CAE_STKSIZE    _regidx(13)
1345 LEAF(cpu_apientry)
1347                 sub     sp,CAE_STKSIZE          # Make room for our stuff
1349                 mfc0    v0,C0_SR                # Get current interrupt flag
1350                 SR      v0,CAE_SRSAVE(sp)       # save on stack
1351                 li      t0,M_SR_IE              # master interrupt control
1352                 not     t0                      # disable interrupts
1353                 and     v0,t0                   # SR now has IE=0
1354 #ifdef __long64
1355                 or      v0,M_SR_KX
1356 #endif
1357                 mtc0    v0,C0_SR                # put back into CP0
1358                 HAZARD
1360                 SR      gp,CAE_GPSAVE(sp)       # save GP
1361                 SR      ra,CAE_RASAVE(sp)       # and old RA
1363                 SR      s0,CAE_S0SAVE(sp)
1364                 SR      s1,CAE_S1SAVE(sp)
1365                 SR      s2,CAE_S2SAVE(sp)
1366                 SR      s3,CAE_S3SAVE(sp)
1367                 SR      s4,CAE_S4SAVE(sp)
1368                 SR      s5,CAE_S5SAVE(sp)
1369                 SR      s6,CAE_S6SAVE(sp)
1370                 SR      s7,CAE_S7SAVE(sp)
1371                 SR      k0,CAE_K0SAVE(sp)
1372                 SR      k1,CAE_K1SAVE(sp)
1374                 move    gp,a0                   # set up new GP
1375                 move    a0,a1                   # A0 points at IOCB
1377 #if CFG_RUNFROMKSEG0
1378                 bal     cpu_kseg0_switch        # switch to kseg0 if not already there
1379 #endif
1381 #if CFG_MULTI_CPUS
1382                 SPIN_LOCK(cfe_spinlock,t0,t1)
1383 #endif
1385                 CALLINIT_RELOC(init_table,R_INIT_DOXREQ)
1387 #if CFG_MULTI_CPUS
1388                 SPIN_UNLOCK(cfe_spinlock,t0)
1389 #endif
1391                 #
1392                 # Restore the saved registers.
1393                 #
1395                 LR      k1,CAE_K1SAVE(sp)
1396                 LR      k0,CAE_K0SAVE(sp)
1397                 LR      s7,CAE_S7SAVE(sp)
1398                 LR      s6,CAE_S6SAVE(sp)
1399                 LR      s5,CAE_S5SAVE(sp)
1400                 LR      s4,CAE_S4SAVE(sp)
1401                 LR      s3,CAE_S3SAVE(sp)
1402                 LR      s2,CAE_S2SAVE(sp)
1403                 LR      s1,CAE_S1SAVE(sp)
1404                 LR      s0,CAE_S0SAVE(sp)
1406                 LR      ra,CAE_RASAVE(sp)       # unwind the stack
1407                 LR      gp,CAE_GPSAVE(sp)
1409                 LR      t0,CAE_SRSAVE(sp)       # old interrupt mask
1411                 add     sp,CAE_STKSIZE          # restore old stack pointer
1413                 mtc0    t0,C0_SR                # restore interrupts
1414                 HAZARD
1415                 j       ra
1416                 nop
1418 END(cpu_apientry)
1421 /*  *********************************************************************
1422     *  CPU_KSEG0_SWITCH
1423     *
1424     *  Hack the return address so we will come back in KSEG0
1425     *
1426     *  Input parameters:
1427     *      nothing
1428     *
1429     *  Return value:
1430     *      nothing
1431     ********************************************************************* */
1433 LEAF(cpu_kseg0_switch)
1435                 and     ra,(K0SIZE-1)
1436                 or      ra,K0BASE
1437                 jr      ra
1439 END(cpu_kseg0_switch)
1444 /*  *********************************************************************
1445     *  _GETSTATUS()
1446     *
1447     *  Read the STATUS register into v0
1448     *
1449     *  Input parameters:
1450     *      nothing
1451     *
1452     *  Return value:
1453     *      v0 - Status register
1454     ********************************************************************* */
1456 LEAF(_getstatus)
1458                 mfc0    v0,C0_SR
1459                 j       ra
1460 END(_getstatus)
1462 /*  *********************************************************************
1463     *  _SETSTATUS()
1464     *
1465     *  Set the STATUS register to the value in a0
1466     *
1467     *  Input parameters:
1468     *      nothing
1469     *
1470     *  Return value:
1471     *      v0 - Status register
1472     ********************************************************************* */
1474 LEAF(_setstatus)
1476                 mtc0    a0,C0_SR
1477                 j       ra
1478 END(_setstatus)
1481 /*  *********************************************************************
1482     *  _GETCAUSE()
1483     *
1484     *  Read the CAUSE register into v0
1485     *
1486     *  Input parameters:
1487     *      nothing
1488     *
1489     *  Return value:
1490     *      v0 - Cause register
1491     ********************************************************************* */
1493 LEAF(_getcause)
1495                 mfc0    v0,C0_CAUSE
1496                 j       ra
1497 END(_getcause)
1500 /*  *********************************************************************
1501     *  _GETTICKS()
1502     *
1503     *  Read the COUNT register into v0
1504     *
1505     *  Input parameters:
1506     *      nothing
1507     *
1508     *  Return value:
1509     *      v0 - count register
1510     ********************************************************************* */
1512 LEAF(_getticks)
1514                 mfc0    v0,C0_COUNT
1515                 j       ra
1516 END(_getticks)
1519 /*  *********************************************************************
1520     *  _SETALARM(ticks)
1521     *
1522     *  Set the C0_Compare register from a0
1523     *
1524     *  Input parameters:
1525     *      a0 - compare register
1526     *
1527     *  Return value:
1528     *      none
1529     ********************************************************************* */
1531 LEAF(_setalarm)
1533                 mtc0    a0,C0_COMPARE
1534                 j       ra
1535 END(_setalarm)
1538 /*  *********************************************************************
1539     *  _SETCONTEXT()
1540     *
1541     *  Set the CONTEXT register.
1542     *
1543     *  Input parameters:
1544     *      a0 - context
1545     *
1546     *  Return value:
1547     *      nothing
1548     ********************************************************************* */
1550 LEAF(_setcontext)
1552                 mtc0    a0,C0_CTEXT
1553                 j       ra
1554 END(_setcontext)
1556 /*  *********************************************************************
1557     *  _GETSEGTBL()
1558     *
1559     *  Return the address of the segment table.  We use this
1560     *  to display the startup messages.
1561     *
1562     *  You can't just address the table from C because it lives
1563     *  in the text segment.
1564     *
1565     *  Input parameters:
1566     *      nothing
1567     *
1568     *  Return value:
1569     *      address of table
1570     ********************************************************************* */
1573 LEAF(_getsegtbl)
1574                 move    t0,ra
1575                 LOADREL(v0,segment_table)
1576                 move    ra,t0
1577                 j       ra
1578 END(_getsegtbl)
1581 /*  *********************************************************************
1582     *  _wbflush()
1583     *
1584     *  Flush the write buffer.  This is probably not necessary
1585     *  on SiByte CPUs, but we have it for completeness.
1586     *
1587     *  Input parameters:
1588     *      nothing
1589     *
1590     *  Return value:
1591     *      nothing
1592     ********************************************************************* */
1594 LEAF(_wbflush)
1596                 sync                    /* drain the buffers */
1597                 la      t0,__junk       /* do an uncached read to force it out */
1598                 or      t0,K1BASE
1599                 lw      zero,0(t0)
1600                 j       ra
1602 END(_wbflush)
1605 /*  *********************************************************************
1606     *  End
1607     ********************************************************************* */