1#!/usr/bin/env python 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2018, Linaro Limited 5# 6from __future__ import print_function 7 8import argparse 9import sys 10import re 11 12 13def eprint(*args, **kwargs): 14 print(*args, file=sys.stderr, **kwargs) 15 16 17def my_err(line_number, msg): 18 eprint('Error: line:' + repr(line_number) + ' ' + msg) 19 sys.exit(1) 20 21 22def gen_read64_macro(reg_name, opc1, crm, descr): 23 print('') 24 if len(descr): 25 print('\t# ' + descr) 26 print('\t.macro read_' + reg_name.lower() + ' reg0, reg1') 27 print('\tmrrc\tp15, ' + opc1 + ', \\reg0, \\reg1, ' + crm) 28 print('\t.endm') 29 30 31def gen_write64_macro(reg_name, opc1, crm, descr): 32 print('') 33 if len(descr): 34 print('\t# ' + descr) 35 print('\t.macro write_' + reg_name.lower() + ' reg0, reg1') 36 print('\tmcrr\tp15, ' + opc1 + ', \\reg0, \\reg1, ' + crm) 37 print('\t.endm') 38 39 40def gen_read32_macro(reg_name, crn, opc1, crm, opc2, descr): 41 print('') 42 if len(descr): 43 print('\t# ' + descr) 44 print('\t.macro read_' + reg_name.lower() + ' reg') 45 print('\tmrc p15, ' + opc1 + ', \\reg, ' + crn + ', ' + crm + ', ' + opc2) 46 print('\t.endm') 47 48 49def gen_write32_macro(reg_name, crn, opc1, crm, opc2, descr): 50 print('') 51 if len(descr): 52 print('\t# ' + descr) 53 print('\t.macro write_' + reg_name.lower() + ' reg') 54 print('\tmcr p15, ' + opc1 + ', \\reg, ' + crn + ', ' + crm + ', ' + opc2) 55 print('\t.endm') 56 57 58def gen_write32_dummy_macro(reg_name, crn, opc1, crm, opc2, descr): 59 print('') 60 if len(descr): 61 print('\t# ' + descr) 62 print('\t.macro write_' + reg_name.lower()) 63 print('\t# Register ignored') 64 print('\tmcr p15, ' + opc1 + ', r0, ' + crn + ', ' + crm + ', ' + opc2) 65 print('\t.endm') 66 67 68def gen_read64_func(reg_name, opc1, crm, descr): 69 print('') 70 if len(descr): 71 print('/* ' + descr + ' */') 72 print('static inline __noprof uint64_t read_' + reg_name.lower() + '(void)') 73 print('{') 74 print('\tuint64_t v;') 75 print('') 76 print('\tasm volatile ("mrrc p15, ' + opc1 + ', %Q0, %R0, ' + 77 crm + '"' + ' : "=r" (v));') 78 print('') 79 print('\treturn v;') 80 print('}') 81 82 83def gen_write64_func(reg_name, opc1, crm, descr): 84 print('') 85 if len(descr): 86 print('/* ' + descr + ' */') 87 print('static inline __noprof void write_' + reg_name.lower() + 88 '(uint64_t v)') 89 print('{') 90 print('\tasm volatile ("mcrr p15, ' + opc1 + ', %Q0, %R0, ' + 91 crm + '"' + ' : : "r" (v));') 92 print('}') 93 94 95def gen_read32_func(reg_name, crn, opc1, crm, opc2, descr): 96 print('') 97 if len(descr): 98 print('/* ' + descr + ' */') 99 print('static inline __noprof uint32_t read_' + reg_name.lower() + '(void)') 100 print('{') 101 print('\tuint32_t v;') 102 print('') 103 print('\tasm volatile ("mrc p15, ' + opc1 + ', %0, ' + crn + ', ' + 104 crm + ', ' + opc2 + '"' + ' : "=r" (v));') 105 print('') 106 print('\treturn v;') 107 print('}') 108 109 110def gen_write32_func(reg_name, crn, opc1, crm, opc2, descr): 111 print('') 112 if len(descr): 113 print('/* ' + descr + ' */') 114 print('static inline __noprof void write_' + reg_name.lower() + 115 '(uint32_t v)') 116 print('{') 117 print('\tasm volatile ("mcr p15, ' + opc1 + ', %0, ' + crn + ', ' + 118 crm + ', ' + opc2 + '"' + ' : : "r" (v));') 119 print('}') 120 121 122def gen_write32_dummy_func(reg_name, crn, opc1, crm, opc2, descr): 123 print('') 124 if len(descr): 125 print('/* ' + descr + ' */') 126 print('static inline void write_' + reg_name.lower() + '(void)') 127 print('{') 128 print('\t/* Register ignored */') 129 print('\tasm volatile ("mcr p15, ' + opc1 + ', r0, ' + crn + ', ' + 130 crm + ', ' + opc2 + '");') 131 print('}') 132 133 134def gen_file(line, line_number, s_file): 135 words = line.split() 136 if len(words) == 0: 137 return 138 139 if len(re.findall('^ *#', line)): 140 return 141 142 if len(re.findall('^ *@', line)): 143 comment = re.sub('^ *@', '', line) 144 comment = re.sub('^ *', '', comment) 145 comment = re.sub('[ \n]*$', '', comment) 146 if len(comment) == 0: 147 print('') 148 return 149 if s_file: 150 print('# ' + comment) 151 else: 152 print('/* ' + comment + ' */') 153 return 154 155 reg_name = words[0] 156 crn = words[1] 157 opc1 = words[2] 158 crm = words[3] 159 opc2 = words[4] 160 access_type = words[5] 161 descr = " ".join(words[6:]) 162 163 read_access = access_type == 'RO' or access_type == 'RW' 164 write_access = (access_type == 'WO' or access_type == 'RW' or 165 access_type == 'WOD') 166 dummy_access = access_type == 'WOD' 167 168 if not read_access and not write_access: 169 my_err(line_number, 'bad Access Type "' + access_type + '"') 170 171 if crn == '-': 172 if opc2 != '-': 173 my_err(line_number, 'bad opc2, expected -') 174 175 if read_access: 176 if s_file: 177 gen_read64_macro(reg_name, opc1, crm, descr) 178 else: 179 gen_read64_func(reg_name, opc1, crm, descr) 180 181 if s_file: 182 gen_write64_macro(reg_name, opc1, crm, descr) 183 else: 184 gen_write64_func(reg_name, opc1, crm, descr) 185 else: 186 if read_access: 187 if s_file: 188 gen_read32_macro(reg_name, crn, opc1, crm, opc2, descr) 189 else: 190 gen_read32_func(reg_name, crn, opc1, crm, opc2, descr) 191 192 if write_access: 193 if dummy_access: 194 if s_file: 195 gen_write32_dummy_macro(reg_name, crn, opc1, crm, opc2, 196 descr) 197 else: 198 gen_write32_dummy_func(reg_name, crn, opc1, crm, opc2, 199 descr) 200 else: 201 if s_file: 202 gen_write32_macro(reg_name, crn, opc1, crm, opc2, descr) 203 else: 204 gen_write32_func(reg_name, crn, opc1, crm, opc2, descr) 205 206 207def get_args(): 208 parser = argparse.ArgumentParser(description='Generates instructions to ' 209 'access ARM32 system registers.') 210 211 parser.add_argument('--s_file', action='store_true', 212 help='Generate an Assembly instead of a C file') 213 parser.add_argument('--guard', 214 help='Provide #ifdef <guard_argument> in C file') 215 216 return parser.parse_args() 217 218 219def main(): 220 args = get_args() 221 222 cmnt = 'Automatically generated, do not edit' 223 if args.s_file: 224 print('# ' + cmnt) 225 else: 226 print('/* ' + cmnt + ' */') 227 if args.guard is not None: 228 print('#ifndef ' + args.guard.upper().replace('.', '_')) 229 print('#define ' + args.guard.upper().replace('.', '_')) 230 print('#include <compiler.h>') 231 232 line_number = 0 233 for line in sys.stdin: 234 line_number = line_number + 1 235 gen_file(line, line_number, args.s_file) 236 237 if not args.s_file and args.guard is not None: 238 print('#endif /*' + args.guard.upper().replace('.', '_') + '*/') 239 240 241if __name__ == '__main__': 242 main() 243