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(name, val) { 48 printf "%-56s%s\n", "#define " name, val 49} 50 51# Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field 52function 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) 57} 58 59# Print a field _SIGNED definition for a field 60function define_field_sign(reg, field, sign) { 61 define(reg "_" field "_SIGNED", sign) 62} 63 64# Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb 65function parse_bitdef(reg, field, bitdef, _bits) 66{ 67 if (bitdef ~ /^[0-9]+$/) { 68 msb = bitdef 69 lsb = bitdef 70 } else if (split(bitdef, _bits, ":") == 2) { 71 msb = _bits[1] 72 lsb = _bits[2] 73 } else { 74 fatal("invalid bit-range definition '" bitdef "'") 75 } 76 77 78 if (msb != next_bit) 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 "'") 84 if (msb < lsb) 85 fatal(reg "." field " invalid bit-range '" bitdef "'") 86 if (low > high) 87 fatal(reg "." field " has invalid range " high "-" low) 88 89 next_bit = lsb - 1 90} 91 92BEGIN { 93 print "#ifndef __ASM_SYSREG_DEFS_H" 94 print "#define __ASM_SYSREG_DEFS_H" 95 print "" 96 print "/* Generated file - do not edit */" 97 print "" 98 99 __current_block_depth = 0 100 __current_block[__current_block_depth] = "Root" 101} 102 103END { 104 if (__current_block_depth != 0) 105 fatal("Missing terminator for " block_current() " block") 106 107 print "#endif /* __ASM_SYSREG_DEFS_H */" 108} 109 110# skip blank lines and comment lines 111/^$/ { next } 112/^[\t ]*#/ { next } 113 114$1 == "SysregFields" && block_current() == "Root" { 115 block_push("SysregFields") 116 117 expect_fields(2) 118 119 reg = $2 120 121 res0 = "UL(0)" 122 res1 = "UL(0)" 123 unkn = "UL(0)" 124 125 if (reg in defined_fields) 126 fatal("Duplicate SysregFields definition for " reg) 127 defined_fields[reg] = 1 128 129 next_bit = 63 130 131 next 132} 133 134$1 == "EndSysregFields" && block_current() == "SysregFields" { 135 expect_fields(1) 136 if (next_bit > 0) 137 fatal("Unspecified bits in " reg) 138 139 define(reg "_RES0", "(" res0 ")") 140 define(reg "_RES1", "(" res1 ")") 141 define(reg "_UNKN", "(" unkn ")") 142 print "" 143 144 reg = null 145 res0 = null 146 res1 = null 147 unkn = null 148 149 block_pop() 150 next 151} 152 153$1 == "Sysreg" && block_current() == "Root" { 154 block_push("Sysreg") 155 156 expect_fields(7) 157 158 reg = $2 159 op0 = $3 160 op1 = $4 161 crn = $5 162 crm = $6 163 op2 = $7 164 165 res0 = "UL(0)" 166 res1 = "UL(0)" 167 unkn = "UL(0)" 168 169 if (reg in defined_regs) 170 fatal("Duplicate Sysreg definition for " reg) 171 defined_regs[reg] = 1 172 173 define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2) 174 define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")") 175 176 define("SYS_" reg "_Op0", op0) 177 define("SYS_" reg "_Op1", op1) 178 define("SYS_" reg "_CRn", crn) 179 define("SYS_" reg "_CRm", crm) 180 define("SYS_" reg "_Op2", op2) 181 182 print "" 183 184 next_bit = 63 185 186 next 187} 188 189$1 == "EndSysreg" && block_current() == "Sysreg" { 190 expect_fields(1) 191 if (next_bit > 0) 192 fatal("Unspecified bits in " reg) 193 194 if (res0 != null) 195 define(reg "_RES0", "(" res0 ")") 196 if (res1 != null) 197 define(reg "_RES1", "(" res1 ")") 198 if (unkn != null) 199 define(reg "_UNKN", "(" unkn ")") 200 if (res0 != null || res1 != null || unkn != null) 201 print "" 202 203 reg = null 204 op0 = null 205 op1 = null 206 crn = null 207 crm = null 208 op2 = null 209 res0 = null 210 res1 = null 211 unkn = null 212 213 block_pop() 214 next 215} 216 217# Currently this is effectivey a comment, in future we may want to emit 218# defines for the fields. 219($1 == "Fields" || $1 == "Mapping") && block_current() == "Sysreg" { 220 expect_fields(2) 221 222 if (next_bit != 63) 223 fatal("Some fields already defined for " reg) 224 225 print "/* For " reg " fields see " $2 " */" 226 print "" 227 228 next_bit = 0 229 res0 = null 230 res1 = null 231 unkn = null 232 233 next 234} 235 236 237$1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 238 expect_fields(2) 239 parse_bitdef(reg, "RES0", $2) 240 field = "RES0_" msb "_" lsb 241 242 res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")" 243 244 next 245} 246 247$1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 248 expect_fields(2) 249 parse_bitdef(reg, "RES1", $2) 250 field = "RES1_" msb "_" lsb 251 252 res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")" 253 254 next 255} 256 257$1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 258 expect_fields(2) 259 parse_bitdef(reg, "UNKN", $2) 260 field = "UNKN_" msb "_" lsb 261 262 unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")" 263 264 next 265} 266 267$1 == "Field" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 268 expect_fields(3) 269 field = $3 270 parse_bitdef(reg, field, $2) 271 272 define_field(reg, field, msb, lsb) 273 print "" 274 275 next 276} 277 278$1 == "Raz" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 279 expect_fields(2) 280 parse_bitdef(reg, field, $2) 281 282 next 283} 284 285$1 == "SignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 286 block_push("Enum") 287 288 expect_fields(3) 289 field = $3 290 parse_bitdef(reg, field, $2) 291 292 define_field(reg, field, msb, lsb) 293 define_field_sign(reg, field, "true") 294 295 delete seen_enum_vals 296 297 next 298} 299 300$1 == "UnsignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 301 block_push("Enum") 302 303 expect_fields(3) 304 field = $3 305 parse_bitdef(reg, field, $2) 306 307 define_field(reg, field, msb, lsb) 308 define_field_sign(reg, field, "false") 309 310 delete seen_enum_vals 311 312 next 313} 314 315$1 == "Enum" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 316 block_push("Enum") 317 318 expect_fields(3) 319 field = $3 320 parse_bitdef(reg, field, $2) 321 322 define_field(reg, field, msb, lsb) 323 324 delete seen_enum_vals 325 326 next 327} 328 329$1 == "EndEnum" && block_current() == "Enum" { 330 expect_fields(1) 331 332 field = null 333 msb = null 334 lsb = null 335 print "" 336 337 delete seen_enum_vals 338 339 block_pop() 340 next 341} 342 343/0b[01]+/ && block_current() == "Enum" { 344 expect_fields(2) 345 val = $1 346 name = $2 347 348 if (val in seen_enum_vals) 349 fatal("Duplicate Enum value " val " for " name) 350 seen_enum_vals[val] = 1 351 352 define(reg "_" field "_" name, "UL(" val ")") 353 next 354} 355 356# Any lines not handled by previous rules are unexpected 357{ 358 fatal("unhandled statement") 359} 360