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