gen-sysreg.awk 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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(name, val) {
  38. printf "%-56s%s\n", "#define " name, val
  39. }
  40. # Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field
  41. function define_field(reg, field, msb, lsb) {
  42. define(reg "_" field, "GENMASK(" msb ", " lsb ")")
  43. define(reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")")
  44. define(reg "_" field "_SHIFT", lsb)
  45. define(reg "_" field "_WIDTH", msb - lsb + 1)
  46. }
  47. # Print a field _SIGNED definition for a field
  48. function define_field_sign(reg, field, sign) {
  49. define(reg "_" field "_SIGNED", sign)
  50. }
  51. # Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb
  52. function parse_bitdef(reg, field, bitdef, _bits)
  53. {
  54. if (bitdef ~ /^[0-9]+$/) {
  55. msb = bitdef
  56. lsb = bitdef
  57. } else if (split(bitdef, _bits, ":") == 2) {
  58. msb = _bits[1]
  59. lsb = _bits[2]
  60. } else {
  61. fatal("invalid bit-range definition '" bitdef "'")
  62. }
  63. if (msb != next_bit)
  64. fatal(reg "." field " starts at " msb " not " next_bit)
  65. if (63 < msb || msb < 0)
  66. fatal(reg "." field " invalid high bit in '" bitdef "'")
  67. if (63 < lsb || lsb < 0)
  68. fatal(reg "." field " invalid low bit in '" bitdef "'")
  69. if (msb < lsb)
  70. fatal(reg "." field " invalid bit-range '" bitdef "'")
  71. if (low > high)
  72. fatal(reg "." field " has invalid range " high "-" low)
  73. next_bit = lsb - 1
  74. }
  75. BEGIN {
  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. __current_block_depth = 0
  82. __current_block[__current_block_depth] = "Root"
  83. }
  84. END {
  85. if (__current_block_depth != 0)
  86. fatal("Missing terminator for " block_current() " block")
  87. print "#endif /* __ASM_SYSREG_DEFS_H */"
  88. }
  89. # skip blank lines and comment lines
  90. /^$/ { next }
  91. /^[\t ]*#/ { next }
  92. /^SysregFields/ && block_current() == "Root" {
  93. block_push("SysregFields")
  94. expect_fields(2)
  95. reg = $2
  96. res0 = "UL(0)"
  97. res1 = "UL(0)"
  98. unkn = "UL(0)"
  99. next_bit = 63
  100. next
  101. }
  102. /^EndSysregFields/ && block_current() == "SysregFields" {
  103. if (next_bit > 0)
  104. fatal("Unspecified bits in " reg)
  105. define(reg "_RES0", "(" res0 ")")
  106. define(reg "_RES1", "(" res1 ")")
  107. define(reg "_UNKN", "(" unkn ")")
  108. print ""
  109. reg = null
  110. res0 = null
  111. res1 = null
  112. unkn = null
  113. block_pop()
  114. next
  115. }
  116. /^Sysreg/ && block_current() == "Root" {
  117. block_push("Sysreg")
  118. expect_fields(7)
  119. reg = $2
  120. op0 = $3
  121. op1 = $4
  122. crn = $5
  123. crm = $6
  124. op2 = $7
  125. res0 = "UL(0)"
  126. res1 = "UL(0)"
  127. unkn = "UL(0)"
  128. define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2)
  129. define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")")
  130. define("SYS_" reg "_Op0", op0)
  131. define("SYS_" reg "_Op1", op1)
  132. define("SYS_" reg "_CRn", crn)
  133. define("SYS_" reg "_CRm", crm)
  134. define("SYS_" reg "_Op2", op2)
  135. print ""
  136. next_bit = 63
  137. next
  138. }
  139. /^EndSysreg/ && block_current() == "Sysreg" {
  140. if (next_bit > 0)
  141. fatal("Unspecified bits in " reg)
  142. if (res0 != null)
  143. define(reg "_RES0", "(" res0 ")")
  144. if (res1 != null)
  145. define(reg "_RES1", "(" res1 ")")
  146. if (unkn != null)
  147. define(reg "_UNKN", "(" unkn ")")
  148. if (res0 != null || res1 != null || unkn != null)
  149. print ""
  150. reg = null
  151. op0 = null
  152. op1 = null
  153. crn = null
  154. crm = null
  155. op2 = null
  156. res0 = null
  157. res1 = null
  158. unkn = null
  159. block_pop()
  160. next
  161. }
  162. # Currently this is effectivey a comment, in future we may want to emit
  163. # defines for the fields.
  164. /^Fields/ && block_current() == "Sysreg" {
  165. expect_fields(2)
  166. if (next_bit != 63)
  167. fatal("Some fields already defined for " reg)
  168. print "/* For " reg " fields see " $2 " */"
  169. print ""
  170. next_bit = 0
  171. res0 = null
  172. res1 = null
  173. unkn = null
  174. next
  175. }
  176. /^Res0/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
  177. expect_fields(2)
  178. parse_bitdef(reg, "RES0", $2)
  179. field = "RES0_" msb "_" lsb
  180. res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")"
  181. next
  182. }
  183. /^Res1/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
  184. expect_fields(2)
  185. parse_bitdef(reg, "RES1", $2)
  186. field = "RES1_" msb "_" lsb
  187. res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")"
  188. next
  189. }
  190. /^Unkn/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
  191. expect_fields(2)
  192. parse_bitdef(reg, "UNKN", $2)
  193. field = "UNKN_" msb "_" lsb
  194. unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")"
  195. next
  196. }
  197. /^Field/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
  198. expect_fields(3)
  199. field = $3
  200. parse_bitdef(reg, field, $2)
  201. define_field(reg, field, msb, lsb)
  202. print ""
  203. next
  204. }
  205. /^Raz/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
  206. expect_fields(2)
  207. parse_bitdef(reg, field, $2)
  208. next
  209. }
  210. /^SignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
  211. block_push("Enum")
  212. expect_fields(3)
  213. field = $3
  214. parse_bitdef(reg, field, $2)
  215. define_field(reg, field, msb, lsb)
  216. define_field_sign(reg, field, "true")
  217. next
  218. }
  219. /^UnsignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
  220. block_push("Enum")
  221. expect_fields(3)
  222. field = $3
  223. parse_bitdef(reg, field, $2)
  224. define_field(reg, field, msb, lsb)
  225. define_field_sign(reg, field, "false")
  226. next
  227. }
  228. /^Enum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") {
  229. block_push("Enum")
  230. expect_fields(3)
  231. field = $3
  232. parse_bitdef(reg, field, $2)
  233. define_field(reg, field, msb, lsb)
  234. next
  235. }
  236. /^EndEnum/ && block_current() == "Enum" {
  237. field = null
  238. msb = null
  239. lsb = null
  240. print ""
  241. block_pop()
  242. next
  243. }
  244. /0b[01]+/ && block_current() == "Enum" {
  245. expect_fields(2)
  246. val = $1
  247. name = $2
  248. define(reg "_" field "_" name, "UL(" val ")")
  249. next
  250. }
  251. # Any lines not handled by previous rules are unexpected
  252. {
  253. fatal("unhandled statement")
  254. }