gen-sysreg.awk 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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. # Log an error and terminate
  7. function fatal(msg) {
  8. print "Error at " NR ": " msg > "/dev/stderr"
  9. exit 1
  10. }
  11. # Sanity check that the start or end of a block makes sense at this point in
  12. # the file. If not, produce an error and terminate.
  13. #
  14. # @this - the $Block or $EndBlock
  15. # @prev - the only valid block to already be in (value of @block)
  16. # @new - the new value of @block
  17. function change_block(this, prev, new) {
  18. if (block != prev)
  19. fatal("unexpected " this " (inside " block ")")
  20. block = new
  21. }
  22. # Sanity check the number of records for a field makes sense. If not, produce
  23. # an error and terminate.
  24. function expect_fields(nf) {
  25. if (NF != nf)
  26. fatal(NF " fields found where " nf " expected")
  27. }
  28. # Print a CPP macro definition, padded with spaces so that the macro bodies
  29. # line up in a column
  30. function define(name, val) {
  31. printf "%-48s%s\n", "#define " name, val
  32. }
  33. # Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field
  34. function define_field(reg, field, msb, lsb) {
  35. define(reg "_" field, "GENMASK(" msb ", " lsb ")")
  36. define(reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")")
  37. define(reg "_" field "_SHIFT", lsb)
  38. define(reg "_" field "_WIDTH", msb - lsb + 1)
  39. }
  40. # Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb
  41. function parse_bitdef(reg, field, bitdef, _bits)
  42. {
  43. if (bitdef ~ /^[0-9]+$/) {
  44. msb = bitdef
  45. lsb = bitdef
  46. } else if (split(bitdef, _bits, ":") == 2) {
  47. msb = _bits[1]
  48. lsb = _bits[2]
  49. } else {
  50. fatal("invalid bit-range definition '" bitdef "'")
  51. }
  52. if (msb != next_bit)
  53. fatal(reg "." field " starts at " msb " not " next_bit)
  54. if (63 < msb || msb < 0)
  55. fatal(reg "." field " invalid high bit in '" bitdef "'")
  56. if (63 < lsb || lsb < 0)
  57. fatal(reg "." field " invalid low bit in '" bitdef "'")
  58. if (msb < lsb)
  59. fatal(reg "." field " invalid bit-range '" bitdef "'")
  60. if (low > high)
  61. fatal(reg "." field " has invalid range " high "-" low)
  62. next_bit = lsb - 1
  63. }
  64. BEGIN {
  65. print "#ifndef __ASM_SYSREG_DEFS_H"
  66. print "#define __ASM_SYSREG_DEFS_H"
  67. print ""
  68. print "/* Generated file - do not edit */"
  69. print ""
  70. block = "None"
  71. }
  72. END {
  73. print "#endif /* __ASM_SYSREG_DEFS_H */"
  74. }
  75. # skip blank lines and comment lines
  76. /^$/ { next }
  77. /^[\t ]*#/ { next }
  78. /^SysregFields/ {
  79. change_block("SysregFields", "None", "SysregFields")
  80. expect_fields(2)
  81. reg = $2
  82. res0 = "UL(0)"
  83. res1 = "UL(0)"
  84. next_bit = 63
  85. next
  86. }
  87. /^EndSysregFields/ {
  88. if (next_bit > 0)
  89. fatal("Unspecified bits in " reg)
  90. change_block("EndSysregFields", "SysregFields", "None")
  91. define(reg "_RES0", "(" res0 ")")
  92. define(reg "_RES1", "(" res1 ")")
  93. print ""
  94. reg = null
  95. res0 = null
  96. res1 = null
  97. next
  98. }
  99. /^Sysreg/ {
  100. change_block("Sysreg", "None", "Sysreg")
  101. expect_fields(7)
  102. reg = $2
  103. op0 = $3
  104. op1 = $4
  105. crn = $5
  106. crm = $6
  107. op2 = $7
  108. res0 = "UL(0)"
  109. res1 = "UL(0)"
  110. define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2)
  111. define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")")
  112. define("SYS_" reg "_Op0", op0)
  113. define("SYS_" reg "_Op1", op1)
  114. define("SYS_" reg "_CRn", crn)
  115. define("SYS_" reg "_CRm", crm)
  116. define("SYS_" reg "_Op2", op2)
  117. print ""
  118. next_bit = 63
  119. next
  120. }
  121. /^EndSysreg/ {
  122. if (next_bit > 0)
  123. fatal("Unspecified bits in " reg)
  124. change_block("EndSysreg", "Sysreg", "None")
  125. if (res0 != null)
  126. define(reg "_RES0", "(" res0 ")")
  127. if (res1 != null)
  128. define(reg "_RES1", "(" res1 ")")
  129. if (res0 != null || res1 != null)
  130. print ""
  131. reg = null
  132. op0 = null
  133. op1 = null
  134. crn = null
  135. crm = null
  136. op2 = null
  137. res0 = null
  138. res1 = null
  139. next
  140. }
  141. # Currently this is effectivey a comment, in future we may want to emit
  142. # defines for the fields.
  143. /^Fields/ && (block == "Sysreg") {
  144. expect_fields(2)
  145. if (next_bit != 63)
  146. fatal("Some fields already defined for " reg)
  147. print "/* For " reg " fields see " $2 " */"
  148. print ""
  149. next_bit = 0
  150. res0 = null
  151. res1 = null
  152. next
  153. }
  154. /^Res0/ && (block == "Sysreg" || block == "SysregFields") {
  155. expect_fields(2)
  156. parse_bitdef(reg, "RES0", $2)
  157. field = "RES0_" msb "_" lsb
  158. res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")"
  159. next
  160. }
  161. /^Res1/ && (block == "Sysreg" || block == "SysregFields") {
  162. expect_fields(2)
  163. parse_bitdef(reg, "RES1", $2)
  164. field = "RES1_" msb "_" lsb
  165. res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")"
  166. next
  167. }
  168. /^Field/ && (block == "Sysreg" || block == "SysregFields") {
  169. expect_fields(3)
  170. field = $3
  171. parse_bitdef(reg, field, $2)
  172. define_field(reg, field, msb, lsb)
  173. print ""
  174. next
  175. }
  176. /^Raz/ && (block == "Sysreg" || block == "SysregFields") {
  177. expect_fields(2)
  178. parse_bitdef(reg, field, $2)
  179. next
  180. }
  181. /^Enum/ {
  182. change_block("Enum", "Sysreg", "Enum")
  183. expect_fields(3)
  184. field = $3
  185. parse_bitdef(reg, field, $2)
  186. define_field(reg, field, msb, lsb)
  187. next
  188. }
  189. /^EndEnum/ {
  190. change_block("EndEnum", "Enum", "Sysreg")
  191. field = null
  192. msb = null
  193. lsb = null
  194. print ""
  195. next
  196. }
  197. /0b[01]+/ && block == "Enum" {
  198. expect_fields(2)
  199. val = $1
  200. name = $2
  201. define(reg "_" field "_" name, "UL(" val ")")
  202. next
  203. }
  204. # Any lines not handled by previous rules are unexpected
  205. {
  206. fatal("unhandled statement")
  207. }