2 # SPDX-License-Identifier: GPL-2.0
3 # gen-sysreg.awk: arm64 sysreg header generator
5 # Usage: awk -f gen-sysreg.awk sysregs.txt
7 function block_current() {
8 return __current_block[__current_block_depth];
11 # Log an error and terminate
13 print "Error at " NR ": " msg > "/dev/stderr"
15 printf "Current block nesting:"
17 for (i = 0; i <= __current_block_depth; i++) {
18 printf " " __current_block[i]
25 # Enter a new block, setting the active block to @block
26 function block_push(block) {
27 __current_block[++__current_block_depth] = block
30 # Exit a block, setting the active block to the parent block
31 function block_pop() {
32 if (__current_block_depth == 0)
33 fatal("error: block_pop() in root block")
35 __current_block_depth--;
38 # Sanity check the number of records for a field makes sense. If not, produce
39 # an error and terminate.
40 function expect_fields(nf) {
42 fatal(NF " fields found where " nf " expected")
45 # Print a CPP macro definition, padded with spaces so that the macro bodies
47 function define(name, val) {
48 printf "%-56s%s\n", "#define " name, val
51 # Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field
52 function define_field(reg, field, msb, lsb) {
53 define(reg "_" field, "GENMASK(" msb ", " lsb ")")
54 define(reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")")
55 define(reg "_" field "_SHIFT", lsb)
56 define(reg "_" field "_WIDTH", msb - lsb + 1)
59 # Print a field _SIGNED definition for a field
60 function define_field_sign(reg, field, sign) {
61 define(reg "_" field "_SIGNED", sign)
64 # Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb
65 function parse_bitdef(reg, field, bitdef, _bits)
67 if (bitdef ~ /^[0-9]+$/) {
70 } else if (split(bitdef, _bits, ":") == 2) {
74 fatal("invalid bit-range definition '" bitdef "'")
79 fatal(reg "." field " starts at " msb " not " next_bit)
80 if (63 < msb || msb < 0)
81 fatal(reg "." field " invalid high bit in '" bitdef "'")
82 if (63 < lsb || lsb < 0)
83 fatal(reg "." field " invalid low bit in '" bitdef "'")
85 fatal(reg "." field " invalid bit-range '" bitdef "'")
87 fatal(reg "." field " has invalid range " high "-" low)
93 print "#ifndef __ASM_SYSREG_DEFS_H"
94 print "#define __ASM_SYSREG_DEFS_H"
96 print "/* Generated file - do not edit */"
99 __current_block_depth = 0
100 __current_block[__current_block_depth] = "Root"
104 if (__current_block_depth != 0)
105 fatal("Missing terminator for " block_current() " block")
107 print "#endif /* __ASM_SYSREG_DEFS_H */"
110 # skip blank lines and comment lines
114 /^SysregFields/ && block_current() == "Root" {
115 block_push("SysregFields")
130 /^EndSysregFields/ && block_current() == "SysregFields" {
132 fatal("Unspecified bits in " reg)
134 define(reg "_RES0", "(" res0 ")")
135 define(reg "_RES1", "(" res1 ")")
136 define(reg "_UNKN", "(" unkn ")")
148 /^Sysreg/ && block_current() == "Root" {
164 define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2)
165 define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")")
167 define("SYS_" reg "_Op0", op0)
168 define("SYS_" reg "_Op1", op1)
169 define("SYS_" reg "_CRn", crn)
170 define("SYS_" reg "_CRm", crm)
171 define("SYS_" reg "_Op2", op2)
180 /^EndSysreg/ && block_current() == "Sysreg" {
182 fatal("Unspecified bits in " reg)
185 define(reg "_RES0", "(" res0 ")")
187 define(reg "_RES1", "(" res1 ")")
189 define(reg "_UNKN", "(" unkn ")")
190 if (res0 != null || res1 != null || unkn != null)
207 # Currently this is effectivey a comment, in future we may want to emit
208 # defines for the fields.
209 /^Fields/ && block_current() == "Sysreg" {
213 fatal("Some fields already defined for " reg)
215 print "/* For " reg " fields see " $2 " */"
227 /^Res0/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
229 parse_bitdef(reg, "RES0", $2)
230 field = "RES0_" msb "_" lsb
232 res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")"
237 /^Res1/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
239 parse_bitdef(reg, "RES1", $2)
240 field = "RES1_" msb "_" lsb
242 res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")"
247 /^Unkn/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
249 parse_bitdef(reg, "UNKN", $2)
250 field = "UNKN_" msb "_" lsb
252 unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")"
257 /^Field/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
260 parse_bitdef(reg, field, $2)
262 define_field(reg, field, msb, lsb)
268 /^Raz/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
270 parse_bitdef(reg, field, $2)
275 /^SignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
280 parse_bitdef(reg, field, $2)
282 define_field(reg, field, msb, lsb)
283 define_field_sign(reg, field, "true")
288 /^UnsignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
293 parse_bitdef(reg, field, $2)
295 define_field(reg, field, msb, lsb)
296 define_field_sign(reg, field, "false")
301 /^Enum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
306 parse_bitdef(reg, field, $2)
308 define_field(reg, field, msb, lsb)
313 /^EndEnum/ && block_current() == "Enum" {
324 /0b[01]+/ && block_current() == "Enum" {
329 define(reg "_" field "_" name, "UL(" val ")")
333 # Any lines not handled by previous rules are unexpected
335 fatal("unhandled statement")