#!/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 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()