BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src-rt / cfe / cfe / arch / mips / common / src / init_ram.S
blob9f764c48ebbef6ae09817cf98b6e5a9a61054eab
1 /*  *********************************************************************
2     *  Broadcom Common Firmware Environment (CFE)
3     *  
4     *  CPU init module                          File: init_ram.S
5     *
6     *  This module contains the vectors and lowest-level CPU startup
7     *  functions for CFE.
8     * 
9     *  This is very similar to "init_mips.S" but is used when
10     *  you want to locate CFE in DRAM, loading it like an
11     *  application program.
12     *
13     *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
14     *  
15     *********************************************************************  
16     *
17     *  Copyright 2000,2001,2002,2003
18     *  Broadcom Corporation. All rights reserved.
19     *  
20     *  This software is furnished under license and may be used and 
21     *  copied only in accordance with the following terms and 
22     *  conditions.  Subject to these conditions, you may download, 
23     *  copy, install, use, modify and distribute modified or unmodified 
24     *  copies of this software in source and/or binary form.  No title 
25     *  or ownership is transferred hereby.
26     *  
27     *  1) Any source code used, modified or distributed must reproduce 
28     *     and retain this copyright notice and list of conditions 
29     *     as they appear in the source file.
30     *  
31     *  2) No right is granted to use any trade name, trademark, or 
32     *     logo of Broadcom Corporation.  The "Broadcom Corporation" 
33     *     name may not be used to endorse or promote products derived 
34     *     from this software without the prior written permission of 
35     *     Broadcom Corporation.
36     *  
37     *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
38     *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
39     *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
40     *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 
41     *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 
42     *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
43     *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
44     *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
45     *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
46     *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
47     *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
48     *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 
49     *     THE POSSIBILITY OF SUCH DAMAGE.
50     ********************************************************************* */
53 #include "sbmips.h"
54 #include "exception.h"
56 #include "bsp_config.h"
57 #include "cpu_config.h"
59 #include "cfe_devfuncs.h"
61 /*  *********************************************************************
62     *  Check some stuff
63     ********************************************************************* */
65 #if CFG_RELOC
66 #error "RAM version is not compatible with relocation."
67 #endif
68 #if !CFG_RUNFROMKSEG0 && !defined(JTAG_RAM_BOOT)
69 #error "RAM version should be run cached"
70 #endif
72 #if CFG_MULTI_CPUS
73 #error "Multiple CPUs not compatible with RAM version"
74 #endif
77 /*  *********************************************************************
78     *  Macros
79     ********************************************************************* */
81 #include "mipsmacros.h"
84 /*  *********************************************************************
85     *  SETLEDS(a,b,c,d)
86     *  
87     *  Sets the on-board LED display (if present). 
88     *  
89     *  Input parameters: 
90     *      a,b,c,d - four ASCII characters (literal constants)
91     *      
92     *  Return value:
93     *      a0,k1,ra trashed
94     ********************************************************************* */
97 #define SETLEDS(a,b,c,d)                     \
98        li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
99        jal    board_setleds ;
102 /*  *********************************************************************
103     *  Other constants
104     ********************************************************************* */
107  * This is the size of the stack, rounded to KByte boundaries.
108  */
110 #ifndef CFG_STACK_SIZE
111 #error "CFG_STACK_SIZE not defined"
112 #else
113 #define STACK_SIZE      ((CFG_STACK_SIZE+1023) & ~1023)
114 #endif
117  * Duplicates from cfe_iocb.h -- warning!
118  */
120 #define CFE_CACHE_FLUSH_D       1
121 #define CFE_CACHE_INVAL_I       2
122 #define CFE_CACHE_INVAL_D       4
123 #define CFE_CACHE_INVAL_L2      8
124 #define CFE_CACHE_FLUSH_L2      16
125 #define CFE_CACHE_INVAL_RANGE   32
126 #define CFE_CACHE_FLUSH_RANGE   64
130  * To make life easier reading this code, define "KSEGBASE" 
131  * to either K0BASE or K1BASE depending on whether we're running
132  * uncached.
133  */
134 #ifdef JTAG_RAM_BOOT
135 #define KSEGBASE        K1BASE   /* JTAG RAM version always uncached */
136 #else
137 #define KSEGBASE        K0BASE   /* RAM version always cached */
138 #endif /* JTAG_RAM_BOOT */
140 /*  *********************************************************************
141     *  Names of registers used in this module
142     ********************************************************************* */
144                 .sdata
146 #include "initdata.h"           /* declare variables we use here */
148 #if CFG_MULTI_CPUS
149                 .globl  cfe_spinlock
150 cfe_spinlock:   .word   0
151 #endif
153                 .extern _fdata
154                 .extern _edata
155                 .extern _etext
157 /*  *********************************************************************
158     *  uninitialized data
159     ********************************************************************* */
161                 .bss
163                 .comm   __junk,4
165                 .text
166         
167                 .set noreorder
170 /*  *********************************************************************
171     *  CFE Entry Point (used by OS boot loaders and such)
172     ********************************************************************* */
174                 .set  noreorder
176                 .globl vec_reset
178 vec_reset:      b      cpu_reset
179                 nop
182 vec_apientry:   b       cpu_apientry
183                 nop
184                 .word   CFE_EPTSEAL
185                 .word   CFE_EPTSEAL
187                 .set   reorder
190 /*  *********************************************************************
191     *  Segment Table.
192     *
193     *  Addresses of data segments and of certain routines we're going
194     *  to call from KSEG1.  These are here mostly for the embedded
195     *  PIC case, since we can't count on the 'la' instruction to
196     *  do the expected thing (the assembler expands it into a macro
197     *  for doing GP-relative stuff, and the code is NOT GP-relative.
198     *  So, we (relocatably) get the offset of this table and then
199     *  index within it.  
200     *
201     *  Pointer values in this segment will be relative to KSEG0 for 
202     *  cached versions of CFE, so we need to OR in K1BASE in the
203     *  case of calling to a uncached address.
204     *
205     *  The LOADREL macro handles most of the nastiness here.
206     ********************************************************************* */
209 #include "segtable.h"
211                 .globl segment_table
212 segment_table:
213                 _LONG_  _etext                  # [  0] End of text (R_SEG_ETEXT)
214                 _LONG_  _fdata                  # [  1] Beginning of data (R_SEG_FDATA)
215                 _LONG_  _edata                  # [  2] End of data (R_SEG_EDATA)
216                 _LONG_  _end                    # [  3] End of BSS (R_SEG_END)
217                 _LONG_  _ftext                  # [  4] Beginning of text (R_SEG_FTEXT)
218                 _LONG_  _fbss                   # [  5] Beginning of BSS (R_SEG_FBSS)
219                 _LONG_  _gp                     # [  6] Global Pointer (R_SEG_GP)
220                 _LONG_  0                       # [  7] Beginning of reloc entries
221                 _LONG_  0                       # [  8] End of reloc entries
222                 _LONG_  cpu_apientry            # [  9] R_SEG_APIENTRY
225 /*  *********************************************************************
226     *  Init Table.
227     *  
228     *  This is like segment_table except it contains pointers to 
229     *  routines used during initialization.  It serves both as a
230     *  table for doing PIC stuff and also to separate out 
231     *  machine-specific init routines.
232     *  
233     *  The CALLINIT_xxx macros are used to call routines in this table.
234     ********************************************************************* */
237                 .globl  init_table
238 init_table:
239                 _LONG_  board_earlyinit         # [  0] R_INIT_EARLYINIT
240                 _LONG_  board_setleds           # [  1] R_INIT_SETLEDS
241                 _LONG_  board_draminfo          # [  2] R_INIT_DRAMINFO
242                 _LONG_  CPUCFG_CPUINIT          # [  3] R_INIT_CPUINIT
243                 _LONG_  CPUCFG_ALTCPU_START1    # [  4] R_INIT_ALTCPU_START1
244                 _LONG_  CPUCFG_ALTCPU_START2    # [  5] R_INIT_ALTCPU_START2
245                 _LONG_  CPUCFG_ALTCPU_RESET     # [  6] R_INIT_ALTCPU_RESET
246                 _LONG_  CPUCFG_CPURESTART       # [  7] R_INIT_CPURESTART
247                 _LONG_  CPUCFG_DRAMINIT         # [  8] R_INIT_DRAMINIT
248                 _LONG_  CPUCFG_CACHEOPS         # [  9] R_INIT_CACHEOPS
249                 _LONG_  CPUCFG_TLBHANDLER       # [ 10] R_INIT_TLBHANDLER
250                 _LONG_  cfe_main                # [ 11] R_INIT_CMDSTART
251                 _LONG_  cfe_command_restart     # [ 12] R_INIT_CMDRESTART
252                 _LONG_  cfe_doxreq              # [ 13] R_INIT_DOXREQ
254 /*  *********************************************************************
255     *  CPU Startup Code
256     ********************************************************************* */
259 cpu_reset:
261 #------------------------------------------------------------------------------
263         /*
264          * Do low-level board initialization.  This is our first
265          * chance to customize the startup sequence.
266          */
268                 CALLINIT_KSEG0(init_table,R_INIT_EARLYINIT)
270                 SETLEDS('H','E','L','O')
272 #------------------------------------------------------------------------------
274         /*
275          * DRAM is now running, and we're alive in cacheable memory
276          * on cpu0 in K0SEG.  Set up GP.
277          */
279                 LOADREL(a0,segment_table)
280                 LR      gp,R_SEG_GP(a0)
282 #------------------------------------------------------------------------------
283         /*
284          * Zero BSS
285          */
287                 SETLEDS('Z','B','S','S')
289                 LOADREL(a0,segment_table)
290 __ZeroBss:
292                 LR      v0,R_SEG_FBSS(a0)
293                 LR      v1,R_SEG_END(a0)
295 1:              SR      zero,0(v0)              # Zero one cacheline at a time
296                 SR      zero,(REGSIZE*1)(v0)
297                 SR      zero,(REGSIZE*2)(v0)
298                 SR      zero,(REGSIZE*3)(v0)
299                 add     v0,REGSIZE*4
300                 blt     v0,v1,1b
303 #------------------------------------------------------------------------------
305                 li      k0,256                  # memory size in megabytes
308 #ifdef __long64
309                 mfc0    t0,C0_SR
310                 or      t0,t0,M_SR_KX
311                 mtc0    t0,C0_SR
312 #endif
314 #------------------------------------------------------------------------------
316         /*
317          * Remember total amount of memory.  This is *still* in k0
318          * after all this time.  Hopefully.
319          */
321 __MemVars:
322                 SR      k0,mem_totalsize
323                 SR      zero,mem_datareloc
325                 move    v0,zero
327                 LOADREL(a0,segment_table)       # trashed by l2 cache flush
328                 LR      v0,R_SEG_FTEXT(a0)      # bottom = beginning of text
329                 LR      v1,R_SEG_END(a0)
331                 SR      v0,mem_bottomofmem
332                 SR      v1,mem_heapstart
334                 add     v1,(CFG_HEAP_SIZE*1024) # Otherwise
335                 add     v1,STACK_SIZE
336                 SR      v1,mem_topofmem
338                 SR      zero,mem_textreloc
341                 LR      t1,R_SEG_FTEXT(a0)
342                 LR      t0,R_SEG_ETEXT(a0)
343                 sub     t0,t0,t1
344                 SR      t0,mem_textsize
345                 SR      t1,mem_textbase
348 #------------------------------------------------------------------------------
350 #if CFG_MULTI_CPUS
351         /*
352          * Let secondary CPU(s) run their idle loops.  Set the 
353          * mailbox register to our relocation factor so we can read
354          * it out of the mailbox register and relocate GP properly.
355          */
357                 move    a0,zero
358                 CALLINIT_KSEG0(init_table,R_INIT_ALTCPU_START2)
359 #endif
360                 
361         /*
362          * Stash away some config register stuff
363          */
365                 mfc0    v0,C0_PRID
366                 SR      v0,cpu_prid             
369 #------------------------------------------------------------------------------
371         /*
372          * Set up the "C" stack and jump to the main routine.
373          */
375                 SETLEDS('M','A','I','N')
377                 LR      sp,mem_heapstart
378                 ADD     sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
379                 li      a0,0                    # call as "cfe_main(0,0)"
380                 li      a1,0
382                 CALLINIT_KSEG0(init_table,R_INIT_CMDSTART)  # should not return
385         /*
386          * Terminate the simulator.
387          */
389 crash_sim:      li $2,1
390                 li $4,0
391                 syscall 0xCA
392                 b       cpu_reset
396 /*  *********************************************************************
397     *  CFE_WARMSTART
398     *  
399     *  Restart the command interpreter
400     *  
401     *  Input parameters: 
402     *      A0 - command status
403     *      nothing (GP has already been set up for us)
404     *      
405     *  Return value:
406     *      nothing
407     ********************************************************************* */
409 LEAF(cfe_warmstart)
411                 SR      a0,0(sp)                # store on old stack
412                 LOADREL(v0,init_table)
413                 LR      v0,R_INIT_CPURESTART(v0)
414                 jal     v0                      # had better not trash GP or K1
415                 LR      a0,0(sp)
417                 LR      sp,mem_heapstart
418                 ADD     sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
420         /*
421          * If someone called the API to do a warm start, clear the
422          * spin lock, since the call will never return.
423          */
425 #if CFG_MULTI_CPUS
426                 SPIN_UNLOCK(cfe_spinlock,t0)
427 #endif
429                 CALLINIT_KSEG0(init_table,R_INIT_CMDRESTART)  # should not return
431 END(cfe_warmstart)
433 /*  *********************************************************************
434     *  CFE_FLUSHCACHE
435     *  
436     *  Perform certain cache operations
437     *  
438     *  Input parameters: 
439     *      a0 - flags (CFE_CACHE_xxx flags, or zero for a default)
440     *      a1,a2 - start/end of range for "range invalidate" operations
441     *      (not used otherwise)
442     *      
443     *  Return value:
444     *      nothing
445     ********************************************************************* */
447 LEAF(_cfe_flushcache)
448 #ifndef JTAG_RAM_BOOT
449                 sub     sp,32
450                 SR      ra,0(sp)
451                 SR      a0,8(sp)
452                 SR      s0,16(sp)
453                 SR      v1,32(sp)
456                 CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
458                 LR      v1,32(sp)
459                 LR      s0,16(sp)
460                 LR      a0,8(sp)
461                 LR      ra,0(sp)
462                 add     sp,32
463                 j       ra
464 #endif
465 END(_cfe_flushcache)
468 /*  *********************************************************************
469     *  CFE_LAUNCH
470     *  
471     *  Start the user program.  The program is passed a handle
472     *  that must be passed back when calling the firmware.
473     *
474     *  Parameters passed to the called program are as follows:
475     *
476     *      a0 - CFE handle
477     *      a1 - entry vector
478     *      a2 - reserved, will be 0
479     *      a3 - entrypoint signature.
480     *  
481     *  Input parameters: 
482     *      a0 - entry vector
483     *      
484     *  Return value:
485     *      does not return
486     ********************************************************************* */
488 LEAF(cfe_launch)
490                 sub     sp,8
491                 SR      a0,0(sp)
493         /*
494          * Mask all interrupts.
495          */
496                 mfc0    v0,C0_SR                # Get current interrupt flag
497                 li      v1,M_SR_IE              # master interrupt control
498                 not     v1                      # disable interrupts
499                 and     v0,v1                   # SR now has IE=0
500                 mtc0    v0,C0_SR                # put back into CP0
502 #ifndef JTAG_RAM_BOOT
503         /*
504          * Flush the D-Cache, since the program we loaded is "data".
505          * Invalidate the I-Cache, so that addresses in the program
506          * region will miss and need to be filled from the data we 
507          * just flushed above.
508          */
509                 li      a0,CFE_CACHE_FLUSH_D|CFE_CACHE_INVAL_I
510                 CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
511 #endif
512         /*
513          * Set things up for launching the program.  Pass the
514          * handle in A0 - apps need to remember that and pass it
515          * back.
516          */
518                 j       RunProgram
520 END(cfe_launch)
522         /*
523          * This is a nice place to set a breakpoint.
524          */
525 LEAF(RunProgram)
527                 LOADREL(a2,segment_table)
528                 LR      a2,R_SEG_APIENTRY(a2) # A2 = code entry
529                 move    t0,a0           # 
530                 move    a1,zero         # A1 = 0
531                 move    a0,gp           # A0 = handle
532                 li      a3,CFE_EPTSEAL  # A3 = entrypoint signature
533                 LR      t0,0(sp)        # entry point
534                 j       t0              # go for it.
535 END(RunProgram)
540 /*  *********************************************************************
541     *  CFE_LEDS
542     *  
543     *  Set the on-board LEDs.
544     *  
545     *  Input parameters: 
546     *      a0 - LEDs
547     *      
548     *  Return value:
549     *      nothing
550     ********************************************************************* */
552 LEAF(cfe_leds)
554                 j       board_setleds           # jump to BSP routine
556 END(cfe_leds)
558 /*  *********************************************************************
559     *  TLB Fill Exeption Handler
560     ********************************************************************* */
562 cpu_tlbfill:    
563                 move    k0,ra                   # Save, we're about to trash
564                 LOADREL(k1,init_table)          # Load offset of init table
565                 LR      k1,R_INIT_TLBHANDLER(k1) # Get entry from table
566                 move    ra,k0                   # restore trashed ra
567                 j       k1                      # Dispatch to handler
569 /*  *********************************************************************
570     *  XTLB Fill Exception Handler
571     ********************************************************************* */
573 cpu_xtlbfill:   
574                 j       _exc_entry
576 /*  *********************************************************************
577     *  Cache Error Exception Handler
578     ********************************************************************* */
580 cpu_cacheerr:
581                 j       _exc_entry
584 /*  *********************************************************************
585     *  General Exception Handler
586     ********************************************************************* */
588 cpu_exception:
589                 j       _exc_entry
592 /*  *********************************************************************
593     *  General Interrupt Handler
594     ********************************************************************* */
596 cpu_interrupt:
597                 j       _exc_entry
600 /*  *********************************************************************
601     *  EJTAG Debug Exception Handler
602     ********************************************************************* */
604 cpu_ejtag:
605                 j       cpu_reset
607 /*  *********************************************************************
608     *  cpu_apientry(handle,iocb)
609     *
610     *  API entry point for external apps.
611     *  
612     *  Input parameters: 
613     *      a0 - firmware handle (used to determine the location of
614     *           our relocated data)
615     *      a1 - pointer to IOCB to execute
616     *      
617     *  Return value:
618     *      v0 - return code, 0 if ok
619     ********************************************************************* */
621 #define _regidx(x)    ((x)*8)
623 #define CAE_SRSAVE     _regidx(0)
624 #define CAE_GPSAVE     _regidx(1)
625 #define CAE_RASAVE     _regidx(2)
626 #define CAE_S0SAVE     _regidx(3)
627 #define CAE_S1SAVE     _regidx(4)
628 #define CAE_S2SAVE     _regidx(5)
629 #define CAE_S3SAVE     _regidx(6)
630 #define CAE_S4SAVE     _regidx(7)
631 #define CAE_S5SAVE     _regidx(8)
632 #define CAE_S6SAVE     _regidx(9)
633 #define CAE_S7SAVE     _regidx(10)
635 #define CAE_STKSIZE    _regidx(11)
637 LEAF(cpu_apientry)
639                 sub     sp,CAE_STKSIZE          # Make room for our stuff
641                 mfc0    v0,C0_SR                # Get current interrupt flag
642                 SR      v0,CAE_SRSAVE(sp)       # save on stack
643                 li      t0,M_SR_IE              # master interrupt control
644                 not     t0                      # disable interrupts
645                 and     v0,t0                   # SR now has IE=0
646                 mtc0    v0,C0_SR                # put back into CP0
648                 SR      gp,CAE_GPSAVE(sp)       # save GP
649                 SR      ra,CAE_RASAVE(sp)       # and old RA
651                 SR      s0,CAE_S0SAVE(sp)
652                 SR      s1,CAE_S1SAVE(sp)
653                 SR      s2,CAE_S2SAVE(sp)
654                 SR      s3,CAE_S3SAVE(sp)
655                 SR      s4,CAE_S4SAVE(sp)
656                 SR      s5,CAE_S5SAVE(sp)
657                 SR      s6,CAE_S6SAVE(sp)
658                 SR      s7,CAE_S7SAVE(sp)
660                 move    gp,a0                   # set up new GP
661                 move    a0,a1                   # A0 points at IOCB
664 #if CFG_MULTI_CPUS
665                 SPIN_LOCK(cfe_spinlock,t0,t1)
666 #endif
668                 CALLINIT_KSEG0(init_table,R_INIT_DOXREQ)  # should not return
670 #if CFG_MULTI_CPUS
671                 SPIN_UNLOCK(cfe_spinlock,t0)
672 #endif
674                 #
675                 # Restore the saved registers.
676                 #
678                 LR      s7,CAE_S7SAVE(sp)
679                 LR      s6,CAE_S6SAVE(sp)
680                 LR      s5,CAE_S5SAVE(sp)
681                 LR      s4,CAE_S4SAVE(sp)
682                 LR      s3,CAE_S3SAVE(sp)
683                 LR      s2,CAE_S2SAVE(sp)
684                 LR      s1,CAE_S1SAVE(sp)
685                 LR      s0,CAE_S0SAVE(sp)
687                 LR      ra,CAE_RASAVE(sp)       # unwind the stack
688                 LR      gp,CAE_GPSAVE(sp)
690                 LR      t0,CAE_SRSAVE(sp)       # old interrupt mask
692                 add     sp,CAE_STKSIZE          # restore old stack pointer
694                 mtc0    t0,C0_SR                # restore interrupts
695                 j       ra
696                 nop
698 END(cpu_apientry)
701 /*  *********************************************************************
702     *  CPU_KSEG0_SWITCH
703     *  
704     *  Hack the return address so we will come back in KSEG0
705     *  
706     *  Input parameters: 
707     *      nothing
708     *      
709     *  Return value:
710     *      nothing
711     ********************************************************************* */
713 LEAF(cpu_kseg0_switch)
715                 and     ra,(K0SIZE-1)
716                 or      ra,K0BASE
717                 jr      ra
719 END(cpu_kseg0_switch)
724 /*  *********************************************************************
725     *  _GETSTATUS()
726     *  
727     *  Read the STATUS register into v0
728     *  
729     *  Input parameters: 
730     *      nothing
731     *      
732     *  Return value:
733     *      v0 - Status register
734     ********************************************************************* */
736 LEAF(_getstatus)
738                 mfc0    v0,C0_SR
739                 j       ra
740 END(_getstatus)
743 /*  *********************************************************************
744     *  _SETSTATUS()
745     *  
746     *  Set the STATUS register to the value in a0
747     *  
748     *  Input parameters: 
749     *      nothing
750     *      
751     *  Return value:
752     *      v0 - Status register
753     ********************************************************************* */
755 LEAF(_setstatus)
757                 mtc0    a0,C0_SR
758                 j       ra
759 END(_setstatus)
761 /*  *********************************************************************
762     *  _GETCAUSE()
763     *  
764     *  Read the CAUSE register into v0
765     *  
766     *  Input parameters: 
767     *      nothing
768     *      
769     *  Return value:
770     *      v0 - Cause register
771     ********************************************************************* */
773 LEAF(_getcause)
775                 mfc0    v0,C0_CAUSE
776                 j       ra
777 END(_getcause)
780 /*  *********************************************************************
781     *  _GETTICKS()
782     *  
783     *  Read the COUNT register into v0
784     *  
785     *  Input parameters: 
786     *      nothing
787     *      
788     *  Return value:
789     *      v0 - count register
790     ********************************************************************* */
792 LEAF(_getticks)
794                 mfc0    v0,C0_COUNT
795                 j       ra
796 END(_getticks)
799 /*  *********************************************************************
800     *  _SETALARM(ticks)
801     *  
802     *  Set the C0_Compare register from a0
803     *  
804     *  Input parameters: 
805     *      a0 - compare register
806     *      
807     *  Return value:
808     *      none
809     ********************************************************************* */
811 LEAF(_setalarm)
813                 mtc0    a0,C0_COMPARE
814                 j       ra
815 END(_setalarm)
818 /*  *********************************************************************
819     *  _SETCONTEXT()
820     *  
821     *  Set the CONTEXT register.
822     *  
823     *  Input parameters: 
824     *      a0 - context
825     *      
826     *  Return value:
827     *      nothing
828     ********************************************************************* */
830 LEAF(_setcontext)
832                 mtc0    a0,C0_CTEXT
833                 j       ra
834 END(_setcontext)
836 /*  *********************************************************************
837     *  _GETSEGTBL()
838     *  
839     *  Return the address of the segment table.  We use this
840     *  to display the startup messages.
841     *  
842     *  You can't just address the table from C because it lives
843     *  in the text segment.
844     *  
845     *  Input parameters: 
846     *      nothing
847     *      
848     *  Return value:
849     *      address of table
850     ********************************************************************* */
853 LEAF(_getsegtbl)
854                 move    t0,ra
855                 LOADREL(v0,segment_table)
856                 move    ra,t0
857                 j       ra
858 END(_getsegtbl)
861 /*  *********************************************************************
862     *  _wbflush()
863     *  
864     *  Flush the write buffer.  This is probably not necessary
865     *  on SiByte CPUs, but we have it for completeness.
866     *  
867     *  Input parameters: 
868     *      nothing
869     *      
870     *  Return value:
871     *      nothing
872     ********************************************************************* */
874 LEAF(_wbflush)
876                 sync                    /* drain the buffers */
877                 la      t0,__junk       /* do an uncached read to force it out */
878                 or      t0,K1BASE
879                 lw      zero,0(t0)
880                 j       ra      
882 END(_wbflush)
885 /*  *********************************************************************
886     *  End
887     ********************************************************************* */