gen-sysreg.awk 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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. function block_current() {
  7. return __current_block[__current_block_depth];
  8. }
  9. # Log an error and terminate
  10. function fatal(msg) {
  11. print "Error at " NR ": " msg > "/dev/stderr"
  12. printf "Current block nesting:"
  13. for (i = 0; i <= __current_block_depth; i++) {
  14. printf " " __current_block[i]
  15. }
  16. printf "\n"
  17. exit 1
  18. }
  19. # Enter a new block, setting the active block to @block
  20. function block_push(block) {
  21. __current_block[++__current_block_depth] = block
  22. }
  23. # Exit a block, setting the active block to the parent block
  24. function block_pop() {
  25. if (__current_block_depth == 0)
  26. fatal("error: block_pop() in root block")
  27. __current_block_depth--;
  28. }
  29. # Sanity check the number of records for a field makes sense. If not, produce
  30. # an error and terminate.
  31. function expect_fields(nf) {
  32. if (NF != nf)
  33. fatal(NF " fields found where " nf " expected")
  34. }
  35. # Print a CPP macro definition, padded with spaces so that the macro bodies
  36. # line up in a column
  37. function define(prefix, name, val) {
  38. printf "%-56s%s\n", "#define " prefix name, val
  39. }
  40. # Same as above, but without a prefix
  41. function define_reg(name, val) {
  42. define(null, name, val)
  43. }
  44. # Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field
  45. function define_field(prefix, reg, field, msb, lsb) {
  46. define(prefix, reg "_" field, "GENMASK(" msb ", " lsb ")")
  47. define(prefix, reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")")
  48. define(prefix, reg "_" field "_SHIFT", lsb)
  49. define(prefix, reg "_" field "_WIDTH", msb - lsb + 1)
  50. }
  51. # Print a field _SIGNED definition for a field
  52. function define_field_sign(prefix, reg, field, sign) {
  53. define(prefix, reg "_" field "_SIGNED", sign)
  54. }
  55. # Print the Res0, Res1, Unkn masks
  56. function define_resx_unkn(prefix, reg, res0, res1, unkn) {
  57. if (res0 != null)
  58. define(prefix, reg "_RES0", "(" res0 ")")
  59. if (res1 != null)
  60. define(prefix, reg "_RES1", "(" res1 ")")
  61. if (unkn != null)
  62. define(prefix, reg "_UNKN", "(" unkn ")")
  63. if (res0 != null || res1 != null || unkn != null)
  64. print ""
  65. }
  66. # Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb
  67. function parse_bitdef(reg, field, bitdef, _bits)
  68. {
  69. if (bitdef ~ /^[0-9]+$/) {
  70. msb = bitdef
  71. lsb = bitdef
  72. } else if (split(bitdef, _bits, ":") == 2) {
  73. msb = _bits[1]
  74. lsb = _bits[2]
  75. } else {
  76. fatal("invalid bit-range definition '" bitdef "'")
  77. }
  78. if (msb != next_bit)
  79. fatal(reg "." field " starts at " msb " not " next_bit)
  80. if (63 < msb || msb < 0)
  81. fatal(reg "." field " invalid high bit in '" bitdef "'")
  82. if (63 < lsb || lsb < 0)
  83. fatal(reg "." field " invalid low bit in '" bitdef "'")
  84. if (msb < lsb)
  85. fatal(reg "." field " invalid bit-range '" bitdef "'")
  86. if (low > high)
  87. fatal(reg "." field " has invalid range " high "-" low)
  88. next_bit = lsb - 1
  89. }
  90. BEGIN {
  91. print "#ifndef __ASM_SYSREG_DEFS_H"
  92. print "#define __ASM_SYSREG_DEFS_H"
  93. print ""
  94. print "/* Generated file - do not edit */"
  95. print ""
  96. __current_block_depth = 0
  97. __current_block[__current_block_depth] = "Root"
  98. }
  99. END {
  100. if (__current_block_depth != 0)
  101. fatal("Missing terminator for " block_current() " block")
  102. print "#endif /* __ASM_SYSREG_DEFS_H */"
  103. }
  104. # skip blank lines and comment lines
  105. /^$/ { next }
  106. /^[\t ]*#/ { next }
  107. $1 == "SysregFields" && block_current() == "Root" {
  108. block_push("SysregFields")
  109. expect_fields(2)
  110. reg = $2
  111. res0 = "UL(0)"
  112. res1 = "UL(0)"
  113. unkn = "UL(0)"
  114. if (reg in defined_fields)
  115. fatal("Duplicate SysregFields definition for " reg)
  116. defined_fields[reg] = 1
  117. next_bit = 63
  118. delete seen_prefixes
  119. next
  120. }
  121. $1 == "EndSysregFields" && block_current() == "SysregFields" {
  122. expect_fields(1)
  123. if (next_bit >= 0)
  124. fatal("Unspecified bits in " reg)
  125. define_resx_unkn(prefix, reg, res0, res1, unkn)
  126. reg = null
  127. res0 = null
  128. res1 = null
  129. unkn = null
  130. block_pop()
  131. next
  132. }
  133. $1 == "Sysreg" && block_current() == "Root" {
  134. block_push("Sysreg")
  135. expect_fields(7)
  136. reg = $2
  137. op0 = $3
  138. op1 = $4
  139. crn = $5
  140. crm = $6
  141. op2 = $7
  142. res0 = "UL(0)"
  143. res1 = "UL(0)"
  144. unkn = "UL(0)"
  145. if (reg in defined_regs)
  146. fatal("Duplicate Sysreg definition for " reg)
  147. defined_regs[reg] = 1
  148. define_reg("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2)
  149. define_reg("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")")
  150. define_reg("SYS_" reg "_Op0", op0)
  151. define_reg("SYS_" reg "_Op1", op1)
  152. define_reg("SYS_" reg "_CRn", crn)
  153. define_reg("SYS_" reg "_CRm", crm)
  154. define_reg("SYS_" reg "_Op2", op2)
  155. print ""
  156. prefix = null
  157. next_bit = 63
  158. delete seen_prefixes
  159. next
  160. }
  161. $1 == "EndSysreg" && block_current() == "Sysreg" {
  162. expect_fields(1)
  163. if (next_bit >= 0)
  164. fatal("Unspecified bits in " reg)
  165. define_resx_unkn(prefix, reg, res0, res1, unkn)
  166. reg = null
  167. op0 = null
  168. op1 = null
  169. crn = null
  170. crm = null
  171. op2 = null
  172. res0 = null
  173. res1 = null
  174. unkn = null
  175. prefix = null
  176. block_pop()
  177. next
  178. }
  179. # Currently this is effectivey a comment, in future we may want to emit
  180. # defines for the fields.
  181. ($1 == "Fields" || $1 == "Mapping") && block_current() == "Sysreg" {
  182. expect_fields(2)
  183. if (next_bit != 63)
  184. fatal("Some fields already defined for " reg)
  185. print "/* For " reg " fields see " $2 " */"
  186. print ""
  187. next_bit = -1
  188. res0 = null
  189. res1 = null
  190. unkn = null
  191. next
  192. }
  193. $1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
  194. expect_fields(2)
  195. parse_bitdef(reg, "RES0", $2)
  196. field = "RES0_" msb "_" lsb
  197. res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")"
  198. next
  199. }
  200. $1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
  201. expect_fields(2)
  202. parse_bitdef(reg, "RES1", $2)
  203. field = "RES1_" msb "_" lsb
  204. res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")"
  205. next
  206. }
  207. $1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
  208. expect_fields(2)
  209. parse_bitdef(reg, "UNKN", $2)
  210. field = "UNKN_" msb "_" lsb
  211. unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")"
  212. next
  213. }
  214. $1 == "Field" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
  215. expect_fields(3)
  216. field = $3
  217. parse_bitdef(reg, field, $2)
  218. define_field(prefix, reg, field, msb, lsb)
  219. print ""
  220. next
  221. }
  222. $1 == "Raz" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
  223. expect_fields(2)
  224. parse_bitdef(reg, field, $2)
  225. next
  226. }
  227. $1 == "SignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
  228. block_push("Enum")
  229. expect_fields(3)
  230. field = $3
  231. parse_bitdef(reg, field, $2)
  232. define_field(prefix, reg, field, msb, lsb)
  233. define_field_sign(prefix, reg, field, "true")
  234. delete seen_enum_vals
  235. next
  236. }
  237. $1 == "UnsignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
  238. block_push("Enum")
  239. expect_fields(3)
  240. field = $3
  241. parse_bitdef(reg, field, $2)
  242. define_field(prefix, reg, field, msb, lsb)
  243. define_field_sign(prefix, reg, field, "false")
  244. delete seen_enum_vals
  245. next
  246. }
  247. $1 == "Enum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") {
  248. block_push("Enum")
  249. expect_fields(3)
  250. field = $3
  251. parse_bitdef(reg, field, $2)
  252. define_field(prefix, reg, field, msb, lsb)
  253. delete seen_enum_vals
  254. next
  255. }
  256. $1 == "EndEnum" && block_current() == "Enum" {
  257. expect_fields(1)
  258. field = null
  259. msb = null
  260. lsb = null
  261. print ""
  262. delete seen_enum_vals
  263. block_pop()
  264. next
  265. }
  266. /0b[01]+/ && block_current() == "Enum" {
  267. expect_fields(2)
  268. val = $1
  269. name = $2
  270. if (val in seen_enum_vals)
  271. fatal("Duplicate Enum value " val " for " name)
  272. seen_enum_vals[val] = 1
  273. define(prefix, reg "_" field "_" name, "UL(" val ")")
  274. next
  275. }
  276. $1 == "Prefix" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
  277. block_push("Prefix")
  278. expect_fields(2)
  279. if (next_bit < 63)
  280. fatal("Prefixed fields must precede non-prefixed fields (" reg ")")
  281. prefix = $2 "_"
  282. if (prefix in seen_prefixes)
  283. fatal("Duplicate prefix " prefix " for " reg)
  284. seen_prefixes[prefix] = 1
  285. res0 = "UL(0)"
  286. res1 = "UL(0)"
  287. unkn = "UL(0)"
  288. next_bit = 63
  289. next
  290. }
  291. $1 == "EndPrefix" && block_current() == "Prefix" {
  292. expect_fields(1)
  293. if (next_bit >= 0)
  294. fatal("Unspecified bits in prefix " prefix " for " reg)
  295. define_resx_unkn(prefix, reg, res0, res1, unkn)
  296. prefix = null
  297. res0 = "UL(0)"
  298. res1 = "UL(0)"
  299. unkn = "UL(0)"
  300. next_bit = 63
  301. block_pop()
  302. next
  303. }
  304. # Any lines not handled by previous rules are unexpected
  305. {
  306. fatal("unhandled statement")
  307. }