GNU Linux-libre 6.1.91-gnu
[releases.git] / arch / arm64 / tools / gen-sysreg.awk
1 #!/bin/awk -f
2 # SPDX-License-Identifier: GPL-2.0
3 # gen-sysreg.awk: arm64 sysreg header generator
4 #
5 # Usage: awk -f gen-sysreg.awk sysregs.txt
6
7 # Log an error and terminate
8 function fatal(msg) {
9         print "Error at " NR ": " msg > "/dev/stderr"
10         exit 1
11 }
12
13 # Sanity check that the start or end of a block makes sense at this point in
14 # the file. If not, produce an error and terminate.
15 #
16 # @this - the $Block or $EndBlock
17 # @prev - the only valid block to already be in (value of @block)
18 # @new - the new value of @block
19 function change_block(this, prev, new) {
20         if (block != prev)
21                 fatal("unexpected " this " (inside " block ")")
22
23         block = new
24 }
25
26 # Sanity check the number of records for a field makes sense. If not, produce
27 # an error and terminate.
28 function expect_fields(nf) {
29         if (NF != nf)
30                 fatal(NF " fields found where " nf " expected")
31 }
32
33 # Print a CPP macro definition, padded with spaces so that the macro bodies
34 # line up in a column
35 function define(name, val) {
36         printf "%-48s%s\n", "#define " name, val
37 }
38
39 # Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field
40 function define_field(reg, field, msb, lsb) {
41         define(reg "_" field, "GENMASK(" msb ", " lsb ")")
42         define(reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")")
43         define(reg "_" field "_SHIFT", lsb)
44         define(reg "_" field "_WIDTH", msb - lsb + 1)
45 }
46
47 # Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb
48 function parse_bitdef(reg, field, bitdef, _bits)
49 {
50         if (bitdef ~ /^[0-9]+$/) {
51                 msb = bitdef
52                 lsb = bitdef
53         } else if (split(bitdef, _bits, ":") == 2) {
54                 msb = _bits[1]
55                 lsb = _bits[2]
56         } else {
57                 fatal("invalid bit-range definition '" bitdef "'")
58         }
59
60
61         if (msb != next_bit)
62                 fatal(reg "." field " starts at " msb " not " next_bit)
63         if (63 < msb || msb < 0)
64                 fatal(reg "." field " invalid high bit in '" bitdef "'")
65         if (63 < lsb || lsb < 0)
66                 fatal(reg "." field " invalid low bit in '" bitdef "'")
67         if (msb < lsb)
68                 fatal(reg "." field " invalid bit-range '" bitdef "'")
69         if (low > high)
70                 fatal(reg "." field " has invalid range " high "-" low)
71
72         next_bit = lsb - 1
73 }
74
75 BEGIN {
76         print "#ifndef __ASM_SYSREG_DEFS_H"
77         print "#define __ASM_SYSREG_DEFS_H"
78         print ""
79         print "/* Generated file - do not edit */"
80         print ""
81
82         block = "None"
83 }
84
85 END {
86         print "#endif /* __ASM_SYSREG_DEFS_H */"
87 }
88
89 # skip blank lines and comment lines
90 /^$/ { next }
91 /^[\t ]*#/ { next }
92
93 /^SysregFields/ {
94         change_block("SysregFields", "None", "SysregFields")
95         expect_fields(2)
96
97         reg = $2
98
99         res0 = "UL(0)"
100         res1 = "UL(0)"
101
102         next_bit = 63
103
104         next
105 }
106
107 /^EndSysregFields/ {
108         if (next_bit > 0)
109                 fatal("Unspecified bits in " reg)
110
111         change_block("EndSysregFields", "SysregFields", "None")
112
113         define(reg "_RES0", "(" res0 ")")
114         define(reg "_RES1", "(" res1 ")")
115         print ""
116
117         reg = null
118         res0 = null
119         res1 = null
120
121         next
122 }
123
124 /^Sysreg/ {
125         change_block("Sysreg", "None", "Sysreg")
126         expect_fields(7)
127
128         reg = $2
129         op0 = $3
130         op1 = $4
131         crn = $5
132         crm = $6
133         op2 = $7
134
135         res0 = "UL(0)"
136         res1 = "UL(0)"
137
138         define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2)
139         define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")")
140
141         define("SYS_" reg "_Op0", op0)
142         define("SYS_" reg "_Op1", op1)
143         define("SYS_" reg "_CRn", crn)
144         define("SYS_" reg "_CRm", crm)
145         define("SYS_" reg "_Op2", op2)
146
147         print ""
148
149         next_bit = 63
150
151         next
152 }
153
154 /^EndSysreg/ {
155         if (next_bit > 0)
156                 fatal("Unspecified bits in " reg)
157
158         change_block("EndSysreg", "Sysreg", "None")
159
160         if (res0 != null)
161                 define(reg "_RES0", "(" res0 ")")
162         if (res1 != null)
163                 define(reg "_RES1", "(" res1 ")")
164         if (res0 != null || res1 != null)
165                 print ""
166
167         reg = null
168         op0 = null
169         op1 = null
170         crn = null
171         crm = null
172         op2 = null
173         res0 = null
174         res1 = null
175
176         next
177 }
178
179 # Currently this is effectivey a comment, in future we may want to emit
180 # defines for the fields.
181 /^Fields/ && (block == "Sysreg") {
182         expect_fields(2)
183
184         if (next_bit != 63)
185                 fatal("Some fields already defined for " reg)
186
187         print "/* For " reg " fields see " $2 " */"
188         print ""
189
190         next_bit = 0
191         res0 = null
192         res1 = null
193
194         next
195 }
196
197
198 /^Res0/ && (block == "Sysreg" || block == "SysregFields") {
199         expect_fields(2)
200         parse_bitdef(reg, "RES0", $2)
201         field = "RES0_" msb "_" lsb
202
203         res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")"
204
205         next
206 }
207
208 /^Res1/ && (block == "Sysreg" || block == "SysregFields") {
209         expect_fields(2)
210         parse_bitdef(reg, "RES1", $2)
211         field = "RES1_" msb "_" lsb
212
213         res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")"
214
215         next
216 }
217
218 /^Field/ && (block == "Sysreg" || block == "SysregFields") {
219         expect_fields(3)
220         field = $3
221         parse_bitdef(reg, field, $2)
222
223         define_field(reg, field, msb, lsb)
224         print ""
225
226         next
227 }
228
229 /^Raz/ && (block == "Sysreg" || block == "SysregFields") {
230         expect_fields(2)
231         parse_bitdef(reg, field, $2)
232
233         next
234 }
235
236 /^Enum/ {
237         change_block("Enum", "Sysreg", "Enum")
238         expect_fields(3)
239         field = $3
240         parse_bitdef(reg, field, $2)
241
242         define_field(reg, field, msb, lsb)
243
244         next
245 }
246
247 /^EndEnum/ {
248         change_block("EndEnum", "Enum", "Sysreg")
249         field = null
250         msb = null
251         lsb = null
252         print ""
253         next
254 }
255
256 /0b[01]+/ && block == "Enum" {
257         expect_fields(2)
258         val = $1
259         name = $2
260
261         define(reg "_" field "_" name, "UL(" val ")")
262         next
263 }
264
265 # Any lines not handled by previous rules are unexpected
266 {
267         fatal("unhandled statement")
268 }