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/^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 next_bit = 63 126 127 next 128} 129 130/^EndSysregFields/ && block_current() == "SysregFields" { 131 if (next_bit > 0) 132 fatal("Unspecified bits in " reg) 133 134 define(reg "_RES0", "(" res0 ")") 135 define(reg "_RES1", "(" res1 ")") 136 define(reg "_UNKN", "(" unkn ")") 137 print "" 138 139 reg = null 140 res0 = null 141 res1 = null 142 unkn = null 143 144 block_pop() 145 next 146} 147 148/^Sysreg/ && block_current() == "Root" { 149 block_push("Sysreg") 150 151 expect_fields(7) 152 153 reg = $2 154 op0 = $3 155 op1 = $4 156 crn = $5 157 crm = $6 158 op2 = $7 159 160 res0 = "UL(0)" 161 res1 = "UL(0)" 162 unkn = "UL(0)" 163 164 define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2) 165 define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")") 166 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) 172 173 print "" 174 175 next_bit = 63 176 177 next 178} 179 180/^EndSysreg/ && block_current() == "Sysreg" { 181 if (next_bit > 0) 182 fatal("Unspecified bits in " reg) 183 184 if (res0 != null) 185 define(reg "_RES0", "(" res0 ")") 186 if (res1 != null) 187 define(reg "_RES1", "(" res1 ")") 188 if (unkn != null) 189 define(reg "_UNKN", "(" unkn ")") 190 if (res0 != null || res1 != null || unkn != null) 191 print "" 192 193 reg = null 194 op0 = null 195 op1 = null 196 crn = null 197 crm = null 198 op2 = null 199 res0 = null 200 res1 = null 201 unkn = null 202 203 block_pop() 204 next 205} 206 207# Currently this is effectivey a comment, in future we may want to emit 208# defines for the fields. 209/^Fields/ && block_current() == "Sysreg" { 210 expect_fields(2) 211 212 if (next_bit != 63) 213 fatal("Some fields already defined for " reg) 214 215 print "/* For " reg " fields see " $2 " */" 216 print "" 217 218 next_bit = 0 219 res0 = null 220 res1 = null 221 unkn = null 222 223 next 224} 225 226 227/^Res0/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 228 expect_fields(2) 229 parse_bitdef(reg, "RES0", $2) 230 field = "RES0_" msb "_" lsb 231 232 res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")" 233 234 next 235} 236 237/^Res1/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 238 expect_fields(2) 239 parse_bitdef(reg, "RES1", $2) 240 field = "RES1_" msb "_" lsb 241 242 res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")" 243 244 next 245} 246 247/^Unkn/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 248 expect_fields(2) 249 parse_bitdef(reg, "UNKN", $2) 250 field = "UNKN_" msb "_" lsb 251 252 unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")" 253 254 next 255} 256 257/^Field/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 258 expect_fields(3) 259 field = $3 260 parse_bitdef(reg, field, $2) 261 262 define_field(reg, field, msb, lsb) 263 print "" 264 265 next 266} 267 268/^Raz/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 269 expect_fields(2) 270 parse_bitdef(reg, field, $2) 271 272 next 273} 274 275/^SignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 276 block_push("Enum") 277 278 expect_fields(3) 279 field = $3 280 parse_bitdef(reg, field, $2) 281 282 define_field(reg, field, msb, lsb) 283 define_field_sign(reg, field, "true") 284 285 next 286} 287 288/^UnsignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 289 block_push("Enum") 290 291 expect_fields(3) 292 field = $3 293 parse_bitdef(reg, field, $2) 294 295 define_field(reg, field, msb, lsb) 296 define_field_sign(reg, field, "false") 297 298 next 299} 300 301/^Enum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 302 block_push("Enum") 303 304 expect_fields(3) 305 field = $3 306 parse_bitdef(reg, field, $2) 307 308 define_field(reg, field, msb, lsb) 309 310 next 311} 312 313/^EndEnum/ && block_current() == "Enum" { 314 315 field = null 316 msb = null 317 lsb = null 318 print "" 319 320 block_pop() 321 next 322} 323 324/0b[01]+/ && block_current() == "Enum" { 325 expect_fields(2) 326 val = $1 327 name = $2 328 329 define(reg "_" field "_" name, "UL(" val ")") 330 next 331} 332 333# Any lines not handled by previous rules are unexpected 334{ 335 fatal("unhandled statement") 336} 337