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,4355 @@
1
+ |// Low-level VM code for MIPS CPUs.
2
+ |// Bytecode interpreter, fast functions and helper functions.
3
+ |// Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
4
+ |
5
+ |.arch mips
6
+ |.section code_op, code_sub
7
+ |
8
+ |.actionlist build_actionlist
9
+ |.globals GLOB_
10
+ |.globalnames globnames
11
+ |.externnames extnames
12
+ |
13
+ |// Note: The ragged indentation of the instructions is intentional.
14
+ |// The starting columns indicate data dependencies.
15
+ |
16
+ |//-----------------------------------------------------------------------
17
+ |
18
+ |// Fixed register assignments for the interpreter.
19
+ |// Don't use: r0 = 0, r26/r27 = reserved, r28 = gp, r29 = sp, r31 = ra
20
+ |
21
+ |// The following must be C callee-save (but BASE is often refetched).
22
+ |.define BASE, r16 // Base of current Lua stack frame.
23
+ |.define KBASE, r17 // Constants of current Lua function.
24
+ |.define PC, r18 // Next PC.
25
+ |.define DISPATCH, r19 // Opcode dispatch table.
26
+ |.define LREG, r20 // Register holding lua_State (also in SAVE_L).
27
+ |.define MULTRES, r21 // Size of multi-result: (nresults+1)*8.
28
+ |// NYI: r22 currently unused.
29
+ |
30
+ |.define JGL, r30 // On-trace: global_State + 32768.
31
+ |
32
+ |// Constants for type-comparisons, stores and conversions. C callee-save.
33
+ |.define TISNIL, r30
34
+ |.define TOBIT, f30 // 2^52 + 2^51.
35
+ |
36
+ |// The following temporaries are not saved across C calls, except for RA.
37
+ |.define RA, r23 // Callee-save.
38
+ |.define RB, r8
39
+ |.define RC, r9
40
+ |.define RD, r10
41
+ |.define INS, r11
42
+ |
43
+ |.define AT, r1 // Assembler temporary.
44
+ |.define TMP0, r12
45
+ |.define TMP1, r13
46
+ |.define TMP2, r14
47
+ |.define TMP3, r15
48
+ |
49
+ |// Calling conventions.
50
+ |.define CFUNCADDR, r25
51
+ |.define CARG1, r4
52
+ |.define CARG2, r5
53
+ |.define CARG3, r6
54
+ |.define CARG4, r7
55
+ |
56
+ |.define CRET1, r2
57
+ |.define CRET2, r3
58
+ |
59
+ |.define FARG1, f12
60
+ |.define FARG2, f14
61
+ |
62
+ |.define FRET1, f0
63
+ |.define FRET2, f2
64
+ |
65
+ |// Stack layout while in interpreter. Must match with lj_frame.h.
66
+ |.define CFRAME_SPACE, 112 // Delta for sp.
67
+ |
68
+ |.define SAVE_ERRF, 124(sp) // 32 bit C frame info.
69
+ |.define SAVE_NRES, 120(sp)
70
+ |.define SAVE_CFRAME, 116(sp)
71
+ |.define SAVE_L, 112(sp)
72
+ |//----- 8 byte aligned, ^^^^ 16 byte register save area, owned by interpreter.
73
+ |.define SAVE_GPR_, 72 // .. 72+10*4: 32 bit GPR saves.
74
+ |.define SAVE_FPR_, 24 // .. 24+6*8: 64 bit FPR saves.
75
+ |.define SAVE_PC, 20(sp)
76
+ |.define ARG5, 16(sp)
77
+ |.define CSAVE_4, 12(sp)
78
+ |.define CSAVE_3, 8(sp)
79
+ |.define CSAVE_2, 4(sp)
80
+ |.define CSAVE_1, 0(sp)
81
+ |//----- 8 byte aligned, ^^^^ 16 byte register save area, owned by callee.
82
+ |
83
+ |.define ARG5_OFS, 16
84
+ |.define SAVE_MULTRES, ARG5
85
+ |
86
+ |.macro saveregs
87
+ | addiu sp, sp, -CFRAME_SPACE
88
+ | sw ra, SAVE_GPR_+9*4(sp)
89
+ | sw r30, SAVE_GPR_+8*4(sp)
90
+ | sdc1 f30, SAVE_FPR_+5*8(sp)
91
+ | sw r23, SAVE_GPR_+7*4(sp)
92
+ | sw r22, SAVE_GPR_+6*4(sp)
93
+ | sdc1 f28, SAVE_FPR_+4*8(sp)
94
+ | sw r21, SAVE_GPR_+5*4(sp)
95
+ | sw r20, SAVE_GPR_+4*4(sp)
96
+ | sdc1 f26, SAVE_FPR_+3*8(sp)
97
+ | sw r19, SAVE_GPR_+3*4(sp)
98
+ | sw r18, SAVE_GPR_+2*4(sp)
99
+ | sdc1 f24, SAVE_FPR_+2*8(sp)
100
+ | sw r17, SAVE_GPR_+1*4(sp)
101
+ | sw r16, SAVE_GPR_+0*4(sp)
102
+ | sdc1 f22, SAVE_FPR_+1*8(sp)
103
+ | sdc1 f20, SAVE_FPR_+0*8(sp)
104
+ |.endmacro
105
+ |
106
+ |.macro restoreregs_ret
107
+ | lw ra, SAVE_GPR_+9*4(sp)
108
+ | lw r30, SAVE_GPR_+8*4(sp)
109
+ | ldc1 f30, SAVE_FPR_+5*8(sp)
110
+ | lw r23, SAVE_GPR_+7*4(sp)
111
+ | lw r22, SAVE_GPR_+6*4(sp)
112
+ | ldc1 f28, SAVE_FPR_+4*8(sp)
113
+ | lw r21, SAVE_GPR_+5*4(sp)
114
+ | lw r20, SAVE_GPR_+4*4(sp)
115
+ | ldc1 f26, SAVE_FPR_+3*8(sp)
116
+ | lw r19, SAVE_GPR_+3*4(sp)
117
+ | lw r18, SAVE_GPR_+2*4(sp)
118
+ | ldc1 f24, SAVE_FPR_+2*8(sp)
119
+ | lw r17, SAVE_GPR_+1*4(sp)
120
+ | lw r16, SAVE_GPR_+0*4(sp)
121
+ | ldc1 f22, SAVE_FPR_+1*8(sp)
122
+ | ldc1 f20, SAVE_FPR_+0*8(sp)
123
+ | jr ra
124
+ | addiu sp, sp, CFRAME_SPACE
125
+ |.endmacro
126
+ |
127
+ |// Type definitions. Some of these are only used for documentation.
128
+ |.type L, lua_State, LREG
129
+ |.type GL, global_State
130
+ |.type TVALUE, TValue
131
+ |.type GCOBJ, GCobj
132
+ |.type STR, GCstr
133
+ |.type TAB, GCtab
134
+ |.type LFUNC, GCfuncL
135
+ |.type CFUNC, GCfuncC
136
+ |.type PROTO, GCproto
137
+ |.type UPVAL, GCupval
138
+ |.type NODE, Node
139
+ |.type NARGS8, int
140
+ |.type TRACE, GCtrace
141
+ |.type SBUF, SBuf
142
+ |
143
+ |//-----------------------------------------------------------------------
144
+ |
145
+ |// Trap for not-yet-implemented parts.
146
+ |.macro NYI; .long 0xf0f0f0f0; .endmacro
147
+ |
148
+ |// Macros to mark delay slots.
149
+ |.macro ., a; a; .endmacro
150
+ |.macro ., a,b; a,b; .endmacro
151
+ |.macro ., a,b,c; a,b,c; .endmacro
152
+ |
153
+ |//-----------------------------------------------------------------------
154
+ |
155
+ |// Endian-specific defines.
156
+ |.define FRAME_PC, LJ_ENDIAN_SELECT(-4,-8)
157
+ |.define FRAME_FUNC, LJ_ENDIAN_SELECT(-8,-4)
158
+ |.define HI, LJ_ENDIAN_SELECT(4,0)
159
+ |.define LO, LJ_ENDIAN_SELECT(0,4)
160
+ |.define OFS_RD, LJ_ENDIAN_SELECT(2,0)
161
+ |.define OFS_RA, LJ_ENDIAN_SELECT(1,2)
162
+ |.define OFS_OP, LJ_ENDIAN_SELECT(0,3)
163
+ |
164
+ |// Instruction decode.
165
+ |.macro decode_OP1, dst, ins; andi dst, ins, 0xff; .endmacro
166
+ |.macro decode_OP4a, dst, ins; andi dst, ins, 0xff; .endmacro
167
+ |.macro decode_OP4b, dst; sll dst, dst, 2; .endmacro
168
+ |.macro decode_RC4a, dst, ins; srl dst, ins, 14; .endmacro
169
+ |.macro decode_RC4b, dst; andi dst, dst, 0x3fc; .endmacro
170
+ |.macro decode_RD4b, dst; sll dst, dst, 2; .endmacro
171
+ |.macro decode_RA8a, dst, ins; srl dst, ins, 5; .endmacro
172
+ |.macro decode_RA8b, dst; andi dst, dst, 0x7f8; .endmacro
173
+ |.macro decode_RB8a, dst, ins; srl dst, ins, 21; .endmacro
174
+ |.macro decode_RB8b, dst; andi dst, dst, 0x7f8; .endmacro
175
+ |.macro decode_RD8a, dst, ins; srl dst, ins, 16; .endmacro
176
+ |.macro decode_RD8b, dst; sll dst, dst, 3; .endmacro
177
+ |.macro decode_RDtoRC8, dst, src; andi dst, src, 0x7f8; .endmacro
178
+ |
179
+ |// Instruction fetch.
180
+ |.macro ins_NEXT1
181
+ | lw INS, 0(PC)
182
+ | addiu PC, PC, 4
183
+ |.endmacro
184
+ |// Instruction decode+dispatch.
185
+ |.macro ins_NEXT2
186
+ | decode_OP4a TMP1, INS
187
+ | decode_OP4b TMP1
188
+ | addu TMP0, DISPATCH, TMP1
189
+ | decode_RD8a RD, INS
190
+ | lw AT, 0(TMP0)
191
+ | decode_RA8a RA, INS
192
+ | decode_RD8b RD
193
+ | jr AT
194
+ | decode_RA8b RA
195
+ |.endmacro
196
+ |.macro ins_NEXT
197
+ | ins_NEXT1
198
+ | ins_NEXT2
199
+ |.endmacro
200
+ |
201
+ |// Instruction footer.
202
+ |.if 1
203
+ | // Replicated dispatch. Less unpredictable branches, but higher I-Cache use.
204
+ | .define ins_next, ins_NEXT
205
+ | .define ins_next_, ins_NEXT
206
+ | .define ins_next1, ins_NEXT1
207
+ | .define ins_next2, ins_NEXT2
208
+ |.else
209
+ | // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch.
210
+ | // Affects only certain kinds of benchmarks (and only with -j off).
211
+ | .macro ins_next
212
+ | b ->ins_next
213
+ | .endmacro
214
+ | .macro ins_next1
215
+ | .endmacro
216
+ | .macro ins_next2
217
+ | b ->ins_next
218
+ | .endmacro
219
+ | .macro ins_next_
220
+ | ->ins_next:
221
+ | ins_NEXT
222
+ | .endmacro
223
+ |.endif
224
+ |
225
+ |// Call decode and dispatch.
226
+ |.macro ins_callt
227
+ | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC
228
+ | lw PC, LFUNC:RB->pc
229
+ | lw INS, 0(PC)
230
+ | addiu PC, PC, 4
231
+ | decode_OP4a TMP1, INS
232
+ | decode_RA8a RA, INS
233
+ | decode_OP4b TMP1
234
+ | decode_RA8b RA
235
+ | addu TMP0, DISPATCH, TMP1
236
+ | lw TMP0, 0(TMP0)
237
+ | jr TMP0
238
+ | addu RA, RA, BASE
239
+ |.endmacro
240
+ |
241
+ |.macro ins_call
242
+ | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, PC = caller PC
243
+ | sw PC, FRAME_PC(BASE)
244
+ | ins_callt
245
+ |.endmacro
246
+ |
247
+ |//-----------------------------------------------------------------------
248
+ |
249
+ |.macro branch_RD
250
+ | srl TMP0, RD, 1
251
+ | lui AT, (-(BCBIAS_J*4 >> 16) & 65535)
252
+ | addu TMP0, TMP0, AT
253
+ | addu PC, PC, TMP0
254
+ |.endmacro
255
+ |
256
+ |// Assumes DISPATCH is relative to GL.
257
+ #define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field))
258
+ #define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field))
259
+ #define GG_DISP2GOT (GG_OFS(got) - GG_OFS(dispatch))
260
+ #define DISPATCH_GOT(name) (GG_DISP2GOT + 4*LJ_GOT_##name)
261
+ |
262
+ #define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto))
263
+ |
264
+ |.macro load_got, func
265
+ | lw CFUNCADDR, DISPATCH_GOT(func)(DISPATCH)
266
+ |.endmacro
267
+ |// Much faster. Sadly, there's no easy way to force the required code layout.
268
+ |// .macro call_intern, func; bal extern func; .endmacro
269
+ |.macro call_intern, func; jalr CFUNCADDR; .endmacro
270
+ |.macro call_extern; jalr CFUNCADDR; .endmacro
271
+ |.macro jmp_extern; jr CFUNCADDR; .endmacro
272
+ |
273
+ |.macro hotcheck, delta, target
274
+ | srl TMP1, PC, 1
275
+ | andi TMP1, TMP1, 126
276
+ | addu TMP1, TMP1, DISPATCH
277
+ | lhu TMP2, GG_DISP2HOT(TMP1)
278
+ | addiu TMP2, TMP2, -delta
279
+ | bltz TMP2, target
280
+ |. sh TMP2, GG_DISP2HOT(TMP1)
281
+ |.endmacro
282
+ |
283
+ |.macro hotloop
284
+ | hotcheck HOTCOUNT_LOOP, ->vm_hotloop
285
+ |.endmacro
286
+ |
287
+ |.macro hotcall
288
+ | hotcheck HOTCOUNT_CALL, ->vm_hotcall
289
+ |.endmacro
290
+ |
291
+ |// Set current VM state. Uses TMP0.
292
+ |.macro li_vmstate, st; li TMP0, ~LJ_VMST_..st; .endmacro
293
+ |.macro st_vmstate; sw TMP0, DISPATCH_GL(vmstate)(DISPATCH); .endmacro
294
+ |
295
+ |// Move table write barrier back. Overwrites mark and tmp.
296
+ |.macro barrierback, tab, mark, tmp, target
297
+ | lw tmp, DISPATCH_GL(gc.grayagain)(DISPATCH)
298
+ | andi mark, mark, ~LJ_GC_BLACK & 255 // black2gray(tab)
299
+ | sw tab, DISPATCH_GL(gc.grayagain)(DISPATCH)
300
+ | sb mark, tab->marked
301
+ | b target
302
+ |. sw tmp, tab->gclist
303
+ |.endmacro
304
+ |
305
+ |//-----------------------------------------------------------------------
306
+
307
+ /* Generate subroutines used by opcodes and other parts of the VM. */
308
+ /* The .code_sub section should be last to help static branch prediction. */
309
+ static void build_subroutines(BuildCtx *ctx)
310
+ {
311
+ |.code_sub
312
+ |
313
+ |//-----------------------------------------------------------------------
314
+ |//-- Return handling ----------------------------------------------------
315
+ |//-----------------------------------------------------------------------
316
+ |
317
+ |->vm_returnp:
318
+ | // See vm_return. Also: TMP2 = previous base.
319
+ | andi AT, PC, FRAME_P
320
+ | beqz AT, ->cont_dispatch
321
+ |. li TMP1, LJ_TTRUE
322
+ |
323
+ | // Return from pcall or xpcall fast func.
324
+ | lw PC, FRAME_PC(TMP2) // Fetch PC of previous frame.
325
+ | move BASE, TMP2 // Restore caller base.
326
+ | // Prepending may overwrite the pcall frame, so do it at the end.
327
+ | sw TMP1, FRAME_PC(RA) // Prepend true to results.
328
+ | addiu RA, RA, -8
329
+ |
330
+ |->vm_returnc:
331
+ | addiu RD, RD, 8 // RD = (nresults+1)*8.
332
+ | andi TMP0, PC, FRAME_TYPE
333
+ | beqz RD, ->vm_unwind_c_eh
334
+ |. li CRET1, LUA_YIELD
335
+ | beqz TMP0, ->BC_RET_Z // Handle regular return to Lua.
336
+ |. move MULTRES, RD
337
+ |
338
+ |->vm_return:
339
+ | // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return
340
+ | // TMP0 = PC & FRAME_TYPE
341
+ | li TMP2, -8
342
+ | xori AT, TMP0, FRAME_C
343
+ | and TMP2, PC, TMP2
344
+ | bnez AT, ->vm_returnp
345
+ | subu TMP2, BASE, TMP2 // TMP2 = previous base.
346
+ |
347
+ | addiu TMP1, RD, -8
348
+ | sw TMP2, L->base
349
+ | li_vmstate C
350
+ | lw TMP2, SAVE_NRES
351
+ | addiu BASE, BASE, -8
352
+ | st_vmstate
353
+ | beqz TMP1, >2
354
+ |. sll TMP2, TMP2, 3
355
+ |1:
356
+ | addiu TMP1, TMP1, -8
357
+ | ldc1 f0, 0(RA)
358
+ | addiu RA, RA, 8
359
+ | sdc1 f0, 0(BASE)
360
+ | bnez TMP1, <1
361
+ |. addiu BASE, BASE, 8
362
+ |
363
+ |2:
364
+ | bne TMP2, RD, >6
365
+ |3:
366
+ |. sw BASE, L->top // Store new top.
367
+ |
368
+ |->vm_leave_cp:
369
+ | lw TMP0, SAVE_CFRAME // Restore previous C frame.
370
+ | move CRET1, r0 // Ok return status for vm_pcall.
371
+ | sw TMP0, L->cframe
372
+ |
373
+ |->vm_leave_unw:
374
+ | restoreregs_ret
375
+ |
376
+ |6:
377
+ | lw TMP1, L->maxstack
378
+ | slt AT, TMP2, RD
379
+ | bnez AT, >7 // Less results wanted?
380
+ | // More results wanted. Check stack size and fill up results with nil.
381
+ |. slt AT, BASE, TMP1
382
+ | beqz AT, >8
383
+ |. nop
384
+ | sw TISNIL, HI(BASE)
385
+ | addiu RD, RD, 8
386
+ | b <2
387
+ |. addiu BASE, BASE, 8
388
+ |
389
+ |7: // Less results wanted.
390
+ | subu TMP0, RD, TMP2
391
+ | subu TMP0, BASE, TMP0 // Either keep top or shrink it.
392
+ | b <3
393
+ |. movn BASE, TMP0, TMP2 // LUA_MULTRET+1 case?
394
+ |
395
+ |8: // Corner case: need to grow stack for filling up results.
396
+ | // This can happen if:
397
+ | // - A C function grows the stack (a lot).
398
+ | // - The GC shrinks the stack in between.
399
+ | // - A return back from a lua_call() with (high) nresults adjustment.
400
+ | load_got lj_state_growstack
401
+ | move MULTRES, RD
402
+ | srl CARG2, TMP2, 3
403
+ | call_intern lj_state_growstack // (lua_State *L, int n)
404
+ |. move CARG1, L
405
+ | lw TMP2, SAVE_NRES
406
+ | lw BASE, L->top // Need the (realloced) L->top in BASE.
407
+ | move RD, MULTRES
408
+ | b <2
409
+ |. sll TMP2, TMP2, 3
410
+ |
411
+ |->vm_unwind_c: // Unwind C stack, return from vm_pcall.
412
+ | // (void *cframe, int errcode)
413
+ | move sp, CARG1
414
+ | move CRET1, CARG2
415
+ |->vm_unwind_c_eh: // Landing pad for external unwinder.
416
+ | lw L, SAVE_L
417
+ | li TMP0, ~LJ_VMST_C
418
+ | lw GL:TMP1, L->glref
419
+ | b ->vm_leave_unw
420
+ |. sw TMP0, GL:TMP1->vmstate
421
+ |
422
+ |->vm_unwind_ff: // Unwind C stack, return from ff pcall.
423
+ | // (void *cframe)
424
+ | li AT, -4
425
+ | and sp, CARG1, AT
426
+ |->vm_unwind_ff_eh: // Landing pad for external unwinder.
427
+ | lw L, SAVE_L
428
+ | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
429
+ | li TISNIL, LJ_TNIL
430
+ | lw BASE, L->base
431
+ | lw DISPATCH, L->glref // Setup pointer to dispatch table.
432
+ | mtc1 TMP3, TOBIT
433
+ | li TMP1, LJ_TFALSE
434
+ | li_vmstate INTERP
435
+ | lw PC, FRAME_PC(BASE) // Fetch PC of previous frame.
436
+ | cvt.d.s TOBIT, TOBIT
437
+ | addiu RA, BASE, -8 // Results start at BASE-8.
438
+ | addiu DISPATCH, DISPATCH, GG_G2DISP
439
+ | sw TMP1, HI(RA) // Prepend false to error message.
440
+ | st_vmstate
441
+ | b ->vm_returnc
442
+ |. li RD, 16 // 2 results: false + error message.
443
+ |
444
+ |//-----------------------------------------------------------------------
445
+ |//-- Grow stack for calls -----------------------------------------------
446
+ |//-----------------------------------------------------------------------
447
+ |
448
+ |->vm_growstack_c: // Grow stack for C function.
449
+ | b >2
450
+ |. li CARG2, LUA_MINSTACK
451
+ |
452
+ |->vm_growstack_l: // Grow stack for Lua function.
453
+ | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC
454
+ | addu RC, BASE, RC
455
+ | subu RA, RA, BASE
456
+ | sw BASE, L->base
457
+ | addiu PC, PC, 4 // Must point after first instruction.
458
+ | sw RC, L->top
459
+ | srl CARG2, RA, 3
460
+ |2:
461
+ | // L->base = new base, L->top = top
462
+ | load_got lj_state_growstack
463
+ | sw PC, SAVE_PC
464
+ | call_intern lj_state_growstack // (lua_State *L, int n)
465
+ |. move CARG1, L
466
+ | lw BASE, L->base
467
+ | lw RC, L->top
468
+ | lw LFUNC:RB, FRAME_FUNC(BASE)
469
+ | subu RC, RC, BASE
470
+ | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC
471
+ | ins_callt // Just retry the call.
472
+ |
473
+ |//-----------------------------------------------------------------------
474
+ |//-- Entry points into the assembler VM ---------------------------------
475
+ |//-----------------------------------------------------------------------
476
+ |
477
+ |->vm_resume: // Setup C frame and resume thread.
478
+ | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0)
479
+ | saveregs
480
+ | move L, CARG1
481
+ | lw DISPATCH, L->glref // Setup pointer to dispatch table.
482
+ | move BASE, CARG2
483
+ | lbu TMP1, L->status
484
+ | sw L, SAVE_L
485
+ | li PC, FRAME_CP
486
+ | addiu TMP0, sp, CFRAME_RESUME
487
+ | addiu DISPATCH, DISPATCH, GG_G2DISP
488
+ | sw r0, SAVE_NRES
489
+ | sw r0, SAVE_ERRF
490
+ | sw CARG1, SAVE_PC // Any value outside of bytecode is ok.
491
+ | sw r0, SAVE_CFRAME
492
+ | beqz TMP1, >3
493
+ |. sw TMP0, L->cframe
494
+ |
495
+ | // Resume after yield (like a return).
496
+ | sw L, DISPATCH_GL(cur_L)(DISPATCH)
497
+ | move RA, BASE
498
+ | lw BASE, L->base
499
+ | lw TMP1, L->top
500
+ | lw PC, FRAME_PC(BASE)
501
+ | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
502
+ | subu RD, TMP1, BASE
503
+ | mtc1 TMP3, TOBIT
504
+ | sb r0, L->status
505
+ | cvt.d.s TOBIT, TOBIT
506
+ | li_vmstate INTERP
507
+ | addiu RD, RD, 8
508
+ | st_vmstate
509
+ | move MULTRES, RD
510
+ | andi TMP0, PC, FRAME_TYPE
511
+ | beqz TMP0, ->BC_RET_Z
512
+ |. li TISNIL, LJ_TNIL
513
+ | b ->vm_return
514
+ |. nop
515
+ |
516
+ |->vm_pcall: // Setup protected C frame and enter VM.
517
+ | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef)
518
+ | saveregs
519
+ | sw CARG4, SAVE_ERRF
520
+ | b >1
521
+ |. li PC, FRAME_CP
522
+ |
523
+ |->vm_call: // Setup C frame and enter VM.
524
+ | // (lua_State *L, TValue *base, int nres1)
525
+ | saveregs
526
+ | li PC, FRAME_C
527
+ |
528
+ |1: // Entry point for vm_pcall above (PC = ftype).
529
+ | lw TMP1, L:CARG1->cframe
530
+ | move L, CARG1
531
+ | sw CARG3, SAVE_NRES
532
+ | lw DISPATCH, L->glref // Setup pointer to dispatch table.
533
+ | sw CARG1, SAVE_L
534
+ | move BASE, CARG2
535
+ | addiu DISPATCH, DISPATCH, GG_G2DISP
536
+ | sw CARG1, SAVE_PC // Any value outside of bytecode is ok.
537
+ | sw TMP1, SAVE_CFRAME
538
+ | sw sp, L->cframe // Add our C frame to cframe chain.
539
+ |
540
+ |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype).
541
+ | sw L, DISPATCH_GL(cur_L)(DISPATCH)
542
+ | lw TMP2, L->base // TMP2 = old base (used in vmeta_call).
543
+ | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
544
+ | lw TMP1, L->top
545
+ | mtc1 TMP3, TOBIT
546
+ | addu PC, PC, BASE
547
+ | subu NARGS8:RC, TMP1, BASE
548
+ | subu PC, PC, TMP2 // PC = frame delta + frame type
549
+ | cvt.d.s TOBIT, TOBIT
550
+ | li_vmstate INTERP
551
+ | li TISNIL, LJ_TNIL
552
+ | st_vmstate
553
+ |
554
+ |->vm_call_dispatch:
555
+ | // TMP2 = old base, BASE = new base, RC = nargs*8, PC = caller PC
556
+ | lw TMP0, FRAME_PC(BASE)
557
+ | li AT, LJ_TFUNC
558
+ | bne TMP0, AT, ->vmeta_call
559
+ |. lw LFUNC:RB, FRAME_FUNC(BASE)
560
+ |
561
+ |->vm_call_dispatch_f:
562
+ | ins_call
563
+ | // BASE = new base, RB = func, RC = nargs*8, PC = caller PC
564
+ |
565
+ |->vm_cpcall: // Setup protected C frame, call C.
566
+ | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp)
567
+ | saveregs
568
+ | move L, CARG1
569
+ | lw TMP0, L:CARG1->stack
570
+ | sw CARG1, SAVE_L
571
+ | lw TMP1, L->top
572
+ | lw DISPATCH, L->glref // Setup pointer to dispatch table.
573
+ | sw CARG1, SAVE_PC // Any value outside of bytecode is ok.
574
+ | subu TMP0, TMP0, TMP1 // Compute -savestack(L, L->top).
575
+ | lw TMP1, L->cframe
576
+ | addiu DISPATCH, DISPATCH, GG_G2DISP
577
+ | sw TMP0, SAVE_NRES // Neg. delta means cframe w/o frame.
578
+ | sw r0, SAVE_ERRF // No error function.
579
+ | sw TMP1, SAVE_CFRAME
580
+ | sw sp, L->cframe // Add our C frame to cframe chain.
581
+ | sw L, DISPATCH_GL(cur_L)(DISPATCH)
582
+ | jalr CARG4 // (lua_State *L, lua_CFunction func, void *ud)
583
+ |. move CFUNCADDR, CARG4
584
+ | move BASE, CRET1
585
+ | bnez CRET1, <3 // Else continue with the call.
586
+ |. li PC, FRAME_CP
587
+ | b ->vm_leave_cp // No base? Just remove C frame.
588
+ |. nop
589
+ |
590
+ |//-----------------------------------------------------------------------
591
+ |//-- Metamethod handling ------------------------------------------------
592
+ |//-----------------------------------------------------------------------
593
+ |
594
+ |// The lj_meta_* functions (except for lj_meta_cat) don't reallocate the
595
+ |// stack, so BASE doesn't need to be reloaded across these calls.
596
+ |
597
+ |//-- Continuation dispatch ----------------------------------------------
598
+ |
599
+ |->cont_dispatch:
600
+ | // BASE = meta base, RA = resultptr, RD = (nresults+1)*8
601
+ | lw TMP0, -16+LO(BASE) // Continuation.
602
+ | move RB, BASE
603
+ | move BASE, TMP2 // Restore caller BASE.
604
+ | lw LFUNC:TMP1, FRAME_FUNC(TMP2)
605
+ |.if FFI
606
+ | sltiu AT, TMP0, 2
607
+ |.endif
608
+ | lw PC, -16+HI(RB) // Restore PC from [cont|PC].
609
+ | addu TMP2, RA, RD
610
+ | lw TMP1, LFUNC:TMP1->pc
611
+ |.if FFI
612
+ | bnez AT, >1
613
+ |.endif
614
+ |. sw TISNIL, -8+HI(TMP2) // Ensure one valid arg.
615
+ | // BASE = base, RA = resultptr, RB = meta base
616
+ | jr TMP0 // Jump to continuation.
617
+ |. lw KBASE, PC2PROTO(k)(TMP1)
618
+ |
619
+ |.if FFI
620
+ |1:
621
+ | bnez TMP0, ->cont_ffi_callback // cont = 1: return from FFI callback.
622
+ | // cont = 0: tailcall from C function.
623
+ |. addiu TMP1, RB, -16
624
+ | b ->vm_call_tail
625
+ |. subu RC, TMP1, BASE
626
+ |.endif
627
+ |
628
+ |->cont_cat: // RA = resultptr, RB = meta base
629
+ | lw INS, -4(PC)
630
+ | addiu CARG2, RB, -16
631
+ | ldc1 f0, 0(RA)
632
+ | decode_RB8a MULTRES, INS
633
+ | decode_RA8a RA, INS
634
+ | decode_RB8b MULTRES
635
+ | decode_RA8b RA
636
+ | addu TMP1, BASE, MULTRES
637
+ | sw BASE, L->base
638
+ | subu CARG3, CARG2, TMP1
639
+ | bne TMP1, CARG2, ->BC_CAT_Z
640
+ |. sdc1 f0, 0(CARG2)
641
+ | addu RA, BASE, RA
642
+ | b ->cont_nop
643
+ |. sdc1 f0, 0(RA)
644
+ |
645
+ |//-- Table indexing metamethods -----------------------------------------
646
+ |
647
+ |->vmeta_tgets1:
648
+ | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv)
649
+ | li TMP0, LJ_TSTR
650
+ | sw STR:RC, LO(CARG3)
651
+ | b >1
652
+ |. sw TMP0, HI(CARG3)
653
+ |
654
+ |->vmeta_tgets:
655
+ | addiu CARG2, DISPATCH, DISPATCH_GL(tmptv)
656
+ | li TMP0, LJ_TTAB
657
+ | sw TAB:RB, LO(CARG2)
658
+ | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv2)
659
+ | sw TMP0, HI(CARG2)
660
+ | li TMP1, LJ_TSTR
661
+ | sw STR:RC, LO(CARG3)
662
+ | b >1
663
+ |. sw TMP1, HI(CARG3)
664
+ |
665
+ |->vmeta_tgetb: // TMP0 = index
666
+ | mtc1 TMP0, f0
667
+ | cvt.d.w f0, f0
668
+ | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv)
669
+ | sdc1 f0, 0(CARG3)
670
+ |
671
+ |->vmeta_tgetv:
672
+ |1:
673
+ | load_got lj_meta_tget
674
+ | sw BASE, L->base
675
+ | sw PC, SAVE_PC
676
+ | call_intern lj_meta_tget // (lua_State *L, TValue *o, TValue *k)
677
+ |. move CARG1, L
678
+ | // Returns TValue * (finished) or NULL (metamethod).
679
+ | beqz CRET1, >3
680
+ |. addiu TMP1, BASE, -FRAME_CONT
681
+ | ldc1 f0, 0(CRET1)
682
+ | ins_next1
683
+ | sdc1 f0, 0(RA)
684
+ | ins_next2
685
+ |
686
+ |3: // Call __index metamethod.
687
+ | // BASE = base, L->top = new base, stack = cont/func/t/k
688
+ | lw BASE, L->top
689
+ | sw PC, -16+HI(BASE) // [cont|PC]
690
+ | subu PC, BASE, TMP1
691
+ | lw LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here.
692
+ | b ->vm_call_dispatch_f
693
+ |. li NARGS8:RC, 16 // 2 args for func(t, k).
694
+ |
695
+ |->vmeta_tgetr:
696
+ | load_got lj_tab_getinth
697
+ | call_intern lj_tab_getinth // (GCtab *t, int32_t key)
698
+ |. nop
699
+ | // Returns cTValue * or NULL.
700
+ | beqz CRET1, >1
701
+ |. nop
702
+ | b ->BC_TGETR_Z
703
+ |. ldc1 f0, 0(CRET1)
704
+ |
705
+ |//-----------------------------------------------------------------------
706
+ |
707
+ |->vmeta_tsets1:
708
+ | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv)
709
+ | li TMP0, LJ_TSTR
710
+ | sw STR:RC, LO(CARG3)
711
+ | b >1
712
+ |. sw TMP0, HI(CARG3)
713
+ |
714
+ |->vmeta_tsets:
715
+ | addiu CARG2, DISPATCH, DISPATCH_GL(tmptv)
716
+ | li TMP0, LJ_TTAB
717
+ | sw TAB:RB, LO(CARG2)
718
+ | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv2)
719
+ | sw TMP0, HI(CARG2)
720
+ | li TMP1, LJ_TSTR
721
+ | sw STR:RC, LO(CARG3)
722
+ | b >1
723
+ |. sw TMP1, HI(CARG3)
724
+ |
725
+ |->vmeta_tsetb: // TMP0 = index
726
+ | mtc1 TMP0, f0
727
+ | cvt.d.w f0, f0
728
+ | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv)
729
+ | sdc1 f0, 0(CARG3)
730
+ |
731
+ |->vmeta_tsetv:
732
+ |1:
733
+ | load_got lj_meta_tset
734
+ | sw BASE, L->base
735
+ | sw PC, SAVE_PC
736
+ | call_intern lj_meta_tset // (lua_State *L, TValue *o, TValue *k)
737
+ |. move CARG1, L
738
+ | // Returns TValue * (finished) or NULL (metamethod).
739
+ | beqz CRET1, >3
740
+ |. ldc1 f0, 0(RA)
741
+ | // NOBARRIER: lj_meta_tset ensures the table is not black.
742
+ | ins_next1
743
+ | sdc1 f0, 0(CRET1)
744
+ | ins_next2
745
+ |
746
+ |3: // Call __newindex metamethod.
747
+ | // BASE = base, L->top = new base, stack = cont/func/t/k/(v)
748
+ | addiu TMP1, BASE, -FRAME_CONT
749
+ | lw BASE, L->top
750
+ | sw PC, -16+HI(BASE) // [cont|PC]
751
+ | subu PC, BASE, TMP1
752
+ | lw LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here.
753
+ | sdc1 f0, 16(BASE) // Copy value to third argument.
754
+ | b ->vm_call_dispatch_f
755
+ |. li NARGS8:RC, 24 // 3 args for func(t, k, v)
756
+ |
757
+ |->vmeta_tsetr:
758
+ | load_got lj_tab_setinth
759
+ | sw BASE, L->base
760
+ | sw PC, SAVE_PC
761
+ | call_intern lj_tab_setinth // (lua_State *L, GCtab *t, int32_t key)
762
+ |. move CARG1, L
763
+ | // Returns TValue *.
764
+ | b ->BC_TSETR_Z
765
+ |. nop
766
+ |
767
+ |//-- Comparison metamethods ---------------------------------------------
768
+ |
769
+ |->vmeta_comp:
770
+ | // CARG2, CARG3 are already set by BC_ISLT/BC_ISGE/BC_ISLE/BC_ISGT.
771
+ | load_got lj_meta_comp
772
+ | addiu PC, PC, -4
773
+ | sw BASE, L->base
774
+ | sw PC, SAVE_PC
775
+ | decode_OP1 CARG4, INS
776
+ | call_intern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op)
777
+ |. move CARG1, L
778
+ | // Returns 0/1 or TValue * (metamethod).
779
+ |3:
780
+ | sltiu AT, CRET1, 2
781
+ | beqz AT, ->vmeta_binop
782
+ | negu TMP2, CRET1
783
+ |4:
784
+ | lhu RD, OFS_RD(PC)
785
+ | addiu PC, PC, 4
786
+ | lui TMP1, (-(BCBIAS_J*4 >> 16) & 65535)
787
+ | sll RD, RD, 2
788
+ | addu RD, RD, TMP1
789
+ | and RD, RD, TMP2
790
+ | addu PC, PC, RD
791
+ |->cont_nop:
792
+ | ins_next
793
+ |
794
+ |->cont_ra: // RA = resultptr
795
+ | lbu TMP1, -4+OFS_RA(PC)
796
+ | ldc1 f0, 0(RA)
797
+ | sll TMP1, TMP1, 3
798
+ | addu TMP1, BASE, TMP1
799
+ | b ->cont_nop
800
+ |. sdc1 f0, 0(TMP1)
801
+ |
802
+ |->cont_condt: // RA = resultptr
803
+ | lw TMP0, HI(RA)
804
+ | sltiu AT, TMP0, LJ_TISTRUECOND
805
+ | b <4
806
+ |. negu TMP2, AT // Branch if result is true.
807
+ |
808
+ |->cont_condf: // RA = resultptr
809
+ | lw TMP0, HI(RA)
810
+ | sltiu AT, TMP0, LJ_TISTRUECOND
811
+ | b <4
812
+ |. addiu TMP2, AT, -1 // Branch if result is false.
813
+ |
814
+ |->vmeta_equal:
815
+ | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV.
816
+ | load_got lj_meta_equal
817
+ | addiu PC, PC, -4
818
+ | sw BASE, L->base
819
+ | sw PC, SAVE_PC
820
+ | call_intern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne)
821
+ |. move CARG1, L
822
+ | // Returns 0/1 or TValue * (metamethod).
823
+ | b <3
824
+ |. nop
825
+ |
826
+ |->vmeta_equal_cd:
827
+ |.if FFI
828
+ | load_got lj_meta_equal_cd
829
+ | move CARG2, INS
830
+ | addiu PC, PC, -4
831
+ | sw BASE, L->base
832
+ | sw PC, SAVE_PC
833
+ | call_intern lj_meta_equal_cd // (lua_State *L, BCIns op)
834
+ |. move CARG1, L
835
+ | // Returns 0/1 or TValue * (metamethod).
836
+ | b <3
837
+ |. nop
838
+ |.endif
839
+ |
840
+ |->vmeta_istype:
841
+ | load_got lj_meta_istype
842
+ | addiu PC, PC, -4
843
+ | sw BASE, L->base
844
+ | srl CARG2, RA, 3
845
+ | srl CARG3, RD, 3
846
+ | sw PC, SAVE_PC
847
+ | call_intern lj_meta_istype // (lua_State *L, BCReg ra, BCReg tp)
848
+ |. move CARG1, L
849
+ | b ->cont_nop
850
+ |. nop
851
+ |
852
+ |//-- Arithmetic metamethods ---------------------------------------------
853
+ |
854
+ |->vmeta_unm:
855
+ | move CARG4, CARG3
856
+ |
857
+ |->vmeta_arith:
858
+ | load_got lj_meta_arith
859
+ | decode_OP1 TMP0, INS
860
+ | sw BASE, L->base
861
+ | sw PC, SAVE_PC
862
+ | move CARG2, RA
863
+ | sw TMP0, ARG5
864
+ | call_intern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
865
+ |. move CARG1, L
866
+ | // Returns NULL (finished) or TValue * (metamethod).
867
+ | beqz CRET1, ->cont_nop
868
+ |. nop
869
+ |
870
+ | // Call metamethod for binary op.
871
+ |->vmeta_binop:
872
+ | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2
873
+ | subu TMP1, CRET1, BASE
874
+ | sw PC, -16+HI(CRET1) // [cont|PC]
875
+ | move TMP2, BASE
876
+ | addiu PC, TMP1, FRAME_CONT
877
+ | move BASE, CRET1
878
+ | b ->vm_call_dispatch
879
+ |. li NARGS8:RC, 16 // 2 args for func(o1, o2).
880
+ |
881
+ |->vmeta_len:
882
+ | // CARG2 already set by BC_LEN.
883
+ #if LJ_52
884
+ | move MULTRES, CARG1
885
+ #endif
886
+ | load_got lj_meta_len
887
+ | sw BASE, L->base
888
+ | sw PC, SAVE_PC
889
+ | call_intern lj_meta_len // (lua_State *L, TValue *o)
890
+ |. move CARG1, L
891
+ | // Returns NULL (retry) or TValue * (metamethod base).
892
+ #if LJ_52
893
+ | bnez CRET1, ->vmeta_binop // Binop call for compatibility.
894
+ |. nop
895
+ | b ->BC_LEN_Z
896
+ |. move CARG1, MULTRES
897
+ #else
898
+ | b ->vmeta_binop // Binop call for compatibility.
899
+ |. nop
900
+ #endif
901
+ |
902
+ |//-- Call metamethod ----------------------------------------------------
903
+ |
904
+ |->vmeta_call: // Resolve and call __call metamethod.
905
+ | // TMP2 = old base, BASE = new base, RC = nargs*8
906
+ | load_got lj_meta_call
907
+ | sw TMP2, L->base // This is the callers base!
908
+ | addiu CARG2, BASE, -8
909
+ | sw PC, SAVE_PC
910
+ | addu CARG3, BASE, RC
911
+ | move MULTRES, NARGS8:RC
912
+ | call_intern lj_meta_call // (lua_State *L, TValue *func, TValue *top)
913
+ |. move CARG1, L
914
+ | lw LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here.
915
+ | addiu NARGS8:RC, MULTRES, 8 // Got one more argument now.
916
+ | ins_call
917
+ |
918
+ |->vmeta_callt: // Resolve __call for BC_CALLT.
919
+ | // BASE = old base, RA = new base, RC = nargs*8
920
+ | load_got lj_meta_call
921
+ | sw BASE, L->base
922
+ | addiu CARG2, RA, -8
923
+ | sw PC, SAVE_PC
924
+ | addu CARG3, RA, RC
925
+ | move MULTRES, NARGS8:RC
926
+ | call_intern lj_meta_call // (lua_State *L, TValue *func, TValue *top)
927
+ |. move CARG1, L
928
+ | lw TMP1, FRAME_PC(BASE)
929
+ | lw LFUNC:RB, FRAME_FUNC(RA) // Guaranteed to be a function here.
930
+ | b ->BC_CALLT_Z
931
+ |. addiu NARGS8:RC, MULTRES, 8 // Got one more argument now.
932
+ |
933
+ |//-- Argument coercion for 'for' statement ------------------------------
934
+ |
935
+ |->vmeta_for:
936
+ | load_got lj_meta_for
937
+ | sw BASE, L->base
938
+ | move CARG2, RA
939
+ | sw PC, SAVE_PC
940
+ | move MULTRES, INS
941
+ | call_intern lj_meta_for // (lua_State *L, TValue *base)
942
+ |. move CARG1, L
943
+ |.if JIT
944
+ | decode_OP1 TMP0, MULTRES
945
+ | li AT, BC_JFORI
946
+ |.endif
947
+ | decode_RA8a RA, MULTRES
948
+ | decode_RD8a RD, MULTRES
949
+ | decode_RA8b RA
950
+ |.if JIT
951
+ | beq TMP0, AT, =>BC_JFORI
952
+ |. decode_RD8b RD
953
+ | b =>BC_FORI
954
+ |. nop
955
+ |.else
956
+ | b =>BC_FORI
957
+ |. decode_RD8b RD
958
+ |.endif
959
+ |
960
+ |//-----------------------------------------------------------------------
961
+ |//-- Fast functions -----------------------------------------------------
962
+ |//-----------------------------------------------------------------------
963
+ |
964
+ |.macro .ffunc, name
965
+ |->ff_ .. name:
966
+ |.endmacro
967
+ |
968
+ |.macro .ffunc_1, name
969
+ |->ff_ .. name:
970
+ | beqz NARGS8:RC, ->fff_fallback
971
+ |. lw CARG3, HI(BASE)
972
+ | lw CARG1, LO(BASE)
973
+ |.endmacro
974
+ |
975
+ |.macro .ffunc_2, name
976
+ |->ff_ .. name:
977
+ | sltiu AT, NARGS8:RC, 16
978
+ | lw CARG3, HI(BASE)
979
+ | bnez AT, ->fff_fallback
980
+ |. lw CARG4, 8+HI(BASE)
981
+ | lw CARG1, LO(BASE)
982
+ | lw CARG2, 8+LO(BASE)
983
+ |.endmacro
984
+ |
985
+ |.macro .ffunc_n, name // Caveat: has delay slot!
986
+ |->ff_ .. name:
987
+ | lw CARG3, HI(BASE)
988
+ | beqz NARGS8:RC, ->fff_fallback
989
+ |. ldc1 FARG1, 0(BASE)
990
+ | sltiu AT, CARG3, LJ_TISNUM
991
+ | beqz AT, ->fff_fallback
992
+ |.endmacro
993
+ |
994
+ |.macro .ffunc_nn, name // Caveat: has delay slot!
995
+ |->ff_ .. name:
996
+ | sltiu AT, NARGS8:RC, 16
997
+ | lw CARG3, HI(BASE)
998
+ | bnez AT, ->fff_fallback
999
+ |. lw CARG4, 8+HI(BASE)
1000
+ | ldc1 FARG1, 0(BASE)
1001
+ | ldc1 FARG2, 8(BASE)
1002
+ | sltiu TMP0, CARG3, LJ_TISNUM
1003
+ | sltiu TMP1, CARG4, LJ_TISNUM
1004
+ | and TMP0, TMP0, TMP1
1005
+ | beqz TMP0, ->fff_fallback
1006
+ |.endmacro
1007
+ |
1008
+ |// Inlined GC threshold check. Caveat: uses TMP0 and TMP1 and has delay slot!
1009
+ |.macro ffgccheck
1010
+ | lw TMP0, DISPATCH_GL(gc.total)(DISPATCH)
1011
+ | lw TMP1, DISPATCH_GL(gc.threshold)(DISPATCH)
1012
+ | subu AT, TMP0, TMP1
1013
+ | bgezal AT, ->fff_gcstep
1014
+ |.endmacro
1015
+ |
1016
+ |//-- Base library: checks -----------------------------------------------
1017
+ |
1018
+ |.ffunc_1 assert
1019
+ | sltiu AT, CARG3, LJ_TISTRUECOND
1020
+ | beqz AT, ->fff_fallback
1021
+ |. addiu RA, BASE, -8
1022
+ | lw PC, FRAME_PC(BASE)
1023
+ | addiu RD, NARGS8:RC, 8 // Compute (nresults+1)*8.
1024
+ | addu TMP2, RA, NARGS8:RC
1025
+ | sw CARG3, HI(RA)
1026
+ | addiu TMP1, BASE, 8
1027
+ | beq BASE, TMP2, ->fff_res // Done if exactly 1 argument.
1028
+ |. sw CARG1, LO(RA)
1029
+ |1:
1030
+ | ldc1 f0, 0(TMP1)
1031
+ | sdc1 f0, -8(TMP1)
1032
+ | bne TMP1, TMP2, <1
1033
+ |. addiu TMP1, TMP1, 8
1034
+ | b ->fff_res
1035
+ |. nop
1036
+ |
1037
+ |.ffunc type
1038
+ | lw CARG3, HI(BASE)
1039
+ | li TMP1, LJ_TISNUM
1040
+ | beqz NARGS8:RC, ->fff_fallback
1041
+ |. sltiu TMP0, CARG3, LJ_TISNUM
1042
+ | movz TMP1, CARG3, TMP0
1043
+ | not TMP1, TMP1
1044
+ | sll TMP1, TMP1, 3
1045
+ | addu TMP1, CFUNC:RB, TMP1
1046
+ | b ->fff_resn
1047
+ |. ldc1 FRET1, CFUNC:TMP1->upvalue
1048
+ |
1049
+ |//-- Base library: getters and setters ---------------------------------
1050
+ |
1051
+ |.ffunc_1 getmetatable
1052
+ | li AT, LJ_TTAB
1053
+ | bne CARG3, AT, >6
1054
+ |. li AT, LJ_TUDATA
1055
+ |1: // Field metatable must be at same offset for GCtab and GCudata!
1056
+ | lw TAB:CARG1, TAB:CARG1->metatable
1057
+ |2:
1058
+ | lw STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH)
1059
+ | beqz TAB:CARG1, ->fff_restv
1060
+ |. li CARG3, LJ_TNIL
1061
+ | lw TMP0, TAB:CARG1->hmask
1062
+ | li CARG3, LJ_TTAB // Use metatable as default result.
1063
+ | lw TMP1, STR:RC->hash
1064
+ | lw NODE:TMP2, TAB:CARG1->node
1065
+ | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask
1066
+ | sll TMP0, TMP1, 5
1067
+ | sll TMP1, TMP1, 3
1068
+ | subu TMP1, TMP0, TMP1
1069
+ | addu NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8)
1070
+ | li AT, LJ_TSTR
1071
+ |3: // Rearranged logic, because we expect _not_ to find the key.
1072
+ | lw CARG4, offsetof(Node, key)+HI(NODE:TMP2)
1073
+ | lw TMP0, offsetof(Node, key)+LO(NODE:TMP2)
1074
+ | lw NODE:TMP3, NODE:TMP2->next
1075
+ | bne CARG4, AT, >4
1076
+ |. lw CARG2, offsetof(Node, val)+HI(NODE:TMP2)
1077
+ | beq TMP0, STR:RC, >5
1078
+ |. lw TMP1, offsetof(Node, val)+LO(NODE:TMP2)
1079
+ |4:
1080
+ | beqz NODE:TMP3, ->fff_restv // Not found, keep default result.
1081
+ |. move NODE:TMP2, NODE:TMP3
1082
+ | b <3
1083
+ |. nop
1084
+ |5:
1085
+ | beq CARG2, TISNIL, ->fff_restv // Ditto for nil value.
1086
+ |. nop
1087
+ | move CARG3, CARG2 // Return value of mt.__metatable.
1088
+ | b ->fff_restv
1089
+ |. move CARG1, TMP1
1090
+ |
1091
+ |6:
1092
+ | beq CARG3, AT, <1
1093
+ |. sltiu TMP0, CARG3, LJ_TISNUM
1094
+ | li TMP1, LJ_TISNUM
1095
+ | movz TMP1, CARG3, TMP0
1096
+ | not TMP1, TMP1
1097
+ | sll TMP1, TMP1, 2
1098
+ | addu TMP1, DISPATCH, TMP1
1099
+ | b <2
1100
+ |. lw TAB:CARG1, DISPATCH_GL(gcroot[GCROOT_BASEMT])(TMP1)
1101
+ |
1102
+ |.ffunc_2 setmetatable
1103
+ | // Fast path: no mt for table yet and not clearing the mt.
1104
+ | li AT, LJ_TTAB
1105
+ | bne CARG3, AT, ->fff_fallback
1106
+ |. addiu CARG4, CARG4, -LJ_TTAB
1107
+ | lw TAB:TMP1, TAB:CARG1->metatable
1108
+ | lbu TMP3, TAB:CARG1->marked
1109
+ | or AT, CARG4, TAB:TMP1
1110
+ | bnez AT, ->fff_fallback
1111
+ |. andi AT, TMP3, LJ_GC_BLACK // isblack(table)
1112
+ | beqz AT, ->fff_restv
1113
+ |. sw TAB:CARG2, TAB:CARG1->metatable
1114
+ | barrierback TAB:CARG1, TMP3, TMP0, ->fff_restv
1115
+ |
1116
+ |.ffunc rawget
1117
+ | lw CARG4, HI(BASE)
1118
+ | sltiu AT, NARGS8:RC, 16
1119
+ | lw TAB:CARG2, LO(BASE)
1120
+ | load_got lj_tab_get
1121
+ | addiu CARG4, CARG4, -LJ_TTAB
1122
+ | or AT, AT, CARG4
1123
+ | bnez AT, ->fff_fallback
1124
+ | addiu CARG3, BASE, 8
1125
+ | call_intern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key)
1126
+ |. move CARG1, L
1127
+ | // Returns cTValue *.
1128
+ | b ->fff_resn
1129
+ |. ldc1 FRET1, 0(CRET1)
1130
+ |
1131
+ |//-- Base library: conversions ------------------------------------------
1132
+ |
1133
+ |.ffunc tonumber
1134
+ | // Only handles the number case inline (without a base argument).
1135
+ | lw CARG1, HI(BASE)
1136
+ | xori AT, NARGS8:RC, 8
1137
+ | sltiu CARG1, CARG1, LJ_TISNUM
1138
+ | movn CARG1, r0, AT
1139
+ | beqz CARG1, ->fff_fallback // Exactly one number argument.
1140
+ |. ldc1 FRET1, 0(BASE)
1141
+ | b ->fff_resn
1142
+ |. nop
1143
+ |
1144
+ |.ffunc_1 tostring
1145
+ | // Only handles the string or number case inline.
1146
+ | li AT, LJ_TSTR
1147
+ | // A __tostring method in the string base metatable is ignored.
1148
+ | beq CARG3, AT, ->fff_restv // String key?
1149
+ | // Handle numbers inline, unless a number base metatable is present.
1150
+ |. lw TMP1, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])(DISPATCH)
1151
+ | sltiu TMP0, CARG3, LJ_TISNUM
1152
+ | sltiu TMP1, TMP1, 1
1153
+ | and TMP0, TMP0, TMP1
1154
+ | beqz TMP0, ->fff_fallback
1155
+ |. sw BASE, L->base // Add frame since C call can throw.
1156
+ | ffgccheck
1157
+ |. sw PC, SAVE_PC // Redundant (but a defined value).
1158
+ | load_got lj_strfmt_num
1159
+ | move CARG1, L
1160
+ | call_intern lj_strfmt_num // (lua_State *L, lua_Number *np)
1161
+ |. move CARG2, BASE
1162
+ | // Returns GCstr *.
1163
+ | li CARG3, LJ_TSTR
1164
+ | b ->fff_restv
1165
+ |. move CARG1, CRET1
1166
+ |
1167
+ |//-- Base library: iterators -------------------------------------------
1168
+ |
1169
+ |.ffunc next
1170
+ | lw CARG1, HI(BASE)
1171
+ | lw TAB:CARG2, LO(BASE)
1172
+ | beqz NARGS8:RC, ->fff_fallback
1173
+ |. addu TMP2, BASE, NARGS8:RC
1174
+ | li AT, LJ_TTAB
1175
+ | sw TISNIL, HI(TMP2) // Set missing 2nd arg to nil.
1176
+ | bne CARG1, AT, ->fff_fallback
1177
+ |. lw PC, FRAME_PC(BASE)
1178
+ | load_got lj_tab_next
1179
+ | sw BASE, L->base // Add frame since C call can throw.
1180
+ | sw BASE, L->top // Dummy frame length is ok.
1181
+ | addiu CARG3, BASE, 8
1182
+ | sw PC, SAVE_PC
1183
+ | call_intern lj_tab_next // (lua_State *L, GCtab *t, TValue *key)
1184
+ |. move CARG1, L
1185
+ | // Returns 0 at end of traversal.
1186
+ | beqz CRET1, ->fff_restv // End of traversal: return nil.
1187
+ |. li CARG3, LJ_TNIL
1188
+ | ldc1 f0, 8(BASE) // Copy key and value to results.
1189
+ | addiu RA, BASE, -8
1190
+ | ldc1 f2, 16(BASE)
1191
+ | li RD, (2+1)*8
1192
+ | sdc1 f0, 0(RA)
1193
+ | b ->fff_res
1194
+ |. sdc1 f2, 8(RA)
1195
+ |
1196
+ |.ffunc_1 pairs
1197
+ | li AT, LJ_TTAB
1198
+ | bne CARG3, AT, ->fff_fallback
1199
+ |. lw PC, FRAME_PC(BASE)
1200
+ #if LJ_52
1201
+ | lw TAB:TMP2, TAB:CARG1->metatable
1202
+ | ldc1 f0, CFUNC:RB->upvalue[0]
1203
+ | bnez TAB:TMP2, ->fff_fallback
1204
+ #else
1205
+ | ldc1 f0, CFUNC:RB->upvalue[0]
1206
+ #endif
1207
+ |. addiu RA, BASE, -8
1208
+ | sw TISNIL, 8+HI(BASE)
1209
+ | li RD, (3+1)*8
1210
+ | b ->fff_res
1211
+ |. sdc1 f0, 0(RA)
1212
+ |
1213
+ |.ffunc ipairs_aux
1214
+ | sltiu AT, NARGS8:RC, 16
1215
+ | lw CARG3, HI(BASE)
1216
+ | lw TAB:CARG1, LO(BASE)
1217
+ | lw CARG4, 8+HI(BASE)
1218
+ | bnez AT, ->fff_fallback
1219
+ |. ldc1 FARG2, 8(BASE)
1220
+ | addiu CARG3, CARG3, -LJ_TTAB
1221
+ | sltiu AT, CARG4, LJ_TISNUM
1222
+ | li TMP0, 1
1223
+ | movn AT, r0, CARG3
1224
+ | mtc1 TMP0, FARG1
1225
+ | beqz AT, ->fff_fallback
1226
+ |. lw PC, FRAME_PC(BASE)
1227
+ | trunc.w.d FRET1, FARG2
1228
+ | cvt.d.w FARG1, FARG1
1229
+ | lw TMP0, TAB:CARG1->asize
1230
+ | lw TMP1, TAB:CARG1->array
1231
+ | mfc1 TMP2, FRET1
1232
+ | addiu RA, BASE, -8
1233
+ | add.d FARG2, FARG2, FARG1
1234
+ | addiu TMP2, TMP2, 1
1235
+ | sltu AT, TMP2, TMP0
1236
+ | sll TMP3, TMP2, 3
1237
+ | addu TMP3, TMP1, TMP3
1238
+ | beqz AT, >2 // Not in array part?
1239
+ |. sdc1 FARG2, 0(RA)
1240
+ | lw TMP2, HI(TMP3)
1241
+ | ldc1 f0, 0(TMP3)
1242
+ |1:
1243
+ | beq TMP2, TISNIL, ->fff_res // End of iteration, return 0 results.
1244
+ |. li RD, (0+1)*8
1245
+ | li RD, (2+1)*8
1246
+ | b ->fff_res
1247
+ |. sdc1 f0, 8(RA)
1248
+ |2: // Check for empty hash part first. Otherwise call C function.
1249
+ | lw TMP0, TAB:CARG1->hmask
1250
+ | load_got lj_tab_getinth
1251
+ | beqz TMP0, ->fff_res
1252
+ |. li RD, (0+1)*8
1253
+ | call_intern lj_tab_getinth // (GCtab *t, int32_t key)
1254
+ |. move CARG2, TMP2
1255
+ | // Returns cTValue * or NULL.
1256
+ | beqz CRET1, ->fff_res
1257
+ |. li RD, (0+1)*8
1258
+ | lw TMP2, HI(CRET1)
1259
+ | b <1
1260
+ |. ldc1 f0, 0(CRET1)
1261
+ |
1262
+ |.ffunc_1 ipairs
1263
+ | li AT, LJ_TTAB
1264
+ | bne CARG3, AT, ->fff_fallback
1265
+ |. lw PC, FRAME_PC(BASE)
1266
+ #if LJ_52
1267
+ | lw TAB:TMP2, TAB:CARG1->metatable
1268
+ | ldc1 f0, CFUNC:RB->upvalue[0]
1269
+ | bnez TAB:TMP2, ->fff_fallback
1270
+ #else
1271
+ | ldc1 f0, CFUNC:RB->upvalue[0]
1272
+ #endif
1273
+ |. addiu RA, BASE, -8
1274
+ | sw r0, 8+HI(BASE)
1275
+ | sw r0, 8+LO(BASE)
1276
+ | li RD, (3+1)*8
1277
+ | b ->fff_res
1278
+ |. sdc1 f0, 0(RA)
1279
+ |
1280
+ |//-- Base library: catch errors ----------------------------------------
1281
+ |
1282
+ |.ffunc pcall
1283
+ | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH)
1284
+ | beqz NARGS8:RC, ->fff_fallback
1285
+ | move TMP2, BASE
1286
+ | addiu BASE, BASE, 8
1287
+ | // Remember active hook before pcall.
1288
+ | srl TMP3, TMP3, HOOK_ACTIVE_SHIFT
1289
+ | andi TMP3, TMP3, 1
1290
+ | addiu PC, TMP3, 8+FRAME_PCALL
1291
+ | b ->vm_call_dispatch
1292
+ |. addiu NARGS8:RC, NARGS8:RC, -8
1293
+ |
1294
+ |.ffunc xpcall
1295
+ | sltiu AT, NARGS8:RC, 16
1296
+ | lw CARG4, 8+HI(BASE)
1297
+ | bnez AT, ->fff_fallback
1298
+ |. ldc1 FARG2, 8(BASE)
1299
+ | ldc1 FARG1, 0(BASE)
1300
+ | lbu TMP1, DISPATCH_GL(hookmask)(DISPATCH)
1301
+ | li AT, LJ_TFUNC
1302
+ | move TMP2, BASE
1303
+ | bne CARG4, AT, ->fff_fallback // Traceback must be a function.
1304
+ | addiu BASE, BASE, 16
1305
+ | // Remember active hook before pcall.
1306
+ | srl TMP3, TMP3, HOOK_ACTIVE_SHIFT
1307
+ | sdc1 FARG2, 0(TMP2) // Swap function and traceback.
1308
+ | andi TMP3, TMP3, 1
1309
+ | sdc1 FARG1, 8(TMP2)
1310
+ | addiu PC, TMP3, 16+FRAME_PCALL
1311
+ | b ->vm_call_dispatch
1312
+ |. addiu NARGS8:RC, NARGS8:RC, -16
1313
+ |
1314
+ |//-- Coroutine library --------------------------------------------------
1315
+ |
1316
+ |.macro coroutine_resume_wrap, resume
1317
+ |.if resume
1318
+ |.ffunc_1 coroutine_resume
1319
+ | li AT, LJ_TTHREAD
1320
+ | bne CARG3, AT, ->fff_fallback
1321
+ |.else
1322
+ |.ffunc coroutine_wrap_aux
1323
+ | lw L:CARG1, CFUNC:RB->upvalue[0].gcr
1324
+ |.endif
1325
+ | lbu TMP0, L:CARG1->status
1326
+ | lw TMP1, L:CARG1->cframe
1327
+ | lw CARG2, L:CARG1->top
1328
+ | lw TMP2, L:CARG1->base
1329
+ | addiu TMP3, TMP0, -LUA_YIELD
1330
+ | bgtz TMP3, ->fff_fallback // st > LUA_YIELD?
1331
+ |. xor TMP2, TMP2, CARG2
1332
+ | bnez TMP1, ->fff_fallback // cframe != 0?
1333
+ |. or AT, TMP2, TMP0
1334
+ | lw TMP0, L:CARG1->maxstack
1335
+ | beqz AT, ->fff_fallback // base == top && st == 0?
1336
+ |. lw PC, FRAME_PC(BASE)
1337
+ | addu TMP2, CARG2, NARGS8:RC
1338
+ | sltu AT, TMP0, TMP2
1339
+ | bnez AT, ->fff_fallback // Stack overflow?
1340
+ |. sw PC, SAVE_PC
1341
+ | sw BASE, L->base
1342
+ |1:
1343
+ |.if resume
1344
+ | addiu BASE, BASE, 8 // Keep resumed thread in stack for GC.
1345
+ | addiu NARGS8:RC, NARGS8:RC, -8
1346
+ | addiu TMP2, TMP2, -8
1347
+ |.endif
1348
+ | sw TMP2, L:CARG1->top
1349
+ | addu TMP1, BASE, NARGS8:RC
1350
+ | move CARG3, CARG2
1351
+ | sw BASE, L->top
1352
+ |2: // Move args to coroutine.
1353
+ | ldc1 f0, 0(BASE)
1354
+ | sltu AT, BASE, TMP1
1355
+ | beqz AT, >3
1356
+ |. addiu BASE, BASE, 8
1357
+ | sdc1 f0, 0(CARG3)
1358
+ | b <2
1359
+ |. addiu CARG3, CARG3, 8
1360
+ |3:
1361
+ | bal ->vm_resume // (lua_State *L, TValue *base, 0, 0)
1362
+ |. move L:RA, L:CARG1
1363
+ | // Returns thread status.
1364
+ |4:
1365
+ | lw TMP2, L:RA->base
1366
+ | sltiu AT, CRET1, LUA_YIELD+1
1367
+ | lw TMP3, L:RA->top
1368
+ | li_vmstate INTERP
1369
+ | lw BASE, L->base
1370
+ | sw L, DISPATCH_GL(cur_L)(DISPATCH)
1371
+ | st_vmstate
1372
+ | beqz AT, >8
1373
+ |. subu RD, TMP3, TMP2
1374
+ | lw TMP0, L->maxstack
1375
+ | beqz RD, >6 // No results?
1376
+ |. addu TMP1, BASE, RD
1377
+ | sltu AT, TMP0, TMP1
1378
+ | bnez AT, >9 // Need to grow stack?
1379
+ |. addu TMP3, TMP2, RD
1380
+ | sw TMP2, L:RA->top // Clear coroutine stack.
1381
+ | move TMP1, BASE
1382
+ |5: // Move results from coroutine.
1383
+ | ldc1 f0, 0(TMP2)
1384
+ | addiu TMP2, TMP2, 8
1385
+ | sltu AT, TMP2, TMP3
1386
+ | sdc1 f0, 0(TMP1)
1387
+ | bnez AT, <5
1388
+ |. addiu TMP1, TMP1, 8
1389
+ |6:
1390
+ | andi TMP0, PC, FRAME_TYPE
1391
+ |.if resume
1392
+ | li TMP1, LJ_TTRUE
1393
+ | addiu RA, BASE, -8
1394
+ | sw TMP1, -8+HI(BASE) // Prepend true to results.
1395
+ | addiu RD, RD, 16
1396
+ |.else
1397
+ | move RA, BASE
1398
+ | addiu RD, RD, 8
1399
+ |.endif
1400
+ |7:
1401
+ | sw PC, SAVE_PC
1402
+ | beqz TMP0, ->BC_RET_Z
1403
+ |. move MULTRES, RD
1404
+ | b ->vm_return
1405
+ |. nop
1406
+ |
1407
+ |8: // Coroutine returned with error (at co->top-1).
1408
+ |.if resume
1409
+ | addiu TMP3, TMP3, -8
1410
+ | li TMP1, LJ_TFALSE
1411
+ | ldc1 f0, 0(TMP3)
1412
+ | sw TMP3, L:RA->top // Remove error from coroutine stack.
1413
+ | li RD, (2+1)*8
1414
+ | sw TMP1, -8+HI(BASE) // Prepend false to results.
1415
+ | addiu RA, BASE, -8
1416
+ | sdc1 f0, 0(BASE) // Copy error message.
1417
+ | b <7
1418
+ |. andi TMP0, PC, FRAME_TYPE
1419
+ |.else
1420
+ | load_got lj_ffh_coroutine_wrap_err
1421
+ | move CARG2, L:RA
1422
+ | call_intern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co)
1423
+ |. move CARG1, L
1424
+ |.endif
1425
+ |
1426
+ |9: // Handle stack expansion on return from yield.
1427
+ | load_got lj_state_growstack
1428
+ | srl CARG2, RD, 3
1429
+ | call_intern lj_state_growstack // (lua_State *L, int n)
1430
+ |. move CARG1, L
1431
+ | b <4
1432
+ |. li CRET1, 0
1433
+ |.endmacro
1434
+ |
1435
+ | coroutine_resume_wrap 1 // coroutine.resume
1436
+ | coroutine_resume_wrap 0 // coroutine.wrap
1437
+ |
1438
+ |.ffunc coroutine_yield
1439
+ | lw TMP0, L->cframe
1440
+ | addu TMP1, BASE, NARGS8:RC
1441
+ | sw BASE, L->base
1442
+ | andi TMP0, TMP0, CFRAME_RESUME
1443
+ | sw TMP1, L->top
1444
+ | beqz TMP0, ->fff_fallback
1445
+ |. li CRET1, LUA_YIELD
1446
+ | sw r0, L->cframe
1447
+ | b ->vm_leave_unw
1448
+ |. sb CRET1, L->status
1449
+ |
1450
+ |//-- Math library -------------------------------------------------------
1451
+ |
1452
+ |.ffunc_n math_abs
1453
+ |. abs.d FRET1, FARG1
1454
+ |->fff_resn:
1455
+ | lw PC, FRAME_PC(BASE)
1456
+ | addiu RA, BASE, -8
1457
+ | b ->fff_res1
1458
+ |. sdc1 FRET1, -8(BASE)
1459
+ |
1460
+ |->fff_restv:
1461
+ | // CARG3/CARG1 = TValue result.
1462
+ | lw PC, FRAME_PC(BASE)
1463
+ | sw CARG3, -8+HI(BASE)
1464
+ | addiu RA, BASE, -8
1465
+ | sw CARG1, -8+LO(BASE)
1466
+ |->fff_res1:
1467
+ | // RA = results, PC = return.
1468
+ | li RD, (1+1)*8
1469
+ |->fff_res:
1470
+ | // RA = results, RD = (nresults+1)*8, PC = return.
1471
+ | andi TMP0, PC, FRAME_TYPE
1472
+ | bnez TMP0, ->vm_return
1473
+ |. move MULTRES, RD
1474
+ | lw INS, -4(PC)
1475
+ | decode_RB8a RB, INS
1476
+ | decode_RB8b RB
1477
+ |5:
1478
+ | sltu AT, RD, RB
1479
+ | bnez AT, >6 // More results expected?
1480
+ |. decode_RA8a TMP0, INS
1481
+ | decode_RA8b TMP0
1482
+ | ins_next1
1483
+ | // Adjust BASE. KBASE is assumed to be set for the calling frame.
1484
+ | subu BASE, RA, TMP0
1485
+ | ins_next2
1486
+ |
1487
+ |6: // Fill up results with nil.
1488
+ | addu TMP1, RA, RD
1489
+ | addiu RD, RD, 8
1490
+ | b <5
1491
+ |. sw TISNIL, -8+HI(TMP1)
1492
+ |
1493
+ |.macro math_extern, func
1494
+ |->ff_math_ .. func:
1495
+ | lw CARG3, HI(BASE)
1496
+ | beqz NARGS8:RC, ->fff_fallback
1497
+ |. load_got func
1498
+ | sltiu AT, CARG3, LJ_TISNUM
1499
+ | beqz AT, ->fff_fallback
1500
+ |. nop
1501
+ | call_extern
1502
+ |. ldc1 FARG1, 0(BASE)
1503
+ | b ->fff_resn
1504
+ |. nop
1505
+ |.endmacro
1506
+ |
1507
+ |.macro math_extern2, func
1508
+ | .ffunc_nn math_ .. func
1509
+ |. load_got func
1510
+ | call_extern
1511
+ |. nop
1512
+ | b ->fff_resn
1513
+ |. nop
1514
+ |.endmacro
1515
+ |
1516
+ |.macro math_round, func
1517
+ | .ffunc_n math_ .. func
1518
+ |. nop
1519
+ | bal ->vm_ .. func
1520
+ |. nop
1521
+ | b ->fff_resn
1522
+ |. nop
1523
+ |.endmacro
1524
+ |
1525
+ | math_round floor
1526
+ | math_round ceil
1527
+ |
1528
+ |.ffunc math_log
1529
+ | lw CARG3, HI(BASE)
1530
+ | li AT, 8
1531
+ | bne NARGS8:RC, AT, ->fff_fallback // Exactly 1 argument.
1532
+ |. load_got log
1533
+ | sltiu AT, CARG3, LJ_TISNUM
1534
+ | beqz AT, ->fff_fallback
1535
+ |. nop
1536
+ | call_extern
1537
+ |. ldc1 FARG1, 0(BASE)
1538
+ | b ->fff_resn
1539
+ |. nop
1540
+ |
1541
+ | math_extern log10
1542
+ | math_extern exp
1543
+ | math_extern sin
1544
+ | math_extern cos
1545
+ | math_extern tan
1546
+ | math_extern asin
1547
+ | math_extern acos
1548
+ | math_extern atan
1549
+ | math_extern sinh
1550
+ | math_extern cosh
1551
+ | math_extern tanh
1552
+ | math_extern2 pow
1553
+ | math_extern2 atan2
1554
+ | math_extern2 fmod
1555
+ |
1556
+ |.ffunc_n math_sqrt
1557
+ |. sqrt.d FRET1, FARG1
1558
+ | b ->fff_resn
1559
+ |. nop
1560
+ |
1561
+ |.ffunc_nn math_ldexp
1562
+ | trunc.w.d FARG2, FARG2
1563
+ | load_got ldexp
1564
+ | mfc1 CARG3, FARG2
1565
+ | call_extern
1566
+ |. nop
1567
+ | b ->fff_resn
1568
+ |. nop
1569
+ |
1570
+ |.ffunc_n math_frexp
1571
+ | load_got frexp
1572
+ | lw PC, FRAME_PC(BASE)
1573
+ | call_extern
1574
+ |. addiu CARG3, DISPATCH, DISPATCH_GL(tmptv)
1575
+ | lw TMP1, DISPATCH_GL(tmptv)(DISPATCH)
1576
+ | addiu RA, BASE, -8
1577
+ | mtc1 TMP1, FARG2
1578
+ | sdc1 FRET1, 0(RA)
1579
+ | cvt.d.w FARG2, FARG2
1580
+ | sdc1 FARG2, 8(RA)
1581
+ | b ->fff_res
1582
+ |. li RD, (2+1)*8
1583
+ |
1584
+ |.ffunc_n math_modf
1585
+ | load_got modf
1586
+ | lw PC, FRAME_PC(BASE)
1587
+ | call_extern
1588
+ |. addiu CARG3, BASE, -8
1589
+ | addiu RA, BASE, -8
1590
+ | sdc1 FRET1, 0(BASE)
1591
+ | b ->fff_res
1592
+ |. li RD, (2+1)*8
1593
+ |
1594
+ |.macro math_minmax, name, ismax
1595
+ |->ff_ .. name:
1596
+ | lw CARG3, HI(BASE)
1597
+ | beqz NARGS8:RC, ->fff_fallback
1598
+ |. ldc1 FRET1, 0(BASE)
1599
+ | sltiu AT, CARG3, LJ_TISNUM
1600
+ | beqz AT, ->fff_fallback
1601
+ |. addu TMP2, BASE, NARGS8:RC
1602
+ | addiu TMP1, BASE, 8
1603
+ | beq TMP1, TMP2, ->fff_resn
1604
+ |1:
1605
+ |. lw CARG3, HI(TMP1)
1606
+ | ldc1 FARG1, 0(TMP1)
1607
+ | addiu TMP1, TMP1, 8
1608
+ | sltiu AT, CARG3, LJ_TISNUM
1609
+ | beqz AT, ->fff_fallback
1610
+ |.if ismax
1611
+ |. c.olt.d FARG1, FRET1
1612
+ |.else
1613
+ |. c.olt.d FRET1, FARG1
1614
+ |.endif
1615
+ | bne TMP1, TMP2, <1
1616
+ |. movf.d FRET1, FARG1
1617
+ | b ->fff_resn
1618
+ |. nop
1619
+ |.endmacro
1620
+ |
1621
+ | math_minmax math_min, 0
1622
+ | math_minmax math_max, 1
1623
+ |
1624
+ |//-- String library -----------------------------------------------------
1625
+ |
1626
+ |.ffunc string_byte // Only handle the 1-arg case here.
1627
+ | lw CARG3, HI(BASE)
1628
+ | lw STR:CARG1, LO(BASE)
1629
+ | xori AT, NARGS8:RC, 8
1630
+ | addiu CARG3, CARG3, -LJ_TSTR
1631
+ | or AT, AT, CARG3
1632
+ | bnez AT, ->fff_fallback // Need exactly 1 string argument.
1633
+ |. nop
1634
+ | lw TMP0, STR:CARG1->len
1635
+ | lbu TMP1, STR:CARG1[1] // Access is always ok (NUL at end).
1636
+ | addiu RA, BASE, -8
1637
+ | sltu RD, r0, TMP0
1638
+ | mtc1 TMP1, f0
1639
+ | addiu RD, RD, 1
1640
+ | cvt.d.w f0, f0
1641
+ | lw PC, FRAME_PC(BASE)
1642
+ | sll RD, RD, 3 // RD = ((str->len != 0)+1)*8
1643
+ | b ->fff_res
1644
+ |. sdc1 f0, 0(RA)
1645
+ |
1646
+ |.ffunc string_char // Only handle the 1-arg case here.
1647
+ | ffgccheck
1648
+ | lw CARG3, HI(BASE)
1649
+ | ldc1 FARG1, 0(BASE)
1650
+ | li AT, 8
1651
+ | bne NARGS8:RC, AT, ->fff_fallback // Exactly 1 argument.
1652
+ |. sltiu AT, CARG3, LJ_TISNUM
1653
+ | beqz AT, ->fff_fallback
1654
+ |. li CARG3, 1
1655
+ | trunc.w.d FARG1, FARG1
1656
+ | addiu CARG2, sp, ARG5_OFS
1657
+ | sltiu AT, TMP0, 256
1658
+ | mfc1 TMP0, FARG1
1659
+ | beqz AT, ->fff_fallback
1660
+ |. sw TMP0, ARG5
1661
+ |->fff_newstr:
1662
+ | load_got lj_str_new
1663
+ | sw BASE, L->base
1664
+ | sw PC, SAVE_PC
1665
+ | call_intern lj_str_new // (lua_State *L, char *str, size_t l)
1666
+ |. move CARG1, L
1667
+ | // Returns GCstr *.
1668
+ | lw BASE, L->base
1669
+ |->fff_resstr:
1670
+ | move CARG1, CRET1
1671
+ | b ->fff_restv
1672
+ |. li CARG3, LJ_TSTR
1673
+ |
1674
+ |.ffunc string_sub
1675
+ | ffgccheck
1676
+ | addiu AT, NARGS8:RC, -16
1677
+ | lw CARG3, 16+HI(BASE)
1678
+ | ldc1 f0, 16(BASE)
1679
+ | lw TMP0, HI(BASE)
1680
+ | lw STR:CARG1, LO(BASE)
1681
+ | bltz AT, ->fff_fallback
1682
+ | lw CARG2, 8+HI(BASE)
1683
+ | ldc1 f2, 8(BASE)
1684
+ | beqz AT, >1
1685
+ |. li CARG4, -1
1686
+ | trunc.w.d f0, f0
1687
+ | sltiu AT, CARG3, LJ_TISNUM
1688
+ | beqz AT, ->fff_fallback
1689
+ |. mfc1 CARG4, f0
1690
+ |1:
1691
+ | sltiu AT, CARG2, LJ_TISNUM
1692
+ | beqz AT, ->fff_fallback
1693
+ |. li AT, LJ_TSTR
1694
+ | trunc.w.d f2, f2
1695
+ | bne TMP0, AT, ->fff_fallback
1696
+ |. lw CARG2, STR:CARG1->len
1697
+ | mfc1 CARG3, f2
1698
+ | // STR:CARG1 = str, CARG2 = str->len, CARG3 = start, CARG4 = end
1699
+ | slt AT, CARG4, r0
1700
+ | addiu TMP0, CARG2, 1
1701
+ | addu TMP1, CARG4, TMP0
1702
+ | slt TMP3, CARG3, r0
1703
+ | movn CARG4, TMP1, AT // if (end < 0) end += len+1
1704
+ | addu TMP1, CARG3, TMP0
1705
+ | movn CARG3, TMP1, TMP3 // if (start < 0) start += len+1
1706
+ | li TMP2, 1
1707
+ | slt AT, CARG4, r0
1708
+ | slt TMP3, r0, CARG3
1709
+ | movn CARG4, r0, AT // if (end < 0) end = 0
1710
+ | movz CARG3, TMP2, TMP3 // if (start < 1) start = 1
1711
+ | slt AT, CARG2, CARG4
1712
+ | movn CARG4, CARG2, AT // if (end > len) end = len
1713
+ | addu CARG2, STR:CARG1, CARG3
1714
+ | subu CARG3, CARG4, CARG3 // len = end - start
1715
+ | addiu CARG2, CARG2, sizeof(GCstr)-1
1716
+ | bgez CARG3, ->fff_newstr
1717
+ |. addiu CARG3, CARG3, 1 // len++
1718
+ |->fff_emptystr: // Return empty string.
1719
+ | addiu STR:CARG1, DISPATCH, DISPATCH_GL(strempty)
1720
+ | b ->fff_restv
1721
+ |. li CARG3, LJ_TSTR
1722
+ |
1723
+ |.macro ffstring_op, name
1724
+ | .ffunc string_ .. name
1725
+ | ffgccheck
1726
+ | lw CARG3, HI(BASE)
1727
+ | lw STR:CARG2, LO(BASE)
1728
+ | beqz NARGS8:RC, ->fff_fallback
1729
+ |. li AT, LJ_TSTR
1730
+ | bne CARG3, AT, ->fff_fallback
1731
+ |. addiu SBUF:CARG1, DISPATCH, DISPATCH_GL(tmpbuf)
1732
+ | load_got lj_buf_putstr_ .. name
1733
+ | lw TMP0, SBUF:CARG1->b
1734
+ | sw L, SBUF:CARG1->L
1735
+ | sw BASE, L->base
1736
+ | sw TMP0, SBUF:CARG1->p
1737
+ | call_intern extern lj_buf_putstr_ .. name
1738
+ |. sw PC, SAVE_PC
1739
+ | load_got lj_buf_tostr
1740
+ | call_intern lj_buf_tostr
1741
+ |. move SBUF:CARG1, SBUF:CRET1
1742
+ | b ->fff_resstr
1743
+ |. lw BASE, L->base
1744
+ |.endmacro
1745
+ |
1746
+ |ffstring_op reverse
1747
+ |ffstring_op lower
1748
+ |ffstring_op upper
1749
+ |
1750
+ |//-- Bit library --------------------------------------------------------
1751
+ |
1752
+ |.macro .ffunc_bit, name
1753
+ | .ffunc_n bit_..name
1754
+ |. add.d FARG1, FARG1, TOBIT
1755
+ | mfc1 CRET1, FARG1
1756
+ |.endmacro
1757
+ |
1758
+ |.macro .ffunc_bit_op, name, ins
1759
+ | .ffunc_bit name
1760
+ | addiu TMP1, BASE, 8
1761
+ | addu TMP2, BASE, NARGS8:RC
1762
+ |1:
1763
+ | lw CARG4, HI(TMP1)
1764
+ | beq TMP1, TMP2, ->fff_resi
1765
+ |. ldc1 FARG1, 0(TMP1)
1766
+ | sltiu AT, CARG4, LJ_TISNUM
1767
+ | beqz AT, ->fff_fallback
1768
+ | add.d FARG1, FARG1, TOBIT
1769
+ | mfc1 CARG2, FARG1
1770
+ | ins CRET1, CRET1, CARG2
1771
+ | b <1
1772
+ |. addiu TMP1, TMP1, 8
1773
+ |.endmacro
1774
+ |
1775
+ |.ffunc_bit_op band, and
1776
+ |.ffunc_bit_op bor, or
1777
+ |.ffunc_bit_op bxor, xor
1778
+ |
1779
+ |.ffunc_bit bswap
1780
+ | srl TMP0, CRET1, 24
1781
+ | srl TMP2, CRET1, 8
1782
+ | sll TMP1, CRET1, 24
1783
+ | andi TMP2, TMP2, 0xff00
1784
+ | or TMP0, TMP0, TMP1
1785
+ | andi CRET1, CRET1, 0xff00
1786
+ | or TMP0, TMP0, TMP2
1787
+ | sll CRET1, CRET1, 8
1788
+ | b ->fff_resi
1789
+ |. or CRET1, TMP0, CRET1
1790
+ |
1791
+ |.ffunc_bit bnot
1792
+ | b ->fff_resi
1793
+ |. not CRET1, CRET1
1794
+ |
1795
+ |.macro .ffunc_bit_sh, name, ins, shmod
1796
+ | .ffunc_nn bit_..name
1797
+ |. add.d FARG1, FARG1, TOBIT
1798
+ | add.d FARG2, FARG2, TOBIT
1799
+ | mfc1 CARG1, FARG1
1800
+ | mfc1 CARG2, FARG2
1801
+ |.if shmod == 1
1802
+ | li AT, 32
1803
+ | subu TMP0, AT, CARG2
1804
+ | sllv CARG2, CARG1, CARG2
1805
+ | srlv CARG1, CARG1, TMP0
1806
+ |.elif shmod == 2
1807
+ | li AT, 32
1808
+ | subu TMP0, AT, CARG2
1809
+ | srlv CARG2, CARG1, CARG2
1810
+ | sllv CARG1, CARG1, TMP0
1811
+ |.endif
1812
+ | b ->fff_resi
1813
+ |. ins CRET1, CARG1, CARG2
1814
+ |.endmacro
1815
+ |
1816
+ |.ffunc_bit_sh lshift, sllv, 0
1817
+ |.ffunc_bit_sh rshift, srlv, 0
1818
+ |.ffunc_bit_sh arshift, srav, 0
1819
+ |// Can't use rotrv, since it's only in MIPS32R2.
1820
+ |.ffunc_bit_sh rol, or, 1
1821
+ |.ffunc_bit_sh ror, or, 2
1822
+ |
1823
+ |.ffunc_bit tobit
1824
+ |->fff_resi:
1825
+ | mtc1 CRET1, FRET1
1826
+ | b ->fff_resn
1827
+ |. cvt.d.w FRET1, FRET1
1828
+ |
1829
+ |//-----------------------------------------------------------------------
1830
+ |
1831
+ |->fff_fallback: // Call fast function fallback handler.
1832
+ | // BASE = new base, RB = CFUNC, RC = nargs*8
1833
+ | lw TMP3, CFUNC:RB->f
1834
+ | addu TMP1, BASE, NARGS8:RC
1835
+ | lw PC, FRAME_PC(BASE) // Fallback may overwrite PC.
1836
+ | addiu TMP0, TMP1, 8*LUA_MINSTACK
1837
+ | lw TMP2, L->maxstack
1838
+ | sw PC, SAVE_PC // Redundant (but a defined value).
1839
+ | sltu AT, TMP2, TMP0
1840
+ | sw BASE, L->base
1841
+ | sw TMP1, L->top
1842
+ | bnez AT, >5 // Need to grow stack.
1843
+ |. move CFUNCADDR, TMP3
1844
+ | jalr TMP3 // (lua_State *L)
1845
+ |. move CARG1, L
1846
+ | // Either throws an error, or recovers and returns -1, 0 or nresults+1.
1847
+ | lw BASE, L->base
1848
+ | sll RD, CRET1, 3
1849
+ | bgtz CRET1, ->fff_res // Returned nresults+1?
1850
+ |. addiu RA, BASE, -8
1851
+ |1: // Returned 0 or -1: retry fast path.
1852
+ | lw TMP0, L->top
1853
+ | lw LFUNC:RB, FRAME_FUNC(BASE)
1854
+ | bnez CRET1, ->vm_call_tail // Returned -1?
1855
+ |. subu NARGS8:RC, TMP0, BASE
1856
+ | ins_callt // Returned 0: retry fast path.
1857
+ |
1858
+ |// Reconstruct previous base for vmeta_call during tailcall.
1859
+ |->vm_call_tail:
1860
+ | andi TMP0, PC, FRAME_TYPE
1861
+ | li AT, -4
1862
+ | bnez TMP0, >3
1863
+ |. and TMP1, PC, AT
1864
+ | lbu TMP1, OFS_RA(PC)
1865
+ | sll TMP1, TMP1, 3
1866
+ | addiu TMP1, TMP1, 8
1867
+ |3:
1868
+ | b ->vm_call_dispatch // Resolve again for tailcall.
1869
+ |. subu TMP2, BASE, TMP1
1870
+ |
1871
+ |5: // Grow stack for fallback handler.
1872
+ | load_got lj_state_growstack
1873
+ | li CARG2, LUA_MINSTACK
1874
+ | call_intern lj_state_growstack // (lua_State *L, int n)
1875
+ |. move CARG1, L
1876
+ | lw BASE, L->base
1877
+ | b <1
1878
+ |. li CRET1, 0 // Force retry.
1879
+ |
1880
+ |->fff_gcstep: // Call GC step function.
1881
+ | // BASE = new base, RC = nargs*8
1882
+ | move MULTRES, ra
1883
+ | load_got lj_gc_step
1884
+ | sw BASE, L->base
1885
+ | addu TMP0, BASE, NARGS8:RC
1886
+ | sw PC, SAVE_PC // Redundant (but a defined value).
1887
+ | sw TMP0, L->top
1888
+ | call_intern lj_gc_step // (lua_State *L)
1889
+ |. move CARG1, L
1890
+ | lw BASE, L->base
1891
+ | move ra, MULTRES
1892
+ | lw TMP0, L->top
1893
+ | lw CFUNC:RB, FRAME_FUNC(BASE)
1894
+ | jr ra
1895
+ |. subu NARGS8:RC, TMP0, BASE
1896
+ |
1897
+ |//-----------------------------------------------------------------------
1898
+ |//-- Special dispatch targets -------------------------------------------
1899
+ |//-----------------------------------------------------------------------
1900
+ |
1901
+ |->vm_record: // Dispatch target for recording phase.
1902
+ |.if JIT
1903
+ | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH)
1904
+ | andi AT, TMP3, HOOK_VMEVENT // No recording while in vmevent.
1905
+ | bnez AT, >5
1906
+ | // Decrement the hookcount for consistency, but always do the call.
1907
+ |. lw TMP2, DISPATCH_GL(hookcount)(DISPATCH)
1908
+ | andi AT, TMP3, HOOK_ACTIVE
1909
+ | bnez AT, >1
1910
+ |. addiu TMP2, TMP2, -1
1911
+ | andi AT, TMP3, LUA_MASKLINE|LUA_MASKCOUNT
1912
+ | beqz AT, >1
1913
+ |. nop
1914
+ | b >1
1915
+ |. sw TMP2, DISPATCH_GL(hookcount)(DISPATCH)
1916
+ |.endif
1917
+ |
1918
+ |->vm_rethook: // Dispatch target for return hooks.
1919
+ | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH)
1920
+ | andi AT, TMP3, HOOK_ACTIVE // Hook already active?
1921
+ | beqz AT, >1
1922
+ |5: // Re-dispatch to static ins.
1923
+ |. lw AT, GG_DISP2STATIC(TMP0) // Assumes TMP0 holds DISPATCH+OP*4.
1924
+ | jr AT
1925
+ |. nop
1926
+ |
1927
+ |->vm_inshook: // Dispatch target for instr/line hooks.
1928
+ | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH)
1929
+ | lw TMP2, DISPATCH_GL(hookcount)(DISPATCH)
1930
+ | andi AT, TMP3, HOOK_ACTIVE // Hook already active?
1931
+ | bnez AT, <5
1932
+ |. andi AT, TMP3, LUA_MASKLINE|LUA_MASKCOUNT
1933
+ | beqz AT, <5
1934
+ |. addiu TMP2, TMP2, -1
1935
+ | beqz TMP2, >1
1936
+ |. sw TMP2, DISPATCH_GL(hookcount)(DISPATCH)
1937
+ | andi AT, TMP3, LUA_MASKLINE
1938
+ | beqz AT, <5
1939
+ |1:
1940
+ |. load_got lj_dispatch_ins
1941
+ | sw MULTRES, SAVE_MULTRES
1942
+ | move CARG2, PC
1943
+ | sw BASE, L->base
1944
+ | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC.
1945
+ | call_intern lj_dispatch_ins // (lua_State *L, const BCIns *pc)
1946
+ |. move CARG1, L
1947
+ |3:
1948
+ | lw BASE, L->base
1949
+ |4: // Re-dispatch to static ins.
1950
+ | lw INS, -4(PC)
1951
+ | decode_OP4a TMP1, INS
1952
+ | decode_OP4b TMP1
1953
+ | addu TMP0, DISPATCH, TMP1
1954
+ | decode_RD8a RD, INS
1955
+ | lw AT, GG_DISP2STATIC(TMP0)
1956
+ | decode_RA8a RA, INS
1957
+ | decode_RD8b RD
1958
+ | jr AT
1959
+ | decode_RA8b RA
1960
+ |
1961
+ |->cont_hook: // Continue from hook yield.
1962
+ | addiu PC, PC, 4
1963
+ | b <4
1964
+ |. lw MULTRES, -24+LO(RB) // Restore MULTRES for *M ins.
1965
+ |
1966
+ |->vm_hotloop: // Hot loop counter underflow.
1967
+ |.if JIT
1968
+ | lw LFUNC:TMP1, FRAME_FUNC(BASE)
1969
+ | addiu CARG1, DISPATCH, GG_DISP2J
1970
+ | sw PC, SAVE_PC
1971
+ | lw TMP1, LFUNC:TMP1->pc
1972
+ | move CARG2, PC
1973
+ | sw L, DISPATCH_J(L)(DISPATCH)
1974
+ | lbu TMP1, PC2PROTO(framesize)(TMP1)
1975
+ | load_got lj_trace_hot
1976
+ | sw BASE, L->base
1977
+ | sll TMP1, TMP1, 3
1978
+ | addu TMP1, BASE, TMP1
1979
+ | call_intern lj_trace_hot // (jit_State *J, const BCIns *pc)
1980
+ |. sw TMP1, L->top
1981
+ | b <3
1982
+ |. nop
1983
+ |.endif
1984
+ |
1985
+ |->vm_callhook: // Dispatch target for call hooks.
1986
+ |.if JIT
1987
+ | b >1
1988
+ |.endif
1989
+ |. move CARG2, PC
1990
+ |
1991
+ |->vm_hotcall: // Hot call counter underflow.
1992
+ |.if JIT
1993
+ | ori CARG2, PC, 1
1994
+ |1:
1995
+ |.endif
1996
+ | load_got lj_dispatch_call
1997
+ | addu TMP0, BASE, RC
1998
+ | sw PC, SAVE_PC
1999
+ | sw BASE, L->base
2000
+ | subu RA, RA, BASE
2001
+ | sw TMP0, L->top
2002
+ | call_intern lj_dispatch_call // (lua_State *L, const BCIns *pc)
2003
+ |. move CARG1, L
2004
+ | // Returns ASMFunction.
2005
+ | lw BASE, L->base
2006
+ | lw TMP0, L->top
2007
+ | sw r0, SAVE_PC // Invalidate for subsequent line hook.
2008
+ | subu NARGS8:RC, TMP0, BASE
2009
+ | addu RA, BASE, RA
2010
+ | lw LFUNC:RB, FRAME_FUNC(BASE)
2011
+ | jr CRET1
2012
+ |. lw INS, -4(PC)
2013
+ |
2014
+ |->cont_stitch: // Trace stitching.
2015
+ |.if JIT
2016
+ | // RA = resultptr, RB = meta base
2017
+ | lw INS, -4(PC)
2018
+ | lw TMP3, -24+LO(RB) // Save previous trace number.
2019
+ | decode_RA8a RC, INS
2020
+ | addiu AT, MULTRES, -8
2021
+ | decode_RA8b RC
2022
+ | beqz AT, >2
2023
+ |. addu RC, BASE, RC // Call base.
2024
+ |1: // Move results down.
2025
+ | ldc1 f0, 0(RA)
2026
+ | addiu AT, AT, -8
2027
+ | addiu RA, RA, 8
2028
+ | sdc1 f0, 0(RC)
2029
+ | bnez AT, <1
2030
+ |. addiu RC, RC, 8
2031
+ |2:
2032
+ | decode_RA8a RA, INS
2033
+ | decode_RB8a RB, INS
2034
+ | decode_RA8b RA
2035
+ | decode_RB8b RB
2036
+ | addu RA, RA, RB
2037
+ | lw TMP1, DISPATCH_J(trace)(DISPATCH)
2038
+ | addu RA, BASE, RA
2039
+ |3:
2040
+ | sltu AT, RC, RA
2041
+ | bnez AT, >9 // More results wanted?
2042
+ |. sll TMP2, TMP3, 2
2043
+ |
2044
+ | addu TMP2, TMP1, TMP2
2045
+ | lw TRACE:TMP2, 0(TMP2)
2046
+ | beqz TRACE:TMP2, ->cont_nop
2047
+ |. nop
2048
+ | lhu RD, TRACE:TMP2->link
2049
+ | beq RD, TMP3, ->cont_nop // Blacklisted.
2050
+ |. load_got lj_dispatch_stitch
2051
+ | bnez RD, =>BC_JLOOP // Jump to stitched trace.
2052
+ |. sll RD, RD, 3
2053
+ |
2054
+ | // Stitch a new trace to the previous trace.
2055
+ | sw TMP3, DISPATCH_J(exitno)(DISPATCH)
2056
+ | sw L, DISPATCH_J(L)(DISPATCH)
2057
+ | sw BASE, L->base
2058
+ | addiu CARG1, DISPATCH, GG_DISP2J
2059
+ | call_intern lj_dispatch_stitch // (jit_State *J, const BCIns *pc)
2060
+ |. move CARG2, PC
2061
+ | b ->cont_nop
2062
+ |. lw BASE, L->base
2063
+ |
2064
+ |9:
2065
+ | sw TISNIL, HI(RC)
2066
+ | b <3
2067
+ |. addiu RC, RC, 8
2068
+ |.endif
2069
+ |
2070
+ |->vm_profhook: // Dispatch target for profiler hook.
2071
+ #if LJ_HASPROFILE
2072
+ | load_got lj_dispatch_profile
2073
+ | sw MULTRES, SAVE_MULTRES
2074
+ | move CARG2, PC
2075
+ | sw BASE, L->base
2076
+ | call_intern lj_dispatch_profile // (lua_State *L, const BCIns *pc)
2077
+ |. move CARG1, L
2078
+ | // HOOK_PROFILE is off again, so re-dispatch to dynamic instruction.
2079
+ | addiu PC, PC, -4
2080
+ | b ->cont_nop
2081
+ |. lw BASE, L->base
2082
+ #endif
2083
+ |
2084
+ |//-----------------------------------------------------------------------
2085
+ |//-- Trace exit handler -------------------------------------------------
2086
+ |//-----------------------------------------------------------------------
2087
+ |
2088
+ |.macro savex_, a, b
2089
+ | sdc1 f..a, 16+a*8(sp)
2090
+ | sw r..a, 16+32*8+a*4(sp)
2091
+ | sw r..b, 16+32*8+b*4(sp)
2092
+ |.endmacro
2093
+ |
2094
+ |->vm_exit_handler:
2095
+ |.if JIT
2096
+ | addiu sp, sp, -(16+32*8+32*4)
2097
+ | savex_ 0, 1
2098
+ | savex_ 2, 3
2099
+ | savex_ 4, 5
2100
+ | savex_ 6, 7
2101
+ | savex_ 8, 9
2102
+ | savex_ 10, 11
2103
+ | savex_ 12, 13
2104
+ | savex_ 14, 15
2105
+ | savex_ 16, 17
2106
+ | savex_ 18, 19
2107
+ | savex_ 20, 21
2108
+ | savex_ 22, 23
2109
+ | savex_ 24, 25
2110
+ | savex_ 26, 27
2111
+ | sdc1 f28, 16+28*8(sp)
2112
+ | sw r28, 16+32*8+28*4(sp)
2113
+ | sdc1 f30, 16+30*8(sp)
2114
+ | sw r30, 16+32*8+30*4(sp)
2115
+ | sw r0, 16+32*8+31*4(sp) // Clear RID_TMP.
2116
+ | li_vmstate EXIT
2117
+ | addiu TMP2, sp, 16+32*8+32*4 // Recompute original value of sp.
2118
+ | addiu DISPATCH, JGL, -GG_DISP2G-32768
2119
+ | lw TMP1, 0(TMP2) // Load exit number.
2120
+ | st_vmstate
2121
+ | sw TMP2, 16+32*8+29*4(sp) // Store sp in RID_SP.
2122
+ | lw L, DISPATCH_GL(cur_L)(DISPATCH)
2123
+ | lw BASE, DISPATCH_GL(jit_base)(DISPATCH)
2124
+ | load_got lj_trace_exit
2125
+ | sw L, DISPATCH_J(L)(DISPATCH)
2126
+ | sw ra, DISPATCH_J(parent)(DISPATCH) // Store trace number.
2127
+ | sw BASE, L->base
2128
+ | sw TMP1, DISPATCH_J(exitno)(DISPATCH) // Store exit number.
2129
+ | addiu CARG1, DISPATCH, GG_DISP2J
2130
+ | sw r0, DISPATCH_GL(jit_base)(DISPATCH)
2131
+ | call_intern lj_trace_exit // (jit_State *J, ExitState *ex)
2132
+ |. addiu CARG2, sp, 16
2133
+ | // Returns MULTRES (unscaled) or negated error code.
2134
+ | lw TMP1, L->cframe
2135
+ | li AT, -4
2136
+ | lw BASE, L->base
2137
+ | and sp, TMP1, AT
2138
+ | lw PC, SAVE_PC // Get SAVE_PC.
2139
+ | b >1
2140
+ |. sw L, SAVE_L // Set SAVE_L (on-trace resume/yield).
2141
+ |.endif
2142
+ |->vm_exit_interp:
2143
+ |.if JIT
2144
+ | // CRET1 = MULTRES or negated error code, BASE, PC and JGL set.
2145
+ | lw L, SAVE_L
2146
+ | addiu DISPATCH, JGL, -GG_DISP2G-32768
2147
+ | sw BASE, L->base
2148
+ |1:
2149
+ | bltz CRET1, >9 // Check for error from exit.
2150
+ |. lw LFUNC:RB, FRAME_FUNC(BASE)
2151
+ | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
2152
+ | sll MULTRES, CRET1, 3
2153
+ | li TISNIL, LJ_TNIL
2154
+ | sw MULTRES, SAVE_MULTRES
2155
+ | mtc1 TMP3, TOBIT
2156
+ | lw TMP1, LFUNC:RB->pc
2157
+ | sw r0, DISPATCH_GL(jit_base)(DISPATCH)
2158
+ | lw KBASE, PC2PROTO(k)(TMP1)
2159
+ | cvt.d.s TOBIT, TOBIT
2160
+ | // Modified copy of ins_next which handles function header dispatch, too.
2161
+ | lw INS, 0(PC)
2162
+ | addiu PC, PC, 4
2163
+ | // Assumes TISNIL == ~LJ_VMST_INTERP == -1
2164
+ | sw TISNIL, DISPATCH_GL(vmstate)(DISPATCH)
2165
+ | decode_OP4a TMP1, INS
2166
+ | decode_OP4b TMP1
2167
+ | sltiu TMP2, TMP1, BC_FUNCF*4 // Function header?
2168
+ | addu TMP0, DISPATCH, TMP1
2169
+ | decode_RD8a RD, INS
2170
+ | lw AT, 0(TMP0)
2171
+ | decode_RA8a RA, INS
2172
+ | beqz TMP2, >2
2173
+ |. decode_RA8b RA
2174
+ | jr AT
2175
+ |. decode_RD8b RD
2176
+ |2:
2177
+ | sltiu TMP2, TMP1, (BC_FUNCC+2)*4 // Fast function?
2178
+ | bnez TMP2, >3
2179
+ |. lw TMP1, FRAME_PC(BASE)
2180
+ | // Check frame below fast function.
2181
+ | andi TMP0, TMP1, FRAME_TYPE
2182
+ | bnez TMP0, >3 // Trace stitching continuation?
2183
+ |. nop
2184
+ | // Otherwise set KBASE for Lua function below fast function.
2185
+ | lw TMP2, -4(TMP1)
2186
+ | decode_RA8a TMP0, TMP2
2187
+ | decode_RA8b TMP0
2188
+ | subu TMP1, BASE, TMP0
2189
+ | lw LFUNC:TMP2, -8+FRAME_FUNC(TMP1)
2190
+ | lw TMP1, LFUNC:TMP2->pc
2191
+ | lw KBASE, PC2PROTO(k)(TMP1)
2192
+ |3:
2193
+ | addiu RC, MULTRES, -8
2194
+ | jr AT
2195
+ |. addu RA, RA, BASE
2196
+ |
2197
+ |9: // Rethrow error from the right C frame.
2198
+ | load_got lj_err_throw
2199
+ | negu CARG2, CRET1
2200
+ | call_intern lj_err_throw // (lua_State *L, int errcode)
2201
+ |. move CARG1, L
2202
+ |.endif
2203
+ |
2204
+ |//-----------------------------------------------------------------------
2205
+ |//-- Math helper functions ----------------------------------------------
2206
+ |//-----------------------------------------------------------------------
2207
+ |
2208
+ |// Modifies AT, TMP0, FRET1, FRET2, f4. Keeps all others incl. FARG1.
2209
+ |.macro vm_round, func
2210
+ | lui TMP0, 0x4330 // Hiword of 2^52 (double).
2211
+ | mtc1 r0, f4
2212
+ | mtc1 TMP0, f5
2213
+ | abs.d FRET2, FARG1 // |x|
2214
+ | mfc1 AT, f13
2215
+ | c.olt.d 0, FRET2, f4
2216
+ | add.d FRET1, FRET2, f4 // (|x| + 2^52) - 2^52
2217
+ | bc1f 0, >1 // Truncate only if |x| < 2^52.
2218
+ |. sub.d FRET1, FRET1, f4
2219
+ | slt AT, AT, r0
2220
+ |.if "func" == "ceil"
2221
+ | lui TMP0, 0xbff0 // Hiword of -1 (double). Preserves -0.
2222
+ |.else
2223
+ | lui TMP0, 0x3ff0 // Hiword of +1 (double).
2224
+ |.endif
2225
+ |.if "func" == "trunc"
2226
+ | mtc1 TMP0, f5
2227
+ | c.olt.d 0, FRET2, FRET1 // |x| < result?
2228
+ | sub.d FRET2, FRET1, f4
2229
+ | movt.d FRET1, FRET2, 0 // If yes, subtract +1.
2230
+ | neg.d FRET2, FRET1
2231
+ | jr ra
2232
+ |. movn.d FRET1, FRET2, AT // Merge sign bit back in.
2233
+ |.else
2234
+ | neg.d FRET2, FRET1
2235
+ | mtc1 TMP0, f5
2236
+ | movn.d FRET1, FRET2, AT // Merge sign bit back in.
2237
+ |.if "func" == "ceil"
2238
+ | c.olt.d 0, FRET1, FARG1 // x > result?
2239
+ |.else
2240
+ | c.olt.d 0, FARG1, FRET1 // x < result?
2241
+ |.endif
2242
+ | sub.d FRET2, FRET1, f4 // If yes, subtract +-1.
2243
+ | jr ra
2244
+ |. movt.d FRET1, FRET2, 0
2245
+ |.endif
2246
+ |1:
2247
+ | jr ra
2248
+ |. mov.d FRET1, FARG1
2249
+ |.endmacro
2250
+ |
2251
+ |->vm_floor:
2252
+ | vm_round floor
2253
+ |->vm_ceil:
2254
+ | vm_round ceil
2255
+ |->vm_trunc:
2256
+ |.if JIT
2257
+ | vm_round trunc
2258
+ |.endif
2259
+ |
2260
+ |//-----------------------------------------------------------------------
2261
+ |//-- Miscellaneous functions --------------------------------------------
2262
+ |//-----------------------------------------------------------------------
2263
+ |
2264
+ |//-----------------------------------------------------------------------
2265
+ |//-- FFI helper functions -----------------------------------------------
2266
+ |//-----------------------------------------------------------------------
2267
+ |
2268
+ |// Handler for callback functions. Callback slot number in r1, g in r2.
2269
+ |->vm_ffi_callback:
2270
+ |.if FFI
2271
+ |.type CTSTATE, CTState, PC
2272
+ | saveregs
2273
+ | lw CTSTATE, GL:r2->ctype_state
2274
+ | addiu DISPATCH, r2, GG_G2DISP
2275
+ | load_got lj_ccallback_enter
2276
+ | sw r1, CTSTATE->cb.slot
2277
+ | sw CARG1, CTSTATE->cb.gpr[0]
2278
+ | sw CARG2, CTSTATE->cb.gpr[1]
2279
+ | sdc1 FARG1, CTSTATE->cb.fpr[0]
2280
+ | sw CARG3, CTSTATE->cb.gpr[2]
2281
+ | sw CARG4, CTSTATE->cb.gpr[3]
2282
+ | sdc1 FARG2, CTSTATE->cb.fpr[1]
2283
+ | addiu TMP0, sp, CFRAME_SPACE+16
2284
+ | sw TMP0, CTSTATE->cb.stack
2285
+ | sw r0, SAVE_PC // Any value outside of bytecode is ok.
2286
+ | move CARG2, sp
2287
+ | call_intern lj_ccallback_enter // (CTState *cts, void *cf)
2288
+ |. move CARG1, CTSTATE
2289
+ | // Returns lua_State *.
2290
+ | lw BASE, L:CRET1->base
2291
+ | lw RC, L:CRET1->top
2292
+ | move L, CRET1
2293
+ | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
2294
+ | lw LFUNC:RB, FRAME_FUNC(BASE)
2295
+ | mtc1 TMP3, TOBIT
2296
+ | li_vmstate INTERP
2297
+ | li TISNIL, LJ_TNIL
2298
+ | subu RC, RC, BASE
2299
+ | st_vmstate
2300
+ | cvt.d.s TOBIT, TOBIT
2301
+ | ins_callt
2302
+ |.endif
2303
+ |
2304
+ |->cont_ffi_callback: // Return from FFI callback.
2305
+ |.if FFI
2306
+ | load_got lj_ccallback_leave
2307
+ | lw CTSTATE, DISPATCH_GL(ctype_state)(DISPATCH)
2308
+ | sw BASE, L->base
2309
+ | sw RB, L->top
2310
+ | sw L, CTSTATE->L
2311
+ | move CARG2, RA
2312
+ | call_intern lj_ccallback_leave // (CTState *cts, TValue *o)
2313
+ |. move CARG1, CTSTATE
2314
+ | lw CRET1, CTSTATE->cb.gpr[0]
2315
+ | ldc1 FRET1, CTSTATE->cb.fpr[0]
2316
+ | lw CRET2, CTSTATE->cb.gpr[1]
2317
+ | b ->vm_leave_unw
2318
+ |. ldc1 FRET2, CTSTATE->cb.fpr[1]
2319
+ |.endif
2320
+ |
2321
+ |->vm_ffi_call: // Call C function via FFI.
2322
+ | // Caveat: needs special frame unwinding, see below.
2323
+ |.if FFI
2324
+ | .type CCSTATE, CCallState, CARG1
2325
+ | lw TMP1, CCSTATE->spadj
2326
+ | lbu CARG2, CCSTATE->nsp
2327
+ | move TMP2, sp
2328
+ | subu sp, sp, TMP1
2329
+ | sw ra, -4(TMP2)
2330
+ | sll CARG2, CARG2, 2
2331
+ | sw r16, -8(TMP2)
2332
+ | sw CCSTATE, -12(TMP2)
2333
+ | move r16, TMP2
2334
+ | addiu TMP1, CCSTATE, offsetof(CCallState, stack)
2335
+ | addiu TMP2, sp, 16
2336
+ | beqz CARG2, >2
2337
+ |. addu TMP3, TMP1, CARG2
2338
+ |1:
2339
+ | lw TMP0, 0(TMP1)
2340
+ | addiu TMP1, TMP1, 4
2341
+ | sltu AT, TMP1, TMP3
2342
+ | sw TMP0, 0(TMP2)
2343
+ | bnez AT, <1
2344
+ |. addiu TMP2, TMP2, 4
2345
+ |2:
2346
+ | lw CFUNCADDR, CCSTATE->func
2347
+ | lw CARG2, CCSTATE->gpr[1]
2348
+ | lw CARG3, CCSTATE->gpr[2]
2349
+ | lw CARG4, CCSTATE->gpr[3]
2350
+ | ldc1 FARG1, CCSTATE->fpr[0]
2351
+ | ldc1 FARG2, CCSTATE->fpr[1]
2352
+ | jalr CFUNCADDR
2353
+ |. lw CARG1, CCSTATE->gpr[0] // Do this last, since CCSTATE is CARG1.
2354
+ | lw CCSTATE:TMP1, -12(r16)
2355
+ | lw TMP2, -8(r16)
2356
+ | lw ra, -4(r16)
2357
+ | sw CRET1, CCSTATE:TMP1->gpr[0]
2358
+ | sw CRET2, CCSTATE:TMP1->gpr[1]
2359
+ | sdc1 FRET1, CCSTATE:TMP1->fpr[0]
2360
+ | sdc1 FRET2, CCSTATE:TMP1->fpr[1]
2361
+ | move sp, r16
2362
+ | jr ra
2363
+ |. move r16, TMP2
2364
+ |.endif
2365
+ |// Note: vm_ffi_call must be the last function in this object file!
2366
+ |
2367
+ |//-----------------------------------------------------------------------
2368
+ }
2369
+
2370
+ /* Generate the code for a single instruction. */
2371
+ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
2372
+ {
2373
+ int vk = 0;
2374
+ |=>defop:
2375
+
2376
+ switch (op) {
2377
+
2378
+ /* -- Comparison ops ---------------------------------------------------- */
2379
+
2380
+ /* Remember: all ops branch for a true comparison, fall through otherwise. */
2381
+
2382
+ case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
2383
+ | // RA = src1*8, RD = src2*8, JMP with RD = target
2384
+ | addu CARG2, BASE, RA
2385
+ | addu CARG3, BASE, RD
2386
+ | lw TMP0, HI(CARG2)
2387
+ | lw TMP1, HI(CARG3)
2388
+ | ldc1 f0, 0(CARG2)
2389
+ | ldc1 f2, 0(CARG3)
2390
+ | sltiu TMP0, TMP0, LJ_TISNUM
2391
+ | sltiu TMP1, TMP1, LJ_TISNUM
2392
+ | lhu TMP2, OFS_RD(PC)
2393
+ | and TMP0, TMP0, TMP1
2394
+ | addiu PC, PC, 4
2395
+ | beqz TMP0, ->vmeta_comp
2396
+ |. lui TMP1, (-(BCBIAS_J*4 >> 16) & 65535)
2397
+ | decode_RD4b TMP2
2398
+ | addu TMP2, TMP2, TMP1
2399
+ if (op == BC_ISLT || op == BC_ISGE) {
2400
+ | c.olt.d f0, f2
2401
+ } else {
2402
+ | c.ole.d f0, f2
2403
+ }
2404
+ if (op == BC_ISLT || op == BC_ISLE) {
2405
+ | movf TMP2, r0
2406
+ } else {
2407
+ | movt TMP2, r0
2408
+ }
2409
+ | addu PC, PC, TMP2
2410
+ |1:
2411
+ | ins_next
2412
+ break;
2413
+
2414
+ case BC_ISEQV: case BC_ISNEV:
2415
+ vk = op == BC_ISEQV;
2416
+ | // RA = src1*8, RD = src2*8, JMP with RD = target
2417
+ | addu RA, BASE, RA
2418
+ | addiu PC, PC, 4
2419
+ | lw TMP0, HI(RA)
2420
+ | ldc1 f0, 0(RA)
2421
+ | addu RD, BASE, RD
2422
+ | lhu TMP2, -4+OFS_RD(PC)
2423
+ | lw TMP1, HI(RD)
2424
+ | ldc1 f2, 0(RD)
2425
+ | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535)
2426
+ | sltiu AT, TMP0, LJ_TISNUM
2427
+ | sltiu CARG1, TMP1, LJ_TISNUM
2428
+ | decode_RD4b TMP2
2429
+ | and AT, AT, CARG1
2430
+ | beqz AT, >5
2431
+ |. addu TMP2, TMP2, TMP3
2432
+ | c.eq.d f0, f2
2433
+ if (vk) {
2434
+ | movf TMP2, r0
2435
+ } else {
2436
+ | movt TMP2, r0
2437
+ }
2438
+ |1:
2439
+ | addu PC, PC, TMP2
2440
+ | ins_next
2441
+ |5: // Either or both types are not numbers.
2442
+ | lw CARG2, LO(RA)
2443
+ | lw CARG3, LO(RD)
2444
+ |.if FFI
2445
+ | li TMP3, LJ_TCDATA
2446
+ | beq TMP0, TMP3, ->vmeta_equal_cd
2447
+ |.endif
2448
+ |. sltiu AT, TMP0, LJ_TISPRI // Not a primitive?
2449
+ |.if FFI
2450
+ | beq TMP1, TMP3, ->vmeta_equal_cd
2451
+ |.endif
2452
+ |. xor TMP3, CARG2, CARG3 // Same tv?
2453
+ | xor TMP1, TMP1, TMP0 // Same type?
2454
+ | sltiu CARG1, TMP0, LJ_TISTABUD+1 // Table or userdata?
2455
+ | movz TMP3, r0, AT // Ignore tv if primitive.
2456
+ | movn CARG1, r0, TMP1 // Tab/ud and same type?
2457
+ | or AT, TMP1, TMP3 // Same type && (pri||same tv).
2458
+ | movz CARG1, r0, AT
2459
+ | beqz CARG1, <1 // Done if not tab/ud or not same type or same tv.
2460
+ if (vk) {
2461
+ |. movn TMP2, r0, AT
2462
+ } else {
2463
+ |. movz TMP2, r0, AT
2464
+ }
2465
+ | // Different tables or userdatas. Need to check __eq metamethod.
2466
+ | // Field metatable must be at same offset for GCtab and GCudata!
2467
+ | lw TAB:TMP1, TAB:CARG2->metatable
2468
+ | beqz TAB:TMP1, <1 // No metatable?
2469
+ |. nop
2470
+ | lbu TMP1, TAB:TMP1->nomm
2471
+ | andi TMP1, TMP1, 1<<MM_eq
2472
+ | bnez TMP1, <1 // Or 'no __eq' flag set?
2473
+ |. nop
2474
+ | b ->vmeta_equal // Handle __eq metamethod.
2475
+ |. li CARG4, 1-vk // ne = 0 or 1.
2476
+ break;
2477
+
2478
+ case BC_ISEQS: case BC_ISNES:
2479
+ vk = op == BC_ISEQS;
2480
+ | // RA = src*8, RD = str_const*8 (~), JMP with RD = target
2481
+ | addu RA, BASE, RA
2482
+ | addiu PC, PC, 4
2483
+ | lw TMP0, HI(RA)
2484
+ | srl RD, RD, 1
2485
+ | lw STR:TMP3, LO(RA)
2486
+ | subu RD, KBASE, RD
2487
+ | lhu TMP2, -4+OFS_RD(PC)
2488
+ |.if FFI
2489
+ | li AT, LJ_TCDATA
2490
+ | beq TMP0, AT, ->vmeta_equal_cd
2491
+ |.endif
2492
+ |. lw STR:TMP1, -4(RD) // KBASE-4-str_const*4
2493
+ | addiu TMP0, TMP0, -LJ_TSTR
2494
+ | decode_RD4b TMP2
2495
+ | xor TMP1, STR:TMP1, STR:TMP3
2496
+ | or TMP0, TMP0, TMP1
2497
+ | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535)
2498
+ | addu TMP2, TMP2, TMP3
2499
+ if (vk) {
2500
+ | movn TMP2, r0, TMP0
2501
+ } else {
2502
+ | movz TMP2, r0, TMP0
2503
+ }
2504
+ | addu PC, PC, TMP2
2505
+ | ins_next
2506
+ break;
2507
+
2508
+ case BC_ISEQN: case BC_ISNEN:
2509
+ vk = op == BC_ISEQN;
2510
+ | // RA = src*8, RD = num_const*8, JMP with RD = target
2511
+ | addu RA, BASE, RA
2512
+ | addiu PC, PC, 4
2513
+ | lw TMP0, HI(RA)
2514
+ | ldc1 f0, 0(RA)
2515
+ | addu RD, KBASE, RD
2516
+ | lhu TMP2, -4+OFS_RD(PC)
2517
+ | ldc1 f2, 0(RD)
2518
+ | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535)
2519
+ | sltiu AT, TMP0, LJ_TISNUM
2520
+ | decode_RD4b TMP2
2521
+ |.if FFI
2522
+ | beqz AT, >5
2523
+ |.else
2524
+ | beqz AT, >1
2525
+ |.endif
2526
+ |. addu TMP2, TMP2, TMP3
2527
+ | c.eq.d f0, f2
2528
+ if (vk) {
2529
+ | movf TMP2, r0
2530
+ | addu PC, PC, TMP2
2531
+ |1:
2532
+ } else {
2533
+ | movt TMP2, r0
2534
+ |1:
2535
+ | addu PC, PC, TMP2
2536
+ }
2537
+ | ins_next
2538
+ |.if FFI
2539
+ |5:
2540
+ | li AT, LJ_TCDATA
2541
+ | beq TMP0, AT, ->vmeta_equal_cd
2542
+ |. nop
2543
+ | b <1
2544
+ |. nop
2545
+ |.endif
2546
+ break;
2547
+
2548
+ case BC_ISEQP: case BC_ISNEP:
2549
+ vk = op == BC_ISEQP;
2550
+ | // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target
2551
+ | addu RA, BASE, RA
2552
+ | srl TMP1, RD, 3
2553
+ | lw TMP0, HI(RA)
2554
+ | lhu TMP2, OFS_RD(PC)
2555
+ | not TMP1, TMP1
2556
+ | addiu PC, PC, 4
2557
+ |.if FFI
2558
+ | li AT, LJ_TCDATA
2559
+ | beq TMP0, AT, ->vmeta_equal_cd
2560
+ |.endif
2561
+ |. xor TMP0, TMP0, TMP1
2562
+ | decode_RD4b TMP2
2563
+ | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535)
2564
+ | addu TMP2, TMP2, TMP3
2565
+ if (vk) {
2566
+ | movn TMP2, r0, TMP0
2567
+ } else {
2568
+ | movz TMP2, r0, TMP0
2569
+ }
2570
+ | addu PC, PC, TMP2
2571
+ | ins_next
2572
+ break;
2573
+
2574
+ /* -- Unary test and copy ops ------------------------------------------- */
2575
+
2576
+ case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF:
2577
+ | // RA = dst*8 or unused, RD = src*8, JMP with RD = target
2578
+ | addu RD, BASE, RD
2579
+ | lhu TMP2, OFS_RD(PC)
2580
+ | lw TMP0, HI(RD)
2581
+ | addiu PC, PC, 4
2582
+ if (op == BC_IST || op == BC_ISF) {
2583
+ | sltiu TMP0, TMP0, LJ_TISTRUECOND
2584
+ | decode_RD4b TMP2
2585
+ | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535)
2586
+ | addu TMP2, TMP2, TMP3
2587
+ if (op == BC_IST) {
2588
+ | movz TMP2, r0, TMP0
2589
+ } else {
2590
+ | movn TMP2, r0, TMP0
2591
+ }
2592
+ | addu PC, PC, TMP2
2593
+ } else {
2594
+ | sltiu TMP0, TMP0, LJ_TISTRUECOND
2595
+ | ldc1 f0, 0(RD)
2596
+ if (op == BC_ISTC) {
2597
+ | beqz TMP0, >1
2598
+ } else {
2599
+ | bnez TMP0, >1
2600
+ }
2601
+ |. addu RA, BASE, RA
2602
+ | decode_RD4b TMP2
2603
+ | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535)
2604
+ | addu TMP2, TMP2, TMP3
2605
+ | sdc1 f0, 0(RA)
2606
+ | addu PC, PC, TMP2
2607
+ |1:
2608
+ }
2609
+ | ins_next
2610
+ break;
2611
+
2612
+ case BC_ISTYPE:
2613
+ | // RA = src*8, RD = -type*8
2614
+ | addu TMP2, BASE, RA
2615
+ | srl TMP1, RD, 3
2616
+ | lw TMP0, HI(TMP2)
2617
+ | ins_next1
2618
+ | addu AT, TMP0, TMP1
2619
+ | bnez AT, ->vmeta_istype
2620
+ |. ins_next2
2621
+ break;
2622
+ case BC_ISNUM:
2623
+ | // RA = src*8, RD = -(TISNUM-1)*8
2624
+ | addu TMP2, BASE, RA
2625
+ | lw TMP0, HI(TMP2)
2626
+ | ins_next1
2627
+ | sltiu AT, TMP0, LJ_TISNUM
2628
+ | beqz AT, ->vmeta_istype
2629
+ |. ins_next2
2630
+ break;
2631
+
2632
+ /* -- Unary ops --------------------------------------------------------- */
2633
+
2634
+ case BC_MOV:
2635
+ | // RA = dst*8, RD = src*8
2636
+ | addu RD, BASE, RD
2637
+ | addu RA, BASE, RA
2638
+ | ldc1 f0, 0(RD)
2639
+ | ins_next1
2640
+ | sdc1 f0, 0(RA)
2641
+ | ins_next2
2642
+ break;
2643
+ case BC_NOT:
2644
+ | // RA = dst*8, RD = src*8
2645
+ | addu RD, BASE, RD
2646
+ | addu RA, BASE, RA
2647
+ | lw TMP0, HI(RD)
2648
+ | li TMP1, LJ_TFALSE
2649
+ | sltiu TMP0, TMP0, LJ_TISTRUECOND
2650
+ | addiu TMP1, TMP0, LJ_TTRUE
2651
+ | ins_next1
2652
+ | sw TMP1, HI(RA)
2653
+ | ins_next2
2654
+ break;
2655
+ case BC_UNM:
2656
+ | // RA = dst*8, RD = src*8
2657
+ | addu CARG3, BASE, RD
2658
+ | addu RA, BASE, RA
2659
+ | lw TMP0, HI(CARG3)
2660
+ | ldc1 f0, 0(CARG3)
2661
+ | sltiu AT, TMP0, LJ_TISNUM
2662
+ | beqz AT, ->vmeta_unm
2663
+ |. neg.d f0, f0
2664
+ | ins_next1
2665
+ | sdc1 f0, 0(RA)
2666
+ | ins_next2
2667
+ break;
2668
+ case BC_LEN:
2669
+ | // RA = dst*8, RD = src*8
2670
+ | addu CARG2, BASE, RD
2671
+ | addu RA, BASE, RA
2672
+ | lw TMP0, HI(CARG2)
2673
+ | lw CARG1, LO(CARG2)
2674
+ | li AT, LJ_TSTR
2675
+ | bne TMP0, AT, >2
2676
+ |. li AT, LJ_TTAB
2677
+ | lw CRET1, STR:CARG1->len
2678
+ |1:
2679
+ | mtc1 CRET1, f0
2680
+ | cvt.d.w f0, f0
2681
+ | ins_next1
2682
+ | sdc1 f0, 0(RA)
2683
+ | ins_next2
2684
+ |2:
2685
+ | bne TMP0, AT, ->vmeta_len
2686
+ |. nop
2687
+ #if LJ_52
2688
+ | lw TAB:TMP2, TAB:CARG1->metatable
2689
+ | bnez TAB:TMP2, >9
2690
+ |. nop
2691
+ |3:
2692
+ #endif
2693
+ |->BC_LEN_Z:
2694
+ | load_got lj_tab_len
2695
+ | call_intern lj_tab_len // (GCtab *t)
2696
+ |. nop
2697
+ | // Returns uint32_t (but less than 2^31).
2698
+ | b <1
2699
+ |. nop
2700
+ #if LJ_52
2701
+ |9:
2702
+ | lbu TMP0, TAB:TMP2->nomm
2703
+ | andi TMP0, TMP0, 1<<MM_len
2704
+ | bnez TMP0, <3 // 'no __len' flag set: done.
2705
+ |. nop
2706
+ | b ->vmeta_len
2707
+ |. nop
2708
+ #endif
2709
+ break;
2710
+
2711
+ /* -- Binary ops -------------------------------------------------------- */
2712
+
2713
+ |.macro ins_arithpre
2714
+ ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
2715
+ | decode_RB8a RB, INS
2716
+ | decode_RB8b RB
2717
+ | decode_RDtoRC8 RC, RD
2718
+ | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8
2719
+ ||switch (vk) {
2720
+ ||case 0:
2721
+ | addu CARG3, BASE, RB
2722
+ | addu CARG4, KBASE, RC
2723
+ | lw TMP1, HI(CARG3)
2724
+ | ldc1 f20, 0(CARG3)
2725
+ | ldc1 f22, 0(CARG4)
2726
+ | sltiu AT, TMP1, LJ_TISNUM
2727
+ || break;
2728
+ ||case 1:
2729
+ | addu CARG4, BASE, RB
2730
+ | addu CARG3, KBASE, RC
2731
+ | lw TMP1, HI(CARG4)
2732
+ | ldc1 f22, 0(CARG4)
2733
+ | ldc1 f20, 0(CARG3)
2734
+ | sltiu AT, TMP1, LJ_TISNUM
2735
+ || break;
2736
+ ||default:
2737
+ | addu CARG3, BASE, RB
2738
+ | addu CARG4, BASE, RC
2739
+ | lw TMP1, HI(CARG3)
2740
+ | lw TMP2, HI(CARG4)
2741
+ | ldc1 f20, 0(CARG3)
2742
+ | ldc1 f22, 0(CARG4)
2743
+ | sltiu AT, TMP1, LJ_TISNUM
2744
+ | sltiu TMP0, TMP2, LJ_TISNUM
2745
+ | and AT, AT, TMP0
2746
+ || break;
2747
+ ||}
2748
+ | beqz AT, ->vmeta_arith
2749
+ |. addu RA, BASE, RA
2750
+ |.endmacro
2751
+ |
2752
+ |.macro fpmod, a, b, c
2753
+ |->BC_MODVN_Z:
2754
+ | bal ->vm_floor // floor(b/c)
2755
+ |. div.d FARG1, b, c
2756
+ | mul.d a, FRET1, c
2757
+ | sub.d a, b, a // b - floor(b/c)*c
2758
+ |.endmacro
2759
+ |
2760
+ |.macro ins_arith, ins
2761
+ | ins_arithpre
2762
+ |.if "ins" == "fpmod_"
2763
+ | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway.
2764
+ |. nop
2765
+ |.else
2766
+ | ins f0, f20, f22
2767
+ | ins_next1
2768
+ | sdc1 f0, 0(RA)
2769
+ | ins_next2
2770
+ |.endif
2771
+ |.endmacro
2772
+
2773
+ case BC_ADDVN: case BC_ADDNV: case BC_ADDVV:
2774
+ | ins_arith add.d
2775
+ break;
2776
+ case BC_SUBVN: case BC_SUBNV: case BC_SUBVV:
2777
+ | ins_arith sub.d
2778
+ break;
2779
+ case BC_MULVN: case BC_MULNV: case BC_MULVV:
2780
+ | ins_arith mul.d
2781
+ break;
2782
+ case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
2783
+ | ins_arith div.d
2784
+ break;
2785
+ case BC_MODVN:
2786
+ | ins_arith fpmod
2787
+ break;
2788
+ case BC_MODNV: case BC_MODVV:
2789
+ | ins_arith fpmod_
2790
+ break;
2791
+ case BC_POW:
2792
+ | decode_RB8a RB, INS
2793
+ | decode_RB8b RB
2794
+ | decode_RDtoRC8 RC, RD
2795
+ | addu CARG3, BASE, RB
2796
+ | addu CARG4, BASE, RC
2797
+ | lw TMP1, HI(CARG3)
2798
+ | lw TMP2, HI(CARG4)
2799
+ | ldc1 FARG1, 0(CARG3)
2800
+ | ldc1 FARG2, 0(CARG4)
2801
+ | sltiu AT, TMP1, LJ_TISNUM
2802
+ | sltiu TMP0, TMP2, LJ_TISNUM
2803
+ | and AT, AT, TMP0
2804
+ | load_got pow
2805
+ | beqz AT, ->vmeta_arith
2806
+ |. addu RA, BASE, RA
2807
+ | call_extern
2808
+ |. nop
2809
+ | ins_next1
2810
+ | sdc1 FRET1, 0(RA)
2811
+ | ins_next2
2812
+ break;
2813
+
2814
+ case BC_CAT:
2815
+ | // RA = dst*8, RB = src_start*8, RC = src_end*8
2816
+ | decode_RB8a RB, INS
2817
+ | decode_RB8b RB
2818
+ | decode_RDtoRC8 RC, RD
2819
+ | subu CARG3, RC, RB
2820
+ | sw BASE, L->base
2821
+ | addu CARG2, BASE, RC
2822
+ | move MULTRES, RB
2823
+ |->BC_CAT_Z:
2824
+ | load_got lj_meta_cat
2825
+ | srl CARG3, CARG3, 3
2826
+ | sw PC, SAVE_PC
2827
+ | call_intern lj_meta_cat // (lua_State *L, TValue *top, int left)
2828
+ |. move CARG1, L
2829
+ | // Returns NULL (finished) or TValue * (metamethod).
2830
+ | bnez CRET1, ->vmeta_binop
2831
+ |. lw BASE, L->base
2832
+ | addu RB, BASE, MULTRES
2833
+ | ldc1 f0, 0(RB)
2834
+ | addu RA, BASE, RA
2835
+ | ins_next1
2836
+ | sdc1 f0, 0(RA) // Copy result from RB to RA.
2837
+ | ins_next2
2838
+ break;
2839
+
2840
+ /* -- Constant ops ------------------------------------------------------ */
2841
+
2842
+ case BC_KSTR:
2843
+ | // RA = dst*8, RD = str_const*8 (~)
2844
+ | srl TMP1, RD, 1
2845
+ | subu TMP1, KBASE, TMP1
2846
+ | ins_next1
2847
+ | lw TMP0, -4(TMP1) // KBASE-4-str_const*4
2848
+ | addu RA, BASE, RA
2849
+ | li TMP2, LJ_TSTR
2850
+ | sw TMP0, LO(RA)
2851
+ | sw TMP2, HI(RA)
2852
+ | ins_next2
2853
+ break;
2854
+ case BC_KCDATA:
2855
+ |.if FFI
2856
+ | // RA = dst*8, RD = cdata_const*8 (~)
2857
+ | srl TMP1, RD, 1
2858
+ | subu TMP1, KBASE, TMP1
2859
+ | ins_next1
2860
+ | lw TMP0, -4(TMP1) // KBASE-4-cdata_const*4
2861
+ | addu RA, BASE, RA
2862
+ | li TMP2, LJ_TCDATA
2863
+ | sw TMP0, LO(RA)
2864
+ | sw TMP2, HI(RA)
2865
+ | ins_next2
2866
+ |.endif
2867
+ break;
2868
+ case BC_KSHORT:
2869
+ | // RA = dst*8, RD = int16_literal*8
2870
+ | sra RD, INS, 16
2871
+ | mtc1 RD, f0
2872
+ | addu RA, BASE, RA
2873
+ | cvt.d.w f0, f0
2874
+ | ins_next1
2875
+ | sdc1 f0, 0(RA)
2876
+ | ins_next2
2877
+ break;
2878
+ case BC_KNUM:
2879
+ | // RA = dst*8, RD = num_const*8
2880
+ | addu RD, KBASE, RD
2881
+ | addu RA, BASE, RA
2882
+ | ldc1 f0, 0(RD)
2883
+ | ins_next1
2884
+ | sdc1 f0, 0(RA)
2885
+ | ins_next2
2886
+ break;
2887
+ case BC_KPRI:
2888
+ | // RA = dst*8, RD = primitive_type*8 (~)
2889
+ | srl TMP1, RD, 3
2890
+ | addu RA, BASE, RA
2891
+ | not TMP0, TMP1
2892
+ | ins_next1
2893
+ | sw TMP0, HI(RA)
2894
+ | ins_next2
2895
+ break;
2896
+ case BC_KNIL:
2897
+ | // RA = base*8, RD = end*8
2898
+ | addu RA, BASE, RA
2899
+ | sw TISNIL, HI(RA)
2900
+ | addiu RA, RA, 8
2901
+ | addu RD, BASE, RD
2902
+ |1:
2903
+ | sw TISNIL, HI(RA)
2904
+ | slt AT, RA, RD
2905
+ | bnez AT, <1
2906
+ |. addiu RA, RA, 8
2907
+ | ins_next_
2908
+ break;
2909
+
2910
+ /* -- Upvalue and function ops ------------------------------------------ */
2911
+
2912
+ case BC_UGET:
2913
+ | // RA = dst*8, RD = uvnum*8
2914
+ | lw LFUNC:RB, FRAME_FUNC(BASE)
2915
+ | srl RD, RD, 1
2916
+ | addu RD, RD, LFUNC:RB
2917
+ | lw UPVAL:RB, LFUNC:RD->uvptr
2918
+ | ins_next1
2919
+ | lw TMP1, UPVAL:RB->v
2920
+ | ldc1 f0, 0(TMP1)
2921
+ | addu RA, BASE, RA
2922
+ | sdc1 f0, 0(RA)
2923
+ | ins_next2
2924
+ break;
2925
+ case BC_USETV:
2926
+ | // RA = uvnum*8, RD = src*8
2927
+ | lw LFUNC:RB, FRAME_FUNC(BASE)
2928
+ | srl RA, RA, 1
2929
+ | addu RD, BASE, RD
2930
+ | addu RA, RA, LFUNC:RB
2931
+ | ldc1 f0, 0(RD)
2932
+ | lw UPVAL:RB, LFUNC:RA->uvptr
2933
+ | lbu TMP3, UPVAL:RB->marked
2934
+ | lw CARG2, UPVAL:RB->v
2935
+ | andi TMP3, TMP3, LJ_GC_BLACK // isblack(uv)
2936
+ | lbu TMP0, UPVAL:RB->closed
2937
+ | lw TMP2, HI(RD)
2938
+ | sdc1 f0, 0(CARG2)
2939
+ | li AT, LJ_GC_BLACK|1
2940
+ | or TMP3, TMP3, TMP0
2941
+ | beq TMP3, AT, >2 // Upvalue is closed and black?
2942
+ |. addiu TMP2, TMP2, -(LJ_TNUMX+1)
2943
+ |1:
2944
+ | ins_next
2945
+ |
2946
+ |2: // Check if new value is collectable.
2947
+ | sltiu AT, TMP2, LJ_TISGCV - (LJ_TNUMX+1)
2948
+ | beqz AT, <1 // tvisgcv(v)
2949
+ |. lw TMP1, LO(RD)
2950
+ | lbu TMP3, GCOBJ:TMP1->gch.marked
2951
+ | andi TMP3, TMP3, LJ_GC_WHITES // iswhite(v)
2952
+ | beqz TMP3, <1
2953
+ |. load_got lj_gc_barrieruv
2954
+ | // Crossed a write barrier. Move the barrier forward.
2955
+ | call_intern lj_gc_barrieruv // (global_State *g, TValue *tv)
2956
+ |. addiu CARG1, DISPATCH, GG_DISP2G
2957
+ | b <1
2958
+ |. nop
2959
+ break;
2960
+ case BC_USETS:
2961
+ | // RA = uvnum*8, RD = str_const*8 (~)
2962
+ | lw LFUNC:RB, FRAME_FUNC(BASE)
2963
+ | srl RA, RA, 1
2964
+ | srl TMP1, RD, 1
2965
+ | addu RA, RA, LFUNC:RB
2966
+ | subu TMP1, KBASE, TMP1
2967
+ | lw UPVAL:RB, LFUNC:RA->uvptr
2968
+ | lw STR:TMP1, -4(TMP1) // KBASE-4-str_const*4
2969
+ | lbu TMP2, UPVAL:RB->marked
2970
+ | lw CARG2, UPVAL:RB->v
2971
+ | lbu TMP3, STR:TMP1->marked
2972
+ | andi AT, TMP2, LJ_GC_BLACK // isblack(uv)
2973
+ | lbu TMP2, UPVAL:RB->closed
2974
+ | li TMP0, LJ_TSTR
2975
+ | sw STR:TMP1, LO(CARG2)
2976
+ | bnez AT, >2
2977
+ |. sw TMP0, HI(CARG2)
2978
+ |1:
2979
+ | ins_next
2980
+ |
2981
+ |2: // Check if string is white and ensure upvalue is closed.
2982
+ | beqz TMP2, <1
2983
+ |. andi AT, TMP3, LJ_GC_WHITES // iswhite(str)
2984
+ | beqz AT, <1
2985
+ |. load_got lj_gc_barrieruv
2986
+ | // Crossed a write barrier. Move the barrier forward.
2987
+ | call_intern lj_gc_barrieruv // (global_State *g, TValue *tv)
2988
+ |. addiu CARG1, DISPATCH, GG_DISP2G
2989
+ | b <1
2990
+ |. nop
2991
+ break;
2992
+ case BC_USETN:
2993
+ | // RA = uvnum*8, RD = num_const*8
2994
+ | lw LFUNC:RB, FRAME_FUNC(BASE)
2995
+ | srl RA, RA, 1
2996
+ | addu RD, KBASE, RD
2997
+ | addu RA, RA, LFUNC:RB
2998
+ | ldc1 f0, 0(RD)
2999
+ | lw UPVAL:RB, LFUNC:RA->uvptr
3000
+ | ins_next1
3001
+ | lw TMP1, UPVAL:RB->v
3002
+ | sdc1 f0, 0(TMP1)
3003
+ | ins_next2
3004
+ break;
3005
+ case BC_USETP:
3006
+ | // RA = uvnum*8, RD = primitive_type*8 (~)
3007
+ | lw LFUNC:RB, FRAME_FUNC(BASE)
3008
+ | srl RA, RA, 1
3009
+ | srl TMP0, RD, 3
3010
+ | addu RA, RA, LFUNC:RB
3011
+ | not TMP0, TMP0
3012
+ | lw UPVAL:RB, LFUNC:RA->uvptr
3013
+ | ins_next1
3014
+ | lw TMP1, UPVAL:RB->v
3015
+ | sw TMP0, HI(TMP1)
3016
+ | ins_next2
3017
+ break;
3018
+
3019
+ case BC_UCLO:
3020
+ | // RA = level*8, RD = target
3021
+ | lw TMP2, L->openupval
3022
+ | branch_RD // Do this first since RD is not saved.
3023
+ | load_got lj_func_closeuv
3024
+ | sw BASE, L->base
3025
+ | beqz TMP2, >1
3026
+ |. move CARG1, L
3027
+ | call_intern lj_func_closeuv // (lua_State *L, TValue *level)
3028
+ |. addu CARG2, BASE, RA
3029
+ | lw BASE, L->base
3030
+ |1:
3031
+ | ins_next
3032
+ break;
3033
+
3034
+ case BC_FNEW:
3035
+ | // RA = dst*8, RD = proto_const*8 (~) (holding function prototype)
3036
+ | srl TMP1, RD, 1
3037
+ | load_got lj_func_newL_gc
3038
+ | subu TMP1, KBASE, TMP1
3039
+ | lw CARG3, FRAME_FUNC(BASE)
3040
+ | lw CARG2, -4(TMP1) // KBASE-4-tab_const*4
3041
+ | sw BASE, L->base
3042
+ | sw PC, SAVE_PC
3043
+ | // (lua_State *L, GCproto *pt, GCfuncL *parent)
3044
+ | call_intern lj_func_newL_gc
3045
+ |. move CARG1, L
3046
+ | // Returns GCfuncL *.
3047
+ | lw BASE, L->base
3048
+ | li TMP0, LJ_TFUNC
3049
+ | ins_next1
3050
+ | addu RA, BASE, RA
3051
+ | sw TMP0, HI(RA)
3052
+ | sw LFUNC:CRET1, LO(RA)
3053
+ | ins_next2
3054
+ break;
3055
+
3056
+ /* -- Table ops --------------------------------------------------------- */
3057
+
3058
+ case BC_TNEW:
3059
+ case BC_TDUP:
3060
+ | // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~)
3061
+ | lw TMP0, DISPATCH_GL(gc.total)(DISPATCH)
3062
+ | lw TMP1, DISPATCH_GL(gc.threshold)(DISPATCH)
3063
+ | sw BASE, L->base
3064
+ | sw PC, SAVE_PC
3065
+ | sltu AT, TMP0, TMP1
3066
+ | beqz AT, >5
3067
+ |1:
3068
+ if (op == BC_TNEW) {
3069
+ | load_got lj_tab_new
3070
+ | srl CARG2, RD, 3
3071
+ | andi CARG2, CARG2, 0x7ff
3072
+ | li TMP0, 0x801
3073
+ | addiu AT, CARG2, -0x7ff
3074
+ | srl CARG3, RD, 14
3075
+ | movz CARG2, TMP0, AT
3076
+ | // (lua_State *L, int32_t asize, uint32_t hbits)
3077
+ | call_intern lj_tab_new
3078
+ |. move CARG1, L
3079
+ | // Returns Table *.
3080
+ } else {
3081
+ | load_got lj_tab_dup
3082
+ | srl TMP1, RD, 1
3083
+ | subu TMP1, KBASE, TMP1
3084
+ | move CARG1, L
3085
+ | call_intern lj_tab_dup // (lua_State *L, Table *kt)
3086
+ |. lw CARG2, -4(TMP1) // KBASE-4-str_const*4
3087
+ | // Returns Table *.
3088
+ }
3089
+ | lw BASE, L->base
3090
+ | ins_next1
3091
+ | addu RA, BASE, RA
3092
+ | li TMP0, LJ_TTAB
3093
+ | sw TAB:CRET1, LO(RA)
3094
+ | sw TMP0, HI(RA)
3095
+ | ins_next2
3096
+ |5:
3097
+ | load_got lj_gc_step_fixtop
3098
+ | move MULTRES, RD
3099
+ | call_intern lj_gc_step_fixtop // (lua_State *L)
3100
+ |. move CARG1, L
3101
+ | b <1
3102
+ |. move RD, MULTRES
3103
+ break;
3104
+
3105
+ case BC_GGET:
3106
+ | // RA = dst*8, RD = str_const*8 (~)
3107
+ case BC_GSET:
3108
+ | // RA = src*8, RD = str_const*8 (~)
3109
+ | lw LFUNC:TMP2, FRAME_FUNC(BASE)
3110
+ | srl TMP1, RD, 1
3111
+ | subu TMP1, KBASE, TMP1
3112
+ | lw TAB:RB, LFUNC:TMP2->env
3113
+ | lw STR:RC, -4(TMP1) // KBASE-4-str_const*4
3114
+ if (op == BC_GGET) {
3115
+ | b ->BC_TGETS_Z
3116
+ } else {
3117
+ | b ->BC_TSETS_Z
3118
+ }
3119
+ |. addu RA, BASE, RA
3120
+ break;
3121
+
3122
+ case BC_TGETV:
3123
+ | // RA = dst*8, RB = table*8, RC = key*8
3124
+ | decode_RB8a RB, INS
3125
+ | decode_RB8b RB
3126
+ | decode_RDtoRC8 RC, RD
3127
+ | addu CARG2, BASE, RB
3128
+ | addu CARG3, BASE, RC
3129
+ | lw TMP1, HI(CARG2)
3130
+ | lw TMP2, HI(CARG3)
3131
+ | lw TAB:RB, LO(CARG2)
3132
+ | li AT, LJ_TTAB
3133
+ | ldc1 f0, 0(CARG3)
3134
+ | bne TMP1, AT, ->vmeta_tgetv
3135
+ |. addu RA, BASE, RA
3136
+ | sltiu AT, TMP2, LJ_TISNUM
3137
+ | beqz AT, >5
3138
+ |. li AT, LJ_TSTR
3139
+ |
3140
+ | // Convert number key to integer, check for integerness and range.
3141
+ | cvt.w.d f2, f0
3142
+ | lw TMP0, TAB:RB->asize
3143
+ | mfc1 TMP2, f2
3144
+ | cvt.d.w f4, f2
3145
+ | lw TMP1, TAB:RB->array
3146
+ | c.eq.d f0, f4
3147
+ | sltu AT, TMP2, TMP0
3148
+ | movf AT, r0
3149
+ | sll TMP2, TMP2, 3
3150
+ | beqz AT, ->vmeta_tgetv // Integer key and in array part?
3151
+ |. addu TMP2, TMP1, TMP2
3152
+ | lw TMP0, HI(TMP2)
3153
+ | beq TMP0, TISNIL, >2
3154
+ |. ldc1 f0, 0(TMP2)
3155
+ |1:
3156
+ | ins_next1
3157
+ | sdc1 f0, 0(RA)
3158
+ | ins_next2
3159
+ |
3160
+ |2: // Check for __index if table value is nil.
3161
+ | lw TAB:TMP2, TAB:RB->metatable
3162
+ | beqz TAB:TMP2, <1 // No metatable: done.
3163
+ |. nop
3164
+ | lbu TMP0, TAB:TMP2->nomm
3165
+ | andi TMP0, TMP0, 1<<MM_index
3166
+ | bnez TMP0, <1 // 'no __index' flag set: done.
3167
+ |. nop
3168
+ | b ->vmeta_tgetv
3169
+ |. nop
3170
+ |
3171
+ |5:
3172
+ | bne TMP2, AT, ->vmeta_tgetv
3173
+ |. lw STR:RC, LO(CARG3)
3174
+ | b ->BC_TGETS_Z // String key?
3175
+ |. nop
3176
+ break;
3177
+ case BC_TGETS:
3178
+ | // RA = dst*8, RB = table*8, RC = str_const*4 (~)
3179
+ | decode_RB8a RB, INS
3180
+ | decode_RB8b RB
3181
+ | addu CARG2, BASE, RB
3182
+ | decode_RC4a RC, INS
3183
+ | lw TMP0, HI(CARG2)
3184
+ | decode_RC4b RC
3185
+ | li AT, LJ_TTAB
3186
+ | lw TAB:RB, LO(CARG2)
3187
+ | subu CARG3, KBASE, RC
3188
+ | lw STR:RC, -4(CARG3) // KBASE-4-str_const*4
3189
+ | bne TMP0, AT, ->vmeta_tgets1
3190
+ |. addu RA, BASE, RA
3191
+ |->BC_TGETS_Z:
3192
+ | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8
3193
+ | lw TMP0, TAB:RB->hmask
3194
+ | lw TMP1, STR:RC->hash
3195
+ | lw NODE:TMP2, TAB:RB->node
3196
+ | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask
3197
+ | sll TMP0, TMP1, 5
3198
+ | sll TMP1, TMP1, 3
3199
+ | subu TMP1, TMP0, TMP1
3200
+ | addu NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8)
3201
+ |1:
3202
+ | lw CARG1, offsetof(Node, key)+HI(NODE:TMP2)
3203
+ | lw TMP0, offsetof(Node, key)+LO(NODE:TMP2)
3204
+ | lw NODE:TMP1, NODE:TMP2->next
3205
+ | lw CARG2, offsetof(Node, val)+HI(NODE:TMP2)
3206
+ | addiu CARG1, CARG1, -LJ_TSTR
3207
+ | xor TMP0, TMP0, STR:RC
3208
+ | or AT, CARG1, TMP0
3209
+ | bnez AT, >4
3210
+ |. lw TAB:TMP3, TAB:RB->metatable
3211
+ | beq CARG2, TISNIL, >5 // Key found, but nil value?
3212
+ |. lw CARG1, offsetof(Node, val)+LO(NODE:TMP2)
3213
+ |3:
3214
+ | ins_next1
3215
+ | sw CARG2, HI(RA)
3216
+ | sw CARG1, LO(RA)
3217
+ | ins_next2
3218
+ |
3219
+ |4: // Follow hash chain.
3220
+ | bnez NODE:TMP1, <1
3221
+ |. move NODE:TMP2, NODE:TMP1
3222
+ | // End of hash chain: key not found, nil result.
3223
+ |
3224
+ |5: // Check for __index if table value is nil.
3225
+ | beqz TAB:TMP3, <3 // No metatable: done.
3226
+ |. li CARG2, LJ_TNIL
3227
+ | lbu TMP0, TAB:TMP3->nomm
3228
+ | andi TMP0, TMP0, 1<<MM_index
3229
+ | bnez TMP0, <3 // 'no __index' flag set: done.
3230
+ |. nop
3231
+ | b ->vmeta_tgets
3232
+ |. nop
3233
+ break;
3234
+ case BC_TGETB:
3235
+ | // RA = dst*8, RB = table*8, RC = index*8
3236
+ | decode_RB8a RB, INS
3237
+ | decode_RB8b RB
3238
+ | addu CARG2, BASE, RB
3239
+ | decode_RDtoRC8 RC, RD
3240
+ | lw CARG1, HI(CARG2)
3241
+ | li AT, LJ_TTAB
3242
+ | lw TAB:RB, LO(CARG2)
3243
+ | addu RA, BASE, RA
3244
+ | bne CARG1, AT, ->vmeta_tgetb
3245
+ |. srl TMP0, RC, 3
3246
+ | lw TMP1, TAB:RB->asize
3247
+ | lw TMP2, TAB:RB->array
3248
+ | sltu AT, TMP0, TMP1
3249
+ | beqz AT, ->vmeta_tgetb
3250
+ |. addu RC, TMP2, RC
3251
+ | lw TMP1, HI(RC)
3252
+ | beq TMP1, TISNIL, >5
3253
+ |. ldc1 f0, 0(RC)
3254
+ |1:
3255
+ | ins_next1
3256
+ | sdc1 f0, 0(RA)
3257
+ | ins_next2
3258
+ |
3259
+ |5: // Check for __index if table value is nil.
3260
+ | lw TAB:TMP2, TAB:RB->metatable
3261
+ | beqz TAB:TMP2, <1 // No metatable: done.
3262
+ |. nop
3263
+ | lbu TMP1, TAB:TMP2->nomm
3264
+ | andi TMP1, TMP1, 1<<MM_index
3265
+ | bnez TMP1, <1 // 'no __index' flag set: done.
3266
+ |. nop
3267
+ | b ->vmeta_tgetb // Caveat: preserve TMP0!
3268
+ |. nop
3269
+ break;
3270
+ case BC_TGETR:
3271
+ | // RA = dst*8, RB = table*8, RC = key*8
3272
+ | decode_RB8a RB, INS
3273
+ | decode_RB8b RB
3274
+ | decode_RDtoRC8 RC, RD
3275
+ | addu CARG2, BASE, RB
3276
+ | addu CARG3, BASE, RC
3277
+ | lw TAB:CARG1, LO(CARG2)
3278
+ | ldc1 f0, 0(CARG3)
3279
+ | trunc.w.d f2, f0
3280
+ | lw TMP0, TAB:CARG1->asize
3281
+ | mfc1 CARG2, f2
3282
+ | lw TMP1, TAB:CARG1->array
3283
+ | sltu AT, CARG2, TMP0
3284
+ | sll TMP2, CARG2, 3
3285
+ | beqz AT, ->vmeta_tgetr // In array part?
3286
+ |. addu TMP2, TMP1, TMP2
3287
+ | ldc1 f0, 0(TMP2)
3288
+ |->BC_TGETR_Z:
3289
+ | addu RA, BASE, RA
3290
+ | ins_next1
3291
+ | sdc1 f0, 0(RA)
3292
+ | ins_next2
3293
+ break;
3294
+
3295
+ case BC_TSETV:
3296
+ | // RA = src*8, RB = table*8, RC = key*8
3297
+ | decode_RB8a RB, INS
3298
+ | decode_RB8b RB
3299
+ | decode_RDtoRC8 RC, RD
3300
+ | addu CARG2, BASE, RB
3301
+ | addu CARG3, BASE, RC
3302
+ | lw TMP1, HI(CARG2)
3303
+ | lw TMP2, HI(CARG3)
3304
+ | lw TAB:RB, LO(CARG2)
3305
+ | li AT, LJ_TTAB
3306
+ | ldc1 f0, 0(CARG3)
3307
+ | bne TMP1, AT, ->vmeta_tsetv
3308
+ |. addu RA, BASE, RA
3309
+ | sltiu AT, TMP2, LJ_TISNUM
3310
+ | beqz AT, >5
3311
+ |. li AT, LJ_TSTR
3312
+ |
3313
+ | // Convert number key to integer, check for integerness and range.
3314
+ | cvt.w.d f2, f0
3315
+ | lw TMP0, TAB:RB->asize
3316
+ | mfc1 TMP2, f2
3317
+ | cvt.d.w f4, f2
3318
+ | lw TMP1, TAB:RB->array
3319
+ | c.eq.d f0, f4
3320
+ | sltu AT, TMP2, TMP0
3321
+ | movf AT, r0
3322
+ | sll TMP2, TMP2, 3
3323
+ | beqz AT, ->vmeta_tsetv // Integer key and in array part?
3324
+ |. addu TMP1, TMP1, TMP2
3325
+ | lbu TMP3, TAB:RB->marked
3326
+ | lw TMP0, HI(TMP1)
3327
+ | beq TMP0, TISNIL, >3
3328
+ |. ldc1 f0, 0(RA)
3329
+ |1:
3330
+ | andi AT, TMP3, LJ_GC_BLACK // isblack(table)
3331
+ | bnez AT, >7
3332
+ |. sdc1 f0, 0(TMP1)
3333
+ |2:
3334
+ | ins_next
3335
+ |
3336
+ |3: // Check for __newindex if previous value is nil.
3337
+ | lw TAB:TMP2, TAB:RB->metatable
3338
+ | beqz TAB:TMP2, <1 // No metatable: done.
3339
+ |. nop
3340
+ | lbu TMP2, TAB:TMP2->nomm
3341
+ | andi TMP2, TMP2, 1<<MM_newindex
3342
+ | bnez TMP2, <1 // 'no __newindex' flag set: done.
3343
+ |. nop
3344
+ | b ->vmeta_tsetv
3345
+ |. nop
3346
+ |
3347
+ |5:
3348
+ | bne TMP2, AT, ->vmeta_tsetv
3349
+ |. lw STR:RC, LO(CARG3)
3350
+ | b ->BC_TSETS_Z // String key?
3351
+ |. nop
3352
+ |
3353
+ |7: // Possible table write barrier for the value. Skip valiswhite check.
3354
+ | barrierback TAB:RB, TMP3, TMP0, <2
3355
+ break;
3356
+ case BC_TSETS:
3357
+ | // RA = src*8, RB = table*8, RC = str_const*8 (~)
3358
+ | decode_RB8a RB, INS
3359
+ | decode_RB8b RB
3360
+ | addu CARG2, BASE, RB
3361
+ | decode_RC4a RC, INS
3362
+ | lw TMP0, HI(CARG2)
3363
+ | decode_RC4b RC
3364
+ | li AT, LJ_TTAB
3365
+ | subu CARG3, KBASE, RC
3366
+ | lw TAB:RB, LO(CARG2)
3367
+ | lw STR:RC, -4(CARG3) // KBASE-4-str_const*4
3368
+ | bne TMP0, AT, ->vmeta_tsets1
3369
+ |. addu RA, BASE, RA
3370
+ |->BC_TSETS_Z:
3371
+ | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = BASE+src*8
3372
+ | lw TMP0, TAB:RB->hmask
3373
+ | lw TMP1, STR:RC->hash
3374
+ | lw NODE:TMP2, TAB:RB->node
3375
+ | sb r0, TAB:RB->nomm // Clear metamethod cache.
3376
+ | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask
3377
+ | sll TMP0, TMP1, 5
3378
+ | sll TMP1, TMP1, 3
3379
+ | subu TMP1, TMP0, TMP1
3380
+ | addu NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8)
3381
+ | ldc1 f20, 0(RA)
3382
+ |1:
3383
+ | lw CARG1, offsetof(Node, key)+HI(NODE:TMP2)
3384
+ | lw TMP0, offsetof(Node, key)+LO(NODE:TMP2)
3385
+ | li AT, LJ_TSTR
3386
+ | lw NODE:TMP1, NODE:TMP2->next
3387
+ | bne CARG1, AT, >5
3388
+ |. lw CARG2, offsetof(Node, val)+HI(NODE:TMP2)
3389
+ | bne TMP0, STR:RC, >5
3390
+ |. lbu TMP3, TAB:RB->marked
3391
+ | beq CARG2, TISNIL, >4 // Key found, but nil value?
3392
+ |. lw TAB:TMP0, TAB:RB->metatable
3393
+ |2:
3394
+ | andi AT, TMP3, LJ_GC_BLACK // isblack(table)
3395
+ | bnez AT, >7
3396
+ |. sdc1 f20, NODE:TMP2->val
3397
+ |3:
3398
+ | ins_next
3399
+ |
3400
+ |4: // Check for __newindex if previous value is nil.
3401
+ | beqz TAB:TMP0, <2 // No metatable: done.
3402
+ |. nop
3403
+ | lbu TMP0, TAB:TMP0->nomm
3404
+ | andi TMP0, TMP0, 1<<MM_newindex
3405
+ | bnez TMP0, <2 // 'no __newindex' flag set: done.
3406
+ |. nop
3407
+ | b ->vmeta_tsets
3408
+ |. nop
3409
+ |
3410
+ |5: // Follow hash chain.
3411
+ | bnez NODE:TMP1, <1
3412
+ |. move NODE:TMP2, NODE:TMP1
3413
+ | // End of hash chain: key not found, add a new one
3414
+ |
3415
+ | // But check for __newindex first.
3416
+ | lw TAB:TMP2, TAB:RB->metatable
3417
+ | beqz TAB:TMP2, >6 // No metatable: continue.
3418
+ |. addiu CARG3, DISPATCH, DISPATCH_GL(tmptv)
3419
+ | lbu TMP0, TAB:TMP2->nomm
3420
+ | andi TMP0, TMP0, 1<<MM_newindex
3421
+ | beqz TMP0, ->vmeta_tsets // 'no __newindex' flag NOT set: check.
3422
+ |. li AT, LJ_TSTR
3423
+ |6:
3424
+ | load_got lj_tab_newkey
3425
+ | sw STR:RC, LO(CARG3)
3426
+ | sw AT, HI(CARG3)
3427
+ | sw BASE, L->base
3428
+ | move CARG2, TAB:RB
3429
+ | sw PC, SAVE_PC
3430
+ | call_intern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k
3431
+ |. move CARG1, L
3432
+ | // Returns TValue *.
3433
+ | lw BASE, L->base
3434
+ | b <3 // No 2nd write barrier needed.
3435
+ |. sdc1 f20, 0(CRET1)
3436
+ |
3437
+ |7: // Possible table write barrier for the value. Skip valiswhite check.
3438
+ | barrierback TAB:RB, TMP3, TMP0, <3
3439
+ break;
3440
+ case BC_TSETB:
3441
+ | // RA = src*8, RB = table*8, RC = index*8
3442
+ | decode_RB8a RB, INS
3443
+ | decode_RB8b RB
3444
+ | addu CARG2, BASE, RB
3445
+ | decode_RDtoRC8 RC, RD
3446
+ | lw CARG1, HI(CARG2)
3447
+ | li AT, LJ_TTAB
3448
+ | lw TAB:RB, LO(CARG2)
3449
+ | addu RA, BASE, RA
3450
+ | bne CARG1, AT, ->vmeta_tsetb
3451
+ |. srl TMP0, RC, 3
3452
+ | lw TMP1, TAB:RB->asize
3453
+ | lw TMP2, TAB:RB->array
3454
+ | sltu AT, TMP0, TMP1
3455
+ | beqz AT, ->vmeta_tsetb
3456
+ |. addu RC, TMP2, RC
3457
+ | lw TMP1, HI(RC)
3458
+ | lbu TMP3, TAB:RB->marked
3459
+ | beq TMP1, TISNIL, >5
3460
+ |. ldc1 f0, 0(RA)
3461
+ |1:
3462
+ | andi AT, TMP3, LJ_GC_BLACK // isblack(table)
3463
+ | bnez AT, >7
3464
+ |. sdc1 f0, 0(RC)
3465
+ |2:
3466
+ | ins_next
3467
+ |
3468
+ |5: // Check for __newindex if previous value is nil.
3469
+ | lw TAB:TMP2, TAB:RB->metatable
3470
+ | beqz TAB:TMP2, <1 // No metatable: done.
3471
+ |. nop
3472
+ | lbu TMP1, TAB:TMP2->nomm
3473
+ | andi TMP1, TMP1, 1<<MM_newindex
3474
+ | bnez TMP1, <1 // 'no __newindex' flag set: done.
3475
+ |. nop
3476
+ | b ->vmeta_tsetb // Caveat: preserve TMP0!
3477
+ |. nop
3478
+ |
3479
+ |7: // Possible table write barrier for the value. Skip valiswhite check.
3480
+ | barrierback TAB:RB, TMP3, TMP0, <2
3481
+ break;
3482
+ case BC_TSETR:
3483
+ | // RA = dst*8, RB = table*8, RC = key*8
3484
+ | decode_RB8a RB, INS
3485
+ | decode_RB8b RB
3486
+ | decode_RDtoRC8 RC, RD
3487
+ | addu CARG1, BASE, RB
3488
+ | addu CARG3, BASE, RC
3489
+ | lw TAB:CARG2, LO(CARG1)
3490
+ | ldc1 f0, 0(CARG3)
3491
+ | trunc.w.d f2, f0
3492
+ | lbu TMP3, TAB:CARG2->marked
3493
+ | lw TMP0, TAB:CARG2->asize
3494
+ | mfc1 CARG3, f2
3495
+ | lw TMP1, TAB:CARG2->array
3496
+ | andi AT, TMP3, LJ_GC_BLACK // isblack(table)
3497
+ | bnez AT, >7
3498
+ |. addu RA, BASE, RA
3499
+ |2:
3500
+ | sltu AT, CARG3, TMP0
3501
+ | sll TMP2, CARG3, 3
3502
+ | beqz AT, ->vmeta_tsetr // In array part?
3503
+ |. ldc1 f20, 0(RA)
3504
+ | addu CRET1, TMP1, TMP2
3505
+ |->BC_TSETR_Z:
3506
+ | ins_next1
3507
+ | sdc1 f20, 0(CRET1)
3508
+ | ins_next2
3509
+ |
3510
+ |7: // Possible table write barrier for the value. Skip valiswhite check.
3511
+ | barrierback TAB:RB, TMP3, TMP0, <2
3512
+ break;
3513
+
3514
+
3515
+ case BC_TSETM:
3516
+ | // RA = base*8 (table at base-1), RD = num_const*8 (start index)
3517
+ | addu RA, BASE, RA
3518
+ |1:
3519
+ | addu TMP3, KBASE, RD
3520
+ | lw TAB:CARG2, -8+LO(RA) // Guaranteed to be a table.
3521
+ | addiu TMP0, MULTRES, -8
3522
+ | lw TMP3, LO(TMP3) // Integer constant is in lo-word.
3523
+ | beqz TMP0, >4 // Nothing to copy?
3524
+ |. srl CARG3, TMP0, 3
3525
+ | addu CARG3, CARG3, TMP3
3526
+ | lw TMP2, TAB:CARG2->asize
3527
+ | sll TMP1, TMP3, 3
3528
+ | lbu TMP3, TAB:CARG2->marked
3529
+ | lw CARG1, TAB:CARG2->array
3530
+ | sltu AT, TMP2, CARG3
3531
+ | bnez AT, >5
3532
+ |. addu TMP2, RA, TMP0
3533
+ | addu TMP1, TMP1, CARG1
3534
+ | andi TMP0, TMP3, LJ_GC_BLACK // isblack(table)
3535
+ |3: // Copy result slots to table.
3536
+ | ldc1 f0, 0(RA)
3537
+ | addiu RA, RA, 8
3538
+ | sltu AT, RA, TMP2
3539
+ | sdc1 f0, 0(TMP1)
3540
+ | bnez AT, <3
3541
+ |. addiu TMP1, TMP1, 8
3542
+ | bnez TMP0, >7
3543
+ |. nop
3544
+ |4:
3545
+ | ins_next
3546
+ |
3547
+ |5: // Need to resize array part.
3548
+ | load_got lj_tab_reasize
3549
+ | sw BASE, L->base
3550
+ | sw PC, SAVE_PC
3551
+ | move BASE, RD
3552
+ | call_intern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize)
3553
+ |. move CARG1, L
3554
+ | // Must not reallocate the stack.
3555
+ | move RD, BASE
3556
+ | b <1
3557
+ |. lw BASE, L->base // Reload BASE for lack of a saved register.
3558
+ |
3559
+ |7: // Possible table write barrier for any value. Skip valiswhite check.
3560
+ | barrierback TAB:CARG2, TMP3, TMP0, <4
3561
+ break;
3562
+
3563
+ /* -- Calls and vararg handling ----------------------------------------- */
3564
+
3565
+ case BC_CALLM:
3566
+ | // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8
3567
+ | decode_RDtoRC8 NARGS8:RC, RD
3568
+ | b ->BC_CALL_Z
3569
+ |. addu NARGS8:RC, NARGS8:RC, MULTRES
3570
+ break;
3571
+ case BC_CALL:
3572
+ | // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8
3573
+ | decode_RDtoRC8 NARGS8:RC, RD
3574
+ |->BC_CALL_Z:
3575
+ | move TMP2, BASE
3576
+ | addu BASE, BASE, RA
3577
+ | li AT, LJ_TFUNC
3578
+ | lw TMP0, HI(BASE)
3579
+ | lw LFUNC:RB, LO(BASE)
3580
+ | addiu BASE, BASE, 8
3581
+ | bne TMP0, AT, ->vmeta_call
3582
+ |. addiu NARGS8:RC, NARGS8:RC, -8
3583
+ | ins_call
3584
+ break;
3585
+
3586
+ case BC_CALLMT:
3587
+ | // RA = base*8, (RB = 0,) RC = extra_nargs*8
3588
+ | addu NARGS8:RD, NARGS8:RD, MULTRES // BC_CALLT gets RC from RD.
3589
+ | // Fall through. Assumes BC_CALLT follows.
3590
+ break;
3591
+ case BC_CALLT:
3592
+ | // RA = base*8, (RB = 0,) RC = (nargs+1)*8
3593
+ | addu RA, BASE, RA
3594
+ | li AT, LJ_TFUNC
3595
+ | lw TMP0, HI(RA)
3596
+ | lw LFUNC:RB, LO(RA)
3597
+ | move NARGS8:RC, RD
3598
+ | lw TMP1, FRAME_PC(BASE)
3599
+ | addiu RA, RA, 8
3600
+ | bne TMP0, AT, ->vmeta_callt
3601
+ |. addiu NARGS8:RC, NARGS8:RC, -8
3602
+ |->BC_CALLT_Z:
3603
+ | andi TMP0, TMP1, FRAME_TYPE // Caveat: preserve TMP0 until the 'or'.
3604
+ | lbu TMP3, LFUNC:RB->ffid
3605
+ | bnez TMP0, >7
3606
+ |. xori TMP2, TMP1, FRAME_VARG
3607
+ |1:
3608
+ | sw LFUNC:RB, FRAME_FUNC(BASE) // Copy function down, but keep PC.
3609
+ | sltiu AT, TMP3, 2 // (> FF_C) Calling a fast function?
3610
+ | move TMP2, BASE
3611
+ | beqz NARGS8:RC, >3
3612
+ |. move TMP3, NARGS8:RC
3613
+ |2:
3614
+ | ldc1 f0, 0(RA)
3615
+ | addiu RA, RA, 8
3616
+ | addiu TMP3, TMP3, -8
3617
+ | sdc1 f0, 0(TMP2)
3618
+ | bnez TMP3, <2
3619
+ |. addiu TMP2, TMP2, 8
3620
+ |3:
3621
+ | or TMP0, TMP0, AT
3622
+ | beqz TMP0, >5
3623
+ |. nop
3624
+ |4:
3625
+ | ins_callt
3626
+ |
3627
+ |5: // Tailcall to a fast function with a Lua frame below.
3628
+ | lw INS, -4(TMP1)
3629
+ | decode_RA8a RA, INS
3630
+ | decode_RA8b RA
3631
+ | subu TMP1, BASE, RA
3632
+ | lw LFUNC:TMP1, -8+FRAME_FUNC(TMP1)
3633
+ | lw TMP1, LFUNC:TMP1->pc
3634
+ | b <4
3635
+ |. lw KBASE, PC2PROTO(k)(TMP1) // Need to prepare KBASE.
3636
+ |
3637
+ |7: // Tailcall from a vararg function.
3638
+ | andi AT, TMP2, FRAME_TYPEP
3639
+ | bnez AT, <1 // Vararg frame below?
3640
+ |. subu TMP2, BASE, TMP2 // Relocate BASE down.
3641
+ | move BASE, TMP2
3642
+ | lw TMP1, FRAME_PC(TMP2)
3643
+ | b <1
3644
+ |. andi TMP0, TMP1, FRAME_TYPE
3645
+ break;
3646
+
3647
+ case BC_ITERC:
3648
+ | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8))
3649
+ | move TMP2, BASE
3650
+ | addu BASE, BASE, RA
3651
+ | li AT, LJ_TFUNC
3652
+ | lw TMP1, -24+HI(BASE)
3653
+ | lw LFUNC:RB, -24+LO(BASE)
3654
+ | ldc1 f2, -8(BASE)
3655
+ | ldc1 f0, -16(BASE)
3656
+ | sw TMP1, HI(BASE) // Copy callable.
3657
+ | sw LFUNC:RB, LO(BASE)
3658
+ | sdc1 f2, 16(BASE) // Copy control var.
3659
+ | sdc1 f0, 8(BASE) // Copy state.
3660
+ | addiu BASE, BASE, 8
3661
+ | bne TMP1, AT, ->vmeta_call
3662
+ |. li NARGS8:RC, 16 // Iterators get 2 arguments.
3663
+ | ins_call
3664
+ break;
3665
+
3666
+ case BC_ITERN:
3667
+ | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8)
3668
+ |.if JIT
3669
+ | // NYI: add hotloop, record BC_ITERN.
3670
+ |.endif
3671
+ | addu RA, BASE, RA
3672
+ | lw TAB:RB, -16+LO(RA)
3673
+ | lw RC, -8+LO(RA) // Get index from control var.
3674
+ | lw TMP0, TAB:RB->asize
3675
+ | lw TMP1, TAB:RB->array
3676
+ | addiu PC, PC, 4
3677
+ |1: // Traverse array part.
3678
+ | sltu AT, RC, TMP0
3679
+ | beqz AT, >5 // Index points after array part?
3680
+ |. sll TMP3, RC, 3
3681
+ | addu TMP3, TMP1, TMP3
3682
+ | lw TMP2, HI(TMP3)
3683
+ | ldc1 f0, 0(TMP3)
3684
+ | mtc1 RC, f2
3685
+ | lhu RD, -4+OFS_RD(PC)
3686
+ | beq TMP2, TISNIL, <1 // Skip holes in array part.
3687
+ |. addiu RC, RC, 1
3688
+ | cvt.d.w f2, f2
3689
+ | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535)
3690
+ | sdc1 f0, 8(RA)
3691
+ | decode_RD4b RD
3692
+ | addu RD, RD, TMP3
3693
+ | sw RC, -8+LO(RA) // Update control var.
3694
+ | addu PC, PC, RD
3695
+ | sdc1 f2, 0(RA)
3696
+ |3:
3697
+ | ins_next
3698
+ |
3699
+ |5: // Traverse hash part.
3700
+ | lw TMP1, TAB:RB->hmask
3701
+ | subu RC, RC, TMP0
3702
+ | lw TMP2, TAB:RB->node
3703
+ |6:
3704
+ | sltu AT, TMP1, RC // End of iteration? Branch to ITERL+1.
3705
+ | bnez AT, <3
3706
+ |. sll TMP3, RC, 5
3707
+ | sll RB, RC, 3
3708
+ | subu TMP3, TMP3, RB
3709
+ | addu NODE:TMP3, TMP3, TMP2
3710
+ | lw RB, HI(NODE:TMP3)
3711
+ | ldc1 f0, 0(NODE:TMP3)
3712
+ | lhu RD, -4+OFS_RD(PC)
3713
+ | beq RB, TISNIL, <6 // Skip holes in hash part.
3714
+ |. addiu RC, RC, 1
3715
+ | ldc1 f2, NODE:TMP3->key
3716
+ | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535)
3717
+ | sdc1 f0, 8(RA)
3718
+ | addu RC, RC, TMP0
3719
+ | decode_RD4b RD
3720
+ | addu RD, RD, TMP3
3721
+ | sdc1 f2, 0(RA)
3722
+ | addu PC, PC, RD
3723
+ | b <3
3724
+ |. sw RC, -8+LO(RA) // Update control var.
3725
+ break;
3726
+
3727
+ case BC_ISNEXT:
3728
+ | // RA = base*8, RD = target (points to ITERN)
3729
+ | addu RA, BASE, RA
3730
+ | lw TMP0, -24+HI(RA)
3731
+ | lw CFUNC:TMP1, -24+LO(RA)
3732
+ | lw TMP2, -16+HI(RA)
3733
+ | lw TMP3, -8+HI(RA)
3734
+ | li AT, LJ_TFUNC
3735
+ | bne TMP0, AT, >5
3736
+ |. addiu TMP2, TMP2, -LJ_TTAB
3737
+ | lbu TMP1, CFUNC:TMP1->ffid
3738
+ | addiu TMP3, TMP3, -LJ_TNIL
3739
+ | srl TMP0, RD, 1
3740
+ | or TMP2, TMP2, TMP3
3741
+ | addiu TMP1, TMP1, -FF_next_N
3742
+ | addu TMP0, PC, TMP0
3743
+ | or TMP1, TMP1, TMP2
3744
+ | bnez TMP1, >5
3745
+ |. lui TMP2, (-(BCBIAS_J*4 >> 16) & 65535)
3746
+ | addu PC, TMP0, TMP2
3747
+ | lui TMP1, 0xfffe
3748
+ | ori TMP1, TMP1, 0x7fff
3749
+ | sw r0, -8+LO(RA) // Initialize control var.
3750
+ | sw TMP1, -8+HI(RA)
3751
+ |1:
3752
+ | ins_next
3753
+ |5: // Despecialize bytecode if any of the checks fail.
3754
+ | li TMP3, BC_JMP
3755
+ | li TMP1, BC_ITERC
3756
+ | sb TMP3, -4+OFS_OP(PC)
3757
+ | addu PC, TMP0, TMP2
3758
+ | b <1
3759
+ |. sb TMP1, OFS_OP(PC)
3760
+ break;
3761
+
3762
+ case BC_VARG:
3763
+ | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8
3764
+ | lw TMP0, FRAME_PC(BASE)
3765
+ | decode_RDtoRC8 RC, RD
3766
+ | decode_RB8a RB, INS
3767
+ | addu RC, BASE, RC
3768
+ | decode_RB8b RB
3769
+ | addu RA, BASE, RA
3770
+ | addiu RC, RC, FRAME_VARG
3771
+ | addu TMP2, RA, RB
3772
+ | addiu TMP3, BASE, -8 // TMP3 = vtop
3773
+ | subu RC, RC, TMP0 // RC = vbase
3774
+ | // Note: RC may now be even _above_ BASE if nargs was < numparams.
3775
+ | beqz RB, >5 // Copy all varargs?
3776
+ |. subu TMP1, TMP3, RC
3777
+ | addiu TMP2, TMP2, -16
3778
+ |1: // Copy vararg slots to destination slots.
3779
+ | lw CARG1, HI(RC)
3780
+ | sltu AT, RC, TMP3
3781
+ | lw CARG2, LO(RC)
3782
+ | addiu RC, RC, 8
3783
+ | movz CARG1, TISNIL, AT
3784
+ | sw CARG1, HI(RA)
3785
+ | sw CARG2, LO(RA)
3786
+ | sltu AT, RA, TMP2
3787
+ | bnez AT, <1
3788
+ |. addiu RA, RA, 8
3789
+ |3:
3790
+ | ins_next
3791
+ |
3792
+ |5: // Copy all varargs.
3793
+ | lw TMP0, L->maxstack
3794
+ | blez TMP1, <3 // No vararg slots?
3795
+ |. li MULTRES, 8 // MULTRES = (0+1)*8
3796
+ | addu TMP2, RA, TMP1
3797
+ | sltu AT, TMP0, TMP2
3798
+ | bnez AT, >7
3799
+ |. addiu MULTRES, TMP1, 8
3800
+ |6:
3801
+ | ldc1 f0, 0(RC)
3802
+ | addiu RC, RC, 8
3803
+ | sdc1 f0, 0(RA)
3804
+ | sltu AT, RC, TMP3
3805
+ | bnez AT, <6 // More vararg slots?
3806
+ |. addiu RA, RA, 8
3807
+ | b <3
3808
+ |. nop
3809
+ |
3810
+ |7: // Grow stack for varargs.
3811
+ | load_got lj_state_growstack
3812
+ | sw RA, L->top
3813
+ | subu RA, RA, BASE
3814
+ | sw BASE, L->base
3815
+ | subu BASE, RC, BASE // Need delta, because BASE may change.
3816
+ | sw PC, SAVE_PC
3817
+ | srl CARG2, TMP1, 3
3818
+ | call_intern lj_state_growstack // (lua_State *L, int n)
3819
+ |. move CARG1, L
3820
+ | move RC, BASE
3821
+ | lw BASE, L->base
3822
+ | addu RA, BASE, RA
3823
+ | addu RC, BASE, RC
3824
+ | b <6
3825
+ |. addiu TMP3, BASE, -8
3826
+ break;
3827
+
3828
+ /* -- Returns ----------------------------------------------------------- */
3829
+
3830
+ case BC_RETM:
3831
+ | // RA = results*8, RD = extra_nresults*8
3832
+ | addu RD, RD, MULTRES // MULTRES >= 8, so RD >= 8.
3833
+ | // Fall through. Assumes BC_RET follows.
3834
+ break;
3835
+
3836
+ case BC_RET:
3837
+ | // RA = results*8, RD = (nresults+1)*8
3838
+ | lw PC, FRAME_PC(BASE)
3839
+ | addu RA, BASE, RA
3840
+ | move MULTRES, RD
3841
+ |1:
3842
+ | andi TMP0, PC, FRAME_TYPE
3843
+ | bnez TMP0, ->BC_RETV_Z
3844
+ |. xori TMP1, PC, FRAME_VARG
3845
+ |
3846
+ |->BC_RET_Z:
3847
+ | // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return
3848
+ | lw INS, -4(PC)
3849
+ | addiu TMP2, BASE, -8
3850
+ | addiu RC, RD, -8
3851
+ | decode_RA8a TMP0, INS
3852
+ | decode_RB8a RB, INS
3853
+ | decode_RA8b TMP0
3854
+ | decode_RB8b RB
3855
+ | addu TMP3, TMP2, RB
3856
+ | beqz RC, >3
3857
+ |. subu BASE, TMP2, TMP0
3858
+ |2:
3859
+ | ldc1 f0, 0(RA)
3860
+ | addiu RA, RA, 8
3861
+ | addiu RC, RC, -8
3862
+ | sdc1 f0, 0(TMP2)
3863
+ | bnez RC, <2
3864
+ |. addiu TMP2, TMP2, 8
3865
+ |3:
3866
+ | addiu TMP3, TMP3, -8
3867
+ |5:
3868
+ | sltu AT, TMP2, TMP3
3869
+ | bnez AT, >6
3870
+ |. lw LFUNC:TMP1, FRAME_FUNC(BASE)
3871
+ | ins_next1
3872
+ | lw TMP1, LFUNC:TMP1->pc
3873
+ | lw KBASE, PC2PROTO(k)(TMP1)
3874
+ | ins_next2
3875
+ |
3876
+ |6: // Fill up results with nil.
3877
+ | sw TISNIL, HI(TMP2)
3878
+ | b <5
3879
+ |. addiu TMP2, TMP2, 8
3880
+ |
3881
+ |->BC_RETV_Z: // Non-standard return case.
3882
+ | andi TMP2, TMP1, FRAME_TYPEP
3883
+ | bnez TMP2, ->vm_return
3884
+ |. nop
3885
+ | // Return from vararg function: relocate BASE down.
3886
+ | subu BASE, BASE, TMP1
3887
+ | b <1
3888
+ |. lw PC, FRAME_PC(BASE)
3889
+ break;
3890
+
3891
+ case BC_RET0: case BC_RET1:
3892
+ | // RA = results*8, RD = (nresults+1)*8
3893
+ | lw PC, FRAME_PC(BASE)
3894
+ | addu RA, BASE, RA
3895
+ | move MULTRES, RD
3896
+ | andi TMP0, PC, FRAME_TYPE
3897
+ | bnez TMP0, ->BC_RETV_Z
3898
+ |. xori TMP1, PC, FRAME_VARG
3899
+ |
3900
+ | lw INS, -4(PC)
3901
+ | addiu TMP2, BASE, -8
3902
+ if (op == BC_RET1) {
3903
+ | ldc1 f0, 0(RA)
3904
+ }
3905
+ | decode_RB8a RB, INS
3906
+ | decode_RA8a RA, INS
3907
+ | decode_RB8b RB
3908
+ | decode_RA8b RA
3909
+ if (op == BC_RET1) {
3910
+ | sdc1 f0, 0(TMP2)
3911
+ }
3912
+ | subu BASE, TMP2, RA
3913
+ |5:
3914
+ | sltu AT, RD, RB
3915
+ | bnez AT, >6
3916
+ |. lw LFUNC:TMP1, FRAME_FUNC(BASE)
3917
+ | ins_next1
3918
+ | lw TMP1, LFUNC:TMP1->pc
3919
+ | lw KBASE, PC2PROTO(k)(TMP1)
3920
+ | ins_next2
3921
+ |
3922
+ |6: // Fill up results with nil.
3923
+ | addiu TMP2, TMP2, 8
3924
+ | addiu RD, RD, 8
3925
+ | b <5
3926
+ if (op == BC_RET1) {
3927
+ |. sw TISNIL, HI(TMP2)
3928
+ } else {
3929
+ |. sw TISNIL, -8+HI(TMP2)
3930
+ }
3931
+ break;
3932
+
3933
+ /* -- Loops and branches ------------------------------------------------ */
3934
+
3935
+ case BC_FORL:
3936
+ |.if JIT
3937
+ | hotloop
3938
+ |.endif
3939
+ | // Fall through. Assumes BC_IFORL follows.
3940
+ break;
3941
+
3942
+ case BC_JFORI:
3943
+ case BC_JFORL:
3944
+ #if !LJ_HASJIT
3945
+ break;
3946
+ #endif
3947
+ case BC_FORI:
3948
+ case BC_IFORL:
3949
+ | // RA = base*8, RD = target (after end of loop or start of loop)
3950
+ vk = (op == BC_IFORL || op == BC_JFORL);
3951
+ | addu RA, BASE, RA
3952
+ if (vk) {
3953
+ | ldc1 f0, FORL_IDX*8(RA)
3954
+ | ldc1 f4, FORL_STEP*8(RA)
3955
+ | ldc1 f2, FORL_STOP*8(RA)
3956
+ | lw TMP3, FORL_STEP*8+HI(RA)
3957
+ | add.d f0, f0, f4
3958
+ | sdc1 f0, FORL_IDX*8(RA)
3959
+ } else {
3960
+ | lw TMP1, FORL_IDX*8+HI(RA)
3961
+ | lw TMP3, FORL_STEP*8+HI(RA)
3962
+ | lw TMP2, FORL_STOP*8+HI(RA)
3963
+ | sltiu TMP1, TMP1, LJ_TISNUM
3964
+ | sltiu TMP0, TMP3, LJ_TISNUM
3965
+ | sltiu TMP2, TMP2, LJ_TISNUM
3966
+ | and TMP1, TMP1, TMP0
3967
+ | and TMP1, TMP1, TMP2
3968
+ | ldc1 f0, FORL_IDX*8(RA)
3969
+ | beqz TMP1, ->vmeta_for
3970
+ |. ldc1 f2, FORL_STOP*8(RA)
3971
+ }
3972
+ if (op != BC_JFORL) {
3973
+ | srl RD, RD, 1
3974
+ | lui TMP0, (-(BCBIAS_J*4 >> 16) & 65535)
3975
+ }
3976
+ | c.le.d 0, f0, f2
3977
+ | c.le.d 1, f2, f0
3978
+ | sdc1 f0, FORL_EXT*8(RA)
3979
+ if (op == BC_JFORI) {
3980
+ | li TMP1, 1
3981
+ | li TMP2, 1
3982
+ | addu TMP0, RD, TMP0
3983
+ | slt TMP3, TMP3, r0
3984
+ | movf TMP1, r0, 0
3985
+ | addu PC, PC, TMP0
3986
+ | movf TMP2, r0, 1
3987
+ | lhu RD, -4+OFS_RD(PC)
3988
+ | movn TMP1, TMP2, TMP3
3989
+ | bnez TMP1, =>BC_JLOOP
3990
+ |. decode_RD8b RD
3991
+ } else if (op == BC_JFORL) {
3992
+ | li TMP1, 1
3993
+ | li TMP2, 1
3994
+ | slt TMP3, TMP3, r0
3995
+ | movf TMP1, r0, 0
3996
+ | movf TMP2, r0, 1
3997
+ | movn TMP1, TMP2, TMP3
3998
+ | bnez TMP1, =>BC_JLOOP
3999
+ |. nop
4000
+ } else {
4001
+ | addu TMP1, RD, TMP0
4002
+ | slt TMP3, TMP3, r0
4003
+ | move TMP2, TMP1
4004
+ if (op == BC_FORI) {
4005
+ | movt TMP1, r0, 0
4006
+ | movt TMP2, r0, 1
4007
+ } else {
4008
+ | movf TMP1, r0, 0
4009
+ | movf TMP2, r0, 1
4010
+ }
4011
+ | movn TMP1, TMP2, TMP3
4012
+ | addu PC, PC, TMP1
4013
+ }
4014
+ | ins_next
4015
+ break;
4016
+
4017
+ case BC_ITERL:
4018
+ |.if JIT
4019
+ | hotloop
4020
+ |.endif
4021
+ | // Fall through. Assumes BC_IITERL follows.
4022
+ break;
4023
+
4024
+ case BC_JITERL:
4025
+ #if !LJ_HASJIT
4026
+ break;
4027
+ #endif
4028
+ case BC_IITERL:
4029
+ | // RA = base*8, RD = target
4030
+ | addu RA, BASE, RA
4031
+ | lw TMP1, HI(RA)
4032
+ | beq TMP1, TISNIL, >1 // Stop if iterator returned nil.
4033
+ |. lw TMP2, LO(RA)
4034
+ if (op == BC_JITERL) {
4035
+ | sw TMP1, -8+HI(RA)
4036
+ | b =>BC_JLOOP
4037
+ |. sw TMP2, -8+LO(RA)
4038
+ } else {
4039
+ | branch_RD // Otherwise save control var + branch.
4040
+ | sw TMP1, -8+HI(RA)
4041
+ | sw TMP2, -8+LO(RA)
4042
+ }
4043
+ |1:
4044
+ | ins_next
4045
+ break;
4046
+
4047
+ case BC_LOOP:
4048
+ | // RA = base*8, RD = target (loop extent)
4049
+ | // Note: RA/RD is only used by trace recorder to determine scope/extent
4050
+ | // This opcode does NOT jump, it's only purpose is to detect a hot loop.
4051
+ |.if JIT
4052
+ | hotloop
4053
+ |.endif
4054
+ | // Fall through. Assumes BC_ILOOP follows.
4055
+ break;
4056
+
4057
+ case BC_ILOOP:
4058
+ | // RA = base*8, RD = target (loop extent)
4059
+ | ins_next
4060
+ break;
4061
+
4062
+ case BC_JLOOP:
4063
+ |.if JIT
4064
+ | // RA = base*8 (ignored), RD = traceno*8
4065
+ | lw TMP1, DISPATCH_J(trace)(DISPATCH)
4066
+ | srl RD, RD, 1
4067
+ | li AT, 0
4068
+ | addu TMP1, TMP1, RD
4069
+ | // Traces on MIPS don't store the trace number, so use 0.
4070
+ | sw AT, DISPATCH_GL(vmstate)(DISPATCH)
4071
+ | lw TRACE:TMP2, 0(TMP1)
4072
+ | sw BASE, DISPATCH_GL(jit_base)(DISPATCH)
4073
+ | lw TMP2, TRACE:TMP2->mcode
4074
+ | sw L, DISPATCH_GL(tmpbuf.L)(DISPATCH)
4075
+ | jr TMP2
4076
+ |. addiu JGL, DISPATCH, GG_DISP2G+32768
4077
+ |.endif
4078
+ break;
4079
+
4080
+ case BC_JMP:
4081
+ | // RA = base*8 (only used by trace recorder), RD = target
4082
+ | branch_RD
4083
+ | ins_next
4084
+ break;
4085
+
4086
+ /* -- Function headers -------------------------------------------------- */
4087
+
4088
+ case BC_FUNCF:
4089
+ |.if JIT
4090
+ | hotcall
4091
+ |.endif
4092
+ case BC_FUNCV: /* NYI: compiled vararg functions. */
4093
+ | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow.
4094
+ break;
4095
+
4096
+ case BC_JFUNCF:
4097
+ #if !LJ_HASJIT
4098
+ break;
4099
+ #endif
4100
+ case BC_IFUNCF:
4101
+ | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8
4102
+ | lw TMP2, L->maxstack
4103
+ | lbu TMP1, -4+PC2PROTO(numparams)(PC)
4104
+ | lw KBASE, -4+PC2PROTO(k)(PC)
4105
+ | sltu AT, TMP2, RA
4106
+ | bnez AT, ->vm_growstack_l
4107
+ |. sll TMP1, TMP1, 3
4108
+ if (op != BC_JFUNCF) {
4109
+ | ins_next1
4110
+ }
4111
+ |2:
4112
+ | sltu AT, NARGS8:RC, TMP1 // Check for missing parameters.
4113
+ | bnez AT, >3
4114
+ |. addu AT, BASE, NARGS8:RC
4115
+ if (op == BC_JFUNCF) {
4116
+ | decode_RD8a RD, INS
4117
+ | b =>BC_JLOOP
4118
+ |. decode_RD8b RD
4119
+ } else {
4120
+ | ins_next2
4121
+ }
4122
+ |
4123
+ |3: // Clear missing parameters.
4124
+ | sw TISNIL, HI(AT)
4125
+ | b <2
4126
+ |. addiu NARGS8:RC, NARGS8:RC, 8
4127
+ break;
4128
+
4129
+ case BC_JFUNCV:
4130
+ #if !LJ_HASJIT
4131
+ break;
4132
+ #endif
4133
+ | NYI // NYI: compiled vararg functions
4134
+ break; /* NYI: compiled vararg functions. */
4135
+
4136
+ case BC_IFUNCV:
4137
+ | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8
4138
+ | addu TMP1, BASE, RC
4139
+ | lw TMP2, L->maxstack
4140
+ | addu TMP0, RA, RC
4141
+ | sw LFUNC:RB, LO(TMP1) // Store copy of LFUNC.
4142
+ | addiu TMP3, RC, 8+FRAME_VARG
4143
+ | sltu AT, TMP0, TMP2
4144
+ | lw KBASE, -4+PC2PROTO(k)(PC)
4145
+ | beqz AT, ->vm_growstack_l
4146
+ |. sw TMP3, HI(TMP1) // Store delta + FRAME_VARG.
4147
+ | lbu TMP2, -4+PC2PROTO(numparams)(PC)
4148
+ | move RA, BASE
4149
+ | move RC, TMP1
4150
+ | ins_next1
4151
+ | beqz TMP2, >3
4152
+ |. addiu BASE, TMP1, 8
4153
+ |1:
4154
+ | lw TMP0, HI(RA)
4155
+ | lw TMP3, LO(RA)
4156
+ | sltu AT, RA, RC // Less args than parameters?
4157
+ | move CARG1, TMP0
4158
+ | movz TMP0, TISNIL, AT // Clear missing parameters.
4159
+ | movn CARG1, TISNIL, AT // Clear old fixarg slot (help the GC).
4160
+ | sw TMP3, 8+LO(TMP1)
4161
+ | addiu TMP2, TMP2, -1
4162
+ | sw TMP0, 8+HI(TMP1)
4163
+ | addiu TMP1, TMP1, 8
4164
+ | sw CARG1, HI(RA)
4165
+ | bnez TMP2, <1
4166
+ |. addiu RA, RA, 8
4167
+ |3:
4168
+ | ins_next2
4169
+ break;
4170
+
4171
+ case BC_FUNCC:
4172
+ case BC_FUNCCW:
4173
+ | // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8
4174
+ if (op == BC_FUNCC) {
4175
+ | lw CFUNCADDR, CFUNC:RB->f
4176
+ } else {
4177
+ | lw CFUNCADDR, DISPATCH_GL(wrapf)(DISPATCH)
4178
+ }
4179
+ | addu TMP1, RA, NARGS8:RC
4180
+ | lw TMP2, L->maxstack
4181
+ | addu RC, BASE, NARGS8:RC
4182
+ | sw BASE, L->base
4183
+ | sltu AT, TMP2, TMP1
4184
+ | sw RC, L->top
4185
+ | li_vmstate C
4186
+ if (op == BC_FUNCCW) {
4187
+ | lw CARG2, CFUNC:RB->f
4188
+ }
4189
+ | bnez AT, ->vm_growstack_c // Need to grow stack.
4190
+ |. move CARG1, L
4191
+ | jalr CFUNCADDR // (lua_State *L [, lua_CFunction f])
4192
+ |. st_vmstate
4193
+ | // Returns nresults.
4194
+ | lw BASE, L->base
4195
+ | sll RD, CRET1, 3
4196
+ | lw TMP1, L->top
4197
+ | li_vmstate INTERP
4198
+ | lw PC, FRAME_PC(BASE) // Fetch PC of caller.
4199
+ | subu RA, TMP1, RD // RA = L->top - nresults*8
4200
+ | sw L, DISPATCH_GL(cur_L)(DISPATCH)
4201
+ | b ->vm_returnc
4202
+ |. st_vmstate
4203
+ break;
4204
+
4205
+ /* ---------------------------------------------------------------------- */
4206
+
4207
+ default:
4208
+ fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]);
4209
+ exit(2);
4210
+ break;
4211
+ }
4212
+ }
4213
+
4214
+ static int build_backend(BuildCtx *ctx)
4215
+ {
4216
+ int op;
4217
+
4218
+ dasm_growpc(Dst, BC__MAX);
4219
+
4220
+ build_subroutines(ctx);
4221
+
4222
+ |.code_op
4223
+ for (op = 0; op < BC__MAX; op++)
4224
+ build_ins(ctx, (BCOp)op, op);
4225
+
4226
+ return BC__MAX;
4227
+ }
4228
+
4229
+ /* Emit pseudo frame-info for all assembler functions. */
4230
+ static void emit_asm_debug(BuildCtx *ctx)
4231
+ {
4232
+ int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code);
4233
+ int i;
4234
+ switch (ctx->mode) {
4235
+ case BUILD_elfasm:
4236
+ fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n");
4237
+ fprintf(ctx->fp,
4238
+ ".Lframe0:\n"
4239
+ "\t.4byte .LECIE0-.LSCIE0\n"
4240
+ ".LSCIE0:\n"
4241
+ "\t.4byte 0xffffffff\n"
4242
+ "\t.byte 0x1\n"
4243
+ "\t.string \"\"\n"
4244
+ "\t.uleb128 0x1\n"
4245
+ "\t.sleb128 -4\n"
4246
+ "\t.byte 31\n"
4247
+ "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n"
4248
+ "\t.align 2\n"
4249
+ ".LECIE0:\n\n");
4250
+ fprintf(ctx->fp,
4251
+ ".LSFDE0:\n"
4252
+ "\t.4byte .LEFDE0-.LASFDE0\n"
4253
+ ".LASFDE0:\n"
4254
+ "\t.4byte .Lframe0\n"
4255
+ "\t.4byte .Lbegin\n"
4256
+ "\t.4byte %d\n"
4257
+ "\t.byte 0xe\n\t.uleb128 %d\n"
4258
+ "\t.byte 0x9f\n\t.sleb128 1\n"
4259
+ "\t.byte 0x9e\n\t.sleb128 2\n",
4260
+ fcofs, CFRAME_SIZE);
4261
+ for (i = 23; i >= 16; i--)
4262
+ fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 26-i);
4263
+ for (i = 30; i >= 20; i -= 2)
4264
+ fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+32+i, 42-i);
4265
+ fprintf(ctx->fp,
4266
+ "\t.align 2\n"
4267
+ ".LEFDE0:\n\n");
4268
+ #if LJ_HASFFI
4269
+ fprintf(ctx->fp,
4270
+ ".LSFDE1:\n"
4271
+ "\t.4byte .LEFDE1-.LASFDE1\n"
4272
+ ".LASFDE1:\n"
4273
+ "\t.4byte .Lframe0\n"
4274
+ "\t.4byte lj_vm_ffi_call\n"
4275
+ "\t.4byte %d\n"
4276
+ "\t.byte 0x9f\n\t.uleb128 1\n"
4277
+ "\t.byte 0x90\n\t.uleb128 2\n"
4278
+ "\t.byte 0xd\n\t.uleb128 0x10\n"
4279
+ "\t.align 2\n"
4280
+ ".LEFDE1:\n\n", (int)ctx->codesz - fcofs);
4281
+ #endif
4282
+ fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n");
4283
+ fprintf(ctx->fp,
4284
+ "\t.globl lj_err_unwind_dwarf\n"
4285
+ ".Lframe1:\n"
4286
+ "\t.4byte .LECIE1-.LSCIE1\n"
4287
+ ".LSCIE1:\n"
4288
+ "\t.4byte 0\n"
4289
+ "\t.byte 0x1\n"
4290
+ "\t.string \"zPR\"\n"
4291
+ "\t.uleb128 0x1\n"
4292
+ "\t.sleb128 -4\n"
4293
+ "\t.byte 31\n"
4294
+ "\t.uleb128 6\n" /* augmentation length */
4295
+ "\t.byte 0\n"
4296
+ "\t.4byte lj_err_unwind_dwarf\n"
4297
+ "\t.byte 0\n"
4298
+ "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n"
4299
+ "\t.align 2\n"
4300
+ ".LECIE1:\n\n");
4301
+ fprintf(ctx->fp,
4302
+ ".LSFDE2:\n"
4303
+ "\t.4byte .LEFDE2-.LASFDE2\n"
4304
+ ".LASFDE2:\n"
4305
+ "\t.4byte .LASFDE2-.Lframe1\n"
4306
+ "\t.4byte .Lbegin\n"
4307
+ "\t.4byte %d\n"
4308
+ "\t.uleb128 0\n" /* augmentation length */
4309
+ "\t.byte 0xe\n\t.uleb128 %d\n"
4310
+ "\t.byte 0x9f\n\t.sleb128 1\n"
4311
+ "\t.byte 0x9e\n\t.sleb128 2\n",
4312
+ fcofs, CFRAME_SIZE);
4313
+ for (i = 23; i >= 16; i--)
4314
+ fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 26-i);
4315
+ for (i = 30; i >= 20; i -= 2)
4316
+ fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+32+i, 42-i);
4317
+ fprintf(ctx->fp,
4318
+ "\t.align 2\n"
4319
+ ".LEFDE2:\n\n");
4320
+ #if LJ_HASFFI
4321
+ fprintf(ctx->fp,
4322
+ ".Lframe2:\n"
4323
+ "\t.4byte .LECIE2-.LSCIE2\n"
4324
+ ".LSCIE2:\n"
4325
+ "\t.4byte 0\n"
4326
+ "\t.byte 0x1\n"
4327
+ "\t.string \"zR\"\n"
4328
+ "\t.uleb128 0x1\n"
4329
+ "\t.sleb128 -4\n"
4330
+ "\t.byte 31\n"
4331
+ "\t.uleb128 1\n" /* augmentation length */
4332
+ "\t.byte 0\n"
4333
+ "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n"
4334
+ "\t.align 2\n"
4335
+ ".LECIE2:\n\n");
4336
+ fprintf(ctx->fp,
4337
+ ".LSFDE3:\n"
4338
+ "\t.4byte .LEFDE3-.LASFDE3\n"
4339
+ ".LASFDE3:\n"
4340
+ "\t.4byte .LASFDE3-.Lframe2\n"
4341
+ "\t.4byte lj_vm_ffi_call\n"
4342
+ "\t.4byte %d\n"
4343
+ "\t.uleb128 0\n" /* augmentation length */
4344
+ "\t.byte 0x9f\n\t.uleb128 1\n"
4345
+ "\t.byte 0x90\n\t.uleb128 2\n"
4346
+ "\t.byte 0xd\n\t.uleb128 0x10\n"
4347
+ "\t.align 2\n"
4348
+ ".LEFDE3:\n\n", (int)ctx->codesz - fcofs);
4349
+ #endif
4350
+ break;
4351
+ default:
4352
+ break;
4353
+ }
4354
+ }
4355
+