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 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 void write_' + reg_name.lower() + '(uint64_t v)') 88 print('{') 89 print('\tasm volatile ("mcrr p15, ' + opc1 + ', %Q0, %R0, ' + 90 crm + '"' + ' : : "r" (v));') 91 print('}') 92 93 94def gen_read32_func(reg_name, crn, opc1, crm, opc2, descr): 95 print('') 96 if len(descr): 97 print('/* ' + descr + ' */') 98 print('static inline uint32_t read_' + reg_name.lower() + '(void)') 99 print('{') 100 print('\tuint32_t v;') 101 print('') 102 print('\tasm volatile ("mrc p15, ' + opc1 + ', %0, ' + crn + ', ' + 103 crm + ', ' + opc2 + '"' + ' : "=r" (v));') 104 print('') 105 print('\treturn v;') 106 print('}') 107 108 109def gen_write32_func(reg_name, crn, opc1, crm, opc2, descr): 110 print('') 111 if len(descr): 112 print('/* ' + descr + ' */') 113 print('static inline void write_' + reg_name.lower() + '(uint32_t v)') 114 print('{') 115 print('\tasm volatile ("mcr p15, ' + opc1 + ', %0, ' + crn + ', ' + 116 crm + ', ' + opc2 + '"' + ' : : "r" (v));') 117 print('}') 118 119 120def gen_write32_dummy_func(reg_name, crn, opc1, crm, opc2, descr): 121 print('') 122 if len(descr): 123 print('/* ' + descr + ' */') 124 print('static inline void write_' + reg_name.lower() + '(void)') 125 print('{') 126 print('\t/* Register ignored */') 127 print('\tasm volatile ("mcr p15, ' + opc1 + ', r0, ' + crn + ', ' + 128 crm + ', ' + opc2 + '");') 129 print('}') 130 131 132def gen_file(line, line_number, s_file): 133 words = line.split() 134 if len(words) == 0: 135 return 136 137 if len(re.findall('^ *#', line)): 138 return 139 140 if len(re.findall('^ *@', line)): 141 comment = re.sub('^ *@', '', line) 142 comment = re.sub('^ *', '', comment) 143 comment = re.sub('[ \n]*$', '', comment) 144 if len(comment) == 0: 145 print('') 146 return 147 if s_file: 148 print('# ' + comment) 149 else: 150 print('/* ' + comment + ' */') 151 return 152 153 reg_name = words[0] 154 crn = words[1] 155 opc1 = words[2] 156 crm = words[3] 157 opc2 = words[4] 158 access_type = words[5] 159 descr = " ".join(words[6:]) 160 161 read_access = access_type == 'RO' or access_type == 'RW' 162 write_access = (access_type == 'WO' or access_type == 'RW' or 163 access_type == 'WOD') 164 dummy_access = access_type == 'WOD' 165 166 if not read_access and not write_access: 167 my_err(line_number, 'bad Access Type "' + access_type + '"') 168 169 if crn == '-': 170 if opc2 != '-': 171 my_err(line_number, 'bad opc2, expected -') 172 173 if read_access: 174 if s_file: 175 gen_read64_macro(reg_name, opc1, crm, descr) 176 else: 177 gen_read64_func(reg_name, opc1, crm, descr) 178 179 if s_file: 180 gen_write64_macro(reg_name, opc1, crm, descr) 181 else: 182 gen_write64_func(reg_name, opc1, crm, descr) 183 else: 184 if read_access: 185 if s_file: 186 gen_read32_macro(reg_name, crn, opc1, crm, opc2, descr) 187 else: 188 gen_read32_func(reg_name, crn, opc1, crm, opc2, descr) 189 190 if write_access: 191 if dummy_access: 192 if s_file: 193 gen_write32_dummy_macro(reg_name, crn, opc1, crm, opc2, 194 descr) 195 else: 196 gen_write32_dummy_func(reg_name, crn, opc1, crm, opc2, 197 descr) 198 else: 199 if s_file: 200 gen_write32_macro(reg_name, crn, opc1, crm, opc2, descr) 201 else: 202 gen_write32_func(reg_name, crn, opc1, crm, opc2, descr) 203 204 205def get_args(): 206 parser = argparse.ArgumentParser(description='Generates instructions to ' 207 'access ARM32 system registers.') 208 209 parser.add_argument('--s_file', action='store_true', 210 help='Generate an Assembly instead of a C file') 211 parser.add_argument('--guard', 212 help='Provide #ifdef <guard_argument> in C file') 213 214 return parser.parse_args() 215 216 217def main(): 218 args = get_args() 219 220 cmnt = 'Automatically generated, do not edit' 221 if args.s_file: 222 print('# ' + cmnt) 223 else: 224 print('/* ' + cmnt + ' */') 225 if args.guard is not None: 226 print('#ifndef ' + args.guard.upper().replace('.', '_')) 227 print('#define ' + args.guard.upper().replace('.', '_')) 228 229 line_number = 0 230 for line in sys.stdin: 231 line_number = line_number + 1 232 gen_file(line, line_number, args.s_file) 233 234 if not args.s_file and args.guard is not None: 235 print('#endif /*' + args.guard.upper().replace('.', '_') + '*/') 236 237 238if __name__ == '__main__': 239 main() 240