xref: /openbmc/linux/arch/arm64/tools/gen-sysreg.awk (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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