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    ********************************************************************* */
51
52
53#include "sbmips.h"
54#include "exception.h"
55
56#include "bsp_config.h"
57#include "cpu_config.h"
58
59#include "cfe_devfuncs.h"
60
61/*  *********************************************************************
62    *  Check some stuff
63    ********************************************************************* */
64
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
71
72#if CFG_MULTI_CPUS
73#error "Multiple CPUs not compatible with RAM version"
74#endif
75
76
77/*  *********************************************************************
78    *  Macros
79    ********************************************************************* */
80
81#include "mipsmacros.h"
82
83
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    ********************************************************************* */
95
96
97#define SETLEDS(a,b,c,d)                     \
98       li     a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ;    \
99       jal    board_setleds ;
100
101
102/*  *********************************************************************
103    *  Other constants
104    ********************************************************************* */
105
106/*
107 * This is the size of the stack, rounded to KByte boundaries.
108 */
109
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
115
116/*
117 * Duplicates from cfe_iocb.h -- warning!
118 */
119
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
127
128
129/*
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 */
139
140/*  *********************************************************************
141    *  Names of registers used in this module
142    ********************************************************************* */
143
144		.sdata
145
146#include "initdata.h"		/* declare variables we use here */
147
148#if CFG_MULTI_CPUS
149		.globl	cfe_spinlock
150cfe_spinlock:	.word	0
151#endif
152
153		.extern	_fdata
154		.extern	_edata
155		.extern	_etext
156
157/*  *********************************************************************
158    *  uninitialized data
159    ********************************************************************* */
160
161		.bss
162
163		.comm	__junk,4
164
165		.text
166
167		.set noreorder
168
169
170/*  *********************************************************************
171    *  CFE Entry Point (used by OS boot loaders and such)
172    ********************************************************************* */
173
174                .set  noreorder
175
176                .globl vec_reset
177
178vec_reset:	b      cpu_reset
179		nop
180
181
182vec_apientry:	b	cpu_apientry
183		nop
184		.word   CFE_EPTSEAL
185		.word   CFE_EPTSEAL
186
187		.set   reorder
188
189
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    ********************************************************************* */
207
208
209#include "segtable.h"
210
211		.globl segment_table
212segment_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
223
224
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    ********************************************************************* */
235
236
237		.globl  init_table
238init_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
253
254/*  *********************************************************************
255    *  CPU Startup Code
256    ********************************************************************* */
257
258
259cpu_reset:
260
261#------------------------------------------------------------------------------
262
263	/*
264	 * Do low-level board initialization.  This is our first
265	 * chance to customize the startup sequence.
266	 */
267
268		CALLINIT_KSEG0(init_table,R_INIT_EARLYINIT)
269
270		SETLEDS('H','E','L','O')
271
272#------------------------------------------------------------------------------
273
274	/*
275	 * DRAM is now running, and we're alive in cacheable memory
276	 * on cpu0 in K0SEG.  Set up GP.
277	 */
278
279		LOADREL(a0,segment_table)
280		LR	gp,R_SEG_GP(a0)
281
282#------------------------------------------------------------------------------
283	/*
284	 * Zero BSS
285         */
286
287		SETLEDS('Z','B','S','S')
288
289		LOADREL(a0,segment_table)
290__ZeroBss:
291
292		LR	v0,R_SEG_FBSS(a0)
293		LR	v1,R_SEG_END(a0)
294
2951:		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
301
302
303#------------------------------------------------------------------------------
304
305		li	k0,256			# memory size in megabytes
306
307
308#ifdef __long64
309		mfc0	t0,C0_SR
310		or	t0,t0,M_SR_KX
311		mtc0	t0,C0_SR
312#endif
313
314#------------------------------------------------------------------------------
315
316	/*
317         * Remember total amount of memory.  This is *still* in k0
318	 * after all this time.  Hopefully.
319	 */
320
321__MemVars:
322		SR	k0,mem_totalsize
323		SR	zero,mem_datareloc
324
325		move	v0,zero
326
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)
330
331		SR	v0,mem_bottomofmem
332		SR	v1,mem_heapstart
333
334		add	v1,(CFG_HEAP_SIZE*1024)	# Otherwise
335		add	v1,STACK_SIZE
336		SR	v1,mem_topofmem
337
338		SR	zero,mem_textreloc
339
340
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
346
347
348#------------------------------------------------------------------------------
349
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	 */
356
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         */
364
365		mfc0	v0,C0_PRID
366		SR	v0,cpu_prid
367
368
369#------------------------------------------------------------------------------
370
371	/*
372	 * Set up the "C" stack and jump to the main routine.
373         */
374
375		SETLEDS('M','A','I','N')
376
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
381
382		CALLINIT_KSEG0(init_table,R_INIT_CMDSTART)  # should not return
383
384
385	/*
386	 * Terminate the simulator.
387	 */
388
389crash_sim:      li $2,1
390                li $4,0
391                syscall	0xCA
392		b	cpu_reset
393
394
395
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    ********************************************************************* */
408
409LEAF(cfe_warmstart)
410
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)
416
417		LR	sp,mem_heapstart
418		ADD	sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
419
420	/*
421	 * If someone called the API to do a warm start, clear the
422	 * spin lock, since the call will never return.
423	 */
424
425#if CFG_MULTI_CPUS
426		SPIN_UNLOCK(cfe_spinlock,t0)
427#endif
428
429		CALLINIT_KSEG0(init_table,R_INIT_CMDRESTART)  # should not return
430
431END(cfe_warmstart)
432
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    ********************************************************************* */
446
447LEAF(_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)
454
455
456		CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
457
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
465END(_cfe_flushcache)
466
467
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    ********************************************************************* */
487
488LEAF(cfe_launch)
489
490		sub	sp,8
491		SR	a0,0(sp)
492
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
501
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	 */
517
518		j	RunProgram
519
520END(cfe_launch)
521
522	/*
523 	 * This is a nice place to set a breakpoint.
524	 */
525LEAF(RunProgram)
526
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.
535END(RunProgram)
536
537
538
539
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    ********************************************************************* */
551
552LEAF(cfe_leds)
553
554		j	board_setleds		# jump to BSP routine
555
556END(cfe_leds)
557
558/*  *********************************************************************
559    *  TLB Fill Exeption Handler
560    ********************************************************************* */
561
562cpu_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
568
569/*  *********************************************************************
570    *  XTLB Fill Exception Handler
571    ********************************************************************* */
572
573cpu_xtlbfill:
574		j	_exc_entry
575
576/*  *********************************************************************
577    *  Cache Error Exception Handler
578    ********************************************************************* */
579
580cpu_cacheerr:
581		j	_exc_entry
582
583
584/*  *********************************************************************
585    *  General Exception Handler
586    ********************************************************************* */
587
588cpu_exception:
589		j	_exc_entry
590
591
592/*  *********************************************************************
593    *  General Interrupt Handler
594    ********************************************************************* */
595
596cpu_interrupt:
597		j	_exc_entry
598
599
600/*  *********************************************************************
601    *  EJTAG Debug Exception Handler
602    ********************************************************************* */
603
604cpu_ejtag:
605		j	cpu_reset
606
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    ********************************************************************* */
620
621#define _regidx(x)    ((x)*8)
622
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)
634
635#define CAE_STKSIZE    _regidx(11)
636
637LEAF(cpu_apientry)
638
639		sub	sp,CAE_STKSIZE		# Make room for our stuff
640
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
647
648		SR	gp,CAE_GPSAVE(sp)	# save GP
649		SR	ra,CAE_RASAVE(sp)	# and old RA
650
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)
659
660		move	gp,a0			# set up new GP
661		move	a0,a1			# A0 points at IOCB
662
663
664#if CFG_MULTI_CPUS
665		SPIN_LOCK(cfe_spinlock,t0,t1)
666#endif
667
668		CALLINIT_KSEG0(init_table,R_INIT_DOXREQ)  # should not return
669
670#if CFG_MULTI_CPUS
671		SPIN_UNLOCK(cfe_spinlock,t0)
672#endif
673
674		#
675		# Restore the saved registers.
676		#
677
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)
686
687		LR	ra,CAE_RASAVE(sp)	# unwind the stack
688		LR	gp,CAE_GPSAVE(sp)
689
690		LR	t0,CAE_SRSAVE(sp)	# old interrupt mask
691
692		add	sp,CAE_STKSIZE		# restore old stack pointer
693
694		mtc0	t0,C0_SR		# restore interrupts
695		j	ra
696		nop
697
698END(cpu_apientry)
699
700
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    ********************************************************************* */
712
713LEAF(cpu_kseg0_switch)
714
715		and	ra,(K0SIZE-1)
716		or	ra,K0BASE
717		jr	ra
718
719END(cpu_kseg0_switch)
720
721
722
723
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    ********************************************************************* */
735
736LEAF(_getstatus)
737
738		mfc0	v0,C0_SR
739		j	ra
740END(_getstatus)
741
742
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    ********************************************************************* */
754
755LEAF(_setstatus)
756
757		mtc0	a0,C0_SR
758		j	ra
759END(_setstatus)
760
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    ********************************************************************* */
772
773LEAF(_getcause)
774
775		mfc0	v0,C0_CAUSE
776		j	ra
777END(_getcause)
778
779
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    ********************************************************************* */
791
792LEAF(_getticks)
793
794		mfc0	v0,C0_COUNT
795		j	ra
796END(_getticks)
797
798
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    ********************************************************************* */
810
811LEAF(_setalarm)
812
813		mtc0	a0,C0_COMPARE
814		j	ra
815END(_setalarm)
816
817
818/*  *********************************************************************
819    *  _SETCONTEXT()
820    *
821    *  Set the CONTEXT register.
822    *
823    *  Input parameters:
824    *  	   a0 - context
825    *
826    *  Return value:
827    *  	   nothing
828    ********************************************************************* */
829
830LEAF(_setcontext)
831
832		mtc0	a0,C0_CTEXT
833		j	ra
834END(_setcontext)
835
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    ********************************************************************* */
851
852
853LEAF(_getsegtbl)
854		move	t0,ra
855		LOADREL(v0,segment_table)
856		move	ra,t0
857		j	ra
858END(_getsegtbl)
859
860
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    ********************************************************************* */
873
874LEAF(_wbflush)
875
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
881
882END(_wbflush)
883
884
885/*  *********************************************************************
886    *  End
887    ********************************************************************* */
888
889
890