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,1833 @@
1
+ /*
2
+ ** MIPS IR assembler (SSA IR -> machine code).
3
+ ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
4
+ */
5
+
6
+ /* -- Register allocator extensions --------------------------------------- */
7
+
8
+ /* Allocate a register with a hint. */
9
+ static Reg ra_hintalloc(ASMState *as, IRRef ref, Reg hint, RegSet allow)
10
+ {
11
+ Reg r = IR(ref)->r;
12
+ if (ra_noreg(r)) {
13
+ if (!ra_hashint(r) && !iscrossref(as, ref))
14
+ ra_sethint(IR(ref)->r, hint); /* Propagate register hint. */
15
+ r = ra_allocref(as, ref, allow);
16
+ }
17
+ ra_noweak(as, r);
18
+ return r;
19
+ }
20
+
21
+ /* Allocate a register or RID_ZERO. */
22
+ static Reg ra_alloc1z(ASMState *as, IRRef ref, RegSet allow)
23
+ {
24
+ Reg r = IR(ref)->r;
25
+ if (ra_noreg(r)) {
26
+ if (!(allow & RSET_FPR) && irref_isk(ref) && IR(ref)->i == 0)
27
+ return RID_ZERO;
28
+ r = ra_allocref(as, ref, allow);
29
+ } else {
30
+ ra_noweak(as, r);
31
+ }
32
+ return r;
33
+ }
34
+
35
+ /* Allocate two source registers for three-operand instructions. */
36
+ static Reg ra_alloc2(ASMState *as, IRIns *ir, RegSet allow)
37
+ {
38
+ IRIns *irl = IR(ir->op1), *irr = IR(ir->op2);
39
+ Reg left = irl->r, right = irr->r;
40
+ if (ra_hasreg(left)) {
41
+ ra_noweak(as, left);
42
+ if (ra_noreg(right))
43
+ right = ra_alloc1z(as, ir->op2, rset_exclude(allow, left));
44
+ else
45
+ ra_noweak(as, right);
46
+ } else if (ra_hasreg(right)) {
47
+ ra_noweak(as, right);
48
+ left = ra_alloc1z(as, ir->op1, rset_exclude(allow, right));
49
+ } else if (ra_hashint(right)) {
50
+ right = ra_alloc1z(as, ir->op2, allow);
51
+ left = ra_alloc1z(as, ir->op1, rset_exclude(allow, right));
52
+ } else {
53
+ left = ra_alloc1z(as, ir->op1, allow);
54
+ right = ra_alloc1z(as, ir->op2, rset_exclude(allow, left));
55
+ }
56
+ return left | (right << 8);
57
+ }
58
+
59
+ /* -- Guard handling ------------------------------------------------------ */
60
+
61
+ /* Need some spare long-range jump slots, for out-of-range branches. */
62
+ #define MIPS_SPAREJUMP 4
63
+
64
+ /* Setup spare long-range jump slots per mcarea. */
65
+ static void asm_sparejump_setup(ASMState *as)
66
+ {
67
+ MCode *mxp = as->mcbot;
68
+ /* Assumes sizeof(MCLink) == 8. */
69
+ if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == 8) {
70
+ lua_assert(MIPSI_NOP == 0);
71
+ memset(mxp+2, 0, MIPS_SPAREJUMP*8);
72
+ mxp += MIPS_SPAREJUMP*2;
73
+ lua_assert(mxp < as->mctop);
74
+ lj_mcode_sync(as->mcbot, mxp);
75
+ lj_mcode_commitbot(as->J, mxp);
76
+ as->mcbot = mxp;
77
+ as->mclim = as->mcbot + MCLIM_REDZONE;
78
+ }
79
+ }
80
+
81
+ /* Setup exit stub after the end of each trace. */
82
+ static void asm_exitstub_setup(ASMState *as)
83
+ {
84
+ MCode *mxp = as->mctop;
85
+ /* sw TMP, 0(sp); j ->vm_exit_handler; li TMP, traceno */
86
+ *--mxp = MIPSI_LI|MIPSF_T(RID_TMP)|as->T->traceno;
87
+ *--mxp = MIPSI_J|((((uintptr_t)(void *)lj_vm_exit_handler)>>2)&0x03ffffffu);
88
+ lua_assert(((uintptr_t)mxp ^ (uintptr_t)(void *)lj_vm_exit_handler)>>28 == 0);
89
+ *--mxp = MIPSI_SW|MIPSF_T(RID_TMP)|MIPSF_S(RID_SP)|0;
90
+ as->mctop = mxp;
91
+ }
92
+
93
+ /* Keep this in-sync with exitstub_trace_addr(). */
94
+ #define asm_exitstub_addr(as) ((as)->mctop)
95
+
96
+ /* Emit conditional branch to exit for guard. */
97
+ static void asm_guard(ASMState *as, MIPSIns mi, Reg rs, Reg rt)
98
+ {
99
+ MCode *target = asm_exitstub_addr(as);
100
+ MCode *p = as->mcp;
101
+ if (LJ_UNLIKELY(p == as->invmcp)) {
102
+ as->invmcp = NULL;
103
+ as->loopinv = 1;
104
+ as->mcp = p+1;
105
+ mi = mi ^ ((mi>>28) == 1 ? 0x04000000u : 0x00010000u); /* Invert cond. */
106
+ target = p; /* Patch target later in asm_loop_fixup. */
107
+ }
108
+ emit_ti(as, MIPSI_LI, RID_TMP, as->snapno);
109
+ emit_branch(as, mi, rs, rt, target);
110
+ }
111
+
112
+ /* -- Operand fusion ------------------------------------------------------ */
113
+
114
+ /* Limit linear search to this distance. Avoids O(n^2) behavior. */
115
+ #define CONFLICT_SEARCH_LIM 31
116
+
117
+ /* Check if there's no conflicting instruction between curins and ref. */
118
+ static int noconflict(ASMState *as, IRRef ref, IROp conflict)
119
+ {
120
+ IRIns *ir = as->ir;
121
+ IRRef i = as->curins;
122
+ if (i > ref + CONFLICT_SEARCH_LIM)
123
+ return 0; /* Give up, ref is too far away. */
124
+ while (--i > ref)
125
+ if (ir[i].o == conflict)
126
+ return 0; /* Conflict found. */
127
+ return 1; /* Ok, no conflict. */
128
+ }
129
+
130
+ /* Fuse the array base of colocated arrays. */
131
+ static int32_t asm_fuseabase(ASMState *as, IRRef ref)
132
+ {
133
+ IRIns *ir = IR(ref);
134
+ if (ir->o == IR_TNEW && ir->op1 <= LJ_MAX_COLOSIZE &&
135
+ !neverfuse(as) && noconflict(as, ref, IR_NEWREF))
136
+ return (int32_t)sizeof(GCtab);
137
+ return 0;
138
+ }
139
+
140
+ /* Fuse array/hash/upvalue reference into register+offset operand. */
141
+ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
142
+ {
143
+ IRIns *ir = IR(ref);
144
+ if (ra_noreg(ir->r)) {
145
+ if (ir->o == IR_AREF) {
146
+ if (mayfuse(as, ref)) {
147
+ if (irref_isk(ir->op2)) {
148
+ IRRef tab = IR(ir->op1)->op1;
149
+ int32_t ofs = asm_fuseabase(as, tab);
150
+ IRRef refa = ofs ? tab : ir->op1;
151
+ ofs += 8*IR(ir->op2)->i;
152
+ if (checki16(ofs)) {
153
+ *ofsp = ofs;
154
+ return ra_alloc1(as, refa, allow);
155
+ }
156
+ }
157
+ }
158
+ } else if (ir->o == IR_HREFK) {
159
+ if (mayfuse(as, ref)) {
160
+ int32_t ofs = (int32_t)(IR(ir->op2)->op2 * sizeof(Node));
161
+ if (checki16(ofs)) {
162
+ *ofsp = ofs;
163
+ return ra_alloc1(as, ir->op1, allow);
164
+ }
165
+ }
166
+ } else if (ir->o == IR_UREFC) {
167
+ if (irref_isk(ir->op1)) {
168
+ GCfunc *fn = ir_kfunc(IR(ir->op1));
169
+ int32_t ofs = i32ptr(&gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.tv);
170
+ int32_t jgl = (intptr_t)J2G(as->J);
171
+ if ((uint32_t)(ofs-jgl) < 65536) {
172
+ *ofsp = ofs-jgl-32768;
173
+ return RID_JGL;
174
+ } else {
175
+ *ofsp = (int16_t)ofs;
176
+ return ra_allock(as, ofs-(int16_t)ofs, allow);
177
+ }
178
+ }
179
+ }
180
+ }
181
+ *ofsp = 0;
182
+ return ra_alloc1(as, ref, allow);
183
+ }
184
+
185
+ /* Fuse XLOAD/XSTORE reference into load/store operand. */
186
+ static void asm_fusexref(ASMState *as, MIPSIns mi, Reg rt, IRRef ref,
187
+ RegSet allow, int32_t ofs)
188
+ {
189
+ IRIns *ir = IR(ref);
190
+ Reg base;
191
+ if (ra_noreg(ir->r) && canfuse(as, ir)) {
192
+ if (ir->o == IR_ADD) {
193
+ int32_t ofs2;
194
+ if (irref_isk(ir->op2) && (ofs2 = ofs + IR(ir->op2)->i, checki16(ofs2))) {
195
+ ref = ir->op1;
196
+ ofs = ofs2;
197
+ }
198
+ } else if (ir->o == IR_STRREF) {
199
+ int32_t ofs2 = 65536;
200
+ lua_assert(ofs == 0);
201
+ ofs = (int32_t)sizeof(GCstr);
202
+ if (irref_isk(ir->op2)) {
203
+ ofs2 = ofs + IR(ir->op2)->i;
204
+ ref = ir->op1;
205
+ } else if (irref_isk(ir->op1)) {
206
+ ofs2 = ofs + IR(ir->op1)->i;
207
+ ref = ir->op2;
208
+ }
209
+ if (!checki16(ofs2)) {
210
+ /* NYI: Fuse ADD with constant. */
211
+ Reg right, left = ra_alloc2(as, ir, allow);
212
+ right = (left >> 8); left &= 255;
213
+ emit_hsi(as, mi, rt, RID_TMP, ofs);
214
+ emit_dst(as, MIPSI_ADDU, RID_TMP, left, right);
215
+ return;
216
+ }
217
+ ofs = ofs2;
218
+ }
219
+ }
220
+ base = ra_alloc1(as, ref, allow);
221
+ emit_hsi(as, mi, rt, base, ofs);
222
+ }
223
+
224
+ /* -- Calls --------------------------------------------------------------- */
225
+
226
+ /* Generate a call to a C function. */
227
+ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
228
+ {
229
+ uint32_t n, nargs = CCI_XNARGS(ci);
230
+ int32_t ofs = 16;
231
+ Reg gpr, fpr = REGARG_FIRSTFPR;
232
+ if ((void *)ci->func)
233
+ emit_call(as, (void *)ci->func);
234
+ for (gpr = REGARG_FIRSTGPR; gpr <= REGARG_LASTGPR; gpr++)
235
+ as->cost[gpr] = REGCOST(~0u, ASMREF_L);
236
+ gpr = REGARG_FIRSTGPR;
237
+ for (n = 0; n < nargs; n++) { /* Setup args. */
238
+ IRRef ref = args[n];
239
+ if (ref) {
240
+ IRIns *ir = IR(ref);
241
+ if (irt_isfp(ir->t) && fpr <= REGARG_LASTFPR &&
242
+ !(ci->flags & CCI_VARARG)) {
243
+ lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */
244
+ ra_leftov(as, fpr, ref);
245
+ fpr += 2;
246
+ gpr += irt_isnum(ir->t) ? 2 : 1;
247
+ } else {
248
+ fpr = REGARG_LASTFPR+1;
249
+ if (irt_isnum(ir->t)) gpr = (gpr+1) & ~1;
250
+ if (gpr <= REGARG_LASTGPR) {
251
+ lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */
252
+ if (irt_isfp(ir->t)) {
253
+ RegSet of = as->freeset;
254
+ Reg r;
255
+ /* Workaround to protect argument GPRs from being used for remat. */
256
+ as->freeset &= ~RSET_RANGE(REGARG_FIRSTGPR, REGARG_LASTGPR+1);
257
+ r = ra_alloc1(as, ref, RSET_FPR);
258
+ as->freeset |= (of & RSET_RANGE(REGARG_FIRSTGPR, REGARG_LASTGPR+1));
259
+ if (irt_isnum(ir->t)) {
260
+ emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?0:1), r+1);
261
+ emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?1:0), r);
262
+ lua_assert(rset_test(as->freeset, gpr+1)); /* Already evicted. */
263
+ gpr += 2;
264
+ } else if (irt_isfloat(ir->t)) {
265
+ emit_tg(as, MIPSI_MFC1, gpr, r);
266
+ gpr++;
267
+ }
268
+ } else {
269
+ ra_leftov(as, gpr, ref);
270
+ gpr++;
271
+ }
272
+ } else {
273
+ Reg r = ra_alloc1z(as, ref, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR);
274
+ if (irt_isnum(ir->t)) ofs = (ofs + 4) & ~4;
275
+ emit_spstore(as, ir, r, ofs);
276
+ ofs += irt_isnum(ir->t) ? 8 : 4;
277
+ }
278
+ }
279
+ } else {
280
+ fpr = REGARG_LASTFPR+1;
281
+ if (gpr <= REGARG_LASTGPR)
282
+ gpr++;
283
+ else
284
+ ofs += 4;
285
+ }
286
+ checkmclim(as);
287
+ }
288
+ }
289
+
290
+ /* Setup result reg/sp for call. Evict scratch regs. */
291
+ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
292
+ {
293
+ RegSet drop = RSET_SCRATCH;
294
+ int hiop = ((ir+1)->o == IR_HIOP);
295
+ if ((ci->flags & CCI_NOFPRCLOBBER))
296
+ drop &= ~RSET_FPR;
297
+ if (ra_hasreg(ir->r))
298
+ rset_clear(drop, ir->r); /* Dest reg handled below. */
299
+ if (hiop && ra_hasreg((ir+1)->r))
300
+ rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
301
+ ra_evictset(as, drop); /* Evictions must be performed first. */
302
+ if (ra_used(ir)) {
303
+ lua_assert(!irt_ispri(ir->t));
304
+ if (irt_isfp(ir->t)) {
305
+ if ((ci->flags & CCI_CASTU64)) {
306
+ int32_t ofs = sps_scale(ir->s);
307
+ Reg dest = ir->r;
308
+ if (ra_hasreg(dest)) {
309
+ ra_free(as, dest);
310
+ ra_modified(as, dest);
311
+ emit_tg(as, MIPSI_MTC1, RID_RETHI, dest+1);
312
+ emit_tg(as, MIPSI_MTC1, RID_RETLO, dest);
313
+ }
314
+ if (ofs) {
315
+ emit_tsi(as, MIPSI_SW, RID_RETLO, RID_SP, ofs+(LJ_BE?4:0));
316
+ emit_tsi(as, MIPSI_SW, RID_RETHI, RID_SP, ofs+(LJ_BE?0:4));
317
+ }
318
+ } else {
319
+ ra_destreg(as, ir, RID_FPRET);
320
+ }
321
+ } else if (hiop) {
322
+ ra_destpair(as, ir);
323
+ } else {
324
+ ra_destreg(as, ir, RID_RET);
325
+ }
326
+ }
327
+ }
328
+
329
+ static void asm_callx(ASMState *as, IRIns *ir)
330
+ {
331
+ IRRef args[CCI_NARGS_MAX*2];
332
+ CCallInfo ci;
333
+ IRRef func;
334
+ IRIns *irf;
335
+ ci.flags = asm_callx_flags(as, ir);
336
+ asm_collectargs(as, ir, &ci, args);
337
+ asm_setupresult(as, ir, &ci);
338
+ func = ir->op2; irf = IR(func);
339
+ if (irf->o == IR_CARG) { func = irf->op1; irf = IR(func); }
340
+ if (irref_isk(func)) { /* Call to constant address. */
341
+ ci.func = (ASMFunction)(void *)(irf->i);
342
+ } else { /* Need specific register for indirect calls. */
343
+ Reg r = ra_alloc1(as, func, RID2RSET(RID_CFUNCADDR));
344
+ MCode *p = as->mcp;
345
+ if (r == RID_CFUNCADDR)
346
+ *--p = MIPSI_NOP;
347
+ else
348
+ *--p = MIPSI_MOVE | MIPSF_D(RID_CFUNCADDR) | MIPSF_S(r);
349
+ *--p = MIPSI_JALR | MIPSF_S(r);
350
+ as->mcp = p;
351
+ ci.func = (ASMFunction)(void *)0;
352
+ }
353
+ asm_gencall(as, &ci, args);
354
+ }
355
+
356
+ static void asm_callround(ASMState *as, IRIns *ir, IRCallID id)
357
+ {
358
+ /* The modified regs must match with the *.dasc implementation. */
359
+ RegSet drop = RID2RSET(RID_R1)|RID2RSET(RID_R12)|RID2RSET(RID_FPRET)|
360
+ RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(REGARG_FIRSTFPR);
361
+ if (ra_hasreg(ir->r)) rset_clear(drop, ir->r);
362
+ ra_evictset(as, drop);
363
+ ra_destreg(as, ir, RID_FPRET);
364
+ emit_call(as, (void *)lj_ir_callinfo[id].func);
365
+ ra_leftov(as, REGARG_FIRSTFPR, ir->op1);
366
+ }
367
+
368
+ /* -- Returns ------------------------------------------------------------- */
369
+
370
+ /* Return to lower frame. Guard that it goes to the right spot. */
371
+ static void asm_retf(ASMState *as, IRIns *ir)
372
+ {
373
+ Reg base = ra_alloc1(as, REF_BASE, RSET_GPR);
374
+ void *pc = ir_kptr(IR(ir->op2));
375
+ int32_t delta = 1+LJ_FR2+bc_a(*((const BCIns *)pc - 1));
376
+ as->topslot -= (BCReg)delta;
377
+ if ((int32_t)as->topslot < 0) as->topslot = 0;
378
+ irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */
379
+ emit_setgl(as, base, jit_base);
380
+ emit_addptr(as, base, -8*delta);
381
+ asm_guard(as, MIPSI_BNE, RID_TMP,
382
+ ra_allock(as, i32ptr(pc), rset_exclude(RSET_GPR, base)));
383
+ emit_tsi(as, MIPSI_LW, RID_TMP, base, -8);
384
+ }
385
+
386
+ /* -- Type conversions ---------------------------------------------------- */
387
+
388
+ static void asm_tointg(ASMState *as, IRIns *ir, Reg left)
389
+ {
390
+ Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left));
391
+ Reg dest = ra_dest(as, ir, RSET_GPR);
392
+ asm_guard(as, MIPSI_BC1F, 0, 0);
393
+ emit_fgh(as, MIPSI_C_EQ_D, 0, tmp, left);
394
+ emit_fg(as, MIPSI_CVT_D_W, tmp, tmp);
395
+ emit_tg(as, MIPSI_MFC1, dest, tmp);
396
+ emit_fg(as, MIPSI_CVT_W_D, tmp, left);
397
+ }
398
+
399
+ static void asm_tobit(ASMState *as, IRIns *ir)
400
+ {
401
+ RegSet allow = RSET_FPR;
402
+ Reg dest = ra_dest(as, ir, RSET_GPR);
403
+ Reg left = ra_alloc1(as, ir->op1, allow);
404
+ Reg right = ra_alloc1(as, ir->op2, rset_clear(allow, left));
405
+ Reg tmp = ra_scratch(as, rset_clear(allow, right));
406
+ emit_tg(as, MIPSI_MFC1, dest, tmp);
407
+ emit_fgh(as, MIPSI_ADD_D, tmp, left, right);
408
+ }
409
+
410
+ static void asm_conv(ASMState *as, IRIns *ir)
411
+ {
412
+ IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK);
413
+ int stfp = (st == IRT_NUM || st == IRT_FLOAT);
414
+ IRRef lref = ir->op1;
415
+ lua_assert(irt_type(ir->t) != st);
416
+ lua_assert(!(irt_isint64(ir->t) ||
417
+ (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */
418
+ if (irt_isfp(ir->t)) {
419
+ Reg dest = ra_dest(as, ir, RSET_FPR);
420
+ if (stfp) { /* FP to FP conversion. */
421
+ emit_fg(as, st == IRT_NUM ? MIPSI_CVT_S_D : MIPSI_CVT_D_S,
422
+ dest, ra_alloc1(as, lref, RSET_FPR));
423
+ } else if (st == IRT_U32) { /* U32 to FP conversion. */
424
+ /* y = (x ^ 0x8000000) + 2147483648.0 */
425
+ Reg left = ra_alloc1(as, lref, RSET_GPR);
426
+ Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, dest));
427
+ emit_fgh(as, irt_isfloat(ir->t) ? MIPSI_ADD_S : MIPSI_ADD_D,
428
+ dest, dest, tmp);
429
+ emit_fg(as, irt_isfloat(ir->t) ? MIPSI_CVT_S_W : MIPSI_CVT_D_W,
430
+ dest, dest);
431
+ if (irt_isfloat(ir->t))
432
+ emit_lsptr(as, MIPSI_LWC1, (tmp & 31),
433
+ (void *)lj_ir_k64_find(as->J, U64x(4f000000,4f000000)),
434
+ RSET_GPR);
435
+ else
436
+ emit_lsptr(as, MIPSI_LDC1, (tmp & 31),
437
+ (void *)lj_ir_k64_find(as->J, U64x(41e00000,00000000)),
438
+ RSET_GPR);
439
+ emit_tg(as, MIPSI_MTC1, RID_TMP, dest);
440
+ emit_dst(as, MIPSI_XOR, RID_TMP, RID_TMP, left);
441
+ emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000);
442
+ } else { /* Integer to FP conversion. */
443
+ Reg left = ra_alloc1(as, lref, RSET_GPR);
444
+ emit_fg(as, irt_isfloat(ir->t) ? MIPSI_CVT_S_W : MIPSI_CVT_D_W,
445
+ dest, dest);
446
+ emit_tg(as, MIPSI_MTC1, left, dest);
447
+ }
448
+ } else if (stfp) { /* FP to integer conversion. */
449
+ if (irt_isguard(ir->t)) {
450
+ /* Checked conversions are only supported from number to int. */
451
+ lua_assert(irt_isint(ir->t) && st == IRT_NUM);
452
+ asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
453
+ } else {
454
+ Reg dest = ra_dest(as, ir, RSET_GPR);
455
+ Reg left = ra_alloc1(as, lref, RSET_FPR);
456
+ Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left));
457
+ if (irt_isu32(ir->t)) {
458
+ /* y = (int)floor(x - 2147483648.0) ^ 0x80000000 */
459
+ emit_dst(as, MIPSI_XOR, dest, dest, RID_TMP);
460
+ emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000);
461
+ emit_tg(as, MIPSI_MFC1, dest, tmp);
462
+ emit_fg(as, st == IRT_FLOAT ? MIPSI_FLOOR_W_S : MIPSI_FLOOR_W_D,
463
+ tmp, tmp);
464
+ emit_fgh(as, st == IRT_FLOAT ? MIPSI_SUB_S : MIPSI_SUB_D,
465
+ tmp, left, tmp);
466
+ if (st == IRT_FLOAT)
467
+ emit_lsptr(as, MIPSI_LWC1, (tmp & 31),
468
+ (void *)lj_ir_k64_find(as->J, U64x(4f000000,4f000000)),
469
+ RSET_GPR);
470
+ else
471
+ emit_lsptr(as, MIPSI_LDC1, (tmp & 31),
472
+ (void *)lj_ir_k64_find(as->J, U64x(41e00000,00000000)),
473
+ RSET_GPR);
474
+ } else {
475
+ emit_tg(as, MIPSI_MFC1, dest, tmp);
476
+ emit_fg(as, st == IRT_FLOAT ? MIPSI_TRUNC_W_S : MIPSI_TRUNC_W_D,
477
+ tmp, left);
478
+ }
479
+ }
480
+ } else {
481
+ Reg dest = ra_dest(as, ir, RSET_GPR);
482
+ if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */
483
+ Reg left = ra_alloc1(as, ir->op1, RSET_GPR);
484
+ lua_assert(irt_isint(ir->t) || irt_isu32(ir->t));
485
+ if ((ir->op2 & IRCONV_SEXT)) {
486
+ if ((as->flags & JIT_F_MIPS32R2)) {
487
+ emit_dst(as, st == IRT_I8 ? MIPSI_SEB : MIPSI_SEH, dest, 0, left);
488
+ } else {
489
+ uint32_t shift = st == IRT_I8 ? 24 : 16;
490
+ emit_dta(as, MIPSI_SRA, dest, dest, shift);
491
+ emit_dta(as, MIPSI_SLL, dest, left, shift);
492
+ }
493
+ } else {
494
+ emit_tsi(as, MIPSI_ANDI, dest, left,
495
+ (int32_t)(st == IRT_U8 ? 0xff : 0xffff));
496
+ }
497
+ } else { /* 32/64 bit integer conversions. */
498
+ /* Only need to handle 32/32 bit no-op (cast) on 32 bit archs. */
499
+ ra_leftov(as, dest, lref); /* Do nothing, but may need to move regs. */
500
+ }
501
+ }
502
+ }
503
+
504
+ static void asm_strto(ASMState *as, IRIns *ir)
505
+ {
506
+ const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num];
507
+ IRRef args[2];
508
+ RegSet drop = RSET_SCRATCH;
509
+ if (ra_hasreg(ir->r)) rset_set(drop, ir->r); /* Spill dest reg (if any). */
510
+ ra_evictset(as, drop);
511
+ asm_guard(as, MIPSI_BEQ, RID_RET, RID_ZERO); /* Test return status. */
512
+ args[0] = ir->op1; /* GCstr *str */
513
+ args[1] = ASMREF_TMP1; /* TValue *n */
514
+ asm_gencall(as, ci, args);
515
+ /* Store the result to the spill slot or temp slots. */
516
+ emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1),
517
+ RID_SP, sps_scale(ir->s));
518
+ }
519
+
520
+ /* -- Memory references --------------------------------------------------- */
521
+
522
+ /* Get pointer to TValue. */
523
+ static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
524
+ {
525
+ IRIns *ir = IR(ref);
526
+ if (irt_isnum(ir->t)) {
527
+ if (irref_isk(ref)) /* Use the number constant itself as a TValue. */
528
+ ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
529
+ else /* Otherwise force a spill and use the spill slot. */
530
+ emit_tsi(as, MIPSI_ADDIU, dest, RID_SP, ra_spill(as, ir));
531
+ } else {
532
+ /* Otherwise use g->tmptv to hold the TValue. */
533
+ RegSet allow = rset_exclude(RSET_GPR, dest);
534
+ Reg type;
535
+ emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, offsetof(global_State, tmptv)-32768);
536
+ if (!irt_ispri(ir->t)) {
537
+ Reg src = ra_alloc1(as, ref, allow);
538
+ emit_setgl(as, src, tmptv.gcr);
539
+ }
540
+ type = ra_allock(as, irt_toitype(ir->t), allow);
541
+ emit_setgl(as, type, tmptv.it);
542
+ }
543
+ }
544
+
545
+ static void asm_aref(ASMState *as, IRIns *ir)
546
+ {
547
+ Reg dest = ra_dest(as, ir, RSET_GPR);
548
+ Reg idx, base;
549
+ if (irref_isk(ir->op2)) {
550
+ IRRef tab = IR(ir->op1)->op1;
551
+ int32_t ofs = asm_fuseabase(as, tab);
552
+ IRRef refa = ofs ? tab : ir->op1;
553
+ ofs += 8*IR(ir->op2)->i;
554
+ if (checki16(ofs)) {
555
+ base = ra_alloc1(as, refa, RSET_GPR);
556
+ emit_tsi(as, MIPSI_ADDIU, dest, base, ofs);
557
+ return;
558
+ }
559
+ }
560
+ base = ra_alloc1(as, ir->op1, RSET_GPR);
561
+ idx = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, base));
562
+ emit_dst(as, MIPSI_ADDU, dest, RID_TMP, base);
563
+ emit_dta(as, MIPSI_SLL, RID_TMP, idx, 3);
564
+ }
565
+
566
+ /* Inlined hash lookup. Specialized for key type and for const keys.
567
+ ** The equivalent C code is:
568
+ ** Node *n = hashkey(t, key);
569
+ ** do {
570
+ ** if (lj_obj_equal(&n->key, key)) return &n->val;
571
+ ** } while ((n = nextnode(n)));
572
+ ** return niltv(L);
573
+ */
574
+ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
575
+ {
576
+ RegSet allow = RSET_GPR;
577
+ int destused = ra_used(ir);
578
+ Reg dest = ra_dest(as, ir, allow);
579
+ Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest));
580
+ Reg key = RID_NONE, type = RID_NONE, tmpnum = RID_NONE, tmp1 = RID_TMP, tmp2;
581
+ IRRef refkey = ir->op2;
582
+ IRIns *irkey = IR(refkey);
583
+ IRType1 kt = irkey->t;
584
+ uint32_t khash;
585
+ MCLabel l_end, l_loop, l_next;
586
+
587
+ rset_clear(allow, tab);
588
+ if (irt_isnum(kt)) {
589
+ key = ra_alloc1(as, refkey, RSET_FPR);
590
+ tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
591
+ } else if (!irt_ispri(kt)) {
592
+ key = ra_alloc1(as, refkey, allow);
593
+ rset_clear(allow, key);
594
+ type = ra_allock(as, irt_toitype(irkey->t), allow);
595
+ rset_clear(allow, type);
596
+ }
597
+ tmp2 = ra_scratch(as, allow);
598
+ rset_clear(allow, tmp2);
599
+
600
+ /* Key not found in chain: jump to exit (if merged) or load niltv. */
601
+ l_end = emit_label(as);
602
+ as->invmcp = NULL;
603
+ if (merge == IR_NE)
604
+ asm_guard(as, MIPSI_B, RID_ZERO, RID_ZERO);
605
+ else if (destused)
606
+ emit_loada(as, dest, niltvg(J2G(as->J)));
607
+ /* Follow hash chain until the end. */
608
+ emit_move(as, dest, tmp2);
609
+ l_loop = --as->mcp;
610
+ emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, next));
611
+ l_next = emit_label(as);
612
+
613
+ /* Type and value comparison. */
614
+ if (merge == IR_EQ) { /* Must match asm_guard(). */
615
+ emit_ti(as, MIPSI_LI, RID_TMP, as->snapno);
616
+ l_end = asm_exitstub_addr(as);
617
+ }
618
+ if (irt_isnum(kt)) {
619
+ emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
620
+ emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key);
621
+ *--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */
622
+ emit_branch(as, MIPSI_BEQ, tmp2, RID_ZERO, l_next);
623
+ emit_tsi(as, MIPSI_SLTIU, tmp2, tmp2, (int32_t)LJ_TISNUM);
624
+ emit_hsi(as, MIPSI_LDC1, tmpnum, dest, (int32_t)offsetof(Node, key.n));
625
+ } else {
626
+ if (irt_ispri(kt)) {
627
+ emit_branch(as, MIPSI_BEQ, tmp2, type, l_end);
628
+ } else {
629
+ emit_branch(as, MIPSI_BEQ, tmp1, key, l_end);
630
+ emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, key.gcr));
631
+ emit_branch(as, MIPSI_BNE, tmp2, type, l_next);
632
+ }
633
+ }
634
+ emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, key.it));
635
+ *l_loop = MIPSI_BNE | MIPSF_S(tmp2) | ((as->mcp-l_loop-1) & 0xffffu);
636
+
637
+ /* Load main position relative to tab->node into dest. */
638
+ khash = irref_isk(refkey) ? ir_khash(irkey) : 1;
639
+ if (khash == 0) {
640
+ emit_tsi(as, MIPSI_LW, dest, tab, (int32_t)offsetof(GCtab, node));
641
+ } else {
642
+ Reg tmphash = tmp1;
643
+ if (irref_isk(refkey))
644
+ tmphash = ra_allock(as, khash, allow);
645
+ emit_dst(as, MIPSI_ADDU, dest, dest, tmp1);
646
+ lua_assert(sizeof(Node) == 24);
647
+ emit_dst(as, MIPSI_SUBU, tmp1, tmp2, tmp1);
648
+ emit_dta(as, MIPSI_SLL, tmp1, tmp1, 3);
649
+ emit_dta(as, MIPSI_SLL, tmp2, tmp1, 5);
650
+ emit_dst(as, MIPSI_AND, tmp1, tmp2, tmphash);
651
+ emit_tsi(as, MIPSI_LW, dest, tab, (int32_t)offsetof(GCtab, node));
652
+ emit_tsi(as, MIPSI_LW, tmp2, tab, (int32_t)offsetof(GCtab, hmask));
653
+ if (irref_isk(refkey)) {
654
+ /* Nothing to do. */
655
+ } else if (irt_isstr(kt)) {
656
+ emit_tsi(as, MIPSI_LW, tmp1, key, (int32_t)offsetof(GCstr, hash));
657
+ } else { /* Must match with hash*() in lj_tab.c. */
658
+ emit_dst(as, MIPSI_SUBU, tmp1, tmp1, tmp2);
659
+ emit_rotr(as, tmp2, tmp2, dest, (-HASH_ROT3)&31);
660
+ emit_dst(as, MIPSI_XOR, tmp1, tmp1, tmp2);
661
+ emit_rotr(as, tmp1, tmp1, dest, (-HASH_ROT2-HASH_ROT1)&31);
662
+ emit_dst(as, MIPSI_SUBU, tmp2, tmp2, dest);
663
+ if (irt_isnum(kt)) {
664
+ emit_dst(as, MIPSI_XOR, tmp2, tmp2, tmp1);
665
+ if ((as->flags & JIT_F_MIPS32R2)) {
666
+ emit_dta(as, MIPSI_ROTR, dest, tmp1, (-HASH_ROT1)&31);
667
+ } else {
668
+ emit_dst(as, MIPSI_OR, dest, dest, tmp1);
669
+ emit_dta(as, MIPSI_SLL, tmp1, tmp1, HASH_ROT1);
670
+ emit_dta(as, MIPSI_SRL, dest, tmp1, (-HASH_ROT1)&31);
671
+ }
672
+ emit_dst(as, MIPSI_ADDU, tmp1, tmp1, tmp1);
673
+ emit_tg(as, MIPSI_MFC1, tmp2, key);
674
+ emit_tg(as, MIPSI_MFC1, tmp1, key+1);
675
+ } else {
676
+ emit_dst(as, MIPSI_XOR, tmp2, key, tmp1);
677
+ emit_rotr(as, dest, tmp1, tmp2, (-HASH_ROT1)&31);
678
+ emit_dst(as, MIPSI_ADDU, tmp1, key, ra_allock(as, HASH_BIAS, allow));
679
+ }
680
+ }
681
+ }
682
+ }
683
+
684
+ static void asm_hrefk(ASMState *as, IRIns *ir)
685
+ {
686
+ IRIns *kslot = IR(ir->op2);
687
+ IRIns *irkey = IR(kslot->op1);
688
+ int32_t ofs = (int32_t)(kslot->op2 * sizeof(Node));
689
+ int32_t kofs = ofs + (int32_t)offsetof(Node, key);
690
+ Reg dest = (ra_used(ir)||ofs > 32736) ? ra_dest(as, ir, RSET_GPR) : RID_NONE;
691
+ Reg node = ra_alloc1(as, ir->op1, RSET_GPR);
692
+ Reg key = RID_NONE, type = RID_TMP, idx = node;
693
+ RegSet allow = rset_exclude(RSET_GPR, node);
694
+ int32_t lo, hi;
695
+ lua_assert(ofs % sizeof(Node) == 0);
696
+ if (ofs > 32736) {
697
+ idx = dest;
698
+ rset_clear(allow, dest);
699
+ kofs = (int32_t)offsetof(Node, key);
700
+ } else if (ra_hasreg(dest)) {
701
+ emit_tsi(as, MIPSI_ADDIU, dest, node, ofs);
702
+ }
703
+ if (!irt_ispri(irkey->t)) {
704
+ key = ra_scratch(as, allow);
705
+ rset_clear(allow, key);
706
+ }
707
+ if (irt_isnum(irkey->t)) {
708
+ lo = (int32_t)ir_knum(irkey)->u32.lo;
709
+ hi = (int32_t)ir_knum(irkey)->u32.hi;
710
+ } else {
711
+ lo = irkey->i;
712
+ hi = irt_toitype(irkey->t);
713
+ if (!ra_hasreg(key))
714
+ goto nolo;
715
+ }
716
+ asm_guard(as, MIPSI_BNE, key, lo ? ra_allock(as, lo, allow) : RID_ZERO);
717
+ nolo:
718
+ asm_guard(as, MIPSI_BNE, type, hi ? ra_allock(as, hi, allow) : RID_ZERO);
719
+ if (ra_hasreg(key)) emit_tsi(as, MIPSI_LW, key, idx, kofs+(LJ_BE?4:0));
720
+ emit_tsi(as, MIPSI_LW, type, idx, kofs+(LJ_BE?0:4));
721
+ if (ofs > 32736)
722
+ emit_tsi(as, MIPSI_ADDU, dest, node, ra_allock(as, ofs, allow));
723
+ }
724
+
725
+ static void asm_uref(ASMState *as, IRIns *ir)
726
+ {
727
+ /* NYI: Check that UREFO is still open and not aliasing a slot. */
728
+ Reg dest = ra_dest(as, ir, RSET_GPR);
729
+ if (irref_isk(ir->op1)) {
730
+ GCfunc *fn = ir_kfunc(IR(ir->op1));
731
+ MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v;
732
+ emit_lsptr(as, MIPSI_LW, dest, v, RSET_GPR);
733
+ } else {
734
+ Reg uv = ra_scratch(as, RSET_GPR);
735
+ Reg func = ra_alloc1(as, ir->op1, RSET_GPR);
736
+ if (ir->o == IR_UREFC) {
737
+ asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
738
+ emit_tsi(as, MIPSI_ADDIU, dest, uv, (int32_t)offsetof(GCupval, tv));
739
+ emit_tsi(as, MIPSI_LBU, RID_TMP, uv, (int32_t)offsetof(GCupval, closed));
740
+ } else {
741
+ emit_tsi(as, MIPSI_LW, dest, uv, (int32_t)offsetof(GCupval, v));
742
+ }
743
+ emit_tsi(as, MIPSI_LW, uv, func,
744
+ (int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)(ir->op2 >> 8));
745
+ }
746
+ }
747
+
748
+ static void asm_fref(ASMState *as, IRIns *ir)
749
+ {
750
+ UNUSED(as); UNUSED(ir);
751
+ lua_assert(!ra_used(ir));
752
+ }
753
+
754
+ static void asm_strref(ASMState *as, IRIns *ir)
755
+ {
756
+ Reg dest = ra_dest(as, ir, RSET_GPR);
757
+ IRRef ref = ir->op2, refk = ir->op1;
758
+ int32_t ofs = (int32_t)sizeof(GCstr);
759
+ Reg r;
760
+ if (irref_isk(ref)) {
761
+ IRRef tmp = refk; refk = ref; ref = tmp;
762
+ } else if (!irref_isk(refk)) {
763
+ Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR);
764
+ IRIns *irr = IR(ir->op2);
765
+ if (ra_hasreg(irr->r)) {
766
+ ra_noweak(as, irr->r);
767
+ right = irr->r;
768
+ } else if (mayfuse(as, irr->op2) &&
769
+ irr->o == IR_ADD && irref_isk(irr->op2) &&
770
+ checki16(ofs + IR(irr->op2)->i)) {
771
+ ofs += IR(irr->op2)->i;
772
+ right = ra_alloc1(as, irr->op1, rset_exclude(RSET_GPR, left));
773
+ } else {
774
+ right = ra_allocref(as, ir->op2, rset_exclude(RSET_GPR, left));
775
+ }
776
+ emit_tsi(as, MIPSI_ADDIU, dest, dest, ofs);
777
+ emit_dst(as, MIPSI_ADDU, dest, left, right);
778
+ return;
779
+ }
780
+ r = ra_alloc1(as, ref, RSET_GPR);
781
+ ofs += IR(refk)->i;
782
+ if (checki16(ofs))
783
+ emit_tsi(as, MIPSI_ADDIU, dest, r, ofs);
784
+ else
785
+ emit_dst(as, MIPSI_ADDU, dest, r,
786
+ ra_allock(as, ofs, rset_exclude(RSET_GPR, r)));
787
+ }
788
+
789
+ /* -- Loads and stores ---------------------------------------------------- */
790
+
791
+ static MIPSIns asm_fxloadins(IRIns *ir)
792
+ {
793
+ switch (irt_type(ir->t)) {
794
+ case IRT_I8: return MIPSI_LB;
795
+ case IRT_U8: return MIPSI_LBU;
796
+ case IRT_I16: return MIPSI_LH;
797
+ case IRT_U16: return MIPSI_LHU;
798
+ case IRT_NUM: return MIPSI_LDC1;
799
+ case IRT_FLOAT: return MIPSI_LWC1;
800
+ default: return MIPSI_LW;
801
+ }
802
+ }
803
+
804
+ static MIPSIns asm_fxstoreins(IRIns *ir)
805
+ {
806
+ switch (irt_type(ir->t)) {
807
+ case IRT_I8: case IRT_U8: return MIPSI_SB;
808
+ case IRT_I16: case IRT_U16: return MIPSI_SH;
809
+ case IRT_NUM: return MIPSI_SDC1;
810
+ case IRT_FLOAT: return MIPSI_SWC1;
811
+ default: return MIPSI_SW;
812
+ }
813
+ }
814
+
815
+ static void asm_fload(ASMState *as, IRIns *ir)
816
+ {
817
+ Reg dest = ra_dest(as, ir, RSET_GPR);
818
+ Reg idx = ra_alloc1(as, ir->op1, RSET_GPR);
819
+ MIPSIns mi = asm_fxloadins(ir);
820
+ int32_t ofs;
821
+ if (ir->op2 == IRFL_TAB_ARRAY) {
822
+ ofs = asm_fuseabase(as, ir->op1);
823
+ if (ofs) { /* Turn the t->array load into an add for colocated arrays. */
824
+ emit_tsi(as, MIPSI_ADDIU, dest, idx, ofs);
825
+ return;
826
+ }
827
+ }
828
+ ofs = field_ofs[ir->op2];
829
+ lua_assert(!irt_isfp(ir->t));
830
+ emit_tsi(as, mi, dest, idx, ofs);
831
+ }
832
+
833
+ static void asm_fstore(ASMState *as, IRIns *ir)
834
+ {
835
+ if (ir->r != RID_SINK) {
836
+ Reg src = ra_alloc1z(as, ir->op2, RSET_GPR);
837
+ IRIns *irf = IR(ir->op1);
838
+ Reg idx = ra_alloc1(as, irf->op1, rset_exclude(RSET_GPR, src));
839
+ int32_t ofs = field_ofs[irf->op2];
840
+ MIPSIns mi = asm_fxstoreins(ir);
841
+ lua_assert(!irt_isfp(ir->t));
842
+ emit_tsi(as, mi, src, idx, ofs);
843
+ }
844
+ }
845
+
846
+ static void asm_xload(ASMState *as, IRIns *ir)
847
+ {
848
+ Reg dest = ra_dest(as, ir, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR);
849
+ lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED));
850
+ asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0);
851
+ }
852
+
853
+ static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
854
+ {
855
+ if (ir->r != RID_SINK) {
856
+ Reg src = ra_alloc1z(as, ir->op2, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR);
857
+ asm_fusexref(as, asm_fxstoreins(ir), src, ir->op1,
858
+ rset_exclude(RSET_GPR, src), ofs);
859
+ }
860
+ }
861
+
862
+ #define asm_xstore(as, ir) asm_xstore_(as, ir, 0)
863
+
864
+ static void asm_ahuvload(ASMState *as, IRIns *ir)
865
+ {
866
+ IRType1 t = ir->t;
867
+ Reg dest = RID_NONE, type = RID_TMP, idx;
868
+ RegSet allow = RSET_GPR;
869
+ int32_t ofs = 0;
870
+ if (ra_used(ir)) {
871
+ lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t));
872
+ dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : RSET_GPR);
873
+ rset_clear(allow, dest);
874
+ }
875
+ idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
876
+ rset_clear(allow, idx);
877
+ if (irt_isnum(t)) {
878
+ asm_guard(as, MIPSI_BEQ, type, RID_ZERO);
879
+ emit_tsi(as, MIPSI_SLTIU, type, type, (int32_t)LJ_TISNUM);
880
+ if (ra_hasreg(dest))
881
+ emit_hsi(as, MIPSI_LDC1, dest, idx, ofs);
882
+ } else {
883
+ asm_guard(as, MIPSI_BNE, type, ra_allock(as, irt_toitype(t), allow));
884
+ if (ra_hasreg(dest)) emit_tsi(as, MIPSI_LW, dest, idx, ofs+(LJ_BE?4:0));
885
+ }
886
+ emit_tsi(as, MIPSI_LW, type, idx, ofs+(LJ_BE?0:4));
887
+ }
888
+
889
+ static void asm_ahustore(ASMState *as, IRIns *ir)
890
+ {
891
+ RegSet allow = RSET_GPR;
892
+ Reg idx, src = RID_NONE, type = RID_NONE;
893
+ int32_t ofs = 0;
894
+ if (ir->r == RID_SINK)
895
+ return;
896
+ if (irt_isnum(ir->t)) {
897
+ src = ra_alloc1(as, ir->op2, RSET_FPR);
898
+ } else {
899
+ if (!irt_ispri(ir->t)) {
900
+ src = ra_alloc1(as, ir->op2, allow);
901
+ rset_clear(allow, src);
902
+ }
903
+ type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
904
+ rset_clear(allow, type);
905
+ }
906
+ idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
907
+ if (irt_isnum(ir->t)) {
908
+ emit_hsi(as, MIPSI_SDC1, src, idx, ofs);
909
+ } else {
910
+ if (ra_hasreg(src))
911
+ emit_tsi(as, MIPSI_SW, src, idx, ofs+(LJ_BE?4:0));
912
+ emit_tsi(as, MIPSI_SW, type, idx, ofs+(LJ_BE?0:4));
913
+ }
914
+ }
915
+
916
+ static void asm_sload(ASMState *as, IRIns *ir)
917
+ {
918
+ int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0);
919
+ IRType1 t = ir->t;
920
+ Reg dest = RID_NONE, type = RID_NONE, base;
921
+ RegSet allow = RSET_GPR;
922
+ lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */
923
+ lua_assert(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK));
924
+ lua_assert(!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)));
925
+ if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) {
926
+ dest = ra_scratch(as, RSET_FPR);
927
+ asm_tointg(as, ir, dest);
928
+ t.irt = IRT_NUM; /* Continue with a regular number type check. */
929
+ } else if (ra_used(ir)) {
930
+ lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t));
931
+ dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : RSET_GPR);
932
+ rset_clear(allow, dest);
933
+ base = ra_alloc1(as, REF_BASE, allow);
934
+ rset_clear(allow, base);
935
+ if ((ir->op2 & IRSLOAD_CONVERT)) {
936
+ if (irt_isint(t)) {
937
+ Reg tmp = ra_scratch(as, RSET_FPR);
938
+ emit_tg(as, MIPSI_MFC1, dest, tmp);
939
+ emit_fg(as, MIPSI_TRUNC_W_D, tmp, tmp);
940
+ dest = tmp;
941
+ t.irt = IRT_NUM; /* Check for original type. */
942
+ } else {
943
+ Reg tmp = ra_scratch(as, RSET_GPR);
944
+ emit_fg(as, MIPSI_CVT_D_W, dest, dest);
945
+ emit_tg(as, MIPSI_MTC1, tmp, dest);
946
+ dest = tmp;
947
+ t.irt = IRT_INT; /* Check for original type. */
948
+ }
949
+ }
950
+ goto dotypecheck;
951
+ }
952
+ base = ra_alloc1(as, REF_BASE, allow);
953
+ rset_clear(allow, base);
954
+ dotypecheck:
955
+ if (irt_isnum(t)) {
956
+ if ((ir->op2 & IRSLOAD_TYPECHECK)) {
957
+ asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
958
+ emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)LJ_TISNUM);
959
+ type = RID_TMP;
960
+ }
961
+ if (ra_hasreg(dest)) emit_hsi(as, MIPSI_LDC1, dest, base, ofs);
962
+ } else {
963
+ if ((ir->op2 & IRSLOAD_TYPECHECK)) {
964
+ Reg ktype = ra_allock(as, irt_toitype(t), allow);
965
+ asm_guard(as, MIPSI_BNE, RID_TMP, ktype);
966
+ type = RID_TMP;
967
+ }
968
+ if (ra_hasreg(dest)) emit_tsi(as, MIPSI_LW, dest, base, ofs ^ (LJ_BE?4:0));
969
+ }
970
+ if (ra_hasreg(type)) emit_tsi(as, MIPSI_LW, type, base, ofs ^ (LJ_BE?0:4));
971
+ }
972
+
973
+ /* -- Allocations --------------------------------------------------------- */
974
+
975
+ #if LJ_HASFFI
976
+ static void asm_cnew(ASMState *as, IRIns *ir)
977
+ {
978
+ CTState *cts = ctype_ctsG(J2G(as->J));
979
+ CTypeID id = (CTypeID)IR(ir->op1)->i;
980
+ CTSize sz;
981
+ CTInfo info = lj_ctype_info(cts, id, &sz);
982
+ const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
983
+ IRRef args[4];
984
+ RegSet drop = RSET_SCRATCH;
985
+ lua_assert(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL));
986
+
987
+ as->gcsteps++;
988
+ if (ra_hasreg(ir->r))
989
+ rset_clear(drop, ir->r); /* Dest reg handled below. */
990
+ ra_evictset(as, drop);
991
+ if (ra_used(ir))
992
+ ra_destreg(as, ir, RID_RET); /* GCcdata * */
993
+
994
+ /* Initialize immutable cdata object. */
995
+ if (ir->o == IR_CNEWI) {
996
+ RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
997
+ int32_t ofs = sizeof(GCcdata);
998
+ lua_assert(sz == 4 || sz == 8);
999
+ if (sz == 8) {
1000
+ ofs += 4;
1001
+ lua_assert((ir+1)->o == IR_HIOP);
1002
+ if (LJ_LE) ir++;
1003
+ }
1004
+ for (;;) {
1005
+ Reg r = ra_alloc1z(as, ir->op2, allow);
1006
+ emit_tsi(as, MIPSI_SW, r, RID_RET, ofs);
1007
+ rset_clear(allow, r);
1008
+ if (ofs == sizeof(GCcdata)) break;
1009
+ ofs -= 4; if (LJ_BE) ir++; else ir--;
1010
+ }
1011
+ } else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
1012
+ ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
1013
+ args[0] = ASMREF_L; /* lua_State *L */
1014
+ args[1] = ir->op1; /* CTypeID id */
1015
+ args[2] = ir->op2; /* CTSize sz */
1016
+ args[3] = ASMREF_TMP1; /* CTSize align */
1017
+ asm_gencall(as, ci, args);
1018
+ emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)ctype_align(info));
1019
+ return;
1020
+ }
1021
+
1022
+ /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
1023
+ emit_tsi(as, MIPSI_SB, RID_RET+1, RID_RET, offsetof(GCcdata, gct));
1024
+ emit_tsi(as, MIPSI_SH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid));
1025
+ emit_ti(as, MIPSI_LI, RID_RET+1, ~LJ_TCDATA);
1026
+ emit_ti(as, MIPSI_LI, RID_TMP, id); /* Lower 16 bit used. Sign-ext ok. */
1027
+ args[0] = ASMREF_L; /* lua_State *L */
1028
+ args[1] = ASMREF_TMP1; /* MSize size */
1029
+ asm_gencall(as, ci, args);
1030
+ ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
1031
+ ra_releasetmp(as, ASMREF_TMP1));
1032
+ }
1033
+ #else
1034
+ #define asm_cnew(as, ir) ((void)0)
1035
+ #endif
1036
+
1037
+ /* -- Write barriers ------------------------------------------------------ */
1038
+
1039
+ static void asm_tbar(ASMState *as, IRIns *ir)
1040
+ {
1041
+ Reg tab = ra_alloc1(as, ir->op1, RSET_GPR);
1042
+ Reg mark = ra_scratch(as, rset_exclude(RSET_GPR, tab));
1043
+ Reg link = RID_TMP;
1044
+ MCLabel l_end = emit_label(as);
1045
+ emit_tsi(as, MIPSI_SW, link, tab, (int32_t)offsetof(GCtab, gclist));
1046
+ emit_tsi(as, MIPSI_SB, mark, tab, (int32_t)offsetof(GCtab, marked));
1047
+ emit_setgl(as, tab, gc.grayagain);
1048
+ emit_getgl(as, link, gc.grayagain);
1049
+ emit_dst(as, MIPSI_XOR, mark, mark, RID_TMP); /* Clear black bit. */
1050
+ emit_branch(as, MIPSI_BEQ, RID_TMP, RID_ZERO, l_end);
1051
+ emit_tsi(as, MIPSI_ANDI, RID_TMP, mark, LJ_GC_BLACK);
1052
+ emit_tsi(as, MIPSI_LBU, mark, tab, (int32_t)offsetof(GCtab, marked));
1053
+ }
1054
+
1055
+ static void asm_obar(ASMState *as, IRIns *ir)
1056
+ {
1057
+ const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_barrieruv];
1058
+ IRRef args[2];
1059
+ MCLabel l_end;
1060
+ Reg obj, val, tmp;
1061
+ /* No need for other object barriers (yet). */
1062
+ lua_assert(IR(ir->op1)->o == IR_UREFC);
1063
+ ra_evictset(as, RSET_SCRATCH);
1064
+ l_end = emit_label(as);
1065
+ args[0] = ASMREF_TMP1; /* global_State *g */
1066
+ args[1] = ir->op1; /* TValue *tv */
1067
+ asm_gencall(as, ci, args);
1068
+ emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768);
1069
+ obj = IR(ir->op1)->r;
1070
+ tmp = ra_scratch(as, rset_exclude(RSET_GPR, obj));
1071
+ emit_branch(as, MIPSI_BEQ, RID_TMP, RID_ZERO, l_end);
1072
+ emit_tsi(as, MIPSI_ANDI, tmp, tmp, LJ_GC_BLACK);
1073
+ emit_branch(as, MIPSI_BEQ, RID_TMP, RID_ZERO, l_end);
1074
+ emit_tsi(as, MIPSI_ANDI, RID_TMP, RID_TMP, LJ_GC_WHITES);
1075
+ val = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, obj));
1076
+ emit_tsi(as, MIPSI_LBU, tmp, obj,
1077
+ (int32_t)offsetof(GCupval, marked)-(int32_t)offsetof(GCupval, tv));
1078
+ emit_tsi(as, MIPSI_LBU, RID_TMP, val, (int32_t)offsetof(GChead, marked));
1079
+ }
1080
+
1081
+ /* -- Arithmetic and logic operations ------------------------------------- */
1082
+
1083
+ static void asm_fparith(ASMState *as, IRIns *ir, MIPSIns mi)
1084
+ {
1085
+ Reg dest = ra_dest(as, ir, RSET_FPR);
1086
+ Reg right, left = ra_alloc2(as, ir, RSET_FPR);
1087
+ right = (left >> 8); left &= 255;
1088
+ emit_fgh(as, mi, dest, left, right);
1089
+ }
1090
+
1091
+ static void asm_fpunary(ASMState *as, IRIns *ir, MIPSIns mi)
1092
+ {
1093
+ Reg dest = ra_dest(as, ir, RSET_FPR);
1094
+ Reg left = ra_hintalloc(as, ir->op1, dest, RSET_FPR);
1095
+ emit_fg(as, mi, dest, left);
1096
+ }
1097
+
1098
+ static void asm_fpmath(ASMState *as, IRIns *ir)
1099
+ {
1100
+ if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir))
1101
+ return;
1102
+ if (ir->op2 <= IRFPM_TRUNC)
1103
+ asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2);
1104
+ else if (ir->op2 == IRFPM_SQRT)
1105
+ asm_fpunary(as, ir, MIPSI_SQRT_D);
1106
+ else
1107
+ asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2);
1108
+ }
1109
+
1110
+ static void asm_add(ASMState *as, IRIns *ir)
1111
+ {
1112
+ if (irt_isnum(ir->t)) {
1113
+ asm_fparith(as, ir, MIPSI_ADD_D);
1114
+ } else {
1115
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1116
+ Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
1117
+ if (irref_isk(ir->op2)) {
1118
+ int32_t k = IR(ir->op2)->i;
1119
+ if (checki16(k)) {
1120
+ emit_tsi(as, MIPSI_ADDIU, dest, left, k);
1121
+ return;
1122
+ }
1123
+ }
1124
+ right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left));
1125
+ emit_dst(as, MIPSI_ADDU, dest, left, right);
1126
+ }
1127
+ }
1128
+
1129
+ static void asm_sub(ASMState *as, IRIns *ir)
1130
+ {
1131
+ if (irt_isnum(ir->t)) {
1132
+ asm_fparith(as, ir, MIPSI_SUB_D);
1133
+ } else {
1134
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1135
+ Reg right, left = ra_alloc2(as, ir, RSET_GPR);
1136
+ right = (left >> 8); left &= 255;
1137
+ emit_dst(as, MIPSI_SUBU, dest, left, right);
1138
+ }
1139
+ }
1140
+
1141
+ static void asm_mul(ASMState *as, IRIns *ir)
1142
+ {
1143
+ if (irt_isnum(ir->t)) {
1144
+ asm_fparith(as, ir, MIPSI_MUL_D);
1145
+ } else {
1146
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1147
+ Reg right, left = ra_alloc2(as, ir, RSET_GPR);
1148
+ right = (left >> 8); left &= 255;
1149
+ emit_dst(as, MIPSI_MUL, dest, left, right);
1150
+ }
1151
+ }
1152
+
1153
+ #define asm_div(as, ir) asm_fparith(as, ir, MIPSI_DIV_D)
1154
+ #define asm_mod(as, ir) asm_callid(as, ir, IRCALL_lj_vm_modi)
1155
+ #define asm_pow(as, ir) asm_callid(as, ir, IRCALL_lj_vm_powi)
1156
+
1157
+ static void asm_neg(ASMState *as, IRIns *ir)
1158
+ {
1159
+ if (irt_isnum(ir->t)) {
1160
+ asm_fpunary(as, ir, MIPSI_NEG_D);
1161
+ } else {
1162
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1163
+ Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
1164
+ emit_dst(as, MIPSI_SUBU, dest, RID_ZERO, left);
1165
+ }
1166
+ }
1167
+
1168
+ #define asm_abs(as, ir) asm_fpunary(as, ir, MIPSI_ABS_D)
1169
+ #define asm_atan2(as, ir) asm_callid(as, ir, IRCALL_atan2)
1170
+ #define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp)
1171
+
1172
+ static void asm_arithov(ASMState *as, IRIns *ir)
1173
+ {
1174
+ Reg right, left, tmp, dest = ra_dest(as, ir, RSET_GPR);
1175
+ if (irref_isk(ir->op2)) {
1176
+ int k = IR(ir->op2)->i;
1177
+ if (ir->o == IR_SUBOV) k = -k;
1178
+ if (checki16(k)) { /* (dest < left) == (k >= 0 ? 1 : 0) */
1179
+ left = ra_alloc1(as, ir->op1, RSET_GPR);
1180
+ asm_guard(as, k >= 0 ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO);
1181
+ emit_dst(as, MIPSI_SLT, RID_TMP, dest, dest == left ? RID_TMP : left);
1182
+ emit_tsi(as, MIPSI_ADDIU, dest, left, k);
1183
+ if (dest == left) emit_move(as, RID_TMP, left);
1184
+ return;
1185
+ }
1186
+ }
1187
+ left = ra_alloc2(as, ir, RSET_GPR);
1188
+ right = (left >> 8); left &= 255;
1189
+ tmp = ra_scratch(as, rset_exclude(rset_exclude(rset_exclude(RSET_GPR, left),
1190
+ right), dest));
1191
+ asm_guard(as, MIPSI_BLTZ, RID_TMP, 0);
1192
+ emit_dst(as, MIPSI_AND, RID_TMP, RID_TMP, tmp);
1193
+ if (ir->o == IR_ADDOV) { /* ((dest^left) & (dest^right)) < 0 */
1194
+ emit_dst(as, MIPSI_XOR, RID_TMP, dest, dest == right ? RID_TMP : right);
1195
+ } else { /* ((dest^left) & (dest^~right)) < 0 */
1196
+ emit_dst(as, MIPSI_XOR, RID_TMP, RID_TMP, dest);
1197
+ emit_dst(as, MIPSI_NOR, RID_TMP, dest == right ? RID_TMP : right, RID_ZERO);
1198
+ }
1199
+ emit_dst(as, MIPSI_XOR, tmp, dest, dest == left ? RID_TMP : left);
1200
+ emit_dst(as, ir->o == IR_ADDOV ? MIPSI_ADDU : MIPSI_SUBU, dest, left, right);
1201
+ if (dest == left || dest == right)
1202
+ emit_move(as, RID_TMP, dest == left ? left : right);
1203
+ }
1204
+
1205
+ #define asm_addov(as, ir) asm_arithov(as, ir)
1206
+ #define asm_subov(as, ir) asm_arithov(as, ir)
1207
+
1208
+ static void asm_mulov(ASMState *as, IRIns *ir)
1209
+ {
1210
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1211
+ Reg tmp, right, left = ra_alloc2(as, ir, RSET_GPR);
1212
+ right = (left >> 8); left &= 255;
1213
+ tmp = ra_scratch(as, rset_exclude(rset_exclude(rset_exclude(RSET_GPR, left),
1214
+ right), dest));
1215
+ asm_guard(as, MIPSI_BNE, RID_TMP, tmp);
1216
+ emit_dta(as, MIPSI_SRA, RID_TMP, dest, 31);
1217
+ emit_dst(as, MIPSI_MFHI, tmp, 0, 0);
1218
+ emit_dst(as, MIPSI_MFLO, dest, 0, 0);
1219
+ emit_dst(as, MIPSI_MULT, 0, left, right);
1220
+ }
1221
+
1222
+ #if LJ_HASFFI
1223
+ static void asm_add64(ASMState *as, IRIns *ir)
1224
+ {
1225
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1226
+ Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR);
1227
+ if (irref_isk(ir->op2)) {
1228
+ int32_t k = IR(ir->op2)->i;
1229
+ if (k == 0) {
1230
+ emit_dst(as, MIPSI_ADDU, dest, left, RID_TMP);
1231
+ goto loarith;
1232
+ } else if (checki16(k)) {
1233
+ emit_dst(as, MIPSI_ADDU, dest, dest, RID_TMP);
1234
+ emit_tsi(as, MIPSI_ADDIU, dest, left, k);
1235
+ goto loarith;
1236
+ }
1237
+ }
1238
+ emit_dst(as, MIPSI_ADDU, dest, dest, RID_TMP);
1239
+ right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left));
1240
+ emit_dst(as, MIPSI_ADDU, dest, left, right);
1241
+ loarith:
1242
+ ir--;
1243
+ dest = ra_dest(as, ir, RSET_GPR);
1244
+ left = ra_alloc1(as, ir->op1, RSET_GPR);
1245
+ if (irref_isk(ir->op2)) {
1246
+ int32_t k = IR(ir->op2)->i;
1247
+ if (k == 0) {
1248
+ if (dest != left)
1249
+ emit_move(as, dest, left);
1250
+ return;
1251
+ } else if (checki16(k)) {
1252
+ if (dest == left) {
1253
+ Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, left));
1254
+ emit_move(as, dest, tmp);
1255
+ dest = tmp;
1256
+ }
1257
+ emit_dst(as, MIPSI_SLTU, RID_TMP, dest, left);
1258
+ emit_tsi(as, MIPSI_ADDIU, dest, left, k);
1259
+ return;
1260
+ }
1261
+ }
1262
+ right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left));
1263
+ if (dest == left && dest == right) {
1264
+ Reg tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_GPR, left), right));
1265
+ emit_move(as, dest, tmp);
1266
+ dest = tmp;
1267
+ }
1268
+ emit_dst(as, MIPSI_SLTU, RID_TMP, dest, dest == left ? right : left);
1269
+ emit_dst(as, MIPSI_ADDU, dest, left, right);
1270
+ }
1271
+
1272
+ static void asm_sub64(ASMState *as, IRIns *ir)
1273
+ {
1274
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1275
+ Reg right, left = ra_alloc2(as, ir, RSET_GPR);
1276
+ right = (left >> 8); left &= 255;
1277
+ emit_dst(as, MIPSI_SUBU, dest, dest, RID_TMP);
1278
+ emit_dst(as, MIPSI_SUBU, dest, left, right);
1279
+ ir--;
1280
+ dest = ra_dest(as, ir, RSET_GPR);
1281
+ left = ra_alloc2(as, ir, RSET_GPR);
1282
+ right = (left >> 8); left &= 255;
1283
+ if (dest == left) {
1284
+ Reg tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_GPR, left), right));
1285
+ emit_move(as, dest, tmp);
1286
+ dest = tmp;
1287
+ }
1288
+ emit_dst(as, MIPSI_SLTU, RID_TMP, left, dest);
1289
+ emit_dst(as, MIPSI_SUBU, dest, left, right);
1290
+ }
1291
+
1292
+ static void asm_neg64(ASMState *as, IRIns *ir)
1293
+ {
1294
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1295
+ Reg left = ra_alloc1(as, ir->op1, RSET_GPR);
1296
+ emit_dst(as, MIPSI_SUBU, dest, dest, RID_TMP);
1297
+ emit_dst(as, MIPSI_SUBU, dest, RID_ZERO, left);
1298
+ ir--;
1299
+ dest = ra_dest(as, ir, RSET_GPR);
1300
+ left = ra_alloc1(as, ir->op1, RSET_GPR);
1301
+ emit_dst(as, MIPSI_SLTU, RID_TMP, RID_ZERO, dest);
1302
+ emit_dst(as, MIPSI_SUBU, dest, RID_ZERO, left);
1303
+ }
1304
+ #endif
1305
+
1306
+ static void asm_bnot(ASMState *as, IRIns *ir)
1307
+ {
1308
+ Reg left, right, dest = ra_dest(as, ir, RSET_GPR);
1309
+ IRIns *irl = IR(ir->op1);
1310
+ if (mayfuse(as, ir->op1) && irl->o == IR_BOR) {
1311
+ left = ra_alloc2(as, irl, RSET_GPR);
1312
+ right = (left >> 8); left &= 255;
1313
+ } else {
1314
+ left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
1315
+ right = RID_ZERO;
1316
+ }
1317
+ emit_dst(as, MIPSI_NOR, dest, left, right);
1318
+ }
1319
+
1320
+ static void asm_bswap(ASMState *as, IRIns *ir)
1321
+ {
1322
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1323
+ Reg left = ra_alloc1(as, ir->op1, RSET_GPR);
1324
+ if ((as->flags & JIT_F_MIPS32R2)) {
1325
+ emit_dta(as, MIPSI_ROTR, dest, RID_TMP, 16);
1326
+ emit_dst(as, MIPSI_WSBH, RID_TMP, 0, left);
1327
+ } else {
1328
+ Reg tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_GPR, left), dest));
1329
+ emit_dst(as, MIPSI_OR, dest, dest, tmp);
1330
+ emit_dst(as, MIPSI_OR, dest, dest, RID_TMP);
1331
+ emit_tsi(as, MIPSI_ANDI, dest, dest, 0xff00);
1332
+ emit_dta(as, MIPSI_SLL, RID_TMP, RID_TMP, 8);
1333
+ emit_dta(as, MIPSI_SRL, dest, left, 8);
1334
+ emit_tsi(as, MIPSI_ANDI, RID_TMP, left, 0xff00);
1335
+ emit_dst(as, MIPSI_OR, tmp, tmp, RID_TMP);
1336
+ emit_dta(as, MIPSI_SRL, tmp, left, 24);
1337
+ emit_dta(as, MIPSI_SLL, RID_TMP, left, 24);
1338
+ }
1339
+ }
1340
+
1341
+ static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik)
1342
+ {
1343
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1344
+ Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
1345
+ if (irref_isk(ir->op2)) {
1346
+ int32_t k = IR(ir->op2)->i;
1347
+ if (checku16(k)) {
1348
+ emit_tsi(as, mik, dest, left, k);
1349
+ return;
1350
+ }
1351
+ }
1352
+ right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left));
1353
+ emit_dst(as, mi, dest, left, right);
1354
+ }
1355
+
1356
+ #define asm_band(as, ir) asm_bitop(as, ir, MIPSI_AND, MIPSI_ANDI)
1357
+ #define asm_bor(as, ir) asm_bitop(as, ir, MIPSI_OR, MIPSI_ORI)
1358
+ #define asm_bxor(as, ir) asm_bitop(as, ir, MIPSI_XOR, MIPSI_XORI)
1359
+
1360
+ static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik)
1361
+ {
1362
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1363
+ if (irref_isk(ir->op2)) { /* Constant shifts. */
1364
+ uint32_t shift = (uint32_t)(IR(ir->op2)->i & 31);
1365
+ emit_dta(as, mik, dest, ra_hintalloc(as, ir->op1, dest, RSET_GPR), shift);
1366
+ } else {
1367
+ Reg right, left = ra_alloc2(as, ir, RSET_GPR);
1368
+ right = (left >> 8); left &= 255;
1369
+ emit_dst(as, mi, dest, right, left); /* Shift amount is in rs. */
1370
+ }
1371
+ }
1372
+
1373
+ #define asm_bshl(as, ir) asm_bitshift(as, ir, MIPSI_SLLV, MIPSI_SLL)
1374
+ #define asm_bshr(as, ir) asm_bitshift(as, ir, MIPSI_SRLV, MIPSI_SRL)
1375
+ #define asm_bsar(as, ir) asm_bitshift(as, ir, MIPSI_SRAV, MIPSI_SRA)
1376
+ #define asm_brol(as, ir) lua_assert(0)
1377
+
1378
+ static void asm_bror(ASMState *as, IRIns *ir)
1379
+ {
1380
+ if ((as->flags & JIT_F_MIPS32R2)) {
1381
+ asm_bitshift(as, ir, MIPSI_ROTRV, MIPSI_ROTR);
1382
+ } else {
1383
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1384
+ if (irref_isk(ir->op2)) { /* Constant shifts. */
1385
+ uint32_t shift = (uint32_t)(IR(ir->op2)->i & 31);
1386
+ Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
1387
+ emit_rotr(as, dest, left, RID_TMP, shift);
1388
+ } else {
1389
+ Reg right, left = ra_alloc2(as, ir, RSET_GPR);
1390
+ right = (left >> 8); left &= 255;
1391
+ emit_dst(as, MIPSI_OR, dest, dest, RID_TMP);
1392
+ emit_dst(as, MIPSI_SRLV, dest, right, left);
1393
+ emit_dst(as, MIPSI_SLLV, RID_TMP, RID_TMP, left);
1394
+ emit_dst(as, MIPSI_SUBU, RID_TMP, ra_allock(as, 32, RSET_GPR), right);
1395
+ }
1396
+ }
1397
+ }
1398
+
1399
+ static void asm_min_max(ASMState *as, IRIns *ir, int ismax)
1400
+ {
1401
+ if (irt_isnum(ir->t)) {
1402
+ Reg dest = ra_dest(as, ir, RSET_FPR);
1403
+ Reg right, left = ra_alloc2(as, ir, RSET_FPR);
1404
+ right = (left >> 8); left &= 255;
1405
+ if (dest == left) {
1406
+ emit_fg(as, MIPSI_MOVT_D, dest, right);
1407
+ } else {
1408
+ emit_fg(as, MIPSI_MOVF_D, dest, left);
1409
+ if (dest != right) emit_fg(as, MIPSI_MOV_D, dest, right);
1410
+ }
1411
+ emit_fgh(as, MIPSI_C_OLT_D, 0, ismax ? left : right, ismax ? right : left);
1412
+ } else {
1413
+ Reg dest = ra_dest(as, ir, RSET_GPR);
1414
+ Reg right, left = ra_alloc2(as, ir, RSET_GPR);
1415
+ right = (left >> 8); left &= 255;
1416
+ if (dest == left) {
1417
+ emit_dst(as, MIPSI_MOVN, dest, right, RID_TMP);
1418
+ } else {
1419
+ emit_dst(as, MIPSI_MOVZ, dest, left, RID_TMP);
1420
+ if (dest != right) emit_move(as, dest, right);
1421
+ }
1422
+ emit_dst(as, MIPSI_SLT, RID_TMP,
1423
+ ismax ? left : right, ismax ? right : left);
1424
+ }
1425
+ }
1426
+
1427
+ #define asm_min(as, ir) asm_min_max(as, ir, 0)
1428
+ #define asm_max(as, ir) asm_min_max(as, ir, 1)
1429
+
1430
+ /* -- Comparisons --------------------------------------------------------- */
1431
+
1432
+ static void asm_comp(ASMState *as, IRIns *ir)
1433
+ {
1434
+ /* ORDER IR: LT GE LE GT ULT UGE ULE UGT. */
1435
+ IROp op = ir->o;
1436
+ if (irt_isnum(ir->t)) {
1437
+ Reg right, left = ra_alloc2(as, ir, RSET_FPR);
1438
+ right = (left >> 8); left &= 255;
1439
+ asm_guard(as, (op&1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
1440
+ emit_fgh(as, MIPSI_C_OLT_D + ((op&3) ^ ((op>>2)&1)), 0, left, right);
1441
+ } else {
1442
+ Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR);
1443
+ if (op == IR_ABC) op = IR_UGT;
1444
+ if ((op&4) == 0 && irref_isk(ir->op2) && IR(ir->op2)->i == 0) {
1445
+ MIPSIns mi = (op&2) ? ((op&1) ? MIPSI_BLEZ : MIPSI_BGTZ) :
1446
+ ((op&1) ? MIPSI_BLTZ : MIPSI_BGEZ);
1447
+ asm_guard(as, mi, left, 0);
1448
+ } else {
1449
+ if (irref_isk(ir->op2)) {
1450
+ int32_t k = IR(ir->op2)->i;
1451
+ if ((op&2)) k++;
1452
+ if (checki16(k)) {
1453
+ asm_guard(as, (op&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO);
1454
+ emit_tsi(as, (op&4) ? MIPSI_SLTIU : MIPSI_SLTI,
1455
+ RID_TMP, left, k);
1456
+ return;
1457
+ }
1458
+ }
1459
+ right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left));
1460
+ asm_guard(as, ((op^(op>>1))&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO);
1461
+ emit_dst(as, (op&4) ? MIPSI_SLTU : MIPSI_SLT,
1462
+ RID_TMP, (op&2) ? right : left, (op&2) ? left : right);
1463
+ }
1464
+ }
1465
+ }
1466
+
1467
+ static void asm_equal(ASMState *as, IRIns *ir)
1468
+ {
1469
+ Reg right, left = ra_alloc2(as, ir, irt_isnum(ir->t) ? RSET_FPR : RSET_GPR);
1470
+ right = (left >> 8); left &= 255;
1471
+ if (irt_isnum(ir->t)) {
1472
+ asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
1473
+ emit_fgh(as, MIPSI_C_EQ_D, 0, left, right);
1474
+ } else {
1475
+ asm_guard(as, (ir->o & 1) ? MIPSI_BEQ : MIPSI_BNE, left, right);
1476
+ }
1477
+ }
1478
+
1479
+ #if LJ_HASFFI
1480
+ /* 64 bit integer comparisons. */
1481
+ static void asm_comp64(ASMState *as, IRIns *ir)
1482
+ {
1483
+ /* ORDER IR: LT GE LE GT ULT UGE ULE UGT. */
1484
+ IROp op = (ir-1)->o;
1485
+ MCLabel l_end;
1486
+ Reg rightlo, leftlo, righthi, lefthi = ra_alloc2(as, ir, RSET_GPR);
1487
+ righthi = (lefthi >> 8); lefthi &= 255;
1488
+ leftlo = ra_alloc2(as, ir-1,
1489
+ rset_exclude(rset_exclude(RSET_GPR, lefthi), righthi));
1490
+ rightlo = (leftlo >> 8); leftlo &= 255;
1491
+ asm_guard(as, ((op^(op>>1))&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO);
1492
+ l_end = emit_label(as);
1493
+ if (lefthi != righthi)
1494
+ emit_dst(as, (op&4) ? MIPSI_SLTU : MIPSI_SLT, RID_TMP,
1495
+ (op&2) ? righthi : lefthi, (op&2) ? lefthi : righthi);
1496
+ emit_dst(as, MIPSI_SLTU, RID_TMP,
1497
+ (op&2) ? rightlo : leftlo, (op&2) ? leftlo : rightlo);
1498
+ if (lefthi != righthi)
1499
+ emit_branch(as, MIPSI_BEQ, lefthi, righthi, l_end);
1500
+ }
1501
+
1502
+ static void asm_comp64eq(ASMState *as, IRIns *ir)
1503
+ {
1504
+ Reg tmp, right, left = ra_alloc2(as, ir, RSET_GPR);
1505
+ right = (left >> 8); left &= 255;
1506
+ asm_guard(as, ((ir-1)->o & 1) ? MIPSI_BEQ : MIPSI_BNE, RID_TMP, RID_ZERO);
1507
+ tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_GPR, left), right));
1508
+ emit_dst(as, MIPSI_OR, RID_TMP, RID_TMP, tmp);
1509
+ emit_dst(as, MIPSI_XOR, tmp, left, right);
1510
+ left = ra_alloc2(as, ir-1, RSET_GPR);
1511
+ right = (left >> 8); left &= 255;
1512
+ emit_dst(as, MIPSI_XOR, RID_TMP, left, right);
1513
+ }
1514
+ #endif
1515
+
1516
+ /* -- Support for 64 bit ops in 32 bit mode ------------------------------- */
1517
+
1518
+ /* Hiword op of a split 64 bit op. Previous op must be the loword op. */
1519
+ static void asm_hiop(ASMState *as, IRIns *ir)
1520
+ {
1521
+ #if LJ_HASFFI
1522
+ /* HIOP is marked as a store because it needs its own DCE logic. */
1523
+ int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
1524
+ if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
1525
+ if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
1526
+ as->curins--; /* Always skip the CONV. */
1527
+ if (usehi || uselo)
1528
+ asm_conv64(as, ir);
1529
+ return;
1530
+ } else if ((ir-1)->o < IR_EQ) { /* 64 bit integer comparisons. ORDER IR. */
1531
+ as->curins--; /* Always skip the loword comparison. */
1532
+ asm_comp64(as, ir);
1533
+ return;
1534
+ } else if ((ir-1)->o <= IR_NE) { /* 64 bit integer comparisons. ORDER IR. */
1535
+ as->curins--; /* Always skip the loword comparison. */
1536
+ asm_comp64eq(as, ir);
1537
+ return;
1538
+ } else if ((ir-1)->o == IR_XSTORE) {
1539
+ as->curins--; /* Handle both stores here. */
1540
+ if ((ir-1)->r != RID_SINK) {
1541
+ asm_xstore_(as, ir, LJ_LE ? 4 : 0);
1542
+ asm_xstore_(as, ir-1, LJ_LE ? 0 : 4);
1543
+ }
1544
+ return;
1545
+ }
1546
+ if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
1547
+ switch ((ir-1)->o) {
1548
+ case IR_ADD: as->curins--; asm_add64(as, ir); break;
1549
+ case IR_SUB: as->curins--; asm_sub64(as, ir); break;
1550
+ case IR_NEG: as->curins--; asm_neg64(as, ir); break;
1551
+ case IR_CALLN:
1552
+ case IR_CALLXS:
1553
+ if (!uselo)
1554
+ ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
1555
+ break;
1556
+ case IR_CNEWI:
1557
+ /* Nothing to do here. Handled by lo op itself. */
1558
+ break;
1559
+ default: lua_assert(0); break;
1560
+ }
1561
+ #else
1562
+ UNUSED(as); UNUSED(ir); lua_assert(0); /* Unused without FFI. */
1563
+ #endif
1564
+ }
1565
+
1566
+ /* -- Profiling ----------------------------------------------------------- */
1567
+
1568
+ static void asm_prof(ASMState *as, IRIns *ir)
1569
+ {
1570
+ UNUSED(ir);
1571
+ asm_guard(as, MIPSI_BNE, RID_TMP, RID_ZERO);
1572
+ emit_tsi(as, MIPSI_ANDI, RID_TMP, RID_TMP, HOOK_PROFILE);
1573
+ emit_lsglptr(as, MIPSI_LBU, RID_TMP,
1574
+ (int32_t)offsetof(global_State, hookmask));
1575
+ }
1576
+
1577
+ /* -- Stack handling ------------------------------------------------------ */
1578
+
1579
+ /* Check Lua stack size for overflow. Use exit handler as fallback. */
1580
+ static void asm_stack_check(ASMState *as, BCReg topslot,
1581
+ IRIns *irp, RegSet allow, ExitNo exitno)
1582
+ {
1583
+ /* Try to get an unused temp. register, otherwise spill/restore RID_RET*. */
1584
+ Reg tmp, pbase = irp ? (ra_hasreg(irp->r) ? irp->r : RID_TMP) : RID_BASE;
1585
+ ExitNo oldsnap = as->snapno;
1586
+ rset_clear(allow, pbase);
1587
+ tmp = allow ? rset_pickbot(allow) :
1588
+ (pbase == RID_RETHI ? RID_RETLO : RID_RETHI);
1589
+ as->snapno = exitno;
1590
+ asm_guard(as, MIPSI_BNE, RID_TMP, RID_ZERO);
1591
+ as->snapno = oldsnap;
1592
+ if (allow == RSET_EMPTY) /* Restore temp. register. */
1593
+ emit_tsi(as, MIPSI_LW, tmp, RID_SP, 0);
1594
+ else
1595
+ ra_modified(as, tmp);
1596
+ emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)(8*topslot));
1597
+ emit_dst(as, MIPSI_SUBU, RID_TMP, tmp, pbase);
1598
+ emit_tsi(as, MIPSI_LW, tmp, tmp, offsetof(lua_State, maxstack));
1599
+ if (pbase == RID_TMP)
1600
+ emit_getgl(as, RID_TMP, jit_base);
1601
+ emit_getgl(as, tmp, cur_L);
1602
+ if (allow == RSET_EMPTY) /* Spill temp. register. */
1603
+ emit_tsi(as, MIPSI_SW, tmp, RID_SP, 0);
1604
+ }
1605
+
1606
+ /* Restore Lua stack from on-trace state. */
1607
+ static void asm_stack_restore(ASMState *as, SnapShot *snap)
1608
+ {
1609
+ SnapEntry *map = &as->T->snapmap[snap->mapofs];
1610
+ SnapEntry *flinks = &as->T->snapmap[snap_nextofs(as->T, snap)-1];
1611
+ MSize n, nent = snap->nent;
1612
+ /* Store the value of all modified slots to the Lua stack. */
1613
+ for (n = 0; n < nent; n++) {
1614
+ SnapEntry sn = map[n];
1615
+ BCReg s = snap_slot(sn);
1616
+ int32_t ofs = 8*((int32_t)s-1);
1617
+ IRRef ref = snap_ref(sn);
1618
+ IRIns *ir = IR(ref);
1619
+ if ((sn & SNAP_NORESTORE))
1620
+ continue;
1621
+ if (irt_isnum(ir->t)) {
1622
+ Reg src = ra_alloc1(as, ref, RSET_FPR);
1623
+ emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs);
1624
+ } else {
1625
+ Reg type;
1626
+ RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
1627
+ lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t) || irt_isinteger(ir->t));
1628
+ if (!irt_ispri(ir->t)) {
1629
+ Reg src = ra_alloc1(as, ref, allow);
1630
+ rset_clear(allow, src);
1631
+ emit_tsi(as, MIPSI_SW, src, RID_BASE, ofs+(LJ_BE?4:0));
1632
+ }
1633
+ if ((sn & (SNAP_CONT|SNAP_FRAME))) {
1634
+ if (s == 0) continue; /* Do not overwrite link to previous frame. */
1635
+ type = ra_allock(as, (int32_t)(*flinks--), allow);
1636
+ } else {
1637
+ type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
1638
+ }
1639
+ emit_tsi(as, MIPSI_SW, type, RID_BASE, ofs+(LJ_BE?0:4));
1640
+ }
1641
+ checkmclim(as);
1642
+ }
1643
+ lua_assert(map + nent == flinks);
1644
+ }
1645
+
1646
+ /* -- GC handling --------------------------------------------------------- */
1647
+
1648
+ /* Check GC threshold and do one or more GC steps. */
1649
+ static void asm_gc_check(ASMState *as)
1650
+ {
1651
+ const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_step_jit];
1652
+ IRRef args[2];
1653
+ MCLabel l_end;
1654
+ Reg tmp;
1655
+ ra_evictset(as, RSET_SCRATCH);
1656
+ l_end = emit_label(as);
1657
+ /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
1658
+ /* Assumes asm_snap_prep() already done. */
1659
+ asm_guard(as, MIPSI_BNE, RID_RET, RID_ZERO);
1660
+ args[0] = ASMREF_TMP1; /* global_State *g */
1661
+ args[1] = ASMREF_TMP2; /* MSize steps */
1662
+ asm_gencall(as, ci, args);
1663
+ emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768);
1664
+ tmp = ra_releasetmp(as, ASMREF_TMP2);
1665
+ emit_loadi(as, tmp, as->gcsteps);
1666
+ /* Jump around GC step if GC total < GC threshold. */
1667
+ emit_branch(as, MIPSI_BNE, RID_TMP, RID_ZERO, l_end);
1668
+ emit_dst(as, MIPSI_SLTU, RID_TMP, RID_TMP, tmp);
1669
+ emit_getgl(as, tmp, gc.threshold);
1670
+ emit_getgl(as, RID_TMP, gc.total);
1671
+ as->gcsteps = 0;
1672
+ checkmclim(as);
1673
+ }
1674
+
1675
+ /* -- Loop handling ------------------------------------------------------- */
1676
+
1677
+ /* Fixup the loop branch. */
1678
+ static void asm_loop_fixup(ASMState *as)
1679
+ {
1680
+ MCode *p = as->mctop;
1681
+ MCode *target = as->mcp;
1682
+ p[-1] = MIPSI_NOP;
1683
+ if (as->loopinv) { /* Inverted loop branch? */
1684
+ /* asm_guard already inverted the cond branch. Only patch the target. */
1685
+ p[-3] |= ((target-p+2) & 0x0000ffffu);
1686
+ } else {
1687
+ p[-2] = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu);
1688
+ }
1689
+ }
1690
+
1691
+ /* -- Head of trace ------------------------------------------------------- */
1692
+
1693
+ /* Coalesce BASE register for a root trace. */
1694
+ static void asm_head_root_base(ASMState *as)
1695
+ {
1696
+ IRIns *ir = IR(REF_BASE);
1697
+ Reg r = ir->r;
1698
+ if (as->loopinv) as->mctop--;
1699
+ if (ra_hasreg(r)) {
1700
+ ra_free(as, r);
1701
+ if (rset_test(as->modset, r) || irt_ismarked(ir->t))
1702
+ ir->r = RID_INIT; /* No inheritance for modified BASE register. */
1703
+ if (r != RID_BASE)
1704
+ emit_move(as, r, RID_BASE);
1705
+ }
1706
+ }
1707
+
1708
+ /* Coalesce BASE register for a side trace. */
1709
+ static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
1710
+ {
1711
+ IRIns *ir = IR(REF_BASE);
1712
+ Reg r = ir->r;
1713
+ if (as->loopinv) as->mctop--;
1714
+ if (ra_hasreg(r)) {
1715
+ ra_free(as, r);
1716
+ if (rset_test(as->modset, r) || irt_ismarked(ir->t))
1717
+ ir->r = RID_INIT; /* No inheritance for modified BASE register. */
1718
+ if (irp->r == r) {
1719
+ rset_clear(allow, r); /* Mark same BASE register as coalesced. */
1720
+ } else if (ra_hasreg(irp->r) && rset_test(as->freeset, irp->r)) {
1721
+ rset_clear(allow, irp->r);
1722
+ emit_move(as, r, irp->r); /* Move from coalesced parent reg. */
1723
+ } else {
1724
+ emit_getgl(as, r, jit_base); /* Otherwise reload BASE. */
1725
+ }
1726
+ }
1727
+ return allow;
1728
+ }
1729
+
1730
+ /* -- Tail of trace ------------------------------------------------------- */
1731
+
1732
+ /* Fixup the tail code. */
1733
+ static void asm_tail_fixup(ASMState *as, TraceNo lnk)
1734
+ {
1735
+ MCode *target = lnk ? traceref(as->J,lnk)->mcode : (MCode *)lj_vm_exit_interp;
1736
+ int32_t spadj = as->T->spadjust;
1737
+ MCode *p = as->mctop-1;
1738
+ *p = spadj ? (MIPSI_ADDIU|MIPSF_T(RID_SP)|MIPSF_S(RID_SP)|spadj) : MIPSI_NOP;
1739
+ p[-1] = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu);
1740
+ }
1741
+
1742
+ /* Prepare tail of code. */
1743
+ static void asm_tail_prep(ASMState *as)
1744
+ {
1745
+ as->mcp = as->mctop-2; /* Leave room for branch plus nop or stack adj. */
1746
+ as->invmcp = as->loopref ? as->mcp : NULL;
1747
+ }
1748
+
1749
+ /* -- Trace setup --------------------------------------------------------- */
1750
+
1751
+ /* Ensure there are enough stack slots for call arguments. */
1752
+ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
1753
+ {
1754
+ IRRef args[CCI_NARGS_MAX*2];
1755
+ uint32_t i, nargs = CCI_XNARGS(ci);
1756
+ int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR;
1757
+ asm_collectargs(as, ir, ci, args);
1758
+ for (i = 0; i < nargs; i++) {
1759
+ if (args[i] && irt_isfp(IR(args[i])->t) &&
1760
+ nfpr > 0 && !(ci->flags & CCI_VARARG)) {
1761
+ nfpr--;
1762
+ ngpr -= irt_isnum(IR(args[i])->t) ? 2 : 1;
1763
+ } else if (args[i] && irt_isnum(IR(args[i])->t)) {
1764
+ nfpr = 0;
1765
+ ngpr = ngpr & ~1;
1766
+ if (ngpr > 0) ngpr -= 2; else nslots = (nslots+3) & ~1;
1767
+ } else {
1768
+ nfpr = 0;
1769
+ if (ngpr > 0) ngpr--; else nslots++;
1770
+ }
1771
+ }
1772
+ if (nslots > as->evenspill) /* Leave room for args in stack slots. */
1773
+ as->evenspill = nslots;
1774
+ return irt_isfp(ir->t) ? REGSP_HINT(RID_FPRET) : REGSP_HINT(RID_RET);
1775
+ }
1776
+
1777
+ static void asm_setup_target(ASMState *as)
1778
+ {
1779
+ asm_sparejump_setup(as);
1780
+ asm_exitstub_setup(as);
1781
+ }
1782
+
1783
+ /* -- Trace patching ------------------------------------------------------ */
1784
+
1785
+ /* Patch exit jumps of existing machine code to a new target. */
1786
+ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
1787
+ {
1788
+ MCode *p = T->mcode;
1789
+ MCode *pe = (MCode *)((char *)p + T->szmcode);
1790
+ MCode *px = exitstub_trace_addr(T, exitno);
1791
+ MCode *cstart = NULL, *cstop = NULL;
1792
+ MCode *mcarea = lj_mcode_patch(J, p, 0);
1793
+ MCode exitload = MIPSI_LI | MIPSF_T(RID_TMP) | exitno;
1794
+ MCode tjump = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu);
1795
+ for (p++; p < pe; p++) {
1796
+ if (*p == exitload) { /* Look for load of exit number. */
1797
+ if (((p[-1] ^ (px-p)) & 0xffffu) == 0) { /* Look for exitstub branch. */
1798
+ ptrdiff_t delta = target - p;
1799
+ if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */
1800
+ patchbranch:
1801
+ p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu);
1802
+ *p = MIPSI_NOP; /* Replace the load of the exit number. */
1803
+ cstop = p;
1804
+ if (!cstart) cstart = p-1;
1805
+ } else { /* Branch out of range. Use spare jump slot in mcarea. */
1806
+ int i;
1807
+ for (i = 2; i < 2+MIPS_SPAREJUMP*2; i += 2) {
1808
+ if (mcarea[i] == tjump) {
1809
+ delta = mcarea+i - p;
1810
+ goto patchbranch;
1811
+ } else if (mcarea[i] == MIPSI_NOP) {
1812
+ mcarea[i] = tjump;
1813
+ cstart = mcarea+i;
1814
+ delta = mcarea+i - p;
1815
+ goto patchbranch;
1816
+ }
1817
+ }
1818
+ /* Ignore jump slot overflow. Child trace is simply not attached. */
1819
+ }
1820
+ } else if (p+1 == pe) {
1821
+ /* Patch NOP after code for inverted loop branch. Use of J is ok. */
1822
+ lua_assert(p[1] == MIPSI_NOP);
1823
+ p[1] = tjump;
1824
+ *p = MIPSI_NOP; /* Replace the load of the exit number. */
1825
+ cstop = p+2;
1826
+ if (!cstart) cstart = p+1;
1827
+ }
1828
+ }
1829
+ }
1830
+ if (cstart) lj_mcode_sync(cstart, cstop);
1831
+ lj_mcode_patch(J, mcarea, 1);
1832
+ }
1833
+