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