xtensa: Interrupt generator script and output for qemu & esp32

This python script reads the core-isa.h interrupt definitions (via
running a template file through the toolchain preprocessor to generate
an input file) and emits a fully populated, optimized C handling code
that binary searches only the declared interrupts at a given level and
correctly detects spurious interrupts (and/or incorrect core-isa.h
definitions).

The generated code, alas, turns out not to be any faster than simply
searching the interrupt mask with CLZ (er, NSAU in xtensese), though
it could be faster in theory if the compiler made different choices,
see comments.  But I like this for the robustness of the fully
populated search trees and the checking of level vs. mask.

This simply commits the script output into the source tree, including
some checking code to force a build error if the toolchain changes the
headers incompatibly.  It would be better long term to have these
headers be generated at build time, but that requires more cmake fu
than I have.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2017-12-11 15:35:32 -08:00 committed by Anas Nashif
commit 7de010b5e5
4 changed files with 812 additions and 0 deletions

129
arch/xtensa/core/xtensa_intgen.py Executable file
View file

@ -0,0 +1,129 @@
#!/usr/bin/env python3
import re
import fileinput
# Pass an Xtensa core-isa.h file on stdin or the command line, emits a
# C file on output containing optimized interrupt dispatch routines.
# FIXME: looking at the assembly generated by the ESP-32 toolchain,
# this isn't as optimal as I'd hoped. the individual cases are tested
# using a L32R + BNONE (i.e. a full mask test) instead of a BBSI, and
# the handlers are being invoked with CALL8 instead of CALL4,
# inexplicably wasting four words of stack. Maybe this should be
# emitting assembly instead. Wouldn't be much more complicated and
# would share all the same structure.
# My manual count of instructions says that a linear search becomes
# faster on average when there are three or fewer bits to test. Would
# be four, if the compiler would generate BBSI instructions.
MAX_TESTS = 3
ints_by_lvl = {}
# print() wrapper that automatically handles indentation levels
cindent = 0
def cprint(s):
global cindent
if s.find("}") >= 0:
cindent -= 1
for xx in range(cindent):
s = "\t" + s
print(s)
if s.find("{") >= 0:
cindent += 1
def emit_int_handler(ints):
if len(ints) <= MAX_TESTS:
for i in ints:
# FIXME: a little work could allow us to extract the
# handler pointer and argument as literals, saving a few
# instructions and avoiding the need to link in
# _sw_isr_table entirely.
cprint("if (mask & (1 << " + str(i) + ")) {")
cprint("struct _isr_table_entry *e = &_sw_isr_table[" + str(i) + "];")
print("");
cprint("e->isr(e->arg);")
cprint("return 1 << " + str(i) + ";")
cprint("}")
else:
half = int(len(ints)/2)
m = 0
for i in ints[0:half]:
m |= 1 << i
cprint("if (mask & " + ("0x%x" % (m)) + ") {")
emit_int_handler(ints[0:half])
cprint("} else {")
emit_int_handler(ints[half:])
cprint("}")
########################################################################
# Annoyingly need to join lines and remove #-marked annotations. Some
# versions of the preprocessor (ahem, esp32 SDK) like to include
# newlines in the output where the original expressions are expanded
# from 100% single line macros. Slurp it into a single string and
# parse via whitespace.
blob = ""
for l in fileinput.input():
l = l if l.find("#") < 0 else l[0:l.find("#")]
blob += l.rstrip() + " "
for match in re.finditer(r'__xtensa_int_level_magic__\s+(\d+)\s+(\d+)', blob):
irq = int(match.group(1))
lvl = int(match.group(2))
if not lvl in ints_by_lvl:
ints_by_lvl[lvl] = []
ints_by_lvl[lvl].append(irq)
cprint("/*")
cprint(" * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.")
cprint(" *")
cprint(" * Functions here are designed to produce efficient code to")
cprint(" * search an Xtensa bitmask of interrupts, inspecting only those bits")
cprint(" * declared to be associated with a given interrupt level. Each")
cprint(" * dispatcher will handle exactly one flagged interrupt, in numerical")
cprint(" * order (low bits first) and will return a mask of that bit that can")
cprint(" * then be cleared by the calling code. Unrecognized bits for the")
cprint(" * level will invoke an error handler.")
cprint(" */")
cprint("")
# Re-include the core-isa header and be sure our definitions match, for sanity
cprint("#include <xtensa/config/core-isa.h>")
cprint("#include <sw_isr_table.h>")
cprint("")
for l in ints_by_lvl:
for i in ints_by_lvl[l]:
v = "XCHAL_INT" + str(i) + "_LEVEL"
cprint("#if !defined(" + v + ") || " + str(v) + " != " + str(l))
cprint("#error core-isa.h interrupt level does not match dispatcher!")
cprint("#endif")
cprint("")
# Populate empty levels just for sanity. The second-to-last interrupt
# level (usually "debug") typically doesn't have any associated
# vectors, but we don't have any way to know that a-prioi.
max = 0
for lvl in ints_by_lvl:
if lvl > max:
max = lvl
for lvl in range(0, max+1):
if not lvl in ints_by_lvl:
ints_by_lvl[lvl] = []
# Emit the handlers
for lvl in ints_by_lvl:
cprint("static inline int _xtensa_handle_one_int" + str(lvl) + "(unsigned int mask)")
cprint("{")
ints_by_lvl[lvl].sort()
emit_int_handler(ints_by_lvl[lvl])
cprint("return 0;")
cprint("}")
cprint("")

View file

@ -0,0 +1,43 @@
#include <xtensa/config/core-isa.h>
/*
* Not a C source code file.
*
* Intended to be preprocessed only, to produce output for
* interpretation by the xtensa-int-handlers.py script. Literally all
* this does is emit records for which interrupts are at which level,
* available per-hardware by an SDK-provided core-isa.h file.
*/
__xtensa_int_level_magic__ 0 XCHAL_INT0_LEVEL
__xtensa_int_level_magic__ 1 XCHAL_INT1_LEVEL
__xtensa_int_level_magic__ 2 XCHAL_INT2_LEVEL
__xtensa_int_level_magic__ 3 XCHAL_INT3_LEVEL
__xtensa_int_level_magic__ 4 XCHAL_INT4_LEVEL
__xtensa_int_level_magic__ 5 XCHAL_INT5_LEVEL
__xtensa_int_level_magic__ 6 XCHAL_INT6_LEVEL
__xtensa_int_level_magic__ 7 XCHAL_INT7_LEVEL
__xtensa_int_level_magic__ 8 XCHAL_INT8_LEVEL
__xtensa_int_level_magic__ 9 XCHAL_INT9_LEVEL
__xtensa_int_level_magic__ 10 XCHAL_INT10_LEVEL
__xtensa_int_level_magic__ 11 XCHAL_INT11_LEVEL
__xtensa_int_level_magic__ 12 XCHAL_INT12_LEVEL
__xtensa_int_level_magic__ 13 XCHAL_INT13_LEVEL
__xtensa_int_level_magic__ 14 XCHAL_INT14_LEVEL
__xtensa_int_level_magic__ 15 XCHAL_INT15_LEVEL
__xtensa_int_level_magic__ 16 XCHAL_INT16_LEVEL
__xtensa_int_level_magic__ 17 XCHAL_INT17_LEVEL
__xtensa_int_level_magic__ 18 XCHAL_INT18_LEVEL
__xtensa_int_level_magic__ 19 XCHAL_INT19_LEVEL
__xtensa_int_level_magic__ 20 XCHAL_INT20_LEVEL
__xtensa_int_level_magic__ 21 XCHAL_INT21_LEVEL
__xtensa_int_level_magic__ 22 XCHAL_INT22_LEVEL
__xtensa_int_level_magic__ 23 XCHAL_INT23_LEVEL
__xtensa_int_level_magic__ 24 XCHAL_INT24_LEVEL
__xtensa_int_level_magic__ 25 XCHAL_INT25_LEVEL
__xtensa_int_level_magic__ 26 XCHAL_INT26_LEVEL
__xtensa_int_level_magic__ 27 XCHAL_INT27_LEVEL
__xtensa_int_level_magic__ 28 XCHAL_INT28_LEVEL
__xtensa_int_level_magic__ 29 XCHAL_INT29_LEVEL
__xtensa_int_level_magic__ 30 XCHAL_INT30_LEVEL
__xtensa_int_level_magic__ 31 XCHAL_INT31_LEVEL

View file

@ -0,0 +1,368 @@
/*
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.
*
* Functions here are designed to produce efficient code to
* search an Xtensa bitmask of interrupts, inspecting only those bits
* declared to be associated with a given interrupt level. Each
* dispatcher will handle exactly one flagged interrupt, in numerical
* order (low bits first) and will return a mask of that bit that can
* then be cleared by the calling code. Unrecognized bits for the
* level will invoke an error handler.
*/
#include <xtensa/config/core-isa.h>
#include <sw_isr_table.h>
#if !defined(XCHAL_INT0_LEVEL) || XCHAL_INT0_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT1_LEVEL) || XCHAL_INT1_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT2_LEVEL) || XCHAL_INT2_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT3_LEVEL) || XCHAL_INT3_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT4_LEVEL) || XCHAL_INT4_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT5_LEVEL) || XCHAL_INT5_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT6_LEVEL) || XCHAL_INT6_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT7_LEVEL) || XCHAL_INT7_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT8_LEVEL) || XCHAL_INT8_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT9_LEVEL) || XCHAL_INT9_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT10_LEVEL) || XCHAL_INT10_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT12_LEVEL) || XCHAL_INT12_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT13_LEVEL) || XCHAL_INT13_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT17_LEVEL) || XCHAL_INT17_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT18_LEVEL) || XCHAL_INT18_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT19_LEVEL) || XCHAL_INT19_LEVEL != 2
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT20_LEVEL) || XCHAL_INT20_LEVEL != 2
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT21_LEVEL) || XCHAL_INT21_LEVEL != 2
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT11_LEVEL) || XCHAL_INT11_LEVEL != 3
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT15_LEVEL) || XCHAL_INT15_LEVEL != 3
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT22_LEVEL) || XCHAL_INT22_LEVEL != 3
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT23_LEVEL) || XCHAL_INT23_LEVEL != 3
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT27_LEVEL) || XCHAL_INT27_LEVEL != 3
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT29_LEVEL) || XCHAL_INT29_LEVEL != 3
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT24_LEVEL) || XCHAL_INT24_LEVEL != 4
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT25_LEVEL) || XCHAL_INT25_LEVEL != 4
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT28_LEVEL) || XCHAL_INT28_LEVEL != 4
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT30_LEVEL) || XCHAL_INT30_LEVEL != 4
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT16_LEVEL) || XCHAL_INT16_LEVEL != 5
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT26_LEVEL) || XCHAL_INT26_LEVEL != 5
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT31_LEVEL) || XCHAL_INT31_LEVEL != 5
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT14_LEVEL) || XCHAL_INT14_LEVEL != 7
#error core-isa.h interrupt level does not match dispatcher!
#endif
static inline int _xtensa_handle_one_int0(unsigned int mask)
{
return 0;
}
static inline int _xtensa_handle_one_int1(unsigned int mask)
{
if (mask & 0x7f) {
if (mask & 0x7) {
if (mask & (1 << 0)) {
struct _isr_table_entry *e = &_sw_isr_table[0];
e->isr(e->arg);
return 1 << 0;
}
if (mask & (1 << 1)) {
struct _isr_table_entry *e = &_sw_isr_table[1];
e->isr(e->arg);
return 1 << 1;
}
if (mask & (1 << 2)) {
struct _isr_table_entry *e = &_sw_isr_table[2];
e->isr(e->arg);
return 1 << 2;
}
} else {
if (mask & 0x18) {
if (mask & (1 << 3)) {
struct _isr_table_entry *e = &_sw_isr_table[3];
e->isr(e->arg);
return 1 << 3;
}
if (mask & (1 << 4)) {
struct _isr_table_entry *e = &_sw_isr_table[4];
e->isr(e->arg);
return 1 << 4;
}
} else {
if (mask & (1 << 5)) {
struct _isr_table_entry *e = &_sw_isr_table[5];
e->isr(e->arg);
return 1 << 5;
}
if (mask & (1 << 6)) {
struct _isr_table_entry *e = &_sw_isr_table[6];
e->isr(e->arg);
return 1 << 6;
}
}
}
} else {
if (mask & 0x780) {
if (mask & 0x180) {
if (mask & (1 << 7)) {
struct _isr_table_entry *e = &_sw_isr_table[7];
e->isr(e->arg);
return 1 << 7;
}
if (mask & (1 << 8)) {
struct _isr_table_entry *e = &_sw_isr_table[8];
e->isr(e->arg);
return 1 << 8;
}
} else {
if (mask & (1 << 9)) {
struct _isr_table_entry *e = &_sw_isr_table[9];
e->isr(e->arg);
return 1 << 9;
}
if (mask & (1 << 10)) {
struct _isr_table_entry *e = &_sw_isr_table[10];
e->isr(e->arg);
return 1 << 10;
}
}
} else {
if (mask & 0x3000) {
if (mask & (1 << 12)) {
struct _isr_table_entry *e = &_sw_isr_table[12];
e->isr(e->arg);
return 1 << 12;
}
if (mask & (1 << 13)) {
struct _isr_table_entry *e = &_sw_isr_table[13];
e->isr(e->arg);
return 1 << 13;
}
} else {
if (mask & (1 << 17)) {
struct _isr_table_entry *e = &_sw_isr_table[17];
e->isr(e->arg);
return 1 << 17;
}
if (mask & (1 << 18)) {
struct _isr_table_entry *e = &_sw_isr_table[18];
e->isr(e->arg);
return 1 << 18;
}
}
}
}
return 0;
}
static inline int _xtensa_handle_one_int2(unsigned int mask)
{
if (mask & (1 << 19)) {
struct _isr_table_entry *e = &_sw_isr_table[19];
e->isr(e->arg);
return 1 << 19;
}
if (mask & (1 << 20)) {
struct _isr_table_entry *e = &_sw_isr_table[20];
e->isr(e->arg);
return 1 << 20;
}
if (mask & (1 << 21)) {
struct _isr_table_entry *e = &_sw_isr_table[21];
e->isr(e->arg);
return 1 << 21;
}
return 0;
}
static inline int _xtensa_handle_one_int3(unsigned int mask)
{
if (mask & 0x408800) {
if (mask & (1 << 11)) {
struct _isr_table_entry *e = &_sw_isr_table[11];
e->isr(e->arg);
return 1 << 11;
}
if (mask & (1 << 15)) {
struct _isr_table_entry *e = &_sw_isr_table[15];
e->isr(e->arg);
return 1 << 15;
}
if (mask & (1 << 22)) {
struct _isr_table_entry *e = &_sw_isr_table[22];
e->isr(e->arg);
return 1 << 22;
}
} else {
if (mask & (1 << 23)) {
struct _isr_table_entry *e = &_sw_isr_table[23];
e->isr(e->arg);
return 1 << 23;
}
if (mask & (1 << 27)) {
struct _isr_table_entry *e = &_sw_isr_table[27];
e->isr(e->arg);
return 1 << 27;
}
if (mask & (1 << 29)) {
struct _isr_table_entry *e = &_sw_isr_table[29];
e->isr(e->arg);
return 1 << 29;
}
}
return 0;
}
static inline int _xtensa_handle_one_int4(unsigned int mask)
{
if (mask & 0x3000000) {
if (mask & (1 << 24)) {
struct _isr_table_entry *e = &_sw_isr_table[24];
e->isr(e->arg);
return 1 << 24;
}
if (mask & (1 << 25)) {
struct _isr_table_entry *e = &_sw_isr_table[25];
e->isr(e->arg);
return 1 << 25;
}
} else {
if (mask & (1 << 28)) {
struct _isr_table_entry *e = &_sw_isr_table[28];
e->isr(e->arg);
return 1 << 28;
}
if (mask & (1 << 30)) {
struct _isr_table_entry *e = &_sw_isr_table[30];
e->isr(e->arg);
return 1 << 30;
}
}
return 0;
}
static inline int _xtensa_handle_one_int5(unsigned int mask)
{
if (mask & (1 << 16)) {
struct _isr_table_entry *e = &_sw_isr_table[16];
e->isr(e->arg);
return 1 << 16;
}
if (mask & (1 << 26)) {
struct _isr_table_entry *e = &_sw_isr_table[26];
e->isr(e->arg);
return 1 << 26;
}
if (mask & (1 << 31)) {
struct _isr_table_entry *e = &_sw_isr_table[31];
e->isr(e->arg);
return 1 << 31;
}
return 0;
}
static inline int _xtensa_handle_one_int6(unsigned int mask)
{
return 0;
}
static inline int _xtensa_handle_one_int7(unsigned int mask)
{
if (mask & (1 << 14)) {
struct _isr_table_entry *e = &_sw_isr_table[14];
e->isr(e->arg);
return 1 << 14;
}
return 0;
}

View file

@ -0,0 +1,272 @@
/*
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.
*
* Functions here are designed to produce efficient code to
* search an Xtensa bitmask of interrupts, inspecting only those bits
* declared to be associated with a given interrupt level. Each
* dispatcher will handle exactly one flagged interrupt, in numerical
* order (low bits first) and will return a mask of that bit that can
* then be cleared by the calling code. Unrecognized bits for the
* level will invoke an error handler.
*/
#include <xtensa/config/core-isa.h>
#include <sw_isr_table.h>
#if !defined(XCHAL_INT0_LEVEL) || XCHAL_INT0_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT1_LEVEL) || XCHAL_INT1_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT2_LEVEL) || XCHAL_INT2_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT3_LEVEL) || XCHAL_INT3_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT4_LEVEL) || XCHAL_INT4_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT5_LEVEL) || XCHAL_INT5_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT6_LEVEL) || XCHAL_INT6_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT7_LEVEL) || XCHAL_INT7_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT15_LEVEL) || XCHAL_INT15_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT16_LEVEL) || XCHAL_INT16_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT17_LEVEL) || XCHAL_INT17_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT18_LEVEL) || XCHAL_INT18_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT19_LEVEL) || XCHAL_INT19_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT20_LEVEL) || XCHAL_INT20_LEVEL != 1
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT8_LEVEL) || XCHAL_INT8_LEVEL != 2
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT9_LEVEL) || XCHAL_INT9_LEVEL != 3
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT10_LEVEL) || XCHAL_INT10_LEVEL != 3
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT11_LEVEL) || XCHAL_INT11_LEVEL != 3
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT21_LEVEL) || XCHAL_INT21_LEVEL != 3
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT12_LEVEL) || XCHAL_INT12_LEVEL != 4
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT13_LEVEL) || XCHAL_INT13_LEVEL != 5
#error core-isa.h interrupt level does not match dispatcher!
#endif
#if !defined(XCHAL_INT14_LEVEL) || XCHAL_INT14_LEVEL != 7
#error core-isa.h interrupt level does not match dispatcher!
#endif
static inline int _xtensa_handle_one_int0(unsigned int mask)
{
return 0;
}
static inline int _xtensa_handle_one_int1(unsigned int mask)
{
if (mask & 0x7f) {
if (mask & 0x7) {
if (mask & (1 << 0)) {
struct _isr_table_entry *e = &_sw_isr_table[0];
e->isr(e->arg);
return 1 << 0;
}
if (mask & (1 << 1)) {
struct _isr_table_entry *e = &_sw_isr_table[1];
e->isr(e->arg);
return 1 << 1;
}
if (mask & (1 << 2)) {
struct _isr_table_entry *e = &_sw_isr_table[2];
e->isr(e->arg);
return 1 << 2;
}
} else {
if (mask & 0x18) {
if (mask & (1 << 3)) {
struct _isr_table_entry *e = &_sw_isr_table[3];
e->isr(e->arg);
return 1 << 3;
}
if (mask & (1 << 4)) {
struct _isr_table_entry *e = &_sw_isr_table[4];
e->isr(e->arg);
return 1 << 4;
}
} else {
if (mask & (1 << 5)) {
struct _isr_table_entry *e = &_sw_isr_table[5];
e->isr(e->arg);
return 1 << 5;
}
if (mask & (1 << 6)) {
struct _isr_table_entry *e = &_sw_isr_table[6];
e->isr(e->arg);
return 1 << 6;
}
}
}
} else {
if (mask & 0x18080) {
if (mask & (1 << 7)) {
struct _isr_table_entry *e = &_sw_isr_table[7];
e->isr(e->arg);
return 1 << 7;
}
if (mask & (1 << 15)) {
struct _isr_table_entry *e = &_sw_isr_table[15];
e->isr(e->arg);
return 1 << 15;
}
if (mask & (1 << 16)) {
struct _isr_table_entry *e = &_sw_isr_table[16];
e->isr(e->arg);
return 1 << 16;
}
} else {
if (mask & 0x60000) {
if (mask & (1 << 17)) {
struct _isr_table_entry *e = &_sw_isr_table[17];
e->isr(e->arg);
return 1 << 17;
}
if (mask & (1 << 18)) {
struct _isr_table_entry *e = &_sw_isr_table[18];
e->isr(e->arg);
return 1 << 18;
}
} else {
if (mask & (1 << 19)) {
struct _isr_table_entry *e = &_sw_isr_table[19];
e->isr(e->arg);
return 1 << 19;
}
if (mask & (1 << 20)) {
struct _isr_table_entry *e = &_sw_isr_table[20];
e->isr(e->arg);
return 1 << 20;
}
}
}
}
return 0;
}
static inline int _xtensa_handle_one_int2(unsigned int mask)
{
if (mask & (1 << 8)) {
struct _isr_table_entry *e = &_sw_isr_table[8];
e->isr(e->arg);
return 1 << 8;
}
return 0;
}
static inline int _xtensa_handle_one_int3(unsigned int mask)
{
if (mask & 0x600) {
if (mask & (1 << 9)) {
struct _isr_table_entry *e = &_sw_isr_table[9];
e->isr(e->arg);
return 1 << 9;
}
if (mask & (1 << 10)) {
struct _isr_table_entry *e = &_sw_isr_table[10];
e->isr(e->arg);
return 1 << 10;
}
} else {
if (mask & (1 << 11)) {
struct _isr_table_entry *e = &_sw_isr_table[11];
e->isr(e->arg);
return 1 << 11;
}
if (mask & (1 << 21)) {
struct _isr_table_entry *e = &_sw_isr_table[21];
e->isr(e->arg);
return 1 << 21;
}
}
return 0;
}
static inline int _xtensa_handle_one_int4(unsigned int mask)
{
if (mask & (1 << 12)) {
struct _isr_table_entry *e = &_sw_isr_table[12];
e->isr(e->arg);
return 1 << 12;
}
return 0;
}
static inline int _xtensa_handle_one_int5(unsigned int mask)
{
if (mask & (1 << 13)) {
struct _isr_table_entry *e = &_sw_isr_table[13];
e->isr(e->arg);
return 1 << 13;
}
return 0;
}
static inline int _xtensa_handle_one_int6(unsigned int mask)
{
return 0;
}
static inline int _xtensa_handle_one_int7(unsigned int mask)
{
if (mask & (1 << 14)) {
struct _isr_table_entry *e = &_sw_isr_table[14];
e->isr(e->arg);
return 1 << 14;
}
return 0;
}