immunio 0.15.4 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (454) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +0 -27
  3. data/ext/immunio/Rakefile +9 -0
  4. data/lib/immunio/plugins/active_record.rb +1 -1
  5. data/lib/immunio/plugins/active_record_relation.rb +1 -1
  6. data/lib/immunio/plugins/environment_reporter.rb +20 -0
  7. data/lib/immunio/rufus_lua_ext/ref.rb +1 -3
  8. data/lib/immunio/version.rb +1 -1
  9. data/lib/immunio/vm.rb +1 -2
  10. data/lua-hooks/Makefile +97 -0
  11. data/lua-hooks/ext/all.c +41 -52
  12. data/lua-hooks/ext/all.o +0 -0
  13. data/lua-hooks/ext/libinjection/libinjection_html5.o +0 -0
  14. data/lua-hooks/ext/libinjection/libinjection_sqli.o +0 -0
  15. data/lua-hooks/ext/libinjection/libinjection_xss.o +0 -0
  16. data/lua-hooks/ext/libinjection/lualib.c +2 -2
  17. data/lua-hooks/ext/lpeg/lpcap.c +2 -2
  18. data/lua-hooks/ext/lpeg/lpcap.o +0 -0
  19. data/lua-hooks/ext/lpeg/lpcode.c +2 -2
  20. data/lua-hooks/ext/lpeg/lpcode.h +1 -1
  21. data/lua-hooks/ext/lpeg/lpcode.o +0 -0
  22. data/lua-hooks/ext/lpeg/lpprint.o +0 -0
  23. data/lua-hooks/ext/lpeg/lptree.c +2 -2
  24. data/lua-hooks/ext/lpeg/lptypes.h +1 -1
  25. data/lua-hooks/ext/lpeg/lpvm.c +2 -2
  26. data/lua-hooks/ext/lpeg/lpvm.o +0 -0
  27. data/lua-hooks/ext/lua-cmsgpack/lua_cmsgpack.c +16 -3
  28. data/lua-hooks/ext/lua-snapshot/snapshot.c +14 -7
  29. data/lua-hooks/ext/luajit/COPYRIGHT +56 -0
  30. data/lua-hooks/ext/luajit/Makefile +159 -0
  31. data/lua-hooks/ext/luajit/README +16 -0
  32. data/lua-hooks/ext/luajit/doc/bluequad-print.css +166 -0
  33. data/lua-hooks/ext/luajit/doc/bluequad.css +325 -0
  34. data/lua-hooks/ext/luajit/doc/changes.html +804 -0
  35. data/lua-hooks/ext/luajit/doc/contact.html +104 -0
  36. data/lua-hooks/ext/luajit/doc/ext_c_api.html +189 -0
  37. data/lua-hooks/ext/luajit/doc/ext_ffi.html +332 -0
  38. data/lua-hooks/ext/luajit/doc/ext_ffi_api.html +570 -0
  39. data/lua-hooks/ext/luajit/doc/ext_ffi_semantics.html +1261 -0
  40. data/lua-hooks/ext/luajit/doc/ext_ffi_tutorial.html +603 -0
  41. data/lua-hooks/ext/luajit/doc/ext_jit.html +201 -0
  42. data/lua-hooks/ext/luajit/doc/ext_profiler.html +365 -0
  43. data/lua-hooks/ext/luajit/doc/extensions.html +448 -0
  44. data/lua-hooks/ext/luajit/doc/faq.html +186 -0
  45. data/lua-hooks/ext/luajit/doc/img/contact.png +0 -0
  46. data/lua-hooks/ext/luajit/doc/install.html +659 -0
  47. data/lua-hooks/ext/luajit/doc/luajit.html +236 -0
  48. data/lua-hooks/ext/luajit/doc/running.html +309 -0
  49. data/lua-hooks/ext/luajit/doc/status.html +118 -0
  50. data/lua-hooks/ext/luajit/dynasm/dasm_arm.h +456 -0
  51. data/lua-hooks/ext/luajit/dynasm/dasm_arm.lua +1125 -0
  52. data/lua-hooks/ext/luajit/dynasm/dasm_arm64.h +518 -0
  53. data/lua-hooks/ext/luajit/dynasm/dasm_arm64.lua +1166 -0
  54. data/lua-hooks/ext/luajit/dynasm/dasm_mips.h +416 -0
  55. data/lua-hooks/ext/luajit/dynasm/dasm_mips.lua +953 -0
  56. data/lua-hooks/ext/luajit/dynasm/dasm_ppc.h +419 -0
  57. data/lua-hooks/ext/luajit/dynasm/dasm_ppc.lua +1919 -0
  58. data/lua-hooks/ext/luajit/dynasm/dasm_proto.h +83 -0
  59. data/lua-hooks/ext/luajit/dynasm/dasm_x64.lua +12 -0
  60. data/lua-hooks/ext/luajit/dynasm/dasm_x86.h +471 -0
  61. data/lua-hooks/ext/luajit/dynasm/dasm_x86.lua +1945 -0
  62. data/lua-hooks/ext/luajit/dynasm/dynasm.lua +1094 -0
  63. data/lua-hooks/ext/luajit/etc/luajit.1 +88 -0
  64. data/lua-hooks/ext/luajit/etc/luajit.pc +25 -0
  65. data/lua-hooks/ext/luajit/src/Makefile +697 -0
  66. data/lua-hooks/ext/luajit/src/Makefile.dep +244 -0
  67. data/lua-hooks/ext/luajit/src/host/README +4 -0
  68. data/lua-hooks/ext/luajit/src/host/buildvm +0 -0
  69. data/lua-hooks/ext/luajit/src/host/buildvm.c +518 -0
  70. data/lua-hooks/ext/luajit/src/host/buildvm.h +105 -0
  71. data/lua-hooks/ext/luajit/src/host/buildvm.o +0 -0
  72. data/lua-hooks/ext/luajit/src/host/buildvm_arch.h +7449 -0
  73. data/lua-hooks/ext/luajit/src/host/buildvm_asm.c +345 -0
  74. data/lua-hooks/ext/luajit/src/host/buildvm_asm.o +0 -0
  75. data/lua-hooks/ext/luajit/src/host/buildvm_fold.c +229 -0
  76. data/lua-hooks/ext/luajit/src/host/buildvm_fold.o +0 -0
  77. data/lua-hooks/ext/luajit/src/host/buildvm_lib.c +457 -0
  78. data/lua-hooks/ext/luajit/src/host/buildvm_lib.o +0 -0
  79. data/lua-hooks/ext/luajit/src/host/buildvm_libbc.h +45 -0
  80. data/lua-hooks/ext/luajit/src/host/buildvm_peobj.c +368 -0
  81. data/lua-hooks/ext/luajit/src/host/buildvm_peobj.o +0 -0
  82. data/lua-hooks/ext/luajit/src/host/genlibbc.lua +197 -0
  83. data/lua-hooks/ext/luajit/src/host/genminilua.lua +428 -0
  84. data/lua-hooks/ext/luajit/src/host/minilua +0 -0
  85. data/lua-hooks/ext/luajit/src/host/minilua.c +7770 -0
  86. data/lua-hooks/ext/luajit/src/host/minilua.o +0 -0
  87. data/lua-hooks/ext/luajit/src/jit/bc.lua +190 -0
  88. data/lua-hooks/ext/luajit/src/jit/bcsave.lua +661 -0
  89. data/lua-hooks/ext/luajit/src/jit/dis_arm.lua +689 -0
  90. data/lua-hooks/ext/luajit/src/jit/dis_mips.lua +428 -0
  91. data/lua-hooks/ext/luajit/src/jit/dis_mipsel.lua +17 -0
  92. data/lua-hooks/ext/luajit/src/jit/dis_ppc.lua +591 -0
  93. data/lua-hooks/ext/luajit/src/jit/dis_x64.lua +17 -0
  94. data/lua-hooks/ext/luajit/src/jit/dis_x86.lua +838 -0
  95. data/lua-hooks/ext/luajit/src/jit/dump.lua +706 -0
  96. data/lua-hooks/ext/luajit/src/jit/p.lua +310 -0
  97. data/lua-hooks/ext/luajit/src/jit/v.lua +170 -0
  98. data/lua-hooks/ext/luajit/src/jit/vmdef.lua +362 -0
  99. data/lua-hooks/ext/luajit/src/jit/zone.lua +45 -0
  100. data/lua-hooks/ext/{lua → luajit/src}/lauxlib.h +10 -17
  101. data/lua-hooks/ext/luajit/src/lib_aux.c +356 -0
  102. data/lua-hooks/ext/luajit/src/lib_aux.o +0 -0
  103. data/lua-hooks/ext/luajit/src/lib_aux_dyn.o +0 -0
  104. data/lua-hooks/ext/luajit/src/lib_base.c +664 -0
  105. data/lua-hooks/ext/luajit/src/lib_base.o +0 -0
  106. data/lua-hooks/ext/luajit/src/lib_base_dyn.o +0 -0
  107. data/lua-hooks/ext/luajit/src/lib_bit.c +180 -0
  108. data/lua-hooks/ext/luajit/src/lib_bit.o +0 -0
  109. data/lua-hooks/ext/luajit/src/lib_bit_dyn.o +0 -0
  110. data/lua-hooks/ext/luajit/src/lib_debug.c +405 -0
  111. data/lua-hooks/ext/luajit/src/lib_debug.o +0 -0
  112. data/lua-hooks/ext/luajit/src/lib_debug_dyn.o +0 -0
  113. data/lua-hooks/ext/luajit/src/lib_ffi.c +872 -0
  114. data/lua-hooks/ext/luajit/src/lib_ffi.o +0 -0
  115. data/lua-hooks/ext/luajit/src/lib_ffi_dyn.o +0 -0
  116. data/lua-hooks/ext/luajit/src/lib_init.c +55 -0
  117. data/lua-hooks/ext/luajit/src/lib_init.o +0 -0
  118. data/lua-hooks/ext/luajit/src/lib_init_dyn.o +0 -0
  119. data/lua-hooks/ext/luajit/src/lib_io.c +541 -0
  120. data/lua-hooks/ext/luajit/src/lib_io.o +0 -0
  121. data/lua-hooks/ext/luajit/src/lib_io_dyn.o +0 -0
  122. data/lua-hooks/ext/luajit/src/lib_jit.c +767 -0
  123. data/lua-hooks/ext/luajit/src/lib_jit.o +0 -0
  124. data/lua-hooks/ext/luajit/src/lib_jit_dyn.o +0 -0
  125. data/lua-hooks/ext/luajit/src/lib_math.c +230 -0
  126. data/lua-hooks/ext/luajit/src/lib_math.o +0 -0
  127. data/lua-hooks/ext/luajit/src/lib_math_dyn.o +0 -0
  128. data/lua-hooks/ext/luajit/src/lib_os.c +292 -0
  129. data/lua-hooks/ext/luajit/src/lib_os.o +0 -0
  130. data/lua-hooks/ext/luajit/src/lib_os_dyn.o +0 -0
  131. data/lua-hooks/ext/luajit/src/lib_package.c +610 -0
  132. data/lua-hooks/ext/luajit/src/lib_package.o +0 -0
  133. data/lua-hooks/ext/luajit/src/lib_package_dyn.o +0 -0
  134. data/lua-hooks/ext/luajit/src/lib_string.c +752 -0
  135. data/lua-hooks/ext/luajit/src/lib_string.o +0 -0
  136. data/lua-hooks/ext/luajit/src/lib_string_dyn.o +0 -0
  137. data/lua-hooks/ext/luajit/src/lib_table.c +307 -0
  138. data/lua-hooks/ext/luajit/src/lib_table.o +0 -0
  139. data/lua-hooks/ext/luajit/src/lib_table_dyn.o +0 -0
  140. data/lua-hooks/ext/luajit/src/libluajit.a +0 -0
  141. data/lua-hooks/ext/luajit/src/libluajit.so +0 -0
  142. data/lua-hooks/ext/luajit/src/lj.supp +26 -0
  143. data/lua-hooks/ext/luajit/src/lj_alloc.c +1398 -0
  144. data/lua-hooks/ext/luajit/src/lj_alloc.h +17 -0
  145. data/lua-hooks/ext/luajit/src/lj_alloc.o +0 -0
  146. data/lua-hooks/ext/luajit/src/lj_alloc_dyn.o +0 -0
  147. data/lua-hooks/ext/luajit/src/lj_api.c +1210 -0
  148. data/lua-hooks/ext/luajit/src/lj_api.o +0 -0
  149. data/lua-hooks/ext/luajit/src/lj_api_dyn.o +0 -0
  150. data/lua-hooks/ext/luajit/src/lj_arch.h +509 -0
  151. data/lua-hooks/ext/luajit/src/lj_asm.c +2278 -0
  152. data/lua-hooks/ext/luajit/src/lj_asm.h +17 -0
  153. data/lua-hooks/ext/luajit/src/lj_asm.o +0 -0
  154. data/lua-hooks/ext/luajit/src/lj_asm_arm.h +2217 -0
  155. data/lua-hooks/ext/luajit/src/lj_asm_dyn.o +0 -0
  156. data/lua-hooks/ext/luajit/src/lj_asm_mips.h +1833 -0
  157. data/lua-hooks/ext/luajit/src/lj_asm_ppc.h +2015 -0
  158. data/lua-hooks/ext/luajit/src/lj_asm_x86.h +2634 -0
  159. data/lua-hooks/ext/luajit/src/lj_bc.c +14 -0
  160. data/lua-hooks/ext/luajit/src/lj_bc.h +265 -0
  161. data/lua-hooks/ext/luajit/src/lj_bc.o +0 -0
  162. data/lua-hooks/ext/luajit/src/lj_bc_dyn.o +0 -0
  163. data/lua-hooks/ext/luajit/src/lj_bcdef.h +220 -0
  164. data/lua-hooks/ext/luajit/src/lj_bcdump.h +68 -0
  165. data/lua-hooks/ext/luajit/src/lj_bcread.c +457 -0
  166. data/lua-hooks/ext/luajit/src/lj_bcread.o +0 -0
  167. data/lua-hooks/ext/luajit/src/lj_bcread_dyn.o +0 -0
  168. data/lua-hooks/ext/luajit/src/lj_bcwrite.c +361 -0
  169. data/lua-hooks/ext/luajit/src/lj_bcwrite.o +0 -0
  170. data/lua-hooks/ext/luajit/src/lj_bcwrite_dyn.o +0 -0
  171. data/lua-hooks/ext/luajit/src/lj_buf.c +234 -0
  172. data/lua-hooks/ext/luajit/src/lj_buf.h +105 -0
  173. data/lua-hooks/ext/luajit/src/lj_buf.o +0 -0
  174. data/lua-hooks/ext/luajit/src/lj_buf_dyn.o +0 -0
  175. data/lua-hooks/ext/luajit/src/lj_carith.c +429 -0
  176. data/lua-hooks/ext/luajit/src/lj_carith.h +37 -0
  177. data/lua-hooks/ext/luajit/src/lj_carith.o +0 -0
  178. data/lua-hooks/ext/luajit/src/lj_carith_dyn.o +0 -0
  179. data/lua-hooks/ext/luajit/src/lj_ccall.c +984 -0
  180. data/lua-hooks/ext/luajit/src/lj_ccall.h +178 -0
  181. data/lua-hooks/ext/luajit/src/lj_ccall.o +0 -0
  182. data/lua-hooks/ext/luajit/src/lj_ccall_dyn.o +0 -0
  183. data/lua-hooks/ext/luajit/src/lj_ccallback.c +712 -0
  184. data/lua-hooks/ext/luajit/src/lj_ccallback.h +25 -0
  185. data/lua-hooks/ext/luajit/src/lj_ccallback.o +0 -0
  186. data/lua-hooks/ext/luajit/src/lj_ccallback_dyn.o +0 -0
  187. data/lua-hooks/ext/luajit/src/lj_cconv.c +752 -0
  188. data/lua-hooks/ext/luajit/src/lj_cconv.h +70 -0
  189. data/lua-hooks/ext/luajit/src/lj_cconv.o +0 -0
  190. data/lua-hooks/ext/luajit/src/lj_cconv_dyn.o +0 -0
  191. data/lua-hooks/ext/luajit/src/lj_cdata.c +288 -0
  192. data/lua-hooks/ext/luajit/src/lj_cdata.h +76 -0
  193. data/lua-hooks/ext/luajit/src/lj_cdata.o +0 -0
  194. data/lua-hooks/ext/luajit/src/lj_cdata_dyn.o +0 -0
  195. data/lua-hooks/ext/luajit/src/lj_char.c +43 -0
  196. data/lua-hooks/ext/luajit/src/lj_char.h +42 -0
  197. data/lua-hooks/ext/luajit/src/lj_char.o +0 -0
  198. data/lua-hooks/ext/luajit/src/lj_char_dyn.o +0 -0
  199. data/lua-hooks/ext/luajit/src/lj_clib.c +418 -0
  200. data/lua-hooks/ext/luajit/src/lj_clib.h +29 -0
  201. data/lua-hooks/ext/luajit/src/lj_clib.o +0 -0
  202. data/lua-hooks/ext/luajit/src/lj_clib_dyn.o +0 -0
  203. data/lua-hooks/ext/luajit/src/lj_cparse.c +1862 -0
  204. data/lua-hooks/ext/luajit/src/lj_cparse.h +65 -0
  205. data/lua-hooks/ext/luajit/src/lj_cparse.o +0 -0
  206. data/lua-hooks/ext/luajit/src/lj_cparse_dyn.o +0 -0
  207. data/lua-hooks/ext/luajit/src/lj_crecord.c +1834 -0
  208. data/lua-hooks/ext/luajit/src/lj_crecord.h +38 -0
  209. data/lua-hooks/ext/luajit/src/lj_crecord.o +0 -0
  210. data/lua-hooks/ext/luajit/src/lj_crecord_dyn.o +0 -0
  211. data/lua-hooks/ext/luajit/src/lj_ctype.c +635 -0
  212. data/lua-hooks/ext/luajit/src/lj_ctype.h +461 -0
  213. data/lua-hooks/ext/luajit/src/lj_ctype.o +0 -0
  214. data/lua-hooks/ext/luajit/src/lj_ctype_dyn.o +0 -0
  215. data/lua-hooks/ext/luajit/src/lj_debug.c +699 -0
  216. data/lua-hooks/ext/luajit/src/lj_debug.h +65 -0
  217. data/lua-hooks/ext/luajit/src/lj_debug.o +0 -0
  218. data/lua-hooks/ext/luajit/src/lj_debug_dyn.o +0 -0
  219. data/lua-hooks/ext/luajit/src/lj_def.h +365 -0
  220. data/lua-hooks/ext/luajit/src/lj_dispatch.c +557 -0
  221. data/lua-hooks/ext/luajit/src/lj_dispatch.h +138 -0
  222. data/lua-hooks/ext/luajit/src/lj_dispatch.o +0 -0
  223. data/lua-hooks/ext/luajit/src/lj_dispatch_dyn.o +0 -0
  224. data/lua-hooks/ext/luajit/src/lj_emit_arm.h +356 -0
  225. data/lua-hooks/ext/luajit/src/lj_emit_mips.h +211 -0
  226. data/lua-hooks/ext/luajit/src/lj_emit_ppc.h +238 -0
  227. data/lua-hooks/ext/luajit/src/lj_emit_x86.h +462 -0
  228. data/lua-hooks/ext/luajit/src/lj_err.c +794 -0
  229. data/lua-hooks/ext/luajit/src/lj_err.h +41 -0
  230. data/lua-hooks/ext/luajit/src/lj_err.o +0 -0
  231. data/lua-hooks/ext/luajit/src/lj_err_dyn.o +0 -0
  232. data/lua-hooks/ext/luajit/src/lj_errmsg.h +190 -0
  233. data/lua-hooks/ext/luajit/src/lj_ff.h +18 -0
  234. data/lua-hooks/ext/luajit/src/lj_ffdef.h +209 -0
  235. data/lua-hooks/ext/luajit/src/lj_ffrecord.c +1247 -0
  236. data/lua-hooks/ext/luajit/src/lj_ffrecord.h +24 -0
  237. data/lua-hooks/ext/luajit/src/lj_ffrecord.o +0 -0
  238. data/lua-hooks/ext/luajit/src/lj_ffrecord_dyn.o +0 -0
  239. data/lua-hooks/ext/luajit/src/lj_folddef.h +1138 -0
  240. data/lua-hooks/ext/luajit/src/lj_frame.h +259 -0
  241. data/lua-hooks/ext/luajit/src/lj_func.c +185 -0
  242. data/lua-hooks/ext/luajit/src/lj_func.h +24 -0
  243. data/lua-hooks/ext/luajit/src/lj_func.o +0 -0
  244. data/lua-hooks/ext/luajit/src/lj_func_dyn.o +0 -0
  245. data/lua-hooks/ext/luajit/src/lj_gc.c +845 -0
  246. data/lua-hooks/ext/luajit/src/lj_gc.h +134 -0
  247. data/lua-hooks/ext/luajit/src/lj_gc.o +0 -0
  248. data/lua-hooks/ext/luajit/src/lj_gc_dyn.o +0 -0
  249. data/lua-hooks/ext/luajit/src/lj_gdbjit.c +787 -0
  250. data/lua-hooks/ext/luajit/src/lj_gdbjit.h +22 -0
  251. data/lua-hooks/ext/luajit/src/lj_gdbjit.o +0 -0
  252. data/lua-hooks/ext/luajit/src/lj_gdbjit_dyn.o +0 -0
  253. data/lua-hooks/ext/luajit/src/lj_ir.c +505 -0
  254. data/lua-hooks/ext/luajit/src/lj_ir.h +577 -0
  255. data/lua-hooks/ext/luajit/src/lj_ir.o +0 -0
  256. data/lua-hooks/ext/luajit/src/lj_ir_dyn.o +0 -0
  257. data/lua-hooks/ext/luajit/src/lj_ircall.h +321 -0
  258. data/lua-hooks/ext/luajit/src/lj_iropt.h +161 -0
  259. data/lua-hooks/ext/luajit/src/lj_jit.h +440 -0
  260. data/lua-hooks/ext/luajit/src/lj_lex.c +482 -0
  261. data/lua-hooks/ext/luajit/src/lj_lex.h +86 -0
  262. data/lua-hooks/ext/luajit/src/lj_lex.o +0 -0
  263. data/lua-hooks/ext/luajit/src/lj_lex_dyn.o +0 -0
  264. data/lua-hooks/ext/luajit/src/lj_lib.c +303 -0
  265. data/lua-hooks/ext/luajit/src/lj_lib.h +115 -0
  266. data/lua-hooks/ext/luajit/src/lj_lib.o +0 -0
  267. data/lua-hooks/ext/luajit/src/lj_lib_dyn.o +0 -0
  268. data/lua-hooks/ext/luajit/src/lj_libdef.h +414 -0
  269. data/lua-hooks/ext/luajit/src/lj_load.c +168 -0
  270. data/lua-hooks/ext/luajit/src/lj_load.o +0 -0
  271. data/lua-hooks/ext/luajit/src/lj_load_dyn.o +0 -0
  272. data/lua-hooks/ext/luajit/src/lj_mcode.c +386 -0
  273. data/lua-hooks/ext/luajit/src/lj_mcode.h +30 -0
  274. data/lua-hooks/ext/luajit/src/lj_mcode.o +0 -0
  275. data/lua-hooks/ext/luajit/src/lj_mcode_dyn.o +0 -0
  276. data/lua-hooks/ext/luajit/src/lj_meta.c +477 -0
  277. data/lua-hooks/ext/luajit/src/lj_meta.h +38 -0
  278. data/lua-hooks/ext/luajit/src/lj_meta.o +0 -0
  279. data/lua-hooks/ext/luajit/src/lj_meta_dyn.o +0 -0
  280. data/lua-hooks/ext/luajit/src/lj_obj.c +50 -0
  281. data/lua-hooks/ext/luajit/src/lj_obj.h +976 -0
  282. data/lua-hooks/ext/luajit/src/lj_obj.o +0 -0
  283. data/lua-hooks/ext/luajit/src/lj_obj_dyn.o +0 -0
  284. data/lua-hooks/ext/luajit/src/lj_opt_dce.c +78 -0
  285. data/lua-hooks/ext/luajit/src/lj_opt_dce.o +0 -0
  286. data/lua-hooks/ext/luajit/src/lj_opt_dce_dyn.o +0 -0
  287. data/lua-hooks/ext/luajit/src/lj_opt_fold.c +2488 -0
  288. data/lua-hooks/ext/luajit/src/lj_opt_fold.o +0 -0
  289. data/lua-hooks/ext/luajit/src/lj_opt_fold_dyn.o +0 -0
  290. data/lua-hooks/ext/luajit/src/lj_opt_loop.c +449 -0
  291. data/lua-hooks/ext/luajit/src/lj_opt_loop.o +0 -0
  292. data/lua-hooks/ext/luajit/src/lj_opt_loop_dyn.o +0 -0
  293. data/lua-hooks/ext/luajit/src/lj_opt_mem.c +935 -0
  294. data/lua-hooks/ext/luajit/src/lj_opt_mem.o +0 -0
  295. data/lua-hooks/ext/luajit/src/lj_opt_mem_dyn.o +0 -0
  296. data/lua-hooks/ext/luajit/src/lj_opt_narrow.c +652 -0
  297. data/lua-hooks/ext/luajit/src/lj_opt_narrow.o +0 -0
  298. data/lua-hooks/ext/luajit/src/lj_opt_narrow_dyn.o +0 -0
  299. data/lua-hooks/ext/luajit/src/lj_opt_sink.c +245 -0
  300. data/lua-hooks/ext/luajit/src/lj_opt_sink.o +0 -0
  301. data/lua-hooks/ext/luajit/src/lj_opt_sink_dyn.o +0 -0
  302. data/lua-hooks/ext/luajit/src/lj_opt_split.c +856 -0
  303. data/lua-hooks/ext/luajit/src/lj_opt_split.o +0 -0
  304. data/lua-hooks/ext/luajit/src/lj_opt_split_dyn.o +0 -0
  305. data/lua-hooks/ext/luajit/src/lj_parse.c +2725 -0
  306. data/lua-hooks/ext/luajit/src/lj_parse.h +18 -0
  307. data/lua-hooks/ext/luajit/src/lj_parse.o +0 -0
  308. data/lua-hooks/ext/luajit/src/lj_parse_dyn.o +0 -0
  309. data/lua-hooks/ext/luajit/src/lj_profile.c +368 -0
  310. data/lua-hooks/ext/luajit/src/lj_profile.h +21 -0
  311. data/lua-hooks/ext/luajit/src/lj_profile.o +0 -0
  312. data/lua-hooks/ext/luajit/src/lj_profile_dyn.o +0 -0
  313. data/lua-hooks/ext/luajit/src/lj_recdef.h +270 -0
  314. data/lua-hooks/ext/luajit/src/lj_record.c +2554 -0
  315. data/lua-hooks/ext/luajit/src/lj_record.h +45 -0
  316. data/lua-hooks/ext/luajit/src/lj_record.o +0 -0
  317. data/lua-hooks/ext/luajit/src/lj_record_dyn.o +0 -0
  318. data/lua-hooks/ext/luajit/src/lj_snap.c +870 -0
  319. data/lua-hooks/ext/luajit/src/lj_snap.h +34 -0
  320. data/lua-hooks/ext/luajit/src/lj_snap.o +0 -0
  321. data/lua-hooks/ext/luajit/src/lj_snap_dyn.o +0 -0
  322. data/lua-hooks/ext/luajit/src/lj_state.c +300 -0
  323. data/lua-hooks/ext/luajit/src/lj_state.h +35 -0
  324. data/lua-hooks/ext/luajit/src/lj_state.o +0 -0
  325. data/lua-hooks/ext/luajit/src/lj_state_dyn.o +0 -0
  326. data/lua-hooks/ext/luajit/src/lj_str.c +197 -0
  327. data/lua-hooks/ext/luajit/src/lj_str.h +27 -0
  328. data/lua-hooks/ext/luajit/src/lj_str.o +0 -0
  329. data/lua-hooks/ext/luajit/src/lj_str_dyn.o +0 -0
  330. data/lua-hooks/ext/luajit/src/lj_strfmt.c +554 -0
  331. data/lua-hooks/ext/luajit/src/lj_strfmt.h +125 -0
  332. data/lua-hooks/ext/luajit/src/lj_strfmt.o +0 -0
  333. data/lua-hooks/ext/luajit/src/lj_strfmt_dyn.o +0 -0
  334. data/lua-hooks/ext/luajit/src/lj_strscan.c +547 -0
  335. data/lua-hooks/ext/luajit/src/lj_strscan.h +39 -0
  336. data/lua-hooks/ext/luajit/src/lj_strscan.o +0 -0
  337. data/lua-hooks/ext/luajit/src/lj_strscan_dyn.o +0 -0
  338. data/lua-hooks/ext/luajit/src/lj_tab.c +666 -0
  339. data/lua-hooks/ext/luajit/src/lj_tab.h +73 -0
  340. data/lua-hooks/ext/luajit/src/lj_tab.o +0 -0
  341. data/lua-hooks/ext/luajit/src/lj_tab_dyn.o +0 -0
  342. data/lua-hooks/ext/luajit/src/lj_target.h +164 -0
  343. data/lua-hooks/ext/luajit/src/lj_target_arm.h +270 -0
  344. data/lua-hooks/ext/luajit/src/lj_target_arm64.h +97 -0
  345. data/lua-hooks/ext/luajit/src/lj_target_mips.h +260 -0
  346. data/lua-hooks/ext/luajit/src/lj_target_ppc.h +280 -0
  347. data/lua-hooks/ext/luajit/src/lj_target_x86.h +345 -0
  348. data/lua-hooks/ext/luajit/src/lj_trace.c +859 -0
  349. data/lua-hooks/ext/luajit/src/lj_trace.h +54 -0
  350. data/lua-hooks/ext/luajit/src/lj_trace.o +0 -0
  351. data/lua-hooks/ext/luajit/src/lj_trace_dyn.o +0 -0
  352. data/lua-hooks/ext/luajit/src/lj_traceerr.h +63 -0
  353. data/lua-hooks/ext/luajit/src/lj_udata.c +34 -0
  354. data/lua-hooks/ext/luajit/src/lj_udata.h +14 -0
  355. data/lua-hooks/ext/luajit/src/lj_udata.o +0 -0
  356. data/lua-hooks/ext/luajit/src/lj_udata_dyn.o +0 -0
  357. data/lua-hooks/ext/luajit/src/lj_vm.S +2730 -0
  358. data/lua-hooks/ext/luajit/src/lj_vm.h +114 -0
  359. data/lua-hooks/ext/luajit/src/lj_vm.o +0 -0
  360. data/lua-hooks/ext/luajit/src/lj_vm_dyn.o +0 -0
  361. data/lua-hooks/ext/luajit/src/lj_vmevent.c +58 -0
  362. data/lua-hooks/ext/luajit/src/lj_vmevent.h +59 -0
  363. data/lua-hooks/ext/luajit/src/lj_vmevent.o +0 -0
  364. data/lua-hooks/ext/luajit/src/lj_vmevent_dyn.o +0 -0
  365. data/lua-hooks/ext/luajit/src/lj_vmmath.c +152 -0
  366. data/lua-hooks/ext/luajit/src/lj_vmmath.o +0 -0
  367. data/lua-hooks/ext/luajit/src/lj_vmmath_dyn.o +0 -0
  368. data/lua-hooks/ext/luajit/src/ljamalg.c +96 -0
  369. data/lua-hooks/ext/{lua → luajit/src}/lua.h +12 -7
  370. data/lua-hooks/ext/luajit/src/lua.hpp +9 -0
  371. data/lua-hooks/ext/luajit/src/luaconf.h +156 -0
  372. data/lua-hooks/ext/luajit/src/luajit +0 -0
  373. data/lua-hooks/ext/luajit/src/luajit.c +570 -0
  374. data/lua-hooks/ext/luajit/src/luajit.h +79 -0
  375. data/lua-hooks/ext/luajit/src/luajit.o +0 -0
  376. data/lua-hooks/ext/luajit/src/lualib.h +43 -0
  377. data/lua-hooks/ext/luajit/src/msvcbuild.bat +114 -0
  378. data/lua-hooks/ext/luajit/src/ps4build.bat +103 -0
  379. data/lua-hooks/ext/luajit/src/psvitabuild.bat +93 -0
  380. data/lua-hooks/ext/luajit/src/vm_arm.dasc +4585 -0
  381. data/lua-hooks/ext/luajit/src/vm_arm64.dasc +3764 -0
  382. data/lua-hooks/ext/luajit/src/vm_mips.dasc +4355 -0
  383. data/lua-hooks/ext/luajit/src/vm_ppc.dasc +5252 -0
  384. data/lua-hooks/ext/luajit/src/vm_x64.dasc +4902 -0
  385. data/lua-hooks/ext/luajit/src/vm_x86.dasc +5710 -0
  386. data/lua-hooks/ext/luajit/src/xb1build.bat +101 -0
  387. data/lua-hooks/ext/luajit/src/xedkbuild.bat +92 -0
  388. data/lua-hooks/ext/luautf8/lutf8lib.c +3 -3
  389. data/lua-hooks/lib/boot.lua +37 -2
  390. metadata +372 -69
  391. data/lua-hooks/ext/bitop/README +0 -22
  392. data/lua-hooks/ext/bitop/bit.c +0 -189
  393. data/lua-hooks/ext/extconf.rb +0 -38
  394. data/lua-hooks/ext/lua/COPYRIGHT +0 -34
  395. data/lua-hooks/ext/lua/lapi.c +0 -1087
  396. data/lua-hooks/ext/lua/lapi.h +0 -16
  397. data/lua-hooks/ext/lua/lauxlib.c +0 -652
  398. data/lua-hooks/ext/lua/lbaselib.c +0 -659
  399. data/lua-hooks/ext/lua/lcode.c +0 -831
  400. data/lua-hooks/ext/lua/lcode.h +0 -76
  401. data/lua-hooks/ext/lua/ldblib.c +0 -398
  402. data/lua-hooks/ext/lua/ldebug.c +0 -638
  403. data/lua-hooks/ext/lua/ldebug.h +0 -33
  404. data/lua-hooks/ext/lua/ldo.c +0 -519
  405. data/lua-hooks/ext/lua/ldo.h +0 -57
  406. data/lua-hooks/ext/lua/ldump.c +0 -164
  407. data/lua-hooks/ext/lua/lfunc.c +0 -174
  408. data/lua-hooks/ext/lua/lfunc.h +0 -34
  409. data/lua-hooks/ext/lua/lgc.c +0 -710
  410. data/lua-hooks/ext/lua/lgc.h +0 -110
  411. data/lua-hooks/ext/lua/linit.c +0 -38
  412. data/lua-hooks/ext/lua/liolib.c +0 -556
  413. data/lua-hooks/ext/lua/llex.c +0 -463
  414. data/lua-hooks/ext/lua/llex.h +0 -81
  415. data/lua-hooks/ext/lua/llimits.h +0 -128
  416. data/lua-hooks/ext/lua/lmathlib.c +0 -263
  417. data/lua-hooks/ext/lua/lmem.c +0 -86
  418. data/lua-hooks/ext/lua/lmem.h +0 -49
  419. data/lua-hooks/ext/lua/loadlib.c +0 -705
  420. data/lua-hooks/ext/lua/loadlib_rel.c +0 -760
  421. data/lua-hooks/ext/lua/lobject.c +0 -214
  422. data/lua-hooks/ext/lua/lobject.h +0 -381
  423. data/lua-hooks/ext/lua/lopcodes.c +0 -102
  424. data/lua-hooks/ext/lua/lopcodes.h +0 -268
  425. data/lua-hooks/ext/lua/loslib.c +0 -243
  426. data/lua-hooks/ext/lua/lparser.c +0 -1339
  427. data/lua-hooks/ext/lua/lparser.h +0 -82
  428. data/lua-hooks/ext/lua/lstate.c +0 -214
  429. data/lua-hooks/ext/lua/lstate.h +0 -169
  430. data/lua-hooks/ext/lua/lstring.c +0 -111
  431. data/lua-hooks/ext/lua/lstring.h +0 -31
  432. data/lua-hooks/ext/lua/lstrlib.c +0 -871
  433. data/lua-hooks/ext/lua/ltable.c +0 -588
  434. data/lua-hooks/ext/lua/ltable.h +0 -40
  435. data/lua-hooks/ext/lua/ltablib.c +0 -287
  436. data/lua-hooks/ext/lua/ltm.c +0 -75
  437. data/lua-hooks/ext/lua/ltm.h +0 -54
  438. data/lua-hooks/ext/lua/lua.c +0 -392
  439. data/lua-hooks/ext/lua/lua.def +0 -131
  440. data/lua-hooks/ext/lua/lua.rc +0 -28
  441. data/lua-hooks/ext/lua/lua_dll.rc +0 -26
  442. data/lua-hooks/ext/lua/luac.c +0 -200
  443. data/lua-hooks/ext/lua/luac.rc +0 -1
  444. data/lua-hooks/ext/lua/luaconf.h +0 -763
  445. data/lua-hooks/ext/lua/luaconf.h.in +0 -724
  446. data/lua-hooks/ext/lua/luaconf.h.orig +0 -763
  447. data/lua-hooks/ext/lua/lualib.h +0 -53
  448. data/lua-hooks/ext/lua/lundump.c +0 -227
  449. data/lua-hooks/ext/lua/lundump.h +0 -36
  450. data/lua-hooks/ext/lua/lvm.c +0 -767
  451. data/lua-hooks/ext/lua/lvm.h +0 -36
  452. data/lua-hooks/ext/lua/lzio.c +0 -82
  453. data/lua-hooks/ext/lua/lzio.h +0 -67
  454. data/lua-hooks/ext/lua/print.c +0 -227
@@ -0,0 +1,3764 @@
1
+ |// Low-level VM code for ARM64 CPUs.
2
+ |// Bytecode interpreter, fast functions and helper functions.
3
+ |// Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
4
+ |
5
+ |.arch arm64
6
+ |.section code_op, code_sub
7
+ |
8
+ |.actionlist build_actionlist
9
+ |.globals GLOB_
10
+ |.globalnames globnames
11
+ |.externnames extnames
12
+ |
13
+ |// Note: The ragged indentation of the instructions is intentional.
14
+ |// The starting columns indicate data dependencies.
15
+ |
16
+ |//-----------------------------------------------------------------------
17
+ |
18
+ |// ARM64 registers and the AAPCS64 ABI 1.0 at a glance:
19
+ |//
20
+ |// x0-x17 temp, x19-x28 callee-saved, x29 fp, x30 lr
21
+ |// x18 is reserved on most platforms. Don't use it, save it or restore it.
22
+ |// x31 doesn't exist. Register number 31 either means xzr/wzr (zero) or sp,
23
+ |// depending on the instruction.
24
+ |// v0-v7 temp, v8-v15 callee-saved (only d8-d15 preserved), v16-v31 temp
25
+ |//
26
+ |// x0-x7/v0-v7 hold parameters and results.
27
+ |
28
+ |// Fixed register assignments for the interpreter.
29
+ |
30
+ |// The following must be C callee-save.
31
+ |.define BASE, x19 // Base of current Lua stack frame.
32
+ |.define KBASE, x20 // Constants of current Lua function.
33
+ |.define PC, x21 // Next PC.
34
+ |.define GLREG, x22 // Global state.
35
+ |.define LREG, x23 // Register holding lua_State (also in SAVE_L).
36
+ |.define TISNUM, x24 // Constant LJ_TISNUM << 47.
37
+ |.define TISNUMhi, x25 // Constant LJ_TISNUM << 15.
38
+ |.define TISNIL, x26 // Constant -1LL.
39
+ |.define fp, x29 // Yes, we have to maintain a frame pointer.
40
+ |
41
+ |.define ST_INTERP, w26 // Constant -1.
42
+ |
43
+ |// The following temporaries are not saved across C calls, except for RA/RC.
44
+ |.define RA, x27
45
+ |.define RC, x28
46
+ |.define RB, x17
47
+ |.define RAw, w27
48
+ |.define RCw, w28
49
+ |.define RBw, w17
50
+ |.define INS, x16
51
+ |.define INSw, w16
52
+ |.define ITYPE, x15
53
+ |.define TMP0, x8
54
+ |.define TMP1, x9
55
+ |.define TMP2, x10
56
+ |.define TMP3, x11
57
+ |.define TMP0w, w8
58
+ |.define TMP1w, w9
59
+ |.define TMP2w, w10
60
+ |.define TMP3w, w11
61
+ |
62
+ |// Calling conventions. Also used as temporaries.
63
+ |.define CARG1, x0
64
+ |.define CARG2, x1
65
+ |.define CARG3, x2
66
+ |.define CARG4, x3
67
+ |.define CARG5, x4
68
+ |.define CARG1w, w0
69
+ |.define CARG2w, w1
70
+ |.define CARG3w, w2
71
+ |.define CARG4w, w3
72
+ |.define CARG5w, w4
73
+ |
74
+ |.define FARG1, d0
75
+ |.define FARG2, d1
76
+ |
77
+ |.define CRET1, x0
78
+ |.define CRET1w, w0
79
+ |
80
+ |// Stack layout while in interpreter. Must match with lj_frame.h.
81
+ |
82
+ |.define CFRAME_SPACE, 208
83
+ |//----- 16 byte aligned, <-- sp entering interpreter
84
+ |// Unused [sp, #204] // 32 bit values
85
+ |.define SAVE_NRES, [sp, #200]
86
+ |.define SAVE_ERRF, [sp, #196]
87
+ |.define SAVE_MULTRES, [sp, #192]
88
+ |.define TMPD, [sp, #184] // 64 bit values
89
+ |.define SAVE_L, [sp, #176]
90
+ |.define SAVE_PC, [sp, #168]
91
+ |.define SAVE_CFRAME, [sp, #160]
92
+ |.define SAVE_FPR_, 96 // 96+8*8: 64 bit FPR saves
93
+ |.define SAVE_GPR_, 16 // 16+10*8: 64 bit GPR saves
94
+ |.define SAVE_LR, [sp, #8]
95
+ |.define SAVE_FP, [sp]
96
+ |//----- 16 byte aligned, <-- sp while in interpreter.
97
+ |
98
+ |.define TMPDofs, #184
99
+ |
100
+ |.macro save_, gpr1, gpr2, fpr1, fpr2
101
+ | stp d..fpr1, d..fpr2, [sp, # SAVE_FPR_+(fpr1-8)*8]
102
+ | stp x..gpr1, x..gpr2, [sp, # SAVE_GPR_+(gpr1-19)*8]
103
+ |.endmacro
104
+ |.macro rest_, gpr1, gpr2, fpr1, fpr2
105
+ | ldp d..fpr1, d..fpr2, [sp, # SAVE_FPR_+(fpr1-8)*8]
106
+ | ldp x..gpr1, x..gpr2, [sp, # SAVE_GPR_+(gpr1-19)*8]
107
+ |.endmacro
108
+ |
109
+ |.macro saveregs
110
+ | stp fp, lr, [sp, #-CFRAME_SPACE]!
111
+ | add fp, sp, #0
112
+ | stp x19, x20, [sp, # SAVE_GPR_]
113
+ | save_ 21, 22, 8, 9
114
+ | save_ 23, 24, 10, 11
115
+ | save_ 25, 26, 12, 13
116
+ | save_ 27, 28, 14, 15
117
+ |.endmacro
118
+ |.macro restoreregs
119
+ | ldp x19, x20, [sp, # SAVE_GPR_]
120
+ | rest_ 21, 22, 8, 9
121
+ | rest_ 23, 24, 10, 11
122
+ | rest_ 25, 26, 12, 13
123
+ | rest_ 27, 28, 14, 15
124
+ | ldp fp, lr, [sp], # CFRAME_SPACE
125
+ |.endmacro
126
+ |
127
+ |// Type definitions. Some of these are only used for documentation.
128
+ |.type L, lua_State, LREG
129
+ |.type GL, global_State, GLREG
130
+ |.type TVALUE, TValue
131
+ |.type GCOBJ, GCobj
132
+ |.type STR, GCstr
133
+ |.type TAB, GCtab
134
+ |.type LFUNC, GCfuncL
135
+ |.type CFUNC, GCfuncC
136
+ |.type PROTO, GCproto
137
+ |.type UPVAL, GCupval
138
+ |.type NODE, Node
139
+ |.type NARGS8, int
140
+ |.type TRACE, GCtrace
141
+ |.type SBUF, SBuf
142
+ |
143
+ |//-----------------------------------------------------------------------
144
+ |
145
+ |// Trap for not-yet-implemented parts.
146
+ |.macro NYI; brk; .endmacro
147
+ |
148
+ |//-----------------------------------------------------------------------
149
+ |
150
+ |// Access to frame relative to BASE.
151
+ |.define FRAME_FUNC, #-16
152
+ |.define FRAME_PC, #-8
153
+ |
154
+ |.macro decode_RA, dst, ins; ubfx dst, ins, #8, #8; .endmacro
155
+ |.macro decode_RB, dst, ins; ubfx dst, ins, #24, #8; .endmacro
156
+ |.macro decode_RC, dst, ins; ubfx dst, ins, #16, #8; .endmacro
157
+ |.macro decode_RD, dst, ins; ubfx dst, ins, #16, #16; .endmacro
158
+ |.macro decode_RC8RD, dst, src; ubfiz dst, src, #3, #8; .endmacro
159
+ |
160
+ |// Instruction decode+dispatch.
161
+ |.macro ins_NEXT
162
+ | ldr INSw, [PC], #4
163
+ | add TMP1, GL, INS, uxtb #3
164
+ | decode_RA RA, INS
165
+ | ldr TMP0, [TMP1, #GG_G2DISP]
166
+ | decode_RD RC, INS
167
+ | br TMP0
168
+ |.endmacro
169
+ |
170
+ |// Instruction footer.
171
+ |.if 1
172
+ | // Replicated dispatch. Less unpredictable branches, but higher I-Cache use.
173
+ | .define ins_next, ins_NEXT
174
+ | .define ins_next_, ins_NEXT
175
+ |.else
176
+ | // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch.
177
+ | // Affects only certain kinds of benchmarks (and only with -j off).
178
+ | .macro ins_next
179
+ | b ->ins_next
180
+ | .endmacro
181
+ | .macro ins_next_
182
+ | ->ins_next:
183
+ | ins_NEXT
184
+ | .endmacro
185
+ |.endif
186
+ |
187
+ |// Call decode and dispatch.
188
+ |.macro ins_callt
189
+ | // BASE = new base, CARG3 = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC
190
+ | ldr PC, LFUNC:CARG3->pc
191
+ | ldr INSw, [PC], #4
192
+ | add TMP1, GL, INS, uxtb #3
193
+ | decode_RA RA, INS
194
+ | ldr TMP0, [TMP1, #GG_G2DISP]
195
+ | add RA, BASE, RA, lsl #3
196
+ | br TMP0
197
+ |.endmacro
198
+ |
199
+ |.macro ins_call
200
+ | // BASE = new base, CARG3 = LFUNC/CFUNC, RC = nargs*8, PC = caller PC
201
+ | str PC, [BASE, FRAME_PC]
202
+ | ins_callt
203
+ |.endmacro
204
+ |
205
+ |//-----------------------------------------------------------------------
206
+ |
207
+ |// Macros to check the TValue type and extract the GCobj. Branch on failure.
208
+ |.macro checktp, reg, tp, target
209
+ | asr ITYPE, reg, #47
210
+ | cmn ITYPE, #-tp
211
+ | and reg, reg, #LJ_GCVMASK
212
+ | bne target
213
+ |.endmacro
214
+ |.macro checktp, dst, reg, tp, target
215
+ | asr ITYPE, reg, #47
216
+ | cmn ITYPE, #-tp
217
+ | and dst, reg, #LJ_GCVMASK
218
+ | bne target
219
+ |.endmacro
220
+ |.macro checkstr, reg, target; checktp reg, LJ_TSTR, target; .endmacro
221
+ |.macro checktab, reg, target; checktp reg, LJ_TTAB, target; .endmacro
222
+ |.macro checkfunc, reg, target; checktp reg, LJ_TFUNC, target; .endmacro
223
+ |.macro checkint, reg, target
224
+ | cmp TISNUMhi, reg, lsr #32
225
+ | bne target
226
+ |.endmacro
227
+ |.macro checknum, reg, target
228
+ | cmp TISNUMhi, reg, lsr #32
229
+ | bls target
230
+ |.endmacro
231
+ |.macro checknumber, reg, target
232
+ | cmp TISNUMhi, reg, lsr #32
233
+ | blo target
234
+ |.endmacro
235
+ |
236
+ |.macro mov_false, reg; movn reg, #0x8000, lsl #32; .endmacro
237
+ |.macro mov_true, reg; movn reg, #0x0001, lsl #48; .endmacro
238
+ |
239
+ #define GL_J(field) (GG_OFS(J) + (int)offsetof(jit_State, field))
240
+ |
241
+ #define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto))
242
+ |
243
+ |.macro hotcheck, delta
244
+ | NYI
245
+ |.endmacro
246
+ |
247
+ |.macro hotloop
248
+ | hotcheck HOTCOUNT_LOOP
249
+ | blo ->vm_hotloop
250
+ |.endmacro
251
+ |
252
+ |.macro hotcall
253
+ | hotcheck HOTCOUNT_CALL
254
+ | blo ->vm_hotcall
255
+ |.endmacro
256
+ |
257
+ |// Set current VM state.
258
+ |.macro mv_vmstate, reg, st; movn reg, #LJ_VMST_..st; .endmacro
259
+ |.macro st_vmstate, reg; str reg, GL->vmstate; .endmacro
260
+ |
261
+ |// Move table write barrier back. Overwrites mark and tmp.
262
+ |.macro barrierback, tab, mark, tmp
263
+ | ldr tmp, GL->gc.grayagain
264
+ | and mark, mark, #~LJ_GC_BLACK // black2gray(tab)
265
+ | str tab, GL->gc.grayagain
266
+ | strb mark, tab->marked
267
+ | str tmp, tab->gclist
268
+ |.endmacro
269
+ |
270
+ |//-----------------------------------------------------------------------
271
+
272
+ #if !LJ_DUALNUM
273
+ #error "Only dual-number mode supported for ARM64 target"
274
+ #endif
275
+
276
+ /* Generate subroutines used by opcodes and other parts of the VM. */
277
+ /* The .code_sub section should be last to help static branch prediction. */
278
+ static void build_subroutines(BuildCtx *ctx)
279
+ {
280
+ |.code_sub
281
+ |
282
+ |//-----------------------------------------------------------------------
283
+ |//-- Return handling ----------------------------------------------------
284
+ |//-----------------------------------------------------------------------
285
+ |
286
+ |->vm_returnp:
287
+ | // See vm_return. Also: RB = previous base.
288
+ | tbz PC, #2, ->cont_dispatch // (PC & FRAME_P) == 0?
289
+ |
290
+ | // Return from pcall or xpcall fast func.
291
+ | ldr PC, [RB, FRAME_PC] // Fetch PC of previous frame.
292
+ | mov_true TMP0
293
+ | mov BASE, RB
294
+ | // Prepending may overwrite the pcall frame, so do it at the end.
295
+ | str TMP0, [RA, #-8]! // Prepend true to results.
296
+ |
297
+ |->vm_returnc:
298
+ | adds RC, RC, #8 // RC = (nresults+1)*8.
299
+ | mov CRET1, #LUA_YIELD
300
+ | beq ->vm_unwind_c_eh
301
+ | str RCw, SAVE_MULTRES
302
+ | ands CARG1, PC, #FRAME_TYPE
303
+ | beq ->BC_RET_Z // Handle regular return to Lua.
304
+ |
305
+ |->vm_return:
306
+ | // BASE = base, RA = resultptr, RC/MULTRES = (nresults+1)*8, PC = return
307
+ | // CARG1 = PC & FRAME_TYPE
308
+ | and RB, PC, #~FRAME_TYPEP
309
+ | cmp CARG1, #FRAME_C
310
+ | sub RB, BASE, RB // RB = previous base.
311
+ | bne ->vm_returnp
312
+ |
313
+ | str RB, L->base
314
+ | ldrsw CARG2, SAVE_NRES // CARG2 = nresults+1.
315
+ | mv_vmstate TMP0w, C
316
+ | sub BASE, BASE, #16
317
+ | subs TMP2, RC, #8
318
+ | st_vmstate TMP0w
319
+ | beq >2
320
+ |1:
321
+ | subs TMP2, TMP2, #8
322
+ | ldr TMP0, [RA], #8
323
+ | str TMP0, [BASE], #8
324
+ | bne <1
325
+ |2:
326
+ | cmp RC, CARG2, lsl #3 // More/less results wanted?
327
+ | bne >6
328
+ |3:
329
+ | str BASE, L->top // Store new top.
330
+ |
331
+ |->vm_leave_cp:
332
+ | ldr RC, SAVE_CFRAME // Restore previous C frame.
333
+ | mov CRET1, #0 // Ok return status for vm_pcall.
334
+ | str RC, L->cframe
335
+ |
336
+ |->vm_leave_unw:
337
+ | restoreregs
338
+ | ret
339
+ |
340
+ |6:
341
+ | bgt >7 // Less results wanted?
342
+ | // More results wanted. Check stack size and fill up results with nil.
343
+ | ldr CARG3, L->maxstack
344
+ | cmp BASE, CARG3
345
+ | bhs >8
346
+ | str TISNIL, [BASE], #8
347
+ | add RC, RC, #8
348
+ | b <2
349
+ |
350
+ |7: // Less results wanted.
351
+ | cbz CARG2, <3 // LUA_MULTRET+1 case?
352
+ | sub CARG1, RC, CARG2, lsl #3
353
+ | sub BASE, BASE, CARG1 // Shrink top.
354
+ | b <3
355
+ |
356
+ |8: // Corner case: need to grow stack for filling up results.
357
+ | // This can happen if:
358
+ | // - A C function grows the stack (a lot).
359
+ | // - The GC shrinks the stack in between.
360
+ | // - A return back from a lua_call() with (high) nresults adjustment.
361
+ | str BASE, L->top // Save current top held in BASE (yes).
362
+ | mov CARG1, L
363
+ | bl extern lj_state_growstack // (lua_State *L, int n)
364
+ | ldr BASE, L->top // Need the (realloced) L->top in BASE.
365
+ | ldrsw CARG2, SAVE_NRES
366
+ | b <2
367
+ |
368
+ |->vm_unwind_c: // Unwind C stack, return from vm_pcall.
369
+ | // (void *cframe, int errcode)
370
+ | mov sp, CARG1
371
+ | mov CRET1, CARG2
372
+ |->vm_unwind_c_eh: // Landing pad for external unwinder.
373
+ | ldr L, SAVE_L
374
+ | mv_vmstate TMP0w, C
375
+ | ldr GL, L->glref
376
+ | st_vmstate TMP0w
377
+ | b ->vm_leave_unw
378
+ |
379
+ |->vm_unwind_ff: // Unwind C stack, return from ff pcall.
380
+ | // (void *cframe)
381
+ | and sp, CARG1, #CFRAME_RAWMASK
382
+ |->vm_unwind_ff_eh: // Landing pad for external unwinder.
383
+ | ldr L, SAVE_L
384
+ | movz TISNUM, #(LJ_TISNUM>>1)&0xffff, lsl #48
385
+ | movz TISNUMhi, #(LJ_TISNUM>>1)&0xffff, lsl #16
386
+ | movn TISNIL, #0
387
+ | mov RC, #16 // 2 results: false + error message.
388
+ | ldr BASE, L->base
389
+ | ldr GL, L->glref // Setup pointer to global state.
390
+ | mov_false TMP0
391
+ | sub RA, BASE, #8 // Results start at BASE-8.
392
+ | ldr PC, [BASE, FRAME_PC] // Fetch PC of previous frame.
393
+ | str TMP0, [BASE, #-8] // Prepend false to error message.
394
+ | st_vmstate ST_INTERP
395
+ | b ->vm_returnc
396
+ |
397
+ |//-----------------------------------------------------------------------
398
+ |//-- Grow stack for calls -----------------------------------------------
399
+ |//-----------------------------------------------------------------------
400
+ |
401
+ |->vm_growstack_c: // Grow stack for C function.
402
+ | // CARG1 = L
403
+ | mov CARG2, #LUA_MINSTACK
404
+ | b >2
405
+ |
406
+ |->vm_growstack_l: // Grow stack for Lua function.
407
+ | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC
408
+ | add RC, BASE, RC
409
+ | sub RA, RA, BASE
410
+ | mov CARG1, L
411
+ | stp BASE, RC, L->base
412
+ | add PC, PC, #4 // Must point after first instruction.
413
+ | lsr CARG2, RA, #3
414
+ |2:
415
+ | // L->base = new base, L->top = top
416
+ | str PC, SAVE_PC
417
+ | bl extern lj_state_growstack // (lua_State *L, int n)
418
+ | ldp BASE, RC, L->base
419
+ | ldr LFUNC:CARG3, [BASE, FRAME_FUNC]
420
+ | sub NARGS8:RC, RC, BASE
421
+ | and LFUNC:CARG3, CARG3, #LJ_GCVMASK
422
+ | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC
423
+ | ins_callt // Just retry the call.
424
+ |
425
+ |//-----------------------------------------------------------------------
426
+ |//-- Entry points into the assembler VM ---------------------------------
427
+ |//-----------------------------------------------------------------------
428
+ |
429
+ |->vm_resume: // Setup C frame and resume thread.
430
+ | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0)
431
+ | saveregs
432
+ | mov L, CARG1
433
+ | ldr GL, L->glref // Setup pointer to global state.
434
+ | mov BASE, CARG2
435
+ | str L, SAVE_L
436
+ | mov PC, #FRAME_CP
437
+ | str wzr, SAVE_NRES
438
+ | add TMP0, sp, #CFRAME_RESUME
439
+ | ldrb TMP1w, L->status
440
+ | str wzr, SAVE_ERRF
441
+ | str L, SAVE_PC // Any value outside of bytecode is ok.
442
+ | str xzr, SAVE_CFRAME
443
+ | str TMP0, L->cframe
444
+ | cbz TMP1w, >3
445
+ |
446
+ | // Resume after yield (like a return).
447
+ | str L, GL->cur_L
448
+ | mov RA, BASE
449
+ | ldp BASE, CARG1, L->base
450
+ | movz TISNUM, #(LJ_TISNUM>>1)&0xffff, lsl #48
451
+ | movz TISNUMhi, #(LJ_TISNUM>>1)&0xffff, lsl #16
452
+ | ldr PC, [BASE, FRAME_PC]
453
+ | strb wzr, L->status
454
+ | movn TISNIL, #0
455
+ | sub RC, CARG1, BASE
456
+ | ands CARG1, PC, #FRAME_TYPE
457
+ | add RC, RC, #8
458
+ | st_vmstate ST_INTERP
459
+ | str RCw, SAVE_MULTRES
460
+ | beq ->BC_RET_Z
461
+ | b ->vm_return
462
+ |
463
+ |->vm_pcall: // Setup protected C frame and enter VM.
464
+ | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef)
465
+ | saveregs
466
+ | mov PC, #FRAME_CP
467
+ | str CARG4w, SAVE_ERRF
468
+ | b >1
469
+ |
470
+ |->vm_call: // Setup C frame and enter VM.
471
+ | // (lua_State *L, TValue *base, int nres1)
472
+ | saveregs
473
+ | mov PC, #FRAME_C
474
+ |
475
+ |1: // Entry point for vm_pcall above (PC = ftype).
476
+ | ldr RC, L:CARG1->cframe
477
+ | str CARG3w, SAVE_NRES
478
+ | mov L, CARG1
479
+ | str CARG1, SAVE_L
480
+ | ldr GL, L->glref // Setup pointer to global state.
481
+ | mov BASE, CARG2
482
+ | str CARG1, SAVE_PC // Any value outside of bytecode is ok.
483
+ | str RC, SAVE_CFRAME
484
+ | str fp, L->cframe // Add our C frame to cframe chain.
485
+ |
486
+ |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype).
487
+ | str L, GL->cur_L
488
+ | ldp RB, CARG1, L->base // RB = old base (for vmeta_call).
489
+ | movz TISNUM, #(LJ_TISNUM>>1)&0xffff, lsl #48
490
+ | movz TISNUMhi, #(LJ_TISNUM>>1)&0xffff, lsl #16
491
+ | add PC, PC, BASE
492
+ | movn TISNIL, #0
493
+ | sub PC, PC, RB // PC = frame delta + frame type
494
+ | sub NARGS8:RC, CARG1, BASE
495
+ | st_vmstate ST_INTERP
496
+ |
497
+ |->vm_call_dispatch:
498
+ | // RB = old base, BASE = new base, RC = nargs*8, PC = caller PC
499
+ | ldr CARG3, [BASE, FRAME_FUNC]
500
+ | checkfunc CARG3, ->vmeta_call
501
+ |
502
+ |->vm_call_dispatch_f:
503
+ | ins_call
504
+ | // BASE = new base, CARG3 = func, RC = nargs*8, PC = caller PC
505
+ |
506
+ |->vm_cpcall: // Setup protected C frame, call C.
507
+ | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp)
508
+ | saveregs
509
+ | mov L, CARG1
510
+ | ldr RA, L:CARG1->stack
511
+ | str CARG1, SAVE_L
512
+ | ldr GL, L->glref // Setup pointer to global state.
513
+ | ldr RB, L->top
514
+ | str CARG1, SAVE_PC // Any value outside of bytecode is ok.
515
+ | ldr RC, L->cframe
516
+ | sub RA, RA, RB // Compute -savestack(L, L->top).
517
+ | str RAw, SAVE_NRES // Neg. delta means cframe w/o frame.
518
+ | str wzr, SAVE_ERRF // No error function.
519
+ | str RC, SAVE_CFRAME
520
+ | str fp, L->cframe // Add our C frame to cframe chain.
521
+ | str L, GL->cur_L
522
+ | blr CARG4 // (lua_State *L, lua_CFunction func, void *ud)
523
+ | mov BASE, CRET1
524
+ | mov PC, #FRAME_CP
525
+ | cbnz BASE, <3 // Else continue with the call.
526
+ | b ->vm_leave_cp // No base? Just remove C frame.
527
+ |
528
+ |//-----------------------------------------------------------------------
529
+ |//-- Metamethod handling ------------------------------------------------
530
+ |//-----------------------------------------------------------------------
531
+ |
532
+ |//-- Continuation dispatch ----------------------------------------------
533
+ |
534
+ |->cont_dispatch:
535
+ | // BASE = meta base, RA = resultptr, RC = (nresults+1)*8
536
+ | ldr LFUNC:CARG3, [RB, FRAME_FUNC]
537
+ | ldr CARG1, [BASE, #-32] // Get continuation.
538
+ | mov CARG4, BASE
539
+ | mov BASE, RB // Restore caller BASE.
540
+ | and LFUNC:CARG3, CARG3, #LJ_GCVMASK
541
+ |.if FFI
542
+ | cmp CARG1, #1
543
+ |.endif
544
+ | ldr PC, [CARG4, #-24] // Restore PC from [cont|PC].
545
+ | ldr CARG3, LFUNC:CARG3->pc
546
+ | add TMP0, RA, RC
547
+ | str TISNIL, [TMP0, #-8] // Ensure one valid arg.
548
+ |.if FFI
549
+ | bls >1
550
+ |.endif
551
+ | ldr KBASE, [CARG3, #PC2PROTO(k)]
552
+ | // BASE = base, RA = resultptr, CARG4 = meta base
553
+ | br CARG1
554
+ |
555
+ |.if FFI
556
+ |1:
557
+ | beq ->cont_ffi_callback // cont = 1: return from FFI callback.
558
+ | // cont = 0: tailcall from C function.
559
+ | sub CARG4, CARG4, #32
560
+ | sub RC, CARG4, BASE
561
+ | b ->vm_call_tail
562
+ |.endif
563
+ |
564
+ |->cont_cat: // RA = resultptr, CARG4 = meta base
565
+ | ldr INSw, [PC, #-4]
566
+ | sub CARG2, CARG4, #32
567
+ | ldr TMP0, [RA]
568
+ | str BASE, L->base
569
+ | decode_RB RB, INS
570
+ | decode_RA RA, INS
571
+ | add TMP1, BASE, RB, lsl #3
572
+ | subs TMP1, CARG2, TMP1
573
+ | beq >1
574
+ | str TMP0, [CARG2]
575
+ | lsr CARG3, TMP1, #3
576
+ | b ->BC_CAT_Z
577
+ |
578
+ |1:
579
+ | str TMP0, [BASE, RA, lsl #3]
580
+ | b ->cont_nop
581
+ |
582
+ |//-- Table indexing metamethods -----------------------------------------
583
+ |
584
+ |->vmeta_tgets1:
585
+ | movn CARG4, #~LJ_TSTR
586
+ | add CARG2, BASE, RB, lsl #3
587
+ | add CARG4, STR:RC, CARG4, lsl #47
588
+ | b >2
589
+ |
590
+ |->vmeta_tgets:
591
+ | movk CARG2, #(LJ_TTAB>>1)&0xffff, lsl #48
592
+ | str CARG2, GL->tmptv
593
+ | add CARG2, GL, #offsetof(global_State, tmptv)
594
+ |2:
595
+ | add CARG3, sp, TMPDofs
596
+ | str CARG4, TMPD
597
+ | b >1
598
+ |
599
+ |->vmeta_tgetb: // RB = table, RC = index
600
+ | add RC, RC, TISNUM
601
+ | add CARG2, BASE, RB, lsl #3
602
+ | add CARG3, sp, TMPDofs
603
+ | str RC, TMPD
604
+ | b >1
605
+ |
606
+ |->vmeta_tgetv: // RB = table, RC = key
607
+ | add CARG2, BASE, RB, lsl #3
608
+ | add CARG3, BASE, RC, lsl #3
609
+ |1:
610
+ | str BASE, L->base
611
+ | mov CARG1, L
612
+ | str PC, SAVE_PC
613
+ | bl extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k)
614
+ | // Returns TValue * (finished) or NULL (metamethod).
615
+ | cbz CRET1, >3
616
+ | ldr TMP0, [CRET1]
617
+ | str TMP0, [BASE, RA, lsl #3]
618
+ | ins_next
619
+ |
620
+ |3: // Call __index metamethod.
621
+ | // BASE = base, L->top = new base, stack = cont/func/t/k
622
+ | sub TMP1, BASE, #FRAME_CONT
623
+ | ldr BASE, L->top
624
+ | mov NARGS8:RC, #16 // 2 args for func(t, k).
625
+ | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here.
626
+ | str PC, [BASE, #-24] // [cont|PC]
627
+ | sub PC, BASE, TMP1
628
+ | and LFUNC:CARG3, CARG3, #LJ_GCVMASK
629
+ | b ->vm_call_dispatch_f
630
+ |
631
+ |->vmeta_tgetr:
632
+ | sxtw CARG2, TMP1w
633
+ | bl extern lj_tab_getinth // (GCtab *t, int32_t key)
634
+ | // Returns cTValue * or NULL.
635
+ | mov TMP0, TISNIL
636
+ | cbz CRET1, ->BC_TGETR_Z
637
+ | ldr TMP0, [CRET1]
638
+ | b ->BC_TGETR_Z
639
+ |
640
+ |//-----------------------------------------------------------------------
641
+ |
642
+ |->vmeta_tsets1:
643
+ | movn CARG4, #~LJ_TSTR
644
+ | add CARG2, BASE, RB, lsl #3
645
+ | add CARG4, STR:RC, CARG4, lsl #47
646
+ | b >2
647
+ |
648
+ |->vmeta_tsets:
649
+ | movk CARG2, #(LJ_TTAB>>1)&0xffff, lsl #48
650
+ | str CARG2, GL->tmptv
651
+ | add CARG2, GL, #offsetof(global_State, tmptv)
652
+ |2:
653
+ | add CARG3, sp, TMPDofs
654
+ | str CARG4, TMPD
655
+ | b >1
656
+ |
657
+ |->vmeta_tsetb: // RB = table, RC = index
658
+ | add RC, RC, TISNUM
659
+ | add CARG2, BASE, RB, lsl #3
660
+ | add CARG3, sp, TMPDofs
661
+ | str RC, TMPD
662
+ | b >1
663
+ |
664
+ |->vmeta_tsetv:
665
+ | add CARG2, BASE, RB, lsl #3
666
+ | add CARG3, BASE, RC, lsl #3
667
+ |1:
668
+ | str BASE, L->base
669
+ | mov CARG1, L
670
+ | str PC, SAVE_PC
671
+ | bl extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k)
672
+ | // Returns TValue * (finished) or NULL (metamethod).
673
+ | ldr TMP0, [BASE, RA, lsl #3]
674
+ | cbz CRET1, >3
675
+ | // NOBARRIER: lj_meta_tset ensures the table is not black.
676
+ | str TMP0, [CRET1]
677
+ | ins_next
678
+ |
679
+ |3: // Call __newindex metamethod.
680
+ | // BASE = base, L->top = new base, stack = cont/func/t/k/(v)
681
+ | sub TMP1, BASE, #FRAME_CONT
682
+ | ldr BASE, L->top
683
+ | mov NARGS8:RC, #24 // 3 args for func(t, k, v).
684
+ | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here.
685
+ | str TMP0, [BASE, #16] // Copy value to third argument.
686
+ | str PC, [BASE, #-24] // [cont|PC]
687
+ | sub PC, BASE, TMP1
688
+ | and LFUNC:CARG3, CARG3, #LJ_GCVMASK
689
+ | b ->vm_call_dispatch_f
690
+ |
691
+ |->vmeta_tsetr:
692
+ | sxtw CARG3, TMP1w
693
+ | str BASE, L->base
694
+ | str PC, SAVE_PC
695
+ | bl extern lj_tab_setinth // (lua_State *L, GCtab *t, int32_t key)
696
+ | // Returns TValue *.
697
+ | b ->BC_TSETR_Z
698
+ |
699
+ |//-- Comparison metamethods ---------------------------------------------
700
+ |
701
+ |->vmeta_comp:
702
+ | add CARG2, BASE, RA, lsl #3
703
+ | sub PC, PC, #4
704
+ | add CARG3, BASE, RC, lsl #3
705
+ | str BASE, L->base
706
+ | mov CARG1, L
707
+ | str PC, SAVE_PC
708
+ | uxtb CARG4w, INSw
709
+ | bl extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op)
710
+ | // Returns 0/1 or TValue * (metamethod).
711
+ |3:
712
+ | cmp CRET1, #1
713
+ | bhi ->vmeta_binop
714
+ |4:
715
+ | ldrh RBw, [PC, #2]
716
+ | add PC, PC, #4
717
+ | add RB, PC, RB, lsl #2
718
+ | sub RB, RB, #0x20000
719
+ | csel PC, PC, RB, lo
720
+ |->cont_nop:
721
+ | ins_next
722
+ |
723
+ |->cont_ra: // RA = resultptr
724
+ | ldr INSw, [PC, #-4]
725
+ | ldr TMP0, [RA]
726
+ | decode_RA TMP1, INS
727
+ | str TMP0, [BASE, TMP1, lsl #3]
728
+ | b ->cont_nop
729
+ |
730
+ |->cont_condt: // RA = resultptr
731
+ | ldr TMP0, [RA]
732
+ | mov_true TMP1
733
+ | cmp TMP1, TMP0 // Branch if result is true.
734
+ | b <4
735
+ |
736
+ |->cont_condf: // RA = resultptr
737
+ | ldr TMP0, [RA]
738
+ | mov_false TMP1
739
+ | cmp TMP0, TMP1 // Branch if result is false.
740
+ | b <4
741
+ |
742
+ |->vmeta_equal:
743
+ | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV.
744
+ | and TAB:CARG3, CARG3, #LJ_GCVMASK
745
+ | sub PC, PC, #4
746
+ | str BASE, L->base
747
+ | mov CARG1, L
748
+ | str PC, SAVE_PC
749
+ | bl extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne)
750
+ | // Returns 0/1 or TValue * (metamethod).
751
+ | b <3
752
+ |
753
+ |->vmeta_equal_cd:
754
+ |.if FFI
755
+ | sub PC, PC, #4
756
+ | str BASE, L->base
757
+ | mov CARG1, L
758
+ | mov CARG2, INS
759
+ | str PC, SAVE_PC
760
+ | bl extern lj_meta_equal_cd // (lua_State *L, BCIns op)
761
+ | // Returns 0/1 or TValue * (metamethod).
762
+ | b <3
763
+ |.endif
764
+ |
765
+ |->vmeta_istype:
766
+ | sub PC, PC, #4
767
+ | str BASE, L->base
768
+ | mov CARG1, L
769
+ | mov CARG2, RA
770
+ | mov CARG3, RC
771
+ | str PC, SAVE_PC
772
+ | bl extern lj_meta_istype // (lua_State *L, BCReg ra, BCReg tp)
773
+ | b ->cont_nop
774
+ |
775
+ |//-- Arithmetic metamethods ---------------------------------------------
776
+ |
777
+ |->vmeta_arith_vn:
778
+ | add CARG3, BASE, RB, lsl #3
779
+ | add CARG4, KBASE, RC, lsl #3
780
+ | b >1
781
+ |
782
+ |->vmeta_arith_nv:
783
+ | add CARG4, BASE, RB, lsl #3
784
+ | add CARG3, KBASE, RC, lsl #3
785
+ | b >1
786
+ |
787
+ |->vmeta_unm:
788
+ | add CARG3, BASE, RC, lsl #3
789
+ | mov CARG4, CARG3
790
+ | b >1
791
+ |
792
+ |->vmeta_arith_vv:
793
+ | add CARG3, BASE, RB, lsl #3
794
+ | add CARG4, BASE, RC, lsl #3
795
+ |1:
796
+ | uxtb CARG5w, INSw
797
+ | add CARG2, BASE, RA, lsl #3
798
+ | str BASE, L->base
799
+ | mov CARG1, L
800
+ | str PC, SAVE_PC
801
+ | bl extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
802
+ | // Returns NULL (finished) or TValue * (metamethod).
803
+ | cbz CRET1, ->cont_nop
804
+ |
805
+ | // Call metamethod for binary op.
806
+ |->vmeta_binop:
807
+ | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2
808
+ | sub TMP1, CRET1, BASE
809
+ | str PC, [CRET1, #-24] // [cont|PC]
810
+ | add PC, TMP1, #FRAME_CONT
811
+ | mov BASE, CRET1
812
+ | mov NARGS8:RC, #16 // 2 args for func(o1, o2).
813
+ | b ->vm_call_dispatch
814
+ |
815
+ |->vmeta_len:
816
+ | add CARG2, BASE, RC, lsl #3
817
+ #if LJ_52
818
+ | mov TAB:RC, TAB:CARG1 // Save table (ignored for other types).
819
+ #endif
820
+ | str BASE, L->base
821
+ | mov CARG1, L
822
+ | str PC, SAVE_PC
823
+ | bl extern lj_meta_len // (lua_State *L, TValue *o)
824
+ | // Returns NULL (retry) or TValue * (metamethod base).
825
+ #if LJ_52
826
+ | cbnz CRET1, ->vmeta_binop // Binop call for compatibility.
827
+ | mov TAB:CARG1, TAB:RC
828
+ | b ->BC_LEN_Z
829
+ #else
830
+ | b ->vmeta_binop // Binop call for compatibility.
831
+ #endif
832
+ |
833
+ |//-- Call metamethod ----------------------------------------------------
834
+ |
835
+ |->vmeta_call: // Resolve and call __call metamethod.
836
+ | // RB = old base, BASE = new base, RC = nargs*8
837
+ | mov CARG1, L
838
+ | str RB, L->base // This is the callers base!
839
+ | sub CARG2, BASE, #16
840
+ | str PC, SAVE_PC
841
+ | add CARG3, BASE, NARGS8:RC
842
+ | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top)
843
+ | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here.
844
+ | add NARGS8:RC, NARGS8:RC, #8 // Got one more argument now.
845
+ | and LFUNC:CARG3, CARG3, #LJ_GCVMASK
846
+ | ins_call
847
+ |
848
+ |->vmeta_callt: // Resolve __call for BC_CALLT.
849
+ | // BASE = old base, RA = new base, RC = nargs*8
850
+ | mov CARG1, L
851
+ | str BASE, L->base
852
+ | sub CARG2, RA, #16
853
+ | str PC, SAVE_PC
854
+ | add CARG3, RA, NARGS8:RC
855
+ | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top)
856
+ | ldr TMP1, [RA, FRAME_FUNC] // Guaranteed to be a function here.
857
+ | ldr PC, [BASE, FRAME_PC]
858
+ | add NARGS8:RC, NARGS8:RC, #8 // Got one more argument now.
859
+ | and LFUNC:CARG3, TMP1, #LJ_GCVMASK
860
+ | b ->BC_CALLT2_Z
861
+ |
862
+ |//-- Argument coercion for 'for' statement ------------------------------
863
+ |
864
+ |->vmeta_for:
865
+ | mov CARG1, L
866
+ | str BASE, L->base
867
+ | mov CARG2, RA
868
+ | str PC, SAVE_PC
869
+ | bl extern lj_meta_for // (lua_State *L, TValue *base)
870
+ | ldr INSw, [PC, #-4]
871
+ |.if JIT
872
+ | uxtb TMP0, INS
873
+ |.endif
874
+ | decode_RA RA, INS
875
+ | decode_RD RC, INS
876
+ |.if JIT
877
+ | cmp TMP0, #BC_JFORI
878
+ | beq =>BC_JFORI
879
+ |.endif
880
+ | b =>BC_FORI
881
+ |
882
+ |//-----------------------------------------------------------------------
883
+ |//-- Fast functions -----------------------------------------------------
884
+ |//-----------------------------------------------------------------------
885
+ |
886
+ |.macro .ffunc, name
887
+ |->ff_ .. name:
888
+ |.endmacro
889
+ |
890
+ |.macro .ffunc_1, name
891
+ |->ff_ .. name:
892
+ | ldr CARG1, [BASE]
893
+ | cmp NARGS8:RC, #8
894
+ | blo ->fff_fallback
895
+ |.endmacro
896
+ |
897
+ |.macro .ffunc_2, name
898
+ |->ff_ .. name:
899
+ | ldp CARG1, CARG2, [BASE]
900
+ | cmp NARGS8:RC, #16
901
+ | blo ->fff_fallback
902
+ |.endmacro
903
+ |
904
+ |.macro .ffunc_n, name
905
+ | .ffunc name
906
+ | ldr CARG1, [BASE]
907
+ | cmp NARGS8:RC, #8
908
+ | ldr FARG1, [BASE]
909
+ | blo ->fff_fallback
910
+ | checknum CARG1, ->fff_fallback
911
+ |.endmacro
912
+ |
913
+ |.macro .ffunc_nn, name
914
+ | .ffunc name
915
+ | ldp CARG1, CARG2, [BASE]
916
+ | cmp NARGS8:RC, #16
917
+ | ldp FARG1, FARG2, [BASE]
918
+ | blo ->fff_fallback
919
+ | checknum CARG1, ->fff_fallback
920
+ | checknum CARG2, ->fff_fallback
921
+ |.endmacro
922
+ |
923
+ |// Inlined GC threshold check. Caveat: uses CARG1 and CARG2.
924
+ |.macro ffgccheck
925
+ | ldp CARG1, CARG2, GL->gc.total // Assumes threshold follows total.
926
+ | cmp CARG1, CARG2
927
+ | blt >1
928
+ | bl ->fff_gcstep
929
+ |1:
930
+ |.endmacro
931
+ |
932
+ |//-- Base library: checks -----------------------------------------------
933
+ |
934
+ |.ffunc_1 assert
935
+ | ldr PC, [BASE, FRAME_PC]
936
+ | mov_false TMP1
937
+ | cmp CARG1, TMP1
938
+ | bhs ->fff_fallback
939
+ | str CARG1, [BASE, #-16]
940
+ | sub RB, BASE, #8
941
+ | subs RA, NARGS8:RC, #8
942
+ | add RC, NARGS8:RC, #8 // Compute (nresults+1)*8.
943
+ | cbz RA, ->fff_res // Done if exactly 1 argument.
944
+ |1:
945
+ | ldr CARG1, [RB, #16]
946
+ | sub RA, RA, #8
947
+ | str CARG1, [RB], #8
948
+ | cbnz RA, <1
949
+ | b ->fff_res
950
+ |
951
+ |.ffunc_1 type
952
+ | mov TMP0, #~LJ_TISNUM
953
+ | asr ITYPE, CARG1, #47
954
+ | cmn ITYPE, #~LJ_TISNUM
955
+ | csinv TMP1, TMP0, ITYPE, lo
956
+ | add TMP1, TMP1, #offsetof(GCfuncC, upvalue)/8
957
+ | ldr CARG1, [CFUNC:CARG3, TMP1, lsl #3]
958
+ | b ->fff_restv
959
+ |
960
+ |//-- Base library: getters and setters ---------------------------------
961
+ |
962
+ |.ffunc_1 getmetatable
963
+ | asr ITYPE, CARG1, #47
964
+ | cmn ITYPE, #-LJ_TTAB
965
+ | ccmn ITYPE, #-LJ_TUDATA, #4, ne
966
+ | and TAB:CARG1, CARG1, #LJ_GCVMASK
967
+ | bne >6
968
+ |1: // Field metatable must be at same offset for GCtab and GCudata!
969
+ | ldr TAB:RB, TAB:CARG1->metatable
970
+ |2:
971
+ | mov CARG1, TISNIL
972
+ | ldr STR:RC, GL->gcroot[GCROOT_MMNAME+MM_metatable]
973
+ | cbz TAB:RB, ->fff_restv
974
+ | ldr TMP1w, TAB:RB->hmask
975
+ | ldr TMP2w, STR:RC->hash
976
+ | ldr NODE:CARG3, TAB:RB->node
977
+ | and TMP1w, TMP1w, TMP2w // idx = str->hash & tab->hmask
978
+ | add TMP1, TMP1, TMP1, lsl #1
979
+ | movn CARG4, #~LJ_TSTR
980
+ | add NODE:CARG3, NODE:CARG3, TMP1, lsl #3 // node = tab->node + idx*3*8
981
+ | add CARG4, STR:RC, CARG4, lsl #47 // Tagged key to look for.
982
+ |3: // Rearranged logic, because we expect _not_ to find the key.
983
+ | ldp CARG1, TMP0, NODE:CARG3->val
984
+ | ldr NODE:CARG3, NODE:CARG3->next
985
+ | cmp TMP0, CARG4
986
+ | beq >5
987
+ | cbnz NODE:CARG3, <3
988
+ |4:
989
+ | mov CARG1, RB // Use metatable as default result.
990
+ | movk CARG1, #(LJ_TTAB>>1)&0xffff, lsl #48
991
+ | b ->fff_restv
992
+ |5:
993
+ | cmp TMP0, TISNIL
994
+ | bne ->fff_restv
995
+ | b <4
996
+ |
997
+ |6:
998
+ | movn TMP0, #~LJ_TISNUM
999
+ | cmp ITYPE, TMP0
1000
+ | csel ITYPE, ITYPE, TMP0, hs
1001
+ | sub TMP1, GL, ITYPE, lsl #3
1002
+ | ldr TAB:RB, [TMP1, #offsetof(global_State, gcroot[GCROOT_BASEMT])-8]
1003
+ | b <2
1004
+ |
1005
+ |.ffunc_2 setmetatable
1006
+ | // Fast path: no mt for table yet and not clearing the mt.
1007
+ | checktp TMP1, CARG1, LJ_TTAB, ->fff_fallback
1008
+ | ldr TAB:TMP0, TAB:TMP1->metatable
1009
+ | asr ITYPE, CARG2, #47
1010
+ | ldrb TMP2w, TAB:TMP1->marked
1011
+ | cmn ITYPE, #-LJ_TTAB
1012
+ | and TAB:CARG2, CARG2, #LJ_GCVMASK
1013
+ | ccmp TAB:TMP0, #0, #0, eq
1014
+ | bne ->fff_fallback
1015
+ | str TAB:CARG2, TAB:TMP1->metatable
1016
+ | tbz TMP2w, #2, ->fff_restv // isblack(table)
1017
+ | barrierback TAB:TMP1, TMP2w, TMP0
1018
+ | b ->fff_restv
1019
+ |
1020
+ |.ffunc rawget
1021
+ | ldr CARG2, [BASE]
1022
+ | cmp NARGS8:RC, #16
1023
+ | blo ->fff_fallback
1024
+ | checktab CARG2, ->fff_fallback
1025
+ | mov CARG1, L
1026
+ | add CARG3, BASE, #8
1027
+ | bl extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key)
1028
+ | // Returns cTValue *.
1029
+ | ldr CARG1, [CRET1]
1030
+ | b ->fff_restv
1031
+ |
1032
+ |//-- Base library: conversions ------------------------------------------
1033
+ |
1034
+ |.ffunc tonumber
1035
+ | // Only handles the number case inline (without a base argument).
1036
+ | ldr CARG1, [BASE]
1037
+ | cmp NARGS8:RC, #8
1038
+ | bne ->fff_fallback
1039
+ | checknumber CARG1, ->fff_fallback
1040
+ | b ->fff_restv
1041
+ |
1042
+ |.ffunc_1 tostring
1043
+ | // Only handles the string or number case inline.
1044
+ | asr ITYPE, CARG1, #47
1045
+ | cmn ITYPE, #-LJ_TSTR
1046
+ | // A __tostring method in the string base metatable is ignored.
1047
+ | beq ->fff_restv
1048
+ | // Handle numbers inline, unless a number base metatable is present.
1049
+ | ldr TMP1, GL->gcroot[GCROOT_BASEMT_NUM]
1050
+ | str BASE, L->base
1051
+ | cmn ITYPE, #-LJ_TISNUM
1052
+ | ccmp TMP1, #0, #0, ls
1053
+ | str PC, SAVE_PC // Redundant (but a defined value).
1054
+ | bne ->fff_fallback
1055
+ | ffgccheck
1056
+ | mov CARG1, L
1057
+ | mov CARG2, BASE
1058
+ | bl extern lj_strfmt_number // (lua_State *L, cTValue *o)
1059
+ | // Returns GCstr *.
1060
+ | movn TMP1, #~LJ_TSTR
1061
+ | ldr BASE, L->base
1062
+ | add CARG1, CARG1, TMP1, lsl #47
1063
+ | b ->fff_restv
1064
+ |
1065
+ |//-- Base library: iterators -------------------------------------------
1066
+ |
1067
+ |.ffunc_1 next
1068
+ | checktp CARG2, CARG1, LJ_TTAB, ->fff_fallback
1069
+ | str TISNIL, [BASE, NARGS8:RC] // Set missing 2nd arg to nil.
1070
+ | ldr PC, [BASE, FRAME_PC]
1071
+ | stp BASE, BASE, L->base // Add frame since C call can throw.
1072
+ | mov CARG1, L
1073
+ | add CARG3, BASE, #8
1074
+ | str PC, SAVE_PC
1075
+ | bl extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key)
1076
+ | // Returns 0 at end of traversal.
1077
+ | str TISNIL, [BASE, #-16]
1078
+ | cbz CRET1, ->fff_res1 // End of traversal: return nil.
1079
+ | ldp CARG1, CARG2, [BASE, #8] // Copy key and value to results.
1080
+ | mov RC, #(2+1)*8
1081
+ | stp CARG1, CARG2, [BASE, #-16]
1082
+ | b ->fff_res
1083
+ |
1084
+ |.ffunc_1 pairs
1085
+ | checktp TMP1, CARG1, LJ_TTAB, ->fff_fallback
1086
+ #if LJ_52
1087
+ | ldr TAB:CARG2, TAB:TMP1->metatable
1088
+ #endif
1089
+ | ldr CFUNC:CARG4, CFUNC:CARG3->upvalue[0]
1090
+ | ldr PC, [BASE, FRAME_PC]
1091
+ #if LJ_52
1092
+ | cbnz TAB:CARG2, ->fff_fallback
1093
+ #endif
1094
+ | mov RC, #(3+1)*8
1095
+ | stp CARG1, TISNIL, [BASE, #-8]
1096
+ | str CFUNC:CARG4, [BASE, #-16]
1097
+ | b ->fff_res
1098
+ |
1099
+ |.ffunc_2 ipairs_aux
1100
+ | checktab CARG1, ->fff_fallback
1101
+ | checkint CARG2, ->fff_fallback
1102
+ | ldr TMP1w, TAB:CARG1->asize
1103
+ | ldr CARG3, TAB:CARG1->array
1104
+ | ldr TMP0w, TAB:CARG1->hmask
1105
+ | add CARG2w, CARG2w, #1
1106
+ | cmp CARG2w, TMP1w
1107
+ | ldr PC, [BASE, FRAME_PC]
1108
+ | add TMP2, CARG2, TISNUM
1109
+ | mov RC, #(0+1)*8
1110
+ | str TMP2, [BASE, #-16]
1111
+ | bhs >2 // Not in array part?
1112
+ | ldr TMP0, [CARG3, CARG2, lsl #3]
1113
+ |1:
1114
+ | mov TMP1, #(2+1)*8
1115
+ | cmp TMP0, TISNIL
1116
+ | str TMP0, [BASE, #-8]
1117
+ | csel RC, RC, TMP1, eq
1118
+ | b ->fff_res
1119
+ |2: // Check for empty hash part first. Otherwise call C function.
1120
+ | cbz TMP0w, ->fff_res
1121
+ | bl extern lj_tab_getinth // (GCtab *t, int32_t key)
1122
+ | // Returns cTValue * or NULL.
1123
+ | cbz CRET1, ->fff_res
1124
+ | ldr TMP0, [CRET1]
1125
+ | b <1
1126
+ |
1127
+ |.ffunc_1 ipairs
1128
+ | checktp TMP1, CARG1, LJ_TTAB, ->fff_fallback
1129
+ #if LJ_52
1130
+ | ldr TAB:CARG2, TAB:TMP1->metatable
1131
+ #endif
1132
+ | ldr CFUNC:CARG4, CFUNC:CARG3->upvalue[0]
1133
+ | ldr PC, [BASE, FRAME_PC]
1134
+ #if LJ_52
1135
+ | cbnz TAB:CARG2, ->fff_fallback
1136
+ #endif
1137
+ | mov RC, #(3+1)*8
1138
+ | stp CARG1, TISNUM, [BASE, #-8]
1139
+ | str CFUNC:CARG4, [BASE, #-16]
1140
+ | b ->fff_res
1141
+ |
1142
+ |//-- Base library: catch errors ----------------------------------------
1143
+ |
1144
+ |.ffunc pcall
1145
+ | ldrb TMP0w, GL->hookmask
1146
+ | subs NARGS8:RC, NARGS8:RC, #8
1147
+ | blo ->fff_fallback
1148
+ | mov RB, BASE
1149
+ | add BASE, BASE, #16
1150
+ | ubfx TMP0w, TMP0w, #HOOK_ACTIVE_SHIFT, #1
1151
+ | add PC, TMP0, #16+FRAME_PCALL
1152
+ | beq ->vm_call_dispatch
1153
+ |1:
1154
+ | add TMP2, BASE, NARGS8:RC
1155
+ |2:
1156
+ | ldr TMP0, [TMP2, #-16]
1157
+ | str TMP0, [TMP2, #-8]!
1158
+ | cmp TMP2, BASE
1159
+ | bne <2
1160
+ | b ->vm_call_dispatch
1161
+ |
1162
+ |.ffunc xpcall
1163
+ | ldp CARG1, CARG2, [BASE]
1164
+ | ldrb TMP0w, GL->hookmask
1165
+ | subs NARGS8:RC, NARGS8:RC, #16
1166
+ | blo ->fff_fallback
1167
+ | mov RB, BASE
1168
+ | add BASE, BASE, #24
1169
+ | asr ITYPE, CARG2, #47
1170
+ | ubfx TMP0w, TMP0w, #HOOK_ACTIVE_SHIFT, #1
1171
+ | cmn ITYPE, #-LJ_TFUNC
1172
+ | add PC, TMP0, #24+FRAME_PCALL
1173
+ | bne ->fff_fallback // Traceback must be a function.
1174
+ | stp CARG2, CARG1, [RB] // Swap function and traceback.
1175
+ | cbz NARGS8:RC, ->vm_call_dispatch
1176
+ | b <1
1177
+ |
1178
+ |//-- Coroutine library --------------------------------------------------
1179
+ |
1180
+ |.macro coroutine_resume_wrap, resume
1181
+ |.if resume
1182
+ |.ffunc_1 coroutine_resume
1183
+ | checktp CARG1, LJ_TTHREAD, ->fff_fallback
1184
+ |.else
1185
+ |.ffunc coroutine_wrap_aux
1186
+ | ldr L:CARG1, CFUNC:CARG3->upvalue[0].gcr
1187
+ | and L:CARG1, CARG1, #LJ_GCVMASK
1188
+ |.endif
1189
+ | ldr PC, [BASE, FRAME_PC]
1190
+ | str BASE, L->base
1191
+ | ldp RB, CARG2, L:CARG1->base
1192
+ | ldrb TMP1w, L:CARG1->status
1193
+ | add TMP0, CARG2, TMP1
1194
+ | str PC, SAVE_PC
1195
+ | cmp TMP0, RB
1196
+ | beq ->fff_fallback
1197
+ | cmp TMP1, #LUA_YIELD
1198
+ | add TMP0, CARG2, #8
1199
+ | csel CARG2, CARG2, TMP0, hs
1200
+ | ldr CARG4, L:CARG1->maxstack
1201
+ | add CARG3, CARG2, NARGS8:RC
1202
+ | ldr RB, L:CARG1->cframe
1203
+ | ccmp CARG3, CARG4, #2, ls
1204
+ | ccmp RB, #0, #2, ls
1205
+ | bhi ->fff_fallback
1206
+ |.if resume
1207
+ | sub CARG3, CARG3, #8 // Keep resumed thread in stack for GC.
1208
+ | add BASE, BASE, #8
1209
+ | sub NARGS8:RC, NARGS8:RC, #8
1210
+ |.endif
1211
+ | str CARG3, L:CARG1->top
1212
+ | str BASE, L->top
1213
+ | cbz NARGS8:RC, >3
1214
+ |2: // Move args to coroutine.
1215
+ | ldr TMP0, [BASE, RB]
1216
+ | cmp RB, NARGS8:RC
1217
+ | str TMP0, [CARG2, RB]
1218
+ | add RB, RB, #8
1219
+ | bne <2
1220
+ |3:
1221
+ | mov CARG3, #0
1222
+ | mov L:RA, L:CARG1
1223
+ | mov CARG4, #0
1224
+ | bl ->vm_resume // (lua_State *L, TValue *base, 0, 0)
1225
+ | // Returns thread status.
1226
+ |4:
1227
+ | ldp CARG3, CARG4, L:RA->base
1228
+ | cmp CRET1, #LUA_YIELD
1229
+ | ldr BASE, L->base
1230
+ | str L, GL->cur_L
1231
+ | st_vmstate ST_INTERP
1232
+ | bhi >8
1233
+ | sub RC, CARG4, CARG3
1234
+ | ldr CARG1, L->maxstack
1235
+ | add CARG2, BASE, RC
1236
+ | cbz RC, >6 // No results?
1237
+ | cmp CARG2, CARG1
1238
+ | mov RB, #0
1239
+ | bhi >9 // Need to grow stack?
1240
+ |
1241
+ | sub CARG4, RC, #8
1242
+ | str CARG3, L:RA->top // Clear coroutine stack.
1243
+ |5: // Move results from coroutine.
1244
+ | ldr TMP0, [CARG3, RB]
1245
+ | cmp RB, CARG4
1246
+ | str TMP0, [BASE, RB]
1247
+ | add RB, RB, #8
1248
+ | bne <5
1249
+ |6:
1250
+ |.if resume
1251
+ | mov_true TMP1
1252
+ | add RC, RC, #16
1253
+ |7:
1254
+ | str TMP1, [BASE, #-8] // Prepend true/false to results.
1255
+ | sub RA, BASE, #8
1256
+ |.else
1257
+ | mov RA, BASE
1258
+ | add RC, RC, #8
1259
+ |.endif
1260
+ | ands CARG1, PC, #FRAME_TYPE
1261
+ | str PC, SAVE_PC
1262
+ | str RCw, SAVE_MULTRES
1263
+ | beq ->BC_RET_Z
1264
+ | b ->vm_return
1265
+ |
1266
+ |8: // Coroutine returned with error (at co->top-1).
1267
+ |.if resume
1268
+ | ldr TMP0, [CARG4, #-8]!
1269
+ | mov_false TMP1
1270
+ | mov RC, #(2+1)*8
1271
+ | str CARG4, L:RA->top // Remove error from coroutine stack.
1272
+ | str TMP0, [BASE] // Copy error message.
1273
+ | b <7
1274
+ |.else
1275
+ | mov CARG1, L
1276
+ | mov CARG2, L:RA
1277
+ | bl extern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co)
1278
+ | // Never returns.
1279
+ |.endif
1280
+ |
1281
+ |9: // Handle stack expansion on return from yield.
1282
+ | mov CARG1, L
1283
+ | lsr CARG2, RC, #3
1284
+ | bl extern lj_state_growstack // (lua_State *L, int n)
1285
+ | mov CRET1, #0
1286
+ | b <4
1287
+ |.endmacro
1288
+ |
1289
+ | coroutine_resume_wrap 1 // coroutine.resume
1290
+ | coroutine_resume_wrap 0 // coroutine.wrap
1291
+ |
1292
+ |.ffunc coroutine_yield
1293
+ | ldr TMP0, L->cframe
1294
+ | add TMP1, BASE, NARGS8:RC
1295
+ | mov CRET1, #LUA_YIELD
1296
+ | stp BASE, TMP1, L->base
1297
+ | tbz TMP0, #0, ->fff_fallback
1298
+ | str xzr, L->cframe
1299
+ | strb CRET1w, L->status
1300
+ | b ->vm_leave_unw
1301
+ |
1302
+ |//-- Math library -------------------------------------------------------
1303
+ |
1304
+ |.macro math_round, func, round
1305
+ | .ffunc math_ .. func
1306
+ | ldr CARG1, [BASE]
1307
+ | cmp NARGS8:RC, #8
1308
+ | ldr d0, [BASE]
1309
+ | blo ->fff_fallback
1310
+ | cmp TISNUMhi, CARG1, lsr #32
1311
+ | beq ->fff_restv
1312
+ | blo ->fff_fallback
1313
+ | round d0, d0
1314
+ | b ->fff_resn
1315
+ |.endmacro
1316
+ |
1317
+ | math_round floor, frintm
1318
+ | math_round ceil, frintp
1319
+ |
1320
+ |.ffunc_1 math_abs
1321
+ | checknumber CARG1, ->fff_fallback
1322
+ | and CARG1, CARG1, #U64x(7fffffff,ffffffff)
1323
+ | bne ->fff_restv
1324
+ | eor CARG2w, CARG1w, CARG1w, asr #31
1325
+ | movz CARG3, #0x41e0, lsl #48 // 2^31.
1326
+ | subs CARG1w, CARG2w, CARG1w, asr #31
1327
+ | add CARG1, CARG1, TISNUM
1328
+ | csel CARG1, CARG1, CARG3, pl
1329
+ | // Fallthrough.
1330
+ |
1331
+ |->fff_restv:
1332
+ | // CARG1 = TValue result.
1333
+ | ldr PC, [BASE, FRAME_PC]
1334
+ | str CARG1, [BASE, #-16]
1335
+ |->fff_res1:
1336
+ | // PC = return.
1337
+ | mov RC, #(1+1)*8
1338
+ |->fff_res:
1339
+ | // RC = (nresults+1)*8, PC = return.
1340
+ | ands CARG1, PC, #FRAME_TYPE
1341
+ | str RCw, SAVE_MULTRES
1342
+ | sub RA, BASE, #16
1343
+ | bne ->vm_return
1344
+ | ldr INSw, [PC, #-4]
1345
+ | decode_RB RB, INS
1346
+ |5:
1347
+ | cmp RC, RB, lsl #3 // More results expected?
1348
+ | blo >6
1349
+ | decode_RA TMP1, INS
1350
+ | // Adjust BASE. KBASE is assumed to be set for the calling frame.
1351
+ | sub BASE, RA, TMP1, lsl #3
1352
+ | ins_next
1353
+ |
1354
+ |6: // Fill up results with nil.
1355
+ | add TMP1, RA, RC
1356
+ | add RC, RC, #8
1357
+ | str TISNIL, [TMP1, #-8]
1358
+ | b <5
1359
+ |
1360
+ |.macro math_extern, func
1361
+ | .ffunc_n math_ .. func
1362
+ | bl extern func
1363
+ | b ->fff_resn
1364
+ |.endmacro
1365
+ |
1366
+ |.macro math_extern2, func
1367
+ | .ffunc_nn math_ .. func
1368
+ | bl extern func
1369
+ | b ->fff_resn
1370
+ |.endmacro
1371
+ |
1372
+ |.ffunc_n math_sqrt
1373
+ | fsqrt d0, d0
1374
+ |->fff_resn:
1375
+ | ldr PC, [BASE, FRAME_PC]
1376
+ | str d0, [BASE, #-16]
1377
+ | b ->fff_res1
1378
+ |
1379
+ |.ffunc math_log
1380
+ | ldr CARG1, [BASE]
1381
+ | cmp NARGS8:RC, #8
1382
+ | ldr FARG1, [BASE]
1383
+ | bne ->fff_fallback // Need exactly 1 argument.
1384
+ | checknum CARG1, ->fff_fallback
1385
+ | bl extern log
1386
+ | b ->fff_resn
1387
+ |
1388
+ | math_extern log10
1389
+ | math_extern exp
1390
+ | math_extern sin
1391
+ | math_extern cos
1392
+ | math_extern tan
1393
+ | math_extern asin
1394
+ | math_extern acos
1395
+ | math_extern atan
1396
+ | math_extern sinh
1397
+ | math_extern cosh
1398
+ | math_extern tanh
1399
+ | math_extern2 pow
1400
+ | math_extern2 atan2
1401
+ | math_extern2 fmod
1402
+ |
1403
+ |.ffunc_2 math_ldexp
1404
+ | ldr FARG1, [BASE]
1405
+ | checknum CARG1, ->fff_fallback
1406
+ | checkint CARG2, ->fff_fallback
1407
+ | sxtw CARG1, CARG2w
1408
+ | bl extern ldexp // (double x, int exp)
1409
+ | b ->fff_resn
1410
+ |
1411
+ |.ffunc_n math_frexp
1412
+ | add CARG1, sp, TMPDofs
1413
+ | bl extern frexp
1414
+ | ldr CARG2w, TMPD
1415
+ | ldr PC, [BASE, FRAME_PC]
1416
+ | str d0, [BASE, #-16]
1417
+ | mov RC, #(2+1)*8
1418
+ | add CARG2, CARG2, TISNUM
1419
+ | str CARG2, [BASE, #-8]
1420
+ | b ->fff_res
1421
+ |
1422
+ |.ffunc_n math_modf
1423
+ | sub CARG1, BASE, #16
1424
+ | ldr PC, [BASE, FRAME_PC]
1425
+ | bl extern modf
1426
+ | mov RC, #(2+1)*8
1427
+ | str d0, [BASE, #-8]
1428
+ | b ->fff_res
1429
+ |
1430
+ |.macro math_minmax, name, cond, fcond
1431
+ | .ffunc_1 name
1432
+ | add RB, BASE, RC
1433
+ | add RA, BASE, #8
1434
+ | checkint CARG1, >4
1435
+ |1: // Handle integers.
1436
+ | ldr CARG2, [RA]
1437
+ | cmp RA, RB
1438
+ | bhs ->fff_restv
1439
+ | checkint CARG2, >3
1440
+ | cmp CARG1w, CARG2w
1441
+ | add RA, RA, #8
1442
+ | csel CARG1, CARG2, CARG1, cond
1443
+ | b <1
1444
+ |3: // Convert intermediate result to number and continue below.
1445
+ | scvtf d0, CARG1w
1446
+ | blo ->fff_fallback
1447
+ | ldr d1, [RA]
1448
+ | b >6
1449
+ |
1450
+ |4:
1451
+ | ldr d0, [BASE]
1452
+ | blo ->fff_fallback
1453
+ |5: // Handle numbers.
1454
+ | ldr CARG2, [RA]
1455
+ | ldr d1, [RA]
1456
+ | cmp RA, RB
1457
+ | bhs ->fff_resn
1458
+ | checknum CARG2, >7
1459
+ |6:
1460
+ | fcmp d0, d1
1461
+ | add RA, RA, #8
1462
+ | fcsel d0, d1, d0, fcond
1463
+ | b <5
1464
+ |7: // Convert integer to number and continue above.
1465
+ | scvtf d1, CARG2w
1466
+ | blo ->fff_fallback
1467
+ | b <6
1468
+ |.endmacro
1469
+ |
1470
+ | math_minmax math_min, gt, hi
1471
+ | math_minmax math_max, lt, lo
1472
+ |
1473
+ |//-- String library -----------------------------------------------------
1474
+ |
1475
+ |.ffunc string_byte // Only handle the 1-arg case here.
1476
+ | ldp PC, CARG1, [BASE, FRAME_PC]
1477
+ | cmp NARGS8:RC, #8
1478
+ | asr ITYPE, CARG1, #47
1479
+ | ccmn ITYPE, #-LJ_TSTR, #0, eq
1480
+ | and STR:CARG1, CARG1, #LJ_GCVMASK
1481
+ | bne ->fff_fallback
1482
+ | ldrb TMP0w, STR:CARG1[1] // Access is always ok (NUL at end).
1483
+ | ldr CARG3w, STR:CARG1->len
1484
+ | add TMP0, TMP0, TISNUM
1485
+ | str TMP0, [BASE, #-16]
1486
+ | mov RC, #(0+1)*8
1487
+ | cbz CARG3, ->fff_res
1488
+ | b ->fff_res1
1489
+ |
1490
+ |.ffunc string_char // Only handle the 1-arg case here.
1491
+ | ffgccheck
1492
+ | ldp PC, CARG1, [BASE, FRAME_PC]
1493
+ | cmp CARG1w, #255
1494
+ | ccmp NARGS8:RC, #8, #0, ls // Need exactly 1 argument.
1495
+ | bne ->fff_fallback
1496
+ | checkint CARG1, ->fff_fallback
1497
+ | mov CARG3, #1
1498
+ | mov CARG2, BASE // Points to stack. Little-endian.
1499
+ |->fff_newstr:
1500
+ | // CARG2 = str, CARG3 = len.
1501
+ | str BASE, L->base
1502
+ | mov CARG1, L
1503
+ | str PC, SAVE_PC
1504
+ | bl extern lj_str_new // (lua_State *L, char *str, size_t l)
1505
+ |->fff_resstr:
1506
+ | // Returns GCstr *.
1507
+ | ldr BASE, L->base
1508
+ | movn TMP1, #~LJ_TSTR
1509
+ | add CARG1, CARG1, TMP1, lsl #47
1510
+ | b ->fff_restv
1511
+ |
1512
+ |.ffunc string_sub
1513
+ | ffgccheck
1514
+ | ldr CARG1, [BASE]
1515
+ | ldr CARG3, [BASE, #16]
1516
+ | cmp NARGS8:RC, #16
1517
+ | movn RB, #0
1518
+ | beq >1
1519
+ | blo ->fff_fallback
1520
+ | checkint CARG3, ->fff_fallback
1521
+ | sxtw RB, CARG3w
1522
+ |1:
1523
+ | ldr CARG2, [BASE, #8]
1524
+ | checkstr CARG1, ->fff_fallback
1525
+ | ldr TMP1w, STR:CARG1->len
1526
+ | checkint CARG2, ->fff_fallback
1527
+ | sxtw CARG2, CARG2w
1528
+ | // CARG1 = str, TMP1 = str->len, CARG2 = start, RB = end
1529
+ | add TMP2, RB, TMP1
1530
+ | cmp RB, #0
1531
+ | add TMP0, CARG2, TMP1
1532
+ | csinc RB, RB, TMP2, ge // if (end < 0) end += len+1
1533
+ | cmp CARG2, #0
1534
+ | csinc CARG2, CARG2, TMP0, ge // if (start < 0) start += len+1
1535
+ | cmp RB, #0
1536
+ | csel RB, RB, xzr, ge // if (end < 0) end = 0
1537
+ | cmp CARG2, #1
1538
+ | csinc CARG2, CARG2, xzr, ge // if (start < 1) start = 1
1539
+ | cmp RB, TMP1
1540
+ | csel RB, RB, TMP1, le // if (end > len) end = len
1541
+ | add CARG1, STR:CARG1, #sizeof(GCstr)-1
1542
+ | subs CARG3, RB, CARG2 // len = end - start
1543
+ | add CARG2, CARG1, CARG2
1544
+ | add CARG3, CARG3, #1 // len += 1
1545
+ | bge ->fff_newstr
1546
+ | add STR:CARG1, GL, #offsetof(global_State, strempty)
1547
+ | movn TMP1, #~LJ_TSTR
1548
+ | add CARG1, CARG1, TMP1, lsl #47
1549
+ | b ->fff_restv
1550
+ |
1551
+ |.macro ffstring_op, name
1552
+ | .ffunc string_ .. name
1553
+ | ffgccheck
1554
+ | ldr CARG2, [BASE]
1555
+ | cmp NARGS8:RC, #8
1556
+ | asr ITYPE, CARG2, #47
1557
+ | ccmn ITYPE, #-LJ_TSTR, #0, hs
1558
+ | and STR:CARG2, CARG2, #LJ_GCVMASK
1559
+ | bne ->fff_fallback
1560
+ | ldr TMP0, GL->tmpbuf.b
1561
+ | add SBUF:CARG1, GL, #offsetof(global_State, tmpbuf)
1562
+ | str BASE, L->base
1563
+ | str PC, SAVE_PC
1564
+ | str L, GL->tmpbuf.L
1565
+ | str TMP0, GL->tmpbuf.p
1566
+ | bl extern lj_buf_putstr_ .. name
1567
+ | bl extern lj_buf_tostr
1568
+ | b ->fff_resstr
1569
+ |.endmacro
1570
+ |
1571
+ |ffstring_op reverse
1572
+ |ffstring_op lower
1573
+ |ffstring_op upper
1574
+ |
1575
+ |//-- Bit library --------------------------------------------------------
1576
+ |
1577
+ |// FP number to bit conversion for soft-float. Clobbers CARG1-CARG3
1578
+ |->vm_tobit_fb:
1579
+ | bls ->fff_fallback
1580
+ | add CARG2, CARG1, CARG1
1581
+ | mov CARG3, #1076
1582
+ | sub CARG3, CARG3, CARG2, lsr #53
1583
+ | cmp CARG3, #53
1584
+ | bhi >1
1585
+ | and CARG2, CARG2, #U64x(001fffff,ffffffff)
1586
+ | orr CARG2, CARG2, #U64x(00200000,00000000)
1587
+ | cmp CARG1, #0
1588
+ | lsr CARG2, CARG2, CARG3
1589
+ | cneg CARG1w, CARG2w, mi
1590
+ | br lr
1591
+ |1:
1592
+ | mov CARG1w, #0
1593
+ | br lr
1594
+ |
1595
+ |.macro .ffunc_bit, name
1596
+ | .ffunc_1 bit_..name
1597
+ | adr lr, >1
1598
+ | checkint CARG1, ->vm_tobit_fb
1599
+ |1:
1600
+ |.endmacro
1601
+ |
1602
+ |.macro .ffunc_bit_op, name, ins
1603
+ | .ffunc_bit name
1604
+ | mov RA, #8
1605
+ | mov TMP0w, CARG1w
1606
+ | adr lr, >2
1607
+ |1:
1608
+ | ldr CARG1, [BASE, RA]
1609
+ | cmp RA, NARGS8:RC
1610
+ | add RA, RA, #8
1611
+ | bge >9
1612
+ | checkint CARG1, ->vm_tobit_fb
1613
+ |2:
1614
+ | ins TMP0w, TMP0w, CARG1w
1615
+ | b <1
1616
+ |.endmacro
1617
+ |
1618
+ |.ffunc_bit_op band, and
1619
+ |.ffunc_bit_op bor, orr
1620
+ |.ffunc_bit_op bxor, eor
1621
+ |
1622
+ |.ffunc_bit tobit
1623
+ | mov TMP0w, CARG1w
1624
+ |9: // Label reused by .ffunc_bit_op users.
1625
+ | add CARG1, TMP0, TISNUM
1626
+ | b ->fff_restv
1627
+ |
1628
+ |.ffunc_bit bswap
1629
+ | rev TMP0w, CARG1w
1630
+ | add CARG1, TMP0, TISNUM
1631
+ | b ->fff_restv
1632
+ |
1633
+ |.ffunc_bit bnot
1634
+ | mvn TMP0w, CARG1w
1635
+ | add CARG1, TMP0, TISNUM
1636
+ | b ->fff_restv
1637
+ |
1638
+ |.macro .ffunc_bit_sh, name, ins, shmod
1639
+ | .ffunc bit_..name
1640
+ | ldp TMP0, CARG1, [BASE]
1641
+ | cmp NARGS8:RC, #16
1642
+ | blo ->fff_fallback
1643
+ | adr lr, >1
1644
+ | checkint CARG1, ->vm_tobit_fb
1645
+ |1:
1646
+ |.if shmod == 0
1647
+ | mov TMP1, CARG1
1648
+ |.else
1649
+ | neg TMP1, CARG1
1650
+ |.endif
1651
+ | mov CARG1, TMP0
1652
+ | adr lr, >2
1653
+ | checkint CARG1, ->vm_tobit_fb
1654
+ |2:
1655
+ | ins TMP0w, CARG1w, TMP1w
1656
+ | add CARG1, TMP0, TISNUM
1657
+ | b ->fff_restv
1658
+ |.endmacro
1659
+ |
1660
+ |.ffunc_bit_sh lshift, lsl, 0
1661
+ |.ffunc_bit_sh rshift, lsr, 0
1662
+ |.ffunc_bit_sh arshift, asr, 0
1663
+ |.ffunc_bit_sh rol, ror, 1
1664
+ |.ffunc_bit_sh ror, ror, 0
1665
+ |
1666
+ |//-----------------------------------------------------------------------
1667
+ |
1668
+ |->fff_fallback: // Call fast function fallback handler.
1669
+ | // BASE = new base, RC = nargs*8
1670
+ | ldp CFUNC:CARG3, PC, [BASE, FRAME_FUNC] // Fallback may overwrite PC.
1671
+ | ldr TMP2, L->maxstack
1672
+ | add TMP1, BASE, NARGS8:RC
1673
+ | stp BASE, TMP1, L->base
1674
+ | and CFUNC:CARG3, CARG3, #LJ_GCVMASK
1675
+ | add TMP1, TMP1, #8*LUA_MINSTACK
1676
+ | ldr CARG3, CFUNC:CARG3->f
1677
+ | str PC, SAVE_PC // Redundant (but a defined value).
1678
+ | cmp TMP1, TMP2
1679
+ | mov CARG1, L
1680
+ | bhi >5 // Need to grow stack.
1681
+ | blr CARG3 // (lua_State *L)
1682
+ | // Either throws an error, or recovers and returns -1, 0 or nresults+1.
1683
+ | ldr BASE, L->base
1684
+ | cmp CRET1w, #0
1685
+ | lsl RC, CRET1, #3
1686
+ | sub RA, BASE, #16
1687
+ | bgt ->fff_res // Returned nresults+1?
1688
+ |1: // Returned 0 or -1: retry fast path.
1689
+ | ldr CARG1, L->top
1690
+ | ldr CFUNC:CARG3, [BASE, FRAME_FUNC]
1691
+ | sub NARGS8:RC, CARG1, BASE
1692
+ | bne ->vm_call_tail // Returned -1?
1693
+ | and CFUNC:CARG3, CARG3, #LJ_GCVMASK
1694
+ | ins_callt // Returned 0: retry fast path.
1695
+ |
1696
+ |// Reconstruct previous base for vmeta_call during tailcall.
1697
+ |->vm_call_tail:
1698
+ | ands TMP0, PC, #FRAME_TYPE
1699
+ | and TMP1, PC, #~FRAME_TYPEP
1700
+ | bne >3
1701
+ | ldrb RAw, [PC, #-3]
1702
+ | lsl RA, RA, #3
1703
+ | add TMP1, RA, #16
1704
+ |3:
1705
+ | sub RB, BASE, TMP1
1706
+ | b ->vm_call_dispatch // Resolve again for tailcall.
1707
+ |
1708
+ |5: // Grow stack for fallback handler.
1709
+ | mov CARG2, #LUA_MINSTACK
1710
+ | bl extern lj_state_growstack // (lua_State *L, int n)
1711
+ | ldr BASE, L->base
1712
+ | cmp CARG1, CARG1 // Set zero-flag to force retry.
1713
+ | b <1
1714
+ |
1715
+ |->fff_gcstep: // Call GC step function.
1716
+ | // BASE = new base, RC = nargs*8
1717
+ | add CARG2, BASE, NARGS8:RC // Calculate L->top.
1718
+ | mov RA, lr
1719
+ | stp BASE, CARG2, L->base
1720
+ | str PC, SAVE_PC // Redundant (but a defined value).
1721
+ | mov CARG1, L
1722
+ | bl extern lj_gc_step // (lua_State *L)
1723
+ | ldp BASE, CARG2, L->base
1724
+ | ldr CFUNC:CARG3, [BASE, FRAME_FUNC]
1725
+ | mov lr, RA // Help return address predictor.
1726
+ | sub NARGS8:RC, CARG2, BASE // Calculate nargs*8.
1727
+ | and CFUNC:CARG3, CARG3, #LJ_GCVMASK
1728
+ | ret
1729
+ |
1730
+ |//-----------------------------------------------------------------------
1731
+ |//-- Special dispatch targets -------------------------------------------
1732
+ |//-----------------------------------------------------------------------
1733
+ |
1734
+ |->vm_record: // Dispatch target for recording phase.
1735
+ | NYI
1736
+ |
1737
+ |->vm_rethook: // Dispatch target for return hooks.
1738
+ | ldrb TMP2w, GL->hookmask
1739
+ | tbz TMP2w, #HOOK_ACTIVE_SHIFT, >1 // Hook already active?
1740
+ |5: // Re-dispatch to static ins.
1741
+ | ldr TMP0, [TMP1, #GG_G2DISP+GG_DISP2STATIC]
1742
+ | br TMP0
1743
+ |
1744
+ |->vm_inshook: // Dispatch target for instr/line hooks.
1745
+ | ldrb TMP2w, GL->hookmask
1746
+ | ldr TMP3w, GL->hookcount
1747
+ | tbnz TMP2w, #HOOK_ACTIVE_SHIFT, <5 // Hook already active?
1748
+ | tst TMP2w, #LUA_MASKLINE|LUA_MASKCOUNT
1749
+ | beq <5
1750
+ | sub TMP3w, TMP3w, #1
1751
+ | str TMP3w, GL->hookcount
1752
+ | cbz TMP3w, >1
1753
+ | tbz TMP2w, #LUA_HOOKLINE, <5
1754
+ |1:
1755
+ | mov CARG1, L
1756
+ | str BASE, L->base
1757
+ | mov CARG2, PC
1758
+ | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC.
1759
+ | bl extern lj_dispatch_ins // (lua_State *L, const BCIns *pc)
1760
+ |3:
1761
+ | ldr BASE, L->base
1762
+ |4: // Re-dispatch to static ins.
1763
+ | ldr INSw, [PC, #-4]
1764
+ | add TMP1, GL, INS, uxtb #3
1765
+ | decode_RA RA, INS
1766
+ | ldr TMP0, [TMP1, #GG_G2DISP+GG_DISP2STATIC]
1767
+ | decode_RD RC, INS
1768
+ | br TMP0
1769
+ |
1770
+ |->cont_hook: // Continue from hook yield.
1771
+ | ldr CARG1, [CARG4, #-40]
1772
+ | add PC, PC, #4
1773
+ | str CARG1w, SAVE_MULTRES // Restore MULTRES for *M ins.
1774
+ | b <4
1775
+ |
1776
+ |->vm_hotloop: // Hot loop counter underflow.
1777
+ | NYI
1778
+ |
1779
+ |->vm_callhook: // Dispatch target for call hooks.
1780
+ | mov CARG2, PC
1781
+ |.if JIT
1782
+ | b >1
1783
+ |.endif
1784
+ |
1785
+ |->vm_hotcall: // Hot call counter underflow.
1786
+ |.if JIT
1787
+ | orr CARG2, PC, #1
1788
+ |1:
1789
+ |.endif
1790
+ | add TMP1, BASE, NARGS8:RC
1791
+ | str PC, SAVE_PC
1792
+ | mov CARG1, L
1793
+ | sub RA, RA, BASE
1794
+ | stp BASE, TMP1, L->base
1795
+ | bl extern lj_dispatch_call // (lua_State *L, const BCIns *pc)
1796
+ | // Returns ASMFunction.
1797
+ | ldp BASE, TMP1, L->base
1798
+ | str xzr, SAVE_PC // Invalidate for subsequent line hook.
1799
+ | ldr LFUNC:CARG3, [BASE, FRAME_FUNC]
1800
+ | add RA, BASE, RA
1801
+ | sub NARGS8:RC, TMP1, BASE
1802
+ | ldr INSw, [PC, #-4]
1803
+ | and LFUNC:CARG3, CARG3, #LJ_GCVMASK
1804
+ | br CRET1
1805
+ |
1806
+ |->cont_stitch: // Trace stitching.
1807
+ | NYI
1808
+ |
1809
+ |->vm_profhook: // Dispatch target for profiler hook.
1810
+ #if LJ_HASPROFILE
1811
+ | mov CARG1, L
1812
+ | str BASE, L->base
1813
+ | mov CARG2, PC
1814
+ | bl extern lj_dispatch_profile // (lua_State *L, const BCIns *pc)
1815
+ | // HOOK_PROFILE is off again, so re-dispatch to dynamic instruction.
1816
+ | ldr BASE, L->base
1817
+ | sub PC, PC, #4
1818
+ | b ->cont_nop
1819
+ #endif
1820
+ |
1821
+ |//-----------------------------------------------------------------------
1822
+ |//-- Trace exit handler -------------------------------------------------
1823
+ |//-----------------------------------------------------------------------
1824
+ |
1825
+ |->vm_exit_handler:
1826
+ | NYI
1827
+ |->vm_exit_interp:
1828
+ | NYI
1829
+ |
1830
+ |//-----------------------------------------------------------------------
1831
+ |//-- Math helper functions ----------------------------------------------
1832
+ |//-----------------------------------------------------------------------
1833
+ |
1834
+ | // int lj_vm_modi(int dividend, int divisor);
1835
+ |->vm_modi:
1836
+ | eor CARG4w, CARG1w, CARG2w
1837
+ | cmp CARG4w, #0
1838
+ | eor CARG3w, CARG1w, CARG1w, asr #31
1839
+ | eor CARG4w, CARG2w, CARG2w, asr #31
1840
+ | sub CARG3w, CARG3w, CARG1w, asr #31
1841
+ | sub CARG4w, CARG4w, CARG2w, asr #31
1842
+ | udiv CARG1w, CARG3w, CARG4w
1843
+ | msub CARG1w, CARG1w, CARG4w, CARG3w
1844
+ | ccmp CARG1w, #0, #4, mi
1845
+ | sub CARG3w, CARG1w, CARG4w
1846
+ | csel CARG1w, CARG1w, CARG3w, eq
1847
+ | eor CARG3w, CARG1w, CARG2w
1848
+ | cmp CARG3w, #0
1849
+ | cneg CARG1w, CARG1w, mi
1850
+ | ret
1851
+ |
1852
+ |//-----------------------------------------------------------------------
1853
+ |//-- Miscellaneous functions --------------------------------------------
1854
+ |//-----------------------------------------------------------------------
1855
+ |
1856
+ |//-----------------------------------------------------------------------
1857
+ |//-- FFI helper functions -----------------------------------------------
1858
+ |//-----------------------------------------------------------------------
1859
+ |
1860
+ |// Handler for callback functions.
1861
+ |// Saveregs already performed. Callback slot number in [sp], g in r12.
1862
+ |->vm_ffi_callback:
1863
+ |.if FFI
1864
+ |.type CTSTATE, CTState, PC
1865
+ | saveregs
1866
+ | ldr CTSTATE, GL:x10->ctype_state
1867
+ | mov GL, x10
1868
+ | add x10, sp, # CFRAME_SPACE
1869
+ | str w9, CTSTATE->cb.slot
1870
+ | stp x0, x1, CTSTATE->cb.gpr[0]
1871
+ | stp d0, d1, CTSTATE->cb.fpr[0]
1872
+ | stp x2, x3, CTSTATE->cb.gpr[2]
1873
+ | stp d2, d3, CTSTATE->cb.fpr[2]
1874
+ | stp x4, x5, CTSTATE->cb.gpr[4]
1875
+ | stp d4, d5, CTSTATE->cb.fpr[4]
1876
+ | stp x6, x7, CTSTATE->cb.gpr[6]
1877
+ | stp d6, d7, CTSTATE->cb.fpr[6]
1878
+ | str x10, CTSTATE->cb.stack
1879
+ | mov CARG1, CTSTATE
1880
+ | str CTSTATE, SAVE_PC // Any value outside of bytecode is ok.
1881
+ | mov CARG2, sp
1882
+ | bl extern lj_ccallback_enter // (CTState *cts, void *cf)
1883
+ | // Returns lua_State *.
1884
+ | ldp BASE, RC, L:CRET1->base
1885
+ | movz TISNUM, #(LJ_TISNUM>>1)&0xffff, lsl #48
1886
+ | movz TISNUMhi, #(LJ_TISNUM>>1)&0xffff, lsl #16
1887
+ | movn TISNIL, #0
1888
+ | mov L, CRET1
1889
+ | ldr LFUNC:CARG3, [BASE, FRAME_FUNC]
1890
+ | sub RC, RC, BASE
1891
+ | st_vmstate ST_INTERP
1892
+ | and LFUNC:CARG3, CARG3, #LJ_GCVMASK
1893
+ | ins_callt
1894
+ |.endif
1895
+ |
1896
+ |->cont_ffi_callback: // Return from FFI callback.
1897
+ |.if FFI
1898
+ | ldr CTSTATE, GL->ctype_state
1899
+ | stp BASE, CARG4, L->base
1900
+ | str L, CTSTATE->L
1901
+ | mov CARG1, CTSTATE
1902
+ | mov CARG2, RA
1903
+ | bl extern lj_ccallback_leave // (CTState *cts, TValue *o)
1904
+ | ldp x0, x1, CTSTATE->cb.gpr[0]
1905
+ | ldp d0, d1, CTSTATE->cb.fpr[0]
1906
+ | b ->vm_leave_unw
1907
+ |.endif
1908
+ |
1909
+ |->vm_ffi_call: // Call C function via FFI.
1910
+ | // Caveat: needs special frame unwinding, see below.
1911
+ |.if FFI
1912
+ | .type CCSTATE, CCallState, x19
1913
+ | stp fp, lr, [sp, #-32]!
1914
+ | add fp, sp, #0
1915
+ | str CCSTATE, [sp, #16]
1916
+ | mov CCSTATE, x0
1917
+ | ldr TMP0w, CCSTATE:x0->spadj
1918
+ | ldrb TMP1w, CCSTATE->nsp
1919
+ | add TMP2, CCSTATE, #offsetof(CCallState, stack)
1920
+ | subs TMP1, TMP1, #1
1921
+ | ldr TMP3, CCSTATE->func
1922
+ | sub sp, fp, TMP0
1923
+ | bmi >2
1924
+ |1: // Copy stack slots
1925
+ | ldr TMP0, [TMP2, TMP1, lsl #3]
1926
+ | str TMP0, [sp, TMP1, lsl #3]
1927
+ | subs TMP1, TMP1, #1
1928
+ | bpl <1
1929
+ |2:
1930
+ | ldp x0, x1, CCSTATE->gpr[0]
1931
+ | ldp d0, d1, CCSTATE->fpr[0]
1932
+ | ldp x2, x3, CCSTATE->gpr[2]
1933
+ | ldp d2, d3, CCSTATE->fpr[2]
1934
+ | ldp x4, x5, CCSTATE->gpr[4]
1935
+ | ldp d4, d5, CCSTATE->fpr[4]
1936
+ | ldp x6, x7, CCSTATE->gpr[6]
1937
+ | ldp d6, d7, CCSTATE->fpr[6]
1938
+ | ldr x8, CCSTATE->retp
1939
+ | blr TMP3
1940
+ | mov sp, fp
1941
+ | stp x0, x1, CCSTATE->gpr[0]
1942
+ | stp d0, d1, CCSTATE->fpr[0]
1943
+ | stp d2, d3, CCSTATE->fpr[2]
1944
+ | ldr CCSTATE, [sp, #16]
1945
+ | ldp fp, lr, [sp], #32
1946
+ | ret
1947
+ |.endif
1948
+ |// Note: vm_ffi_call must be the last function in this object file!
1949
+ |
1950
+ |//-----------------------------------------------------------------------
1951
+ }
1952
+
1953
+ /* Generate the code for a single instruction. */
1954
+ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
1955
+ {
1956
+ int vk = 0;
1957
+ |=>defop:
1958
+
1959
+ switch (op) {
1960
+
1961
+ /* -- Comparison ops ---------------------------------------------------- */
1962
+
1963
+ /* Remember: all ops branch for a true comparison, fall through otherwise. */
1964
+
1965
+ case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
1966
+ | // RA = src1, RC = src2, JMP with RC = target
1967
+ | ldr CARG1, [BASE, RA, lsl #3]
1968
+ | ldrh RBw, [PC, #2]
1969
+ | ldr CARG2, [BASE, RC, lsl #3]
1970
+ | add PC, PC, #4
1971
+ | add RB, PC, RB, lsl #2
1972
+ | sub RB, RB, #0x20000
1973
+ | checkint CARG1, >3
1974
+ | checkint CARG2, >4
1975
+ | cmp CARG1w, CARG2w
1976
+ if (op == BC_ISLT) {
1977
+ | csel PC, RB, PC, lt
1978
+ } else if (op == BC_ISGE) {
1979
+ | csel PC, RB, PC, ge
1980
+ } else if (op == BC_ISLE) {
1981
+ | csel PC, RB, PC, le
1982
+ } else {
1983
+ | csel PC, RB, PC, gt
1984
+ }
1985
+ |1:
1986
+ | ins_next
1987
+ |
1988
+ |3: // RA not int.
1989
+ | ldr FARG1, [BASE, RA, lsl #3]
1990
+ | blo ->vmeta_comp
1991
+ | ldr FARG2, [BASE, RC, lsl #3]
1992
+ | cmp TISNUMhi, CARG2, lsr #32
1993
+ | bhi >5
1994
+ | bne ->vmeta_comp
1995
+ | // RA number, RC int.
1996
+ | scvtf FARG2, CARG2w
1997
+ | b >5
1998
+ |
1999
+ |4: // RA int, RC not int
2000
+ | ldr FARG2, [BASE, RC, lsl #3]
2001
+ | blo ->vmeta_comp
2002
+ | // RA int, RC number.
2003
+ | scvtf FARG1, CARG1w
2004
+ |
2005
+ |5: // RA number, RC number
2006
+ | fcmp FARG1, FARG2
2007
+ | // To preserve NaN semantics GE/GT branch on unordered, but LT/LE don't.
2008
+ if (op == BC_ISLT) {
2009
+ | csel PC, RB, PC, lo
2010
+ } else if (op == BC_ISGE) {
2011
+ | csel PC, RB, PC, hs
2012
+ } else if (op == BC_ISLE) {
2013
+ | csel PC, RB, PC, ls
2014
+ } else {
2015
+ | csel PC, RB, PC, hi
2016
+ }
2017
+ | b <1
2018
+ break;
2019
+
2020
+ case BC_ISEQV: case BC_ISNEV:
2021
+ vk = op == BC_ISEQV;
2022
+ | // RA = src1, RC = src2, JMP with RC = target
2023
+ | ldr CARG1, [BASE, RA, lsl #3]
2024
+ | add RC, BASE, RC, lsl #3
2025
+ | ldrh RBw, [PC, #2]
2026
+ | ldr CARG3, [RC]
2027
+ | add PC, PC, #4
2028
+ | add RB, PC, RB, lsl #2
2029
+ | sub RB, RB, #0x20000
2030
+ | asr ITYPE, CARG3, #47
2031
+ | cmn ITYPE, #-LJ_TISNUM
2032
+ if (vk) {
2033
+ | bls ->BC_ISEQN_Z
2034
+ } else {
2035
+ | bls ->BC_ISNEN_Z
2036
+ }
2037
+ | // RC is not a number.
2038
+ | asr TMP0, CARG1, #47
2039
+ |.if FFI
2040
+ | // Check if RC or RA is a cdata.
2041
+ | cmn ITYPE, #-LJ_TCDATA
2042
+ | ccmn TMP0, #-LJ_TCDATA, #4, ne
2043
+ | beq ->vmeta_equal_cd
2044
+ |.endif
2045
+ | cmp CARG1, CARG3
2046
+ | bne >2
2047
+ | // Tag and value are equal.
2048
+ if (vk) {
2049
+ |->BC_ISEQV_Z:
2050
+ | mov PC, RB // Perform branch.
2051
+ }
2052
+ |1:
2053
+ | ins_next
2054
+ |
2055
+ |2: // Check if the tags are the same and it's a table or userdata.
2056
+ | cmp ITYPE, TMP0
2057
+ | ccmn ITYPE, #-LJ_TISTABUD, #2, eq
2058
+ if (vk) {
2059
+ | bhi <1
2060
+ } else {
2061
+ | bhi ->BC_ISEQV_Z // Reuse code from opposite instruction.
2062
+ }
2063
+ | // Different tables or userdatas. Need to check __eq metamethod.
2064
+ | // Field metatable must be at same offset for GCtab and GCudata!
2065
+ | and TAB:CARG2, CARG1, #LJ_GCVMASK
2066
+ | ldr TAB:TMP2, TAB:CARG2->metatable
2067
+ if (vk) {
2068
+ | cbz TAB:TMP2, <1 // No metatable?
2069
+ | ldrb TMP1w, TAB:TMP2->nomm
2070
+ | mov CARG4, #0 // ne = 0
2071
+ | tbnz TMP1w, #MM_eq, <1 // 'no __eq' flag set: done.
2072
+ } else {
2073
+ | cbz TAB:TMP2, ->BC_ISEQV_Z // No metatable?
2074
+ | ldrb TMP1w, TAB:TMP2->nomm
2075
+ | mov CARG4, #1 // ne = 1.
2076
+ | tbnz TMP1w, #MM_eq, ->BC_ISEQV_Z // 'no __eq' flag set: done.
2077
+ }
2078
+ | b ->vmeta_equal
2079
+ break;
2080
+
2081
+ case BC_ISEQS: case BC_ISNES:
2082
+ vk = op == BC_ISEQS;
2083
+ | // RA = src, RC = str_const (~), JMP with RC = target
2084
+ | ldr CARG1, [BASE, RA, lsl #3]
2085
+ | mvn RC, RC
2086
+ | ldrh RBw, [PC, #2]
2087
+ | ldr CARG2, [KBASE, RC, lsl #3]
2088
+ | add PC, PC, #4
2089
+ | movn TMP0, #~LJ_TSTR
2090
+ |.if FFI
2091
+ | asr ITYPE, CARG1, #47
2092
+ |.endif
2093
+ | add RB, PC, RB, lsl #2
2094
+ | add CARG2, CARG2, TMP0, lsl #47
2095
+ | sub RB, RB, #0x20000
2096
+ |.if FFI
2097
+ | cmn ITYPE, #-LJ_TCDATA
2098
+ | beq ->vmeta_equal_cd
2099
+ |.endif
2100
+ | cmp CARG1, CARG2
2101
+ if (vk) {
2102
+ | csel PC, RB, PC, eq
2103
+ } else {
2104
+ | csel PC, RB, PC, ne
2105
+ }
2106
+ | ins_next
2107
+ break;
2108
+
2109
+ case BC_ISEQN: case BC_ISNEN:
2110
+ vk = op == BC_ISEQN;
2111
+ | // RA = src, RC = num_const (~), JMP with RC = target
2112
+ | ldr CARG1, [BASE, RA, lsl #3]
2113
+ | add RC, KBASE, RC, lsl #3
2114
+ | ldrh RBw, [PC, #2]
2115
+ | ldr CARG3, [RC]
2116
+ | add PC, PC, #4
2117
+ | add RB, PC, RB, lsl #2
2118
+ | sub RB, RB, #0x20000
2119
+ if (vk) {
2120
+ |->BC_ISEQN_Z:
2121
+ } else {
2122
+ |->BC_ISNEN_Z:
2123
+ }
2124
+ | checkint CARG1, >4
2125
+ | checkint CARG3, >6
2126
+ | cmp CARG1w, CARG3w
2127
+ |1:
2128
+ if (vk) {
2129
+ | csel PC, RB, PC, eq
2130
+ |2:
2131
+ } else {
2132
+ |2:
2133
+ | csel PC, RB, PC, ne
2134
+ }
2135
+ |3:
2136
+ | ins_next
2137
+ |
2138
+ |4: // RA not int.
2139
+ |.if FFI
2140
+ | blo >7
2141
+ |.else
2142
+ | blo <2
2143
+ |.endif
2144
+ | ldr FARG1, [BASE, RA, lsl #3]
2145
+ | ldr FARG2, [RC]
2146
+ | cmp TISNUMhi, CARG3, lsr #32
2147
+ | bne >5
2148
+ | // RA number, RC int.
2149
+ | scvtf FARG2, CARG3w
2150
+ |5:
2151
+ | // RA number, RC number.
2152
+ | fcmp FARG1, FARG2
2153
+ | b <1
2154
+ |
2155
+ |6: // RA int, RC number
2156
+ | ldr FARG2, [RC]
2157
+ | scvtf FARG1, CARG1w
2158
+ | fcmp FARG1, FARG2
2159
+ | b <1
2160
+ |
2161
+ |.if FFI
2162
+ |7:
2163
+ | asr ITYPE, CARG1, #47
2164
+ | cmn ITYPE, #-LJ_TCDATA
2165
+ | bne <2
2166
+ | b ->vmeta_equal_cd
2167
+ |.endif
2168
+ break;
2169
+
2170
+ case BC_ISEQP: case BC_ISNEP:
2171
+ vk = op == BC_ISEQP;
2172
+ | // RA = src, RC = primitive_type (~), JMP with RC = target
2173
+ | ldr TMP0, [BASE, RA, lsl #3]
2174
+ | ldrh RBw, [PC, #2]
2175
+ | add PC, PC, #4
2176
+ | add RC, RC, #1
2177
+ | add RB, PC, RB, lsl #2
2178
+ |.if FFI
2179
+ | asr ITYPE, TMP0, #47
2180
+ | cmn ITYPE, #-LJ_TCDATA
2181
+ | beq ->vmeta_equal_cd
2182
+ | cmn RC, ITYPE
2183
+ |.else
2184
+ | cmn RC, TMP0, asr #47
2185
+ |.endif
2186
+ | sub RB, RB, #0x20000
2187
+ if (vk) {
2188
+ | csel PC, RB, PC, eq
2189
+ } else {
2190
+ | csel PC, RB, PC, ne
2191
+ }
2192
+ | ins_next
2193
+ break;
2194
+
2195
+ /* -- Unary test and copy ops ------------------------------------------- */
2196
+
2197
+ case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF:
2198
+ | // RA = dst or unused, RC = src, JMP with RC = target
2199
+ | ldrh RBw, [PC, #2]
2200
+ | ldr TMP0, [BASE, RC, lsl #3]
2201
+ | add PC, PC, #4
2202
+ | mov_false TMP1
2203
+ | add RB, PC, RB, lsl #2
2204
+ | cmp TMP0, TMP1
2205
+ | sub RB, RB, #0x20000
2206
+ if (op == BC_ISTC || op == BC_IST) {
2207
+ if (op == BC_ISTC) {
2208
+ | csel RA, RA, RC, lo
2209
+ }
2210
+ | csel PC, RB, PC, lo
2211
+ } else {
2212
+ if (op == BC_ISFC) {
2213
+ | csel RA, RA, RC, hs
2214
+ }
2215
+ | csel PC, RB, PC, hs
2216
+ }
2217
+ if (op == BC_ISTC || op == BC_ISFC) {
2218
+ | str TMP0, [BASE, RA, lsl #3]
2219
+ }
2220
+ | ins_next
2221
+ break;
2222
+
2223
+ case BC_ISTYPE:
2224
+ | // RA = src, RC = -type
2225
+ | ldr TMP0, [BASE, RA, lsl #3]
2226
+ | cmn RC, TMP0, asr #47
2227
+ | bne ->vmeta_istype
2228
+ | ins_next
2229
+ break;
2230
+ case BC_ISNUM:
2231
+ | // RA = src, RC = -(TISNUM-1)
2232
+ | ldr TMP0, [BASE, RA]
2233
+ | checknum TMP0, ->vmeta_istype
2234
+ | ins_next
2235
+ break;
2236
+
2237
+ /* -- Unary ops --------------------------------------------------------- */
2238
+
2239
+ case BC_MOV:
2240
+ | // RA = dst, RC = src
2241
+ | ldr TMP0, [BASE, RC, lsl #3]
2242
+ | str TMP0, [BASE, RA, lsl #3]
2243
+ | ins_next
2244
+ break;
2245
+ case BC_NOT:
2246
+ | // RA = dst, RC = src
2247
+ | ldr TMP0, [BASE, RC, lsl #3]
2248
+ | mov_false TMP1
2249
+ | mov_true TMP2
2250
+ | cmp TMP0, TMP1
2251
+ | csel TMP0, TMP1, TMP2, lo
2252
+ | str TMP0, [BASE, RA, lsl #3]
2253
+ | ins_next
2254
+ break;
2255
+ case BC_UNM:
2256
+ | // RA = dst, RC = src
2257
+ | ldr TMP0, [BASE, RC, lsl #3]
2258
+ | asr ITYPE, TMP0, #47
2259
+ | cmn ITYPE, #-LJ_TISNUM
2260
+ | bhi ->vmeta_unm
2261
+ | eor TMP0, TMP0, #U64x(80000000,00000000)
2262
+ | bne >5
2263
+ | negs TMP0w, TMP0w
2264
+ | movz CARG3, #0x41e0, lsl #48 // 2^31.
2265
+ | add TMP0, TMP0, TISNUM
2266
+ | csel TMP0, TMP0, CARG3, vc
2267
+ |5:
2268
+ | str TMP0, [BASE, RA, lsl #3]
2269
+ | ins_next
2270
+ break;
2271
+ case BC_LEN:
2272
+ | // RA = dst, RC = src
2273
+ | ldr CARG1, [BASE, RC, lsl #3]
2274
+ | asr ITYPE, CARG1, #47
2275
+ | cmn ITYPE, #-LJ_TSTR
2276
+ | and CARG1, CARG1, #LJ_GCVMASK
2277
+ | bne >2
2278
+ | ldr CARG1w, STR:CARG1->len
2279
+ |1:
2280
+ | add CARG1, CARG1, TISNUM
2281
+ | str CARG1, [BASE, RA, lsl #3]
2282
+ | ins_next
2283
+ |
2284
+ |2:
2285
+ | cmn ITYPE, #-LJ_TTAB
2286
+ | bne ->vmeta_len
2287
+ #if LJ_52
2288
+ | ldr TAB:CARG2, TAB:CARG1->metatable
2289
+ | cbnz TAB:CARG2, >9
2290
+ |3:
2291
+ #endif
2292
+ |->BC_LEN_Z:
2293
+ | bl extern lj_tab_len // (GCtab *t)
2294
+ | // Returns uint32_t (but less than 2^31).
2295
+ | b <1
2296
+ |
2297
+ #if LJ_52
2298
+ |9:
2299
+ | ldrb TMP1w, TAB:CARG2->nomm
2300
+ | tbnz TMP1w, #MM_len, <3 // 'no __len' flag set: done.
2301
+ | b ->vmeta_len
2302
+ #endif
2303
+ break;
2304
+
2305
+ /* -- Binary ops -------------------------------------------------------- */
2306
+
2307
+ |.macro ins_arithcheck_int, target
2308
+ | checkint CARG1, target
2309
+ | checkint CARG2, target
2310
+ |.endmacro
2311
+ |
2312
+ |.macro ins_arithcheck_num, target
2313
+ | checknum CARG1, target
2314
+ | checknum CARG2, target
2315
+ |.endmacro
2316
+ |
2317
+ |.macro ins_arithcheck_nzdiv, target
2318
+ | cbz CARG2w, target
2319
+ |.endmacro
2320
+ |
2321
+ |.macro ins_arithhead
2322
+ ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
2323
+ ||if (vk == 1) {
2324
+ | and RC, RC, #255
2325
+ | decode_RB RB, INS
2326
+ ||} else {
2327
+ | decode_RB RB, INS
2328
+ | and RC, RC, #255
2329
+ ||}
2330
+ |.endmacro
2331
+ |
2332
+ |.macro ins_arithload, reg1, reg2
2333
+ | // RA = dst, RB = src1, RC = src2 | num_const
2334
+ ||switch (vk) {
2335
+ ||case 0:
2336
+ | ldr reg1, [BASE, RB, lsl #3]
2337
+ | ldr reg2, [KBASE, RC, lsl #3]
2338
+ || break;
2339
+ ||case 1:
2340
+ | ldr reg1, [KBASE, RC, lsl #3]
2341
+ | ldr reg2, [BASE, RB, lsl #3]
2342
+ || break;
2343
+ ||default:
2344
+ | ldr reg1, [BASE, RB, lsl #3]
2345
+ | ldr reg2, [BASE, RC, lsl #3]
2346
+ || break;
2347
+ ||}
2348
+ |.endmacro
2349
+ |
2350
+ |.macro ins_arithfallback, ins
2351
+ ||switch (vk) {
2352
+ ||case 0:
2353
+ | ins ->vmeta_arith_vn
2354
+ || break;
2355
+ ||case 1:
2356
+ | ins ->vmeta_arith_nv
2357
+ || break;
2358
+ ||default:
2359
+ | ins ->vmeta_arith_vv
2360
+ || break;
2361
+ ||}
2362
+ |.endmacro
2363
+ |
2364
+ |.macro ins_arithmod, res, reg1, reg2
2365
+ | fdiv d2, reg1, reg2
2366
+ | frintm d2, d2
2367
+ | fmsub res, d2, reg2, reg1
2368
+ |.endmacro
2369
+ |
2370
+ |.macro ins_arithdn, intins, fpins
2371
+ | ins_arithhead
2372
+ | ins_arithload CARG1, CARG2
2373
+ | ins_arithcheck_int >5
2374
+ |.if "intins" == "smull"
2375
+ | smull CARG1, CARG1w, CARG2w
2376
+ | cmp CARG1, CARG1, sxtw
2377
+ | mov CARG1w, CARG1w
2378
+ | ins_arithfallback bne
2379
+ |.elif "intins" == "ins_arithmodi"
2380
+ | ins_arithfallback ins_arithcheck_nzdiv
2381
+ | bl ->vm_modi
2382
+ |.else
2383
+ | intins CARG1w, CARG1w, CARG2w
2384
+ | ins_arithfallback bvs
2385
+ |.endif
2386
+ | add CARG1, CARG1, TISNUM
2387
+ | str CARG1, [BASE, RA, lsl #3]
2388
+ |4:
2389
+ | ins_next
2390
+ |
2391
+ |5: // FP variant.
2392
+ | ins_arithload FARG1, FARG2
2393
+ | ins_arithfallback ins_arithcheck_num
2394
+ | fpins FARG1, FARG1, FARG2
2395
+ | str FARG1, [BASE, RA, lsl #3]
2396
+ | b <4
2397
+ |.endmacro
2398
+ |
2399
+ |.macro ins_arithfp, fpins
2400
+ | ins_arithhead
2401
+ | ins_arithload CARG1, CARG2
2402
+ | ins_arithload FARG1, FARG2
2403
+ | ins_arithfallback ins_arithcheck_num
2404
+ |.if "fpins" == "fpow"
2405
+ | bl extern pow
2406
+ |.else
2407
+ | fpins FARG1, FARG1, FARG2
2408
+ |.endif
2409
+ | str FARG1, [BASE, RA, lsl #3]
2410
+ | ins_next
2411
+ |.endmacro
2412
+
2413
+ case BC_ADDVN: case BC_ADDNV: case BC_ADDVV:
2414
+ | ins_arithdn adds, fadd
2415
+ break;
2416
+ case BC_SUBVN: case BC_SUBNV: case BC_SUBVV:
2417
+ | ins_arithdn subs, fsub
2418
+ break;
2419
+ case BC_MULVN: case BC_MULNV: case BC_MULVV:
2420
+ | ins_arithdn smull, fmul
2421
+ break;
2422
+ case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
2423
+ | ins_arithfp fdiv
2424
+ break;
2425
+ case BC_MODVN: case BC_MODNV: case BC_MODVV:
2426
+ | ins_arithdn ins_arithmodi, ins_arithmod
2427
+ break;
2428
+ case BC_POW:
2429
+ | // NYI: (partial) integer arithmetic.
2430
+ | ins_arithfp fpow
2431
+ break;
2432
+
2433
+ case BC_CAT:
2434
+ | decode_RB RB, INS
2435
+ | and RC, RC, #255
2436
+ | // RA = dst, RB = src_start, RC = src_end
2437
+ | str BASE, L->base
2438
+ | sub CARG3, RC, RB
2439
+ | add CARG2, BASE, RC, lsl #3
2440
+ |->BC_CAT_Z:
2441
+ | // RA = dst, CARG2 = top-1, CARG3 = left
2442
+ | mov CARG1, L
2443
+ | str PC, SAVE_PC
2444
+ | bl extern lj_meta_cat // (lua_State *L, TValue *top, int left)
2445
+ | // Returns NULL (finished) or TValue * (metamethod).
2446
+ | ldrb RBw, [PC, #-1]
2447
+ | ldr BASE, L->base
2448
+ | cbnz CRET1, ->vmeta_binop
2449
+ | ldr TMP0, [BASE, RB, lsl #3]
2450
+ | str TMP0, [BASE, RA, lsl #3] // Copy result to RA.
2451
+ | ins_next
2452
+ break;
2453
+
2454
+ /* -- Constant ops ------------------------------------------------------ */
2455
+
2456
+ case BC_KSTR:
2457
+ | // RA = dst, RC = str_const (~)
2458
+ | mvn RC, RC
2459
+ | ldr TMP0, [KBASE, RC, lsl #3]
2460
+ | movn TMP1, #~LJ_TSTR
2461
+ | add TMP0, TMP0, TMP1, lsl #47
2462
+ | str TMP0, [BASE, RA, lsl #3]
2463
+ | ins_next
2464
+ break;
2465
+ case BC_KCDATA:
2466
+ |.if FFI
2467
+ | // RA = dst, RC = cdata_const (~)
2468
+ | mvn RC, RC
2469
+ | ldr TMP0, [KBASE, RC, lsl #3]
2470
+ | movn TMP1, #~LJ_TCDATA
2471
+ | add TMP0, TMP0, TMP1, lsl #47
2472
+ | str TMP0, [BASE, RA, lsl #3]
2473
+ | ins_next
2474
+ |.endif
2475
+ break;
2476
+ case BC_KSHORT:
2477
+ | // RA = dst, RC = int16_literal
2478
+ | sxth RCw, RCw
2479
+ | add TMP0, RC, TISNUM
2480
+ | str TMP0, [BASE, RA, lsl #3]
2481
+ | ins_next
2482
+ break;
2483
+ case BC_KNUM:
2484
+ | // RA = dst, RC = num_const
2485
+ | ldr TMP0, [KBASE, RC, lsl #3]
2486
+ | str TMP0, [BASE, RA, lsl #3]
2487
+ | ins_next
2488
+ break;
2489
+ case BC_KPRI:
2490
+ | // RA = dst, RC = primitive_type (~)
2491
+ | mvn TMP0, RC, lsl #47
2492
+ | str TMP0, [BASE, RA, lsl #3]
2493
+ | ins_next
2494
+ break;
2495
+ case BC_KNIL:
2496
+ | // RA = base, RC = end
2497
+ | add RA, BASE, RA, lsl #3
2498
+ | add RC, BASE, RC, lsl #3
2499
+ | str TISNIL, [RA], #8
2500
+ |1:
2501
+ | cmp RA, RC
2502
+ | str TISNIL, [RA], #8
2503
+ | blt <1
2504
+ | ins_next_
2505
+ break;
2506
+
2507
+ /* -- Upvalue and function ops ------------------------------------------ */
2508
+
2509
+ case BC_UGET:
2510
+ | // RA = dst, RC = uvnum
2511
+ | ldr LFUNC:CARG2, [BASE, FRAME_FUNC]
2512
+ | add RC, RC, #offsetof(GCfuncL, uvptr)/8
2513
+ | and LFUNC:CARG2, CARG2, #LJ_GCVMASK
2514
+ | ldr UPVAL:CARG2, [LFUNC:CARG2, RC, lsl #3]
2515
+ | ldr CARG2, UPVAL:CARG2->v
2516
+ | ldr TMP0, [CARG2]
2517
+ | str TMP0, [BASE, RA, lsl #3]
2518
+ | ins_next
2519
+ break;
2520
+ case BC_USETV:
2521
+ | // RA = uvnum, RC = src
2522
+ | ldr LFUNC:CARG2, [BASE, FRAME_FUNC]
2523
+ | add RA, RA, #offsetof(GCfuncL, uvptr)/8
2524
+ | and LFUNC:CARG2, CARG2, #LJ_GCVMASK
2525
+ | ldr UPVAL:CARG1, [LFUNC:CARG2, RA, lsl #3]
2526
+ | ldr CARG3, [BASE, RC, lsl #3]
2527
+ | ldr CARG2, UPVAL:CARG1->v
2528
+ | ldrb TMP2w, UPVAL:CARG1->marked
2529
+ | ldrb TMP0w, UPVAL:CARG1->closed
2530
+ | asr ITYPE, CARG3, #47
2531
+ | str CARG3, [CARG2]
2532
+ | add ITYPE, ITYPE, #-LJ_TISGCV
2533
+ | tst TMP2w, #LJ_GC_BLACK // isblack(uv)
2534
+ | ccmp TMP0w, #0, #4, ne // && uv->closed
2535
+ | ccmn ITYPE, #-(LJ_TNUMX - LJ_TISGCV), #0, ne // && tvisgcv(v)
2536
+ | bhi >2
2537
+ |1:
2538
+ | ins_next
2539
+ |
2540
+ |2: // Check if new value is white.
2541
+ | and GCOBJ:CARG3, CARG3, #LJ_GCVMASK
2542
+ | ldrb TMP1w, GCOBJ:CARG3->gch.marked
2543
+ | tst TMP1w, #LJ_GC_WHITES // iswhite(str)
2544
+ | beq <1
2545
+ | // Crossed a write barrier. Move the barrier forward.
2546
+ | mov CARG1, GL
2547
+ | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv)
2548
+ | b <1
2549
+ break;
2550
+ case BC_USETS:
2551
+ | // RA = uvnum, RC = str_const (~)
2552
+ | ldr LFUNC:CARG2, [BASE, FRAME_FUNC]
2553
+ | add RA, RA, #offsetof(GCfuncL, uvptr)/8
2554
+ | mvn RC, RC
2555
+ | and LFUNC:CARG2, CARG2, #LJ_GCVMASK
2556
+ | ldr UPVAL:CARG1, [LFUNC:CARG2, RA, lsl #3]
2557
+ | ldr STR:CARG3, [KBASE, RC, lsl #3]
2558
+ | movn TMP0, #~LJ_TSTR
2559
+ | ldr CARG2, UPVAL:CARG1->v
2560
+ | ldrb TMP2w, UPVAL:CARG1->marked
2561
+ | add TMP0, STR:CARG3, TMP0, lsl #47
2562
+ | ldrb TMP1w, STR:CARG3->marked
2563
+ | str TMP0, [CARG2]
2564
+ | tbnz TMP2w, #2, >2 // isblack(uv)
2565
+ |1:
2566
+ | ins_next
2567
+ |
2568
+ |2: // Check if string is white and ensure upvalue is closed.
2569
+ | ldrb TMP0w, UPVAL:CARG1->closed
2570
+ | tst TMP1w, #LJ_GC_WHITES // iswhite(str)
2571
+ | ccmp TMP0w, #0, #0, ne
2572
+ | beq <1
2573
+ | // Crossed a write barrier. Move the barrier forward.
2574
+ | mov CARG1, GL
2575
+ | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv)
2576
+ | b <1
2577
+ break;
2578
+ case BC_USETN:
2579
+ | // RA = uvnum, RC = num_const
2580
+ | ldr LFUNC:CARG2, [BASE, FRAME_FUNC]
2581
+ | add RA, RA, #offsetof(GCfuncL, uvptr)/8
2582
+ | and LFUNC:CARG2, CARG2, #LJ_GCVMASK
2583
+ | ldr UPVAL:CARG2, [LFUNC:CARG2, RA, lsl #3]
2584
+ | ldr TMP0, [KBASE, RC, lsl #3]
2585
+ | ldr CARG2, UPVAL:CARG2->v
2586
+ | str TMP0, [CARG2]
2587
+ | ins_next
2588
+ break;
2589
+ case BC_USETP:
2590
+ | // RA = uvnum, RC = primitive_type (~)
2591
+ | ldr LFUNC:CARG2, [BASE, FRAME_FUNC]
2592
+ | add RA, RA, #offsetof(GCfuncL, uvptr)/8
2593
+ | and LFUNC:CARG2, CARG2, #LJ_GCVMASK
2594
+ | ldr UPVAL:CARG2, [LFUNC:CARG2, RA, lsl #3]
2595
+ | mvn TMP0, RC, lsl #47
2596
+ | ldr CARG2, UPVAL:CARG2->v
2597
+ | str TMP0, [CARG2]
2598
+ | ins_next
2599
+ break;
2600
+
2601
+ case BC_UCLO:
2602
+ | // RA = level, RC = target
2603
+ | ldr CARG3, L->openupval
2604
+ | add RC, PC, RC, lsl #2
2605
+ | str BASE, L->base
2606
+ | sub PC, RC, #0x20000
2607
+ | cbz CARG3, >1
2608
+ | mov CARG1, L
2609
+ | add CARG2, BASE, RA, lsl #3
2610
+ | bl extern lj_func_closeuv // (lua_State *L, TValue *level)
2611
+ | ldr BASE, L->base
2612
+ |1:
2613
+ | ins_next
2614
+ break;
2615
+
2616
+ case BC_FNEW:
2617
+ | // RA = dst, RC = proto_const (~) (holding function prototype)
2618
+ | mvn RC, RC
2619
+ | str BASE, L->base
2620
+ | ldr LFUNC:CARG3, [BASE, FRAME_FUNC]
2621
+ | str PC, SAVE_PC
2622
+ | ldr CARG2, [KBASE, RC, lsl #3]
2623
+ | mov CARG1, L
2624
+ | and LFUNC:CARG3, CARG3, #LJ_GCVMASK
2625
+ | // (lua_State *L, GCproto *pt, GCfuncL *parent)
2626
+ | bl extern lj_func_newL_gc
2627
+ | // Returns GCfuncL *.
2628
+ | ldr BASE, L->base
2629
+ | movn TMP0, #~LJ_TFUNC
2630
+ | add CRET1, CRET1, TMP0, lsl #47
2631
+ | str CRET1, [BASE, RA, lsl #3]
2632
+ | ins_next
2633
+ break;
2634
+
2635
+ /* -- Table ops --------------------------------------------------------- */
2636
+
2637
+ case BC_TNEW:
2638
+ case BC_TDUP:
2639
+ | // RA = dst, RC = (hbits|asize) | tab_const (~)
2640
+ | ldp CARG3, CARG4, GL->gc.total // Assumes threshold follows total.
2641
+ | str BASE, L->base
2642
+ | str PC, SAVE_PC
2643
+ | mov CARG1, L
2644
+ | cmp CARG3, CARG4
2645
+ | bhs >5
2646
+ |1:
2647
+ if (op == BC_TNEW) {
2648
+ | and CARG2, RC, #0x7ff
2649
+ | lsr CARG3, RC, #11
2650
+ | cmp CARG2, #0x7ff
2651
+ | mov TMP0, #0x801
2652
+ | csel CARG2, CARG2, TMP0, ne
2653
+ | bl extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits)
2654
+ | // Returns GCtab *.
2655
+ } else {
2656
+ | mvn RC, RC
2657
+ | ldr CARG2, [KBASE, RC, lsl #3]
2658
+ | bl extern lj_tab_dup // (lua_State *L, Table *kt)
2659
+ | // Returns GCtab *.
2660
+ }
2661
+ | ldr BASE, L->base
2662
+ | movk CRET1, #(LJ_TTAB>>1)&0xffff, lsl #48
2663
+ | str CRET1, [BASE, RA, lsl #3]
2664
+ | ins_next
2665
+ |
2666
+ |5:
2667
+ | bl extern lj_gc_step_fixtop // (lua_State *L)
2668
+ | mov CARG1, L
2669
+ | b <1
2670
+ break;
2671
+
2672
+ case BC_GGET:
2673
+ | // RA = dst, RC = str_const (~)
2674
+ case BC_GSET:
2675
+ | // RA = dst, RC = str_const (~)
2676
+ | ldr LFUNC:CARG1, [BASE, FRAME_FUNC]
2677
+ | mvn RC, RC
2678
+ | and LFUNC:CARG1, CARG1, #LJ_GCVMASK
2679
+ | ldr TAB:CARG2, LFUNC:CARG1->env
2680
+ | ldr STR:RC, [KBASE, RC, lsl #3]
2681
+ if (op == BC_GGET) {
2682
+ | b ->BC_TGETS_Z
2683
+ } else {
2684
+ | b ->BC_TSETS_Z
2685
+ }
2686
+ break;
2687
+
2688
+ case BC_TGETV:
2689
+ | decode_RB RB, INS
2690
+ | and RC, RC, #255
2691
+ | // RA = dst, RB = table, RC = key
2692
+ | ldr CARG2, [BASE, RB, lsl #3]
2693
+ | ldr TMP1, [BASE, RC, lsl #3]
2694
+ | checktab CARG2, ->vmeta_tgetv
2695
+ | checkint TMP1, >9 // Integer key?
2696
+ | ldr CARG3, TAB:CARG2->array
2697
+ | ldr CARG1w, TAB:CARG2->asize
2698
+ | add CARG3, CARG3, TMP1, uxtw #3
2699
+ | cmp TMP1w, CARG1w // In array part?
2700
+ | bhs ->vmeta_tgetv
2701
+ | ldr TMP0, [CARG3]
2702
+ | cmp TMP0, TISNIL
2703
+ | beq >5
2704
+ |1:
2705
+ | str TMP0, [BASE, RA, lsl #3]
2706
+ | ins_next
2707
+ |
2708
+ |5: // Check for __index if table value is nil.
2709
+ | ldr TAB:CARG1, TAB:CARG2->metatable
2710
+ | cbz TAB:CARG1, <1 // No metatable: done.
2711
+ | ldrb TMP1w, TAB:CARG1->nomm
2712
+ | tbnz TMP1w, #MM_index, <1 // 'no __index' flag set: done.
2713
+ | b ->vmeta_tgetv
2714
+ |
2715
+ |9:
2716
+ | asr ITYPE, TMP1, #47
2717
+ | cmn ITYPE, #-LJ_TSTR // String key?
2718
+ | bne ->vmeta_tgetv
2719
+ | and STR:RC, TMP1, #LJ_GCVMASK
2720
+ | b ->BC_TGETS_Z
2721
+ break;
2722
+ case BC_TGETS:
2723
+ | decode_RB RB, INS
2724
+ | and RC, RC, #255
2725
+ | // RA = dst, RB = table, RC = str_const (~)
2726
+ | ldr CARG2, [BASE, RB, lsl #3]
2727
+ | mvn RC, RC
2728
+ | ldr STR:RC, [KBASE, RC, lsl #3]
2729
+ | checktab CARG2, ->vmeta_tgets1
2730
+ |->BC_TGETS_Z:
2731
+ | // TAB:CARG2 = GCtab *, STR:RC = GCstr *, RA = dst
2732
+ | ldr TMP1w, TAB:CARG2->hmask
2733
+ | ldr TMP2w, STR:RC->hash
2734
+ | ldr NODE:CARG3, TAB:CARG2->node
2735
+ | and TMP1w, TMP1w, TMP2w // idx = str->hash & tab->hmask
2736
+ | add TMP1, TMP1, TMP1, lsl #1
2737
+ | movn CARG4, #~LJ_TSTR
2738
+ | add NODE:CARG3, NODE:CARG3, TMP1, lsl #3 // node = tab->node + idx*3*8
2739
+ | add CARG4, STR:RC, CARG4, lsl #47 // Tagged key to look for.
2740
+ |1:
2741
+ | ldp TMP0, CARG1, NODE:CARG3->val
2742
+ | ldr NODE:CARG3, NODE:CARG3->next
2743
+ | cmp CARG1, CARG4
2744
+ | bne >4
2745
+ | cmp TMP0, TISNIL
2746
+ | beq >5
2747
+ |3:
2748
+ | str TMP0, [BASE, RA, lsl #3]
2749
+ | ins_next
2750
+ |
2751
+ |4: // Follow hash chain.
2752
+ | cbnz NODE:CARG3, <1
2753
+ | // End of hash chain: key not found, nil result.
2754
+ | mov TMP0, TISNIL
2755
+ |
2756
+ |5: // Check for __index if table value is nil.
2757
+ | ldr TAB:CARG1, TAB:CARG2->metatable
2758
+ | cbz TAB:CARG1, <3 // No metatable: done.
2759
+ | ldrb TMP1w, TAB:CARG1->nomm
2760
+ | tbnz TMP1w, #MM_index, <3 // 'no __index' flag set: done.
2761
+ | b ->vmeta_tgets
2762
+ break;
2763
+ case BC_TGETB:
2764
+ | decode_RB RB, INS
2765
+ | and RC, RC, #255
2766
+ | // RA = dst, RB = table, RC = index
2767
+ | ldr CARG2, [BASE, RB, lsl #3]
2768
+ | checktab CARG2, ->vmeta_tgetb
2769
+ | ldr CARG3, TAB:CARG2->array
2770
+ | ldr CARG1w, TAB:CARG2->asize
2771
+ | add CARG3, CARG3, RC, lsl #3
2772
+ | cmp RCw, CARG1w // In array part?
2773
+ | bhs ->vmeta_tgetb
2774
+ | ldr TMP0, [CARG3]
2775
+ | cmp TMP0, TISNIL
2776
+ | beq >5
2777
+ |1:
2778
+ | str TMP0, [BASE, RA, lsl #3]
2779
+ | ins_next
2780
+ |
2781
+ |5: // Check for __index if table value is nil.
2782
+ | ldr TAB:CARG1, TAB:CARG2->metatable
2783
+ | cbz TAB:CARG1, <1 // No metatable: done.
2784
+ | ldrb TMP1w, TAB:CARG1->nomm
2785
+ | tbnz TMP1w, #MM_index, <1 // 'no __index' flag set: done.
2786
+ | b ->vmeta_tgetb
2787
+ break;
2788
+ case BC_TGETR:
2789
+ | decode_RB RB, INS
2790
+ | and RC, RC, #255
2791
+ | // RA = dst, RB = table, RC = key
2792
+ | ldr CARG1, [BASE, RB, lsl #3]
2793
+ | ldr TMP1, [BASE, RC, lsl #3]
2794
+ | and TAB:CARG1, CARG1, #LJ_GCVMASK
2795
+ | ldr CARG3, TAB:CARG1->array
2796
+ | ldr TMP2w, TAB:CARG1->asize
2797
+ | add CARG3, CARG3, TMP1w, uxtw #3
2798
+ | cmp TMP1w, TMP2w // In array part?
2799
+ | bhs ->vmeta_tgetr
2800
+ | ldr TMP0, [CARG3]
2801
+ |->BC_TGETR_Z:
2802
+ | str TMP0, [BASE, RA, lsl #3]
2803
+ | ins_next
2804
+ break;
2805
+
2806
+ case BC_TSETV:
2807
+ | decode_RB RB, INS
2808
+ | and RC, RC, #255
2809
+ | // RA = src, RB = table, RC = key
2810
+ | ldr CARG2, [BASE, RB, lsl #3]
2811
+ | ldr TMP1, [BASE, RC, lsl #3]
2812
+ | checktab CARG2, ->vmeta_tsetv
2813
+ | checkint TMP1, >9 // Integer key?
2814
+ | ldr CARG3, TAB:CARG2->array
2815
+ | ldr CARG1w, TAB:CARG2->asize
2816
+ | add CARG3, CARG3, TMP1, uxtw #3
2817
+ | cmp TMP1w, CARG1w // In array part?
2818
+ | bhs ->vmeta_tsetv
2819
+ | ldr TMP1, [CARG3]
2820
+ | ldr TMP0, [BASE, RA, lsl #3]
2821
+ | ldrb TMP2w, TAB:CARG2->marked
2822
+ | cmp TMP1, TISNIL // Previous value is nil?
2823
+ | beq >5
2824
+ |1:
2825
+ | str TMP0, [CARG3]
2826
+ | tbnz TMP2w, #2, >7 // isblack(table)
2827
+ |2:
2828
+ | ins_next
2829
+ |
2830
+ |5: // Check for __newindex if previous value is nil.
2831
+ | ldr TAB:CARG1, TAB:CARG2->metatable
2832
+ | cbz TAB:CARG1, <1 // No metatable: done.
2833
+ | ldrb TMP1w, TAB:CARG1->nomm
2834
+ | tbnz TMP1w, #MM_newindex, <1 // 'no __newindex' flag set: done.
2835
+ | b ->vmeta_tsetv
2836
+ |
2837
+ |7: // Possible table write barrier for the value. Skip valiswhite check.
2838
+ | barrierback TAB:CARG2, TMP2w, TMP1
2839
+ | b <2
2840
+ |
2841
+ |9:
2842
+ | asr ITYPE, TMP1, #47
2843
+ | cmn ITYPE, #-LJ_TSTR // String key?
2844
+ | bne ->vmeta_tsetv
2845
+ | and STR:RC, TMP1, #LJ_GCVMASK
2846
+ | b ->BC_TSETS_Z
2847
+ break;
2848
+ case BC_TSETS:
2849
+ | decode_RB RB, INS
2850
+ | and RC, RC, #255
2851
+ | // RA = dst, RB = table, RC = str_const (~)
2852
+ | ldr CARG2, [BASE, RB, lsl #3]
2853
+ | mvn RC, RC
2854
+ | ldr STR:RC, [KBASE, RC, lsl #3]
2855
+ | checktab CARG2, ->vmeta_tsets1
2856
+ |->BC_TSETS_Z:
2857
+ | // TAB:CARG2 = GCtab *, STR:RC = GCstr *, RA = src
2858
+ | ldr TMP1w, TAB:CARG2->hmask
2859
+ | ldr TMP2w, STR:RC->hash
2860
+ | ldr NODE:CARG3, TAB:CARG2->node
2861
+ | and TMP1w, TMP1w, TMP2w // idx = str->hash & tab->hmask
2862
+ | add TMP1, TMP1, TMP1, lsl #1
2863
+ | movn CARG4, #~LJ_TSTR
2864
+ | add NODE:CARG3, NODE:CARG3, TMP1, lsl #3 // node = tab->node + idx*3*8
2865
+ | add CARG4, STR:RC, CARG4, lsl #47 // Tagged key to look for.
2866
+ | strb wzr, TAB:CARG2->nomm // Clear metamethod cache.
2867
+ |1:
2868
+ | ldp TMP1, CARG1, NODE:CARG3->val
2869
+ | ldr NODE:TMP3, NODE:CARG3->next
2870
+ | ldrb TMP2w, TAB:CARG2->marked
2871
+ | cmp CARG1, CARG4
2872
+ | bne >5
2873
+ | ldr TMP0, [BASE, RA, lsl #3]
2874
+ | cmp TMP1, TISNIL // Previous value is nil?
2875
+ | beq >4
2876
+ |2:
2877
+ | str TMP0, NODE:CARG3->val
2878
+ | tbnz TMP2w, #2, >7 // isblack(table)
2879
+ |3:
2880
+ | ins_next
2881
+ |
2882
+ |4: // Check for __newindex if previous value is nil.
2883
+ | ldr TAB:CARG1, TAB:CARG2->metatable
2884
+ | cbz TAB:CARG1, <2 // No metatable: done.
2885
+ | ldrb TMP1w, TAB:CARG1->nomm
2886
+ | tbnz TMP1w, #MM_newindex, <2 // 'no __newindex' flag set: done.
2887
+ | b ->vmeta_tsets
2888
+ |
2889
+ |5: // Follow hash chain.
2890
+ | mov NODE:CARG3, NODE:TMP3
2891
+ | cbnz NODE:TMP3, <1
2892
+ | // End of hash chain: key not found, add a new one.
2893
+ |
2894
+ | // But check for __newindex first.
2895
+ | ldr TAB:CARG1, TAB:CARG2->metatable
2896
+ | cbz TAB:CARG1, >6 // No metatable: continue.
2897
+ | ldrb TMP1w, TAB:CARG1->nomm
2898
+ | // 'no __newindex' flag NOT set: check.
2899
+ | tbz TMP1w, #MM_newindex, ->vmeta_tsets
2900
+ |6:
2901
+ | movn TMP1, #~LJ_TSTR
2902
+ | str PC, SAVE_PC
2903
+ | add TMP0, STR:RC, TMP1, lsl #47
2904
+ | str BASE, L->base
2905
+ | mov CARG1, L
2906
+ | str TMP0, TMPD
2907
+ | add CARG3, sp, TMPDofs
2908
+ | bl extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k)
2909
+ | // Returns TValue *.
2910
+ | ldr BASE, L->base
2911
+ | ldr TMP0, [BASE, RA, lsl #3]
2912
+ | str TMP0, [CRET1]
2913
+ | b <3 // No 2nd write barrier needed.
2914
+ |
2915
+ |7: // Possible table write barrier for the value. Skip valiswhite check.
2916
+ | barrierback TAB:CARG2, TMP2w, TMP1
2917
+ | b <3
2918
+ break;
2919
+ case BC_TSETB:
2920
+ | decode_RB RB, INS
2921
+ | and RC, RC, #255
2922
+ | // RA = src, RB = table, RC = index
2923
+ | ldr CARG2, [BASE, RB, lsl #3]
2924
+ | checktab CARG2, ->vmeta_tsetb
2925
+ | ldr CARG3, TAB:CARG2->array
2926
+ | ldr CARG1w, TAB:CARG2->asize
2927
+ | add CARG3, CARG3, RC, lsl #3
2928
+ | cmp RCw, CARG1w // In array part?
2929
+ | bhs ->vmeta_tsetb
2930
+ | ldr TMP1, [CARG3]
2931
+ | ldr TMP0, [BASE, RA, lsl #3]
2932
+ | ldrb TMP2w, TAB:CARG2->marked
2933
+ | cmp TMP1, TISNIL // Previous value is nil?
2934
+ | beq >5
2935
+ |1:
2936
+ | str TMP0, [CARG3]
2937
+ | tbnz TMP2w, #2, >7 // isblack(table)
2938
+ |2:
2939
+ | ins_next
2940
+ |
2941
+ |5: // Check for __newindex if previous value is nil.
2942
+ | ldr TAB:CARG1, TAB:CARG2->metatable
2943
+ | cbz TAB:CARG1, <1 // No metatable: done.
2944
+ | ldrb TMP1w, TAB:CARG1->nomm
2945
+ | tbnz TMP1w, #MM_newindex, <1 // 'no __newindex' flag set: done.
2946
+ | b ->vmeta_tsetb
2947
+ |
2948
+ |7: // Possible table write barrier for the value. Skip valiswhite check.
2949
+ | barrierback TAB:CARG2, TMP2w, TMP1
2950
+ | b <2
2951
+ break;
2952
+ case BC_TSETR:
2953
+ | decode_RB RB, INS
2954
+ | and RC, RC, #255
2955
+ | // RA = src, RB = table, RC = key
2956
+ | ldr CARG2, [BASE, RB, lsl #3]
2957
+ | ldr TMP1, [BASE, RC, lsl #3]
2958
+ | and TAB:CARG2, CARG2, #LJ_GCVMASK
2959
+ | ldr CARG1, TAB:CARG2->array
2960
+ | ldrb TMP2w, TAB:CARG2->marked
2961
+ | ldr CARG4w, TAB:CARG2->asize
2962
+ | add CARG1, CARG1, TMP1, uxtw #3
2963
+ | tbnz TMP2w, #2, >7 // isblack(table)
2964
+ |2:
2965
+ | cmp TMP1w, CARG4w // In array part?
2966
+ | bhs ->vmeta_tsetr
2967
+ |->BC_TSETR_Z:
2968
+ | ldr TMP0, [BASE, RA, lsl #3]
2969
+ | str TMP0, [CARG1]
2970
+ | ins_next
2971
+ |
2972
+ |7: // Possible table write barrier for the value. Skip valiswhite check.
2973
+ | barrierback TAB:CARG2, TMP2w, TMP0
2974
+ | b <2
2975
+ break;
2976
+
2977
+ case BC_TSETM:
2978
+ | // RA = base (table at base-1), RC = num_const (start index)
2979
+ | add RA, BASE, RA, lsl #3
2980
+ |1:
2981
+ | ldr RBw, SAVE_MULTRES
2982
+ | ldr TAB:CARG2, [RA, #-8] // Guaranteed to be a table.
2983
+ | ldr TMP1, [KBASE, RC, lsl #3] // Integer constant is in lo-word.
2984
+ | sub RB, RB, #8
2985
+ | cbz RB, >4 // Nothing to copy?
2986
+ | and TAB:CARG2, CARG2, #LJ_GCVMASK
2987
+ | ldr CARG1w, TAB:CARG2->asize
2988
+ | add CARG3w, TMP1w, RBw, lsr #3
2989
+ | ldr CARG4, TAB:CARG2->array
2990
+ | cmp CARG3, CARG1
2991
+ | add RB, RA, RB
2992
+ | bhi >5
2993
+ | add TMP1, CARG4, TMP1w, uxtw #3
2994
+ | ldrb TMP2w, TAB:CARG2->marked
2995
+ |3: // Copy result slots to table.
2996
+ | ldr TMP0, [RA], #8
2997
+ | str TMP0, [TMP1], #8
2998
+ | cmp RA, RB
2999
+ | blo <3
3000
+ | tbnz TMP2w, #2, >7 // isblack(table)
3001
+ |4:
3002
+ | ins_next
3003
+ |
3004
+ |5: // Need to resize array part.
3005
+ | str BASE, L->base
3006
+ | mov CARG1, L
3007
+ | str PC, SAVE_PC
3008
+ | bl extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize)
3009
+ | // Must not reallocate the stack.
3010
+ | b <1
3011
+ |
3012
+ |7: // Possible table write barrier for any value. Skip valiswhite check.
3013
+ | barrierback TAB:CARG2, TMP2w, TMP1
3014
+ | b <4
3015
+ break;
3016
+
3017
+ /* -- Calls and vararg handling ----------------------------------------- */
3018
+
3019
+ case BC_CALLM:
3020
+ | // RA = base, (RB = nresults+1,) RC = extra_nargs
3021
+ | ldr TMP0w, SAVE_MULTRES
3022
+ | decode_RC8RD NARGS8:RC, RC
3023
+ | add NARGS8:RC, NARGS8:RC, TMP0
3024
+ | b ->BC_CALL_Z
3025
+ break;
3026
+ case BC_CALL:
3027
+ | decode_RC8RD NARGS8:RC, RC
3028
+ | // RA = base, (RB = nresults+1,) RC = (nargs+1)*8
3029
+ |->BC_CALL_Z:
3030
+ | mov RB, BASE // Save old BASE for vmeta_call.
3031
+ | add BASE, BASE, RA, lsl #3
3032
+ | ldr CARG3, [BASE]
3033
+ | sub NARGS8:RC, NARGS8:RC, #8
3034
+ | add BASE, BASE, #16
3035
+ | checkfunc CARG3, ->vmeta_call
3036
+ | ins_call
3037
+ break;
3038
+
3039
+ case BC_CALLMT:
3040
+ | // RA = base, (RB = 0,) RC = extra_nargs
3041
+ | ldr TMP0w, SAVE_MULTRES
3042
+ | add NARGS8:RC, TMP0, RC, lsl #3
3043
+ | b ->BC_CALLT1_Z
3044
+ break;
3045
+ case BC_CALLT:
3046
+ | lsl NARGS8:RC, RC, #3
3047
+ | // RA = base, (RB = 0,) RC = (nargs+1)*8
3048
+ |->BC_CALLT1_Z:
3049
+ | add RA, BASE, RA, lsl #3
3050
+ | ldr TMP1, [RA]
3051
+ | sub NARGS8:RC, NARGS8:RC, #8
3052
+ | add RA, RA, #16
3053
+ | checktp CARG3, TMP1, LJ_TFUNC, ->vmeta_callt
3054
+ | ldr PC, [BASE, FRAME_PC]
3055
+ |->BC_CALLT2_Z:
3056
+ | mov RB, #0
3057
+ | ldrb TMP2w, LFUNC:CARG3->ffid
3058
+ | tst PC, #FRAME_TYPE
3059
+ | bne >7
3060
+ |1:
3061
+ | str TMP1, [BASE, FRAME_FUNC] // Copy function down, but keep PC.
3062
+ | cbz NARGS8:RC, >3
3063
+ |2:
3064
+ | ldr TMP0, [RA, RB]
3065
+ | add TMP1, RB, #8
3066
+ | cmp TMP1, NARGS8:RC
3067
+ | str TMP0, [BASE, RB]
3068
+ | mov RB, TMP1
3069
+ | bne <2
3070
+ |3:
3071
+ | cmp TMP2, #1 // (> FF_C) Calling a fast function?
3072
+ | bhi >5
3073
+ |4:
3074
+ | ins_callt
3075
+ |
3076
+ |5: // Tailcall to a fast function with a Lua frame below.
3077
+ | ldrb RAw, [PC, #-3]
3078
+ | sub CARG1, BASE, RA, lsl #3
3079
+ | ldr LFUNC:CARG1, [CARG1, #-32]
3080
+ | and LFUNC:CARG1, CARG1, #LJ_GCVMASK
3081
+ | ldr CARG1, LFUNC:CARG1->pc
3082
+ | ldr KBASE, [CARG1, #PC2PROTO(k)]
3083
+ | b <4
3084
+ |
3085
+ |7: // Tailcall from a vararg function.
3086
+ | eor PC, PC, #FRAME_VARG
3087
+ | tst PC, #FRAME_TYPEP // Vararg frame below?
3088
+ | csel TMP2, RB, TMP2, ne // Clear ffid if no Lua function below.
3089
+ | bne <1
3090
+ | sub BASE, BASE, PC
3091
+ | ldr PC, [BASE, FRAME_PC]
3092
+ | tst PC, #FRAME_TYPE
3093
+ | csel TMP2, RB, TMP2, ne // Clear ffid if no Lua function below.
3094
+ | b <1
3095
+ break;
3096
+
3097
+ case BC_ITERC:
3098
+ | // RA = base, (RB = nresults+1, RC = nargs+1 (2+1))
3099
+ | add RA, BASE, RA, lsl #3
3100
+ | ldr CARG3, [RA, #-24]
3101
+ | mov RB, BASE // Save old BASE for vmeta_call.
3102
+ | ldp CARG1, CARG2, [RA, #-16]
3103
+ | add BASE, RA, #16
3104
+ | mov NARGS8:RC, #16 // Iterators get 2 arguments.
3105
+ | str CARG3, [RA] // Copy callable.
3106
+ | stp CARG1, CARG2, [RA, #16] // Copy state and control var.
3107
+ | checkfunc CARG3, ->vmeta_call
3108
+ | ins_call
3109
+ break;
3110
+
3111
+ case BC_ITERN:
3112
+ | // RA = base, (RB = nresults+1, RC = nargs+1 (2+1))
3113
+ |.if JIT
3114
+ | // NYI: add hotloop, record BC_ITERN.
3115
+ |.endif
3116
+ | add RA, BASE, RA, lsl #3
3117
+ | ldr TAB:RB, [RA, #-16]
3118
+ | ldrh TMP3w, [PC, #2]
3119
+ | ldr CARG1w, [RA, #-8] // Get index from control var.
3120
+ | add PC, PC, #4
3121
+ | add TMP3, PC, TMP3, lsl #2
3122
+ | and TAB:RB, RB, #LJ_GCVMASK
3123
+ | sub TMP3, TMP3, #0x20000
3124
+ | ldr TMP1w, TAB:RB->asize
3125
+ | ldr CARG2, TAB:RB->array
3126
+ |1: // Traverse array part.
3127
+ | subs RC, CARG1, TMP1
3128
+ | add CARG3, CARG2, CARG1, lsl #3
3129
+ | bhs >5 // Index points after array part?
3130
+ | ldr TMP0, [CARG3]
3131
+ | cmp TMP0, TISNIL
3132
+ | cinc CARG1, CARG1, eq // Skip holes in array part.
3133
+ | beq <1
3134
+ | add CARG1, CARG1, TISNUM
3135
+ | stp CARG1, TMP0, [RA]
3136
+ | add CARG1, CARG1, #1
3137
+ |3:
3138
+ | str CARG1w, [RA, #-8] // Update control var.
3139
+ | mov PC, TMP3
3140
+ |4:
3141
+ | ins_next
3142
+ |
3143
+ |5: // Traverse hash part.
3144
+ | ldr TMP2w, TAB:RB->hmask
3145
+ | ldr NODE:RB, TAB:RB->node
3146
+ |6:
3147
+ | add CARG1, RC, RC, lsl #1
3148
+ | cmp RC, TMP2 // End of iteration? Branch to ITERN+1.
3149
+ | add NODE:CARG3, NODE:RB, CARG1, lsl #3 // node = tab->node + idx*3*8
3150
+ | bhi <4
3151
+ | ldp TMP0, CARG1, NODE:CARG3->val
3152
+ | cmp TMP0, TISNIL
3153
+ | add RC, RC, #1
3154
+ | beq <6 // Skip holes in hash part.
3155
+ | stp CARG1, TMP0, [RA]
3156
+ | add CARG1, RC, TMP1
3157
+ | b <3
3158
+ break;
3159
+
3160
+ case BC_ISNEXT:
3161
+ | // RA = base, RC = target (points to ITERN)
3162
+ | add RA, BASE, RA, lsl #3
3163
+ | ldr CFUNC:CARG1, [RA, #-24]
3164
+ | add RC, PC, RC, lsl #2
3165
+ | ldp TAB:CARG3, CARG4, [RA, #-16]
3166
+ | sub RC, RC, #0x20000
3167
+ | checkfunc CFUNC:CARG1, >5
3168
+ | asr TMP0, TAB:CARG3, #47
3169
+ | ldrb TMP1w, CFUNC:CARG1->ffid
3170
+ | cmn TMP0, #-LJ_TTAB
3171
+ | ccmp CARG4, TISNIL, #0, eq
3172
+ | ccmp TMP1w, #FF_next_N, #0, eq
3173
+ | bne >5
3174
+ | mov TMP0w, #0xfffe7fff
3175
+ | lsl TMP0, TMP0, #32
3176
+ | str TMP0, [RA, #-8] // Initialize control var.
3177
+ |1:
3178
+ | mov PC, RC
3179
+ | ins_next
3180
+ |
3181
+ |5: // Despecialize bytecode if any of the checks fail.
3182
+ | mov TMP0, #BC_JMP
3183
+ | mov TMP1, #BC_ITERC
3184
+ | strb TMP0w, [PC, #-4]
3185
+ | strb TMP1w, [RC]
3186
+ | b <1
3187
+ break;
3188
+
3189
+ case BC_VARG:
3190
+ | decode_RB RB, INS
3191
+ | and RC, RC, #255
3192
+ | // RA = base, RB = (nresults+1), RC = numparams
3193
+ | ldr TMP1, [BASE, FRAME_PC]
3194
+ | add RC, BASE, RC, lsl #3
3195
+ | add RA, BASE, RA, lsl #3
3196
+ | add RC, RC, #FRAME_VARG
3197
+ | add TMP2, RA, RB, lsl #3
3198
+ | sub RC, RC, TMP1 // RC = vbase
3199
+ | // Note: RC may now be even _above_ BASE if nargs was < numparams.
3200
+ | sub TMP3, BASE, #16 // TMP3 = vtop
3201
+ | cbz RB, >5
3202
+ | sub TMP2, TMP2, #16
3203
+ |1: // Copy vararg slots to destination slots.
3204
+ | cmp RC, TMP3
3205
+ | ldr TMP0, [RC], #8
3206
+ | csel TMP0, TMP0, TISNIL, lo
3207
+ | cmp RA, TMP2
3208
+ | str TMP0, [RA], #8
3209
+ | blo <1
3210
+ |2:
3211
+ | ins_next
3212
+ |
3213
+ |5: // Copy all varargs.
3214
+ | ldr TMP0, L->maxstack
3215
+ | subs TMP2, TMP3, RC
3216
+ | csel RB, xzr, TMP2, le // MULTRES = (max(vtop-vbase,0)+1)*8
3217
+ | add RB, RB, #8
3218
+ | add TMP1, RA, TMP2
3219
+ | str RBw, SAVE_MULTRES
3220
+ | ble <2 // Nothing to copy.
3221
+ | cmp TMP1, TMP0
3222
+ | bhi >7
3223
+ |6:
3224
+ | ldr TMP0, [RC], #8
3225
+ | str TMP0, [RA], #8
3226
+ | cmp RC, TMP3
3227
+ | blo <6
3228
+ | b <2
3229
+ |
3230
+ |7: // Grow stack for varargs.
3231
+ | lsr CARG2, TMP2, #3
3232
+ | stp BASE, RA, L->base
3233
+ | mov CARG1, L
3234
+ | sub RC, RC, BASE // Need delta, because BASE may change.
3235
+ | str PC, SAVE_PC
3236
+ | bl extern lj_state_growstack // (lua_State *L, int n)
3237
+ | ldp BASE, RA, L->base
3238
+ | add RC, BASE, RC
3239
+ | sub TMP3, BASE, #16
3240
+ | b <6
3241
+ break;
3242
+
3243
+ /* -- Returns ----------------------------------------------------------- */
3244
+
3245
+ case BC_RETM:
3246
+ | // RA = results, RC = extra results
3247
+ | ldr TMP0w, SAVE_MULTRES
3248
+ | ldr PC, [BASE, FRAME_PC]
3249
+ | add RA, BASE, RA, lsl #3
3250
+ | add RC, TMP0, RC, lsl #3
3251
+ | b ->BC_RETM_Z
3252
+ break;
3253
+
3254
+ case BC_RET:
3255
+ | // RA = results, RC = nresults+1
3256
+ | ldr PC, [BASE, FRAME_PC]
3257
+ | lsl RC, RC, #3
3258
+ | add RA, BASE, RA, lsl #3
3259
+ |->BC_RETM_Z:
3260
+ | str RCw, SAVE_MULTRES
3261
+ |1:
3262
+ | ands CARG1, PC, #FRAME_TYPE
3263
+ | eor CARG2, PC, #FRAME_VARG
3264
+ | bne ->BC_RETV2_Z
3265
+ |
3266
+ |->BC_RET_Z:
3267
+ | // BASE = base, RA = resultptr, RC = (nresults+1)*8, PC = return
3268
+ | ldr INSw, [PC, #-4]
3269
+ | subs TMP1, RC, #8
3270
+ | sub CARG3, BASE, #16
3271
+ | beq >3
3272
+ |2:
3273
+ | ldr TMP0, [RA], #8
3274
+ | add BASE, BASE, #8
3275
+ | sub TMP1, TMP1, #8
3276
+ | str TMP0, [BASE, #-24]
3277
+ | cbnz TMP1, <2
3278
+ |3:
3279
+ | decode_RA RA, INS
3280
+ | sub CARG4, CARG3, RA, lsl #3
3281
+ | decode_RB RB, INS
3282
+ | ldr LFUNC:CARG1, [CARG4, FRAME_FUNC]
3283
+ |5:
3284
+ | cmp RC, RB, lsl #3 // More results expected?
3285
+ | blo >6
3286
+ | and LFUNC:CARG1, CARG1, #LJ_GCVMASK
3287
+ | mov BASE, CARG4
3288
+ | ldr CARG2, LFUNC:CARG1->pc
3289
+ | ldr KBASE, [CARG2, #PC2PROTO(k)]
3290
+ | ins_next
3291
+ |
3292
+ |6: // Fill up results with nil.
3293
+ | add BASE, BASE, #8
3294
+ | add RC, RC, #8
3295
+ | str TISNIL, [BASE, #-24]
3296
+ | b <5
3297
+ |
3298
+ |->BC_RETV1_Z: // Non-standard return case.
3299
+ | add RA, BASE, RA, lsl #3
3300
+ |->BC_RETV2_Z:
3301
+ | tst CARG2, #FRAME_TYPEP
3302
+ | bne ->vm_return
3303
+ | // Return from vararg function: relocate BASE down.
3304
+ | sub BASE, BASE, CARG2
3305
+ | ldr PC, [BASE, FRAME_PC]
3306
+ | b <1
3307
+ break;
3308
+
3309
+ case BC_RET0: case BC_RET1:
3310
+ | // RA = results, RC = nresults+1
3311
+ | ldr PC, [BASE, FRAME_PC]
3312
+ | lsl RC, RC, #3
3313
+ | str RCw, SAVE_MULTRES
3314
+ | ands CARG1, PC, #FRAME_TYPE
3315
+ | eor CARG2, PC, #FRAME_VARG
3316
+ | bne ->BC_RETV1_Z
3317
+ | ldr INSw, [PC, #-4]
3318
+ if (op == BC_RET1) {
3319
+ | ldr TMP0, [BASE, RA, lsl #3]
3320
+ }
3321
+ | sub CARG4, BASE, #16
3322
+ | decode_RA RA, INS
3323
+ | sub BASE, CARG4, RA, lsl #3
3324
+ if (op == BC_RET1) {
3325
+ | str TMP0, [CARG4], #8
3326
+ }
3327
+ | decode_RB RB, INS
3328
+ | ldr LFUNC:CARG1, [BASE, FRAME_FUNC]
3329
+ |5:
3330
+ | cmp RC, RB, lsl #3
3331
+ | blo >6
3332
+ | and LFUNC:CARG1, CARG1, #LJ_GCVMASK
3333
+ | ldr CARG2, LFUNC:CARG1->pc
3334
+ | ldr KBASE, [CARG2, #PC2PROTO(k)]
3335
+ | ins_next
3336
+ |
3337
+ |6: // Fill up results with nil.
3338
+ | add RC, RC, #8
3339
+ | str TISNIL, [CARG4], #8
3340
+ | b <5
3341
+ break;
3342
+
3343
+ /* -- Loops and branches ------------------------------------------------ */
3344
+
3345
+ |.define FOR_IDX, [RA]; .define FOR_TIDX, [RA, #4]
3346
+ |.define FOR_STOP, [RA, #8]; .define FOR_TSTOP, [RA, #12]
3347
+ |.define FOR_STEP, [RA, #16]; .define FOR_TSTEP, [RA, #20]
3348
+ |.define FOR_EXT, [RA, #24]; .define FOR_TEXT, [RA, #28]
3349
+
3350
+ case BC_FORL:
3351
+ |.if JIT
3352
+ | hotloop
3353
+ |.endif
3354
+ | // Fall through. Assumes BC_IFORL follows.
3355
+ break;
3356
+
3357
+ case BC_JFORI:
3358
+ case BC_JFORL:
3359
+ #if !LJ_HASJIT
3360
+ break;
3361
+ #endif
3362
+ case BC_FORI:
3363
+ case BC_IFORL:
3364
+ | // RA = base, RC = target (after end of loop or start of loop)
3365
+ vk = (op == BC_IFORL || op == BC_JFORL);
3366
+ | add RA, BASE, RA, lsl #3
3367
+ | ldp CARG1, CARG2, FOR_IDX // CARG1 = IDX, CARG2 = STOP
3368
+ | ldr CARG3, FOR_STEP // CARG3 = STEP
3369
+ if (op != BC_JFORL) {
3370
+ | add RC, PC, RC, lsl #2
3371
+ | sub RC, RC, #0x20000
3372
+ }
3373
+ | checkint CARG1, >5
3374
+ if (!vk) {
3375
+ | checkint CARG2, ->vmeta_for
3376
+ | checkint CARG3, ->vmeta_for
3377
+ | tbnz CARG3w, #31, >4
3378
+ | cmp CARG1w, CARG2w
3379
+ } else {
3380
+ | adds CARG1w, CARG1w, CARG3w
3381
+ | bvs >2
3382
+ | add TMP0, CARG1, TISNUM
3383
+ | tbnz CARG3w, #31, >4
3384
+ | cmp CARG1w, CARG2w
3385
+ }
3386
+ |1:
3387
+ if (op == BC_FORI) {
3388
+ | csel PC, RC, PC, gt
3389
+ } else if (op == BC_JFORI) {
3390
+ | ldrh RCw, [RC, #-2]
3391
+ } else if (op == BC_IFORL) {
3392
+ | csel PC, RC, PC, le
3393
+ }
3394
+ if (vk) {
3395
+ | str TMP0, FOR_IDX
3396
+ | str TMP0, FOR_EXT
3397
+ } else {
3398
+ | str CARG1, FOR_EXT
3399
+ }
3400
+ if (op == BC_JFORI || op == BC_JFORL) {
3401
+ | ble =>BC_JLOOP
3402
+ }
3403
+ |2:
3404
+ | ins_next
3405
+ |
3406
+ |4: // Invert check for negative step.
3407
+ | cmp CARG2w, CARG1w
3408
+ | b <1
3409
+ |
3410
+ |5: // FP loop.
3411
+ | ldp d0, d1, FOR_IDX
3412
+ | blo ->vmeta_for
3413
+ if (!vk) {
3414
+ | checknum CARG2, ->vmeta_for
3415
+ | checknum CARG3, ->vmeta_for
3416
+ | str d0, FOR_EXT
3417
+ } else {
3418
+ | ldr d2, FOR_STEP
3419
+ | fadd d0, d0, d2
3420
+ }
3421
+ | tbnz CARG3, #63, >7
3422
+ | fcmp d0, d1
3423
+ |6:
3424
+ if (vk) {
3425
+ | str d0, FOR_IDX
3426
+ | str d0, FOR_EXT
3427
+ }
3428
+ if (op == BC_FORI) {
3429
+ | csel PC, RC, PC, hi
3430
+ } else if (op == BC_JFORI) {
3431
+ | ldrh RCw, [RC, #-2]
3432
+ | bls =>BC_JLOOP
3433
+ } else if (op == BC_IFORL) {
3434
+ | csel PC, RC, PC, ls
3435
+ } else {
3436
+ | bls =>BC_JLOOP
3437
+ }
3438
+ | b <2
3439
+ |
3440
+ |7: // Invert check for negative step.
3441
+ | fcmp d1, d0
3442
+ | b <6
3443
+ break;
3444
+
3445
+ case BC_ITERL:
3446
+ |.if JIT
3447
+ | hotloop
3448
+ |.endif
3449
+ | // Fall through. Assumes BC_IITERL follows.
3450
+ break;
3451
+
3452
+ case BC_JITERL:
3453
+ #if !LJ_HASJIT
3454
+ break;
3455
+ #endif
3456
+ case BC_IITERL:
3457
+ | // RA = base, RC = target
3458
+ | ldr CARG1, [BASE, RA, lsl #3]
3459
+ | add TMP1, BASE, RA, lsl #3
3460
+ | cmp CARG1, TISNIL
3461
+ | beq >1 // Stop if iterator returned nil.
3462
+ if (op == BC_JITERL) {
3463
+ | str CARG1, [TMP1, #-8]
3464
+ | b =>BC_JLOOP
3465
+ } else {
3466
+ | add TMP0, PC, RC, lsl #2 // Otherwise save control var + branch.
3467
+ | sub PC, TMP0, #0x20000
3468
+ | str CARG1, [TMP1, #-8]
3469
+ }
3470
+ |1:
3471
+ | ins_next
3472
+ break;
3473
+
3474
+ case BC_LOOP:
3475
+ | // RA = base, RC = target (loop extent)
3476
+ | // Note: RA/RC is only used by trace recorder to determine scope/extent
3477
+ | // This opcode does NOT jump, it's only purpose is to detect a hot loop.
3478
+ |.if JIT
3479
+ | hotloop
3480
+ |.endif
3481
+ | // Fall through. Assumes BC_ILOOP follows.
3482
+ break;
3483
+
3484
+ case BC_ILOOP:
3485
+ | // RA = base, RC = target (loop extent)
3486
+ | ins_next
3487
+ break;
3488
+
3489
+ case BC_JLOOP:
3490
+ |.if JIT
3491
+ | NYI
3492
+ |.endif
3493
+ break;
3494
+
3495
+ case BC_JMP:
3496
+ | // RA = base (only used by trace recorder), RC = target
3497
+ | add RC, PC, RC, lsl #2
3498
+ | sub PC, RC, #0x20000
3499
+ | ins_next
3500
+ break;
3501
+
3502
+ /* -- Function headers -------------------------------------------------- */
3503
+
3504
+ case BC_FUNCF:
3505
+ |.if JIT
3506
+ | hotcall
3507
+ |.endif
3508
+ case BC_FUNCV: /* NYI: compiled vararg functions. */
3509
+ | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow.
3510
+ break;
3511
+
3512
+ case BC_JFUNCF:
3513
+ #if !LJ_HASJIT
3514
+ break;
3515
+ #endif
3516
+ case BC_IFUNCF:
3517
+ | // BASE = new base, RA = BASE+framesize*8, CARG3 = LFUNC, RC = nargs*8
3518
+ | ldr CARG1, L->maxstack
3519
+ | ldrb TMP1w, [PC, #-4+PC2PROTO(numparams)]
3520
+ | ldr KBASE, [PC, #-4+PC2PROTO(k)]
3521
+ | cmp RA, CARG1
3522
+ | bhi ->vm_growstack_l
3523
+ |2:
3524
+ | cmp NARGS8:RC, TMP1, lsl #3 // Check for missing parameters.
3525
+ | blo >3
3526
+ if (op == BC_JFUNCF) {
3527
+ | decode_RD RC, INS
3528
+ | b =>BC_JLOOP
3529
+ } else {
3530
+ | ins_next
3531
+ }
3532
+ |
3533
+ |3: // Clear missing parameters.
3534
+ | str TISNIL, [BASE, NARGS8:RC]
3535
+ | add NARGS8:RC, NARGS8:RC, #8
3536
+ | b <2
3537
+ break;
3538
+
3539
+ case BC_JFUNCV:
3540
+ #if !LJ_HASJIT
3541
+ break;
3542
+ #endif
3543
+ | NYI // NYI: compiled vararg functions
3544
+ break; /* NYI: compiled vararg functions. */
3545
+
3546
+ case BC_IFUNCV:
3547
+ | // BASE = new base, RA = BASE+framesize*8, CARG3 = LFUNC, RC = nargs*8
3548
+ | ldr CARG1, L->maxstack
3549
+ | add TMP2, BASE, RC
3550
+ | add RA, RA, RC
3551
+ | add TMP0, RC, #16+FRAME_VARG
3552
+ | str LFUNC:CARG3, [TMP2], #8 // Store (untagged) copy of LFUNC.
3553
+ | ldr KBASE, [PC, #-4+PC2PROTO(k)]
3554
+ | cmp RA, CARG1
3555
+ | str TMP0, [TMP2], #8 // Store delta + FRAME_VARG.
3556
+ | bhs ->vm_growstack_l
3557
+ | sub RC, TMP2, #16
3558
+ | ldrb TMP1w, [PC, #-4+PC2PROTO(numparams)]
3559
+ | mov RA, BASE
3560
+ | mov BASE, TMP2
3561
+ | cbz TMP1, >2
3562
+ |1:
3563
+ | cmp RA, RC // Less args than parameters?
3564
+ | bhs >3
3565
+ | ldr TMP0, [RA]
3566
+ | sub TMP1, TMP1, #1
3567
+ | str TISNIL, [RA], #8 // Clear old fixarg slot (help the GC).
3568
+ | str TMP0, [TMP2], #8
3569
+ | cbnz TMP1, <1
3570
+ |2:
3571
+ | ins_next
3572
+ |
3573
+ |3:
3574
+ | sub TMP1, TMP1, #1
3575
+ | str TISNIL, [TMP2], #8
3576
+ | cbz TMP1, <2
3577
+ | b <3
3578
+ break;
3579
+
3580
+ case BC_FUNCC:
3581
+ case BC_FUNCCW:
3582
+ | // BASE = new base, RA = BASE+framesize*8, CARG3 = CFUNC, RC = nargs*8
3583
+ if (op == BC_FUNCC) {
3584
+ | ldr CARG4, CFUNC:CARG3->f
3585
+ } else {
3586
+ | ldr CARG4, GL->wrapf
3587
+ }
3588
+ | add CARG2, RA, NARGS8:RC
3589
+ | ldr CARG1, L->maxstack
3590
+ | add RC, BASE, NARGS8:RC
3591
+ | cmp CARG2, CARG1
3592
+ | stp BASE, RC, L->base
3593
+ if (op == BC_FUNCCW) {
3594
+ | ldr CARG2, CFUNC:CARG3->f
3595
+ }
3596
+ | mv_vmstate TMP0w, C
3597
+ | mov CARG1, L
3598
+ | bhi ->vm_growstack_c // Need to grow stack.
3599
+ | st_vmstate TMP0w
3600
+ | blr CARG4 // (lua_State *L [, lua_CFunction f])
3601
+ | // Returns nresults.
3602
+ | ldp BASE, TMP1, L->base
3603
+ | str L, GL->cur_L
3604
+ | sbfiz RC, CRET1, #3, #32
3605
+ | st_vmstate ST_INTERP
3606
+ | ldr PC, [BASE, FRAME_PC]
3607
+ | sub RA, TMP1, RC // RA = L->top - nresults*8
3608
+ | b ->vm_returnc
3609
+ break;
3610
+
3611
+ /* ---------------------------------------------------------------------- */
3612
+
3613
+ default:
3614
+ fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]);
3615
+ exit(2);
3616
+ break;
3617
+ }
3618
+ }
3619
+
3620
+ static int build_backend(BuildCtx *ctx)
3621
+ {
3622
+ int op;
3623
+
3624
+ dasm_growpc(Dst, BC__MAX);
3625
+
3626
+ build_subroutines(ctx);
3627
+
3628
+ |.code_op
3629
+ for (op = 0; op < BC__MAX; op++)
3630
+ build_ins(ctx, (BCOp)op, op);
3631
+
3632
+ return BC__MAX;
3633
+ }
3634
+
3635
+ /* Emit pseudo frame-info for all assembler functions. */
3636
+ static void emit_asm_debug(BuildCtx *ctx)
3637
+ {
3638
+ int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code);
3639
+ int i, cf = CFRAME_SIZE >> 3;
3640
+ switch (ctx->mode) {
3641
+ case BUILD_elfasm:
3642
+ fprintf(ctx->fp, "\t.section .debug_frame,\"\",%%progbits\n");
3643
+ fprintf(ctx->fp,
3644
+ ".Lframe0:\n"
3645
+ "\t.long .LECIE0-.LSCIE0\n"
3646
+ ".LSCIE0:\n"
3647
+ "\t.long 0xffffffff\n"
3648
+ "\t.byte 0x1\n"
3649
+ "\t.string \"\"\n"
3650
+ "\t.uleb128 0x1\n"
3651
+ "\t.sleb128 -8\n"
3652
+ "\t.byte 30\n" /* Return address is in lr. */
3653
+ "\t.byte 0xc\n\t.uleb128 31\n\t.uleb128 0\n" /* def_cfa sp */
3654
+ "\t.align 3\n"
3655
+ ".LECIE0:\n\n");
3656
+ fprintf(ctx->fp,
3657
+ ".LSFDE0:\n"
3658
+ "\t.long .LEFDE0-.LASFDE0\n"
3659
+ ".LASFDE0:\n"
3660
+ "\t.long .Lframe0\n"
3661
+ "\t.quad .Lbegin\n"
3662
+ "\t.quad %d\n"
3663
+ "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */
3664
+ "\t.byte 0x9d\n\t.uleb128 %d\n" /* offset fp */
3665
+ "\t.byte 0x9e\n\t.uleb128 %d\n", /* offset lr */
3666
+ fcofs, CFRAME_SIZE, cf, cf-1);
3667
+ for (i = 19; i <= 28; i++) /* offset x19-x28 */
3668
+ fprintf(ctx->fp, "\t.byte 0x%x\n\t.uleb128 %d\n", 0x80+i, cf-i+17);
3669
+ for (i = 8; i <= 15; i++) /* offset d8-d15 */
3670
+ fprintf(ctx->fp, "\t.byte 5\n\t.uleb128 0x%x\n\t.uleb128 %d\n",
3671
+ 64+i, cf-i-4);
3672
+ fprintf(ctx->fp,
3673
+ "\t.align 3\n"
3674
+ ".LEFDE0:\n\n");
3675
+ #if LJ_HASFFI
3676
+ fprintf(ctx->fp,
3677
+ ".LSFDE1:\n"
3678
+ "\t.long .LEFDE1-.LASFDE1\n"
3679
+ ".LASFDE1:\n"
3680
+ "\t.long .Lframe0\n"
3681
+ "\t.quad lj_vm_ffi_call\n"
3682
+ "\t.quad %d\n"
3683
+ "\t.byte 0xe\n\t.uleb128 32\n" /* def_cfa_offset */
3684
+ "\t.byte 0x9d\n\t.uleb128 4\n" /* offset fp */
3685
+ "\t.byte 0x9e\n\t.uleb128 3\n" /* offset lr */
3686
+ "\t.byte 0x93\n\t.uleb128 2\n" /* offset x19 */
3687
+ "\t.align 3\n"
3688
+ ".LEFDE1:\n\n", (int)ctx->codesz - fcofs);
3689
+ #endif
3690
+ fprintf(ctx->fp, "\t.section .eh_frame,\"a\",%%progbits\n");
3691
+ fprintf(ctx->fp,
3692
+ ".Lframe1:\n"
3693
+ "\t.long .LECIE1-.LSCIE1\n"
3694
+ ".LSCIE1:\n"
3695
+ "\t.long 0\n"
3696
+ "\t.byte 0x1\n"
3697
+ "\t.string \"zPR\"\n"
3698
+ "\t.uleb128 0x1\n"
3699
+ "\t.sleb128 -8\n"
3700
+ "\t.byte 30\n" /* Return address is in lr. */
3701
+ "\t.uleb128 6\n" /* augmentation length */
3702
+ "\t.byte 0x1b\n" /* pcrel|sdata4 */
3703
+ "\t.long lj_err_unwind_dwarf-.\n"
3704
+ "\t.byte 0x1b\n" /* pcrel|sdata4 */
3705
+ "\t.byte 0xc\n\t.uleb128 31\n\t.uleb128 0\n" /* def_cfa sp */
3706
+ "\t.align 3\n"
3707
+ ".LECIE1:\n\n");
3708
+ fprintf(ctx->fp,
3709
+ ".LSFDE2:\n"
3710
+ "\t.long .LEFDE2-.LASFDE2\n"
3711
+ ".LASFDE2:\n"
3712
+ "\t.long .LASFDE2-.Lframe1\n"
3713
+ "\t.long .Lbegin-.\n"
3714
+ "\t.long %d\n"
3715
+ "\t.uleb128 0\n" /* augmentation length */
3716
+ "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */
3717
+ "\t.byte 0x9d\n\t.uleb128 %d\n" /* offset fp */
3718
+ "\t.byte 0x9e\n\t.uleb128 %d\n", /* offset lr */
3719
+ fcofs, CFRAME_SIZE, cf, cf-1);
3720
+ for (i = 19; i <= 28; i++) /* offset x19-x28 */
3721
+ fprintf(ctx->fp, "\t.byte 0x%x\n\t.uleb128 %d\n", 0x80+i, cf-i+17);
3722
+ for (i = 8; i <= 15; i++) /* offset d8-d15 */
3723
+ fprintf(ctx->fp, "\t.byte 5\n\t.uleb128 0x%x\n\t.uleb128 %d\n",
3724
+ 64+i, cf-i-4);
3725
+ fprintf(ctx->fp,
3726
+ "\t.align 3\n"
3727
+ ".LEFDE2:\n\n");
3728
+ #if LJ_HASFFI
3729
+ fprintf(ctx->fp,
3730
+ ".Lframe2:\n"
3731
+ "\t.long .LECIE2-.LSCIE2\n"
3732
+ ".LSCIE2:\n"
3733
+ "\t.long 0\n"
3734
+ "\t.byte 0x1\n"
3735
+ "\t.string \"zR\"\n"
3736
+ "\t.uleb128 0x1\n"
3737
+ "\t.sleb128 -8\n"
3738
+ "\t.byte 30\n" /* Return address is in lr. */
3739
+ "\t.uleb128 1\n" /* augmentation length */
3740
+ "\t.byte 0x1b\n" /* pcrel|sdata4 */
3741
+ "\t.byte 0xc\n\t.uleb128 31\n\t.uleb128 0\n" /* def_cfa sp */
3742
+ "\t.align 3\n"
3743
+ ".LECIE2:\n\n");
3744
+ fprintf(ctx->fp,
3745
+ ".LSFDE3:\n"
3746
+ "\t.long .LEFDE3-.LASFDE3\n"
3747
+ ".LASFDE3:\n"
3748
+ "\t.long .LASFDE3-.Lframe2\n"
3749
+ "\t.long lj_vm_ffi_call-.\n"
3750
+ "\t.long %d\n"
3751
+ "\t.uleb128 0\n" /* augmentation length */
3752
+ "\t.byte 0xe\n\t.uleb128 32\n" /* def_cfa_offset */
3753
+ "\t.byte 0x9d\n\t.uleb128 4\n" /* offset fp */
3754
+ "\t.byte 0x9e\n\t.uleb128 3\n" /* offset lr */
3755
+ "\t.byte 0x93\n\t.uleb128 2\n" /* offset x19 */
3756
+ "\t.align 3\n"
3757
+ ".LEFDE3:\n\n", (int)ctx->codesz - fcofs);
3758
+ #endif
3759
+ break;
3760
+ default:
3761
+ break;
3762
+ }
3763
+ }
3764
+