1 /* interrupt-pri.h - Definitions and macros related to interrupt prioritization */
2 /*
3  * Copyright (c) 2002-2004, 2006 Tensilica Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)
26 # error "The interrupt-pri.h header file is meant for inclusion by assembly source code only."
27 #endif
28 
29 #include <xtensa/coreasm.h>
30 #include "xtos-internal.h"
31 
32 /*
33  *  The following macros are used by int-lowpri-dispatcher.S to
34  *  implement prioritized interrupt dispatching and fairness.
35  *  The prioritization scheme is set by XTOS parameters in xtos-params.h .
36  */
37 
38 
39 #if XCHAL_HAVE_INTERRUPTS
40 
41 	//  msindex_int
42 	//
43 	//  Return in register \aindex the index of the first (most significant) bit set
44 	//  in register \amask.
45 	//  Register \amask is clobbered (modified) by this macro.
46 	//
47 	//  Note: this code is similar to the find_ms_setbit macro in <xtensa/coreasm.h>.
48 	//
49 	.macro	msindex_int		aindex, amask
50 # if XCHAL_HAVE_NSA
51 	nsau	\aindex, \amask		// \aindex = interrupt index, from 0 to 31, from left to right
52 	//movi	\amask, 31
53 	//sub	\aindex, \amask, \aindex
54 # else
55 	movi	\aindex, 0		// start with result of 0 (point to lsbit of 32)
56 #  if XCHAL_NUM_INTERRUPTS > 16
57 	bltui	\amask, 0x10000, 2f	// is it one of the 16 lsbits? (if so, check lower 16 bits)
58 	addi	\aindex, \aindex, 16	// no, increment result to upper 16 bits (of 32)
59 	extui	\amask, \amask, 16, 16	// check upper half (shift right 16 bits)
60 2:
61 #  endif
62 #  if XCHAL_NUM_INTERRUPTS > 8
63 	bltui	\amask, 0x100, 2f	// is it one of the 8 lsbits? (if so, check lower 8 bits)
64 	addi	\aindex, \aindex, 8	// no, increment result to upper 8 bits (of 16)
65 	srli	\amask, \amask, 8	// shift right to check upper 8 bits
66 2:
67 #  endif
68 #  if XCHAL_NUM_INTERRUPTS > 4
69 	bltui	\amask, 0x10, 2f	// is it one of the 4 lsbits? (if so, check lower 4 bits)
70 	addi	\aindex, \aindex, 4	// no, increment result to upper 4 bits (of 8)
71 	srli	\amask, \amask, 4	// shift right 4 bits to check upper half
72 2:
73 #  endif
74 	bltui	\amask, 0x4, 2f		// is it one of the 2 lsbits? (if so, check lower 2 bits)
75 	addi	\aindex, \aindex, 2	// no, increment result to upper 2 bits (of 4)
76 	srli	\amask, \amask, 2	// shift right 2 bits to check upper half
77 2:
78 	bltui	\amask, 0x2, 2f		// is it the lsbit?
79 	addi	\aindex, \aindex, 1	// no, increment result to upper bit (of 2)
80 2:					// done!
81 # endif /*!NSA*/
82 	//  HERE:  \aindex = index of interrupt to handle
83 	//	   \amask is available
84 	.endm
85 
86 
87 	//  msindex_int_nc
88 	//
89 	//  Same as msindex_int, but does not clobber \amask.
90 	//  Uses extra register \atmp (a temporary register) if needed.
91 	//
92 	.macro	msindex_int_nc	aindex, amask, atmp
93 # if XCHAL_HAVE_NSA
94 	msindex_int	\aindex, \amask		// does not clobber \amask in this case
95 # else
96 	mov		\atmp, \amask
97 	msindex_int	\aindex, \atmp
98 # endif
99 	.endm
100 
101 
102 	//  indexmask_int
103 	//
104 	//  Compute index of highest priority interrupt in given mask,
105 	//  and trim mask to single bit corresponding to that interrupt.
106 	//  This is used for interrupt dispatching.
107 	//
108 	//  Entry:
109 	//	\index  = (undefined)
110 	//	\mask   = non-zero mask of interrupt bits to consider handling
111 	//	\intptr = &_xtos_intstruct if INTENABLE virtualized, else undefined
112 	//	\tmp    = (undefined)
113 	//  Exit:
114 	//	\index  = index of interrupt (reversed if NSA present)
115 	//	\mask   = single bit corresponding to index
116 	//	\intptr = (preserved)
117 	//	\tmp    = (clobbered)
118 	//
119 	.macro	indexmask_int	index, mask, intptr, tmp
120 # if XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_LO
121 
122 	msindex_int	\index, \mask	// \index = index of msbit set in \mask (\tmp is tmp, \mask clobbered)
123 	//  \index now contains the index of the highest priority pending+enabled interrupt.
124 #  if XCHAL_HAVE_NSA
125 	movi		\mask, 0x80000000
126 	ssr		\index
127 	srl		\mask, \mask	//  \mask = single bit set corresponding to interrupt to be processed...
128 #  else
129 	movi		\mask, 1
130 	ssl		\index
131 	sll		\mask, \mask	//  \mask = single bit set corresponding to interrupt to be processed...
132 #  endif
133 
134 # elif XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_HI
135 
136 	neg		\index, \mask		// find lsbit in \mask ...
137 	and		\mask, \index, \mask	// ...
138 	msindex_int_nc	\index, \mask, \tmp	// \index = index of msbit set in \mask (\tmp is tmp, \mask not clobbered)
139 
140 # else
141 #  error Unsupported priority ordering.
142 # endif /*SUBPRI_ORDER*/
143 	.endm
144 
145 
146 	//  index_int
147 	//
148 	//  Compute index of highest priority interrupt in given mask.
149 	//  This is used for fairness computations.
150 	//
151 	//  Entry:
152 	//	\index  = (undefined)
153 	//	\mask   = non-zero mask of interrupt bits to consider handling
154 	//	\intptr = &_xtos_intptr
155 	//	\tmp    = (undefined)
156 	//  Exit:
157 	//	\index  = index of interrupt (reversed if NSA present)
158 	//	\mask   = (preserved)
159 	//	\intptr = (preserved)
160 	//	\tmp    = (clobbered)
161 	//
162 	.macro	index_int	index, mask, intptr, tmp
163 # if XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_LO
164 	msindex_int_nc	\index, \mask, \tmp	// \index = index of msbit set in \mask (\mask not clobbered)
165 # elif XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_HI
166 	neg		\tmp, \mask		// find lsbit in \mask ...
167 	and		\tmp, \tmp, \mask	// ...
168 	msindex_int	\index, \tmp		// \index = index of msbit set in \tmp (\tmp is clobbered)
169 # else
170 #  error oops
171 # endif
172 	.endm	// index_int
173 
174 
175 #endif /* XCHAL_HAVE_INTERRUPTS */
176 
177 
178