xref: /optee_os/scripts/arm32_sysreg.py (revision 4486d5866e231c6bdb1993d08be67e6c029910c8)
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