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