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 "%-48s%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# Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb 48function parse_bitdef(reg, field, bitdef, _bits) 49{ 50 if (bitdef ~ /^[0-9]+$/) { 51 msb = bitdef 52 lsb = bitdef 53 } else if (split(bitdef, _bits, ":") == 2) { 54 msb = _bits[1] 55 lsb = _bits[2] 56 } else { 57 fatal("invalid bit-range definition '" bitdef "'") 58 } 59 60 61 if (msb != next_bit) 62 fatal(reg "." field " starts at " msb " not " next_bit) 63 if (63 < msb || msb < 0) 64 fatal(reg "." field " invalid high bit in '" bitdef "'") 65 if (63 < lsb || lsb < 0) 66 fatal(reg "." field " invalid low bit in '" bitdef "'") 67 if (msb < lsb) 68 fatal(reg "." field " invalid bit-range '" bitdef "'") 69 if (low > high) 70 fatal(reg "." field " has invalid range " high "-" low) 71 72 next_bit = lsb - 1 73} 74 75BEGIN { 76 print "#ifndef __ASM_SYSREG_DEFS_H" 77 print "#define __ASM_SYSREG_DEFS_H" 78 print "" 79 print "/* Generated file - do not edit */" 80 print "" 81 82 block = "None" 83} 84 85END { 86 print "#endif /* __ASM_SYSREG_DEFS_H */" 87} 88 89# skip blank lines and comment lines 90/^$/ { next } 91/^#/ { next } 92 93/^SysregFields/ { 94 change_block("SysregFields", "None", "SysregFields") 95 expect_fields(2) 96 97 reg = $2 98 99 res0 = "UL(0)" 100 res1 = "UL(0)" 101 102 next_bit = 63 103 104 next 105} 106 107/^EndSysregFields/ { 108 if (next_bit > 0) 109 fatal("Unspecified bits in " reg) 110 111 change_block("EndSysregFields", "SysregFields", "None") 112 113 define(reg "_RES0", "(" res0 ")") 114 define(reg "_RES1", "(" res1 ")") 115 print "" 116 117 reg = null 118 res0 = null 119 res1 = null 120 121 next 122} 123 124/^Sysreg/ { 125 change_block("Sysreg", "None", "Sysreg") 126 expect_fields(7) 127 128 reg = $2 129 op0 = $3 130 op1 = $4 131 crn = $5 132 crm = $6 133 op2 = $7 134 135 res0 = "UL(0)" 136 res1 = "UL(0)" 137 138 define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2) 139 define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")") 140 141 define("SYS_" reg "_Op0", op0) 142 define("SYS_" reg "_Op1", op1) 143 define("SYS_" reg "_CRn", crn) 144 define("SYS_" reg "_CRm", crm) 145 define("SYS_" reg "_Op2", op2) 146 147 print "" 148 149 next_bit = 63 150 151 next 152} 153 154/^EndSysreg/ { 155 if (next_bit > 0) 156 fatal("Unspecified bits in " reg) 157 158 change_block("EndSysreg", "Sysreg", "None") 159 160 if (res0 != null) 161 define(reg "_RES0", "(" res0 ")") 162 if (res1 != null) 163 define(reg "_RES1", "(" res1 ")") 164 if (res0 != null || res1 != null) 165 print "" 166 167 reg = null 168 op0 = null 169 op1 = null 170 crn = null 171 crm = null 172 op2 = null 173 res0 = null 174 res1 = null 175 176 next 177} 178 179# Currently this is effectivey a comment, in future we may want to emit 180# defines for the fields. 181/^Fields/ && (block == "Sysreg") { 182 expect_fields(2) 183 184 if (next_bit != 63) 185 fatal("Some fields already defined for " reg) 186 187 print "/* For " reg " fields see " $2 " */" 188 print "" 189 190 next_bit = 0 191 res0 = null 192 res1 = null 193 194 next 195} 196 197 198/^Res0/ && (block == "Sysreg" || block == "SysregFields") { 199 expect_fields(2) 200 parse_bitdef(reg, "RES0", $2) 201 field = "RES0_" msb "_" lsb 202 203 res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")" 204 205 next 206} 207 208/^Res1/ && (block == "Sysreg" || block == "SysregFields") { 209 expect_fields(2) 210 parse_bitdef(reg, "RES1", $2) 211 field = "RES1_" msb "_" lsb 212 213 res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")" 214 215 next 216} 217 218/^Field/ && (block == "Sysreg" || block == "SysregFields") { 219 expect_fields(3) 220 field = $3 221 parse_bitdef(reg, field, $2) 222 223 define_field(reg, field, msb, lsb) 224 print "" 225 226 next 227} 228 229/^Raz/ && (block == "Sysreg" || block == "SysregFields") { 230 expect_fields(2) 231 parse_bitdef(reg, field, $2) 232 233 next 234} 235 236/^Enum/ { 237 change_block("Enum", "Sysreg", "Enum") 238 expect_fields(3) 239 field = $3 240 parse_bitdef(reg, field, $2) 241 242 define_field(reg, field, msb, lsb) 243 244 next 245} 246 247/^EndEnum/ { 248 change_block("EndEnum", "Enum", "Sysreg") 249 field = null 250 msb = null 251 lsb = null 252 print "" 253 next 254} 255 256/0b[01]+/ && block == "Enum" { 257 expect_fields(2) 258 val = $1 259 name = $2 260 261 define(reg "_" field "_" name, "UL(" val ")") 262 next 263} 264 265# Any lines not handled by previous rules are unexpected 266{ 267 fatal("unhandled statement") 268} 269