Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
7function block_current() {
8 return __current_block[__current_block_depth];
9}
10
11# Log an error and terminate
12function fatal(msg) {
13 print "Error at " NR ": " msg > "/dev/stderr"
14
15 printf "Current block nesting:"
16
17 for (i = 0; i <= __current_block_depth; i++) {
18 printf " " __current_block[i]
19 }
20 printf "\n"
21
22 exit 1
23}
24
25# Enter a new block, setting the active block to @block
26function block_push(block) {
27 __current_block[++__current_block_depth] = block
28}
29
30# Exit a block, setting the active block to the parent block
31function block_pop() {
32 if (__current_block_depth == 0)
33 fatal("error: block_pop() in root block")
34
35 __current_block_depth--;
36}
37
38# Sanity check the number of records for a field makes sense. If not, produce
39# an error and terminate.
40function expect_fields(nf) {
41 if (NF != nf)
42 fatal(NF " fields found where " nf " expected")
43}
44
45# Print a CPP macro definition, padded with spaces so that the macro bodies
46# line up in a column
47function define(prefix, name, val) {
48 printf "%-56s%s\n", "#define " prefix name, val
49}
50
51# Same as above, but without a prefix
52function define_reg(name, val) {
53 define(null, name, val)
54}
55
56# Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field
57function define_field(prefix, reg, field, msb, lsb) {
58 define(prefix, reg "_" field, "GENMASK(" msb ", " lsb ")")
59 define(prefix, reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")")
60 define(prefix, reg "_" field "_SHIFT", lsb)
61 define(prefix, reg "_" field "_WIDTH", msb - lsb + 1)
62}
63
64# Print a field _SIGNED definition for a field
65function define_field_sign(prefix, reg, field, sign) {
66 define(prefix, reg "_" field "_SIGNED", sign)
67}
68
69# Print the Res0, Res1, Unkn masks
70function define_resx_unkn(prefix, reg, res0, res1, unkn) {
71 if (res0 != null)
72 define(prefix, reg "_RES0", "(" res0 ")")
73 if (res1 != null)
74 define(prefix, reg "_RES1", "(" res1 ")")
75 if (unkn != null)
76 define(prefix, reg "_UNKN", "(" unkn ")")
77 if (res0 != null || res1 != null || unkn != null)
78 print ""
79}
80
81# Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb
82function parse_bitdef(reg, field, bitdef, _bits)
83{
84 if (bitdef ~ /^[0-9]+$/) {
85 msb = bitdef
86 lsb = bitdef
87 } else if (split(bitdef, _bits, ":") == 2) {
88 msb = _bits[1]
89 lsb = _bits[2]
90 } else {
91 fatal("invalid bit-range definition '" bitdef "'")
92 }
93
94
95 if (msb != next_bit)
96 fatal(reg "." field " starts at " msb " not " next_bit)
97 if (63 < msb || msb < 0)
98 fatal(reg "." field " invalid high bit in '" bitdef "'")
99 if (63 < lsb || lsb < 0)
100 fatal(reg "." field " invalid low bit in '" bitdef "'")
101 if (msb < lsb)
102 fatal(reg "." field " invalid bit-range '" bitdef "'")
103 if (low > high)
104 fatal(reg "." field " has invalid range " high "-" low)
105
106 next_bit = lsb - 1
107}
108
109BEGIN {
110 print "#ifndef __ASM_SYSREG_DEFS_H"
111 print "#define __ASM_SYSREG_DEFS_H"
112 print ""
113 print "/* Generated file - do not edit */"
114 print ""
115
116 __current_block_depth = 0
117 __current_block[__current_block_depth] = "Root"
118}
119
120END {
121 if (__current_block_depth != 0)
122 fatal("Missing terminator for " block_current() " block")
123
124 print "#endif /* __ASM_SYSREG_DEFS_H */"
125}
126
127# skip blank lines and comment lines
128/^$/ { next }
129/^[\t ]*#/ { next }
130
131$1 == "SysregFields" && block_current() == "Root" {
132 block_push("SysregFields")
133
134 expect_fields(2)
135
136 reg = $2
137
138 res0 = "UL(0)"
139 res1 = "UL(0)"
140 unkn = "UL(0)"
141
142 if (reg in defined_fields)
143 fatal("Duplicate SysregFields definition for " reg)
144 defined_fields[reg] = 1
145
146 next_bit = 63
147
148 delete seen_prefixes
149
150 next
151}
152
153$1 == "EndSysregFields" && block_current() == "SysregFields" {
154 expect_fields(1)
155 if (next_bit >= 0)
156 fatal("Unspecified bits in " reg)
157
158 define_resx_unkn(prefix, reg, res0, res1, unkn)
159
160 reg = null
161 res0 = null
162 res1 = null
163 unkn = null
164
165 block_pop()
166 next
167}
168
169$1 == "Sysreg" && block_current() == "Root" {
170 block_push("Sysreg")
171
172 expect_fields(7)
173
174 reg = $2
175 op0 = $3
176 op1 = $4
177 crn = $5
178 crm = $6
179 op2 = $7
180
181 res0 = "UL(0)"
182 res1 = "UL(0)"
183 unkn = "UL(0)"
184
185 if (reg in defined_regs)
186 fatal("Duplicate Sysreg definition for " reg)
187 defined_regs[reg] = 1
188
189 define_reg("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2)
190 define_reg("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")")
191
192 define_reg("SYS_" reg "_Op0", op0)
193 define_reg("SYS_" reg "_Op1", op1)
194 define_reg("SYS_" reg "_CRn", crn)
195 define_reg("SYS_" reg "_CRm", crm)
196 define_reg("SYS_" reg "_Op2", op2)
197
198 print ""
199
200 prefix = null
201 next_bit = 63
202
203 delete seen_prefixes
204
205 next
206}
207
208$1 == "EndSysreg" && block_current() == "Sysreg" {
209 expect_fields(1)
210 if (next_bit >= 0)
211 fatal("Unspecified bits in " reg)
212
213 define_resx_unkn(prefix, reg, res0, res1, unkn)
214
215 reg = null
216 op0 = null
217 op1 = null
218 crn = null
219 crm = null
220 op2 = null
221 res0 = null
222 res1 = null
223 unkn = null
224 prefix = null
225
226 block_pop()
227 next
228}
229
230# Currently this is effectivey a comment, in future we may want to emit
231# defines for the fields.
232($1 == "Fields" || $1 == "Mapping") && block_current() == "Sysreg" {
233 expect_fields(2)
234
235 if (next_bit != 63)
236 fatal("Some fields already defined for " reg)
237
238 print "/* For " reg " fields see " $2 " */"
239 print ""
240
241 next_bit = -1
242 res0 = null
243 res1 = null
244 unkn = null
245
246 next
247}
248
249$1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
250 expect_fields(2)
251 parse_bitdef(reg, "RES0", $2)
252 field = "RES0_" msb "_" lsb
253
254 res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")"
255
256 next
257}
258
259$1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
260 expect_fields(2)
261 parse_bitdef(reg, "RES1", $2)
262 field = "RES1_" msb "_" lsb
263
264 res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")"
265
266 next
267}
268
269$1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
270 expect_fields(2)
271 parse_bitdef(reg, "UNKN", $2)
272 field = "UNKN_" msb "_" lsb
273
274 unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")"
275
276 next
277}
278
279$1 == "Field" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
280 expect_fields(3)
281 field = $3
282 parse_bitdef(reg, field, $2)
283
284 define_field(prefix, reg, field, msb, lsb)
285 print ""
286
287 next
288}
289
290$1 == "Raz" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
291 expect_fields(2)
292 parse_bitdef(reg, field, $2)
293
294 next
295}
296
297$1 == "SignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
298 block_push("Enum")
299
300 expect_fields(3)
301 field = $3
302 parse_bitdef(reg, field, $2)
303
304 define_field(prefix, reg, field, msb, lsb)
305 define_field_sign(prefix, reg, field, "true")
306
307 delete seen_enum_vals
308
309 next
310}
311
312$1 == "UnsignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
313 block_push("Enum")
314
315 expect_fields(3)
316 field = $3
317 parse_bitdef(reg, field, $2)
318
319 define_field(prefix, reg, field, msb, lsb)
320 define_field_sign(prefix, reg, field, "false")
321
322 delete seen_enum_vals
323
324 next
325}
326
327$1 == "Enum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
328 block_push("Enum")
329
330 expect_fields(3)
331 field = $3
332 parse_bitdef(reg, field, $2)
333
334 define_field(prefix, reg, field, msb, lsb)
335
336 delete seen_enum_vals
337
338 next
339}
340
341$1 == "EndEnum" && block_current() == "Enum" {
342 expect_fields(1)
343
344 field = null
345 msb = null
346 lsb = null
347 print ""
348
349 delete seen_enum_vals
350
351 block_pop()
352 next
353}
354
355/0b[01]+/ && block_current() == "Enum" {
356 expect_fields(2)
357 val = $1
358 name = $2
359
360 if (val in seen_enum_vals)
361 fatal("Duplicate Enum value " val " for " name)
362 seen_enum_vals[val] = 1
363
364 define(prefix, reg "_" field "_" name, "UL(" val ")")
365 next
366}
367
368$1 == "Prefix" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
369 block_push("Prefix")
370
371 expect_fields(2)
372
373 if (next_bit < 63)
374 fatal("Prefixed fields must precede non-prefixed fields (" reg ")")
375
376 prefix = $2 "_"
377
378 if (prefix in seen_prefixes)
379 fatal("Duplicate prefix " prefix " for " reg)
380 seen_prefixes[prefix] = 1
381
382 res0 = "UL(0)"
383 res1 = "UL(0)"
384 unkn = "UL(0)"
385 next_bit = 63
386
387 next
388}
389
390$1 == "EndPrefix" && block_current() == "Prefix" {
391 expect_fields(1)
392 if (next_bit >= 0)
393 fatal("Unspecified bits in prefix " prefix " for " reg)
394
395 define_resx_unkn(prefix, reg, res0, res1, unkn)
396
397 prefix = null
398 res0 = "UL(0)"
399 res1 = "UL(0)"
400 unkn = "UL(0)"
401 next_bit = 63
402
403 block_pop()
404
405 next
406}
407
408# Any lines not handled by previous rules are unexpected
409{
410 fatal("unhandled statement")
411}