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