aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorJens Wiklander <jens.wiklander@linaro.org>2018-08-16 22:12:26 +0200
committerJérôme Forissier <jerome.forissier@linaro.org>2018-08-23 11:28:56 +0200
commit18b580248e9dfd46f90bbddf2a6d104052a29635 (patch)
treec5ea4f281af5e7f556f43948e9d088924b94212a /scripts
parent6cea5715bc9fb13b6f8903661e0f7f9cf89a9b50 (diff)
core: arm32: generate system register access code
Replaces the hand crafted system register code in <arm32.h> and <arm32_macros.S> with generated code based on arm32_sysreg.txt which is extracted from the ARM Architecture Reference Manual. The remaining hand crafted code for cp15 accesses is not covered by the ARM Architecture Reference Manual. A script is added to generate both assembly macros and static inline functions to access the system registers. Reviewed-by: Jerome Forissier <jerome.forissier@linaro.org> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/arm32_sysreg.py239
1 files changed, 239 insertions, 0 deletions
diff --git a/scripts/arm32_sysreg.py b/scripts/arm32_sysreg.py
new file mode 100755
index 00000000..bd0c619e
--- /dev/null
+++ b/scripts/arm32_sysreg.py
@@ -0,0 +1,239 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2018, Linaro Limited
+#
+from __future__ import print_function
+
+import argparse
+import sys
+import re
+
+
+def eprint(*args, **kwargs):
+ print(*args, file=sys.stderr, **kwargs)
+
+
+def my_err(line_number, msg):
+ eprint('Error: line:' + repr(line_number) + ' ' + msg)
+ sys.exit(1)
+
+
+def gen_read64_macro(reg_name, opc1, crm, descr):
+ print('')
+ if len(descr):
+ print('\t# ' + descr)
+ print('\t.macro read_' + reg_name.lower() + ' reg0, reg1')
+ print('\tmrrc\tp15, ' + opc1 + ', \\reg0, \\reg1, ' + crm)
+ print('\t.endm')
+
+
+def gen_write64_macro(reg_name, opc1, crm, descr):
+ print('')
+ if len(descr):
+ print('\t# ' + descr)
+ print('\t.macro write_' + reg_name.lower() + ' reg0, reg1')
+ print('\tmcrr\tp15, ' + opc1 + ', \\reg0, \\reg1, ' + crm)
+ print('\t.endm')
+
+
+def gen_read32_macro(reg_name, crn, opc1, crm, opc2, descr):
+ print('')
+ if len(descr):
+ print('\t# ' + descr)
+ print('\t.macro read_' + reg_name.lower() + ' reg')
+ print('\tmrc p15, ' + opc1 + ', \\reg, ' + crn + ', ' + crm + ', ' + opc2)
+ print('\t.endm')
+
+
+def gen_write32_macro(reg_name, crn, opc1, crm, opc2, descr):
+ print('')
+ if len(descr):
+ print('\t# ' + descr)
+ print('\t.macro write_' + reg_name.lower() + ' reg')
+ print('\tmcr p15, ' + opc1 + ', \\reg, ' + crn + ', ' + crm + ', ' + opc2)
+ print('\t.endm')
+
+
+def gen_write32_dummy_macro(reg_name, crn, opc1, crm, opc2, descr):
+ print('')
+ if len(descr):
+ print('\t# ' + descr)
+ print('\t.macro write_' + reg_name.lower())
+ print('\t# Register ignored')
+ print('\tmcr p15, ' + opc1 + ', r0, ' + crn + ', ' + crm + ', ' + opc2)
+ print('\t.endm')
+
+
+def gen_read64_func(reg_name, opc1, crm, descr):
+ print('')
+ if len(descr):
+ print('/* ' + descr + ' */')
+ print('static inline uint64_t read_' + reg_name.lower() + '(void)')
+ print('{')
+ print('\tuint64_t v;')
+ print('')
+ print('\tasm volatile ("mrrc p15, ' + opc1 + ', %Q0, %R0, ' +
+ crm + '"' + ' : "=r" (v));')
+ print('')
+ print('\treturn v;')
+ print('}')
+
+
+def gen_write64_func(reg_name, opc1, crm, descr):
+ print('')
+ if len(descr):
+ print('/* ' + descr + ' */')
+ print('static inline void write_' + reg_name.lower() + '(uint64_t v)')
+ print('{')
+ print('\tasm volatile ("mcrr p15, ' + opc1 + ', %Q0, %R0, ' +
+ crm + '"' + ' : : "r" (v));')
+ print('}')
+
+
+def gen_read32_func(reg_name, crn, opc1, crm, opc2, descr):
+ print('')
+ if len(descr):
+ print('/* ' + descr + ' */')
+ print('static inline uint32_t read_' + reg_name.lower() + '(void)')
+ print('{')
+ print('\tuint32_t v;')
+ print('')
+ print('\tasm volatile ("mrc p15, ' + opc1 + ', %0, ' + crn + ', ' +
+ crm + ', ' + opc2 + '"' + ' : "=r" (v));')
+ print('')
+ print('\treturn v;')
+ print('}')
+
+
+def gen_write32_func(reg_name, crn, opc1, crm, opc2, descr):
+ print('')
+ if len(descr):
+ print('/* ' + descr + ' */')
+ print('static inline void write_' + reg_name.lower() + '(uint32_t v)')
+ print('{')
+ print('\tasm volatile ("mcr p15, ' + opc1 + ', %0, ' + crn + ', ' +
+ crm + ', ' + opc2 + '"' + ' : : "r" (v));')
+ print('}')
+
+
+def gen_write32_dummy_func(reg_name, crn, opc1, crm, opc2, descr):
+ print('')
+ if len(descr):
+ print('/* ' + descr + ' */')
+ print('static inline void write_' + reg_name.lower() + '(void)')
+ print('{')
+ print('\t/* Register ignored */')
+ print('\tasm volatile ("mcr p15, ' + opc1 + ', r0, ' + crn + ', ' +
+ crm + ', ' + opc2 + '");')
+ print('}')
+
+
+def gen_file(line, line_number, s_file):
+ words = line.split()
+ if len(words) == 0:
+ return
+
+ if len(re.findall('^ *#', line)):
+ return
+
+ if len(re.findall('^ *@', line)):
+ comment = re.sub('^ *@', '', line)
+ comment = re.sub('^ *', '', comment)
+ comment = re.sub('[ \n]*$', '', comment)
+ if len(comment) == 0:
+ print('')
+ return
+ if s_file:
+ print('# ' + comment)
+ else:
+ print('/* ' + comment + ' */')
+ return
+
+ reg_name = words[0]
+ crn = words[1]
+ opc1 = words[2]
+ crm = words[3]
+ opc2 = words[4]
+ access_type = words[5]
+ descr = " ".join(words[6:])
+
+ read_access = access_type == 'RO' or access_type == 'RW'
+ write_access = (access_type == 'WO' or access_type == 'RW' or
+ access_type == 'WOD')
+ dummy_access = access_type == 'WOD'
+
+ if not read_access and not write_access:
+ my_err(line_number, 'bad Access Type "' + access_type + '"')
+
+ if crn == '-':
+ if opc2 != '-':
+ my_err(line_number, 'bad opc2, expected -')
+
+ if read_access:
+ if s_file:
+ gen_read64_macro(reg_name, opc1, crm, descr)
+ else:
+ gen_read64_func(reg_name, opc1, crm, descr)
+
+ if s_file:
+ gen_write64_macro(reg_name, opc1, crm, descr)
+ else:
+ gen_write64_func(reg_name, opc1, crm, descr)
+ else:
+ if read_access:
+ if s_file:
+ gen_read32_macro(reg_name, crn, opc1, crm, opc2, descr)
+ else:
+ gen_read32_func(reg_name, crn, opc1, crm, opc2, descr)
+
+ if write_access:
+ if dummy_access:
+ if s_file:
+ gen_write32_dummy_macro(reg_name, crn, opc1, crm, opc2,
+ descr)
+ else:
+ gen_write32_dummy_func(reg_name, crn, opc1, crm, opc2,
+ descr)
+ else:
+ if s_file:
+ gen_write32_macro(reg_name, crn, opc1, crm, opc2, descr)
+ else:
+ gen_write32_func(reg_name, crn, opc1, crm, opc2, descr)
+
+
+def get_args():
+ parser = argparse.ArgumentParser(description='Generates instructions to '
+ 'access ARM32 system registers.')
+
+ parser.add_argument('--s_file', action='store_true',
+ help='Generate an Assembly instead of a C file')
+ parser.add_argument('--guard',
+ help='Provide #ifdef <guard_argument> in C file')
+
+ return parser.parse_args()
+
+
+def main():
+ args = get_args()
+
+ cmnt = 'Automatically generated, do not edit'
+ if args.s_file:
+ print('# ' + cmnt)
+ else:
+ print('/* ' + cmnt + ' */')
+ if args.guard is not None:
+ print('#ifndef ' + args.guard.upper().replace('.', '_'))
+ print('#define ' + args.guard.upper().replace('.', '_'))
+
+ line_number = 0
+ for line in sys.stdin:
+ line_number = line_number + 1
+ gen_file(line, line_number, args.s_file)
+
+ if not args.s_file and args.guard is not None:
+ print('#endif /*' + args.guard.upper().replace('.', '_') + '*/')
+
+
+if __name__ == '__main__':
+ main()