linux/arch/arm64/tools/gen-sysreg.awk
<<
>>
Prefs
   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