1//
2// clock.S - assembly language clock routines
3//
4// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/clock.S#1 $
5
6// Copyright (c) 2003-2010 Tensilica Inc.
7//
8// Permission is hereby granted, free of charge, to any person obtaining
9// a copy of this software and associated documentation files (the
10// "Software"), to deal in the Software without restriction, including
11// without limitation the rights to use, copy, modify, merge, publish,
12// distribute, sublicense, and/or sell copies of the Software, and to
13// permit persons to whom the Software is furnished to do so, subject to
14// the following conditions:
15//
16// The above copyright notice and this permission notice shall be included
17// in all copies or substantial portions of the Software.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27#include <xtensa/coreasm.h>
28
29
30//  A useful looping macro:
31//  'iterate' invokes 'what' (an instruction, pseudo-op or other macro)
32//  multiple times, passing it a numbered parameter from 'from' to 'to'
33//  inclusively.  Does not invoke 'what' at all if from > to.
34//  Maximum difference between 'from' and 'to' is 99 minus nesting depth
35//  (GNU 'as' doesn't allow nesting deeper than 100).
36//
37	.macro	iterate		from, to, what
38	.ifeq	((\to-\from) & ~0xFFF)
39	\what	\from
40	iterate	"(\from+1)", \to, \what
41	.endif
42	.endm	// iterate
43
44
45//----------------------------------------------------------------------
46// Read CCOUNT register
47//----------------------------------------------------------------------
48
49// unsigned xthal_get_ccount(void)
50//
51	.global	xthal_get_ccount
52	.type	xthal_get_ccount,@function
53	.align	4
54xthal_get_ccount:
55	abi_entry
56#if XCHAL_HAVE_CCOUNT
57	rsr.ccount	a2
58/*
59 *  The following alternative (in absence of CCOUNT) doesn't work well,
60 *  because ICOUNT is often used for debugging.  (And when it isn't,
61 *  one would have to ensure that ICOUNTLEVEL is high enough and that
62 *  ICOUNT is incremented to zero in the debug exception handler upon
63 *  ICOUNT exceptions.)
64 *
65 *	#elif XCHAL_HAVE_DEBUG
66 *		rsr.icount	a2	// no CCOUNT, return ICOUNT if available
67 */
68#else
69	movi	a2, 0		// else no counter at all, just return zero
70#endif
71	abi_return
72	.size	xthal_get_ccount, . - xthal_get_ccount
73
74
75//----------------------------------------------------------------------
76// Access CCOMPAREn registers
77//----------------------------------------------------------------------
78
79// void xthal_set_ccompare(int, unsigned)
80//
81	.global	xthal_set_ccompare
82	.type	xthal_set_ccompare,@function
83	.align	4
84xthal_set_ccompare:
85	abi_entry
86#if XCHAL_NUM_TIMERS > 0
87	bnez	a2, 1f
88	wsr.ccompare0	a3
89	rsync
90	abi_return
91#endif
921:
93#if XCHAL_NUM_TIMERS > 1
94	bnei	a2, 1, 2f
95	wsr.ccompare1	a3
96	rsync
97	abi_return
98#endif
992:
100#if XCHAL_NUM_TIMERS > 2
101	bnei	a2, 2, 3f
102	wsr.ccompare2	a3
103	rsync
104#endif
1053:
106	abi_return
107	.size	xthal_set_ccompare, . - xthal_set_ccompare
108
109
110// unsigned xthal_get_ccompare(int)
111//
112	.global	xthal_get_ccompare
113	.type	xthal_get_ccompare,@function
114	.align	4
115xthal_get_ccompare:
116	abi_entry
117#if XCHAL_NUM_TIMERS > 0
118	bnez	a2, 1f
119	rsr.ccompare0	a2
120	abi_return
121#endif
1221:
123#if XCHAL_NUM_TIMERS > 1
124	bnei	a2, 1, 2f
125	rsr.ccompare1	a2
126	abi_return
127#endif
1282:
129#if XCHAL_NUM_TIMERS > 2
130	bnei	a2, 2, 3f
131	rsr.ccompare2	a2
132	abi_return
133#endif
1343:
135	movi	a2, 0
136	abi_return
137	.size	xthal_get_ccompare, . - xthal_get_ccompare
138
139