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