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} 412