166847e06SMark Rutland#!/bin/awk -f 266847e06SMark Rutland# SPDX-License-Identifier: GPL-2.0 366847e06SMark Rutland# gen-sysreg.awk: arm64 sysreg header generator 466847e06SMark Rutland# 566847e06SMark Rutland# Usage: awk -f gen-sysreg.awk sysregs.txt 666847e06SMark Rutland 7*013ecd44SMark Rutlandfunction block_current() { 8*013ecd44SMark Rutland return __current_block[__current_block_depth]; 9*013ecd44SMark Rutland} 10*013ecd44SMark Rutland 1166847e06SMark Rutland# Log an error and terminate 1266847e06SMark Rutlandfunction fatal(msg) { 1366847e06SMark Rutland print "Error at " NR ": " msg > "/dev/stderr" 14*013ecd44SMark Rutland 15*013ecd44SMark Rutland printf "Current block nesting:" 16*013ecd44SMark Rutland 17*013ecd44SMark Rutland for (i = 0; i <= __current_block_depth; i++) { 18*013ecd44SMark Rutland printf " " __current_block[i] 19*013ecd44SMark Rutland } 20*013ecd44SMark Rutland printf "\n" 21*013ecd44SMark Rutland 2266847e06SMark Rutland exit 1 2366847e06SMark Rutland} 2466847e06SMark Rutland 25*013ecd44SMark Rutland# Enter a new block, setting the active block to @block 26*013ecd44SMark Rutlandfunction block_push(block) { 27*013ecd44SMark Rutland __current_block[++__current_block_depth] = block 28*013ecd44SMark Rutland} 2966847e06SMark Rutland 30*013ecd44SMark Rutland# Exit a block, setting the active block to the parent block 31*013ecd44SMark Rutlandfunction block_pop() { 32*013ecd44SMark Rutland if (__current_block_depth == 0) 33*013ecd44SMark Rutland fatal("error: block_pop() in root block") 34*013ecd44SMark Rutland 35*013ecd44SMark Rutland __current_block_depth--; 3666847e06SMark Rutland} 3766847e06SMark Rutland 3866847e06SMark Rutland# Sanity check the number of records for a field makes sense. If not, produce 3966847e06SMark Rutland# an error and terminate. 4066847e06SMark Rutlandfunction expect_fields(nf) { 4166847e06SMark Rutland if (NF != nf) 4266847e06SMark Rutland fatal(NF " fields found where " nf " expected") 4366847e06SMark Rutland} 4466847e06SMark Rutland 4566847e06SMark Rutland# Print a CPP macro definition, padded with spaces so that the macro bodies 4666847e06SMark Rutland# line up in a column 4766847e06SMark Rutlandfunction define(name, val) { 487587cdefSJames Morse printf "%-56s%s\n", "#define " name, val 4966847e06SMark Rutland} 5066847e06SMark Rutland 5166847e06SMark Rutland# Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field 5266847e06SMark Rutlandfunction define_field(reg, field, msb, lsb) { 5366847e06SMark Rutland define(reg "_" field, "GENMASK(" msb ", " lsb ")") 5466847e06SMark Rutland define(reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")") 5566847e06SMark Rutland define(reg "_" field "_SHIFT", lsb) 5666847e06SMark Rutland define(reg "_" field "_WIDTH", msb - lsb + 1) 5766847e06SMark Rutland} 5866847e06SMark Rutland 59a55d1425SMark Brown# Print a field _SIGNED definition for a field 60a55d1425SMark Brownfunction define_field_sign(reg, field, sign) { 61a55d1425SMark Brown define(reg "_" field "_SIGNED", sign) 62a55d1425SMark Brown} 63a55d1425SMark Brown 6466847e06SMark Rutland# Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb 6566847e06SMark Rutlandfunction parse_bitdef(reg, field, bitdef, _bits) 6666847e06SMark Rutland{ 6766847e06SMark Rutland if (bitdef ~ /^[0-9]+$/) { 6866847e06SMark Rutland msb = bitdef 6966847e06SMark Rutland lsb = bitdef 7066847e06SMark Rutland } else if (split(bitdef, _bits, ":") == 2) { 7166847e06SMark Rutland msb = _bits[1] 7266847e06SMark Rutland lsb = _bits[2] 7366847e06SMark Rutland } else { 7466847e06SMark Rutland fatal("invalid bit-range definition '" bitdef "'") 7566847e06SMark Rutland } 7666847e06SMark Rutland 7766847e06SMark Rutland 7866847e06SMark Rutland if (msb != next_bit) 7966847e06SMark Rutland fatal(reg "." field " starts at " msb " not " next_bit) 8066847e06SMark Rutland if (63 < msb || msb < 0) 8166847e06SMark Rutland fatal(reg "." field " invalid high bit in '" bitdef "'") 8266847e06SMark Rutland if (63 < lsb || lsb < 0) 8366847e06SMark Rutland fatal(reg "." field " invalid low bit in '" bitdef "'") 8466847e06SMark Rutland if (msb < lsb) 8566847e06SMark Rutland fatal(reg "." field " invalid bit-range '" bitdef "'") 8666847e06SMark Rutland if (low > high) 8766847e06SMark Rutland fatal(reg "." field " has invalid range " high "-" low) 8866847e06SMark Rutland 8966847e06SMark Rutland next_bit = lsb - 1 9066847e06SMark Rutland} 9166847e06SMark Rutland 9266847e06SMark RutlandBEGIN { 9366847e06SMark Rutland print "#ifndef __ASM_SYSREG_DEFS_H" 9466847e06SMark Rutland print "#define __ASM_SYSREG_DEFS_H" 9566847e06SMark Rutland print "" 9666847e06SMark Rutland print "/* Generated file - do not edit */" 975005d1dbSMark Rutland print "" 9866847e06SMark Rutland 99*013ecd44SMark Rutland __current_block_depth = 0 100*013ecd44SMark Rutland __current_block[__current_block_depth] = "Root" 10166847e06SMark Rutland} 10266847e06SMark Rutland 10366847e06SMark RutlandEND { 104*013ecd44SMark Rutland if (__current_block_depth != 0) 105*013ecd44SMark Rutland fatal("Missing terminator for " block_current() " block") 106*013ecd44SMark Rutland 10766847e06SMark Rutland print "#endif /* __ASM_SYSREG_DEFS_H */" 10866847e06SMark Rutland} 10966847e06SMark Rutland 11066847e06SMark Rutland# skip blank lines and comment lines 11166847e06SMark Rutland/^$/ { next } 112f43ff286SMark Brown/^[\t ]*#/ { next } 11366847e06SMark Rutland 114*013ecd44SMark Rutland/^SysregFields/ && block_current() == "Root" { 115*013ecd44SMark Rutland block_push("SysregFields") 116*013ecd44SMark Rutland 11766847e06SMark Rutland expect_fields(2) 11866847e06SMark Rutland 11966847e06SMark Rutland reg = $2 12066847e06SMark Rutland 12166847e06SMark Rutland res0 = "UL(0)" 12266847e06SMark Rutland res1 = "UL(0)" 123e2c0b51fSMarc Zyngier unkn = "UL(0)" 12466847e06SMark Rutland 12566847e06SMark Rutland next_bit = 63 12666847e06SMark Rutland 12766847e06SMark Rutland next 12866847e06SMark Rutland} 12966847e06SMark Rutland 130*013ecd44SMark Rutland/^EndSysregFields/ && block_current() == "SysregFields" { 13166847e06SMark Rutland if (next_bit > 0) 13266847e06SMark Rutland fatal("Unspecified bits in " reg) 13366847e06SMark Rutland 13466847e06SMark Rutland define(reg "_RES0", "(" res0 ")") 13566847e06SMark Rutland define(reg "_RES1", "(" res1 ")") 136e2c0b51fSMarc Zyngier define(reg "_UNKN", "(" unkn ")") 13766847e06SMark Rutland print "" 13866847e06SMark Rutland 13966847e06SMark Rutland reg = null 14066847e06SMark Rutland res0 = null 14166847e06SMark Rutland res1 = null 142e2c0b51fSMarc Zyngier unkn = null 14366847e06SMark Rutland 144*013ecd44SMark Rutland block_pop() 14566847e06SMark Rutland next 14666847e06SMark Rutland} 14766847e06SMark Rutland 148*013ecd44SMark Rutland/^Sysreg/ && block_current() == "Root" { 149*013ecd44SMark Rutland block_push("Sysreg") 150*013ecd44SMark Rutland 15166847e06SMark Rutland expect_fields(7) 15266847e06SMark Rutland 15366847e06SMark Rutland reg = $2 15466847e06SMark Rutland op0 = $3 15566847e06SMark Rutland op1 = $4 15666847e06SMark Rutland crn = $5 15766847e06SMark Rutland crm = $6 15866847e06SMark Rutland op2 = $7 15966847e06SMark Rutland 16066847e06SMark Rutland res0 = "UL(0)" 16166847e06SMark Rutland res1 = "UL(0)" 162e2c0b51fSMarc Zyngier unkn = "UL(0)" 16366847e06SMark Rutland 16466847e06SMark Rutland define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2) 16566847e06SMark Rutland define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")") 16666847e06SMark Rutland 16766847e06SMark Rutland define("SYS_" reg "_Op0", op0) 16866847e06SMark Rutland define("SYS_" reg "_Op1", op1) 16966847e06SMark Rutland define("SYS_" reg "_CRn", crn) 17066847e06SMark Rutland define("SYS_" reg "_CRm", crm) 17166847e06SMark Rutland define("SYS_" reg "_Op2", op2) 17266847e06SMark Rutland 17366847e06SMark Rutland print "" 17466847e06SMark Rutland 17566847e06SMark Rutland next_bit = 63 17666847e06SMark Rutland 17766847e06SMark Rutland next 17866847e06SMark Rutland} 17966847e06SMark Rutland 180*013ecd44SMark Rutland/^EndSysreg/ && block_current() == "Sysreg" { 18166847e06SMark Rutland if (next_bit > 0) 18266847e06SMark Rutland fatal("Unspecified bits in " reg) 18366847e06SMark Rutland 18466847e06SMark Rutland if (res0 != null) 18566847e06SMark Rutland define(reg "_RES0", "(" res0 ")") 18666847e06SMark Rutland if (res1 != null) 18766847e06SMark Rutland define(reg "_RES1", "(" res1 ")") 188e2c0b51fSMarc Zyngier if (unkn != null) 189e2c0b51fSMarc Zyngier define(reg "_UNKN", "(" unkn ")") 190e2c0b51fSMarc Zyngier if (res0 != null || res1 != null || unkn != null) 19166847e06SMark Rutland print "" 19266847e06SMark Rutland 19366847e06SMark Rutland reg = null 19466847e06SMark Rutland op0 = null 19566847e06SMark Rutland op1 = null 19666847e06SMark Rutland crn = null 19766847e06SMark Rutland crm = null 19866847e06SMark Rutland op2 = null 19966847e06SMark Rutland res0 = null 20066847e06SMark Rutland res1 = null 201e2c0b51fSMarc Zyngier unkn = null 20266847e06SMark Rutland 203*013ecd44SMark Rutland block_pop() 20466847e06SMark Rutland next 20566847e06SMark Rutland} 20666847e06SMark Rutland 20766847e06SMark Rutland# Currently this is effectivey a comment, in future we may want to emit 20866847e06SMark Rutland# defines for the fields. 209*013ecd44SMark Rutland/^Fields/ && block_current() == "Sysreg" { 21066847e06SMark Rutland expect_fields(2) 21166847e06SMark Rutland 21266847e06SMark Rutland if (next_bit != 63) 21366847e06SMark Rutland fatal("Some fields already defined for " reg) 21466847e06SMark Rutland 21582bf5900SMark Rutland print "/* For " reg " fields see " $2 " */" 21666847e06SMark Rutland print "" 21766847e06SMark Rutland 21866847e06SMark Rutland next_bit = 0 21966847e06SMark Rutland res0 = null 22066847e06SMark Rutland res1 = null 221e2c0b51fSMarc Zyngier unkn = null 22266847e06SMark Rutland 22366847e06SMark Rutland next 22466847e06SMark Rutland} 22566847e06SMark Rutland 22666847e06SMark Rutland 227*013ecd44SMark Rutland/^Res0/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 22866847e06SMark Rutland expect_fields(2) 22966847e06SMark Rutland parse_bitdef(reg, "RES0", $2) 23066847e06SMark Rutland field = "RES0_" msb "_" lsb 23166847e06SMark Rutland 23266847e06SMark Rutland res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")" 23366847e06SMark Rutland 23466847e06SMark Rutland next 23566847e06SMark Rutland} 23666847e06SMark Rutland 237*013ecd44SMark Rutland/^Res1/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 23866847e06SMark Rutland expect_fields(2) 23966847e06SMark Rutland parse_bitdef(reg, "RES1", $2) 24066847e06SMark Rutland field = "RES1_" msb "_" lsb 24166847e06SMark Rutland 24266847e06SMark Rutland res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")" 24366847e06SMark Rutland 24466847e06SMark Rutland next 24566847e06SMark Rutland} 24666847e06SMark Rutland 247*013ecd44SMark Rutland/^Unkn/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 248e2c0b51fSMarc Zyngier expect_fields(2) 249e2c0b51fSMarc Zyngier parse_bitdef(reg, "UNKN", $2) 250e2c0b51fSMarc Zyngier field = "UNKN_" msb "_" lsb 251e2c0b51fSMarc Zyngier 252e2c0b51fSMarc Zyngier unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")" 253e2c0b51fSMarc Zyngier 254e2c0b51fSMarc Zyngier next 255e2c0b51fSMarc Zyngier} 256e2c0b51fSMarc Zyngier 257*013ecd44SMark Rutland/^Field/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 25866847e06SMark Rutland expect_fields(3) 25966847e06SMark Rutland field = $3 26066847e06SMark Rutland parse_bitdef(reg, field, $2) 26166847e06SMark Rutland 26266847e06SMark Rutland define_field(reg, field, msb, lsb) 26366847e06SMark Rutland print "" 26466847e06SMark Rutland 26566847e06SMark Rutland next 26666847e06SMark Rutland} 26766847e06SMark Rutland 268*013ecd44SMark Rutland/^Raz/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 2699e2c0819SMark Brown expect_fields(2) 2709e2c0819SMark Brown parse_bitdef(reg, field, $2) 2719e2c0819SMark Brown 2729e2c0819SMark Brown next 2739e2c0819SMark Brown} 2749e2c0819SMark Brown 275*013ecd44SMark Rutland/^SignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 276*013ecd44SMark Rutland block_push("Enum") 277*013ecd44SMark Rutland 278a55d1425SMark Brown expect_fields(3) 279a55d1425SMark Brown field = $3 280a55d1425SMark Brown parse_bitdef(reg, field, $2) 281a55d1425SMark Brown 282a55d1425SMark Brown define_field(reg, field, msb, lsb) 283a55d1425SMark Brown define_field_sign(reg, field, "true") 284a55d1425SMark Brown 285a55d1425SMark Brown next 286a55d1425SMark Brown} 287a55d1425SMark Brown 288*013ecd44SMark Rutland/^UnsignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 289*013ecd44SMark Rutland block_push("Enum") 290*013ecd44SMark Rutland 291a55d1425SMark Brown expect_fields(3) 292a55d1425SMark Brown field = $3 293a55d1425SMark Brown parse_bitdef(reg, field, $2) 294a55d1425SMark Brown 295a55d1425SMark Brown define_field(reg, field, msb, lsb) 296a55d1425SMark Brown define_field_sign(reg, field, "false") 297a55d1425SMark Brown 298a55d1425SMark Brown next 299a55d1425SMark Brown} 300a55d1425SMark Brown 301*013ecd44SMark Rutland/^Enum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { 302*013ecd44SMark Rutland block_push("Enum") 303*013ecd44SMark Rutland 30466847e06SMark Rutland expect_fields(3) 30566847e06SMark Rutland field = $3 30666847e06SMark Rutland parse_bitdef(reg, field, $2) 30766847e06SMark Rutland 30866847e06SMark Rutland define_field(reg, field, msb, lsb) 30966847e06SMark Rutland 31066847e06SMark Rutland next 31166847e06SMark Rutland} 31266847e06SMark Rutland 313*013ecd44SMark Rutland/^EndEnum/ && block_current() == "Enum" { 314*013ecd44SMark Rutland 31566847e06SMark Rutland field = null 31666847e06SMark Rutland msb = null 31766847e06SMark Rutland lsb = null 31866847e06SMark Rutland print "" 319*013ecd44SMark Rutland 320*013ecd44SMark Rutland block_pop() 32166847e06SMark Rutland next 32266847e06SMark Rutland} 32366847e06SMark Rutland 324*013ecd44SMark Rutland/0b[01]+/ && block_current() == "Enum" { 32566847e06SMark Rutland expect_fields(2) 32666847e06SMark Rutland val = $1 32766847e06SMark Rutland name = $2 32866847e06SMark Rutland 32966847e06SMark Rutland define(reg "_" field "_" name, "UL(" val ")") 33066847e06SMark Rutland next 33166847e06SMark Rutland} 33266847e06SMark Rutland 33366847e06SMark Rutland# Any lines not handled by previous rules are unexpected 33466847e06SMark Rutland{ 33566847e06SMark Rutland fatal("unhandled statement") 33666847e06SMark Rutland} 337