2 * xtos-internal.h -- internal definitions for single-threaded run-time
4 * Copyright (c) 2003-2010 Tensilica Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #ifndef XTOS_INTERNAL_H
27 #define XTOS_INTERNAL_H
29 #include <xtensa/config/core.h>
30 #include <xtensa/xtruntime.h>
31 #include <xtensa/xtruntime-frames.h>
32 #include <xtensa/xtensa-versions.h>
33 #ifndef XTOS_PARAMS_H /* this to allow indirect inclusion of this header from the outside */
34 #include "xtos-params.h"
37 /* Relative ordering of subpriorities within an interrupt level (or vector): */
38 #define XTOS_SPO_ZERO_LO 0 /* lower (eg. zero) numbered interrupts are lower priority than higher numbered interrupts */
39 #define XTOS_SPO_ZERO_HI 1 /* lower (eg. zero) numbered interrupts are higher priority than higher numbered interrupts */
42 /* Sanity check some parameters from xtos-params.h: */
43 #if XTOS_LOCKLEVEL < XCHAL_EXCM_LEVEL || XTOS_LOCKLEVEL > 15
44 # error Invalid XTOS_LOCKLEVEL value, must be >= EXCM_LEVEL and <= 15, please fix xtos-params.h
47 /* Mask of interrupts locked out at XTOS_LOCKLEVEL: */
48 #define XTOS_LOCKOUT_MASK XCHAL_INTLEVEL_ANDBELOW_MASK(XTOS_LOCKLEVEL)
49 /* Mask of interrupts that can still be enabled at XTOS_LOCKLEVEL: */
50 #define XTOS_UNLOCKABLE_MASK (0xFFFFFFFF-XTOS_LOCKOUT_MASK)
53 #define XTOS_HIGHINT_TRAMP 0 /* mapping high-pri ints to low-pri not auto-supported */
54 #define XTOS_VIRTUAL_INTERRUPT XTOS_HIGHINT_TRAMP /* partially-virtualized INTERRUPT register not currently supported */
55 #if XTOS_HIGHINT_TRAMP
56 # error Automatically-generated high-level interrupt trampolines are not presently supported.
60 * If single interrupt at level-one, sub-prioritization is irrelevant:
62 #if defined(XCHAL_INTLEVEL1_NUM)
64 # define XTOS_SUBPRI 0 /* override - only one interrupt */
68 * In XEA1, the INTENABLE special register must be virtualized to provide
69 * standard XTOS functionality.
70 * In XEA2, this is only needed for software interrupt prioritization.
72 #if XTOS_SUBPRI || XCHAL_HAVE_XEA1
73 #define XTOS_VIRTUAL_INTENABLE 1
75 #define XTOS_VIRTUAL_INTENABLE 0
79 * If single interrupt per priority, then fairness is irrelevant:
81 #if (XTOS_SUBPRI && !XTOS_SUBPRI_GROUPS) || defined(XCHAL_INTLEVEL1_NUM)
82 # undef XTOS_INT_FAIRNESS
83 # define XTOS_INT_FAIRNESS 0
86 /* Identify special case interrupt handling code in int-lowpri-dispatcher.S: */
87 #define XTOS_INT_SPECIALCASE (XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_HI && XTOS_INT_FAIRNESS == 0 && XTOS_SUBPRI_GROUPS == 0)
90 * Determine whether to extend the interrupt entry array:
92 #define XIE_EXTEND (XTOS_VIRTUAL_INTENABLE && !XTOS_INT_SPECIALCASE)
94 /* If we have the NSAU instruction, ordering of interrupts is reversed in _xtos_interrupt_table[]: */
96 # define MAPINT(n) ((XCHAL_NUM_INTERRUPTS-1)-(n))
100 addi \an, \an, XCHAL_NUM_INTERRUPTS-1
104 # define MAPINT(n) (n)
112 #if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
114 /*********** Useful macros ***********/
117 * A useful looping macro:
118 * 'iterate' invokes 'what' (an instruction, pseudo-op or other macro)
119 * multiple times, passing it a numbered parameter from 'from' to 'to'
120 * inclusively. Does not invoke 'what' at all if from > to.
121 * Maximum difference between 'from' and 'to' is 99 minus nesting depth
122 * (GNU 'as' doesn't allow nesting deeper than 100).
124 .macro iterate from, to, what
125 .ifeq ((\to-\from) & ~0xFFF)
127 iterate "(\from+1)", \to, \what
135 // Execute RSIL \ar, \tolevel if \tolevel is different than \fromlevel.
136 // This way the RSIL is avoided if we know at assembly time that
137 // it will not change the level. Typically, this means the \ar register
138 // is ignored, ie. RSIL is used only to change PS.INTLEVEL.
140 .macro rsilft ar, fromlevel, tolevel
141 #if XCHAL_HAVE_INTERRUPTS
142 .if \fromlevel - \tolevel
149 // Save LOOP and MAC16 registers, if configured, to the exception stack
150 // frame pointed to by address register \esf, using \aa and \ab as temporaries.
152 // This macro essentially saves optional registers that the compiler uses by
153 // default when present.
154 // Note that the acclo/acchi subset of MAC16 may be used even if others
155 // multipliers are present (e.g. mul16, mul32).
157 // Only two temp registers required for this code to be optimal (no interlocks) in both
158 // T10xx (Athens) and Xtensa LX microarchitectures (both 5 and 7 stage pipes):
160 .macro save_loops_mac16 esf, aa, ab
164 s32i \aa, \esf, UEXC_lcount
166 s32i \ab, \esf, UEXC_lbeg
167 s32i \aa, \esf, UEXC_lend
172 s32i \aa, \esf, UEXC_acclo
173 s32i \ab, \esf, UEXC_acchi
174 # if XTOS_SAVE_ALL_MAC16
177 s32i \aa, \esf, UEXC_mr + 0
178 s32i \ab, \esf, UEXC_mr + 4
181 s32i \aa, \esf, UEXC_mr + 8
182 s32i \ab, \esf, UEXC_mr + 12
187 // Restore LOOP and MAC16 registers, if configured, from the exception stack
188 // frame pointed to by address register \esf, using \aa, \ab and \ac as temporaries.
190 // Three temp registers are required for this code to be optimal (no interlocks) in
191 // Xtensa LX microarchitectures with 7-stage pipe; otherwise only two
192 // registers would be needed.
194 .macro restore_loops_mac16 esf, aa, ab, ac
196 l32i \aa, \esf, UEXC_lcount
197 l32i \ab, \esf, UEXC_lbeg
198 l32i \ac, \esf, UEXC_lend
204 l32i \aa, \esf, UEXC_acclo
205 l32i \ab, \esf, UEXC_acchi
206 # if XTOS_SAVE_ALL_MAC16
207 l32i \ac, \esf, UEXC_mr + 0
211 l32i \aa, \esf, UEXC_mr + 4
212 l32i \ab, \esf, UEXC_mr + 8
213 l32i \ac, \esf, UEXC_mr + 12
225 /* Offsets from _xtos_intstruct structure: */
227 #if XTOS_VIRTUAL_INTENABLE
228 XTOS_ENABLED_OFS: .space 4 /* _xtos_enabled variable */
229 XTOS_VPRI_ENABLED_OFS: .space 4 /* _xtos_vpri_enabled variable */
231 #if XTOS_VIRTUAL_INTERRUPT
232 XTOS_PENDING_OFS: .space 4 /* _xtos_pending variable */
237 #if XTOS_VIRTUAL_INTENABLE
238 // Update INTENABLE register, computing it as follows:
239 // INTENABLE = _xtos_enabled & _xtos_vpri_enabled
240 // [ & ~_xtos_pending ]
243 // register ax = &_xtos_intstruct
244 // register ay, az undefined (temporaries)
245 // PS.INTLEVEL set to XTOS_LOCKLEVEL or higher (eg. via xtos_lock)
246 // window overflows prevented (PS.WOE=0, PS.EXCM=1, or overflows
247 // already done for registers ax, ay, az)
250 // registers ax, ay, az clobbered
252 // caller needs to SYNC (?) for INTENABLE changes to take effect
254 // Note: in other software prioritization schemes/implementations,
255 // the term <_xtos_vpri_enabled> in the above expression is often
256 // replaced with another expression that computes the set of
257 // interrupts allowed to be enabled at the current software virtualized
258 // interrupt priority.
260 // For example, a simple alternative implementation of software
261 // prioritization for XTOS might have been the following:
262 // INTENABLE = _xtos_enabled & (vpri_enabled | UNLOCKABLE_MASK)
263 // which removes the need for the interrupt dispatcher to 'or' the
264 // UNLOCKABLE_MASK bits into _xtos_vpri_enabled, and lets other code
265 // disable all lockout level interrupts by just clearing _xtos_vpri_enabled
266 // rather than setting it to UNLOCKABLE_MASK.
267 // Other implementations sometimes use a table, eg:
268 // INTENABLE = _xtos_enabled & enable_table[current_vpri]
269 // The HAL (used by some 3rd party OSes) uses essentially a table-driven
270 // version, with other tables enabling run-time changing of priorities.
272 .macro xtos_update_intenable ax, ay, az
273 //movi \ax, _xtos_intstruct
274 l32i \ay, \ax, XTOS_VPRI_ENABLED_OFS // ay = _xtos_vpri_enabled
275 l32i \az, \ax, XTOS_ENABLED_OFS // az = _xtos_enabled
277 and \az, \az, \ay // az = _xtos_enabled & _xtos_vpri_enabled
278 # if XTOS_VIRTUAL_INTERRUPT
279 l32i \ay, \ax, XTOS_PENDING_OFS // ay = _xtos_pending
281 xor \ay, \ay, \ax // ay = ~_xtos_pending
282 and \az, \az, \ay // az &= ~_xtos_pending
286 #endif /* VIRTUAL_INTENABLE */
289 rsil \ax, XTOS_LOCKLEVEL // lockout
292 .macro xtos_unlock ax
293 wsr \ax, PS // unlock
297 /* Offsets to XtosIntHandlerEntry structure fields (see below): */
298 # define XIE_HANDLER 0
302 # define XIE_VPRIMASK (XIE_SIZE*XCHAL_NUM_INTERRUPTS+0) /* if VIRTUAL_INTENABLE [SUBPRI||XEA1] && !SPECIALCASE */
303 # define XIE_LEVELMASK (XIE_SIZE*XCHAL_NUM_INTERRUPTS+4) /* [fairness preloop] if FAIRNESS && SUBPRI [&& SUBPRI_GROUPS] */
306 /* To simplify code: */
308 # define IFNSA(a,b) a
310 # define IFNSA(a,b) b
313 #else /* !_ASMLANGUAGE && !__ASSEMBLER__ */
316 * Interrupt handler table entry.
317 * Unregistered entries have 'handler' point to _xtos_unhandled_interrupt().
319 typedef struct XtosIntHandlerEntry {
320 _xtos_handler handler;
322 } XtosIntHandlerEntry;
324 typedef struct XtosIntMaskEntry {
325 unsigned vpri_mask; /* mask of interrupts enabled when this interrupt is taken */
326 unsigned level_mask; /* mask of interrupts at this interrupt's level */
330 #endif /* !_ASMLANGUAGE && !__ASSEMBLER__ */
335 * XEA1 and interrupt-SUBPRIoritization both imply virtualization of INTENABLE.
336 * Synchronous trampoloines imply partial virtualization of the INTERRUPT
337 * register, which in turn also implies virtualization of INTENABLE register.
338 * High-level interrupts manipulating the set of enabled interrupts implies
339 * at least a high XTOS_LOCK_LEVEL, although not necessarily INTENABLE virtualization.
341 * With INTENABLE register virtualization, at all times the INTENABLE
342 * register reflects the expression:
343 * (set of interrupts enabled) & (set of interrupts enabled by current
346 * Unrelated (DBREAK semantics):
349 * ---------------------
350 * A[5-0] & DBC[5-C] & szmask
352 * = DBA[5-0] & szmask
357 /* Report whether the XSR instruction is available (conservative): */
358 #define HAVE_XSR (XCHAL_HAVE_XEA2 || !XCHAL_HAVE_EXCEPTIONS)
360 * This is more accurate, but not a reliable test in software releases prior to 6.0
361 * (where the targeted hardware parameter was not explicit in the XPG):
363 *#define HAVE_XSR (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_T1040_0)
368 /* Macros for supporting hi-level and medium-level interrupt handling. */
370 #if XCHAL_NUM_INTLEVELS > 6
371 #error Template files (*-template.S) limit support to interrupt levels <= 6
374 #if defined(__XTENSA_WINDOWED_ABI__) && XCHAL_HAVE_CALL4AND12 == 0
375 #error CALL8-only is not supported!
378 #define INTERRUPT_IS_HI(level) \
379 ( XCHAL_HAVE_INTERRUPTS && \
380 (XCHAL_EXCM_LEVEL < level) && \
381 (XCHAL_NUM_INTLEVELS >= level) && \
382 (XCHAL_HAVE_DEBUG ? XCHAL_DEBUGLEVEL != level : 1))
384 #define INTERRUPT_IS_MED(level) \
385 (XCHAL_HAVE_INTERRUPTS && (XCHAL_EXCM_LEVEL >= level))
388 #define _JOIN(x,y) x ## y
389 #define JOIN(x,y) _JOIN(x,y)
391 #define _JOIN3(a,b,c) a ## b ## c
392 #define JOIN3(a,b,c) _JOIN3(a,b,c)
394 #define LABEL(x,y) JOIN3(x,_INTERRUPT_LEVEL,y)
395 #define EXCSAVE_LEVEL JOIN(EXCSAVE_,_INTERRUPT_LEVEL)
396 #define INTLEVEL_VSIZE JOIN3(XSHAL_INTLEVEL,_INTERRUPT_LEVEL,_VECTOR_SIZE)
400 #endif /* XTOS_INTERNAL_H */