arch/xtensa: Add special register allocation generator

Zephyr likes to use the various Xtensa scratch registers for its own
purposes in several places.  Unfortunately, owing to the
configurability of the architecture, we have to use different
registers for different platforms.  This has been done so far with a
collection of different tricks, some... less elegant than others.

Put it all in one place.  This is a python script that emites a
"zsr.h" header with register assignments for all the existing users.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2022-01-08 15:51:04 -08:00 committed by Anas Nashif
commit 82071be443
2 changed files with 80 additions and 0 deletions

View file

@ -25,3 +25,26 @@ zephyr_library_sources_ifdef(CONFIG_GDBSTUB gdbstub.c)
zephyr_library_include_directories(include)
add_subdirectory(startup)
# This produces a preprocessed and regenerated (in the sense of gcc
# -dM, supported by all Xtensa toolchains) core-isa.h file available
# as "core-isa-dM.h". This can be easily parsed by non-C tooling.
#
# Note that this adds the SOC/HAL include directory explicitly, they
# are the official places where we find core-isa.h.
set(CORE_ISA_DM ${CMAKE_BINARY_DIR}/zephyr/include/generated/core-isa-dM.h)
set(CORE_ISA_IN ${CMAKE_BINARY_DIR}/zephyr/include/generated/core-isa-dM.c)
file(WRITE ${CORE_ISA_IN} "#include <xtensa/config/core-isa.h>")
add_custom_command(OUTPUT ${CORE_ISA_DM}
COMMAND ${CMAKE_C_COMPILER} -E -dM
-I${ZEPHYR_XTENSA_MODULE_DIR}/zephyr/soc/${CONFIG_SOC}
-I${SOC_DIR}/${ARCH}/${SOC_PATH}
${CORE_ISA_IN} -o ${CORE_ISA_DM})
# Generates a list of device-specific scratch register choices
set(ZSR_H ${CMAKE_BINARY_DIR}/zephyr/include/generated/zsr.h)
add_custom_command(OUTPUT ${ZSR_H} DEPENDS ${CORE_ISA_DM}
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gen_zsr.py
${CORE_ISA_DM} ${ZSR_H})
add_custom_target(zsr_h DEPENDS ${ZSR_H})
add_dependencies(zephyr_interface zsr_h)

57
arch/xtensa/core/gen_zsr.py Executable file
View file

@ -0,0 +1,57 @@
#!/usr/bin/env python3
# Copyright (c) 2022 Intel corporation
# SPDX-License-Identifier: Apache-2.0
import sys
import re
# Scratch register allocator. Zephyr uses multiple Xtensa SRs as
# scratch space for various special purposes. Unfortunately the
# configurable architecture means that not all registers will be the
# same on every device. This script parses a pre-cooked ("gcc -E
# -dM") core-isa.h file for the current architecture and assigns
# registers to usages.
NEEDED = ("ALLOCA", "CPU", "FLUSH")
coreisa = sys.argv[1]
outfile = sys.argv[2]
syms = {}
def get(s):
return syms[s] if s in syms else 0
with open(coreisa) as infile:
for line in infile.readlines():
m = re.match(r"^#define\s+([^ ]+)\s*(.*)", line.rstrip())
if m:
syms[m.group(1)] = m.group(2)
# Use MISC registers first if available, that's what they're for
regs = [ f"MISC{n}" for n in range(0, int(get("XCHAL_NUM_MISC_REGS"))) ]
# Next come EXCSAVE. Also record our highest non-debug interrupt level.
maxint = 0
for il in range(1, 1 + int(get("XCHAL_NUM_INTLEVELS"))):
regs.append(f"EXCSAVE{il}")
if il != int(get("XCHAL_DEBUGLEVEL")):
maxint = max(il, maxint)
# Now emit our output header with the assignments we chose
with open(outfile, "w") as f:
f.write("/* Generated File, see gen_zsr.py */\n")
f.write("#ifndef ZEPHYR_ZSR_H\n")
f.write("#define ZEPHYR_ZSR_H\n")
for i, need in enumerate(NEEDED):
f.write(f"# define ZSR_{need} {regs[i]}\n")
f.write(f"# define ZSR_{need}_STR \"{regs[i]}\"\n")
# Emit any remaining registers as generics
for i in range(len(NEEDED), len(regs)):
f.write(f"# define ZSR_EXTRA{i - len(NEEDED)} {regs[i]}\n")
# Also, our highest level EPC/EPS registers
f.write(f"# define ZSR_RFI_LEVEL {maxint}\n")
f.write(f"# define ZSR_EPC EPC{maxint}\n")
f.write(f"# define ZSR_EPS EPS{maxint}\n")
f.write("#endif\n")