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 7# Log an error and terminate 8function fatal(msg) { 9 print "Error at " NR ": " msg > "/dev/stderr" 10 exit 1 11} 12 13# Sanity check that the start or end of a block makes sense at this point in 14# the file. If not, produce an error and terminate. 15# 16# @this - the $Block or $EndBlock 17# @prev - the only valid block to already be in (value of @block) 18# @new - the new value of @block 19function change_block(this, prev, new) { 20 if (block != prev) 21 fatal("unexpected " this " (inside " block ")") 22 23 block = new 24} 25 26# Sanity check the number of records for a field makes sense. If not, produce 27# an error and terminate. 28function expect_fields(nf) { 29 if (NF != nf) 30 fatal(NF " fields found where " nf " expected") 31} 32 33# Print a CPP macro definition, padded with spaces so that the macro bodies 34# line up in a column 35function define(name, val) { 36 printf "%-56s%s\n", "#define " name, val 37} 38 39# Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field 40function define_field(reg, field, msb, lsb) { 41 define(reg "_" field, "GENMASK(" msb ", " lsb ")") 42 define(reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")") 43 define(reg "_" field "_SHIFT", lsb) 44 define(reg "_" field "_WIDTH", msb - lsb + 1) 45} 46 47# Print a field _SIGNED definition for a field 48function define_field_sign(reg, field, sign) { 49 define(reg "_" field "_SIGNED", sign) 50} 51 52# Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb 53function parse_bitdef(reg, field, bitdef, _bits) 54{ 55 if (bitdef ~ /^[0-9]+$/) { 56 msb = bitdef 57 lsb = bitdef 58 } else if (split(bitdef, _bits, ":") == 2) { 59 msb = _bits[1] 60 lsb = _bits[2] 61 } else { 62 fatal("invalid bit-range definition '" bitdef "'") 63 } 64 65 66 if (msb != next_bit) 67 fatal(reg "." field " starts at " msb " not " next_bit) 68 if (63 < msb || msb < 0) 69 fatal(reg "." field " invalid high bit in '" bitdef "'") 70 if (63 < lsb || lsb < 0) 71 fatal(reg "." field " invalid low bit in '" bitdef "'") 72 if (msb < lsb) 73 fatal(reg "." field " invalid bit-range '" bitdef "'") 74 if (low > high) 75 fatal(reg "." field " has invalid range " high "-" low) 76 77 next_bit = lsb - 1 78} 79 80BEGIN { 81 print "#ifndef __ASM_SYSREG_DEFS_H" 82 print "#define __ASM_SYSREG_DEFS_H" 83 print "" 84 print "/* Generated file - do not edit */" 85 print "" 86 87 block = "None" 88} 89 90END { 91 print "#endif /* __ASM_SYSREG_DEFS_H */" 92} 93 94# skip blank lines and comment lines 95/^$/ { next } 96/^[\t ]*#/ { next } 97 98/^SysregFields/ { 99 change_block("SysregFields", "None", "SysregFields") 100 expect_fields(2) 101 102 reg = $2 103 104 res0 = "UL(0)" 105 res1 = "UL(0)" 106 unkn = "UL(0)" 107 108 next_bit = 63 109 110 next 111} 112 113/^EndSysregFields/ { 114 if (next_bit > 0) 115 fatal("Unspecified bits in " reg) 116 117 change_block("EndSysregFields", "SysregFields", "None") 118 119 define(reg "_RES0", "(" res0 ")") 120 define(reg "_RES1", "(" res1 ")") 121 define(reg "_UNKN", "(" unkn ")") 122 print "" 123 124 reg = null 125 res0 = null 126 res1 = null 127 unkn = null 128 129 next 130} 131 132/^Sysreg/ { 133 change_block("Sysreg", "None", "Sysreg") 134 expect_fields(7) 135 136 reg = $2 137 op0 = $3 138 op1 = $4 139 crn = $5 140 crm = $6 141 op2 = $7 142 143 res0 = "UL(0)" 144 res1 = "UL(0)" 145 unkn = "UL(0)" 146 147 define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2) 148 define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")") 149 150 define("SYS_" reg "_Op0", op0) 151 define("SYS_" reg "_Op1", op1) 152 define("SYS_" reg "_CRn", crn) 153 define("SYS_" reg "_CRm", crm) 154 define("SYS_" reg "_Op2", op2) 155 156 print "" 157 158 next_bit = 63 159 160 next 161} 162 163/^EndSysreg/ { 164 if (next_bit > 0) 165 fatal("Unspecified bits in " reg) 166 167 change_block("EndSysreg", "Sysreg", "None") 168 169 if (res0 != null) 170 define(reg "_RES0", "(" res0 ")") 171 if (res1 != null) 172 define(reg "_RES1", "(" res1 ")") 173 if (unkn != null) 174 define(reg "_UNKN", "(" unkn ")") 175 if (res0 != null || res1 != null || unkn != null) 176 print "" 177 178 reg = null 179 op0 = null 180 op1 = null 181 crn = null 182 crm = null 183 op2 = null 184 res0 = null 185 res1 = null 186 unkn = null 187 188 next 189} 190 191# Currently this is effectivey a comment, in future we may want to emit 192# defines for the fields. 193/^Fields/ && (block == "Sysreg") { 194 expect_fields(2) 195 196 if (next_bit != 63) 197 fatal("Some fields already defined for " reg) 198 199 print "/* For " reg " fields see " $2 " */" 200 print "" 201 202 next_bit = 0 203 res0 = null 204 res1 = null 205 unkn = null 206 207 next 208} 209 210 211/^Res0/ && (block == "Sysreg" || block == "SysregFields") { 212 expect_fields(2) 213 parse_bitdef(reg, "RES0", $2) 214 field = "RES0_" msb "_" lsb 215 216 res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")" 217 218 next 219} 220 221/^Res1/ && (block == "Sysreg" || block == "SysregFields") { 222 expect_fields(2) 223 parse_bitdef(reg, "RES1", $2) 224 field = "RES1_" msb "_" lsb 225 226 res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")" 227 228 next 229} 230 231/^Unkn/ && (block == "Sysreg" || block == "SysregFields") { 232 expect_fields(2) 233 parse_bitdef(reg, "UNKN", $2) 234 field = "UNKN_" msb "_" lsb 235 236 unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")" 237 238 next 239} 240 241/^Field/ && (block == "Sysreg" || block == "SysregFields") { 242 expect_fields(3) 243 field = $3 244 parse_bitdef(reg, field, $2) 245 246 define_field(reg, field, msb, lsb) 247 print "" 248 249 next 250} 251 252/^Raz/ && (block == "Sysreg" || block == "SysregFields") { 253 expect_fields(2) 254 parse_bitdef(reg, field, $2) 255 256 next 257} 258 259/^SignedEnum/ { 260 change_block("Enum<", "Sysreg", "Enum") 261 expect_fields(3) 262 field = $3 263 parse_bitdef(reg, field, $2) 264 265 define_field(reg, field, msb, lsb) 266 define_field_sign(reg, field, "true") 267 268 next 269} 270 271/^UnsignedEnum/ { 272 change_block("Enum<", "Sysreg", "Enum") 273 expect_fields(3) 274 field = $3 275 parse_bitdef(reg, field, $2) 276 277 define_field(reg, field, msb, lsb) 278 define_field_sign(reg, field, "false") 279 280 next 281} 282 283/^Enum/ { 284 change_block("Enum", "Sysreg", "Enum") 285 expect_fields(3) 286 field = $3 287 parse_bitdef(reg, field, $2) 288 289 define_field(reg, field, msb, lsb) 290 291 next 292} 293 294/^EndEnum/ { 295 change_block("EndEnum", "Enum", "Sysreg") 296 field = null 297 msb = null 298 lsb = null 299 print "" 300 next 301} 302 303/0b[01]+/ && block == "Enum" { 304 expect_fields(2) 305 val = $1 306 name = $2 307 308 define(reg "_" field "_" name, "UL(" val ")") 309 next 310} 311 312# Any lines not handled by previous rules are unexpected 313{ 314 fatal("unhandled statement") 315} 316