list7.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // cmd/7l/list.c and cmd/7l/sub.c from Vita Nuova.
  2. // https://code.google.com/p/ken-cc/source/browse/
  3. //
  4. // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
  5. // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
  6. // Portions Copyright © 1997-1999 Vita Nuova Limited
  7. // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
  8. // Portions Copyright © 2004,2006 Bruce Ellis
  9. // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
  10. // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
  11. // Portions Copyright © 2009 The Go Authors. All rights reserved.
  12. //
  13. // Permission is hereby granted, free of charge, to any person obtaining a copy
  14. // of this software and associated documentation files (the "Software"), to deal
  15. // in the Software without restriction, including without limitation the rights
  16. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  17. // copies of the Software, and to permit persons to whom the Software is
  18. // furnished to do so, subject to the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be included in
  21. // all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  24. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  26. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  27. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  28. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  29. // THE SOFTWARE.
  30. package arm64
  31. import (
  32. "github.com/twitchyliquid64/golang-asm/obj"
  33. "fmt"
  34. )
  35. var strcond = [16]string{
  36. "EQ",
  37. "NE",
  38. "HS",
  39. "LO",
  40. "MI",
  41. "PL",
  42. "VS",
  43. "VC",
  44. "HI",
  45. "LS",
  46. "GE",
  47. "LT",
  48. "GT",
  49. "LE",
  50. "AL",
  51. "NV",
  52. }
  53. func init() {
  54. obj.RegisterRegister(obj.RBaseARM64, REG_SPECIAL+1024, rconv)
  55. obj.RegisterOpcode(obj.ABaseARM64, Anames)
  56. obj.RegisterRegisterList(obj.RegListARM64Lo, obj.RegListARM64Hi, rlconv)
  57. obj.RegisterOpSuffix("arm64", obj.CConvARM)
  58. }
  59. func arrange(a int) string {
  60. switch a {
  61. case ARNG_8B:
  62. return "B8"
  63. case ARNG_16B:
  64. return "B16"
  65. case ARNG_4H:
  66. return "H4"
  67. case ARNG_8H:
  68. return "H8"
  69. case ARNG_2S:
  70. return "S2"
  71. case ARNG_4S:
  72. return "S4"
  73. case ARNG_1D:
  74. return "D1"
  75. case ARNG_2D:
  76. return "D2"
  77. case ARNG_B:
  78. return "B"
  79. case ARNG_H:
  80. return "H"
  81. case ARNG_S:
  82. return "S"
  83. case ARNG_D:
  84. return "D"
  85. case ARNG_1Q:
  86. return "Q1"
  87. default:
  88. return ""
  89. }
  90. }
  91. func rconv(r int) string {
  92. ext := (r >> 5) & 7
  93. if r == REGG {
  94. return "g"
  95. }
  96. switch {
  97. case REG_R0 <= r && r <= REG_R30:
  98. return fmt.Sprintf("R%d", r-REG_R0)
  99. case r == REG_R31:
  100. return "ZR"
  101. case REG_F0 <= r && r <= REG_F31:
  102. return fmt.Sprintf("F%d", r-REG_F0)
  103. case REG_V0 <= r && r <= REG_V31:
  104. return fmt.Sprintf("V%d", r-REG_V0)
  105. case COND_EQ <= r && r <= COND_NV:
  106. return strcond[r-COND_EQ]
  107. case r == REGSP:
  108. return "RSP"
  109. case r == REG_DAIFSet:
  110. return "DAIFSet"
  111. case r == REG_DAIFClr:
  112. return "DAIFClr"
  113. case r == REG_PLDL1KEEP:
  114. return "PLDL1KEEP"
  115. case r == REG_PLDL1STRM:
  116. return "PLDL1STRM"
  117. case r == REG_PLDL2KEEP:
  118. return "PLDL2KEEP"
  119. case r == REG_PLDL2STRM:
  120. return "PLDL2STRM"
  121. case r == REG_PLDL3KEEP:
  122. return "PLDL3KEEP"
  123. case r == REG_PLDL3STRM:
  124. return "PLDL3STRM"
  125. case r == REG_PLIL1KEEP:
  126. return "PLIL1KEEP"
  127. case r == REG_PLIL1STRM:
  128. return "PLIL1STRM"
  129. case r == REG_PLIL2KEEP:
  130. return "PLIL2KEEP"
  131. case r == REG_PLIL2STRM:
  132. return "PLIL2STRM"
  133. case r == REG_PLIL3KEEP:
  134. return "PLIL3KEEP"
  135. case r == REG_PLIL3STRM:
  136. return "PLIL3STRM"
  137. case r == REG_PSTL1KEEP:
  138. return "PSTL1KEEP"
  139. case r == REG_PSTL1STRM:
  140. return "PSTL1STRM"
  141. case r == REG_PSTL2KEEP:
  142. return "PSTL2KEEP"
  143. case r == REG_PSTL2STRM:
  144. return "PSTL2STRM"
  145. case r == REG_PSTL3KEEP:
  146. return "PSTL3KEEP"
  147. case r == REG_PSTL3STRM:
  148. return "PSTL3STRM"
  149. case REG_UXTB <= r && r < REG_UXTH:
  150. if ext != 0 {
  151. return fmt.Sprintf("%s.UXTB<<%d", regname(r), ext)
  152. } else {
  153. return fmt.Sprintf("%s.UXTB", regname(r))
  154. }
  155. case REG_UXTH <= r && r < REG_UXTW:
  156. if ext != 0 {
  157. return fmt.Sprintf("%s.UXTH<<%d", regname(r), ext)
  158. } else {
  159. return fmt.Sprintf("%s.UXTH", regname(r))
  160. }
  161. case REG_UXTW <= r && r < REG_UXTX:
  162. if ext != 0 {
  163. return fmt.Sprintf("%s.UXTW<<%d", regname(r), ext)
  164. } else {
  165. return fmt.Sprintf("%s.UXTW", regname(r))
  166. }
  167. case REG_UXTX <= r && r < REG_SXTB:
  168. if ext != 0 {
  169. return fmt.Sprintf("%s.UXTX<<%d", regname(r), ext)
  170. } else {
  171. return fmt.Sprintf("%s.UXTX", regname(r))
  172. }
  173. case REG_SXTB <= r && r < REG_SXTH:
  174. if ext != 0 {
  175. return fmt.Sprintf("%s.SXTB<<%d", regname(r), ext)
  176. } else {
  177. return fmt.Sprintf("%s.SXTB", regname(r))
  178. }
  179. case REG_SXTH <= r && r < REG_SXTW:
  180. if ext != 0 {
  181. return fmt.Sprintf("%s.SXTH<<%d", regname(r), ext)
  182. } else {
  183. return fmt.Sprintf("%s.SXTH", regname(r))
  184. }
  185. case REG_SXTW <= r && r < REG_SXTX:
  186. if ext != 0 {
  187. return fmt.Sprintf("%s.SXTW<<%d", regname(r), ext)
  188. } else {
  189. return fmt.Sprintf("%s.SXTW", regname(r))
  190. }
  191. case REG_SXTX <= r && r < REG_SPECIAL:
  192. if ext != 0 {
  193. return fmt.Sprintf("%s.SXTX<<%d", regname(r), ext)
  194. } else {
  195. return fmt.Sprintf("%s.SXTX", regname(r))
  196. }
  197. // bits 0-4 indicate register, bits 5-7 indicate shift amount, bit 8 equals to 0.
  198. case REG_LSL <= r && r < (REG_LSL+1<<8):
  199. return fmt.Sprintf("R%d<<%d", r&31, (r>>5)&7)
  200. case REG_ARNG <= r && r < REG_ELEM:
  201. return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15))
  202. case REG_ELEM <= r && r < REG_ELEM_END:
  203. return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15))
  204. }
  205. // Return system register name.
  206. name, _, _ := SysRegEnc(int16(r))
  207. if name != "" {
  208. return name
  209. }
  210. return fmt.Sprintf("badreg(%d)", r)
  211. }
  212. func DRconv(a int) string {
  213. if a >= C_NONE && a <= C_NCLASS {
  214. return cnames7[a]
  215. }
  216. return "C_??"
  217. }
  218. func rlconv(list int64) string {
  219. str := ""
  220. // ARM64 register list follows ARM64 instruction decode schema
  221. // | 31 | 30 | ... | 15 - 12 | 11 - 10 | ... |
  222. // +----+----+-----+---------+---------+-----+
  223. // | | Q | ... | opcode | size | ... |
  224. firstReg := int(list & 31)
  225. opcode := (list >> 12) & 15
  226. var regCnt int
  227. var t string
  228. switch opcode {
  229. case 0x7:
  230. regCnt = 1
  231. case 0xa:
  232. regCnt = 2
  233. case 0x6:
  234. regCnt = 3
  235. case 0x2:
  236. regCnt = 4
  237. default:
  238. regCnt = -1
  239. }
  240. // Q:size
  241. arng := ((list>>30)&1)<<2 | (list>>10)&3
  242. switch arng {
  243. case 0:
  244. t = "B8"
  245. case 4:
  246. t = "B16"
  247. case 1:
  248. t = "H4"
  249. case 5:
  250. t = "H8"
  251. case 2:
  252. t = "S2"
  253. case 6:
  254. t = "S4"
  255. case 3:
  256. t = "D1"
  257. case 7:
  258. t = "D2"
  259. }
  260. for i := 0; i < regCnt; i++ {
  261. if str == "" {
  262. str += "["
  263. } else {
  264. str += ","
  265. }
  266. str += fmt.Sprintf("V%d.", (firstReg+i)&31)
  267. str += t
  268. }
  269. str += "]"
  270. return str
  271. }
  272. func regname(r int) string {
  273. if r&31 == 31 {
  274. return "ZR"
  275. }
  276. return fmt.Sprintf("R%d", r&31)
  277. }