From 38219f1774cddece088070ee4ea1bc748f965cdc Mon Sep 17 00:00:00 2001
From: RaphaelIT7 <64648134+RaphaelIT7@users.noreply.github.com>
Date: Mon, 6 Oct 2025 09:35:01 +0200
Subject: [PATCH 01/14] Push LuaJIT 2.1
---
LuaJIT-2.1/.gitattributes | 1 +
LuaJIT-2.1/.gitignore | 11 +
LuaJIT-2.1/.relver | 1 +
LuaJIT-2.1/COPYRIGHT | 56 +
LuaJIT-2.1/Makefile | 175 +
LuaJIT-2.1/README | 16 +
LuaJIT-2.1/doc/bluequad-print.css | 166 +
LuaJIT-2.1/doc/bluequad.css | 323 +
LuaJIT-2.1/doc/contact.html | 112 +
LuaJIT-2.1/doc/ext_buffer.html | 689 +++
LuaJIT-2.1/doc/ext_c_api.html | 183 +
LuaJIT-2.1/doc/ext_ffi.html | 326 ++
LuaJIT-2.1/doc/ext_ffi_api.html | 568 ++
LuaJIT-2.1/doc/ext_ffi_semantics.html | 1269 ++++
LuaJIT-2.1/doc/ext_ffi_tutorial.html | 597 ++
LuaJIT-2.1/doc/ext_jit.html | 197 +
LuaJIT-2.1/doc/ext_profiler.html | 359 ++
LuaJIT-2.1/doc/extensions.html | 502 ++
LuaJIT-2.1/doc/img/contact.png | Bin 0 -> 1340 bytes
LuaJIT-2.1/doc/install.html | 582 ++
LuaJIT-2.1/doc/luajit.html | 203 +
LuaJIT-2.1/doc/running.html | 317 +
LuaJIT-2.1/dynasm/dasm_arm.h | 456 ++
LuaJIT-2.1/dynasm/dasm_arm.lua | 1125 ++++
LuaJIT-2.1/dynasm/dasm_arm64.h | 558 ++
LuaJIT-2.1/dynasm/dasm_arm64.lua | 1226 ++++
LuaJIT-2.1/dynasm/dasm_mips.h | 419 ++
LuaJIT-2.1/dynasm/dasm_mips.lua | 1181 ++++
LuaJIT-2.1/dynasm/dasm_mips64.lua | 12 +
LuaJIT-2.1/dynasm/dasm_ppc.h | 418 ++
LuaJIT-2.1/dynasm/dasm_ppc.lua | 1919 ++++++
LuaJIT-2.1/dynasm/dasm_proto.h | 83 +
LuaJIT-2.1/dynasm/dasm_x64.lua | 12 +
LuaJIT-2.1/dynasm/dasm_x86.h | 523 ++
LuaJIT-2.1/dynasm/dasm_x86.lua | 2394 ++++++++
LuaJIT-2.1/dynasm/dynasm.lua | 1095 ++++
LuaJIT-2.1/etc/luajit.1 | 88 +
LuaJIT-2.1/etc/luajit.pc | 25 +
LuaJIT-2.1/luajit | Bin 0 -> 587644 bytes
LuaJIT-2.1/src/.gitignore | 9 +
LuaJIT-2.1/src/Makefile | 751 +++
LuaJIT-2.1/src/Makefile.dep | 261 +
LuaJIT-2.1/src/gmod.cpp | 218 +
LuaJIT-2.1/src/gmod.h | 14 +
LuaJIT-2.1/src/host/.gitignore | 3 +
LuaJIT-2.1/src/host/README | 4 +
LuaJIT-2.1/src/host/buildvm.c | 529 ++
LuaJIT-2.1/src/host/buildvm.h | 105 +
LuaJIT-2.1/src/host/buildvm_asm.c | 355 ++
LuaJIT-2.1/src/host/buildvm_fold.c | 236 +
LuaJIT-2.1/src/host/buildvm_lib.c | 466 ++
LuaJIT-2.1/src/host/buildvm_libbc.h | 81 +
LuaJIT-2.1/src/host/buildvm_peobj.c | 473 ++
LuaJIT-2.1/src/host/genlibbc.lua | 234 +
LuaJIT-2.1/src/host/genminilua.lua | 436 ++
LuaJIT-2.1/src/host/genversion.lua | 45 +
LuaJIT-2.1/src/host/minilua.c | 7795 +++++++++++++++++++++++++
LuaJIT-2.1/src/jit/.gitignore | 1 +
LuaJIT-2.1/src/jit/bc.lua | 189 +
LuaJIT-2.1/src/jit/bcsave.lua | 629 ++
LuaJIT-2.1/src/jit/dis_arm.lua | 689 +++
LuaJIT-2.1/src/jit/dis_arm64.lua | 1227 ++++
LuaJIT-2.1/src/jit/dis_arm64be.lua | 12 +
LuaJIT-2.1/src/jit/dis_mips.lua | 694 +++
LuaJIT-2.1/src/jit/dis_mips64.lua | 17 +
LuaJIT-2.1/src/jit/dis_mips64el.lua | 17 +
LuaJIT-2.1/src/jit/dis_mips64r6.lua | 17 +
LuaJIT-2.1/src/jit/dis_mips64r6el.lua | 17 +
LuaJIT-2.1/src/jit/dis_mipsel.lua | 17 +
LuaJIT-2.1/src/jit/dis_ppc.lua | 591 ++
LuaJIT-2.1/src/jit/dis_x64.lua | 17 +
LuaJIT-2.1/src/jit/dis_x86.lua | 953 +++
LuaJIT-2.1/src/jit/dump.lua | 730 +++
LuaJIT-2.1/src/jit/p.lua | 309 +
LuaJIT-2.1/src/jit/v.lua | 174 +
LuaJIT-2.1/src/jit/zone.lua | 45 +
LuaJIT-2.1/src/lauxlib.h | 162 +
LuaJIT-2.1/src/lib_aux.c | 401 ++
LuaJIT-2.1/src/lib_base.c | 720 +++
LuaJIT-2.1/src/lib_bit.c | 181 +
LuaJIT-2.1/src/lib_buffer.c | 360 ++
LuaJIT-2.1/src/lib_debug.c | 406 ++
LuaJIT-2.1/src/lib_ffi.c | 857 +++
LuaJIT-2.1/src/lib_init.c | 55 +
LuaJIT-2.1/src/lib_io.c | 551 ++
LuaJIT-2.1/src/lib_jit.c | 746 +++
LuaJIT-2.1/src/lib_math.c | 205 +
LuaJIT-2.1/src/lib_os.c | 292 +
LuaJIT-2.1/src/lib_package.c | 628 ++
LuaJIT-2.1/src/lib_string.c | 690 +++
LuaJIT-2.1/src/lib_table.c | 328 ++
LuaJIT-2.1/src/lj_alloc.c | 1485 +++++
LuaJIT-2.1/src/lj_alloc.h | 18 +
LuaJIT-2.1/src/lj_api.c | 1361 +++++
LuaJIT-2.1/src/lj_arch.h | 742 +++
LuaJIT-2.1/src/lj_asm.c | 2631 +++++++++
LuaJIT-2.1/src/lj_asm.h | 17 +
LuaJIT-2.1/src/lj_asm_arm.h | 2308 ++++++++
LuaJIT-2.1/src/lj_asm_arm64.h | 2075 +++++++
LuaJIT-2.1/src/lj_asm_mips.h | 2815 +++++++++
LuaJIT-2.1/src/lj_asm_ppc.h | 2333 ++++++++
LuaJIT-2.1/src/lj_asm_x86.h | 3139 ++++++++++
LuaJIT-2.1/src/lj_assert.c | 28 +
LuaJIT-2.1/src/lj_bc.c | 14 +
LuaJIT-2.1/src/lj_bc.h | 265 +
LuaJIT-2.1/src/lj_bcdump.h | 70 +
LuaJIT-2.1/src/lj_bcread.c | 456 ++
LuaJIT-2.1/src/lj_bcwrite.c | 452 ++
LuaJIT-2.1/src/lj_buf.c | 303 +
LuaJIT-2.1/src/lj_buf.h | 198 +
LuaJIT-2.1/src/lj_carith.c | 434 ++
LuaJIT-2.1/src/lj_carith.h | 37 +
LuaJIT-2.1/src/lj_ccall.c | 1209 ++++
LuaJIT-2.1/src/lj_ccall.h | 201 +
LuaJIT-2.1/src/lj_ccallback.c | 796 +++
LuaJIT-2.1/src/lj_ccallback.h | 25 +
LuaJIT-2.1/src/lj_cconv.c | 770 +++
LuaJIT-2.1/src/lj_cconv.h | 71 +
LuaJIT-2.1/src/lj_cdata.c | 304 +
LuaJIT-2.1/src/lj_cdata.h | 79 +
LuaJIT-2.1/src/lj_char.c | 43 +
LuaJIT-2.1/src/lj_char.h | 42 +
LuaJIT-2.1/src/lj_clib.c | 434 ++
LuaJIT-2.1/src/lj_clib.h | 29 +
LuaJIT-2.1/src/lj_cparse.c | 1929 ++++++
LuaJIT-2.1/src/lj_cparse.h | 67 +
LuaJIT-2.1/src/lj_crecord.c | 1985 +++++++
LuaJIT-2.1/src/lj_crecord.h | 43 +
LuaJIT-2.1/src/lj_ctype.c | 670 +++
LuaJIT-2.1/src/lj_ctype.h | 483 ++
LuaJIT-2.1/src/lj_debug.c | 709 +++
LuaJIT-2.1/src/lj_debug.h | 66 +
LuaJIT-2.1/src/lj_def.h | 392 ++
LuaJIT-2.1/src/lj_dispatch.c | 559 ++
LuaJIT-2.1/src/lj_dispatch.h | 164 +
LuaJIT-2.1/src/lj_emit_arm.h | 361 ++
LuaJIT-2.1/src/lj_emit_arm64.h | 473 ++
LuaJIT-2.1/src/lj_emit_mips.h | 310 +
LuaJIT-2.1/src/lj_emit_ppc.h | 238 +
LuaJIT-2.1/src/lj_emit_x86.h | 572 ++
LuaJIT-2.1/src/lj_err.c | 1154 ++++
LuaJIT-2.1/src/lj_err.h | 59 +
LuaJIT-2.1/src/lj_errmsg.h | 202 +
LuaJIT-2.1/src/lj_ff.h | 18 +
LuaJIT-2.1/src/lj_ffrecord.c | 1603 +++++
LuaJIT-2.1/src/lj_ffrecord.h | 24 +
LuaJIT-2.1/src/lj_frame.h | 297 +
LuaJIT-2.1/src/lj_func.c | 191 +
LuaJIT-2.1/src/lj_func.h | 24 +
LuaJIT-2.1/src/lj_gc.c | 903 +++
LuaJIT-2.1/src/lj_gc.h | 136 +
LuaJIT-2.1/src/lj_gdbjit.c | 818 +++
LuaJIT-2.1/src/lj_gdbjit.h | 22 +
LuaJIT-2.1/src/lj_ir.c | 500 ++
LuaJIT-2.1/src/lj_ir.h | 615 ++
LuaJIT-2.1/src/lj_ircall.h | 383 ++
LuaJIT-2.1/src/lj_iropt.h | 168 +
LuaJIT-2.1/src/lj_jit.h | 533 ++
LuaJIT-2.1/src/lj_lex.c | 551 ++
LuaJIT-2.1/src/lj_lex.h | 94 +
LuaJIT-2.1/src/lj_lib.c | 377 ++
LuaJIT-2.1/src/lj_lib.h | 117 +
LuaJIT-2.1/src/lj_load.c | 184 +
LuaJIT-2.1/src/lj_mcode.c | 378 ++
LuaJIT-2.1/src/lj_mcode.h | 30 +
LuaJIT-2.1/src/lj_meta.c | 482 ++
LuaJIT-2.1/src/lj_meta.h | 38 +
LuaJIT-2.1/src/lj_obj.c | 51 +
LuaJIT-2.1/src/lj_obj.h | 1064 ++++
LuaJIT-2.1/src/lj_opt_dce.c | 75 +
LuaJIT-2.1/src/lj_opt_fold.c | 2647 +++++++++
LuaJIT-2.1/src/lj_opt_loop.c | 453 ++
LuaJIT-2.1/src/lj_opt_mem.c | 990 ++++
LuaJIT-2.1/src/lj_opt_narrow.c | 623 ++
LuaJIT-2.1/src/lj_opt_sink.c | 258 +
LuaJIT-2.1/src/lj_opt_split.c | 848 +++
LuaJIT-2.1/src/lj_parse.c | 2788 +++++++++
LuaJIT-2.1/src/lj_parse.h | 18 +
LuaJIT-2.1/src/lj_prng.c | 259 +
LuaJIT-2.1/src/lj_prng.h | 24 +
LuaJIT-2.1/src/lj_profile.c | 371 ++
LuaJIT-2.1/src/lj_profile.h | 21 +
LuaJIT-2.1/src/lj_record.c | 2907 +++++++++
LuaJIT-2.1/src/lj_record.h | 47 +
LuaJIT-2.1/src/lj_serialize.c | 539 ++
LuaJIT-2.1/src/lj_serialize.h | 28 +
LuaJIT-2.1/src/lj_snap.c | 1032 ++++
LuaJIT-2.1/src/lj_snap.h | 35 +
LuaJIT-2.1/src/lj_state.c | 385 ++
LuaJIT-2.1/src/lj_state.h | 38 +
LuaJIT-2.1/src/lj_str.c | 370 ++
LuaJIT-2.1/src/lj_str.h | 31 +
LuaJIT-2.1/src/lj_strfmt.c | 606 ++
LuaJIT-2.1/src/lj_strfmt.h | 131 +
LuaJIT-2.1/src/lj_strfmt_num.c | 593 ++
LuaJIT-2.1/src/lj_strscan.c | 558 ++
LuaJIT-2.1/src/lj_strscan.h | 40 +
LuaJIT-2.1/src/lj_tab.c | 686 +++
LuaJIT-2.1/src/lj_tab.h | 93 +
LuaJIT-2.1/src/lj_target.h | 164 +
LuaJIT-2.1/src/lj_target_arm.h | 271 +
LuaJIT-2.1/src/lj_target_arm64.h | 346 ++
LuaJIT-2.1/src/lj_target_mips.h | 417 ++
LuaJIT-2.1/src/lj_target_ppc.h | 280 +
LuaJIT-2.1/src/lj_target_x86.h | 357 ++
LuaJIT-2.1/src/lj_trace.c | 999 ++++
LuaJIT-2.1/src/lj_trace.h | 58 +
LuaJIT-2.1/src/lj_traceerr.h | 61 +
LuaJIT-2.1/src/lj_udata.c | 62 +
LuaJIT-2.1/src/lj_udata.h | 17 +
LuaJIT-2.1/src/lj_vm.h | 116 +
LuaJIT-2.1/src/lj_vmevent.c | 58 +
LuaJIT-2.1/src/lj_vmevent.h | 60 +
LuaJIT-2.1/src/lj_vmmath.c | 118 +
LuaJIT-2.1/src/ljamalg.c | 91 +
LuaJIT-2.1/src/lua.h | 402 ++
LuaJIT-2.1/src/lua.hpp | 9 +
LuaJIT-2.1/src/luaconf.h | 154 +
LuaJIT-2.1/src/luajit.c | 586 ++
LuaJIT-2.1/src/luajit_rolling.h | 80 +
LuaJIT-2.1/src/lualib.h | 44 +
LuaJIT-2.1/src/msvcbuild.bat | 162 +
LuaJIT-2.1/src/msvcbuild_86.bat | 141 +
LuaJIT-2.1/src/nxbuild.bat | 165 +
LuaJIT-2.1/src/ps4build.bat | 127 +
LuaJIT-2.1/src/ps5build.bat | 126 +
LuaJIT-2.1/src/psvitabuild.bat | 96 +
LuaJIT-2.1/src/vm_arm.dasc | 4694 +++++++++++++++
LuaJIT-2.1/src/vm_arm64.dasc | 4222 +++++++++++++
LuaJIT-2.1/src/vm_mips.dasc | 5418 +++++++++++++++++
LuaJIT-2.1/src/vm_mips64.dasc | 5566 ++++++++++++++++++
LuaJIT-2.1/src/vm_ppc.dasc | 6067 +++++++++++++++++++
LuaJIT-2.1/src/vm_x64.dasc | 4951 ++++++++++++++++
LuaJIT-2.1/src/vm_x86.dasc | 5851 +++++++++++++++++++
LuaJIT-2.1/src/xb1build.bat | 104 +
LuaJIT-2.1/src/xedkbuild.bat | 95 +
236 files changed, 148379 insertions(+)
create mode 100644 LuaJIT-2.1/.gitattributes
create mode 100644 LuaJIT-2.1/.gitignore
create mode 100644 LuaJIT-2.1/.relver
create mode 100644 LuaJIT-2.1/COPYRIGHT
create mode 100644 LuaJIT-2.1/Makefile
create mode 100644 LuaJIT-2.1/README
create mode 100644 LuaJIT-2.1/doc/bluequad-print.css
create mode 100644 LuaJIT-2.1/doc/bluequad.css
create mode 100644 LuaJIT-2.1/doc/contact.html
create mode 100644 LuaJIT-2.1/doc/ext_buffer.html
create mode 100644 LuaJIT-2.1/doc/ext_c_api.html
create mode 100644 LuaJIT-2.1/doc/ext_ffi.html
create mode 100644 LuaJIT-2.1/doc/ext_ffi_api.html
create mode 100644 LuaJIT-2.1/doc/ext_ffi_semantics.html
create mode 100644 LuaJIT-2.1/doc/ext_ffi_tutorial.html
create mode 100644 LuaJIT-2.1/doc/ext_jit.html
create mode 100644 LuaJIT-2.1/doc/ext_profiler.html
create mode 100644 LuaJIT-2.1/doc/extensions.html
create mode 100644 LuaJIT-2.1/doc/img/contact.png
create mode 100644 LuaJIT-2.1/doc/install.html
create mode 100644 LuaJIT-2.1/doc/luajit.html
create mode 100644 LuaJIT-2.1/doc/running.html
create mode 100644 LuaJIT-2.1/dynasm/dasm_arm.h
create mode 100644 LuaJIT-2.1/dynasm/dasm_arm.lua
create mode 100644 LuaJIT-2.1/dynasm/dasm_arm64.h
create mode 100644 LuaJIT-2.1/dynasm/dasm_arm64.lua
create mode 100644 LuaJIT-2.1/dynasm/dasm_mips.h
create mode 100644 LuaJIT-2.1/dynasm/dasm_mips.lua
create mode 100644 LuaJIT-2.1/dynasm/dasm_mips64.lua
create mode 100644 LuaJIT-2.1/dynasm/dasm_ppc.h
create mode 100644 LuaJIT-2.1/dynasm/dasm_ppc.lua
create mode 100644 LuaJIT-2.1/dynasm/dasm_proto.h
create mode 100644 LuaJIT-2.1/dynasm/dasm_x64.lua
create mode 100644 LuaJIT-2.1/dynasm/dasm_x86.h
create mode 100644 LuaJIT-2.1/dynasm/dasm_x86.lua
create mode 100644 LuaJIT-2.1/dynasm/dynasm.lua
create mode 100644 LuaJIT-2.1/etc/luajit.1
create mode 100644 LuaJIT-2.1/etc/luajit.pc
create mode 100644 LuaJIT-2.1/luajit
create mode 100644 LuaJIT-2.1/src/.gitignore
create mode 100644 LuaJIT-2.1/src/Makefile
create mode 100644 LuaJIT-2.1/src/Makefile.dep
create mode 100644 LuaJIT-2.1/src/gmod.cpp
create mode 100644 LuaJIT-2.1/src/gmod.h
create mode 100644 LuaJIT-2.1/src/host/.gitignore
create mode 100644 LuaJIT-2.1/src/host/README
create mode 100644 LuaJIT-2.1/src/host/buildvm.c
create mode 100644 LuaJIT-2.1/src/host/buildvm.h
create mode 100644 LuaJIT-2.1/src/host/buildvm_asm.c
create mode 100644 LuaJIT-2.1/src/host/buildvm_fold.c
create mode 100644 LuaJIT-2.1/src/host/buildvm_lib.c
create mode 100644 LuaJIT-2.1/src/host/buildvm_libbc.h
create mode 100644 LuaJIT-2.1/src/host/buildvm_peobj.c
create mode 100644 LuaJIT-2.1/src/host/genlibbc.lua
create mode 100644 LuaJIT-2.1/src/host/genminilua.lua
create mode 100644 LuaJIT-2.1/src/host/genversion.lua
create mode 100644 LuaJIT-2.1/src/host/minilua.c
create mode 100644 LuaJIT-2.1/src/jit/.gitignore
create mode 100644 LuaJIT-2.1/src/jit/bc.lua
create mode 100644 LuaJIT-2.1/src/jit/bcsave.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_arm.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_arm64.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_arm64be.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_mips.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_mips64.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_mips64el.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_mips64r6.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_mips64r6el.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_mipsel.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_ppc.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_x64.lua
create mode 100644 LuaJIT-2.1/src/jit/dis_x86.lua
create mode 100644 LuaJIT-2.1/src/jit/dump.lua
create mode 100644 LuaJIT-2.1/src/jit/p.lua
create mode 100644 LuaJIT-2.1/src/jit/v.lua
create mode 100644 LuaJIT-2.1/src/jit/zone.lua
create mode 100644 LuaJIT-2.1/src/lauxlib.h
create mode 100644 LuaJIT-2.1/src/lib_aux.c
create mode 100644 LuaJIT-2.1/src/lib_base.c
create mode 100644 LuaJIT-2.1/src/lib_bit.c
create mode 100644 LuaJIT-2.1/src/lib_buffer.c
create mode 100644 LuaJIT-2.1/src/lib_debug.c
create mode 100644 LuaJIT-2.1/src/lib_ffi.c
create mode 100644 LuaJIT-2.1/src/lib_init.c
create mode 100644 LuaJIT-2.1/src/lib_io.c
create mode 100644 LuaJIT-2.1/src/lib_jit.c
create mode 100644 LuaJIT-2.1/src/lib_math.c
create mode 100644 LuaJIT-2.1/src/lib_os.c
create mode 100644 LuaJIT-2.1/src/lib_package.c
create mode 100644 LuaJIT-2.1/src/lib_string.c
create mode 100644 LuaJIT-2.1/src/lib_table.c
create mode 100644 LuaJIT-2.1/src/lj_alloc.c
create mode 100644 LuaJIT-2.1/src/lj_alloc.h
create mode 100644 LuaJIT-2.1/src/lj_api.c
create mode 100644 LuaJIT-2.1/src/lj_arch.h
create mode 100644 LuaJIT-2.1/src/lj_asm.c
create mode 100644 LuaJIT-2.1/src/lj_asm.h
create mode 100644 LuaJIT-2.1/src/lj_asm_arm.h
create mode 100644 LuaJIT-2.1/src/lj_asm_arm64.h
create mode 100644 LuaJIT-2.1/src/lj_asm_mips.h
create mode 100644 LuaJIT-2.1/src/lj_asm_ppc.h
create mode 100644 LuaJIT-2.1/src/lj_asm_x86.h
create mode 100644 LuaJIT-2.1/src/lj_assert.c
create mode 100644 LuaJIT-2.1/src/lj_bc.c
create mode 100644 LuaJIT-2.1/src/lj_bc.h
create mode 100644 LuaJIT-2.1/src/lj_bcdump.h
create mode 100644 LuaJIT-2.1/src/lj_bcread.c
create mode 100644 LuaJIT-2.1/src/lj_bcwrite.c
create mode 100644 LuaJIT-2.1/src/lj_buf.c
create mode 100644 LuaJIT-2.1/src/lj_buf.h
create mode 100644 LuaJIT-2.1/src/lj_carith.c
create mode 100644 LuaJIT-2.1/src/lj_carith.h
create mode 100644 LuaJIT-2.1/src/lj_ccall.c
create mode 100644 LuaJIT-2.1/src/lj_ccall.h
create mode 100644 LuaJIT-2.1/src/lj_ccallback.c
create mode 100644 LuaJIT-2.1/src/lj_ccallback.h
create mode 100644 LuaJIT-2.1/src/lj_cconv.c
create mode 100644 LuaJIT-2.1/src/lj_cconv.h
create mode 100644 LuaJIT-2.1/src/lj_cdata.c
create mode 100644 LuaJIT-2.1/src/lj_cdata.h
create mode 100644 LuaJIT-2.1/src/lj_char.c
create mode 100644 LuaJIT-2.1/src/lj_char.h
create mode 100644 LuaJIT-2.1/src/lj_clib.c
create mode 100644 LuaJIT-2.1/src/lj_clib.h
create mode 100644 LuaJIT-2.1/src/lj_cparse.c
create mode 100644 LuaJIT-2.1/src/lj_cparse.h
create mode 100644 LuaJIT-2.1/src/lj_crecord.c
create mode 100644 LuaJIT-2.1/src/lj_crecord.h
create mode 100644 LuaJIT-2.1/src/lj_ctype.c
create mode 100644 LuaJIT-2.1/src/lj_ctype.h
create mode 100644 LuaJIT-2.1/src/lj_debug.c
create mode 100644 LuaJIT-2.1/src/lj_debug.h
create mode 100644 LuaJIT-2.1/src/lj_def.h
create mode 100644 LuaJIT-2.1/src/lj_dispatch.c
create mode 100644 LuaJIT-2.1/src/lj_dispatch.h
create mode 100644 LuaJIT-2.1/src/lj_emit_arm.h
create mode 100644 LuaJIT-2.1/src/lj_emit_arm64.h
create mode 100644 LuaJIT-2.1/src/lj_emit_mips.h
create mode 100644 LuaJIT-2.1/src/lj_emit_ppc.h
create mode 100644 LuaJIT-2.1/src/lj_emit_x86.h
create mode 100644 LuaJIT-2.1/src/lj_err.c
create mode 100644 LuaJIT-2.1/src/lj_err.h
create mode 100644 LuaJIT-2.1/src/lj_errmsg.h
create mode 100644 LuaJIT-2.1/src/lj_ff.h
create mode 100644 LuaJIT-2.1/src/lj_ffrecord.c
create mode 100644 LuaJIT-2.1/src/lj_ffrecord.h
create mode 100644 LuaJIT-2.1/src/lj_frame.h
create mode 100644 LuaJIT-2.1/src/lj_func.c
create mode 100644 LuaJIT-2.1/src/lj_func.h
create mode 100644 LuaJIT-2.1/src/lj_gc.c
create mode 100644 LuaJIT-2.1/src/lj_gc.h
create mode 100644 LuaJIT-2.1/src/lj_gdbjit.c
create mode 100644 LuaJIT-2.1/src/lj_gdbjit.h
create mode 100644 LuaJIT-2.1/src/lj_ir.c
create mode 100644 LuaJIT-2.1/src/lj_ir.h
create mode 100644 LuaJIT-2.1/src/lj_ircall.h
create mode 100644 LuaJIT-2.1/src/lj_iropt.h
create mode 100644 LuaJIT-2.1/src/lj_jit.h
create mode 100644 LuaJIT-2.1/src/lj_lex.c
create mode 100644 LuaJIT-2.1/src/lj_lex.h
create mode 100644 LuaJIT-2.1/src/lj_lib.c
create mode 100644 LuaJIT-2.1/src/lj_lib.h
create mode 100644 LuaJIT-2.1/src/lj_load.c
create mode 100644 LuaJIT-2.1/src/lj_mcode.c
create mode 100644 LuaJIT-2.1/src/lj_mcode.h
create mode 100644 LuaJIT-2.1/src/lj_meta.c
create mode 100644 LuaJIT-2.1/src/lj_meta.h
create mode 100644 LuaJIT-2.1/src/lj_obj.c
create mode 100644 LuaJIT-2.1/src/lj_obj.h
create mode 100644 LuaJIT-2.1/src/lj_opt_dce.c
create mode 100644 LuaJIT-2.1/src/lj_opt_fold.c
create mode 100644 LuaJIT-2.1/src/lj_opt_loop.c
create mode 100644 LuaJIT-2.1/src/lj_opt_mem.c
create mode 100644 LuaJIT-2.1/src/lj_opt_narrow.c
create mode 100644 LuaJIT-2.1/src/lj_opt_sink.c
create mode 100644 LuaJIT-2.1/src/lj_opt_split.c
create mode 100644 LuaJIT-2.1/src/lj_parse.c
create mode 100644 LuaJIT-2.1/src/lj_parse.h
create mode 100644 LuaJIT-2.1/src/lj_prng.c
create mode 100644 LuaJIT-2.1/src/lj_prng.h
create mode 100644 LuaJIT-2.1/src/lj_profile.c
create mode 100644 LuaJIT-2.1/src/lj_profile.h
create mode 100644 LuaJIT-2.1/src/lj_record.c
create mode 100644 LuaJIT-2.1/src/lj_record.h
create mode 100644 LuaJIT-2.1/src/lj_serialize.c
create mode 100644 LuaJIT-2.1/src/lj_serialize.h
create mode 100644 LuaJIT-2.1/src/lj_snap.c
create mode 100644 LuaJIT-2.1/src/lj_snap.h
create mode 100644 LuaJIT-2.1/src/lj_state.c
create mode 100644 LuaJIT-2.1/src/lj_state.h
create mode 100644 LuaJIT-2.1/src/lj_str.c
create mode 100644 LuaJIT-2.1/src/lj_str.h
create mode 100644 LuaJIT-2.1/src/lj_strfmt.c
create mode 100644 LuaJIT-2.1/src/lj_strfmt.h
create mode 100644 LuaJIT-2.1/src/lj_strfmt_num.c
create mode 100644 LuaJIT-2.1/src/lj_strscan.c
create mode 100644 LuaJIT-2.1/src/lj_strscan.h
create mode 100644 LuaJIT-2.1/src/lj_tab.c
create mode 100644 LuaJIT-2.1/src/lj_tab.h
create mode 100644 LuaJIT-2.1/src/lj_target.h
create mode 100644 LuaJIT-2.1/src/lj_target_arm.h
create mode 100644 LuaJIT-2.1/src/lj_target_arm64.h
create mode 100644 LuaJIT-2.1/src/lj_target_mips.h
create mode 100644 LuaJIT-2.1/src/lj_target_ppc.h
create mode 100644 LuaJIT-2.1/src/lj_target_x86.h
create mode 100644 LuaJIT-2.1/src/lj_trace.c
create mode 100644 LuaJIT-2.1/src/lj_trace.h
create mode 100644 LuaJIT-2.1/src/lj_traceerr.h
create mode 100644 LuaJIT-2.1/src/lj_udata.c
create mode 100644 LuaJIT-2.1/src/lj_udata.h
create mode 100644 LuaJIT-2.1/src/lj_vm.h
create mode 100644 LuaJIT-2.1/src/lj_vmevent.c
create mode 100644 LuaJIT-2.1/src/lj_vmevent.h
create mode 100644 LuaJIT-2.1/src/lj_vmmath.c
create mode 100644 LuaJIT-2.1/src/ljamalg.c
create mode 100644 LuaJIT-2.1/src/lua.h
create mode 100644 LuaJIT-2.1/src/lua.hpp
create mode 100644 LuaJIT-2.1/src/luaconf.h
create mode 100644 LuaJIT-2.1/src/luajit.c
create mode 100644 LuaJIT-2.1/src/luajit_rolling.h
create mode 100644 LuaJIT-2.1/src/lualib.h
create mode 100644 LuaJIT-2.1/src/msvcbuild.bat
create mode 100644 LuaJIT-2.1/src/msvcbuild_86.bat
create mode 100644 LuaJIT-2.1/src/nxbuild.bat
create mode 100644 LuaJIT-2.1/src/ps4build.bat
create mode 100644 LuaJIT-2.1/src/ps5build.bat
create mode 100644 LuaJIT-2.1/src/psvitabuild.bat
create mode 100644 LuaJIT-2.1/src/vm_arm.dasc
create mode 100644 LuaJIT-2.1/src/vm_arm64.dasc
create mode 100644 LuaJIT-2.1/src/vm_mips.dasc
create mode 100644 LuaJIT-2.1/src/vm_mips64.dasc
create mode 100644 LuaJIT-2.1/src/vm_ppc.dasc
create mode 100644 LuaJIT-2.1/src/vm_x64.dasc
create mode 100644 LuaJIT-2.1/src/vm_x86.dasc
create mode 100644 LuaJIT-2.1/src/xb1build.bat
create mode 100644 LuaJIT-2.1/src/xedkbuild.bat
diff --git a/LuaJIT-2.1/.gitattributes b/LuaJIT-2.1/.gitattributes
new file mode 100644
index 00000000..c048531e
--- /dev/null
+++ b/LuaJIT-2.1/.gitattributes
@@ -0,0 +1 @@
+/.relver export-subst
diff --git a/LuaJIT-2.1/.gitignore b/LuaJIT-2.1/.gitignore
new file mode 100644
index 00000000..1a07bf75
--- /dev/null
+++ b/LuaJIT-2.1/.gitignore
@@ -0,0 +1,11 @@
+*.[oa]
+*.so
+*.obj
+*.lib
+*.exp
+*.dll
+*.exe
+*.manifest
+*.dmp
+*.swp
+.tags
diff --git a/LuaJIT-2.1/.relver b/LuaJIT-2.1/.relver
new file mode 100644
index 00000000..c0a29354
--- /dev/null
+++ b/LuaJIT-2.1/.relver
@@ -0,0 +1 @@
+1736781742
diff --git a/LuaJIT-2.1/COPYRIGHT b/LuaJIT-2.1/COPYRIGHT
new file mode 100644
index 00000000..a192ae49
--- /dev/null
+++ b/LuaJIT-2.1/COPYRIGHT
@@ -0,0 +1,56 @@
+===============================================================================
+LuaJIT -- a Just-In-Time Compiler for Lua. https://luajit.org/
+
+Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+[ MIT license: https://www.opensource.org/licenses/mit-license.php ]
+
+===============================================================================
+[ LuaJIT includes code from Lua 5.1/5.2, which has this license statement: ]
+
+Copyright (C) 1994-2012 Lua.org, PUC-Rio.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+===============================================================================
+[ LuaJIT includes code from dlmalloc, which has this license statement: ]
+
+This is a version (aka dlmalloc) of malloc/free/realloc written by
+Doug Lea and released to the public domain, as explained at
+https://creativecommons.org/licenses/publicdomain
+
+===============================================================================
diff --git a/LuaJIT-2.1/Makefile b/LuaJIT-2.1/Makefile
new file mode 100644
index 00000000..d789e9f3
--- /dev/null
+++ b/LuaJIT-2.1/Makefile
@@ -0,0 +1,175 @@
+##############################################################################
+# LuaJIT top level Makefile for installation. Requires GNU Make.
+#
+# Please read doc/install.html before changing any variables!
+#
+# Suitable for POSIX platforms (Linux, *BSD, OSX etc.).
+# Note: src/Makefile has many more configurable options.
+#
+# ##### This Makefile is NOT useful for Windows! #####
+# For MSVC, please follow the instructions given in src/msvcbuild.bat.
+# For MinGW and Cygwin, cd to src and run make with the Makefile there.
+#
+# Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h
+##############################################################################
+
+MAJVER= 2
+MINVER= 1
+ABIVER= 5.1
+
+# LuaJIT uses rolling releases. The release version is based on the time of
+# the latest git commit. The 'git' command must be available during the build.
+RELVER= $(shell cat src/luajit_relver.txt 2>/dev/null || : )
+# Note: setting it with := doesn't work, since it will change during the build.
+
+MMVERSION= $(MAJVER).$(MINVER)
+VERSION= $(MMVERSION).$(RELVER)
+
+##############################################################################
+#
+# Change the installation path as needed. This automatically adjusts
+# the paths in src/luaconf.h, too. Note: PREFIX must be an absolute path!
+#
+export PREFIX= /usr/local
+export MULTILIB= lib
+##############################################################################
+
+DPREFIX= $(DESTDIR)$(PREFIX)
+INSTALL_BIN= $(DPREFIX)/bin
+INSTALL_LIB= $(DPREFIX)/$(MULTILIB)
+INSTALL_SHARE_= $(PREFIX)/share
+INSTALL_SHARE= $(DESTDIR)$(INSTALL_SHARE_)
+INSTALL_DEFINC= $(DPREFIX)/include/luajit-$(MMVERSION)
+INSTALL_INC= $(INSTALL_DEFINC)
+
+export INSTALL_LJLIBD= $(INSTALL_SHARE_)/luajit-$(MMVERSION)
+INSTALL_JITLIB= $(DESTDIR)$(INSTALL_LJLIBD)/jit
+INSTALL_LMODD= $(INSTALL_SHARE)/lua
+INSTALL_LMOD= $(INSTALL_LMODD)/$(ABIVER)
+INSTALL_CMODD= $(INSTALL_LIB)/lua
+INSTALL_CMOD= $(INSTALL_CMODD)/$(ABIVER)
+INSTALL_MAN= $(INSTALL_SHARE)/man/man1
+INSTALL_PKGCONFIG= $(INSTALL_LIB)/pkgconfig
+
+INSTALL_TNAME= luajit-$(VERSION)
+INSTALL_TSYMNAME= luajit
+INSTALL_ANAME= libluajit-$(ABIVER).a
+INSTALL_SOSHORT1= libluajit-$(ABIVER).so
+INSTALL_SOSHORT2= libluajit-$(ABIVER).so.$(MAJVER)
+INSTALL_SONAME= libluajit-$(ABIVER).so.$(VERSION)
+INSTALL_DYLIBSHORT1= libluajit-$(ABIVER).dylib
+INSTALL_DYLIBSHORT2= libluajit-$(ABIVER).$(MAJVER).dylib
+INSTALL_DYLIBNAME= libluajit-$(ABIVER).$(VERSION).dylib
+INSTALL_PCNAME= luajit.pc
+
+INSTALL_STATIC= $(INSTALL_LIB)/$(INSTALL_ANAME)
+INSTALL_DYN= $(INSTALL_LIB)/$(INSTALL_SONAME)
+INSTALL_SHORT1= $(INSTALL_LIB)/$(INSTALL_SOSHORT1)
+INSTALL_SHORT2= $(INSTALL_LIB)/$(INSTALL_SOSHORT2)
+INSTALL_T= $(INSTALL_BIN)/$(INSTALL_TNAME)
+INSTALL_TSYM= $(INSTALL_BIN)/$(INSTALL_TSYMNAME)
+INSTALL_PC= $(INSTALL_PKGCONFIG)/$(INSTALL_PCNAME)
+
+INSTALL_DIRS= $(INSTALL_BIN) $(INSTALL_LIB) $(INSTALL_INC) $(INSTALL_MAN) \
+ $(INSTALL_PKGCONFIG) $(INSTALL_JITLIB) $(INSTALL_LMOD) $(INSTALL_CMOD)
+UNINSTALL_DIRS= $(INSTALL_JITLIB) $(DESTDIR)$(INSTALL_LJLIBD) $(INSTALL_INC) \
+ $(INSTALL_LMOD) $(INSTALL_LMODD) $(INSTALL_CMOD) $(INSTALL_CMODD)
+
+RM= rm -f
+MKDIR= mkdir -p
+RMDIR= rmdir 2>/dev/null
+SYMLINK= ln -sf
+INSTALL_X= install -m 0755
+INSTALL_F= install -m 0644
+UNINSTALL= $(RM)
+LDCONFIG= ldconfig -n 2>/dev/null
+SED_PC= sed -e "s|^prefix=.*|prefix=$(PREFIX)|" \
+ -e "s|^multilib=.*|multilib=$(MULTILIB)|" \
+ -e "s|^relver=.*|relver=$(RELVER)|"
+ifneq ($(INSTALL_DEFINC),$(INSTALL_INC))
+ SED_PC+= -e "s|^includedir=.*|includedir=$(INSTALL_INC)|"
+endif
+
+FILE_T= luajit
+FILE_A= libluajit.a
+FILE_SO= libluajit.so
+FILE_MAN= luajit.1
+FILE_PC= luajit.pc
+FILES_INC= lua.h lualib.h lauxlib.h luaconf.h lua.hpp luajit.h
+FILES_JITLIB= bc.lua bcsave.lua dump.lua p.lua v.lua zone.lua \
+ dis_x86.lua dis_x64.lua dis_arm.lua dis_arm64.lua \
+ dis_arm64be.lua dis_ppc.lua dis_mips.lua dis_mipsel.lua \
+ dis_mips64.lua dis_mips64el.lua \
+ dis_mips64r6.lua dis_mips64r6el.lua \
+ vmdef.lua
+
+ifeq (,$(findstring Windows,$(OS)))
+ HOST_SYS:= $(shell uname -s)
+else
+ HOST_SYS= Windows
+endif
+TARGET_SYS?= $(HOST_SYS)
+
+ifeq (Darwin,$(TARGET_SYS))
+ INSTALL_SONAME= $(INSTALL_DYLIBNAME)
+ INSTALL_SOSHORT1= $(INSTALL_DYLIBSHORT1)
+ INSTALL_SOSHORT2= $(INSTALL_DYLIBSHORT2)
+ LDCONFIG= :
+ SED_PC+= -e "s| -Wl,-E||"
+endif
+
+##############################################################################
+
+INSTALL_DEP= src/luajit
+
+default all $(INSTALL_DEP):
+ @echo "==== Building LuaJIT $(MMVERSION) ===="
+ $(MAKE) -C src
+ @echo "==== Successfully built LuaJIT $(MMVERSION) ===="
+
+install: $(INSTALL_DEP)
+ @echo "==== Installing LuaJIT $(VERSION) to $(PREFIX) ===="
+ $(MKDIR) $(INSTALL_DIRS)
+ cd src && $(INSTALL_X) $(FILE_T) $(INSTALL_T)
+ cd src && test -f $(FILE_A) && $(INSTALL_F) $(FILE_A) $(INSTALL_STATIC) || :
+ $(RM) $(INSTALL_DYN) $(INSTALL_SHORT1) $(INSTALL_SHORT2)
+ cd src && test -f $(FILE_SO) && \
+ $(INSTALL_X) $(FILE_SO) $(INSTALL_DYN) && \
+ ( $(LDCONFIG) $(INSTALL_LIB) || : ) && \
+ $(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT1) && \
+ $(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT2) || :
+ cd etc && $(INSTALL_F) $(FILE_MAN) $(INSTALL_MAN)
+ cd etc && $(SED_PC) $(FILE_PC) > $(FILE_PC).tmp && \
+ $(INSTALL_F) $(FILE_PC).tmp $(INSTALL_PC) && \
+ $(RM) $(FILE_PC).tmp
+ cd src && $(INSTALL_F) $(FILES_INC) $(INSTALL_INC)
+ cd src/jit && $(INSTALL_F) $(FILES_JITLIB) $(INSTALL_JITLIB)
+ $(SYMLINK) $(INSTALL_TNAME) $(INSTALL_TSYM)
+ @echo "==== Successfully installed LuaJIT $(VERSION) to $(PREFIX) ===="
+
+uninstall:
+ @echo "==== Uninstalling LuaJIT $(VERSION) from $(PREFIX) ===="
+ $(UNINSTALL) $(INSTALL_TSYM) $(INSTALL_T) $(INSTALL_STATIC) $(INSTALL_DYN) $(INSTALL_SHORT1) $(INSTALL_SHORT2) $(INSTALL_MAN)/$(FILE_MAN) $(INSTALL_PC)
+ for file in $(FILES_JITLIB); do \
+ $(UNINSTALL) $(INSTALL_JITLIB)/$$file; \
+ done
+ for file in $(FILES_INC); do \
+ $(UNINSTALL) $(INSTALL_INC)/$$file; \
+ done
+ $(LDCONFIG) $(INSTALL_LIB)
+ $(RMDIR) $(UNINSTALL_DIRS) || :
+ @echo "==== Successfully uninstalled LuaJIT $(VERSION) from $(PREFIX) ===="
+
+##############################################################################
+
+amalg:
+ @echo "==== Building LuaJIT $(MMVERSION) (amalgamation) ===="
+ $(MAKE) -C src amalg
+ @echo "==== Successfully built LuaJIT $(MMVERSION) (amalgamation) ===="
+
+clean:
+ $(MAKE) -C src clean
+
+.PHONY: all install amalg clean
+
+##############################################################################
diff --git a/LuaJIT-2.1/README b/LuaJIT-2.1/README
new file mode 100644
index 00000000..201f1b72
--- /dev/null
+++ b/LuaJIT-2.1/README
@@ -0,0 +1,16 @@
+README for LuaJIT 2.1
+---------------------
+
+LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.
+
+Project Homepage: https://luajit.org/
+
+LuaJIT is Copyright (C) 2005-2025 Mike Pall.
+LuaJIT is free software, released under the MIT license.
+See full Copyright Notice in the COPYRIGHT file or in luajit.h.
+
+Documentation for LuaJIT is available in HTML format.
+Please point your favorite browser to:
+
+ doc/luajit.html
+
diff --git a/LuaJIT-2.1/doc/bluequad-print.css b/LuaJIT-2.1/doc/bluequad-print.css
new file mode 100644
index 00000000..5bfda5d3
--- /dev/null
+++ b/LuaJIT-2.1/doc/bluequad-print.css
@@ -0,0 +1,166 @@
+/* Copyright (C) 2004-2025 Mike Pall.
+ *
+ * You are welcome to use the general ideas of this design for your own sites.
+ * But please do not steal the stylesheet, the layout or the color scheme.
+ */
+body {
+ font-family: serif;
+ font-size: 11pt;
+ margin: 0 3em;
+ padding: 0;
+ border: none;
+}
+a:link, a:visited, a:hover, a:active {
+ text-decoration: none;
+ background: transparent;
+ color: #0000ff;
+}
+h1, h2, h3 {
+ font-family: sans-serif;
+ font-weight: bold;
+ text-align: left;
+ margin: 0.5em 0;
+ padding: 0;
+}
+h1 {
+ font-size: 200%;
+}
+h2 {
+ font-size: 150%;
+}
+h3 {
+ font-size: 125%;
+}
+p {
+ margin: 0 0 0.5em 0;
+ padding: 0;
+}
+ul, ol {
+ margin: 0.5em 0;
+ padding: 0 0 0 2em;
+}
+ul {
+ list-style: outside square;
+}
+ol {
+ list-style: outside decimal;
+}
+li {
+ margin: 0;
+ padding: 0;
+}
+dl {
+ margin: 1em 0;
+ padding: 1em;
+ border: 1px solid black;
+}
+dt {
+ font-weight: bold;
+ margin: 0;
+ padding: 0;
+}
+dt sup {
+ float: right;
+ margin-left: 1em;
+}
+dd {
+ margin: 0.5em 0 0 2em;
+ padding: 0;
+}
+table {
+ table-layout: fixed;
+ width: 100%;
+ margin: 1em 0;
+ padding: 0;
+ border: 1px solid black;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+tr {
+ margin: 0;
+ padding: 0;
+ border: none;
+}
+td {
+ text-align: left;
+ margin: 0;
+ padding: 0.2em 0.5em;
+ border-top: 1px solid black;
+ border-bottom: 1px solid black;
+}
+tr.separate td {
+ border-top: double;
+}
+tt, pre, code, kbd, samp {
+ font-family: monospace;
+ font-size: 75%;
+}
+kbd {
+ font-weight: bolder;
+}
+blockquote, pre {
+ margin: 1em 2em;
+ padding: 0;
+}
+img {
+ border: none;
+ vertical-align: baseline;
+ margin: 0;
+ padding: 0;
+}
+img.left {
+ float: left;
+ margin: 0.5em 1em 0.5em 0;
+}
+img.right {
+ float: right;
+ margin: 0.5em 0 0.5em 1em;
+}
+.flush {
+ clear: both;
+ visibility: hidden;
+}
+.hide, .noprint, #nav {
+ display: none !important;
+}
+.pagebreak {
+ page-break-before: always;
+}
+#site {
+ text-align: right;
+ font-family: sans-serif;
+ font-weight: bold;
+ margin: 0 1em;
+ border-bottom: 1pt solid black;
+}
+#site a {
+ font-size: 1.2em;
+}
+#site a:link, #site a:visited {
+ text-decoration: none;
+ font-weight: bold;
+ background: transparent;
+ color: #ffffff;
+}
+#logo {
+ color: #ff8000;
+}
+#head {
+ clear: both;
+ margin: 0 1em;
+}
+#main {
+ line-height: 1.3;
+ text-align: justify;
+ margin: 1em;
+}
+#foot {
+ clear: both;
+ font-size: 80%;
+ text-align: center;
+ margin: 0 1.25em;
+ padding: 0.5em 0 0 0;
+ border-top: 1pt solid black;
+ page-break-before: avoid;
+ page-break-after: avoid;
+}
diff --git a/LuaJIT-2.1/doc/bluequad.css b/LuaJIT-2.1/doc/bluequad.css
new file mode 100644
index 00000000..5334a759
--- /dev/null
+++ b/LuaJIT-2.1/doc/bluequad.css
@@ -0,0 +1,323 @@
+/* Copyright (C) 2004-2025 Mike Pall.
+ *
+ * You are welcome to use the general ideas of this design for your own sites.
+ * But please do not steal the stylesheet, the layout or the color scheme.
+ */
+/* colorscheme:
+ *
+ * site | head #4162bf/white | #6078bf/#e6ecff
+ * ------+------ ----------------+-------------------
+ * nav | main #bfcfff | #e6ecff/black
+ *
+ * nav: hiback loback #c5d5ff #b9c9f9
+ * hiborder loborder #e6ecff #97a7d7
+ * link hover #2142bf #ff0000
+ *
+ * link: link visited hover #2142bf #8122bf #ff0000
+ *
+ * main: boxback boxborder #f0f4ff #bfcfff
+ */
+body {
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-size: 10pt;
+ margin: 0;
+ padding: 0;
+ border: none;
+ background: #e0e0e0;
+ color: #000000;
+}
+a:link {
+ text-decoration: none;
+ background: transparent;
+ color: #2142bf;
+}
+a:visited {
+ text-decoration: none;
+ background: transparent;
+ color: #8122bf;
+}
+a:hover, a:active {
+ text-decoration: underline;
+ background: transparent;
+ color: #ff0000;
+}
+h1, h2, h3 {
+ font-weight: bold;
+ text-align: left;
+ margin: 0.5em 0;
+ padding: 0;
+ background: transparent;
+}
+h1 {
+ font-size: 200%;
+ line-height: 3em; /* really 6em relative to body, match #site span */
+ margin: 0;
+}
+h2 {
+ font-size: 150%;
+ color: #606060;
+}
+h3 {
+ font-size: 125%;
+ color: #404040;
+}
+p {
+ max-width: 600px;
+ margin: 0 0 0.5em 0;
+ padding: 0;
+}
+b {
+ color: #404040;
+}
+ul, ol {
+ max-width: 600px;
+ margin: 0.5em 0;
+ padding: 0 0 0 2em;
+}
+ul {
+ list-style: outside square;
+}
+ol {
+ list-style: outside decimal;
+}
+li {
+ margin: 0;
+ padding: 0;
+}
+dl {
+ max-width: 600px;
+ margin: 1em 0;
+ padding: 1em;
+ border: 1px solid #bfcfff;
+ background: #f0f4ff;
+}
+dt {
+ font-weight: bold;
+ margin: 0;
+ padding: 0;
+}
+dt sup {
+ float: right;
+ margin-left: 1em;
+ color: #808080;
+}
+dt a:visited {
+ text-decoration: none;
+ color: #2142bf;
+}
+dt a:hover, dt a:active {
+ text-decoration: none;
+ color: #ff0000;
+}
+dd {
+ margin: 0.5em 0 0 2em;
+ padding: 0;
+}
+div.tablewrap { /* for IE *sigh* */
+ max-width: 600px;
+}
+table {
+ table-layout: fixed;
+ border-spacing: 0;
+ border-collapse: collapse;
+ max-width: 600px;
+ width: 100%;
+ margin: 1em 0;
+ padding: 0;
+ border: 1px solid #bfcfff;
+}
+tr {
+ margin: 0;
+ padding: 0;
+ border: none;
+}
+tr.odd {
+ background: #f0f4ff;
+}
+tr.separate td {
+ border-top: 1px solid #bfcfff;
+}
+td {
+ text-align: left;
+ margin: 0;
+ padding: 0.2em 0.5em;
+ border: none;
+}
+tt, code, kbd, samp {
+ font-family: Courier New, Courier, monospace;
+ line-height: 1.2;
+ font-size: 110%;
+}
+kbd {
+ font-weight: bolder;
+}
+blockquote, pre {
+ max-width: 600px;
+ margin: 1em 2em;
+ padding: 0;
+}
+pre {
+ line-height: 1.1;
+}
+pre.code {
+ line-height: 1.4;
+ margin: 0.5em 0 1em 0.5em;
+ padding: 0.5em 1em;
+ border: 1px solid #bfcfff;
+ background: #f0f4ff;
+}
+pre.mark {
+ padding-left: 2em;
+}
+span.codemark {
+ position:absolute;
+ left: 16em;
+ color: #4040c0;
+}
+span.mark {
+ color: #4040c0;
+ font-family: Courier New, Courier, monospace;
+ line-height: 1.1;
+}
+img {
+ border: none;
+ vertical-align: baseline;
+ margin: 0;
+ padding: 0;
+}
+img.left {
+ float: left;
+ margin: 0.5em 1em 0.5em 0;
+}
+img.right {
+ float: right;
+ margin: 0.5em 0 0.5em 1em;
+}
+.indent {
+ padding-left: 1em;
+}
+.flush {
+ clear: both;
+ visibility: hidden;
+}
+.hide, .noscreen {
+ display: none !important;
+}
+.ext {
+ color: #ff8000;
+}
+.note {
+ padding: 0.5em 1em;
+ border-left: 3px solid #bfcfff;
+}
+#site {
+ clear: both;
+ float: left;
+ width: 13em;
+ text-align: center;
+ font-weight: bold;
+ margin: 0;
+ padding: 0;
+ background: transparent;
+ color: #ffffff;
+}
+#site a {
+ font-size: 200%;
+}
+#site a:link, #site a:visited {
+ text-decoration: none;
+ font-weight: bold;
+ background: transparent;
+ color: #ffffff;
+}
+#site span {
+ line-height: 3em; /* really 6em relative to body, match h1 */
+}
+#logo {
+ color: #ffb380;
+}
+#head {
+ margin: 0;
+ padding: 0 0 0 2em;
+ border-left: solid 13em #4162bf;
+ border-right: solid 3em #6078bf;
+ background: #6078bf;
+ color: #e6ecff;
+}
+#nav {
+ clear: both;
+ float: left;
+ overflow: hidden;
+ text-align: left;
+ line-height: 1.5;
+ width: 13em;
+ padding-top: 1em;
+ background: transparent;
+}
+#nav ul {
+ list-style: none outside;
+ margin: 0;
+ padding: 0;
+}
+#nav li {
+ margin: 0;
+ padding: 0;
+}
+#nav a {
+ display: block;
+ text-decoration: none;
+ font-weight: bold;
+ margin: 0;
+ padding: 2px 1em;
+ border-top: 1px solid transparent;
+ border-bottom: 1px solid transparent;
+ background: transparent;
+ color: #2142bf;
+}
+#nav a:hover, #nav a:active {
+ text-decoration: none;
+ border-top: 1px solid #97a7d7;
+ border-bottom: 1px solid #e6ecff;
+ background: #b9c9f9;
+ color: #ff0000;
+}
+#nav a.current, #nav a.current:hover, #nav a.current:active {
+ border-top: 1px solid #e6ecff;
+ border-bottom: 1px solid #97a7d7;
+ background: #c5d5ff;
+ color: #2142bf;
+}
+#nav ul ul a {
+ padding: 0 1em 0 1.7em;
+}
+#nav ul ul ul a {
+ padding: 0 0.5em 0 2.4em;
+}
+#main {
+ line-height: 1.5;
+ text-align: left;
+ margin: 0;
+ padding: 1em 2em;
+ border-left: solid 13em #bfcfff;
+ border-right: solid 3em #e6ecff;
+ background: #e6ecff;
+}
+#foot {
+ clear: both;
+ font-size: 80%;
+ text-align: center;
+ margin: 0;
+ padding: 0.5em;
+ background: #6078bf;
+ color: #ffffff;
+}
+#foot a:link, #foot a:visited {
+ text-decoration: underline;
+ background: transparent;
+ color: #ffffff;
+}
+#foot a:hover, #foot a:active {
+ text-decoration: underline;
+ background: transparent;
+ color: #bfcfff;
+}
diff --git a/LuaJIT-2.1/doc/contact.html b/LuaJIT-2.1/doc/contact.html
new file mode 100644
index 00000000..d8d34a69
--- /dev/null
+++ b/LuaJIT-2.1/doc/contact.html
@@ -0,0 +1,112 @@
+
+
+
+Contact
+
+
+
+
+
+
+
+
+
+
Contact
+
+
+
+
+If you want to report bugs, propose fixes or suggest enhancements,
+please use the
+» GitHub issue tracker .
+
+
+Please send general questions to the
+» LuaJIT mailing list .
+
+
+You can also send any questions you have directly to me:
+
+
+
+
+
+
+
+
+
+
+Note: I cannot reply to GMail, Google Workplace, Outlook or Office365
+mail addresses, since they prefer to mindlessly filter out mails sent
+from small domains using independent mail servers, such as mine. If you
+don't like that, please complain to Google or Microsoft, not me.
+
+
+
Copyright
+
+All documentation is
+Copyright © 2005-2025 Mike Pall.
+
+
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/ext_buffer.html b/LuaJIT-2.1/doc/ext_buffer.html
new file mode 100644
index 00000000..1ab392f0
--- /dev/null
+++ b/LuaJIT-2.1/doc/ext_buffer.html
@@ -0,0 +1,689 @@
+
+
+
+String Buffer Library
+
+
+
+
+
+
+
+
+
+
+
String Buffer Library
+
+
+
+
+The string buffer library allows high-performance manipulation of
+string-like data .
+
+
+Unlike Lua strings, which are constants, string buffers are
+mutable sequences of 8-bit (binary-transparent) characters. Data
+can be stored, formatted and encoded into a string buffer and later
+converted, extracted or decoded.
+
+
+The convenient string buffer API simplifies common string manipulation
+tasks, that would otherwise require creating many intermediate strings.
+String buffers improve performance by eliminating redundant memory
+copies, object creation, string interning and garbage collection
+overhead. In conjunction with the FFI library, they allow zero-copy
+operations.
+
+
+The string buffer library also includes a high-performance
+serializer for Lua objects.
+
+
+
Using the String Buffer Library
+
+The string buffer library is built into LuaJIT by default, but it's not
+loaded by default. Add this to the start of every Lua file that needs
+one of its functions:
+
+
+local buffer = require("string.buffer")
+
+
+The convention for the syntax shown on this page is that buffer
+refers to the buffer library and buf refers to an individual
+buffer object.
+
+
+Please note the difference between a Lua function call, e.g.
+buffer.new() (with a dot) and a Lua method call, e.g.
+buf:reset() (with a colon).
+
+
+
Buffer Objects
+
+A buffer object is a garbage-collected Lua object. After creation with
+buffer.new() , it can (and should) be reused for many operations.
+When the last reference to a buffer object is gone, it will eventually
+be freed by the garbage collector, along with the allocated buffer
+space.
+
+
+Buffers operate like a FIFO (first-in first-out) data structure. Data
+can be appended (written) to the end of the buffer and consumed (read)
+from the front of the buffer. These operations may be freely mixed.
+
+
+The buffer space that holds the characters is managed automatically
+— it grows as needed and already consumed space is recycled. Use
+buffer.new(size) and buf:free() , if you need more
+control.
+
+
+The maximum size of a single buffer is the same as the maximum size of a
+Lua string, which is slightly below two gigabytes. For huge data sizes,
+neither strings nor buffers are the right data structure — use the
+FFI library to directly map memory or files up to the virtual memory
+limit of your OS.
+
+
+
Buffer Method Overview
+
+
+The buf:put*() -like methods append (write) characters to the
+end of the buffer.
+
+
+The buf:get*() -like methods consume (read) characters from the
+front of the buffer.
+
+
+Other methods, like buf:tostring() only read the buffer
+contents, but don't change the buffer.
+
+
+The buf:set() method allows zero-copy consumption of a string
+or an FFI cdata object as a buffer.
+
+
+The FFI-specific methods allow zero-copy read/write-style operations or
+modifying the buffer contents in-place. Please check the
+FFI caveats below, too.
+
+
+Methods that don't need to return anything specific, return the buffer
+object itself as a convenience. This allows method chaining, e.g.:
+buf:reset():encode(obj) or buf:skip(len):get()
+
+
+
+
Buffer Creation and Management
+
+
local buf = buffer.new([size [,options]])
+local buf = buffer.new([options])
+
+Creates a new buffer object.
+
+
+The optional size argument ensures a minimum initial buffer
+size. This is strictly an optimization when the required buffer size is
+known beforehand. The buffer space will grow as needed, in any case.
+
+
+The optional table options sets various
+serialization options .
+
+
+
buf = buf:reset()
+
+Reset (empty) the buffer. The allocated buffer space is not freed and
+may be reused.
+
+
+
buf = buf:free()
+
+The buffer space of the buffer object is freed. The object itself
+remains intact, empty and may be reused.
+
+
+Note: you normally don't need to use this method. The garbage collector
+automatically frees the buffer space, when the buffer object is
+collected. Use this method, if you need to free the associated memory
+immediately.
+
+
+
Buffer Writers
+
+
buf = buf:put([str|num|obj] [,…])
+
+Appends a string str , a number num or any object
+obj with a __tostring metamethod to the buffer.
+Multiple arguments are appended in the given order.
+
+
+Appending a buffer to a buffer is possible and short-circuited
+internally. But it still involves a copy. Better combine the buffer
+writes to use a single buffer.
+
+
+
buf = buf:putf(format, …)
+
+Appends the formatted arguments to the buffer. The format
+string supports the same options as string.format() .
+
+
+
buf = buf:putcdata(cdata, len) FFI
+
+Appends the given len number of bytes from the memory pointed
+to by the FFI cdata object to the buffer. The object needs to
+be convertible to a (constant) pointer.
+
+
+
buf = buf:set(str)
+buf = buf:set(cdata, len) FFI
+
+This method allows zero-copy consumption of a string or an FFI cdata
+object as a buffer. It stores a reference to the passed string
+str or the FFI cdata object in the buffer. Any buffer
+space originally allocated is freed. This is not an append
+operation, unlike the buf:put*() methods.
+
+
+After calling this method, the buffer behaves as if
+buf:free():put(str) or buf:free():put(cdata, len)
+had been called. However, the data is only referenced and not copied, as
+long as the buffer is only consumed.
+
+
+In case the buffer is written to later on, the referenced data is copied
+and the object reference is removed (copy-on-write semantics).
+
+
+The stored reference is an anchor for the garbage collector and keeps the
+originally passed string or FFI cdata object alive.
+
+
+
ptr, len = buf:reserve(size) FFI
+buf = buf:commit(used) FFI
+
+The reserve method reserves at least size bytes of
+write space in the buffer. It returns an uint8_t * FFI
+cdata pointer ptr that points to this space.
+
+
+The available length in bytes is returned in len . This is at
+least size bytes, but may be more to facilitate efficient
+buffer growth. You can either make use of the additional space or ignore
+len and only use size bytes.
+
+
+The commit method appends the used bytes of the
+previously returned write space to the buffer data.
+
+
+This pair of methods allows zero-copy use of C read-style APIs:
+
+
+local MIN_SIZE = 65536
+repeat
+ local ptr, len = buf:reserve(MIN_SIZE)
+ local n = C.read(fd, ptr, len)
+ if n == 0 then break end -- EOF.
+ if n < 0 then error("read error") end
+ buf:commit(n)
+until false
+
+
+The reserved write space is not initialized. At least the
+used bytes must be written to before calling the
+commit method. There's no need to call the commit
+method, if nothing is added to the buffer (e.g. on error).
+
+
+
Buffer Readers
+
+
len = #buf
+
+Returns the current length of the buffer data in bytes.
+
+
+
res = str|num|buf .. str|num|buf […]
+
+The Lua concatenation operator .. also accepts buffers, just
+like strings or numbers. It always returns a string and not a buffer.
+
+
+Note that although this is supported for convenience, this thwarts one
+of the main reasons to use buffers, which is to avoid string
+allocations. Rewrite it with buf:put() and buf:get() .
+
+
+Mixing this with unrelated objects that have a __concat
+metamethod may not work, since these probably only expect strings.
+
+
+
buf = buf:skip(len)
+
+Skips (consumes) len bytes from the buffer up to the current
+length of the buffer data.
+
+
+
str, … = buf:get([len|nil] [,…])
+
+Consumes the buffer data and returns one or more strings. If called
+without arguments, the whole buffer data is consumed. If called with a
+number, up to len bytes are consumed. A nil argument
+consumes the remaining buffer space (this only makes sense as the last
+argument). Multiple arguments consume the buffer data in the given
+order.
+
+
+Note: a zero length or no remaining buffer data returns an empty string
+and not nil .
+
+
+
str = buf:tostring()
+str = tostring(buf)
+
+Creates a string from the buffer data, but doesn't consume it. The
+buffer remains unchanged.
+
+
+Buffer objects also define a __tostring metamethod. This means
+buffers can be passed to the global tostring() function and
+many other functions that accept this in place of strings. The important
+internal uses in functions like io.write() are short-circuited
+to avoid the creation of an intermediate string object.
+
+
+
ptr, len = buf:ref() FFI
+
+Returns an uint8_t * FFI cdata pointer ptr that
+points to the buffer data. The length of the buffer data in bytes is
+returned in len .
+
+
+The returned pointer can be directly passed to C functions that expect a
+buffer and a length. You can also do bytewise reads
+(local x = ptr[i] ) or writes
+(ptr[i] = 0x40 ) of the buffer data.
+
+
+In conjunction with the skip method, this allows zero-copy use
+of C write-style APIs:
+
+
+repeat
+ local ptr, len = buf:ref()
+ if len == 0 then break end
+ local n = C.write(fd, ptr, len)
+ if n < 0 then error("write error") end
+ buf:skip(n)
+until n >= len
+
+
+Unlike Lua strings, buffer data is not implicitly
+zero-terminated. It's not safe to pass ptr to C functions that
+expect zero-terminated strings. If you're not using len , then
+you're doing something wrong.
+
+
+
Serialization of Lua Objects
+
+The following functions and methods allow high-speed serialization
+(encoding) of a Lua object into a string and decoding it back to a Lua
+object. This allows convenient storage and transport of structured
+data .
+
+
+The encoded data is in an internal binary
+format . The data can be stored in files, binary-transparent
+databases or transmitted to other LuaJIT instances across threads,
+processes or networks.
+
+
+Encoding speed can reach up to 1 Gigabyte/second on a modern desktop- or
+server-class system, even when serializing many small objects. Decoding
+speed is mostly constrained by object creation cost.
+
+
+The serializer handles most Lua types, common FFI number types and
+nested structures. Functions, thread objects, other FFI cdata and full
+userdata cannot be serialized (yet).
+
+
+The encoder serializes nested structures as trees. Multiple references
+to a single object will be stored separately and create distinct objects
+after decoding. Circular references cause an error.
+
+
+
Serialization Functions and Methods
+
+
str = buffer.encode(obj)
+buf = buf:encode(obj)
+
+Serializes (encodes) the Lua object obj . The stand-alone
+function returns a string str . The buffer method appends the
+encoding to the buffer.
+
+
+obj can be any of the supported Lua types — it doesn't
+need to be a Lua table.
+
+
+This function may throw an error when attempting to serialize
+unsupported object types, circular references or deeply nested tables.
+
+
+
obj = buffer.decode(str)
+obj = buf:decode()
+
+The stand-alone function deserializes (decodes) the string
+str , the buffer method deserializes one object from the
+buffer. Both return a Lua object obj .
+
+
+The returned object may be any of the supported Lua types —
+even nil .
+
+
+This function may throw an error when fed with malformed or incomplete
+encoded data. The stand-alone function throws when there's left-over
+data after decoding a single top-level object. The buffer method leaves
+any left-over data in the buffer.
+
+
+Attempting to deserialize an FFI type will throw an error, if the FFI
+library is not built-in or has not been loaded, yet.
+
+
+
Serialization Options
+
+The options table passed to buffer.new() may contain
+the following members (all optional):
+
+
+
+dict is a Lua table holding a dictionary of strings that
+commonly occur as table keys of objects you are serializing. These keys
+are compactly encoded as indexes during serialization. A well-chosen
+dictionary saves space and improves serialization performance.
+
+
+metatable is a Lua table holding a dictionary of metatables
+for the table objects you are serializing.
+
+
+
+dict needs to be an array of strings and metatable needs
+to be an array of tables. Both starting at index 1 and without holes (no
+nil in between). The tables are anchored in the buffer object and
+internally modified into a two-way index (don't do this yourself, just pass
+a plain array). The tables must not be modified after they have been passed
+to buffer.new() .
+
+
+The dict and metatable tables used by the encoder and
+decoder must be the same. Put the most common entries at the front. Extend
+at the end to ensure backwards-compatibility — older encodings can
+then still be read. You may also set some indexes to false to
+explicitly drop backwards-compatibility. Old encodings that use these
+indexes will throw an error when decoded.
+
+
+Metatables that are not found in the metatable dictionary are
+ignored when encoding. Decoding returns a table with a nil
+metatable.
+
+
+Note: parsing and preparation of the options table is somewhat
+expensive. Create a buffer object only once and recycle it for multiple
+uses. Avoid mixing encoder and decoder buffers, since the
+buf:set() method frees the already allocated buffer space:
+
+
+local options = {
+ dict = { "commonly", "used", "string", "keys" },
+}
+local buf_enc = buffer.new(options)
+local buf_dec = buffer.new(options)
+
+local function encode(obj)
+ return buf_enc:reset():encode(obj):get()
+end
+
+local function decode(str)
+ return buf_dec:set(str):decode()
+end
+
+
+
Streaming Serialization
+
+In some contexts, it's desirable to do piecewise serialization of large
+datasets, also known as streaming .
+
+
+This serialization format can be safely concatenated and supports streaming.
+Multiple encodings can simply be appended to a buffer and later decoded
+individually:
+
+
+local buf = buffer.new()
+buf:encode(obj1)
+buf:encode(obj2)
+local copy1 = buf:decode()
+local copy2 = buf:decode()
+
+
+Here's how to iterate over a stream:
+
+
+while #buf ~= 0 do
+ local obj = buf:decode()
+ -- Do something with obj.
+end
+
+
+Since the serialization format doesn't prepend a length to its encoding,
+network applications may need to transmit the length, too.
+
+
+
+
+This serialization format is designed for internal use by LuaJIT
+applications. Serialized data is upwards-compatible and portable across
+all supported LuaJIT platforms.
+
+
+It's an 8-bit binary format and not human-readable. It uses e.g.
+embedded zeroes and stores embedded Lua string objects unmodified, which
+are 8-bit-clean, too. Encoded data can be safely concatenated for
+streaming and later decoded one top-level object at a time.
+
+
+The encoding is reasonably compact, but tuned for maximum performance,
+not for minimum space usage. It compresses well with any of the common
+byte-oriented data compression algorithms.
+
+
+Although documented here for reference, this format is explicitly
+not intended to be a 'public standard' for structured data
+interchange across computer languages (like JSON or MessagePack). Please
+do not use it as such.
+
+
+The specification is given below as a context-free grammar with a
+top-level object as the starting point. Alternatives are
+separated by the | symbol and * indicates repeats.
+Grouping is implicit or indicated by {…} . Terminals are
+either plain hex numbers, encoded as bytes, or have a .format
+suffix.
+
+
+object → nil | false | true
+ | null | lightud32 | lightud64
+ | int | num | tab | tab_mt
+ | int64 | uint64 | complex
+ | string
+
+nil → 0x00
+false → 0x01
+true → 0x02
+
+null → 0x03 // NULL lightuserdata
+lightud32 → 0x04 data.I // 32 bit lightuserdata
+lightud64 → 0x05 data.L // 64 bit lightuserdata
+
+int → 0x06 int.I // int32_t
+num → 0x07 double.L
+
+tab → 0x08 // Empty table
+ | 0x09 h.U h*{object object} // Key/value hash
+ | 0x0a a.U a*object // 0-based array
+ | 0x0b a.U h.U a*object h*{object object} // Mixed
+ | 0x0c a.U (a-1)*object // 1-based array
+ | 0x0d a.U h.U (a-1)*object h*{object object} // Mixed
+tab_mt → 0x0e (index-1).U tab // Metatable dict entry
+
+int64 → 0x10 int.L // FFI int64_t
+uint64 → 0x11 uint.L // FFI uint64_t
+complex → 0x12 re.L im.L // FFI complex
+
+string → (0x20+len).U len*char.B
+ | 0x0f (index-1).U // String dict entry
+
+.B = 8 bit
+.I = 32 bit little-endian
+.L = 64 bit little-endian
+.U = prefix-encoded 32 bit unsigned number n:
+ 0x00..0xdf → n.B
+ 0xe0..0x1fdf → (0xe0|(((n-0xe0)>>8)&0x1f)).B ((n-0xe0)&0xff).B
+ 0x1fe0.. → 0xff n.I
+
+
+
Error handling
+
+Many of the buffer methods can throw an error. Out-of-memory or usage
+errors are best caught with an outer wrapper for larger parts of code.
+There's not much one can do after that, anyway.
+
+
+OTOH, you may want to catch some errors individually. Buffer methods need
+to receive the buffer object as the first argument. The Lua colon-syntax
+obj:method() does that implicitly. But to wrap a method with
+pcall() , the arguments need to be passed like this:
+
+
+local ok, err = pcall(buf.encode, buf, obj)
+if not ok then
+ -- Handle error in err.
+end
+
+
+
FFI caveats
+
+The string buffer library has been designed to work well together with
+the FFI library. But due to the low-level nature of the FFI library,
+some care needs to be taken:
+
+
+First, please remember that FFI pointers are zero-indexed. The space
+returned by buf:reserve() and buf:ref() starts at the
+returned pointer and ends before len bytes after that.
+
+
+I.e. the first valid index is ptr[0] and the last valid index
+is ptr[len-1] . If the returned length is zero, there's no valid
+index at all. The returned pointer may even be NULL .
+
+
+The space pointed to by the returned pointer is only valid as long as
+the buffer is not modified in any way (neither append, nor consume, nor
+reset, etc.). The pointer is also not a GC anchor for the buffer object
+itself.
+
+
+Buffer data is only guaranteed to be byte-aligned. Casting the returned
+pointer to a data type with higher alignment may cause unaligned
+accesses. It depends on the CPU architecture whether this is allowed or
+not (it's always OK on x86/x64 and mostly OK on other modern
+architectures).
+
+
+FFI pointers or references do not count as GC anchors for an underlying
+object. E.g. an array allocated with ffi.new() is
+anchored by buf:set(array, len) , but not by
+buf:set(array+offset, len) . The addition of the offset
+creates a new pointer, even when the offset is zero. In this case, you
+need to make sure there's still a reference to the original array as
+long as its contents are in use by the buffer.
+
+
+Even though each LuaJIT VM instance is single-threaded (but you can
+create multiple VMs), FFI data structures can be accessed concurrently.
+Be careful when reading/writing FFI cdata from/to buffers to avoid
+concurrent accesses or modifications. In particular, the memory
+referenced by buf:set(cdata, len) must not be modified
+while buffer readers are working on it. Shared, but read-only memory
+mappings of files are OK, but only if the file does not change.
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/ext_c_api.html b/LuaJIT-2.1/doc/ext_c_api.html
new file mode 100644
index 00000000..673a9b9a
--- /dev/null
+++ b/LuaJIT-2.1/doc/ext_c_api.html
@@ -0,0 +1,183 @@
+
+
+
+Lua/C API Extensions
+
+
+
+
+
+
+
+
+
+
Lua/C API Extensions
+
+
+
+
+LuaJIT adds some extensions to the standard Lua/C API. The LuaJIT include
+directory must be in the compiler search path (-Ipath )
+to be able to include the required header for C code:
+
+
+#include "luajit.h"
+
+
+Or for C++ code:
+
+
+#include "lua.hpp"
+
+
+
luaJIT_setmode(L, idx, mode)
+— Control VM
+
+This is a C API extension to allow control of the VM from C code. The
+full prototype of LuaJIT_setmode is:
+
+
+LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode);
+
+
+The returned status is either success (1 ) or failure (0 ).
+The second argument is either 0 or a stack index (similar to the
+other Lua/C API functions).
+
+
+The third argument specifies the mode, which is 'or'ed with a flag.
+The flag can be LUAJIT_MODE_OFF to turn a feature off,
+LUAJIT_MODE_ON to turn a feature on, or
+LUAJIT_MODE_FLUSH to flush cached code.
+
+
+The following modes are defined:
+
+
+
luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE|flag)
+
+Turn the whole JIT compiler on or off or flush the whole cache of compiled code.
+
+
+
luaJIT_setmode(L, idx, LUAJIT_MODE_FUNC|flag)
+luaJIT_setmode(L, idx, LUAJIT_MODE_ALLFUNC|flag)
+luaJIT_setmode(L, idx, LUAJIT_MODE_ALLSUBFUNC|flag)
+
+This sets the mode for the function at the stack index idx or
+the parent of the calling function (idx = 0 ). It either
+enables JIT compilation for a function, disables it and flushes any
+already compiled code, or only flushes already compiled code. This
+applies recursively to all sub-functions of the function with
+LUAJIT_MODE_ALLFUNC or only to the sub-functions with
+LUAJIT_MODE_ALLSUBFUNC .
+
+
+
luaJIT_setmode(L, trace,
+ LUAJIT_MODE_TRACE|LUAJIT_MODE_FLUSH)
+
+Flushes the specified root trace and all of its side traces from the cache.
+The code for the trace will be retained as long as there are any other
+traces which link to it.
+
+
+
luaJIT_setmode(L, idx, LUAJIT_MODE_WRAPCFUNC|flag)
+
+This mode defines a wrapper function for calls to C functions. If
+called with LUAJIT_MODE_ON , the stack index at idx
+must be a lightuserdata object holding a pointer to the wrapper
+function. From now on, all C functions are called through the wrapper
+function. If called with LUAJIT_MODE_OFF this mode is turned
+off and all C functions are directly called.
+
+
+The wrapper function can be used for debugging purposes or to catch
+and convert foreign exceptions. But please read the section on
+C++ exception interoperability
+first. Recommended usage can be seen in this C++ code excerpt:
+
+
+#include <exception>
+#include "lua.hpp"
+
+// Catch C++ exceptions and convert them to Lua error messages.
+// Customize as needed for your own exception classes.
+static int wrap_exceptions(lua_State *L, lua_CFunction f)
+{
+ try {
+ return f(L); // Call wrapped function and return result.
+ } catch (const char *s) { // Catch and convert exceptions.
+ lua_pushstring(L, s);
+ } catch (std::exception& e) {
+ lua_pushstring(L, e.what());
+ } catch (...) {
+ lua_pushliteral(L, "caught (...)");
+ }
+ return lua_error(L); // Rethrow as a Lua error.
+}
+
+static int myinit(lua_State *L)
+{
+ ...
+ // Define wrapper function and enable it.
+ lua_pushlightuserdata(L, (void *)wrap_exceptions);
+ luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_ON);
+ lua_pop(L, 1);
+ ...
+}
+
+
+Note that you can only define a single global wrapper function ,
+so be careful when using this mechanism from multiple C++ modules.
+Also note that this mechanism is not without overhead.
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/ext_ffi.html b/LuaJIT-2.1/doc/ext_ffi.html
new file mode 100644
index 00000000..aa6d8363
--- /dev/null
+++ b/LuaJIT-2.1/doc/ext_ffi.html
@@ -0,0 +1,326 @@
+
+
+
+FFI Library
+
+
+
+
+
+
+
+
+
+
FFI Library
+
+
+
+
+
+The FFI library allows calling external C functions and
+using C data structures from pure Lua code.
+
+
+
+
+The FFI library largely obviates the need to write tedious manual
+Lua/C bindings in C. No need to learn a separate binding language
+— it parses plain C declarations! These can be
+cut-n-pasted from C header files or reference manuals. It's up to
+the task of binding large libraries without the need for dealing with
+fragile binding generators.
+
+
+
+The FFI library is tightly integrated into LuaJIT (it's not available
+as a separate module). The code generated by the JIT-compiler for
+accesses to C data structures from Lua code is on par with the
+code a C compiler would generate. Calls to C functions can
+be inlined in JIT-compiled code, unlike calls to functions bound via
+the classic Lua/C API.
+
+
+This page gives a short introduction to the usage of the FFI library.
+Please use the FFI sub-topics in the navigation bar to learn more.
+
+
+
Motivating Example: Calling External C Functions
+
+It's really easy to call an external C library function:
+
+
+①
+②
+
+
+③ local ffi = require("ffi")
+ffi.cdef[[
+int printf(const char *fmt, ...);
+]]
+ffi.C.printf("Hello %s!", "world")
+
+
+So, let's pick that apart:
+
+
+① Load the FFI library.
+
+
+② Add a C declaration
+for the function. The part inside the double-brackets (in green) is
+just standard C syntax.
+
+
+③ Call the named
+C function — Yes, it's that simple!
+
+
+Actually, what goes on behind the scenes is far from simple: ③ makes use of the standard
+C library namespace ffi.C . Indexing this namespace with
+a symbol name ("printf" ) automatically binds it to the
+standard C library. The result is a special kind of object which,
+when called, runs the printf function. The arguments passed
+to this function are automatically converted from Lua objects to the
+corresponding C types.
+
+
+Ok, so maybe the use of printf() wasn't such a spectacular
+example. You could have done that with io.write() and
+string.format() , too. But you get the idea ...
+
+
+So here's something to pop up a message box on Windows:
+
+
+local ffi = require("ffi")
+ffi.cdef[[
+int MessageBoxA(void *w, const char *txt, const char *cap, int type);
+]]
+ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0)
+
+
+Bing! Again, that was far too easy, no?
+
+
+Compare this with the effort required to bind that function using the
+classic Lua/C API: create an extra C file, add a C function
+that retrieves and checks the argument types passed from Lua and calls
+the actual C function, add a list of module functions and their
+names, add a luaopen_* function and register all module
+functions, compile and link it into a shared library (DLL), move it to
+the proper path, add Lua code that loads the module aaaand ... finally
+call the binding function. Phew!
+
+
+
Motivating Example: Using C Data Structures
+
+The FFI library allows you to create and access C data
+structures. Of course, the main use for this is for interfacing with
+C functions. But they can be used stand-alone, too.
+
+
+Lua is built upon high-level data types. They are flexible, extensible
+and dynamic. That's why we all love Lua so much. Alas, this can be
+inefficient for certain tasks, where you'd really want a low-level
+data type. E.g. a large array of a fixed structure needs to be
+implemented with a big table holding lots of tiny tables. This imposes
+both a substantial memory overhead as well as a performance overhead.
+
+
+Here's a sketch of a library that operates on color images, plus a
+simple benchmark. First, the plain Lua version:
+
+
+local floor = math.floor
+
+local function image_ramp_green(n)
+ local img = {}
+ local f = 255/(n-1)
+ for i=1,n do
+ img[i] = { red = 0, green = floor((i-1)*f), blue = 0, alpha = 255 }
+ end
+ return img
+end
+
+local function image_to_gray(img, n)
+ for i=1,n do
+ local y = floor(0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue)
+ img[i].red = y; img[i].green = y; img[i].blue = y
+ end
+end
+
+local N = 400*400
+local img = image_ramp_green(N)
+for i=1,1000 do
+ image_to_gray(img, N)
+end
+
+
+This creates a table with 160.000 pixels, each of which is a table
+holding four number values in the range of 0-255. First, an image with
+a green ramp is created (1D for simplicity), then the image is
+converted to grayscale 1000 times. Yes, that's silly, but I was in
+need of a simple example ...
+
+
+And here's the FFI version. The modified parts have been marked in
+bold:
+
+
+①
+
+
+
+
+
+②
+
+③
+④
+
+
+
+
+
+
+③
+⑤ local ffi = require("ffi")
+ffi.cdef[[
+ typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;
+]]
+
+local function image_ramp_green(n)
+ local img = ffi.new("rgba_pixel[?]", n)
+ local f = 255/(n-1)
+ for i=0,n-1 do
+ img[i].green = i*f
+ img[i].alpha = 255
+ end
+ return img
+end
+
+local function image_to_grey(img, n)
+ for i=0,n-1 do
+ local y = 0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue
+ img[i].red = y; img[i].green = y; img[i].blue = y
+ end
+end
+
+local N = 400*400
+local img = image_ramp_green(N)
+for i=1,1000 do
+ image_to_grey(img, N)
+end
+
+
+Ok, so that wasn't too difficult:
+
+
+① First, load the FFI
+library and declare the low-level data type. Here we choose a
+struct which holds four byte fields, one for each component
+of a 4x8 bit RGBA pixel.
+
+
+② Creating the data
+structure with ffi.new() is straightforward — the
+'?' is a placeholder for the number of elements of a
+variable-length array.
+
+
+③ C arrays are
+zero-based, so the indexes have to run from 0 to
+n-1 . One might want to allocate one more element instead to
+simplify converting legacy code.
+
+
+④ Since ffi.new()
+zero-fills the array by default, we only need to set the green and the
+alpha fields.
+
+
+⑤ The calls to
+math.floor() can be omitted here, because floating-point
+numbers are already truncated towards zero when converting them to an
+integer. This happens implicitly when the number is stored in the
+fields of each pixel.
+
+
+Now let's have a look at the impact of the changes: first, memory
+consumption for the image is down from 22 Megabytes to
+640 Kilobytes (400*400*4 bytes). That's a factor of 35x less! So,
+yes, tables do have a noticeable overhead. BTW: The original program
+would consume 40 Megabytes in plain Lua (on x64).
+
+
+Next, performance: the pure Lua version runs in 9.57 seconds (52.9
+seconds with the Lua interpreter) and the FFI version runs in 0.48
+seconds on my machine (YMMV). That's a factor of 20x faster (110x
+faster than the Lua interpreter).
+
+
+The avid reader may notice that converting the pure Lua version over
+to use array indexes for the colors ([1] instead of
+.red , [2] instead of .green etc.) ought to
+be more compact and faster. This is certainly true (by a factor of
+~1.7x). Switching to a struct-of-arrays would help, too.
+
+
+However, the resulting code would be less idiomatic and rather
+error-prone. And it still doesn't get even close to the performance of
+the FFI version of the code. Also, high-level data structures cannot
+be easily passed to other C functions, especially I/O functions,
+without undue conversion penalties.
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/ext_ffi_api.html b/LuaJIT-2.1/doc/ext_ffi_api.html
new file mode 100644
index 00000000..360dd521
--- /dev/null
+++ b/LuaJIT-2.1/doc/ext_ffi_api.html
@@ -0,0 +1,568 @@
+
+
+
+ffi.* API Functions
+
+
+
+
+
+
+
+
+
+
+
ffi.* API Functions
+
+
+
+
+This page describes the API functions provided by the FFI library in
+detail. It's recommended to read through the
+introduction and the
+FFI tutorial first.
+
+
+
Glossary
+
+cdecl — An abstract C type declaration (a Lua
+string).
+ctype — A C type object. This is a special kind of
+cdata returned by ffi.typeof() . It serves as a
+cdata constructor when called.
+cdata — A C data object. It holds a value of the
+corresponding ctype .
+ct — A C type specification which can be used for
+most of the API functions. Either a cdecl , a ctype or a
+cdata serving as a template type.
+cb — A callback object. This is a C data object
+holding a special function pointer. Calling this function from
+C code runs an associated Lua function.
+VLA — A variable-length array is declared with a
+? instead of the number of elements, e.g. "int[?]" .
+The number of elements (nelem ) must be given when it's
+created .
+VLS — A variable-length struct is a struct C
+type where the last element is a VLA . The same rules for
+declaration and creation apply.
+
+
+
Declaring and Accessing External Symbols
+
+External symbols must be declared first and can then be accessed by
+indexing a C library
+namespace , which automatically binds the symbol to a specific
+library.
+
+
+
ffi.cdef(def)
+
+Adds multiple C declarations for types or external symbols (named
+variables or functions). def must be a Lua string. It's
+recommended to use the syntactic sugar for string arguments as
+follows:
+
+
+ffi.cdef[[
+typedef struct foo { int a, b; } foo_t; // Declare a struct and typedef.
+int dofoo(foo_t *f, int n); /* Declare an external C function. */
+]]
+
+
+The contents of the string (the part in green above) must be a
+sequence of
+C declarations ,
+separated by semicolons. The trailing semicolon for a single
+declaration may be omitted.
+
+
+Please note, that external symbols are only declared , but they
+are not bound to any specific address, yet. Binding is
+achieved with C library namespaces (see below).
+
+
+C declarations are not passed through a C pre-processor,
+yet. No pre-processor tokens are allowed, except for
+#pragma pack . Replace #define in existing
+C header files with enum , static const
+or typedef and/or pass the files through an external
+C pre-processor (once). Be careful not to include unneeded or
+redundant declarations from unrelated header files.
+
+
+
ffi.C
+
+This is the default C library namespace — note the
+uppercase 'C' . It binds to the default set of symbols or
+libraries on the target system. These are more or less the same as a
+C compiler would offer by default, without specifying extra link
+libraries.
+
+
+On POSIX systems, this binds to symbols in the default or global
+namespace. This includes all exported symbols from the executable and
+any libraries loaded into the global namespace. This includes at least
+libc , libm , libdl (on Linux),
+libgcc (if compiled with GCC), as well as any exported
+symbols from the Lua/C API provided by LuaJIT itself.
+
+
+On Windows systems, this binds to symbols exported from the
+*.exe , the lua51.dll (i.e. the Lua/C API
+provided by LuaJIT itself), the C runtime library LuaJIT was linked
+with (msvcrt*.dll ), kernel32.dll ,
+user32.dll and gdi32.dll .
+
+
+
clib = ffi.load(name [,global])
+
+This loads the dynamic library given by name and returns
+a new C library namespace which binds to its symbols. On POSIX
+systems, if global is true , the library symbols are
+loaded into the global namespace, too.
+
+
+If name is a path, the library is loaded from this path.
+Otherwise name is canonicalized in a system-dependent way and
+searched in the default search path for dynamic libraries:
+
+
+On POSIX systems, if the name contains no dot, the extension
+.so is appended. Also, the lib prefix is prepended
+if necessary. So ffi.load("z") looks for "libz.so"
+in the default shared library search path.
+
+
+On Windows systems, if the name contains no dot, the extension
+.dll is appended. So ffi.load("ws2_32") looks for
+"ws2_32.dll" in the default DLL search path.
+
+
+
Creating cdata Objects
+
+The following API functions create cdata objects (type()
+returns "cdata" ). All created cdata objects are
+garbage collected .
+
+
+
cdata = ffi.new(ct [,nelem] [,init...])
+cdata = ctype ([nelem,] [init...])
+
+Creates a cdata object for the given ct . VLA/VLS types
+require the nelem argument. The second syntax uses a ctype as
+a constructor and is otherwise fully equivalent.
+
+
+The cdata object is initialized according to the
+rules for initializers ,
+using the optional init arguments. Excess initializers cause
+an error.
+
+
+Performance notice: if you want to create many objects of one kind,
+parse the cdecl only once and get its ctype with
+ffi.typeof() . Then use the ctype as a constructor repeatedly.
+
+
+Please note, that an anonymous struct declaration implicitly
+creates a new and distinguished ctype every time you use it for
+ffi.new() . This is probably not what you want,
+especially if you create more than one cdata object. Different anonymous
+structs are not considered assignment-compatible by the
+C standard, even though they may have the same fields! Also, they
+are considered different types by the JIT-compiler, which may cause an
+excessive number of traces. It's strongly suggested to either declare
+a named struct or typedef with ffi.cdef()
+or to create a single ctype object for an anonymous struct
+with ffi.typeof() .
+
+
+
ctype = ffi.typeof(ct)
+
+Creates a ctype object for the given ct .
+
+
+This function is especially useful to parse a cdecl only once and then
+use the resulting ctype object as a constructor .
+
+
+
cdata = ffi.cast(ct, init)
+
+Creates a scalar cdata object for the given ct . The cdata
+object is initialized with init using the "cast" variant of
+the C type conversion
+rules .
+
+
+This functions is mainly useful to override the pointer compatibility
+checks or to convert pointers to addresses or vice versa.
+
+
+
+
+Creates a ctype object for the given ct and associates it with
+a metatable. Only struct /union types, complex numbers
+and vectors are allowed. Other types may be wrapped in a
+struct , if needed.
+
+
+The association with a metatable is permanent and cannot be changed
+afterwards. Neither the contents of the metatable nor the
+contents of an __index table (if any) may be modified
+afterwards. The associated metatable automatically applies to all uses
+of this type, no matter how the objects are created or where they
+originate from. Note that predefined operations on types have
+precedence (e.g. declared field names cannot be overridden).
+
+
+All standard Lua metamethods are implemented. These are called directly,
+without shortcuts, and on any mix of types. For binary operations, the
+left operand is checked first for a valid ctype metamethod. The
+__gc metamethod only applies to struct /union
+types and performs an implicit ffi.gc()
+call during creation of an instance.
+
+
+
cdata = ffi.gc(cdata, finalizer)
+
+Associates a finalizer with a pointer or aggregate cdata object. The
+cdata object is returned unchanged.
+
+
+This function allows safe integration of unmanaged resources into the
+automatic memory management of the LuaJIT garbage collector. Typical
+usage:
+
+
+local p = ffi.gc(ffi.C.malloc(n), ffi.C.free)
+...
+p = nil -- Last reference to p is gone.
+-- GC will eventually run finalizer: ffi.C.free(p)
+
+
+A cdata finalizer works like the __gc metamethod for userdata
+objects: when the last reference to a cdata object is gone, the
+associated finalizer is called with the cdata object as an argument. The
+finalizer can be a Lua function or a cdata function or cdata function
+pointer. An existing finalizer can be removed by setting a nil
+finalizer, e.g. right before explicitly deleting a resource:
+
+
+ffi.C.free(ffi.gc(p, nil)) -- Manually free the memory.
+
+
+
C Type Information
+
+The following API functions return information about C types.
+They are most useful for inspecting cdata objects.
+
+
+
size = ffi.sizeof(ct [,nelem])
+
+Returns the size of ct in bytes. Returns nil if
+the size is not known (e.g. for "void" or function types).
+Requires nelem for VLA/VLS types, except for cdata objects.
+
+
+
align = ffi.alignof(ct)
+
+Returns the minimum required alignment for ct in bytes.
+
+
+
ofs [,bpos,bsize] = ffi.offsetof(ct, field)
+
+Returns the offset (in bytes) of field relative to the start
+of ct , which must be a struct . Additionally returns
+the position and the field size (in bits) for bit fields.
+
+
+
status = ffi.istype(ct, obj)
+
+Returns true if obj has the C type given by
+ct . Returns false otherwise.
+
+
+C type qualifiers (const etc.) are ignored. Pointers are
+checked with the standard pointer compatibility rules, but without any
+special treatment for void * . If ct specifies a
+struct /union , then a pointer to this type is accepted,
+too. Otherwise the types must match exactly.
+
+
+Note: this function accepts all kinds of Lua objects for the
+obj argument, but always returns false for non-cdata
+objects.
+
+
+
Utility Functions
+
+
err = ffi.errno([newerr])
+
+Returns the error number set by the last C function call which
+indicated an error condition. If the optional newerr argument
+is present, the error number is set to the new value and the previous
+value is returned.
+
+
+This function offers a portable and OS-independent way to get and set the
+error number. Note that only some C functions set the error
+number. And it's only significant if the function actually indicated an
+error condition (e.g. with a return value of -1 or
+NULL ). Otherwise, it may or may not contain any previously set
+value.
+
+
+You're advised to call this function only when needed and as close as
+possible after the return of the related C function. The
+errno value is preserved across hooks, memory allocations,
+invocations of the JIT compiler and other internal VM activity. The same
+applies to the value returned by GetLastError() on Windows, but
+you need to declare and call it yourself.
+
+
+
str = ffi.string(ptr [,len])
+
+Creates an interned Lua string from the data pointed to by
+ptr .
+
+
+If the optional argument len is missing, ptr is
+converted to a "char *" and the data is assumed to be
+zero-terminated. The length of the string is computed with
+strlen() .
+
+
+Otherwise ptr is converted to a "void *" and
+len gives the length of the data. The data may contain
+embedded zeros and need not be byte-oriented (though this may cause
+endianess issues).
+
+
+This function is mainly useful to convert (temporary)
+"const char *" pointers returned by
+C functions to Lua strings and store them or pass them to other
+functions expecting a Lua string. The Lua string is an (interned) copy
+of the data and bears no relation to the original data area anymore.
+Lua strings are 8 bit clean and may be used to hold arbitrary,
+non-character data.
+
+
+Performance notice: it's faster to pass the length of the string, if
+it's known. E.g. when the length is returned by a C call like
+sprintf() .
+
+
+
ffi.copy(dst, src, len)
+ffi.copy(dst, str)
+
+Copies the data pointed to by src to dst .
+dst is converted to a "void *" and src
+is converted to a "const void *" .
+
+
+In the first syntax, len gives the number of bytes to copy.
+Caveat: if src is a Lua string, then len must not
+exceed #src+1 .
+
+
+In the second syntax, the source of the copy must be a Lua string. All
+bytes of the string plus a zero-terminator are copied to
+dst (i.e. #src+1 bytes).
+
+
+Performance notice: ffi.copy() may be used as a faster
+(inlinable) replacement for the C library functions
+memcpy() , strcpy() and strncpy() .
+
+
+
ffi.fill(dst, len [,c])
+
+Fills the data pointed to by dst with len constant
+bytes, given by c . If c is omitted, the data is
+zero-filled.
+
+
+Performance notice: ffi.fill() may be used as a faster
+(inlinable) replacement for the C library function
+memset(dst, c, len) . Please note the different
+order of arguments!
+
+
+
Target-specific Information
+
+
status = ffi.abi(param)
+
+Returns true if param (a Lua string) applies for the
+target ABI (Application Binary Interface). Returns false
+otherwise. The following parameters are currently defined:
+
+
+
+Parameter
+Description
+
+
+32bit 32 bit architecture
+
+64bit 64 bit architecture
+
+le Little-endian architecture
+
+be Big-endian architecture
+
+fpu Target has a hardware FPU
+
+softfp softfp calling conventions
+
+hardfp hardfp calling conventions
+
+eabi EABI variant of the standard ABI
+
+win Windows variant of the standard ABI
+
+pauth Pointer authentication ABI
+
+uwp Universal Windows Platform
+
+gc64 64 bit GC references
+
+
+
ffi.os
+
+Contains the target OS name. Same contents as
+jit.os .
+
+
+
ffi.arch
+
+Contains the target architecture name. Same contents as
+jit.arch .
+
+
+
Methods for Callbacks
+
+The C types for callbacks
+have some extra methods:
+
+
+
cb:free()
+
+Free the resources associated with a callback. The associated Lua
+function is unanchored and may be garbage collected. The callback
+function pointer is no longer valid and must not be called again
+(it may be reused by a subsequently created callback).
+
+
+
cb:set(func)
+
+Associate a new Lua function with a callback. The C type of the
+callback and the callback function pointer are unchanged.
+
+
+This method is useful to dynamically switch the receiver of callbacks
+without creating a new callback each time and registering it again (e.g.
+with a GUI library).
+
+
+
Extended Standard Library Functions
+
+The following standard library functions have been extended to work
+with cdata objects:
+
+
+
n = tonumber(cdata)
+
+Converts a number cdata object to a double and returns it as
+a Lua number. This is particularly useful for boxed 64 bit
+integer values. Caveat: this conversion may incur a precision loss.
+
+
+
s = tostring(cdata)
+
+Returns a string representation of the value of 64 bit integers
+(" nnnLL" or " nnnULL" ) or
+complex numbers (" re±imi" ). Otherwise
+returns a string representation of the C type of a ctype object
+("ctype< type>" ) or a cdata object
+("cdata< type>: address" ), unless you
+override it with a __tostring metamethod (see
+ffi.metatype() ).
+
+
+
iter, obj, start = pairs(cdata)
+iter, obj, start = ipairs(cdata)
+
+Calls the __pairs or __ipairs metamethod of the
+corresponding ctype.
+
+
+
Extensions to the Lua Parser
+
+The parser for Lua source code treats numeric literals with the
+suffixes LL or ULL as signed or unsigned 64 bit
+integers. Case doesn't matter, but uppercase is recommended for
+readability. It handles decimal (42LL ), hexadecimal
+(0x2aLL ) and binary (0b101010LL ) literals.
+
+
+The imaginary part of complex numbers can be specified by suffixing
+number literals with i or I , e.g. 12.5i .
+Caveat: you'll need to use 1i to get an imaginary part with
+the value one, since i itself still refers to a variable
+named i .
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/ext_ffi_semantics.html b/LuaJIT-2.1/doc/ext_ffi_semantics.html
new file mode 100644
index 00000000..cd533e8c
--- /dev/null
+++ b/LuaJIT-2.1/doc/ext_ffi_semantics.html
@@ -0,0 +1,1269 @@
+
+
+
+FFI Semantics
+
+
+
+
+
+
+
+
+
+
+
FFI Semantics
+
+
+
+
+This page describes the detailed semantics underlying the FFI library
+and its interaction with both Lua and C code.
+
+
+Given that the FFI library is designed to interface with C code
+and that declarations can be written in plain C syntax, it
+closely follows the C language semantics , wherever possible.
+Some minor concessions are needed for smoother interoperation with Lua
+language semantics.
+
+
+Please don't be overwhelmed by the contents of this page — this
+is a reference and you may need to consult it, if in doubt. It doesn't
+hurt to skim this page, but most of the semantics "just work" as you'd
+expect them to work. It should be straightforward to write
+applications using the LuaJIT FFI for developers with a C or C++
+background.
+
+
+
C Language Support
+
+The FFI library has a built-in C parser with a minimal memory
+footprint. It's used by the ffi.* library
+functions to declare C types or external symbols.
+
+
+Its only purpose is to parse C declarations, as found e.g. in
+C header files. Although it does evaluate constant expressions,
+it's not a C compiler. The body of inline
+C function definitions is simply ignored.
+
+
+Also, this is not a validating C parser. It expects and
+accepts correctly formed C declarations, but it may choose to
+ignore bad declarations or show rather generic error messages. If in
+doubt, please check the input against your favorite C compiler.
+
+
+The C parser complies to the C99 language standard plus
+the following extensions:
+
+
+
+The '\e' escape in character and string literals.
+
+The C99/C++ boolean type, declared with the keywords bool
+or _Bool .
+
+Complex numbers, declared with the keywords complex or
+_Complex .
+
+Two complex number types: complex (aka
+complex double ) and complex float .
+
+Vector types, declared with the GCC mode or
+vector_size attribute.
+
+Unnamed ('transparent') struct /union fields
+inside a struct /union .
+
+Incomplete enum declarations, handled like incomplete
+struct declarations.
+
+Unnamed enum fields inside a
+struct /union . This is similar to a scoped C++
+enum , except that declared constants are visible in the
+global namespace, too.
+
+Scoped static const declarations inside a
+struct /union (from C++).
+
+Zero-length arrays ([0] ), empty
+struct /union , variable-length arrays (VLA,
+[?] ) and variable-length structs (VLS, with a trailing
+VLA).
+
+C++ reference types (int &x ).
+
+Alternate GCC keywords with '__ ', e.g.
+__const__ .
+
+GCC __attribute__ with the following attributes:
+aligned , packed , mode ,
+vector_size , cdecl , fastcall ,
+stdcall , thiscall .
+
+The GCC __extension__ keyword and the GCC
+__alignof__ operator.
+
+GCC __asm__("symname") symbol name redirection for
+function declarations.
+
+MSVC keywords for fixed-length types: __int8 ,
+__int16 , __int32 and __int64 .
+
+MSVC __cdecl , __fastcall , __stdcall ,
+__thiscall , __ptr32 , __ptr64 ,
+__declspec(align(n)) and #pragma pack .
+
+All other GCC/MSVC-specific attributes are ignored.
+
+
+
+The following C types are predefined by the C parser (like
+a typedef , except re-declarations will be ignored):
+
+
+
+Vararg handling: va_list , __builtin_va_list ,
+__gnuc_va_list .
+
+From <stddef.h> : ptrdiff_t ,
+size_t , wchar_t .
+
+From <stdint.h> : int8_t , int16_t ,
+int32_t , int64_t , uint8_t ,
+uint16_t , uint32_t , uint64_t ,
+intptr_t , uintptr_t .
+
+From <unistd.h> (POSIX): ssize_t .
+
+
+
+You're encouraged to use these types in preference to
+compiler-specific extensions or target-dependent standard types.
+E.g. char differs in signedness and long differs in
+size, depending on the target architecture and platform ABI.
+
+
+The following C features are not supported:
+
+
+
+A declaration must always have a type specifier; it doesn't
+default to an int type.
+
+Old-style empty function declarations (K&R) are not allowed.
+All C functions must have a proper prototype declaration. A
+function declared without parameters (int foo(); ) is
+treated as a function taking zero arguments, like in C++.
+
+The long double C type is parsed correctly, but
+there's no support for the related conversions, accesses or arithmetic
+operations.
+
+Wide character strings and character literals are not
+supported.
+
+See below for features that are currently
+not implemented.
+
+
+
+
C Type Conversion Rules
+
+
Conversions from C types to Lua objects
+
+These conversion rules apply for read accesses to
+C types: indexing pointers, arrays or
+struct /union types; reading external variables or
+constant values; retrieving return values from C calls:
+
+
+
+Input
+Conversion
+Output
+
+
+int8_t , int16_t →sign-ext int32_t → double number
+
+uint8_t , uint16_t →zero-ext int32_t → double number
+
+int32_t , uint32_t → double number
+
+int64_t , uint64_t boxed value 64 bit int cdata
+
+double , float → double number
+
+bool 0 → false , otherwise true boolean
+
+enum boxed value enum cdata
+
+Complex number boxed value complex cdata
+
+Vector boxed value vector cdata
+
+Pointer boxed value pointer cdata
+
+Array boxed reference reference cdata
+
+struct /union boxed reference reference cdata
+
+
+Bitfields are treated like their underlying type.
+
+
+Reference types are dereferenced before a conversion can take
+place — the conversion is applied to the C type pointed to
+by the reference.
+
+
+
Conversions from Lua objects to C types
+
+These conversion rules apply for write accesses to
+C types: indexing pointers, arrays or
+struct /union types; initializing cdata objects;
+casts to C types; writing to external variables; passing
+arguments to C calls:
+
+
+
+Input
+Conversion
+Output
+
+
+number → double
+
+boolean false → 0, true → 1bool
+
+nil NULL →(void *)
+
+lightuserdata lightuserdata address → (void *)
+
+userdata userdata payload → (void *)
+
+io.* file get FILE * handle → (void *)
+
+string match against enum constant enum
+
+string copy string data + zero-byte int8_t[] , uint8_t[]
+
+string string data → const char[]
+
+function create callback →C function type
+
+table table initializer Array
+
+table table initializer struct /union
+
+cdata cdata payload → C type
+
+
+If the result type of this conversion doesn't match the
+C type of the destination, the
+conversion rules between C types
+are applied.
+
+
+Reference types are immutable after initialization ("no re-seating of
+references"). For initialization purposes or when passing values to
+reference parameters, they are treated like pointers. Note that unlike
+in C++, there's no way to implement automatic reference generation of
+variables under the Lua language semantics. If you want to call a
+function with a reference parameter, you need to explicitly pass a
+one-element array.
+
+
+
Conversions between C types
+
+These conversion rules are more or less the same as the standard
+C conversion rules. Some rules only apply to casts, or require
+pointer or type compatibility:
+
+
+
+Input
+Conversion
+Output
+
+
+Signed integer →narrow or sign-extend Integer
+
+Unsigned integer →narrow or zero-extend Integer
+
+Integer →round double , float
+
+double , float →trunc int32_t →narrow (u)int8_t , (u)int16_t
+
+double , float →trunc (u)int32_t , (u)int64_t
+
+double , float →round float , double
+
+Number n == 0 → 0, otherwise 1 bool
+
+bool false → 0, true → 1Number
+
+Complex number convert real part Number
+
+Number convert real part, imag = 0 Complex number
+
+Complex number convert real and imag part Complex number
+
+Number convert scalar and replicate Vector
+
+Vector copy (same size) Vector
+
+struct /union take base address (compat) Pointer
+
+Array take base address (compat) Pointer
+
+Function take function address Function pointer
+
+Number convert via uintptr_t (cast) Pointer
+
+Pointer convert address (compat/cast) Pointer
+
+Pointer convert address (cast) Integer
+
+Array convert base address (cast) Integer
+
+Array copy (compat) Array
+
+struct /union copy (identical type) struct /union
+
+
+Bitfields or enum types are treated like their underlying
+type.
+
+
+Conversions not listed above will raise an error. E.g. it's not
+possible to convert a pointer to a complex number or vice versa.
+
+
+
Conversions for vararg C function arguments
+
+The following default conversion rules apply when passing Lua objects
+to the variable argument part of vararg C functions:
+
+
+
+Input
+Conversion
+Output
+
+
+number → double
+
+boolean false → 0, true → 1bool
+
+nil NULL →(void *)
+
+userdata userdata payload → (void *)
+
+lightuserdata lightuserdata address → (void *)
+
+string string data → const char *
+
+float cdata→ double
+
+Array cdata take base address Element pointer
+
+struct /union cdatatake base address struct /union pointer
+
+Function cdata take function address Function pointer
+
+Any other cdata no conversion C type
+
+
+To pass a Lua object, other than a cdata object, as a specific type,
+you need to override the conversion rules: create a temporary cdata
+object with a constructor or a cast and initialize it with the value
+to pass:
+
+
+Assuming x is a Lua number, here's how to pass it as an
+integer to a vararg function:
+
+
+ffi.cdef[[
+int printf(const char *fmt, ...);
+]]
+ffi.C.printf("integer value: %d\n", ffi.new("int", x))
+
+
+If you don't do this, the default Lua number → double
+conversion rule applies. A vararg C function expecting an integer
+will see a garbled or uninitialized value.
+
+
+Note: this is the only place where creating a boxed scalar number type is
+actually useful. Never use ffi.new("int") , ffi.new("float")
+etc. anywhere else!
+
+
+Ditto for ffi.cast() . Explicitly boxing scalars does not
+improve performance or force int or float arithmetic! It
+just adds costly boxing, unboxing and conversions steps. And it may lead
+to surprise results, because
+cdata arithmetic on scalar numbers
+is always performed on 64 bit integers.
+
+
+
Initializers
+
+Creating a cdata object with
+ffi.new() or the
+equivalent constructor syntax always initializes its contents, too.
+Different rules apply, depending on the number of optional
+initializers and the C types involved:
+
+
+If no initializers are given, the object is filled with zero bytes.
+
+Scalar types (numbers and pointers) accept a single initializer.
+The Lua object is converted to the scalar
+C type .
+
+Valarrays (complex numbers and vectors) are treated like scalars
+when a single initializer is given. Otherwise they are treated like
+regular arrays.
+
+Aggregate types (arrays and structs) accept either a single cdata
+initializer of the same type (copy constructor), a single
+table initializer , or a flat list of
+initializers.
+
+The elements of an array are initialized, starting at index zero.
+If a single initializer is given for an array, it's repeated for all
+remaining elements. This doesn't happen if two or more initializers
+are given: all remaining uninitialized elements are filled with zero
+bytes.
+
+Byte arrays may also be initialized with a Lua string. This copies
+the whole string plus a terminating zero-byte. The copy stops early only
+if the array has a known, fixed size.
+
+The fields of a struct are initialized in the order of
+their declaration. Uninitialized fields are filled with zero
+bytes.
+
+Only the first field of a union can be initialized with a
+flat initializer.
+
+Elements or fields which are aggregates themselves are initialized
+with a single initializer, but this may be a table
+initializer or a compatible aggregate.
+
+Excess initializers cause an error.
+
+
+
+
Table Initializers
+
+The following rules apply if a Lua table is used to initialize an
+Array or a struct /union :
+
+
+
+If the table index [0] is non-nil , then the
+table is assumed to be zero-based. Otherwise it's assumed to be
+one-based.
+
+Array elements, starting at index zero, are initialized one-by-one
+with the consecutive table elements, starting at either index
+[0] or [1] . This process stops at the first
+nil table element.
+
+If exactly one array element was initialized, it's repeated for
+all the remaining elements. Otherwise all remaining uninitialized
+elements are filled with zero bytes.
+
+The above logic only applies to arrays with a known fixed size.
+A VLA is only initialized with the element(s) given in the table.
+Depending on the use case, you may need to explicitly add a
+NULL or 0 terminator to a VLA.
+
+A struct /union can be initialized in the
+order of the declaration of its fields. Each field is initialized with
+consecutive table elements, starting at either index [0]
+or [1] . This process stops at the first nil table
+element.
+
+Otherwise, if neither index [0] nor [1] is present,
+a struct /union is initialized by looking up each field
+name (as a string key) in the table. Each non-nil value is
+used to initialize the corresponding field.
+
+Uninitialized fields of a struct are filled with zero
+bytes, except for the trailing VLA of a VLS.
+
+Initialization of a union stops after one field has been
+initialized. If no field has been initialized, the union is
+filled with zero bytes.
+
+Elements or fields which are aggregates themselves are initialized
+with a single initializer, but this may be a nested table
+initializer (or a compatible aggregate).
+
+Excess initializers for an array cause an error. Excess
+initializers for a struct /union are ignored.
+Unrelated table entries are ignored, too.
+
+
+
+Example:
+
+
+local ffi = require("ffi")
+
+ffi.cdef[[
+struct foo { int a, b; };
+union bar { int i; double d; };
+struct nested { int x; struct foo y; };
+]]
+
+ffi.new("int[3]", {}) --> 0, 0, 0
+ffi.new("int[3]", {1}) --> 1, 1, 1
+ffi.new("int[3]", {1,2}) --> 1, 2, 0
+ffi.new("int[3]", {1,2,3}) --> 1, 2, 3
+ffi.new("int[3]", {[0]=1}) --> 1, 1, 1
+ffi.new("int[3]", {[0]=1,2}) --> 1, 2, 0
+ffi.new("int[3]", {[0]=1,2,3}) --> 1, 2, 3
+ffi.new("int[3]", {[0]=1,2,3,4}) --> error: too many initializers
+
+ffi.new("struct foo", {}) --> a = 0, b = 0
+ffi.new("struct foo", {1}) --> a = 1, b = 0
+ffi.new("struct foo", {1,2}) --> a = 1, b = 2
+ffi.new("struct foo", {[0]=1,2}) --> a = 1, b = 2
+ffi.new("struct foo", {b=2}) --> a = 0, b = 2
+ffi.new("struct foo", {a=1,b=2,c=3}) --> a = 1, b = 2 'c' is ignored
+
+ffi.new("union bar", {}) --> i = 0, d = 0.0
+ffi.new("union bar", {1}) --> i = 1, d = ?
+ffi.new("union bar", {[0]=1,2}) --> i = 1, d = ? '2' is ignored
+ffi.new("union bar", {d=2}) --> i = ?, d = 2.0
+
+ffi.new("struct nested", {1,{2,3}}) --> x = 1, y.a = 2, y.b = 3
+ffi.new("struct nested", {x=1,y={2,3}}) --> x = 1, y.a = 2, y.b = 3
+
+
+
Operations on cdata Objects
+
+All standard Lua operators can be applied to cdata objects or a
+mix of a cdata object and another Lua object. The following list shows
+the predefined operations.
+
+
+Reference types are dereferenced before performing each of
+the operations below — the operation is applied to the
+C type pointed to by the reference.
+
+
+The predefined operations are always tried first before deferring to a
+metamethod or index table (if any) for the corresponding ctype (except
+for __new ). An error is raised if the metamethod lookup or
+index table lookup fails.
+
+
+
Indexing a cdata object
+
+
+Indexing a pointer/array : a cdata pointer/array can be
+indexed by a cdata number or a Lua number. The element address is
+computed as the base address plus the number value multiplied by the
+element size in bytes. A read access loads the element value and
+converts it to a Lua object . A write
+access converts a Lua object to the element
+type and stores the converted value to the element. An error is
+raised if the element size is undefined or a write access to a
+constant element is attempted.
+
+Dereferencing a struct /union field : a
+cdata struct /union or a pointer to a
+struct /union can be dereferenced by a string key,
+giving the field name. The field address is computed as the base
+address plus the relative offset of the field. A read access loads the
+field value and converts it to a Lua
+object . A write access converts a Lua
+object to the field type and stores the converted value to the
+field. An error is raised if a write access to a constant
+struct /union or a constant field is attempted.
+Scoped enum constants or static constants are treated like a constant
+field.
+
+Indexing a complex number : a complex number can be indexed
+either by a cdata number or a Lua number with the values 0 or 1, or by
+the strings "re" or "im" . A read access loads the
+real part ([0] , .re ) or the imaginary part
+([1] , .im ) part of a complex number and
+converts it to a Lua number . The
+sub-parts of a complex number are immutable — assigning to an
+index of a complex number raises an error. Accessing out-of-bound
+indexes returns unspecified results, but is guaranteed not to trigger
+memory access violations.
+
+Indexing a vector : a vector is treated like an array for
+indexing purposes, except the vector elements are immutable —
+assigning to an index of a vector raises an error.
+
+
+
+A ctype object can be indexed with a string key, too. The only
+predefined operation is reading scoped constants of
+struct /union types. All other accesses defer
+to the corresponding metamethods or index tables (if any).
+
+
+Note: since there's (deliberately) no address-of operator, a cdata
+object holding a value type is effectively immutable after
+initialization. The JIT compiler benefits from this fact when applying
+certain optimizations.
+
+
+As a consequence, the elements of complex numbers and
+vectors are immutable. But the elements of an aggregate holding these
+types may be modified, of course. I.e. you cannot assign to
+foo.c.im , but you can assign a (newly created) complex number
+to foo.c .
+
+
+The JIT compiler implements strict aliasing rules: accesses to different
+types do not alias, except for differences in signedness (this
+applies even to char pointers, unlike C99). Type punning
+through unions is explicitly detected and allowed.
+
+
+
Calling a cdata object
+
+
+Constructor : a ctype object can be called and used as a
+constructor . This is equivalent
+to ffi.new(ct, ...) , unless a __new metamethod is
+defined. The __new metamethod is called with the ctype object
+plus any other arguments passed to the constructor. Note that you have to
+use ffi.new inside the metamethod, since calling ct(...)
+would cause infinite recursion.
+
+C function call : a cdata function or cdata function
+pointer can be called. The passed arguments are
+converted to the C types of the
+parameters given by the function declaration. Arguments passed to the
+variable argument part of vararg C function use
+special conversion rules . This
+C function is called and the return value (if any) is
+converted to a Lua object .
+On Windows/x86 systems, __stdcall functions are automatically
+detected, and a function declared as __cdecl (the default) is
+silently fixed up after the first call.
+
+
+
+
Arithmetic on cdata objects
+
+
+Pointer arithmetic : a cdata pointer/array and a cdata
+number or a Lua number can be added or subtracted. The number must be
+on the right-hand side for a subtraction. The result is a pointer of
+the same type with an address plus or minus the number value
+multiplied by the element size in bytes. An error is raised if the
+element size is undefined.
+
+Pointer difference : two compatible cdata pointers/arrays
+can be subtracted. The result is the difference between their
+addresses, divided by the element size in bytes. An error is raised if
+the element size is undefined or zero.
+
+64 bit integer arithmetic : the standard arithmetic
+operators (+ - * / % ^ and unary
+minus) can be applied to two cdata numbers, or a cdata number and a
+Lua number. If one of them is an uint64_t , the other side is
+converted to an uint64_t and an unsigned arithmetic operation
+is performed. Otherwise, both sides are converted to an
+int64_t and a signed arithmetic operation is performed. The
+result is a boxed 64 bit cdata object.
+
+If one of the operands is an enum and the other operand is a
+string, the string is converted to the value of a matching enum
+constant before the above conversion.
+
+These rules ensure that 64 bit integers are "sticky". Any
+expression involving at least one 64 bit integer operand results
+in another one. The undefined cases for the division, modulo and power
+operators return 2LL ^ 63 or
+2ULL ^ 63 .
+
+You'll have to explicitly convert a 64 bit integer to a Lua
+number (e.g. for regular floating-point calculations) with
+tonumber() . But note this may incur a precision loss.
+
+64 bit bitwise operations : the rules for 64 bit
+arithmetic operators apply analogously.
+
+Unlike the other bit.* operations, bit.tobit()
+converts a cdata number via int64_t to int32_t and
+returns a Lua number.
+
+For bit.band() , bit.bor() and bit.bxor() , the
+conversion to int64_t or uint64_t applies to
+all arguments, if any argument is a cdata number.
+
+For all other operations, only the first argument is used to determine
+the output type. This implies that a cdata number as a shift count for
+shifts and rotates is accepted, but that alone does not cause
+a cdata number output.
+
+
+
+
Comparisons of cdata objects
+
+
+Pointer comparison : two compatible cdata pointers/arrays
+can be compared. The result is the same as an unsigned comparison of
+their addresses. nil is treated like a NULL pointer,
+which is compatible with any other pointer type.
+
+64 bit integer comparison : two cdata numbers, or a
+cdata number and a Lua number can be compared with each other. If one
+of them is an uint64_t , the other side is converted to an
+uint64_t and an unsigned comparison is performed. Otherwise,
+both sides are converted to an int64_t and a signed
+comparison is performed.
+
+If one of the operands is an enum and the other operand is a
+string, the string is converted to the value of a matching enum
+constant before the above conversion.
+
+Comparisons for equality/inequality never raise an error.
+Even incompatible pointers can be compared for equality by address. Any
+other incompatible comparison (also with non-cdata objects) treats the
+two sides as unequal.
+
+
+
+
cdata objects as table keys
+
+Lua tables may be indexed by cdata objects, but this doesn't provide
+any useful semantics — cdata objects are unsuitable as table
+keys!
+
+
+A cdata object is treated like any other garbage-collected object and
+is hashed and compared by its address for table indexing. Since
+there's no interning for cdata value types, the same value may be
+boxed in different cdata objects with different addresses. Thus,
+t[1LL+1LL] and t[2LL] usually do not point to
+the same hash slot, and they certainly do not point to the same
+hash slot as t[2] .
+
+
+It would seriously drive up implementation complexity and slow down
+the common case, if one were to add extra handling for by-value
+hashing and comparisons to Lua tables. Given the ubiquity of their use
+inside the VM, this is not acceptable.
+
+
+There are three viable alternatives, if you really need to use cdata
+objects as keys:
+
+
+
+If you can get by with the precision of Lua numbers
+(52 bits), then use tonumber() on a cdata number or
+combine multiple fields of a cdata aggregate to a Lua number. Then use
+the resulting Lua number as a key when indexing tables.
+One obvious benefit: t[tonumber(2LL)] does point to
+the same slot as t[2] .
+
+Otherwise, use either tostring() on 64 bit integers
+or complex numbers or combine multiple fields of a cdata aggregate to
+a Lua string (e.g. with
+ffi.string() ). Then
+use the resulting Lua string as a key when indexing tables.
+
+Create your own specialized hash table implementation using the
+C types provided by the FFI library, just like you would in
+C code. Ultimately, this may give much better performance than the
+other alternatives or what a generic by-value hash table could
+possibly provide.
+
+
+
+
Parameterized Types
+
+To facilitate some abstractions, the two functions
+ffi.typeof and
+ffi.cdef support
+parameterized types in C declarations. Note: none of the other API
+functions taking a cdecl allow this.
+
+
+Any place you can write a typedef name , an
+identifier or a number in a declaration, you can write
+$ (the dollar sign) instead. These placeholders are replaced in
+order of appearance with the arguments following the cdecl string:
+
+
+-- Declare a struct with a parameterized field type and name:
+ffi.cdef([[
+typedef struct { $ $; } foo_t;
+]], type1, name1)
+
+-- Anonymous struct with dynamic names:
+local bar_t = ffi.typeof("struct { int $, $; }", name1, name2)
+-- Derived pointer type:
+local bar_ptr_t = ffi.typeof("$ *", bar_t)
+
+-- Parameterized dimensions work even where a VLA won't work:
+local matrix_t = ffi.typeof("uint8_t[$][$]", width, height)
+
+
+Caveat: this is not simple text substitution! A passed ctype or
+cdata object is treated like the underlying type, a passed string is
+considered an identifier and a number is considered a number. You must
+not mix this up: e.g. passing "int" as a string doesn't work in
+place of a type, you'd need to use ffi.typeof("int") instead.
+
+
+The main use for parameterized types are libraries implementing abstract
+data types
+(» example ),
+similar to what can be achieved with C++ template metaprogramming.
+Another use case are derived types of anonymous structs, which avoids
+pollution of the global struct namespace.
+
+
+Please note that parameterized types are a nice tool and indispensable
+for certain use cases. But you'll want to use them sparingly in regular
+code, e.g. when all types are actually fixed.
+
+
+
Garbage Collection of cdata Objects
+
+All explicitly (ffi.new() , ffi.cast() etc.) or
+implicitly (accessors) created cdata objects are garbage collected.
+You need to ensure to retain valid references to cdata objects
+somewhere on a Lua stack, an upvalue or in a Lua table while they are
+still in use. Once the last reference to a cdata object is gone, the
+garbage collector will automatically free the memory used by it (at
+the end of the next GC cycle).
+
+
+Please note, that pointers themselves are cdata objects, however they
+are not followed by the garbage collector. So e.g. if you
+assign a cdata array to a pointer, you must keep the cdata object
+holding the array alive as long as the pointer is still in use:
+
+
+ffi.cdef[[
+typedef struct { int *a; } foo_t;
+]]
+
+local s = ffi.new("foo_t", ffi.new("int[10]")) -- WRONG!
+
+local a = ffi.new("int[10]") -- OK
+local s = ffi.new("foo_t", a)
+-- Now do something with 's', but keep 'a' alive until you're done.
+
+
+Similar rules apply for Lua strings which are implicitly converted to
+"const char *" : the string object itself must be
+referenced somewhere or it'll be garbage collected eventually. The
+pointer will then point to stale data, which may have already been
+overwritten. Note that string literals are automatically kept
+alive as long as the function containing it (actually its prototype)
+is not garbage collected.
+
+
+Objects which are passed as an argument to an external C function
+are kept alive until the call returns. So it's generally safe to
+create temporary cdata objects in argument lists. This is a common
+idiom for passing specific C types to
+vararg functions .
+
+
+Memory areas returned by C functions (e.g. from malloc() )
+must be manually managed, of course (or use
+ffi.gc() ). Pointers to
+cdata objects are indistinguishable from pointers returned by C
+functions (which is one of the reasons why the GC cannot follow them).
+
+
+
Callbacks
+
+The LuaJIT FFI automatically generates special callback functions
+whenever a Lua function is converted to a C function pointer. This
+associates the generated callback function pointer with the C type
+of the function pointer and the Lua function object (closure).
+
+
+This can happen implicitly due to the usual conversions, e.g. when
+passing a Lua function to a function pointer argument. Or, you can use
+ffi.cast() to explicitly cast a Lua function to a
+C function pointer.
+
+
+Currently, only certain C function types can be used as callback
+functions. Neither C vararg functions nor functions with
+pass-by-value aggregate argument or result types are supported. There
+are no restrictions on the kind of Lua functions that can be called
+from the callback — no checks for the proper number of arguments
+are made. The return value of the Lua function will be converted to the
+result type, and an error will be thrown for invalid conversions.
+
+
+It's allowed to throw errors across a callback invocation, but it's not
+advisable in general. Do this only if you know the C function, that
+called the callback, copes with the forced stack unwinding and doesn't
+leak resources.
+
+
+One thing that's not allowed, is to let an FFI call into a C function
+get JIT-compiled, which in turn calls a callback, calling into Lua again.
+Usually this attempt is caught by the interpreter first and the
+C function is blacklisted for compilation.
+
+
+However, this heuristic may fail under specific circumstances: e.g. a
+message polling function might not run Lua callbacks right away and the call
+gets JIT-compiled. If it later happens to call back into Lua (e.g. a rarely
+invoked error callback), you'll get a VM PANIC with the message
+"bad callback" . Then you'll need to manually turn off
+JIT-compilation with
+jit.off() for the
+surrounding Lua function that invokes such a message polling function (or
+similar).
+
+
+
Callback resource handling
+
+Callbacks take up resources — you can only have a limited number
+of them at the same time (500 - 1000, depending on the
+architecture). The associated Lua functions are anchored to prevent
+garbage collection, too.
+
+
+Callbacks due to implicit conversions are permanent! There is no
+way to guess their lifetime, since the C side might store the
+function pointer for later use (typical for GUI toolkits). The associated
+resources cannot be reclaimed until termination:
+
+
+ffi.cdef[[
+typedef int (__stdcall *WNDENUMPROC)(void *hwnd, intptr_t l);
+int EnumWindows(WNDENUMPROC func, intptr_t l);
+]]
+
+-- Implicit conversion to a callback via function pointer argument.
+local count = 0
+ffi.C.EnumWindows(function(hwnd, l)
+ count = count + 1
+ return true
+end, 0)
+-- The callback is permanent and its resources cannot be reclaimed!
+-- Ok, so this may not be a problem, if you do this only once.
+
+
+Note: this example shows that you must properly declare
+__stdcall callbacks on Windows/x86 systems. The calling
+convention cannot be automatically detected, unlike for
+__stdcall calls to Windows functions.
+
+
+For some use cases, it's necessary to free up the resources or to
+dynamically redirect callbacks. Use an explicit cast to a
+C function pointer and keep the resulting cdata object. Then use
+the cb:free()
+or cb:set() methods
+on the cdata object:
+
+
+-- Explicitly convert to a callback via cast.
+local count = 0
+local cb = ffi.cast("WNDENUMPROC", function(hwnd, l)
+ count = count + 1
+ return true
+end)
+
+-- Pass it to a C function.
+ffi.C.EnumWindows(cb, 0)
+-- EnumWindows doesn't need the callback after it returns, so free it.
+
+cb:free()
+-- The callback function pointer is no longer valid and its resources
+-- will be reclaimed. The created Lua closure will be garbage collected.
+
+
+
+
+Callbacks are slow! First, the C to Lua transition itself
+has an unavoidable cost, similar to a lua_call() or
+lua_pcall() . Argument and result marshalling add to that cost.
+And finally, neither the C compiler nor LuaJIT can inline or
+optimize across the language barrier and hoist repeated computations out
+of a callback function.
+
+
+Do not use callbacks for performance-sensitive work: e.g. consider a
+numerical integration routine which takes a user-defined function to
+integrate over. It's a bad idea to call a user-defined Lua function from
+C code millions of times. The callback overhead will be absolutely
+detrimental for performance.
+
+
+It's considerably faster to write the numerical integration routine
+itself in Lua — the JIT compiler will be able to inline the
+user-defined function and optimize it together with its calling context,
+with very competitive performance.
+
+
+As a general guideline: use callbacks only when you must , because
+of existing C APIs. E.g. callback performance is irrelevant for a
+GUI application, which waits for user input most of the time, anyway.
+
+
+For new designs avoid push-style APIs : a C function repeatedly
+calling a callback for each result. Instead, use pull-style APIs :
+call a C function repeatedly to get a new result. Calls from Lua
+to C via the FFI are much faster than the other way round. Most well-designed
+libraries already use pull-style APIs (read/write, get/put).
+
+
+
C Library Namespaces
+
+A C library namespace is a special kind of object which allows
+access to the symbols contained in shared libraries or the default
+symbol namespace. The default
+ffi.C namespace is
+automatically created when the FFI library is loaded. C library
+namespaces for specific shared libraries may be created with the
+ffi.load() API
+function.
+
+
+Indexing a C library namespace object with a symbol name (a Lua
+string) automatically binds it to the library. First, the symbol type
+is resolved — it must have been declared with
+ffi.cdef . Then the
+symbol address is resolved by searching for the symbol name in the
+associated shared libraries or the default symbol namespace. Finally,
+the resulting binding between the symbol name, the symbol type and its
+address is cached. Missing symbol declarations or nonexistent symbol
+names cause an error.
+
+
+This is what happens on a read access for the different kinds of
+symbols:
+
+
+
+External functions: a cdata object with the type of the function
+and its address is returned.
+
+External variables: the symbol address is dereferenced and the
+loaded value is converted to a Lua object
+and returned.
+
+Constant values (static const or enum
+constants): the constant is converted to a
+Lua object and returned.
+
+
+
+This is what happens on a write access :
+
+
+
+External variables: the value to be written is
+converted to the C type of the
+variable and then stored at the symbol address.
+
+Writing to constant variables or to any other symbol type causes
+an error, like any other attempted write to a constant location.
+
+
+
+C library namespaces themselves are garbage collected objects. If
+the last reference to the namespace object is gone, the garbage
+collector will eventually release the shared library reference and
+remove all memory associated with the namespace. Since this may
+trigger the removal of the shared library from the memory of the
+running process, it's generally not safe to use function
+cdata objects obtained from a library if the namespace object may be
+unreferenced.
+
+
+Performance notice: the JIT compiler specializes to the identity of
+namespace objects and to the strings used to index it. This
+effectively turns function cdata objects into constants. It's not
+useful and actually counter-productive to explicitly cache these
+function objects, e.g. local strlen = ffi.C.strlen . OTOH, it
+is useful to cache the namespace itself, e.g. local C =
+ffi.C .
+
+
+
No Hand-holding!
+
+The FFI library has been designed as a low-level library . The
+goal is to interface with C code and C data types with a
+minimum of overhead. This means you can do anything you can do
+from C : access all memory, overwrite anything in memory, call
+machine code at any memory address and so on.
+
+
+The FFI library provides no memory safety , unlike regular Lua
+code. It will happily allow you to dereference a NULL
+pointer, to access arrays out of bounds or to misdeclare
+C functions. If you make a mistake, your application might crash,
+just like equivalent C code would.
+
+
+This behavior is inevitable, since the goal is to provide full
+interoperability with C code. Adding extra safety measures, like
+bounds checks, would be futile. There's no way to detect
+misdeclarations of C functions, since shared libraries only
+provide symbol names, but no type information. Likewise, there's no way
+to infer the valid range of indexes for a returned pointer.
+
+
+Again: the FFI library is a low-level library. This implies it needs
+to be used with care, but it's flexibility and performance often
+outweigh this concern. If you're a C or C++ developer, it'll be easy
+to apply your existing knowledge. OTOH, writing code for the FFI
+library is not for the faint of heart and probably shouldn't be the
+first exercise for someone with little experience in Lua, C or C++.
+
+
+As a corollary of the above, the FFI library is not safe for use by
+untrusted Lua code . If you're sandboxing untrusted Lua code, you
+definitely don't want to give this code access to the FFI library or
+to any cdata object (except 64 bit integers or complex
+numbers). Any properly engineered Lua sandbox needs to provide safety
+wrappers for many of the standard Lua library functions —
+similar wrappers need to be written for high-level operations on FFI
+data types, too.
+
+
+
Current Status
+
+The initial release of the FFI library has some limitations and is
+missing some features. Most of these will be fixed in future releases.
+
+
+C language support is
+currently incomplete:
+
+
+C declarations are not passed through a C pre-processor,
+yet.
+The C parser is able to evaluate most constant expressions
+commonly found in C header files. However, it doesn't handle the
+full range of C expression semantics and may fail for some
+obscure constructs.
+static const declarations only work for integer types
+up to 32 bits. Neither declaring string constants nor
+floating-point constants is supported.
+Packed struct bitfields that cross container boundaries
+are not implemented.
+Native vector types may be defined with the GCC mode or
+vector_size attribute. But no operations other than loading,
+storing and initializing them are supported, yet.
+The volatile type qualifier is currently ignored by
+compiled code.
+ffi.cdef silently
+ignores most re-declarations. Note: avoid re-declarations which do not
+conform to C99. The implementation will eventually be changed to
+perform strict checks.
+
+
+The JIT compiler already handles a large subset of all FFI operations.
+It automatically falls back to the interpreter for unimplemented
+operations (you can check for this with the
+-jv command line option).
+The following operations are currently not compiled and may exhibit
+suboptimal performance, especially when used in inner loops:
+
+
+Vector operations.
+Table initializers.
+Initialization of nested struct /union types.
+Non-default initialization of VLA/VLS or large C types
+(> 128 bytes or > 16 array elements).
+Bitfield initializations.
+Pointer differences for element sizes that are not a power of
+two.
+Calls to C functions with aggregates passed or returned by
+value.
+Calls to ctype metamethods which are not plain functions.
+ctype __newindex tables and non-string lookups in ctype
+__index tables.
+tostring() for cdata types.
+Calls to ffi.cdef() , ffi.load() and
+ffi.metatype() .
+
+
+Other missing features:
+
+
+Arithmetic for complex numbers.
+Passing structs by value to vararg C functions.
+C++ exception interoperability
+does not extend to C functions called via the FFI, if the call is
+compiled.
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/ext_ffi_tutorial.html b/LuaJIT-2.1/doc/ext_ffi_tutorial.html
new file mode 100644
index 00000000..5ea55a74
--- /dev/null
+++ b/LuaJIT-2.1/doc/ext_ffi_tutorial.html
@@ -0,0 +1,597 @@
+
+
+
+FFI Tutorial
+
+
+
+
+
+
+
+
+
+
+
FFI Tutorial
+
+
+
+
+This page is intended to give you an overview of the features of the FFI
+library by presenting a few use cases and guidelines.
+
+
+This page makes no attempt to explain all of the FFI library, though.
+You'll want to have a look at the ffi.* API
+function reference and the FFI
+semantics to learn more.
+
+
+
Loading the FFI Library
+
+The FFI library is built into LuaJIT by default, but it's not loaded
+and initialized by default. The suggested way to use the FFI library
+is to add the following to the start of every Lua file that needs one
+of its functions:
+
+
+local ffi = require("ffi")
+
+
+Please note, this doesn't define an ffi variable in the table
+of globals — you really need to use the local variable. The
+require function ensures the library is only loaded once.
+
+
+Note: If you want to experiment with the FFI from the interactive prompt
+of the command line executable, omit the local , as it doesn't
+preserve local variables across lines.
+
+
+
Accessing Standard System Functions
+
+The following code explains how to access standard system functions.
+We slowly print two lines of dots by sleeping for 10 milliseconds
+after each dot:
+
+
+
+①
+
+
+
+
+
+②
+③
+④
+
+
+
+⑤
+
+
+
+
+
+⑥ local ffi = require("ffi")
+ffi.cdef[[
+void Sleep(int ms);
+int poll(struct pollfd *fds, unsigned long nfds, int timeout);
+]]
+
+local sleep
+if ffi.os == "Windows" then
+ function sleep(s)
+ ffi.C.Sleep(s*1000)
+ end
+else
+ function sleep(s)
+ ffi.C.poll(nil, 0, s*1000)
+ end
+end
+
+for i=1,160 do
+ io.write("."); io.flush()
+ sleep(0.01)
+end
+io.write("\n")
+
+
+Here's the step-by-step explanation:
+
+
+① This defines the
+C library functions we're going to use. The part inside the
+double-brackets (in green) is just standard C syntax. You can
+usually get this info from the C header files or the
+documentation provided by each C library or C compiler.
+
+
+② The difficulty we're
+facing here, is that there are different standards to choose from.
+Windows has a simple Sleep() function. On other systems there
+are a variety of functions available to achieve sub-second sleeps, but
+with no clear consensus. Thankfully poll() can be used for
+this task, too, and it's present on most non-Windows systems. The
+check for ffi.os makes sure we use the Windows-specific
+function only on Windows systems.
+
+
+③ Here we're wrapping the
+call to the C function in a Lua function. This isn't strictly
+necessary, but it's helpful to deal with system-specific issues only
+in one part of the code. The way we're wrapping it ensures the check
+for the OS is only done during initialization and not for every call.
+
+
+④ A more subtle point is
+that we defined our sleep() function (for the sake of this
+example) as taking the number of seconds, but accepting fractional
+seconds. Multiplying this by 1000 gets us milliseconds, but that still
+leaves it a Lua number, which is a floating-point value. Alas, the
+Sleep() function only accepts an integer value. Luckily for
+us, the FFI library automatically performs the conversion when calling
+the function (truncating the FP value towards zero, like in C).
+
+
+Some readers will notice that Sleep() is part of
+KERNEL32.DLL and is also a stdcall function. So how
+can this possibly work? The FFI library provides the ffi.C
+default C library namespace, which allows calling functions from
+the default set of libraries, like a C compiler would. Also, the
+FFI library automatically detects stdcall functions, so you
+don't need to declare them as such.
+
+
+⑤ The poll()
+function takes a couple more arguments we're not going to use. You can
+simply use nil to pass a NULL pointer and 0
+for the nfds parameter. Please note, that the
+number 0 does not convert to a pointer value ,
+unlike in C++. You really have to pass pointers to pointer arguments
+and numbers to number arguments.
+
+
+The page on FFI semantics has all
+of the gory details about
+conversions between Lua
+objects and C types . For the most part you don't have to deal
+with this, as it's performed automatically and it's carefully designed
+to bridge the semantic differences between Lua and C.
+
+
+⑥ Now that we have defined
+our own sleep() function, we can just call it from plain Lua
+code. That wasn't so bad, huh? Turning these boring animated dots into
+a fascinating best-selling game is left as an exercise for the reader.
+:-)
+
+
+
Accessing the zlib Compression Library
+
+The following code shows how to access the » zlib compression library from Lua code.
+We'll define two convenience wrapper functions that take a string and
+compress or uncompress it to another string:
+
+
+
+①
+
+
+
+
+
+
+②
+
+
+③
+
+④
+
+
+⑤
+
+
+⑥
+
+
+
+
+
+
+
+⑦ local ffi = require("ffi")
+ffi.cdef[[
+unsigned long compressBound(unsigned long sourceLen);
+int compress2(uint8_t *dest, unsigned long *destLen,
+ const uint8_t *source, unsigned long sourceLen, int level);
+int uncompress(uint8_t *dest, unsigned long *destLen,
+ const uint8_t *source, unsigned long sourceLen);
+]]
+local zlib = ffi.load(ffi.os == "Windows" and "zlib1" or "z")
+
+local function compress(txt)
+ local n = zlib.compressBound(#txt)
+ local buf = ffi.new("uint8_t[?]", n)
+ local buflen = ffi.new("unsigned long[1]", n)
+ local res = zlib.compress2(buf, buflen, txt, #txt, 9)
+ assert(res == 0)
+ return ffi.string(buf, buflen[0])
+end
+
+local function uncompress(comp, n)
+ local buf = ffi.new("uint8_t[?]", n)
+ local buflen = ffi.new("unsigned long[1]", n)
+ local res = zlib.uncompress(buf, buflen, comp, #comp)
+ assert(res == 0)
+ return ffi.string(buf, buflen[0])
+end
+
+-- Simple test code.
+local txt = string.rep("abcd", 1000)
+print("Uncompressed size: ", #txt)
+local c = compress(txt)
+print("Compressed size: ", #c)
+local txt2 = uncompress(c, #txt)
+assert(txt2 == txt)
+
+
+Here's the step-by-step explanation:
+
+
+① This defines some of the
+C functions provided by zlib. For the sake of this example, some
+type indirections have been reduced and it uses the predefined
+fixed-size integer types, while still adhering to the zlib API/ABI.
+
+
+② This loads the zlib shared
+library. On POSIX systems, it's named libz.so and usually
+comes pre-installed. Since ffi.load() automatically adds any
+missing standard prefixes/suffixes, we can simply load the
+"z" library. On Windows it's named zlib1.dll and
+you'll have to download it first from the
+» zlib site . The check for
+ffi.os makes sure we pass the right name to
+ffi.load() .
+
+
+③ First, the maximum size of
+the compression buffer is obtained by calling the
+zlib.compressBound function with the length of the
+uncompressed string. The next line allocates a byte buffer of this
+size. The [?] in the type specification indicates a
+variable-length array (VLA). The actual number of elements of this
+array is given as the 2nd argument to ffi.new() .
+
+
+④ This may look strange at
+first, but have a look at the declaration of the compress2
+function from zlib: the destination length is defined as a pointer!
+This is because you pass in the maximum buffer size and get back the
+actual length that was used.
+
+
+In C you'd pass in the address of a local variable
+(&buflen ). But since there's no address-of operator in
+Lua, we'll just pass in a one-element array. Conveniently, it can be
+initialized with the maximum buffer size in one step. Calling the
+actual zlib.compress2 function is then straightforward.
+
+
+⑤ We want to return the
+compressed data as a Lua string, so we'll use ffi.string() .
+It needs a pointer to the start of the data and the actual length. The
+length has been returned in the buflen array, so we'll just
+get it from there.
+
+
+Note that since the function returns now, the buf and
+buflen variables will eventually be garbage collected. This
+is fine, because ffi.string() has copied the contents to a
+newly created (interned) Lua string. If you plan to call this function
+lots of times, consider reusing the buffers and/or handing back the
+results in buffers instead of strings. This will reduce the overhead
+for garbage collection and string interning.
+
+
+⑥ The uncompress
+functions does the exact opposite of the compress function.
+The compressed data doesn't include the size of the original string,
+so this needs to be passed in. Otherwise, no surprises here.
+
+
+⑦ The code, that makes use
+of the functions we just defined, is just plain Lua code. It doesn't
+need to know anything about the LuaJIT FFI — the convenience
+wrapper functions completely hide it.
+
+
+One major advantage of the LuaJIT FFI is that you are now able to
+write those wrappers in Lua . And at a fraction of the time it
+would cost you to create an extra C module using the Lua/C API.
+Many of the simpler C functions can probably be used directly
+from your Lua code, without any wrappers.
+
+
+Side note: the zlib API uses the long type for passing
+lengths and sizes around. But all those zlib functions actually only
+deal with 32 bit values. This is an unfortunate choice for a
+public API, but may be explained by zlib's history — we'll just
+have to deal with it.
+
+
+First, you should know that a long is a 64 bit type e.g.
+on POSIX/x64 systems, but a 32 bit type on Windows/x64 and on
+32 bit systems. Thus a long result can be either a plain
+Lua number or a boxed 64 bit integer cdata object, depending on
+the target system.
+
+
+Ok, so the ffi.* functions generally accept cdata objects
+wherever you'd want to use a number. That's why we get a away with
+passing n to ffi.string() above. But other Lua
+library functions or modules don't know how to deal with this. So for
+maximum portability, one needs to use tonumber() on returned
+long results before passing them on. Otherwise the
+application might work on some systems, but would fail in a POSIX/x64
+environment.
+
+
+
+
+The following code explains how to define metamethods for a C type.
+We define a simple point type and add some operations to it:
+
+
+
+①
+
+
+
+②
+
+③
+
+④
+
+
+
+⑤
+
+⑥ local ffi = require("ffi")
+ffi.cdef[[
+typedef struct { double x, y; } point_t;
+]]
+
+local point
+local mt = {
+ __add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
+ __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
+ __index = {
+ area = function(a) return a.x*a.x + a.y*a.y end,
+ },
+}
+point = ffi.metatype("point_t", mt)
+
+local a = point(3, 4)
+print(a.x, a.y) --> 3 4
+print(#a) --> 5
+print(a:area()) --> 25
+local b = a + point(0.5, 8)
+print(#b) --> 12.5
+
+
+Here's the step-by-step explanation:
+
+
+① This defines the C type for a
+two-dimensional point object.
+
+
+② We have to declare the variable
+holding the point constructor first, because it's used inside of a
+metamethod.
+
+
+③ Let's define an __add
+metamethod which adds the coordinates of two points and creates a new
+point object. For simplicity, this function assumes that both arguments
+are points. But it could be any mix of objects, if at least one operand
+is of the required type (e.g. adding a point plus a number or vice
+versa). Our __len metamethod returns the distance of a point to
+the origin.
+
+
+④ If we run out of operators, we can
+define named methods, too. Here, the __index table defines an
+area function. For custom indexing needs, one might want to
+define __index and __newindex functions instead.
+
+
+⑤ This associates the metamethods with
+our C type. This only needs to be done once. For convenience, a
+constructor is returned by
+ffi.metatype() .
+We're not required to use it, though. The original C type can still
+be used e.g. to create an array of points. The metamethods automatically
+apply to any and all uses of this type.
+
+
+Please note, that the association with a metatable is permanent and
+the metatable must not be modified afterwards! Ditto for the
+__index table.
+
+
+⑥ Here are some simple usage examples
+for the point type and their expected results. The predefined
+operations (such as a.x ) can be freely mixed with the newly
+defined metamethods. Note that area is a method and must be
+called with the Lua syntax for methods: a:area() , not
+a.area() .
+
+
+The C type metamethod mechanism is most useful when used in
+conjunction with C libraries that are written in an object-oriented
+style. Creators return a pointer to a new instance, and methods take an
+instance pointer as the first argument. Sometimes you can just point
+__index to the library namespace and __gc to the
+destructor and you're done. But often enough you'll want to add
+convenience wrappers, e.g. to return actual Lua strings or when
+returning multiple values.
+
+
+Some C libraries only declare instance pointers as an opaque
+void * type. In this case you can use a fake type for all
+declarations, e.g. a pointer to a named (incomplete) struct will do:
+typedef struct foo_type *foo_handle . The C side doesn't
+know what you declare with the LuaJIT FFI, but as long as the underlying
+types are compatible, everything still works.
+
+
+
Translating C Idioms
+
+Here's a list of common C idioms and their translation to the
+LuaJIT FFI:
+
+
+
+Idiom
+C code
+Lua code
+
+
+Pointer dereferenceint *p; x = *p; *p = y; x = p[0] p[0] = y
+
+Pointer indexingint i, *p; x = p[i]; p[i+1] = y; x = p[i] p[i+1] = y
+
+Array indexingint i, a[]; x = a[i]; a[i+1] = y; x = a[i] a[i+1] = y
+
+struct /union dereferencestruct foo s; x = s.field; s.field = y; x = s.field s.field = y
+
+struct /union pointer deref.struct foo *sp; x = sp->field; sp->field = y; x = s.field s.field = y
+
+Pointer arithmeticint i, *p; x = p + i; y = p - i; x = p + i y = p - i
+
+Pointer differenceint *p1, *p2; x = p1 - p2; x = p1 - p2
+
+Array element pointerint i, a[]; x = &a[i]; x = a+i
+
+Cast pointer to addressint *p; x = (intptr_t)p; x = tonumber( ffi.cast("intptr_t", p))
+
+Functions with outargsvoid foo(int *inoutlen); int len = x; foo(&len); y = len; local len = ffi.new("int[1]", x) foo(len) y = len[0]
+
+Vararg conversions int printf(char *fmt, ...); printf("%g", 1.0); printf("%d", 1); printf("%g", 1); printf("%d", ffi.new("int", 1) )
+
+
+
To Cache or Not to Cache
+
+It's a common Lua idiom to cache library functions in local variables
+or upvalues, e.g.:
+
+
+local byte, char = string.byte, string.char
+local function foo(x)
+ return char(byte(x)+1)
+end
+
+
+This replaces several hash-table lookups with a (faster) direct use of
+a local or an upvalue. This is less important with LuaJIT, since the
+JIT compiler optimizes hash-table lookups a lot and is even able to
+hoist most of them out of the inner loops. It can't eliminate
+all of them, though, and it saves some typing for often-used
+functions. So there's still a place for this, even with LuaJIT.
+
+
+The situation is a bit different with C function calls via the
+FFI library. The JIT compiler has special logic to eliminate all
+of the lookup overhead for functions resolved from a
+C library namespace !
+Thus it's not helpful and actually counter-productive to cache
+individual C functions like this:
+
+
+local funca , funcb = ffi.C.funca, ffi.C.funcb -- Not helpful!
+local function foo(x, n)
+ for i=1,n do funcb (funca (x, i), 1) end
+end
+
+
+This turns them into indirect calls and generates bigger and slower
+machine code. Instead, you'll want to cache the namespace itself and
+rely on the JIT compiler to eliminate the lookups:
+
+
+local C = ffi.C -- Instead use this!
+local function foo(x, n)
+ for i=1,n do C.funcb (C.funca (x, i), 1) end
+end
+
+
+This generates both shorter and faster code. So don't cache
+C functions , but do cache namespaces! Most often the
+namespace is already in a local variable at an outer scope, e.g. from
+local lib = ffi.load(...) . Note that copying
+it to a local variable in the function scope is unnecessary.
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/ext_jit.html b/LuaJIT-2.1/doc/ext_jit.html
new file mode 100644
index 00000000..15c75af1
--- /dev/null
+++ b/LuaJIT-2.1/doc/ext_jit.html
@@ -0,0 +1,197 @@
+
+
+
+jit.* Library
+
+
+
+
+
+
+
+
+
+
jit.* Library
+
+
+
+
+The functions in this built-in module control the behavior of the JIT
+compiler engine. Note that JIT-compilation is fully automatic —
+you probably won't need to use any of the following functions unless
+you have special needs.
+
+
+
jit.on()
+jit.off()
+
+Turns the whole JIT compiler on (default) or off.
+
+
+These functions are typically used with the command line options
+-j on or -j off .
+
+
+
jit.flush()
+
+Flushes the whole cache of compiled code.
+
+
+
jit.on(func|true [,true|false])
+jit.off(func|true [,true|false])
+jit.flush(func|true [,true|false])
+
+jit.on enables JIT compilation for a Lua function (this is
+the default).
+
+
+jit.off disables JIT compilation for a Lua function and
+flushes any already compiled code from the code cache.
+
+
+jit.flush flushes the code, but doesn't affect the
+enable/disable status.
+
+
+The current function, i.e. the Lua function calling this library
+function, can also be specified by passing true as the first
+argument.
+
+
+If the second argument is true , JIT compilation is also
+enabled, disabled or flushed recursively for all sub-functions of a
+function. With false only the sub-functions are affected.
+
+
+The jit.on and jit.off functions only set a flag
+which is checked when the function is about to be compiled. They do
+not trigger immediate compilation.
+
+
+Typical usage is jit.off(true, true) in the main chunk
+of a module to turn off JIT compilation for the whole module for
+debugging purposes.
+
+
+
jit.flush(tr)
+
+Flushes the root trace, specified by its number, and all of its side
+traces from the cache. The code for the trace will be retained as long
+as there are any other traces which link to it.
+
+
+
status, ... = jit.status()
+
+Returns the current status of the JIT compiler. The first result is
+either true or false if the JIT compiler is turned
+on or off. The remaining results are strings for CPU-specific features
+and enabled optimizations.
+
+
+
jit.version
+
+Contains the LuaJIT version string.
+
+
+
jit.version_num
+
+Contains the version number of the LuaJIT core. Version xx.yy.zz
+is represented by the decimal number xxyyzz.
+DEPRECATED after the switch to
+» rolling releases . zz is frozen at 99.
+
+
+
jit.os
+
+Contains the target OS name:
+"Windows", "Linux", "OSX", "BSD", "POSIX" or "Other".
+
+
+
jit.arch
+
+Contains the target architecture name:
+"x86", "x64", "arm", "arm64", "arm64be", "ppc", "mips", "mipsel", "mips64", "mips64el", "mips64r6", "mips64r6el".
+
+
+
jit.opt.* — JIT compiler optimization control
+
+This submodule provides the backend for the -O command line
+option.
+
+
+You can also use it programmatically, e.g.:
+
+
+jit.opt.start(2) -- same as -O2
+jit.opt.start("-dce")
+jit.opt.start("hotloop=10", "hotexit=2")
+
+
+Unlike in LuaJIT 1.x, the module is built-in and
+optimization is turned on by default!
+It's no longer necessary to run require("jit.opt").start() ,
+which was one of the ways to enable optimization.
+
+
+
jit.util.* — JIT compiler introspection
+
+This submodule holds functions to introspect the bytecode, generated
+traces, the IR and the generated machine code. The functionality
+provided by this module is still in flux and therefore undocumented.
+
+
+The debug modules -jbc , -jv and -jdump make
+extensive use of these functions. Please check out their source code,
+if you want to know more.
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/ext_profiler.html b/LuaJIT-2.1/doc/ext_profiler.html
new file mode 100644
index 00000000..c24ca97b
--- /dev/null
+++ b/LuaJIT-2.1/doc/ext_profiler.html
@@ -0,0 +1,359 @@
+
+
+
+Profiler
+
+
+
+
+
+
+
+
+
+
Profiler
+
+
+
+
+LuaJIT has an integrated statistical profiler with very low overhead. It
+allows sampling the currently executing stack and other parameters in
+regular intervals.
+
+
+The integrated profiler can be accessed from three levels:
+
+
+
+
High-Level Profiler
+
+The bundled high-level profiler offers basic profiling functionality. It
+generates simple textual summaries or source code annotations. It can be
+accessed with the -jp command line option
+or from Lua code by loading the underlying jit.p module.
+
+
+To cut to the chase — run this to get a CPU usage profile by
+function name:
+
+
+luajit -jp myapp.lua
+
+
+It's not a stated goal of the bundled profiler to add every
+possible option or to cater for special profiling needs. The low-level
+profiler APIs are documented below. They may be used by third-party
+authors to implement advanced functionality, e.g. IDE integration or
+graphical profilers.
+
+
+Note: Sampling works for both interpreted and JIT-compiled code. The
+results for JIT-compiled code may sometimes be surprising. LuaJIT
+heavily optimizes and inlines Lua code — there's no simple
+one-to-one correspondence between source code lines and the sampled
+machine code.
+
+
+
-jp=[options[,output]]
+
+The -jp command line option starts the high-level profiler.
+When the application run by the command line terminates, the profiler
+stops and writes the results to stdout or to the specified
+output file.
+
+
+The options argument specifies how the profiling is to be
+performed:
+
+
+f — Stack dump: function name, otherwise module:line.
+This is the default mode.
+F — Stack dump: ditto, but dump module:name.
+l — Stack dump: module:line.
+<number> — stack dump depth (callee ←
+caller). Default: 1.
+-<number> — Inverse stack dump depth (caller
+→ callee).
+s — Split stack dump after first stack level. Implies
+depth ≥ 2 or depth ≤ -2.
+p — Show full path for module names.
+v — Show VM states.
+z — Show zones .
+r — Show raw sample counts. Default: show percentages.
+a — Annotate excerpts from source code files.
+A — Annotate complete source code files.
+G — Produce raw output suitable for graphical tools.
+m<number> — Minimum sample percentage to be shown.
+Default: 3%.
+i<number> — Sampling interval in milliseconds.
+Default: 10ms.
+Note: The actual sampling precision is OS-dependent.
+
+
+The default output for -jp is a list of the most CPU consuming
+spots in the application. Increasing the stack dump depth with (say)
+-jp=2 may help to point out the main callers or callees of
+hotspots. But sample aggregation is still flat per unique stack dump.
+
+
+To get a two-level view (split view) of callers/callees, use
+-jp=s or -jp=-s . The percentages shown for the second
+level are relative to the first level.
+
+
+To see how much time is spent in each line relative to a function, use
+-jp=fl .
+
+
+To see how much time is spent in different VM states or
+zones , use -jp=v or -jp=z .
+
+
+Combinations of v/z with f/F/l produce two-level
+views, e.g. -jp=vf or -jp=fv . This shows the time
+spent in a VM state or zone vs. hotspots. This can be used to answer
+questions like "Which time-consuming functions are only interpreted?" or
+"What's the garbage collector overhead for a specific function?".
+
+
+Multiple options can be combined — but not all combinations make
+sense, see above. E.g. -jp=3si4m1 samples three stack levels
+deep in 4ms intervals and shows a split view of the CPU consuming
+functions and their callers with a 1% threshold.
+
+
+Source code annotations produced by -jp=a or -jp=A are
+always flat and at the line level. Obviously, the source code files need
+to be readable by the profiler script.
+
+
+The high-level profiler can also be started and stopped from Lua code with:
+
+
+require("jit.p").start(options, output)
+...
+require("jit.p").stop()
+
+
+
jit.zone — Zones
+
+Zones can be used to provide information about different parts of an
+application to the high-level profiler. E.g. a game could make use of an
+"AI" zone, a "PHYS" zone, etc. Zones are hierarchical,
+organized as a stack.
+
+
+The jit.zone module needs to be loaded explicitly:
+
+
+local zone = require("jit.zone")
+
+
+zone("name") pushes a named zone to the zone stack.
+zone() pops the current zone from the zone stack and
+returns its name.
+zone:get() returns the current zone name or nil .
+zone:flush() flushes the zone stack.
+
+
+To show the time spent in each zone use -jp=z . To show the time
+spent relative to hotspots use e.g. -jp=zf or -jp=fz .
+
+
+
Low-level Lua API
+
+The jit.profile module gives access to the low-level API of the
+profiler from Lua code. This module needs to be loaded explicitly:
+
+local profile = require("jit.profile")
+
+
+This module can be used to implement your own higher-level profiler.
+A typical profiling run starts the profiler, captures stack dumps in
+the profiler callback, adds them to a hash table to aggregate the number
+of samples, stops the profiler and then analyzes all captured
+stack dumps. Other parameters can be sampled in the profiler callback,
+too. But it's important not to spend too much time in the callback,
+since this may skew the statistics.
+
+
+
profile.start(mode, cb)
+— Start profiler
+
+This function starts the profiler. The mode argument is a
+string holding options:
+
+
+f — Profile with precision down to the function level.
+l — Profile with precision down to the line level.
+i<number> — Sampling interval in milliseconds (default
+10ms).
+Note: The actual sampling precision is OS-dependent.
+
+
+
+The cb argument is a callback function which is called with
+three arguments: (thread, samples, vmstate) . The callback is
+called on a separate coroutine, the thread argument is the
+state that holds the stack to sample for profiling. Note: do
+not modify the stack of that state or call functions on it.
+
+
+samples gives the number of accumulated samples since the last
+callback (usually 1).
+
+
+vmstate holds the VM state at the time the profiling timer
+triggered. This may or may not correspond to the state of the VM when
+the profiling callback is called. The state is either 'N'
+native (compiled) code, 'I' interpreted code, 'C'
+C code, 'G' the garbage collector, or 'J' the JIT
+compiler.
+
+
+
profile.stop()
+— Stop profiler
+
+This function stops the profiler.
+
+
+
dump = profile.dumpstack([thread,] fmt, depth)
+— Dump stack
+
+This function allows taking stack dumps in an efficient manner. It
+returns a string with a stack dump for the thread (coroutine),
+formatted according to the fmt argument:
+
+
+p — Preserve the full path for module names. Otherwise,
+only the file name is used.
+f — Dump the function name if it can be derived. Otherwise,
+use module:line.
+F — Ditto, but dump module:name.
+l — Dump module:line.
+Z — Zap the following characters for the last dumped
+frame.
+All other characters are added verbatim to the output string.
+
+
+The depth argument gives the number of frames to dump, starting
+at the topmost frame of the thread. A negative number dumps the frames in
+inverse order.
+
+
+The first example prints a list of the current module names and line
+numbers of up to 10 frames in separate lines. The second example prints
+semicolon-separated function names for all frames (up to 100) in inverse
+order:
+
+
+print(profile.dumpstack(thread, "l\n", 10))
+print(profile.dumpstack(thread, "lZ;", -100))
+
+
+
Low-level C API
+
+The profiler can be controlled directly from C code, e.g. for
+use by IDEs. The declarations are in "luajit.h" (see
+Lua/C API extensions).
+
+
+
luaJIT_profile_start(L, mode, cb, data)
+— Start profiler
+
+This function starts the profiler. See
+above for a description of the mode argument.
+
+
+The cb argument is a callback function with the following
+declaration:
+
+
+typedef void (*luaJIT_profile_callback)(void *data, lua_State *L,
+ int samples, int vmstate);
+
+
+data is available for use by the callback. L is the
+state that holds the stack to sample for profiling. Note: do
+not modify this stack or call functions on this stack —
+use a separate coroutine for this purpose. See
+above for a description of samples and vmstate .
+
+
+
luaJIT_profile_stop(L)
+— Stop profiler
+
+This function stops the profiler.
+
+
+
p = luaJIT_profile_dumpstack(L, fmt, depth, len)
+— Dump stack
+
+This function allows taking stack dumps in an efficient manner.
+See above for a description of fmt
+and depth .
+
+
+This function returns a const char * pointing to a
+private string buffer of the profiler. The int *len
+argument returns the length of the output string. The buffer is
+overwritten on the next call and deallocated when the profiler stops.
+You either need to consume the content immediately or copy it for later
+use.
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/extensions.html b/LuaJIT-2.1/doc/extensions.html
new file mode 100644
index 00000000..75b466db
--- /dev/null
+++ b/LuaJIT-2.1/doc/extensions.html
@@ -0,0 +1,502 @@
+
+
+
+Extensions
+
+
+
+
+
+
+
+
+
+
+
Extensions
+
+
+
+
+
+LuaJIT is fully upwards-compatible with Lua 5.1. It supports all
+» standard Lua
+library functions and the full set of
+» Lua/C API
+functions .
+
+
+LuaJIT is also fully ABI-compatible to Lua 5.1 at the linker/dynamic
+loader level. This means you can compile a C module against the
+standard Lua headers and load the same shared library from either Lua
+or LuaJIT.
+
+
+LuaJIT extends the standard Lua VM with new functionality and adds
+several extension modules. Please note, this page is only about
+functional enhancements and not about performance enhancements,
+such as the optimized VM, the faster interpreter or the JIT compiler.
+
+
+
Extensions Modules
+
+LuaJIT comes with several built-in extension modules:
+
+
+
bit.* — Bitwise operations
+
+LuaJIT supports all bitwise operations as defined by
+» Lua BitOp :
+
+
+bit.tobit bit.tohex bit.bnot bit.band bit.bor bit.bxor
+bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap
+
+
+This module is a LuaJIT built-in — you don't need to download or
+install Lua BitOp. The Lua BitOp site has full documentation for all
+» Lua BitOp API functions .
+The FFI adds support for
+64 bit bitwise operations ,
+using the same API functions.
+
+
+Please make sure to require the module before using any of
+its functions:
+
+
+local bit = require("bit")
+
+
+An already installed Lua BitOp module is ignored by LuaJIT.
+This way you can use bit operations from both Lua and LuaJIT on a
+shared installation.
+
+
+
ffi.* — FFI library
+
+The FFI library allows calling external
+C functions and the use of C data structures from pure Lua
+code.
+
+
+
jit.* — JIT compiler control
+
+The functions in this module
+control the behavior of the JIT compiler engine .
+
+
+
C API extensions
+
+LuaJIT adds some
+extra functions to the Lua/C API .
+
+
+
Profiler
+
+LuaJIT has an integrated profiler .
+
+
+
Enhanced Standard Library Functions
+
+
xpcall(f, err [,args...]) passes arguments
+
+Unlike the standard implementation in Lua 5.1, xpcall()
+passes any arguments after the error function to the function
+which is called in a protected context.
+
+
+
load*() handle UTF-8 source code
+
+Non-ASCII characters are handled transparently by the Lua source code parser.
+This allows the use of UTF-8 characters in identifiers and strings.
+A UTF-8 BOM is skipped at the start of the source code.
+
+
+
load*() add a mode parameter
+
+As an extension from Lua 5.2, the functions loadstring() ,
+loadfile() and (new) load() add an optional
+mode parameter.
+
+
+The default mode string is "bt" , which allows loading of both
+source code and bytecode. Use "t" to allow only source code
+or "b" to allow only bytecode to be loaded.
+
+
+By default, the load* functions generate the native bytecode format.
+For cross-compilation purposes, add W to the mode string to
+force the 32 bit format and X to force the 64 bit format.
+Add both to force the opposite format. Note that non-native bytecode
+generated by load* cannot be run, but can still be passed
+to string.dump .
+
+
+
tostring() etc. canonicalize NaN and ±Inf
+
+All number-to-string conversions consistently convert non-finite numbers
+to the same strings on all platforms. NaN results in "nan" ,
+positive infinity results in "inf" and negative infinity results
+in "-inf" .
+
+
+
tonumber() etc. use builtin string to number conversion
+
+All string-to-number conversions consistently convert integer and
+floating-point inputs in decimal, hexadecimal and binary on all platforms.
+strtod() is not used anymore, which avoids numerous
+problems with poor C library implementations. The builtin conversion
+function provides full precision according to the IEEE-754 standard, it
+works independently of the current locale and it supports hex floating-point
+numbers (e.g. 0x1.5p-3 ).
+
+
+
string.dump(f [,mode]) generates portable bytecode
+
+An extra argument has been added to string.dump() . If set to
+true or to a string which contains the character s ,
+'stripped' bytecode without debug information is generated. This speeds
+up later bytecode loading and reduces memory usage. See also the
+-b command line option .
+
+
+The generated bytecode is portable and can be loaded on any architecture
+that LuaJIT supports. However, the bytecode compatibility versions must
+match. Bytecode only stays compatible within a major+minor version
+(x.y.aaa → x.y.bbb), except for development branches. Foreign bytecode
+(e.g. from Lua 5.1) is incompatible and cannot be loaded.
+
+
+Note: LJ_GC64 mode requires a different frame layout, which implies
+a different, incompatible bytecode format between 32 bit and 64 bit ports.
+This may be rectified in the future. In the meantime, use the W
+and X modes of the load* functions
+for cross-compilation purposes.
+
+
+Due to VM hardening, bytecode is not deterministic. Add d to the
+mode string to dump it in a deterministic manner: identical source code
+always gives a byte-for-byte identical bytecode dump. This feature is
+mainly useful for reproducible builds.
+
+
+
table.new(narray, nhash) allocates a pre-sized table
+
+An extra library function table.new() can be made available via
+require("table.new") . This creates a pre-sized table, just like
+the C API equivalent lua_createtable() . This is useful for big
+tables if the final table size is known and automatic table resizing is
+too expensive.
+
+
+
table.clear(tab) clears a table
+
+An extra library function table.clear() can be made available
+via require("table.clear") . This clears all keys and values
+from a table, but preserves the allocated array/hash sizes. This is
+useful when a table, which is linked from multiple places, needs to be
+cleared and/or when recycling a table for use by the same context. This
+avoids managing backlinks, saves an allocation and the overhead of
+incremental array/hash part growth.
+
+
+Please note, this function is meant for very specific situations. In most
+cases it's better to replace the (usually single) link with a new table
+and let the GC do its work.
+
+
+
Enhanced PRNG for math.random()
+
+LuaJIT uses a Tausworthe PRNG with period 2^223 to implement
+math.random() and math.randomseed() . The quality of
+the PRNG results is much superior compared to the standard Lua
+implementation, which uses the platform-specific ANSI rand() .
+
+
+The PRNG generates the same sequences from the same seeds on all
+platforms and makes use of all bits in the seed argument.
+math.random() without arguments generates 52 pseudo-random bits
+for every call. The result is uniformly distributed between 0.0 and 1.0.
+It's correctly scaled up and rounded for math.random(n [,m]) to
+preserve uniformity.
+
+
+Call math.randomseed() without any arguments to seed it from
+system entropy.
+
+
+Important: Neither this nor any other PRNG based on the simplistic
+math.random() API is suitable for cryptographic use.
+
+
+
io.* functions handle 64 bit file offsets
+
+The file I/O functions in the standard io.* library handle
+64 bit file offsets. In particular, this means it's possible
+to open files larger than 2 Gigabytes and to reposition or obtain
+the current file position for offsets beyond 2 GB
+(fp:seek() method).
+
+
+
+
+debug.getinfo() and lua_getinfo() also return information
+about invoked metamethods. The namewhat field is set to
+"metamethod" and the name field has the name of
+the corresponding metamethod (e.g. "__index" ).
+
+
+
Fully Resumable VM
+
+The LuaJIT VM is fully resumable. This means you can yield from a
+coroutine even across contexts, where this would not possible with
+the standard Lua 5.1 VM: e.g. you can yield across pcall()
+and xpcall() , across iterators and across metamethods.
+
+
+
Extensions from Lua 5.2
+
+LuaJIT supports some language and library extensions from Lua 5.2.
+Features that are unlikely to break existing code are unconditionally
+enabled:
+
+
+goto and ::labels:: .
+Hex escapes '\x3F' and '\z' escape in strings.
+load(string|reader [, chunkname [,mode [,env]]]) .
+loadstring() is an alias for load() .
+loadfile(filename [,mode [,env]]) .
+math.log(x [,base]) .
+string.rep(s, n [,sep]) .
+string.format() : %q reversible.
+%s checks __tostring .
+%a and "%A added.
+String matching pattern %g added.
+io.read("*L") .
+io.lines() and file:lines() process
+io.read() options.
+os.exit(status|true|false [,close]) .
+package.searchpath(name, path [, sep [, rep]]) .
+package.loadlib(name, "*") .
+debug.getinfo() returns nparams and isvararg
+for option "u" .
+debug.getlocal() accepts function instead of level.
+debug.getlocal() and debug.setlocal() accept negative
+indexes for varargs.
+debug.getupvalue() and debug.setupvalue() handle
+C functions.
+debug.upvalueid() and debug.upvaluejoin() .
+Lua/C API extensions:
+lua_version()
+lua_upvalueid()
+lua_upvaluejoin()
+lua_loadx()
+lua_copy()
+lua_tonumberx()
+lua_tointegerx()
+luaL_fileresult()
+luaL_execresult()
+luaL_loadfilex()
+luaL_loadbufferx()
+luaL_traceback()
+luaL_setfuncs()
+luaL_pushmodule()
+luaL_newlibtable()
+luaL_newlib()
+luaL_testudata()
+luaL_setmetatable()
+
+Command line option -E .
+Command line checks __tostring for errors.
+
+
+Other features are only enabled, if LuaJIT is built with
+-DLUAJIT_ENABLE_LUA52COMPAT :
+
+
+goto is a keyword and not a valid variable name anymore.
+break can be placed anywhere. Empty statements (;; )
+are allowed.
+__lt , __le are invoked for mixed types.
+__len for tables. rawlen() library function.
+pairs() and ipairs() check for __pairs and
+__ipairs .
+coroutine.running() returns two results.
+table.pack() and table.unpack()
+(same as unpack() ).
+io.write() and file:write() return file handle
+instead of true .
+os.execute() and pipe:close() return detailed
+exit status.
+debug.setmetatable() returns object.
+debug.getuservalue() and debug.setuservalue() .
+Remove math.mod() , string.gfind() .
+package.searchers .
+module() returns the module table.
+
+
+Note: this provides only partial compatibility with Lua 5.2 at the
+language and Lua library level. LuaJIT is API+ABI-compatible with
+Lua 5.1, which prevents implementing features that would otherwise
+break the Lua/C API and ABI (e.g. _ENV ).
+
+
+
Extensions from Lua 5.3
+
+LuaJIT supports some extensions from Lua 5.3:
+
+Unicode escape '\u{XX...}' embeds the UTF-8 encoding in string literals.
+The argument table arg can be read (and modified) by LUA_INIT and -e chunks.
+io.read() and file:read() accept formats with or without a leading * .
+assert() accepts any type of error object.
+table.move(a1, f, e, t [,a2]) .
+coroutine.isyieldable() .
+Lua/C API extensions:
+lua_isyieldable()
+
+
+
+
C++ Exception Interoperability
+
+LuaJIT has built-in support for interoperating with C++ exceptions.
+The available range of features depends on the target platform and
+the toolchain used to compile LuaJIT:
+
+
+
+Platform
+Compiler
+Interoperability
+
+
+External frame unwinding
+GCC, Clang, MSVC
+Full
+
+
+Internal frame unwinding + DWARF2
+GCC, Clang
+Limited
+
+
+Windows 64 bit
+non-MSVC
+Limited
+
+
+Other platforms
+Other compilers
+No
+
+
+
+Full interoperability means:
+
+
+C++ exceptions can be caught on the Lua side with pcall() ,
+lua_pcall() etc.
+C++ exceptions will be converted to the generic Lua error
+"C++ exception" , unless you use the
+C call wrapper feature.
+It's safe to throw C++ exceptions across non-protected Lua frames
+on the C stack. The contents of the C++ exception object
+pass through unmodified.
+Lua errors can be caught on the C++ side with catch(...) .
+The corresponding Lua error message can be retrieved from the Lua stack.
+Throwing Lua errors across C++ frames is safe. C++ destructors
+will be called.
+
+
+Limited interoperability means:
+
+
+C++ exceptions can be caught on the Lua side with pcall() ,
+lua_pcall() etc.
+C++ exceptions will be converted to the generic Lua error
+"C++ exception" , unless you use the
+C call wrapper feature.
+C++ exceptions will be caught by non-protected Lua frames and
+are rethrown as a generic Lua error. The C++ exception object will
+be destroyed.
+Lua errors cannot be caught on the C++ side.
+Throwing Lua errors across C++ frames will not call
+C++ destructors.
+
+
+
+No interoperability means:
+
+
+It's not safe to throw C++ exceptions across Lua frames.
+C++ exceptions cannot be caught on the Lua side.
+Lua errors cannot be caught on the C++ side.
+Throwing Lua errors across C++ frames will not call
+C++ destructors.
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/img/contact.png b/LuaJIT-2.1/doc/img/contact.png
new file mode 100644
index 0000000000000000000000000000000000000000..9c73dc594efc1f47309d6c9b73d7719c3a9e04df
GIT binary patch
literal 1340
zcmV-C1;hG@P)sQ4|K#fZOHEVa==(`aQP0%nM@di3(&I%(O)@h#$&+f^&9&U}9=sU}#xfW8dZX
zS6X4+hl`eQb9`=bdTMQUS6N_FRb1EH?oLrx)!OXR*y%bu
zKs7fzyTH%6zRkD1%O4*iwYte19Urr}$DpLK7#SM{1qGa-tpfuC0RaJph?9SUjedfR
ze1M8)YI0?0aARg}VPtGhP*&yZ{!C6(sq^PzF3k;#Avk3_bkCL7T2MCRjoQjT_h>Vwp
zij{MAe{pnuZ*qHWaCvKPcUD+m*xm0?Qd!p9?bO-p)7k3L*XYmH<~BGyy}{8mHafb$
z&bYnIARr?h9v~YW9vK=O7Z@4@1O%I(tO5c8@Y5f50008dNklZz)3AlitwxnPH%H`Uot)Wm#A~UJD{dq04A@c=B#o!5#fVO
zK9y#&^Z}?|*LsioK&(FDooZAR)tQj#4t{T51EP;48U9I=7br`Bk^O8MkeX!ZNe^m_BH=Vrj*jZZuSKj$t2j7FZ^2u4YKv8(~
zaMJ@oQZ>+`rSiG$iy;5QP}GpcaF4=ry2srsiZ0RqYjK@LQA)d@GB0_aay0Tvrp83dAL2x{13
zII2|!RUp(7P{l^2T*QHZ71!E*QcTqNtMh0|uLS!2k^8W?Ka#6$aBn3*=LUe(BpUo6
z=nkI1fP*0x3aYH^su6tQT}{)EfU4IyLBQ-;(w1i;#)>KNGk41l6I5_B2)f}c}CK-PL&a{M5Rut(jQ@VX1_p&z6vN)t
zNcp7CYSP6-mE96jwhE}y?lvr|2kRa0g^iLTaJ1y+9qs~F+W}}-FHd&oy;TeG2n6hM
z2eK~@vIu+Z%WDWZDK7wkG0}TEXW(~!Gk+0t(i)Sck-Ht%F=yzi{ZFXe-}F6T**!vM
y)$^3mN5{Eb6*vAD>S)nmP3aw7v29)6WaBSReaJM4z7xj)0000
+
+
+Installation
+
+
+
+
+
+
+
+
+
+
+
Installation
+
+
+
+
+LuaJIT is only distributed as source code — get it from the
+» git repository . This page explains how to build
+and install the LuaJIT binary and library for different operating systems.
+
+
+For the impatient (on POSIX systems):
+
+
+make && sudo make install
+
+
+
Requirements
+
+LuaJIT currently builds out-of-the box on most systems. Please check the
+supported operating systems and CPU architectures on the
+» status page .
+
+
+Building LuaJIT requires a recent toolchain based on GCC, Clang/LLVM or
+MSVC++.
+
+
+The Makefile-based build system requires GNU Make and supports
+cross-builds.
+
+
+Batch files are provided for MSVC++ builds and console cross-builds.
+
+
+
Configuring LuaJIT
+
+The standard configuration should work fine for most installations.
+Usually there is no need to tweak the settings. The following files
+hold all user-configurable settings:
+
+
+Makefile has settings for installing LuaJIT (POSIX
+only).
+src/Makefile has settings for compiling LuaJIT
+under POSIX, MinGW or Cygwin.
+src/msvcbuild.bat has settings for compiling LuaJIT with
+MSVC (Visual Studio).
+
+
+Please read the instructions given in these files, before changing
+any settings.
+
+
+All LuaJIT 64 bit ports use 64 bit GC objects by default (LJ_GC64 ).
+For x64, you can select the old 32-on-64 bit mode by adding
+XCFLAGS=-DLUAJIT_DISABLE_GC64 to the make command.
+Please check the note about the
+bytecode format differences, too.
+
+
+
POSIX Systems (Linux, macOS, *BSD etc.)
+
Prerequisites
+
+Depending on your distribution, you may need to install a package for a
+compiler (GCC or Clang/LLVM), the development headers and/or a complete SDK.
+E.g. on a current Debian/Ubuntu, install build-essential with the
+package manager.
+
+
+
Building LuaJIT
+
+The supplied Makefiles try to auto-detect the settings needed for your
+operating system and your compiler. They need to be run with GNU Make,
+which is probably the default on your system, anyway. Simply run:
+
+
+make
+
+
+This always builds a native binary, depending on the host OS
+you're running this command on. Check the section on
+cross-compilation for more options.
+
+
+By default, modules are only searched under the prefix /usr/local .
+You can add an extra prefix to the search paths by appending the
+PREFIX option, e.g.:
+
+
+make PREFIX=/home/myself/lj2
+
+
+Note for macOS: you must set the MACOSX_DEPLOYMENT_TARGET
+environment variable to a value supported by your toolchain:
+
+
+MACOSX_DEPLOYMENT_TARGET=XX.YY make
+
+
Installing LuaJIT
+
+The top-level Makefile installs LuaJIT by default under
+/usr/local , i.e. the executable ends up in
+/usr/local/bin and so on. You need root privileges
+to write to this path. So, assuming sudo is installed on your system,
+run the following command and enter your sudo password:
+
+
+sudo make install
+
+
+Otherwise specify the directory prefix as an absolute path, e.g.:
+
+
+make install PREFIX=/home/myself/lj2
+
+
+Obviously the prefixes given during build and installation need to be the same.
+
+
+
Windows Systems
+
Prerequisites
+
+Either install one of the open source SDKs
+(» MinGW or
+» Cygwin ), which come with a modified
+GCC plus the required development headers.
+Or install Microsoft's Visual Studio (MSVC).
+
+
Building with MSVC
+
+Open a "Visual Studio Command Prompt" (x86, x64 or ARM64), cd to the
+directory with the source code and run these commands:
+
+
+cd src
+msvcbuild
+
+
+Check the msvcbuild.bat file for more options.
+Then follow the installation instructions below.
+
+
+For an x64 to ARM64 cross-build run this first: vcvarsall.bat x64_arm64
+
+
Building with MinGW or Cygwin
+
+Open a command prompt window and make sure the MinGW or Cygwin programs
+are in your path. Then cd to the directory of the git repository.
+Then run this command for MinGW:
+
+
+mingw32-make
+
+
+Or this command for Cygwin:
+
+
+make
+
+
+Then follow the installation instructions below.
+
+
Installing LuaJIT
+
+Copy luajit.exe and lua51.dll (built in the src
+directory) to a newly created directory (any location is ok).
+Add lua and lua\jit directories below it and copy
+all Lua files from the src\jit directory of the distribution
+to the latter directory.
+
+
+There are no hardcoded
+absolute path names — all modules are loaded relative to the
+directory where luajit.exe is installed
+(see src/luaconf.h ).
+
+
+
Cross-compiling LuaJIT
+
+First, let's clear up some terminology:
+
+
+Host: This is your development system, usually based on a x64 or x86 CPU.
+Target: This is the target system you want LuaJIT to run on, e.g. Android/ARM.
+Toolchain: This comprises a C compiler, linker, assembler and a matching C library.
+Host (or system) toolchain: This is the toolchain used to build native binaries for your host system.
+Cross-compile toolchain: This is the toolchain used to build binaries for the target system. They can only be run on the target system.
+
+
+The GNU Makefile-based build system allows cross-compiling on any host
+for any supported target:
+
+
+Yes, you need a toolchain for both your host and your target!
+Both host and target architectures must have the same pointer size.
+E.g. if you want to cross-compile to a 32 bit target on a 64 bit host, you need to install the multilib development package (e.g. libc6-dev-i386 on Debian/Ubuntu) and build a 32 bit host part (HOST_CC="gcc -m32" ).
+On some distro versions, multilib conflicts with cross-compilers. The workaround is to install the x86 cross-compiler package gcc-i686-linux-gnu and use it to build the host part (HOST_CC=i686-linux-gnu-gcc ).
+64 bit targets always require compilation on a 64 bit host.
+
+
+You need to specify TARGET_SYS whenever the host OS and the
+target OS differ, or you'll get assembler or linker errors:
+
+
+E.g. if you're compiling on a Windows or macOS host for embedded Linux or Android, you need to add TARGET_SYS=Linux to the examples below.
+For a minimal target OS, you may need to disable the built-in allocator in src/Makefile and use TARGET_SYS=Other .
+Don't forget to specify the same TARGET_SYS for the install step, too.
+
+
+Here are some examples where host and target have the same CPU:
+
+
+# Cross-compile to a 32 bit binary on a multilib x64 OS
+make CC="gcc -m32"
+
+# Cross-compile on Debian/Ubuntu for Windows (mingw32 package)
+make HOST_CC="gcc -m32" CROSS=i586-mingw32msvc- TARGET_SYS=Windows
+
+
+The CROSS prefix allows specifying a standard GNU cross-compile
+toolchain (Binutils, GCC and a matching libc). The prefix may vary
+depending on the --target the toolchain was built for (note the
+CROSS prefix has a trailing "-" ). The examples below
+use the canonical toolchain triplets for Linux.
+
+
+Since there's often no easy way to detect CPU features at runtime, it's
+important to compile with the proper CPU or architecture settings:
+
+
+The best way to get consistent results is to specify the correct settings when building the toolchain yourself.
+For a pre-built, generic toolchain add -mcpu=... or -march=... and other necessary flags to TARGET_CFLAGS .
+For ARM it's important to have the correct -mfloat-abi=... setting, too. Otherwise LuaJIT may not run at the full performance of your target CPU.
+For MIPS it's important to select a supported ABI (o32 on MIPS32, n64 on MIPS64) and consistently compile your project either with hard-float or soft-float compiler settings.
+
+
+Here are some examples for targets with a different CPU than the host:
+
+
+# ARM soft-float
+make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
+ TARGET_CFLAGS="-mfloat-abi=soft"
+
+# ARM soft-float ABI with VFP (example for Cortex-A9)
+make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
+ TARGET_CFLAGS="-mcpu=cortex-a9 -mfloat-abi=softfp"
+
+# ARM hard-float ABI with VFP (armhf, most modern toolchains)
+make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabihf-
+
+# ARM64
+make CROSS=aarch64-linux-gnu-
+
+# PPC
+make HOST_CC="gcc -m32" CROSS=powerpc-linux-gnu-
+
+# MIPS32 big-endian
+make HOST_CC="gcc -m32" CROSS=mips-linux-gnu-
+# MIPS32 little-endian
+make HOST_CC="gcc -m32" CROSS=mipsel-linux-gnu-
+
+# MIPS64 big-endian
+make CROSS=mips-linux- TARGET_CFLAGS="-mips64r2 -mabi=64"
+# MIPS64 little-endian
+make CROSS=mipsel-linux- TARGET_CFLAGS="-mips64r2 -mabi=64"
+
+
+You can cross-compile for Android using the » Android NDK .
+Please adapt the environment variables to match the install locations and the
+desired target platform. E.g. Android 4.1 corresponds to ABI level 16.
+
+
+# Android/ARM64, aarch64, Android 5.0+ (L)
+NDKDIR=/opt/android/ndk
+NDKBIN=$NDKDIR/toolchains/llvm/prebuilt/linux-x86_64/bin
+NDKCROSS=$NDKBIN/aarch64-linux-android-
+NDKCC=$NDKBIN/aarch64-linux-android21-clang
+make CROSS=$NDKCROSS \
+ STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
+ TARGET_LD=$NDKCC TARGET_AR="$NDKBIN/llvm-ar rcus" \
+ TARGET_STRIP=$NDKBIN/llvm-strip
+
+# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.1+ (JB)
+NDKDIR=/opt/android/ndk
+NDKBIN=$NDKDIR/toolchains/llvm/prebuilt/linux-x86_64/bin
+NDKCROSS=$NDKBIN/arm-linux-androideabi-
+NDKCC=$NDKBIN/armv7a-linux-androideabi16-clang
+make HOST_CC="gcc -m32" CROSS=$NDKCROSS \
+ STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
+ TARGET_LD=$NDKCC TARGET_AR="$NDKBIN/llvm-ar rcus" \
+ TARGET_STRIP=$NDKBIN/llvm-strip
+
+
+You can cross-compile for iOS 3.0+ (iPhone/iPad) using the » iOS SDK :
+
+
+Note: the JIT compiler is disabled for iOS , because regular iOS Apps
+are not allowed to generate code at runtime. You'll only get the performance
+of the LuaJIT interpreter on iOS. This is still faster than plain Lua, but
+much slower than the JIT compiler. Please complain to Apple, not me.
+Or use Android. :-p
+
+
+# iOS/ARM64
+ISDKP=$(xcrun --sdk iphoneos --show-sdk-path)
+ICC=$(xcrun --sdk iphoneos --find clang)
+ISDKF="-arch arm64 -isysroot $ISDKP"
+make DEFAULT_CC=clang CROSS="$(dirname $ICC)/" \
+ TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS
+
+
+
Cross-compiling for consoles
+
+Building LuaJIT for consoles requires both a supported host compiler
+(x86 or x64) and a cross-compiler from the official console SDK.
+
+
+Due to restrictions on consoles, the JIT compiler is disabled and only
+the fast interpreter is built. This is still faster than plain Lua,
+but much slower than the JIT compiler. The FFI is disabled, too, since
+it's not very useful in such an environment.
+
+
+The following commands build a static library libluajit.a ,
+which can be linked against your game, just like the Lua library.
+
+
+To cross-compile for PS3 from a Linux host (requires
+32 bit GCC, i.e. multilib Linux/x64) or a Windows host (requires
+32 bit MinGW), run this command:
+
+
+make HOST_CC="gcc -m32" CROSS=ppu-lv2-
+
+
+To cross-compile for the other consoles from a Windows host, open a
+"Native Tools Command Prompt for VS". You need to choose either the 32
+or the 64 bit version of the host compiler to match the target.
+Then cd to the src directory below the source code
+and run the build command given in the table:
+
+
+
+Console
+Bits
+Build Command
+
+
+PS4
+64
+ps4build
+
+
+PS5
+64
+ps5build
+
+
+PS Vita
+32
+psvitabuild
+
+
+Xbox 360
+32
+xedkbuild
+
+
+Xbox One
+64
+xb1build
+
+
+Nintendo Switch NX32
+32
+nxbuild
+
+
+Nintendo Switch NX64
+64
+nxbuild
+
+
+
+Please check out the comments in the corresponding *.bat
+file for more options.
+
+
+
Embedding LuaJIT
+
+LuaJIT is API-compatible with Lua 5.1. If you've already embedded Lua
+into your application, you probably don't need to do anything to switch
+to LuaJIT, except link with a different library:
+
+
+It's strongly suggested to build LuaJIT separately using the supplied
+build system. Please do not attempt to integrate the individual
+source files into your build tree. You'll most likely get the internal build
+dependencies wrong or mess up the compiler flags. Treat LuaJIT like any
+other external library and link your application with either the dynamic
+or static library, depending on your needs.
+If you want to load C modules compiled for plain Lua
+with require() , you need to make sure the public symbols
+(e.g. lua_pushnumber ) are exported, too:
+On POSIX systems you can either link to the shared library
+or link the static library into your application. In the latter case
+you'll need to export all public symbols from your main executable
+(e.g. -Wl,-E on Linux) and add the external dependencies
+(e.g. -lm -ldl on Linux).
+Since Windows symbols are bound to a specific DLL name, you need to
+link to the lua51.dll created by the LuaJIT build (do not rename
+the DLL). You may link LuaJIT statically on Windows only if you don't
+intend to load Lua/C modules at runtime.
+
+
+
+
Additional hints for initializing LuaJIT using the C API functions:
+
+Here's a
+» simple example
+for embedding Lua or LuaJIT into your application.
+Make sure you use luaL_newstate . Avoid using
+lua_newstate , since this uses the (slower) default memory
+allocator from your system (no support for this on 64 bit architectures).
+Make sure you use luaL_openlibs and not the old Lua 5.0 style
+of calling luaopen_base etc. directly.
+To change or extend the list of standard libraries to load, copy
+src/lib_init.c to your project and modify it accordingly.
+Make sure the jit library is loaded, or the JIT compiler
+will not be activated.
+The bit.* module for bitwise operations
+is already built-in. There's no need to statically link
+» Lua BitOp to your application.
+
+
+
Hints for Distribution Maintainers
+
+The LuaJIT build system has extra provisions for the needs of most
+POSIX-based distributions. If you're a package maintainer for
+a distribution, please make use of these features and
+avoid patching, subverting, autotoolizing or messing up the build system
+in unspeakable ways.
+
+
+There should be absolutely no need to patch luaconf.h or any
+of the Makefiles. And please do not hand-pick files for your packages —
+simply use whatever make install creates. There's a reason
+for all the files and directories it creates.
+
+
+The build system uses GNU make and auto-detects most settings based on
+the host you're building it on. This should work fine for native builds,
+even when sandboxed. You may need to pass some of the following flags to
+both the make and the make install command lines
+for a regular distribution build:
+
+
+PREFIX overrides the installation path and should usually
+be set to /usr . Setting this also changes the module paths and
+the paths needed to locate the shared library.
+DESTDIR is an absolute path which allows you to install
+to a shadow tree instead of the root tree of the build system.
+MULTILIB sets the architecture-specific library path component
+for multilib systems. The default is lib .
+Have a look at the top-level Makefile and src/Makefile
+for additional variables to tweak. The following variables may be
+overridden, but it's not recommended, except for special needs
+like cross-builds:
+BUILDMODE, CC, HOST_CC, STATIC_CC, DYNAMIC_CC, CFLAGS, HOST_CFLAGS,
+TARGET_CFLAGS, LDFLAGS, HOST_LDFLAGS, TARGET_LDFLAGS, TARGET_SHLDFLAGS,
+TARGET_FLAGS, LIBS, HOST_LIBS, TARGET_LIBS, CROSS, HOST_SYS, TARGET_SYS
+
+
+
+The build system has a special target for an amalgamated build, i.e.
+make amalg . This compiles the LuaJIT core as one huge C file
+and allows GCC to generate faster and shorter code. Alas, this requires
+lots of memory during the build. This may be a problem for some users,
+that's why it's not enabled by default. But it shouldn't be a problem for
+most build farms. It's recommended that binary distributions use this
+target for their LuaJIT builds.
+
+
+The tl;dr version of the above:
+
+
+make amalg PREFIX=/usr && \
+make install PREFIX=/usr DESTDIR=/tmp/buildroot
+
+
+Finally, if you encounter any difficulties, please
+contact me first, instead of releasing a broken
+package onto unsuspecting users. Because they'll usually gonna complain
+to me (the upstream) and not you (the package maintainer), anyway.
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/luajit.html b/LuaJIT-2.1/doc/luajit.html
new file mode 100644
index 00000000..73a1c17f
--- /dev/null
+++ b/LuaJIT-2.1/doc/luajit.html
@@ -0,0 +1,203 @@
+
+
+
+LuaJIT
+
+
+
+
+
+
+
+
+
+
+
+
LuaJIT
+
+
+
+
+LuaJIT is a Just-In-Time Compiler (JIT) for the
+» Lua programming language.
+Lua is a powerful, dynamic and light-weight programming language.
+It may be embedded or used as a general-purpose, stand-alone language.
+
+
+LuaJIT is Copyright © 2005-2025 Mike Pall, released under the
+» MIT open source license .
+
+
+
+
+
Compatibility
+
+Windows Linux BSD macOS POSIX
+
+
+
+PS3 PS4 PS5 PS Vita Xbox 360 Xbox One Nintendo Switch
+
+
+
+x86 x64 ARM ARM64 PPC MIPS32 MIPS64
+
+
+Lua 5.1 API+ABI + JIT + BitOp + FFI Drop-in DLL/.so
+
+
+
Overview
+
+LuaJIT has been successfully used as a scripting middleware in
+games, appliances, network and graphics apps, numerical simulations,
+trading platforms and many other specialty applications.
+
+
+LuaJIT is part of a hundred million web sites, huge SaaS installations,
+network switches, set-top boxes and other embedded devices. You've probably
+already used LuaJIT without knowing about it.
+
+
+LuaJIT scales from embedded devices, smartphones, desktops up to server
+farms. It combines high flexibility with high performance and an unmatched
+low memory footprint .
+
+
+LuaJIT has been in continuous development since 2005. It's widely
+considered to be one of the fastest dynamic language
+implementations . It has outperformed other dynamic languages on many
+cross-language benchmarks since its first release — often by a
+substantial margin.
+
+
+For LuaJIT 2.0 , the whole VM has been rewritten from the ground up
+and relentlessly optimized for performance. It combines a high-speed
+interpreter , written in assembler, with a state-of-the-art JIT
+compiler .
+
+
+An innovative trace compiler is integrated with advanced,
+SSA-based optimizations and highly tuned code generation backends.
+A substantial reduction of the overhead associated with dynamic languages
+allows it to break into the performance range traditionally reserved for
+offline, static language compilers.
+
+
+
More ...
+
+Please select a sub-topic in the navigation bar to learn more about LuaJIT.
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/doc/running.html b/LuaJIT-2.1/doc/running.html
new file mode 100644
index 00000000..f71eee42
--- /dev/null
+++ b/LuaJIT-2.1/doc/running.html
@@ -0,0 +1,317 @@
+
+
+
+Running LuaJIT
+
+
+
+
+
+
+
+
+
+
+
Running LuaJIT
+
+
+
+
+
+LuaJIT has only a single stand-alone executable, called luajit on
+POSIX systems or luajit.exe on Windows. It can be used to run simple
+Lua statements or whole Lua applications from the command line. It has an
+interactive mode, too.
+
+
+
Command Line Options
+
+The luajit stand-alone executable is just a slightly modified
+version of the regular lua stand-alone executable.
+It supports the same basic options, too. luajit -h
+prints a short list of the available options. Please have a look at the
+» Lua manual
+for details.
+
+
+LuaJIT has some additional options:
+
+
+
-b[options] input output
+
+This option saves or lists bytecode. The following additional options
+are accepted:
+
+
+-l — Only list bytecode.
+-s — Strip debug info (this is the default).
+-g — Keep debug info.
+-W — Generate 32 bit (non-GC64) bytecode.
+-X — Generate 64 bit (GC64) bytecode.
+-d — Generate bytecode in deterministic manner.
+-n name — Set module name (default: auto-detect from input name)
+-t type — Set output file type (default: auto-detect from output name).
+-a arch — Override architecture for object files (default: native).
+-o os — Override OS for object files (default: native).
+-F name — Override filename (default: input filename).
+-e chunk — Use chunk string as input.
+- (a single minus sign) — Use stdin as input and/or stdout as output.
+
+
+The output file type is auto-detected from the extension of the output
+file name:
+
+
+c — C source file, exported bytecode data.
+cc — C++ source file, exported bytecode data.
+h — C/C++ header file, static bytecode data.
+obj or o — Object file, exported bytecode data
+(OS- and architecture-specific).
+raw or any other extension — Raw bytecode file (portable).
+
+
+Notes:
+
+
+See also string.dump()
+for information on bytecode portability and compatibility.
+A file in raw bytecode format is auto-detected and can be loaded like
+any Lua source file. E.g. directly from the command line or with
+loadfile() , dofile() etc.
+To statically embed the bytecode of a module in your application,
+generate an object file and just link it with your application.
+On most ELF-based systems (e.g. Linux) you need to explicitly export the
+global symbols when linking your application, e.g. with: -Wl,-E
+require() tries to load embedded bytecode data from exported
+symbols (in *.exe or lua51.dll on Windows) and from
+shared libraries in package.cpath .
+
+
+Typical usage examples:
+
+
+luajit -b test.lua test.out # Save bytecode to test.out
+luajit -bg test.lua test.out # Keep debug info
+luajit -be "print('hello world')" test.out # Save cmdline script
+
+luajit -bl test.lua # List to stdout
+luajit -bl test.lua test.txt # List to test.txt
+luajit -ble "print('hello world')" # List cmdline script
+
+luajit -b test.lua test.obj # Generate object file
+# Link test.obj with your application and load it with require("test")
+
+
+
-j cmd[=arg[,arg...]]
+
+This option performs a LuaJIT control command or activates one of the
+loadable extension modules. The command is first looked up in the
+jit.* library. If no matching function is found, a module
+named jit.<cmd> is loaded and the start()
+function of the module is called with the specified arguments (if
+any). The space between -j and cmd is optional.
+
+
+Here are the available LuaJIT control commands:
+
+
+-jon — Turns the JIT compiler on (default).
+-joff — Turns the JIT compiler off (only use the interpreter).
+-jflush — Flushes the whole cache of compiled code.
+-jv — Shows verbose information about the progress of the JIT compiler.
+-jdump — Dumps the code and structures used in various compiler stages.
+-jp — Start the integrated profiler .
+
+
+The -jv and -jdump commands are extension modules
+written in Lua. They are mainly used for debugging the JIT compiler
+itself. For a description of their options and output format, please
+read the comment block at the start of their source.
+They can be found in the lib directory of the source
+distribution or installed under the jit directory. By default,
+this is /usr/local/share/luajit-XX.YY.ZZ>/jit on POSIX
+systems (replace XX.YY.ZZ by the installed version).
+
+
+
-O[level]
+-O[+]flag -O-flag
+-Oparam=value
+
+This options allows fine-tuned control of the optimizations used by
+the JIT compiler. This is mainly intended for debugging LuaJIT itself.
+Please note that the JIT compiler is extremely fast (we are talking
+about the microsecond to millisecond range). Disabling optimizations
+doesn't have any visible impact on its overhead, but usually generates
+code that runs slower.
+
+
+The first form sets an optimization level — this enables a
+specific mix of optimization flags. -O0 turns off all
+optimizations and higher numbers enable more optimizations. Omitting
+the level (i.e. just -O ) sets the default optimization level,
+which is -O3 in the current version.
+
+
+The second form adds or removes individual optimization flags.
+The third form sets a parameter for the VM or the JIT compiler
+to a specific value.
+
+
+You can either use this option multiple times (like -Ocse
+-O-dce -Ohotloop=10 ) or separate several settings with a comma
+(like -O+cse,-dce,hotloop=10 ). The settings are applied from
+left to right, and later settings override earlier ones. You can freely
+mix the three forms, but note that setting an optimization level
+overrides all earlier flags.
+
+
+Note that -Ofma is not enabled by default at any level,
+because it affects floating-point result accuracy. Only enable this,
+if you fully understand the trade-offs of FMA for performance (higher),
+determinism (lower) and numerical accuracy (higher).
+
+
+Here are the available flags and at what optimization levels they
+are enabled:
+
+
+
+Flag
+-O1
+-O2
+-O3
+
+
+
+fold • • • Constant Folding, Simplifications and Reassociation
+
+cse • • • Common-Subexpression Elimination
+
+dce • • • Dead-Code Elimination
+
+narrow • • Narrowing of numbers to integers
+
+loop • • Loop Optimizations (code hoisting)
+
+fwd • Load Forwarding (L2L) and Store Forwarding (S2L)
+
+dse • Dead-Store Elimination
+
+abc • Array Bounds Check Elimination
+
+sink • Allocation/Store Sinking
+
+fuse • Fusion of operands into instructions
+
+fma Fused multiply-add
+
+
+Here are the parameters and their default settings:
+
+
+
+Parameter
+Default
+
+
+
+maxtrace 1000 Max. number of traces in the cache
+
+maxrecord 4000 Max. number of recorded IR instructions
+
+maxirconst 500 Max. number of IR constants of a trace
+
+maxside 100 Max. number of side traces of a root trace
+
+maxsnap 500 Max. number of snapshots for a trace
+
+hotloop 56 Number of iterations to detect a hot loop or hot call
+
+hotexit 10 Number of taken exits to start a side trace
+
+tryside 4 Number of attempts to compile a side trace
+
+instunroll 4 Max. unroll factor for instable loops
+
+loopunroll 15 Max. unroll factor for loop ops in side traces
+
+callunroll 3 Max. unroll factor for pseudo-recursive calls
+
+recunroll 2 Min. unroll factor for true recursion
+
+sizemcode 32 Size of each machine code area in KBytes (Windows: 64K)
+
+maxmcode 512 Max. total size of all machine code areas in KBytes
+
+
+
+
+
+
diff --git a/LuaJIT-2.1/dynasm/dasm_arm.h b/LuaJIT-2.1/dynasm/dasm_arm.h
new file mode 100644
index 00000000..824e8be0
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_arm.h
@@ -0,0 +1,456 @@
+/*
+** DynASM ARM encoding engine.
+** Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+** Released under the MIT license. See dynasm.lua for full copyright notice.
+*/
+
+#include
+#include
+#include
+#include
+
+#define DASM_ARCH "arm"
+
+#ifndef DASM_EXTERN
+#define DASM_EXTERN(a,b,c,d) 0
+#endif
+
+/* Action definitions. */
+enum {
+ DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
+ /* The following actions need a buffer position. */
+ DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
+ /* The following actions also have an argument. */
+ DASM_REL_PC, DASM_LABEL_PC,
+ DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12, DASM_IMMV8,
+ DASM__MAX
+};
+
+/* Maximum number of section buffer positions for a single dasm_put() call. */
+#define DASM_MAXSECPOS 25
+
+/* DynASM encoder status codes. Action list offset or number are or'ed in. */
+#define DASM_S_OK 0x00000000
+#define DASM_S_NOMEM 0x01000000
+#define DASM_S_PHASE 0x02000000
+#define DASM_S_MATCH_SEC 0x03000000
+#define DASM_S_RANGE_I 0x11000000
+#define DASM_S_RANGE_SEC 0x12000000
+#define DASM_S_RANGE_LG 0x13000000
+#define DASM_S_RANGE_PC 0x14000000
+#define DASM_S_RANGE_REL 0x15000000
+#define DASM_S_UNDEF_LG 0x21000000
+#define DASM_S_UNDEF_PC 0x22000000
+
+/* Macros to convert positions (8 bit section + 24 bit index). */
+#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
+#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
+#define DASM_SEC2POS(sec) ((sec)<<24)
+#define DASM_POS2SEC(pos) ((pos)>>24)
+#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
+
+/* Action list type. */
+typedef const unsigned int *dasm_ActList;
+
+/* Per-section structure. */
+typedef struct dasm_Section {
+ int *rbuf; /* Biased buffer pointer (negative section bias). */
+ int *buf; /* True buffer pointer. */
+ size_t bsize; /* Buffer size in bytes. */
+ int pos; /* Biased buffer position. */
+ int epos; /* End of biased buffer position - max single put. */
+ int ofs; /* Byte offset into section. */
+} dasm_Section;
+
+/* Core structure holding the DynASM encoding state. */
+struct dasm_State {
+ size_t psize; /* Allocated size of this structure. */
+ dasm_ActList actionlist; /* Current actionlist pointer. */
+ int *lglabels; /* Local/global chain/pos ptrs. */
+ size_t lgsize;
+ int *pclabels; /* PC label chains/pos ptrs. */
+ size_t pcsize;
+ void **globals; /* Array of globals. */
+ dasm_Section *section; /* Pointer to active section. */
+ size_t codesize; /* Total size of all code sections. */
+ int maxsection; /* 0 <= sectionidx < maxsection. */
+ int status; /* Status code. */
+ dasm_Section sections[1]; /* All sections. Alloc-extended. */
+};
+
+/* The size of the core structure depends on the max. number of sections. */
+#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
+
+
+/* Initialize DynASM state. */
+void dasm_init(Dst_DECL, int maxsection)
+{
+ dasm_State *D;
+ size_t psz = 0;
+ Dst_REF = NULL;
+ DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
+ D = Dst_REF;
+ D->psize = psz;
+ D->lglabels = NULL;
+ D->lgsize = 0;
+ D->pclabels = NULL;
+ D->pcsize = 0;
+ D->globals = NULL;
+ D->maxsection = maxsection;
+ memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section));
+}
+
+/* Free DynASM state. */
+void dasm_free(Dst_DECL)
+{
+ dasm_State *D = Dst_REF;
+ int i;
+ for (i = 0; i < D->maxsection; i++)
+ if (D->sections[i].buf)
+ DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
+ if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
+ if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
+ DASM_M_FREE(Dst, D, D->psize);
+}
+
+/* Setup global label array. Must be called before dasm_setup(). */
+void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
+{
+ dasm_State *D = Dst_REF;
+ D->globals = gl;
+ DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
+}
+
+/* Grow PC label array. Can be called after dasm_setup(), too. */
+void dasm_growpc(Dst_DECL, unsigned int maxpc)
+{
+ dasm_State *D = Dst_REF;
+ size_t osz = D->pcsize;
+ DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
+ memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
+}
+
+/* Setup encoder. */
+void dasm_setup(Dst_DECL, const void *actionlist)
+{
+ dasm_State *D = Dst_REF;
+ int i;
+ D->actionlist = (dasm_ActList)actionlist;
+ D->status = DASM_S_OK;
+ D->section = &D->sections[0];
+ memset((void *)D->lglabels, 0, D->lgsize);
+ if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
+ for (i = 0; i < D->maxsection; i++) {
+ D->sections[i].pos = DASM_SEC2POS(i);
+ D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos;
+ D->sections[i].ofs = 0;
+ }
+}
+
+
+#ifdef DASM_CHECKS
+#define CK(x, st) \
+ do { if (!(x)) { \
+ D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
+#define CKPL(kind, st) \
+ do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
+ D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
+#else
+#define CK(x, st) ((void)0)
+#define CKPL(kind, st) ((void)0)
+#endif
+
+static int dasm_imm12(unsigned int n)
+{
+ int i;
+ for (i = 0; i < 16; i++, n = (n << 2) | (n >> 30))
+ if (n <= 255) return (int)(n + (i << 8));
+ return -1;
+}
+
+/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
+void dasm_put(Dst_DECL, int start, ...)
+{
+ va_list ap;
+ dasm_State *D = Dst_REF;
+ dasm_ActList p = D->actionlist + start;
+ dasm_Section *sec = D->section;
+ int pos = sec->pos, ofs = sec->ofs;
+ int *b;
+
+ if (pos >= sec->epos) {
+ DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
+ sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
+ sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
+ sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
+ }
+
+ b = sec->rbuf;
+ b[pos++] = start;
+
+ va_start(ap, start);
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16);
+ if (action >= DASM__MAX) {
+ ofs += 4;
+ } else {
+ int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
+ switch (action) {
+ case DASM_STOP: goto stop;
+ case DASM_SECTION:
+ n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
+ D->section = &D->sections[n]; goto stop;
+ case DASM_ESC: p++; ofs += 4; break;
+ case DASM_REL_EXT: break;
+ case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
+ case DASM_REL_LG:
+ n = (ins & 2047) - 10; pl = D->lglabels + n;
+ /* Bkwd rel or global. */
+ if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
+ pl += 10; n = *pl;
+ if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
+ goto linkrel;
+ case DASM_REL_PC:
+ pl = D->pclabels + n; CKPL(pc, PC);
+ putrel:
+ n = *pl;
+ if (n < 0) { /* Label exists. Get label pos and store it. */
+ b[pos] = -n;
+ } else {
+ linkrel:
+ b[pos] = n; /* Else link to rel chain, anchored at label. */
+ *pl = pos;
+ }
+ pos++;
+ break;
+ case DASM_LABEL_LG:
+ pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
+ case DASM_LABEL_PC:
+ pl = D->pclabels + n; CKPL(pc, PC);
+ putlabel:
+ n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
+ while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
+ }
+ *pl = -pos; /* Label exists now. */
+ b[pos++] = ofs; /* Store pass1 offset estimate. */
+ break;
+ case DASM_IMM:
+ case DASM_IMM16:
+#ifdef DASM_CHECKS
+ CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
+ if ((ins & 0x8000))
+ CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
+ else
+ CK((n>>((ins>>5)&31)) == 0, RANGE_I);
+#endif
+ b[pos++] = n;
+ break;
+ case DASM_IMMV8:
+ CK((n & 3) == 0, RANGE_I);
+ n >>= 2;
+ /* fallthrough */
+ case DASM_IMML8:
+ case DASM_IMML12:
+ CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) :
+ (((-n)>>((ins>>5)&31)) == 0), RANGE_I);
+ b[pos++] = n;
+ break;
+ case DASM_IMM12:
+ CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
+ b[pos++] = n;
+ break;
+ }
+ }
+ }
+stop:
+ va_end(ap);
+ sec->pos = pos;
+ sec->ofs = ofs;
+}
+#undef CK
+
+/* Pass 2: Link sections, shrink aligns, fix label offsets. */
+int dasm_link(Dst_DECL, size_t *szp)
+{
+ dasm_State *D = Dst_REF;
+ int secnum;
+ int ofs = 0;
+
+#ifdef DASM_CHECKS
+ *szp = 0;
+ if (D->status != DASM_S_OK) return D->status;
+ {
+ int pc;
+ for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
+ if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
+ }
+#endif
+
+ { /* Handle globals not defined in this translation unit. */
+ int idx;
+ for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
+ int n = D->lglabels[idx];
+ /* Undefined label: Collapse rel chain and replace with marker (< 0). */
+ while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
+ }
+ }
+
+ /* Combine all code sections. No support for data sections (yet). */
+ for (secnum = 0; secnum < D->maxsection; secnum++) {
+ dasm_Section *sec = D->sections + secnum;
+ int *b = sec->rbuf;
+ int pos = DASM_SEC2POS(secnum);
+ int lastpos = sec->pos;
+
+ while (pos != lastpos) {
+ dasm_ActList p = D->actionlist + b[pos++];
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16);
+ switch (action) {
+ case DASM_STOP: case DASM_SECTION: goto stop;
+ case DASM_ESC: p++; break;
+ case DASM_REL_EXT: break;
+ case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
+ case DASM_REL_LG: case DASM_REL_PC: pos++; break;
+ case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
+ case DASM_IMM: case DASM_IMM12: case DASM_IMM16:
+ case DASM_IMML8: case DASM_IMML12: case DASM_IMMV8: pos++; break;
+ }
+ }
+ stop: (void)0;
+ }
+ ofs += sec->ofs; /* Next section starts right after current section. */
+ }
+
+ D->codesize = ofs; /* Total size of all code sections */
+ *szp = ofs;
+ return DASM_S_OK;
+}
+
+#ifdef DASM_CHECKS
+#define CK(x, st) \
+ do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
+#else
+#define CK(x, st) ((void)0)
+#endif
+
+/* Pass 3: Encode sections. */
+int dasm_encode(Dst_DECL, void *buffer)
+{
+ dasm_State *D = Dst_REF;
+ char *base = (char *)buffer;
+ unsigned int *cp = (unsigned int *)buffer;
+ int secnum;
+
+ /* Encode all code sections. No support for data sections (yet). */
+ for (secnum = 0; secnum < D->maxsection; secnum++) {
+ dasm_Section *sec = D->sections + secnum;
+ int *b = sec->buf;
+ int *endb = sec->rbuf + sec->pos;
+
+ while (b != endb) {
+ dasm_ActList p = D->actionlist + *b++;
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16);
+ int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
+ switch (action) {
+ case DASM_STOP: case DASM_SECTION: goto stop;
+ case DASM_ESC: *cp++ = *p++; break;
+ case DASM_REL_EXT:
+ n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
+ goto patchrel;
+ case DASM_ALIGN:
+ ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
+ break;
+ case DASM_REL_LG:
+ if (n < 0) {
+ n = (int)((ptrdiff_t)D->globals[-n-10] - (ptrdiff_t)cp - 4);
+ goto patchrel;
+ }
+ /* fallthrough */
+ case DASM_REL_PC:
+ CK(n >= 0, UNDEF_PC);
+ n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4;
+ patchrel:
+ if ((ins & 0x800) == 0) {
+ CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL);
+ cp[-1] |= ((n >> 2) & 0x00ffffff);
+ } else if ((ins & 0x1000)) {
+ CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL);
+ goto patchimml8;
+ } else if ((ins & 0x2000) == 0) {
+ CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL);
+ goto patchimml;
+ } else {
+ CK((n & 3) == 0 && -1020 <= n && n <= 1020, RANGE_REL);
+ n >>= 2;
+ goto patchimml;
+ }
+ break;
+ case DASM_LABEL_LG:
+ ins &= 2047; if (ins >= 20) D->globals[ins-20] = (void *)(base + n);
+ break;
+ case DASM_LABEL_PC: break;
+ case DASM_IMM:
+ cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31);
+ break;
+ case DASM_IMM12:
+ cp[-1] |= dasm_imm12((unsigned int)n);
+ break;
+ case DASM_IMM16:
+ cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff);
+ break;
+ case DASM_IMML8: patchimml8:
+ cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) :
+ ((-n & 0x0f) | ((-n & 0xf0) << 4));
+ break;
+ case DASM_IMML12: case DASM_IMMV8: patchimml:
+ cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n);
+ break;
+ default: *cp++ = ins; break;
+ }
+ }
+ stop: (void)0;
+ }
+ }
+
+ if (base + D->codesize != (char *)cp) /* Check for phase errors. */
+ return DASM_S_PHASE;
+ return DASM_S_OK;
+}
+#undef CK
+
+/* Get PC label offset. */
+int dasm_getpclabel(Dst_DECL, unsigned int pc)
+{
+ dasm_State *D = Dst_REF;
+ if (pc*sizeof(int) < D->pcsize) {
+ int pos = D->pclabels[pc];
+ if (pos < 0) return *DASM_POS2PTR(D, -pos);
+ if (pos > 0) return -1; /* Undefined. */
+ }
+ return -2; /* Unused or out of range. */
+}
+
+#ifdef DASM_CHECKS
+/* Optional sanity checker to call between isolated encoding steps. */
+int dasm_checkstep(Dst_DECL, int secmatch)
+{
+ dasm_State *D = Dst_REF;
+ if (D->status == DASM_S_OK) {
+ int i;
+ for (i = 1; i <= 9; i++) {
+ if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
+ D->lglabels[i] = 0;
+ }
+ }
+ if (D->status == DASM_S_OK && secmatch >= 0 &&
+ D->section != &D->sections[secmatch])
+ D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
+ return D->status;
+}
+#endif
+
diff --git a/LuaJIT-2.1/dynasm/dasm_arm.lua b/LuaJIT-2.1/dynasm/dasm_arm.lua
new file mode 100644
index 00000000..12540d17
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_arm.lua
@@ -0,0 +1,1125 @@
+------------------------------------------------------------------------------
+-- DynASM ARM module.
+--
+-- Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+-- See dynasm.lua for full copyright notice.
+------------------------------------------------------------------------------
+
+-- Module information:
+local _info = {
+ arch = "arm",
+ description = "DynASM ARM module",
+ version = "1.5.0",
+ vernum = 10500,
+ release = "2021-05-02",
+ author = "Mike Pall",
+ license = "MIT",
+}
+
+-- Exported glue functions for the arch-specific module.
+local _M = { _info = _info }
+
+-- Cache library functions.
+local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
+local assert, setmetatable, rawget = assert, setmetatable, rawget
+local _s = string
+local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
+local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
+local concat, sort, insert = table.concat, table.sort, table.insert
+local bit = bit or require("bit")
+local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
+local ror, tohex = bit.ror, bit.tohex
+
+-- Inherited tables and callbacks.
+local g_opt, g_arch
+local wline, werror, wfatal, wwarn
+
+-- Action name list.
+-- CHECK: Keep this in sync with the C code!
+local action_names = {
+ "STOP", "SECTION", "ESC", "REL_EXT",
+ "ALIGN", "REL_LG", "LABEL_LG",
+ "REL_PC", "LABEL_PC", "IMM", "IMM12", "IMM16", "IMML8", "IMML12", "IMMV8",
+}
+
+-- Maximum number of section buffer positions for dasm_put().
+-- CHECK: Keep this in sync with the C code!
+local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
+
+-- Action name -> action number.
+local map_action = {}
+for n,name in ipairs(action_names) do
+ map_action[name] = n-1
+end
+
+-- Action list buffer.
+local actlist = {}
+
+-- Argument list for next dasm_put(). Start with offset 0 into action list.
+local actargs = { 0 }
+
+-- Current number of section buffer positions for dasm_put().
+local secpos = 1
+
+------------------------------------------------------------------------------
+
+-- Dump action names and numbers.
+local function dumpactions(out)
+ out:write("DynASM encoding engine action codes:\n")
+ for n,name in ipairs(action_names) do
+ local num = map_action[name]
+ out:write(format(" %-10s %02X %d\n", name, num, num))
+ end
+ out:write("\n")
+end
+
+-- Write action list buffer as a huge static C array.
+local function writeactions(out, name)
+ local nn = #actlist
+ if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
+ out:write("static const unsigned int ", name, "[", nn, "] = {\n")
+ for i = 1,nn-1 do
+ assert(out:write("0x", tohex(actlist[i]), ",\n"))
+ end
+ assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
+end
+
+------------------------------------------------------------------------------
+
+-- Add word to action list.
+local function wputxw(n)
+ assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
+ actlist[#actlist+1] = n
+end
+
+-- Add action to list with optional arg. Advance buffer pos, too.
+local function waction(action, val, a, num)
+ local w = assert(map_action[action], "bad action name `"..action.."'")
+ wputxw(w * 0x10000 + (val or 0))
+ if a then actargs[#actargs+1] = a end
+ if a or num then secpos = secpos + (num or 1) end
+end
+
+-- Flush action list (intervening C code or buffer pos overflow).
+local function wflush(term)
+ if #actlist == actargs[1] then return end -- Nothing to flush.
+ if not term then waction("STOP") end -- Terminate action list.
+ wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
+ actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
+ secpos = 1 -- The actionlist offset occupies a buffer position, too.
+end
+
+-- Put escaped word.
+local function wputw(n)
+ if n <= 0x000fffff then waction("ESC") end
+ wputxw(n)
+end
+
+-- Reserve position for word.
+local function wpos()
+ local pos = #actlist+1
+ actlist[pos] = ""
+ return pos
+end
+
+-- Store word to reserved position.
+local function wputpos(pos, n)
+ assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
+ if n <= 0x000fffff then
+ insert(actlist, pos+1, n)
+ n = map_action.ESC * 0x10000
+ end
+ actlist[pos] = n
+end
+
+------------------------------------------------------------------------------
+
+-- Global label name -> global label number. With auto assignment on 1st use.
+local next_global = 20
+local map_global = setmetatable({}, { __index = function(t, name)
+ if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
+ local n = next_global
+ if n > 2047 then werror("too many global labels") end
+ next_global = n + 1
+ t[name] = n
+ return n
+end})
+
+-- Dump global labels.
+local function dumpglobals(out, lvl)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("Global labels:\n")
+ for i=20,next_global-1 do
+ out:write(format(" %s\n", t[i]))
+ end
+ out:write("\n")
+end
+
+-- Write global label enum.
+local function writeglobals(out, prefix)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("enum {\n")
+ for i=20,next_global-1 do
+ out:write(" ", prefix, t[i], ",\n")
+ end
+ out:write(" ", prefix, "_MAX\n};\n")
+end
+
+-- Write global label names.
+local function writeglobalnames(out, name)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("static const char *const ", name, "[] = {\n")
+ for i=20,next_global-1 do
+ out:write(" \"", t[i], "\",\n")
+ end
+ out:write(" (const char *)0\n};\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Extern label name -> extern label number. With auto assignment on 1st use.
+local next_extern = 0
+local map_extern_ = {}
+local map_extern = setmetatable({}, { __index = function(t, name)
+ -- No restrictions on the name for now.
+ local n = next_extern
+ if n > 2047 then werror("too many extern labels") end
+ next_extern = n + 1
+ t[name] = n
+ map_extern_[n] = name
+ return n
+end})
+
+-- Dump extern labels.
+local function dumpexterns(out, lvl)
+ out:write("Extern labels:\n")
+ for i=0,next_extern-1 do
+ out:write(format(" %s\n", map_extern_[i]))
+ end
+ out:write("\n")
+end
+
+-- Write extern label names.
+local function writeexternnames(out, name)
+ out:write("static const char *const ", name, "[] = {\n")
+ for i=0,next_extern-1 do
+ out:write(" \"", map_extern_[i], "\",\n")
+ end
+ out:write(" (const char *)0\n};\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Arch-specific maps.
+
+-- Ext. register name -> int. name.
+local map_archdef = { sp = "r13", lr = "r14", pc = "r15", }
+
+-- Int. register name -> ext. name.
+local map_reg_rev = { r13 = "sp", r14 = "lr", r15 = "pc", }
+
+local map_type = {} -- Type name -> { ctype, reg }
+local ctypenum = 0 -- Type number (for Dt... macros).
+
+-- Reverse defines for registers.
+function _M.revdef(s)
+ return map_reg_rev[s] or s
+end
+
+local map_shift = { lsl = 0, lsr = 1, asr = 2, ror = 3, }
+
+local map_cond = {
+ eq = 0, ne = 1, cs = 2, cc = 3, mi = 4, pl = 5, vs = 6, vc = 7,
+ hi = 8, ls = 9, ge = 10, lt = 11, gt = 12, le = 13, al = 14,
+ hs = 2, lo = 3,
+}
+
+------------------------------------------------------------------------------
+
+-- Template strings for ARM instructions.
+local map_op = {
+ -- Basic data processing instructions.
+ and_3 = "e0000000DNPs",
+ eor_3 = "e0200000DNPs",
+ sub_3 = "e0400000DNPs",
+ rsb_3 = "e0600000DNPs",
+ add_3 = "e0800000DNPs",
+ adc_3 = "e0a00000DNPs",
+ sbc_3 = "e0c00000DNPs",
+ rsc_3 = "e0e00000DNPs",
+ tst_2 = "e1100000NP",
+ teq_2 = "e1300000NP",
+ cmp_2 = "e1500000NP",
+ cmn_2 = "e1700000NP",
+ orr_3 = "e1800000DNPs",
+ mov_2 = "e1a00000DPs",
+ bic_3 = "e1c00000DNPs",
+ mvn_2 = "e1e00000DPs",
+
+ and_4 = "e0000000DNMps",
+ eor_4 = "e0200000DNMps",
+ sub_4 = "e0400000DNMps",
+ rsb_4 = "e0600000DNMps",
+ add_4 = "e0800000DNMps",
+ adc_4 = "e0a00000DNMps",
+ sbc_4 = "e0c00000DNMps",
+ rsc_4 = "e0e00000DNMps",
+ tst_3 = "e1100000NMp",
+ teq_3 = "e1300000NMp",
+ cmp_3 = "e1500000NMp",
+ cmn_3 = "e1700000NMp",
+ orr_4 = "e1800000DNMps",
+ mov_3 = "e1a00000DMps",
+ bic_4 = "e1c00000DNMps",
+ mvn_3 = "e1e00000DMps",
+
+ lsl_3 = "e1a00000DMws",
+ lsr_3 = "e1a00020DMws",
+ asr_3 = "e1a00040DMws",
+ ror_3 = "e1a00060DMws",
+ rrx_2 = "e1a00060DMs",
+
+ -- Multiply and multiply-accumulate.
+ mul_3 = "e0000090NMSs",
+ mla_4 = "e0200090NMSDs",
+ umaal_4 = "e0400090DNMSs", -- v6
+ mls_4 = "e0600090DNMSs", -- v6T2
+ umull_4 = "e0800090DNMSs",
+ umlal_4 = "e0a00090DNMSs",
+ smull_4 = "e0c00090DNMSs",
+ smlal_4 = "e0e00090DNMSs",
+
+ -- Halfword multiply and multiply-accumulate.
+ smlabb_4 = "e1000080NMSD", -- v5TE
+ smlatb_4 = "e10000a0NMSD", -- v5TE
+ smlabt_4 = "e10000c0NMSD", -- v5TE
+ smlatt_4 = "e10000e0NMSD", -- v5TE
+ smlawb_4 = "e1200080NMSD", -- v5TE
+ smulwb_3 = "e12000a0NMS", -- v5TE
+ smlawt_4 = "e12000c0NMSD", -- v5TE
+ smulwt_3 = "e12000e0NMS", -- v5TE
+ smlalbb_4 = "e1400080NMSD", -- v5TE
+ smlaltb_4 = "e14000a0NMSD", -- v5TE
+ smlalbt_4 = "e14000c0NMSD", -- v5TE
+ smlaltt_4 = "e14000e0NMSD", -- v5TE
+ smulbb_3 = "e1600080NMS", -- v5TE
+ smultb_3 = "e16000a0NMS", -- v5TE
+ smulbt_3 = "e16000c0NMS", -- v5TE
+ smultt_3 = "e16000e0NMS", -- v5TE
+
+ -- Miscellaneous data processing instructions.
+ clz_2 = "e16f0f10DM", -- v5T
+ rev_2 = "e6bf0f30DM", -- v6
+ rev16_2 = "e6bf0fb0DM", -- v6
+ revsh_2 = "e6ff0fb0DM", -- v6
+ sel_3 = "e6800fb0DNM", -- v6
+ usad8_3 = "e780f010NMS", -- v6
+ usada8_4 = "e7800010NMSD", -- v6
+ rbit_2 = "e6ff0f30DM", -- v6T2
+ movw_2 = "e3000000DW", -- v6T2
+ movt_2 = "e3400000DW", -- v6T2
+ -- Note: the X encodes width-1, not width.
+ sbfx_4 = "e7a00050DMvX", -- v6T2
+ ubfx_4 = "e7e00050DMvX", -- v6T2
+ -- Note: the X encodes the msb field, not the width.
+ bfc_3 = "e7c0001fDvX", -- v6T2
+ bfi_4 = "e7c00010DMvX", -- v6T2
+
+ -- Packing and unpacking instructions.
+ pkhbt_3 = "e6800010DNM", pkhbt_4 = "e6800010DNMv", -- v6
+ pkhtb_3 = "e6800050DNM", pkhtb_4 = "e6800050DNMv", -- v6
+ sxtab_3 = "e6a00070DNM", sxtab_4 = "e6a00070DNMv", -- v6
+ sxtab16_3 = "e6800070DNM", sxtab16_4 = "e6800070DNMv", -- v6
+ sxtah_3 = "e6b00070DNM", sxtah_4 = "e6b00070DNMv", -- v6
+ sxtb_2 = "e6af0070DM", sxtb_3 = "e6af0070DMv", -- v6
+ sxtb16_2 = "e68f0070DM", sxtb16_3 = "e68f0070DMv", -- v6
+ sxth_2 = "e6bf0070DM", sxth_3 = "e6bf0070DMv", -- v6
+ uxtab_3 = "e6e00070DNM", uxtab_4 = "e6e00070DNMv", -- v6
+ uxtab16_3 = "e6c00070DNM", uxtab16_4 = "e6c00070DNMv", -- v6
+ uxtah_3 = "e6f00070DNM", uxtah_4 = "e6f00070DNMv", -- v6
+ uxtb_2 = "e6ef0070DM", uxtb_3 = "e6ef0070DMv", -- v6
+ uxtb16_2 = "e6cf0070DM", uxtb16_3 = "e6cf0070DMv", -- v6
+ uxth_2 = "e6ff0070DM", uxth_3 = "e6ff0070DMv", -- v6
+
+ -- Saturating instructions.
+ qadd_3 = "e1000050DMN", -- v5TE
+ qsub_3 = "e1200050DMN", -- v5TE
+ qdadd_3 = "e1400050DMN", -- v5TE
+ qdsub_3 = "e1600050DMN", -- v5TE
+ -- Note: the X for ssat* encodes sat_imm-1, not sat_imm.
+ ssat_3 = "e6a00010DXM", ssat_4 = "e6a00010DXMp", -- v6
+ usat_3 = "e6e00010DXM", usat_4 = "e6e00010DXMp", -- v6
+ ssat16_3 = "e6a00f30DXM", -- v6
+ usat16_3 = "e6e00f30DXM", -- v6
+
+ -- Parallel addition and subtraction.
+ sadd16_3 = "e6100f10DNM", -- v6
+ sasx_3 = "e6100f30DNM", -- v6
+ ssax_3 = "e6100f50DNM", -- v6
+ ssub16_3 = "e6100f70DNM", -- v6
+ sadd8_3 = "e6100f90DNM", -- v6
+ ssub8_3 = "e6100ff0DNM", -- v6
+ qadd16_3 = "e6200f10DNM", -- v6
+ qasx_3 = "e6200f30DNM", -- v6
+ qsax_3 = "e6200f50DNM", -- v6
+ qsub16_3 = "e6200f70DNM", -- v6
+ qadd8_3 = "e6200f90DNM", -- v6
+ qsub8_3 = "e6200ff0DNM", -- v6
+ shadd16_3 = "e6300f10DNM", -- v6
+ shasx_3 = "e6300f30DNM", -- v6
+ shsax_3 = "e6300f50DNM", -- v6
+ shsub16_3 = "e6300f70DNM", -- v6
+ shadd8_3 = "e6300f90DNM", -- v6
+ shsub8_3 = "e6300ff0DNM", -- v6
+ uadd16_3 = "e6500f10DNM", -- v6
+ uasx_3 = "e6500f30DNM", -- v6
+ usax_3 = "e6500f50DNM", -- v6
+ usub16_3 = "e6500f70DNM", -- v6
+ uadd8_3 = "e6500f90DNM", -- v6
+ usub8_3 = "e6500ff0DNM", -- v6
+ uqadd16_3 = "e6600f10DNM", -- v6
+ uqasx_3 = "e6600f30DNM", -- v6
+ uqsax_3 = "e6600f50DNM", -- v6
+ uqsub16_3 = "e6600f70DNM", -- v6
+ uqadd8_3 = "e6600f90DNM", -- v6
+ uqsub8_3 = "e6600ff0DNM", -- v6
+ uhadd16_3 = "e6700f10DNM", -- v6
+ uhasx_3 = "e6700f30DNM", -- v6
+ uhsax_3 = "e6700f50DNM", -- v6
+ uhsub16_3 = "e6700f70DNM", -- v6
+ uhadd8_3 = "e6700f90DNM", -- v6
+ uhsub8_3 = "e6700ff0DNM", -- v6
+
+ -- Load/store instructions.
+ str_2 = "e4000000DL", str_3 = "e4000000DL", str_4 = "e4000000DL",
+ strb_2 = "e4400000DL", strb_3 = "e4400000DL", strb_4 = "e4400000DL",
+ ldr_2 = "e4100000DL", ldr_3 = "e4100000DL", ldr_4 = "e4100000DL",
+ ldrb_2 = "e4500000DL", ldrb_3 = "e4500000DL", ldrb_4 = "e4500000DL",
+ strh_2 = "e00000b0DL", strh_3 = "e00000b0DL",
+ ldrh_2 = "e01000b0DL", ldrh_3 = "e01000b0DL",
+ ldrd_2 = "e00000d0DL", ldrd_3 = "e00000d0DL", -- v5TE
+ ldrsb_2 = "e01000d0DL", ldrsb_3 = "e01000d0DL",
+ strd_2 = "e00000f0DL", strd_3 = "e00000f0DL", -- v5TE
+ ldrsh_2 = "e01000f0DL", ldrsh_3 = "e01000f0DL",
+
+ ldm_2 = "e8900000oR", ldmia_2 = "e8900000oR", ldmfd_2 = "e8900000oR",
+ ldmda_2 = "e8100000oR", ldmfa_2 = "e8100000oR",
+ ldmdb_2 = "e9100000oR", ldmea_2 = "e9100000oR",
+ ldmib_2 = "e9900000oR", ldmed_2 = "e9900000oR",
+ stm_2 = "e8800000oR", stmia_2 = "e8800000oR", stmfd_2 = "e8800000oR",
+ stmda_2 = "e8000000oR", stmfa_2 = "e8000000oR",
+ stmdb_2 = "e9000000oR", stmea_2 = "e9000000oR",
+ stmib_2 = "e9800000oR", stmed_2 = "e9800000oR",
+ pop_1 = "e8bd0000R", push_1 = "e92d0000R",
+
+ -- Branch instructions.
+ b_1 = "ea000000B",
+ bl_1 = "eb000000B",
+ blx_1 = "e12fff30C",
+ bx_1 = "e12fff10M",
+
+ -- Miscellaneous instructions.
+ nop_0 = "e1a00000",
+ mrs_1 = "e10f0000D",
+ bkpt_1 = "e1200070K", -- v5T
+ svc_1 = "ef000000T", swi_1 = "ef000000T",
+ ud_0 = "e7f001f0",
+
+ -- VFP instructions.
+ ["vadd.f32_3"] = "ee300a00dnm",
+ ["vadd.f64_3"] = "ee300b00Gdnm",
+ ["vsub.f32_3"] = "ee300a40dnm",
+ ["vsub.f64_3"] = "ee300b40Gdnm",
+ ["vmul.f32_3"] = "ee200a00dnm",
+ ["vmul.f64_3"] = "ee200b00Gdnm",
+ ["vnmul.f32_3"] = "ee200a40dnm",
+ ["vnmul.f64_3"] = "ee200b40Gdnm",
+ ["vmla.f32_3"] = "ee000a00dnm",
+ ["vmla.f64_3"] = "ee000b00Gdnm",
+ ["vmls.f32_3"] = "ee000a40dnm",
+ ["vmls.f64_3"] = "ee000b40Gdnm",
+ ["vnmla.f32_3"] = "ee100a40dnm",
+ ["vnmla.f64_3"] = "ee100b40Gdnm",
+ ["vnmls.f32_3"] = "ee100a00dnm",
+ ["vnmls.f64_3"] = "ee100b00Gdnm",
+ ["vdiv.f32_3"] = "ee800a00dnm",
+ ["vdiv.f64_3"] = "ee800b00Gdnm",
+
+ ["vabs.f32_2"] = "eeb00ac0dm",
+ ["vabs.f64_2"] = "eeb00bc0Gdm",
+ ["vneg.f32_2"] = "eeb10a40dm",
+ ["vneg.f64_2"] = "eeb10b40Gdm",
+ ["vsqrt.f32_2"] = "eeb10ac0dm",
+ ["vsqrt.f64_2"] = "eeb10bc0Gdm",
+ ["vcmp.f32_2"] = "eeb40a40dm",
+ ["vcmp.f64_2"] = "eeb40b40Gdm",
+ ["vcmpe.f32_2"] = "eeb40ac0dm",
+ ["vcmpe.f64_2"] = "eeb40bc0Gdm",
+ ["vcmpz.f32_1"] = "eeb50a40d",
+ ["vcmpz.f64_1"] = "eeb50b40Gd",
+ ["vcmpze.f32_1"] = "eeb50ac0d",
+ ["vcmpze.f64_1"] = "eeb50bc0Gd",
+
+ vldr_2 = "ed100a00dl|ed100b00Gdl",
+ vstr_2 = "ed000a00dl|ed000b00Gdl",
+ vldm_2 = "ec900a00or",
+ vldmia_2 = "ec900a00or",
+ vldmdb_2 = "ed100a00or",
+ vpop_1 = "ecbd0a00r",
+ vstm_2 = "ec800a00or",
+ vstmia_2 = "ec800a00or",
+ vstmdb_2 = "ed000a00or",
+ vpush_1 = "ed2d0a00r",
+
+ ["vmov.f32_2"] = "eeb00a40dm|eeb00a00dY", -- #imm is VFPv3 only
+ ["vmov.f64_2"] = "eeb00b40Gdm|eeb00b00GdY", -- #imm is VFPv3 only
+ vmov_2 = "ee100a10Dn|ee000a10nD",
+ vmov_3 = "ec500a10DNm|ec400a10mDN|ec500b10GDNm|ec400b10GmDN",
+
+ vmrs_0 = "eef1fa10",
+ vmrs_1 = "eef10a10D",
+ vmsr_1 = "eee10a10D",
+
+ ["vcvt.s32.f32_2"] = "eebd0ac0dm",
+ ["vcvt.s32.f64_2"] = "eebd0bc0dGm",
+ ["vcvt.u32.f32_2"] = "eebc0ac0dm",
+ ["vcvt.u32.f64_2"] = "eebc0bc0dGm",
+ ["vcvtr.s32.f32_2"] = "eebd0a40dm",
+ ["vcvtr.s32.f64_2"] = "eebd0b40dGm",
+ ["vcvtr.u32.f32_2"] = "eebc0a40dm",
+ ["vcvtr.u32.f64_2"] = "eebc0b40dGm",
+ ["vcvt.f32.s32_2"] = "eeb80ac0dm",
+ ["vcvt.f64.s32_2"] = "eeb80bc0GdFm",
+ ["vcvt.f32.u32_2"] = "eeb80a40dm",
+ ["vcvt.f64.u32_2"] = "eeb80b40GdFm",
+ ["vcvt.f32.f64_2"] = "eeb70bc0dGm",
+ ["vcvt.f64.f32_2"] = "eeb70ac0GdFm",
+
+ -- VFPv4 only:
+ ["vfma.f32_3"] = "eea00a00dnm",
+ ["vfma.f64_3"] = "eea00b00Gdnm",
+ ["vfms.f32_3"] = "eea00a40dnm",
+ ["vfms.f64_3"] = "eea00b40Gdnm",
+ ["vfnma.f32_3"] = "ee900a40dnm",
+ ["vfnma.f64_3"] = "ee900b40Gdnm",
+ ["vfnms.f32_3"] = "ee900a00dnm",
+ ["vfnms.f64_3"] = "ee900b00Gdnm",
+
+ -- NYI: Advanced SIMD instructions.
+
+ -- NYI: I have no need for these instructions right now:
+ -- swp, swpb, strex, ldrex, strexd, ldrexd, strexb, ldrexb, strexh, ldrexh
+ -- msr, nopv6, yield, wfe, wfi, sev, dbg, bxj, smc, srs, rfe
+ -- cps, setend, pli, pld, pldw, clrex, dsb, dmb, isb
+ -- stc, ldc, mcr, mcr2, mrc, mrc2, mcrr, mcrr2, mrrc, mrrc2, cdp, cdp2
+}
+
+-- Add mnemonics for "s" variants.
+do
+ local t = {}
+ for k,v in pairs(map_op) do
+ if sub(v, -1) == "s" then
+ local v2 = sub(v, 1, 2)..char(byte(v, 3)+1)..sub(v, 4, -2)
+ t[sub(k, 1, -3).."s"..sub(k, -2)] = v2
+ end
+ end
+ for k,v in pairs(t) do
+ map_op[k] = v
+ end
+end
+
+------------------------------------------------------------------------------
+
+local function parse_gpr(expr)
+ local tname, ovreg = match(expr, "^([%w_]+):(r1?[0-9])$")
+ local tp = map_type[tname or expr]
+ if tp then
+ local reg = ovreg or tp.reg
+ if not reg then
+ werror("type `"..(tname or expr).."' needs a register override")
+ end
+ expr = reg
+ end
+ local r = match(expr, "^r(1?[0-9])$")
+ if r then
+ r = tonumber(r)
+ if r <= 15 then return r, tp end
+ end
+ werror("bad register name `"..expr.."'")
+end
+
+local function parse_gpr_pm(expr)
+ local pm, expr2 = match(expr, "^([+-]?)(.*)$")
+ return parse_gpr(expr2), (pm == "-")
+end
+
+local function parse_vr(expr, tp)
+ local t, r = match(expr, "^([sd])([0-9]+)$")
+ if t == tp then
+ r = tonumber(r)
+ if r <= 31 then
+ if t == "s" then return shr(r, 1), band(r, 1) end
+ return band(r, 15), shr(r, 4)
+ end
+ end
+ werror("bad register name `"..expr.."'")
+end
+
+local function parse_reglist(reglist)
+ reglist = match(reglist, "^{%s*([^}]*)}$")
+ if not reglist then werror("register list expected") end
+ local rr = 0
+ for p in gmatch(reglist..",", "%s*([^,]*),") do
+ local rbit = shl(1, parse_gpr(gsub(p, "%s+$", "")))
+ if band(rr, rbit) ~= 0 then
+ werror("duplicate register `"..p.."'")
+ end
+ rr = rr + rbit
+ end
+ return rr
+end
+
+local function parse_vrlist(reglist)
+ local ta, ra, tb, rb = match(reglist,
+ "^{%s*([sd])([0-9]+)%s*%-%s*([sd])([0-9]+)%s*}$")
+ ra, rb = tonumber(ra), tonumber(rb)
+ if ta and ta == tb and ra and rb and ra <= 31 and rb <= 31 and ra <= rb then
+ local nr = rb+1 - ra
+ if ta == "s" then
+ return shl(shr(ra,1),12)+shl(band(ra,1),22) + nr
+ else
+ return shl(band(ra,15),12)+shl(shr(ra,4),22) + nr*2 + 0x100
+ end
+ end
+ werror("register list expected")
+end
+
+local function parse_imm(imm, bits, shift, scale, signed)
+ imm = match(imm, "^#(.*)$")
+ if not imm then werror("expected immediate operand") end
+ local n = tonumber(imm)
+ if n then
+ local m = sar(n, scale)
+ if shl(m, scale) == n then
+ if signed then
+ local s = sar(m, bits-1)
+ if s == 0 then return shl(m, shift)
+ elseif s == -1 then return shl(m + shl(1, bits), shift) end
+ else
+ if sar(m, bits) == 0 then return shl(m, shift) end
+ end
+ end
+ werror("out of range immediate `"..imm.."'")
+ else
+ waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
+ return 0
+ end
+end
+
+local function parse_imm12(imm)
+ local n = tonumber(imm)
+ if n then
+ local m = band(n)
+ for i=0,-15,-1 do
+ if shr(m, 8) == 0 then return m + shl(band(i, 15), 8) end
+ m = ror(m, 2)
+ end
+ werror("out of range immediate `"..imm.."'")
+ else
+ waction("IMM12", 0, imm)
+ return 0
+ end
+end
+
+local function parse_imm16(imm)
+ imm = match(imm, "^#(.*)$")
+ if not imm then werror("expected immediate operand") end
+ local n = tonumber(imm)
+ if n then
+ if shr(n, 16) == 0 then return band(n, 0x0fff) + shl(band(n, 0xf000), 4) end
+ werror("out of range immediate `"..imm.."'")
+ else
+ waction("IMM16", 32*16, imm)
+ return 0
+ end
+end
+
+local function parse_imm_load(imm, ext)
+ local n = tonumber(imm)
+ if n then
+ if ext then
+ if n >= -255 and n <= 255 then
+ local up = 0x00800000
+ if n < 0 then n = -n; up = 0 end
+ return shl(band(n, 0xf0), 4) + band(n, 0x0f) + up
+ end
+ else
+ if n >= -4095 and n <= 4095 then
+ if n >= 0 then return n+0x00800000 end
+ return -n
+ end
+ end
+ werror("out of range immediate `"..imm.."'")
+ else
+ waction(ext and "IMML8" or "IMML12", 32768 + shl(ext and 8 or 12, 5), imm)
+ return 0
+ end
+end
+
+local function parse_shift(shift, gprok)
+ if shift == "rrx" then
+ return 3 * 32
+ else
+ local s, s2 = match(shift, "^(%S+)%s*(.*)$")
+ s = map_shift[s]
+ if not s then werror("expected shift operand") end
+ if sub(s2, 1, 1) == "#" then
+ return parse_imm(s2, 5, 7, 0, false) + shl(s, 5)
+ else
+ if not gprok then werror("expected immediate shift operand") end
+ return shl(parse_gpr(s2), 8) + shl(s, 5) + 16
+ end
+ end
+end
+
+local function parse_label(label, def)
+ local prefix = sub(label, 1, 2)
+ -- =>label (pc label reference)
+ if prefix == "=>" then
+ return "PC", 0, sub(label, 3)
+ end
+ -- ->name (global label reference)
+ if prefix == "->" then
+ return "LG", map_global[sub(label, 3)]
+ end
+ if def then
+ -- [1-9] (local label definition)
+ if match(label, "^[1-9]$") then
+ return "LG", 10+tonumber(label)
+ end
+ else
+ -- [<>][1-9] (local label reference)
+ local dir, lnum = match(label, "^([<>])([1-9])$")
+ if dir then -- Fwd: 1-9, Bkwd: 11-19.
+ return "LG", lnum + (dir == ">" and 0 or 10)
+ end
+ -- extern label (extern label reference)
+ local extname = match(label, "^extern%s+(%S+)$")
+ if extname then
+ return "EXT", map_extern[extname]
+ end
+ end
+ werror("bad label `"..label.."'")
+end
+
+local function parse_load(params, nparams, n, op)
+ local oplo = band(op, 255)
+ local ext, ldrd = (oplo ~= 0), (oplo == 208)
+ local d
+ if (ldrd or oplo == 240) then
+ d = band(shr(op, 12), 15)
+ if band(d, 1) ~= 0 then werror("odd destination register") end
+ end
+ local pn = params[n]
+ local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
+ local p2 = params[n+1]
+ if not p1 then
+ if not p2 then
+ if match(pn, "^[<>=%-]") or match(pn, "^extern%s+") then
+ local mode, n, s = parse_label(pn, false)
+ waction("REL_"..mode, n + (ext and 0x1800 or 0x0800), s, 1)
+ return op + 15 * 65536 + 0x01000000 + (ext and 0x00400000 or 0)
+ end
+ local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
+ if reg and tailr ~= "" then
+ local d, tp = parse_gpr(reg)
+ if tp then
+ waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12),
+ format(tp.ctypefmt, tailr))
+ return op + shl(d, 16) + 0x01000000 + (ext and 0x00400000 or 0)
+ end
+ end
+ end
+ werror("expected address operand")
+ end
+ if wb == "!" then op = op + 0x00200000 end
+ if p2 then
+ if wb == "!" then werror("bad use of '!'") end
+ local p3 = params[n+2]
+ op = op + shl(parse_gpr(p1), 16)
+ local imm = match(p2, "^#(.*)$")
+ if imm then
+ local m = parse_imm_load(imm, ext)
+ if p3 then werror("too many parameters") end
+ op = op + m + (ext and 0x00400000 or 0)
+ else
+ local m, neg = parse_gpr_pm(p2)
+ if ldrd and (m == d or m-1 == d) then werror("register conflict") end
+ op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000)
+ if p3 then op = op + parse_shift(p3) end
+ end
+ else
+ local p1a, p2 = match(p1, "^([^,%s]*)%s*(.*)$")
+ op = op + shl(parse_gpr(p1a), 16) + 0x01000000
+ if p2 ~= "" then
+ local imm = match(p2, "^,%s*#(.*)$")
+ if imm then
+ local m = parse_imm_load(imm, ext)
+ op = op + m + (ext and 0x00400000 or 0)
+ else
+ local p2a, p3 = match(p2, "^,%s*([^,%s]*)%s*,?%s*(.*)$")
+ local m, neg = parse_gpr_pm(p2a)
+ if ldrd and (m == d or m-1 == d) then werror("register conflict") end
+ op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000)
+ if p3 ~= "" then
+ if ext then werror("too many parameters") end
+ op = op + parse_shift(p3)
+ end
+ end
+ else
+ if wb == "!" then werror("bad use of '!'") end
+ op = op + (ext and 0x00c00000 or 0x00800000)
+ end
+ end
+ return op
+end
+
+local function parse_vload(q)
+ local reg, imm = match(q, "^%[%s*([^,%s]*)%s*(.*)%]$")
+ if reg then
+ local d = shl(parse_gpr(reg), 16)
+ if imm == "" then return d end
+ imm = match(imm, "^,%s*#(.*)$")
+ if imm then
+ local n = tonumber(imm)
+ if n then
+ if n >= -1020 and n <= 1020 and n%4 == 0 then
+ return d + (n >= 0 and n/4+0x00800000 or -n/4)
+ end
+ werror("out of range immediate `"..imm.."'")
+ else
+ waction("IMMV8", 32768 + 32*8, imm)
+ return d
+ end
+ end
+ else
+ if match(q, "^[<>=%-]") or match(q, "^extern%s+") then
+ local mode, n, s = parse_label(q, false)
+ waction("REL_"..mode, n + 0x2800, s, 1)
+ return 15 * 65536
+ end
+ local reg, tailr = match(q, "^([%w_:]+)%s*(.*)$")
+ if reg and tailr ~= "" then
+ local d, tp = parse_gpr(reg)
+ if tp then
+ waction("IMMV8", 32768 + 32*8, format(tp.ctypefmt, tailr))
+ return shl(d, 16)
+ end
+ end
+ end
+ werror("expected address operand")
+end
+
+------------------------------------------------------------------------------
+
+-- Handle opcodes defined with template strings.
+local function parse_template(params, template, nparams, pos)
+ local op = tonumber(sub(template, 1, 8), 16)
+ local n = 1
+ local vr = "s"
+
+ -- Process each character.
+ for p in gmatch(sub(template, 9), ".") do
+ local q = params[n]
+ if p == "D" then
+ op = op + shl(parse_gpr(q), 12); n = n + 1
+ elseif p == "N" then
+ op = op + shl(parse_gpr(q), 16); n = n + 1
+ elseif p == "S" then
+ op = op + shl(parse_gpr(q), 8); n = n + 1
+ elseif p == "M" then
+ op = op + parse_gpr(q); n = n + 1
+ elseif p == "d" then
+ local r,h = parse_vr(q, vr); op = op+shl(r,12)+shl(h,22); n = n + 1
+ elseif p == "n" then
+ local r,h = parse_vr(q, vr); op = op+shl(r,16)+shl(h,7); n = n + 1
+ elseif p == "m" then
+ local r,h = parse_vr(q, vr); op = op+r+shl(h,5); n = n + 1
+ elseif p == "P" then
+ local imm = match(q, "^#(.*)$")
+ if imm then
+ op = op + parse_imm12(imm) + 0x02000000
+ else
+ op = op + parse_gpr(q)
+ end
+ n = n + 1
+ elseif p == "p" then
+ op = op + parse_shift(q, true); n = n + 1
+ elseif p == "L" then
+ op = parse_load(params, nparams, n, op)
+ elseif p == "l" then
+ op = op + parse_vload(q)
+ elseif p == "B" then
+ local mode, n, s = parse_label(q, false)
+ waction("REL_"..mode, n, s, 1)
+ elseif p == "C" then -- blx gpr vs. blx label.
+ if match(q, "^([%w_]+):(r1?[0-9])$") or match(q, "^r(1?[0-9])$") then
+ op = op + parse_gpr(q)
+ else
+ if op < 0xe0000000 then werror("unconditional instruction") end
+ local mode, n, s = parse_label(q, false)
+ waction("REL_"..mode, n, s, 1)
+ op = 0xfa000000
+ end
+ elseif p == "F" then
+ vr = "s"
+ elseif p == "G" then
+ vr = "d"
+ elseif p == "o" then
+ local r, wb = match(q, "^([^!]*)(!?)$")
+ op = op + shl(parse_gpr(r), 16) + (wb == "!" and 0x00200000 or 0)
+ n = n + 1
+ elseif p == "R" then
+ op = op + parse_reglist(q); n = n + 1
+ elseif p == "r" then
+ op = op + parse_vrlist(q); n = n + 1
+ elseif p == "W" then
+ op = op + parse_imm16(q); n = n + 1
+ elseif p == "v" then
+ op = op + parse_imm(q, 5, 7, 0, false); n = n + 1
+ elseif p == "w" then
+ local imm = match(q, "^#(.*)$")
+ if imm then
+ op = op + parse_imm(q, 5, 7, 0, false); n = n + 1
+ else
+ op = op + shl(parse_gpr(q), 8) + 16
+ end
+ elseif p == "X" then
+ op = op + parse_imm(q, 5, 16, 0, false); n = n + 1
+ elseif p == "Y" then
+ local imm = tonumber(match(q, "^#(.*)$")); n = n + 1
+ if not imm or shr(imm, 8) ~= 0 then
+ werror("bad immediate operand")
+ end
+ op = op + shl(band(imm, 0xf0), 12) + band(imm, 0x0f)
+ elseif p == "K" then
+ local imm = tonumber(match(q, "^#(.*)$")); n = n + 1
+ if not imm or shr(imm, 16) ~= 0 then
+ werror("bad immediate operand")
+ end
+ op = op + shl(band(imm, 0xfff0), 4) + band(imm, 0x000f)
+ elseif p == "T" then
+ op = op + parse_imm(q, 24, 0, 0, false); n = n + 1
+ elseif p == "s" then
+ -- Ignored.
+ else
+ assert(false)
+ end
+ end
+ wputpos(pos, op)
+end
+
+map_op[".template__"] = function(params, template, nparams)
+ if not params then return template:gsub("%x%x%x%x%x%x%x%x", "") end
+
+ -- Limit number of section buffer positions used by a single dasm_put().
+ -- A single opcode needs a maximum of 3 positions.
+ if secpos+3 > maxsecpos then wflush() end
+ local pos = wpos()
+ local lpos, apos, spos = #actlist, #actargs, secpos
+
+ local ok, err
+ for t in gmatch(template, "[^|]+") do
+ ok, err = pcall(parse_template, params, t, nparams, pos)
+ if ok then return end
+ secpos = spos
+ actlist[lpos+1] = nil
+ actlist[lpos+2] = nil
+ actlist[lpos+3] = nil
+ actargs[apos+1] = nil
+ actargs[apos+2] = nil
+ actargs[apos+3] = nil
+ end
+ error(err, 0)
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcode to mark the position where the action list is to be emitted.
+map_op[".actionlist_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeactions(out, name) end)
+end
+
+-- Pseudo-opcode to mark the position where the global enum is to be emitted.
+map_op[".globals_1"] = function(params)
+ if not params then return "prefix" end
+ local prefix = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeglobals(out, prefix) end)
+end
+
+-- Pseudo-opcode to mark the position where the global names are to be emitted.
+map_op[".globalnames_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeglobalnames(out, name) end)
+end
+
+-- Pseudo-opcode to mark the position where the extern names are to be emitted.
+map_op[".externnames_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeexternnames(out, name) end)
+end
+
+------------------------------------------------------------------------------
+
+-- Label pseudo-opcode (converted from trailing colon form).
+map_op[".label_1"] = function(params)
+ if not params then return "[1-9] | ->global | =>pcexpr" end
+ if secpos+1 > maxsecpos then wflush() end
+ local mode, n, s = parse_label(params[1], true)
+ if mode == "EXT" then werror("bad label definition") end
+ waction("LABEL_"..mode, n, s, 1)
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcodes for data storage.
+map_op[".long_*"] = function(params)
+ if not params then return "imm..." end
+ for _,p in ipairs(params) do
+ local n = tonumber(p)
+ if not n then werror("bad immediate `"..p.."'") end
+ if n < 0 then n = n + 2^32 end
+ wputw(n)
+ if secpos+2 > maxsecpos then wflush() end
+ end
+end
+
+-- Alignment pseudo-opcode.
+map_op[".align_1"] = function(params)
+ if not params then return "numpow2" end
+ if secpos+1 > maxsecpos then wflush() end
+ local align = tonumber(params[1])
+ if align then
+ local x = align
+ -- Must be a power of 2 in the range (2 ... 256).
+ for i=1,8 do
+ x = x / 2
+ if x == 1 then
+ waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
+ return
+ end
+ end
+ end
+ werror("bad alignment")
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcode for (primitive) type definitions (map to C types).
+map_op[".type_3"] = function(params, nparams)
+ if not params then
+ return nparams == 2 and "name, ctype" or "name, ctype, reg"
+ end
+ local name, ctype, reg = params[1], params[2], params[3]
+ if not match(name, "^[%a_][%w_]*$") then
+ werror("bad type name `"..name.."'")
+ end
+ local tp = map_type[name]
+ if tp then
+ werror("duplicate type `"..name.."'")
+ end
+ -- Add #type to defines. A bit unclean to put it in map_archdef.
+ map_archdef["#"..name] = "sizeof("..ctype..")"
+ -- Add new type and emit shortcut define.
+ local num = ctypenum + 1
+ map_type[name] = {
+ ctype = ctype,
+ ctypefmt = format("Dt%X(%%s)", num),
+ reg = reg,
+ }
+ wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
+ ctypenum = num
+end
+map_op[".type_2"] = map_op[".type_3"]
+
+-- Dump type definitions.
+local function dumptypes(out, lvl)
+ local t = {}
+ for name in pairs(map_type) do t[#t+1] = name end
+ sort(t)
+ out:write("Type definitions:\n")
+ for _,name in ipairs(t) do
+ local tp = map_type[name]
+ local reg = tp.reg or ""
+ out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
+ end
+ out:write("\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Set the current section.
+function _M.section(num)
+ waction("SECTION", num)
+ wflush(true) -- SECTION is a terminal action.
+end
+
+------------------------------------------------------------------------------
+
+-- Dump architecture description.
+function _M.dumparch(out)
+ out:write(format("DynASM %s version %s, released %s\n\n",
+ _info.arch, _info.version, _info.release))
+ dumpactions(out)
+end
+
+-- Dump all user defined elements.
+function _M.dumpdef(out, lvl)
+ dumptypes(out, lvl)
+ dumpglobals(out, lvl)
+ dumpexterns(out, lvl)
+end
+
+------------------------------------------------------------------------------
+
+-- Pass callbacks from/to the DynASM core.
+function _M.passcb(wl, we, wf, ww)
+ wline, werror, wfatal, wwarn = wl, we, wf, ww
+ return wflush
+end
+
+-- Setup the arch-specific module.
+function _M.setup(arch, opt)
+ g_arch, g_opt = arch, opt
+end
+
+-- Merge the core maps and the arch-specific maps.
+function _M.mergemaps(map_coreop, map_def)
+ setmetatable(map_op, { __index = function(t, k)
+ local v = map_coreop[k]
+ if v then return v end
+ local k1, cc, k2 = match(k, "^(.-)(..)([._].*)$")
+ local cv = map_cond[cc]
+ if cv then
+ local v = rawget(t, k1..k2)
+ if type(v) == "string" then
+ local scv = format("%x", cv)
+ return gsub(scv..sub(v, 2), "|e", "|"..scv)
+ end
+ end
+ end })
+ setmetatable(map_def, { __index = map_archdef })
+ return map_op, map_def
+end
+
+return _M
+
+------------------------------------------------------------------------------
+
diff --git a/LuaJIT-2.1/dynasm/dasm_arm64.h b/LuaJIT-2.1/dynasm/dasm_arm64.h
new file mode 100644
index 00000000..a922a4ae
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_arm64.h
@@ -0,0 +1,558 @@
+/*
+** DynASM ARM64 encoding engine.
+** Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+** Released under the MIT license. See dynasm.lua for full copyright notice.
+*/
+
+#include
+#include
+#include
+#include
+
+#define DASM_ARCH "arm64"
+
+#ifndef DASM_EXTERN
+#define DASM_EXTERN(a,b,c,d) 0
+#endif
+
+/* Action definitions. */
+enum {
+ DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
+ /* The following actions need a buffer position. */
+ DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
+ /* The following actions also have an argument. */
+ DASM_REL_PC, DASM_LABEL_PC, DASM_REL_A,
+ DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
+ DASM_IMMV, DASM_VREG,
+ DASM__MAX
+};
+
+/* Maximum number of section buffer positions for a single dasm_put() call. */
+#define DASM_MAXSECPOS 25
+
+/* DynASM encoder status codes. Action list offset or number are or'ed in. */
+#define DASM_S_OK 0x00000000
+#define DASM_S_NOMEM 0x01000000
+#define DASM_S_PHASE 0x02000000
+#define DASM_S_MATCH_SEC 0x03000000
+#define DASM_S_RANGE_I 0x11000000
+#define DASM_S_RANGE_SEC 0x12000000
+#define DASM_S_RANGE_LG 0x13000000
+#define DASM_S_RANGE_PC 0x14000000
+#define DASM_S_RANGE_REL 0x15000000
+#define DASM_S_RANGE_VREG 0x16000000
+#define DASM_S_UNDEF_LG 0x21000000
+#define DASM_S_UNDEF_PC 0x22000000
+
+/* Macros to convert positions (8 bit section + 24 bit index). */
+#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
+#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
+#define DASM_SEC2POS(sec) ((sec)<<24)
+#define DASM_POS2SEC(pos) ((pos)>>24)
+#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
+
+/* Action list type. */
+typedef const unsigned int *dasm_ActList;
+
+/* Per-section structure. */
+typedef struct dasm_Section {
+ int *rbuf; /* Biased buffer pointer (negative section bias). */
+ int *buf; /* True buffer pointer. */
+ size_t bsize; /* Buffer size in bytes. */
+ int pos; /* Biased buffer position. */
+ int epos; /* End of biased buffer position - max single put. */
+ int ofs; /* Byte offset into section. */
+} dasm_Section;
+
+/* Core structure holding the DynASM encoding state. */
+struct dasm_State {
+ size_t psize; /* Allocated size of this structure. */
+ dasm_ActList actionlist; /* Current actionlist pointer. */
+ int *lglabels; /* Local/global chain/pos ptrs. */
+ size_t lgsize;
+ int *pclabels; /* PC label chains/pos ptrs. */
+ size_t pcsize;
+ void **globals; /* Array of globals. */
+ dasm_Section *section; /* Pointer to active section. */
+ size_t codesize; /* Total size of all code sections. */
+ int maxsection; /* 0 <= sectionidx < maxsection. */
+ int status; /* Status code. */
+ dasm_Section sections[1]; /* All sections. Alloc-extended. */
+};
+
+/* The size of the core structure depends on the max. number of sections. */
+#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
+
+
+/* Initialize DynASM state. */
+void dasm_init(Dst_DECL, int maxsection)
+{
+ dasm_State *D;
+ size_t psz = 0;
+ Dst_REF = NULL;
+ DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
+ D = Dst_REF;
+ D->psize = psz;
+ D->lglabels = NULL;
+ D->lgsize = 0;
+ D->pclabels = NULL;
+ D->pcsize = 0;
+ D->globals = NULL;
+ D->maxsection = maxsection;
+ memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section));
+}
+
+/* Free DynASM state. */
+void dasm_free(Dst_DECL)
+{
+ dasm_State *D = Dst_REF;
+ int i;
+ for (i = 0; i < D->maxsection; i++)
+ if (D->sections[i].buf)
+ DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
+ if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
+ if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
+ DASM_M_FREE(Dst, D, D->psize);
+}
+
+/* Setup global label array. Must be called before dasm_setup(). */
+void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
+{
+ dasm_State *D = Dst_REF;
+ D->globals = gl;
+ DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
+}
+
+/* Grow PC label array. Can be called after dasm_setup(), too. */
+void dasm_growpc(Dst_DECL, unsigned int maxpc)
+{
+ dasm_State *D = Dst_REF;
+ size_t osz = D->pcsize;
+ DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
+ memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
+}
+
+/* Setup encoder. */
+void dasm_setup(Dst_DECL, const void *actionlist)
+{
+ dasm_State *D = Dst_REF;
+ int i;
+ D->actionlist = (dasm_ActList)actionlist;
+ D->status = DASM_S_OK;
+ D->section = &D->sections[0];
+ memset((void *)D->lglabels, 0, D->lgsize);
+ if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
+ for (i = 0; i < D->maxsection; i++) {
+ D->sections[i].pos = DASM_SEC2POS(i);
+ D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos;
+ D->sections[i].ofs = 0;
+ }
+}
+
+
+#ifdef DASM_CHECKS
+#define CK(x, st) \
+ do { if (!(x)) { \
+ D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
+#define CKPL(kind, st) \
+ do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
+ D->status = DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
+#else
+#define CK(x, st) ((void)0)
+#define CKPL(kind, st) ((void)0)
+#endif
+
+static int dasm_imm12(unsigned int n)
+{
+ if ((n >> 12) == 0)
+ return n;
+ else if ((n & 0xff000fff) == 0)
+ return (n >> 12) | 0x1000;
+ else
+ return -1;
+}
+
+static int dasm_ffs(unsigned long long x)
+{
+ int n = -1;
+ while (x) { x >>= 1; n++; }
+ return n;
+}
+
+static int dasm_imm13(int lo, int hi)
+{
+ int inv = 0, w = 64, s = 0xfff, xa, xb;
+ unsigned long long n = (((unsigned long long)hi) << 32) | (unsigned int)lo;
+ unsigned long long m = 1ULL, a, b, c;
+ if (n & 1) { n = ~n; inv = 1; }
+ a = n & (unsigned long long)-(long long)n;
+ b = (n+a)&(unsigned long long)-(long long)(n+a);
+ c = (n+a-b)&(unsigned long long)-(long long)(n+a-b);
+ xa = dasm_ffs(a); xb = dasm_ffs(b);
+ if (c) {
+ w = dasm_ffs(c) - xa;
+ if (w == 32) m = 0x0000000100000001UL;
+ else if (w == 16) m = 0x0001000100010001UL;
+ else if (w == 8) m = 0x0101010101010101UL;
+ else if (w == 4) m = 0x1111111111111111UL;
+ else if (w == 2) m = 0x5555555555555555UL;
+ else return -1;
+ s = (-2*w & 0x3f) - 1;
+ } else if (!a) {
+ return -1;
+ } else if (xb == -1) {
+ xb = 64;
+ }
+ if ((b-a) * m != n) return -1;
+ if (inv) {
+ return ((w - xb) << 6) | (s+w+xa-xb);
+ } else {
+ return ((w - xa) << 6) | (s+xb-xa);
+ }
+ return -1;
+}
+
+/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
+void dasm_put(Dst_DECL, int start, ...)
+{
+ va_list ap;
+ dasm_State *D = Dst_REF;
+ dasm_ActList p = D->actionlist + start;
+ dasm_Section *sec = D->section;
+ int pos = sec->pos, ofs = sec->ofs;
+ int *b;
+
+ if (pos >= sec->epos) {
+ DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
+ sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
+ sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
+ sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
+ }
+
+ b = sec->rbuf;
+ b[pos++] = start;
+
+ va_start(ap, start);
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16);
+ if (action >= DASM__MAX) {
+ ofs += 4;
+ } else {
+ int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
+ switch (action) {
+ case DASM_STOP: goto stop;
+ case DASM_SECTION:
+ n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
+ D->section = &D->sections[n]; goto stop;
+ case DASM_ESC: p++; ofs += 4; break;
+ case DASM_REL_EXT: if ((ins & 0x8000)) ofs += 8; break;
+ case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
+ case DASM_REL_LG:
+ n = (ins & 2047) - 10; pl = D->lglabels + n;
+ /* Bkwd rel or global. */
+ if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
+ pl += 10; n = *pl;
+ if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
+ goto linkrel;
+ case DASM_REL_PC:
+ pl = D->pclabels + n; CKPL(pc, PC);
+ putrel:
+ n = *pl;
+ if (n < 0) { /* Label exists. Get label pos and store it. */
+ b[pos] = -n;
+ } else {
+ linkrel:
+ b[pos] = n; /* Else link to rel chain, anchored at label. */
+ *pl = pos;
+ }
+ pos++;
+ if ((ins & 0x8000)) ofs += 8;
+ break;
+ case DASM_REL_A:
+ b[pos++] = n;
+ b[pos++] = va_arg(ap, int);
+ break;
+ case DASM_LABEL_LG:
+ pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
+ case DASM_LABEL_PC:
+ pl = D->pclabels + n; CKPL(pc, PC);
+ putlabel:
+ n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
+ while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
+ }
+ *pl = -pos; /* Label exists now. */
+ b[pos++] = ofs; /* Store pass1 offset estimate. */
+ break;
+ case DASM_IMM:
+ CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
+ n >>= ((ins>>10)&31);
+#ifdef DASM_CHECKS
+ if ((ins & 0x8000))
+ CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
+ else
+ CK((n>>((ins>>5)&31)) == 0, RANGE_I);
+#endif
+ b[pos++] = n;
+ break;
+ case DASM_IMM6:
+ CK((n >> 6) == 0, RANGE_I);
+ b[pos++] = n;
+ break;
+ case DASM_IMM12:
+ CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
+ b[pos++] = n;
+ break;
+ case DASM_IMM13W:
+ CK(dasm_imm13(n, n) != -1, RANGE_I);
+ b[pos++] = n;
+ break;
+ case DASM_IMM13X: {
+ int m = va_arg(ap, int);
+ CK(dasm_imm13(n, m) != -1, RANGE_I);
+ b[pos++] = n;
+ b[pos++] = m;
+ break;
+ }
+ case DASM_IMML: {
+#ifdef DASM_CHECKS
+ int scale = (ins & 3);
+ CK((!(n & ((1<>scale) < 4096) ||
+ (unsigned int)(n+256) < 512, RANGE_I);
+#endif
+ b[pos++] = n;
+ break;
+ }
+ case DASM_IMMV:
+ ofs += 4;
+ b[pos++] = n;
+ break;
+ case DASM_VREG:
+ CK(n < 32, RANGE_VREG);
+ b[pos++] = n;
+ break;
+ }
+ }
+ }
+stop:
+ va_end(ap);
+ sec->pos = pos;
+ sec->ofs = ofs;
+}
+#undef CK
+
+/* Pass 2: Link sections, shrink aligns, fix label offsets. */
+int dasm_link(Dst_DECL, size_t *szp)
+{
+ dasm_State *D = Dst_REF;
+ int secnum;
+ int ofs = 0;
+
+#ifdef DASM_CHECKS
+ *szp = 0;
+ if (D->status != DASM_S_OK) return D->status;
+ {
+ int pc;
+ for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
+ if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
+ }
+#endif
+
+ { /* Handle globals not defined in this translation unit. */
+ int idx;
+ for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
+ int n = D->lglabels[idx];
+ /* Undefined label: Collapse rel chain and replace with marker (< 0). */
+ while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
+ }
+ }
+
+ /* Combine all code sections. No support for data sections (yet). */
+ for (secnum = 0; secnum < D->maxsection; secnum++) {
+ dasm_Section *sec = D->sections + secnum;
+ int *b = sec->rbuf;
+ int pos = DASM_SEC2POS(secnum);
+ int lastpos = sec->pos;
+
+ while (pos != lastpos) {
+ dasm_ActList p = D->actionlist + b[pos++];
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16);
+ switch (action) {
+ case DASM_STOP: case DASM_SECTION: goto stop;
+ case DASM_ESC: p++; break;
+ case DASM_REL_EXT: break;
+ case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
+ case DASM_REL_LG: case DASM_REL_PC: pos++; break;
+ case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
+ case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
+ case DASM_IMML: case DASM_IMMV: case DASM_VREG: pos++; break;
+ case DASM_IMM13X: case DASM_REL_A: pos += 2; break;
+ }
+ }
+ stop: (void)0;
+ }
+ ofs += sec->ofs; /* Next section starts right after current section. */
+ }
+
+ D->codesize = ofs; /* Total size of all code sections */
+ *szp = ofs;
+ return DASM_S_OK;
+}
+
+#ifdef DASM_CHECKS
+#define CK(x, st) \
+ do { if (!(x)) return DASM_S_##st|(int)(p-D->actionlist-1); } while (0)
+#else
+#define CK(x, st) ((void)0)
+#endif
+
+/* Pass 3: Encode sections. */
+int dasm_encode(Dst_DECL, void *buffer)
+{
+ dasm_State *D = Dst_REF;
+ char *base = (char *)buffer;
+ unsigned int *cp = (unsigned int *)buffer;
+ int secnum;
+
+ /* Encode all code sections. No support for data sections (yet). */
+ for (secnum = 0; secnum < D->maxsection; secnum++) {
+ dasm_Section *sec = D->sections + secnum;
+ int *b = sec->buf;
+ int *endb = sec->rbuf + sec->pos;
+
+ while (b != endb) {
+ dasm_ActList p = D->actionlist + *b++;
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16);
+ int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
+ switch (action) {
+ case DASM_STOP: case DASM_SECTION: goto stop;
+ case DASM_ESC: *cp++ = *p++; break;
+ case DASM_REL_EXT:
+ n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
+ goto patchrel;
+ case DASM_ALIGN:
+ ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xd503201f;
+ break;
+ case DASM_REL_LG:
+ if (n < 0) {
+ ptrdiff_t na = (ptrdiff_t)D->globals[-n-10] - (ptrdiff_t)cp + 4;
+ n = (int)na;
+ CK((ptrdiff_t)n == na, RANGE_REL);
+ goto patchrel;
+ }
+ /* fallthrough */
+ case DASM_REL_PC:
+ CK(n >= 0, UNDEF_PC);
+ n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) + 4;
+ patchrel:
+ if (!(ins & 0xf800)) { /* B, BL */
+ CK((n & 3) == 0 && ((n+0x08000000) >> 28) == 0, RANGE_REL);
+ cp[-1] |= ((n >> 2) & 0x03ffffff);
+ } else if ((ins & 0x800)) { /* B.cond, CBZ, CBNZ, LDR* literal */
+ CK((n & 3) == 0 && ((n+0x00100000) >> 21) == 0, RANGE_REL);
+ cp[-1] |= ((n << 3) & 0x00ffffe0);
+ } else if ((ins & 0x3000) == 0x2000) { /* ADR */
+ CK(((n+0x00100000) >> 21) == 0, RANGE_REL);
+ cp[-1] |= ((n << 3) & 0x00ffffe0) | ((n & 3) << 29);
+ } else if ((ins & 0x3000) == 0x3000) { /* ADRP */
+ cp[-1] |= ((n >> 9) & 0x00ffffe0) | (((n >> 12) & 3) << 29);
+ } else if ((ins & 0x1000)) { /* TBZ, TBNZ */
+ CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL);
+ cp[-1] |= ((n << 3) & 0x0007ffe0);
+ } else if ((ins & 0x8000)) { /* absolute */
+ cp[0] = (unsigned int)((ptrdiff_t)cp - 4 + n);
+ cp[1] = (unsigned int)(((ptrdiff_t)cp - 4 + n) >> 32);
+ cp += 2;
+ }
+ break;
+ case DASM_REL_A: {
+ ptrdiff_t na = (((ptrdiff_t)(*b++) << 32) | (unsigned int)n);
+ if ((ins & 0x3000) == 0x3000) { /* ADRP */
+ ins &= ~0x1000;
+ na = (na >> 12) - (((ptrdiff_t)cp - 4) >> 12);
+ } else {
+ na = na - (ptrdiff_t)cp + 4;
+ }
+ n = (int)na;
+ CK((ptrdiff_t)n == na, RANGE_REL);
+ goto patchrel;
+ }
+ case DASM_LABEL_LG:
+ ins &= 2047; if (ins >= 20) D->globals[ins-20] = (void *)(base + n);
+ break;
+ case DASM_LABEL_PC: break;
+ case DASM_IMM:
+ cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
+ break;
+ case DASM_IMM6:
+ cp[-1] |= ((n&31) << 19) | ((n&32) << 26);
+ break;
+ case DASM_IMM12:
+ cp[-1] |= (dasm_imm12((unsigned int)n) << 10);
+ break;
+ case DASM_IMM13W:
+ cp[-1] |= (dasm_imm13(n, n) << 10);
+ break;
+ case DASM_IMM13X:
+ cp[-1] |= (dasm_imm13(n, *b++) << 10);
+ break;
+ case DASM_IMML: {
+ int scale = (ins & 3);
+ cp[-1] |= (!(n & ((1<>scale) < 4096) ?
+ ((n << (10-scale)) | 0x01000000) : ((n & 511) << 12);
+ break;
+ }
+ case DASM_IMMV:
+ *cp++ = n;
+ break;
+ case DASM_VREG:
+ cp[-1] |= (n & 0x1f) << (ins & 0x1f);
+ break;
+ default: *cp++ = ins; break;
+ }
+ }
+ stop: (void)0;
+ }
+ }
+
+ if (base + D->codesize != (char *)cp) /* Check for phase errors. */
+ return DASM_S_PHASE;
+ return DASM_S_OK;
+}
+#undef CK
+
+/* Get PC label offset. */
+int dasm_getpclabel(Dst_DECL, unsigned int pc)
+{
+ dasm_State *D = Dst_REF;
+ if (pc*sizeof(int) < D->pcsize) {
+ int pos = D->pclabels[pc];
+ if (pos < 0) return *DASM_POS2PTR(D, -pos);
+ if (pos > 0) return -1; /* Undefined. */
+ }
+ return -2; /* Unused or out of range. */
+}
+
+#ifdef DASM_CHECKS
+/* Optional sanity checker to call between isolated encoding steps. */
+int dasm_checkstep(Dst_DECL, int secmatch)
+{
+ dasm_State *D = Dst_REF;
+ if (D->status == DASM_S_OK) {
+ int i;
+ for (i = 1; i <= 9; i++) {
+ if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
+ D->lglabels[i] = 0;
+ }
+ }
+ if (D->status == DASM_S_OK && secmatch >= 0 &&
+ D->section != &D->sections[secmatch])
+ D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
+ return D->status;
+}
+#endif
+
diff --git a/LuaJIT-2.1/dynasm/dasm_arm64.lua b/LuaJIT-2.1/dynasm/dasm_arm64.lua
new file mode 100644
index 00000000..8b27e962
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_arm64.lua
@@ -0,0 +1,1226 @@
+------------------------------------------------------------------------------
+-- DynASM ARM64 module.
+--
+-- Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+-- See dynasm.lua for full copyright notice.
+------------------------------------------------------------------------------
+
+-- Module information:
+local _info = {
+ arch = "arm",
+ description = "DynASM ARM64 module",
+ version = "1.5.0",
+ vernum = 10500,
+ release = "2021-05-02",
+ author = "Mike Pall",
+ license = "MIT",
+}
+
+-- Exported glue functions for the arch-specific module.
+local _M = { _info = _info }
+
+-- Cache library functions.
+local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
+local assert, setmetatable, rawget = assert, setmetatable, rawget
+local _s = string
+local format, byte, char = _s.format, _s.byte, _s.char
+local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
+local concat, sort, insert = table.concat, table.sort, table.insert
+local bit = bit or require("bit")
+local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
+local ror, tohex, tobit = bit.ror, bit.tohex, bit.tobit
+
+-- Inherited tables and callbacks.
+local g_opt, g_arch
+local wline, werror, wfatal, wwarn
+
+-- Action name list.
+-- CHECK: Keep this in sync with the C code!
+local action_names = {
+ "STOP", "SECTION", "ESC", "REL_EXT",
+ "ALIGN", "REL_LG", "LABEL_LG",
+ "REL_PC", "LABEL_PC", "REL_A",
+ "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", "IMMV",
+ "VREG",
+}
+
+-- Maximum number of section buffer positions for dasm_put().
+-- CHECK: Keep this in sync with the C code!
+local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
+
+-- Action name -> action number.
+local map_action = {}
+for n,name in ipairs(action_names) do
+ map_action[name] = n-1
+end
+
+-- Action list buffer.
+local actlist = {}
+
+-- Argument list for next dasm_put(). Start with offset 0 into action list.
+local actargs = { 0 }
+
+-- Current number of section buffer positions for dasm_put().
+local secpos = 1
+
+------------------------------------------------------------------------------
+
+-- Dump action names and numbers.
+local function dumpactions(out)
+ out:write("DynASM encoding engine action codes:\n")
+ for n,name in ipairs(action_names) do
+ local num = map_action[name]
+ out:write(format(" %-10s %02X %d\n", name, num, num))
+ end
+ out:write("\n")
+end
+
+-- Write action list buffer as a huge static C array.
+local function writeactions(out, name)
+ local nn = #actlist
+ if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
+ out:write("static const unsigned int ", name, "[", nn, "] = {\n")
+ for i = 1,nn-1 do
+ assert(out:write("0x", tohex(actlist[i]), ",\n"))
+ end
+ assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
+end
+
+------------------------------------------------------------------------------
+
+-- Add word to action list.
+local function wputxw(n)
+ assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
+ actlist[#actlist+1] = n
+end
+
+-- Add action to list with optional arg. Advance buffer pos, too.
+local function waction(action, val, a, num)
+ local w = assert(map_action[action], "bad action name `"..action.."'")
+ wputxw(w * 0x10000 + (val or 0))
+ if a then actargs[#actargs+1] = a end
+ if a or num then secpos = secpos + (num or 1) end
+end
+
+-- Flush action list (intervening C code or buffer pos overflow).
+local function wflush(term)
+ if #actlist == actargs[1] then return end -- Nothing to flush.
+ if not term then waction("STOP") end -- Terminate action list.
+ wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
+ actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
+ secpos = 1 -- The actionlist offset occupies a buffer position, too.
+end
+
+-- Put escaped word.
+local function wputw(n)
+ if n <= 0x000fffff then waction("ESC") end
+ wputxw(n)
+end
+
+-- Reserve position for word.
+local function wpos()
+ local pos = #actlist+1
+ actlist[pos] = ""
+ return pos
+end
+
+-- Store word to reserved position.
+local function wputpos(pos, n)
+ assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
+ if n <= 0x000fffff then
+ insert(actlist, pos+1, n)
+ n = map_action.ESC * 0x10000
+ end
+ actlist[pos] = n
+end
+
+------------------------------------------------------------------------------
+
+-- Global label name -> global label number. With auto assignment on 1st use.
+local next_global = 20
+local map_global = setmetatable({}, { __index = function(t, name)
+ if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
+ local n = next_global
+ if n > 2047 then werror("too many global labels") end
+ next_global = n + 1
+ t[name] = n
+ return n
+end})
+
+-- Dump global labels.
+local function dumpglobals(out, lvl)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("Global labels:\n")
+ for i=20,next_global-1 do
+ out:write(format(" %s\n", t[i]))
+ end
+ out:write("\n")
+end
+
+-- Write global label enum.
+local function writeglobals(out, prefix)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("enum {\n")
+ for i=20,next_global-1 do
+ out:write(" ", prefix, t[i], ",\n")
+ end
+ out:write(" ", prefix, "_MAX\n};\n")
+end
+
+-- Write global label names.
+local function writeglobalnames(out, name)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("static const char *const ", name, "[] = {\n")
+ for i=20,next_global-1 do
+ out:write(" \"", t[i], "\",\n")
+ end
+ out:write(" (const char *)0\n};\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Extern label name -> extern label number. With auto assignment on 1st use.
+local next_extern = 0
+local map_extern_ = {}
+local map_extern = setmetatable({}, { __index = function(t, name)
+ -- No restrictions on the name for now.
+ local n = next_extern
+ if n > 2047 then werror("too many extern labels") end
+ next_extern = n + 1
+ t[name] = n
+ map_extern_[n] = name
+ return n
+end})
+
+-- Dump extern labels.
+local function dumpexterns(out, lvl)
+ out:write("Extern labels:\n")
+ for i=0,next_extern-1 do
+ out:write(format(" %s\n", map_extern_[i]))
+ end
+ out:write("\n")
+end
+
+-- Write extern label names.
+local function writeexternnames(out, name)
+ out:write("static const char *const ", name, "[] = {\n")
+ for i=0,next_extern-1 do
+ out:write(" \"", map_extern_[i], "\",\n")
+ end
+ out:write(" (const char *)0\n};\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Arch-specific maps.
+
+-- Ext. register name -> int. name.
+local map_archdef = { xzr = "@x31", wzr = "@w31", lr = "x30", }
+
+-- Int. register name -> ext. name.
+local map_reg_rev = { ["@x31"] = "xzr", ["@w31"] = "wzr", x30 = "lr", }
+
+local map_type = {} -- Type name -> { ctype, reg }
+local ctypenum = 0 -- Type number (for Dt... macros).
+
+-- Reverse defines for registers.
+function _M.revdef(s)
+ return map_reg_rev[s] or s
+end
+
+local map_shift = { lsl = 0, lsr = 1, asr = 2, }
+
+local map_extend = {
+ uxtb = 0, uxth = 1, uxtw = 2, uxtx = 3,
+ sxtb = 4, sxth = 5, sxtw = 6, sxtx = 7,
+}
+
+local map_cond = {
+ eq = 0, ne = 1, cs = 2, cc = 3, mi = 4, pl = 5, vs = 6, vc = 7,
+ hi = 8, ls = 9, ge = 10, lt = 11, gt = 12, le = 13, al = 14,
+ hs = 2, lo = 3,
+}
+
+------------------------------------------------------------------------------
+
+local parse_reg_type
+
+local function parse_reg(expr, shift, no_vreg)
+ if not expr then werror("expected register name") end
+ local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$")
+ if not tname then
+ tname, ovreg = match(expr, "^([%w_]+):(R[xwqdshb]%b())$")
+ end
+ local tp = map_type[tname or expr]
+ if tp then
+ local reg = ovreg or tp.reg
+ if not reg then
+ werror("type `"..(tname or expr).."' needs a register override")
+ end
+ expr = reg
+ end
+ local ok31, rt, r = match(expr, "^(@?)([xwqdshb])([123]?[0-9])$")
+ if r then
+ r = tonumber(r)
+ if r <= 30 or (r == 31 and ok31 ~= "" or (rt ~= "w" and rt ~= "x")) then
+ if not parse_reg_type then
+ parse_reg_type = rt
+ elseif parse_reg_type ~= rt then
+ werror("register size mismatch")
+ end
+ return shl(r, shift), tp
+ end
+ end
+ local vrt, vreg = match(expr, "^R([xwqdshb])(%b())$")
+ if vreg then
+ if not parse_reg_type then
+ parse_reg_type = vrt
+ elseif parse_reg_type ~= vrt then
+ werror("register size mismatch")
+ end
+ if not no_vreg then waction("VREG", shift, vreg) end
+ return 0
+ end
+ werror("bad register name `"..expr.."'")
+end
+
+local function parse_reg_base(expr)
+ if expr == "sp" then return 0x3e0 end
+ local base, tp = parse_reg(expr, 5)
+ if parse_reg_type ~= "x" then werror("bad register type") end
+ parse_reg_type = false
+ return base, tp
+end
+
+local parse_ctx = {}
+
+local loadenv = setfenv and function(s)
+ local code = loadstring(s, "")
+ if code then setfenv(code, parse_ctx) end
+ return code
+end or function(s)
+ return load(s, "", nil, parse_ctx)
+end
+
+-- Try to parse simple arithmetic, too, since some basic ops are aliases.
+local function parse_number(n)
+ local x = tonumber(n)
+ if x then return x end
+ local code = loadenv("return "..n)
+ if code then
+ local ok, y = pcall(code)
+ if ok and type(y) == "number" then return y end
+ end
+ return nil
+end
+
+local function parse_imm(imm, bits, shift, scale, signed)
+ imm = match(imm, "^#(.*)$")
+ if not imm then werror("expected immediate operand") end
+ local n = parse_number(imm)
+ if n then
+ local m = sar(n, scale)
+ if shl(m, scale) == n then
+ if signed then
+ local s = sar(m, bits-1)
+ if s == 0 then return shl(m, shift)
+ elseif s == -1 then return shl(m + shl(1, bits), shift) end
+ else
+ if sar(m, bits) == 0 then return shl(m, shift) end
+ end
+ end
+ werror("out of range immediate `"..imm.."'")
+ else
+ waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
+ return 0
+ end
+end
+
+local function parse_imm12(imm)
+ imm = match(imm, "^#(.*)$")
+ if not imm then werror("expected immediate operand") end
+ local n = parse_number(imm)
+ if n then
+ if shr(n, 12) == 0 then
+ return shl(n, 10)
+ elseif band(n, 0xff000fff) == 0 then
+ return shr(n, 2) + 0x00400000
+ end
+ werror("out of range immediate `"..imm.."'")
+ else
+ waction("IMM12", 0, imm)
+ return 0
+ end
+end
+
+local function parse_imm13(imm)
+ imm = match(imm, "^#(.*)$")
+ if not imm then werror("expected immediate operand") end
+ local n = parse_number(imm)
+ local r64 = parse_reg_type == "x"
+ if n and n % 1 == 0 and n >= 0 and n <= 0xffffffff then
+ local inv = false
+ if band(n, 1) == 1 then n = bit.bnot(n); inv = true end
+ local t = {}
+ for i=1,32 do t[i] = band(n, 1); n = shr(n, 1) end
+ local b = table.concat(t)
+ b = b..(r64 and (inv and "1" or "0"):rep(32) or b)
+ local p0, p1, p0a, p1a = b:match("^(0+)(1+)(0*)(1*)")
+ if p0 then
+ local w = p1a == "" and (r64 and 64 or 32) or #p1+#p0a
+ if band(w, w-1) == 0 and b == b:sub(1, w):rep(64/w) then
+ local s = band(-2*w, 0x3f) - 1
+ if w == 64 then s = s + 0x1000 end
+ if inv then
+ return shl(w-#p1-#p0, 16) + shl(s+w-#p1, 10)
+ else
+ return shl(w-#p0, 16) + shl(s+#p1, 10)
+ end
+ end
+ end
+ werror("out of range immediate `"..imm.."'")
+ elseif r64 then
+ waction("IMM13X", 0, format("(unsigned int)(%s)", imm))
+ actargs[#actargs+1] = format("(unsigned int)((unsigned long long)(%s)>>32)", imm)
+ return 0
+ else
+ waction("IMM13W", 0, imm)
+ return 0
+ end
+end
+
+local function parse_imm6(imm)
+ imm = match(imm, "^#(.*)$")
+ if not imm then werror("expected immediate operand") end
+ local n = parse_number(imm)
+ if n then
+ if n >= 0 and n <= 63 then
+ return shl(band(n, 0x1f), 19) + (n >= 32 and 0x80000000 or 0)
+ end
+ werror("out of range immediate `"..imm.."'")
+ else
+ waction("IMM6", 0, imm)
+ return 0
+ end
+end
+
+local function parse_imm_load(imm, scale)
+ local n = parse_number(imm)
+ if n then
+ local m = sar(n, scale)
+ if shl(m, scale) == n and m >= 0 and m < 0x1000 then
+ return shl(m, 10) + 0x01000000 -- Scaled, unsigned 12 bit offset.
+ elseif n >= -256 and n < 256 then
+ return shl(band(n, 511), 12) -- Unscaled, signed 9 bit offset.
+ end
+ werror("out of range immediate `"..imm.."'")
+ else
+ waction("IMML", scale, imm)
+ return 0
+ end
+end
+
+local function parse_fpimm(imm)
+ imm = match(imm, "^#(.*)$")
+ if not imm then werror("expected immediate operand") end
+ local n = parse_number(imm)
+ if n then
+ local m, e = math.frexp(n)
+ local s, e2 = 0, band(e-2, 7)
+ if m < 0 then m = -m; s = 0x00100000 end
+ m = m*32-16
+ if m % 1 == 0 and m >= 0 and m <= 15 and sar(shl(e2, 29), 29)+2 == e then
+ return s + shl(e2, 17) + shl(m, 13)
+ end
+ werror("out of range immediate `"..imm.."'")
+ else
+ werror("NYI fpimm action")
+ end
+end
+
+local function parse_shift(expr)
+ local s, s2 = match(expr, "^(%S+)%s*(.*)$")
+ s = map_shift[s]
+ if not s then werror("expected shift operand") end
+ return parse_imm(s2, 6, 10, 0, false) + shl(s, 22)
+end
+
+local function parse_lslx16(expr)
+ local n = match(expr, "^lsl%s*#(%d+)$")
+ n = tonumber(n)
+ if not n then werror("expected shift operand") end
+ if band(n, parse_reg_type == "x" and 0xffffffcf or 0xffffffef) ~= 0 then
+ werror("bad shift amount")
+ end
+ return shl(n, 17)
+end
+
+local function parse_extend(expr)
+ local s, s2 = match(expr, "^(%S+)%s*(.*)$")
+ if s == "lsl" then
+ s = parse_reg_type == "x" and 3 or 2
+ else
+ s = map_extend[s]
+ end
+ if not s then werror("expected extend operand") end
+ return (s2 == "" and 0 or parse_imm(s2, 3, 10, 0, false)) + shl(s, 13)
+end
+
+local function parse_cond(expr, inv)
+ local c = map_cond[expr]
+ if not c then werror("expected condition operand") end
+ return shl(bit.bxor(c, inv), 12)
+end
+
+local function parse_load(params, nparams, n, op)
+ if params[n+2] then werror("too many operands") end
+ local scale = shr(op, 30)
+ local pn, p2 = params[n], params[n+1]
+ local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
+ if not p1 then
+ if not p2 then
+ local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
+ if reg and tailr ~= "" then
+ local base, tp = parse_reg_base(reg)
+ if tp then
+ waction("IMML", scale, format(tp.ctypefmt, tailr))
+ return op + base
+ end
+ end
+ end
+ werror("expected address operand")
+ end
+ if p2 then
+ if wb == "!" then werror("bad use of '!'") end
+ op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400
+ elseif wb == "!" then
+ local p1a, p2a = match(p1, "^([^,%s]*)%s*,%s*(.*)$")
+ if not p1a then werror("bad use of '!'") end
+ op = op + parse_reg_base(p1a) + parse_imm(p2a, 9, 12, 0, true) + 0xc00
+ else
+ local p1a, p2a = match(p1, "^([^,%s]*)%s*(.*)$")
+ op = op + parse_reg_base(p1a)
+ if p2a ~= "" then
+ local imm = match(p2a, "^,%s*#(.*)$")
+ if imm then
+ op = op + parse_imm_load(imm, scale)
+ else
+ local p2b, p3b, p3s = match(p2a, "^,%s*([^,%s]*)%s*,?%s*(%S*)%s*(.*)$")
+ op = op + parse_reg(p2b, 16) + 0x00200800
+ if parse_reg_type ~= "x" and parse_reg_type ~= "w" then
+ werror("bad index register type")
+ end
+ if p3b == "" then
+ if parse_reg_type ~= "x" then werror("bad index register type") end
+ op = op + 0x6000
+ else
+ if p3s == "" or p3s == "#0" then
+ elseif p3s == "#"..scale then
+ op = op + 0x1000
+ else
+ werror("bad scale")
+ end
+ if parse_reg_type == "x" then
+ if p3b == "lsl" and p3s ~= "" then op = op + 0x6000
+ elseif p3b == "sxtx" then op = op + 0xe000
+ else
+ werror("bad extend/shift specifier")
+ end
+ else
+ if p3b == "uxtw" then op = op + 0x4000
+ elseif p3b == "sxtw" then op = op + 0xc000
+ else
+ werror("bad extend/shift specifier")
+ end
+ end
+ end
+ end
+ else
+ if wb == "!" then werror("bad use of '!'") end
+ op = op + 0x01000000
+ end
+ end
+ return op
+end
+
+local function parse_load_pair(params, nparams, n, op)
+ if params[n+2] then werror("too many operands") end
+ local pn, p2 = params[n], params[n+1]
+ local scale = 2 + shr(op, 31 - band(shr(op, 26), 1))
+ local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
+ if not p1 then
+ if not p2 then
+ local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
+ if reg and tailr ~= "" then
+ local base, tp = parse_reg_base(reg)
+ if tp then
+ waction("IMM", 32768+7*32+15+scale*1024, format(tp.ctypefmt, tailr))
+ return op + base + 0x01000000
+ end
+ end
+ end
+ werror("expected address operand")
+ end
+ if p2 then
+ if wb == "!" then werror("bad use of '!'") end
+ op = op + 0x00800000
+ else
+ local p1a, p2a = match(p1, "^([^,%s]*)%s*,%s*(.*)$")
+ if p1a then p1, p2 = p1a, p2a else p2 = "#0" end
+ op = op + (wb == "!" and 0x01800000 or 0x01000000)
+ end
+ return op + parse_reg_base(p1) + parse_imm(p2, 7, 15, scale, true)
+end
+
+local function parse_label(label, def)
+ local prefix = label:sub(1, 2)
+ -- =>label (pc label reference)
+ if prefix == "=>" then
+ return "PC", 0, label:sub(3)
+ end
+ -- ->name (global label reference)
+ if prefix == "->" then
+ return "LG", map_global[label:sub(3)]
+ end
+ if def then
+ -- [1-9] (local label definition)
+ if match(label, "^[1-9]$") then
+ return "LG", 10+tonumber(label)
+ end
+ else
+ -- [<>][1-9] (local label reference)
+ local dir, lnum = match(label, "^([<>])([1-9])$")
+ if dir then -- Fwd: 1-9, Bkwd: 11-19.
+ return "LG", lnum + (dir == ">" and 0 or 10)
+ end
+ -- extern label (extern label reference)
+ local extname = match(label, "^extern%s+(%S+)$")
+ if extname then
+ return "EXT", map_extern[extname]
+ end
+ -- &expr (pointer)
+ if label:sub(1, 1) == "&" then
+ return "A", 0, format("(ptrdiff_t)(%s)", label:sub(2))
+ end
+ end
+end
+
+local function branch_type(op)
+ if band(op, 0x7c000000) == 0x14000000 then return 0 -- B, BL
+ elseif shr(op, 24) == 0x54 or band(op, 0x7e000000) == 0x34000000 or
+ band(op, 0x3b000000) == 0x18000000 then
+ return 0x800 -- B.cond, CBZ, CBNZ, LDR* literal
+ elseif band(op, 0x7e000000) == 0x36000000 then return 0x1000 -- TBZ, TBNZ
+ elseif band(op, 0x9f000000) == 0x10000000 then return 0x2000 -- ADR
+ elseif band(op, 0x9f000000) == band(0x90000000) then return 0x3000 -- ADRP
+ else
+ assert(false, "unknown branch type")
+ end
+end
+
+------------------------------------------------------------------------------
+
+local map_op, op_template
+
+local function op_alias(opname, f)
+ return function(params, nparams)
+ if not params then return "-> "..opname:sub(1, -3) end
+ f(params, nparams)
+ op_template(params, map_op[opname], nparams)
+ end
+end
+
+local function alias_bfx(p)
+ p[4] = "#("..p[3]:sub(2)..")+("..p[4]:sub(2)..")-1"
+end
+
+local function alias_bfiz(p)
+ parse_reg(p[1], 0, true)
+ if parse_reg_type == "w" then
+ p[3] = "#(32-("..p[3]:sub(2).."))%32"
+ p[4] = "#("..p[4]:sub(2)..")-1"
+ else
+ p[3] = "#(64-("..p[3]:sub(2).."))%64"
+ p[4] = "#("..p[4]:sub(2)..")-1"
+ end
+end
+
+local alias_lslimm = op_alias("ubfm_4", function(p)
+ parse_reg(p[1], 0, true)
+ local sh = p[3]:sub(2)
+ if parse_reg_type == "w" then
+ p[3] = "#(32-("..sh.."))%32"
+ p[4] = "#31-("..sh..")"
+ else
+ p[3] = "#(64-("..sh.."))%64"
+ p[4] = "#63-("..sh..")"
+ end
+end)
+
+-- Template strings for ARM instructions.
+map_op = {
+ -- Basic data processing instructions.
+ add_3 = "0b000000DNMg|11000000pDpNIg|8b206000pDpNMx",
+ add_4 = "0b000000DNMSg|0b200000DNMXg|8b200000pDpNMXx|8b200000pDpNxMwX",
+ adds_3 = "2b000000DNMg|31000000DpNIg|ab206000DpNMx",
+ adds_4 = "2b000000DNMSg|2b200000DNMXg|ab200000DpNMXx|ab200000DpNxMwX",
+ cmn_2 = "2b00001fNMg|3100001fpNIg|ab20601fpNMx",
+ cmn_3 = "2b00001fNMSg|2b20001fNMXg|ab20001fpNMXx|ab20001fpNxMwX",
+
+ sub_3 = "4b000000DNMg|51000000pDpNIg|cb206000pDpNMx",
+ sub_4 = "4b000000DNMSg|4b200000DNMXg|cb200000pDpNMXx|cb200000pDpNxMwX",
+ subs_3 = "6b000000DNMg|71000000DpNIg|eb206000DpNMx",
+ subs_4 = "6b000000DNMSg|6b200000DNMXg|eb200000DpNMXx|eb200000DpNxMwX",
+ cmp_2 = "6b00001fNMg|7100001fpNIg|eb20601fpNMx",
+ cmp_3 = "6b00001fNMSg|6b20001fNMXg|eb20001fpNMXx|eb20001fpNxMwX",
+
+ neg_2 = "4b0003e0DMg",
+ neg_3 = "4b0003e0DMSg",
+ negs_2 = "6b0003e0DMg",
+ negs_3 = "6b0003e0DMSg",
+
+ adc_3 = "1a000000DNMg",
+ adcs_3 = "3a000000DNMg",
+ sbc_3 = "5a000000DNMg",
+ sbcs_3 = "7a000000DNMg",
+ ngc_2 = "5a0003e0DMg",
+ ngcs_2 = "7a0003e0DMg",
+
+ and_3 = "0a000000DNMg|12000000pDNig",
+ and_4 = "0a000000DNMSg",
+ orr_3 = "2a000000DNMg|32000000pDNig",
+ orr_4 = "2a000000DNMSg",
+ eor_3 = "4a000000DNMg|52000000pDNig",
+ eor_4 = "4a000000DNMSg",
+ ands_3 = "6a000000DNMg|72000000DNig",
+ ands_4 = "6a000000DNMSg",
+ tst_2 = "6a00001fNMg|7200001fNig",
+ tst_3 = "6a00001fNMSg",
+
+ bic_3 = "0a200000DNMg",
+ bic_4 = "0a200000DNMSg",
+ orn_3 = "2a200000DNMg",
+ orn_4 = "2a200000DNMSg",
+ eon_3 = "4a200000DNMg",
+ eon_4 = "4a200000DNMSg",
+ bics_3 = "6a200000DNMg",
+ bics_4 = "6a200000DNMSg",
+
+ movn_2 = "12800000DWg",
+ movn_3 = "12800000DWRg",
+ movz_2 = "52800000DWg",
+ movz_3 = "52800000DWRg",
+ movk_2 = "72800000DWg",
+ movk_3 = "72800000DWRg",
+
+ -- TODO: this doesn't cover all valid immediates for mov reg, #imm.
+ mov_2 = "2a0003e0DMg|52800000DW|320003e0pDig|11000000pDpNg",
+ mov_3 = "2a0003e0DMSg",
+ mvn_2 = "2a2003e0DMg",
+ mvn_3 = "2a2003e0DMSg",
+
+ adr_2 = "10000000DBx",
+ adrp_2 = "90000000DBx",
+
+ csel_4 = "1a800000DNMCg",
+ csinc_4 = "1a800400DNMCg",
+ csinv_4 = "5a800000DNMCg",
+ csneg_4 = "5a800400DNMCg",
+ cset_2 = "1a9f07e0Dcg",
+ csetm_2 = "5a9f03e0Dcg",
+ cinc_3 = "1a800400DNmcg",
+ cinv_3 = "5a800000DNmcg",
+ cneg_3 = "5a800400DNmcg",
+
+ ccmn_4 = "3a400000NMVCg|3a400800N5VCg",
+ ccmp_4 = "7a400000NMVCg|7a400800N5VCg",
+
+ madd_4 = "1b000000DNMAg",
+ msub_4 = "1b008000DNMAg",
+ mul_3 = "1b007c00DNMg",
+ mneg_3 = "1b00fc00DNMg",
+
+ smaddl_4 = "9b200000DxNMwAx",
+ smsubl_4 = "9b208000DxNMwAx",
+ smull_3 = "9b207c00DxNMw",
+ smnegl_3 = "9b20fc00DxNMw",
+ smulh_3 = "9b407c00DNMx",
+ umaddl_4 = "9ba00000DxNMwAx",
+ umsubl_4 = "9ba08000DxNMwAx",
+ umull_3 = "9ba07c00DxNMw",
+ umnegl_3 = "9ba0fc00DxNMw",
+ umulh_3 = "9bc07c00DNMx",
+
+ udiv_3 = "1ac00800DNMg",
+ sdiv_3 = "1ac00c00DNMg",
+
+ -- Bit operations.
+ sbfm_4 = "13000000DN12w|93400000DN12x",
+ bfm_4 = "33000000DN12w|b3400000DN12x",
+ ubfm_4 = "53000000DN12w|d3400000DN12x",
+ extr_4 = "13800000DNM2w|93c00000DNM2x",
+
+ sxtb_2 = "13001c00DNw|93401c00DNx",
+ sxth_2 = "13003c00DNw|93403c00DNx",
+ sxtw_2 = "93407c00DxNw",
+ uxtb_2 = "53001c00DNw",
+ uxth_2 = "53003c00DNw",
+
+ sbfx_4 = op_alias("sbfm_4", alias_bfx),
+ bfxil_4 = op_alias("bfm_4", alias_bfx),
+ ubfx_4 = op_alias("ubfm_4", alias_bfx),
+ sbfiz_4 = op_alias("sbfm_4", alias_bfiz),
+ bfi_4 = op_alias("bfm_4", alias_bfiz),
+ ubfiz_4 = op_alias("ubfm_4", alias_bfiz),
+
+ lsl_3 = function(params, nparams)
+ if params and params[3]:byte() == 35 then
+ return alias_lslimm(params, nparams)
+ else
+ return op_template(params, "1ac02000DNMg", nparams)
+ end
+ end,
+ lsr_3 = "1ac02400DNMg|53007c00DN1w|d340fc00DN1x",
+ asr_3 = "1ac02800DNMg|13007c00DN1w|9340fc00DN1x",
+ ror_3 = "1ac02c00DNMg|13800000DNm2w|93c00000DNm2x",
+
+ clz_2 = "5ac01000DNg",
+ cls_2 = "5ac01400DNg",
+ rbit_2 = "5ac00000DNg",
+ rev_2 = "5ac00800DNw|dac00c00DNx",
+ rev16_2 = "5ac00400DNg",
+ rev32_2 = "dac00800DNx",
+
+ -- Loads and stores.
+ ["strb_*"] = "38000000DwL",
+ ["ldrb_*"] = "38400000DwL",
+ ["ldrsb_*"] = "38c00000DwL|38800000DxL",
+ ["strh_*"] = "78000000DwL",
+ ["ldrh_*"] = "78400000DwL",
+ ["ldrsh_*"] = "78c00000DwL|78800000DxL",
+ ["str_*"] = "b8000000DwL|f8000000DxL|bc000000DsL|fc000000DdL",
+ ["ldr_*"] = "18000000DwB|58000000DxB|1c000000DsB|5c000000DdB|b8400000DwL|f8400000DxL|bc400000DsL|fc400000DdL",
+ ["ldrsw_*"] = "98000000DxB|b8800000DxL",
+ -- NOTE: ldur etc. are handled by ldr et al.
+
+ ["stp_*"] = "28000000DAwP|a8000000DAxP|2c000000DAsP|6c000000DAdP|ac000000DAqP",
+ ["ldp_*"] = "28400000DAwP|a8400000DAxP|2c400000DAsP|6c400000DAdP|ac400000DAqP",
+ ["ldpsw_*"] = "68400000DAxP",
+
+ -- Branches.
+ b_1 = "14000000B",
+ bl_1 = "94000000B",
+ blr_1 = "d63f0000Nx",
+ br_1 = "d61f0000Nx",
+ ret_0 = "d65f03c0",
+ ret_1 = "d65f0000Nx",
+ -- b.cond is added below.
+ cbz_2 = "34000000DBg",
+ cbnz_2 = "35000000DBg",
+ tbz_3 = "36000000DTBw|36000000DTBx",
+ tbnz_3 = "37000000DTBw|37000000DTBx",
+
+ -- ARM64e: Pointer authentication codes (PAC).
+ blraaz_1 = "d63f081fNx",
+ braa_2 = "d71f0800NDx",
+ braaz_1 = "d61f081fNx",
+ pacibsp_0 = "d503237f",
+ retab_0 = "d65f0fff",
+
+ -- Miscellaneous instructions.
+ -- TODO: hlt, hvc, smc, svc, eret, dcps[123], drps, mrs, msr
+ -- TODO: sys, sysl, ic, dc, at, tlbi
+ -- TODO: hint, yield, wfe, wfi, sev, sevl
+ -- TODO: clrex, dsb, dmb, isb
+ nop_0 = "d503201f",
+ brk_0 = "d4200000",
+ brk_1 = "d4200000W",
+
+ -- Floating point instructions.
+ fmov_2 = "1e204000DNf|1e260000DwNs|1e270000DsNw|9e660000DxNd|9e670000DdNx|1e201000DFf",
+ fabs_2 = "1e20c000DNf",
+ fneg_2 = "1e214000DNf",
+ fsqrt_2 = "1e21c000DNf",
+
+ fcvt_2 = "1e22c000DdNs|1e624000DsNd",
+
+ -- TODO: half-precision and fixed-point conversions.
+ fcvtas_2 = "1e240000DwNs|9e240000DxNs|1e640000DwNd|9e640000DxNd",
+ fcvtau_2 = "1e250000DwNs|9e250000DxNs|1e650000DwNd|9e650000DxNd",
+ fcvtms_2 = "1e300000DwNs|9e300000DxNs|1e700000DwNd|9e700000DxNd",
+ fcvtmu_2 = "1e310000DwNs|9e310000DxNs|1e710000DwNd|9e710000DxNd",
+ fcvtns_2 = "1e200000DwNs|9e200000DxNs|1e600000DwNd|9e600000DxNd",
+ fcvtnu_2 = "1e210000DwNs|9e210000DxNs|1e610000DwNd|9e610000DxNd",
+ fcvtps_2 = "1e280000DwNs|9e280000DxNs|1e680000DwNd|9e680000DxNd",
+ fcvtpu_2 = "1e290000DwNs|9e290000DxNs|1e690000DwNd|9e690000DxNd",
+ fcvtzs_2 = "1e380000DwNs|9e380000DxNs|1e780000DwNd|9e780000DxNd",
+ fcvtzu_2 = "1e390000DwNs|9e390000DxNs|1e790000DwNd|9e790000DxNd",
+
+ scvtf_2 = "1e220000DsNw|9e220000DsNx|1e620000DdNw|9e620000DdNx",
+ ucvtf_2 = "1e230000DsNw|9e230000DsNx|1e630000DdNw|9e630000DdNx",
+
+ frintn_2 = "1e244000DNf",
+ frintp_2 = "1e24c000DNf",
+ frintm_2 = "1e254000DNf",
+ frintz_2 = "1e25c000DNf",
+ frinta_2 = "1e264000DNf",
+ frintx_2 = "1e274000DNf",
+ frinti_2 = "1e27c000DNf",
+
+ fadd_3 = "1e202800DNMf",
+ fsub_3 = "1e203800DNMf",
+ fmul_3 = "1e200800DNMf",
+ fnmul_3 = "1e208800DNMf",
+ fdiv_3 = "1e201800DNMf",
+
+ fmadd_4 = "1f000000DNMAf",
+ fmsub_4 = "1f008000DNMAf",
+ fnmadd_4 = "1f200000DNMAf",
+ fnmsub_4 = "1f208000DNMAf",
+
+ fmax_3 = "1e204800DNMf",
+ fmaxnm_3 = "1e206800DNMf",
+ fmin_3 = "1e205800DNMf",
+ fminnm_3 = "1e207800DNMf",
+
+ fcmp_2 = "1e202000NMf|1e202008NZf",
+ fcmpe_2 = "1e202010NMf|1e202018NZf",
+
+ fccmp_4 = "1e200400NMVCf",
+ fccmpe_4 = "1e200410NMVCf",
+
+ fcsel_4 = "1e200c00DNMCf",
+
+ -- TODO: crc32*, aes*, sha*, pmull
+ -- TODO: SIMD instructions.
+}
+
+for cond,c in pairs(map_cond) do
+ map_op["b"..cond.."_1"] = tohex(0x54000000+c).."B"
+end
+
+------------------------------------------------------------------------------
+
+-- Handle opcodes defined with template strings.
+local function parse_template(params, template, nparams, pos)
+ local op = tonumber(template:sub(1, 8), 16)
+ local n = 1
+ local rtt = {}
+
+ parse_reg_type = false
+
+ -- Process each character.
+ for p in gmatch(template:sub(9), ".") do
+ local q = params[n]
+ if p == "D" then
+ op = op + parse_reg(q, 0); n = n + 1
+ elseif p == "N" then
+ op = op + parse_reg(q, 5); n = n + 1
+ elseif p == "M" then
+ op = op + parse_reg(q, 16); n = n + 1
+ elseif p == "A" then
+ op = op + parse_reg(q, 10); n = n + 1
+ elseif p == "m" then
+ op = op + parse_reg(params[n-1], 16)
+
+ elseif p == "p" then
+ if q == "sp" then params[n] = "@x31" end
+ elseif p == "g" then
+ if parse_reg_type == "x" then
+ op = op + 0x80000000
+ elseif parse_reg_type ~= "w" then
+ werror("bad register type")
+ end
+ parse_reg_type = false
+ elseif p == "f" then
+ if parse_reg_type == "d" then
+ op = op + 0x00400000
+ elseif parse_reg_type ~= "s" then
+ werror("bad register type")
+ end
+ parse_reg_type = false
+ elseif p == "x" or p == "w" or p == "d" or p == "s" or p == "q" then
+ if parse_reg_type ~= p then
+ werror("register size mismatch")
+ end
+ parse_reg_type = false
+
+ elseif p == "L" then
+ op = parse_load(params, nparams, n, op)
+ elseif p == "P" then
+ op = parse_load_pair(params, nparams, n, op)
+
+ elseif p == "B" then
+ local mode, v, s = parse_label(q, false); n = n + 1
+ if not mode then werror("bad label `"..q.."'") end
+ local m = branch_type(op)
+ if mode == "A" then
+ waction("REL_"..mode, v+m, format("(unsigned int)(%s)", s))
+ actargs[#actargs+1] = format("(unsigned int)((%s)>>32)", s)
+ else
+ waction("REL_"..mode, v+m, s, 1)
+ end
+
+ elseif p == "I" then
+ op = op + parse_imm12(q); n = n + 1
+ elseif p == "i" then
+ op = op + parse_imm13(q); n = n + 1
+ elseif p == "W" then
+ op = op + parse_imm(q, 16, 5, 0, false); n = n + 1
+ elseif p == "T" then
+ op = op + parse_imm6(q); n = n + 1
+ elseif p == "1" then
+ op = op + parse_imm(q, 6, 16, 0, false); n = n + 1
+ elseif p == "2" then
+ op = op + parse_imm(q, 6, 10, 0, false); n = n + 1
+ elseif p == "5" then
+ op = op + parse_imm(q, 5, 16, 0, false); n = n + 1
+ elseif p == "V" then
+ op = op + parse_imm(q, 4, 0, 0, false); n = n + 1
+ elseif p == "F" then
+ op = op + parse_fpimm(q); n = n + 1
+ elseif p == "Z" then
+ if q ~= "#0" and q ~= "#0.0" then werror("expected zero immediate") end
+ n = n + 1
+
+ elseif p == "S" then
+ op = op + parse_shift(q); n = n + 1
+ elseif p == "X" then
+ op = op + parse_extend(q); n = n + 1
+ elseif p == "R" then
+ op = op + parse_lslx16(q); n = n + 1
+ elseif p == "C" then
+ op = op + parse_cond(q, 0); n = n + 1
+ elseif p == "c" then
+ op = op + parse_cond(q, 1); n = n + 1
+
+ else
+ assert(false)
+ end
+ end
+ wputpos(pos, op)
+end
+
+function op_template(params, template, nparams)
+ if not params then return template:gsub("%x%x%x%x%x%x%x%x", "") end
+
+ -- Limit number of section buffer positions used by a single dasm_put().
+ -- A single opcode needs a maximum of 4 positions.
+ if secpos+4 > maxsecpos then wflush() end
+ local pos = wpos()
+ local lpos, apos, spos = #actlist, #actargs, secpos
+
+ local ok, err
+ for t in gmatch(template, "[^|]+") do
+ ok, err = pcall(parse_template, params, t, nparams, pos)
+ if ok then return end
+ secpos = spos
+ actlist[lpos+1] = nil
+ actlist[lpos+2] = nil
+ actlist[lpos+3] = nil
+ actlist[lpos+4] = nil
+ actargs[apos+1] = nil
+ actargs[apos+2] = nil
+ actargs[apos+3] = nil
+ actargs[apos+4] = nil
+ end
+ error(err, 0)
+end
+
+map_op[".template__"] = op_template
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcode to mark the position where the action list is to be emitted.
+map_op[".actionlist_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeactions(out, name) end)
+end
+
+-- Pseudo-opcode to mark the position where the global enum is to be emitted.
+map_op[".globals_1"] = function(params)
+ if not params then return "prefix" end
+ local prefix = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeglobals(out, prefix) end)
+end
+
+-- Pseudo-opcode to mark the position where the global names are to be emitted.
+map_op[".globalnames_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeglobalnames(out, name) end)
+end
+
+-- Pseudo-opcode to mark the position where the extern names are to be emitted.
+map_op[".externnames_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeexternnames(out, name) end)
+end
+
+------------------------------------------------------------------------------
+
+-- Label pseudo-opcode (converted from trailing colon form).
+map_op[".label_1"] = function(params)
+ if not params then return "[1-9] | ->global | =>pcexpr" end
+ if secpos+1 > maxsecpos then wflush() end
+ local mode, n, s = parse_label(params[1], true)
+ if not mode or mode == "EXT" then werror("bad label definition") end
+ waction("LABEL_"..mode, n, s, 1)
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcodes for data storage.
+local function op_data(params)
+ if not params then return "imm..." end
+ local sz = params.op == ".long" and 4 or 8
+ for _,p in ipairs(params) do
+ local imm = parse_number(p)
+ if imm then
+ local n = tobit(imm)
+ if n == imm or (n < 0 and n + 2^32 == imm) then
+ wputw(n < 0 and n + 2^32 or n)
+ if sz == 8 then
+ wputw(imm < 0 and 0xffffffff or 0)
+ end
+ elseif sz == 4 then
+ werror("bad immediate `"..p.."'")
+ else
+ imm = nil
+ end
+ end
+ if not imm then
+ local mode, v, s = parse_label(p, false)
+ if sz == 4 then
+ if mode then werror("label does not fit into .long") end
+ waction("IMMV", 0, p)
+ elseif mode and mode ~= "A" then
+ waction("REL_"..mode, v+0x8000, s, 1)
+ else
+ if mode == "A" then p = s end
+ waction("IMMV", 0, format("(unsigned int)(%s)", p))
+ waction("IMMV", 0, format("(unsigned int)((unsigned long long)(%s)>>32)", p))
+ end
+ end
+ if secpos+2 > maxsecpos then wflush() end
+ end
+end
+map_op[".long_*"] = op_data
+map_op[".quad_*"] = op_data
+map_op[".addr_*"] = op_data
+
+-- Alignment pseudo-opcode.
+map_op[".align_1"] = function(params)
+ if not params then return "numpow2" end
+ if secpos+1 > maxsecpos then wflush() end
+ local align = tonumber(params[1])
+ if align then
+ local x = align
+ -- Must be a power of 2 in the range (2 ... 256).
+ for i=1,8 do
+ x = x / 2
+ if x == 1 then
+ waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
+ return
+ end
+ end
+ end
+ werror("bad alignment")
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcode for (primitive) type definitions (map to C types).
+map_op[".type_3"] = function(params, nparams)
+ if not params then
+ return nparams == 2 and "name, ctype" or "name, ctype, reg"
+ end
+ local name, ctype, reg = params[1], params[2], params[3]
+ if not match(name, "^[%a_][%w_]*$") then
+ werror("bad type name `"..name.."'")
+ end
+ local tp = map_type[name]
+ if tp then
+ werror("duplicate type `"..name.."'")
+ end
+ -- Add #type to defines. A bit unclean to put it in map_archdef.
+ map_archdef["#"..name] = "sizeof("..ctype..")"
+ -- Add new type and emit shortcut define.
+ local num = ctypenum + 1
+ map_type[name] = {
+ ctype = ctype,
+ ctypefmt = format("Dt%X(%%s)", num),
+ reg = reg,
+ }
+ wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
+ ctypenum = num
+end
+map_op[".type_2"] = map_op[".type_3"]
+
+-- Dump type definitions.
+local function dumptypes(out, lvl)
+ local t = {}
+ for name in pairs(map_type) do t[#t+1] = name end
+ sort(t)
+ out:write("Type definitions:\n")
+ for _,name in ipairs(t) do
+ local tp = map_type[name]
+ local reg = tp.reg or ""
+ out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
+ end
+ out:write("\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Set the current section.
+function _M.section(num)
+ waction("SECTION", num)
+ wflush(true) -- SECTION is a terminal action.
+end
+
+------------------------------------------------------------------------------
+
+-- Dump architecture description.
+function _M.dumparch(out)
+ out:write(format("DynASM %s version %s, released %s\n\n",
+ _info.arch, _info.version, _info.release))
+ dumpactions(out)
+end
+
+-- Dump all user defined elements.
+function _M.dumpdef(out, lvl)
+ dumptypes(out, lvl)
+ dumpglobals(out, lvl)
+ dumpexterns(out, lvl)
+end
+
+------------------------------------------------------------------------------
+
+-- Pass callbacks from/to the DynASM core.
+function _M.passcb(wl, we, wf, ww)
+ wline, werror, wfatal, wwarn = wl, we, wf, ww
+ return wflush
+end
+
+-- Setup the arch-specific module.
+function _M.setup(arch, opt)
+ g_arch, g_opt = arch, opt
+end
+
+-- Merge the core maps and the arch-specific maps.
+function _M.mergemaps(map_coreop, map_def)
+ setmetatable(map_op, { __index = map_coreop })
+ setmetatable(map_def, { __index = map_archdef })
+ return map_op, map_def
+end
+
+return _M
+
+------------------------------------------------------------------------------
+
diff --git a/LuaJIT-2.1/dynasm/dasm_mips.h b/LuaJIT-2.1/dynasm/dasm_mips.h
new file mode 100644
index 00000000..3fa2ef42
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_mips.h
@@ -0,0 +1,419 @@
+/*
+** DynASM MIPS encoding engine.
+** Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+** Released under the MIT license. See dynasm.lua for full copyright notice.
+*/
+
+#include
+#include
+#include
+#include
+
+#define DASM_ARCH "mips"
+
+#ifndef DASM_EXTERN
+#define DASM_EXTERN(a,b,c,d) 0
+#endif
+
+/* Action definitions. */
+enum {
+ DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
+ /* The following actions need a buffer position. */
+ DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
+ /* The following actions also have an argument. */
+ DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMS,
+ DASM__MAX
+};
+
+/* Maximum number of section buffer positions for a single dasm_put() call. */
+#define DASM_MAXSECPOS 25
+
+/* DynASM encoder status codes. Action list offset or number are or'ed in. */
+#define DASM_S_OK 0x00000000
+#define DASM_S_NOMEM 0x01000000
+#define DASM_S_PHASE 0x02000000
+#define DASM_S_MATCH_SEC 0x03000000
+#define DASM_S_RANGE_I 0x11000000
+#define DASM_S_RANGE_SEC 0x12000000
+#define DASM_S_RANGE_LG 0x13000000
+#define DASM_S_RANGE_PC 0x14000000
+#define DASM_S_RANGE_REL 0x15000000
+#define DASM_S_UNDEF_LG 0x21000000
+#define DASM_S_UNDEF_PC 0x22000000
+
+/* Macros to convert positions (8 bit section + 24 bit index). */
+#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
+#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
+#define DASM_SEC2POS(sec) ((sec)<<24)
+#define DASM_POS2SEC(pos) ((pos)>>24)
+#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
+
+/* Action list type. */
+typedef const unsigned int *dasm_ActList;
+
+/* Per-section structure. */
+typedef struct dasm_Section {
+ int *rbuf; /* Biased buffer pointer (negative section bias). */
+ int *buf; /* True buffer pointer. */
+ size_t bsize; /* Buffer size in bytes. */
+ int pos; /* Biased buffer position. */
+ int epos; /* End of biased buffer position - max single put. */
+ int ofs; /* Byte offset into section. */
+} dasm_Section;
+
+/* Core structure holding the DynASM encoding state. */
+struct dasm_State {
+ size_t psize; /* Allocated size of this structure. */
+ dasm_ActList actionlist; /* Current actionlist pointer. */
+ int *lglabels; /* Local/global chain/pos ptrs. */
+ size_t lgsize;
+ int *pclabels; /* PC label chains/pos ptrs. */
+ size_t pcsize;
+ void **globals; /* Array of globals. */
+ dasm_Section *section; /* Pointer to active section. */
+ size_t codesize; /* Total size of all code sections. */
+ int maxsection; /* 0 <= sectionidx < maxsection. */
+ int status; /* Status code. */
+ dasm_Section sections[1]; /* All sections. Alloc-extended. */
+};
+
+/* The size of the core structure depends on the max. number of sections. */
+#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
+
+
+/* Initialize DynASM state. */
+void dasm_init(Dst_DECL, int maxsection)
+{
+ dasm_State *D;
+ size_t psz = 0;
+ Dst_REF = NULL;
+ DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
+ D = Dst_REF;
+ D->psize = psz;
+ D->lglabels = NULL;
+ D->lgsize = 0;
+ D->pclabels = NULL;
+ D->pcsize = 0;
+ D->globals = NULL;
+ D->maxsection = maxsection;
+ memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section));
+}
+
+/* Free DynASM state. */
+void dasm_free(Dst_DECL)
+{
+ dasm_State *D = Dst_REF;
+ int i;
+ for (i = 0; i < D->maxsection; i++)
+ if (D->sections[i].buf)
+ DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
+ if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
+ if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
+ DASM_M_FREE(Dst, D, D->psize);
+}
+
+/* Setup global label array. Must be called before dasm_setup(). */
+void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
+{
+ dasm_State *D = Dst_REF;
+ D->globals = gl;
+ DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
+}
+
+/* Grow PC label array. Can be called after dasm_setup(), too. */
+void dasm_growpc(Dst_DECL, unsigned int maxpc)
+{
+ dasm_State *D = Dst_REF;
+ size_t osz = D->pcsize;
+ DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
+ memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
+}
+
+/* Setup encoder. */
+void dasm_setup(Dst_DECL, const void *actionlist)
+{
+ dasm_State *D = Dst_REF;
+ int i;
+ D->actionlist = (dasm_ActList)actionlist;
+ D->status = DASM_S_OK;
+ D->section = &D->sections[0];
+ memset((void *)D->lglabels, 0, D->lgsize);
+ if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
+ for (i = 0; i < D->maxsection; i++) {
+ D->sections[i].pos = DASM_SEC2POS(i);
+ D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos;
+ D->sections[i].ofs = 0;
+ }
+}
+
+
+#ifdef DASM_CHECKS
+#define CK(x, st) \
+ do { if (!(x)) { \
+ D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
+#define CKPL(kind, st) \
+ do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
+ D->status = DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
+#else
+#define CK(x, st) ((void)0)
+#define CKPL(kind, st) ((void)0)
+#endif
+
+/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
+void dasm_put(Dst_DECL, int start, ...)
+{
+ va_list ap;
+ dasm_State *D = Dst_REF;
+ dasm_ActList p = D->actionlist + start;
+ dasm_Section *sec = D->section;
+ int pos = sec->pos, ofs = sec->ofs;
+ int *b;
+
+ if (pos >= sec->epos) {
+ DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
+ sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
+ sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
+ sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
+ }
+
+ b = sec->rbuf;
+ b[pos++] = start;
+
+ va_start(ap, start);
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16) - 0xff00;
+ if (action >= DASM__MAX) {
+ ofs += 4;
+ } else {
+ int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
+ switch (action) {
+ case DASM_STOP: goto stop;
+ case DASM_SECTION:
+ n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
+ D->section = &D->sections[n]; goto stop;
+ case DASM_ESC: p++; ofs += 4; break;
+ case DASM_REL_EXT: break;
+ case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
+ case DASM_REL_LG:
+ n = (ins & 2047) - 10; pl = D->lglabels + n;
+ /* Bkwd rel or global. */
+ if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
+ pl += 10; n = *pl;
+ if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
+ goto linkrel;
+ case DASM_REL_PC:
+ pl = D->pclabels + n; CKPL(pc, PC);
+ putrel:
+ n = *pl;
+ if (n < 0) { /* Label exists. Get label pos and store it. */
+ b[pos] = -n;
+ } else {
+ linkrel:
+ b[pos] = n; /* Else link to rel chain, anchored at label. */
+ *pl = pos;
+ }
+ pos++;
+ break;
+ case DASM_LABEL_LG:
+ pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
+ case DASM_LABEL_PC:
+ pl = D->pclabels + n; CKPL(pc, PC);
+ putlabel:
+ n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
+ while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
+ }
+ *pl = -pos; /* Label exists now. */
+ b[pos++] = ofs; /* Store pass1 offset estimate. */
+ break;
+ case DASM_IMM: case DASM_IMMS:
+#ifdef DASM_CHECKS
+ CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
+#endif
+ n >>= ((ins>>10)&31);
+#ifdef DASM_CHECKS
+ if (ins & 0x8000)
+ CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
+ else
+ CK((n>>((ins>>5)&31)) == 0, RANGE_I);
+#endif
+ b[pos++] = n;
+ break;
+ }
+ }
+ }
+stop:
+ va_end(ap);
+ sec->pos = pos;
+ sec->ofs = ofs;
+}
+#undef CK
+
+/* Pass 2: Link sections, shrink aligns, fix label offsets. */
+int dasm_link(Dst_DECL, size_t *szp)
+{
+ dasm_State *D = Dst_REF;
+ int secnum;
+ int ofs = 0;
+
+#ifdef DASM_CHECKS
+ *szp = 0;
+ if (D->status != DASM_S_OK) return D->status;
+ {
+ int pc;
+ for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
+ if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
+ }
+#endif
+
+ { /* Handle globals not defined in this translation unit. */
+ int idx;
+ for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
+ int n = D->lglabels[idx];
+ /* Undefined label: Collapse rel chain and replace with marker (< 0). */
+ while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
+ }
+ }
+
+ /* Combine all code sections. No support for data sections (yet). */
+ for (secnum = 0; secnum < D->maxsection; secnum++) {
+ dasm_Section *sec = D->sections + secnum;
+ int *b = sec->rbuf;
+ int pos = DASM_SEC2POS(secnum);
+ int lastpos = sec->pos;
+
+ while (pos != lastpos) {
+ dasm_ActList p = D->actionlist + b[pos++];
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16) - 0xff00;
+ switch (action) {
+ case DASM_STOP: case DASM_SECTION: goto stop;
+ case DASM_ESC: p++; break;
+ case DASM_REL_EXT: break;
+ case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
+ case DASM_REL_LG: case DASM_REL_PC: pos++; break;
+ case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
+ case DASM_IMM: case DASM_IMMS: pos++; break;
+ }
+ }
+ stop: (void)0;
+ }
+ ofs += sec->ofs; /* Next section starts right after current section. */
+ }
+
+ D->codesize = ofs; /* Total size of all code sections */
+ *szp = ofs;
+ return DASM_S_OK;
+}
+
+#ifdef DASM_CHECKS
+#define CK(x, st) \
+ do { if (!(x)) return DASM_S_##st|(int)(p-D->actionlist-1); } while (0)
+#else
+#define CK(x, st) ((void)0)
+#endif
+
+/* Pass 3: Encode sections. */
+int dasm_encode(Dst_DECL, void *buffer)
+{
+ dasm_State *D = Dst_REF;
+ char *base = (char *)buffer;
+ unsigned int *cp = (unsigned int *)buffer;
+ int secnum;
+
+ /* Encode all code sections. No support for data sections (yet). */
+ for (secnum = 0; secnum < D->maxsection; secnum++) {
+ dasm_Section *sec = D->sections + secnum;
+ int *b = sec->buf;
+ int *endb = sec->rbuf + sec->pos;
+
+ while (b != endb) {
+ dasm_ActList p = D->actionlist + *b++;
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16) - 0xff00;
+ int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
+ switch (action) {
+ case DASM_STOP: case DASM_SECTION: goto stop;
+ case DASM_ESC: *cp++ = *p++; break;
+ case DASM_REL_EXT:
+ n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1);
+ goto patchrel;
+ case DASM_ALIGN:
+ ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
+ break;
+ case DASM_REL_LG:
+ if (n < 0) {
+ n = (int)((ptrdiff_t)D->globals[-n-10] - (ptrdiff_t)cp);
+ goto patchrel;
+ }
+ /* fallthrough */
+ case DASM_REL_PC:
+ CK(n >= 0, UNDEF_PC);
+ n = *DASM_POS2PTR(D, n);
+ if (ins & 2048)
+ n = (n + (int)(size_t)base) & 0x0fffffff;
+ else
+ n = n - (int)((char *)cp - base);
+ patchrel: {
+ unsigned int e = 16 + ((ins >> 12) & 15);
+ CK((n & 3) == 0 &&
+ ((n + ((ins & 2048) ? 0 : (1<<(e+1)))) >> (e+2)) == 0, RANGE_REL);
+ cp[-1] |= ((n>>2) & ((1<= 20) D->globals[ins-20] = (void *)(base + n);
+ break;
+ case DASM_LABEL_PC: break;
+ case DASM_IMMS:
+ cp[-1] |= ((n>>3) & 4); n &= 0x1f;
+ /* fallthrough */
+ case DASM_IMM:
+ cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
+ break;
+ default: *cp++ = ins; break;
+ }
+ }
+ stop: (void)0;
+ }
+ }
+
+ if (base + D->codesize != (char *)cp) /* Check for phase errors. */
+ return DASM_S_PHASE;
+ return DASM_S_OK;
+}
+#undef CK
+
+/* Get PC label offset. */
+int dasm_getpclabel(Dst_DECL, unsigned int pc)
+{
+ dasm_State *D = Dst_REF;
+ if (pc*sizeof(int) < D->pcsize) {
+ int pos = D->pclabels[pc];
+ if (pos < 0) return *DASM_POS2PTR(D, -pos);
+ if (pos > 0) return -1; /* Undefined. */
+ }
+ return -2; /* Unused or out of range. */
+}
+
+#ifdef DASM_CHECKS
+/* Optional sanity checker to call between isolated encoding steps. */
+int dasm_checkstep(Dst_DECL, int secmatch)
+{
+ dasm_State *D = Dst_REF;
+ if (D->status == DASM_S_OK) {
+ int i;
+ for (i = 1; i <= 9; i++) {
+ if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
+ D->lglabels[i] = 0;
+ }
+ }
+ if (D->status == DASM_S_OK && secmatch >= 0 &&
+ D->section != &D->sections[secmatch])
+ D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
+ return D->status;
+}
+#endif
+
diff --git a/LuaJIT-2.1/dynasm/dasm_mips.lua b/LuaJIT-2.1/dynasm/dasm_mips.lua
new file mode 100644
index 00000000..2ab3f3ce
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_mips.lua
@@ -0,0 +1,1181 @@
+------------------------------------------------------------------------------
+-- DynASM MIPS32/MIPS64 module.
+--
+-- Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+-- See dynasm.lua for full copyright notice.
+------------------------------------------------------------------------------
+
+local mips64 = mips64
+local mipsr6 = _map_def.MIPSR6
+
+-- Module information:
+local _info = {
+ arch = mips64 and "mips64" or "mips",
+ description = "DynASM MIPS32/MIPS64 module",
+ version = "1.5.0",
+ vernum = 10500,
+ release = "2021-05-02",
+ author = "Mike Pall",
+ license = "MIT",
+}
+
+-- Exported glue functions for the arch-specific module.
+local _M = { _info = _info }
+
+-- Cache library functions.
+local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
+local assert, setmetatable = assert, setmetatable
+local _s = string
+local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
+local match, gmatch = _s.match, _s.gmatch
+local concat, sort = table.concat, table.sort
+local bit = bit or require("bit")
+local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
+local tohex = bit.tohex
+
+-- Inherited tables and callbacks.
+local g_opt, g_arch
+local wline, werror, wfatal, wwarn
+
+-- Action name list.
+-- CHECK: Keep this in sync with the C code!
+local action_names = {
+ "STOP", "SECTION", "ESC", "REL_EXT",
+ "ALIGN", "REL_LG", "LABEL_LG",
+ "REL_PC", "LABEL_PC", "IMM", "IMMS",
+}
+
+-- Maximum number of section buffer positions for dasm_put().
+-- CHECK: Keep this in sync with the C code!
+local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
+
+-- Action name -> action number.
+local map_action = {}
+for n,name in ipairs(action_names) do
+ map_action[name] = n-1
+end
+
+-- Action list buffer.
+local actlist = {}
+
+-- Argument list for next dasm_put(). Start with offset 0 into action list.
+local actargs = { 0 }
+
+-- Current number of section buffer positions for dasm_put().
+local secpos = 1
+
+------------------------------------------------------------------------------
+
+-- Dump action names and numbers.
+local function dumpactions(out)
+ out:write("DynASM encoding engine action codes:\n")
+ for n,name in ipairs(action_names) do
+ local num = map_action[name]
+ out:write(format(" %-10s %02X %d\n", name, num, num))
+ end
+ out:write("\n")
+end
+
+-- Write action list buffer as a huge static C array.
+local function writeactions(out, name)
+ local nn = #actlist
+ if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
+ out:write("static const unsigned int ", name, "[", nn, "] = {\n")
+ for i = 1,nn-1 do
+ assert(out:write("0x", tohex(actlist[i]), ",\n"))
+ end
+ assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
+end
+
+------------------------------------------------------------------------------
+
+-- Add word to action list.
+local function wputxw(n)
+ assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
+ actlist[#actlist+1] = n
+end
+
+-- Add action to list with optional arg. Advance buffer pos, too.
+local function waction(action, val, a, num)
+ local w = assert(map_action[action], "bad action name `"..action.."'")
+ wputxw(0xff000000 + w * 0x10000 + (val or 0))
+ if a then actargs[#actargs+1] = a end
+ if a or num then secpos = secpos + (num or 1) end
+end
+
+-- Flush action list (intervening C code or buffer pos overflow).
+local function wflush(term)
+ if #actlist == actargs[1] then return end -- Nothing to flush.
+ if not term then waction("STOP") end -- Terminate action list.
+ wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
+ actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
+ secpos = 1 -- The actionlist offset occupies a buffer position, too.
+end
+
+-- Put escaped word.
+local function wputw(n)
+ if n >= 0xff000000 then waction("ESC") end
+ wputxw(n)
+end
+
+-- Reserve position for word.
+local function wpos()
+ local pos = #actlist+1
+ actlist[pos] = ""
+ return pos
+end
+
+-- Store word to reserved position.
+local function wputpos(pos, n)
+ assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
+ actlist[pos] = n
+end
+
+------------------------------------------------------------------------------
+
+-- Global label name -> global label number. With auto assignment on 1st use.
+local next_global = 20
+local map_global = setmetatable({}, { __index = function(t, name)
+ if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
+ local n = next_global
+ if n > 2047 then werror("too many global labels") end
+ next_global = n + 1
+ t[name] = n
+ return n
+end})
+
+-- Dump global labels.
+local function dumpglobals(out, lvl)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("Global labels:\n")
+ for i=20,next_global-1 do
+ out:write(format(" %s\n", t[i]))
+ end
+ out:write("\n")
+end
+
+-- Write global label enum.
+local function writeglobals(out, prefix)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("enum {\n")
+ for i=20,next_global-1 do
+ out:write(" ", prefix, t[i], ",\n")
+ end
+ out:write(" ", prefix, "_MAX\n};\n")
+end
+
+-- Write global label names.
+local function writeglobalnames(out, name)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("static const char *const ", name, "[] = {\n")
+ for i=20,next_global-1 do
+ out:write(" \"", t[i], "\",\n")
+ end
+ out:write(" (const char *)0\n};\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Extern label name -> extern label number. With auto assignment on 1st use.
+local next_extern = 0
+local map_extern_ = {}
+local map_extern = setmetatable({}, { __index = function(t, name)
+ -- No restrictions on the name for now.
+ local n = next_extern
+ if n > 2047 then werror("too many extern labels") end
+ next_extern = n + 1
+ t[name] = n
+ map_extern_[n] = name
+ return n
+end})
+
+-- Dump extern labels.
+local function dumpexterns(out, lvl)
+ out:write("Extern labels:\n")
+ for i=0,next_extern-1 do
+ out:write(format(" %s\n", map_extern_[i]))
+ end
+ out:write("\n")
+end
+
+-- Write extern label names.
+local function writeexternnames(out, name)
+ out:write("static const char *const ", name, "[] = {\n")
+ for i=0,next_extern-1 do
+ out:write(" \"", map_extern_[i], "\",\n")
+ end
+ out:write(" (const char *)0\n};\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Arch-specific maps.
+local map_archdef = { sp="r29", ra="r31" } -- Ext. register name -> int. name.
+
+local map_type = {} -- Type name -> { ctype, reg }
+local ctypenum = 0 -- Type number (for Dt... macros).
+
+-- Reverse defines for registers.
+function _M.revdef(s)
+ if s == "r29" then return "sp"
+ elseif s == "r31" then return "ra" end
+ return s
+end
+
+------------------------------------------------------------------------------
+
+-- Template strings for MIPS instructions.
+local map_op = {
+ -- First-level opcodes.
+ j_1 = "08000000J",
+ jal_1 = "0c000000J",
+ b_1 = "10000000B",
+ beqz_2 = "10000000SB",
+ beq_3 = "10000000STB",
+ bnez_2 = "14000000SB",
+ bne_3 = "14000000STB",
+ blez_2 = "18000000SB",
+ bgtz_2 = "1c000000SB",
+ li_2 = "24000000TI",
+ addiu_3 = "24000000TSI",
+ slti_3 = "28000000TSI",
+ sltiu_3 = "2c000000TSI",
+ andi_3 = "30000000TSU",
+ lu_2 = "34000000TU",
+ ori_3 = "34000000TSU",
+ xori_3 = "38000000TSU",
+ lui_2 = "3c000000TU",
+ daddiu_3 = mips64 and "64000000TSI",
+ ldl_2 = mips64 and "68000000TO",
+ ldr_2 = mips64 and "6c000000TO",
+ lb_2 = "80000000TO",
+ lh_2 = "84000000TO",
+ lw_2 = "8c000000TO",
+ lbu_2 = "90000000TO",
+ lhu_2 = "94000000TO",
+ lwu_2 = mips64 and "9c000000TO",
+ sb_2 = "a0000000TO",
+ sh_2 = "a4000000TO",
+ sw_2 = "ac000000TO",
+ lwc1_2 = "c4000000HO",
+ ldc1_2 = "d4000000HO",
+ ld_2 = mips64 and "dc000000TO",
+ swc1_2 = "e4000000HO",
+ sdc1_2 = "f4000000HO",
+ sd_2 = mips64 and "fc000000TO",
+
+ -- Opcode SPECIAL.
+ nop_0 = "00000000",
+ sll_3 = "00000000DTA",
+ sextw_2 = "00000000DT",
+ srl_3 = "00000002DTA",
+ rotr_3 = "00200002DTA",
+ sra_3 = "00000003DTA",
+ sllv_3 = "00000004DTS",
+ srlv_3 = "00000006DTS",
+ rotrv_3 = "00000046DTS",
+ drotrv_3 = mips64 and "00000056DTS",
+ srav_3 = "00000007DTS",
+ jalr_1 = "0000f809S",
+ jalr_2 = "00000009DS",
+ syscall_0 = "0000000c",
+ syscall_1 = "0000000cY",
+ break_0 = "0000000d",
+ break_1 = "0000000dY",
+ sync_0 = "0000000f",
+ dsllv_3 = mips64 and "00000014DTS",
+ dsrlv_3 = mips64 and "00000016DTS",
+ dsrav_3 = mips64 and "00000017DTS",
+ add_3 = "00000020DST",
+ move_2 = mips64 and "00000025DS" or "00000021DS",
+ addu_3 = "00000021DST",
+ sub_3 = "00000022DST",
+ negu_2 = mips64 and "0000002fDT" or "00000023DT",
+ subu_3 = "00000023DST",
+ and_3 = "00000024DST",
+ or_3 = "00000025DST",
+ xor_3 = "00000026DST",
+ not_2 = "00000027DS",
+ nor_3 = "00000027DST",
+ slt_3 = "0000002aDST",
+ sltu_3 = "0000002bDST",
+ dadd_3 = mips64 and "0000002cDST",
+ daddu_3 = mips64 and "0000002dDST",
+ dsub_3 = mips64 and "0000002eDST",
+ dsubu_3 = mips64 and "0000002fDST",
+ tge_2 = "00000030ST",
+ tge_3 = "00000030STZ",
+ tgeu_2 = "00000031ST",
+ tgeu_3 = "00000031STZ",
+ tlt_2 = "00000032ST",
+ tlt_3 = "00000032STZ",
+ tltu_2 = "00000033ST",
+ tltu_3 = "00000033STZ",
+ teq_2 = "00000034ST",
+ teq_3 = "00000034STZ",
+ tne_2 = "00000036ST",
+ tne_3 = "00000036STZ",
+ dsll_3 = mips64 and "00000038DTa",
+ dsrl_3 = mips64 and "0000003aDTa",
+ drotr_3 = mips64 and "0020003aDTa",
+ dsra_3 = mips64 and "0000003bDTa",
+ dsll32_3 = mips64 and "0000003cDTA",
+ dsrl32_3 = mips64 and "0000003eDTA",
+ drotr32_3 = mips64 and "0020003eDTA",
+ dsra32_3 = mips64 and "0000003fDTA",
+
+ -- Opcode REGIMM.
+ bltz_2 = "04000000SB",
+ bgez_2 = "04010000SB",
+ bltzl_2 = "04020000SB",
+ bgezl_2 = "04030000SB",
+ bal_1 = "04110000B",
+ synci_1 = "041f0000O",
+
+ -- Opcode SPECIAL3.
+ ext_4 = "7c000000TSAM", -- Note: last arg is msbd = size-1
+ dextm_4 = mips64 and "7c000001TSAM", -- Args: pos | size-1-32
+ dextu_4 = mips64 and "7c000002TSAM", -- Args: pos-32 | size-1
+ dext_4 = mips64 and "7c000003TSAM", -- Args: pos | size-1
+ zextw_2 = mips64 and "7c00f803TS",
+ ins_4 = "7c000004TSAM", -- Note: last arg is msb = pos+size-1
+ dinsm_4 = mips64 and "7c000005TSAM", -- Args: pos | pos+size-33
+ dinsu_4 = mips64 and "7c000006TSAM", -- Args: pos-32 | pos+size-33
+ dins_4 = mips64 and "7c000007TSAM", -- Args: pos | pos+size-1
+ wsbh_2 = "7c0000a0DT",
+ dsbh_2 = mips64 and "7c0000a4DT",
+ dshd_2 = mips64 and "7c000164DT",
+ seb_2 = "7c000420DT",
+ seh_2 = "7c000620DT",
+ rdhwr_2 = "7c00003bTD",
+
+ -- Opcode COP0.
+ mfc0_2 = "40000000TD",
+ mfc0_3 = "40000000TDW",
+ dmfc0_2 = mips64 and "40200000TD",
+ dmfc0_3 = mips64 and "40200000TDW",
+ mtc0_2 = "40800000TD",
+ mtc0_3 = "40800000TDW",
+ dmtc0_2 = mips64 and "40a00000TD",
+ dmtc0_3 = mips64 and "40a00000TDW",
+ rdpgpr_2 = "41400000DT",
+ di_0 = "41606000",
+ di_1 = "41606000T",
+ ei_0 = "41606020",
+ ei_1 = "41606020T",
+ wrpgpr_2 = "41c00000DT",
+ tlbr_0 = "42000001",
+ tlbwi_0 = "42000002",
+ tlbwr_0 = "42000006",
+ tlbp_0 = "42000008",
+ eret_0 = "42000018",
+ deret_0 = "4200001f",
+ wait_0 = "42000020",
+
+ -- Opcode COP1.
+ mfc1_2 = "44000000TG",
+ dmfc1_2 = mips64 and "44200000TG",
+ cfc1_2 = "44400000TG",
+ mfhc1_2 = "44600000TG",
+ mtc1_2 = "44800000TG",
+ dmtc1_2 = mips64 and "44a00000TG",
+ ctc1_2 = "44c00000TG",
+ mthc1_2 = "44e00000TG",
+
+ ["add.s_3"] = "46000000FGH",
+ ["sub.s_3"] = "46000001FGH",
+ ["mul.s_3"] = "46000002FGH",
+ ["div.s_3"] = "46000003FGH",
+ ["sqrt.s_2"] = "46000004FG",
+ ["abs.s_2"] = "46000005FG",
+ ["mov.s_2"] = "46000006FG",
+ ["neg.s_2"] = "46000007FG",
+ ["round.l.s_2"] = "46000008FG",
+ ["trunc.l.s_2"] = "46000009FG",
+ ["ceil.l.s_2"] = "4600000aFG",
+ ["floor.l.s_2"] = "4600000bFG",
+ ["round.w.s_2"] = "4600000cFG",
+ ["trunc.w.s_2"] = "4600000dFG",
+ ["ceil.w.s_2"] = "4600000eFG",
+ ["floor.w.s_2"] = "4600000fFG",
+ ["recip.s_2"] = "46000015FG",
+ ["rsqrt.s_2"] = "46000016FG",
+ ["cvt.d.s_2"] = "46000021FG",
+ ["cvt.w.s_2"] = "46000024FG",
+ ["cvt.l.s_2"] = "46000025FG",
+ ["add.d_3"] = "46200000FGH",
+ ["sub.d_3"] = "46200001FGH",
+ ["mul.d_3"] = "46200002FGH",
+ ["div.d_3"] = "46200003FGH",
+ ["sqrt.d_2"] = "46200004FG",
+ ["abs.d_2"] = "46200005FG",
+ ["mov.d_2"] = "46200006FG",
+ ["neg.d_2"] = "46200007FG",
+ ["round.l.d_2"] = "46200008FG",
+ ["trunc.l.d_2"] = "46200009FG",
+ ["ceil.l.d_2"] = "4620000aFG",
+ ["floor.l.d_2"] = "4620000bFG",
+ ["round.w.d_2"] = "4620000cFG",
+ ["trunc.w.d_2"] = "4620000dFG",
+ ["ceil.w.d_2"] = "4620000eFG",
+ ["floor.w.d_2"] = "4620000fFG",
+ ["recip.d_2"] = "46200015FG",
+ ["rsqrt.d_2"] = "46200016FG",
+ ["cvt.s.d_2"] = "46200020FG",
+ ["cvt.w.d_2"] = "46200024FG",
+ ["cvt.l.d_2"] = "46200025FG",
+ ["cvt.s.w_2"] = "46800020FG",
+ ["cvt.d.w_2"] = "46800021FG",
+ ["cvt.s.l_2"] = "46a00020FG",
+ ["cvt.d.l_2"] = "46a00021FG",
+}
+
+if mipsr6 then -- Instructions added with MIPSR6.
+
+ for k,v in pairs({
+
+ -- Add immediate to upper bits.
+ aui_3 = "3c000000TSI",
+ daui_3 = mips64 and "74000000TSI",
+ dahi_2 = mips64 and "04060000SI",
+ dati_2 = mips64 and "041e0000SI",
+
+ -- TODO: addiupc, auipc, aluipc, lwpc, lwupc, ldpc.
+
+ -- Compact branches.
+ blezalc_2 = "18000000TB", -- rt != 0.
+ bgezalc_2 = "18000000T=SB", -- rt != 0.
+ bgtzalc_2 = "1c000000TB", -- rt != 0.
+ bltzalc_2 = "1c000000T=SB", -- rt != 0.
+
+ blezc_2 = "58000000TB", -- rt != 0.
+ bgezc_2 = "58000000T=SB", -- rt != 0.
+ bgec_3 = "58000000STB", -- rs != rt.
+ blec_3 = "58000000TSB", -- rt != rs.
+
+ bgtzc_2 = "5c000000TB", -- rt != 0.
+ bltzc_2 = "5c000000T=SB", -- rt != 0.
+ bltc_3 = "5c000000STB", -- rs != rt.
+ bgtc_3 = "5c000000TSB", -- rt != rs.
+
+ bgeuc_3 = "18000000STB", -- rs != rt.
+ bleuc_3 = "18000000TSB", -- rt != rs.
+ bltuc_3 = "1c000000STB", -- rs != rt.
+ bgtuc_3 = "1c000000TSB", -- rt != rs.
+
+ beqzalc_2 = "20000000TB", -- rt != 0.
+ bnezalc_2 = "60000000TB", -- rt != 0.
+ beqc_3 = "20000000STB", -- rs < rt.
+ bnec_3 = "60000000STB", -- rs < rt.
+ bovc_3 = "20000000STB", -- rs >= rt.
+ bnvc_3 = "60000000STB", -- rs >= rt.
+
+ beqzc_2 = "d8000000SK", -- rs != 0.
+ bnezc_2 = "f8000000SK", -- rs != 0.
+ jic_2 = "d8000000TI",
+ jialc_2 = "f8000000TI",
+ bc_1 = "c8000000L",
+ balc_1 = "e8000000L",
+
+ -- Opcode SPECIAL.
+ jr_1 = "00000009S",
+ sdbbp_0 = "0000000e",
+ sdbbp_1 = "0000000eY",
+ lsa_4 = "00000005DSTA",
+ dlsa_4 = mips64 and "00000015DSTA",
+ seleqz_3 = "00000035DST",
+ selnez_3 = "00000037DST",
+ clz_2 = "00000050DS",
+ clo_2 = "00000051DS",
+ dclz_2 = mips64 and "00000052DS",
+ dclo_2 = mips64 and "00000053DS",
+ mul_3 = "00000098DST",
+ muh_3 = "000000d8DST",
+ mulu_3 = "00000099DST",
+ muhu_3 = "000000d9DST",
+ div_3 = "0000009aDST",
+ mod_3 = "000000daDST",
+ divu_3 = "0000009bDST",
+ modu_3 = "000000dbDST",
+ dmul_3 = mips64 and "0000009cDST",
+ dmuh_3 = mips64 and "000000dcDST",
+ dmulu_3 = mips64 and "0000009dDST",
+ dmuhu_3 = mips64 and "000000ddDST",
+ ddiv_3 = mips64 and "0000009eDST",
+ dmod_3 = mips64 and "000000deDST",
+ ddivu_3 = mips64 and "0000009fDST",
+ dmodu_3 = mips64 and "000000dfDST",
+
+ -- Opcode SPECIAL3.
+ align_4 = "7c000220DSTA",
+ dalign_4 = mips64 and "7c000224DSTA",
+ bitswap_2 = "7c000020DT",
+ dbitswap_2 = mips64 and "7c000024DT",
+
+ -- Opcode COP1.
+ bc1eqz_2 = "45200000HB",
+ bc1nez_2 = "45a00000HB",
+
+ ["sel.s_3"] = "46000010FGH",
+ ["seleqz.s_3"] = "46000014FGH",
+ ["selnez.s_3"] = "46000017FGH",
+ ["maddf.s_3"] = "46000018FGH",
+ ["msubf.s_3"] = "46000019FGH",
+ ["rint.s_2"] = "4600001aFG",
+ ["class.s_2"] = "4600001bFG",
+ ["min.s_3"] = "4600001cFGH",
+ ["mina.s_3"] = "4600001dFGH",
+ ["max.s_3"] = "4600001eFGH",
+ ["maxa.s_3"] = "4600001fFGH",
+ ["cmp.af.s_3"] = "46800000FGH",
+ ["cmp.un.s_3"] = "46800001FGH",
+ ["cmp.or.s_3"] = "46800011FGH",
+ ["cmp.eq.s_3"] = "46800002FGH",
+ ["cmp.une.s_3"] = "46800012FGH",
+ ["cmp.ueq.s_3"] = "46800003FGH",
+ ["cmp.ne.s_3"] = "46800013FGH",
+ ["cmp.lt.s_3"] = "46800004FGH",
+ ["cmp.ult.s_3"] = "46800005FGH",
+ ["cmp.le.s_3"] = "46800006FGH",
+ ["cmp.ule.s_3"] = "46800007FGH",
+ ["cmp.saf.s_3"] = "46800008FGH",
+ ["cmp.sun.s_3"] = "46800009FGH",
+ ["cmp.sor.s_3"] = "46800019FGH",
+ ["cmp.seq.s_3"] = "4680000aFGH",
+ ["cmp.sune.s_3"] = "4680001aFGH",
+ ["cmp.sueq.s_3"] = "4680000bFGH",
+ ["cmp.sne.s_3"] = "4680001bFGH",
+ ["cmp.slt.s_3"] = "4680000cFGH",
+ ["cmp.sult.s_3"] = "4680000dFGH",
+ ["cmp.sle.s_3"] = "4680000eFGH",
+ ["cmp.sule.s_3"] = "4680000fFGH",
+
+ ["sel.d_3"] = "46200010FGH",
+ ["seleqz.d_3"] = "46200014FGH",
+ ["selnez.d_3"] = "46200017FGH",
+ ["maddf.d_3"] = "46200018FGH",
+ ["msubf.d_3"] = "46200019FGH",
+ ["rint.d_2"] = "4620001aFG",
+ ["class.d_2"] = "4620001bFG",
+ ["min.d_3"] = "4620001cFGH",
+ ["mina.d_3"] = "4620001dFGH",
+ ["max.d_3"] = "4620001eFGH",
+ ["maxa.d_3"] = "4620001fFGH",
+ ["cmp.af.d_3"] = "46a00000FGH",
+ ["cmp.un.d_3"] = "46a00001FGH",
+ ["cmp.or.d_3"] = "46a00011FGH",
+ ["cmp.eq.d_3"] = "46a00002FGH",
+ ["cmp.une.d_3"] = "46a00012FGH",
+ ["cmp.ueq.d_3"] = "46a00003FGH",
+ ["cmp.ne.d_3"] = "46a00013FGH",
+ ["cmp.lt.d_3"] = "46a00004FGH",
+ ["cmp.ult.d_3"] = "46a00005FGH",
+ ["cmp.le.d_3"] = "46a00006FGH",
+ ["cmp.ule.d_3"] = "46a00007FGH",
+ ["cmp.saf.d_3"] = "46a00008FGH",
+ ["cmp.sun.d_3"] = "46a00009FGH",
+ ["cmp.sor.d_3"] = "46a00019FGH",
+ ["cmp.seq.d_3"] = "46a0000aFGH",
+ ["cmp.sune.d_3"] = "46a0001aFGH",
+ ["cmp.sueq.d_3"] = "46a0000bFGH",
+ ["cmp.sne.d_3"] = "46a0001bFGH",
+ ["cmp.slt.d_3"] = "46a0000cFGH",
+ ["cmp.sult.d_3"] = "46a0000dFGH",
+ ["cmp.sle.d_3"] = "46a0000eFGH",
+ ["cmp.sule.d_3"] = "46a0000fFGH",
+
+ }) do map_op[k] = v end
+
+else -- Instructions removed by MIPSR6.
+
+ for k,v in pairs({
+ -- Traps, don't use.
+ addi_3 = "20000000TSI",
+ daddi_3 = mips64 and "60000000TSI",
+
+ -- Branch on likely, don't use.
+ beqzl_2 = "50000000SB",
+ beql_3 = "50000000STB",
+ bnezl_2 = "54000000SB",
+ bnel_3 = "54000000STB",
+ blezl_2 = "58000000SB",
+ bgtzl_2 = "5c000000SB",
+
+ lwl_2 = "88000000TO",
+ lwr_2 = "98000000TO",
+ swl_2 = "a8000000TO",
+ sdl_2 = mips64 and "b0000000TO",
+ sdr_2 = mips64 and "b1000000TO",
+ swr_2 = "b8000000TO",
+ cache_2 = "bc000000NO",
+ ll_2 = "c0000000TO",
+ pref_2 = "cc000000NO",
+ sc_2 = "e0000000TO",
+ scd_2 = mips64 and "f0000000TO",
+
+ -- Opcode SPECIAL.
+ movf_2 = "00000001DS",
+ movf_3 = "00000001DSC",
+ movt_2 = "00010001DS",
+ movt_3 = "00010001DSC",
+ jr_1 = "00000008S",
+ movz_3 = "0000000aDST",
+ movn_3 = "0000000bDST",
+ mfhi_1 = "00000010D",
+ mthi_1 = "00000011S",
+ mflo_1 = "00000012D",
+ mtlo_1 = "00000013S",
+ mult_2 = "00000018ST",
+ multu_2 = "00000019ST",
+ div_3 = "0000001aST",
+ divu_3 = "0000001bST",
+ ddiv_3 = mips64 and "0000001eST",
+ ddivu_3 = mips64 and "0000001fST",
+ dmult_2 = mips64 and "0000001cST",
+ dmultu_2 = mips64 and "0000001dST",
+
+ -- Opcode REGIMM.
+ tgei_2 = "04080000SI",
+ tgeiu_2 = "04090000SI",
+ tlti_2 = "040a0000SI",
+ tltiu_2 = "040b0000SI",
+ teqi_2 = "040c0000SI",
+ tnei_2 = "040e0000SI",
+ bltzal_2 = "04100000SB",
+ bgezal_2 = "04110000SB",
+ bltzall_2 = "04120000SB",
+ bgezall_2 = "04130000SB",
+
+ -- Opcode SPECIAL2.
+ madd_2 = "70000000ST",
+ maddu_2 = "70000001ST",
+ mul_3 = "70000002DST",
+ msub_2 = "70000004ST",
+ msubu_2 = "70000005ST",
+ clz_2 = "70000020D=TS",
+ clo_2 = "70000021D=TS",
+ dclz_2 = mips64 and "70000024D=TS",
+ dclo_2 = mips64 and "70000025D=TS",
+ sdbbp_0 = "7000003f",
+ sdbbp_1 = "7000003fY",
+
+ -- Opcode COP1.
+ bc1f_1 = "45000000B",
+ bc1f_2 = "45000000CB",
+ bc1t_1 = "45010000B",
+ bc1t_2 = "45010000CB",
+ bc1fl_1 = "45020000B",
+ bc1fl_2 = "45020000CB",
+ bc1tl_1 = "45030000B",
+ bc1tl_2 = "45030000CB",
+
+ ["movf.s_2"] = "46000011FG",
+ ["movf.s_3"] = "46000011FGC",
+ ["movt.s_2"] = "46010011FG",
+ ["movt.s_3"] = "46010011FGC",
+ ["movz.s_3"] = "46000012FGT",
+ ["movn.s_3"] = "46000013FGT",
+ ["cvt.ps.s_3"] = "46000026FGH",
+ ["c.f.s_2"] = "46000030GH",
+ ["c.f.s_3"] = "46000030VGH",
+ ["c.un.s_2"] = "46000031GH",
+ ["c.un.s_3"] = "46000031VGH",
+ ["c.eq.s_2"] = "46000032GH",
+ ["c.eq.s_3"] = "46000032VGH",
+ ["c.ueq.s_2"] = "46000033GH",
+ ["c.ueq.s_3"] = "46000033VGH",
+ ["c.olt.s_2"] = "46000034GH",
+ ["c.olt.s_3"] = "46000034VGH",
+ ["c.ult.s_2"] = "46000035GH",
+ ["c.ult.s_3"] = "46000035VGH",
+ ["c.ole.s_2"] = "46000036GH",
+ ["c.ole.s_3"] = "46000036VGH",
+ ["c.ule.s_2"] = "46000037GH",
+ ["c.ule.s_3"] = "46000037VGH",
+ ["c.sf.s_2"] = "46000038GH",
+ ["c.sf.s_3"] = "46000038VGH",
+ ["c.ngle.s_2"] = "46000039GH",
+ ["c.ngle.s_3"] = "46000039VGH",
+ ["c.seq.s_2"] = "4600003aGH",
+ ["c.seq.s_3"] = "4600003aVGH",
+ ["c.ngl.s_2"] = "4600003bGH",
+ ["c.ngl.s_3"] = "4600003bVGH",
+ ["c.lt.s_2"] = "4600003cGH",
+ ["c.lt.s_3"] = "4600003cVGH",
+ ["c.nge.s_2"] = "4600003dGH",
+ ["c.nge.s_3"] = "4600003dVGH",
+ ["c.le.s_2"] = "4600003eGH",
+ ["c.le.s_3"] = "4600003eVGH",
+ ["c.ngt.s_2"] = "4600003fGH",
+ ["c.ngt.s_3"] = "4600003fVGH",
+ ["movf.d_2"] = "46200011FG",
+ ["movf.d_3"] = "46200011FGC",
+ ["movt.d_2"] = "46210011FG",
+ ["movt.d_3"] = "46210011FGC",
+ ["movz.d_3"] = "46200012FGT",
+ ["movn.d_3"] = "46200013FGT",
+ ["c.f.d_2"] = "46200030GH",
+ ["c.f.d_3"] = "46200030VGH",
+ ["c.un.d_2"] = "46200031GH",
+ ["c.un.d_3"] = "46200031VGH",
+ ["c.eq.d_2"] = "46200032GH",
+ ["c.eq.d_3"] = "46200032VGH",
+ ["c.ueq.d_2"] = "46200033GH",
+ ["c.ueq.d_3"] = "46200033VGH",
+ ["c.olt.d_2"] = "46200034GH",
+ ["c.olt.d_3"] = "46200034VGH",
+ ["c.ult.d_2"] = "46200035GH",
+ ["c.ult.d_3"] = "46200035VGH",
+ ["c.ole.d_2"] = "46200036GH",
+ ["c.ole.d_3"] = "46200036VGH",
+ ["c.ule.d_2"] = "46200037GH",
+ ["c.ule.d_3"] = "46200037VGH",
+ ["c.sf.d_2"] = "46200038GH",
+ ["c.sf.d_3"] = "46200038VGH",
+ ["c.ngle.d_2"] = "46200039GH",
+ ["c.ngle.d_3"] = "46200039VGH",
+ ["c.seq.d_2"] = "4620003aGH",
+ ["c.seq.d_3"] = "4620003aVGH",
+ ["c.ngl.d_2"] = "4620003bGH",
+ ["c.ngl.d_3"] = "4620003bVGH",
+ ["c.lt.d_2"] = "4620003cGH",
+ ["c.lt.d_3"] = "4620003cVGH",
+ ["c.nge.d_2"] = "4620003dGH",
+ ["c.nge.d_3"] = "4620003dVGH",
+ ["c.le.d_2"] = "4620003eGH",
+ ["c.le.d_3"] = "4620003eVGH",
+ ["c.ngt.d_2"] = "4620003fGH",
+ ["c.ngt.d_3"] = "4620003fVGH",
+ ["add.ps_3"] = "46c00000FGH",
+ ["sub.ps_3"] = "46c00001FGH",
+ ["mul.ps_3"] = "46c00002FGH",
+ ["abs.ps_2"] = "46c00005FG",
+ ["mov.ps_2"] = "46c00006FG",
+ ["neg.ps_2"] = "46c00007FG",
+ ["movf.ps_2"] = "46c00011FG",
+ ["movf.ps_3"] = "46c00011FGC",
+ ["movt.ps_2"] = "46c10011FG",
+ ["movt.ps_3"] = "46c10011FGC",
+ ["movz.ps_3"] = "46c00012FGT",
+ ["movn.ps_3"] = "46c00013FGT",
+ ["cvt.s.pu_2"] = "46c00020FG",
+ ["cvt.s.pl_2"] = "46c00028FG",
+ ["pll.ps_3"] = "46c0002cFGH",
+ ["plu.ps_3"] = "46c0002dFGH",
+ ["pul.ps_3"] = "46c0002eFGH",
+ ["puu.ps_3"] = "46c0002fFGH",
+ ["c.f.ps_2"] = "46c00030GH",
+ ["c.f.ps_3"] = "46c00030VGH",
+ ["c.un.ps_2"] = "46c00031GH",
+ ["c.un.ps_3"] = "46c00031VGH",
+ ["c.eq.ps_2"] = "46c00032GH",
+ ["c.eq.ps_3"] = "46c00032VGH",
+ ["c.ueq.ps_2"] = "46c00033GH",
+ ["c.ueq.ps_3"] = "46c00033VGH",
+ ["c.olt.ps_2"] = "46c00034GH",
+ ["c.olt.ps_3"] = "46c00034VGH",
+ ["c.ult.ps_2"] = "46c00035GH",
+ ["c.ult.ps_3"] = "46c00035VGH",
+ ["c.ole.ps_2"] = "46c00036GH",
+ ["c.ole.ps_3"] = "46c00036VGH",
+ ["c.ule.ps_2"] = "46c00037GH",
+ ["c.ule.ps_3"] = "46c00037VGH",
+ ["c.sf.ps_2"] = "46c00038GH",
+ ["c.sf.ps_3"] = "46c00038VGH",
+ ["c.ngle.ps_2"] = "46c00039GH",
+ ["c.ngle.ps_3"] = "46c00039VGH",
+ ["c.seq.ps_2"] = "46c0003aGH",
+ ["c.seq.ps_3"] = "46c0003aVGH",
+ ["c.ngl.ps_2"] = "46c0003bGH",
+ ["c.ngl.ps_3"] = "46c0003bVGH",
+ ["c.lt.ps_2"] = "46c0003cGH",
+ ["c.lt.ps_3"] = "46c0003cVGH",
+ ["c.nge.ps_2"] = "46c0003dGH",
+ ["c.nge.ps_3"] = "46c0003dVGH",
+ ["c.le.ps_2"] = "46c0003eGH",
+ ["c.le.ps_3"] = "46c0003eVGH",
+ ["c.ngt.ps_2"] = "46c0003fGH",
+ ["c.ngt.ps_3"] = "46c0003fVGH",
+
+ -- Opcode COP1X.
+ lwxc1_2 = "4c000000FX",
+ ldxc1_2 = "4c000001FX",
+ luxc1_2 = "4c000005FX",
+ swxc1_2 = "4c000008FX",
+ sdxc1_2 = "4c000009FX",
+ suxc1_2 = "4c00000dFX",
+ prefx_2 = "4c00000fMX",
+ ["alnv.ps_4"] = "4c00001eFGHS",
+ ["madd.s_4"] = "4c000020FRGH",
+ ["madd.d_4"] = "4c000021FRGH",
+ ["madd.ps_4"] = "4c000026FRGH",
+ ["msub.s_4"] = "4c000028FRGH",
+ ["msub.d_4"] = "4c000029FRGH",
+ ["msub.ps_4"] = "4c00002eFRGH",
+ ["nmadd.s_4"] = "4c000030FRGH",
+ ["nmadd.d_4"] = "4c000031FRGH",
+ ["nmadd.ps_4"] = "4c000036FRGH",
+ ["nmsub.s_4"] = "4c000038FRGH",
+ ["nmsub.d_4"] = "4c000039FRGH",
+ ["nmsub.ps_4"] = "4c00003eFRGH",
+
+ }) do map_op[k] = v end
+
+end
+
+------------------------------------------------------------------------------
+
+local function parse_gpr(expr)
+ local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$")
+ local tp = map_type[tname or expr]
+ if tp then
+ local reg = ovreg or tp.reg
+ if not reg then
+ werror("type `"..(tname or expr).."' needs a register override")
+ end
+ expr = reg
+ end
+ local r = match(expr, "^r([1-3]?[0-9])$")
+ if r then
+ r = tonumber(r)
+ if r <= 31 then return r, tp end
+ end
+ werror("bad register name `"..expr.."'")
+end
+
+local function parse_fpr(expr)
+ local r = match(expr, "^f([1-3]?[0-9])$")
+ if r then
+ r = tonumber(r)
+ if r <= 31 then return r end
+ end
+ werror("bad register name `"..expr.."'")
+end
+
+local function parse_imm(imm, bits, shift, scale, signed, action)
+ local n = tonumber(imm)
+ if n then
+ local m = sar(n, scale)
+ if shl(m, scale) == n then
+ if signed then
+ local s = sar(m, bits-1)
+ if s == 0 then return shl(m, shift)
+ elseif s == -1 then return shl(m + shl(1, bits), shift) end
+ else
+ if sar(m, bits) == 0 then return shl(m, shift) end
+ end
+ end
+ werror("out of range immediate `"..imm.."'")
+ elseif match(imm, "^[rf]([1-3]?[0-9])$") or
+ match(imm, "^([%w_]+):([rf][1-3]?[0-9])$") then
+ werror("expected immediate operand, got register")
+ else
+ waction(action or "IMM",
+ (signed and 32768 or 0)+shl(scale, 10)+shl(bits, 5)+shift, imm)
+ return 0
+ end
+end
+
+local function parse_disp(disp)
+ local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
+ if imm then
+ local r = shl(parse_gpr(reg), 21)
+ local extname = match(imm, "^extern%s+(%S+)$")
+ if extname then
+ waction("REL_EXT", map_extern[extname], nil, 1)
+ return r
+ else
+ return r + parse_imm(imm, 16, 0, 0, true)
+ end
+ end
+ local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
+ if reg and tailr ~= "" then
+ local r, tp = parse_gpr(reg)
+ if tp then
+ waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
+ return shl(r, 21)
+ end
+ end
+ werror("bad displacement `"..disp.."'")
+end
+
+local function parse_index(idx)
+ local rt, rs = match(idx, "^(.*)%(([%w_:]+)%)$")
+ if rt then
+ rt = parse_gpr(rt)
+ rs = parse_gpr(rs)
+ return shl(rt, 16) + shl(rs, 21)
+ end
+ werror("bad index `"..idx.."'")
+end
+
+local function parse_label(label, def)
+ local prefix = sub(label, 1, 2)
+ -- =>label (pc label reference)
+ if prefix == "=>" then
+ return "PC", 0, sub(label, 3)
+ end
+ -- ->name (global label reference)
+ if prefix == "->" then
+ return "LG", map_global[sub(label, 3)]
+ end
+ if def then
+ -- [1-9] (local label definition)
+ if match(label, "^[1-9]$") then
+ return "LG", 10+tonumber(label)
+ end
+ else
+ -- [<>][1-9] (local label reference)
+ local dir, lnum = match(label, "^([<>])([1-9])$")
+ if dir then -- Fwd: 1-9, Bkwd: 11-19.
+ return "LG", lnum + (dir == ">" and 0 or 10)
+ end
+ -- extern label (extern label reference)
+ local extname = match(label, "^extern%s+(%S+)$")
+ if extname then
+ return "EXT", map_extern[extname]
+ end
+ end
+ werror("bad label `"..label.."'")
+end
+
+------------------------------------------------------------------------------
+
+-- Handle opcodes defined with template strings.
+map_op[".template__"] = function(params, template, nparams)
+ if not params then return sub(template, 9) end
+ local op = tonumber(sub(template, 1, 8), 16)
+ local n = 1
+
+ -- Limit number of section buffer positions used by a single dasm_put().
+ -- A single opcode needs a maximum of 2 positions (ins/ext).
+ if secpos+2 > maxsecpos then wflush() end
+ local pos = wpos()
+
+ -- Process each character.
+ for p in gmatch(sub(template, 9), ".") do
+ if p == "D" then
+ op = op + shl(parse_gpr(params[n]), 11); n = n + 1
+ elseif p == "T" then
+ op = op + shl(parse_gpr(params[n]), 16); n = n + 1
+ elseif p == "S" then
+ op = op + shl(parse_gpr(params[n]), 21); n = n + 1
+ elseif p == "F" then
+ op = op + shl(parse_fpr(params[n]), 6); n = n + 1
+ elseif p == "G" then
+ op = op + shl(parse_fpr(params[n]), 11); n = n + 1
+ elseif p == "H" then
+ op = op + shl(parse_fpr(params[n]), 16); n = n + 1
+ elseif p == "R" then
+ op = op + shl(parse_fpr(params[n]), 21); n = n + 1
+ elseif p == "I" then
+ op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1
+ elseif p == "U" then
+ op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1
+ elseif p == "O" then
+ op = op + parse_disp(params[n]); n = n + 1
+ elseif p == "X" then
+ op = op + parse_index(params[n]); n = n + 1
+ elseif p == "B" or p == "J" or p == "K" or p == "L" then
+ local mode, m, s = parse_label(params[n], false)
+ if p == "J" then m = m + 0xa800
+ elseif p == "K" then m = m + 0x5000
+ elseif p == "L" then m = m + 0xa000 end
+ waction("REL_"..mode, m, s, 1)
+ n = n + 1
+ elseif p == "A" then
+ op = op + parse_imm(params[n], 5, 6, 0, false); n = n + 1
+ elseif p == "a" then
+ local m = parse_imm(params[n], 6, 6, 0, false, "IMMS"); n = n + 1
+ op = op + band(m, 0x7c0) + band(shr(m, 9), 4)
+ elseif p == "M" then
+ op = op + parse_imm(params[n], 5, 11, 0, false); n = n + 1
+ elseif p == "N" then
+ op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1
+ elseif p == "C" then
+ op = op + parse_imm(params[n], 3, 18, 0, false); n = n + 1
+ elseif p == "V" then
+ op = op + parse_imm(params[n], 3, 8, 0, false); n = n + 1
+ elseif p == "W" then
+ op = op + parse_imm(params[n], 3, 0, 0, false); n = n + 1
+ elseif p == "Y" then
+ op = op + parse_imm(params[n], 20, 6, 0, false); n = n + 1
+ elseif p == "Z" then
+ op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1
+ elseif p == "=" then
+ n = n - 1 -- Re-use previous parameter for next template char.
+ else
+ assert(false)
+ end
+ end
+ wputpos(pos, op)
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcode to mark the position where the action list is to be emitted.
+map_op[".actionlist_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeactions(out, name) end)
+end
+
+-- Pseudo-opcode to mark the position where the global enum is to be emitted.
+map_op[".globals_1"] = function(params)
+ if not params then return "prefix" end
+ local prefix = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeglobals(out, prefix) end)
+end
+
+-- Pseudo-opcode to mark the position where the global names are to be emitted.
+map_op[".globalnames_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeglobalnames(out, name) end)
+end
+
+-- Pseudo-opcode to mark the position where the extern names are to be emitted.
+map_op[".externnames_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeexternnames(out, name) end)
+end
+
+------------------------------------------------------------------------------
+
+-- Label pseudo-opcode (converted from trailing colon form).
+map_op[".label_1"] = function(params)
+ if not params then return "[1-9] | ->global | =>pcexpr" end
+ if secpos+1 > maxsecpos then wflush() end
+ local mode, n, s = parse_label(params[1], true)
+ if mode == "EXT" then werror("bad label definition") end
+ waction("LABEL_"..mode, n, s, 1)
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcodes for data storage.
+map_op[".long_*"] = function(params)
+ if not params then return "imm..." end
+ for _,p in ipairs(params) do
+ local n = tonumber(p)
+ if not n then werror("bad immediate `"..p.."'") end
+ if n < 0 then n = n + 2^32 end
+ wputw(n)
+ if secpos+2 > maxsecpos then wflush() end
+ end
+end
+
+-- Alignment pseudo-opcode.
+map_op[".align_1"] = function(params)
+ if not params then return "numpow2" end
+ if secpos+1 > maxsecpos then wflush() end
+ local align = tonumber(params[1])
+ if align then
+ local x = align
+ -- Must be a power of 2 in the range (2 ... 256).
+ for i=1,8 do
+ x = x / 2
+ if x == 1 then
+ waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
+ return
+ end
+ end
+ end
+ werror("bad alignment")
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcode for (primitive) type definitions (map to C types).
+map_op[".type_3"] = function(params, nparams)
+ if not params then
+ return nparams == 2 and "name, ctype" or "name, ctype, reg"
+ end
+ local name, ctype, reg = params[1], params[2], params[3]
+ if not match(name, "^[%a_][%w_]*$") then
+ werror("bad type name `"..name.."'")
+ end
+ local tp = map_type[name]
+ if tp then
+ werror("duplicate type `"..name.."'")
+ end
+ -- Add #type to defines. A bit unclean to put it in map_archdef.
+ map_archdef["#"..name] = "sizeof("..ctype..")"
+ -- Add new type and emit shortcut define.
+ local num = ctypenum + 1
+ map_type[name] = {
+ ctype = ctype,
+ ctypefmt = format("Dt%X(%%s)", num),
+ reg = reg,
+ }
+ wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
+ ctypenum = num
+end
+map_op[".type_2"] = map_op[".type_3"]
+
+-- Dump type definitions.
+local function dumptypes(out, lvl)
+ local t = {}
+ for name in pairs(map_type) do t[#t+1] = name end
+ sort(t)
+ out:write("Type definitions:\n")
+ for _,name in ipairs(t) do
+ local tp = map_type[name]
+ local reg = tp.reg or ""
+ out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
+ end
+ out:write("\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Set the current section.
+function _M.section(num)
+ waction("SECTION", num)
+ wflush(true) -- SECTION is a terminal action.
+end
+
+------------------------------------------------------------------------------
+
+-- Dump architecture description.
+function _M.dumparch(out)
+ out:write(format("DynASM %s version %s, released %s\n\n",
+ _info.arch, _info.version, _info.release))
+ dumpactions(out)
+end
+
+-- Dump all user defined elements.
+function _M.dumpdef(out, lvl)
+ dumptypes(out, lvl)
+ dumpglobals(out, lvl)
+ dumpexterns(out, lvl)
+end
+
+------------------------------------------------------------------------------
+
+-- Pass callbacks from/to the DynASM core.
+function _M.passcb(wl, we, wf, ww)
+ wline, werror, wfatal, wwarn = wl, we, wf, ww
+ return wflush
+end
+
+-- Setup the arch-specific module.
+function _M.setup(arch, opt)
+ g_arch, g_opt = arch, opt
+end
+
+-- Merge the core maps and the arch-specific maps.
+function _M.mergemaps(map_coreop, map_def)
+ setmetatable(map_op, { __index = map_coreop })
+ setmetatable(map_def, { __index = map_archdef })
+ return map_op, map_def
+end
+
+return _M
+
+------------------------------------------------------------------------------
+
diff --git a/LuaJIT-2.1/dynasm/dasm_mips64.lua b/LuaJIT-2.1/dynasm/dasm_mips64.lua
new file mode 100644
index 00000000..cfcf20e5
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_mips64.lua
@@ -0,0 +1,12 @@
+------------------------------------------------------------------------------
+-- DynASM MIPS64 module.
+--
+-- Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+-- See dynasm.lua for full copyright notice.
+------------------------------------------------------------------------------
+-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
+-- All the interesting stuff is there.
+------------------------------------------------------------------------------
+
+mips64 = true -- Using a global is an ugly, but effective solution.
+return require("dasm_mips")
diff --git a/LuaJIT-2.1/dynasm/dasm_ppc.h b/LuaJIT-2.1/dynasm/dasm_ppc.h
new file mode 100644
index 00000000..e97b4efa
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_ppc.h
@@ -0,0 +1,418 @@
+/*
+** DynASM PPC/PPC64 encoding engine.
+** Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+** Released under the MIT license. See dynasm.lua for full copyright notice.
+*/
+
+#include
+#include
+#include
+#include
+
+#define DASM_ARCH "ppc"
+
+#ifndef DASM_EXTERN
+#define DASM_EXTERN(a,b,c,d) 0
+#endif
+
+/* Action definitions. */
+enum {
+ DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
+ /* The following actions need a buffer position. */
+ DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
+ /* The following actions also have an argument. */
+ DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMSH,
+ DASM__MAX
+};
+
+/* Maximum number of section buffer positions for a single dasm_put() call. */
+#define DASM_MAXSECPOS 25
+
+/* DynASM encoder status codes. Action list offset or number are or'ed in. */
+#define DASM_S_OK 0x00000000
+#define DASM_S_NOMEM 0x01000000
+#define DASM_S_PHASE 0x02000000
+#define DASM_S_MATCH_SEC 0x03000000
+#define DASM_S_RANGE_I 0x11000000
+#define DASM_S_RANGE_SEC 0x12000000
+#define DASM_S_RANGE_LG 0x13000000
+#define DASM_S_RANGE_PC 0x14000000
+#define DASM_S_RANGE_REL 0x15000000
+#define DASM_S_UNDEF_LG 0x21000000
+#define DASM_S_UNDEF_PC 0x22000000
+
+/* Macros to convert positions (8 bit section + 24 bit index). */
+#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
+#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
+#define DASM_SEC2POS(sec) ((sec)<<24)
+#define DASM_POS2SEC(pos) ((pos)>>24)
+#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
+
+/* Action list type. */
+typedef const unsigned int *dasm_ActList;
+
+/* Per-section structure. */
+typedef struct dasm_Section {
+ int *rbuf; /* Biased buffer pointer (negative section bias). */
+ int *buf; /* True buffer pointer. */
+ size_t bsize; /* Buffer size in bytes. */
+ int pos; /* Biased buffer position. */
+ int epos; /* End of biased buffer position - max single put. */
+ int ofs; /* Byte offset into section. */
+} dasm_Section;
+
+/* Core structure holding the DynASM encoding state. */
+struct dasm_State {
+ size_t psize; /* Allocated size of this structure. */
+ dasm_ActList actionlist; /* Current actionlist pointer. */
+ int *lglabels; /* Local/global chain/pos ptrs. */
+ size_t lgsize;
+ int *pclabels; /* PC label chains/pos ptrs. */
+ size_t pcsize;
+ void **globals; /* Array of globals. */
+ dasm_Section *section; /* Pointer to active section. */
+ size_t codesize; /* Total size of all code sections. */
+ int maxsection; /* 0 <= sectionidx < maxsection. */
+ int status; /* Status code. */
+ dasm_Section sections[1]; /* All sections. Alloc-extended. */
+};
+
+/* The size of the core structure depends on the max. number of sections. */
+#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
+
+
+/* Initialize DynASM state. */
+void dasm_init(Dst_DECL, int maxsection)
+{
+ dasm_State *D;
+ size_t psz = 0;
+ Dst_REF = NULL;
+ DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
+ D = Dst_REF;
+ D->psize = psz;
+ D->lglabels = NULL;
+ D->lgsize = 0;
+ D->pclabels = NULL;
+ D->pcsize = 0;
+ D->globals = NULL;
+ D->maxsection = maxsection;
+ memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section));
+}
+
+/* Free DynASM state. */
+void dasm_free(Dst_DECL)
+{
+ dasm_State *D = Dst_REF;
+ int i;
+ for (i = 0; i < D->maxsection; i++)
+ if (D->sections[i].buf)
+ DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
+ if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
+ if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
+ DASM_M_FREE(Dst, D, D->psize);
+}
+
+/* Setup global label array. Must be called before dasm_setup(). */
+void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
+{
+ dasm_State *D = Dst_REF;
+ D->globals = gl;
+ DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
+}
+
+/* Grow PC label array. Can be called after dasm_setup(), too. */
+void dasm_growpc(Dst_DECL, unsigned int maxpc)
+{
+ dasm_State *D = Dst_REF;
+ size_t osz = D->pcsize;
+ DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
+ memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
+}
+
+/* Setup encoder. */
+void dasm_setup(Dst_DECL, const void *actionlist)
+{
+ dasm_State *D = Dst_REF;
+ int i;
+ D->actionlist = (dasm_ActList)actionlist;
+ D->status = DASM_S_OK;
+ D->section = &D->sections[0];
+ memset((void *)D->lglabels, 0, D->lgsize);
+ if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
+ for (i = 0; i < D->maxsection; i++) {
+ D->sections[i].pos = DASM_SEC2POS(i);
+ D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos;
+ D->sections[i].ofs = 0;
+ }
+}
+
+
+#ifdef DASM_CHECKS
+#define CK(x, st) \
+ do { if (!(x)) { \
+ D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
+#define CKPL(kind, st) \
+ do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
+ D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
+#else
+#define CK(x, st) ((void)0)
+#define CKPL(kind, st) ((void)0)
+#endif
+
+/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
+void dasm_put(Dst_DECL, int start, ...)
+{
+ va_list ap;
+ dasm_State *D = Dst_REF;
+ dasm_ActList p = D->actionlist + start;
+ dasm_Section *sec = D->section;
+ int pos = sec->pos, ofs = sec->ofs;
+ int *b;
+
+ if (pos >= sec->epos) {
+ DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
+ sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
+ sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
+ sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
+ }
+
+ b = sec->rbuf;
+ b[pos++] = start;
+
+ va_start(ap, start);
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16);
+ if (action >= DASM__MAX) {
+ ofs += 4;
+ } else {
+ int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
+ switch (action) {
+ case DASM_STOP: goto stop;
+ case DASM_SECTION:
+ n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
+ D->section = &D->sections[n]; goto stop;
+ case DASM_ESC: p++; ofs += 4; break;
+ case DASM_REL_EXT: break;
+ case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
+ case DASM_REL_LG:
+ n = (ins & 2047) - 10; pl = D->lglabels + n;
+ /* Bkwd rel or global. */
+ if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
+ pl += 10; n = *pl;
+ if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
+ goto linkrel;
+ case DASM_REL_PC:
+ pl = D->pclabels + n; CKPL(pc, PC);
+ putrel:
+ n = *pl;
+ if (n < 0) { /* Label exists. Get label pos and store it. */
+ b[pos] = -n;
+ } else {
+ linkrel:
+ b[pos] = n; /* Else link to rel chain, anchored at label. */
+ *pl = pos;
+ }
+ pos++;
+ break;
+ case DASM_LABEL_LG:
+ pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
+ case DASM_LABEL_PC:
+ pl = D->pclabels + n; CKPL(pc, PC);
+ putlabel:
+ n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
+ while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
+ }
+ *pl = -pos; /* Label exists now. */
+ b[pos++] = ofs; /* Store pass1 offset estimate. */
+ break;
+ case DASM_IMM:
+#ifdef DASM_CHECKS
+ CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
+#endif
+ n >>= ((ins>>10)&31);
+#ifdef DASM_CHECKS
+ if (ins & 0x8000)
+ CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
+ else
+ CK((n>>((ins>>5)&31)) == 0, RANGE_I);
+#endif
+ b[pos++] = n;
+ break;
+ case DASM_IMMSH:
+ CK((n >> 6) == 0, RANGE_I);
+ b[pos++] = n;
+ break;
+ }
+ }
+ }
+stop:
+ va_end(ap);
+ sec->pos = pos;
+ sec->ofs = ofs;
+}
+#undef CK
+
+/* Pass 2: Link sections, shrink aligns, fix label offsets. */
+int dasm_link(Dst_DECL, size_t *szp)
+{
+ dasm_State *D = Dst_REF;
+ int secnum;
+ int ofs = 0;
+
+#ifdef DASM_CHECKS
+ *szp = 0;
+ if (D->status != DASM_S_OK) return D->status;
+ {
+ int pc;
+ for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
+ if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
+ }
+#endif
+
+ { /* Handle globals not defined in this translation unit. */
+ int idx;
+ for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
+ int n = D->lglabels[idx];
+ /* Undefined label: Collapse rel chain and replace with marker (< 0). */
+ while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
+ }
+ }
+
+ /* Combine all code sections. No support for data sections (yet). */
+ for (secnum = 0; secnum < D->maxsection; secnum++) {
+ dasm_Section *sec = D->sections + secnum;
+ int *b = sec->rbuf;
+ int pos = DASM_SEC2POS(secnum);
+ int lastpos = sec->pos;
+
+ while (pos != lastpos) {
+ dasm_ActList p = D->actionlist + b[pos++];
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16);
+ switch (action) {
+ case DASM_STOP: case DASM_SECTION: goto stop;
+ case DASM_ESC: p++; break;
+ case DASM_REL_EXT: break;
+ case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
+ case DASM_REL_LG: case DASM_REL_PC: pos++; break;
+ case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
+ case DASM_IMM: case DASM_IMMSH: pos++; break;
+ }
+ }
+ stop: (void)0;
+ }
+ ofs += sec->ofs; /* Next section starts right after current section. */
+ }
+
+ D->codesize = ofs; /* Total size of all code sections */
+ *szp = ofs;
+ return DASM_S_OK;
+}
+
+#ifdef DASM_CHECKS
+#define CK(x, st) \
+ do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
+#else
+#define CK(x, st) ((void)0)
+#endif
+
+/* Pass 3: Encode sections. */
+int dasm_encode(Dst_DECL, void *buffer)
+{
+ dasm_State *D = Dst_REF;
+ char *base = (char *)buffer;
+ unsigned int *cp = (unsigned int *)buffer;
+ int secnum;
+
+ /* Encode all code sections. No support for data sections (yet). */
+ for (secnum = 0; secnum < D->maxsection; secnum++) {
+ dasm_Section *sec = D->sections + secnum;
+ int *b = sec->buf;
+ int *endb = sec->rbuf + sec->pos;
+
+ while (b != endb) {
+ dasm_ActList p = D->actionlist + *b++;
+ while (1) {
+ unsigned int ins = *p++;
+ unsigned int action = (ins >> 16);
+ int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
+ switch (action) {
+ case DASM_STOP: case DASM_SECTION: goto stop;
+ case DASM_ESC: *cp++ = *p++; break;
+ case DASM_REL_EXT:
+ n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1) - 4;
+ goto patchrel;
+ case DASM_ALIGN:
+ ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
+ break;
+ case DASM_REL_LG:
+ if (n < 0) {
+ n = (int)((ptrdiff_t)D->globals[-n-10] - (ptrdiff_t)cp);
+ goto patchrel;
+ }
+ /* fallthrough */
+ case DASM_REL_PC:
+ CK(n >= 0, UNDEF_PC);
+ n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base);
+ patchrel:
+ CK((n & 3) == 0 &&
+ (((n+4) + ((ins & 2048) ? 0x00008000 : 0x02000000)) >>
+ ((ins & 2048) ? 16 : 26)) == 0, RANGE_REL);
+ cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc));
+ break;
+ case DASM_LABEL_LG:
+ ins &= 2047; if (ins >= 20) D->globals[ins-20] = (void *)(base + n);
+ break;
+ case DASM_LABEL_PC: break;
+ case DASM_IMM:
+ cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
+ break;
+ case DASM_IMMSH:
+ cp[-1] |= (ins & 1) ? ((n&31)<<11)|((n&32)>>4) : ((n&31)<<6)|(n&32);
+ break;
+ default: *cp++ = ins; break;
+ }
+ }
+ stop: (void)0;
+ }
+ }
+
+ if (base + D->codesize != (char *)cp) /* Check for phase errors. */
+ return DASM_S_PHASE;
+ return DASM_S_OK;
+}
+#undef CK
+
+/* Get PC label offset. */
+int dasm_getpclabel(Dst_DECL, unsigned int pc)
+{
+ dasm_State *D = Dst_REF;
+ if (pc*sizeof(int) < D->pcsize) {
+ int pos = D->pclabels[pc];
+ if (pos < 0) return *DASM_POS2PTR(D, -pos);
+ if (pos > 0) return -1; /* Undefined. */
+ }
+ return -2; /* Unused or out of range. */
+}
+
+#ifdef DASM_CHECKS
+/* Optional sanity checker to call between isolated encoding steps. */
+int dasm_checkstep(Dst_DECL, int secmatch)
+{
+ dasm_State *D = Dst_REF;
+ if (D->status == DASM_S_OK) {
+ int i;
+ for (i = 1; i <= 9; i++) {
+ if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
+ D->lglabels[i] = 0;
+ }
+ }
+ if (D->status == DASM_S_OK && secmatch >= 0 &&
+ D->section != &D->sections[secmatch])
+ D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
+ return D->status;
+}
+#endif
+
diff --git a/LuaJIT-2.1/dynasm/dasm_ppc.lua b/LuaJIT-2.1/dynasm/dasm_ppc.lua
new file mode 100644
index 00000000..67662330
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_ppc.lua
@@ -0,0 +1,1919 @@
+------------------------------------------------------------------------------
+-- DynASM PPC/PPC64 module.
+--
+-- Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+-- See dynasm.lua for full copyright notice.
+--
+-- Support for various extensions contributed by Caio Souza Oliveira.
+------------------------------------------------------------------------------
+
+-- Module information:
+local _info = {
+ arch = "ppc",
+ description = "DynASM PPC module",
+ version = "1.5.0",
+ vernum = 10500,
+ release = "2021-05-02",
+ author = "Mike Pall",
+ license = "MIT",
+}
+
+-- Exported glue functions for the arch-specific module.
+local _M = { _info = _info }
+
+-- Cache library functions.
+local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
+local assert, setmetatable = assert, setmetatable
+local _s = string
+local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
+local match, gmatch = _s.match, _s.gmatch
+local concat, sort = table.concat, table.sort
+local bit = bit or require("bit")
+local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
+local tohex = bit.tohex
+
+-- Inherited tables and callbacks.
+local g_opt, g_arch
+local wline, werror, wfatal, wwarn
+
+-- Action name list.
+-- CHECK: Keep this in sync with the C code!
+local action_names = {
+ "STOP", "SECTION", "ESC", "REL_EXT",
+ "ALIGN", "REL_LG", "LABEL_LG",
+ "REL_PC", "LABEL_PC", "IMM", "IMMSH"
+}
+
+-- Maximum number of section buffer positions for dasm_put().
+-- CHECK: Keep this in sync with the C code!
+local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
+
+-- Action name -> action number.
+local map_action = {}
+for n,name in ipairs(action_names) do
+ map_action[name] = n-1
+end
+
+-- Action list buffer.
+local actlist = {}
+
+-- Argument list for next dasm_put(). Start with offset 0 into action list.
+local actargs = { 0 }
+
+-- Current number of section buffer positions for dasm_put().
+local secpos = 1
+
+------------------------------------------------------------------------------
+
+-- Dump action names and numbers.
+local function dumpactions(out)
+ out:write("DynASM encoding engine action codes:\n")
+ for n,name in ipairs(action_names) do
+ local num = map_action[name]
+ out:write(format(" %-10s %02X %d\n", name, num, num))
+ end
+ out:write("\n")
+end
+
+-- Write action list buffer as a huge static C array.
+local function writeactions(out, name)
+ local nn = #actlist
+ if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
+ out:write("static const unsigned int ", name, "[", nn, "] = {\n")
+ for i = 1,nn-1 do
+ assert(out:write("0x", tohex(actlist[i]), ",\n"))
+ end
+ assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
+end
+
+------------------------------------------------------------------------------
+
+-- Add word to action list.
+local function wputxw(n)
+ assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
+ actlist[#actlist+1] = n
+end
+
+-- Add action to list with optional arg. Advance buffer pos, too.
+local function waction(action, val, a, num)
+ local w = assert(map_action[action], "bad action name `"..action.."'")
+ wputxw(w * 0x10000 + (val or 0))
+ if a then actargs[#actargs+1] = a end
+ if a or num then secpos = secpos + (num or 1) end
+end
+
+-- Flush action list (intervening C code or buffer pos overflow).
+local function wflush(term)
+ if #actlist == actargs[1] then return end -- Nothing to flush.
+ if not term then waction("STOP") end -- Terminate action list.
+ wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
+ actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
+ secpos = 1 -- The actionlist offset occupies a buffer position, too.
+end
+
+-- Put escaped word.
+local function wputw(n)
+ if n <= 0xffffff then waction("ESC") end
+ wputxw(n)
+end
+
+-- Reserve position for word.
+local function wpos()
+ local pos = #actlist+1
+ actlist[pos] = ""
+ return pos
+end
+
+-- Store word to reserved position.
+local function wputpos(pos, n)
+ assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range")
+ actlist[pos] = n
+end
+
+------------------------------------------------------------------------------
+
+-- Global label name -> global label number. With auto assignment on 1st use.
+local next_global = 20
+local map_global = setmetatable({}, { __index = function(t, name)
+ if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
+ local n = next_global
+ if n > 2047 then werror("too many global labels") end
+ next_global = n + 1
+ t[name] = n
+ return n
+end})
+
+-- Dump global labels.
+local function dumpglobals(out, lvl)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("Global labels:\n")
+ for i=20,next_global-1 do
+ out:write(format(" %s\n", t[i]))
+ end
+ out:write("\n")
+end
+
+-- Write global label enum.
+local function writeglobals(out, prefix)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("enum {\n")
+ for i=20,next_global-1 do
+ out:write(" ", prefix, t[i], ",\n")
+ end
+ out:write(" ", prefix, "_MAX\n};\n")
+end
+
+-- Write global label names.
+local function writeglobalnames(out, name)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("static const char *const ", name, "[] = {\n")
+ for i=20,next_global-1 do
+ out:write(" \"", t[i], "\",\n")
+ end
+ out:write(" (const char *)0\n};\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Extern label name -> extern label number. With auto assignment on 1st use.
+local next_extern = 0
+local map_extern_ = {}
+local map_extern = setmetatable({}, { __index = function(t, name)
+ -- No restrictions on the name for now.
+ local n = next_extern
+ if n > 2047 then werror("too many extern labels") end
+ next_extern = n + 1
+ t[name] = n
+ map_extern_[n] = name
+ return n
+end})
+
+-- Dump extern labels.
+local function dumpexterns(out, lvl)
+ out:write("Extern labels:\n")
+ for i=0,next_extern-1 do
+ out:write(format(" %s\n", map_extern_[i]))
+ end
+ out:write("\n")
+end
+
+-- Write extern label names.
+local function writeexternnames(out, name)
+ out:write("static const char *const ", name, "[] = {\n")
+ for i=0,next_extern-1 do
+ out:write(" \"", map_extern_[i], "\",\n")
+ end
+ out:write(" (const char *)0\n};\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Arch-specific maps.
+local map_archdef = { sp = "r1" } -- Ext. register name -> int. name.
+
+local map_type = {} -- Type name -> { ctype, reg }
+local ctypenum = 0 -- Type number (for Dt... macros).
+
+-- Reverse defines for registers.
+function _M.revdef(s)
+ if s == "r1" then return "sp" end
+ return s
+end
+
+local map_cond = {
+ lt = 0, gt = 1, eq = 2, so = 3,
+ ge = 4, le = 5, ne = 6, ns = 7,
+}
+
+------------------------------------------------------------------------------
+
+local map_op, op_template
+
+local function op_alias(opname, f)
+ return function(params, nparams)
+ if not params then return "-> "..opname:sub(1, -3) end
+ f(params, nparams)
+ op_template(params, map_op[opname], nparams)
+ end
+end
+
+-- Template strings for PPC instructions.
+map_op = {
+ tdi_3 = "08000000ARI",
+ twi_3 = "0c000000ARI",
+ mulli_3 = "1c000000RRI",
+ subfic_3 = "20000000RRI",
+ cmplwi_3 = "28000000XRU",
+ cmplwi_2 = "28000000-RU",
+ cmpldi_3 = "28200000XRU",
+ cmpldi_2 = "28200000-RU",
+ cmpwi_3 = "2c000000XRI",
+ cmpwi_2 = "2c000000-RI",
+ cmpdi_3 = "2c200000XRI",
+ cmpdi_2 = "2c200000-RI",
+ addic_3 = "30000000RRI",
+ ["addic._3"] = "34000000RRI",
+ addi_3 = "38000000RR0I",
+ li_2 = "38000000RI",
+ la_2 = "38000000RD",
+ addis_3 = "3c000000RR0I",
+ lis_2 = "3c000000RI",
+ lus_2 = "3c000000RU",
+ bc_3 = "40000000AAK",
+ bcl_3 = "40000001AAK",
+ bdnz_1 = "42000000K",
+ bdz_1 = "42400000K",
+ sc_0 = "44000000",
+ b_1 = "48000000J",
+ bl_1 = "48000001J",
+ rlwimi_5 = "50000000RR~AAA.",
+ rlwinm_5 = "54000000RR~AAA.",
+ rlwnm_5 = "5c000000RR~RAA.",
+ ori_3 = "60000000RR~U",
+ nop_0 = "60000000",
+ oris_3 = "64000000RR~U",
+ xori_3 = "68000000RR~U",
+ xoris_3 = "6c000000RR~U",
+ ["andi._3"] = "70000000RR~U",
+ ["andis._3"] = "74000000RR~U",
+ lwz_2 = "80000000RD",
+ lwzu_2 = "84000000RD",
+ lbz_2 = "88000000RD",
+ lbzu_2 = "8c000000RD",
+ stw_2 = "90000000RD",
+ stwu_2 = "94000000RD",
+ stb_2 = "98000000RD",
+ stbu_2 = "9c000000RD",
+ lhz_2 = "a0000000RD",
+ lhzu_2 = "a4000000RD",
+ lha_2 = "a8000000RD",
+ lhau_2 = "ac000000RD",
+ sth_2 = "b0000000RD",
+ sthu_2 = "b4000000RD",
+ lmw_2 = "b8000000RD",
+ stmw_2 = "bc000000RD",
+ lfs_2 = "c0000000FD",
+ lfsu_2 = "c4000000FD",
+ lfd_2 = "c8000000FD",
+ lfdu_2 = "cc000000FD",
+ stfs_2 = "d0000000FD",
+ stfsu_2 = "d4000000FD",
+ stfd_2 = "d8000000FD",
+ stfdu_2 = "dc000000FD",
+ ld_2 = "e8000000RD", -- NYI: displacement must be divisible by 4.
+ ldu_2 = "e8000001RD",
+ lwa_2 = "e8000002RD",
+ std_2 = "f8000000RD",
+ stdu_2 = "f8000001RD",
+
+ subi_3 = op_alias("addi_3", function(p) p[3] = "-("..p[3]..")" end),
+ subis_3 = op_alias("addis_3", function(p) p[3] = "-("..p[3]..")" end),
+ subic_3 = op_alias("addic_3", function(p) p[3] = "-("..p[3]..")" end),
+ ["subic._3"] = op_alias("addic._3", function(p) p[3] = "-("..p[3]..")" end),
+
+ rotlwi_3 = op_alias("rlwinm_5", function(p)
+ p[4] = "0"; p[5] = "31"
+ end),
+ rotrwi_3 = op_alias("rlwinm_5", function(p)
+ p[3] = "32-("..p[3]..")"; p[4] = "0"; p[5] = "31"
+ end),
+ rotlw_3 = op_alias("rlwnm_5", function(p)
+ p[4] = "0"; p[5] = "31"
+ end),
+ slwi_3 = op_alias("rlwinm_5", function(p)
+ p[5] = "31-("..p[3]..")"; p[4] = "0"
+ end),
+ srwi_3 = op_alias("rlwinm_5", function(p)
+ p[4] = p[3]; p[3] = "32-("..p[3]..")"; p[5] = "31"
+ end),
+ clrlwi_3 = op_alias("rlwinm_5", function(p)
+ p[4] = p[3]; p[3] = "0"; p[5] = "31"
+ end),
+ clrrwi_3 = op_alias("rlwinm_5", function(p)
+ p[5] = "31-("..p[3]..")"; p[3] = "0"; p[4] = "0"
+ end),
+
+ -- Primary opcode 4:
+ mulhhwu_3 = "10000010RRR.",
+ machhwu_3 = "10000018RRR.",
+ mulhhw_3 = "10000050RRR.",
+ nmachhw_3 = "1000005cRRR.",
+ machhwsu_3 = "10000098RRR.",
+ machhws_3 = "100000d8RRR.",
+ nmachhws_3 = "100000dcRRR.",
+ mulchwu_3 = "10000110RRR.",
+ macchwu_3 = "10000118RRR.",
+ mulchw_3 = "10000150RRR.",
+ macchw_3 = "10000158RRR.",
+ nmacchw_3 = "1000015cRRR.",
+ macchwsu_3 = "10000198RRR.",
+ macchws_3 = "100001d8RRR.",
+ nmacchws_3 = "100001dcRRR.",
+ mullhw_3 = "10000350RRR.",
+ maclhw_3 = "10000358RRR.",
+ nmaclhw_3 = "1000035cRRR.",
+ maclhwsu_3 = "10000398RRR.",
+ maclhws_3 = "100003d8RRR.",
+ nmaclhws_3 = "100003dcRRR.",
+ machhwuo_3 = "10000418RRR.",
+ nmachhwo_3 = "1000045cRRR.",
+ machhwsuo_3 = "10000498RRR.",
+ machhwso_3 = "100004d8RRR.",
+ nmachhwso_3 = "100004dcRRR.",
+ macchwuo_3 = "10000518RRR.",
+ macchwo_3 = "10000558RRR.",
+ nmacchwo_3 = "1000055cRRR.",
+ macchwsuo_3 = "10000598RRR.",
+ macchwso_3 = "100005d8RRR.",
+ nmacchwso_3 = "100005dcRRR.",
+ maclhwo_3 = "10000758RRR.",
+ nmaclhwo_3 = "1000075cRRR.",
+ maclhwsuo_3 = "10000798RRR.",
+ maclhwso_3 = "100007d8RRR.",
+ nmaclhwso_3 = "100007dcRRR.",
+
+ vaddubm_3 = "10000000VVV",
+ vmaxub_3 = "10000002VVV",
+ vrlb_3 = "10000004VVV",
+ vcmpequb_3 = "10000006VVV",
+ vmuloub_3 = "10000008VVV",
+ vaddfp_3 = "1000000aVVV",
+ vmrghb_3 = "1000000cVVV",
+ vpkuhum_3 = "1000000eVVV",
+ vmhaddshs_4 = "10000020VVVV",
+ vmhraddshs_4 = "10000021VVVV",
+ vmladduhm_4 = "10000022VVVV",
+ vmsumubm_4 = "10000024VVVV",
+ vmsummbm_4 = "10000025VVVV",
+ vmsumuhm_4 = "10000026VVVV",
+ vmsumuhs_4 = "10000027VVVV",
+ vmsumshm_4 = "10000028VVVV",
+ vmsumshs_4 = "10000029VVVV",
+ vsel_4 = "1000002aVVVV",
+ vperm_4 = "1000002bVVVV",
+ vsldoi_4 = "1000002cVVVP",
+ vpermxor_4 = "1000002dVVVV",
+ vmaddfp_4 = "1000002eVVVV~",
+ vnmsubfp_4 = "1000002fVVVV~",
+ vaddeuqm_4 = "1000003cVVVV",
+ vaddecuq_4 = "1000003dVVVV",
+ vsubeuqm_4 = "1000003eVVVV",
+ vsubecuq_4 = "1000003fVVVV",
+ vadduhm_3 = "10000040VVV",
+ vmaxuh_3 = "10000042VVV",
+ vrlh_3 = "10000044VVV",
+ vcmpequh_3 = "10000046VVV",
+ vmulouh_3 = "10000048VVV",
+ vsubfp_3 = "1000004aVVV",
+ vmrghh_3 = "1000004cVVV",
+ vpkuwum_3 = "1000004eVVV",
+ vadduwm_3 = "10000080VVV",
+ vmaxuw_3 = "10000082VVV",
+ vrlw_3 = "10000084VVV",
+ vcmpequw_3 = "10000086VVV",
+ vmulouw_3 = "10000088VVV",
+ vmuluwm_3 = "10000089VVV",
+ vmrghw_3 = "1000008cVVV",
+ vpkuhus_3 = "1000008eVVV",
+ vaddudm_3 = "100000c0VVV",
+ vmaxud_3 = "100000c2VVV",
+ vrld_3 = "100000c4VVV",
+ vcmpeqfp_3 = "100000c6VVV",
+ vcmpequd_3 = "100000c7VVV",
+ vpkuwus_3 = "100000ceVVV",
+ vadduqm_3 = "10000100VVV",
+ vmaxsb_3 = "10000102VVV",
+ vslb_3 = "10000104VVV",
+ vmulosb_3 = "10000108VVV",
+ vrefp_2 = "1000010aV-V",
+ vmrglb_3 = "1000010cVVV",
+ vpkshus_3 = "1000010eVVV",
+ vaddcuq_3 = "10000140VVV",
+ vmaxsh_3 = "10000142VVV",
+ vslh_3 = "10000144VVV",
+ vmulosh_3 = "10000148VVV",
+ vrsqrtefp_2 = "1000014aV-V",
+ vmrglh_3 = "1000014cVVV",
+ vpkswus_3 = "1000014eVVV",
+ vaddcuw_3 = "10000180VVV",
+ vmaxsw_3 = "10000182VVV",
+ vslw_3 = "10000184VVV",
+ vmulosw_3 = "10000188VVV",
+ vexptefp_2 = "1000018aV-V",
+ vmrglw_3 = "1000018cVVV",
+ vpkshss_3 = "1000018eVVV",
+ vmaxsd_3 = "100001c2VVV",
+ vsl_3 = "100001c4VVV",
+ vcmpgefp_3 = "100001c6VVV",
+ vlogefp_2 = "100001caV-V",
+ vpkswss_3 = "100001ceVVV",
+ vadduhs_3 = "10000240VVV",
+ vminuh_3 = "10000242VVV",
+ vsrh_3 = "10000244VVV",
+ vcmpgtuh_3 = "10000246VVV",
+ vmuleuh_3 = "10000248VVV",
+ vrfiz_2 = "1000024aV-V",
+ vsplth_3 = "1000024cVV3",
+ vupkhsh_2 = "1000024eV-V",
+ vminuw_3 = "10000282VVV",
+ vminud_3 = "100002c2VVV",
+ vcmpgtud_3 = "100002c7VVV",
+ vrfim_2 = "100002caV-V",
+ vcmpgtsb_3 = "10000306VVV",
+ vcfux_3 = "1000030aVVA~",
+ vaddshs_3 = "10000340VVV",
+ vminsh_3 = "10000342VVV",
+ vsrah_3 = "10000344VVV",
+ vcmpgtsh_3 = "10000346VVV",
+ vmulesh_3 = "10000348VVV",
+ vcfsx_3 = "1000034aVVA~",
+ vspltish_2 = "1000034cVS",
+ vupkhpx_2 = "1000034eV-V",
+ vaddsws_3 = "10000380VVV",
+ vminsw_3 = "10000382VVV",
+ vsraw_3 = "10000384VVV",
+ vcmpgtsw_3 = "10000386VVV",
+ vmulesw_3 = "10000388VVV",
+ vctuxs_3 = "1000038aVVA~",
+ vspltisw_2 = "1000038cVS",
+ vminsd_3 = "100003c2VVV",
+ vsrad_3 = "100003c4VVV",
+ vcmpbfp_3 = "100003c6VVV",
+ vcmpgtsd_3 = "100003c7VVV",
+ vctsxs_3 = "100003caVVA~",
+ vupklpx_2 = "100003ceV-V",
+ vsububm_3 = "10000400VVV",
+ ["bcdadd._4"] = "10000401VVVy.",
+ vavgub_3 = "10000402VVV",
+ vand_3 = "10000404VVV",
+ ["vcmpequb._3"] = "10000406VVV",
+ vmaxfp_3 = "1000040aVVV",
+ vsubuhm_3 = "10000440VVV",
+ ["bcdsub._4"] = "10000441VVVy.",
+ vavguh_3 = "10000442VVV",
+ vandc_3 = "10000444VVV",
+ ["vcmpequh._3"] = "10000446VVV",
+ vminfp_3 = "1000044aVVV",
+ vpkudum_3 = "1000044eVVV",
+ vsubuwm_3 = "10000480VVV",
+ vavguw_3 = "10000482VVV",
+ vor_3 = "10000484VVV",
+ ["vcmpequw._3"] = "10000486VVV",
+ vpmsumw_3 = "10000488VVV",
+ ["vcmpeqfp._3"] = "100004c6VVV",
+ ["vcmpequd._3"] = "100004c7VVV",
+ vpkudus_3 = "100004ceVVV",
+ vavgsb_3 = "10000502VVV",
+ vavgsh_3 = "10000542VVV",
+ vorc_3 = "10000544VVV",
+ vbpermq_3 = "1000054cVVV",
+ vpksdus_3 = "1000054eVVV",
+ vavgsw_3 = "10000582VVV",
+ vsld_3 = "100005c4VVV",
+ ["vcmpgefp._3"] = "100005c6VVV",
+ vpksdss_3 = "100005ceVVV",
+ vsububs_3 = "10000600VVV",
+ mfvscr_1 = "10000604V--",
+ vsum4ubs_3 = "10000608VVV",
+ vsubuhs_3 = "10000640VVV",
+ mtvscr_1 = "10000644--V",
+ ["vcmpgtuh._3"] = "10000646VVV",
+ vsum4shs_3 = "10000648VVV",
+ vupkhsw_2 = "1000064eV-V",
+ vsubuws_3 = "10000680VVV",
+ vshasigmaw_4 = "10000682VVYp",
+ veqv_3 = "10000684VVV",
+ vsum2sws_3 = "10000688VVV",
+ vmrgow_3 = "1000068cVVV",
+ vshasigmad_4 = "100006c2VVYp",
+ vsrd_3 = "100006c4VVV",
+ ["vcmpgtud._3"] = "100006c7VVV",
+ vupklsw_2 = "100006ceV-V",
+ vupkslw_2 = "100006ceV-V",
+ vsubsbs_3 = "10000700VVV",
+ vclzb_2 = "10000702V-V",
+ vpopcntb_2 = "10000703V-V",
+ ["vcmpgtsb._3"] = "10000706VVV",
+ vsum4sbs_3 = "10000708VVV",
+ vsubshs_3 = "10000740VVV",
+ vclzh_2 = "10000742V-V",
+ vpopcnth_2 = "10000743V-V",
+ ["vcmpgtsh._3"] = "10000746VVV",
+ vsubsws_3 = "10000780VVV",
+ vclzw_2 = "10000782V-V",
+ vpopcntw_2 = "10000783V-V",
+ ["vcmpgtsw._3"] = "10000786VVV",
+ vsumsws_3 = "10000788VVV",
+ vmrgew_3 = "1000078cVVV",
+ vclzd_2 = "100007c2V-V",
+ vpopcntd_2 = "100007c3V-V",
+ ["vcmpbfp._3"] = "100007c6VVV",
+ ["vcmpgtsd._3"] = "100007c7VVV",
+
+ -- Primary opcode 19:
+ mcrf_2 = "4c000000XX",
+ isync_0 = "4c00012c",
+ crnor_3 = "4c000042CCC",
+ crnot_2 = "4c000042CC=",
+ crandc_3 = "4c000102CCC",
+ crxor_3 = "4c000182CCC",
+ crclr_1 = "4c000182C==",
+ crnand_3 = "4c0001c2CCC",
+ crand_3 = "4c000202CCC",
+ creqv_3 = "4c000242CCC",
+ crset_1 = "4c000242C==",
+ crorc_3 = "4c000342CCC",
+ cror_3 = "4c000382CCC",
+ crmove_2 = "4c000382CC=",
+ bclr_2 = "4c000020AA",
+ bclrl_2 = "4c000021AA",
+ bcctr_2 = "4c000420AA",
+ bcctrl_2 = "4c000421AA",
+ bctar_2 = "4c000460AA",
+ bctarl_2 = "4c000461AA",
+ blr_0 = "4e800020",
+ blrl_0 = "4e800021",
+ bctr_0 = "4e800420",
+ bctrl_0 = "4e800421",
+
+ -- Primary opcode 31:
+ cmpw_3 = "7c000000XRR",
+ cmpw_2 = "7c000000-RR",
+ cmpd_3 = "7c200000XRR",
+ cmpd_2 = "7c200000-RR",
+ tw_3 = "7c000008ARR",
+ lvsl_3 = "7c00000cVRR",
+ subfc_3 = "7c000010RRR.",
+ subc_3 = "7c000010RRR~.",
+ mulhdu_3 = "7c000012RRR.",
+ addc_3 = "7c000014RRR.",
+ mulhwu_3 = "7c000016RRR.",
+ isel_4 = "7c00001eRRRC",
+ isellt_3 = "7c00001eRRR",
+ iselgt_3 = "7c00005eRRR",
+ iseleq_3 = "7c00009eRRR",
+ mfcr_1 = "7c000026R",
+ mfocrf_2 = "7c100026RG",
+ mtcrf_2 = "7c000120GR",
+ mtocrf_2 = "7c100120GR",
+ lwarx_3 = "7c000028RR0R",
+ ldx_3 = "7c00002aRR0R",
+ lwzx_3 = "7c00002eRR0R",
+ slw_3 = "7c000030RR~R.",
+ cntlzw_2 = "7c000034RR~",
+ sld_3 = "7c000036RR~R.",
+ and_3 = "7c000038RR~R.",
+ cmplw_3 = "7c000040XRR",
+ cmplw_2 = "7c000040-RR",
+ cmpld_3 = "7c200040XRR",
+ cmpld_2 = "7c200040-RR",
+ lvsr_3 = "7c00004cVRR",
+ subf_3 = "7c000050RRR.",
+ sub_3 = "7c000050RRR~.",
+ lbarx_3 = "7c000068RR0R",
+ ldux_3 = "7c00006aRR0R",
+ dcbst_2 = "7c00006c-RR",
+ lwzux_3 = "7c00006eRR0R",
+ cntlzd_2 = "7c000074RR~",
+ andc_3 = "7c000078RR~R.",
+ td_3 = "7c000088ARR",
+ lvewx_3 = "7c00008eVRR",
+ mulhd_3 = "7c000092RRR.",
+ addg6s_3 = "7c000094RRR",
+ mulhw_3 = "7c000096RRR.",
+ dlmzb_3 = "7c00009cRR~R.",
+ ldarx_3 = "7c0000a8RR0R",
+ dcbf_2 = "7c0000ac-RR",
+ lbzx_3 = "7c0000aeRR0R",
+ lvx_3 = "7c0000ceVRR",
+ neg_2 = "7c0000d0RR.",
+ lharx_3 = "7c0000e8RR0R",
+ lbzux_3 = "7c0000eeRR0R",
+ popcntb_2 = "7c0000f4RR~",
+ not_2 = "7c0000f8RR~%.",
+ nor_3 = "7c0000f8RR~R.",
+ stvebx_3 = "7c00010eVRR",
+ subfe_3 = "7c000110RRR.",
+ sube_3 = "7c000110RRR~.",
+ adde_3 = "7c000114RRR.",
+ stdx_3 = "7c00012aRR0R",
+ ["stwcx._3"] = "7c00012dRR0R.",
+ stwx_3 = "7c00012eRR0R",
+ prtyw_2 = "7c000134RR~",
+ stvehx_3 = "7c00014eVRR",
+ stdux_3 = "7c00016aRR0R",
+ ["stqcx._3"] = "7c00016dR:R0R.",
+ stwux_3 = "7c00016eRR0R",
+ prtyd_2 = "7c000174RR~",
+ stvewx_3 = "7c00018eVRR",
+ subfze_2 = "7c000190RR.",
+ addze_2 = "7c000194RR.",
+ ["stdcx._3"] = "7c0001adRR0R.",
+ stbx_3 = "7c0001aeRR0R",
+ stvx_3 = "7c0001ceVRR",
+ subfme_2 = "7c0001d0RR.",
+ mulld_3 = "7c0001d2RRR.",
+ addme_2 = "7c0001d4RR.",
+ mullw_3 = "7c0001d6RRR.",
+ dcbtst_2 = "7c0001ec-RR",
+ stbux_3 = "7c0001eeRR0R",
+ bpermd_3 = "7c0001f8RR~R",
+ lvepxl_3 = "7c00020eVRR",
+ add_3 = "7c000214RRR.",
+ lqarx_3 = "7c000228R:R0R",
+ dcbt_2 = "7c00022c-RR",
+ lhzx_3 = "7c00022eRR0R",
+ cdtbcd_2 = "7c000234RR~",
+ eqv_3 = "7c000238RR~R.",
+ lvepx_3 = "7c00024eVRR",
+ eciwx_3 = "7c00026cRR0R",
+ lhzux_3 = "7c00026eRR0R",
+ cbcdtd_2 = "7c000274RR~",
+ xor_3 = "7c000278RR~R.",
+ mfspefscr_1 = "7c0082a6R",
+ mfxer_1 = "7c0102a6R",
+ mflr_1 = "7c0802a6R",
+ mfctr_1 = "7c0902a6R",
+ lwax_3 = "7c0002aaRR0R",
+ lhax_3 = "7c0002aeRR0R",
+ mftb_1 = "7c0c42e6R",
+ mftbu_1 = "7c0d42e6R",
+ lvxl_3 = "7c0002ceVRR",
+ lwaux_3 = "7c0002eaRR0R",
+ lhaux_3 = "7c0002eeRR0R",
+ popcntw_2 = "7c0002f4RR~",
+ divdeu_3 = "7c000312RRR.",
+ divweu_3 = "7c000316RRR.",
+ sthx_3 = "7c00032eRR0R",
+ orc_3 = "7c000338RR~R.",
+ ecowx_3 = "7c00036cRR0R",
+ sthux_3 = "7c00036eRR0R",
+ or_3 = "7c000378RR~R.",
+ mr_2 = "7c000378RR~%.",
+ divdu_3 = "7c000392RRR.",
+ divwu_3 = "7c000396RRR.",
+ mtspefscr_1 = "7c0083a6R",
+ mtxer_1 = "7c0103a6R",
+ mtlr_1 = "7c0803a6R",
+ mtctr_1 = "7c0903a6R",
+ dcbi_2 = "7c0003ac-RR",
+ nand_3 = "7c0003b8RR~R.",
+ dsn_2 = "7c0003c6-RR",
+ stvxl_3 = "7c0003ceVRR",
+ divd_3 = "7c0003d2RRR.",
+ divw_3 = "7c0003d6RRR.",
+ popcntd_2 = "7c0003f4RR~",
+ cmpb_3 = "7c0003f8RR~R.",
+ mcrxr_1 = "7c000400X",
+ lbdx_3 = "7c000406RRR",
+ subfco_3 = "7c000410RRR.",
+ subco_3 = "7c000410RRR~.",
+ addco_3 = "7c000414RRR.",
+ ldbrx_3 = "7c000428RR0R",
+ lswx_3 = "7c00042aRR0R",
+ lwbrx_3 = "7c00042cRR0R",
+ lfsx_3 = "7c00042eFR0R",
+ srw_3 = "7c000430RR~R.",
+ srd_3 = "7c000436RR~R.",
+ lhdx_3 = "7c000446RRR",
+ subfo_3 = "7c000450RRR.",
+ subo_3 = "7c000450RRR~.",
+ lfsux_3 = "7c00046eFR0R",
+ lwdx_3 = "7c000486RRR",
+ lswi_3 = "7c0004aaRR0A",
+ sync_0 = "7c0004ac",
+ lwsync_0 = "7c2004ac",
+ ptesync_0 = "7c4004ac",
+ lfdx_3 = "7c0004aeFR0R",
+ lddx_3 = "7c0004c6RRR",
+ nego_2 = "7c0004d0RR.",
+ lfdux_3 = "7c0004eeFR0R",
+ stbdx_3 = "7c000506RRR",
+ subfeo_3 = "7c000510RRR.",
+ subeo_3 = "7c000510RRR~.",
+ addeo_3 = "7c000514RRR.",
+ stdbrx_3 = "7c000528RR0R",
+ stswx_3 = "7c00052aRR0R",
+ stwbrx_3 = "7c00052cRR0R",
+ stfsx_3 = "7c00052eFR0R",
+ sthdx_3 = "7c000546RRR",
+ ["stbcx._3"] = "7c00056dRRR",
+ stfsux_3 = "7c00056eFR0R",
+ stwdx_3 = "7c000586RRR",
+ subfzeo_2 = "7c000590RR.",
+ addzeo_2 = "7c000594RR.",
+ stswi_3 = "7c0005aaRR0A",
+ ["sthcx._3"] = "7c0005adRRR",
+ stfdx_3 = "7c0005aeFR0R",
+ stddx_3 = "7c0005c6RRR",
+ subfmeo_2 = "7c0005d0RR.",
+ mulldo_3 = "7c0005d2RRR.",
+ addmeo_2 = "7c0005d4RR.",
+ mullwo_3 = "7c0005d6RRR.",
+ dcba_2 = "7c0005ec-RR",
+ stfdux_3 = "7c0005eeFR0R",
+ stvepxl_3 = "7c00060eVRR",
+ addo_3 = "7c000614RRR.",
+ lhbrx_3 = "7c00062cRR0R",
+ lfdpx_3 = "7c00062eF:RR",
+ sraw_3 = "7c000630RR~R.",
+ srad_3 = "7c000634RR~R.",
+ lfddx_3 = "7c000646FRR",
+ stvepx_3 = "7c00064eVRR",
+ srawi_3 = "7c000670RR~A.",
+ sradi_3 = "7c000674RR~H.",
+ eieio_0 = "7c0006ac",
+ lfiwax_3 = "7c0006aeFR0R",
+ divdeuo_3 = "7c000712RRR.",
+ divweuo_3 = "7c000716RRR.",
+ sthbrx_3 = "7c00072cRR0R",
+ stfdpx_3 = "7c00072eF:RR",
+ extsh_2 = "7c000734RR~.",
+ stfddx_3 = "7c000746FRR",
+ divdeo_3 = "7c000752RRR.",
+ divweo_3 = "7c000756RRR.",
+ extsb_2 = "7c000774RR~.",
+ divduo_3 = "7c000792RRR.",
+ divwou_3 = "7c000796RRR.",
+ icbi_2 = "7c0007ac-RR",
+ stfiwx_3 = "7c0007aeFR0R",
+ extsw_2 = "7c0007b4RR~.",
+ divdo_3 = "7c0007d2RRR.",
+ divwo_3 = "7c0007d6RRR.",
+ dcbz_2 = "7c0007ec-RR",
+
+ ["tbegin._1"] = "7c00051d1",
+ ["tbegin._0"] = "7c00051d",
+ ["tend._1"] = "7c00055dY",
+ ["tend._0"] = "7c00055d",
+ ["tendall._0"] = "7e00055d",
+ tcheck_1 = "7c00059cX",
+ ["tsr._1"] = "7c0005dd1",
+ ["tsuspend._0"] = "7c0005dd",
+ ["tresume._0"] = "7c2005dd",
+ ["tabortwc._3"] = "7c00061dARR",
+ ["tabortdc._3"] = "7c00065dARR",
+ ["tabortwci._3"] = "7c00069dARS",
+ ["tabortdci._3"] = "7c0006ddARS",
+ ["tabort._1"] = "7c00071d-R-",
+ ["treclaim._1"] = "7c00075d-R",
+ ["trechkpt._0"] = "7c0007dd",
+
+ lxsiwzx_3 = "7c000018QRR",
+ lxsiwax_3 = "7c000098QRR",
+ mfvsrd_2 = "7c000066-Rq",
+ mfvsrwz_2 = "7c0000e6-Rq",
+ stxsiwx_3 = "7c000118QRR",
+ mtvsrd_2 = "7c000166QR",
+ mtvsrwa_2 = "7c0001a6QR",
+ lxvdsx_3 = "7c000298QRR",
+ lxsspx_3 = "7c000418QRR",
+ lxsdx_3 = "7c000498QRR",
+ stxsspx_3 = "7c000518QRR",
+ stxsdx_3 = "7c000598QRR",
+ lxvw4x_3 = "7c000618QRR",
+ lxvd2x_3 = "7c000698QRR",
+ stxvw4x_3 = "7c000718QRR",
+ stxvd2x_3 = "7c000798QRR",
+
+ -- Primary opcode 30:
+ rldicl_4 = "78000000RR~HM.",
+ rldicr_4 = "78000004RR~HM.",
+ rldic_4 = "78000008RR~HM.",
+ rldimi_4 = "7800000cRR~HM.",
+ rldcl_4 = "78000010RR~RM.",
+ rldcr_4 = "78000012RR~RM.",
+
+ rotldi_3 = op_alias("rldicl_4", function(p)
+ p[4] = "0"
+ end),
+ rotrdi_3 = op_alias("rldicl_4", function(p)
+ p[3] = "64-("..p[3]..")"; p[4] = "0"
+ end),
+ rotld_3 = op_alias("rldcl_4", function(p)
+ p[4] = "0"
+ end),
+ sldi_3 = op_alias("rldicr_4", function(p)
+ p[4] = "63-("..p[3]..")"
+ end),
+ srdi_3 = op_alias("rldicl_4", function(p)
+ p[4] = p[3]; p[3] = "64-("..p[3]..")"
+ end),
+ clrldi_3 = op_alias("rldicl_4", function(p)
+ p[4] = p[3]; p[3] = "0"
+ end),
+ clrrdi_3 = op_alias("rldicr_4", function(p)
+ p[4] = "63-("..p[3]..")"; p[3] = "0"
+ end),
+
+ -- Primary opcode 56:
+ lq_2 = "e0000000R:D", -- NYI: displacement must be divisible by 8.
+
+ -- Primary opcode 57:
+ lfdp_2 = "e4000000F:D", -- NYI: displacement must be divisible by 4.
+
+ -- Primary opcode 59:
+ fdivs_3 = "ec000024FFF.",
+ fsubs_3 = "ec000028FFF.",
+ fadds_3 = "ec00002aFFF.",
+ fsqrts_2 = "ec00002cF-F.",
+ fres_2 = "ec000030F-F.",
+ fmuls_3 = "ec000032FF-F.",
+ frsqrtes_2 = "ec000034F-F.",
+ fmsubs_4 = "ec000038FFFF~.",
+ fmadds_4 = "ec00003aFFFF~.",
+ fnmsubs_4 = "ec00003cFFFF~.",
+ fnmadds_4 = "ec00003eFFFF~.",
+ fcfids_2 = "ec00069cF-F.",
+ fcfidus_2 = "ec00079cF-F.",
+
+ dadd_3 = "ec000004FFF.",
+ dqua_4 = "ec000006FFFZ.",
+ dmul_3 = "ec000044FFF.",
+ drrnd_4 = "ec000046FFFZ.",
+ dscli_3 = "ec000084FF6.",
+ dquai_4 = "ec000086SF~FZ.",
+ dscri_3 = "ec0000c4FF6.",
+ drintx_4 = "ec0000c61F~FZ.",
+ dcmpo_3 = "ec000104XFF",
+ dtstex_3 = "ec000144XFF",
+ dtstdc_3 = "ec000184XF6",
+ dtstdg_3 = "ec0001c4XF6",
+ drintn_4 = "ec0001c61F~FZ.",
+ dctdp_2 = "ec000204F-F.",
+ dctfix_2 = "ec000244F-F.",
+ ddedpd_3 = "ec000284ZF~F.",
+ dxex_2 = "ec0002c4F-F.",
+ dsub_3 = "ec000404FFF.",
+ ddiv_3 = "ec000444FFF.",
+ dcmpu_3 = "ec000504XFF",
+ dtstsf_3 = "ec000544XFF",
+ drsp_2 = "ec000604F-F.",
+ dcffix_2 = "ec000644F-F.",
+ denbcd_3 = "ec000684YF~F.",
+ diex_3 = "ec0006c4FFF.",
+
+ -- Primary opcode 60:
+ xsaddsp_3 = "f0000000QQQ",
+ xsmaddasp_3 = "f0000008QQQ",
+ xxsldwi_4 = "f0000010QQQz",
+ xsrsqrtesp_2 = "f0000028Q-Q",
+ xssqrtsp_2 = "f000002cQ-Q",
+ xxsel_4 = "f0000030QQQQ",
+ xssubsp_3 = "f0000040QQQ",
+ xsmaddmsp_3 = "f0000048QQQ",
+ xxpermdi_4 = "f0000050QQQz",
+ xsresp_2 = "f0000068Q-Q",
+ xsmulsp_3 = "f0000080QQQ",
+ xsmsubasp_3 = "f0000088QQQ",
+ xxmrghw_3 = "f0000090QQQ",
+ xsdivsp_3 = "f00000c0QQQ",
+ xsmsubmsp_3 = "f00000c8QQQ",
+ xsadddp_3 = "f0000100QQQ",
+ xsmaddadp_3 = "f0000108QQQ",
+ xscmpudp_3 = "f0000118XQQ",
+ xscvdpuxws_2 = "f0000120Q-Q",
+ xsrdpi_2 = "f0000124Q-Q",
+ xsrsqrtedp_2 = "f0000128Q-Q",
+ xssqrtdp_2 = "f000012cQ-Q",
+ xssubdp_3 = "f0000140QQQ",
+ xsmaddmdp_3 = "f0000148QQQ",
+ xscmpodp_3 = "f0000158XQQ",
+ xscvdpsxws_2 = "f0000160Q-Q",
+ xsrdpiz_2 = "f0000164Q-Q",
+ xsredp_2 = "f0000168Q-Q",
+ xsmuldp_3 = "f0000180QQQ",
+ xsmsubadp_3 = "f0000188QQQ",
+ xxmrglw_3 = "f0000190QQQ",
+ xsrdpip_2 = "f00001a4Q-Q",
+ xstsqrtdp_2 = "f00001a8X-Q",
+ xsrdpic_2 = "f00001acQ-Q",
+ xsdivdp_3 = "f00001c0QQQ",
+ xsmsubmdp_3 = "f00001c8QQQ",
+ xsrdpim_2 = "f00001e4Q-Q",
+ xstdivdp_3 = "f00001e8XQQ",
+ xvaddsp_3 = "f0000200QQQ",
+ xvmaddasp_3 = "f0000208QQQ",
+ xvcmpeqsp_3 = "f0000218QQQ",
+ xvcvspuxws_2 = "f0000220Q-Q",
+ xvrspi_2 = "f0000224Q-Q",
+ xvrsqrtesp_2 = "f0000228Q-Q",
+ xvsqrtsp_2 = "f000022cQ-Q",
+ xvsubsp_3 = "f0000240QQQ",
+ xvmaddmsp_3 = "f0000248QQQ",
+ xvcmpgtsp_3 = "f0000258QQQ",
+ xvcvspsxws_2 = "f0000260Q-Q",
+ xvrspiz_2 = "f0000264Q-Q",
+ xvresp_2 = "f0000268Q-Q",
+ xvmulsp_3 = "f0000280QQQ",
+ xvmsubasp_3 = "f0000288QQQ",
+ xxspltw_3 = "f0000290QQg~",
+ xvcmpgesp_3 = "f0000298QQQ",
+ xvcvuxwsp_2 = "f00002a0Q-Q",
+ xvrspip_2 = "f00002a4Q-Q",
+ xvtsqrtsp_2 = "f00002a8X-Q",
+ xvrspic_2 = "f00002acQ-Q",
+ xvdivsp_3 = "f00002c0QQQ",
+ xvmsubmsp_3 = "f00002c8QQQ",
+ xvcvsxwsp_2 = "f00002e0Q-Q",
+ xvrspim_2 = "f00002e4Q-Q",
+ xvtdivsp_3 = "f00002e8XQQ",
+ xvadddp_3 = "f0000300QQQ",
+ xvmaddadp_3 = "f0000308QQQ",
+ xvcmpeqdp_3 = "f0000318QQQ",
+ xvcvdpuxws_2 = "f0000320Q-Q",
+ xvrdpi_2 = "f0000324Q-Q",
+ xvrsqrtedp_2 = "f0000328Q-Q",
+ xvsqrtdp_2 = "f000032cQ-Q",
+ xvsubdp_3 = "f0000340QQQ",
+ xvmaddmdp_3 = "f0000348QQQ",
+ xvcmpgtdp_3 = "f0000358QQQ",
+ xvcvdpsxws_2 = "f0000360Q-Q",
+ xvrdpiz_2 = "f0000364Q-Q",
+ xvredp_2 = "f0000368Q-Q",
+ xvmuldp_3 = "f0000380QQQ",
+ xvmsubadp_3 = "f0000388QQQ",
+ xvcmpgedp_3 = "f0000398QQQ",
+ xvcvuxwdp_2 = "f00003a0Q-Q",
+ xvrdpip_2 = "f00003a4Q-Q",
+ xvtsqrtdp_2 = "f00003a8X-Q",
+ xvrdpic_2 = "f00003acQ-Q",
+ xvdivdp_3 = "f00003c0QQQ",
+ xvmsubmdp_3 = "f00003c8QQQ",
+ xvcvsxwdp_2 = "f00003e0Q-Q",
+ xvrdpim_2 = "f00003e4Q-Q",
+ xvtdivdp_3 = "f00003e8XQQ",
+ xsnmaddasp_3 = "f0000408QQQ",
+ xxland_3 = "f0000410QQQ",
+ xscvdpsp_2 = "f0000424Q-Q",
+ xscvdpspn_2 = "f000042cQ-Q",
+ xsnmaddmsp_3 = "f0000448QQQ",
+ xxlandc_3 = "f0000450QQQ",
+ xsrsp_2 = "f0000464Q-Q",
+ xsnmsubasp_3 = "f0000488QQQ",
+ xxlor_3 = "f0000490QQQ",
+ xscvuxdsp_2 = "f00004a0Q-Q",
+ xsnmsubmsp_3 = "f00004c8QQQ",
+ xxlxor_3 = "f00004d0QQQ",
+ xscvsxdsp_2 = "f00004e0Q-Q",
+ xsmaxdp_3 = "f0000500QQQ",
+ xsnmaddadp_3 = "f0000508QQQ",
+ xxlnor_3 = "f0000510QQQ",
+ xscvdpuxds_2 = "f0000520Q-Q",
+ xscvspdp_2 = "f0000524Q-Q",
+ xscvspdpn_2 = "f000052cQ-Q",
+ xsmindp_3 = "f0000540QQQ",
+ xsnmaddmdp_3 = "f0000548QQQ",
+ xxlorc_3 = "f0000550QQQ",
+ xscvdpsxds_2 = "f0000560Q-Q",
+ xsabsdp_2 = "f0000564Q-Q",
+ xscpsgndp_3 = "f0000580QQQ",
+ xsnmsubadp_3 = "f0000588QQQ",
+ xxlnand_3 = "f0000590QQQ",
+ xscvuxddp_2 = "f00005a0Q-Q",
+ xsnabsdp_2 = "f00005a4Q-Q",
+ xsnmsubmdp_3 = "f00005c8QQQ",
+ xxleqv_3 = "f00005d0QQQ",
+ xscvsxddp_2 = "f00005e0Q-Q",
+ xsnegdp_2 = "f00005e4Q-Q",
+ xvmaxsp_3 = "f0000600QQQ",
+ xvnmaddasp_3 = "f0000608QQQ",
+ ["xvcmpeqsp._3"] = "f0000618QQQ",
+ xvcvspuxds_2 = "f0000620Q-Q",
+ xvcvdpsp_2 = "f0000624Q-Q",
+ xvminsp_3 = "f0000640QQQ",
+ xvnmaddmsp_3 = "f0000648QQQ",
+ ["xvcmpgtsp._3"] = "f0000658QQQ",
+ xvcvspsxds_2 = "f0000660Q-Q",
+ xvabssp_2 = "f0000664Q-Q",
+ xvcpsgnsp_3 = "f0000680QQQ",
+ xvnmsubasp_3 = "f0000688QQQ",
+ ["xvcmpgesp._3"] = "f0000698QQQ",
+ xvcvuxdsp_2 = "f00006a0Q-Q",
+ xvnabssp_2 = "f00006a4Q-Q",
+ xvnmsubmsp_3 = "f00006c8QQQ",
+ xvcvsxdsp_2 = "f00006e0Q-Q",
+ xvnegsp_2 = "f00006e4Q-Q",
+ xvmaxdp_3 = "f0000700QQQ",
+ xvnmaddadp_3 = "f0000708QQQ",
+ ["xvcmpeqdp._3"] = "f0000718QQQ",
+ xvcvdpuxds_2 = "f0000720Q-Q",
+ xvcvspdp_2 = "f0000724Q-Q",
+ xvmindp_3 = "f0000740QQQ",
+ xvnmaddmdp_3 = "f0000748QQQ",
+ ["xvcmpgtdp._3"] = "f0000758QQQ",
+ xvcvdpsxds_2 = "f0000760Q-Q",
+ xvabsdp_2 = "f0000764Q-Q",
+ xvcpsgndp_3 = "f0000780QQQ",
+ xvnmsubadp_3 = "f0000788QQQ",
+ ["xvcmpgedp._3"] = "f0000798QQQ",
+ xvcvuxddp_2 = "f00007a0Q-Q",
+ xvnabsdp_2 = "f00007a4Q-Q",
+ xvnmsubmdp_3 = "f00007c8QQQ",
+ xvcvsxddp_2 = "f00007e0Q-Q",
+ xvnegdp_2 = "f00007e4Q-Q",
+
+ -- Primary opcode 61:
+ stfdp_2 = "f4000000F:D", -- NYI: displacement must be divisible by 4.
+
+ -- Primary opcode 62:
+ stq_2 = "f8000002R:D", -- NYI: displacement must be divisible by 8.
+
+ -- Primary opcode 63:
+ fdiv_3 = "fc000024FFF.",
+ fsub_3 = "fc000028FFF.",
+ fadd_3 = "fc00002aFFF.",
+ fsqrt_2 = "fc00002cF-F.",
+ fsel_4 = "fc00002eFFFF~.",
+ fre_2 = "fc000030F-F.",
+ fmul_3 = "fc000032FF-F.",
+ frsqrte_2 = "fc000034F-F.",
+ fmsub_4 = "fc000038FFFF~.",
+ fmadd_4 = "fc00003aFFFF~.",
+ fnmsub_4 = "fc00003cFFFF~.",
+ fnmadd_4 = "fc00003eFFFF~.",
+ fcmpu_3 = "fc000000XFF",
+ fcpsgn_3 = "fc000010FFF.",
+ fcmpo_3 = "fc000040XFF",
+ mtfsb1_1 = "fc00004cA",
+ fneg_2 = "fc000050F-F.",
+ mcrfs_2 = "fc000080XX",
+ mtfsb0_1 = "fc00008cA",
+ fmr_2 = "fc000090F-F.",
+ frsp_2 = "fc000018F-F.",
+ fctiw_2 = "fc00001cF-F.",
+ fctiwz_2 = "fc00001eF-F.",
+ ftdiv_2 = "fc000100X-F.",
+ fctiwu_2 = "fc00011cF-F.",
+ fctiwuz_2 = "fc00011eF-F.",
+ mtfsfi_2 = "fc00010cAA", -- NYI: upshift.
+ fnabs_2 = "fc000110F-F.",
+ ftsqrt_2 = "fc000140X-F.",
+ fabs_2 = "fc000210F-F.",
+ frin_2 = "fc000310F-F.",
+ friz_2 = "fc000350F-F.",
+ frip_2 = "fc000390F-F.",
+ frim_2 = "fc0003d0F-F.",
+ mffs_1 = "fc00048eF.",
+ -- NYI: mtfsf, mtfsb0, mtfsb1.
+ fctid_2 = "fc00065cF-F.",
+ fctidz_2 = "fc00065eF-F.",
+ fmrgow_3 = "fc00068cFFF",
+ fcfid_2 = "fc00069cF-F.",
+ fctidu_2 = "fc00075cF-F.",
+ fctiduz_2 = "fc00075eF-F.",
+ fmrgew_3 = "fc00078cFFF",
+ fcfidu_2 = "fc00079cF-F.",
+
+ daddq_3 = "fc000004F:F:F:.",
+ dquaq_4 = "fc000006F:F:F:Z.",
+ dmulq_3 = "fc000044F:F:F:.",
+ drrndq_4 = "fc000046F:F:F:Z.",
+ dscliq_3 = "fc000084F:F:6.",
+ dquaiq_4 = "fc000086SF:~F:Z.",
+ dscriq_3 = "fc0000c4F:F:6.",
+ drintxq_4 = "fc0000c61F:~F:Z.",
+ dcmpoq_3 = "fc000104XF:F:",
+ dtstexq_3 = "fc000144XF:F:",
+ dtstdcq_3 = "fc000184XF:6",
+ dtstdgq_3 = "fc0001c4XF:6",
+ drintnq_4 = "fc0001c61F:~F:Z.",
+ dctqpq_2 = "fc000204F:-F:.",
+ dctfixq_2 = "fc000244F:-F:.",
+ ddedpdq_3 = "fc000284ZF:~F:.",
+ dxexq_2 = "fc0002c4F:-F:.",
+ dsubq_3 = "fc000404F:F:F:.",
+ ddivq_3 = "fc000444F:F:F:.",
+ dcmpuq_3 = "fc000504XF:F:",
+ dtstsfq_3 = "fc000544XF:F:",
+ drdpq_2 = "fc000604F:-F:.",
+ dcffixq_2 = "fc000644F:-F:.",
+ denbcdq_3 = "fc000684YF:~F:.",
+ diexq_3 = "fc0006c4F:FF:.",
+
+ -- Primary opcode 4, SPE APU extension:
+ evaddw_3 = "10000200RRR",
+ evaddiw_3 = "10000202RAR~",
+ evsubw_3 = "10000204RRR~",
+ evsubiw_3 = "10000206RAR~",
+ evabs_2 = "10000208RR",
+ evneg_2 = "10000209RR",
+ evextsb_2 = "1000020aRR",
+ evextsh_2 = "1000020bRR",
+ evrndw_2 = "1000020cRR",
+ evcntlzw_2 = "1000020dRR",
+ evcntlsw_2 = "1000020eRR",
+ brinc_3 = "1000020fRRR",
+ evand_3 = "10000211RRR",
+ evandc_3 = "10000212RRR",
+ evxor_3 = "10000216RRR",
+ evor_3 = "10000217RRR",
+ evmr_2 = "10000217RR=",
+ evnor_3 = "10000218RRR",
+ evnot_2 = "10000218RR=",
+ eveqv_3 = "10000219RRR",
+ evorc_3 = "1000021bRRR",
+ evnand_3 = "1000021eRRR",
+ evsrwu_3 = "10000220RRR",
+ evsrws_3 = "10000221RRR",
+ evsrwiu_3 = "10000222RRA",
+ evsrwis_3 = "10000223RRA",
+ evslw_3 = "10000224RRR",
+ evslwi_3 = "10000226RRA",
+ evrlw_3 = "10000228RRR",
+ evsplati_2 = "10000229RS",
+ evrlwi_3 = "1000022aRRA",
+ evsplatfi_2 = "1000022bRS",
+ evmergehi_3 = "1000022cRRR",
+ evmergelo_3 = "1000022dRRR",
+ evcmpgtu_3 = "10000230XRR",
+ evcmpgtu_2 = "10000230-RR",
+ evcmpgts_3 = "10000231XRR",
+ evcmpgts_2 = "10000231-RR",
+ evcmpltu_3 = "10000232XRR",
+ evcmpltu_2 = "10000232-RR",
+ evcmplts_3 = "10000233XRR",
+ evcmplts_2 = "10000233-RR",
+ evcmpeq_3 = "10000234XRR",
+ evcmpeq_2 = "10000234-RR",
+ evsel_4 = "10000278RRRW",
+ evsel_3 = "10000278RRR",
+ evfsadd_3 = "10000280RRR",
+ evfssub_3 = "10000281RRR",
+ evfsabs_2 = "10000284RR",
+ evfsnabs_2 = "10000285RR",
+ evfsneg_2 = "10000286RR",
+ evfsmul_3 = "10000288RRR",
+ evfsdiv_3 = "10000289RRR",
+ evfscmpgt_3 = "1000028cXRR",
+ evfscmpgt_2 = "1000028c-RR",
+ evfscmplt_3 = "1000028dXRR",
+ evfscmplt_2 = "1000028d-RR",
+ evfscmpeq_3 = "1000028eXRR",
+ evfscmpeq_2 = "1000028e-RR",
+ evfscfui_2 = "10000290R-R",
+ evfscfsi_2 = "10000291R-R",
+ evfscfuf_2 = "10000292R-R",
+ evfscfsf_2 = "10000293R-R",
+ evfsctui_2 = "10000294R-R",
+ evfsctsi_2 = "10000295R-R",
+ evfsctuf_2 = "10000296R-R",
+ evfsctsf_2 = "10000297R-R",
+ evfsctuiz_2 = "10000298R-R",
+ evfsctsiz_2 = "1000029aR-R",
+ evfststgt_3 = "1000029cXRR",
+ evfststgt_2 = "1000029c-RR",
+ evfststlt_3 = "1000029dXRR",
+ evfststlt_2 = "1000029d-RR",
+ evfststeq_3 = "1000029eXRR",
+ evfststeq_2 = "1000029e-RR",
+ efsadd_3 = "100002c0RRR",
+ efssub_3 = "100002c1RRR",
+ efsabs_2 = "100002c4RR",
+ efsnabs_2 = "100002c5RR",
+ efsneg_2 = "100002c6RR",
+ efsmul_3 = "100002c8RRR",
+ efsdiv_3 = "100002c9RRR",
+ efscmpgt_3 = "100002ccXRR",
+ efscmpgt_2 = "100002cc-RR",
+ efscmplt_3 = "100002cdXRR",
+ efscmplt_2 = "100002cd-RR",
+ efscmpeq_3 = "100002ceXRR",
+ efscmpeq_2 = "100002ce-RR",
+ efscfd_2 = "100002cfR-R",
+ efscfui_2 = "100002d0R-R",
+ efscfsi_2 = "100002d1R-R",
+ efscfuf_2 = "100002d2R-R",
+ efscfsf_2 = "100002d3R-R",
+ efsctui_2 = "100002d4R-R",
+ efsctsi_2 = "100002d5R-R",
+ efsctuf_2 = "100002d6R-R",
+ efsctsf_2 = "100002d7R-R",
+ efsctuiz_2 = "100002d8R-R",
+ efsctsiz_2 = "100002daR-R",
+ efststgt_3 = "100002dcXRR",
+ efststgt_2 = "100002dc-RR",
+ efststlt_3 = "100002ddXRR",
+ efststlt_2 = "100002dd-RR",
+ efststeq_3 = "100002deXRR",
+ efststeq_2 = "100002de-RR",
+ efdadd_3 = "100002e0RRR",
+ efdsub_3 = "100002e1RRR",
+ efdcfuid_2 = "100002e2R-R",
+ efdcfsid_2 = "100002e3R-R",
+ efdabs_2 = "100002e4RR",
+ efdnabs_2 = "100002e5RR",
+ efdneg_2 = "100002e6RR",
+ efdmul_3 = "100002e8RRR",
+ efddiv_3 = "100002e9RRR",
+ efdctuidz_2 = "100002eaR-R",
+ efdctsidz_2 = "100002ebR-R",
+ efdcmpgt_3 = "100002ecXRR",
+ efdcmpgt_2 = "100002ec-RR",
+ efdcmplt_3 = "100002edXRR",
+ efdcmplt_2 = "100002ed-RR",
+ efdcmpeq_3 = "100002eeXRR",
+ efdcmpeq_2 = "100002ee-RR",
+ efdcfs_2 = "100002efR-R",
+ efdcfui_2 = "100002f0R-R",
+ efdcfsi_2 = "100002f1R-R",
+ efdcfuf_2 = "100002f2R-R",
+ efdcfsf_2 = "100002f3R-R",
+ efdctui_2 = "100002f4R-R",
+ efdctsi_2 = "100002f5R-R",
+ efdctuf_2 = "100002f6R-R",
+ efdctsf_2 = "100002f7R-R",
+ efdctuiz_2 = "100002f8R-R",
+ efdctsiz_2 = "100002faR-R",
+ efdtstgt_3 = "100002fcXRR",
+ efdtstgt_2 = "100002fc-RR",
+ efdtstlt_3 = "100002fdXRR",
+ efdtstlt_2 = "100002fd-RR",
+ efdtsteq_3 = "100002feXRR",
+ efdtsteq_2 = "100002fe-RR",
+ evlddx_3 = "10000300RR0R",
+ evldd_2 = "10000301R8",
+ evldwx_3 = "10000302RR0R",
+ evldw_2 = "10000303R8",
+ evldhx_3 = "10000304RR0R",
+ evldh_2 = "10000305R8",
+ evlwhex_3 = "10000310RR0R",
+ evlwhe_2 = "10000311R4",
+ evlwhoux_3 = "10000314RR0R",
+ evlwhou_2 = "10000315R4",
+ evlwhosx_3 = "10000316RR0R",
+ evlwhos_2 = "10000317R4",
+ evstddx_3 = "10000320RR0R",
+ evstdd_2 = "10000321R8",
+ evstdwx_3 = "10000322RR0R",
+ evstdw_2 = "10000323R8",
+ evstdhx_3 = "10000324RR0R",
+ evstdh_2 = "10000325R8",
+ evstwhex_3 = "10000330RR0R",
+ evstwhe_2 = "10000331R4",
+ evstwhox_3 = "10000334RR0R",
+ evstwho_2 = "10000335R4",
+ evstwwex_3 = "10000338RR0R",
+ evstwwe_2 = "10000339R4",
+ evstwwox_3 = "1000033cRR0R",
+ evstwwo_2 = "1000033dR4",
+ evmhessf_3 = "10000403RRR",
+ evmhossf_3 = "10000407RRR",
+ evmheumi_3 = "10000408RRR",
+ evmhesmi_3 = "10000409RRR",
+ evmhesmf_3 = "1000040bRRR",
+ evmhoumi_3 = "1000040cRRR",
+ evmhosmi_3 = "1000040dRRR",
+ evmhosmf_3 = "1000040fRRR",
+ evmhessfa_3 = "10000423RRR",
+ evmhossfa_3 = "10000427RRR",
+ evmheumia_3 = "10000428RRR",
+ evmhesmia_3 = "10000429RRR",
+ evmhesmfa_3 = "1000042bRRR",
+ evmhoumia_3 = "1000042cRRR",
+ evmhosmia_3 = "1000042dRRR",
+ evmhosmfa_3 = "1000042fRRR",
+ evmwhssf_3 = "10000447RRR",
+ evmwlumi_3 = "10000448RRR",
+ evmwhumi_3 = "1000044cRRR",
+ evmwhsmi_3 = "1000044dRRR",
+ evmwhsmf_3 = "1000044fRRR",
+ evmwssf_3 = "10000453RRR",
+ evmwumi_3 = "10000458RRR",
+ evmwsmi_3 = "10000459RRR",
+ evmwsmf_3 = "1000045bRRR",
+ evmwhssfa_3 = "10000467RRR",
+ evmwlumia_3 = "10000468RRR",
+ evmwhumia_3 = "1000046cRRR",
+ evmwhsmia_3 = "1000046dRRR",
+ evmwhsmfa_3 = "1000046fRRR",
+ evmwssfa_3 = "10000473RRR",
+ evmwumia_3 = "10000478RRR",
+ evmwsmia_3 = "10000479RRR",
+ evmwsmfa_3 = "1000047bRRR",
+ evmra_2 = "100004c4RR",
+ evdivws_3 = "100004c6RRR",
+ evdivwu_3 = "100004c7RRR",
+ evmwssfaa_3 = "10000553RRR",
+ evmwumiaa_3 = "10000558RRR",
+ evmwsmiaa_3 = "10000559RRR",
+ evmwsmfaa_3 = "1000055bRRR",
+ evmwssfan_3 = "100005d3RRR",
+ evmwumian_3 = "100005d8RRR",
+ evmwsmian_3 = "100005d9RRR",
+ evmwsmfan_3 = "100005dbRRR",
+ evmergehilo_3 = "1000022eRRR",
+ evmergelohi_3 = "1000022fRRR",
+ evlhhesplatx_3 = "10000308RR0R",
+ evlhhesplat_2 = "10000309R2",
+ evlhhousplatx_3 = "1000030cRR0R",
+ evlhhousplat_2 = "1000030dR2",
+ evlhhossplatx_3 = "1000030eRR0R",
+ evlhhossplat_2 = "1000030fR2",
+ evlwwsplatx_3 = "10000318RR0R",
+ evlwwsplat_2 = "10000319R4",
+ evlwhsplatx_3 = "1000031cRR0R",
+ evlwhsplat_2 = "1000031dR4",
+ evaddusiaaw_2 = "100004c0RR",
+ evaddssiaaw_2 = "100004c1RR",
+ evsubfusiaaw_2 = "100004c2RR",
+ evsubfssiaaw_2 = "100004c3RR",
+ evaddumiaaw_2 = "100004c8RR",
+ evaddsmiaaw_2 = "100004c9RR",
+ evsubfumiaaw_2 = "100004caRR",
+ evsubfsmiaaw_2 = "100004cbRR",
+ evmheusiaaw_3 = "10000500RRR",
+ evmhessiaaw_3 = "10000501RRR",
+ evmhessfaaw_3 = "10000503RRR",
+ evmhousiaaw_3 = "10000504RRR",
+ evmhossiaaw_3 = "10000505RRR",
+ evmhossfaaw_3 = "10000507RRR",
+ evmheumiaaw_3 = "10000508RRR",
+ evmhesmiaaw_3 = "10000509RRR",
+ evmhesmfaaw_3 = "1000050bRRR",
+ evmhoumiaaw_3 = "1000050cRRR",
+ evmhosmiaaw_3 = "1000050dRRR",
+ evmhosmfaaw_3 = "1000050fRRR",
+ evmhegumiaa_3 = "10000528RRR",
+ evmhegsmiaa_3 = "10000529RRR",
+ evmhegsmfaa_3 = "1000052bRRR",
+ evmhogumiaa_3 = "1000052cRRR",
+ evmhogsmiaa_3 = "1000052dRRR",
+ evmhogsmfaa_3 = "1000052fRRR",
+ evmwlusiaaw_3 = "10000540RRR",
+ evmwlssiaaw_3 = "10000541RRR",
+ evmwlumiaaw_3 = "10000548RRR",
+ evmwlsmiaaw_3 = "10000549RRR",
+ evmheusianw_3 = "10000580RRR",
+ evmhessianw_3 = "10000581RRR",
+ evmhessfanw_3 = "10000583RRR",
+ evmhousianw_3 = "10000584RRR",
+ evmhossianw_3 = "10000585RRR",
+ evmhossfanw_3 = "10000587RRR",
+ evmheumianw_3 = "10000588RRR",
+ evmhesmianw_3 = "10000589RRR",
+ evmhesmfanw_3 = "1000058bRRR",
+ evmhoumianw_3 = "1000058cRRR",
+ evmhosmianw_3 = "1000058dRRR",
+ evmhosmfanw_3 = "1000058fRRR",
+ evmhegumian_3 = "100005a8RRR",
+ evmhegsmian_3 = "100005a9RRR",
+ evmhegsmfan_3 = "100005abRRR",
+ evmhogumian_3 = "100005acRRR",
+ evmhogsmian_3 = "100005adRRR",
+ evmhogsmfan_3 = "100005afRRR",
+ evmwlusianw_3 = "100005c0RRR",
+ evmwlssianw_3 = "100005c1RRR",
+ evmwlumianw_3 = "100005c8RRR",
+ evmwlsmianw_3 = "100005c9RRR",
+
+ -- NYI: Book E instructions.
+}
+
+-- Add mnemonics for "." variants.
+do
+ local t = {}
+ for k,v in pairs(map_op) do
+ if type(v) == "string" and sub(v, -1) == "." then
+ local v2 = sub(v, 1, 7)..char(byte(v, 8)+1)..sub(v, 9, -2)
+ t[sub(k, 1, -3).."."..sub(k, -2)] = v2
+ end
+ end
+ for k,v in pairs(t) do
+ map_op[k] = v
+ end
+end
+
+-- Add more branch mnemonics.
+for cond,c in pairs(map_cond) do
+ local b1 = "b"..cond
+ local c1 = shl(band(c, 3), 16) + (c < 4 and 0x01000000 or 0)
+ -- bX[l]
+ map_op[b1.."_1"] = tohex(0x40800000 + c1).."K"
+ map_op[b1.."y_1"] = tohex(0x40a00000 + c1).."K"
+ map_op[b1.."l_1"] = tohex(0x40800001 + c1).."K"
+ map_op[b1.."_2"] = tohex(0x40800000 + c1).."-XK"
+ map_op[b1.."y_2"] = tohex(0x40a00000 + c1).."-XK"
+ map_op[b1.."l_2"] = tohex(0x40800001 + c1).."-XK"
+ -- bXlr[l]
+ map_op[b1.."lr_0"] = tohex(0x4c800020 + c1)
+ map_op[b1.."lrl_0"] = tohex(0x4c800021 + c1)
+ map_op[b1.."ctr_0"] = tohex(0x4c800420 + c1)
+ map_op[b1.."ctrl_0"] = tohex(0x4c800421 + c1)
+ -- bXctr[l]
+ map_op[b1.."lr_1"] = tohex(0x4c800020 + c1).."-X"
+ map_op[b1.."lrl_1"] = tohex(0x4c800021 + c1).."-X"
+ map_op[b1.."ctr_1"] = tohex(0x4c800420 + c1).."-X"
+ map_op[b1.."ctrl_1"] = tohex(0x4c800421 + c1).."-X"
+end
+
+------------------------------------------------------------------------------
+
+local function parse_gpr(expr)
+ local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$")
+ local tp = map_type[tname or expr]
+ if tp then
+ local reg = ovreg or tp.reg
+ if not reg then
+ werror("type `"..(tname or expr).."' needs a register override")
+ end
+ expr = reg
+ end
+ local r = match(expr, "^r([1-3]?[0-9])$")
+ if r then
+ r = tonumber(r)
+ if r <= 31 then return r, tp end
+ end
+ werror("bad register name `"..expr.."'")
+end
+
+local function parse_fpr(expr)
+ local r = match(expr, "^f([1-3]?[0-9])$")
+ if r then
+ r = tonumber(r)
+ if r <= 31 then return r end
+ end
+ werror("bad register name `"..expr.."'")
+end
+
+local function parse_vr(expr)
+ local r = match(expr, "^v([1-3]?[0-9])$")
+ if r then
+ r = tonumber(r)
+ if r <= 31 then return r end
+ end
+ werror("bad register name `"..expr.."'")
+end
+
+local function parse_vs(expr)
+ local r = match(expr, "^vs([1-6]?[0-9])$")
+ if r then
+ r = tonumber(r)
+ if r <= 63 then return r end
+ end
+ werror("bad register name `"..expr.."'")
+end
+
+local function parse_cr(expr)
+ local r = match(expr, "^cr([0-7])$")
+ if r then return tonumber(r) end
+ werror("bad condition register name `"..expr.."'")
+end
+
+local function parse_cond(expr)
+ local r, cond = match(expr, "^4%*cr([0-7])%+(%w%w)$")
+ if r then
+ r = tonumber(r)
+ local c = map_cond[cond]
+ if c and c < 4 then return r*4+c end
+ end
+ werror("bad condition bit name `"..expr.."'")
+end
+
+local parse_ctx = {}
+
+local loadenv = setfenv and function(s)
+ local code = loadstring(s, "")
+ if code then setfenv(code, parse_ctx) end
+ return code
+end or function(s)
+ return load(s, "", nil, parse_ctx)
+end
+
+-- Try to parse simple arithmetic, too, since some basic ops are aliases.
+local function parse_number(n)
+ local x = tonumber(n)
+ if x then return x end
+ local code = loadenv("return "..n)
+ if code then
+ local ok, y = pcall(code)
+ if ok then return y end
+ end
+ return nil
+end
+
+local function parse_imm(imm, bits, shift, scale, signed)
+ local n = parse_number(imm)
+ if n then
+ local m = sar(n, scale)
+ if shl(m, scale) == n then
+ if signed then
+ local s = sar(m, bits-1)
+ if s == 0 then return shl(m, shift)
+ elseif s == -1 then return shl(m + shl(1, bits), shift) end
+ else
+ if sar(m, bits) == 0 then return shl(m, shift) end
+ end
+ end
+ werror("out of range immediate `"..imm.."'")
+ elseif match(imm, "^[rfv]([1-3]?[0-9])$") or
+ match(imm, "^vs([1-6]?[0-9])$") or
+ match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then
+ werror("expected immediate operand, got register")
+ else
+ waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
+ return 0
+ end
+end
+
+local function parse_shiftmask(imm, isshift)
+ local n = parse_number(imm)
+ if n then
+ if shr(n, 6) == 0 then
+ local lsb = band(n, 31)
+ local msb = n - lsb
+ return isshift and (shl(lsb, 11)+shr(msb, 4)) or (shl(lsb, 6)+msb)
+ end
+ werror("out of range immediate `"..imm.."'")
+ elseif match(imm, "^r([1-3]?[0-9])$") or
+ match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then
+ werror("expected immediate operand, got register")
+ else
+ waction("IMMSH", isshift and 1 or 0, imm)
+ return 0;
+ end
+end
+
+local function parse_disp(disp)
+ local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
+ if imm then
+ local r = parse_gpr(reg)
+ if r == 0 then werror("cannot use r0 in displacement") end
+ return shl(r, 16) + parse_imm(imm, 16, 0, 0, true)
+ end
+ local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
+ if reg and tailr ~= "" then
+ local r, tp = parse_gpr(reg)
+ if r == 0 then werror("cannot use r0 in displacement") end
+ if tp then
+ waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
+ return shl(r, 16)
+ end
+ end
+ werror("bad displacement `"..disp.."'")
+end
+
+local function parse_u5disp(disp, scale)
+ local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
+ if imm then
+ local r = parse_gpr(reg)
+ if r == 0 then werror("cannot use r0 in displacement") end
+ return shl(r, 16) + parse_imm(imm, 5, 11, scale, false)
+ end
+ local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
+ if reg and tailr ~= "" then
+ local r, tp = parse_gpr(reg)
+ if r == 0 then werror("cannot use r0 in displacement") end
+ if tp then
+ waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr))
+ return shl(r, 16)
+ end
+ end
+ werror("bad displacement `"..disp.."'")
+end
+
+local function parse_label(label, def)
+ local prefix = sub(label, 1, 2)
+ -- =>label (pc label reference)
+ if prefix == "=>" then
+ return "PC", 0, sub(label, 3)
+ end
+ -- ->name (global label reference)
+ if prefix == "->" then
+ return "LG", map_global[sub(label, 3)]
+ end
+ if def then
+ -- [1-9] (local label definition)
+ if match(label, "^[1-9]$") then
+ return "LG", 10+tonumber(label)
+ end
+ else
+ -- [<>][1-9] (local label reference)
+ local dir, lnum = match(label, "^([<>])([1-9])$")
+ if dir then -- Fwd: 1-9, Bkwd: 11-19.
+ return "LG", lnum + (dir == ">" and 0 or 10)
+ end
+ -- extern label (extern label reference)
+ local extname = match(label, "^extern%s+(%S+)$")
+ if extname then
+ return "EXT", map_extern[extname]
+ end
+ end
+ werror("bad label `"..label.."'")
+end
+
+------------------------------------------------------------------------------
+
+-- Handle opcodes defined with template strings.
+op_template = function(params, template, nparams)
+ if not params then return sub(template, 9) end
+ local op = tonumber(sub(template, 1, 8), 16)
+ local n, rs = 1, 26
+
+ -- Limit number of section buffer positions used by a single dasm_put().
+ -- A single opcode needs a maximum of 3 positions (rlwinm).
+ if secpos+3 > maxsecpos then wflush() end
+ local pos = wpos()
+
+ -- Process each character.
+ for p in gmatch(sub(template, 9), ".") do
+ if p == "R" then
+ rs = rs - 5; op = op + shl(parse_gpr(params[n]), rs); n = n + 1
+ elseif p == "F" then
+ rs = rs - 5; op = op + shl(parse_fpr(params[n]), rs); n = n + 1
+ elseif p == "V" then
+ rs = rs - 5; op = op + shl(parse_vr(params[n]), rs); n = n + 1
+ elseif p == "Q" then
+ local vs = parse_vs(params[n]); n = n + 1; rs = rs - 5
+ local sh = rs == 6 and 2 or 3 + band(shr(rs, 1), 3)
+ op = op + shl(band(vs, 31), rs) + shr(band(vs, 32), sh)
+ elseif p == "q" then
+ local vs = parse_vs(params[n]); n = n + 1
+ op = op + shl(band(vs, 31), 21) + shr(band(vs, 32), 5)
+ elseif p == "A" then
+ rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1
+ elseif p == "S" then
+ rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, true); n = n + 1
+ elseif p == "I" then
+ op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1
+ elseif p == "U" then
+ op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1
+ elseif p == "D" then
+ op = op + parse_disp(params[n]); n = n + 1
+ elseif p == "2" then
+ op = op + parse_u5disp(params[n], 1); n = n + 1
+ elseif p == "4" then
+ op = op + parse_u5disp(params[n], 2); n = n + 1
+ elseif p == "8" then
+ op = op + parse_u5disp(params[n], 3); n = n + 1
+ elseif p == "C" then
+ rs = rs - 5; op = op + shl(parse_cond(params[n]), rs); n = n + 1
+ elseif p == "X" then
+ rs = rs - 5; op = op + shl(parse_cr(params[n]), rs+2); n = n + 1
+ elseif p == "1" then
+ rs = rs - 5; op = op + parse_imm(params[n], 1, rs, 0, false); n = n + 1
+ elseif p == "g" then
+ rs = rs - 5; op = op + parse_imm(params[n], 2, rs, 0, false); n = n + 1
+ elseif p == "3" then
+ rs = rs - 5; op = op + parse_imm(params[n], 3, rs, 0, false); n = n + 1
+ elseif p == "P" then
+ rs = rs - 5; op = op + parse_imm(params[n], 4, rs, 0, false); n = n + 1
+ elseif p == "p" then
+ op = op + parse_imm(params[n], 4, rs, 0, false); n = n + 1
+ elseif p == "6" then
+ rs = rs - 6; op = op + parse_imm(params[n], 6, rs, 0, false); n = n + 1
+ elseif p == "Y" then
+ rs = rs - 5; op = op + parse_imm(params[n], 1, rs+4, 0, false); n = n + 1
+ elseif p == "y" then
+ rs = rs - 5; op = op + parse_imm(params[n], 1, rs+3, 0, false); n = n + 1
+ elseif p == "Z" then
+ rs = rs - 5; op = op + parse_imm(params[n], 2, rs+3, 0, false); n = n + 1
+ elseif p == "z" then
+ rs = rs - 5; op = op + parse_imm(params[n], 2, rs+2, 0, false); n = n + 1
+ elseif p == "W" then
+ op = op + parse_cr(params[n]); n = n + 1
+ elseif p == "G" then
+ op = op + parse_imm(params[n], 8, 12, 0, false); n = n + 1
+ elseif p == "H" then
+ op = op + parse_shiftmask(params[n], true); n = n + 1
+ elseif p == "M" then
+ op = op + parse_shiftmask(params[n], false); n = n + 1
+ elseif p == "J" or p == "K" then
+ local mode, m, s = parse_label(params[n], false)
+ if p == "K" then m = m + 2048 end
+ waction("REL_"..mode, m, s, 1)
+ n = n + 1
+ elseif p == "0" then
+ if band(shr(op, rs), 31) == 0 then werror("cannot use r0") end
+ elseif p == "=" or p == "%" then
+ local t = band(shr(op, p == "%" and rs+5 or rs), 31)
+ rs = rs - 5
+ op = op + shl(t, rs)
+ elseif p == "~" then
+ local mm = shl(31, rs)
+ local lo = band(op, mm)
+ local hi = band(op, shl(mm, 5))
+ op = op - lo - hi + shl(lo, 5) + shr(hi, 5)
+ elseif p == ":" then
+ if band(shr(op, rs), 1) ~= 0 then werror("register pair expected") end
+ elseif p == "-" then
+ rs = rs - 5
+ elseif p == "." then
+ -- Ignored.
+ else
+ assert(false)
+ end
+ end
+ wputpos(pos, op)
+end
+
+map_op[".template__"] = op_template
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcode to mark the position where the action list is to be emitted.
+map_op[".actionlist_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeactions(out, name) end)
+end
+
+-- Pseudo-opcode to mark the position where the global enum is to be emitted.
+map_op[".globals_1"] = function(params)
+ if not params then return "prefix" end
+ local prefix = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeglobals(out, prefix) end)
+end
+
+-- Pseudo-opcode to mark the position where the global names are to be emitted.
+map_op[".globalnames_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeglobalnames(out, name) end)
+end
+
+-- Pseudo-opcode to mark the position where the extern names are to be emitted.
+map_op[".externnames_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeexternnames(out, name) end)
+end
+
+------------------------------------------------------------------------------
+
+-- Label pseudo-opcode (converted from trailing colon form).
+map_op[".label_1"] = function(params)
+ if not params then return "[1-9] | ->global | =>pcexpr" end
+ if secpos+1 > maxsecpos then wflush() end
+ local mode, n, s = parse_label(params[1], true)
+ if mode == "EXT" then werror("bad label definition") end
+ waction("LABEL_"..mode, n, s, 1)
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcodes for data storage.
+map_op[".long_*"] = function(params)
+ if not params then return "imm..." end
+ for _,p in ipairs(params) do
+ local n = tonumber(p)
+ if not n then werror("bad immediate `"..p.."'") end
+ if n < 0 then n = n + 2^32 end
+ wputw(n)
+ if secpos+2 > maxsecpos then wflush() end
+ end
+end
+
+-- Alignment pseudo-opcode.
+map_op[".align_1"] = function(params)
+ if not params then return "numpow2" end
+ if secpos+1 > maxsecpos then wflush() end
+ local align = tonumber(params[1])
+ if align then
+ local x = align
+ -- Must be a power of 2 in the range (2 ... 256).
+ for i=1,8 do
+ x = x / 2
+ if x == 1 then
+ waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
+ return
+ end
+ end
+ end
+ werror("bad alignment")
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcode for (primitive) type definitions (map to C types).
+map_op[".type_3"] = function(params, nparams)
+ if not params then
+ return nparams == 2 and "name, ctype" or "name, ctype, reg"
+ end
+ local name, ctype, reg = params[1], params[2], params[3]
+ if not match(name, "^[%a_][%w_]*$") then
+ werror("bad type name `"..name.."'")
+ end
+ local tp = map_type[name]
+ if tp then
+ werror("duplicate type `"..name.."'")
+ end
+ -- Add #type to defines. A bit unclean to put it in map_archdef.
+ map_archdef["#"..name] = "sizeof("..ctype..")"
+ -- Add new type and emit shortcut define.
+ local num = ctypenum + 1
+ map_type[name] = {
+ ctype = ctype,
+ ctypefmt = format("Dt%X(%%s)", num),
+ reg = reg,
+ }
+ wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
+ ctypenum = num
+end
+map_op[".type_2"] = map_op[".type_3"]
+
+-- Dump type definitions.
+local function dumptypes(out, lvl)
+ local t = {}
+ for name in pairs(map_type) do t[#t+1] = name end
+ sort(t)
+ out:write("Type definitions:\n")
+ for _,name in ipairs(t) do
+ local tp = map_type[name]
+ local reg = tp.reg or ""
+ out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
+ end
+ out:write("\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Set the current section.
+function _M.section(num)
+ waction("SECTION", num)
+ wflush(true) -- SECTION is a terminal action.
+end
+
+------------------------------------------------------------------------------
+
+-- Dump architecture description.
+function _M.dumparch(out)
+ out:write(format("DynASM %s version %s, released %s\n\n",
+ _info.arch, _info.version, _info.release))
+ dumpactions(out)
+end
+
+-- Dump all user defined elements.
+function _M.dumpdef(out, lvl)
+ dumptypes(out, lvl)
+ dumpglobals(out, lvl)
+ dumpexterns(out, lvl)
+end
+
+------------------------------------------------------------------------------
+
+-- Pass callbacks from/to the DynASM core.
+function _M.passcb(wl, we, wf, ww)
+ wline, werror, wfatal, wwarn = wl, we, wf, ww
+ return wflush
+end
+
+-- Setup the arch-specific module.
+function _M.setup(arch, opt)
+ g_arch, g_opt = arch, opt
+end
+
+-- Merge the core maps and the arch-specific maps.
+function _M.mergemaps(map_coreop, map_def)
+ setmetatable(map_op, { __index = map_coreop })
+ setmetatable(map_def, { __index = map_archdef })
+ return map_op, map_def
+end
+
+return _M
+
+------------------------------------------------------------------------------
+
diff --git a/LuaJIT-2.1/dynasm/dasm_proto.h b/LuaJIT-2.1/dynasm/dasm_proto.h
new file mode 100644
index 00000000..38f5e71a
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_proto.h
@@ -0,0 +1,83 @@
+/*
+** DynASM encoding engine prototypes.
+** Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+** Released under the MIT license. See dynasm.lua for full copyright notice.
+*/
+
+#ifndef _DASM_PROTO_H
+#define _DASM_PROTO_H
+
+#include
+#include
+
+#define DASM_IDENT "DynASM 1.5.0"
+#define DASM_VERSION 10500 /* 1.5.0 */
+
+#ifndef Dst_DECL
+#define Dst_DECL dasm_State **Dst
+#endif
+
+#ifndef Dst_REF
+#define Dst_REF (*Dst)
+#endif
+
+#ifndef DASM_FDEF
+#define DASM_FDEF extern
+#endif
+
+#ifndef DASM_M_GROW
+#define DASM_M_GROW(ctx, t, p, sz, need) \
+ do { \
+ size_t _sz = (sz), _need = (need); \
+ if (_sz < _need) { \
+ if (_sz < 16) _sz = 16; \
+ while (_sz < _need) _sz += _sz; \
+ (p) = (t *)realloc((p), _sz); \
+ if ((p) == NULL) exit(1); \
+ (sz) = _sz; \
+ } \
+ } while(0)
+#endif
+
+#ifndef DASM_M_FREE
+#define DASM_M_FREE(ctx, p, sz) free(p)
+#endif
+
+/* Internal DynASM encoder state. */
+typedef struct dasm_State dasm_State;
+
+
+/* Initialize and free DynASM state. */
+DASM_FDEF void dasm_init(Dst_DECL, int maxsection);
+DASM_FDEF void dasm_free(Dst_DECL);
+
+/* Setup global array. Must be called before dasm_setup(). */
+DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl);
+
+/* Grow PC label array. Can be called after dasm_setup(), too. */
+DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc);
+
+/* Setup encoder. */
+DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist);
+
+/* Feed encoder with actions. Calls are generated by pre-processor. */
+DASM_FDEF void dasm_put(Dst_DECL, int start, ...);
+
+/* Link sections and return the resulting size. */
+DASM_FDEF int dasm_link(Dst_DECL, size_t *szp);
+
+/* Encode sections into buffer. */
+DASM_FDEF int dasm_encode(Dst_DECL, void *buffer);
+
+/* Get PC label offset. */
+DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc);
+
+#ifdef DASM_CHECKS
+/* Optional sanity checker to call between isolated encoding steps. */
+DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch);
+#else
+#define dasm_checkstep(a, b) 0
+#endif
+
+
+#endif /* _DASM_PROTO_H */
diff --git a/LuaJIT-2.1/dynasm/dasm_x64.lua b/LuaJIT-2.1/dynasm/dasm_x64.lua
new file mode 100644
index 00000000..d23fcd99
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_x64.lua
@@ -0,0 +1,12 @@
+------------------------------------------------------------------------------
+-- DynASM x64 module.
+--
+-- Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+-- See dynasm.lua for full copyright notice.
+------------------------------------------------------------------------------
+-- This module just sets 64 bit mode for the combined x86/x64 module.
+-- All the interesting stuff is there.
+------------------------------------------------------------------------------
+
+x64 = true -- Using a global is an ugly, but effective solution.
+return require("dasm_x86")
diff --git a/LuaJIT-2.1/dynasm/dasm_x86.h b/LuaJIT-2.1/dynasm/dasm_x86.h
new file mode 100644
index 00000000..ff54c9f1
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_x86.h
@@ -0,0 +1,523 @@
+/*
+** DynASM x86 encoding engine.
+** Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+** Released under the MIT license. See dynasm.lua for full copyright notice.
+*/
+
+#include
+#include
+#include
+#include
+
+#define DASM_ARCH "x86"
+
+#ifndef DASM_EXTERN
+#define DASM_EXTERN(a,b,c,d) 0
+#endif
+
+/* Action definitions. DASM_STOP must be 255. */
+enum {
+ DASM_DISP = 233,
+ DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB,
+ DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC,
+ DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN,
+ DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP
+};
+
+/* Maximum number of section buffer positions for a single dasm_put() call. */
+#define DASM_MAXSECPOS 25
+
+/* DynASM encoder status codes. Action list offset or number are or'ed in. */
+#define DASM_S_OK 0x00000000
+#define DASM_S_NOMEM 0x01000000
+#define DASM_S_PHASE 0x02000000
+#define DASM_S_MATCH_SEC 0x03000000
+#define DASM_S_RANGE_I 0x11000000
+#define DASM_S_RANGE_SEC 0x12000000
+#define DASM_S_RANGE_LG 0x13000000
+#define DASM_S_RANGE_PC 0x14000000
+#define DASM_S_RANGE_VREG 0x15000000
+#define DASM_S_UNDEF_L 0x21000000
+#define DASM_S_UNDEF_PC 0x22000000
+
+/* Macros to convert positions (8 bit section + 24 bit index). */
+#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
+#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
+#define DASM_SEC2POS(sec) ((sec)<<24)
+#define DASM_POS2SEC(pos) ((pos)>>24)
+#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
+
+/* Action list type. */
+typedef const unsigned char *dasm_ActList;
+
+/* Per-section structure. */
+typedef struct dasm_Section {
+ int *rbuf; /* Biased buffer pointer (negative section bias). */
+ int *buf; /* True buffer pointer. */
+ size_t bsize; /* Buffer size in bytes. */
+ int pos; /* Biased buffer position. */
+ int epos; /* End of biased buffer position - max single put. */
+ int ofs; /* Byte offset into section. */
+} dasm_Section;
+
+/* Core structure holding the DynASM encoding state. */
+struct dasm_State {
+ size_t psize; /* Allocated size of this structure. */
+ dasm_ActList actionlist; /* Current actionlist pointer. */
+ int *lglabels; /* Local/global chain/pos ptrs. */
+ size_t lgsize;
+ int *pclabels; /* PC label chains/pos ptrs. */
+ size_t pcsize;
+ void **globals; /* Array of globals. */
+ dasm_Section *section; /* Pointer to active section. */
+ size_t codesize; /* Total size of all code sections. */
+ int maxsection; /* 0 <= sectionidx < maxsection. */
+ int status; /* Status code. */
+ dasm_Section sections[1]; /* All sections. Alloc-extended. */
+};
+
+/* The size of the core structure depends on the max. number of sections. */
+#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
+
+
+/* Initialize DynASM state. */
+void dasm_init(Dst_DECL, int maxsection)
+{
+ dasm_State *D;
+ size_t psz = 0;
+ Dst_REF = NULL;
+ DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
+ D = Dst_REF;
+ D->psize = psz;
+ D->lglabels = NULL;
+ D->lgsize = 0;
+ D->pclabels = NULL;
+ D->pcsize = 0;
+ D->globals = NULL;
+ D->maxsection = maxsection;
+ memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section));
+}
+
+/* Free DynASM state. */
+void dasm_free(Dst_DECL)
+{
+ dasm_State *D = Dst_REF;
+ int i;
+ for (i = 0; i < D->maxsection; i++)
+ if (D->sections[i].buf)
+ DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
+ if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
+ if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
+ DASM_M_FREE(Dst, D, D->psize);
+}
+
+/* Setup global label array. Must be called before dasm_setup(). */
+void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
+{
+ dasm_State *D = Dst_REF;
+ D->globals = gl;
+ DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
+}
+
+/* Grow PC label array. Can be called after dasm_setup(), too. */
+void dasm_growpc(Dst_DECL, unsigned int maxpc)
+{
+ dasm_State *D = Dst_REF;
+ size_t osz = D->pcsize;
+ DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
+ memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
+}
+
+/* Setup encoder. */
+void dasm_setup(Dst_DECL, const void *actionlist)
+{
+ dasm_State *D = Dst_REF;
+ int i;
+ D->actionlist = (dasm_ActList)actionlist;
+ D->status = DASM_S_OK;
+ D->section = &D->sections[0];
+ memset((void *)D->lglabels, 0, D->lgsize);
+ if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
+ for (i = 0; i < D->maxsection; i++) {
+ D->sections[i].pos = DASM_SEC2POS(i);
+ D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos;
+ D->sections[i].ofs = 0;
+ }
+}
+
+
+#ifdef DASM_CHECKS
+#define CK(x, st) \
+ do { if (!(x)) { \
+ D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
+#define CKPL(kind, st) \
+ do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
+ D->status=DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
+#else
+#define CK(x, st) ((void)0)
+#define CKPL(kind, st) ((void)0)
+#endif
+
+/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
+void dasm_put(Dst_DECL, int start, ...)
+{
+ va_list ap;
+ dasm_State *D = Dst_REF;
+ dasm_ActList p = D->actionlist + start;
+ dasm_Section *sec = D->section;
+ int pos = sec->pos, ofs = sec->ofs, mrm = -1;
+ int *b;
+
+ if (pos >= sec->epos) {
+ DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
+ sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
+ sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
+ sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
+ }
+
+ b = sec->rbuf;
+ b[pos++] = start;
+
+ va_start(ap, start);
+ while (1) {
+ int action = *p++;
+ if (action < DASM_DISP) {
+ ofs++;
+ } else if (action <= DASM_REL_A) {
+ int n = va_arg(ap, int);
+ b[pos++] = n;
+ switch (action) {
+ case DASM_DISP:
+ if (n == 0) { if (mrm < 0) mrm = p[-2]; if ((mrm&7) != 5) break; }
+ /* fallthrough */
+ case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */
+ case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */
+ case DASM_IMM_D: ofs += 4; break;
+ case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob;
+ case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break;
+ case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */
+ case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break;
+ case DASM_SPACE: p++; ofs += n; break;
+ case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */
+ case DASM_VREG: CK((n&-16) == 0 && (n != 4 || (*p>>5) != 2), RANGE_VREG);
+ if (*p < 0x40 && p[1] == DASM_DISP) mrm = n;
+ if (*p < 0x20 && (n&7) == 4) ofs++;
+ switch ((*p++ >> 3) & 3) {
+ case 3: n |= b[pos-3]; /* fallthrough */
+ case 2: n |= b[pos-2]; /* fallthrough */
+ case 1: if (n <= 7) { b[pos-1] |= 0x10; ofs--; }
+ }
+ continue;
+ }
+ mrm = -1;
+ } else {
+ int *pl, n;
+ switch (action) {
+ case DASM_REL_LG:
+ case DASM_IMM_LG:
+ n = *p++; pl = D->lglabels + n;
+ /* Bkwd rel or global. */
+ if (n <= 246) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
+ pl -= 246; n = *pl;
+ if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
+ goto linkrel;
+ case DASM_REL_PC:
+ case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
+ putrel:
+ n = *pl;
+ if (n < 0) { /* Label exists. Get label pos and store it. */
+ b[pos] = -n;
+ } else {
+ linkrel:
+ b[pos] = n; /* Else link to rel chain, anchored at label. */
+ *pl = pos;
+ }
+ pos++;
+ ofs += 4; /* Maximum offset needed. */
+ if (action == DASM_REL_LG || action == DASM_REL_PC) {
+ b[pos++] = ofs; /* Store pass1 offset estimate. */
+ } else if (sizeof(ptrdiff_t) == 8) {
+ ofs += 4;
+ }
+ break;
+ case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel;
+ case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
+ putlabel:
+ n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
+ while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; }
+ *pl = -pos; /* Label exists now. */
+ b[pos++] = ofs; /* Store pass1 offset estimate. */
+ break;
+ case DASM_ALIGN:
+ ofs += *p++; /* Maximum alignment needed (arg is 2**n-1). */
+ b[pos++] = ofs; /* Store pass1 offset estimate. */
+ break;
+ case DASM_EXTERN: p += 2; ofs += 4; break;
+ case DASM_ESC: p++; ofs++; break;
+ case DASM_MARK: mrm = p[-2]; break;
+ case DASM_SECTION:
+ n = *p; CK(n < D->maxsection, RANGE_SEC); D->section = &D->sections[n];
+ case DASM_STOP: goto stop;
+ }
+ }
+ }
+stop:
+ va_end(ap);
+ sec->pos = pos;
+ sec->ofs = ofs;
+}
+#undef CK
+
+/* Pass 2: Link sections, shrink branches/aligns, fix label offsets. */
+int dasm_link(Dst_DECL, size_t *szp)
+{
+ dasm_State *D = Dst_REF;
+ int secnum;
+ int ofs = 0;
+
+#ifdef DASM_CHECKS
+ *szp = 0;
+ if (D->status != DASM_S_OK) return D->status;
+ {
+ int pc;
+ for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
+ if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
+ }
+#endif
+
+ { /* Handle globals not defined in this translation unit. */
+ int idx;
+ for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
+ int n = D->lglabels[idx];
+ /* Undefined label: Collapse rel chain and replace with marker (< 0). */
+ while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
+ }
+ }
+
+ /* Combine all code sections. No support for data sections (yet). */
+ for (secnum = 0; secnum < D->maxsection; secnum++) {
+ dasm_Section *sec = D->sections + secnum;
+ int *b = sec->rbuf;
+ int pos = DASM_SEC2POS(secnum);
+ int lastpos = sec->pos;
+
+ while (pos != lastpos) {
+ dasm_ActList p = D->actionlist + b[pos++];
+ int op = 0;
+ while (1) {
+ int action = *p++;
+ switch (action) {
+ case DASM_REL_LG: p++;
+ /* fallthrough */
+ case DASM_REL_PC: {
+ int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0);
+ if (shrink) { /* Shrinkable branch opcode? */
+ int lofs, lpos = b[pos];
+ if (lpos < 0) goto noshrink; /* Ext global? */
+ lofs = *DASM_POS2PTR(D, lpos);
+ if (lpos > pos) { /* Fwd label: add cumulative section offsets. */
+ int i;
+ for (i = secnum; i < DASM_POS2SEC(lpos); i++)
+ lofs += D->sections[i].ofs;
+ } else {
+ lofs -= ofs; /* Bkwd label: unfix offset. */
+ }
+ lofs -= b[pos+1]; /* Short branch ok? */
+ if (lofs >= -128-shrink && lofs <= 127) ofs -= shrink; /* Yes. */
+ else { noshrink: shrink = 0; } /* No, cannot shrink op. */
+ }
+ b[pos+1] = shrink;
+ pos += 2;
+ break;
+ }
+ /* fallthrough */
+ case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++;
+ /* fallthrough */
+ case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W:
+ case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB:
+ case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break;
+ case DASM_LABEL_LG: p++;
+ /* fallthrough */
+ case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */
+ case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */
+ case DASM_EXTERN: p += 2; break;
+ case DASM_ESC: op = *p++; break;
+ case DASM_MARK: break;
+ case DASM_SECTION: case DASM_STOP: goto stop;
+ default: op = action; break;
+ }
+ }
+ stop: (void)0;
+ }
+ ofs += sec->ofs; /* Next section starts right after current section. */
+ }
+
+ D->codesize = ofs; /* Total size of all code sections */
+ *szp = ofs;
+ return DASM_S_OK;
+}
+
+#define dasmb(x) *cp++ = (unsigned char)(x)
+#ifndef DASM_ALIGNED_WRITES
+#define dasmw(x) \
+ do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0)
+#define dasmd(x) \
+ do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0)
+#define dasmq(x) \
+ do { *((unsigned long long *)cp) = (unsigned long long)(x); cp+=8; } while (0)
+#else
+#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0)
+#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0)
+#define dasmq(x) do { dasmd(x); dasmd((x)>>32); } while (0)
+#endif
+static unsigned char *dasma_(unsigned char *cp, ptrdiff_t x)
+{
+ if (sizeof(ptrdiff_t) == 8)
+ dasmq((unsigned long long)x);
+ else
+ dasmd((unsigned int)x);
+ return cp;
+}
+#define dasma(x) (cp = dasma_(cp, (x)))
+
+/* Pass 3: Encode sections. */
+int dasm_encode(Dst_DECL, void *buffer)
+{
+ dasm_State *D = Dst_REF;
+ unsigned char *base = (unsigned char *)buffer;
+ unsigned char *cp = base;
+ int secnum;
+
+ /* Encode all code sections. No support for data sections (yet). */
+ for (secnum = 0; secnum < D->maxsection; secnum++) {
+ dasm_Section *sec = D->sections + secnum;
+ int *b = sec->buf;
+ int *endb = sec->rbuf + sec->pos;
+
+ while (b != endb) {
+ dasm_ActList p = D->actionlist + *b++;
+ unsigned char *mark = NULL;
+ while (1) {
+ int action = *p++;
+ int n = (action >= DASM_DISP && action <= DASM_ALIGN) ? *b++ : 0;
+ switch (action) {
+ case DASM_DISP: if (!mark) mark = cp; {
+ unsigned char *mm = mark;
+ if (*p != DASM_IMM_DB && *p != DASM_IMM_WB) mark = NULL;
+ if (n == 0) { int mrm = mm[-1]&7; if (mrm == 4) mrm = mm[0]&7;
+ if (mrm != 5) { mm[-1] -= 0x80; break; } }
+ if (((n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40;
+ }
+ /* fallthrough */
+ case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break;
+ case DASM_IMM_DB: if (((n+128)&-256) == 0) {
+ db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb;
+ } else mark = NULL;
+ /* fallthrough */
+ case DASM_IMM_D: wd: dasmd(n); break;
+ case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL;
+ /* fallthrough */
+ case DASM_IMM_W: dasmw(n); break;
+ case DASM_VREG: {
+ int t = *p++;
+ unsigned char *ex = cp - (t&7);
+ if ((n & 8) && t < 0xa0) {
+ if (*ex & 0x80) ex[1] ^= 0x20 << (t>>6); else *ex ^= 1 << (t>>6);
+ n &= 7;
+ } else if (n & 0x10) {
+ if (*ex & 0x80) {
+ *ex = 0xc5; ex[1] = (ex[1] & 0x80) | ex[2]; ex += 2;
+ }
+ while (++ex < cp) ex[-1] = *ex;
+ if (mark) mark--;
+ cp--;
+ n &= 7;
+ }
+ if (t >= 0xc0) n <<= 4;
+ else if (t >= 0x40) n <<= 3;
+ else if (n == 4 && t < 0x20) { cp[-1] ^= n; *cp++ = 0x20; }
+ cp[-1] ^= n;
+ break;
+ }
+ case DASM_REL_LG: p++; if (n >= 0) goto rel_pc;
+ b++; n = (int)(ptrdiff_t)D->globals[-n-10];
+ /* fallthrough */
+ case DASM_REL_A: rel_a:
+ n -= (unsigned int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */
+ case DASM_REL_PC: rel_pc: {
+ int shrink = *b++;
+ int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; }
+ n = *pb - ((int)(cp-base) + 4-shrink);
+ if (shrink == 0) goto wd;
+ if (shrink == 4) { cp--; cp[-1] = *cp-0x10; } else cp[-1] = 0xeb;
+ goto wb;
+ }
+ case DASM_IMM_LG:
+ p++;
+ if (n < 0) { dasma((ptrdiff_t)D->globals[-n-10]); break; }
+ /* fallthrough */
+ case DASM_IMM_PC: {
+ int *pb = DASM_POS2PTR(D, n);
+ dasma(*pb < 0 ? (ptrdiff_t)pb[1] : (*pb + (ptrdiff_t)base));
+ break;
+ }
+ case DASM_LABEL_LG: {
+ int idx = *p++;
+ if (idx >= 10)
+ D->globals[idx-10] = (void *)(base + (*p == DASM_SETLABEL ? *b : n));
+ break;
+ }
+ case DASM_LABEL_PC: case DASM_SETLABEL: break;
+ case DASM_SPACE: { int fill = *p++; while (n--) *cp++ = fill; break; }
+ case DASM_ALIGN:
+ n = *p++;
+ while (((cp-base) & n)) *cp++ = 0x90; /* nop */
+ break;
+ case DASM_EXTERN: n = DASM_EXTERN(Dst, cp, p[1], *p); p += 2; goto wd;
+ case DASM_MARK: mark = cp; break;
+ case DASM_ESC: action = *p++;
+ /* fallthrough */
+ default: *cp++ = action; break;
+ case DASM_SECTION: case DASM_STOP: goto stop;
+ }
+ }
+ stop: (void)0;
+ }
+ }
+
+ if (base + D->codesize != cp) /* Check for phase errors. */
+ return DASM_S_PHASE;
+ return DASM_S_OK;
+}
+
+/* Get PC label offset. */
+int dasm_getpclabel(Dst_DECL, unsigned int pc)
+{
+ dasm_State *D = Dst_REF;
+ if (pc*sizeof(int) < D->pcsize) {
+ int pos = D->pclabels[pc];
+ if (pos < 0) return *DASM_POS2PTR(D, -pos);
+ if (pos > 0) return -1; /* Undefined. */
+ }
+ return -2; /* Unused or out of range. */
+}
+
+#ifdef DASM_CHECKS
+/* Optional sanity checker to call between isolated encoding steps. */
+int dasm_checkstep(Dst_DECL, int secmatch)
+{
+ dasm_State *D = Dst_REF;
+ if (D->status == DASM_S_OK) {
+ int i;
+ for (i = 1; i <= 9; i++) {
+ if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_L|i; break; }
+ D->lglabels[i] = 0;
+ }
+ }
+ if (D->status == DASM_S_OK && secmatch >= 0 &&
+ D->section != &D->sections[secmatch])
+ D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
+ return D->status;
+}
+#endif
+
diff --git a/LuaJIT-2.1/dynasm/dasm_x86.lua b/LuaJIT-2.1/dynasm/dasm_x86.lua
new file mode 100644
index 00000000..c767cdeb
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dasm_x86.lua
@@ -0,0 +1,2394 @@
+------------------------------------------------------------------------------
+-- DynASM x86/x64 module.
+--
+-- Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+-- See dynasm.lua for full copyright notice.
+------------------------------------------------------------------------------
+
+local x64 = x64
+
+-- Module information:
+local _info = {
+ arch = x64 and "x64" or "x86",
+ description = "DynASM x86/x64 module",
+ version = "1.5.0",
+ vernum = 10500,
+ release = "2021-05-02",
+ author = "Mike Pall",
+ license = "MIT",
+}
+
+-- Exported glue functions for the arch-specific module.
+local _M = { _info = _info }
+
+-- Cache library functions.
+local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
+local assert, unpack, setmetatable = assert, unpack or table.unpack, setmetatable
+local _s = string
+local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
+local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub
+local concat, sort, remove = table.concat, table.sort, table.remove
+local bit = bit or require("bit")
+local band, bxor, shl, shr = bit.band, bit.bxor, bit.lshift, bit.rshift
+
+-- Inherited tables and callbacks.
+local g_opt, g_arch
+local wline, werror, wfatal, wwarn
+
+-- Action name list.
+-- CHECK: Keep this in sync with the C code!
+local action_names = {
+ -- int arg, 1 buffer pos:
+ "DISP", "IMM_S", "IMM_B", "IMM_W", "IMM_D", "IMM_WB", "IMM_DB",
+ -- action arg (1 byte), int arg, 1 buffer pos (reg/num):
+ "VREG", "SPACE",
+ -- ptrdiff_t arg, 1 buffer pos (address): !x64
+ "SETLABEL", "REL_A",
+ -- action arg (1 byte) or int arg, 2 buffer pos (link, offset):
+ "REL_LG", "REL_PC",
+ -- action arg (1 byte) or int arg, 1 buffer pos (link):
+ "IMM_LG", "IMM_PC",
+ -- action arg (1 byte) or int arg, 1 buffer pos (offset):
+ "LABEL_LG", "LABEL_PC",
+ -- action arg (1 byte), 1 buffer pos (offset):
+ "ALIGN",
+ -- action args (2 bytes), no buffer pos.
+ "EXTERN",
+ -- action arg (1 byte), no buffer pos.
+ "ESC",
+ -- no action arg, no buffer pos.
+ "MARK",
+ -- action arg (1 byte), no buffer pos, terminal action:
+ "SECTION",
+ -- no args, no buffer pos, terminal action:
+ "STOP"
+}
+
+-- Maximum number of section buffer positions for dasm_put().
+-- CHECK: Keep this in sync with the C code!
+local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
+
+-- Action name -> action number (dynamically generated below).
+local map_action = {}
+-- First action number. Everything below does not need to be escaped.
+local actfirst = 256-#action_names
+
+-- Action list buffer and string (only used to remove dupes).
+local actlist = {}
+local actstr = ""
+
+-- Argument list for next dasm_put(). Start with offset 0 into action list.
+local actargs = { 0 }
+
+-- Current number of section buffer positions for dasm_put().
+local secpos = 1
+
+-- VREG kind encodings, pre-shifted by 5 bits.
+local map_vreg = {
+ ["modrm.rm.m"] = 0x00,
+ ["modrm.rm.r"] = 0x20,
+ ["opcode"] = 0x20,
+ ["sib.base"] = 0x20,
+ ["sib.index"] = 0x40,
+ ["modrm.reg"] = 0x80,
+ ["vex.v"] = 0xa0,
+ ["imm.hi"] = 0xc0,
+}
+
+-- Current number of VREG actions contributing to REX/VEX shrinkage.
+local vreg_shrink_count = 0
+
+------------------------------------------------------------------------------
+
+-- Compute action numbers for action names.
+for n,name in ipairs(action_names) do
+ local num = actfirst + n - 1
+ map_action[name] = num
+end
+
+-- Dump action names and numbers.
+local function dumpactions(out)
+ out:write("DynASM encoding engine action codes:\n")
+ for n,name in ipairs(action_names) do
+ local num = map_action[name]
+ out:write(format(" %-10s %02X %d\n", name, num, num))
+ end
+ out:write("\n")
+end
+
+-- Write action list buffer as a huge static C array.
+local function writeactions(out, name)
+ local nn = #actlist
+ local last = actlist[nn] or 255
+ actlist[nn] = nil -- Remove last byte.
+ if nn == 0 then nn = 1 end
+ out:write("static const unsigned char ", name, "[", nn, "] = {\n")
+ local s = " "
+ for n,b in ipairs(actlist) do
+ s = s..b..","
+ if #s >= 75 then
+ assert(out:write(s, "\n"))
+ s = " "
+ end
+ end
+ out:write(s, last, "\n};\n\n") -- Add last byte back.
+end
+
+------------------------------------------------------------------------------
+
+-- Add byte to action list.
+local function wputxb(n)
+ assert(n >= 0 and n <= 255 and n % 1 == 0, "byte out of range")
+ actlist[#actlist+1] = n
+end
+
+-- Add action to list with optional arg. Advance buffer pos, too.
+local function waction(action, a, num)
+ wputxb(assert(map_action[action], "bad action name `"..action.."'"))
+ if a then actargs[#actargs+1] = a end
+ if a or num then secpos = secpos + (num or 1) end
+end
+
+-- Optionally add a VREG action.
+local function wvreg(kind, vreg, psz, sk, defer)
+ if not vreg then return end
+ waction("VREG", vreg)
+ local b = assert(map_vreg[kind], "bad vreg kind `"..vreg.."'")
+ if b < (sk or 0) then
+ vreg_shrink_count = vreg_shrink_count + 1
+ end
+ if not defer then
+ b = b + vreg_shrink_count * 8
+ vreg_shrink_count = 0
+ end
+ wputxb(b + (psz or 0))
+end
+
+-- Add call to embedded DynASM C code.
+local function wcall(func, args)
+ wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true)
+end
+
+-- Delete duplicate action list chunks. A tad slow, but so what.
+local function dedupechunk(offset)
+ local al, as = actlist, actstr
+ local chunk = char(unpack(al, offset+1, #al))
+ local orig = find(as, chunk, 1, true)
+ if orig then
+ actargs[1] = orig-1 -- Replace with original offset.
+ for i=offset+1,#al do al[i] = nil end -- Kill dupe.
+ else
+ actstr = as..chunk
+ end
+end
+
+-- Flush action list (intervening C code or buffer pos overflow).
+local function wflush(term)
+ local offset = actargs[1]
+ if #actlist == offset then return end -- Nothing to flush.
+ if not term then waction("STOP") end -- Terminate action list.
+ dedupechunk(offset)
+ wcall("put", actargs) -- Add call to dasm_put().
+ actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
+ secpos = 1 -- The actionlist offset occupies a buffer position, too.
+end
+
+-- Put escaped byte.
+local function wputb(n)
+ if n >= actfirst then waction("ESC") end -- Need to escape byte.
+ wputxb(n)
+end
+
+------------------------------------------------------------------------------
+
+-- Global label name -> global label number. With auto assignment on 1st use.
+local next_global = 10
+local map_global = setmetatable({}, { __index = function(t, name)
+ if not match(name, "^[%a_][%w_@]*$") then werror("bad global label") end
+ local n = next_global
+ if n > 246 then werror("too many global labels") end
+ next_global = n + 1
+ t[name] = n
+ return n
+end})
+
+-- Dump global labels.
+local function dumpglobals(out, lvl)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("Global labels:\n")
+ for i=10,next_global-1 do
+ out:write(format(" %s\n", t[i]))
+ end
+ out:write("\n")
+end
+
+-- Write global label enum.
+local function writeglobals(out, prefix)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("enum {\n")
+ for i=10,next_global-1 do
+ out:write(" ", prefix, gsub(t[i], "@.*", ""), ",\n")
+ end
+ out:write(" ", prefix, "_MAX\n};\n")
+end
+
+-- Write global label names.
+local function writeglobalnames(out, name)
+ local t = {}
+ for name, n in pairs(map_global) do t[n] = name end
+ out:write("static const char *const ", name, "[] = {\n")
+ for i=10,next_global-1 do
+ out:write(" \"", t[i], "\",\n")
+ end
+ out:write(" (const char *)0\n};\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Extern label name -> extern label number. With auto assignment on 1st use.
+local next_extern = -1
+local map_extern = setmetatable({}, { __index = function(t, name)
+ -- No restrictions on the name for now.
+ local n = next_extern
+ if n < -256 then werror("too many extern labels") end
+ next_extern = n - 1
+ t[name] = n
+ return n
+end})
+
+-- Dump extern labels.
+local function dumpexterns(out, lvl)
+ local t = {}
+ for name, n in pairs(map_extern) do t[-n] = name end
+ out:write("Extern labels:\n")
+ for i=1,-next_extern-1 do
+ out:write(format(" %s\n", t[i]))
+ end
+ out:write("\n")
+end
+
+-- Write extern label names.
+local function writeexternnames(out, name)
+ local t = {}
+ for name, n in pairs(map_extern) do t[-n] = name end
+ out:write("static const char *const ", name, "[] = {\n")
+ for i=1,-next_extern-1 do
+ out:write(" \"", t[i], "\",\n")
+ end
+ out:write(" (const char *)0\n};\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Arch-specific maps.
+local map_archdef = {} -- Ext. register name -> int. name.
+local map_reg_rev = {} -- Int. register name -> ext. name.
+local map_reg_num = {} -- Int. register name -> register number.
+local map_reg_opsize = {} -- Int. register name -> operand size.
+local map_reg_valid_base = {} -- Int. register name -> valid base register?
+local map_reg_valid_index = {} -- Int. register name -> valid index register?
+local map_reg_needrex = {} -- Int. register name -> need rex vs. no rex.
+local reg_list = {} -- Canonical list of int. register names.
+
+local map_type = {} -- Type name -> { ctype, reg }
+local ctypenum = 0 -- Type number (for _PTx macros).
+
+local addrsize = x64 and "q" or "d" -- Size for address operands.
+
+-- Helper functions to fill register maps.
+local function mkrmap(sz, cl, names)
+ local cname = format("@%s", sz)
+ reg_list[#reg_list+1] = cname
+ map_archdef[cl] = cname
+ map_reg_rev[cname] = cl
+ map_reg_num[cname] = -1
+ map_reg_opsize[cname] = sz
+ if sz == addrsize or sz == "d" then
+ map_reg_valid_base[cname] = true
+ map_reg_valid_index[cname] = true
+ end
+ if names then
+ for n,name in ipairs(names) do
+ local iname = format("@%s%x", sz, n-1)
+ reg_list[#reg_list+1] = iname
+ map_archdef[name] = iname
+ map_reg_rev[iname] = name
+ map_reg_num[iname] = n-1
+ map_reg_opsize[iname] = sz
+ if sz == "b" and n > 4 then map_reg_needrex[iname] = false end
+ if sz == addrsize or sz == "d" then
+ map_reg_valid_base[iname] = true
+ map_reg_valid_index[iname] = true
+ end
+ end
+ end
+ for i=0,(x64 and sz ~= "f") and 15 or 7 do
+ local needrex = sz == "b" and i > 3
+ local iname = format("@%s%x%s", sz, i, needrex and "R" or "")
+ if needrex then map_reg_needrex[iname] = true end
+ local name
+ if sz == "o" or sz == "y" then name = format("%s%d", cl, i)
+ elseif sz == "f" then name = format("st%d", i)
+ else name = format("r%d%s", i, sz == addrsize and "" or sz) end
+ map_archdef[name] = iname
+ if not map_reg_rev[iname] then
+ reg_list[#reg_list+1] = iname
+ map_reg_rev[iname] = name
+ map_reg_num[iname] = i
+ map_reg_opsize[iname] = sz
+ if sz == addrsize or sz == "d" then
+ map_reg_valid_base[iname] = true
+ map_reg_valid_index[iname] = true
+ end
+ end
+ end
+ reg_list[#reg_list+1] = ""
+end
+
+-- Integer registers (qword, dword, word and byte sized).
+if x64 then
+ mkrmap("q", "Rq", {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"})
+end
+mkrmap("d", "Rd", {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"})
+mkrmap("w", "Rw", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"})
+mkrmap("b", "Rb", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"})
+map_reg_valid_index[map_archdef.esp] = false
+if x64 then map_reg_valid_index[map_archdef.rsp] = false end
+if x64 then map_reg_needrex[map_archdef.Rb] = true end
+map_archdef["Ra"] = "@"..addrsize
+
+-- FP registers (internally tword sized, but use "f" as operand size).
+mkrmap("f", "Rf")
+
+-- SSE registers (oword sized, but qword and dword accessible).
+mkrmap("o", "xmm")
+
+-- AVX registers (yword sized, but oword, qword and dword accessible).
+mkrmap("y", "ymm")
+
+-- Operand size prefixes to codes.
+local map_opsize = {
+ byte = "b", word = "w", dword = "d", qword = "q", oword = "o", yword = "y",
+ tword = "t", aword = addrsize,
+}
+
+-- Operand size code to number.
+local map_opsizenum = {
+ b = 1, w = 2, d = 4, q = 8, o = 16, y = 32, t = 10,
+}
+
+-- Operand size code to name.
+local map_opsizename = {
+ b = "byte", w = "word", d = "dword", q = "qword", o = "oword", y = "yword",
+ t = "tword", f = "fpword",
+}
+
+-- Valid index register scale factors.
+local map_xsc = {
+ ["1"] = 0, ["2"] = 1, ["4"] = 2, ["8"] = 3,
+}
+
+-- Condition codes.
+local map_cc = {
+ o = 0, no = 1, b = 2, nb = 3, e = 4, ne = 5, be = 6, nbe = 7,
+ s = 8, ns = 9, p = 10, np = 11, l = 12, nl = 13, le = 14, nle = 15,
+ c = 2, nae = 2, nc = 3, ae = 3, z = 4, nz = 5, na = 6, a = 7,
+ pe = 10, po = 11, nge = 12, ge = 13, ng = 14, g = 15,
+}
+
+
+-- Reverse defines for registers.
+function _M.revdef(s)
+ return gsub(s, "@%w+", map_reg_rev)
+end
+
+-- Dump register names and numbers
+local function dumpregs(out)
+ out:write("Register names, sizes and internal numbers:\n")
+ for _,reg in ipairs(reg_list) do
+ if reg == "" then
+ out:write("\n")
+ else
+ local name = map_reg_rev[reg]
+ local num = map_reg_num[reg]
+ local opsize = map_opsizename[map_reg_opsize[reg]]
+ out:write(format(" %-5s %-8s %s\n", name, opsize,
+ num < 0 and "(variable)" or num))
+ end
+ end
+end
+
+------------------------------------------------------------------------------
+
+-- Put action for label arg (IMM_LG, IMM_PC, REL_LG, REL_PC).
+local function wputlabel(aprefix, imm, num)
+ if type(imm) == "number" then
+ if imm < 0 then
+ waction("EXTERN")
+ wputxb(aprefix == "IMM_" and 0 or 1)
+ imm = -imm-1
+ else
+ waction(aprefix.."LG", nil, num);
+ end
+ wputxb(imm)
+ else
+ waction(aprefix.."PC", imm, num)
+ end
+end
+
+-- Put signed byte or arg.
+local function wputsbarg(n)
+ if type(n) == "number" then
+ if n < -128 or n > 127 then
+ werror("signed immediate byte out of range")
+ end
+ if n < 0 then n = n + 256 end
+ wputb(n)
+ else waction("IMM_S", n) end
+end
+
+-- Put unsigned byte or arg.
+local function wputbarg(n)
+ if type(n) == "number" then
+ if n < 0 or n > 255 then
+ werror("unsigned immediate byte out of range")
+ end
+ wputb(n)
+ else waction("IMM_B", n) end
+end
+
+-- Put unsigned word or arg.
+local function wputwarg(n)
+ if type(n) == "number" then
+ if shr(n, 16) ~= 0 then
+ werror("unsigned immediate word out of range")
+ end
+ wputb(band(n, 255)); wputb(shr(n, 8));
+ else waction("IMM_W", n) end
+end
+
+-- Put signed or unsigned dword or arg.
+local function wputdarg(n)
+ local tn = type(n)
+ if tn == "number" then
+ wputb(band(n, 255))
+ wputb(band(shr(n, 8), 255))
+ wputb(band(shr(n, 16), 255))
+ wputb(shr(n, 24))
+ elseif tn == "table" then
+ wputlabel("IMM_", n[1], 1)
+ else
+ waction("IMM_D", n)
+ end
+end
+
+-- Put signed or unsigned qword or arg.
+local function wputqarg(n)
+ local tn = type(n)
+ if tn == "number" then -- This is only used for numbers from -2^31..2^32-1.
+ wputb(band(n, 255))
+ wputb(band(shr(n, 8), 255))
+ wputb(band(shr(n, 16), 255))
+ wputb(shr(n, 24))
+ local sign = n < 0 and 255 or 0
+ wputb(sign); wputb(sign); wputb(sign); wputb(sign)
+ else
+ waction("IMM_D", format("(unsigned int)(%s)", n))
+ waction("IMM_D", format("(unsigned int)((unsigned long long)(%s)>>32)", n))
+ end
+end
+
+-- Put operand-size dependent number or arg (defaults to dword).
+local function wputszarg(sz, n)
+ if not sz or sz == "d" or sz == "q" then wputdarg(n)
+ elseif sz == "w" then wputwarg(n)
+ elseif sz == "b" then wputbarg(n)
+ elseif sz == "s" then wputsbarg(n)
+ else werror("bad operand size") end
+end
+
+-- Put multi-byte opcode with operand-size dependent modifications.
+local function wputop(sz, op, rex, vex, vregr, vregxb)
+ local psz, sk = 0, nil
+ if vex then
+ local tail
+ if vex.m == 1 and band(rex, 11) == 0 then
+ if x64 and vregxb then
+ sk = map_vreg["modrm.reg"]
+ else
+ wputb(0xc5)
+ tail = shl(bxor(band(rex, 4), 4), 5)
+ psz = 3
+ end
+ end
+ if not tail then
+ wputb(0xc4)
+ wputb(shl(bxor(band(rex, 7), 7), 5) + vex.m)
+ tail = shl(band(rex, 8), 4)
+ psz = 4
+ end
+ local reg, vreg = 0, nil
+ if vex.v then
+ reg = vex.v.reg
+ if not reg then werror("bad vex operand") end
+ if reg < 0 then reg = 0; vreg = vex.v.vreg end
+ end
+ if sz == "y" or vex.l then tail = tail + 4 end
+ wputb(tail + shl(bxor(reg, 15), 3) + vex.p)
+ wvreg("vex.v", vreg)
+ rex = 0
+ if op >= 256 then werror("bad vex opcode") end
+ else
+ if rex ~= 0 then
+ if not x64 then werror("bad operand size") end
+ elseif (vregr or vregxb) and x64 then
+ rex = 0x10
+ sk = map_vreg["vex.v"]
+ end
+ end
+ local r
+ if sz == "w" then wputb(102) end
+ -- Needs >32 bit numbers, but only for crc32 eax, word [ebx]
+ if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end
+ if op >= 16777216 then wputb(shr(op, 24)); op = band(op, 0xffffff) end
+ if op >= 65536 then
+ if rex ~= 0 then
+ local opc3 = band(op, 0xffff00)
+ if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then
+ wputb(64 + band(rex, 15)); rex = 0; psz = 2
+ end
+ end
+ wputb(shr(op, 16)); op = band(op, 0xffff); psz = psz + 1
+ end
+ if op >= 256 then
+ local b = shr(op, 8)
+ if b == 15 and rex ~= 0 then wputb(64 + band(rex, 15)); rex = 0; psz = 2 end
+ wputb(b); op = band(op, 255); psz = psz + 1
+ end
+ if rex ~= 0 then wputb(64 + band(rex, 15)); psz = 2 end
+ if sz == "b" then op = op - 1 end
+ wputb(op)
+ return psz, sk
+end
+
+-- Put ModRM or SIB formatted byte.
+local function wputmodrm(m, s, rm, vs, vrm)
+ assert(m < 4 and s < 16 and rm < 16, "bad modrm operands")
+ wputb(shl(m, 6) + shl(band(s, 7), 3) + band(rm, 7))
+end
+
+-- Put ModRM/SIB plus optional displacement.
+local function wputmrmsib(t, imark, s, vsreg, psz, sk)
+ local vreg, vxreg
+ local reg, xreg = t.reg, t.xreg
+ if reg and reg < 0 then reg = 0; vreg = t.vreg end
+ if xreg and xreg < 0 then xreg = 0; vxreg = t.vxreg end
+ if s < 0 then s = 0 end
+
+ -- Register mode.
+ if sub(t.mode, 1, 1) == "r" then
+ wputmodrm(3, s, reg)
+ wvreg("modrm.reg", vsreg, psz+1, sk, vreg)
+ wvreg("modrm.rm.r", vreg, psz+1, sk)
+ return
+ end
+
+ local disp = t.disp
+ local tdisp = type(disp)
+ -- No base register?
+ if not reg then
+ local riprel = false
+ if xreg then
+ -- Indexed mode with index register only.
+ -- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp)
+ wputmodrm(0, s, 4)
+ if imark == "I" then waction("MARK") end
+ wvreg("modrm.reg", vsreg, psz+1, sk, vxreg)
+ wputmodrm(t.xsc, xreg, 5)
+ wvreg("sib.index", vxreg, psz+2, sk)
+ else
+ -- Pure 32 bit displacement.
+ if x64 and tdisp ~= "table" then
+ wputmodrm(0, s, 4) -- [disp] -> (0, s, esp) (0, esp, ebp)
+ wvreg("modrm.reg", vsreg, psz+1, sk)
+ if imark == "I" then waction("MARK") end
+ wputmodrm(0, 4, 5)
+ else
+ riprel = x64
+ wputmodrm(0, s, 5) -- [disp|rip-label] -> (0, s, ebp)
+ wvreg("modrm.reg", vsreg, psz+1, sk)
+ if imark == "I" then waction("MARK") end
+ end
+ end
+ if riprel then -- Emit rip-relative displacement.
+ if match("UWSiI", imark) then
+ werror("NYI: rip-relative displacement followed by immediate")
+ end
+ -- The previous byte in the action buffer cannot be 0xe9 or 0x80-0x8f.
+ if disp[2] == "iPJ" then
+ waction("REL_A", disp[1])
+ else
+ wputlabel("REL_", disp[1], 2)
+ end
+ else
+ wputdarg(disp)
+ end
+ return
+ end
+
+ local m
+ if tdisp == "number" then -- Check displacement size at assembly time.
+ if disp == 0 and band(reg, 7) ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too)
+ if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0]
+ elseif disp >= -128 and disp <= 127 then m = 1
+ else m = 2 end
+ elseif tdisp == "table" then
+ m = 2
+ end
+
+ -- Index register present or esp as base register: need SIB encoding.
+ if xreg or band(reg, 7) == 4 then
+ wputmodrm(m or 2, s, 4) -- ModRM.
+ if m == nil or imark == "I" then waction("MARK") end
+ wvreg("modrm.reg", vsreg, psz+1, sk, vxreg or vreg)
+ wputmodrm(t.xsc or 0, xreg or 4, reg) -- SIB.
+ wvreg("sib.index", vxreg, psz+2, sk, vreg)
+ wvreg("sib.base", vreg, psz+2, sk)
+ else
+ wputmodrm(m or 2, s, reg) -- ModRM.
+ if (imark == "I" and (m == 1 or m == 2)) or
+ (m == nil and (vsreg or vreg)) then waction("MARK") end
+ wvreg("modrm.reg", vsreg, psz+1, sk, vreg)
+ wvreg("modrm.rm.m", vreg, psz+1, sk)
+ end
+
+ -- Put displacement.
+ if m == 1 then wputsbarg(disp)
+ elseif m == 2 then wputdarg(disp)
+ elseif m == nil then waction("DISP", disp) end
+end
+
+------------------------------------------------------------------------------
+
+-- Return human-readable operand mode string.
+local function opmodestr(op, args)
+ local m = {}
+ for i=1,#args do
+ local a = args[i]
+ m[#m+1] = sub(a.mode, 1, 1)..(a.opsize or "?")
+ end
+ return op.." "..concat(m, ",")
+end
+
+-- Convert number to valid integer or nil.
+local function toint(expr, isqword)
+ local n = tonumber(expr)
+ if n then
+ if n % 1 ~= 0 then
+ werror("not an integer number `"..expr.."'")
+ elseif isqword then
+ if n < -2147483648 or n > 2147483647 then
+ n = nil -- Handle it as an expression to avoid precision loss.
+ end
+ elseif n < -2147483648 or n > 4294967295 then
+ werror("bad integer number `"..expr.."'")
+ end
+ return n
+ end
+end
+
+-- Parse immediate expression.
+local function immexpr(expr)
+ -- &expr (pointer)
+ if sub(expr, 1, 1) == "&" then
+ return "iPJ", format("(ptrdiff_t)(%s)", sub(expr,2))
+ end
+
+ local prefix = sub(expr, 1, 2)
+ -- =>expr (pc label reference)
+ if prefix == "=>" then
+ return "iJ", sub(expr, 3)
+ end
+ -- ->name (global label reference)
+ if prefix == "->" then
+ return "iJ", map_global[sub(expr, 3)]
+ end
+
+ -- [<>][1-9] (local label reference)
+ local dir, lnum = match(expr, "^([<>])([1-9])$")
+ if dir then -- Fwd: 247-255, Bkwd: 1-9.
+ return "iJ", lnum + (dir == ">" and 246 or 0)
+ end
+
+ local extname = match(expr, "^extern%s+(%S+)$")
+ if extname then
+ return "iJ", map_extern[extname]
+ end
+
+ -- expr (interpreted as immediate)
+ return "iI", expr
+end
+
+-- Parse displacement expression: +-num, +-expr, +-opsize*num
+local function dispexpr(expr)
+ local disp = expr == "" and 0 or toint(expr)
+ if disp then return disp end
+ local c, dispt = match(expr, "^([+-])%s*(.+)$")
+ if c == "+" then
+ expr = dispt
+ elseif not c then
+ werror("bad displacement expression `"..expr.."'")
+ end
+ local opsize, tailops = match(dispt, "^(%w+)%s*%*%s*(.+)$")
+ local ops, imm = map_opsize[opsize], toint(tailops)
+ if ops and imm then
+ if c == "-" then imm = -imm end
+ return imm*map_opsizenum[ops]
+ end
+ local mode, iexpr = immexpr(dispt)
+ if mode == "iJ" or mode == "iPJ" then
+ if c == "-" then werror("cannot invert label reference") end
+ return { iexpr, mode }
+ end
+ return expr -- Need to return original signed expression.
+end
+
+-- Parse register or type expression.
+local function rtexpr(expr)
+ if not expr then return end
+ local tname, ovreg = match(expr, "^([%w_]+):(@[%w_]+)$")
+ local tp = map_type[tname or expr]
+ if tp then
+ local reg = ovreg or tp.reg
+ local rnum = map_reg_num[reg]
+ if not rnum then
+ werror("type `"..(tname or expr).."' needs a register override")
+ end
+ if not map_reg_valid_base[reg] then
+ werror("bad base register override `"..(map_reg_rev[reg] or reg).."'")
+ end
+ return reg, rnum, tp
+ end
+ return expr, map_reg_num[expr]
+end
+
+-- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }.
+local function parseoperand(param, isqword)
+ local t = {}
+
+ local expr = param
+ local opsize, tailops = match(param, "^(%w+)%s*(.+)$")
+ if opsize then
+ t.opsize = map_opsize[opsize]
+ if t.opsize then expr = tailops end
+ end
+
+ local br = match(expr, "^%[%s*(.-)%s*%]$")
+ repeat
+ if br then
+ t.mode = "xm"
+
+ -- [disp]
+ t.disp = toint(br)
+ if t.disp then
+ t.mode = x64 and "xm" or "xmO"
+ break
+ end
+
+ -- [reg...]
+ local tp
+ local reg, tailr = match(br, "^([@%w_:]+)%s*(.*)$")
+ reg, t.reg, tp = rtexpr(reg)
+ if not t.reg then
+ -- [expr]
+ t.mode = x64 and "xm" or "xmO"
+ t.disp = dispexpr("+"..br)
+ break
+ end
+
+ if t.reg == -1 then
+ t.vreg, tailr = match(tailr, "^(%b())(.*)$")
+ if not t.vreg then werror("bad variable register expression") end
+ end
+
+ -- [xreg*xsc] or [xreg*xsc+-disp] or [xreg*xsc+-expr]
+ local xsc, tailsc = match(tailr, "^%*%s*([1248])%s*(.*)$")
+ if xsc then
+ if not map_reg_valid_index[reg] then
+ werror("bad index register `"..map_reg_rev[reg].."'")
+ end
+ t.xsc = map_xsc[xsc]
+ t.xreg = t.reg
+ t.vxreg = t.vreg
+ t.reg = nil
+ t.vreg = nil
+ t.disp = dispexpr(tailsc)
+ break
+ end
+ if not map_reg_valid_base[reg] then
+ werror("bad base register `"..map_reg_rev[reg].."'")
+ end
+
+ -- [reg] or [reg+-disp]
+ t.disp = toint(tailr) or (tailr == "" and 0)
+ if t.disp then break end
+
+ -- [reg+xreg...]
+ local xreg, tailx = match(tailr, "^%+%s*([@%w_:]+)%s*(.*)$")
+ xreg, t.xreg, tp = rtexpr(xreg)
+ if not t.xreg then
+ -- [reg+-expr]
+ t.disp = dispexpr(tailr)
+ break
+ end
+ if not map_reg_valid_index[xreg] then
+ werror("bad index register `"..map_reg_rev[xreg].."'")
+ end
+
+ if t.xreg == -1 then
+ t.vxreg, tailx = match(tailx, "^(%b())(.*)$")
+ if not t.vxreg then werror("bad variable register expression") end
+ end
+
+ -- [reg+xreg*xsc...]
+ local xsc, tailsc = match(tailx, "^%*%s*([1248])%s*(.*)$")
+ if xsc then
+ t.xsc = map_xsc[xsc]
+ tailx = tailsc
+ end
+
+ -- [...] or [...+-disp] or [...+-expr]
+ t.disp = dispexpr(tailx)
+ else
+ -- imm or opsize*imm
+ local imm = toint(expr, isqword)
+ if not imm and sub(expr, 1, 1) == "*" and t.opsize then
+ imm = toint(sub(expr, 2))
+ if imm then
+ imm = imm * map_opsizenum[t.opsize]
+ t.opsize = nil
+ end
+ end
+ if imm then
+ if t.opsize then werror("bad operand size override") end
+ local m = "i"
+ if imm == 1 then m = m.."1" end
+ if imm >= 4294967168 and imm <= 4294967295 then imm = imm-4294967296 end
+ if imm >= -128 and imm <= 127 then m = m.."S" end
+ t.imm = imm
+ t.mode = m
+ break
+ end
+
+ local tp
+ local reg, tailr = match(expr, "^([@%w_:]+)%s*(.*)$")
+ reg, t.reg, tp = rtexpr(reg)
+ if t.reg then
+ if t.reg == -1 then
+ t.vreg, tailr = match(tailr, "^(%b())(.*)$")
+ if not t.vreg then werror("bad variable register expression") end
+ end
+ -- reg
+ if tailr == "" then
+ if t.opsize then werror("bad operand size override") end
+ t.opsize = map_reg_opsize[reg]
+ if t.opsize == "f" then
+ t.mode = t.reg == 0 and "fF" or "f"
+ else
+ if reg == "@w4" or (x64 and reg == "@d4") then
+ wwarn("bad idea, try again with `"..(x64 and "rsp'" or "esp'"))
+ end
+ t.mode = t.reg == 0 and "rmR" or (reg == "@b1" and "rmC" or "rm")
+ end
+ t.needrex = map_reg_needrex[reg]
+ break
+ end
+
+ -- type[idx], type[idx].field, type->field -> [reg+offset_expr]
+ if not tp then werror("bad operand `"..param.."'") end
+ t.mode = "xm"
+ t.disp = format(tp.ctypefmt, tailr)
+ else
+ t.mode, t.imm = immexpr(expr)
+ if sub(t.mode, -1) == "J" then
+ if t.opsize and t.opsize ~= addrsize then
+ werror("bad operand size override")
+ end
+ t.opsize = addrsize
+ end
+ end
+ end
+ until true
+ return t
+end
+
+------------------------------------------------------------------------------
+-- x86 Template String Description
+-- ===============================
+--
+-- Each template string is a list of [match:]pattern pairs,
+-- separated by "|". The first match wins. No match means a
+-- bad or unsupported combination of operand modes or sizes.
+--
+-- The match part and the ":" is omitted if the operation has
+-- no operands. Otherwise the first N characters are matched
+-- against the mode strings of each of the N operands.
+--
+-- The mode string for each operand type is (see parseoperand()):
+-- Integer register: "rm", +"R" for eax, ax, al, +"C" for cl
+-- FP register: "f", +"F" for st0
+-- Index operand: "xm", +"O" for [disp] (pure offset)
+-- Immediate: "i", +"S" for signed 8 bit, +"1" for 1,
+-- +"I" for arg, +"P" for pointer
+-- Any: +"J" for valid jump targets
+--
+-- So a match character "m" (mixed) matches both an integer register
+-- and an index operand (to be encoded with the ModRM/SIB scheme).
+-- But "r" matches only a register and "x" only an index operand
+-- (e.g. for FP memory access operations).
+--
+-- The operand size match string starts right after the mode match
+-- characters and ends before the ":". "dwb" or "qdwb" is assumed, if empty.
+-- The effective data size of the operation is matched against this list.
+--
+-- If only the regular "b", "w", "d", "q", "t" operand sizes are
+-- present, then all operands must be the same size. Unspecified sizes
+-- are ignored, but at least one operand must have a size or the pattern
+-- won't match (use the "byte", "word", "dword", "qword", "tword"
+-- operand size overrides. E.g.: mov dword [eax], 1).
+--
+-- If the list has a "1" or "2" prefix, the operand size is taken
+-- from the respective operand and any other operand sizes are ignored.
+-- If the list contains only ".", all operand sizes are ignored.
+-- If the list has a "/" prefix, the concatenated (mixed) operand sizes
+-- are compared to the match.
+--
+-- E.g. "rrdw" matches for either two dword registers or two word
+-- registers. "Fx2dq" matches an st0 operand plus an index operand
+-- pointing to a dword (float) or qword (double).
+--
+-- Every character after the ":" is part of the pattern string:
+-- Hex chars are accumulated to form the opcode (left to right).
+-- "n" disables the standard opcode mods
+-- (otherwise: -1 for "b", o16 prefix for "w", rex.w for "q")
+-- "X" Force REX.W.
+-- "r"/"R" adds the reg. number from the 1st/2nd operand to the opcode.
+-- "m"/"M" generates ModRM/SIB from the 1st/2nd operand.
+-- The spare 3 bits are either filled with the last hex digit or
+-- the result from a previous "r"/"R". The opcode is restored.
+-- "u" Use VEX encoding, vvvv unused.
+-- "v"/"V" Use VEX encoding, vvvv from 1st/2nd operand (the operand is
+-- removed from the list used by future characters).
+-- "w" Use VEX encoding, vvvv from 3rd operand.
+-- "L" Force VEX.L
+--
+-- All of the following characters force a flush of the opcode:
+-- "o"/"O" stores a pure 32 bit disp (offset) from the 1st/2nd operand.
+-- "s" stores a 4 bit immediate from the last register operand,
+-- followed by 4 zero bits.
+-- "S" stores a signed 8 bit immediate from the last operand.
+-- "U" stores an unsigned 8 bit immediate from the last operand.
+-- "W" stores an unsigned 16 bit immediate from the last operand.
+-- "i" stores an operand sized immediate from the last operand.
+-- "I" dito, but generates an action code to optionally modify
+-- the opcode (+2) for a signed 8 bit immediate.
+-- "J" generates one of the REL action codes from the last operand.
+--
+------------------------------------------------------------------------------
+
+-- Template strings for x86 instructions. Ordered by first opcode byte.
+-- Unimplemented opcodes (deliberate omissions) are marked with *.
+local map_op = {
+ -- 00-05: add...
+ -- 06: *push es
+ -- 07: *pop es
+ -- 08-0D: or...
+ -- 0E: *push cs
+ -- 0F: two byte opcode prefix
+ -- 10-15: adc...
+ -- 16: *push ss
+ -- 17: *pop ss
+ -- 18-1D: sbb...
+ -- 1E: *push ds
+ -- 1F: *pop ds
+ -- 20-25: and...
+ es_0 = "26",
+ -- 27: *daa
+ -- 28-2D: sub...
+ cs_0 = "2E",
+ -- 2F: *das
+ -- 30-35: xor...
+ ss_0 = "36",
+ -- 37: *aaa
+ -- 38-3D: cmp...
+ ds_0 = "3E",
+ -- 3F: *aas
+ inc_1 = x64 and "m:FF0m" or "rdw:40r|m:FF0m",
+ dec_1 = x64 and "m:FF1m" or "rdw:48r|m:FF1m",
+ push_1 = (x64 and "rq:n50r|rw:50r|mq:nFF6m|mw:FF6m" or
+ "rdw:50r|mdw:FF6m").."|S.:6AS|ib:n6Ai|i.:68i",
+ pop_1 = x64 and "rq:n58r|rw:58r|mq:n8F0m|mw:8F0m" or "rdw:58r|mdw:8F0m",
+ -- 60: *pusha, *pushad, *pushaw
+ -- 61: *popa, *popad, *popaw
+ -- 62: *bound rdw,x
+ -- 63: x86: *arpl mw,rw
+ movsxd_2 = x64 and "rm/qd:63rM",
+ fs_0 = "64",
+ gs_0 = "65",
+ o16_0 = "66",
+ a16_0 = not x64 and "67" or nil,
+ a32_0 = x64 and "67",
+ -- 68: push idw
+ -- 69: imul rdw,mdw,idw
+ -- 6A: push ib
+ -- 6B: imul rdw,mdw,S
+ -- 6C: *insb
+ -- 6D: *insd, *insw
+ -- 6E: *outsb
+ -- 6F: *outsd, *outsw
+ -- 70-7F: jcc lb
+ -- 80: add... mb,i
+ -- 81: add... mdw,i
+ -- 82: *undefined
+ -- 83: add... mdw,S
+ test_2 = "mr:85Rm|rm:85rM|Ri:A9ri|mi:F70mi",
+ -- 86: xchg rb,mb
+ -- 87: xchg rdw,mdw
+ -- 88: mov mb,r
+ -- 89: mov mdw,r
+ -- 8A: mov r,mb
+ -- 8B: mov r,mdw
+ -- 8C: *mov mdw,seg
+ lea_2 = "rx1dq:8DrM",
+ -- 8E: *mov seg,mdw
+ -- 8F: pop mdw
+ nop_0 = "90",
+ xchg_2 = "Rrqdw:90R|rRqdw:90r|rm:87rM|mr:87Rm",
+ cbw_0 = "6698",
+ cwde_0 = "98",
+ cdqe_0 = "4898",
+ cwd_0 = "6699",
+ cdq_0 = "99",
+ cqo_0 = "4899",
+ -- 9A: *call iw:idw
+ wait_0 = "9B",
+ fwait_0 = "9B",
+ pushf_0 = "9C",
+ pushfd_0 = not x64 and "9C",
+ pushfq_0 = x64 and "9C",
+ popf_0 = "9D",
+ popfd_0 = not x64 and "9D",
+ popfq_0 = x64 and "9D",
+ sahf_0 = "9E",
+ lahf_0 = "9F",
+ mov_2 = "OR:A3o|RO:A1O|mr:89Rm|rm:8BrM|rib:nB0ri|ridw:B8ri|mi:C70mi",
+ movsb_0 = "A4",
+ movsw_0 = "66A5",
+ movsd_0 = "A5",
+ cmpsb_0 = "A6",
+ cmpsw_0 = "66A7",
+ cmpsd_0 = "A7",
+ -- A8: test Rb,i
+ -- A9: test Rdw,i
+ stosb_0 = "AA",
+ stosw_0 = "66AB",
+ stosd_0 = "AB",
+ lodsb_0 = "AC",
+ lodsw_0 = "66AD",
+ lodsd_0 = "AD",
+ scasb_0 = "AE",
+ scasw_0 = "66AF",
+ scasd_0 = "AF",
+ -- B0-B7: mov rb,i
+ -- B8-BF: mov rdw,i
+ -- C0: rol... mb,i
+ -- C1: rol... mdw,i
+ ret_1 = "i.:nC2W",
+ ret_0 = "C3",
+ -- C4: *les rdw,mq
+ -- C5: *lds rdw,mq
+ -- C6: mov mb,i
+ -- C7: mov mdw,i
+ -- C8: *enter iw,ib
+ leave_0 = "C9",
+ -- CA: *retf iw
+ -- CB: *retf
+ int3_0 = "CC",
+ int_1 = "i.:nCDU",
+ into_0 = "CE",
+ -- CF: *iret
+ -- D0: rol... mb,1
+ -- D1: rol... mdw,1
+ -- D2: rol... mb,cl
+ -- D3: rol... mb,cl
+ -- D4: *aam ib
+ -- D5: *aad ib
+ -- D6: *salc
+ -- D7: *xlat
+ -- D8-DF: floating point ops
+ -- E0: *loopne
+ -- E1: *loope
+ -- E2: *loop
+ -- E3: *jcxz, *jecxz
+ -- E4: *in Rb,ib
+ -- E5: *in Rdw,ib
+ -- E6: *out ib,Rb
+ -- E7: *out ib,Rdw
+ call_1 = x64 and "mq:nFF2m|J.:E8nJ" or "md:FF2m|J.:E8J",
+ jmp_1 = x64 and "mq:nFF4m|J.:E9nJ" or "md:FF4m|J.:E9J", -- short: EB
+ -- EA: *jmp iw:idw
+ -- EB: jmp ib
+ -- EC: *in Rb,dx
+ -- ED: *in Rdw,dx
+ -- EE: *out dx,Rb
+ -- EF: *out dx,Rdw
+ lock_0 = "F0",
+ int1_0 = "F1",
+ repne_0 = "F2",
+ repnz_0 = "F2",
+ rep_0 = "F3",
+ repe_0 = "F3",
+ repz_0 = "F3",
+ endbr32_0 = "F30F1EFB",
+ endbr64_0 = "F30F1EFA",
+ -- F4: *hlt
+ cmc_0 = "F5",
+ -- F6: test... mb,i; div... mb
+ -- F7: test... mdw,i; div... mdw
+ clc_0 = "F8",
+ stc_0 = "F9",
+ -- FA: *cli
+ cld_0 = "FC",
+ std_0 = "FD",
+ -- FE: inc... mb
+ -- FF: inc... mdw
+
+ -- misc ops
+ not_1 = "m:F72m",
+ neg_1 = "m:F73m",
+ mul_1 = "m:F74m",
+ imul_1 = "m:F75m",
+ div_1 = "m:F76m",
+ idiv_1 = "m:F77m",
+
+ imul_2 = "rmqdw:0FAFrM|rIqdw:69rmI|rSqdw:6BrmS|riqdw:69rmi",
+ imul_3 = "rmIqdw:69rMI|rmSqdw:6BrMS|rmiqdw:69rMi",
+
+ movzx_2 = "rm/db:0FB6rM|rm/qb:|rm/wb:0FB6rM|rm/dw:0FB7rM|rm/qw:",
+ movsx_2 = "rm/db:0FBErM|rm/qb:|rm/wb:0FBErM|rm/dw:0FBFrM|rm/qw:",
+
+ bswap_1 = "rqd:0FC8r",
+ bsf_2 = "rmqdw:0FBCrM",
+ bsr_2 = "rmqdw:0FBDrM",
+ bt_2 = "mrqdw:0FA3Rm|miqdw:0FBA4mU",
+ btc_2 = "mrqdw:0FBBRm|miqdw:0FBA7mU",
+ btr_2 = "mrqdw:0FB3Rm|miqdw:0FBA6mU",
+ bts_2 = "mrqdw:0FABRm|miqdw:0FBA5mU",
+
+ shld_3 = "mriqdw:0FA4RmU|mrC/qq:0FA5Rm|mrC/dd:|mrC/ww:",
+ shrd_3 = "mriqdw:0FACRmU|mrC/qq:0FADRm|mrC/dd:|mrC/ww:",
+
+ rdtsc_0 = "0F31", -- P1+
+ rdpmc_0 = "0F33", -- P6+
+ cpuid_0 = "0FA2", -- P1+
+
+ -- floating point ops
+ fst_1 = "ff:DDD0r|xd:D92m|xq:nDD2m",
+ fstp_1 = "ff:DDD8r|xd:D93m|xq:nDD3m|xt:DB7m",
+ fld_1 = "ff:D9C0r|xd:D90m|xq:nDD0m|xt:DB5m",
+
+ fpop_0 = "DDD8", -- Alias for fstp st0.
+
+ fist_1 = "xw:nDF2m|xd:DB2m",
+ fistp_1 = "xw:nDF3m|xd:DB3m|xq:nDF7m",
+ fild_1 = "xw:nDF0m|xd:DB0m|xq:nDF5m",
+
+ fxch_0 = "D9C9",
+ fxch_1 = "ff:D9C8r",
+ fxch_2 = "fFf:D9C8r|Fff:D9C8R",
+
+ fucom_1 = "ff:DDE0r",
+ fucom_2 = "Fff:DDE0R",
+ fucomp_1 = "ff:DDE8r",
+ fucomp_2 = "Fff:DDE8R",
+ fucomi_1 = "ff:DBE8r", -- P6+
+ fucomi_2 = "Fff:DBE8R", -- P6+
+ fucomip_1 = "ff:DFE8r", -- P6+
+ fucomip_2 = "Fff:DFE8R", -- P6+
+ fcomi_1 = "ff:DBF0r", -- P6+
+ fcomi_2 = "Fff:DBF0R", -- P6+
+ fcomip_1 = "ff:DFF0r", -- P6+
+ fcomip_2 = "Fff:DFF0R", -- P6+
+ fucompp_0 = "DAE9",
+ fcompp_0 = "DED9",
+
+ fldenv_1 = "x.:D94m",
+ fnstenv_1 = "x.:D96m",
+ fstenv_1 = "x.:9BD96m",
+ fldcw_1 = "xw:nD95m",
+ fstcw_1 = "xw:n9BD97m",
+ fnstcw_1 = "xw:nD97m",
+ fstsw_1 = "Rw:n9BDFE0|xw:n9BDD7m",
+ fnstsw_1 = "Rw:nDFE0|xw:nDD7m",
+ fclex_0 = "9BDBE2",
+ fnclex_0 = "DBE2",
+
+ fnop_0 = "D9D0",
+ -- D9D1-D9DF: unassigned
+
+ fchs_0 = "D9E0",
+ fabs_0 = "D9E1",
+ -- D9E2: unassigned
+ -- D9E3: unassigned
+ ftst_0 = "D9E4",
+ fxam_0 = "D9E5",
+ -- D9E6: unassigned
+ -- D9E7: unassigned
+ fld1_0 = "D9E8",
+ fldl2t_0 = "D9E9",
+ fldl2e_0 = "D9EA",
+ fldpi_0 = "D9EB",
+ fldlg2_0 = "D9EC",
+ fldln2_0 = "D9ED",
+ fldz_0 = "D9EE",
+ -- D9EF: unassigned
+
+ f2xm1_0 = "D9F0",
+ fyl2x_0 = "D9F1",
+ fptan_0 = "D9F2",
+ fpatan_0 = "D9F3",
+ fxtract_0 = "D9F4",
+ fprem1_0 = "D9F5",
+ fdecstp_0 = "D9F6",
+ fincstp_0 = "D9F7",
+ fprem_0 = "D9F8",
+ fyl2xp1_0 = "D9F9",
+ fsqrt_0 = "D9FA",
+ fsincos_0 = "D9FB",
+ frndint_0 = "D9FC",
+ fscale_0 = "D9FD",
+ fsin_0 = "D9FE",
+ fcos_0 = "D9FF",
+
+ -- SSE, SSE2
+ andnpd_2 = "rmo:660F55rM",
+ andnps_2 = "rmo:0F55rM",
+ andpd_2 = "rmo:660F54rM",
+ andps_2 = "rmo:0F54rM",
+ clflush_1 = "x.:0FAE7m",
+ cmppd_3 = "rmio:660FC2rMU",
+ cmpps_3 = "rmio:0FC2rMU",
+ cmpsd_3 = "rrio:F20FC2rMU|rxi/oq:",
+ cmpss_3 = "rrio:F30FC2rMU|rxi/od:",
+ comisd_2 = "rro:660F2FrM|rx/oq:",
+ comiss_2 = "rro:0F2FrM|rx/od:",
+ cvtdq2pd_2 = "rro:F30FE6rM|rx/oq:",
+ cvtdq2ps_2 = "rmo:0F5BrM",
+ cvtpd2dq_2 = "rmo:F20FE6rM",
+ cvtpd2ps_2 = "rmo:660F5ArM",
+ cvtpi2pd_2 = "rx/oq:660F2ArM",
+ cvtpi2ps_2 = "rx/oq:0F2ArM",
+ cvtps2dq_2 = "rmo:660F5BrM",
+ cvtps2pd_2 = "rro:0F5ArM|rx/oq:",
+ cvtsd2si_2 = "rr/do:F20F2DrM|rr/qo:|rx/dq:|rxq:",
+ cvtsd2ss_2 = "rro:F20F5ArM|rx/oq:",
+ cvtsi2sd_2 = "rm/od:F20F2ArM|rm/oq:F20F2ArXM",
+ cvtsi2ss_2 = "rm/od:F30F2ArM|rm/oq:F30F2ArXM",
+ cvtss2sd_2 = "rro:F30F5ArM|rx/od:",
+ cvtss2si_2 = "rr/do:F30F2DrM|rr/qo:|rxd:|rx/qd:",
+ cvttpd2dq_2 = "rmo:660FE6rM",
+ cvttps2dq_2 = "rmo:F30F5BrM",
+ cvttsd2si_2 = "rr/do:F20F2CrM|rr/qo:|rx/dq:|rxq:",
+ cvttss2si_2 = "rr/do:F30F2CrM|rr/qo:|rxd:|rx/qd:",
+ fxsave_1 = "x.:0FAE0m",
+ fxrstor_1 = "x.:0FAE1m",
+ ldmxcsr_1 = "xd:0FAE2m",
+ lfence_0 = "0FAEE8",
+ maskmovdqu_2 = "rro:660FF7rM",
+ mfence_0 = "0FAEF0",
+ movapd_2 = "rmo:660F28rM|mro:660F29Rm",
+ movaps_2 = "rmo:0F28rM|mro:0F29Rm",
+ movd_2 = "rm/od:660F6ErM|rm/oq:660F6ErXM|mr/do:660F7ERm|mr/qo:",
+ movdqa_2 = "rmo:660F6FrM|mro:660F7FRm",
+ movdqu_2 = "rmo:F30F6FrM|mro:F30F7FRm",
+ movhlps_2 = "rro:0F12rM",
+ movhpd_2 = "rx/oq:660F16rM|xr/qo:n660F17Rm",
+ movhps_2 = "rx/oq:0F16rM|xr/qo:n0F17Rm",
+ movlhps_2 = "rro:0F16rM",
+ movlpd_2 = "rx/oq:660F12rM|xr/qo:n660F13Rm",
+ movlps_2 = "rx/oq:0F12rM|xr/qo:n0F13Rm",
+ movmskpd_2 = "rr/do:660F50rM",
+ movmskps_2 = "rr/do:0F50rM",
+ movntdq_2 = "xro:660FE7Rm",
+ movnti_2 = "xrqd:0FC3Rm",
+ movntpd_2 = "xro:660F2BRm",
+ movntps_2 = "xro:0F2BRm",
+ movq_2 = "rro:F30F7ErM|rx/oq:|xr/qo:n660FD6Rm",
+ movsd_2 = "rro:F20F10rM|rx/oq:|xr/qo:nF20F11Rm",
+ movss_2 = "rro:F30F10rM|rx/od:|xr/do:F30F11Rm",
+ movupd_2 = "rmo:660F10rM|mro:660F11Rm",
+ movups_2 = "rmo:0F10rM|mro:0F11Rm",
+ orpd_2 = "rmo:660F56rM",
+ orps_2 = "rmo:0F56rM",
+ pause_0 = "F390",
+ pextrw_3 = "rri/do:660FC5rMU|xri/wo:660F3A15nRmU", -- Mem op: SSE4.1 only.
+ pinsrw_3 = "rri/od:660FC4rMU|rxi/ow:",
+ pmovmskb_2 = "rr/do:660FD7rM",
+ prefetchnta_1 = "xb:n0F180m",
+ prefetcht0_1 = "xb:n0F181m",
+ prefetcht1_1 = "xb:n0F182m",
+ prefetcht2_1 = "xb:n0F183m",
+ pshufd_3 = "rmio:660F70rMU",
+ pshufhw_3 = "rmio:F30F70rMU",
+ pshuflw_3 = "rmio:F20F70rMU",
+ pslld_2 = "rmo:660FF2rM|rio:660F726mU",
+ pslldq_2 = "rio:660F737mU",
+ psllq_2 = "rmo:660FF3rM|rio:660F736mU",
+ psllw_2 = "rmo:660FF1rM|rio:660F716mU",
+ psrad_2 = "rmo:660FE2rM|rio:660F724mU",
+ psraw_2 = "rmo:660FE1rM|rio:660F714mU",
+ psrld_2 = "rmo:660FD2rM|rio:660F722mU",
+ psrldq_2 = "rio:660F733mU",
+ psrlq_2 = "rmo:660FD3rM|rio:660F732mU",
+ psrlw_2 = "rmo:660FD1rM|rio:660F712mU",
+ rcpps_2 = "rmo:0F53rM",
+ rcpss_2 = "rro:F30F53rM|rx/od:",
+ rsqrtps_2 = "rmo:0F52rM",
+ rsqrtss_2 = "rmo:F30F52rM",
+ sfence_0 = "0FAEF8",
+ shufpd_3 = "rmio:660FC6rMU",
+ shufps_3 = "rmio:0FC6rMU",
+ stmxcsr_1 = "xd:0FAE3m",
+ ucomisd_2 = "rro:660F2ErM|rx/oq:",
+ ucomiss_2 = "rro:0F2ErM|rx/od:",
+ unpckhpd_2 = "rmo:660F15rM",
+ unpckhps_2 = "rmo:0F15rM",
+ unpcklpd_2 = "rmo:660F14rM",
+ unpcklps_2 = "rmo:0F14rM",
+ xorpd_2 = "rmo:660F57rM",
+ xorps_2 = "rmo:0F57rM",
+
+ -- SSE3 ops
+ fisttp_1 = "xw:nDF1m|xd:DB1m|xq:nDD1m",
+ addsubpd_2 = "rmo:660FD0rM",
+ addsubps_2 = "rmo:F20FD0rM",
+ haddpd_2 = "rmo:660F7CrM",
+ haddps_2 = "rmo:F20F7CrM",
+ hsubpd_2 = "rmo:660F7DrM",
+ hsubps_2 = "rmo:F20F7DrM",
+ lddqu_2 = "rxo:F20FF0rM",
+ movddup_2 = "rmo:F20F12rM",
+ movshdup_2 = "rmo:F30F16rM",
+ movsldup_2 = "rmo:F30F12rM",
+
+ -- SSSE3 ops
+ pabsb_2 = "rmo:660F381CrM",
+ pabsd_2 = "rmo:660F381ErM",
+ pabsw_2 = "rmo:660F381DrM",
+ palignr_3 = "rmio:660F3A0FrMU",
+ phaddd_2 = "rmo:660F3802rM",
+ phaddsw_2 = "rmo:660F3803rM",
+ phaddw_2 = "rmo:660F3801rM",
+ phsubd_2 = "rmo:660F3806rM",
+ phsubsw_2 = "rmo:660F3807rM",
+ phsubw_2 = "rmo:660F3805rM",
+ pmaddubsw_2 = "rmo:660F3804rM",
+ pmulhrsw_2 = "rmo:660F380BrM",
+ pshufb_2 = "rmo:660F3800rM",
+ psignb_2 = "rmo:660F3808rM",
+ psignd_2 = "rmo:660F380ArM",
+ psignw_2 = "rmo:660F3809rM",
+
+ -- SSE4.1 ops
+ blendpd_3 = "rmio:660F3A0DrMU",
+ blendps_3 = "rmio:660F3A0CrMU",
+ blendvpd_3 = "rmRo:660F3815rM",
+ blendvps_3 = "rmRo:660F3814rM",
+ dppd_3 = "rmio:660F3A41rMU",
+ dpps_3 = "rmio:660F3A40rMU",
+ extractps_3 = "mri/do:660F3A17RmU|rri/qo:660F3A17RXmU",
+ insertps_3 = "rrio:660F3A41rMU|rxi/od:",
+ movntdqa_2 = "rxo:660F382ArM",
+ mpsadbw_3 = "rmio:660F3A42rMU",
+ packusdw_2 = "rmo:660F382BrM",
+ pblendvb_3 = "rmRo:660F3810rM",
+ pblendw_3 = "rmio:660F3A0ErMU",
+ pcmpeqq_2 = "rmo:660F3829rM",
+ pextrb_3 = "rri/do:660F3A14nRmU|rri/qo:|xri/bo:",
+ pextrd_3 = "mri/do:660F3A16RmU",
+ pextrq_3 = "mri/qo:660F3A16RmU",
+ -- pextrw is SSE2, mem operand is SSE4.1 only
+ phminposuw_2 = "rmo:660F3841rM",
+ pinsrb_3 = "rri/od:660F3A20nrMU|rxi/ob:",
+ pinsrd_3 = "rmi/od:660F3A22rMU",
+ pinsrq_3 = "rmi/oq:660F3A22rXMU",
+ pmaxsb_2 = "rmo:660F383CrM",
+ pmaxsd_2 = "rmo:660F383DrM",
+ pmaxud_2 = "rmo:660F383FrM",
+ pmaxuw_2 = "rmo:660F383ErM",
+ pminsb_2 = "rmo:660F3838rM",
+ pminsd_2 = "rmo:660F3839rM",
+ pminud_2 = "rmo:660F383BrM",
+ pminuw_2 = "rmo:660F383ArM",
+ pmovsxbd_2 = "rro:660F3821rM|rx/od:",
+ pmovsxbq_2 = "rro:660F3822rM|rx/ow:",
+ pmovsxbw_2 = "rro:660F3820rM|rx/oq:",
+ pmovsxdq_2 = "rro:660F3825rM|rx/oq:",
+ pmovsxwd_2 = "rro:660F3823rM|rx/oq:",
+ pmovsxwq_2 = "rro:660F3824rM|rx/od:",
+ pmovzxbd_2 = "rro:660F3831rM|rx/od:",
+ pmovzxbq_2 = "rro:660F3832rM|rx/ow:",
+ pmovzxbw_2 = "rro:660F3830rM|rx/oq:",
+ pmovzxdq_2 = "rro:660F3835rM|rx/oq:",
+ pmovzxwd_2 = "rro:660F3833rM|rx/oq:",
+ pmovzxwq_2 = "rro:660F3834rM|rx/od:",
+ pmuldq_2 = "rmo:660F3828rM",
+ pmulld_2 = "rmo:660F3840rM",
+ ptest_2 = "rmo:660F3817rM",
+ roundpd_3 = "rmio:660F3A09rMU",
+ roundps_3 = "rmio:660F3A08rMU",
+ roundsd_3 = "rrio:660F3A0BrMU|rxi/oq:",
+ roundss_3 = "rrio:660F3A0ArMU|rxi/od:",
+
+ -- SSE4.2 ops
+ crc32_2 = "rmqd:F20F38F1rM|rm/dw:66F20F38F1rM|rm/db:F20F38F0rM|rm/qb:",
+ pcmpestri_3 = "rmio:660F3A61rMU",
+ pcmpestrm_3 = "rmio:660F3A60rMU",
+ pcmpgtq_2 = "rmo:660F3837rM",
+ pcmpistri_3 = "rmio:660F3A63rMU",
+ pcmpistrm_3 = "rmio:660F3A62rMU",
+ popcnt_2 = "rmqdw:F30FB8rM",
+
+ -- SSE4a
+ extrq_2 = "rro:660F79rM",
+ extrq_3 = "riio:660F780mUU",
+ insertq_2 = "rro:F20F79rM",
+ insertq_4 = "rriio:F20F78rMUU",
+ lzcnt_2 = "rmqdw:F30FBDrM",
+ movntsd_2 = "xr/qo:nF20F2BRm",
+ movntss_2 = "xr/do:F30F2BRm",
+ -- popcnt is also in SSE4.2
+
+ -- AES-NI
+ aesdec_2 = "rmo:660F38DErM",
+ aesdeclast_2 = "rmo:660F38DFrM",
+ aesenc_2 = "rmo:660F38DCrM",
+ aesenclast_2 = "rmo:660F38DDrM",
+ aesimc_2 = "rmo:660F38DBrM",
+ aeskeygenassist_3 = "rmio:660F3ADFrMU",
+ pclmulqdq_3 = "rmio:660F3A44rMU",
+
+ -- AVX FP ops
+ vaddsubpd_3 = "rrmoy:660FVD0rM",
+ vaddsubps_3 = "rrmoy:F20FVD0rM",
+ vandpd_3 = "rrmoy:660FV54rM",
+ vandps_3 = "rrmoy:0FV54rM",
+ vandnpd_3 = "rrmoy:660FV55rM",
+ vandnps_3 = "rrmoy:0FV55rM",
+ vblendpd_4 = "rrmioy:660F3AV0DrMU",
+ vblendps_4 = "rrmioy:660F3AV0CrMU",
+ vblendvpd_4 = "rrmroy:660F3AV4BrMs",
+ vblendvps_4 = "rrmroy:660F3AV4ArMs",
+ vbroadcastf128_2 = "rx/yo:660F38u1ArM",
+ vcmppd_4 = "rrmioy:660FVC2rMU",
+ vcmpps_4 = "rrmioy:0FVC2rMU",
+ vcmpsd_4 = "rrrio:F20FVC2rMU|rrxi/ooq:",
+ vcmpss_4 = "rrrio:F30FVC2rMU|rrxi/ood:",
+ vcomisd_2 = "rro:660Fu2FrM|rx/oq:",
+ vcomiss_2 = "rro:0Fu2FrM|rx/od:",
+ vcvtdq2pd_2 = "rro:F30FuE6rM|rx/oq:|rm/yo:",
+ vcvtdq2ps_2 = "rmoy:0Fu5BrM",
+ vcvtpd2dq_2 = "rmoy:F20FuE6rM",
+ vcvtpd2ps_2 = "rmoy:660Fu5ArM",
+ vcvtps2dq_2 = "rmoy:660Fu5BrM",
+ vcvtps2pd_2 = "rro:0Fu5ArM|rx/oq:|rm/yo:",
+ vcvtsd2si_2 = "rr/do:F20Fu2DrM|rx/dq:|rr/qo:|rxq:",
+ vcvtsd2ss_3 = "rrro:F20FV5ArM|rrx/ooq:",
+ vcvtsi2sd_3 = "rrm/ood:F20FV2ArM|rrm/ooq:F20FVX2ArM",
+ vcvtsi2ss_3 = "rrm/ood:F30FV2ArM|rrm/ooq:F30FVX2ArM",
+ vcvtss2sd_3 = "rrro:F30FV5ArM|rrx/ood:",
+ vcvtss2si_2 = "rr/do:F30Fu2DrM|rxd:|rr/qo:|rx/qd:",
+ vcvttpd2dq_2 = "rmo:660FuE6rM|rm/oy:660FuLE6rM",
+ vcvttps2dq_2 = "rmoy:F30Fu5BrM",
+ vcvttsd2si_2 = "rr/do:F20Fu2CrM|rx/dq:|rr/qo:|rxq:",
+ vcvttss2si_2 = "rr/do:F30Fu2CrM|rxd:|rr/qo:|rx/qd:",
+ vdppd_4 = "rrmio:660F3AV41rMU",
+ vdpps_4 = "rrmioy:660F3AV40rMU",
+ vextractf128_3 = "mri/oy:660F3AuL19RmU",
+ vextractps_3 = "mri/do:660F3Au17RmU",
+ vhaddpd_3 = "rrmoy:660FV7CrM",
+ vhaddps_3 = "rrmoy:F20FV7CrM",
+ vhsubpd_3 = "rrmoy:660FV7DrM",
+ vhsubps_3 = "rrmoy:F20FV7DrM",
+ vinsertf128_4 = "rrmi/yyo:660F3AV18rMU",
+ vinsertps_4 = "rrrio:660F3AV21rMU|rrxi/ood:",
+ vldmxcsr_1 = "xd:0FuAE2m",
+ vmaskmovps_3 = "rrxoy:660F38V2CrM|xrroy:660F38V2ERm",
+ vmaskmovpd_3 = "rrxoy:660F38V2DrM|xrroy:660F38V2FRm",
+ vmovapd_2 = "rmoy:660Fu28rM|mroy:660Fu29Rm",
+ vmovaps_2 = "rmoy:0Fu28rM|mroy:0Fu29Rm",
+ vmovd_2 = "rm/od:660Fu6ErM|rm/oq:660FuX6ErM|mr/do:660Fu7ERm|mr/qo:",
+ vmovq_2 = "rro:F30Fu7ErM|rx/oq:|xr/qo:660FuD6Rm",
+ vmovddup_2 = "rmy:F20Fu12rM|rro:|rx/oq:",
+ vmovhlps_3 = "rrro:0FV12rM",
+ vmovhpd_2 = "xr/qo:660Fu17Rm",
+ vmovhpd_3 = "rrx/ooq:660FV16rM",
+ vmovhps_2 = "xr/qo:0Fu17Rm",
+ vmovhps_3 = "rrx/ooq:0FV16rM",
+ vmovlhps_3 = "rrro:0FV16rM",
+ vmovlpd_2 = "xr/qo:660Fu13Rm",
+ vmovlpd_3 = "rrx/ooq:660FV12rM",
+ vmovlps_2 = "xr/qo:0Fu13Rm",
+ vmovlps_3 = "rrx/ooq:0FV12rM",
+ vmovmskpd_2 = "rr/do:660Fu50rM|rr/dy:660FuL50rM",
+ vmovmskps_2 = "rr/do:0Fu50rM|rr/dy:0FuL50rM",
+ vmovntpd_2 = "xroy:660Fu2BRm",
+ vmovntps_2 = "xroy:0Fu2BRm",
+ vmovsd_2 = "rx/oq:F20Fu10rM|xr/qo:F20Fu11Rm",
+ vmovsd_3 = "rrro:F20FV10rM",
+ vmovshdup_2 = "rmoy:F30Fu16rM",
+ vmovsldup_2 = "rmoy:F30Fu12rM",
+ vmovss_2 = "rx/od:F30Fu10rM|xr/do:F30Fu11Rm",
+ vmovss_3 = "rrro:F30FV10rM",
+ vmovupd_2 = "rmoy:660Fu10rM|mroy:660Fu11Rm",
+ vmovups_2 = "rmoy:0Fu10rM|mroy:0Fu11Rm",
+ vorpd_3 = "rrmoy:660FV56rM",
+ vorps_3 = "rrmoy:0FV56rM",
+ vpermilpd_3 = "rrmoy:660F38V0DrM|rmioy:660F3Au05rMU",
+ vpermilps_3 = "rrmoy:660F38V0CrM|rmioy:660F3Au04rMU",
+ vperm2f128_4 = "rrmiy:660F3AV06rMU",
+ vptestpd_2 = "rmoy:660F38u0FrM",
+ vptestps_2 = "rmoy:660F38u0ErM",
+ vrcpps_2 = "rmoy:0Fu53rM",
+ vrcpss_3 = "rrro:F30FV53rM|rrx/ood:",
+ vrsqrtps_2 = "rmoy:0Fu52rM",
+ vrsqrtss_3 = "rrro:F30FV52rM|rrx/ood:",
+ vroundpd_3 = "rmioy:660F3Au09rMU",
+ vroundps_3 = "rmioy:660F3Au08rMU",
+ vroundsd_4 = "rrrio:660F3AV0BrMU|rrxi/ooq:",
+ vroundss_4 = "rrrio:660F3AV0ArMU|rrxi/ood:",
+ vshufpd_4 = "rrmioy:660FVC6rMU",
+ vshufps_4 = "rrmioy:0FVC6rMU",
+ vsqrtps_2 = "rmoy:0Fu51rM",
+ vsqrtss_2 = "rro:F30Fu51rM|rx/od:",
+ vsqrtpd_2 = "rmoy:660Fu51rM",
+ vsqrtsd_2 = "rro:F20Fu51rM|rx/oq:",
+ vstmxcsr_1 = "xd:0FuAE3m",
+ vucomisd_2 = "rro:660Fu2ErM|rx/oq:",
+ vucomiss_2 = "rro:0Fu2ErM|rx/od:",
+ vunpckhpd_3 = "rrmoy:660FV15rM",
+ vunpckhps_3 = "rrmoy:0FV15rM",
+ vunpcklpd_3 = "rrmoy:660FV14rM",
+ vunpcklps_3 = "rrmoy:0FV14rM",
+ vxorpd_3 = "rrmoy:660FV57rM",
+ vxorps_3 = "rrmoy:0FV57rM",
+ vzeroall_0 = "0FuL77",
+ vzeroupper_0 = "0Fu77",
+
+ -- AVX2 FP ops
+ vbroadcastss_2 = "rx/od:660F38u18rM|rx/yd:|rro:|rr/yo:",
+ vbroadcastsd_2 = "rx/yq:660F38u19rM|rr/yo:",
+ -- *vgather* (!vsib)
+ vpermpd_3 = "rmiy:660F3AuX01rMU",
+ vpermps_3 = "rrmy:660F38V16rM",
+
+ -- AVX, AVX2 integer ops
+ -- In general, xmm requires AVX, ymm requires AVX2.
+ vaesdec_3 = "rrmo:660F38VDErM",
+ vaesdeclast_3 = "rrmo:660F38VDFrM",
+ vaesenc_3 = "rrmo:660F38VDCrM",
+ vaesenclast_3 = "rrmo:660F38VDDrM",
+ vaesimc_2 = "rmo:660F38uDBrM",
+ vaeskeygenassist_3 = "rmio:660F3AuDFrMU",
+ vlddqu_2 = "rxoy:F20FuF0rM",
+ vmaskmovdqu_2 = "rro:660FuF7rM",
+ vmovdqa_2 = "rmoy:660Fu6FrM|mroy:660Fu7FRm",
+ vmovdqu_2 = "rmoy:F30Fu6FrM|mroy:F30Fu7FRm",
+ vmovntdq_2 = "xroy:660FuE7Rm",
+ vmovntdqa_2 = "rxoy:660F38u2ArM",
+ vmpsadbw_4 = "rrmioy:660F3AV42rMU",
+ vpabsb_2 = "rmoy:660F38u1CrM",
+ vpabsd_2 = "rmoy:660F38u1ErM",
+ vpabsw_2 = "rmoy:660F38u1DrM",
+ vpackusdw_3 = "rrmoy:660F38V2BrM",
+ vpalignr_4 = "rrmioy:660F3AV0FrMU",
+ vpblendvb_4 = "rrmroy:660F3AV4CrMs",
+ vpblendw_4 = "rrmioy:660F3AV0ErMU",
+ vpclmulqdq_4 = "rrmio:660F3AV44rMU",
+ vpcmpeqq_3 = "rrmoy:660F38V29rM",
+ vpcmpestri_3 = "rmio:660F3Au61rMU",
+ vpcmpestrm_3 = "rmio:660F3Au60rMU",
+ vpcmpgtq_3 = "rrmoy:660F38V37rM",
+ vpcmpistri_3 = "rmio:660F3Au63rMU",
+ vpcmpistrm_3 = "rmio:660F3Au62rMU",
+ vpextrb_3 = "rri/do:660F3Au14nRmU|rri/qo:|xri/bo:",
+ vpextrw_3 = "rri/do:660FuC5rMU|xri/wo:660F3Au15nRmU",
+ vpextrd_3 = "mri/do:660F3Au16RmU",
+ vpextrq_3 = "mri/qo:660F3Au16RmU",
+ vphaddw_3 = "rrmoy:660F38V01rM",
+ vphaddd_3 = "rrmoy:660F38V02rM",
+ vphaddsw_3 = "rrmoy:660F38V03rM",
+ vphminposuw_2 = "rmo:660F38u41rM",
+ vphsubw_3 = "rrmoy:660F38V05rM",
+ vphsubd_3 = "rrmoy:660F38V06rM",
+ vphsubsw_3 = "rrmoy:660F38V07rM",
+ vpinsrb_4 = "rrri/ood:660F3AV20rMU|rrxi/oob:",
+ vpinsrw_4 = "rrri/ood:660FVC4rMU|rrxi/oow:",
+ vpinsrd_4 = "rrmi/ood:660F3AV22rMU",
+ vpinsrq_4 = "rrmi/ooq:660F3AVX22rMU",
+ vpmaddubsw_3 = "rrmoy:660F38V04rM",
+ vpmaxsb_3 = "rrmoy:660F38V3CrM",
+ vpmaxsd_3 = "rrmoy:660F38V3DrM",
+ vpmaxuw_3 = "rrmoy:660F38V3ErM",
+ vpmaxud_3 = "rrmoy:660F38V3FrM",
+ vpminsb_3 = "rrmoy:660F38V38rM",
+ vpminsd_3 = "rrmoy:660F38V39rM",
+ vpminuw_3 = "rrmoy:660F38V3ArM",
+ vpminud_3 = "rrmoy:660F38V3BrM",
+ vpmovmskb_2 = "rr/do:660FuD7rM|rr/dy:660FuLD7rM",
+ vpmovsxbw_2 = "rroy:660F38u20rM|rx/oq:|rx/yo:",
+ vpmovsxbd_2 = "rroy:660F38u21rM|rx/od:|rx/yq:",
+ vpmovsxbq_2 = "rroy:660F38u22rM|rx/ow:|rx/yd:",
+ vpmovsxwd_2 = "rroy:660F38u23rM|rx/oq:|rx/yo:",
+ vpmovsxwq_2 = "rroy:660F38u24rM|rx/od:|rx/yq:",
+ vpmovsxdq_2 = "rroy:660F38u25rM|rx/oq:|rx/yo:",
+ vpmovzxbw_2 = "rroy:660F38u30rM|rx/oq:|rx/yo:",
+ vpmovzxbd_2 = "rroy:660F38u31rM|rx/od:|rx/yq:",
+ vpmovzxbq_2 = "rroy:660F38u32rM|rx/ow:|rx/yd:",
+ vpmovzxwd_2 = "rroy:660F38u33rM|rx/oq:|rx/yo:",
+ vpmovzxwq_2 = "rroy:660F38u34rM|rx/od:|rx/yq:",
+ vpmovzxdq_2 = "rroy:660F38u35rM|rx/oq:|rx/yo:",
+ vpmuldq_3 = "rrmoy:660F38V28rM",
+ vpmulhrsw_3 = "rrmoy:660F38V0BrM",
+ vpmulld_3 = "rrmoy:660F38V40rM",
+ vpshufb_3 = "rrmoy:660F38V00rM",
+ vpshufd_3 = "rmioy:660Fu70rMU",
+ vpshufhw_3 = "rmioy:F30Fu70rMU",
+ vpshuflw_3 = "rmioy:F20Fu70rMU",
+ vpsignb_3 = "rrmoy:660F38V08rM",
+ vpsignw_3 = "rrmoy:660F38V09rM",
+ vpsignd_3 = "rrmoy:660F38V0ArM",
+ vpslldq_3 = "rrioy:660Fv737mU",
+ vpsllw_3 = "rrmoy:660FVF1rM|rrioy:660Fv716mU",
+ vpslld_3 = "rrmoy:660FVF2rM|rrioy:660Fv726mU",
+ vpsllq_3 = "rrmoy:660FVF3rM|rrioy:660Fv736mU",
+ vpsraw_3 = "rrmoy:660FVE1rM|rrioy:660Fv714mU",
+ vpsrad_3 = "rrmoy:660FVE2rM|rrioy:660Fv724mU",
+ vpsrldq_3 = "rrioy:660Fv733mU",
+ vpsrlw_3 = "rrmoy:660FVD1rM|rrioy:660Fv712mU",
+ vpsrld_3 = "rrmoy:660FVD2rM|rrioy:660Fv722mU",
+ vpsrlq_3 = "rrmoy:660FVD3rM|rrioy:660Fv732mU",
+ vptest_2 = "rmoy:660F38u17rM",
+
+ -- AVX2 integer ops
+ vbroadcasti128_2 = "rx/yo:660F38u5ArM",
+ vinserti128_4 = "rrmi/yyo:660F3AV38rMU",
+ vextracti128_3 = "mri/oy:660F3AuL39RmU",
+ vpblendd_4 = "rrmioy:660F3AV02rMU",
+ vpbroadcastb_2 = "rro:660F38u78rM|rx/ob:|rr/yo:|rx/yb:",
+ vpbroadcastw_2 = "rro:660F38u79rM|rx/ow:|rr/yo:|rx/yw:",
+ vpbroadcastd_2 = "rro:660F38u58rM|rx/od:|rr/yo:|rx/yd:",
+ vpbroadcastq_2 = "rro:660F38u59rM|rx/oq:|rr/yo:|rx/yq:",
+ vpermd_3 = "rrmy:660F38V36rM",
+ vpermq_3 = "rmiy:660F3AuX00rMU",
+ -- *vpgather* (!vsib)
+ vperm2i128_4 = "rrmiy:660F3AV46rMU",
+ vpmaskmovd_3 = "rrxoy:660F38V8CrM|xrroy:660F38V8ERm",
+ vpmaskmovq_3 = "rrxoy:660F38VX8CrM|xrroy:660F38VX8ERm",
+ vpsllvd_3 = "rrmoy:660F38V47rM",
+ vpsllvq_3 = "rrmoy:660F38VX47rM",
+ vpsravd_3 = "rrmoy:660F38V46rM",
+ vpsrlvd_3 = "rrmoy:660F38V45rM",
+ vpsrlvq_3 = "rrmoy:660F38VX45rM",
+
+ -- Intel ADX
+ adcx_2 = "rmqd:660F38F6rM",
+ adox_2 = "rmqd:F30F38F6rM",
+
+ -- BMI1
+ andn_3 = "rrmqd:0F38VF2rM",
+ bextr_3 = "rmrqd:0F38wF7rM",
+ blsi_2 = "rmqd:0F38vF33m",
+ blsmsk_2 = "rmqd:0F38vF32m",
+ blsr_2 = "rmqd:0F38vF31m",
+ tzcnt_2 = "rmqdw:F30FBCrM",
+
+ -- BMI2
+ bzhi_3 = "rmrqd:0F38wF5rM",
+ mulx_3 = "rrmqd:F20F38VF6rM",
+ pdep_3 = "rrmqd:F20F38VF5rM",
+ pext_3 = "rrmqd:F30F38VF5rM",
+ rorx_3 = "rmSqd:F20F3AuF0rMS",
+ sarx_3 = "rmrqd:F30F38wF7rM",
+ shrx_3 = "rmrqd:F20F38wF7rM",
+ shlx_3 = "rmrqd:660F38wF7rM",
+
+ -- FMA3
+ vfmaddsub132pd_3 = "rrmoy:660F38VX96rM",
+ vfmaddsub132ps_3 = "rrmoy:660F38V96rM",
+ vfmaddsub213pd_3 = "rrmoy:660F38VXA6rM",
+ vfmaddsub213ps_3 = "rrmoy:660F38VA6rM",
+ vfmaddsub231pd_3 = "rrmoy:660F38VXB6rM",
+ vfmaddsub231ps_3 = "rrmoy:660F38VB6rM",
+
+ vfmsubadd132pd_3 = "rrmoy:660F38VX97rM",
+ vfmsubadd132ps_3 = "rrmoy:660F38V97rM",
+ vfmsubadd213pd_3 = "rrmoy:660F38VXA7rM",
+ vfmsubadd213ps_3 = "rrmoy:660F38VA7rM",
+ vfmsubadd231pd_3 = "rrmoy:660F38VXB7rM",
+ vfmsubadd231ps_3 = "rrmoy:660F38VB7rM",
+
+ vfmadd132pd_3 = "rrmoy:660F38VX98rM",
+ vfmadd132ps_3 = "rrmoy:660F38V98rM",
+ vfmadd132sd_3 = "rrro:660F38VX99rM|rrx/ooq:",
+ vfmadd132ss_3 = "rrro:660F38V99rM|rrx/ood:",
+ vfmadd213pd_3 = "rrmoy:660F38VXA8rM",
+ vfmadd213ps_3 = "rrmoy:660F38VA8rM",
+ vfmadd213sd_3 = "rrro:660F38VXA9rM|rrx/ooq:",
+ vfmadd213ss_3 = "rrro:660F38VA9rM|rrx/ood:",
+ vfmadd231pd_3 = "rrmoy:660F38VXB8rM",
+ vfmadd231ps_3 = "rrmoy:660F38VB8rM",
+ vfmadd231sd_3 = "rrro:660F38VXB9rM|rrx/ooq:",
+ vfmadd231ss_3 = "rrro:660F38VB9rM|rrx/ood:",
+
+ vfmsub132pd_3 = "rrmoy:660F38VX9ArM",
+ vfmsub132ps_3 = "rrmoy:660F38V9ArM",
+ vfmsub132sd_3 = "rrro:660F38VX9BrM|rrx/ooq:",
+ vfmsub132ss_3 = "rrro:660F38V9BrM|rrx/ood:",
+ vfmsub213pd_3 = "rrmoy:660F38VXAArM",
+ vfmsub213ps_3 = "rrmoy:660F38VAArM",
+ vfmsub213sd_3 = "rrro:660F38VXABrM|rrx/ooq:",
+ vfmsub213ss_3 = "rrro:660F38VABrM|rrx/ood:",
+ vfmsub231pd_3 = "rrmoy:660F38VXBArM",
+ vfmsub231ps_3 = "rrmoy:660F38VBArM",
+ vfmsub231sd_3 = "rrro:660F38VXBBrM|rrx/ooq:",
+ vfmsub231ss_3 = "rrro:660F38VBBrM|rrx/ood:",
+
+ vfnmadd132pd_3 = "rrmoy:660F38VX9CrM",
+ vfnmadd132ps_3 = "rrmoy:660F38V9CrM",
+ vfnmadd132sd_3 = "rrro:660F38VX9DrM|rrx/ooq:",
+ vfnmadd132ss_3 = "rrro:660F38V9DrM|rrx/ood:",
+ vfnmadd213pd_3 = "rrmoy:660F38VXACrM",
+ vfnmadd213ps_3 = "rrmoy:660F38VACrM",
+ vfnmadd213sd_3 = "rrro:660F38VXADrM|rrx/ooq:",
+ vfnmadd213ss_3 = "rrro:660F38VADrM|rrx/ood:",
+ vfnmadd231pd_3 = "rrmoy:660F38VXBCrM",
+ vfnmadd231ps_3 = "rrmoy:660F38VBCrM",
+ vfnmadd231sd_3 = "rrro:660F38VXBDrM|rrx/ooq:",
+ vfnmadd231ss_3 = "rrro:660F38VBDrM|rrx/ood:",
+
+ vfnmsub132pd_3 = "rrmoy:660F38VX9ErM",
+ vfnmsub132ps_3 = "rrmoy:660F38V9ErM",
+ vfnmsub132sd_3 = "rrro:660F38VX9FrM|rrx/ooq:",
+ vfnmsub132ss_3 = "rrro:660F38V9FrM|rrx/ood:",
+ vfnmsub213pd_3 = "rrmoy:660F38VXAErM",
+ vfnmsub213ps_3 = "rrmoy:660F38VAErM",
+ vfnmsub213sd_3 = "rrro:660F38VXAFrM|rrx/ooq:",
+ vfnmsub213ss_3 = "rrro:660F38VAFrM|rrx/ood:",
+ vfnmsub231pd_3 = "rrmoy:660F38VXBErM",
+ vfnmsub231ps_3 = "rrmoy:660F38VBErM",
+ vfnmsub231sd_3 = "rrro:660F38VXBFrM|rrx/ooq:",
+ vfnmsub231ss_3 = "rrro:660F38VBFrM|rrx/ood:",
+}
+
+------------------------------------------------------------------------------
+
+-- Arithmetic ops.
+for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3,
+ ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do
+ local n8 = shl(n, 3)
+ map_op[name.."_2"] = format(
+ "mr:%02XRm|rm:%02XrM|mI1qdw:81%XmI|mS1qdw:83%XmS|Ri1qdwb:%02Xri|mi1qdwb:81%Xmi",
+ 1+n8, 3+n8, n, n, 5+n8, n)
+end
+
+-- Shift ops.
+for name,n in pairs{ rol = 0, ror = 1, rcl = 2, rcr = 3,
+ shl = 4, shr = 5, sar = 7, sal = 4 } do
+ map_op[name.."_2"] = format("m1:D1%Xm|mC1qdwb:D3%Xm|mi:C1%XmU", n, n, n)
+end
+
+-- Conditional ops.
+for cc,n in pairs(map_cc) do
+ map_op["j"..cc.."_1"] = format("J.:n0F8%XJ", n) -- short: 7%X
+ map_op["set"..cc.."_1"] = format("mb:n0F9%X2m", n)
+ map_op["cmov"..cc.."_2"] = format("rmqdw:0F4%XrM", n) -- P6+
+end
+
+-- FP arithmetic ops.
+for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3,
+ sub = 4, subr = 5, div = 6, divr = 7 } do
+ local nc = 0xc0 + shl(n, 3)
+ local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8))
+ local fn = "f"..name
+ map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:nDC%Xm", nc, n, n)
+ if n == 2 or n == 3 then
+ map_op[fn.."_2"] = format("Fff:D8%02XR|Fx2d:D8%XM|Fx2q:nDC%XM", nc, n, n)
+ else
+ map_op[fn.."_2"] = format("Fff:D8%02XR|fFf:DC%02Xr|Fx2d:D8%XM|Fx2q:nDC%XM", nc, nr, n, n)
+ map_op[fn.."p_1"] = format("ff:DE%02Xr", nr)
+ map_op[fn.."p_2"] = format("fFf:DE%02Xr", nr)
+ end
+ map_op["fi"..name.."_1"] = format("xd:DA%Xm|xw:nDE%Xm", n, n)
+end
+
+-- FP conditional moves.
+for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do
+ local nc = 0xdac0 + shl(band(n, 3), 3) + shl(band(n, 4), 6)
+ map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+
+ map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+
+end
+
+-- SSE / AVX FP arithmetic ops.
+for name,n in pairs{ sqrt = 1, add = 8, mul = 9,
+ sub = 12, min = 13, div = 14, max = 15 } do
+ map_op[name.."ps_2"] = format("rmo:0F5%XrM", n)
+ map_op[name.."ss_2"] = format("rro:F30F5%XrM|rx/od:", n)
+ map_op[name.."pd_2"] = format("rmo:660F5%XrM", n)
+ map_op[name.."sd_2"] = format("rro:F20F5%XrM|rx/oq:", n)
+ if n ~= 1 then
+ map_op["v"..name.."ps_3"] = format("rrmoy:0FV5%XrM", n)
+ map_op["v"..name.."ss_3"] = format("rrro:F30FV5%XrM|rrx/ood:", n)
+ map_op["v"..name.."pd_3"] = format("rrmoy:660FV5%XrM", n)
+ map_op["v"..name.."sd_3"] = format("rrro:F20FV5%XrM|rrx/ooq:", n)
+ end
+end
+
+-- SSE2 / AVX / AVX2 integer arithmetic ops (66 0F leaf).
+for name,n in pairs{
+ paddb = 0xFC, paddw = 0xFD, paddd = 0xFE, paddq = 0xD4,
+ paddsb = 0xEC, paddsw = 0xED, packssdw = 0x6B,
+ packsswb = 0x63, packuswb = 0x67, paddusb = 0xDC,
+ paddusw = 0xDD, pand = 0xDB, pandn = 0xDF, pavgb = 0xE0,
+ pavgw = 0xE3, pcmpeqb = 0x74, pcmpeqd = 0x76,
+ pcmpeqw = 0x75, pcmpgtb = 0x64, pcmpgtd = 0x66,
+ pcmpgtw = 0x65, pmaddwd = 0xF5, pmaxsw = 0xEE,
+ pmaxub = 0xDE, pminsw = 0xEA, pminub = 0xDA,
+ pmulhuw = 0xE4, pmulhw = 0xE5, pmullw = 0xD5,
+ pmuludq = 0xF4, por = 0xEB, psadbw = 0xF6, psubb = 0xF8,
+ psubw = 0xF9, psubd = 0xFA, psubq = 0xFB, psubsb = 0xE8,
+ psubsw = 0xE9, psubusb = 0xD8, psubusw = 0xD9,
+ punpckhbw = 0x68, punpckhwd = 0x69, punpckhdq = 0x6A,
+ punpckhqdq = 0x6D, punpcklbw = 0x60, punpcklwd = 0x61,
+ punpckldq = 0x62, punpcklqdq = 0x6C, pxor = 0xEF
+} do
+ map_op[name.."_2"] = format("rmo:660F%02XrM", n)
+ map_op["v"..name.."_3"] = format("rrmoy:660FV%02XrM", n)
+end
+
+------------------------------------------------------------------------------
+
+local map_vexarg = { u = false, v = 1, V = 2, w = 3 }
+
+-- Process pattern string.
+local function dopattern(pat, args, sz, op, needrex)
+ local digit, addin, vex
+ local opcode = 0
+ local szov = sz
+ local narg = 1
+ local rex = 0
+
+ -- Limit number of section buffer positions used by a single dasm_put().
+ -- A single opcode needs a maximum of 6 positions.
+ if secpos+6 > maxsecpos then wflush() end
+
+ -- Process each character.
+ for c in gmatch(pat.."|", ".") do
+ if match(c, "%x") then -- Hex digit.
+ digit = byte(c) - 48
+ if digit > 48 then digit = digit - 39
+ elseif digit > 16 then digit = digit - 7 end
+ opcode = opcode*16 + digit
+ addin = nil
+ elseif c == "n" then -- Disable operand size mods for opcode.
+ szov = nil
+ elseif c == "X" then -- Force REX.W.
+ rex = 8
+ elseif c == "L" then -- Force VEX.L.
+ vex.l = true
+ elseif c == "r" then -- Merge 1st operand regno. into opcode.
+ addin = args[1]; opcode = opcode + (addin.reg % 8)
+ if narg < 2 then narg = 2 end
+ elseif c == "R" then -- Merge 2nd operand regno. into opcode.
+ addin = args[2]; opcode = opcode + (addin.reg % 8)
+ narg = 3
+ elseif c == "m" or c == "M" then -- Encode ModRM/SIB.
+ local s
+ if addin then
+ s = addin.reg
+ opcode = opcode - band(s, 7) -- Undo regno opcode merge.
+ else
+ s = band(opcode, 15) -- Undo last digit.
+ opcode = shr(opcode, 4)
+ end
+ local nn = c == "m" and 1 or 2
+ local t = args[nn]
+ if narg <= nn then narg = nn + 1 end
+ if szov == "q" and rex == 0 then rex = rex + 8 end
+ if t.reg and t.reg > 7 then rex = rex + 1 end
+ if t.xreg and t.xreg > 7 then rex = rex + 2 end
+ if s > 7 then rex = rex + 4 end
+ if needrex then rex = rex + 16 end
+ local psz, sk = wputop(szov, opcode, rex, vex, s < 0, t.vreg or t.vxreg)
+ opcode = nil
+ local imark = sub(pat, -1) -- Force a mark (ugly).
+ -- Put ModRM/SIB with regno/last digit as spare.
+ wputmrmsib(t, imark, s, addin and addin.vreg, psz, sk)
+ addin = nil
+ elseif map_vexarg[c] ~= nil then -- Encode using VEX prefix
+ local b = band(opcode, 255); opcode = shr(opcode, 8)
+ local m = 1
+ if b == 0x38 then m = 2
+ elseif b == 0x3a then m = 3 end
+ if m ~= 1 then b = band(opcode, 255); opcode = shr(opcode, 8) end
+ if b ~= 0x0f then
+ werror("expected `0F', `0F38', or `0F3A' to precede `"..c..
+ "' in pattern `"..pat.."' for `"..op.."'")
+ end
+ local v = map_vexarg[c]
+ if v then v = remove(args, v) end
+ b = band(opcode, 255)
+ local p = 0
+ if b == 0x66 then p = 1
+ elseif b == 0xf3 then p = 2
+ elseif b == 0xf2 then p = 3 end
+ if p ~= 0 then opcode = shr(opcode, 8) end
+ if opcode ~= 0 then wputop(nil, opcode, 0); opcode = 0 end
+ vex = { m = m, p = p, v = v }
+ else
+ if opcode then -- Flush opcode.
+ if szov == "q" and rex == 0 then rex = rex + 8 end
+ if needrex then rex = rex + 16 end
+ if addin and addin.reg == -1 then
+ local psz, sk = wputop(szov, opcode - 7, rex, vex, true)
+ wvreg("opcode", addin.vreg, psz, sk)
+ else
+ if addin and addin.reg > 7 then rex = rex + 1 end
+ wputop(szov, opcode, rex, vex)
+ end
+ opcode = nil
+ end
+ if c == "|" then break end
+ if c == "o" then -- Offset (pure 32 bit displacement).
+ wputdarg(args[1].disp); if narg < 2 then narg = 2 end
+ elseif c == "O" then
+ wputdarg(args[2].disp); narg = 3
+ else
+ -- Anything else is an immediate operand.
+ local a = args[narg]
+ narg = narg + 1
+ local mode, imm = a.mode, a.imm
+ if mode == "iJ" and not match(x64 and "J" or "iIJ", c) then
+ werror("bad operand size for label")
+ end
+ if c == "S" then
+ wputsbarg(imm)
+ elseif c == "U" then
+ wputbarg(imm)
+ elseif c == "W" then
+ wputwarg(imm)
+ elseif c == "i" or c == "I" then
+ if mode == "iJ" then
+ wputlabel("IMM_", imm, 1)
+ elseif mode == "iI" and c == "I" then
+ waction(sz == "w" and "IMM_WB" or "IMM_DB", imm)
+ else
+ wputszarg(sz, imm)
+ end
+ elseif c == "J" then
+ if mode == "iPJ" then
+ waction("REL_A", imm) -- !x64 (secpos)
+ else
+ wputlabel("REL_", imm, 2)
+ end
+ elseif c == "s" then
+ local reg = a.reg
+ if reg < 0 then
+ wputb(0)
+ wvreg("imm.hi", a.vreg)
+ else
+ wputb(shl(reg, 4))
+ end
+ else
+ werror("bad char `"..c.."' in pattern `"..pat.."' for `"..op.."'")
+ end
+ end
+ end
+ end
+end
+
+------------------------------------------------------------------------------
+
+-- Mapping of operand modes to short names. Suppress output with '#'.
+local map_modename = {
+ r = "reg", R = "eax", C = "cl", x = "mem", m = "mrm", i = "imm",
+ f = "stx", F = "st0", J = "lbl", ["1"] = "1",
+ I = "#", S = "#", O = "#",
+}
+
+-- Return a table/string showing all possible operand modes.
+local function templatehelp(template, nparams)
+ if nparams == 0 then return "" end
+ local t = {}
+ for tm in gmatch(template, "[^%|]+") do
+ local s = map_modename[sub(tm, 1, 1)]
+ s = s..gsub(sub(tm, 2, nparams), ".", function(c)
+ return ", "..map_modename[c]
+ end)
+ if not match(s, "#") then t[#t+1] = s end
+ end
+ return t
+end
+
+-- Match operand modes against mode match part of template.
+local function matchtm(tm, args)
+ for i=1,#args do
+ if not match(args[i].mode, sub(tm, i, i)) then return end
+ end
+ return true
+end
+
+-- Handle opcodes defined with template strings.
+map_op[".template__"] = function(params, template, nparams)
+ if not params then return templatehelp(template, nparams) end
+ local args = {}
+
+ -- Zero-operand opcodes have no match part.
+ if #params == 0 then
+ dopattern(template, args, "d", params.op, nil)
+ return
+ end
+
+ -- Determine common operand size (coerce undefined size) or flag as mixed.
+ local sz, szmix, needrex
+ for i,p in ipairs(params) do
+ args[i] = parseoperand(p)
+ local nsz = args[i].opsize
+ if nsz then
+ if sz and sz ~= nsz then szmix = true else sz = nsz end
+ end
+ local nrex = args[i].needrex
+ if nrex ~= nil then
+ if needrex == nil then
+ needrex = nrex
+ elseif needrex ~= nrex then
+ werror("bad mix of byte-addressable registers")
+ end
+ end
+ end
+
+ -- Try all match:pattern pairs (separated by '|').
+ local gotmatch, lastpat
+ for tm in gmatch(template, "[^%|]+") do
+ -- Split off size match (starts after mode match) and pattern string.
+ local szm, pat = match(tm, "^(.-):(.*)$", #args+1)
+ if pat == "" then pat = lastpat else lastpat = pat end
+ if matchtm(tm, args) then
+ local prefix = sub(szm, 1, 1)
+ if prefix == "/" then -- Exactly match leading operand sizes.
+ for i = #szm,1,-1 do
+ if i == 1 then
+ dopattern(pat, args, sz, params.op, needrex) -- Process pattern.
+ return
+ elseif args[i-1].opsize ~= sub(szm, i, i) then
+ break
+ end
+ end
+ else -- Match common operand size.
+ local szp = sz
+ if szm == "" then szm = x64 and "qdwb" or "dwb" end -- Default sizes.
+ if prefix == "1" then szp = args[1].opsize; szmix = nil
+ elseif prefix == "2" then szp = args[2].opsize; szmix = nil end
+ if not szmix and (prefix == "." or match(szm, szp or "#")) then
+ dopattern(pat, args, szp, params.op, needrex) -- Process pattern.
+ return
+ end
+ end
+ gotmatch = true
+ end
+ end
+
+ local msg = "bad operand mode"
+ if gotmatch then
+ if szmix then
+ msg = "mixed operand size"
+ else
+ msg = sz and "bad operand size" or "missing operand size"
+ end
+ end
+
+ werror(msg.." in `"..opmodestr(params.op, args).."'")
+end
+
+------------------------------------------------------------------------------
+
+-- x64-specific opcode for 64 bit immediates and displacements.
+if x64 then
+ function map_op.mov64_2(params)
+ if not params then return { "reg, imm", "reg, [disp]", "[disp], reg" } end
+ if secpos+2 > maxsecpos then wflush() end
+ local opcode, op64, sz, rex, vreg
+ local op64 = match(params[1], "^%[%s*(.-)%s*%]$")
+ if op64 then
+ local a = parseoperand(params[2])
+ if a.mode ~= "rmR" then werror("bad operand mode") end
+ sz = a.opsize
+ rex = sz == "q" and 8 or 0
+ opcode = 0xa3
+ else
+ op64 = match(params[2], "^%[%s*(.-)%s*%]$")
+ local a = parseoperand(params[1])
+ if op64 then
+ if a.mode ~= "rmR" then werror("bad operand mode") end
+ sz = a.opsize
+ rex = sz == "q" and 8 or 0
+ opcode = 0xa1
+ else
+ if sub(a.mode, 1, 1) ~= "r" or a.opsize ~= "q" then
+ werror("bad operand mode")
+ end
+ op64 = params[2]
+ if a.reg == -1 then
+ vreg = a.vreg
+ opcode = 0xb8
+ else
+ opcode = 0xb8 + band(a.reg, 7)
+ end
+ rex = a.reg > 7 and 9 or 8
+ end
+ end
+ local psz, sk = wputop(sz, opcode, rex, nil, vreg)
+ wvreg("opcode", vreg, psz, sk)
+ waction("IMM_D", format("(unsigned int)(%s)", op64))
+ waction("IMM_D", format("(unsigned int)((%s)>>32)", op64))
+ end
+end
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcodes for data storage.
+local function op_data(params)
+ if not params then return "imm..." end
+ local sz = sub(params.op, 2, 2)
+ if sz == "l" then sz = "d" elseif sz == "a" then sz = addrsize end
+ for _,p in ipairs(params) do
+ local a = parseoperand(p, sz == "q")
+ if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then
+ werror("bad mode or size in `"..p.."'")
+ end
+ if a.mode == "iJ" then
+ wputlabel("IMM_", a.imm, 1)
+ elseif sz == "q" then
+ wputqarg(a.imm)
+ else
+ wputszarg(sz, a.imm)
+ end
+ if secpos+2 > maxsecpos then wflush() end
+ end
+end
+
+map_op[".byte_*"] = op_data
+map_op[".sbyte_*"] = op_data
+map_op[".word_*"] = op_data
+map_op[".dword_*"] = op_data
+map_op[".qword_*"] = op_data
+map_op[".aword_*"] = op_data
+map_op[".long_*"] = op_data
+map_op[".quad_*"] = op_data
+map_op[".addr_*"] = op_data
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcode to mark the position where the action list is to be emitted.
+map_op[".actionlist_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeactions(out, name) end)
+end
+
+-- Pseudo-opcode to mark the position where the global enum is to be emitted.
+map_op[".globals_1"] = function(params)
+ if not params then return "prefix" end
+ local prefix = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeglobals(out, prefix) end)
+end
+
+-- Pseudo-opcode to mark the position where the global names are to be emitted.
+map_op[".globalnames_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeglobalnames(out, name) end)
+end
+
+-- Pseudo-opcode to mark the position where the extern names are to be emitted.
+map_op[".externnames_1"] = function(params)
+ if not params then return "cvar" end
+ local name = params[1] -- No syntax check. You get to keep the pieces.
+ wline(function(out) writeexternnames(out, name) end)
+end
+
+------------------------------------------------------------------------------
+
+-- Label pseudo-opcode (converted from trailing colon form).
+map_op[".label_2"] = function(params)
+ if not params then return "[1-9] | ->global | =>pcexpr [, addr]" end
+ if secpos+2 > maxsecpos then wflush() end
+ local a = parseoperand(params[1])
+ local mode, imm = a.mode, a.imm
+ if type(imm) == "number" and (mode == "iJ" or (imm >= 1 and imm <= 9)) then
+ -- Local label (1: ... 9:) or global label (->global:).
+ waction("LABEL_LG", nil, 1)
+ wputxb(imm)
+ elseif mode == "iJ" then
+ -- PC label (=>pcexpr:).
+ waction("LABEL_PC", imm)
+ else
+ werror("bad label definition")
+ end
+ -- SETLABEL must immediately follow LABEL_LG/LABEL_PC.
+ local addr = params[2]
+ if addr then
+ local a = parseoperand(addr)
+ if a.mode == "iPJ" then
+ waction("SETLABEL", a.imm)
+ else
+ werror("bad label assignment")
+ end
+ end
+end
+map_op[".label_1"] = map_op[".label_2"]
+
+------------------------------------------------------------------------------
+
+-- Alignment pseudo-opcode.
+map_op[".align_1"] = function(params)
+ if not params then return "numpow2" end
+ if secpos+1 > maxsecpos then wflush() end
+ local align = tonumber(params[1]) or map_opsizenum[map_opsize[params[1]]]
+ if align then
+ local x = align
+ -- Must be a power of 2 in the range (2 ... 256).
+ for i=1,8 do
+ x = x / 2
+ if x == 1 then
+ waction("ALIGN", nil, 1)
+ wputxb(align-1) -- Action byte is 2**n-1.
+ return
+ end
+ end
+ end
+ werror("bad alignment")
+end
+
+-- Spacing pseudo-opcode.
+map_op[".space_2"] = function(params)
+ if not params then return "num [, filler]" end
+ if secpos+1 > maxsecpos then wflush() end
+ waction("SPACE", params[1])
+ local fill = params[2]
+ if fill then
+ fill = tonumber(fill)
+ if not fill or fill < 0 or fill > 255 then werror("bad filler") end
+ end
+ wputxb(fill or 0)
+end
+map_op[".space_1"] = map_op[".space_2"]
+
+------------------------------------------------------------------------------
+
+-- Pseudo-opcode for (primitive) type definitions (map to C types).
+map_op[".type_3"] = function(params, nparams)
+ if not params then
+ return nparams == 2 and "name, ctype" or "name, ctype, reg"
+ end
+ local name, ctype, reg = params[1], params[2], params[3]
+ if not match(name, "^[%a_][%w_]*$") then
+ werror("bad type name `"..name.."'")
+ end
+ local tp = map_type[name]
+ if tp then
+ werror("duplicate type `"..name.."'")
+ end
+ if reg and not map_reg_valid_base[reg] then
+ werror("bad base register `"..(map_reg_rev[reg] or reg).."'")
+ end
+ -- Add #type to defines. A bit unclean to put it in map_archdef.
+ map_archdef["#"..name] = "sizeof("..ctype..")"
+ -- Add new type and emit shortcut define.
+ local num = ctypenum + 1
+ map_type[name] = {
+ ctype = ctype,
+ ctypefmt = format("Dt%X(%%s)", num),
+ reg = reg,
+ }
+ wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
+ ctypenum = num
+end
+map_op[".type_2"] = map_op[".type_3"]
+
+-- Dump type definitions.
+local function dumptypes(out, lvl)
+ local t = {}
+ for name in pairs(map_type) do t[#t+1] = name end
+ sort(t)
+ out:write("Type definitions:\n")
+ for _,name in ipairs(t) do
+ local tp = map_type[name]
+ local reg = tp.reg and map_reg_rev[tp.reg] or ""
+ out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
+ end
+ out:write("\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Set the current section.
+function _M.section(num)
+ waction("SECTION")
+ wputxb(num)
+ wflush(true) -- SECTION is a terminal action.
+end
+
+------------------------------------------------------------------------------
+
+-- Dump architecture description.
+function _M.dumparch(out)
+ out:write(format("DynASM %s version %s, released %s\n\n",
+ _info.arch, _info.version, _info.release))
+ dumpregs(out)
+ dumpactions(out)
+end
+
+-- Dump all user defined elements.
+function _M.dumpdef(out, lvl)
+ dumptypes(out, lvl)
+ dumpglobals(out, lvl)
+ dumpexterns(out, lvl)
+end
+
+------------------------------------------------------------------------------
+
+-- Pass callbacks from/to the DynASM core.
+function _M.passcb(wl, we, wf, ww)
+ wline, werror, wfatal, wwarn = wl, we, wf, ww
+ return wflush
+end
+
+-- Setup the arch-specific module.
+function _M.setup(arch, opt)
+ g_arch, g_opt = arch, opt
+end
+
+-- Merge the core maps and the arch-specific maps.
+function _M.mergemaps(map_coreop, map_def)
+ setmetatable(map_op, { __index = map_coreop })
+ setmetatable(map_def, { __index = map_archdef })
+ return map_op, map_def
+end
+
+return _M
+
+------------------------------------------------------------------------------
+
diff --git a/LuaJIT-2.1/dynasm/dynasm.lua b/LuaJIT-2.1/dynasm/dynasm.lua
new file mode 100644
index 00000000..2a4d649e
--- /dev/null
+++ b/LuaJIT-2.1/dynasm/dynasm.lua
@@ -0,0 +1,1095 @@
+------------------------------------------------------------------------------
+-- DynASM. A dynamic assembler for code generation engines.
+-- Originally designed and implemented for LuaJIT.
+--
+-- Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+-- See below for full copyright notice.
+------------------------------------------------------------------------------
+
+-- Application information.
+local _info = {
+ name = "DynASM",
+ description = "A dynamic assembler for code generation engines",
+ version = "1.5.0",
+ vernum = 10500,
+ release = "2021-05-02",
+ author = "Mike Pall",
+ url = "https://luajit.org/dynasm.html",
+ license = "MIT",
+ copyright = [[
+Copyright (C) 2005-2025 Mike Pall. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+[ MIT license: https://www.opensource.org/licenses/mit-license.php ]
+]],
+}
+
+-- Cache library functions.
+local type, pairs, ipairs = type, pairs, ipairs
+local pcall, error, assert = pcall, error, assert
+local _s = string
+local sub, match, gmatch, gsub = _s.sub, _s.match, _s.gmatch, _s.gsub
+local format, rep, upper = _s.format, _s.rep, _s.upper
+local _t = table
+local insert, remove, concat, sort = _t.insert, _t.remove, _t.concat, _t.sort
+local exit = os.exit
+local io = io
+local stdin, stdout, stderr = io.stdin, io.stdout, io.stderr
+
+------------------------------------------------------------------------------
+
+-- Program options.
+local g_opt = {}
+
+-- Global state for current file.
+local g_fname, g_curline, g_indent, g_lineno, g_synclineno, g_arch
+local g_errcount = 0
+
+-- Write buffer for output file.
+local g_wbuffer, g_capbuffer
+
+------------------------------------------------------------------------------
+
+-- Write an output line (or callback function) to the buffer.
+local function wline(line, needindent)
+ local buf = g_capbuffer or g_wbuffer
+ buf[#buf+1] = needindent and g_indent..line or line
+ g_synclineno = g_synclineno + 1
+end
+
+-- Write assembler line as a comment, if requested.
+local function wcomment(aline)
+ if g_opt.comment then
+ wline(g_opt.comment..aline..g_opt.endcomment, true)
+ end
+end
+
+-- Resync CPP line numbers.
+local function wsync()
+ if g_synclineno ~= g_lineno and g_opt.cpp then
+ wline("#line "..g_lineno..' "'..g_fname..'"')
+ g_synclineno = g_lineno
+ end
+end
+
+-- Dummy action flush function. Replaced with arch-specific function later.
+local function wflush(term)
+end
+
+-- Dump all buffered output lines.
+local function wdumplines(out, buf)
+ for _,line in ipairs(buf) do
+ if type(line) == "string" then
+ assert(out:write(line, "\n"))
+ else
+ -- Special callback to dynamically insert lines after end of processing.
+ line(out)
+ end
+ end
+end
+
+------------------------------------------------------------------------------
+
+-- Emit an error. Processing continues with next statement.
+local function werror(msg)
+ error(format("%s:%s: error: %s:\n%s", g_fname, g_lineno, msg, g_curline), 0)
+end
+
+-- Emit a fatal error. Processing stops.
+local function wfatal(msg)
+ g_errcount = "fatal"
+ werror(msg)
+end
+
+-- Print a warning. Processing continues.
+local function wwarn(msg)
+ stderr:write(format("%s:%s: warning: %s:\n%s\n",
+ g_fname, g_lineno, msg, g_curline))
+end
+
+-- Print caught error message. But suppress excessive errors.
+local function wprinterr(...)
+ if type(g_errcount) == "number" then
+ -- Regular error.
+ g_errcount = g_errcount + 1
+ if g_errcount < 21 then -- Seems to be a reasonable limit.
+ stderr:write(...)
+ elseif g_errcount == 21 then
+ stderr:write(g_fname,
+ ":*: warning: too many errors (suppressed further messages).\n")
+ end
+ else
+ -- Fatal error.
+ stderr:write(...)
+ return true -- Stop processing.
+ end
+end
+
+------------------------------------------------------------------------------
+
+-- Map holding all option handlers.
+local opt_map = {}
+local opt_current
+
+-- Print error and exit with error status.
+local function opterror(...)
+ stderr:write("dynasm.lua: ERROR: ", ...)
+ stderr:write("\n")
+ exit(1)
+end
+
+-- Get option parameter.
+local function optparam(args)
+ local argn = args.argn
+ local p = args[argn]
+ if not p then
+ opterror("missing parameter for option `", opt_current, "'.")
+ end
+ args.argn = argn + 1
+ return p
+end
+
+------------------------------------------------------------------------------
+
+-- Core pseudo-opcodes.
+local map_coreop = {}
+-- Dummy opcode map. Replaced by arch-specific map.
+local map_op = {}
+
+-- Forward declarations.
+local dostmt
+local readfile
+
+------------------------------------------------------------------------------
+
+-- Map for defines (initially empty, chains to arch-specific map).
+local map_def = {}
+
+-- Pseudo-opcode to define a substitution.
+map_coreop[".define_2"] = function(params, nparams)
+ if not params then return nparams == 1 and "name" or "name, subst" end
+ local name, def = params[1], params[2] or "1"
+ if not match(name, "^[%a_][%w_]*$") then werror("bad or duplicate define") end
+ map_def[name] = def
+end
+map_coreop[".define_1"] = map_coreop[".define_2"]
+
+-- Define a substitution on the command line.
+function opt_map.D(args)
+ local namesubst = optparam(args)
+ local name, subst = match(namesubst, "^([%a_][%w_]*)=(.*)$")
+ if name then
+ map_def[name] = subst
+ elseif match(namesubst, "^[%a_][%w_]*$") then
+ map_def[namesubst] = "1"
+ else
+ opterror("bad define")
+ end
+end
+
+-- Undefine a substitution on the command line.
+function opt_map.U(args)
+ local name = optparam(args)
+ if match(name, "^[%a_][%w_]*$") then
+ map_def[name] = nil
+ else
+ opterror("bad define")
+ end
+end
+
+-- Helper for definesubst.
+local gotsubst
+
+local function definesubst_one(word)
+ local subst = map_def[word]
+ if subst then gotsubst = word; return subst else return word end
+end
+
+-- Iteratively substitute defines.
+local function definesubst(stmt)
+ -- Limit number of iterations.
+ for i=1,100 do
+ gotsubst = false
+ stmt = gsub(stmt, "#?[%w_]+", definesubst_one)
+ if not gotsubst then break end
+ end
+ if gotsubst then wfatal("recursive define involving `"..gotsubst.."'") end
+ return stmt
+end
+
+-- Dump all defines.
+local function dumpdefines(out, lvl)
+ local t = {}
+ for name in pairs(map_def) do
+ t[#t+1] = name
+ end
+ sort(t)
+ out:write("Defines:\n")
+ for _,name in ipairs(t) do
+ local subst = map_def[name]
+ if g_arch then subst = g_arch.revdef(subst) end
+ out:write(format(" %-20s %s\n", name, subst))
+ end
+ out:write("\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Support variables for conditional assembly.
+local condlevel = 0
+local condstack = {}
+
+-- Evaluate condition with a Lua expression. Substitutions already performed.
+local function cond_eval(cond)
+ local func, err
+ if setfenv then
+ func, err = loadstring("return "..cond, "=expr")
+ else
+ -- No globals. All unknown identifiers evaluate to nil.
+ func, err = load("return "..cond, "=expr", "t", {})
+ end
+ if func then
+ if setfenv then
+ setfenv(func, {}) -- No globals. All unknown identifiers evaluate to nil.
+ end
+ local ok, res = pcall(func)
+ if ok then
+ if res == 0 then return false end -- Oh well.
+ return not not res
+ end
+ err = res
+ end
+ wfatal("bad condition: "..err)
+end
+
+-- Skip statements until next conditional pseudo-opcode at the same level.
+local function stmtskip()
+ local dostmt_save = dostmt
+ local lvl = 0
+ dostmt = function(stmt)
+ local op = match(stmt, "^%s*(%S+)")
+ if op == ".if" then
+ lvl = lvl + 1
+ elseif lvl ~= 0 then
+ if op == ".endif" then lvl = lvl - 1 end
+ elseif op == ".elif" or op == ".else" or op == ".endif" then
+ dostmt = dostmt_save
+ dostmt(stmt)
+ end
+ end
+end
+
+-- Pseudo-opcodes for conditional assembly.
+map_coreop[".if_1"] = function(params)
+ if not params then return "condition" end
+ local lvl = condlevel + 1
+ local res = cond_eval(params[1])
+ condlevel = lvl
+ condstack[lvl] = res
+ if not res then stmtskip() end
+end
+
+map_coreop[".elif_1"] = function(params)
+ if not params then return "condition" end
+ if condlevel == 0 then wfatal(".elif without .if") end
+ local lvl = condlevel
+ local res = condstack[lvl]
+ if res then
+ if res == "else" then wfatal(".elif after .else") end
+ else
+ res = cond_eval(params[1])
+ if res then
+ condstack[lvl] = res
+ return
+ end
+ end
+ stmtskip()
+end
+
+map_coreop[".else_0"] = function(params)
+ if condlevel == 0 then wfatal(".else without .if") end
+ local lvl = condlevel
+ local res = condstack[lvl]
+ condstack[lvl] = "else"
+ if res then
+ if res == "else" then wfatal(".else after .else") end
+ stmtskip()
+ end
+end
+
+map_coreop[".endif_0"] = function(params)
+ local lvl = condlevel
+ if lvl == 0 then wfatal(".endif without .if") end
+ condlevel = lvl - 1
+end
+
+-- Check for unfinished conditionals.
+local function checkconds()
+ if g_errcount ~= "fatal" and condlevel ~= 0 then
+ wprinterr(g_fname, ":*: error: unbalanced conditional\n")
+ end
+end
+
+------------------------------------------------------------------------------
+
+-- Search for a file in the given path and open it for reading.
+local function pathopen(path, name)
+ local dirsep = package and match(package.path, "\\") and "\\" or "/"
+ for _,p in ipairs(path) do
+ local fullname = p == "" and name or p..dirsep..name
+ local fin = io.open(fullname, "r")
+ if fin then
+ g_fname = fullname
+ return fin
+ end
+ end
+end
+
+-- Include a file.
+map_coreop[".include_1"] = function(params)
+ if not params then return "filename" end
+ local name = params[1]
+ -- Save state. Ugly, I know. but upvalues are fast.
+ local gf, gl, gcl, gi = g_fname, g_lineno, g_curline, g_indent
+ -- Read the included file.
+ local fatal = readfile(pathopen(g_opt.include, name) or
+ wfatal("include file `"..name.."' not found"))
+ -- Restore state.
+ g_synclineno = -1
+ g_fname, g_lineno, g_curline, g_indent = gf, gl, gcl, gi
+ if fatal then wfatal("in include file") end
+end
+
+-- Make .include and conditionals initially available, too.
+map_op[".include_1"] = map_coreop[".include_1"]
+map_op[".if_1"] = map_coreop[".if_1"]
+map_op[".elif_1"] = map_coreop[".elif_1"]
+map_op[".else_0"] = map_coreop[".else_0"]
+map_op[".endif_0"] = map_coreop[".endif_0"]
+
+------------------------------------------------------------------------------
+
+-- Support variables for macros.
+local mac_capture, mac_lineno, mac_name
+local mac_active = {}
+local mac_list = {}
+
+-- Pseudo-opcode to define a macro.
+map_coreop[".macro_*"] = function(mparams)
+ if not mparams then return "name [, params...]" end
+ -- Split off and validate macro name.
+ local name = remove(mparams, 1)
+ if not name then werror("missing macro name") end
+ if not (match(name, "^[%a_][%w_%.]*$") or match(name, "^%.[%w_%.]*$")) then
+ wfatal("bad macro name `"..name.."'")
+ end
+ -- Validate macro parameter names.
+ local mdup = {}
+ for _,mp in ipairs(mparams) do
+ if not match(mp, "^[%a_][%w_]*$") then
+ wfatal("bad macro parameter name `"..mp.."'")
+ end
+ if mdup[mp] then wfatal("duplicate macro parameter name `"..mp.."'") end
+ mdup[mp] = true
+ end
+ -- Check for duplicate or recursive macro definitions.
+ local opname = name.."_"..#mparams
+ if map_op[opname] or map_op[name.."_*"] then
+ wfatal("duplicate macro `"..name.."' ("..#mparams.." parameters)")
+ end
+ if mac_capture then wfatal("recursive macro definition") end
+
+ -- Enable statement capture.
+ local lines = {}
+ mac_lineno = g_lineno
+ mac_name = name
+ mac_capture = function(stmt) -- Statement capture function.
+ -- Stop macro definition with .endmacro pseudo-opcode.
+ if not match(stmt, "^%s*.endmacro%s*$") then
+ lines[#lines+1] = stmt
+ return
+ end
+ mac_capture = nil
+ mac_lineno = nil
+ mac_name = nil
+ mac_list[#mac_list+1] = opname
+ -- Add macro-op definition.
+ map_op[opname] = function(params)
+ if not params then return mparams, lines end
+ -- Protect against recursive macro invocation.
+ if mac_active[opname] then wfatal("recursive macro invocation") end
+ mac_active[opname] = true
+ -- Setup substitution map.
+ local subst = {}
+ for i,mp in ipairs(mparams) do subst[mp] = params[i] end
+ local mcom
+ if g_opt.maccomment and g_opt.comment then
+ mcom = " MACRO "..name.." ("..#mparams..")"
+ wcomment("{"..mcom)
+ end
+ -- Loop through all captured statements
+ for _,stmt in ipairs(lines) do
+ -- Substitute macro parameters.
+ local st = gsub(stmt, "[%w_]+", subst)
+ st = definesubst(st)
+ st = gsub(st, "%s*%.%.%s*", "") -- Token paste a..b.
+ if mcom and sub(st, 1, 1) ~= "|" then wcomment(st) end
+ -- Emit statement. Use a protected call for better diagnostics.
+ local ok, err = pcall(dostmt, st)
+ if not ok then
+ -- Add the captured statement to the error.
+ wprinterr(err, "\n", g_indent, "| ", stmt,
+ "\t[MACRO ", name, " (", #mparams, ")]\n")
+ end
+ end
+ if mcom then wcomment("}"..mcom) end
+ mac_active[opname] = nil
+ end
+ end
+end
+
+-- An .endmacro pseudo-opcode outside of a macro definition is an error.
+map_coreop[".endmacro_0"] = function(params)
+ wfatal(".endmacro without .macro")
+end
+
+-- Dump all macros and their contents (with -PP only).
+local function dumpmacros(out, lvl)
+ sort(mac_list)
+ out:write("Macros:\n")
+ for _,opname in ipairs(mac_list) do
+ local name = sub(opname, 1, -3)
+ local params, lines = map_op[opname]()
+ out:write(format(" %-20s %s\n", name, concat(params, ", ")))
+ if lvl > 1 then
+ for _,line in ipairs(lines) do
+ out:write(" |", line, "\n")
+ end
+ out:write("\n")
+ end
+ end
+ out:write("\n")
+end
+
+-- Check for unfinished macro definitions.
+local function checkmacros()
+ if mac_capture then
+ wprinterr(g_fname, ":", mac_lineno,
+ ": error: unfinished .macro `", mac_name ,"'\n")
+ end
+end
+
+------------------------------------------------------------------------------
+
+-- Support variables for captures.
+local cap_lineno, cap_name
+local cap_buffers = {}
+local cap_used = {}
+
+-- Start a capture.
+map_coreop[".capture_1"] = function(params)
+ if not params then return "name" end
+ wflush()
+ local name = params[1]
+ if not match(name, "^[%a_][%w_]*$") then
+ wfatal("bad capture name `"..name.."'")
+ end
+ if cap_name then
+ wfatal("already capturing to `"..cap_name.."' since line "..cap_lineno)
+ end
+ cap_name = name
+ cap_lineno = g_lineno
+ -- Create or continue a capture buffer and start the output line capture.
+ local buf = cap_buffers[name]
+ if not buf then buf = {}; cap_buffers[name] = buf end
+ g_capbuffer = buf
+ g_synclineno = 0
+end
+
+-- Stop a capture.
+map_coreop[".endcapture_0"] = function(params)
+ wflush()
+ if not cap_name then wfatal(".endcapture without a valid .capture") end
+ cap_name = nil
+ cap_lineno = nil
+ g_capbuffer = nil
+ g_synclineno = 0
+end
+
+-- Dump a capture buffer.
+map_coreop[".dumpcapture_1"] = function(params)
+ if not params then return "name" end
+ wflush()
+ local name = params[1]
+ if not match(name, "^[%a_][%w_]*$") then
+ wfatal("bad capture name `"..name.."'")
+ end
+ cap_used[name] = true
+ wline(function(out)
+ local buf = cap_buffers[name]
+ if buf then wdumplines(out, buf) end
+ end)
+ g_synclineno = 0
+end
+
+-- Dump all captures and their buffers (with -PP only).
+local function dumpcaptures(out, lvl)
+ out:write("Captures:\n")
+ for name,buf in pairs(cap_buffers) do
+ out:write(format(" %-20s %4s)\n", name, "("..#buf))
+ if lvl > 1 then
+ local bar = rep("=", 76)
+ out:write(" ", bar, "\n")
+ for _,line in ipairs(buf) do
+ out:write(" ", line, "\n")
+ end
+ out:write(" ", bar, "\n\n")
+ end
+ end
+ out:write("\n")
+end
+
+-- Check for unfinished or unused captures.
+local function checkcaptures()
+ if cap_name then
+ wprinterr(g_fname, ":", cap_lineno,
+ ": error: unfinished .capture `", cap_name,"'\n")
+ return
+ end
+ for name in pairs(cap_buffers) do
+ if not cap_used[name] then
+ wprinterr(g_fname, ":*: error: missing .dumpcapture ", name ,"\n")
+ end
+ end
+end
+
+------------------------------------------------------------------------------
+
+-- Sections names.
+local map_sections = {}
+
+-- Pseudo-opcode to define code sections.
+-- TODO: Data sections, BSS sections. Needs extra C code and API.
+map_coreop[".section_*"] = function(params)
+ if not params then return "name..." end
+ if #map_sections > 0 then werror("duplicate section definition") end
+ wflush()
+ for sn,name in ipairs(params) do
+ local opname = "."..name.."_0"
+ if not match(name, "^[%a][%w_]*$") or
+ map_op[opname] or map_op["."..name.."_*"] then
+ werror("bad section name `"..name.."'")
+ end
+ map_sections[#map_sections+1] = name
+ wline(format("#define DASM_SECTION_%s\t%d", upper(name), sn-1))
+ map_op[opname] = function(params) g_arch.section(sn-1) end
+ end
+ wline(format("#define DASM_MAXSECTION\t\t%d", #map_sections))
+end
+
+-- Dump all sections.
+local function dumpsections(out, lvl)
+ out:write("Sections:\n")
+ for _,name in ipairs(map_sections) do
+ out:write(format(" %s\n", name))
+ end
+ out:write("\n")
+end
+
+------------------------------------------------------------------------------
+
+-- Replacement for customized Lua, which lacks the package library.
+local prefix = ""
+if not require then
+ function require(name)
+ local fp = assert(io.open(prefix..name..".lua"))
+ local s = fp:read("*a")
+ assert(fp:close())
+ return assert(loadstring(s, "@"..name..".lua"))()
+ end
+end
+
+-- Load architecture-specific module.
+local function loadarch(arch)
+ if not match(arch, "^[%w_]+$") then return "bad arch name" end
+ _G._map_def = map_def
+ local ok, m_arch = pcall(require, "dasm_"..arch)
+ if not ok then return "cannot load module: "..m_arch end
+ g_arch = m_arch
+ wflush = m_arch.passcb(wline, werror, wfatal, wwarn)
+ m_arch.setup(arch, g_opt)
+ map_op, map_def = m_arch.mergemaps(map_coreop, map_def)
+end
+
+-- Dump architecture description.
+function opt_map.dumparch(args)
+ local name = optparam(args)
+ if not g_arch then
+ local err = loadarch(name)
+ if err then opterror(err) end
+ end
+
+ local t = {}
+ for name in pairs(map_coreop) do t[#t+1] = name end
+ for name in pairs(map_op) do t[#t+1] = name end
+ sort(t)
+
+ local out = stdout
+ local _arch = g_arch._info
+ out:write(format("%s version %s, released %s, %s\n",
+ _info.name, _info.version, _info.release, _info.url))
+ g_arch.dumparch(out)
+
+ local pseudo = true
+ out:write("Pseudo-Opcodes:\n")
+ for _,sname in ipairs(t) do
+ local name, nparam = match(sname, "^(.+)_([0-9%*])$")
+ if name then
+ if pseudo and sub(name, 1, 1) ~= "." then
+ out:write("\nOpcodes:\n")
+ pseudo = false
+ end
+ local f = map_op[sname]
+ local s
+ if nparam ~= "*" then nparam = nparam + 0 end
+ if nparam == 0 then
+ s = ""
+ elseif type(f) == "string" then
+ s = map_op[".template__"](nil, f, nparam)
+ else
+ s = f(nil, nparam)
+ end
+ if type(s) == "table" then
+ for _,s2 in ipairs(s) do
+ out:write(format(" %-12s %s\n", name, s2))
+ end
+ else
+ out:write(format(" %-12s %s\n", name, s))
+ end
+ end
+ end
+ out:write("\n")
+ exit(0)
+end
+
+-- Pseudo-opcode to set the architecture.
+-- Only initially available (map_op is replaced when called).
+map_op[".arch_1"] = function(params)
+ if not params then return "name" end
+ local err = loadarch(params[1])
+ if err then wfatal(err) end
+ wline(format("#if DASM_VERSION != %d", _info.vernum))
+ wline('#error "Version mismatch between DynASM and included encoding engine"')
+ wline("#endif")
+end
+
+-- Dummy .arch pseudo-opcode to improve the error report.
+map_coreop[".arch_1"] = function(params)
+ if not params then return "name" end
+ wfatal("duplicate .arch statement")
+end
+
+------------------------------------------------------------------------------
+
+-- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'.
+map_coreop[".nop_*"] = function(params)
+ if not params then return "[ignored...]" end
+end
+
+-- Pseudo-opcodes to raise errors.
+map_coreop[".error_1"] = function(params)
+ if not params then return "message" end
+ werror(params[1])
+end
+
+map_coreop[".fatal_1"] = function(params)
+ if not params then return "message" end
+ wfatal(params[1])
+end
+
+-- Dump all user defined elements.
+local function dumpdef(out)
+ local lvl = g_opt.dumpdef
+ if lvl == 0 then return end
+ dumpsections(out, lvl)
+ dumpdefines(out, lvl)
+ if g_arch then g_arch.dumpdef(out, lvl) end
+ dumpmacros(out, lvl)
+ dumpcaptures(out, lvl)
+end
+
+------------------------------------------------------------------------------
+
+-- Helper for splitstmt.
+local splitlvl
+
+local function splitstmt_one(c)
+ if c == "(" then
+ splitlvl = ")"..splitlvl
+ elseif c == "[" then
+ splitlvl = "]"..splitlvl
+ elseif c == "{" then
+ splitlvl = "}"..splitlvl
+ elseif c == ")" or c == "]" or c == "}" then
+ if sub(splitlvl, 1, 1) ~= c then werror("unbalanced (), [] or {}") end
+ splitlvl = sub(splitlvl, 2)
+ elseif splitlvl == "" then
+ return " \0 "
+ end
+ return c
+end
+
+-- Split statement into (pseudo-)opcode and params.
+local function splitstmt(stmt)
+ -- Convert label with trailing-colon into .label statement.
+ local label = match(stmt, "^%s*(.+):%s*$")
+ if label then return ".label", {label} end
+
+ -- Split at commas and equal signs, but obey parentheses and brackets.
+ splitlvl = ""
+ stmt = gsub(stmt, "[,%(%)%[%]{}]", splitstmt_one)
+ if splitlvl ~= "" then werror("unbalanced () or []") end
+
+ -- Split off opcode.
+ local op, other = match(stmt, "^%s*([^%s%z]+)%s*(.*)$")
+ if not op then werror("bad statement syntax") end
+
+ -- Split parameters.
+ local params = {}
+ for p in gmatch(other, "%s*(%Z+)%z?") do
+ params[#params+1] = gsub(p, "%s+$", "")
+ end
+ if #params > 16 then werror("too many parameters") end
+
+ params.op = op
+ return op, params
+end
+
+-- Process a single statement.
+dostmt = function(stmt)
+ -- Ignore empty statements.
+ if match(stmt, "^%s*$") then return end
+
+ -- Capture macro defs before substitution.
+ if mac_capture then return mac_capture(stmt) end
+ stmt = definesubst(stmt)
+
+ -- Emit C code without parsing the line.
+ if sub(stmt, 1, 1) == "|" then
+ local tail = sub(stmt, 2)
+ wflush()
+ if sub(tail, 1, 2) == "//" then wcomment(tail) else wline(tail, true) end
+ return
+ end
+
+ -- Split into (pseudo-)opcode and params.
+ local op, params = splitstmt(stmt)
+
+ -- Get opcode handler (matching # of parameters or generic handler).
+ local f = map_op[op.."_"..#params] or map_op[op.."_*"]
+ if not f then
+ if not g_arch then wfatal("first statement must be .arch") end
+ -- Improve error report.
+ for i=0,9 do
+ if map_op[op.."_"..i] then
+ werror("wrong number of parameters for `"..op.."'")
+ end
+ end
+ werror("unknown statement `"..op.."'")
+ end
+
+ -- Call opcode handler or special handler for template strings.
+ if type(f) == "string" then
+ map_op[".template__"](params, f)
+ else
+ f(params)
+ end
+end
+
+-- Process a single line.
+local function doline(line)
+ if g_opt.flushline then wflush() end
+
+ -- Assembler line?
+ local indent, aline = match(line, "^(%s*)%|(.*)$")
+ if not aline then
+ -- No, plain C code line, need to flush first.
+ wflush()
+ wsync()
+ wline(line, false)
+ return
+ end
+
+ g_indent = indent -- Remember current line indentation.
+
+ -- Emit C code (even from macros). Avoids echo and line parsing.
+ if sub(aline, 1, 1) == "|" then
+ if not mac_capture then
+ wsync()
+ elseif g_opt.comment then
+ wsync()
+ wcomment(aline)
+ end
+ dostmt(aline)
+ return
+ end
+
+ -- Echo assembler line as a comment.
+ if g_opt.comment then
+ wsync()
+ wcomment(aline)
+ end
+
+ -- Strip assembler comments.
+ aline = gsub(aline, "//.*$", "")
+
+ -- Split line into statements at semicolons.
+ if match(aline, ";") then
+ for stmt in gmatch(aline, "[^;]+") do dostmt(stmt) end
+ else
+ dostmt(aline)
+ end
+end
+
+------------------------------------------------------------------------------
+
+-- Write DynASM header.
+local function dasmhead(out)
+ out:write(format([[
+/*
+** This file has been pre-processed with DynASM.
+** %s
+** DynASM version %s, DynASM %s version %s
+** DO NOT EDIT! The original file is in "%s".
+*/
+
+]], _info.url,
+ _info.version, g_arch._info.arch, g_arch._info.version,
+ g_fname))
+end
+
+-- Read input file.
+readfile = function(fin)
+ g_indent = ""
+ g_lineno = 0
+ g_synclineno = -1
+
+ -- Process all lines.
+ for line in fin:lines() do
+ g_lineno = g_lineno + 1
+ g_curline = line
+ local ok, err = pcall(doline, line)
+ if not ok and wprinterr(err, "\n") then return true end
+ end
+ wflush()
+
+ -- Close input file.
+ assert(fin == stdin or fin:close())
+end
+
+-- Write output file.
+local function writefile(outfile)
+ local fout
+
+ -- Open output file.
+ if outfile == nil or outfile == "-" then
+ fout = stdout
+ else
+ fout = assert(io.open(outfile, "w"))
+ end
+
+ -- Write all buffered lines
+ wdumplines(fout, g_wbuffer)
+
+ -- Close output file.
+ assert(fout == stdout or fout:close())
+
+ -- Optionally dump definitions.
+ dumpdef(fout == stdout and stderr or stdout)
+end
+
+-- Translate an input file to an output file.
+local function translate(infile, outfile)
+ g_wbuffer = {}
+ g_indent = ""
+ g_lineno = 0
+ g_synclineno = -1
+
+ -- Put header.
+ wline(dasmhead)
+
+ -- Read input file.
+ local fin
+ if infile == "-" then
+ g_fname = "(stdin)"
+ fin = stdin
+ else
+ g_fname = infile
+ fin = assert(io.open(infile, "r"))
+ end
+ readfile(fin)
+
+ -- Check for errors.
+ if not g_arch then
+ wprinterr(g_fname, ":*: error: missing .arch directive\n")
+ end
+ checkconds()
+ checkmacros()
+ checkcaptures()
+
+ if g_errcount ~= 0 then
+ stderr:write(g_fname, ":*: info: ", g_errcount, " error",
+ (type(g_errcount) == "number" and g_errcount > 1) and "s" or "",
+ " in input file -- no output file generated.\n")
+ dumpdef(stderr)
+ exit(1)
+ end
+
+ -- Write output file.
+ writefile(outfile)
+end
+
+------------------------------------------------------------------------------
+
+-- Print help text.
+function opt_map.help()
+ stdout:write("DynASM -- ", _info.description, ".\n")
+ stdout:write("DynASM ", _info.version, " ", _info.release, " ", _info.url, "\n")
+ stdout:write[[
+
+Usage: dynasm [OPTION]... INFILE.dasc|-
+
+ -h, --help Display this help text.
+ -V, --version Display version and copyright information.
+
+ -o, --outfile FILE Output file name (default is stdout).
+ -I, --include DIR Add directory to the include search path.
+
+ -c, --ccomment Use /* */ comments for assembler lines.
+ -C, --cppcomment Use // comments for assembler lines (default).
+ -N, --nocomment Suppress assembler lines in output.
+ -M, --maccomment Show macro expansions as comments (default off).
+
+ -L, --nolineno Suppress CPP line number information in output.
+ -F, --flushline Flush action list for every line.
+
+ -D NAME[=SUBST] Define a substitution.
+ -U NAME Undefine a substitution.
+
+ -P, --dumpdef Dump defines, macros, etc. Repeat for more output.
+ -A, --dumparch ARCH Load architecture ARCH and dump description.
+]]
+ exit(0)
+end
+
+-- Print version information.
+function opt_map.version()
+ stdout:write(format("%s version %s, released %s\n%s\n\n%s",
+ _info.name, _info.version, _info.release, _info.url, _info.copyright))
+ exit(0)
+end
+
+-- Misc. options.
+function opt_map.outfile(args) g_opt.outfile = optparam(args) end
+function opt_map.include(args) insert(g_opt.include, 1, optparam(args)) end
+function opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" end
+function opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" end
+function opt_map.nocomment() g_opt.comment = false end
+function opt_map.maccomment() g_opt.maccomment = true end
+function opt_map.nolineno() g_opt.cpp = false end
+function opt_map.flushline() g_opt.flushline = true end
+function opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end
+
+------------------------------------------------------------------------------
+
+-- Short aliases for long options.
+local opt_alias = {
+ h = "help", ["?"] = "help", V = "version",
+ o = "outfile", I = "include",
+ c = "ccomment", C = "cppcomment", N = "nocomment", M = "maccomment",
+ L = "nolineno", F = "flushline",
+ P = "dumpdef", A = "dumparch",
+}
+
+-- Parse single option.
+local function parseopt(opt, args)
+ opt_current = #opt == 1 and "-"..opt or "--"..opt
+ local f = opt_map[opt] or opt_map[opt_alias[opt]]
+ if not f then
+ opterror("unrecognized option `", opt_current, "'. Try `--help'.\n")
+ end
+ f(args)
+end
+
+-- Parse arguments.
+local function parseargs(args)
+ -- Default options.
+ g_opt.comment = "//|"
+ g_opt.endcomment = ""
+ g_opt.cpp = true
+ g_opt.dumpdef = 0
+ g_opt.include = { "" }
+
+ -- Process all option arguments.
+ args.argn = 1
+ repeat
+ local a = args[args.argn]
+ if not a then break end
+ local lopt, opt = match(a, "^%-(%-?)(.+)")
+ if not opt then break end
+ args.argn = args.argn + 1
+ if lopt == "" then
+ -- Loop through short options.
+ for o in gmatch(opt, ".") do parseopt(o, args) end
+ else
+ -- Long option.
+ parseopt(opt, args)
+ end
+ until false
+
+ -- Check for proper number of arguments.
+ local nargs = #args - args.argn + 1
+ if nargs ~= 1 then
+ if nargs == 0 then
+ if g_opt.dumpdef > 0 then return dumpdef(stdout) end
+ end
+ opt_map.help()
+ end
+
+ -- Translate a single input file to a single output file
+ -- TODO: Handle multiple files?
+ translate(args[args.argn], g_opt.outfile)
+end
+
+------------------------------------------------------------------------------
+
+-- Add the directory dynasm.lua resides in to the Lua module search path.
+local arg = arg
+if arg and arg[0] then
+ prefix = match(arg[0], "^(.*[/\\])")
+ if package and prefix then package.path = prefix.."?.lua;"..package.path end
+end
+
+-- Start DynASM.
+parseargs{...}
+
+------------------------------------------------------------------------------
+
diff --git a/LuaJIT-2.1/etc/luajit.1 b/LuaJIT-2.1/etc/luajit.1
new file mode 100644
index 00000000..c16b4172
--- /dev/null
+++ b/LuaJIT-2.1/etc/luajit.1
@@ -0,0 +1,88 @@
+.TH luajit 1 "" "" "LuaJIT documentation"
+.SH NAME
+luajit \- Just-In-Time Compiler for the Lua Language
+\fB
+.SH SYNOPSIS
+.B luajit
+[\fIoptions\fR]... [\fIscript\fR [\fIargs\fR]...]
+.SH "WEB SITE"
+.IR https://luajit.org
+.SH DESCRIPTION
+.PP
+This is the command-line program to run Lua programs with \fBLuaJIT\fR.
+.PP
+\fBLuaJIT\fR is a just-in-time (JIT) compiler for the Lua language.
+The virtual machine (VM) is based on a fast interpreter combined with
+a trace compiler. It can significantly improve the performance of Lua programs.
+.PP
+\fBLuaJIT\fR is API\- and ABI-compatible with the VM of the standard
+Lua\ 5.1 interpreter. When embedding the VM into an application,
+the built library can be used as a drop-in replacement.
+.SH OPTIONS
+.TP
+.BI "\-e " chunk
+Run the given chunk of Lua code.
+.TP
+.BI "\-l " library
+Load the named library, just like \fBrequire("\fR\fIlibrary\fR\fB")\fR.
+.TP
+.BI "\-b " ...
+Save or list bytecode. Run without arguments to get help on options.
+.TP
+.BI "\-j " command
+Perform LuaJIT control command (optional space after \fB\-j\fR).
+.TP
+.BI "\-O" [opt]
+Control LuaJIT optimizations.
+.TP
+.B "\-i"
+Run in interactive mode.
+.TP
+.B "\-v"
+Show \fBLuaJIT\fR version.
+.TP
+.B "\-E"
+Ignore environment variables.
+.TP
+.B "\-\-"
+Stop processing options.
+.TP
+.B "\-"
+Read script from stdin instead.
+.PP
+After all options are processed, the given \fIscript\fR is run.
+The arguments are passed in the global \fIarg\fR table.
+.PP
+Interactive mode is only entered, if no \fIscript\fR and no \fB\-e\fR
+option is given. Interactive mode can be left with EOF (\fICtrl\-Z\fB).
+.SH EXAMPLES
+.TP
+luajit hello.lua world
+
+Prints "Hello world", assuming \fIhello.lua\fR contains:
+.br
+ print("Hello", arg[1])
+.TP
+luajit \-e "local x=0; for i=1,1e9 do x=x+i end; print(x)"
+
+Calculates the sum of the numbers from 1 to 1000000000.
+.br
+And finishes in a reasonable amount of time, too.
+.TP
+luajit \-jv \-e "for i=1,10 do for j=1,10 do for k=1,100 do end end end"
+
+Runs some nested loops and shows the resulting traces.
+.SH COPYRIGHT
+.PP
+\fBLuaJIT\fR is Copyright \(co 2005-2025 Mike Pall.
+.br
+\fBLuaJIT\fR is open source software, released under the MIT license.
+.SH SEE ALSO
+.PP
+More details in the provided HTML docs or at:
+.IR https://luajit.org
+.br
+More about the Lua language can be found at:
+.IR https://lua.org/docs.html
+.PP
+lua(1)
diff --git a/LuaJIT-2.1/etc/luajit.pc b/LuaJIT-2.1/etc/luajit.pc
new file mode 100644
index 00000000..96433008
--- /dev/null
+++ b/LuaJIT-2.1/etc/luajit.pc
@@ -0,0 +1,25 @@
+# Package information for LuaJIT to be used by pkg-config.
+majver=2
+minver=1
+relver=ROLLING
+version=${majver}.${minver}.${relver}
+abiver=5.1
+
+prefix=/usr/local
+multilib=lib
+exec_prefix=${prefix}
+libdir=${exec_prefix}/${multilib}
+libname=luajit-${abiver}
+includedir=${prefix}/include/luajit-${majver}.${minver}
+
+INSTALL_LMOD=${prefix}/share/lua/${abiver}
+INSTALL_CMOD=${prefix}/${multilib}/lua/${abiver}
+
+Name: LuaJIT
+Description: Just-in-time compiler for Lua
+URL: https://luajit.org
+Version: ${version}
+Requires:
+Libs: -L${libdir} -l${libname}
+Libs.private: -Wl,-E -lm -ldl
+Cflags: -I${includedir}
diff --git a/LuaJIT-2.1/luajit b/LuaJIT-2.1/luajit
new file mode 100644
index 0000000000000000000000000000000000000000..d53e664dde79d7455f62eb9944f31c3b5f5edd80
GIT binary patch
literal 587644
zcmeFae?U}a_CJ0HMwpbE$)=*3YHX*1LW5!plD1J1P)SEcrLuqoghC;hQ7o&Wf#mM>
z)>Ll!u6DE5ZQae?rOk-UY5)baGW?OD_JhjmPNOZFDgH>luk+k9fV1z<_pi^NA9k;=
zd+zf*=Q-y*=Q+=h``qcV$+=kugFy=aMN82VQOVholnVUlh)E=+N_HtuN|3IQE|+5P
zgwn#77X|1t;u&4hxHfx8eZP=wMnuZ)-Nx38b?b)ZYm!IHr+p&r0z5NWr9$2kzT}ut}f8wD-$$b
z;WX4N4d)M1O6GL1mt5buiyK>FrSNq$QIhBim!FArDiirf^;7v-NFUC>?>tGOi^`Mz
zZm1}~?}m!vu@&WuJ+2mKN7rq@@Ty?nUk92(kS0gSN*Y9zuxajXG
zTz+vUNzVdT;rauv=WwmY^#ZOJanavPI*5P&h<{&ZdJW?%jDG>X#`k|^{5#`682<@;
z1J}QCy@_iBu4Y_s<7&b64z71`ZNl{)F8ccbSAcHt*N$tmxYPgH0_b463%C{6He4U$
z`UKYwTsv`nit966J-GJa+K=lCT)nvH?`vG&;QAKV0bJkXqCX8+2-iVeKj8}h9p;-O
zjQ!yR;0au(nf{gW450!4#}$Rkh-(C{7+kTqsBgCKDLMC&k00B3^TBtvei(acTKb3c
zpS@E%bnwJ0cV4{Xjk#AfIpQzL+q`GYK;Dvl4?U8S_@}7v8$a7JX8L(GpT0jgDtTJe
zMa>_a^WoULA7A;nV*bzQ^sigSZ8)%GscZko-~Op_!ts>LOHTI8JG$@tf9|Wh_44FV
zx5xcsd4+#doqdW&-k$UiTgHpQgj~6GWBI5}*SvP)qQA6n`*T71o98xtaK-pK`!Byd
zF=NsP1qGSqmfQb5{>@{`i+4_Fol}&aGA<|XH>-bs_)qWKGQNKJ-hzK;JIDNd>h22P
z^pUsUbl?6%uVh!g+!$-U{eimC=~|-TBNLyDmLfyY6=ik>Bh(mDezGUiF@-N%ueY
z!t$KP7gDAy_}9+zeMjakY5K{r>9vdp{&Cm$pLLdR`()Je`1>gB7O3(3{?KH
zVd>|C9vM-eYgjtv&xlC>FoNG9EtM$m6YzasK4jG%W#&^sc^w+xey>{${)Ul*a@
z^TW!M{|+CAseDvK{$GaWr}Ul(+80sZtOzRiP^u7ps
zYD9gjBIth`iL?Gk{AunQ{v&!xm;e$To(s}rq6_GT|A>ymqGQcCgER&AqowntzmCNG
z>_JJolIi1^JNH4TM5bfounxJ&Anj%P9;7=_p8Sf+A2Zn9TPe5?vi!QO>AQ4-C?
zDE$NEubLhu=Ga7g(VtwWMo6n*2cn-tdN&%C=HP;kfqcnB^0gs_Hl|FkIS
zw_N@Yqag1TgY-P7H-TU8B?jppPQL~Gnr=5p-JHH0bnnIyVvbJrErdO)QVi1naJm(W
zB;R2W^Giy<4(Z)D8pPb6=)I^1@9?CHJUAbrm1d#L<%Sfg`#KJxpg8YDat`6obL3;ajs{QE&W?}!oe
z9OCB%zdi`-=KL+F-0_9_4fdlwjhmUC3x2NKhWI(i
z{v!?2bms2^Eln^;OPJmcds*O5?{j%88mJh;$Tep`&x$o{ty`u3s!(wdOUH$ndH-x;JC;ry^~
zArc|3NdGDX^5jNIFuBM-i}j>wKoWiCzosQo($}2cf{ay=
z?>VNQr~a8SG@t21{$BXYg`9rNu=cW`y=2gZlML7y)$4PhKO}!_kb<25B9j07q5e@p
z_C@~+%X6qMIgE=W%=D6Lsg
zv>4SRxkiW#ElTxE3&
zsxBd@(s`6FtuA+$NTt;!Ma5Ee$zp0AC{wgRm-PWENp>tQFV*b>orHNG5Y}=pswyq7
zC=miLs4XfeEr+$s9|DhMkh=ngFL5uq&r?d0FREOEipbi?PHgnnV*e|^>y-uE85R|x
zc}n#JJYGa^TW*$cS6rdLc){($1;|ZQ3MDMivlQrD7Swo1l5(lSQ$+O@lvmPi!Gf}q
z1<P+#L_Z!XORmfxID2E
zjw7Cf7_5XiqnXG^x^k4`?1#Dtxdra(q6H=Qg@toh-d9-(A3=8~5y+T}O58=F0yK6_
zNp&%Tfu0CKNs7^7H_%11_uA%Tl_oUF0
zQkH@qR2MCUH7Jd_FZL|DPj5$Rq_WCNz3pp-H;QbiKdeWX9x9Y8s;Dlh@l@zGKn0}2
zpp^F`3W;LW#6$T=6+Pw)IU&=ae+>GQXfL5^amjt2g(Bmi(Wy;^0jU*p=S(QbE^*I6
ztLH7NVnZ$v1u9BvYTRYIn+REld9L8SsK{L=a+cQ&sU>o{%S5k-^aYjo-A{2%C_*kl
z%7{i5EQajMMm@`3RcKz_g+w(F9KKq)Ks2P@Kt&ZEU1n;o;jQJa)J4+$33k<6xuAgD
zX{f*C!UdP2OCeB^u*g?R;f?M|SaE|KXLkzWTf>YYIyht-awOeXbSFc!a8rc~9-vWK
zXIbn)grZ8$sy!@oSQJmylC$(1W@MORs5a7lSeHhOsS;6UFvg%?42wC#V%4yyMq*OM
zh!!O^ZqHz^D{@yAEiM-x!A;~2`w2Nx*jgk*Mft)q_i$5@J%?J1ix06buMr(N-2H?@
z+y^NNN)~hP7Cl0jYGIA%KB=Izs-SGCu+M@@3|C}AQS*==VRTzSAxn%hLZ71I;-O>;
zklf7+ZY)SCNV(;vn{P==xg{0T8!#(hjE=zFv1F(t3zHQs)+frV~X6Q-_Z<fd3n~|59;26lJ;*?VmFccggej&_erRYJ9Em20P(GPvN)*cm
z-8by4qN5M;6viZ8g0Ze*!SG0fx;?ttS(|dI(Nb>Lr7c2_ASr?y#WJ!=o$gF)SG94MTx6oO{TVxagvy8htb(Q|U3V
z9MN11soA+xCQd525!0LSU9yxtX;Q&W<8ERE&3SGdyi1`}etOH`-Hqv3k3>my%E*Xo
zgt()VH}oX@KRW3{>3S;VGU0#GSeuQ&xfH!*wBRy|d0{bx=OYG7=$v9XmCDlpqL|j}
zr+=eF3GCuZv79F?1J$LMITuJWpPeHL@)3W-|NGznB@0AJcfioJf0c~u{POa1CFxvg
zJl4hZ%pz!$G#NDg8PF>EoZkt0_BG3}f{&ACoR$9^k)O)DM0%_=Z?OCbsg%nXB7L;r
zKT0a#@-Tt*jT9%CV6F=H8H1!EPXo3WO0Iir`c
zp0SZ}CF2^#wT$Z+*E2RTZeVO-+{74Q+|1a;_z`0_<8H_dc
zGoEIYa1N5%$H-`6jAOJgS{dURZH#tC2cwfQlQD-em(j(T$C%GJpRtg!n6Zqpg0YIx
z%~;F0oYBiz&)CSglF`q&ig69&TE=yZ>lvFEH!!v^Zek2DZf5La{D`reaW`WR_dcGoEIYj&eIPni%64EsR#ict#teozcOVz?j6C%$UlU#+bqAWXxpD
zVa#Q8G3GJmGtOr$WGrSZW2|8GGS)LTGOlFwGp=G>&G-`I8pgGZ>loKFHZcYmH#2rI
ze#F?#xSO$uv6t}xqsDlUv5)a6V?X0*M(G!BKSmQ{9HWKN${5dRW3)3m7!w$i7?T-O
z8Pgau7@drTjKz#)j1`PkjBdtS#^sD(Ks^#+8hI##M}K7}qkcV_eVJ#JGX6g>e&O
zfN?Wp7vo2a-Hf{#dl-8e4=`$s2O0Yqk23Z%o@S(jA7UJ1G%?y49gGQ#NsP&isf=li
z8H`TGLdIgoGR6wVDn>VBE#q=VFJnDpBjXyzwT$Z+*E4QlY+>BQ7+~yWJiw?i9%Sre
zJjy5?XFD;P7~>c%jCMu`V*+CmV=`kZV;W-yqmwa{F^4gi(Z!g@n9n$$v5>Ktv5c{T
z(aTuR*vPn&(a*SwaW&&hjB6OzGOl9`Fm7h-V*H4)n{hW|598;Iy^IGKHO7OCeT+vL
z`x&KvZWl%qqn**gn829Cn9P{Un8ujF=w!@f%wf!BbTQ^J<}=P`EMzQZEMu%-tYUOC
z)-o<<^fJ~nHZrbc^fRtvT+R3r;~K`bjO!TJGd3}9U~FOB#28@Q%-F^F5o0&wZpI$Q
z&l!6e4=`$s2O0Yqk23Z%o@SIzaJw>^7~>c%j8?{YMjNA@(ZQI&n8cXOn97*On8D~|
z%w)`A%w=>j<}v0o&SxxSEM_cYtYEBSbTig6E@$*I)-yITu4MExu3}ux_!8q9#YXNVcf(RVBE~u#rP3pH{))`9>&iZdl?TfYK#XN`xuWh_A{PllumN{GnyFV
z7%hxe#&|{>qn**gn829Cn9P{Un8ujF=w!@f%wf!BbTQ^J<}=P`EMzQZEMu%-tYUOC
z)-o<<^fJ~nHZrbc^fRtvT+R3r;~K`bjO!TJGd3}9U~FOB#28@Q%-F^F5o0&wZpI$Q
z&l!6e4=`$s2O0Yqk23Z%o@SIzar-lx7~>c%j8?{YMjNA@(ZQI&n8fI0%wcpf<}(&D
zmN8Z_)-rk-8yWqKs~OiYu48OsY+(#Ab}@D{_AvG`YK(o1{fyFS-99Ep3u8Q^oiTwi
znK6yg$(Y0FV$5eOWGrK>VytEKGBz^$8CNr|VNAm}l{CL}GUhP481oqm8Os=}82yZ^
z8P_nbV{BqT;oCdH9DH9&
zco*$}o+G}Qvk*qnc_1M6A>#=lhm84UPxu=;-w#B4tt7k}XP*eKp>H>VX!q5G
z3G|%^Fj11$5MC!qYYCGiX&oUBSFI-;2R|Xafxf{6Ce!zqKpbA%M0g|ohVUl(-V%uR
z>mtNqxQ__oSKWlSNYZXXy!7ZH#9_A232{iWmk|DQfDnGC5#CPUQUaauGr|dISHg+#
zH^NEu?IbW$!Ui~SGWH`0v*>6bFdOYp2>-MYPDT3@PDA?>=A!)x??C$#PDlF_;?QdX
zA^bRra3Yv_Ii}Xn(>5Xn(?Dv_D}9+Mlo#`v1Sb|0@=l?K^1F=wphy
z_TwLzB*k}NU|^sj;Eo#T_H8!Z-9GT95%moGnPMva4g49wNSwNqg1yK(@Mi=Asf?0?
z-GWBvm&)j2Fd%3;u~|m{1e*kn&MlSMiC!aUx-CP`l!AUiJBUV)lY(ABQ&L$P(N%&*
zXO+sFL>CI0vXpwUUBGC$D)K~vRbtBGzBG&+M+wub06f-WR_
z9npS4!`Y>>CZfH9Ceg}Th^`WJ1ZlaxnCeh1!h)x#ta-w^Q
zwhP)zv_`Z=(Dg+35iJS2k?4M+`+g<;R}zi)Z_r=Rexh+Q8Tt!)7121^4gCeZnrJ!(
z9&8fyOGMj=UL)u=L?;mK7xY@9lZo~UdL7X?X$$=Yy`E?%(S?F;BAQO>23>;QKr|hz
z4LSwgLUcaS$%5WQbRp4pK?jH~BibV9%|urbEeV=TTUJYS-)YkSBci=T_X?U!UDil+
zx1e_u?I$`QXfl1-YNDG2{W;NVh+ZS;UZU3#?HBX`qML~J3YwaxtcB<*K_4VKKy;y?
zsj14kh;|A3DACnn#-VYvKhct)O+@z--FJ%g
zr!QK{q$tq6g0>KCBD!19R-!FL2Lv5YbUe{bf~GH!%Irk15wxA?1fusdqy33?3ObGGe4>*DjYHaKf1>Szb`o7iv_;UF
zL{||l2|9;p`fMiHcT)6!qP;}-3fe_?qMHOgpXfD2uMu=1
z(d&rz3%Z!-CZfH9E+e{y=qf>15FH@8P|#IGcM`WI-<{x|e9X
zpnIWIDRpA;C!Y+y^OPjLVgzL#^$I;RkLt{H#M50c1$H=MK0nV9AN*otl(hG!;B%Xz
zB>Cf@_xWfkCD2~#Z;7US7vC8JGPtQcMk+Nw+F5F@>9*r$OK`4=C;p-T`RB;r&6_)0
z`wpe*+CA@>B;SEP-$9GwiBn=Q3_a*glRU-Rl2K7oLqP6ym&+LrWwJ?rb1k%xee3XV
zNlcF|93W3>eqUSN!!E3#SB
ztSOLFfn*BgQXrRab4I%#d{P2%ebf)Hlk?zjQ{Zo*ZnmKBpbbptJL0v`Lc>>^p&`6d
z$#mGEsrLEtfdSRm1Zg*tRYj7I9PAw|wj}V26B;Au&if?^BE(SuBw
zK!~R+Fa}Yfr>?~hUB
zKA?w>UWtdQPhBgjF%2bm{wm5`fV#xPp$f^~y1*pu2U{qgyXP$454|gd73LI{APbl@
z-yYahnAk1+1g41-33p+&^WPP5^ZDnz)7LXFFi-BB`##xe_Ior3(y}lT*0t~1K-wk=
zBWFO71l?XHEf!<6>iddGc(aj$&fy;*7`Y$rKix<qlcs8{z$DDccXLIF_+1j@ljOyBJ-ZV*d2W{wI
z4Li;CUlDI|naL>o-cLQkMkcbUwh9qIn8OsdjtB-SECB865256ci4b9618t42pIYIt
zkU3g^9vB!hJY2UBQ$@w6kzFM@iS#hFNDxIBryaTFwv+&ZXF3wKUB8G}ILf=+XdY><
zUx^AEFpj$Mz+t(~Tu=5Ftq;c6_VOT7x0zJajiN_fq23)~zhD)O+FKY9Q+B=sQK)z#Fi`p_?o77(cOxpWG;(4Ejg7#GwC-*3;222}e*CLMW(NLCwP=AjS_}z71&0
zy7o-S*RWGaxQAr)#LIpERZ`c#bI4EN#U%(Dh$K58PK24YsXIl|7208R$|3(iAtyM6
z{-oPe^&Nl_L;L2;6W)8Z5a%s?m5l*T5mO16nuY>#ulgR4
z?HJ+`|_1&c?749yB{xTFdZ$R|cS-`!)nFlnJ_QVb}1C4qWV)PUa
z{EgQj`TC>H^?T7Gn9&(Ua1^m0<2O{p5M}Z8518w_kU}9O3YfALUB6G84E^ZQf2cL#
zh*v{+&`*wqD}Yvgb9MbpErTw6L)sZ74Y&s^G*7v~h
z$e40SZ!*$>!qXdAY2h*M;llIv`i$ECFE9R`WnfqGkvjDFYj6Yk)(
zy3b;|qX#PC=|O5~ntxENz6G(buD$ag`ruE#htg4x;%ohY`87@}2F(!+p6%>%Bpvk-q=>H#+265%0J^?x*p2K8C_o
znCRBEJ0K!8In7OIe(8`ugRK(ek2NbM=(vr;L(y~KFIwOcp+PEGe*kUuZaQAq;1;0)
zVv9`yGeji^ri2L?;o9|h0HIl*OLcuVhIalR^a*~<`p|msEPcLu1NuC7mOgXjE%Q=eWdNBpTAT+{ztK`Wd@x?G0rw@iSGL`>K{N)Z$4aAfChL1L-e)y6xv75RF
zWj)h_cr(`k6SX9vQL?FDAcsx+j$A>^B;*eF1?g>`PRf1*vWGqq@}YM31H_D;XCtHp
zAB4rgKWUil2J|RV?hB|@k
zqCS71Kmqxy1ta%GRK;NAxebO!52E>lapsu;QLWaGu{rb<&l{k_fG+=Xj>CyU2lv%l
zH}btNSivm1#Hi=ef1#D8Q!Am_{M;{haYXXZNjXI8{a?`i>e?IrrjM6yhf98w?5X&~
zx}E}cr`CE89%LKQo_30<-=D)1dT-iT&opzh%iuk^#QfA{u%P#3ruoU=qrCUW$=;JG
z<`pq`Xl~xAY#VhqA!S3s|
zpw%4ah8ZK!-~P%BrP2|ly}!b9OT0q)GGI*3KQ1i
z@da0A3}AY_Z=&LnAxRp)++p+V
zMn2W|_RC_jppSTigYTzURDipK3^xT@9D`a>=7uM6>s#)y8qDpzfLGEmsCDQOLuA~b+DH)k7?W@KEx^kH*zKw0T4%!8@-4ty=zos3$K
zDg1i)hxg=Ib3+ZP)*GQ5cVy-PXdgCp{U4Ao_!UMwuG)(qC^XkUM-S#jsmgmKSf6%<
z7$5bSiSD11$5%M4=9P2cZ)DAst?6P@NLFZP$NbbkP#5WL@Z3$wdZM}EIfMmz9D{Wd
zZZRB^f?5GaN3t0GID_J&q4GT!o?|tj&q3nCeI6an2FH>y?7fKf0wmjfSim6!e+--{
z0X^z2k%S%%$509CkDsh8x6p8-$D)ngT>3Ub8-gg0M%uAm?CaqP;ugeX>}mCBr!lUP
zh(-vfOXDL=ht;{^8q!6#-(u7Y`%!$q4G)C_Qh1LE4uV-5^?
z9UEyeETX({Nt1Rtgw$8ML$QU%5|oKT(qLer2VcJ)@gVTehzB#!4+di+71@s1;p>kv
z*I$i>$AcCTfT=HR{yQG@Y3H&77@$6-4+b(fD)S8(%`SmuV9NMEaXbGF}?C>6#ZD>$9%ht1ychG($aSG*yv-D{z5ZFn!
z7hx;5-ciiGsAC78!>kte)4e&*Vhk4016}#Ep05!0_H{-DN0G_(95g={KdtwkPzJLX
z?K=3n>ie5+eX+PFVXWU`6rl}p3fD$N`zUppfhtv#-Xs5}$ENz7iZQ|5&M-Xf1#nTD;z)w*+&tVra-VrpRATgRiwOBAr
z1b3qtk7pZ5Qgr+ycvDInA=qp{FY~53&Gq!-Gph2Y9;>Pm3S`lyWJ(8GMGwOD4}&|K
z1LKVdGw)EC5q3eW!B`>U0QT{Q!b~b^3r-j+DW3>BA(Pl26Aey&QMnFA`|j-a5UX{}
z@4*c}NiJf*(9WCcdxf>x{Vi0cTt;5KLc^*b_*q=bSI|uOAW(!6)t7jOy(H!T
z=KmCvmPixfRsl?5gF#43{SUKpibN}+7fm#SkC21uenn%ZYHd`aXrv$Kt;Mf0B`C8_
zdvC=s@+1WCK4ich?LT`TqEY=J+zt8{G$8+RKS*V2IEb{YCFGcql{~3!$-I{1L4+3j>?5U<1wZ
zuxX*2>Yx1}4#}_6s1y7P0tMdltUv~E*hr3uGz28g3dW(g@Gx=)914&a?uptnhawF2
z^;&Rz06fB58rEP1%qJGc4H#a<`!;<(8B~#trRsCJ
zFNca*R@K#?zN==m;yUeXH!043dG={}Qonq!6*6k2laL456%_QHwcn2Y$xh5y%g@JK
znvPHZBvxPKxJp3+I%>S)v^4BD*Z+<@(ABSG(^z7adwjj86=zyQpw=}W8w}&$Gzelu4;_b^=~{oq%mZgKqKJEkl5O%9&iRkr)0v%s3{vBaSa8rQ5ao4kp5SCyQgxXyah_+<
z62S?@6|aVJ(0Bwk?FPCrXM^C9{Ij<8E7Y_>%z8@wP($94*s4x2$=Q}clYEa6Xh>jX
zsmXUDMt=V&%6p97(mDTut^4JI1l^Px%{qJ^Mg=b+citZyO$Lczo3dZGwTi4k+9(XS
zkG>wYqj54c3u0Sc`FG|L^y26&|d4wiI4I+a?I
zFH=UyzMO3LQ~;J#T?5!Sv(dxVSW3xlc=gw?lioW^ZXac@`<~>L-#$1J|I(ZTIsf!E
z`Y??u!FymN3Uu^-5AVygjPsyd=h_#={&6yd%RzTcdN-L^;9c7B4$*i=)TjE<7t9TR
z#PefqSfSvhpF|rt@)vkL``u~9W{_=BzJM`ZtNs}}*$i!l)|9}p_9)LBa!IGU!nNQy
zjUbtD*sReI)S1|)W?H)CEQgGq{rTsRD=QgA|La|zh|A{YI74GxROoGPK=a!M@GX_2
zbj{ae=mdc$=j#%>N-ME$G9NL%rAXC=xu9rI0^)wf3tMA8K!P}wPg@8@}BicM(d6QzA
zp@UlCHRKd~CzzxntDW?Xx*#Ivia1051OGs#9PRWd_|TR@@I(J`8iWI3woJP)Di+$isUoWEU8t_6F%Z$?3vj|nTcSWB(
zMpmdhOm<2C@RC0B<9m?P-0X&19!7xGF!7>tCeKWoM+BLT(LE88(LOiv;C
zuwn1hC&cU{{IvMXfq{2L&vC-mVHa8=y-VRUm_*NnJun#eYfDif0^heNY}+^_;k(qo
ze=DSHYr(AqQGFDQ5Fp>V4m3t6qjncPXj8JSYK}>sVU;bNP9x?V1Hn!t_(>0=*d;U9
zUx}x}uQIV8BWyN~Y(}#)BMAg^`pMp;14d=&id-BCjL?$ATNmX?QX94o*H&#i18G=ybs65xaTXA;Cubh1lmW-lMv7?imTuI5PpYYv@*+L
zZl2YtTD!;3j+bX!myVZh`fS6fmHsMpo+NahW|jBK7BSCf)wS17L)vKx;+gh-0*$9x4Ig!!)
z{TAM`u-w9fp3}dxM#8V(by60vW~3S5lVKyGVin;E6+1324$vE&hA&UF>yF8
zXIVSZD=E&SKZ&_>D-05D5B;daVa*Mfp}B-78uE)U^=*IRzVvNNzN9X26Wk-T8+_mpQ>|-F`~$U}
zm3&EcI}-kXJn7u9CmFlR4dB+w(-gYkPLS0hw!Mtnu1Ya8rc(rMa6{quHiu86cT*;<
z;VR_ctGy4u3yY&mrAcu7y0#Zr2~QG}VLIVqg9{@bzCfDs8BXJ=w&tDf;;3S
zhf?pT2c^8^@B-igq>oXXY{#>D$0~XTGdw5kLBYG;;m0$!$p?!?5&bozjfAkMPaG-6
zx{!Fxd=NZVIvSC`VJqGXQSm3jhFv9|k9ZvI2vdr!bIpzd8%2QMs~Mp#1)Mn>X}}^S
zzJxc8nDs2#F$0sJJVbn#GQ;RQab$_{_zui}H~H;YC7{9c6+cy@WLXTm!r@|}GCct*
zC!wu4
z;?Pq~23FE4APkW+}?YAqq`yr|Q5<
zIKfdwIIjOtdN&%HkPLz=hop^MBM&$NA6;hxI_u7^TLd
zOh2t=^&e}E_S~$@M6ceX#(he?T5e0+7Bb=maeyo>oEsX$3#kIlb|rG`)#hL)ME)dY
zr|*YY-$0b-Q{SU~2KQLs*Zovlnci=1o)Y72o$oziUiuC?wK~dX+j7!xlIF>u%$4`dMpVWm#O6>NHa;d?8SjSm#X0)D-ea-8g;&&_
zIovZaP<^g4+j{+MOY6yK)qRnnApi>}DSsdjbjNsWqsy>Uh$A6&Z9i~ZiGh=bO`Ag-
zOFf9Z1ot~&xapo<3AV4(Nz7VV*-%5;CxjzaelWugdq4lSDOb*ISI
zk7U%HqD}MVg^E8H&PkzzWxy5+j4@&asv~O%XZfT8#6Aeqr&&=;!+vGDwRWa5*P`a_
z>rdZSGfkOl6#a21h^!JpB=j0GDO3B!4t?T2bMvy;^v{;tHvR{7C+<^ncf<`A`#6Lt
z$llN!ioXy7`Ge)dMkMq_jY&R;^u>0m1$y^bj~$ID|iP8SM->h7RxvFU4X9Jne%*
zut$2!hP-n(%?yl=b|ns1Dy|G%Nsji}$^;|E{q!F6?*1c7?FfTQFFRtk817C9l$ysy
zi6yi7#ejKon>ZMY#{zx*rp#3?mlBn3xZAucfR|J_hkLhpX)<)45&IUt{-53P
z$nQSa*Z+(A8Z0(_{l}JEq(rsT{sk7F@!{;CnZ2K$o4^nDhyKvcf^Kb;x1;x(xHQ+ecwUGbQd-
zFr(NUm$I#OYi!~+WNot~qT$iZesi<+BJ5^1pCfnQn0dv3ysNeSJZO~CpV$)$Zw^sL
zv0o*3&ra#W$QIukFoM6;+~xZKM9A)}#RdB`NU
zwYHsSIHf)sm(rfN3wrErZ5x${!8N6;bz5v=cls~#k)(kVN+GrirMb*f>&odM%~ijW(p`z4n2ol6pw+!ze1BdqB=+=mkT
z4~>4Zzt@SACFrZ8+(CsW6?
zC3bkyLW_i)Y7V`1u*s+&-42P=YvX}NZOlhvRdx&YN4YDpKd}QR13wY-N7@9;&8O7SCI>0j25kV*mTsVI=ecm2&8ASrhsVsYC0L*;?lg(r4c9^&paom9ER8R$0{w
zi#7eHnsMs8Q%bNkA=ZoL=9sKw_0eA=sv6xSuQ*bA(Z?i&XLR~6o-ciyaV$+2L)2>%
zJt8cZ-hLTS(xudzypNq94UfhyA^uYrQXOVph#Ar56%^EzrTN(F#hWb|txPj)wGqX;zwN
zxZH}fO2#ydzKR()1i)
zuq|ajI43D{^HpO5shXH&!i0$CuVScHvdA0*7a>!gyf|OZnjbz!g(vout!n0o)8Pez
zzP{gy=|-B}{Ct~FGs-UGIXlw7@cf9(w#J-t0#up+1E7K=HT4N6DQd2-rbQAY66Y1-
z@y>{5eOr9ropEP{x$8dUmqUt2B1M&lHPNcBHWr@&q*T^`1Fr
zuN>WQOdjdk3OmQ+kU@f)ecD`4;}U9!4?QF5vyokOqtZ~1s%cqHw?+rp+cgc7GthaI
zG^U$s8>-8F@1O)2H#f2b!N*XA=x<21DVV3}{4o_rWz_jjXjjn)k?Y9om=tS(cvczh
z)}>lkgjr;OMX4XD^iJ0_;Q`g?8w*{TPJ`Lz^PnNA&L>&^_zgmp(!LI~Pm}(dcE+wHOvmMmJQm
z=oFIewlil29>b$F^NK%E2b||tvdOVA`if@IDzRu%X3SSA^O2nvDhXq-Sqe;5@>KLV
zv@~9e;RO%Qk1a#j%#c6Efw;qHp@h)6di+pspNv>NC4F9;e8zJmeTKzz2)s;cwm36M
zrbKOY1l}%VZ|jOq(I$3qNTN**dcy?{VBvX>`OzNTcF^beezlud_^A5**wmVjX%40t
zD*6l9<9&%QKsC@{s`X5Z!W#(_UcEO@vUE%yVU#@LXTcPE9tMo1u5dWc(+TCdcCN6#6dJasu6Sgw^a@kB0nt
ztulK)@l>YekLgz9>J)?Aft|r~G~f4UWRD~plu3mc0Mgs!X@xb(YUXGIL?kJaN%uv~7O>f;gJZ(|NmV2i)V>=d
zNv%J|!(PGN;0a+0Aq*`55=b40N&`Ts2wf*b{>9up7jJX2EveD=ZU;^b-w1BrBhig>
zjlpYiYknJ*Mfp0Sd_nASXP*hy&_fJ7jj`$@7lLnE@J>9z!qAuoal`ha^R{944U+&tUZ*qs^;mJO{qPlWtbhxeO)N3^NCagtGl#%Xb$6m%tYDAYsI
zjCz!4D5#)fPlyBC%Q&J=;Rm5d92&Nbp(PB?N8w#HB5AL|_w^Zh)H&_)rQ`+=!Ujlo
zfhSEGs6Xl+4Br`np(s2u=y7k7C1vNpj6#}yiq4RT-8p?$O#_UP4#Htzxj6Kfv-QRN
z9(Im{UU;lEvuXwT~r>;wjOR3={t*VY>`>N5Nr->1=$c_E`7OW
zs%z^b)-D=I;~Vp1!OU3N=^SA)$SxDs1mPu!K0l*b0ezE}Y;MMDuApjdu%fhP2EPuJ
zkvmZodwyz`liq@2#E`QQ53{arZ1V-|ty;9V&F-)#v{C8CxmP!4;;bWeIg>jtW&hd!
zwNZ!~)Hc9YB+m!~y_bcUbFH1uICwasLEK&Pw$_v9wSFD%{l?JficL8z=OCEBY@L)2
z`*=1{BsMo@q>d#J59cT6MI!$AW~m?+~~R*kgpV2Qn0s0V~%*Afkv{!<}Rwn*KP;t
zfLU%3X2FE3pBe|DB{YW310FWTx*C9kLoL?qbWE7^7XVa=;%xC=l7P))rdFJ}psfInuMexQDYD#DcyP6ol`SdB3mJvRhGhqN^
zGB?k(h*pv0G6c2gMwd~!NVedlV2t`kfH+o}ls7&SH*qqis&(RiZ)@kb>rwTdDbOXqgeWOEmWHw=nBa*1Wp17r>$x6tX!2X~JUvQlE>g&nOKx4DfOPR~7PW2ahuA%>rZt!nLn+pdE{5GV5oc9*j6wcSVrS@8okltJi9BTg0B`aJ-)q3HY}yoxy12nM^0*w_MyF3Q
zy3g&9?s3Y|ILt(o8T|wj($UXC--RP0`N5odS`iK|)pc%t$RyEL2j;!PTlG_Wv=Fqp
z@0U9eM=S6mFawk6`SRfj=+QPgsGTp@q@4XB?=}@S~42ewYMEW*6
zjrs%4SIy18^9{r-*`#I}SOmOZ0DrmF>8%}*JU@s2>Q6a_odf<(0-2W{p5Yz?Q^qxw
zs&AH*;tRENbbHYBtUloBpW*o>^f9`5oZ3`O$*p1K^oWe{Tzo%+_U=YA;T#=KLDzMD
zzRV=GY8Gf=GQYh|nN4#BJG=pF@@>c#r~J;`@Hp&@`P@nD{4T`o240b@JYdCfp+-u9
zOv(7TOtpRKaiIESywJ@^57nfRCb^3r(eOjD+ejEXW
za>}tNyGgw9r-*ICGY5u3aVVzLuO@Xsgdl|YMqe)`Ljw6xw5iiQNy)YxbAA`)z7@vC
z(CO?*>{jL)QcFaMIbN40f8vUt!F{s#Uz)z@}PTdT7a5xo3Qud%XJK0CrQy
zD=rFF?%nb(y#2+tq1OsC(q@w-k
zRf%$EDs?c->afpYOy5&uNeL);jAy>hCb6$MA<6w4I9pJel03EU1kLjvy$Oh$$1XF!
zZJllC4t)&yl{=FSJ)!XI1MB~|XANDUHwXO@`;r$R>#O|0uUP_cn6}rK;b^)h$GZ&20iilt;!naFPSX#GH%vk)9T_T_wjNpGTcij#094vd@iy+Wm^IPmV$E@*JCr{^d$;9l04_M{%FC;#I)+I;0nvwg!A}L+-$C=vkXhqd?!ZhdvCrI
zV?DIxl`LA(T>m#Dqp;^O*dhbAAfdd99+pj^H+(13J?oK_EO#SbVAXZJTbWKhIYTkl
z(R7PS7;*eEW3*?wx%s2)^b?*eB*!5))~D&+YV)(i4BgJ$P>7DESMW!!Ab1D$J&MER
zM}u|`Ru1MArJ+;sH-nF;K}EqqxgZo??+BqD4+{k~>ch4CfKUS^5!cg#cT?EGX+C5(
z$;rAnkA^eS$=GmP=nl*A6Rn#JCG2R}R4obTsOvgbyKycGv1zAGs))q3z5m2
zcIDDOoCHh5_eZ}_=4aQEM%Vc|&yg#SEB71CZ_hHxm8VMOc>{0{bA2N+$r%pcnXxTn
z=@z?*=IlQ5EyHnbS2OhLjPA_-b=N6
z%^C2W7{3H_@7QtU)V!!paO%h&7)K@ZFghP%@
z<~bRTmJA39=G6BEmt=_8kv$&o2K4?(c2}RJNlh>&+z$jNbz-Ku;ShW=)LVCOC8@f>
z;RWEd#%h4}IvqsqxVRc|bEV@YJi(N1IgWhLbX4A?9{|~;ANE+UpVtVuO-h3Ikr>IH
zg$%?*ed06)Mm@KzmsRv? @YbnEn{ib5lHBJ0yRyjQ
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