From a3ea2d5ca0490dcb69ecab4844e17ebb6692c480 Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Sat, 13 Nov 2021 14:36:39 +0800 Subject: [PATCH] Update LuaJIT to LuaJIT/LuaJIT@b4b2dce9fc3ffaaa --- .../LuaJIT-2.1/android/arm64-v8a/jit/bc.lua | 190 +++ .../android/arm64-v8a/jit/bcsave.lua | 665 +++++++++ .../android/arm64-v8a/jit/dis_arm.lua | 689 ++++++++++ .../android/arm64-v8a/jit/dis_arm64.lua | 1216 +++++++++++++++++ .../android/arm64-v8a/jit/dis_arm64be.lua | 12 + .../android/arm64-v8a/jit/dis_mips.lua | 694 ++++++++++ .../android/arm64-v8a/jit/dis_mips64.lua | 17 + .../android/arm64-v8a/jit/dis_mips64el.lua | 17 + .../android/arm64-v8a/jit/dis_mips64r6.lua | 17 + .../android/arm64-v8a/jit/dis_mips64r6el.lua | 17 + .../android/arm64-v8a/jit/dis_mipsel.lua | 17 + .../android/arm64-v8a/jit/dis_ppc.lua | 591 ++++++++ .../android/arm64-v8a/jit/dis_x64.lua | 17 + .../android/arm64-v8a/jit/dis_x86.lua | 953 +++++++++++++ .../LuaJIT-2.1/android/arm64-v8a/jit/dump.lua | 726 ++++++++++ .../LuaJIT-2.1/android/arm64-v8a/jit/p.lua | 312 +++++ .../LuaJIT-2.1/android/arm64-v8a/jit/v.lua | 170 +++ .../android/arm64-v8a/jit/vmdef.lua | 395 ++++++ .../LuaJIT-2.1/android/arm64-v8a/jit/zone.lua | 45 + .../LuaJIT-2.1/android/arm64-v8a/libluajit.a | Bin 697328 -> 733676 bytes .../LuaJIT-2.1/android/armeabi-v7a/jit/bc.lua | 190 +++ .../android/armeabi-v7a/jit/bcsave.lua | 665 +++++++++ .../android/armeabi-v7a/jit/dis_arm.lua | 689 ++++++++++ .../android/armeabi-v7a/jit/dis_arm64.lua | 1216 +++++++++++++++++ .../android/armeabi-v7a/jit/dis_arm64be.lua | 12 + .../android/armeabi-v7a/jit/dis_mips.lua | 694 ++++++++++ .../android/armeabi-v7a/jit/dis_mips64.lua | 17 + .../android/armeabi-v7a/jit/dis_mips64el.lua | 17 + .../android/armeabi-v7a/jit/dis_mips64r6.lua | 17 + .../armeabi-v7a/jit/dis_mips64r6el.lua | 17 + .../android/armeabi-v7a/jit/dis_mipsel.lua | 17 + .../android/armeabi-v7a/jit/dis_ppc.lua | 591 ++++++++ .../android/armeabi-v7a/jit/dis_x64.lua | 17 + .../android/armeabi-v7a/jit/dis_x86.lua | 953 +++++++++++++ .../android/armeabi-v7a/jit/dump.lua | 726 ++++++++++ .../LuaJIT-2.1/android/armeabi-v7a/jit/p.lua | 312 +++++ .../LuaJIT-2.1/android/armeabi-v7a/jit/v.lua | 170 +++ .../android/armeabi-v7a/jit/vmdef.lua | 395 ++++++ .../android/armeabi-v7a/jit/zone.lua | 45 + .../android/armeabi-v7a/libluajit.a | Bin 745576 -> 781320 bytes .../src/jni/LuaJIT-2.1/android/x86/jit/bc.lua | 190 +++ .../jni/LuaJIT-2.1/android/x86/jit/bcsave.lua | 665 +++++++++ .../LuaJIT-2.1/android/x86/jit/dis_arm.lua | 689 ++++++++++ .../LuaJIT-2.1/android/x86/jit/dis_arm64.lua | 1216 +++++++++++++++++ .../android/x86/jit/dis_arm64be.lua | 12 + .../LuaJIT-2.1/android/x86/jit/dis_mips.lua | 694 ++++++++++ .../LuaJIT-2.1/android/x86/jit/dis_mips64.lua | 17 + .../android/x86/jit/dis_mips64el.lua | 17 + .../android/x86/jit/dis_mips64r6.lua | 17 + .../android/x86/jit/dis_mips64r6el.lua | 17 + .../LuaJIT-2.1/android/x86/jit/dis_mipsel.lua | 17 + .../LuaJIT-2.1/android/x86/jit/dis_ppc.lua | 591 ++++++++ .../LuaJIT-2.1/android/x86/jit/dis_x64.lua | 17 + .../LuaJIT-2.1/android/x86/jit/dis_x86.lua | 953 +++++++++++++ .../jni/LuaJIT-2.1/android/x86/jit/dump.lua | 726 ++++++++++ love/src/jni/LuaJIT-2.1/android/x86/jit/p.lua | 312 +++++ love/src/jni/LuaJIT-2.1/android/x86/jit/v.lua | 170 +++ .../jni/LuaJIT-2.1/android/x86/jit/vmdef.lua | 395 ++++++ .../jni/LuaJIT-2.1/android/x86/jit/zone.lua | 45 + .../jni/LuaJIT-2.1/android/x86/libluajit.a | Bin 699532 -> 733506 bytes .../jni/LuaJIT-2.1/android/x86_64/jit/bc.lua | 190 +++ .../LuaJIT-2.1/android/x86_64/jit/bcsave.lua | 665 +++++++++ .../LuaJIT-2.1/android/x86_64/jit/dis_arm.lua | 689 ++++++++++ .../android/x86_64/jit/dis_arm64.lua | 1216 +++++++++++++++++ .../android/x86_64/jit/dis_arm64be.lua | 12 + .../android/x86_64/jit/dis_mips.lua | 694 ++++++++++ .../android/x86_64/jit/dis_mips64.lua | 17 + .../android/x86_64/jit/dis_mips64el.lua | 17 + .../android/x86_64/jit/dis_mips64r6.lua | 17 + .../android/x86_64/jit/dis_mips64r6el.lua | 17 + .../android/x86_64/jit/dis_mipsel.lua | 17 + .../LuaJIT-2.1/android/x86_64/jit/dis_ppc.lua | 591 ++++++++ .../LuaJIT-2.1/android/x86_64/jit/dis_x64.lua | 17 + .../LuaJIT-2.1/android/x86_64/jit/dis_x86.lua | 953 +++++++++++++ .../LuaJIT-2.1/android/x86_64/jit/dump.lua | 726 ++++++++++ .../jni/LuaJIT-2.1/android/x86_64/jit/p.lua | 312 +++++ .../jni/LuaJIT-2.1/android/x86_64/jit/v.lua | 170 +++ .../LuaJIT-2.1/android/x86_64/jit/vmdef.lua | 395 ++++++ .../LuaJIT-2.1/android/x86_64/jit/zone.lua | 45 + .../jni/LuaJIT-2.1/android/x86_64/libluajit.a | Bin 882940 -> 928040 bytes .../src/jni/LuaJIT-2.1/build_instructions.bat | 4 + love/src/jni/LuaJIT-2.1/doc/contact.html | 6 +- love/src/jni/LuaJIT-2.1/doc/ext_buffer.html | 693 ++++++++++ love/src/jni/LuaJIT-2.1/doc/ext_c_api.html | 6 +- love/src/jni/LuaJIT-2.1/doc/ext_ffi.html | 6 +- love/src/jni/LuaJIT-2.1/doc/ext_ffi_api.html | 6 +- .../jni/LuaJIT-2.1/doc/ext_ffi_semantics.html | 6 +- .../jni/LuaJIT-2.1/doc/ext_ffi_tutorial.html | 6 +- love/src/jni/LuaJIT-2.1/doc/ext_jit.html | 6 +- love/src/jni/LuaJIT-2.1/doc/ext_profiler.html | 6 +- love/src/jni/LuaJIT-2.1/doc/extensions.html | 32 +- love/src/jni/LuaJIT-2.1/doc/faq.html | 24 +- love/src/jni/LuaJIT-2.1/doc/install.html | 29 +- love/src/jni/LuaJIT-2.1/doc/luajit.html | 6 +- love/src/jni/LuaJIT-2.1/doc/running.html | 10 +- love/src/jni/LuaJIT-2.1/doc/status.html | 12 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_arm.h | 7 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_arm.lua | 6 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_arm64.h | 58 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_arm64.lua | 135 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_mips.h | 7 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_mips.lua | 6 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_ppc.h | 7 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_ppc.lua | 6 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_proto.h | 4 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_x86.h | 24 +- love/src/jni/LuaJIT-2.1/dynasm/dasm_x86.lua | 50 +- love/src/jni/LuaJIT-2.1/dynasm/dynasm.lua | 6 +- love/src/jni/LuaJIT-2.1/src/Makefile | 21 +- love/src/jni/LuaJIT-2.1/src/Makefile.dep | 74 +- .../src/jni/LuaJIT-2.1/src/host/buildvm_lib.c | 2 + love/src/jni/LuaJIT-2.1/src/host/minilua.c | 2 +- love/src/jni/LuaJIT-2.1/src/jit/dis_arm64.lua | 2 +- love/src/jni/LuaJIT-2.1/src/jit/dump.lua | 28 +- love/src/jni/LuaJIT-2.1/src/jit/p.lua | 1 + love/src/jni/LuaJIT-2.1/src/lib_base.c | 22 +- love/src/jni/LuaJIT-2.1/src/lib_buffer.c | 356 +++++ love/src/jni/LuaJIT-2.1/src/lib_ffi.c | 1 + love/src/jni/LuaJIT-2.1/src/lib_io.c | 32 +- love/src/jni/LuaJIT-2.1/src/lib_jit.c | 6 +- love/src/jni/LuaJIT-2.1/src/lib_string.c | 88 +- love/src/jni/LuaJIT-2.1/src/lib_table.c | 2 +- love/src/jni/LuaJIT-2.1/src/lj_alloc.c | 2 +- love/src/jni/LuaJIT-2.1/src/lj_api.c | 38 +- love/src/jni/LuaJIT-2.1/src/lj_arch.h | 52 +- love/src/jni/LuaJIT-2.1/src/lj_asm.c | 216 ++- love/src/jni/LuaJIT-2.1/src/lj_asm_arm.h | 127 +- love/src/jni/LuaJIT-2.1/src/lj_asm_arm64.h | 113 +- love/src/jni/LuaJIT-2.1/src/lj_asm_mips.h | 234 ++-- love/src/jni/LuaJIT-2.1/src/lj_asm_ppc.h | 130 +- love/src/jni/LuaJIT-2.1/src/lj_asm_x86.h | 152 ++- love/src/jni/LuaJIT-2.1/src/lj_bcread.c | 16 +- love/src/jni/LuaJIT-2.1/src/lj_bcwrite.c | 22 +- love/src/jni/LuaJIT-2.1/src/lj_buf.c | 191 ++- love/src/jni/LuaJIT-2.1/src/lj_buf.h | 133 +- love/src/jni/LuaJIT-2.1/src/lj_ccall.c | 8 +- love/src/jni/LuaJIT-2.1/src/lj_ccallback.c | 9 +- love/src/jni/LuaJIT-2.1/src/lj_cconv.c | 5 + love/src/jni/LuaJIT-2.1/src/lj_cparse.c | 8 +- love/src/jni/LuaJIT-2.1/src/lj_crecord.c | 54 +- love/src/jni/LuaJIT-2.1/src/lj_crecord.h | 5 + love/src/jni/LuaJIT-2.1/src/lj_ctype.c | 2 +- love/src/jni/LuaJIT-2.1/src/lj_ctype.h | 11 + love/src/jni/LuaJIT-2.1/src/lj_debug.c | 2 +- love/src/jni/LuaJIT-2.1/src/lj_dispatch.c | 8 +- love/src/jni/LuaJIT-2.1/src/lj_dispatch.h | 4 +- love/src/jni/LuaJIT-2.1/src/lj_emit_arm64.h | 66 +- love/src/jni/LuaJIT-2.1/src/lj_emit_mips.h | 2 +- love/src/jni/LuaJIT-2.1/src/lj_err.c | 578 +++++--- love/src/jni/LuaJIT-2.1/src/lj_err.h | 19 +- love/src/jni/LuaJIT-2.1/src/lj_errmsg.h | 14 + love/src/jni/LuaJIT-2.1/src/lj_ffrecord.c | 424 +++++- love/src/jni/LuaJIT-2.1/src/lj_frame.h | 12 +- love/src/jni/LuaJIT-2.1/src/lj_gc.c | 9 + love/src/jni/LuaJIT-2.1/src/lj_ir.c | 3 +- love/src/jni/LuaJIT-2.1/src/lj_ir.h | 38 +- love/src/jni/LuaJIT-2.1/src/lj_ircall.h | 76 +- love/src/jni/LuaJIT-2.1/src/lj_iropt.h | 1 + love/src/jni/LuaJIT-2.1/src/lj_jit.h | 8 +- love/src/jni/LuaJIT-2.1/src/lj_lex.c | 16 +- love/src/jni/LuaJIT-2.1/src/lj_lib.c | 56 + love/src/jni/LuaJIT-2.1/src/lj_lib.h | 6 + love/src/jni/LuaJIT-2.1/src/lj_mcode.c | 25 +- love/src/jni/LuaJIT-2.1/src/lj_meta.c | 13 +- love/src/jni/LuaJIT-2.1/src/lj_obj.h | 16 +- love/src/jni/LuaJIT-2.1/src/lj_opt_fold.c | 88 +- love/src/jni/LuaJIT-2.1/src/lj_opt_loop.c | 1 + love/src/jni/LuaJIT-2.1/src/lj_opt_mem.c | 33 +- love/src/jni/LuaJIT-2.1/src/lj_opt_split.c | 2 +- love/src/jni/LuaJIT-2.1/src/lj_parse.c | 6 +- love/src/jni/LuaJIT-2.1/src/lj_prng.c | 16 +- love/src/jni/LuaJIT-2.1/src/lj_profile.c | 5 +- love/src/jni/LuaJIT-2.1/src/lj_record.c | 180 ++- love/src/jni/LuaJIT-2.1/src/lj_record.h | 2 + love/src/jni/LuaJIT-2.1/src/lj_serialize.c | 538 ++++++++ love/src/jni/LuaJIT-2.1/src/lj_serialize.h | 28 + love/src/jni/LuaJIT-2.1/src/lj_snap.c | 63 +- love/src/jni/LuaJIT-2.1/src/lj_state.c | 1 + love/src/jni/LuaJIT-2.1/src/lj_strfmt.c | 210 ++- love/src/jni/LuaJIT-2.1/src/lj_strfmt.h | 5 + love/src/jni/LuaJIT-2.1/src/lj_strfmt_num.c | 2 +- love/src/jni/LuaJIT-2.1/src/lj_tab.c | 85 +- love/src/jni/LuaJIT-2.1/src/lj_tab.h | 26 +- love/src/jni/LuaJIT-2.1/src/lj_target_arm.h | 1 + love/src/jni/LuaJIT-2.1/src/lj_target_arm64.h | 4 + love/src/jni/LuaJIT-2.1/src/lj_target_mips.h | 2 + love/src/jni/LuaJIT-2.1/src/lj_target_x86.h | 5 +- love/src/jni/LuaJIT-2.1/src/lj_trace.c | 89 +- love/src/jni/LuaJIT-2.1/src/lj_trace.h | 3 + love/src/jni/LuaJIT-2.1/src/lj_udata.c | 28 + love/src/jni/LuaJIT-2.1/src/lj_udata.h | 3 + love/src/jni/LuaJIT-2.1/src/lj_vm.h | 5 + love/src/jni/LuaJIT-2.1/src/ljamalg.c | 2 + love/src/jni/LuaJIT-2.1/src/lualib.h | 1 + love/src/jni/LuaJIT-2.1/src/msvcbuild.bat | 2 +- love/src/jni/LuaJIT-2.1/src/ps4build.bat | 2 +- love/src/jni/LuaJIT-2.1/src/psvitabuild.bat | 2 +- love/src/jni/LuaJIT-2.1/src/vm_arm.dasc | 114 +- love/src/jni/LuaJIT-2.1/src/vm_arm64.dasc | 322 +++-- love/src/jni/LuaJIT-2.1/src/vm_mips.dasc | 148 +- love/src/jni/LuaJIT-2.1/src/vm_mips64.dasc | 141 +- love/src/jni/LuaJIT-2.1/src/vm_ppc.dasc | 73 +- love/src/jni/LuaJIT-2.1/src/vm_x64.dasc | 138 +- love/src/jni/LuaJIT-2.1/src/vm_x86.dasc | 169 ++- love/src/jni/LuaJIT-2.1/src/xb1build.bat | 2 +- love/src/jni/LuaJIT-2.1/src/xedkbuild.bat | 2 +- love/src/jni/love | 2 +- 207 files changed, 32782 insertions(+), 1544 deletions(-) create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/bc.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/bcsave.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm64be.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64el.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64r6.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64r6el.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mipsel.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_ppc.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_x64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_x86.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dump.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/p.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/v.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/vmdef.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/zone.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/bc.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/bcsave.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm64be.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64el.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64r6.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64r6el.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mipsel.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_ppc.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_x64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_x86.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dump.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/p.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/v.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/vmdef.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/zone.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/bc.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/bcsave.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm64be.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64el.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64r6.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64r6el.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mipsel.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_ppc.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_x64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dis_x86.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/dump.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/p.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/v.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/vmdef.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86/jit/zone.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/bc.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/bcsave.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm64be.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64el.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64r6.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64r6el.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mipsel.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_ppc.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_x64.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_x86.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/dump.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/p.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/v.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/vmdef.lua create mode 100644 love/src/jni/LuaJIT-2.1/android/x86_64/jit/zone.lua create mode 100644 love/src/jni/LuaJIT-2.1/doc/ext_buffer.html create mode 100644 love/src/jni/LuaJIT-2.1/src/lib_buffer.c create mode 100644 love/src/jni/LuaJIT-2.1/src/lj_serialize.c create mode 100644 love/src/jni/LuaJIT-2.1/src/lj_serialize.h diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/bc.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/bc.lua new file mode 100644 index 00000000..e58a3fef --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/bc.lua @@ -0,0 +1,190 @@ +---------------------------------------------------------------------------- +-- LuaJIT bytecode listing module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module lists the bytecode of a Lua function. If it's loaded by -jbc +-- it hooks into the parser and lists all functions of a chunk as they +-- are parsed. +-- +-- Example usage: +-- +-- luajit -jbc -e 'local x=0; for i=1,1e6 do x=x+i end; print(x)' +-- luajit -jbc=- foo.lua +-- luajit -jbc=foo.list foo.lua +-- +-- Default output is to stderr. To redirect the output to a file, pass a +-- filename as an argument (use '-' for stdout) or set the environment +-- variable LUAJIT_LISTFILE. The file is overwritten every time the module +-- is started. +-- +-- This module can also be used programmatically: +-- +-- local bc = require("jit.bc") +-- +-- local function foo() print("hello") end +-- +-- bc.dump(foo) --> -- BYTECODE -- [...] +-- print(bc.line(foo, 2)) --> 0002 KSTR 1 1 ; "hello" +-- +-- local out = { +-- -- Do something with each line: +-- write = function(t, ...) io.write(...) end, +-- close = function(t) end, +-- flush = function(t) end, +-- } +-- bc.dump(foo, out) +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local bit = require("bit") +local sub, gsub, format = string.sub, string.gsub, string.format +local byte, band, shr = string.byte, bit.band, bit.rshift +local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck +local funcuvname = jutil.funcuvname +local bcnames = vmdef.bcnames +local stdout, stderr = io.stdout, io.stderr + +------------------------------------------------------------------------------ + +local function ctlsub(c) + if c == "\n" then return "\\n" + elseif c == "\r" then return "\\r" + elseif c == "\t" then return "\\t" + else return format("\\%03d", byte(c)) + end +end + +-- Return one bytecode line. +local function bcline(func, pc, prefix) + local ins, m = funcbc(func, pc) + if not ins then return end + local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128) + local a = band(shr(ins, 8), 0xff) + local oidx = 6*band(ins, 0xff) + local op = sub(bcnames, oidx+1, oidx+6) + local s = format("%04d %s %-6s %3s ", + pc, prefix or " ", op, ma == 0 and "" or a) + local d = shr(ins, 16) + if mc == 13*128 then -- BCMjump + return format("%s=> %04d\n", s, pc+d-0x7fff) + end + if mb ~= 0 then + d = band(d, 0xff) + elseif mc == 0 then + return s.."\n" + end + local kc + if mc == 10*128 then -- BCMstr + kc = funck(func, -d-1) + kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub)) + elseif mc == 9*128 then -- BCMnum + kc = funck(func, d) + if op == "TSETM " then kc = kc - 2^52 end + elseif mc == 12*128 then -- BCMfunc + local fi = funcinfo(funck(func, -d-1)) + if fi.ffid then + kc = vmdef.ffnames[fi.ffid] + else + kc = fi.loc + end + elseif mc == 5*128 then -- BCMuv + kc = funcuvname(func, d) + end + if ma == 5 then -- BCMuv + local ka = funcuvname(func, a) + if kc then kc = ka.." ; "..kc else kc = ka end + end + if mb ~= 0 then + local b = shr(ins, 24) + if kc then return format("%s%3d %3d ; %s\n", s, b, d, kc) end + return format("%s%3d %3d\n", s, b, d) + end + if kc then return format("%s%3d ; %s\n", s, d, kc) end + if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits + return format("%s%3d\n", s, d) +end + +-- Collect branch targets of a function. +local function bctargets(func) + local target = {} + for pc=1,1000000000 do + local ins, m = funcbc(func, pc) + if not ins then break end + if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end + end + return target +end + +-- Dump bytecode instructions of a function. +local function bcdump(func, out, all) + if not out then out = stdout end + local fi = funcinfo(func) + if all and fi.children then + for n=-1,-1000000000,-1 do + local k = funck(func, n) + if not k then break end + if type(k) == "proto" then bcdump(k, out, true) end + end + end + out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined)) + local target = bctargets(func) + for pc=1,1000000000 do + local s = bcline(func, pc, target[pc] and "=>") + if not s then break end + out:write(s) + end + out:write("\n") + out:flush() +end + +------------------------------------------------------------------------------ + +-- Active flag and output file handle. +local active, out + +-- List handler. +local function h_list(func) + return bcdump(func, out) +end + +-- Detach list handler. +local function bclistoff() + if active then + active = false + jit.attach(h_list) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach list handler. +local function bcliston(outfile) + if active then bclistoff() end + if not outfile then outfile = os.getenv("LUAJIT_LISTFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stderr + end + jit.attach(h_list, "bc") + active = true +end + +-- Public module functions. +return { + line = bcline, + dump = bcdump, + targets = bctargets, + on = bcliston, + off = bclistoff, + start = bcliston -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/bcsave.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/bcsave.lua new file mode 100644 index 00000000..ab13667a --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/bcsave.lua @@ -0,0 +1,665 @@ +---------------------------------------------------------------------------- +-- LuaJIT module to save/list bytecode. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module saves or lists the bytecode for an input file. +-- It's run by the -b command line option. +-- +------------------------------------------------------------------------------ + +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local bit = require("bit") + +-- Symbol name prefix for LuaJIT bytecode. +local LJBC_PREFIX = "luaJIT_BC_" + +local type, assert = type, assert +local format = string.format +local tremove, tconcat = table.remove, table.concat + +------------------------------------------------------------------------------ + +local function usage() + io.stderr:write[[ +Save LuaJIT bytecode: luajit -b[options] input output + -l Only list bytecode. + -s Strip debug info (default). + -g Keep debug info. + -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). + -e chunk Use chunk string as input. + -- Stop handling options. + - Use stdin as input and/or stdout as output. + +File types: c h obj o raw (default) +]] + os.exit(1) +end + +local function check(ok, ...) + if ok then return ok, ... end + io.stderr:write("luajit: ", ...) + io.stderr:write("\n") + os.exit(1) +end + +local function readfile(input) + if type(input) == "function" then return input end + if input == "-" then input = nil end + return check(loadfile(input)) +end + +local function savefile(name, mode) + if name == "-" then return io.stdout end + return check(io.open(name, mode)) +end + +------------------------------------------------------------------------------ + +local map_type = { + raw = "raw", c = "c", h = "h", o = "obj", obj = "obj", +} + +local map_arch = { + x86 = { e = "le", b = 32, m = 3, p = 0x14c, }, + x64 = { e = "le", b = 64, m = 62, p = 0x8664, }, + arm = { e = "le", b = 32, m = 40, p = 0x1c0, }, + arm64 = { e = "le", b = 64, m = 183, p = 0xaa64, }, + arm64be = { e = "be", b = 64, m = 183, }, + ppc = { e = "be", b = 32, m = 20, }, + mips = { e = "be", b = 32, m = 8, f = 0x50001006, }, + mipsel = { e = "le", b = 32, m = 8, f = 0x50001006, }, + mips64 = { e = "be", b = 64, m = 8, f = 0x80000007, }, + mips64el = { e = "le", b = 64, m = 8, f = 0x80000007, }, + mips64r6 = { e = "be", b = 64, m = 8, f = 0xa0000407, }, + mips64r6el = { e = "le", b = 64, m = 8, f = 0xa0000407, }, +} + +local map_os = { + linux = true, windows = true, osx = true, freebsd = true, netbsd = true, + openbsd = true, dragonfly = true, solaris = true, +} + +local function checkarg(str, map, err) + str = str:lower() + local s = check(map[str], "unknown ", err) + return type(s) == "string" and s or str +end + +local function detecttype(str) + local ext = str:lower():match("%.(%a+)$") + return map_type[ext] or "raw" +end + +local function checkmodname(str) + check(str:match("^[%w_.%-]+$"), "bad module name") + return str:gsub("[%.%-]", "_") +end + +local function detectmodname(str) + if type(str) == "string" then + local tail = str:match("[^/\\]+$") + if tail then str = tail end + local head = str:match("^(.*)%.[^.]*$") + if head then str = head end + str = str:match("^[%w_.%-]+") + else + str = nil + end + check(str, "cannot derive module name, use -n name") + return str:gsub("[%.%-]", "_") +end + +------------------------------------------------------------------------------ + +local function bcsave_tail(fp, output, s) + local ok, err = fp:write(s) + if ok and output ~= "-" then ok, err = fp:close() end + check(ok, "cannot write ", output, ": ", err) +end + +local function bcsave_raw(output, s) + local fp = savefile(output, "wb") + bcsave_tail(fp, output, s) +end + +local function bcsave_c(ctx, output, s) + local fp = savefile(output, "w") + if ctx.type == "c" then + fp:write(format([[ +#ifdef __cplusplus +extern "C" +#endif +#ifdef _WIN32 +__declspec(dllexport) +#endif +const unsigned char %s%s[] = { +]], LJBC_PREFIX, ctx.modname)) + else + fp:write(format([[ +#define %s%s_SIZE %d +static const unsigned char %s%s[] = { +]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname)) + end + local t, n, m = {}, 0, 0 + for i=1,#s do + local b = tostring(string.byte(s, i)) + m = m + #b + 1 + if m > 78 then + fp:write(tconcat(t, ",", 1, n), ",\n") + n, m = 0, #b + 1 + end + n = n + 1 + t[n] = b + end + bcsave_tail(fp, output, tconcat(t, ",", 1, n).."\n};\n") +end + +local function bcsave_elfobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct { + uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; + uint16_t type, machine; + uint32_t version; + uint32_t entry, phofs, shofs; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; +} ELF32header; +typedef struct { + uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; + uint16_t type, machine; + uint32_t version; + uint64_t entry, phofs, shofs; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; +} ELF64header; +typedef struct { + uint32_t name, type, flags, addr, ofs, size, link, info, align, entsize; +} ELF32sectheader; +typedef struct { + uint32_t name, type; + uint64_t flags, addr, ofs, size; + uint32_t link, info; + uint64_t align, entsize; +} ELF64sectheader; +typedef struct { + uint32_t name, value, size; + uint8_t info, other; + uint16_t sectidx; +} ELF32symbol; +typedef struct { + uint32_t name; + uint8_t info, other; + uint16_t sectidx; + uint64_t value, size; +} ELF64symbol; +typedef struct { + ELF32header hdr; + ELF32sectheader sect[6]; + ELF32symbol sym[2]; + uint8_t space[4096]; +} ELF32obj; +typedef struct { + ELF64header hdr; + ELF64sectheader sect[6]; + ELF64symbol sym[2]; + uint8_t space[4096]; +} ELF64obj; +]] + local symname = LJBC_PREFIX..ctx.modname + local ai = assert(map_arch[ctx.arch]) + local is64, isbe = ai.b == 64, ai.e == "be" + + -- Handle different host/target endianess. + local function f32(x) return x end + local f16, fofs = f32, f32 + if ffi.abi("be") ~= isbe then + f32 = bit.bswap + function f16(x) return bit.rshift(bit.bswap(x), 16) end + if is64 then + local two32 = ffi.cast("int64_t", 2^32) + function fofs(x) return bit.bswap(x)*two32 end + else + fofs = f32 + end + end + + -- Create ELF object and fill in header. + local o = ffi.new(is64 and "ELF64obj" or "ELF32obj") + local hdr = o.hdr + if ctx.os == "bsd" or ctx.os == "other" then -- Determine native hdr.eosabi. + local bf = assert(io.open("/bin/ls", "rb")) + local bs = bf:read(9) + bf:close() + ffi.copy(o, bs, 9) + check(hdr.emagic[0] == 127, "no support for writing native object files") + else + hdr.emagic = "\127ELF" + hdr.eosabi = ({ freebsd=9, netbsd=2, openbsd=12, solaris=6 })[ctx.os] or 0 + end + hdr.eclass = is64 and 2 or 1 + hdr.eendian = isbe and 2 or 1 + hdr.eversion = 1 + hdr.type = f16(1) + hdr.machine = f16(ai.m) + hdr.flags = f32(ai.f or 0) + hdr.version = f32(1) + hdr.shofs = fofs(ffi.offsetof(o, "sect")) + hdr.ehsize = f16(ffi.sizeof(hdr)) + hdr.shentsize = f16(ffi.sizeof(o.sect[0])) + hdr.shnum = f16(6) + hdr.shstridx = f16(2) + + -- Fill in sections and symbols. + local sofs, ofs = ffi.offsetof(o, "space"), 1 + for i,name in ipairs{ + ".symtab", ".shstrtab", ".strtab", ".rodata", ".note.GNU-stack", + } do + local sect = o.sect[i] + sect.align = fofs(1) + sect.name = f32(ofs) + ffi.copy(o.space+ofs, name) + ofs = ofs + #name+1 + end + o.sect[1].type = f32(2) -- .symtab + o.sect[1].link = f32(3) + o.sect[1].info = f32(1) + o.sect[1].align = fofs(8) + o.sect[1].ofs = fofs(ffi.offsetof(o, "sym")) + o.sect[1].entsize = fofs(ffi.sizeof(o.sym[0])) + o.sect[1].size = fofs(ffi.sizeof(o.sym)) + o.sym[1].name = f32(1) + o.sym[1].sectidx = f16(4) + o.sym[1].size = fofs(#s) + o.sym[1].info = 17 + o.sect[2].type = f32(3) -- .shstrtab + o.sect[2].ofs = fofs(sofs) + o.sect[2].size = fofs(ofs) + o.sect[3].type = f32(3) -- .strtab + o.sect[3].ofs = fofs(sofs + ofs) + o.sect[3].size = fofs(#symname+2) + ffi.copy(o.space+ofs+1, symname) + ofs = ofs + #symname + 2 + o.sect[4].type = f32(1) -- .rodata + o.sect[4].flags = fofs(2) + o.sect[4].ofs = fofs(sofs + ofs) + o.sect[4].size = fofs(#s) + o.sect[5].type = f32(1) -- .note.GNU-stack + o.sect[5].ofs = fofs(sofs + ofs + #s) + + -- Write ELF object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) + bcsave_tail(fp, output, s) +end + +local function bcsave_peobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct { + uint16_t arch, nsects; + uint32_t time, symtabofs, nsyms; + uint16_t opthdrsz, flags; +} PEheader; +typedef struct { + char name[8]; + uint32_t vsize, vaddr, size, ofs, relocofs, lineofs; + uint16_t nreloc, nline; + uint32_t flags; +} PEsection; +typedef struct __attribute((packed)) { + union { + char name[8]; + uint32_t nameref[2]; + }; + uint32_t value; + int16_t sect; + uint16_t type; + uint8_t scl, naux; +} PEsym; +typedef struct __attribute((packed)) { + uint32_t size; + uint16_t nreloc, nline; + uint32_t cksum; + uint16_t assoc; + uint8_t comdatsel, unused[3]; +} PEsymaux; +typedef struct { + PEheader hdr; + PEsection sect[2]; + // Must be an even number of symbol structs. + PEsym sym0; + PEsymaux sym0aux; + PEsym sym1; + PEsymaux sym1aux; + PEsym sym2; + PEsym sym3; + uint32_t strtabsize; + uint8_t space[4096]; +} PEobj; +]] + local symname = LJBC_PREFIX..ctx.modname + local ai = assert(map_arch[ctx.arch]) + local is64 = ai.b == 64 + local symexport = " /EXPORT:"..symname..",DATA " + + -- The file format is always little-endian. Swap if the host is big-endian. + local function f32(x) return x end + local f16 = f32 + if ffi.abi("be") then + f32 = bit.bswap + function f16(x) return bit.rshift(bit.bswap(x), 16) end + end + + -- Create PE object and fill in header. + local o = ffi.new("PEobj") + local hdr = o.hdr + hdr.arch = f16(assert(ai.p)) + hdr.nsects = f16(2) + hdr.symtabofs = f32(ffi.offsetof(o, "sym0")) + hdr.nsyms = f32(6) + + -- Fill in sections and symbols. + o.sect[0].name = ".drectve" + o.sect[0].size = f32(#symexport) + o.sect[0].flags = f32(0x00100a00) + o.sym0.sect = f16(1) + o.sym0.scl = 3 + o.sym0.name = ".drectve" + o.sym0.naux = 1 + o.sym0aux.size = f32(#symexport) + o.sect[1].name = ".rdata" + o.sect[1].size = f32(#s) + o.sect[1].flags = f32(0x40300040) + o.sym1.sect = f16(2) + o.sym1.scl = 3 + o.sym1.name = ".rdata" + o.sym1.naux = 1 + o.sym1aux.size = f32(#s) + o.sym2.sect = f16(2) + o.sym2.scl = 2 + o.sym2.nameref[1] = f32(4) + o.sym3.sect = f16(-1) + o.sym3.scl = 2 + o.sym3.value = f32(1) + o.sym3.name = "@feat.00" -- Mark as SafeSEH compliant. + ffi.copy(o.space, symname) + local ofs = #symname + 1 + o.strtabsize = f32(ofs + 4) + o.sect[0].ofs = f32(ffi.offsetof(o, "space") + ofs) + ffi.copy(o.space + ofs, symexport) + ofs = ofs + #symexport + o.sect[1].ofs = f32(ffi.offsetof(o, "space") + ofs) + + -- Write PE object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) + bcsave_tail(fp, output, s) +end + +local function bcsave_machobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct +{ + uint32_t magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags; +} mach_header; +typedef struct +{ + mach_header; uint32_t reserved; +} mach_header_64; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint32_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint64_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command_64; +typedef struct { + char sectname[16], segname[16]; + uint32_t addr, size; + uint32_t offset, align, reloff, nreloc, flags; + uint32_t reserved1, reserved2; +} mach_section; +typedef struct { + char sectname[16], segname[16]; + uint64_t addr, size; + uint32_t offset, align, reloff, nreloc, flags; + uint32_t reserved1, reserved2, reserved3; +} mach_section_64; +typedef struct { + uint32_t cmd, cmdsize, symoff, nsyms, stroff, strsize; +} mach_symtab_command; +typedef struct { + int32_t strx; + uint8_t type, sect; + int16_t desc; + uint32_t value; +} mach_nlist; +typedef struct { + uint32_t strx; + uint8_t type, sect; + uint16_t desc; + uint64_t value; +} mach_nlist_64; +typedef struct +{ + uint32_t magic, nfat_arch; +} mach_fat_header; +typedef struct +{ + uint32_t cputype, cpusubtype, offset, size, align; +} mach_fat_arch; +typedef struct { + struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + } arch[1]; + mach_nlist sym_entry; + uint8_t space[4096]; +} mach_obj; +typedef struct { + struct { + mach_header_64 hdr; + mach_segment_command_64 seg; + mach_section_64 sec; + mach_symtab_command sym; + } arch[1]; + mach_nlist_64 sym_entry; + uint8_t space[4096]; +} mach_obj_64; +typedef struct { + mach_fat_header fat; + mach_fat_arch fat_arch[2]; + struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + } arch[2]; + mach_nlist sym_entry; + uint8_t space[4096]; +} mach_fat_obj; +]] + local symname = '_'..LJBC_PREFIX..ctx.modname + local isfat, is64, align, mobj = false, false, 4, "mach_obj" + if ctx.arch == "x64" then + is64, align, mobj = true, 8, "mach_obj_64" + elseif ctx.arch == "arm" then + isfat, mobj = true, "mach_fat_obj" + elseif ctx.arch == "arm64" then + is64, align, isfat, mobj = true, 8, true, "mach_fat_obj" + else + check(ctx.arch == "x86", "unsupported architecture for OSX") + end + local function aligned(v, a) return bit.band(v+a-1, -a) end + local be32 = bit.bswap -- Mach-O FAT is BE, supported archs are LE. + + -- Create Mach-O object and fill in header. + local o = ffi.new(mobj) + local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align) + local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12}, arm64={0x01000007,0x0100000c} })[ctx.arch] + local cpusubtype = ({ x86={3}, x64={3}, arm={3,9}, arm64={3,0} })[ctx.arch] + if isfat then + o.fat.magic = be32(0xcafebabe) + o.fat.nfat_arch = be32(#cpusubtype) + end + + -- Fill in sections and symbols. + for i=0,#cpusubtype-1 do + local ofs = 0 + if isfat then + local a = o.fat_arch[i] + a.cputype = be32(cputype[i+1]) + a.cpusubtype = be32(cpusubtype[i+1]) + -- Subsequent slices overlap each other to share data. + ofs = ffi.offsetof(o, "arch") + i*ffi.sizeof(o.arch[0]) + a.offset = be32(ofs) + a.size = be32(mach_size-ofs+#s) + end + local a = o.arch[i] + a.hdr.magic = is64 and 0xfeedfacf or 0xfeedface + a.hdr.cputype = cputype[i+1] + a.hdr.cpusubtype = cpusubtype[i+1] + a.hdr.filetype = 1 + a.hdr.ncmds = 2 + a.hdr.sizeofcmds = ffi.sizeof(a.seg)+ffi.sizeof(a.sec)+ffi.sizeof(a.sym) + a.seg.cmd = is64 and 0x19 or 0x1 + a.seg.cmdsize = ffi.sizeof(a.seg)+ffi.sizeof(a.sec) + a.seg.vmsize = #s + a.seg.fileoff = mach_size-ofs + a.seg.filesize = #s + a.seg.maxprot = 1 + a.seg.initprot = 1 + a.seg.nsects = 1 + ffi.copy(a.sec.sectname, "__data") + ffi.copy(a.sec.segname, "__DATA") + a.sec.size = #s + a.sec.offset = mach_size-ofs + a.sym.cmd = 2 + a.sym.cmdsize = ffi.sizeof(a.sym) + a.sym.symoff = ffi.offsetof(o, "sym_entry")-ofs + a.sym.nsyms = 1 + a.sym.stroff = ffi.offsetof(o, "sym_entry")+ffi.sizeof(o.sym_entry)-ofs + a.sym.strsize = aligned(#symname+2, align) + end + o.sym_entry.type = 0xf + o.sym_entry.sect = 1 + o.sym_entry.strx = 1 + ffi.copy(o.space+1, symname) + + -- Write Macho-O object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, mach_size)) + bcsave_tail(fp, output, s) +end + +local function bcsave_obj(ctx, output, s) + local ok, ffi = pcall(require, "ffi") + check(ok, "FFI library required to write this file type") + if ctx.os == "windows" then + return bcsave_peobj(ctx, output, s, ffi) + elseif ctx.os == "osx" then + return bcsave_machobj(ctx, output, s, ffi) + else + return bcsave_elfobj(ctx, output, s, ffi) + end +end + +------------------------------------------------------------------------------ + +local function bclist(input, output) + local f = readfile(input) + require("jit.bc").dump(f, savefile(output, "w"), true) +end + +local function bcsave(ctx, input, output) + local f = readfile(input) + local s = string.dump(f, ctx.strip) + local t = ctx.type + if not t then + t = detecttype(output) + ctx.type = t + end + if t == "raw" then + bcsave_raw(output, s) + else + if not ctx.modname then ctx.modname = detectmodname(input) end + if t == "obj" then + bcsave_obj(ctx, output, s) + else + bcsave_c(ctx, output, s) + end + end +end + +local function docmd(...) + local arg = {...} + local n = 1 + local list = false + local ctx = { + strip = true, arch = jit.arch, os = jit.os:lower(), + type = false, modname = false, + } + while n <= #arg do + local a = arg[n] + if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then + tremove(arg, n) + if a == "--" then break end + for m=2,#a do + local opt = a:sub(m, m) + if opt == "l" then + list = true + elseif opt == "s" then + ctx.strip = true + elseif opt == "g" then + ctx.strip = false + else + if arg[n] == nil or m ~= #a then usage() end + if opt == "e" then + if n ~= 1 then usage() end + arg[1] = check(loadstring(arg[1])) + elseif opt == "n" then + ctx.modname = checkmodname(tremove(arg, n)) + elseif opt == "t" then + ctx.type = checkarg(tremove(arg, n), map_type, "file type") + elseif opt == "a" then + ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture") + elseif opt == "o" then + ctx.os = checkarg(tremove(arg, n), map_os, "OS name") + else + usage() + end + end + end + else + n = n + 1 + end + end + if list then + if #arg == 0 or #arg > 2 then usage() end + bclist(arg[1], arg[2] or "-") + else + if #arg ~= 2 then usage() end + bcsave(ctx, arg[1], arg[2]) + end +end + +------------------------------------------------------------------------------ + +-- Public module functions. +return { + start = docmd -- Process -b command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm.lua new file mode 100644 index 00000000..ba79c47e --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm.lua @@ -0,0 +1,689 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles most user-mode ARMv7 instructions +-- NYI: Advanced SIMD and VFP instructions. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch = string.match, string.gmatch +local concat = table.concat +local bit = require("bit") +local band, bor, ror, tohex = bit.band, bit.bor, bit.ror, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Opcode maps +------------------------------------------------------------------------------ + +local map_loadc = { + shift = 8, mask = 15, + [10] = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "vmovFmDN", "vstmFNdr", + _ = { + shift = 21, mask = 1, + [0] = "vstrFdl", + { shift = 16, mask = 15, [13] = "vpushFdr", _ = "vstmdbFNdr", } + }, + }, + { + shift = 23, mask = 3, + [0] = "vmovFDNm", + { shift = 16, mask = 15, [13] = "vpopFdr", _ = "vldmFNdr", }, + _ = { + shift = 21, mask = 1, + [0] = "vldrFdl", "vldmdbFNdr", + }, + }, + }, + [11] = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "vmovGmDN", "vstmGNdr", + _ = { + shift = 21, mask = 1, + [0] = "vstrGdl", + { shift = 16, mask = 15, [13] = "vpushGdr", _ = "vstmdbGNdr", } + }, + }, + { + shift = 23, mask = 3, + [0] = "vmovGDNm", + { shift = 16, mask = 15, [13] = "vpopGdr", _ = "vldmGNdr", }, + _ = { + shift = 21, mask = 1, + [0] = "vldrGdl", "vldmdbGNdr", + }, + }, + }, + _ = { + shift = 0, mask = 0 -- NYI ldc, mcrr, mrrc. + }, +} + +local map_vfps = { + shift = 6, mask = 0x2c001, + [0] = "vmlaF.dnm", "vmlsF.dnm", + [0x04000] = "vnmlsF.dnm", [0x04001] = "vnmlaF.dnm", + [0x08000] = "vmulF.dnm", [0x08001] = "vnmulF.dnm", + [0x0c000] = "vaddF.dnm", [0x0c001] = "vsubF.dnm", + [0x20000] = "vdivF.dnm", + [0x24000] = "vfnmsF.dnm", [0x24001] = "vfnmaF.dnm", + [0x28000] = "vfmaF.dnm", [0x28001] = "vfmsF.dnm", + [0x2c000] = "vmovF.dY", + [0x2c001] = { + shift = 7, mask = 0x1e01, + [0] = "vmovF.dm", "vabsF.dm", + [0x0200] = "vnegF.dm", [0x0201] = "vsqrtF.dm", + [0x0800] = "vcmpF.dm", [0x0801] = "vcmpeF.dm", + [0x0a00] = "vcmpzF.d", [0x0a01] = "vcmpzeF.d", + [0x0e01] = "vcvtG.dF.m", + [0x1000] = "vcvt.f32.u32Fdm", [0x1001] = "vcvt.f32.s32Fdm", + [0x1800] = "vcvtr.u32F.dm", [0x1801] = "vcvt.u32F.dm", + [0x1a00] = "vcvtr.s32F.dm", [0x1a01] = "vcvt.s32F.dm", + }, +} + +local map_vfpd = { + shift = 6, mask = 0x2c001, + [0] = "vmlaG.dnm", "vmlsG.dnm", + [0x04000] = "vnmlsG.dnm", [0x04001] = "vnmlaG.dnm", + [0x08000] = "vmulG.dnm", [0x08001] = "vnmulG.dnm", + [0x0c000] = "vaddG.dnm", [0x0c001] = "vsubG.dnm", + [0x20000] = "vdivG.dnm", + [0x24000] = "vfnmsG.dnm", [0x24001] = "vfnmaG.dnm", + [0x28000] = "vfmaG.dnm", [0x28001] = "vfmsG.dnm", + [0x2c000] = "vmovG.dY", + [0x2c001] = { + shift = 7, mask = 0x1e01, + [0] = "vmovG.dm", "vabsG.dm", + [0x0200] = "vnegG.dm", [0x0201] = "vsqrtG.dm", + [0x0800] = "vcmpG.dm", [0x0801] = "vcmpeG.dm", + [0x0a00] = "vcmpzG.d", [0x0a01] = "vcmpzeG.d", + [0x0e01] = "vcvtF.dG.m", + [0x1000] = "vcvt.f64.u32GdFm", [0x1001] = "vcvt.f64.s32GdFm", + [0x1800] = "vcvtr.u32FdG.m", [0x1801] = "vcvt.u32FdG.m", + [0x1a00] = "vcvtr.s32FdG.m", [0x1a01] = "vcvt.s32FdG.m", + }, +} + +local map_datac = { + shift = 24, mask = 1, + [0] = { + shift = 4, mask = 1, + [0] = { + shift = 8, mask = 15, + [10] = map_vfps, + [11] = map_vfpd, + -- NYI cdp, mcr, mrc. + }, + { + shift = 8, mask = 15, + [10] = { + shift = 20, mask = 15, + [0] = "vmovFnD", "vmovFDn", + [14] = "vmsrD", + [15] = { shift = 12, mask = 15, [15] = "vmrs", _ = "vmrsD", }, + }, + }, + }, + "svcT", +} + +local map_loadcu = { + shift = 0, mask = 0, -- NYI unconditional CP load/store. +} + +local map_datacu = { + shift = 0, mask = 0, -- NYI unconditional CP data. +} + +local map_simddata = { + shift = 0, mask = 0, -- NYI SIMD data. +} + +local map_simdload = { + shift = 0, mask = 0, -- NYI SIMD load/store, preload. +} + +local map_preload = { + shift = 0, mask = 0, -- NYI preload. +} + +local map_media = { + shift = 20, mask = 31, + [0] = false, + { --01 + shift = 5, mask = 7, + [0] = "sadd16DNM", "sasxDNM", "ssaxDNM", "ssub16DNM", + "sadd8DNM", false, false, "ssub8DNM", + }, + { --02 + shift = 5, mask = 7, + [0] = "qadd16DNM", "qasxDNM", "qsaxDNM", "qsub16DNM", + "qadd8DNM", false, false, "qsub8DNM", + }, + { --03 + shift = 5, mask = 7, + [0] = "shadd16DNM", "shasxDNM", "shsaxDNM", "shsub16DNM", + "shadd8DNM", false, false, "shsub8DNM", + }, + false, + { --05 + shift = 5, mask = 7, + [0] = "uadd16DNM", "uasxDNM", "usaxDNM", "usub16DNM", + "uadd8DNM", false, false, "usub8DNM", + }, + { --06 + shift = 5, mask = 7, + [0] = "uqadd16DNM", "uqasxDNM", "uqsaxDNM", "uqsub16DNM", + "uqadd8DNM", false, false, "uqsub8DNM", + }, + { --07 + shift = 5, mask = 7, + [0] = "uhadd16DNM", "uhasxDNM", "uhsaxDNM", "uhsub16DNM", + "uhadd8DNM", false, false, "uhsub8DNM", + }, + { --08 + shift = 5, mask = 7, + [0] = "pkhbtDNMU", false, "pkhtbDNMU", + { shift = 16, mask = 15, [15] = "sxtb16DMU", _ = "sxtab16DNMU", }, + "pkhbtDNMU", "selDNM", "pkhtbDNMU", + }, + false, + { --0a + shift = 5, mask = 7, + [0] = "ssatDxMu", "ssat16DxM", "ssatDxMu", + { shift = 16, mask = 15, [15] = "sxtbDMU", _ = "sxtabDNMU", }, + "ssatDxMu", false, "ssatDxMu", + }, + { --0b + shift = 5, mask = 7, + [0] = "ssatDxMu", "revDM", "ssatDxMu", + { shift = 16, mask = 15, [15] = "sxthDMU", _ = "sxtahDNMU", }, + "ssatDxMu", "rev16DM", "ssatDxMu", + }, + { --0c + shift = 5, mask = 7, + [3] = { shift = 16, mask = 15, [15] = "uxtb16DMU", _ = "uxtab16DNMU", }, + }, + false, + { --0e + shift = 5, mask = 7, + [0] = "usatDwMu", "usat16DwM", "usatDwMu", + { shift = 16, mask = 15, [15] = "uxtbDMU", _ = "uxtabDNMU", }, + "usatDwMu", false, "usatDwMu", + }, + { --0f + shift = 5, mask = 7, + [0] = "usatDwMu", "rbitDM", "usatDwMu", + { shift = 16, mask = 15, [15] = "uxthDMU", _ = "uxtahDNMU", }, + "usatDwMu", "revshDM", "usatDwMu", + }, + { --10 + shift = 12, mask = 15, + [15] = { + shift = 5, mask = 7, + "smuadNMS", "smuadxNMS", "smusdNMS", "smusdxNMS", + }, + _ = { + shift = 5, mask = 7, + [0] = "smladNMSD", "smladxNMSD", "smlsdNMSD", "smlsdxNMSD", + }, + }, + false, false, false, + { --14 + shift = 5, mask = 7, + [0] = "smlaldDNMS", "smlaldxDNMS", "smlsldDNMS", "smlsldxDNMS", + }, + { --15 + shift = 5, mask = 7, + [0] = { shift = 12, mask = 15, [15] = "smmulNMS", _ = "smmlaNMSD", }, + { shift = 12, mask = 15, [15] = "smmulrNMS", _ = "smmlarNMSD", }, + false, false, false, false, + "smmlsNMSD", "smmlsrNMSD", + }, + false, false, + { --18 + shift = 5, mask = 7, + [0] = { shift = 12, mask = 15, [15] = "usad8NMS", _ = "usada8NMSD", }, + }, + false, + { --1a + shift = 5, mask = 3, [2] = "sbfxDMvw", + }, + { --1b + shift = 5, mask = 3, [2] = "sbfxDMvw", + }, + { --1c + shift = 5, mask = 3, + [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", }, + }, + { --1d + shift = 5, mask = 3, + [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", }, + }, + { --1e + shift = 5, mask = 3, [2] = "ubfxDMvw", + }, + { --1f + shift = 5, mask = 3, [2] = "ubfxDMvw", + }, +} + +local map_load = { + shift = 21, mask = 9, + { + shift = 20, mask = 5, + [0] = "strtDL", "ldrtDL", [4] = "strbtDL", [5] = "ldrbtDL", + }, + _ = { + shift = 20, mask = 5, + [0] = "strDL", "ldrDL", [4] = "strbDL", [5] = "ldrbDL", + } +} + +local map_load1 = { + shift = 4, mask = 1, + [0] = map_load, map_media, +} + +local map_loadm = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "stmdaNR", "stmNR", + { shift = 16, mask = 63, [45] = "pushR", _ = "stmdbNR", }, "stmibNR", + }, + { + shift = 23, mask = 3, + [0] = "ldmdaNR", { shift = 16, mask = 63, [61] = "popR", _ = "ldmNR", }, + "ldmdbNR", "ldmibNR", + }, +} + +local map_data = { + shift = 21, mask = 15, + [0] = "andDNPs", "eorDNPs", "subDNPs", "rsbDNPs", + "addDNPs", "adcDNPs", "sbcDNPs", "rscDNPs", + "tstNP", "teqNP", "cmpNP", "cmnNP", + "orrDNPs", "movDPs", "bicDNPs", "mvnDPs", +} + +local map_mul = { + shift = 21, mask = 7, + [0] = "mulNMSs", "mlaNMSDs", "umaalDNMS", "mlsDNMS", + "umullDNMSs", "umlalDNMSs", "smullDNMSs", "smlalDNMSs", +} + +local map_sync = { + shift = 20, mask = 15, -- NYI: brackets around N. R(D+1) for ldrexd/strexd. + [0] = "swpDMN", false, false, false, + "swpbDMN", false, false, false, + "strexDMN", "ldrexDN", "strexdDN", "ldrexdDN", + "strexbDMN", "ldrexbDN", "strexhDN", "ldrexhDN", +} + +local map_mulh = { + shift = 21, mask = 3, + [0] = { shift = 5, mask = 3, + [0] = "smlabbNMSD", "smlatbNMSD", "smlabtNMSD", "smlattNMSD", }, + { shift = 5, mask = 3, + [0] = "smlawbNMSD", "smulwbNMS", "smlawtNMSD", "smulwtNMS", }, + { shift = 5, mask = 3, + [0] = "smlalbbDNMS", "smlaltbDNMS", "smlalbtDNMS", "smlalttDNMS", }, + { shift = 5, mask = 3, + [0] = "smulbbNMS", "smultbNMS", "smulbtNMS", "smulttNMS", }, +} + +local map_misc = { + shift = 4, mask = 7, + -- NYI: decode PSR bits of msr. + [0] = { shift = 21, mask = 1, [0] = "mrsD", "msrM", }, + { shift = 21, mask = 3, "bxM", false, "clzDM", }, + { shift = 21, mask = 3, "bxjM", }, + { shift = 21, mask = 3, "blxM", }, + false, + { shift = 21, mask = 3, [0] = "qaddDMN", "qsubDMN", "qdaddDMN", "qdsubDMN", }, + false, + { shift = 21, mask = 3, "bkptK", }, +} + +local map_datar = { + shift = 4, mask = 9, + [9] = { + shift = 5, mask = 3, + [0] = { shift = 24, mask = 1, [0] = map_mul, map_sync, }, + { shift = 20, mask = 1, [0] = "strhDL", "ldrhDL", }, + { shift = 20, mask = 1, [0] = "ldrdDL", "ldrsbDL", }, + { shift = 20, mask = 1, [0] = "strdDL", "ldrshDL", }, + }, + _ = { + shift = 20, mask = 25, + [16] = { shift = 7, mask = 1, [0] = map_misc, map_mulh, }, + _ = { + shift = 0, mask = 0xffffffff, + [bor(0xe1a00000)] = "nop", + _ = map_data, + } + }, +} + +local map_datai = { + shift = 20, mask = 31, -- NYI: decode PSR bits of msr. Decode imm12. + [16] = "movwDW", [20] = "movtDW", + [18] = { shift = 0, mask = 0xf00ff, [0] = "nopv6", _ = "msrNW", }, + [22] = "msrNW", + _ = map_data, +} + +local map_branch = { + shift = 24, mask = 1, + [0] = "bB", "blB" +} + +local map_condins = { + [0] = map_datar, map_datai, map_load, map_load1, + map_loadm, map_branch, map_loadc, map_datac +} + +-- NYI: setend. +local map_uncondins = { + [0] = false, map_simddata, map_simdload, map_preload, + false, "blxB", map_loadcu, map_datacu, +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", +} + +local map_cond = { + [0] = "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", +} + +local map_shift = { [0] = "lsl", "lsr", "asr", "ror", } + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then + extra = "\t->"..sym + elseif band(ctx.op, 0x0e000000) ~= 0x0a000000 then + extra = "\t; 0x"..tohex(ctx.rel) + end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-5s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-5s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +-- Format operand 2 of load/store opcodes. +local function fmtload(ctx, op, pos) + local base = map_gpr[band(rshift(op, 16), 15)] + local x, ofs + local ext = (band(op, 0x04000000) == 0) + if not ext and band(op, 0x02000000) == 0 then + ofs = band(op, 4095) + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + ofs = "#"..ofs + elseif ext and band(op, 0x00400000) ~= 0 then + ofs = band(op, 15) + band(rshift(op, 4), 0xf0) + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + ofs = "#"..ofs + else + ofs = map_gpr[band(op, 15)] + if ext or band(op, 0xfe0) == 0 then + elseif band(op, 0xfe0) == 0x60 then + ofs = format("%s, rrx", ofs) + else + local sh = band(rshift(op, 7), 31) + if sh == 0 then sh = 32 end + ofs = format("%s, %s #%d", ofs, map_shift[band(rshift(op, 5), 3)], sh) + end + if band(op, 0x00800000) == 0 then ofs = "-"..ofs end + end + if ofs == "#0" then + x = format("[%s]", base) + elseif band(op, 0x01000000) == 0 then + x = format("[%s], %s", base, ofs) + else + x = format("[%s, %s]", base, ofs) + end + if band(op, 0x01200000) == 0x01200000 then x = x.."!" end + return x +end + +-- Format operand 2 of vector load/store opcodes. +local function fmtvload(ctx, op, pos) + local base = map_gpr[band(rshift(op, 16), 15)] + local ofs = band(op, 255)*4 + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + if ofs == 0 then + return format("[%s]", base) + else + return format("[%s, #%d]", base, ofs) + end +end + +local function fmtvr(op, vr, sh0, sh1) + if vr == "s" then + return format("s%d", 2*band(rshift(op, sh0), 15)+band(rshift(op, sh1), 1)) + else + return format("d%d", band(rshift(op, sh0), 15)+band(rshift(op, sh1-4), 16)) + end +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) + local operands = {} + local suffix = "" + local last, name, pat + local vr + ctx.op = op + ctx.rel = nil + + local cond = rshift(op, 28) + local opat + if cond == 15 then + opat = map_uncondins[band(rshift(op, 25), 7)] + else + if cond ~= 14 then suffix = map_cond[cond] end + opat = map_condins[band(rshift(op, 25), 7)] + end + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + name, pat = match(opat, "^([a-z0-9]*)(.*)") + if sub(pat, 1, 1) == "." then + local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") + suffix = suffix..s2 + pat = p2 + end + + for p in gmatch(pat, ".") do + local x = nil + if p == "D" then + x = map_gpr[band(rshift(op, 12), 15)] + elseif p == "N" then + x = map_gpr[band(rshift(op, 16), 15)] + elseif p == "S" then + x = map_gpr[band(rshift(op, 8), 15)] + elseif p == "M" then + x = map_gpr[band(op, 15)] + elseif p == "d" then + x = fmtvr(op, vr, 12, 22) + elseif p == "n" then + x = fmtvr(op, vr, 16, 7) + elseif p == "m" then + x = fmtvr(op, vr, 0, 5) + elseif p == "P" then + if band(op, 0x02000000) ~= 0 then + x = ror(band(op, 255), 2*band(rshift(op, 8), 15)) + else + x = map_gpr[band(op, 15)] + if band(op, 0xff0) ~= 0 then + operands[#operands+1] = x + local s = map_shift[band(rshift(op, 5), 3)] + local r = nil + if band(op, 0xf90) == 0 then + if s == "ror" then s = "rrx" else r = "#32" end + elseif band(op, 0x10) == 0 then + r = "#"..band(rshift(op, 7), 31) + else + r = map_gpr[band(rshift(op, 8), 15)] + end + if name == "mov" then name = s; x = r + elseif r then x = format("%s %s", s, r) + else x = s end + end + end + elseif p == "L" then + x = fmtload(ctx, op, pos) + elseif p == "l" then + x = fmtvload(ctx, op, pos) + elseif p == "B" then + local addr = ctx.addr + pos + 8 + arshift(lshift(op, 8), 6) + if cond == 15 then addr = addr + band(rshift(op, 23), 2) end + ctx.rel = addr + x = "0x"..tohex(addr) + elseif p == "F" then + vr = "s" + elseif p == "G" then + vr = "d" + elseif p == "." then + suffix = suffix..(vr == "s" and ".f32" or ".f64") + elseif p == "R" then + if band(op, 0x00200000) ~= 0 and #operands == 1 then + operands[1] = operands[1].."!" + end + local t = {} + for i=0,15 do + if band(rshift(op, i), 1) == 1 then t[#t+1] = map_gpr[i] end + end + x = "{"..concat(t, ", ").."}" + elseif p == "r" then + if band(op, 0x00200000) ~= 0 and #operands == 2 then + operands[1] = operands[1].."!" + end + local s = tonumber(sub(last, 2)) + local n = band(op, 255) + if vr == "d" then n = rshift(n, 1) end + operands[#operands] = format("{%s-%s%d}", last, vr, s+n-1) + elseif p == "W" then + x = band(op, 0x0fff) + band(rshift(op, 4), 0xf000) + elseif p == "T" then + x = "#0x"..tohex(band(op, 0x00ffffff), 6) + elseif p == "U" then + x = band(rshift(op, 7), 31) + if x == 0 then x = nil end + elseif p == "u" then + x = band(rshift(op, 7), 31) + if band(op, 0x40) == 0 then + if x == 0 then x = nil else x = "lsl #"..x end + else + if x == 0 then x = "asr #32" else x = "asr #"..x end + end + elseif p == "v" then + x = band(rshift(op, 7), 31) + elseif p == "w" then + x = band(rshift(op, 16), 31) + elseif p == "x" then + x = band(rshift(op, 16), 31) + 1 + elseif p == "X" then + x = band(rshift(op, 16), 31) - last + 1 + elseif p == "Y" then + x = band(rshift(op, 12), 0xf0) + band(op, 0x0f) + elseif p == "K" then + x = "#0x"..tohex(band(rshift(op, 4), 0x0000fff0) + band(op, 15), 4) + elseif p == "s" then + if band(op, 0x00100000) ~= 0 then suffix = "s"..suffix end + else + assert(false) + end + if x then + last = x + if type(x) == "number" then x = "#"..x end + operands[#operands+1] = x + end + end + + return putop(ctx, name..suffix, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ctx.pos = ofs + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 16 then return map_gpr[r] end + return "d"..(r-16) +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm64.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm64.lua new file mode 100644 index 00000000..ad909fbd --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm64.lua @@ -0,0 +1,1216 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM64 disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +-- +-- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com. +-- Sponsored by Cisco Systems, Inc. +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles most user-mode AArch64 instructions. +-- NYI: Advanced SIMD and VFP instructions. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local concat = table.concat +local bit = require("bit") +local band, bor, bxor, tohex = bit.band, bit.bor, bit.bxor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift +local ror = bit.ror + +------------------------------------------------------------------------------ +-- Opcode maps +------------------------------------------------------------------------------ + +local map_adr = { -- PC-relative addressing. + shift = 31, mask = 1, + [0] = "adrDBx", "adrpDBx" +} + +local map_addsubi = { -- Add/subtract immediate. + shift = 29, mask = 3, + [0] = "add|movDNIg", "adds|cmnD0NIg", "subDNIg", "subs|cmpD0NIg", +} + +local map_logi = { -- Logical immediate. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "andDNig", "orr|movDN0ig", "eorDNig", "ands|tstD0Nig" + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = "andDNig", "orr|movDN0ig", "eorDNig", "ands|tstD0Nig" + } +} + +local map_movwi = { -- Move wide immediate. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "movnDWRg", false, "movz|movDYRg", "movkDWRg" + }, false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = "movnDWRg", false, "movz|movDYRg", "movkDWRg" + }, +} + +local map_bitf = { -- Bitfield. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "sbfm|sbfiz|sbfx|asr|sxtw|sxth|sxtbDN12w", + "bfm|bfi|bfxilDN13w", + "ubfm|ubfiz|ubfx|lsr|lsl|uxth|uxtbDN12w" + } + }, + { + shift = 22, mask = 1, + { + shift = 29, mask = 3, + [0] = "sbfm|sbfiz|sbfx|asr|sxtw|sxth|sxtbDN12x", + "bfm|bfi|bfxilDN13x", + "ubfm|ubfiz|ubfx|lsr|lsl|uxth|uxtbDN12x" + } + } +} + +local map_datai = { -- Data processing - immediate. + shift = 23, mask = 7, + [0] = map_adr, map_adr, map_addsubi, false, + map_logi, map_movwi, map_bitf, + { + shift = 15, mask = 0x1c0c1, + [0] = "extr|rorDNM4w", [0x10080] = "extr|rorDNM4x", + [0x10081] = "extr|rorDNM4x" + } +} + +local map_logsr = { -- Logical, shifted register. + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = { + shift = 21, mask = 7, + [0] = "andDNMSg", "bicDNMSg", "andDNMSg", "bicDNMSg", + "andDNMSg", "bicDNMSg", "andDNMg", "bicDNMg" + }, + { + shift = 21, mask = 7, + [0] ="orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0MSg", "orn|mvnDN0MSg", + "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0Mg", "orn|mvnDN0Mg" + }, + { + shift = 21, mask = 7, + [0] = "eorDNMSg", "eonDNMSg", "eorDNMSg", "eonDNMSg", + "eorDNMSg", "eonDNMSg", "eorDNMg", "eonDNMg" + }, + { + shift = 21, mask = 7, + [0] = "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMSg", "bicsDNMSg", + "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMg", "bicsDNMg" + } + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = { + shift = 21, mask = 7, + [0] = "andDNMSg", "bicDNMSg", "andDNMSg", "bicDNMSg", + "andDNMSg", "bicDNMSg", "andDNMg", "bicDNMg" + }, + { + shift = 21, mask = 7, + [0] = "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0MSg", "orn|mvnDN0MSg", + "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0Mg", "orn|mvnDN0Mg" + }, + { + shift = 21, mask = 7, + [0] = "eorDNMSg", "eonDNMSg", "eorDNMSg", "eonDNMSg", + "eorDNMSg", "eonDNMSg", "eorDNMg", "eonDNMg" + }, + { + shift = 21, mask = 7, + [0] = "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMSg", "bicsDNMSg", + "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMg", "bicsDNMg" + } + } +} + +local map_assh = { + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "addDNMSg", "addDNMSg", "addDNMSg", "addDNMg" + }, + { + shift = 22, mask = 3, + [0] = "adds|cmnD0NMSg", "adds|cmnD0NMSg", + "adds|cmnD0NMSg", "adds|cmnD0NMg" + }, + { + shift = 22, mask = 3, + [0] = "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0Mg" + }, + { + shift = 22, mask = 3, + [0] = "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0MzSg", + "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0Mzg" + }, + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "addDNMSg", "addDNMSg", "addDNMSg", "addDNMg" + }, + { + shift = 22, mask = 3, + [0] = "adds|cmnD0NMSg", "adds|cmnD0NMSg", "adds|cmnD0NMSg", + "adds|cmnD0NMg" + }, + { + shift = 22, mask = 3, + [0] = "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0Mg" + }, + { + shift = 22, mask = 3, + [0] = "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0MzSg", + "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0Mzg" + } + } +} + +local map_addsubsh = { -- Add/subtract, shifted register. + shift = 22, mask = 3, + [0] = map_assh, map_assh, map_assh +} + +local map_addsubex = { -- Add/subtract, extended register. + shift = 22, mask = 3, + [0] = { + shift = 29, mask = 3, + [0] = "addDNMXg", "adds|cmnD0NMXg", "subDNMXg", "subs|cmpD0NMzXg", + } +} + +local map_addsubc = { -- Add/subtract, with carry. + shift = 10, mask = 63, + [0] = { + shift = 29, mask = 3, + [0] = "adcDNMg", "adcsDNMg", "sbc|ngcDN0Mg", "sbcs|ngcsDN0Mg", + } +} + +local map_ccomp = { + shift = 4, mask = 1, + [0] = { + shift = 10, mask = 3, + [0] = { -- Conditional compare register. + shift = 29, mask = 3, + "ccmnNMVCg", false, "ccmpNMVCg", + }, + [2] = { -- Conditional compare immediate. + shift = 29, mask = 3, + "ccmnN5VCg", false, "ccmpN5VCg", + } + } +} + +local map_csel = { -- Conditional select. + shift = 11, mask = 1, + [0] = { + shift = 10, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "cselDNMzCg", false, "csinv|cinv|csetmDNMcg", false, + }, + { + shift = 29, mask = 3, + [0] = "csinc|cinc|csetDNMcg", false, "csneg|cnegDNMcg", false, + } + } +} + +local map_data1s = { -- Data processing, 1 source. + shift = 29, mask = 1, + [0] = { + shift = 31, mask = 1, + [0] = { + shift = 10, mask = 0x7ff, + [0] = "rbitDNg", "rev16DNg", "revDNw", false, "clzDNg", "clsDNg" + }, + { + shift = 10, mask = 0x7ff, + [0] = "rbitDNg", "rev16DNg", "rev32DNx", "revDNx", "clzDNg", "clsDNg" + } + } +} + +local map_data2s = { -- Data processing, 2 sources. + shift = 29, mask = 1, + [0] = { + shift = 10, mask = 63, + false, "udivDNMg", "sdivDNMg", false, false, false, false, "lslDNMg", + "lsrDNMg", "asrDNMg", "rorDNMg" + } +} + +local map_data3s = { -- Data processing, 3 sources. + shift = 29, mask = 7, + [0] = { + shift = 21, mask = 7, + [0] = { + shift = 15, mask = 1, + [0] = "madd|mulDNMA0g", "msub|mnegDNMA0g" + } + }, false, false, false, + { + shift = 15, mask = 1, + [0] = { + shift = 21, mask = 7, + [0] = "madd|mulDNMA0g", "smaddl|smullDxNMwA0x", "smulhDNMx", false, + false, "umaddl|umullDxNMwA0x", "umulhDNMx" + }, + { + shift = 21, mask = 7, + [0] = "msub|mnegDNMA0g", "smsubl|smneglDxNMwA0x", false, false, + false, "umsubl|umneglDxNMwA0x" + } + } +} + +local map_datar = { -- Data processing, register. + shift = 28, mask = 1, + [0] = { + shift = 24, mask = 1, + [0] = map_logsr, + { + shift = 21, mask = 1, + [0] = map_addsubsh, map_addsubex + } + }, + { + shift = 21, mask = 15, + [0] = map_addsubc, false, map_ccomp, false, map_csel, false, + { + shift = 30, mask = 1, + [0] = map_data2s, map_data1s + }, + false, map_data3s, map_data3s, map_data3s, map_data3s, map_data3s, + map_data3s, map_data3s, map_data3s + } +} + +local map_lrl = { -- Load register, literal. + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = "ldrDwB", "ldrDxB", "ldrswDxB" + }, + { + shift = 30, mask = 3, + [0] = "ldrDsB", "ldrDdB" + } +} + +local map_lsriind = { -- Load/store register, immediate pre/post-indexed. + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwzL", "ldrbDwzL", "ldrsbDxzL", "ldrsbDwzL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strhDwzL", "ldrhDwzL", "ldrshDxzL", "ldrshDwzL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strDwzL", "ldrDwzL", "ldrswDxzL" + }, + { + shift = 22, mask = 3, + [0] = "strDszL", "ldrDszL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strDxzL", "ldrDxzL" + }, + { + shift = 22, mask = 3, + [0] = "strDdzL", "ldrDdzL" + } + } +} + +local map_lsriro = { + shift = 21, mask = 1, + [0] = { -- Load/store register immediate. + shift = 10, mask = 3, + [0] = { -- Unscaled immediate. + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "sturbDwK", "ldurbDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturhDwK", "ldurhDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturDwK", "ldurDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturDxK", "ldurDxK" + } + } + }, map_lsriind, false, map_lsriind + }, + { -- Load/store register, register offset. + shift = 10, mask = 3, + [2] = { + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwO", "ldrbDwO", "ldrsbDxO", "ldrsbDwO" + }, + { + shift = 22, mask = 3, + [0] = "strhDwO", "ldrhDwO", "ldrshDxO", "ldrshDwO" + }, + { + shift = 22, mask = 3, + [0] = "strDwO", "ldrDwO", "ldrswDxO" + }, + { + shift = 22, mask = 3, + [0] = "strDxO", "ldrDxO" + } + }, + { + shift = 30, mask = 3, + [2] = { + shift = 22, mask = 3, + [0] = "strDsO", "ldrDsO" + }, + [3] = { + shift = 22, mask = 3, + [0] = "strDdO", "ldrDdO" + } + } + } + } +} + +local map_lsp = { -- Load/store register pair, offset. + shift = 22, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = "stpDzAzwP", "stpDzAzsP", + }, + { + shift = 26, mask = 1, + "stpDzAzdP" + }, + { + shift = 26, mask = 1, + [0] = "stpDzAzxP" + } + }, + { + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = "ldpDzAzwP", "ldpDzAzsP", + }, + { + shift = 26, mask = 1, + [0] = "ldpswDAxP", "ldpDzAzdP" + }, + { + shift = 26, mask = 1, + [0] = "ldpDzAzxP" + } + } +} + +local map_ls = { -- Loads and stores. + shift = 24, mask = 0x31, + [0x10] = map_lrl, [0x30] = map_lsriro, + [0x20] = { + shift = 23, mask = 3, + map_lsp, map_lsp, map_lsp + }, + [0x21] = { + shift = 23, mask = 3, + map_lsp, map_lsp, map_lsp + }, + [0x31] = { + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwzU", "ldrbDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strhDwzU", "ldrhDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strDwzU", "ldrDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strDxzU", "ldrDxzU" + } + }, + { + shift = 30, mask = 3, + [2] = { + shift = 22, mask = 3, + [0] = "strDszU", "ldrDszU" + }, + [3] = { + shift = 22, mask = 3, + [0] = "strDdzU", "ldrDdzU" + } + } + }, +} + +local map_datafp = { -- Data processing, SIMD and FP. + shift = 28, mask = 7, + { -- 001 + shift = 24, mask = 1, + [0] = { + shift = 21, mask = 1, + { + shift = 10, mask = 3, + [0] = { + shift = 12, mask = 1, + [0] = { + shift = 13, mask = 1, + [0] = { + shift = 14, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { -- FP/int conversion. + shift = 31, mask = 1, + [0] = { + shift = 16, mask = 0xff, + [0x20] = "fcvtnsDwNs", [0x21] = "fcvtnuDwNs", + [0x22] = "scvtfDsNw", [0x23] = "ucvtfDsNw", + [0x24] = "fcvtasDwNs", [0x25] = "fcvtauDwNs", + [0x26] = "fmovDwNs", [0x27] = "fmovDsNw", + [0x28] = "fcvtpsDwNs", [0x29] = "fcvtpuDwNs", + [0x30] = "fcvtmsDwNs", [0x31] = "fcvtmuDwNs", + [0x38] = "fcvtzsDwNs", [0x39] = "fcvtzuDwNs", + [0x60] = "fcvtnsDwNd", [0x61] = "fcvtnuDwNd", + [0x62] = "scvtfDdNw", [0x63] = "ucvtfDdNw", + [0x64] = "fcvtasDwNd", [0x65] = "fcvtauDwNd", + [0x68] = "fcvtpsDwNd", [0x69] = "fcvtpuDwNd", + [0x70] = "fcvtmsDwNd", [0x71] = "fcvtmuDwNd", + [0x78] = "fcvtzsDwNd", [0x79] = "fcvtzuDwNd" + }, + { + shift = 16, mask = 0xff, + [0x20] = "fcvtnsDxNs", [0x21] = "fcvtnuDxNs", + [0x22] = "scvtfDsNx", [0x23] = "ucvtfDsNx", + [0x24] = "fcvtasDxNs", [0x25] = "fcvtauDxNs", + [0x28] = "fcvtpsDxNs", [0x29] = "fcvtpuDxNs", + [0x30] = "fcvtmsDxNs", [0x31] = "fcvtmuDxNs", + [0x38] = "fcvtzsDxNs", [0x39] = "fcvtzuDxNs", + [0x60] = "fcvtnsDxNd", [0x61] = "fcvtnuDxNd", + [0x62] = "scvtfDdNx", [0x63] = "ucvtfDdNx", + [0x64] = "fcvtasDxNd", [0x65] = "fcvtauDxNd", + [0x66] = "fmovDxNd", [0x67] = "fmovDdNx", + [0x68] = "fcvtpsDxNd", [0x69] = "fcvtpuDxNd", + [0x70] = "fcvtmsDxNd", [0x71] = "fcvtmuDxNd", + [0x78] = "fcvtzsDxNd", [0x79] = "fcvtzuDxNd" + } + } + }, + { -- FP data-processing, 1 source. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = { + shift = 15, mask = 63, + [0] = "fmovDNf", "fabsDNf", "fnegDNf", + "fsqrtDNf", false, "fcvtDdNs", false, false, + "frintnDNf", "frintpDNf", "frintmDNf", "frintzDNf", + "frintaDNf", false, "frintxDNf", "frintiDNf", + }, + { + shift = 15, mask = 63, + [0] = "fmovDNf", "fabsDNf", "fnegDNf", + "fsqrtDNf", "fcvtDsNd", false, false, false, + "frintnDNf", "frintpDNf", "frintmDNf", "frintzDNf", + "frintaDNf", false, "frintxDNf", "frintiDNf", + } + } + } + }, + { -- FP compare. + shift = 31, mask = 1, + [0] = { + shift = 14, mask = 3, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 0, mask = 31, + [0] = "fcmpNMf", [8] = "fcmpNZf", + [16] = "fcmpeNMf", [24] = "fcmpeNZf", + } + } + } + } + }, + { -- FP immediate. + shift = 31, mask = 1, + [0] = { + shift = 5, mask = 31, + [0] = { + shift = 23, mask = 1, + [0] = "fmovDFf" + } + } + } + }, + { -- FP conditional compare. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 4, mask = 1, + [0] = "fccmpNMVCf", "fccmpeNMVCf" + } + } + }, + { -- FP data-processing, 2 sources. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 12, mask = 15, + [0] = "fmulDNMf", "fdivDNMf", "faddDNMf", "fsubDNMf", + "fmaxDNMf", "fminDNMf", "fmaxnmDNMf", "fminnmDNMf", + "fnmulDNMf" + } + } + }, + { -- FP conditional select. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = "fcselDNMCf" + } + } + } + }, + { -- FP data-processing, 3 sources. + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 21, mask = 5, + [0] = "fmaddDNMAf", "fnmaddDNMAf" + }, + { + shift = 21, mask = 5, + [0] = "fmsubDNMAf", "fnmsubDNMAf" + } + } + } + } +} + +local map_br = { -- Branches, exception generating and system instructions. + shift = 29, mask = 7, + [0] = "bB", + { -- Compare & branch, immediate. + shift = 24, mask = 3, + [0] = "cbzDBg", "cbnzDBg", "tbzDTBw", "tbnzDTBw" + }, + { -- Conditional branch, immediate. + shift = 24, mask = 3, + [0] = { + shift = 4, mask = 1, + [0] = { + shift = 0, mask = 15, + [0] = "beqB", "bneB", "bhsB", "bloB", "bmiB", "bplB", "bvsB", "bvcB", + "bhiB", "blsB", "bgeB", "bltB", "bgtB", "bleB", "balB" + } + } + }, false, "blB", + { -- Compare & branch, immediate. + shift = 24, mask = 3, + [0] = "cbzDBg", "cbnzDBg", "tbzDTBx", "tbnzDTBx" + }, + { + shift = 24, mask = 3, + [0] = { -- Exception generation. + shift = 0, mask = 0xe0001f, + [0x200000] = "brkW" + }, + { -- System instructions. + shift = 0, mask = 0x3fffff, + [0x03201f] = "nop" + }, + { -- Unconditional branch, register. + shift = 0, mask = 0xfffc1f, + [0x1f0000] = "brNx", [0x3f0000] = "blrNx", + [0x5f0000] = "retNx" + }, + } +} + +local map_init = { + shift = 25, mask = 15, + [0] = false, false, false, false, map_ls, map_datar, map_ls, map_datafp, + map_datai, map_datai, map_br, map_br, map_ls, map_datar, map_ls, map_datafp +} + +------------------------------------------------------------------------------ + +local map_regs = { x = {}, w = {}, d = {}, s = {} } + +for i=0,30 do + map_regs.x[i] = "x"..i + map_regs.w[i] = "w"..i + map_regs.d[i] = "d"..i + map_regs.s[i] = "s"..i +end +map_regs.x[31] = "sp" +map_regs.w[31] = "wsp" +map_regs.d[31] = "d31" +map_regs.s[31] = "s31" + +local map_cond = { + [0] = "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", +} + +local map_shift = { [0] = "lsl", "lsr", "asr", } + +local map_extend = { + [0] = "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx", +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then + extra = "\t->"..sym + end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-5s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-5s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +local function match_reg(p, pat, regnum) + return map_regs[match(pat, p.."%w-([xwds])")][regnum] +end + +local function fmt_hex32(x) + if x < 0 then + return tohex(x) + else + return format("%x", x) + end +end + +local imm13_rep = { 0x55555555, 0x11111111, 0x01010101, 0x00010001, 0x00000001 } + +local function decode_imm13(op) + local imms = band(rshift(op, 10), 63) + local immr = band(rshift(op, 16), 63) + if band(op, 0x00400000) == 0 then + local len = 5 + if imms >= 56 then + if imms >= 60 then len = 1 else len = 2 end + elseif imms >= 48 then len = 3 elseif imms >= 32 then len = 4 end + local l = lshift(1, len)-1 + local s = band(imms, l) + local r = band(immr, l) + local imm = ror(rshift(-1, 31-s), r) + if len ~= 5 then imm = band(imm, lshift(1, l)-1) + rshift(imm, 31-l) end + imm = imm * imm13_rep[len] + local ix = fmt_hex32(imm) + if rshift(op, 31) ~= 0 then + return ix..tohex(imm) + else + return ix + end + else + local lo, hi = -1, 0 + if imms < 32 then lo = rshift(-1, 31-imms) else hi = rshift(-1, 63-imms) end + if immr ~= 0 then + lo, hi = ror(lo, immr), ror(hi, immr) + local x = immr == 32 and 0 or band(bxor(lo, hi), lshift(-1, 32-immr)) + lo, hi = bxor(lo, x), bxor(hi, x) + if immr >= 32 then lo, hi = hi, lo end + end + if hi ~= 0 then + return fmt_hex32(hi)..tohex(lo) + else + return fmt_hex32(lo) + end + end +end + +local function parse_immpc(op, name) + if name == "b" or name == "bl" then + return arshift(lshift(op, 6), 4) + elseif name == "adr" or name == "adrp" then + local immlo = band(rshift(op, 29), 3) + local immhi = lshift(arshift(lshift(op, 8), 13), 2) + return bor(immhi, immlo) + elseif name == "tbz" or name == "tbnz" then + return lshift(arshift(lshift(op, 13), 18), 2) + else + return lshift(arshift(lshift(op, 8), 13), 2) + end +end + +local function parse_fpimm8(op) + local sign = band(op, 0x100000) == 0 and 1 or -1 + local exp = bxor(rshift(arshift(lshift(op, 12), 5), 24), 0x80) - 131 + local frac = 16+band(rshift(op, 13), 15) + return sign * frac * 2^exp +end + +local function prefer_bfx(sf, uns, imms, immr) + if imms < immr or imms == 31 or imms == 63 then + return false + end + if immr == 0 then + if sf == 0 and (imms == 7 or imms == 15) then + return false + end + if sf ~= 0 and uns == 0 and (imms == 7 or imms == 15 or imms == 31) then + return false + end + end + return true +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) + local operands = {} + local suffix = "" + local last, name, pat + local map_reg + ctx.op = op + ctx.rel = nil + last = nil + local opat + opat = map_init[band(rshift(op, 25), 15)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + name, pat = match(opat, "^([a-z0-9]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") + if altname then pat = pat2 end + if sub(pat, 1, 1) == "." then + local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") + suffix = suffix..s2 + pat = p2 + end + + local rt = match(pat, "[gf]") + if rt then + if rt == "g" then + map_reg = band(op, 0x80000000) ~= 0 and map_regs.x or map_regs.w + else + map_reg = band(op, 0x400000) ~= 0 and map_regs.d or map_regs.s + end + end + + local second0, immr + + for p in gmatch(pat, ".") do + local x = nil + if p == "D" then + local regnum = band(op, 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "N" then + local regnum = band(rshift(op, 5), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "M" then + local regnum = band(rshift(op, 16), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "A" then + local regnum = band(rshift(op, 10), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "B" then + local addr = ctx.addr + pos + parse_immpc(op, name) + ctx.rel = addr + x = "0x"..tohex(addr) + elseif p == "T" then + x = bor(band(rshift(op, 26), 32), band(rshift(op, 19), 31)) + elseif p == "V" then + x = band(op, 15) + elseif p == "C" then + x = map_cond[band(rshift(op, 12), 15)] + elseif p == "c" then + local rn = band(rshift(op, 5), 31) + local rm = band(rshift(op, 16), 31) + local cond = band(rshift(op, 12), 15) + local invc = bxor(cond, 1) + x = map_cond[cond] + if altname and cond ~= 14 and cond ~= 15 then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if rn == rm then + local n = #operands + operands[n] = nil + x = map_cond[invc] + if rn ~= 31 then + if a1 then name = a1 else name = altname end + else + operands[n-1] = nil + name = a2 + end + end + end + elseif p == "W" then + x = band(rshift(op, 5), 0xffff) + elseif p == "Y" then + x = band(rshift(op, 5), 0xffff) + local hw = band(rshift(op, 21), 3) + if altname and (hw == 0 or x ~= 0) then + name = altname + end + elseif p == "L" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local imm9 = arshift(lshift(op, 11), 23) + if band(op, 0x800) ~= 0 then + x = "["..rn..", #"..imm9.."]!" + else + x = "["..rn.."], #"..imm9 + end + elseif p == "U" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local sz = band(rshift(op, 30), 3) + local imm12 = lshift(arshift(lshift(op, 10), 20), sz) + if imm12 ~= 0 then + x = "["..rn..", #"..imm12.."]" + else + x = "["..rn.."]" + end + elseif p == "K" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local imm9 = arshift(lshift(op, 11), 23) + if imm9 ~= 0 then + x = "["..rn..", #"..imm9.."]" + else + x = "["..rn.."]" + end + elseif p == "O" then + local rn, rm = map_regs.x[band(rshift(op, 5), 31)] + local m = band(rshift(op, 13), 1) + if m == 0 then + rm = map_regs.w[band(rshift(op, 16), 31)] + else + rm = map_regs.x[band(rshift(op, 16), 31)] + end + x = "["..rn..", "..rm + local opt = band(rshift(op, 13), 7) + local s = band(rshift(op, 12), 1) + local sz = band(rshift(op, 30), 3) + -- extension to be applied + if opt == 3 then + if s == 0 then x = x.."]" + else x = x..", lsl #"..sz.."]" end + elseif opt == 2 or opt == 6 or opt == 7 then + if s == 0 then x = x..", "..map_extend[opt].."]" + else x = x..", "..map_extend[opt].." #"..sz.."]" end + else + x = x.."]" + end + elseif p == "P" then + local opcv, sh = rshift(op, 26), 2 + if opcv >= 0x2a then sh = 4 elseif opcv >= 0x1b then sh = 3 end + local imm7 = lshift(arshift(lshift(op, 10), 25), sh) + local rn = map_regs.x[band(rshift(op, 5), 31)] + local ind = band(rshift(op, 23), 3) + if ind == 1 then + x = "["..rn.."], #"..imm7 + elseif ind == 2 then + if imm7 == 0 then + x = "["..rn.."]" + else + x = "["..rn..", #"..imm7.."]" + end + elseif ind == 3 then + x = "["..rn..", #"..imm7.."]!" + end + elseif p == "I" then + local shf = band(rshift(op, 22), 3) + local imm12 = band(rshift(op, 10), 0x0fff) + local rn, rd = band(rshift(op, 5), 31), band(op, 31) + if altname == "mov" and shf == 0 and imm12 == 0 and (rn == 31 or rd == 31) then + name = altname + x = nil + elseif shf == 0 then + x = imm12 + elseif shf == 1 then + x = imm12..", lsl #12" + end + elseif p == "i" then + x = "#0x"..decode_imm13(op) + elseif p == "1" then + immr = band(rshift(op, 16), 63) + x = immr + elseif p == "2" then + x = band(rshift(op, 10), 63) + if altname then + local a1, a2, a3, a4, a5, a6 = + match(altname, "([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)|(.*)") + local sf = band(rshift(op, 26), 32) + local uns = band(rshift(op, 30), 1) + if prefer_bfx(sf, uns, x, immr) then + name = a2 + x = x - immr + 1 + elseif immr == 0 and x == 7 then + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + name = a6 + x = nil + elseif immr == 0 and x == 15 then + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + name = a5 + x = nil + elseif x == 31 or x == 63 then + if x == 31 and immr == 0 and name == "sbfm" then + name = a4 + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + else + name = a3 + end + x = nil + elseif band(x, 31) ~= 31 and immr == x+1 and name == "ubfm" then + name = a4 + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = nil + elseif x < immr then + name = a1 + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = x + 1 + end + end + elseif p == "3" then + x = band(rshift(op, 10), 63) + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if x < immr then + name = a1 + local sf = band(rshift(op, 26), 32) + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = x + 1 + else + name = a2 + x = x - immr + 1 + end + end + elseif p == "4" then + x = band(rshift(op, 10), 63) + local rn = band(rshift(op, 5), 31) + local rm = band(rshift(op, 16), 31) + if altname and rn == rm then + local n = #operands + operands[n] = nil + last = operands[n-1] + name = altname + end + elseif p == "5" then + x = band(rshift(op, 16), 31) + elseif p == "S" then + x = band(rshift(op, 10), 63) + if x == 0 then x = nil + else x = map_shift[band(rshift(op, 22), 3)].." #"..x end + elseif p == "X" then + local opt = band(rshift(op, 13), 7) + -- Width specifier . + if opt ~= 3 and opt ~= 7 then + last = map_regs.w[band(rshift(op, 16), 31)] + operands[#operands] = last + end + x = band(rshift(op, 10), 7) + -- Extension. + if opt == 2 + band(rshift(op, 31), 1) and + band(rshift(op, second0 and 5 or 0), 31) == 31 then + if x == 0 then x = nil + else x = "lsl #"..x end + else + if x == 0 then x = map_extend[band(rshift(op, 13), 7)] + else x = map_extend[band(rshift(op, 13), 7)].." #"..x end + end + elseif p == "R" then + x = band(rshift(op,21), 3) + if x == 0 then x = nil + else x = "lsl #"..x*16 end + elseif p == "z" then + local n = #operands + if operands[n] == "sp" then operands[n] = "xzr" + elseif operands[n] == "wsp" then operands[n] = "wzr" + end + elseif p == "Z" then + x = 0 + elseif p == "F" then + x = parse_fpimm8(op) + elseif p == "g" or p == "f" or p == "x" or p == "w" or + p == "d" or p == "s" then + -- These are handled in D/N/M/A. + elseif p == "0" then + if last == "sp" or last == "wsp" then + local n = #operands + operands[n] = nil + last = operands[n-1] + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if not a1 then + name = altname + elseif second0 then + name, altname = a2, a1 + else + name, altname = a1, a2 + end + end + end + second0 = true + else + assert(false) + end + if x then + last = x + if type(x) == "number" then x = "#"..x end + operands[#operands+1] = x + end + end + + return putop(ctx, name..suffix, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ctx.pos = ofs + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_regs.x[r] end + return map_regs.d[r-32] +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm64be.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm64be.lua new file mode 100644 index 00000000..edcbffa8 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_arm64be.lua @@ -0,0 +1,12 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM64BE disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- ARM64 instructions are always little-endian. So just forward to the +-- common ARM64 disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +return require((string.match(..., ".*%.") or "").."dis_arm64") + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips.lua new file mode 100644 index 00000000..6ad17f54 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips.lua @@ -0,0 +1,694 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT/X license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles all standard MIPS32R1/R2 instructions. +-- Default mode is big-endian, but see: dis_mipsel.lua +------------------------------------------------------------------------------ + +local type = type +local byte, format = string.byte, string.format +local match, gmatch = string.match, string.gmatch +local concat = table.concat +local bit = require("bit") +local band, bor, tohex = bit.band, bit.bor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Extended opcode maps common to all MIPS releases +------------------------------------------------------------------------------ + +local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", } +local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", } + +local map_cop0 = { + shift = 25, mask = 1, + [0] = { + shift = 21, mask = 15, + [0] = "mfc0TDW", [4] = "mtc0TDW", + [10] = "rdpgprDT", + [11] = { shift = 5, mask = 1, [0] = "diT0", "eiT0", }, + [14] = "wrpgprDT", + }, { + shift = 0, mask = 63, + [1] = "tlbr", [2] = "tlbwi", [6] = "tlbwr", [8] = "tlbp", + [24] = "eret", [31] = "deret", + [32] = "wait", + }, +} + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps for MIPS R1-R5 +------------------------------------------------------------------------------ + +local map_movci = { shift = 16, mask = 1, [0] = "movfDSC", "movtDSC", } + +local map_special = { + shift = 0, mask = 63, + [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, + map_movci, map_srl, "sraDTA", + "sllvDTS", false, map_srlv, "sravDTS", + "jrS", "jalrD1S", "movzDST", "movnDST", + "syscallY", "breakY", false, "sync", + "mfhiD", "mthiS", "mfloD", "mtloS", + "dsllvDST", false, "dsrlvDST", "dsravDST", + "multST", "multuST", "divST", "divuST", + "dmultST", "dmultuST", "ddivST", "ddivuST", + "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", + "andDST", "or|moveDST0", "xorDST", "nor|notDST0", + false, false, "sltDST", "sltuDST", + "daddDST", "dadduDST", "dsubDST", "dsubuDST", + "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", + "teqSTZ", false, "tneSTZ", false, + "dsllDTA", false, "dsrlDTA", "dsraDTA", + "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", +} + +local map_special2 = { + shift = 0, mask = 63, + [0] = "maddST", "madduST", "mulDST", false, + "msubST", "msubuST", + [32] = "clzDS", [33] = "cloDS", + [63] = "sdbbpY", +} + +local map_bshfl = { + shift = 6, mask = 31, + [2] = "wsbhDT", + [16] = "sebDT", + [24] = "sehDT", +} + +local map_dbshfl = { + shift = 6, mask = 31, + [2] = "dsbhDT", + [5] = "dshdDT", +} + +local map_special3 = { + shift = 0, mask = 63, + [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", + [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", + [32] = map_bshfl, [36] = map_dbshfl, [59] = "rdhwrTD", +} + +local map_regimm = { + shift = 16, mask = 31, + [0] = "bltzSB", "bgezSB", "bltzlSB", "bgezlSB", + false, false, false, false, + "tgeiSI", "tgeiuSI", "tltiSI", "tltiuSI", + "teqiSI", false, "tneiSI", false, + "bltzalSB", "bgezalSB", "bltzallSB", "bgezallSB", + false, false, false, false, + false, false, false, false, + false, false, false, "synciSO", +} + +local map_cop1s = { + shift = 0, mask = 63, + [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", + "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG", + "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG", + "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG", + false, + { shift = 16, mask = 1, [0] = "movf.sFGC", "movt.sFGC" }, + "movz.sFGT", "movn.sFGT", + false, "recip.sFG", "rsqrt.sFG", false, + false, false, false, false, + false, false, false, false, + false, "cvt.d.sFG", false, false, + "cvt.w.sFG", "cvt.l.sFG", "cvt.ps.sFGH", false, + false, false, false, false, + false, false, false, false, + "c.f.sVGH", "c.un.sVGH", "c.eq.sVGH", "c.ueq.sVGH", + "c.olt.sVGH", "c.ult.sVGH", "c.ole.sVGH", "c.ule.sVGH", + "c.sf.sVGH", "c.ngle.sVGH", "c.seq.sVGH", "c.ngl.sVGH", + "c.lt.sVGH", "c.nge.sVGH", "c.le.sVGH", "c.ngt.sVGH", +} + +local map_cop1d = { + shift = 0, mask = 63, + [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH", + "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG", + "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG", + "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG", + false, + { shift = 16, mask = 1, [0] = "movf.dFGC", "movt.dFGC" }, + "movz.dFGT", "movn.dFGT", + false, "recip.dFG", "rsqrt.dFG", false, + false, false, false, false, + false, false, false, false, + "cvt.s.dFG", false, false, false, + "cvt.w.dFG", "cvt.l.dFG", false, false, + false, false, false, false, + false, false, false, false, + "c.f.dVGH", "c.un.dVGH", "c.eq.dVGH", "c.ueq.dVGH", + "c.olt.dVGH", "c.ult.dVGH", "c.ole.dVGH", "c.ule.dVGH", + "c.df.dVGH", "c.ngle.dVGH", "c.deq.dVGH", "c.ngl.dVGH", + "c.lt.dVGH", "c.nge.dVGH", "c.le.dVGH", "c.ngt.dVGH", +} + +local map_cop1ps = { + shift = 0, mask = 63, + [0] = "add.psFGH", "sub.psFGH", "mul.psFGH", false, + false, "abs.psFG", "mov.psFG", "neg.psFG", + false, false, false, false, + false, false, false, false, + false, + { shift = 16, mask = 1, [0] = "movf.psFGC", "movt.psFGC" }, + "movz.psFGT", "movn.psFGT", + false, false, false, false, + false, false, false, false, + false, false, false, false, + "cvt.s.puFG", false, false, false, + false, false, false, false, + "cvt.s.plFG", false, false, false, + "pll.psFGH", "plu.psFGH", "pul.psFGH", "puu.psFGH", + "c.f.psVGH", "c.un.psVGH", "c.eq.psVGH", "c.ueq.psVGH", + "c.olt.psVGH", "c.ult.psVGH", "c.ole.psVGH", "c.ule.psVGH", + "c.psf.psVGH", "c.ngle.psVGH", "c.pseq.psVGH", "c.ngl.psVGH", + "c.lt.psVGH", "c.nge.psVGH", "c.le.psVGH", "c.ngt.psVGH", +} + +local map_cop1w = { + shift = 0, mask = 63, + [32] = "cvt.s.wFG", [33] = "cvt.d.wFG", +} + +local map_cop1l = { + shift = 0, mask = 63, + [32] = "cvt.s.lFG", [33] = "cvt.d.lFG", +} + +local map_cop1bc = { + shift = 16, mask = 3, + [0] = "bc1fCB", "bc1tCB", "bc1flCB", "bc1tlCB", +} + +local map_cop1 = { + shift = 21, mask = 31, + [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", + "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", + map_cop1bc, false, false, false, + false, false, false, false, + map_cop1s, map_cop1d, false, false, + map_cop1w, map_cop1l, map_cop1ps, +} + +local map_cop1x = { + shift = 0, mask = 63, + [0] = "lwxc1FSX", "ldxc1FSX", false, false, + false, "luxc1FSX", false, false, + "swxc1FSX", "sdxc1FSX", false, false, + false, "suxc1FSX", false, "prefxMSX", + false, false, false, false, + false, false, false, false, + false, false, false, false, + false, false, "alnv.psFGHS", false, + "madd.sFRGH", "madd.dFRGH", false, false, + false, false, "madd.psFRGH", false, + "msub.sFRGH", "msub.dFRGH", false, false, + false, false, "msub.psFRGH", false, + "nmadd.sFRGH", "nmadd.dFRGH", false, false, + false, false, "nmadd.psFRGH", false, + "nmsub.sFRGH", "nmsub.dFRGH", false, false, + false, false, "nmsub.psFRGH", false, +} + +local map_pri = { + [0] = map_special, map_regimm, "jJ", "jalJ", + "beq|beqz|bST00B", "bne|bnezST0B", "blezSB", "bgtzSB", + "addiTSI", "addiu|liTS0I", "sltiTSI", "sltiuTSI", + "andiTSU", "ori|liTS0U", "xoriTSU", "luiTU", + map_cop0, map_cop1, false, map_cop1x, + "beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB", + "daddiTSI", "daddiuTSI", false, false, + map_special2, "jalxJ", false, map_special3, + "lbTSO", "lhTSO", "lwlTSO", "lwTSO", + "lbuTSO", "lhuTSO", "lwrTSO", false, + "sbTSO", "shTSO", "swlTSO", "swTSO", + false, false, "swrTSO", "cacheNSO", + "llTSO", "lwc1HSO", "lwc2TSO", "prefNSO", + false, "ldc1HSO", "ldc2TSO", "ldTSO", + "scTSO", "swc1HSO", "swc2TSO", false, + false, "sdc1HSO", "sdc2TSO", "sdTSO", +} + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps for MIPS R6 +------------------------------------------------------------------------------ + +local map_mul_r6 = { shift = 6, mask = 3, [2] = "mulDST", [3] = "muhDST" } +local map_mulu_r6 = { shift = 6, mask = 3, [2] = "muluDST", [3] = "muhuDST" } +local map_div_r6 = { shift = 6, mask = 3, [2] = "divDST", [3] = "modDST" } +local map_divu_r6 = { shift = 6, mask = 3, [2] = "divuDST", [3] = "moduDST" } +local map_dmul_r6 = { shift = 6, mask = 3, [2] = "dmulDST", [3] = "dmuhDST" } +local map_dmulu_r6 = { shift = 6, mask = 3, [2] = "dmuluDST", [3] = "dmuhuDST" } +local map_ddiv_r6 = { shift = 6, mask = 3, [2] = "ddivDST", [3] = "dmodDST" } +local map_ddivu_r6 = { shift = 6, mask = 3, [2] = "ddivuDST", [3] = "dmoduDST" } + +local map_special_r6 = { + shift = 0, mask = 63, + [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, + false, map_srl, "sraDTA", + "sllvDTS", false, map_srlv, "sravDTS", + "jrS", "jalrD1S", false, false, + "syscallY", "breakY", false, "sync", + "clzDS", "cloDS", "dclzDS", "dcloDS", + "dsllvDST", "dlsaDSTA", "dsrlvDST", "dsravDST", + map_mul_r6, map_mulu_r6, map_div_r6, map_divu_r6, + map_dmul_r6, map_dmulu_r6, map_ddiv_r6, map_ddivu_r6, + "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", + "andDST", "or|moveDST0", "xorDST", "nor|notDST0", + false, false, "sltDST", "sltuDST", + "daddDST", "dadduDST", "dsubDST", "dsubuDST", + "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", + "teqSTZ", "seleqzDST", "tneSTZ", "selnezDST", + "dsllDTA", false, "dsrlDTA", "dsraDTA", + "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", +} + +local map_bshfl_r6 = { + shift = 9, mask = 3, + [1] = "alignDSTa", + _ = { + shift = 6, mask = 31, + [0] = "bitswapDT", + [2] = "wsbhDT", + [16] = "sebDT", + [24] = "sehDT", + } +} + +local map_dbshfl_r6 = { + shift = 9, mask = 3, + [1] = "dalignDSTa", + _ = { + shift = 6, mask = 31, + [0] = "dbitswapDT", + [2] = "dsbhDT", + [5] = "dshdDT", + } +} + +local map_special3_r6 = { + shift = 0, mask = 63, + [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", + [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", + [32] = map_bshfl_r6, [36] = map_dbshfl_r6, [59] = "rdhwrTD", +} + +local map_regimm_r6 = { + shift = 16, mask = 31, + [0] = "bltzSB", [1] = "bgezSB", + [6] = "dahiSI", [30] = "datiSI", + [23] = "sigrieI", [31] = "synciSO", +} + +local map_pcrel_r6 = { + shift = 19, mask = 3, + [0] = "addiupcS2", "lwpcS2", "lwupcS2", { + shift = 18, mask = 1, + [0] = "ldpcS3", { shift = 16, mask = 3, [2] = "auipcSI", [3] = "aluipcSI" } + } +} + +local map_cop1s_r6 = { + shift = 0, mask = 63, + [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", + "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG", + "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG", + "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG", + "sel.sFGH", false, false, false, + "seleqz.sFGH", "recip.sFG", "rsqrt.sFG", "selnez.sFGH", + "maddf.sFGH", "msubf.sFGH", "rint.sFG", "class.sFG", + "min.sFGH", "mina.sFGH", "max.sFGH", "maxa.sFGH", + false, "cvt.d.sFG", false, false, + "cvt.w.sFG", "cvt.l.sFG", +} + +local map_cop1d_r6 = { + shift = 0, mask = 63, + [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH", + "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG", + "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG", + "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG", + "sel.dFGH", false, false, false, + "seleqz.dFGH", "recip.dFG", "rsqrt.dFG", "selnez.dFGH", + "maddf.dFGH", "msubf.dFGH", "rint.dFG", "class.dFG", + "min.dFGH", "mina.dFGH", "max.dFGH", "maxa.dFGH", + "cvt.s.dFG", false, false, false, + "cvt.w.dFG", "cvt.l.dFG", +} + +local map_cop1w_r6 = { + shift = 0, mask = 63, + [0] = "cmp.af.sFGH", "cmp.un.sFGH", "cmp.eq.sFGH", "cmp.ueq.sFGH", + "cmp.lt.sFGH", "cmp.ult.sFGH", "cmp.le.sFGH", "cmp.ule.sFGH", + "cmp.saf.sFGH", "cmp.sun.sFGH", "cmp.seq.sFGH", "cmp.sueq.sFGH", + "cmp.slt.sFGH", "cmp.sult.sFGH", "cmp.sle.sFGH", "cmp.sule.sFGH", + false, "cmp.or.sFGH", "cmp.une.sFGH", "cmp.ne.sFGH", + false, false, false, false, + false, "cmp.sor.sFGH", "cmp.sune.sFGH", "cmp.sne.sFGH", + false, false, false, false, + "cvt.s.wFG", "cvt.d.wFG", +} + +local map_cop1l_r6 = { + shift = 0, mask = 63, + [0] = "cmp.af.dFGH", "cmp.un.dFGH", "cmp.eq.dFGH", "cmp.ueq.dFGH", + "cmp.lt.dFGH", "cmp.ult.dFGH", "cmp.le.dFGH", "cmp.ule.dFGH", + "cmp.saf.dFGH", "cmp.sun.dFGH", "cmp.seq.dFGH", "cmp.sueq.dFGH", + "cmp.slt.dFGH", "cmp.sult.dFGH", "cmp.sle.dFGH", "cmp.sule.dFGH", + false, "cmp.or.dFGH", "cmp.une.dFGH", "cmp.ne.dFGH", + false, false, false, false, + false, "cmp.sor.dFGH", "cmp.sune.dFGH", "cmp.sne.dFGH", + false, false, false, false, + "cvt.s.lFG", "cvt.d.lFG", +} + +local map_cop1_r6 = { + shift = 21, mask = 31, + [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", + "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", + false, "bc1eqzHB", false, false, + false, "bc1nezHB", false, false, + map_cop1s_r6, map_cop1d_r6, false, false, + map_cop1w_r6, map_cop1l_r6, +} + +local function maprs_popTS(rs, rt) + if rt == 0 then return 0 elseif rs == 0 then return 1 + elseif rs == rt then return 2 else return 3 end +end + +local map_pop06_r6 = { + maprs = maprs_popTS, [0] = "blezSB", "blezalcTB", "bgezalcTB", "bgeucSTB" +} +local map_pop07_r6 = { + maprs = maprs_popTS, [0] = "bgtzSB", "bgtzalcTB", "bltzalcTB", "bltucSTB" +} +local map_pop26_r6 = { + maprs = maprs_popTS, "blezcTB", "bgezcTB", "bgecSTB" +} +local map_pop27_r6 = { + maprs = maprs_popTS, "bgtzcTB", "bltzcTB", "bltcSTB" +} + +local function maprs_popS(rs, rt) + if rs == 0 then return 0 else return 1 end +end + +local map_pop66_r6 = { + maprs = maprs_popS, [0] = "jicTI", "beqzcSb" +} +local map_pop76_r6 = { + maprs = maprs_popS, [0] = "jialcTI", "bnezcSb" +} + +local function maprs_popST(rs, rt) + if rs >= rt then return 0 elseif rs == 0 then return 1 else return 2 end +end + +local map_pop10_r6 = { + maprs = maprs_popST, [0] = "bovcSTB", "beqzalcTB", "beqcSTB" +} +local map_pop30_r6 = { + maprs = maprs_popST, [0] = "bnvcSTB", "bnezalcTB", "bnecSTB" +} + +local map_pri_r6 = { + [0] = map_special_r6, map_regimm_r6, "jJ", "jalJ", + "beq|beqz|bST00B", "bne|bnezST0B", map_pop06_r6, map_pop07_r6, + map_pop10_r6, "addiu|liTS0I", "sltiTSI", "sltiuTSI", + "andiTSU", "ori|liTS0U", "xoriTSU", "aui|luiTS0U", + map_cop0, map_cop1_r6, false, false, + false, false, map_pop26_r6, map_pop27_r6, + map_pop30_r6, "daddiuTSI", false, false, + false, "dauiTSI", false, map_special3_r6, + "lbTSO", "lhTSO", false, "lwTSO", + "lbuTSO", "lhuTSO", false, false, + "sbTSO", "shTSO", false, "swTSO", + false, false, false, false, + false, "lwc1HSO", "bc#", false, + false, "ldc1HSO", map_pop66_r6, "ldTSO", + false, "swc1HSO", "balc#", map_pcrel_r6, + false, "sdc1HSO", map_pop76_r6, "sdTSO", +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "sp", "r30", "ra", +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then extra = "\t->"..sym end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-7s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-7s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +local function get_be(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + return bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3) +end + +local function get_le(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + return bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local op = ctx:get() + local operands = {} + local last = nil + ctx.op = op + ctx.rel = nil + + local opat = ctx.map_pri[rshift(op, 26)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + if opat.maprs then + opat = opat[opat.maprs(band(rshift(op,21),31), band(rshift(op,16),31))] + else + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + end + local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") + if altname then pat = pat2 end + + for p in gmatch(pat, ".") do + local x = nil + if p == "S" then + x = map_gpr[band(rshift(op, 21), 31)] + elseif p == "T" then + x = map_gpr[band(rshift(op, 16), 31)] + elseif p == "D" then + x = map_gpr[band(rshift(op, 11), 31)] + elseif p == "F" then + x = "f"..band(rshift(op, 6), 31) + elseif p == "G" then + x = "f"..band(rshift(op, 11), 31) + elseif p == "H" then + x = "f"..band(rshift(op, 16), 31) + elseif p == "R" then + x = "f"..band(rshift(op, 21), 31) + elseif p == "A" then + x = band(rshift(op, 6), 31) + elseif p == "a" then + x = band(rshift(op, 6), 7) + elseif p == "E" then + x = band(rshift(op, 6), 31) + 32 + elseif p == "M" then + x = band(rshift(op, 11), 31) + elseif p == "N" then + x = band(rshift(op, 16), 31) + elseif p == "C" then + x = band(rshift(op, 18), 7) + if x == 0 then x = nil end + elseif p == "K" then + x = band(rshift(op, 11), 31) + 1 + elseif p == "P" then + x = band(rshift(op, 11), 31) + 33 + elseif p == "L" then + x = band(rshift(op, 11), 31) - last + 1 + elseif p == "Q" then + x = band(rshift(op, 11), 31) - last + 33 + elseif p == "I" then + x = arshift(lshift(op, 16), 16) + elseif p == "2" then + x = arshift(lshift(op, 13), 11) + elseif p == "3" then + x = arshift(lshift(op, 14), 11) + elseif p == "U" then + x = band(op, 0xffff) + elseif p == "O" then + local disp = arshift(lshift(op, 16), 16) + operands[#operands] = format("%d(%s)", disp, last) + elseif p == "X" then + local index = map_gpr[band(rshift(op, 16), 31)] + operands[#operands] = format("%s(%s)", index, last) + elseif p == "B" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 14) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "b" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 11), 9) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "#" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 6), 4) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "J" then + local a = ctx.addr + ctx.pos + x = a - band(a, 0x0fffffff) + band(op, 0x03ffffff)*4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "V" then + x = band(rshift(op, 8), 7) + if x == 0 then x = nil end + elseif p == "W" then + x = band(op, 7) + if x == 0 then x = nil end + elseif p == "Y" then + x = band(rshift(op, 6), 0x000fffff) + if x == 0 then x = nil end + elseif p == "Z" then + x = band(rshift(op, 6), 1023) + if x == 0 then x = nil end + elseif p == "0" then + if last == "r0" or last == 0 then + local n = #operands + operands[n] = nil + last = operands[n-1] + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if a1 then name, altname = a1, a2 + else name = altname end + end + end + elseif p == "1" then + if last == "ra" then + operands[#operands] = nil + end + else + assert(false) + end + if x then operands[#operands+1] = x; last = x end + end + + return putop(ctx, name, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + stop = stop - stop % 4 + ctx.pos = ofs - ofs % 4 + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + ctx.get = get_be + ctx.map_pri = map_pri + return ctx +end + +local function create_el(code, addr, out) + local ctx = create(code, addr, out) + ctx.get = get_le + return ctx +end + +local function create_r6(code, addr, out) + local ctx = create(code, addr, out) + ctx.map_pri = map_pri_r6 + return ctx +end + +local function create_r6_el(code, addr, out) + local ctx = create(code, addr, out) + ctx.get = get_le + ctx.map_pri = map_pri_r6 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +local function disass_el(code, addr, out) + create_el(code, addr, out):disass() +end + +local function disass_r6(code, addr, out) + create_r6(code, addr, out):disass() +end + +local function disass_r6_el(code, addr, out) + create_r6_el(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_gpr[r] end + return "f"..(r-32) +end + +-- Public module functions. +return { + create = create, + create_el = create_el, + create_r6 = create_r6, + create_r6_el = create_r6_el, + disass = disass, + disass_el = disass_el, + disass_r6 = disass_r6, + disass_r6_el = disass_r6_el, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64.lua new file mode 100644 index 00000000..5ad48f8f --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the big-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create, + disass = dis_mips.disass, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64el.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64el.lua new file mode 100644 index 00000000..d50e3a18 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64el.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64EL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_el, + disass = dis_mips.disass_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64r6.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64r6.lua new file mode 100644 index 00000000..921b3cbe --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64r6.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64R6 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the r6 big-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_r6, + disass = dis_mips.disass_r6, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64r6el.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64r6el.lua new file mode 100644 index 00000000..aadef9f3 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mips64r6el.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64R6EL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the r6 little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_r6_el, + disass = dis_mips.disass_r6_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mipsel.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mipsel.lua new file mode 100644 index 00000000..52cebefb --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_mipsel.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPSEL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_el, + disass = dis_mips.disass_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_ppc.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_ppc.lua new file mode 100644 index 00000000..08d742f1 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_ppc.lua @@ -0,0 +1,591 @@ +---------------------------------------------------------------------------- +-- LuaJIT PPC disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT/X license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles all common, non-privileged 32/64 bit PowerPC instructions +-- plus the e500 SPE instructions and some Cell/Xenon extensions. +-- +-- NYI: VMX, VMX128 +------------------------------------------------------------------------------ + +local type = type +local byte, format = string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local concat = table.concat +local bit = require("bit") +local band, bor, tohex = bit.band, bit.bor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps +------------------------------------------------------------------------------ + +local map_crops = { + shift = 1, mask = 1023, + [0] = "mcrfXX", + [33] = "crnor|crnotCCC=", [129] = "crandcCCC", + [193] = "crxor|crclrCCC%", [225] = "crnandCCC", + [257] = "crandCCC", [289] = "creqv|crsetCCC%", + [417] = "crorcCCC", [449] = "cror|crmoveCCC=", + [16] = "b_lrKB", [528] = "b_ctrKB", + [150] = "isync", +} + +local map_rlwinm = setmetatable({ + shift = 0, mask = -1, +}, +{ __index = function(t, x) + local rot = band(rshift(x, 11), 31) + local mb = band(rshift(x, 6), 31) + local me = band(rshift(x, 1), 31) + if mb == 0 and me == 31-rot then + return "slwiRR~A." + elseif me == 31 and mb == 32-rot then + return "srwiRR~-A." + else + return "rlwinmRR~AAA." + end + end +}) + +local map_rld = { + shift = 2, mask = 7, + [0] = "rldiclRR~HM.", "rldicrRR~HM.", "rldicRR~HM.", "rldimiRR~HM.", + { + shift = 1, mask = 1, + [0] = "rldclRR~RM.", "rldcrRR~RM.", + }, +} + +local map_ext = setmetatable({ + shift = 1, mask = 1023, + + [0] = "cmp_YLRR", [32] = "cmpl_YLRR", + [4] = "twARR", [68] = "tdARR", + + [8] = "subfcRRR.", [40] = "subfRRR.", + [104] = "negRR.", [136] = "subfeRRR.", + [200] = "subfzeRR.", [232] = "subfmeRR.", + [520] = "subfcoRRR.", [552] = "subfoRRR.", + [616] = "negoRR.", [648] = "subfeoRRR.", + [712] = "subfzeoRR.", [744] = "subfmeoRR.", + + [9] = "mulhduRRR.", [73] = "mulhdRRR.", [233] = "mulldRRR.", + [457] = "divduRRR.", [489] = "divdRRR.", + [745] = "mulldoRRR.", + [969] = "divduoRRR.", [1001] = "divdoRRR.", + + [10] = "addcRRR.", [138] = "addeRRR.", + [202] = "addzeRR.", [234] = "addmeRR.", [266] = "addRRR.", + [522] = "addcoRRR.", [650] = "addeoRRR.", + [714] = "addzeoRR.", [746] = "addmeoRR.", [778] = "addoRRR.", + + [11] = "mulhwuRRR.", [75] = "mulhwRRR.", [235] = "mullwRRR.", + [459] = "divwuRRR.", [491] = "divwRRR.", + [747] = "mullwoRRR.", + [971] = "divwouRRR.", [1003] = "divwoRRR.", + + [15] = "iselltRRR", [47] = "iselgtRRR", [79] = "iseleqRRR", + + [144] = { shift = 20, mask = 1, [0] = "mtcrfRZ~", "mtocrfRZ~", }, + [19] = { shift = 20, mask = 1, [0] = "mfcrR", "mfocrfRZ", }, + [371] = { shift = 11, mask = 1023, [392] = "mftbR", [424] = "mftbuR", }, + [339] = { + shift = 11, mask = 1023, + [32] = "mferR", [256] = "mflrR", [288] = "mfctrR", [16] = "mfspefscrR", + }, + [467] = { + shift = 11, mask = 1023, + [32] = "mtxerR", [256] = "mtlrR", [288] = "mtctrR", [16] = "mtspefscrR", + }, + + [20] = "lwarxRR0R", [84] = "ldarxRR0R", + + [21] = "ldxRR0R", [53] = "lduxRRR", + [149] = "stdxRR0R", [181] = "stduxRRR", + [341] = "lwaxRR0R", [373] = "lwauxRRR", + + [23] = "lwzxRR0R", [55] = "lwzuxRRR", + [87] = "lbzxRR0R", [119] = "lbzuxRRR", + [151] = "stwxRR0R", [183] = "stwuxRRR", + [215] = "stbxRR0R", [247] = "stbuxRRR", + [279] = "lhzxRR0R", [311] = "lhzuxRRR", + [343] = "lhaxRR0R", [375] = "lhauxRRR", + [407] = "sthxRR0R", [439] = "sthuxRRR", + + [54] = "dcbst-R0R", [86] = "dcbf-R0R", + [150] = "stwcxRR0R.", [214] = "stdcxRR0R.", + [246] = "dcbtst-R0R", [278] = "dcbt-R0R", + [310] = "eciwxRR0R", [438] = "ecowxRR0R", + [470] = "dcbi-RR", + + [598] = { + shift = 21, mask = 3, + [0] = "sync", "lwsync", "ptesync", + }, + [758] = "dcba-RR", + [854] = "eieio", [982] = "icbi-R0R", [1014] = "dcbz-R0R", + + [26] = "cntlzwRR~", [58] = "cntlzdRR~", + [122] = "popcntbRR~", + [154] = "prtywRR~", [186] = "prtydRR~", + + [28] = "andRR~R.", [60] = "andcRR~R.", [124] = "nor|notRR~R=.", + [284] = "eqvRR~R.", [316] = "xorRR~R.", + [412] = "orcRR~R.", [444] = "or|mrRR~R=.", [476] = "nandRR~R.", + [508] = "cmpbRR~R", + + [512] = "mcrxrX", + + [532] = "ldbrxRR0R", [660] = "stdbrxRR0R", + + [533] = "lswxRR0R", [597] = "lswiRR0A", + [661] = "stswxRR0R", [725] = "stswiRR0A", + + [534] = "lwbrxRR0R", [662] = "stwbrxRR0R", + [790] = "lhbrxRR0R", [918] = "sthbrxRR0R", + + [535] = "lfsxFR0R", [567] = "lfsuxFRR", + [599] = "lfdxFR0R", [631] = "lfduxFRR", + [663] = "stfsxFR0R", [695] = "stfsuxFRR", + [727] = "stfdxFR0R", [759] = "stfduxFR0R", + [855] = "lfiwaxFR0R", + [983] = "stfiwxFR0R", + + [24] = "slwRR~R.", + + [27] = "sldRR~R.", [536] = "srwRR~R.", + [792] = "srawRR~R.", [824] = "srawiRR~A.", + + [794] = "sradRR~R.", [826] = "sradiRR~H.", [827] = "sradiRR~H.", + [922] = "extshRR~.", [954] = "extsbRR~.", [986] = "extswRR~.", + + [539] = "srdRR~R.", +}, +{ __index = function(t, x) + if band(x, 31) == 15 then return "iselRRRC" end + end +}) + +local map_ld = { + shift = 0, mask = 3, + [0] = "ldRRE", "lduRRE", "lwaRRE", +} + +local map_std = { + shift = 0, mask = 3, + [0] = "stdRRE", "stduRRE", +} + +local map_fps = { + shift = 5, mask = 1, + { + shift = 1, mask = 15, + [0] = false, false, "fdivsFFF.", false, + "fsubsFFF.", "faddsFFF.", "fsqrtsF-F.", false, + "fresF-F.", "fmulsFF-F.", "frsqrtesF-F.", false, + "fmsubsFFFF~.", "fmaddsFFFF~.", "fnmsubsFFFF~.", "fnmaddsFFFF~.", + } +} + +local map_fpd = { + shift = 5, mask = 1, + [0] = { + shift = 1, mask = 1023, + [0] = "fcmpuXFF", [32] = "fcmpoXFF", [64] = "mcrfsXX", + [38] = "mtfsb1A.", [70] = "mtfsb0A.", [134] = "mtfsfiA>>-A>", + [8] = "fcpsgnFFF.", [40] = "fnegF-F.", [72] = "fmrF-F.", + [136] = "fnabsF-F.", [264] = "fabsF-F.", + [12] = "frspF-F.", + [14] = "fctiwF-F.", [15] = "fctiwzF-F.", + [583] = "mffsF.", [711] = "mtfsfZF.", + [392] = "frinF-F.", [424] = "frizF-F.", + [456] = "fripF-F.", [488] = "frimF-F.", + [814] = "fctidF-F.", [815] = "fctidzF-F.", [846] = "fcfidF-F.", + }, + { + shift = 1, mask = 15, + [0] = false, false, "fdivFFF.", false, + "fsubFFF.", "faddFFF.", "fsqrtF-F.", "fselFFFF~.", + "freF-F.", "fmulFF-F.", "frsqrteF-F.", false, + "fmsubFFFF~.", "fmaddFFFF~.", "fnmsubFFFF~.", "fnmaddFFFF~.", + } +} + +local map_spe = { + shift = 0, mask = 2047, + + [512] = "evaddwRRR", [514] = "evaddiwRAR~", + [516] = "evsubwRRR~", [518] = "evsubiwRAR~", + [520] = "evabsRR", [521] = "evnegRR", + [522] = "evextsbRR", [523] = "evextshRR", [524] = "evrndwRR", + [525] = "evcntlzwRR", [526] = "evcntlswRR", + + [527] = "brincRRR", + + [529] = "evandRRR", [530] = "evandcRRR", [534] = "evxorRRR", + [535] = "evor|evmrRRR=", [536] = "evnor|evnotRRR=", + [537] = "eveqvRRR", [539] = "evorcRRR", [542] = "evnandRRR", + + [544] = "evsrwuRRR", [545] = "evsrwsRRR", + [546] = "evsrwiuRRA", [547] = "evsrwisRRA", + [548] = "evslwRRR", [550] = "evslwiRRA", + [552] = "evrlwRRR", [553] = "evsplatiRS", + [554] = "evrlwiRRA", [555] = "evsplatfiRS", + [556] = "evmergehiRRR", [557] = "evmergeloRRR", + [558] = "evmergehiloRRR", [559] = "evmergelohiRRR", + + [560] = "evcmpgtuYRR", [561] = "evcmpgtsYRR", + [562] = "evcmpltuYRR", [563] = "evcmpltsYRR", + [564] = "evcmpeqYRR", + + [632] = "evselRRR", [633] = "evselRRRW", + [634] = "evselRRRW", [635] = "evselRRRW", + [636] = "evselRRRW", [637] = "evselRRRW", + [638] = "evselRRRW", [639] = "evselRRRW", + + [640] = "evfsaddRRR", [641] = "evfssubRRR", + [644] = "evfsabsRR", [645] = "evfsnabsRR", [646] = "evfsnegRR", + [648] = "evfsmulRRR", [649] = "evfsdivRRR", + [652] = "evfscmpgtYRR", [653] = "evfscmpltYRR", [654] = "evfscmpeqYRR", + [656] = "evfscfuiR-R", [657] = "evfscfsiR-R", + [658] = "evfscfufR-R", [659] = "evfscfsfR-R", + [660] = "evfsctuiR-R", [661] = "evfsctsiR-R", + [662] = "evfsctufR-R", [663] = "evfsctsfR-R", + [664] = "evfsctuizR-R", [666] = "evfsctsizR-R", + [668] = "evfststgtYRR", [669] = "evfststltYRR", [670] = "evfststeqYRR", + + [704] = "efsaddRRR", [705] = "efssubRRR", + [708] = "efsabsRR", [709] = "efsnabsRR", [710] = "efsnegRR", + [712] = "efsmulRRR", [713] = "efsdivRRR", + [716] = "efscmpgtYRR", [717] = "efscmpltYRR", [718] = "efscmpeqYRR", + [719] = "efscfdR-R", + [720] = "efscfuiR-R", [721] = "efscfsiR-R", + [722] = "efscfufR-R", [723] = "efscfsfR-R", + [724] = "efsctuiR-R", [725] = "efsctsiR-R", + [726] = "efsctufR-R", [727] = "efsctsfR-R", + [728] = "efsctuizR-R", [730] = "efsctsizR-R", + [732] = "efststgtYRR", [733] = "efststltYRR", [734] = "efststeqYRR", + + [736] = "efdaddRRR", [737] = "efdsubRRR", + [738] = "efdcfuidR-R", [739] = "efdcfsidR-R", + [740] = "efdabsRR", [741] = "efdnabsRR", [742] = "efdnegRR", + [744] = "efdmulRRR", [745] = "efddivRRR", + [746] = "efdctuidzR-R", [747] = "efdctsidzR-R", + [748] = "efdcmpgtYRR", [749] = "efdcmpltYRR", [750] = "efdcmpeqYRR", + [751] = "efdcfsR-R", + [752] = "efdcfuiR-R", [753] = "efdcfsiR-R", + [754] = "efdcfufR-R", [755] = "efdcfsfR-R", + [756] = "efdctuiR-R", [757] = "efdctsiR-R", + [758] = "efdctufR-R", [759] = "efdctsfR-R", + [760] = "efdctuizR-R", [762] = "efdctsizR-R", + [764] = "efdtstgtYRR", [765] = "efdtstltYRR", [766] = "efdtsteqYRR", + + [768] = "evlddxRR0R", [769] = "evlddRR8", + [770] = "evldwxRR0R", [771] = "evldwRR8", + [772] = "evldhxRR0R", [773] = "evldhRR8", + [776] = "evlhhesplatxRR0R", [777] = "evlhhesplatRR2", + [780] = "evlhhousplatxRR0R", [781] = "evlhhousplatRR2", + [782] = "evlhhossplatxRR0R", [783] = "evlhhossplatRR2", + [784] = "evlwhexRR0R", [785] = "evlwheRR4", + [788] = "evlwhouxRR0R", [789] = "evlwhouRR4", + [790] = "evlwhosxRR0R", [791] = "evlwhosRR4", + [792] = "evlwwsplatxRR0R", [793] = "evlwwsplatRR4", + [796] = "evlwhsplatxRR0R", [797] = "evlwhsplatRR4", + + [800] = "evstddxRR0R", [801] = "evstddRR8", + [802] = "evstdwxRR0R", [803] = "evstdwRR8", + [804] = "evstdhxRR0R", [805] = "evstdhRR8", + [816] = "evstwhexRR0R", [817] = "evstwheRR4", + [820] = "evstwhoxRR0R", [821] = "evstwhoRR4", + [824] = "evstwwexRR0R", [825] = "evstwweRR4", + [828] = "evstwwoxRR0R", [829] = "evstwwoRR4", + + [1027] = "evmhessfRRR", [1031] = "evmhossfRRR", [1032] = "evmheumiRRR", + [1033] = "evmhesmiRRR", [1035] = "evmhesmfRRR", [1036] = "evmhoumiRRR", + [1037] = "evmhosmiRRR", [1039] = "evmhosmfRRR", [1059] = "evmhessfaRRR", + [1063] = "evmhossfaRRR", [1064] = "evmheumiaRRR", [1065] = "evmhesmiaRRR", + [1067] = "evmhesmfaRRR", [1068] = "evmhoumiaRRR", [1069] = "evmhosmiaRRR", + [1071] = "evmhosmfaRRR", [1095] = "evmwhssfRRR", [1096] = "evmwlumiRRR", + [1100] = "evmwhumiRRR", [1101] = "evmwhsmiRRR", [1103] = "evmwhsmfRRR", + [1107] = "evmwssfRRR", [1112] = "evmwumiRRR", [1113] = "evmwsmiRRR", + [1115] = "evmwsmfRRR", [1127] = "evmwhssfaRRR", [1128] = "evmwlumiaRRR", + [1132] = "evmwhumiaRRR", [1133] = "evmwhsmiaRRR", [1135] = "evmwhsmfaRRR", + [1139] = "evmwssfaRRR", [1144] = "evmwumiaRRR", [1145] = "evmwsmiaRRR", + [1147] = "evmwsmfaRRR", + + [1216] = "evaddusiaawRR", [1217] = "evaddssiaawRR", + [1218] = "evsubfusiaawRR", [1219] = "evsubfssiaawRR", + [1220] = "evmraRR", + [1222] = "evdivwsRRR", [1223] = "evdivwuRRR", + [1224] = "evaddumiaawRR", [1225] = "evaddsmiaawRR", + [1226] = "evsubfumiaawRR", [1227] = "evsubfsmiaawRR", + + [1280] = "evmheusiaawRRR", [1281] = "evmhessiaawRRR", + [1283] = "evmhessfaawRRR", [1284] = "evmhousiaawRRR", + [1285] = "evmhossiaawRRR", [1287] = "evmhossfaawRRR", + [1288] = "evmheumiaawRRR", [1289] = "evmhesmiaawRRR", + [1291] = "evmhesmfaawRRR", [1292] = "evmhoumiaawRRR", + [1293] = "evmhosmiaawRRR", [1295] = "evmhosmfaawRRR", + [1320] = "evmhegumiaaRRR", [1321] = "evmhegsmiaaRRR", + [1323] = "evmhegsmfaaRRR", [1324] = "evmhogumiaaRRR", + [1325] = "evmhogsmiaaRRR", [1327] = "evmhogsmfaaRRR", + [1344] = "evmwlusiaawRRR", [1345] = "evmwlssiaawRRR", + [1352] = "evmwlumiaawRRR", [1353] = "evmwlsmiaawRRR", + [1363] = "evmwssfaaRRR", [1368] = "evmwumiaaRRR", + [1369] = "evmwsmiaaRRR", [1371] = "evmwsmfaaRRR", + [1408] = "evmheusianwRRR", [1409] = "evmhessianwRRR", + [1411] = "evmhessfanwRRR", [1412] = "evmhousianwRRR", + [1413] = "evmhossianwRRR", [1415] = "evmhossfanwRRR", + [1416] = "evmheumianwRRR", [1417] = "evmhesmianwRRR", + [1419] = "evmhesmfanwRRR", [1420] = "evmhoumianwRRR", + [1421] = "evmhosmianwRRR", [1423] = "evmhosmfanwRRR", + [1448] = "evmhegumianRRR", [1449] = "evmhegsmianRRR", + [1451] = "evmhegsmfanRRR", [1452] = "evmhogumianRRR", + [1453] = "evmhogsmianRRR", [1455] = "evmhogsmfanRRR", + [1472] = "evmwlusianwRRR", [1473] = "evmwlssianwRRR", + [1480] = "evmwlumianwRRR", [1481] = "evmwlsmianwRRR", + [1491] = "evmwssfanRRR", [1496] = "evmwumianRRR", + [1497] = "evmwsmianRRR", [1499] = "evmwsmfanRRR", +} + +local map_pri = { + [0] = false, false, "tdiARI", "twiARI", + map_spe, false, false, "mulliRRI", + "subficRRI", false, "cmpl_iYLRU", "cmp_iYLRI", + "addicRRI", "addic.RRI", "addi|liRR0I", "addis|lisRR0I", + "b_KBJ", "sc", "bKJ", map_crops, + "rlwimiRR~AAA.", map_rlwinm, false, "rlwnmRR~RAA.", + "oriNRR~U", "orisRR~U", "xoriRR~U", "xorisRR~U", + "andi.RR~U", "andis.RR~U", map_rld, map_ext, + "lwzRRD", "lwzuRRD", "lbzRRD", "lbzuRRD", + "stwRRD", "stwuRRD", "stbRRD", "stbuRRD", + "lhzRRD", "lhzuRRD", "lhaRRD", "lhauRRD", + "sthRRD", "sthuRRD", "lmwRRD", "stmwRRD", + "lfsFRD", "lfsuFRD", "lfdFRD", "lfduFRD", + "stfsFRD", "stfsuFRD", "stfdFRD", "stfduFRD", + false, false, map_ld, map_fps, + false, false, map_std, map_fpd, +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "sp", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", +} + +local map_cond = { [0] = "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", } + +-- Format a condition bit. +local function condfmt(cond) + if cond <= 3 then + return map_cond[band(cond, 3)] + else + return format("4*cr%d+%s", rshift(cond, 2), map_cond[band(cond, 3)]) + end +end + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then extra = "\t->"..sym end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-7s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-7s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3) + local operands = {} + local last = nil + local rs = 21 + ctx.op = op + ctx.rel = nil + + local opat = map_pri[rshift(b0, 2)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] + end + local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.]*)(.*)") + if altname then pat = pat2 end + + for p in gmatch(pat, ".") do + local x = nil + if p == "R" then + x = map_gpr[band(rshift(op, rs), 31)] + rs = rs - 5 + elseif p == "F" then + x = "f"..band(rshift(op, rs), 31) + rs = rs - 5 + elseif p == "A" then + x = band(rshift(op, rs), 31) + rs = rs - 5 + elseif p == "S" then + x = arshift(lshift(op, 27-rs), 27) + rs = rs - 5 + elseif p == "I" then + x = arshift(lshift(op, 16), 16) + elseif p == "U" then + x = band(op, 0xffff) + elseif p == "D" or p == "E" then + local disp = arshift(lshift(op, 16), 16) + if p == "E" then disp = band(disp, -4) end + if last == "r0" then last = "0" end + operands[#operands] = format("%d(%s)", disp, last) + elseif p >= "2" and p <= "8" then + local disp = band(rshift(op, rs), 31) * p + if last == "r0" then last = "0" end + operands[#operands] = format("%d(%s)", disp, last) + elseif p == "H" then + x = band(rshift(op, rs), 31) + lshift(band(op, 2), 4) + rs = rs - 5 + elseif p == "M" then + x = band(rshift(op, rs), 31) + band(op, 0x20) + elseif p == "C" then + x = condfmt(band(rshift(op, rs), 31)) + rs = rs - 5 + elseif p == "B" then + local bo = rshift(op, 21) + local cond = band(rshift(op, 16), 31) + local cn = "" + rs = rs - 10 + if band(bo, 4) == 0 then + cn = band(bo, 2) == 0 and "dnz" or "dz" + if band(bo, 0x10) == 0 then + cn = cn..(band(bo, 8) == 0 and "f" or "t") + end + if band(bo, 0x10) == 0 then x = condfmt(cond) end + name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+") + elseif band(bo, 0x10) == 0 then + cn = map_cond[band(cond, 3) + (band(bo, 8) == 0 and 4 or 0)] + if cond > 3 then x = "cr"..rshift(cond, 2) end + name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+") + end + name = gsub(name, "_", cn) + elseif p == "J" then + x = arshift(lshift(op, 27-rs), 29-rs)*4 + if band(op, 2) == 0 then x = ctx.addr + pos + x end + ctx.rel = x + x = "0x"..tohex(x) + elseif p == "K" then + if band(op, 1) ~= 0 then name = name.."l" end + if band(op, 2) ~= 0 then name = name.."a" end + elseif p == "X" or p == "Y" then + x = band(rshift(op, rs+2), 7) + if x == 0 and p == "Y" then x = nil else x = "cr"..x end + rs = rs - 5 + elseif p == "W" then + x = "cr"..band(op, 7) + elseif p == "Z" then + x = band(rshift(op, rs-4), 255) + rs = rs - 10 + elseif p == ">" then + operands[#operands] = rshift(operands[#operands], 1) + elseif p == "0" then + if last == "r0" then + operands[#operands] = nil + if altname then name = altname end + end + elseif p == "L" then + name = gsub(name, "_", band(op, 0x00200000) ~= 0 and "d" or "w") + elseif p == "." then + if band(op, 1) == 1 then name = name.."." end + elseif p == "N" then + if op == 0x60000000 then name = "nop"; break end + elseif p == "~" then + local n = #operands + operands[n-1], operands[n] = operands[n], operands[n-1] + elseif p == "=" then + local n = #operands + if last == operands[n-1] then + operands[n] = nil + name = altname + end + elseif p == "%" then + local n = #operands + if last == operands[n-1] and last == operands[n-2] then + operands[n] = nil + operands[n-1] = nil + name = altname + end + elseif p == "-" then + rs = rs - 5 + else + assert(false) + end + if x then operands[#operands+1] = x; last = x end + end + + return putop(ctx, name, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + stop = stop - stop % 4 + ctx.pos = ofs - ofs % 4 + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_gpr[r] end + return "f"..(r-32) +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_x64.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_x64.lua new file mode 100644 index 00000000..2d37423e --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_x64.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT x64 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the 64 bit functions from the combined +-- x86/x64 disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_x86 = require((string.match(..., ".*%.") or "").."dis_x86") +return { + create = dis_x86.create64, + disass = dis_x86.disass64, + regname = dis_x86.regname64 +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_x86.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_x86.lua new file mode 100644 index 00000000..5480854c --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dis_x86.lua @@ -0,0 +1,953 @@ +---------------------------------------------------------------------------- +-- LuaJIT x86/x64 disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- Sending small code snippets to an external disassembler and mixing the +-- output with our own stuff was too fragile. So I had to bite the bullet +-- and write yet another x86 disassembler. Oh well ... +-- +-- The output format is very similar to what ndisasm generates. But it has +-- been developed independently by looking at the opcode tables from the +-- Intel and AMD manuals. The supported instruction set is quite extensive +-- and reflects what a current generation Intel or AMD CPU implements in +-- 32 bit and 64 bit mode. Yes, this includes MMX, SSE, SSE2, SSE3, SSSE3, +-- SSE4.1, SSE4.2, SSE4a, AVX, AVX2 and even privileged and hypervisor +-- (VMX/SVM) instructions. +-- +-- Notes: +-- * The (useless) a16 prefix, 3DNow and pre-586 opcodes are unsupported. +-- * No attempt at optimization has been made -- it's fast enough for my needs. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local lower, rep = string.lower, string.rep +local bit = require("bit") +local tohex = bit.tohex + +-- Map for 1st opcode byte in 32 bit mode. Ugly? Well ... read on. +local map_opc1_32 = { +--0x +[0]="addBmr","addVmr","addBrm","addVrm","addBai","addVai","push es","pop es", +"orBmr","orVmr","orBrm","orVrm","orBai","orVai","push cs","opc2*", +--1x +"adcBmr","adcVmr","adcBrm","adcVrm","adcBai","adcVai","push ss","pop ss", +"sbbBmr","sbbVmr","sbbBrm","sbbVrm","sbbBai","sbbVai","push ds","pop ds", +--2x +"andBmr","andVmr","andBrm","andVrm","andBai","andVai","es:seg","daa", +"subBmr","subVmr","subBrm","subVrm","subBai","subVai","cs:seg","das", +--3x +"xorBmr","xorVmr","xorBrm","xorVrm","xorBai","xorVai","ss:seg","aaa", +"cmpBmr","cmpVmr","cmpBrm","cmpVrm","cmpBai","cmpVai","ds:seg","aas", +--4x +"incVR","incVR","incVR","incVR","incVR","incVR","incVR","incVR", +"decVR","decVR","decVR","decVR","decVR","decVR","decVR","decVR", +--5x +"pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR", +"popUR","popUR","popUR","popUR","popUR","popUR","popUR","popUR", +--6x +"sz*pushaw,pusha","sz*popaw,popa","boundVrm","arplWmr", +"fs:seg","gs:seg","o16:","a16", +"pushUi","imulVrmi","pushBs","imulVrms", +"insb","insVS","outsb","outsVS", +--7x +"joBj","jnoBj","jbBj","jnbBj","jzBj","jnzBj","jbeBj","jaBj", +"jsBj","jnsBj","jpeBj","jpoBj","jlBj","jgeBj","jleBj","jgBj", +--8x +"arith!Bmi","arith!Vmi","arith!Bmi","arith!Vms", +"testBmr","testVmr","xchgBrm","xchgVrm", +"movBmr","movVmr","movBrm","movVrm", +"movVmg","leaVrm","movWgm","popUm", +--9x +"nop*xchgVaR|pause|xchgWaR|repne nop","xchgVaR","xchgVaR","xchgVaR", +"xchgVaR","xchgVaR","xchgVaR","xchgVaR", +"sz*cbw,cwde,cdqe","sz*cwd,cdq,cqo","call farViw","wait", +"sz*pushfw,pushf","sz*popfw,popf","sahf","lahf", +--Ax +"movBao","movVao","movBoa","movVoa", +"movsb","movsVS","cmpsb","cmpsVS", +"testBai","testVai","stosb","stosVS", +"lodsb","lodsVS","scasb","scasVS", +--Bx +"movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi", +"movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI", +--Cx +"shift!Bmu","shift!Vmu","retBw","ret","vex*3$lesVrm","vex*2$ldsVrm","movBmi","movVmi", +"enterBwu","leave","retfBw","retf","int3","intBu","into","iretVS", +--Dx +"shift!Bm1","shift!Vm1","shift!Bmc","shift!Vmc","aamBu","aadBu","salc","xlatb", +"fp*0","fp*1","fp*2","fp*3","fp*4","fp*5","fp*6","fp*7", +--Ex +"loopneBj","loopeBj","loopBj","sz*jcxzBj,jecxzBj,jrcxzBj", +"inBau","inVau","outBua","outVua", +"callVj","jmpVj","jmp farViw","jmpBj","inBad","inVad","outBda","outVda", +--Fx +"lock:","int1","repne:rep","rep:","hlt","cmc","testb!Bm","testv!Vm", +"clc","stc","cli","sti","cld","std","incb!Bm","incd!Vm", +} +assert(#map_opc1_32 == 255) + +-- Map for 1st opcode byte in 64 bit mode (overrides only). +local map_opc1_64 = setmetatable({ + [0x06]=false, [0x07]=false, [0x0e]=false, + [0x16]=false, [0x17]=false, [0x1e]=false, [0x1f]=false, + [0x27]=false, [0x2f]=false, [0x37]=false, [0x3f]=false, + [0x60]=false, [0x61]=false, [0x62]=false, [0x63]="movsxdVrDmt", [0x67]="a32:", + [0x40]="rex*", [0x41]="rex*b", [0x42]="rex*x", [0x43]="rex*xb", + [0x44]="rex*r", [0x45]="rex*rb", [0x46]="rex*rx", [0x47]="rex*rxb", + [0x48]="rex*w", [0x49]="rex*wb", [0x4a]="rex*wx", [0x4b]="rex*wxb", + [0x4c]="rex*wr", [0x4d]="rex*wrb", [0x4e]="rex*wrx", [0x4f]="rex*wrxb", + [0x82]=false, [0x9a]=false, [0xc4]="vex*3", [0xc5]="vex*2", [0xce]=false, + [0xd4]=false, [0xd5]=false, [0xd6]=false, [0xea]=false, +}, { __index = map_opc1_32 }) + +-- Map for 2nd opcode byte (0F xx). True CISC hell. Hey, I told you. +-- Prefix dependent MMX/SSE opcodes: (none)|rep|o16|repne, -|F3|66|F2 +local map_opc2 = { +--0x +[0]="sldt!Dmp","sgdt!Ump","larVrm","lslVrm",nil,"syscall","clts","sysret", +"invd","wbinvd",nil,"ud1",nil,"$prefetch!Bm","femms","3dnowMrmu", +--1x +"movupsXrm|movssXrvm|movupdXrm|movsdXrvm", +"movupsXmr|movssXmvr|movupdXmr|movsdXmvr", +"movhlpsXrm$movlpsXrm|movsldupXrm|movlpdXrm|movddupXrm", +"movlpsXmr||movlpdXmr", +"unpcklpsXrvm||unpcklpdXrvm", +"unpckhpsXrvm||unpckhpdXrvm", +"movlhpsXrm$movhpsXrm|movshdupXrm|movhpdXrm", +"movhpsXmr||movhpdXmr", +"$prefetcht!Bm","hintnopVm","hintnopVm","hintnopVm", +"hintnopVm","hintnopVm","hintnopVm","hintnopVm", +--2x +"movUmx$","movUmy$","movUxm$","movUym$","movUmz$",nil,"movUzm$",nil, +"movapsXrm||movapdXrm", +"movapsXmr||movapdXmr", +"cvtpi2psXrMm|cvtsi2ssXrvVmt|cvtpi2pdXrMm|cvtsi2sdXrvVmt", +"movntpsXmr|movntssXmr|movntpdXmr|movntsdXmr", +"cvttps2piMrXm|cvttss2siVrXm|cvttpd2piMrXm|cvttsd2siVrXm", +"cvtps2piMrXm|cvtss2siVrXm|cvtpd2piMrXm|cvtsd2siVrXm", +"ucomissXrm||ucomisdXrm", +"comissXrm||comisdXrm", +--3x +"wrmsr","rdtsc","rdmsr","rdpmc","sysenter","sysexit",nil,"getsec", +"opc3*38",nil,"opc3*3a",nil,nil,nil,nil,nil, +--4x +"cmovoVrm","cmovnoVrm","cmovbVrm","cmovnbVrm", +"cmovzVrm","cmovnzVrm","cmovbeVrm","cmovaVrm", +"cmovsVrm","cmovnsVrm","cmovpeVrm","cmovpoVrm", +"cmovlVrm","cmovgeVrm","cmovleVrm","cmovgVrm", +--5x +"movmskpsVrXm$||movmskpdVrXm$","sqrtpsXrm|sqrtssXrm|sqrtpdXrm|sqrtsdXrm", +"rsqrtpsXrm|rsqrtssXrvm","rcppsXrm|rcpssXrvm", +"andpsXrvm||andpdXrvm","andnpsXrvm||andnpdXrvm", +"orpsXrvm||orpdXrvm","xorpsXrvm||xorpdXrvm", +"addpsXrvm|addssXrvm|addpdXrvm|addsdXrvm","mulpsXrvm|mulssXrvm|mulpdXrvm|mulsdXrvm", +"cvtps2pdXrm|cvtss2sdXrvm|cvtpd2psXrm|cvtsd2ssXrvm", +"cvtdq2psXrm|cvttps2dqXrm|cvtps2dqXrm", +"subpsXrvm|subssXrvm|subpdXrvm|subsdXrvm","minpsXrvm|minssXrvm|minpdXrvm|minsdXrvm", +"divpsXrvm|divssXrvm|divpdXrvm|divsdXrvm","maxpsXrvm|maxssXrvm|maxpdXrvm|maxsdXrvm", +--6x +"punpcklbwPrvm","punpcklwdPrvm","punpckldqPrvm","packsswbPrvm", +"pcmpgtbPrvm","pcmpgtwPrvm","pcmpgtdPrvm","packuswbPrvm", +"punpckhbwPrvm","punpckhwdPrvm","punpckhdqPrvm","packssdwPrvm", +"||punpcklqdqXrvm","||punpckhqdqXrvm", +"movPrVSm","movqMrm|movdquXrm|movdqaXrm", +--7x +"pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pvmu", +"pshiftd!Pvmu","pshiftq!Mvmu||pshiftdq!Xvmu", +"pcmpeqbPrvm","pcmpeqwPrvm","pcmpeqdPrvm","emms*|", +"vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$", +nil,nil, +"||haddpdXrvm|haddpsXrvm","||hsubpdXrvm|hsubpsXrvm", +"movVSmMr|movqXrm|movVSmXr","movqMmr|movdquXmr|movdqaXmr", +--8x +"joVj","jnoVj","jbVj","jnbVj","jzVj","jnzVj","jbeVj","jaVj", +"jsVj","jnsVj","jpeVj","jpoVj","jlVj","jgeVj","jleVj","jgVj", +--9x +"setoBm","setnoBm","setbBm","setnbBm","setzBm","setnzBm","setbeBm","setaBm", +"setsBm","setnsBm","setpeBm","setpoBm","setlBm","setgeBm","setleBm","setgBm", +--Ax +"push fs","pop fs","cpuid","btVmr","shldVmru","shldVmrc",nil,nil, +"push gs","pop gs","rsm","btsVmr","shrdVmru","shrdVmrc","fxsave!Dmp","imulVrm", +--Bx +"cmpxchgBmr","cmpxchgVmr","$lssVrm","btrVmr", +"$lfsVrm","$lgsVrm","movzxVrBmt","movzxVrWmt", +"|popcntVrm","ud2Dp","bt!Vmu","btcVmr", +"bsfVrm","bsrVrm|lzcntVrm|bsrWrm","movsxVrBmt","movsxVrWmt", +--Cx +"xaddBmr","xaddVmr", +"cmppsXrvmu|cmpssXrvmu|cmppdXrvmu|cmpsdXrvmu","$movntiVmr|", +"pinsrwPrvWmu","pextrwDrPmu", +"shufpsXrvmu||shufpdXrvmu","$cmpxchg!Qmp", +"bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR", +--Dx +"||addsubpdXrvm|addsubpsXrvm","psrlwPrvm","psrldPrvm","psrlqPrvm", +"paddqPrvm","pmullwPrvm", +"|movq2dqXrMm|movqXmr|movdq2qMrXm$","pmovmskbVrMm||pmovmskbVrXm", +"psubusbPrvm","psubuswPrvm","pminubPrvm","pandPrvm", +"paddusbPrvm","padduswPrvm","pmaxubPrvm","pandnPrvm", +--Ex +"pavgbPrvm","psrawPrvm","psradPrvm","pavgwPrvm", +"pmulhuwPrvm","pmulhwPrvm", +"|cvtdq2pdXrm|cvttpd2dqXrm|cvtpd2dqXrm","$movntqMmr||$movntdqXmr", +"psubsbPrvm","psubswPrvm","pminswPrvm","porPrvm", +"paddsbPrvm","paddswPrvm","pmaxswPrvm","pxorPrvm", +--Fx +"|||lddquXrm","psllwPrvm","pslldPrvm","psllqPrvm", +"pmuludqPrvm","pmaddwdPrvm","psadbwPrvm","maskmovqMrm||maskmovdquXrm$", +"psubbPrvm","psubwPrvm","psubdPrvm","psubqPrvm", +"paddbPrvm","paddwPrvm","padddPrvm","ud", +} +assert(map_opc2[255] == "ud") + +-- Map for three-byte opcodes. Can't wait for their next invention. +local map_opc3 = { +["38"] = { -- [66] 0f 38 xx +--0x +[0]="pshufbPrvm","phaddwPrvm","phadddPrvm","phaddswPrvm", +"pmaddubswPrvm","phsubwPrvm","phsubdPrvm","phsubswPrvm", +"psignbPrvm","psignwPrvm","psigndPrvm","pmulhrswPrvm", +"||permilpsXrvm","||permilpdXrvm",nil,nil, +--1x +"||pblendvbXrma",nil,nil,nil, +"||blendvpsXrma","||blendvpdXrma","||permpsXrvm","||ptestXrm", +"||broadcastssXrm","||broadcastsdXrm","||broadcastf128XrlXm",nil, +"pabsbPrm","pabswPrm","pabsdPrm",nil, +--2x +"||pmovsxbwXrm","||pmovsxbdXrm","||pmovsxbqXrm","||pmovsxwdXrm", +"||pmovsxwqXrm","||pmovsxdqXrm",nil,nil, +"||pmuldqXrvm","||pcmpeqqXrvm","||$movntdqaXrm","||packusdwXrvm", +"||maskmovpsXrvm","||maskmovpdXrvm","||maskmovpsXmvr","||maskmovpdXmvr", +--3x +"||pmovzxbwXrm","||pmovzxbdXrm","||pmovzxbqXrm","||pmovzxwdXrm", +"||pmovzxwqXrm","||pmovzxdqXrm","||permdXrvm","||pcmpgtqXrvm", +"||pminsbXrvm","||pminsdXrvm","||pminuwXrvm","||pminudXrvm", +"||pmaxsbXrvm","||pmaxsdXrvm","||pmaxuwXrvm","||pmaxudXrvm", +--4x +"||pmulddXrvm","||phminposuwXrm",nil,nil, +nil,"||psrlvVSXrvm","||psravdXrvm","||psllvVSXrvm", +--5x +[0x58] = "||pbroadcastdXrlXm",[0x59] = "||pbroadcastqXrlXm", +[0x5a] = "||broadcasti128XrlXm", +--7x +[0x78] = "||pbroadcastbXrlXm",[0x79] = "||pbroadcastwXrlXm", +--8x +[0x8c] = "||pmaskmovXrvVSm", +[0x8e] = "||pmaskmovVSmXvr", +--9x +[0x96] = "||fmaddsub132pHXrvm",[0x97] = "||fmsubadd132pHXrvm", +[0x98] = "||fmadd132pHXrvm",[0x99] = "||fmadd132sHXrvm", +[0x9a] = "||fmsub132pHXrvm",[0x9b] = "||fmsub132sHXrvm", +[0x9c] = "||fnmadd132pHXrvm",[0x9d] = "||fnmadd132sHXrvm", +[0x9e] = "||fnmsub132pHXrvm",[0x9f] = "||fnmsub132sHXrvm", +--Ax +[0xa6] = "||fmaddsub213pHXrvm",[0xa7] = "||fmsubadd213pHXrvm", +[0xa8] = "||fmadd213pHXrvm",[0xa9] = "||fmadd213sHXrvm", +[0xaa] = "||fmsub213pHXrvm",[0xab] = "||fmsub213sHXrvm", +[0xac] = "||fnmadd213pHXrvm",[0xad] = "||fnmadd213sHXrvm", +[0xae] = "||fnmsub213pHXrvm",[0xaf] = "||fnmsub213sHXrvm", +--Bx +[0xb6] = "||fmaddsub231pHXrvm",[0xb7] = "||fmsubadd231pHXrvm", +[0xb8] = "||fmadd231pHXrvm",[0xb9] = "||fmadd231sHXrvm", +[0xba] = "||fmsub231pHXrvm",[0xbb] = "||fmsub231sHXrvm", +[0xbc] = "||fnmadd231pHXrvm",[0xbd] = "||fnmadd231sHXrvm", +[0xbe] = "||fnmsub231pHXrvm",[0xbf] = "||fnmsub231sHXrvm", +--Dx +[0xdc] = "||aesencXrvm", [0xdd] = "||aesenclastXrvm", +[0xde] = "||aesdecXrvm", [0xdf] = "||aesdeclastXrvm", +--Fx +[0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt", +[0xf7] = "| sarxVrmv| shlxVrmv| shrxVrmv", +}, + +["3a"] = { -- [66] 0f 3a xx +--0x +[0x00]="||permqXrmu","||permpdXrmu","||pblenddXrvmu",nil, +"||permilpsXrmu","||permilpdXrmu","||perm2f128Xrvmu",nil, +"||roundpsXrmu","||roundpdXrmu","||roundssXrvmu","||roundsdXrvmu", +"||blendpsXrvmu","||blendpdXrvmu","||pblendwXrvmu","palignrPrvmu", +--1x +nil,nil,nil,nil, +"||pextrbVmXru","||pextrwVmXru","||pextrVmSXru","||extractpsVmXru", +"||insertf128XrvlXmu","||extractf128XlXmYru",nil,nil, +nil,nil,nil,nil, +--2x +"||pinsrbXrvVmu","||insertpsXrvmu","||pinsrXrvVmuS",nil, +--3x +[0x38] = "||inserti128Xrvmu",[0x39] = "||extracti128XlXmYru", +--4x +[0x40] = "||dppsXrvmu", +[0x41] = "||dppdXrvmu", +[0x42] = "||mpsadbwXrvmu", +[0x44] = "||pclmulqdqXrvmu", +[0x46] = "||perm2i128Xrvmu", +[0x4a] = "||blendvpsXrvmb",[0x4b] = "||blendvpdXrvmb", +[0x4c] = "||pblendvbXrvmb", +--6x +[0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu", +[0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu", +[0xdf] = "||aeskeygenassistXrmu", +--Fx +[0xf0] = "||| rorxVrmu", +}, +} + +-- Map for VMX/SVM opcodes 0F 01 C0-FF (sgdt group with register operands). +local map_opcvm = { +[0xc1]="vmcall",[0xc2]="vmlaunch",[0xc3]="vmresume",[0xc4]="vmxoff", +[0xc8]="monitor",[0xc9]="mwait", +[0xd8]="vmrun",[0xd9]="vmmcall",[0xda]="vmload",[0xdb]="vmsave", +[0xdc]="stgi",[0xdd]="clgi",[0xde]="skinit",[0xdf]="invlpga", +[0xf8]="swapgs",[0xf9]="rdtscp", +} + +-- Map for FP opcodes. And you thought stack machines are simple? +local map_opcfp = { +-- D8-DF 00-BF: opcodes with a memory operand. +-- D8 +[0]="faddFm","fmulFm","fcomFm","fcompFm","fsubFm","fsubrFm","fdivFm","fdivrFm", +"fldFm",nil,"fstFm","fstpFm","fldenvVm","fldcwWm","fnstenvVm","fnstcwWm", +-- DA +"fiaddDm","fimulDm","ficomDm","ficompDm", +"fisubDm","fisubrDm","fidivDm","fidivrDm", +-- DB +"fildDm","fisttpDm","fistDm","fistpDm",nil,"fld twordFmp",nil,"fstp twordFmp", +-- DC +"faddGm","fmulGm","fcomGm","fcompGm","fsubGm","fsubrGm","fdivGm","fdivrGm", +-- DD +"fldGm","fisttpQm","fstGm","fstpGm","frstorDmp",nil,"fnsaveDmp","fnstswWm", +-- DE +"fiaddWm","fimulWm","ficomWm","ficompWm", +"fisubWm","fisubrWm","fidivWm","fidivrWm", +-- DF +"fildWm","fisttpWm","fistWm","fistpWm", +"fbld twordFmp","fildQm","fbstp twordFmp","fistpQm", +-- xx C0-FF: opcodes with a pseudo-register operand. +-- D8 +"faddFf","fmulFf","fcomFf","fcompFf","fsubFf","fsubrFf","fdivFf","fdivrFf", +-- D9 +"fldFf","fxchFf",{"fnop"},nil, +{"fchs","fabs",nil,nil,"ftst","fxam"}, +{"fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz"}, +{"f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp"}, +{"fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"}, +-- DA +"fcmovbFf","fcmoveFf","fcmovbeFf","fcmovuFf",nil,{nil,"fucompp"},nil,nil, +-- DB +"fcmovnbFf","fcmovneFf","fcmovnbeFf","fcmovnuFf", +{nil,nil,"fnclex","fninit"},"fucomiFf","fcomiFf",nil, +-- DC +"fadd toFf","fmul toFf",nil,nil, +"fsub toFf","fsubr toFf","fdivr toFf","fdiv toFf", +-- DD +"ffreeFf",nil,"fstFf","fstpFf","fucomFf","fucompFf",nil,nil, +-- DE +"faddpFf","fmulpFf",nil,{nil,"fcompp"}, +"fsubrpFf","fsubpFf","fdivrpFf","fdivpFf", +-- DF +nil,nil,nil,nil,{"fnstsw ax"},"fucomipFf","fcomipFf",nil, +} +assert(map_opcfp[126] == "fcomipFf") + +-- Map for opcode groups. The subkey is sp from the ModRM byte. +local map_opcgroup = { + arith = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" }, + shift = { "rol", "ror", "rcl", "rcr", "shl", "shr", "sal", "sar" }, + testb = { "testBmi", "testBmi", "not", "neg", "mul", "imul", "div", "idiv" }, + testv = { "testVmi", "testVmi", "not", "neg", "mul", "imul", "div", "idiv" }, + incb = { "inc", "dec" }, + incd = { "inc", "dec", "callUmp", "$call farDmp", + "jmpUmp", "$jmp farDmp", "pushUm" }, + sldt = { "sldt", "str", "lldt", "ltr", "verr", "verw" }, + sgdt = { "vm*$sgdt", "vm*$sidt", "$lgdt", "vm*$lidt", + "smsw", nil, "lmsw", "vm*$invlpg" }, + bt = { nil, nil, nil, nil, "bt", "bts", "btr", "btc" }, + cmpxchg = { nil, "sz*,cmpxchg8bQmp,cmpxchg16bXmp", nil, nil, + nil, nil, "vmptrld|vmxon|vmclear", "vmptrst" }, + pshiftw = { nil, nil, "psrlw", nil, "psraw", nil, "psllw" }, + pshiftd = { nil, nil, "psrld", nil, "psrad", nil, "pslld" }, + pshiftq = { nil, nil, "psrlq", nil, nil, nil, "psllq" }, + pshiftdq = { nil, nil, "psrlq", "psrldq", nil, nil, "psllq", "pslldq" }, + fxsave = { "$fxsave", "$fxrstor", "$ldmxcsr", "$stmxcsr", + nil, "lfenceDp$", "mfenceDp$", "sfenceDp$clflush" }, + prefetch = { "prefetch", "prefetchw" }, + prefetcht = { "prefetchnta", "prefetcht0", "prefetcht1", "prefetcht2" }, +} + +------------------------------------------------------------------------------ + +-- Maps for register names. +local map_regs = { + B = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + B64 = { "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + W = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }, + D = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }, + Q = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }, + M = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", + "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, -- No x64 ext! + X = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" }, + Y = { "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15" }, +} +local map_segregs = { "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7" } + +-- Maps for size names. +local map_sz2n = { + B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16, Y = 32, +} +local map_sz2prefix = { + B = "byte", W = "word", D = "dword", + Q = "qword", + M = "qword", X = "xword", Y = "yword", + F = "dword", G = "qword", -- No need for sizes/register names for these two. +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local code, pos, hex = ctx.code, ctx.pos, "" + local hmax = ctx.hexdump + if hmax > 0 then + for i=ctx.start,pos-1 do + hex = hex..format("%02X", byte(code, i, i)) + end + if #hex > hmax then hex = sub(hex, 1, hmax)..". " + else hex = hex..rep(" ", hmax-#hex+2) end + end + if operands then text = text.." "..operands end + if ctx.o16 then text = "o16 "..text; ctx.o16 = false end + if ctx.a32 then text = "a32 "..text; ctx.a32 = false end + if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end + if ctx.rex then + local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "").. + (ctx.rexx and "x" or "")..(ctx.rexb and "b" or "").. + (ctx.vexl and "l" or "") + if ctx.vexv and ctx.vexv ~= 0 then t = t.."v"..ctx.vexv end + if t ~= "" then text = ctx.rex.."."..t.." "..gsub(text, "^ ", "") + elseif ctx.rex == "vex" then text = gsub("v"..text, "^v ", "") end + ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false + ctx.rex = false; ctx.vexl = false; ctx.vexv = false + end + if ctx.seg then + local text2, n = gsub(text, "%[", "["..ctx.seg..":") + if n == 0 then text = ctx.seg.." "..text else text = text2 end + ctx.seg = false + end + if ctx.lock then text = "lock "..text; ctx.lock = false end + local imm = ctx.imm + if imm then + local sym = ctx.symtab[imm] + if sym then text = text.."\t->"..sym end + end + ctx.out(format("%08x %s%s\n", ctx.addr+ctx.start, hex, text)) + ctx.mrm = false + ctx.vexv = false + ctx.start = pos + ctx.imm = nil +end + +-- Clear all prefix flags. +local function clearprefixes(ctx) + ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false + ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false + ctx.rex = false; ctx.a32 = false; ctx.vexl = false +end + +-- Fallback for incomplete opcodes at the end. +local function incomplete(ctx) + ctx.pos = ctx.stop+1 + clearprefixes(ctx) + return putop(ctx, "(incomplete)") +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + clearprefixes(ctx) + return putop(ctx, "(unknown)") +end + +-- Return an immediate of the specified size. +local function getimm(ctx, pos, n) + if pos+n-1 > ctx.stop then return incomplete(ctx) end + local code = ctx.code + if n == 1 then + local b1 = byte(code, pos, pos) + return b1 + elseif n == 2 then + local b1, b2 = byte(code, pos, pos+1) + return b1+b2*256 + else + local b1, b2, b3, b4 = byte(code, pos, pos+3) + local imm = b1+b2*256+b3*65536+b4*16777216 + ctx.imm = imm + return imm + end +end + +-- Process pattern string and generate the operands. +local function putpat(ctx, name, pat) + local operands, regs, sz, mode, sp, rm, sc, rx, sdisp + local code, pos, stop, vexl = ctx.code, ctx.pos, ctx.stop, ctx.vexl + + -- Chars used: 1DFGHIMPQRSTUVWXYabcdfgijlmoprstuvwxyz + for p in gmatch(pat, ".") do + local x = nil + if p == "V" or p == "U" then + if ctx.rexw then sz = "Q"; ctx.rexw = false + elseif ctx.o16 then sz = "W"; ctx.o16 = false + elseif p == "U" and ctx.x64 then sz = "Q" + else sz = "D" end + regs = map_regs[sz] + elseif p == "T" then + if ctx.rexw then sz = "Q"; ctx.rexw = false else sz = "D" end + regs = map_regs[sz] + elseif p == "B" then + sz = "B" + regs = ctx.rex and map_regs.B64 or map_regs.B + elseif match(p, "[WDQMXYFG]") then + sz = p + if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end + regs = map_regs[sz] + elseif p == "P" then + sz = ctx.o16 and "X" or "M"; ctx.o16 = false + if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end + regs = map_regs[sz] + elseif p == "H" then + name = name..(ctx.rexw and "d" or "s") + ctx.rexw = false + elseif p == "S" then + name = name..lower(sz) + elseif p == "s" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = imm <= 127 and format("+0x%02x", imm) + or format("-0x%02x", 256-imm) + pos = pos+1 + elseif p == "u" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = format("0x%02x", imm) + pos = pos+1 + elseif p == "b" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = regs[imm/16+1] + pos = pos+1 + elseif p == "w" then + local imm = getimm(ctx, pos, 2); if not imm then return end + x = format("0x%x", imm) + pos = pos+2 + elseif p == "o" then -- [offset] + if ctx.x64 then + local imm1 = getimm(ctx, pos, 4); if not imm1 then return end + local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end + x = format("[0x%08x%08x]", imm2, imm1) + pos = pos+8 + else + local imm = getimm(ctx, pos, 4); if not imm then return end + x = format("[0x%08x]", imm) + pos = pos+4 + end + elseif p == "i" or p == "I" then + local n = map_sz2n[sz] + if n == 8 and ctx.x64 and p == "I" then + local imm1 = getimm(ctx, pos, 4); if not imm1 then return end + local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end + x = format("0x%08x%08x", imm2, imm1) + else + if n == 8 then n = 4 end + local imm = getimm(ctx, pos, n); if not imm then return end + if sz == "Q" and (imm < 0 or imm > 0x7fffffff) then + imm = (0xffffffff+1)-imm + x = format(imm > 65535 and "-0x%08x" or "-0x%x", imm) + else + x = format(imm > 65535 and "0x%08x" or "0x%x", imm) + end + end + pos = pos+n + elseif p == "j" then + local n = map_sz2n[sz] + if n == 8 then n = 4 end + local imm = getimm(ctx, pos, n); if not imm then return end + if sz == "B" and imm > 127 then imm = imm-256 + elseif imm > 2147483647 then imm = imm-4294967296 end + pos = pos+n + imm = imm + pos + ctx.addr + if imm > 4294967295 and not ctx.x64 then imm = imm-4294967296 end + ctx.imm = imm + if sz == "W" then + x = format("word 0x%04x", imm%65536) + elseif ctx.x64 then + local lo = imm % 0x1000000 + x = format("0x%02x%06x", (imm-lo) / 0x1000000, lo) + else + x = "0x"..tohex(imm) + end + elseif p == "R" then + local r = byte(code, pos-1, pos-1)%8 + if ctx.rexb then r = r + 8; ctx.rexb = false end + x = regs[r+1] + elseif p == "a" then x = regs[1] + elseif p == "c" then x = "cl" + elseif p == "d" then x = "dx" + elseif p == "1" then x = "1" + else + if not mode then + mode = ctx.mrm + if not mode then + if pos > stop then return incomplete(ctx) end + mode = byte(code, pos, pos) + pos = pos+1 + end + rm = mode%8; mode = (mode-rm)/8 + sp = mode%8; mode = (mode-sp)/8 + sdisp = "" + if mode < 3 then + if rm == 4 then + if pos > stop then return incomplete(ctx) end + sc = byte(code, pos, pos) + pos = pos+1 + rm = sc%8; sc = (sc-rm)/8 + rx = sc%8; sc = (sc-rx)/8 + if ctx.rexx then rx = rx + 8; ctx.rexx = false end + if rx == 4 then rx = nil end + end + if mode > 0 or rm == 5 then + local dsz = mode + if dsz ~= 1 then dsz = 4 end + local disp = getimm(ctx, pos, dsz); if not disp then return end + if mode == 0 then rm = nil end + if rm or rx or (not sc and ctx.x64 and not ctx.a32) then + if dsz == 1 and disp > 127 then + sdisp = format("-0x%x", 256-disp) + elseif disp >= 0 and disp <= 0x7fffffff then + sdisp = format("+0x%x", disp) + else + sdisp = format("-0x%x", (0xffffffff+1)-disp) + end + else + sdisp = format(ctx.x64 and not ctx.a32 and + not (disp >= 0 and disp <= 0x7fffffff) + and "0xffffffff%08x" or "0x%08x", disp) + end + pos = pos+dsz + end + end + if rm and ctx.rexb then rm = rm + 8; ctx.rexb = false end + if ctx.rexr then sp = sp + 8; ctx.rexr = false end + end + if p == "m" then + if mode == 3 then x = regs[rm+1] + else + local aregs = ctx.a32 and map_regs.D or ctx.aregs + local srm, srx = "", "" + if rm then srm = aregs[rm+1] + elseif not sc and ctx.x64 and not ctx.a32 then srm = "rip" end + ctx.a32 = false + if rx then + if rm then srm = srm.."+" end + srx = aregs[rx+1] + if sc > 0 then srx = srx.."*"..(2^sc) end + end + x = format("[%s%s%s]", srm, srx, sdisp) + end + if mode < 3 and + (not match(pat, "[aRrgp]") or match(pat, "t")) then -- Yuck. + x = map_sz2prefix[sz].." "..x + end + elseif p == "r" then x = regs[sp+1] + elseif p == "g" then x = map_segregs[sp+1] + elseif p == "p" then -- Suppress prefix. + elseif p == "f" then x = "st"..rm + elseif p == "x" then + if sp == 0 and ctx.lock and not ctx.x64 then + x = "CR8"; ctx.lock = false + else + x = "CR"..sp + end + elseif p == "v" then + if ctx.vexv then + x = regs[ctx.vexv+1]; ctx.vexv = false + end + elseif p == "y" then x = "DR"..sp + elseif p == "z" then x = "TR"..sp + elseif p == "l" then vexl = false + elseif p == "t" then + else + error("bad pattern `"..pat.."'") + end + end + if x then operands = operands and operands..", "..x or x end + end + ctx.pos = pos + return putop(ctx, name, operands) +end + +-- Forward declaration. +local map_act + +-- Fetch and cache MRM byte. +local function getmrm(ctx) + local mrm = ctx.mrm + if not mrm then + local pos = ctx.pos + if pos > ctx.stop then return nil end + mrm = byte(ctx.code, pos, pos) + ctx.pos = pos+1 + ctx.mrm = mrm + end + return mrm +end + +-- Dispatch to handler depending on pattern. +local function dispatch(ctx, opat, patgrp) + if not opat then return unknown(ctx) end + if match(opat, "%|") then -- MMX/SSE variants depending on prefix. + local p + if ctx.rep then + p = ctx.rep=="rep" and "%|([^%|]*)" or "%|[^%|]*%|[^%|]*%|([^%|]*)" + ctx.rep = false + elseif ctx.o16 then p = "%|[^%|]*%|([^%|]*)"; ctx.o16 = false + else p = "^[^%|]*" end + opat = match(opat, p) + if not opat then return unknown(ctx) end +-- ctx.rep = false; ctx.o16 = false + --XXX fails for 66 f2 0f 38 f1 06 crc32 eax,WORD PTR [esi] + --XXX remove in branches? + end + if match(opat, "%$") then -- reg$mem variants. + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + opat = match(opat, mrm >= 192 and "^[^%$]*" or "%$(.*)") + if opat == "" then return unknown(ctx) end + end + if opat == "" then return unknown(ctx) end + local name, pat = match(opat, "^([a-z0-9 ]*)(.*)") + if pat == "" and patgrp then pat = patgrp end + return map_act[sub(pat, 1, 1)](ctx, name, pat) +end + +-- Get a pattern from an opcode map and dispatch to handler. +local function dispatchmap(ctx, opcmap) + local pos = ctx.pos + local opat = opcmap[byte(ctx.code, pos, pos)] + pos = pos + 1 + ctx.pos = pos + return dispatch(ctx, opat) +end + +-- Map for action codes. The key is the first char after the name. +map_act = { + -- Simple opcodes without operands. + [""] = function(ctx, name, pat) + return putop(ctx, name) + end, + + -- Operand size chars fall right through. + B = putpat, W = putpat, D = putpat, Q = putpat, + V = putpat, U = putpat, T = putpat, + M = putpat, X = putpat, P = putpat, + F = putpat, G = putpat, Y = putpat, + H = putpat, + + -- Collect prefixes. + [":"] = function(ctx, name, pat) + ctx[pat == ":" and name or sub(pat, 2)] = name + if ctx.pos - ctx.start > 5 then return unknown(ctx) end -- Limit #prefixes. + end, + + -- Chain to special handler specified by name. + ["*"] = function(ctx, name, pat) + return map_act[name](ctx, name, sub(pat, 2)) + end, + + -- Use named subtable for opcode group. + ["!"] = function(ctx, name, pat) + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + return dispatch(ctx, map_opcgroup[name][((mrm-(mrm%8))/8)%8+1], sub(pat, 2)) + end, + + -- o16,o32[,o64] variants. + sz = function(ctx, name, pat) + if ctx.o16 then ctx.o16 = false + else + pat = match(pat, ",(.*)") + if ctx.rexw then + local p = match(pat, ",(.*)") + if p then pat = p; ctx.rexw = false end + end + end + pat = match(pat, "^[^,]*") + return dispatch(ctx, pat) + end, + + -- Two-byte opcode dispatch. + opc2 = function(ctx, name, pat) + return dispatchmap(ctx, map_opc2) + end, + + -- Three-byte opcode dispatch. + opc3 = function(ctx, name, pat) + return dispatchmap(ctx, map_opc3[pat]) + end, + + -- VMX/SVM dispatch. + vm = function(ctx, name, pat) + return dispatch(ctx, map_opcvm[ctx.mrm]) + end, + + -- Floating point opcode dispatch. + fp = function(ctx, name, pat) + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + local rm = mrm%8 + local idx = pat*8 + ((mrm-rm)/8)%8 + if mrm >= 192 then idx = idx + 64 end + local opat = map_opcfp[idx] + if type(opat) == "table" then opat = opat[rm+1] end + return dispatch(ctx, opat) + end, + + -- REX prefix. + rex = function(ctx, name, pat) + if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. + for p in gmatch(pat, ".") do ctx["rex"..p] = true end + ctx.rex = "rex" + end, + + -- VEX prefix. + vex = function(ctx, name, pat) + if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. + ctx.rex = "vex" + local pos = ctx.pos + if ctx.mrm then + ctx.mrm = nil + pos = pos-1 + end + local b = byte(ctx.code, pos, pos) + if not b then return incomplete(ctx) end + pos = pos+1 + if b < 128 then ctx.rexr = true end + local m = 1 + if pat == "3" then + m = b%32; b = (b-m)/32 + local nb = b%2; b = (b-nb)/2 + if nb == 0 then ctx.rexb = true end + local nx = b%2 + if nx == 0 then ctx.rexx = true end + b = byte(ctx.code, pos, pos) + if not b then return incomplete(ctx) end + pos = pos+1 + if b >= 128 then ctx.rexw = true end + end + ctx.pos = pos + local map + if m == 1 then map = map_opc2 + elseif m == 2 then map = map_opc3["38"] + elseif m == 3 then map = map_opc3["3a"] + else return unknown(ctx) end + local p = b%4; b = (b-p)/4 + if p == 1 then ctx.o16 = "o16" + elseif p == 2 then ctx.rep = "rep" + elseif p == 3 then ctx.rep = "repne" end + local l = b%2; b = (b-l)/2 + if l ~= 0 then ctx.vexl = true end + ctx.vexv = (-1-b)%16 + return dispatchmap(ctx, map) + end, + + -- Special case for nop with REX prefix. + nop = function(ctx, name, pat) + return dispatch(ctx, ctx.rex and pat or "nop") + end, + + -- Special case for 0F 77. + emms = function(ctx, name, pat) + if ctx.rex ~= "vex" then + return putop(ctx, "emms") + elseif ctx.vexl then + ctx.vexl = false + return putop(ctx, "zeroall") + else + return putop(ctx, "zeroupper") + end + end, +} + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ofs = ofs + 1 + ctx.start = ofs + ctx.pos = ofs + ctx.stop = stop + ctx.imm = nil + ctx.mrm = false + clearprefixes(ctx) + while ctx.pos <= stop do dispatchmap(ctx, ctx.map1) end + if ctx.pos ~= ctx.start then incomplete(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = (addr or 0) - 1 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 16 + ctx.x64 = false + ctx.map1 = map_opc1_32 + ctx.aregs = map_regs.D + return ctx +end + +local function create64(code, addr, out) + local ctx = create(code, addr, out) + ctx.x64 = true + ctx.map1 = map_opc1_64 + ctx.aregs = map_regs.Q + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +local function disass64(code, addr, out) + create64(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 8 then return map_regs.D[r+1] end + return map_regs.X[r-7] +end + +local function regname64(r) + if r < 16 then return map_regs.Q[r+1] end + return map_regs.X[r-15] +end + +-- Public module functions. +return { + create = create, + create64 = create64, + disass = disass, + disass64 = disass64, + regname = regname, + regname64 = regname64 +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dump.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dump.lua new file mode 100644 index 00000000..9eda08c4 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/dump.lua @@ -0,0 +1,726 @@ +---------------------------------------------------------------------------- +-- LuaJIT compiler dump module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module can be used to debug the JIT compiler itself. It dumps the +-- code representations and structures used in various compiler stages. +-- +-- Example usage: +-- +-- luajit -jdump -e "local x=0; for i=1,1e6 do x=x+i end; print(x)" +-- luajit -jdump=im -e "for i=1,1000 do for j=1,1000 do end end" | less -R +-- luajit -jdump=is myapp.lua | less -R +-- luajit -jdump=-b myapp.lua +-- luajit -jdump=+aH,myapp.html myapp.lua +-- luajit -jdump=ixT,myapp.dump myapp.lua +-- +-- The first argument specifies the dump mode. The second argument gives +-- the output file name. Default output is to stdout, unless the environment +-- variable LUAJIT_DUMPFILE is set. The file is overwritten every time the +-- module is started. +-- +-- Different features can be turned on or off with the dump mode. If the +-- mode starts with a '+', the following features are added to the default +-- set of features; a '-' removes them. Otherwise the features are replaced. +-- +-- The following dump features are available (* marks the default): +-- +-- * t Print a line for each started, ended or aborted trace (see also -jv). +-- * b Dump the traced bytecode. +-- * i Dump the IR (intermediate representation). +-- r Augment the IR with register/stack slots. +-- s Dump the snapshot map. +-- * m Dump the generated machine code. +-- x Print each taken trace exit. +-- X Print each taken trace exit and the contents of all registers. +-- a Print the IR of aborted traces, too. +-- +-- The output format can be set with the following characters: +-- +-- T Plain text output. +-- A ANSI-colored text output +-- H Colorized HTML + CSS output. +-- +-- The default output format is plain text. It's set to ANSI-colored text +-- if the COLORTERM variable is set. Note: this is independent of any output +-- redirection, which is actually considered a feature. +-- +-- You probably want to use less -R to enjoy viewing ANSI-colored text from +-- a pipe or a file. Add this to your ~/.bashrc: export LESS="-R" +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc +local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek +local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap +local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr +local bit = require("bit") +local band, shr, tohex = bit.band, bit.rshift, bit.tohex +local sub, gsub, format = string.sub, string.gsub, string.format +local byte, rep = string.byte, string.rep +local type, tostring = type, tostring +local stdout, stderr = io.stdout, io.stderr + +-- Load other modules on-demand. +local bcline, disass + +-- Active flag, output file handle and dump mode. +local active, out, dumpmode + +------------------------------------------------------------------------------ + +local symtabmt = { __index = false } +local symtab = {} +local nexitsym = 0 + +-- Fill nested symbol table with per-trace exit stub addresses. +local function fillsymtab_tr(tr, nexit) + local t = {} + symtabmt.__index = t + if jit.arch:sub(1, 4) == "mips" then + t[traceexitstub(tr, 0)] = "exit" + return + end + for i=0,nexit-1 do + local addr = traceexitstub(tr, i) + if addr < 0 then addr = addr + 2^32 end + t[addr] = tostring(i) + end + local addr = traceexitstub(tr, nexit) + if addr then t[addr] = "stack_check" end +end + +-- Fill symbol table with trace exit stub addresses. +local function fillsymtab(tr, nexit) + local t = symtab + if nexitsym == 0 then + local maskaddr = jit.arch == "arm" and -2 + local ircall = vmdef.ircall + for i=0,#ircall do + local addr = ircalladdr(i) + if addr ~= 0 then + if maskaddr then addr = band(addr, maskaddr) end + if addr < 0 then addr = addr + 2^32 end + t[addr] = ircall[i] + end + end + end + if nexitsym == 1000000 then -- Per-trace exit stubs. + fillsymtab_tr(tr, nexit) + elseif nexit > nexitsym then -- Shared exit stubs. + for i=nexitsym,nexit-1 do + local addr = traceexitstub(i) + if addr == nil then -- Fall back to per-trace exit stubs. + fillsymtab_tr(tr, nexit) + setmetatable(symtab, symtabmt) + nexit = 1000000 + break + end + if addr < 0 then addr = addr + 2^32 end + t[addr] = tostring(i) + end + nexitsym = nexit + end + return t +end + +local function dumpwrite(s) + out:write(s) +end + +-- Disassemble machine code. +local function dump_mcode(tr) + local info = traceinfo(tr) + if not info then return end + local mcode, addr, loop = tracemc(tr) + if not mcode then return end + if not disass then disass = require("jit.dis_"..jit.arch) end + if addr < 0 then addr = addr + 2^32 end + out:write("---- TRACE ", tr, " mcode ", #mcode, "\n") + local ctx = disass.create(mcode, addr, dumpwrite) + ctx.hexdump = 0 + ctx.symtab = fillsymtab(tr, info.nexit) + if loop ~= 0 then + symtab[addr+loop] = "LOOP" + ctx:disass(0, loop) + out:write("->LOOP:\n") + ctx:disass(loop, #mcode-loop) + symtab[addr+loop] = nil + else + ctx:disass(0, #mcode) + end +end + +------------------------------------------------------------------------------ + +local irtype_text = { + [0] = "nil", + "fal", + "tru", + "lud", + "str", + "p32", + "thr", + "pro", + "fun", + "p64", + "cdt", + "tab", + "udt", + "flt", + "num", + "i8 ", + "u8 ", + "i16", + "u16", + "int", + "u32", + "i64", + "u64", + "sfp", +} + +local colortype_ansi = { + [0] = "%s", + "%s", + "%s", + "\027[36m%s\027[m", + "\027[32m%s\027[m", + "%s", + "\027[1m%s\027[m", + "%s", + "\027[1m%s\027[m", + "%s", + "\027[33m%s\027[m", + "\027[31m%s\027[m", + "\027[36m%s\027[m", + "\027[34m%s\027[m", + "\027[34m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", +} + +local function colorize_text(s) + return s +end + +local function colorize_ansi(s, t, extra) + local out = format(colortype_ansi[t], s) + if extra then out = "\027[3m"..out end + return out +end + +local irtype_ansi = setmetatable({}, + { __index = function(tab, t) + local s = colorize_ansi(irtype_text[t], t); tab[t] = s; return s; end }) + +local html_escape = { ["<"] = "<", [">"] = ">", ["&"] = "&", } + +local function colorize_html(s, t, extra) + s = gsub(s, "[<>&]", html_escape) + return format('%s', + irtype_text[t], extra and " irt_extra" or "", s) +end + +local irtype_html = setmetatable({}, + { __index = function(tab, t) + local s = colorize_html(irtype_text[t], t); tab[t] = s; return s; end }) + +local header_html = [[ + +]] + +local colorize, irtype + +-- Lookup tables to convert some literals into names. +local litname = { + ["SLOAD "] = setmetatable({}, { __index = function(t, mode) + local s = "" + if band(mode, 1) ~= 0 then s = s.."P" end + if band(mode, 2) ~= 0 then s = s.."F" end + if band(mode, 4) ~= 0 then s = s.."T" end + if band(mode, 8) ~= 0 then s = s.."C" end + if band(mode, 16) ~= 0 then s = s.."R" end + if band(mode, 32) ~= 0 then s = s.."I" end + if band(mode, 64) ~= 0 then s = s.."K" end + t[mode] = s + return s + end}), + ["XLOAD "] = { [0] = "", "R", "V", "RV", "U", "RU", "VU", "RVU", }, + ["CONV "] = setmetatable({}, { __index = function(t, mode) + local s = irtype[band(mode, 31)] + s = irtype[band(shr(mode, 5), 31)].."."..s + if band(mode, 0x800) ~= 0 then s = s.." sext" end + local c = shr(mode, 12) + if c == 1 then s = s.." none" + elseif c == 2 then s = s.." index" + elseif c == 3 then s = s.." check" end + t[mode] = s + return s + end}), + ["FLOAD "] = vmdef.irfield, + ["FREF "] = vmdef.irfield, + ["FPMATH"] = vmdef.irfpm, + ["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" }, + ["BUFHDR"] = { [0] = "RESET", "APPEND", "WRITE" }, + ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, +} + +local function ctlsub(c) + if c == "\n" then return "\\n" + elseif c == "\r" then return "\\r" + elseif c == "\t" then return "\\t" + else return format("\\%03d", byte(c)) + end +end + +local function fmtfunc(func, pc) + local fi = funcinfo(func, pc) + if fi.loc then + return fi.loc + elseif fi.ffid then + return vmdef.ffnames[fi.ffid] + elseif fi.addr then + return format("C:%x", fi.addr) + else + return "(?)" + end +end + +local function formatk(tr, idx, sn) + local k, t, slot = tracek(tr, idx) + local tn = type(k) + local s + if tn == "number" then + if t < 12 then + s = k == 0 and "NULL" or format("[0x%08x]", k) + elseif band(sn or 0, 0x30000) ~= 0 then + s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz" + elseif k == 2^52+2^51 then + s = "bias" + else + s = format(0 < k and k < 0x1p-1026 and "%+a" or "%+.14g", k) + end + elseif tn == "string" then + s = format(#k > 20 and '"%.20s"~' or '"%s"', gsub(k, "%c", ctlsub)) + elseif tn == "function" then + s = fmtfunc(k) + elseif tn == "table" then + s = format("{%p}", k) + elseif tn == "userdata" then + if t == 12 then + s = format("userdata:%p", k) + else + s = format("[%p]", k) + if s == "[NULL]" then s = "NULL" end + end + elseif t == 21 then -- int64_t + s = sub(tostring(k), 1, -3) + if sub(s, 1, 1) ~= "-" then s = "+"..s end + elseif sn == 0x1057fff then -- SNAP(1, SNAP_FRAME | SNAP_NORESTORE, REF_NIL) + return "----" -- Special case for LJ_FR2 slot 1. + else + s = tostring(k) -- For primitives. + end + s = colorize(format("%-4s", s), t, band(sn or 0, 0x100000) ~= 0) + if slot then + s = format("%s @%d", s, slot) + end + return s +end + +local function printsnap(tr, snap) + local n = 2 + for s=0,snap[1]-1 do + local sn = snap[n] + if shr(sn, 24) == s then + n = n + 1 + local ref = band(sn, 0xffff) - 0x8000 -- REF_BIAS + if ref < 0 then + out:write(formatk(tr, ref, sn)) + elseif band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM + out:write(colorize(format("%04d/%04d", ref, ref+1), 14)) + else + local m, ot, op1, op2 = traceir(tr, ref) + out:write(colorize(format("%04d", ref), band(ot, 31), band(sn, 0x100000) ~= 0)) + end + out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME + else + out:write("---- ") + end + end + out:write("]\n") +end + +-- Dump snapshots (not interleaved with IR). +local function dump_snap(tr) + out:write("---- TRACE ", tr, " snapshots\n") + for i=0,1000000000 do + local snap = tracesnap(tr, i) + if not snap then break end + out:write(format("#%-3d %04d [ ", i, snap[0])) + printsnap(tr, snap) + end +end + +-- Return a register name or stack slot for a rid/sp location. +local function ridsp_name(ridsp, ins) + if not disass then disass = require("jit.dis_"..jit.arch) end + local rid, slot = band(ridsp, 0xff), shr(ridsp, 8) + if rid == 253 or rid == 254 then + return (slot == 0 or slot == 255) and " {sink" or format(" {%04d", ins-slot) + end + if ridsp > 255 then return format("[%x]", slot*4) end + if rid < 128 then return disass.regname(rid) end + return "" +end + +-- Dump CALL* function ref and return optional ctype. +local function dumpcallfunc(tr, ins) + local ctype + if ins > 0 then + local m, ot, op1, op2 = traceir(tr, ins) + if band(ot, 31) == 0 then -- nil type means CARG(func, ctype). + ins = op1 + ctype = formatk(tr, op2) + end + end + if ins < 0 then + out:write(format("[0x%x](", tonumber((tracek(tr, ins))))) + else + out:write(format("%04d (", ins)) + end + return ctype +end + +-- Recursively gather CALL* args and dump them. +local function dumpcallargs(tr, ins) + if ins < 0 then + out:write(formatk(tr, ins)) + else + local m, ot, op1, op2 = traceir(tr, ins) + local oidx = 6*shr(ot, 8) + local op = sub(vmdef.irnames, oidx+1, oidx+6) + if op == "CARG " then + dumpcallargs(tr, op1) + if op2 < 0 then + out:write(" ", formatk(tr, op2)) + else + out:write(" ", format("%04d", op2)) + end + else + out:write(format("%04d", ins)) + end + end +end + +-- Dump IR and interleaved snapshots. +local function dump_ir(tr, dumpsnap, dumpreg) + local info = traceinfo(tr) + if not info then return end + local nins = info.nins + out:write("---- TRACE ", tr, " IR\n") + local irnames = vmdef.irnames + local snapref = 65536 + local snap, snapno + if dumpsnap then + snap = tracesnap(tr, 0) + snapref = snap[0] + snapno = 0 + end + for ins=1,nins do + if ins >= snapref then + if dumpreg then + out:write(format(".... SNAP #%-3d [ ", snapno)) + else + out:write(format(".... SNAP #%-3d [ ", snapno)) + end + printsnap(tr, snap) + snapno = snapno + 1 + snap = tracesnap(tr, snapno) + snapref = snap and snap[0] or 65536 + end + local m, ot, op1, op2, ridsp = traceir(tr, ins) + local oidx, t = 6*shr(ot, 8), band(ot, 31) + local op = sub(irnames, oidx+1, oidx+6) + if op == "LOOP " then + if dumpreg then + out:write(format("%04d ------------ LOOP ------------\n", ins)) + else + out:write(format("%04d ------ LOOP ------------\n", ins)) + end + elseif op ~= "NOP " and op ~= "CARG " and + (dumpreg or op ~= "RENAME") then + local rid = band(ridsp, 255) + if dumpreg then + out:write(format("%04d %-6s", ins, ridsp_name(ridsp, ins))) + else + out:write(format("%04d ", ins)) + end + out:write(format("%s%s %s %s ", + (rid == 254 or rid == 253) and "}" or + (band(ot, 128) == 0 and " " or ">"), + band(ot, 64) == 0 and " " or "+", + irtype[t], op)) + local m1, m2 = band(m, 3), band(m, 3*4) + if sub(op, 1, 4) == "CALL" then + local ctype + if m2 == 1*4 then -- op2 == IRMlit + out:write(format("%-10s (", vmdef.ircall[op2])) + else + ctype = dumpcallfunc(tr, op2) + end + if op1 ~= -1 then dumpcallargs(tr, op1) end + out:write(")") + if ctype then out:write(" ctype ", ctype) end + elseif op == "CNEW " and op2 == -1 then + out:write(formatk(tr, op1)) + elseif m1 ~= 3 then -- op1 != IRMnone + if op1 < 0 then + out:write(formatk(tr, op1)) + else + out:write(format(m1 == 0 and "%04d" or "#%-3d", op1)) + end + if m2 ~= 3*4 then -- op2 != IRMnone + if m2 == 1*4 then -- op2 == IRMlit + local litn = litname[op] + if litn and litn[op2] then + out:write(" ", litn[op2]) + elseif op == "UREFO " or op == "UREFC " then + out:write(format(" #%-3d", shr(op2, 8))) + else + out:write(format(" #%-3d", op2)) + end + elseif op2 < 0 then + out:write(" ", formatk(tr, op2)) + else + out:write(format(" %04d", op2)) + end + end + end + out:write("\n") + end + end + if snap then + if dumpreg then + out:write(format(".... SNAP #%-3d [ ", snapno)) + else + out:write(format(".... SNAP #%-3d [ ", snapno)) + end + printsnap(tr, snap) + end +end + +------------------------------------------------------------------------------ + +local recprefix = "" +local recdepth = 0 + +-- Format trace error message. +local function fmterr(err, info) + if type(err) == "number" then + if type(info) == "function" then info = fmtfunc(info) end + err = format(vmdef.traceerr[err], info) + end + return err +end + +-- Dump trace states. +local function dump_trace(what, tr, func, pc, otr, oex) + if what == "stop" or (what == "abort" and dumpmode.a) then + if dumpmode.i then dump_ir(tr, dumpmode.s, dumpmode.r and what == "stop") + elseif dumpmode.s then dump_snap(tr) end + if dumpmode.m then dump_mcode(tr) end + end + if what == "start" then + if dumpmode.H then out:write('
\n') end
+    out:write("---- TRACE ", tr, " ", what)
+    if otr then out:write(" ", otr, "/", oex == -1 and "stitch" or oex) end
+    out:write(" ", fmtfunc(func, pc), "\n")
+  elseif what == "stop" or what == "abort" then
+    out:write("---- TRACE ", tr, " ", what)
+    if what == "abort" then
+      out:write(" ", fmtfunc(func, pc), " -- ", fmterr(otr, oex), "\n")
+    else
+      local info = traceinfo(tr)
+      local link, ltype = info.link, info.linktype
+      if link == tr or link == 0 then
+	out:write(" -> ", ltype, "\n")
+      elseif ltype == "root" then
+	out:write(" -> ", link, "\n")
+      else
+	out:write(" -> ", link, " ", ltype, "\n")
+      end
+    end
+    if dumpmode.H then out:write("
\n\n") else out:write("\n") end + else + if what == "flush" then symtab, nexitsym = {}, 0 end + out:write("---- TRACE ", what, "\n\n") + end + out:flush() +end + +-- Dump recorded bytecode. +local function dump_record(tr, func, pc, depth) + if depth ~= recdepth then + recdepth = depth + recprefix = rep(" .", depth) + end + local line + if pc >= 0 then + line = bcline(func, pc, recprefix) + if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end + else + line = "0000 "..recprefix.." FUNCC \n" + end + if pc <= 0 then + out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n") + else + out:write(line) + end + if pc >= 0 and band(funcbc(func, pc), 0xff) < 16 then -- ORDER BC + out:write(bcline(func, pc+1, recprefix)) -- Write JMP for cond. + end +end + +------------------------------------------------------------------------------ + +local gpr64 = jit.arch:match("64") +local fprmips32 = jit.arch == "mips" or jit.arch == "mipsel" + +-- Dump taken trace exits. +local function dump_texit(tr, ex, ngpr, nfpr, ...) + out:write("---- TRACE ", tr, " exit ", ex, "\n") + if dumpmode.X then + local regs = {...} + if gpr64 then + for i=1,ngpr do + out:write(format(" %016x", regs[i])) + if i % 4 == 0 then out:write("\n") end + end + else + for i=1,ngpr do + out:write(" ", tohex(regs[i])) + if i % 8 == 0 then out:write("\n") end + end + end + if fprmips32 then + for i=1,nfpr,2 do + out:write(format(" %+17.14g", regs[ngpr+i])) + if i % 8 == 7 then out:write("\n") end + end + else + for i=1,nfpr do + out:write(format(" %+17.14g", regs[ngpr+i])) + if i % 4 == 0 then out:write("\n") end + end + end + end +end + +------------------------------------------------------------------------------ + +-- Detach dump handlers. +local function dumpoff() + if active then + active = false + jit.attach(dump_texit) + jit.attach(dump_record) + jit.attach(dump_trace) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handlers. +local function dumpon(opt, outfile) + if active then dumpoff() end + + local term = os.getenv("TERM") + local colormode = (term and term:match("color") or os.getenv("COLORTERM")) and "A" or "T" + if opt then + opt = gsub(opt, "[TAH]", function(mode) colormode = mode; return ""; end) + end + + local m = { t=true, b=true, i=true, m=true, } + if opt and opt ~= "" then + local o = sub(opt, 1, 1) + if o ~= "+" and o ~= "-" then m = {} end + for i=1,#opt do m[sub(opt, i, i)] = (o ~= "-") end + end + dumpmode = m + + if m.t or m.b or m.i or m.s or m.m then + jit.attach(dump_trace, "trace") + end + if m.b then + jit.attach(dump_record, "record") + if not bcline then bcline = require("jit.bc").line end + end + if m.x or m.X then + jit.attach(dump_texit, "texit") + end + + if not outfile then outfile = os.getenv("LUAJIT_DUMPFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stdout + end + + m[colormode] = true + if colormode == "A" then + colorize = colorize_ansi + irtype = irtype_ansi + elseif colormode == "H" then + colorize = colorize_html + irtype = irtype_html + out:write(header_html) + else + colorize = colorize_text + irtype = irtype_text + end + + active = true +end + +-- Public module functions. +return { + on = dumpon, + off = dumpoff, + start = dumpon -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/p.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/p.lua new file mode 100644 index 00000000..c9ec1d8b --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/p.lua @@ -0,0 +1,312 @@ +---------------------------------------------------------------------------- +-- LuaJIT profiler. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module is a simple command line interface to the built-in +-- low-overhead profiler of LuaJIT. +-- +-- The lower-level API of the profiler is accessible via the "jit.profile" +-- module or the luaJIT_profile_* C API. +-- +-- Example usage: +-- +-- luajit -jp myapp.lua +-- luajit -jp=s myapp.lua +-- luajit -jp=-s myapp.lua +-- luajit -jp=vl myapp.lua +-- luajit -jp=G,profile.txt myapp.lua +-- +-- The following dump features are available: +-- +-- f Stack dump: function name, otherwise module:line. Default mode. +-- F Stack dump: ditto, but always prepend module. +-- l Stack dump: module:line. +-- stack dump depth (callee < caller). Default: 1. +-- - Inverse stack dump depth (caller > callee). +-- s Split stack dump after first stack level. Implies abs(depth) >= 2. +-- p Show full path for module names. +-- v Show VM states. Can be combined with stack dumps, e.g. vf or fv. +-- z Show zones. Can be combined with stack dumps, e.g. zf or fz. +-- 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 (e.g. flame graphs). +-- m Minimum sample percentage to be shown. Default: 3. +-- i Sampling interval in milliseconds. Default: 10. +-- +---------------------------------------------------------------------------- + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local profile = require("jit.profile") +local vmdef = require("jit.vmdef") +local math = math +local pairs, ipairs, tonumber, floor = pairs, ipairs, tonumber, math.floor +local sort, format = table.sort, string.format +local stdout = io.stdout +local zone -- Load jit.zone module on demand. + +-- Output file handle. +local out + +------------------------------------------------------------------------------ + +local prof_ud +local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth +local prof_ann, prof_count1, prof_count2, prof_samples + +local map_vmmode = { + N = "Compiled", + I = "Interpreted", + C = "C code", + G = "Garbage Collector", + J = "JIT Compiler", +} + +-- Profiler callback. +local function prof_cb(th, samples, vmmode) + prof_samples = prof_samples + samples + local key_stack, key_stack2, key_state + -- Collect keys for sample. + if prof_states then + if prof_states == "v" then + key_state = map_vmmode[vmmode] or vmmode + else + key_state = zone:get() or "(none)" + end + end + if prof_fmt then + key_stack = profile.dumpstack(th, prof_fmt, prof_depth) + key_stack = key_stack:gsub("%[builtin#(%d+)%]", function(x) + return vmdef.ffnames[tonumber(x)] + end) + if prof_split == 2 then + local k1, k2 = key_stack:match("(.-) [<>] (.*)") + if k2 then key_stack, key_stack2 = k1, k2 end + elseif prof_split == 3 then + key_stack2 = profile.dumpstack(th, "l", 1) + end + end + -- Order keys. + local k1, k2 + if prof_split == 1 then + if key_state then + k1 = key_state + if key_stack then k2 = key_stack end + end + elseif key_stack then + k1 = key_stack + if key_stack2 then k2 = key_stack2 elseif key_state then k2 = key_state end + end + -- Coalesce samples in one or two levels. + if k1 then + local t1 = prof_count1 + t1[k1] = (t1[k1] or 0) + samples + if k2 then + local t2 = prof_count2 + local t3 = t2[k1] + if not t3 then t3 = {}; t2[k1] = t3 end + t3[k2] = (t3[k2] or 0) + samples + end + end +end + +------------------------------------------------------------------------------ + +-- Show top N list. +local function prof_top(count1, count2, samples, indent) + local t, n = {}, 0 + for k in pairs(count1) do + n = n + 1 + t[n] = k + end + sort(t, function(a, b) return count1[a] > count1[b] end) + for i=1,n do + local k = t[i] + local v = count1[k] + local pct = floor(v*100/samples + 0.5) + if pct < prof_min then break end + if not prof_raw then + out:write(format("%s%2d%% %s\n", indent, pct, k)) + elseif prof_raw == "r" then + out:write(format("%s%5d %s\n", indent, v, k)) + else + out:write(format("%s %d\n", k, v)) + end + if count2 then + local r = count2[k] + if r then + prof_top(r, nil, v, (prof_split == 3 or prof_split == 1) and " -- " or + (prof_depth < 0 and " -> " or " <- ")) + end + end + end +end + +-- Annotate source code +local function prof_annotate(count1, samples) + local files = {} + local ms = 0 + for k, v in pairs(count1) do + local pct = floor(v*100/samples + 0.5) + ms = math.max(ms, v) + if pct >= prof_min then + local file, line = k:match("^(.*):(%d+)$") + if not file then file = k; line = 0 end + local fl = files[file] + if not fl then fl = {}; files[file] = fl; files[#files+1] = file end + line = tonumber(line) + fl[line] = prof_raw and v or pct + end + end + sort(files) + local fmtv, fmtn = " %3d%% | %s\n", " | %s\n" + if prof_raw then + local n = math.max(5, math.ceil(math.log10(ms))) + fmtv = "%"..n.."d | %s\n" + fmtn = (" "):rep(n).." | %s\n" + end + local ann = prof_ann + for _, file in ipairs(files) do + local f0 = file:byte() + if f0 == 40 or f0 == 91 then + out:write(format("\n====== %s ======\n[Cannot annotate non-file]\n", file)) + break + end + local fp, err = io.open(file) + if not fp then + out:write(format("====== ERROR: %s: %s\n", file, err)) + break + end + out:write(format("\n====== %s ======\n", file)) + local fl = files[file] + local n, show = 1, false + if ann ~= 0 then + for i=1,ann do + if fl[i] then show = true; out:write("@@ 1 @@\n"); break end + end + end + for line in fp:lines() do + if line:byte() == 27 then + out:write("[Cannot annotate bytecode file]\n") + break + end + local v = fl[n] + if ann ~= 0 then + local v2 = fl[n+ann] + if show then + if v2 then show = n+ann elseif v then show = n + elseif show+ann < n then show = false end + elseif v2 then + show = n+ann + out:write(format("@@ %d @@\n", n)) + end + if not show then goto next end + end + if v then + out:write(format(fmtv, v, line)) + else + out:write(format(fmtn, line)) + end + ::next:: + n = n + 1 + end + fp:close() + end +end + +------------------------------------------------------------------------------ + +-- Finish profiling and dump result. +local function prof_finish() + if prof_ud then + profile.stop() + local samples = prof_samples + if samples == 0 then + if prof_raw ~= true then out:write("[No samples collected]\n") end + return + end + if prof_ann then + prof_annotate(prof_count1, samples) + else + prof_top(prof_count1, prof_count2, samples, "") + end + prof_count1 = nil + prof_count2 = nil + prof_ud = nil + if out ~= stdout then out:close() end + end +end + +-- Start profiling. +local function prof_start(mode) + local interval = "" + mode = mode:gsub("i%d*", function(s) interval = s; return "" end) + prof_min = 3 + mode = mode:gsub("m(%d+)", function(s) prof_min = tonumber(s); return "" end) + prof_depth = 1 + mode = mode:gsub("%-?%d+", function(s) prof_depth = tonumber(s); return "" end) + local m = {} + for c in mode:gmatch(".") do m[c] = c end + prof_states = m.z or m.v + if prof_states == "z" then zone = require("jit.zone") end + local scope = m.l or m.f or m.F or (prof_states and "" or "f") + local flags = (m.p or "") + prof_raw = m.r + if m.s then + prof_split = 2 + if prof_depth == -1 or m["-"] then prof_depth = -2 + elseif prof_depth == 1 then prof_depth = 2 end + elseif mode:find("[fF].*l") then + scope = "l" + prof_split = 3 + else + prof_split = (scope == "" or mode:find("[zv].*[lfF]")) and 1 or 0 + end + prof_ann = m.A and 0 or (m.a and 3) + if prof_ann then + scope = "l" + prof_fmt = "pl" + prof_split = 0 + prof_depth = 1 + elseif m.G and scope ~= "" then + prof_fmt = flags..scope.."Z;" + prof_depth = -100 + prof_raw = true + prof_min = 0 + elseif scope == "" then + prof_fmt = false + else + local sc = prof_split == 3 and m.f or m.F or scope + prof_fmt = flags..sc..(prof_depth >= 0 and "Z < " or "Z > ") + end + prof_count1 = {} + prof_count2 = {} + prof_samples = 0 + profile.start(scope:lower()..interval, prof_cb) + prof_ud = newproxy(true) + getmetatable(prof_ud).__gc = prof_finish +end + +------------------------------------------------------------------------------ + +local function start(mode, outfile) + if not outfile then outfile = os.getenv("LUAJIT_PROFILEFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stdout + end + prof_start(mode or "f") +end + +-- Public module functions. +return { + start = start, -- For -j command line option. + stop = prof_finish +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/v.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/v.lua new file mode 100644 index 00000000..83589143 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/v.lua @@ -0,0 +1,170 @@ +---------------------------------------------------------------------------- +-- Verbose mode of the LuaJIT compiler. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module shows verbose information about the progress of the +-- JIT compiler. It prints one line for each generated trace. This module +-- is useful to see which code has been compiled or where the compiler +-- punts and falls back to the interpreter. +-- +-- Example usage: +-- +-- luajit -jv -e "for i=1,1000 do for j=1,1000 do end end" +-- luajit -jv=myapp.out myapp.lua +-- +-- Default output is to stderr. To redirect the output to a file, pass a +-- filename as an argument (use '-' for stdout) or set the environment +-- variable LUAJIT_VERBOSEFILE. The file is overwritten every time the +-- module is started. +-- +-- The output from the first example should look like this: +-- +-- [TRACE 1 (command line):1 loop] +-- [TRACE 2 (1/3) (command line):1 -> 1] +-- +-- The first number in each line is the internal trace number. Next are +-- the file name ('(command line)') and the line number (':1') where the +-- trace has started. Side traces also show the parent trace number and +-- the exit number where they are attached to in parentheses ('(1/3)'). +-- An arrow at the end shows where the trace links to ('-> 1'), unless +-- it loops to itself. +-- +-- In this case the inner loop gets hot and is traced first, generating +-- a root trace. Then the last exit from the 1st trace gets hot, too, +-- and triggers generation of the 2nd trace. The side trace follows the +-- path along the outer loop and *around* the inner loop, back to its +-- start, and then links to the 1st trace. Yes, this may seem unusual, +-- if you know how traditional compilers work. Trace compilers are full +-- of surprises like this -- have fun! :-) +-- +-- Aborted traces are shown like this: +-- +-- [TRACE --- foo.lua:44 -- leaving loop in root trace at foo:lua:50] +-- +-- Don't worry -- trace aborts are quite common, even in programs which +-- can be fully compiled. The compiler may retry several times until it +-- finds a suitable trace. +-- +-- Of course this doesn't work with features that are not-yet-implemented +-- (NYI error messages). The VM simply falls back to the interpreter. This +-- may not matter at all if the particular trace is not very high up in +-- the CPU usage profile. Oh, and the interpreter is quite fast, too. +-- +-- Also check out the -jdump module, which prints all the gory details. +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo +local type, format = type, string.format +local stdout, stderr = io.stdout, io.stderr + +-- Active flag and output file handle. +local active, out + +------------------------------------------------------------------------------ + +local startloc, startex + +local function fmtfunc(func, pc) + local fi = funcinfo(func, pc) + if fi.loc then + return fi.loc + elseif fi.ffid then + return vmdef.ffnames[fi.ffid] + elseif fi.addr then + return format("C:%x", fi.addr) + else + return "(?)" + end +end + +-- Format trace error message. +local function fmterr(err, info) + if type(err) == "number" then + if type(info) == "function" then info = fmtfunc(info) end + err = format(vmdef.traceerr[err], info) + end + return err +end + +-- Dump trace states. +local function dump_trace(what, tr, func, pc, otr, oex) + if what == "start" then + startloc = fmtfunc(func, pc) + startex = otr and "("..otr.."/"..(oex == -1 and "stitch" or oex)..") " or "" + else + if what == "abort" then + local loc = fmtfunc(func, pc) + if loc ~= startloc then + out:write(format("[TRACE --- %s%s -- %s at %s]\n", + startex, startloc, fmterr(otr, oex), loc)) + else + out:write(format("[TRACE --- %s%s -- %s]\n", + startex, startloc, fmterr(otr, oex))) + end + elseif what == "stop" then + local info = traceinfo(tr) + local link, ltype = info.link, info.linktype + if ltype == "interpreter" then + out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n", + tr, startex, startloc)) + elseif ltype == "stitch" then + out:write(format("[TRACE %3s %s%s %s %s]\n", + tr, startex, startloc, ltype, fmtfunc(func, pc))) + elseif link == tr or link == 0 then + out:write(format("[TRACE %3s %s%s %s]\n", + tr, startex, startloc, ltype)) + elseif ltype == "root" then + out:write(format("[TRACE %3s %s%s -> %d]\n", + tr, startex, startloc, link)) + else + out:write(format("[TRACE %3s %s%s -> %d %s]\n", + tr, startex, startloc, link, ltype)) + end + else + out:write(format("[TRACE %s]\n", what)) + end + out:flush() + end +end + +------------------------------------------------------------------------------ + +-- Detach dump handlers. +local function dumpoff() + if active then + active = false + jit.attach(dump_trace) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handlers. +local function dumpon(outfile) + if active then dumpoff() end + if not outfile then outfile = os.getenv("LUAJIT_VERBOSEFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stderr + end + jit.attach(dump_trace, "trace") + active = true +end + +-- Public module functions. +return { + on = dumpon, + off = dumpoff, + start = dumpon -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/vmdef.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/vmdef.lua new file mode 100644 index 00000000..68ff7ba2 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/vmdef.lua @@ -0,0 +1,395 @@ +-- This is a generated file. DO NOT EDIT! + +return { + +bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF ISTYPEISNUM MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TGETR TSETV TSETS TSETB TSETM TSETR CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW", + +irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEPROF KPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF TMPREFSTRREFLREF ALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ALEN ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI BUFHDRBUFPUTBUFSTRTBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLA CALLL CALLS CALLXSCARG ", + +irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "log", "log2", "other", }, + +irfield = { [0]="str.len", "func.env", "func.pc", "func.ffid", "thread.env", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "sbuf.w", "sbuf.e", "sbuf.b", "sbuf.l", "sbuf.ref", "sbuf.r", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", }, + +ircall = { +[0]="lj_str_cmp", +"lj_str_find", +"lj_str_new", +"lj_strscan_num", +"lj_strfmt_int", +"lj_strfmt_num", +"lj_strfmt_char", +"lj_strfmt_putint", +"lj_strfmt_putnum", +"lj_strfmt_putquoted", +"lj_strfmt_putfxint", +"lj_strfmt_putfnum_int", +"lj_strfmt_putfnum_uint", +"lj_strfmt_putfnum", +"lj_strfmt_putfstr", +"lj_strfmt_putfchar", +"lj_buf_putmem", +"lj_buf_putstr", +"lj_buf_putchar", +"lj_buf_putstr_reverse", +"lj_buf_putstr_lower", +"lj_buf_putstr_upper", +"lj_buf_putstr_rep", +"lj_buf_puttab", +"lj_bufx_set", +"lj_bufx_more", +"lj_serialize_put", +"lj_serialize_get", +"lj_serialize_encode", +"lj_serialize_decode", +"lj_buf_tostr", +"lj_tab_new_ah", +"lj_tab_new1", +"lj_tab_dup", +"lj_tab_clear", +"lj_tab_newkey", +"lj_tab_keyindex", +"lj_vm_next", +"lj_tab_len", +"lj_tab_len_hint", +"lj_gc_step_jit", +"lj_gc_barrieruv", +"lj_mem_newgco", +"lj_prng_u64d", +"lj_vm_modi", +"log10", +"exp", +"sin", +"cos", +"tan", +"asin", +"acos", +"atan", +"sinh", +"cosh", +"tanh", +"fputc", +"fwrite", +"fflush", +"lj_vm_floor", +"lj_vm_ceil", +"lj_vm_trunc", +"sqrt", +"log", +"lj_vm_log2", +"lj_vm_powi", +"pow", +"atan2", +"ldexp", +"lj_vm_tobit", +"softfp_add", +"softfp_sub", +"softfp_mul", +"softfp_div", +"softfp_cmp", +"softfp_i2d", +"softfp_d2i", +"lj_vm_sfmin", +"lj_vm_sfmax", +"lj_vm_tointg", +"softfp_ui2d", +"softfp_f2d", +"softfp_d2ui", +"softfp_d2f", +"softfp_i2f", +"softfp_ui2f", +"softfp_f2i", +"softfp_f2ui", +"fp64_l2d", +"fp64_ul2d", +"fp64_l2f", +"fp64_ul2f", +"fp64_d2l", +"fp64_d2ul", +"fp64_f2l", +"fp64_f2ul", +"lj_carith_divi64", +"lj_carith_divu64", +"lj_carith_modi64", +"lj_carith_modu64", +"lj_carith_powi64", +"lj_carith_powu64", +"lj_cdata_newv", +"lj_cdata_setfin", +"strlen", +"memcpy", +"memset", +"lj_vm_errno", +"lj_carith_mul64", +"lj_carith_shl64", +"lj_carith_shr64", +"lj_carith_sar64", +"lj_carith_rol64", +"lj_carith_ror64", +}, + +traceerr = { +[0]="error thrown or hook called during recording", +"trace too short", +"trace too long", +"trace too deep", +"too many snapshots", +"blacklisted", +"retry recording", +"NYI: bytecode %d", +"leaving loop in root trace", +"inner loop in root trace", +"loop unroll limit reached", +"bad argument type", +"JIT compilation disabled for function", +"call unroll limit reached", +"down-recursion, restarting", +"NYI: unsupported variant of FastFunc %s", +"NYI: return to lower frame", +"store with nil or NaN key", +"missing metamethod", +"looping index lookup", +"NYI: mixed sparse/dense table", +"symbol not in cache", +"NYI: unsupported C type conversion", +"NYI: unsupported C function type", +"guard would always fail", +"too many PHIs", +"persistent type instability", +"failed to allocate mcode memory", +"machine code too long", +"hit mcode limit (retrying)", +"too many spill slots", +"inconsistent register allocation", +"NYI: cannot assemble IR instruction %d", +"NYI: PHI shuffling too complex", +"NYI: register coalescing too complex", +}, + +ffnames = { +[0]="Lua", +"C", +"assert", +"type", +"next", +"pairs", +"ipairs_aux", +"ipairs", +"getmetatable", +"setmetatable", +"getfenv", +"setfenv", +"rawget", +"rawset", +"rawequal", +"unpack", +"select", +"tonumber", +"tostring", +"error", +"pcall", +"xpcall", +"loadfile", +"load", +"loadstring", +"dofile", +"gcinfo", +"collectgarbage", +"newproxy", +"print", +"coroutine.status", +"coroutine.running", +"coroutine.isyieldable", +"coroutine.create", +"coroutine.yield", +"coroutine.resume", +"coroutine.wrap_aux", +"coroutine.wrap", +"math.abs", +"math.floor", +"math.ceil", +"math.sqrt", +"math.log10", +"math.exp", +"math.sin", +"math.cos", +"math.tan", +"math.asin", +"math.acos", +"math.atan", +"math.sinh", +"math.cosh", +"math.tanh", +"math.frexp", +"math.modf", +"math.log", +"math.atan2", +"math.pow", +"math.fmod", +"math.ldexp", +"math.min", +"math.max", +"math.random", +"math.randomseed", +"bit.tobit", +"bit.bnot", +"bit.bswap", +"bit.lshift", +"bit.rshift", +"bit.arshift", +"bit.rol", +"bit.ror", +"bit.band", +"bit.bor", +"bit.bxor", +"bit.tohex", +"string.byte", +"string.char", +"string.sub", +"string.rep", +"string.reverse", +"string.lower", +"string.upper", +"string.dump", +"string.find", +"string.match", +"string.gmatch_aux", +"string.gmatch", +"string.gsub", +"string.format", +"table.maxn", +"table.insert", +"table.concat", +"table.sort", +"table.new", +"table.clear", +"io.method.close", +"io.method.read", +"io.method.write", +"io.method.flush", +"io.method.seek", +"io.method.setvbuf", +"io.method.lines", +"io.method.__gc", +"io.method.__tostring", +"io.open", +"io.popen", +"io.tmpfile", +"io.close", +"io.read", +"io.write", +"io.flush", +"io.input", +"io.output", +"io.lines", +"io.type", +"os.execute", +"os.remove", +"os.rename", +"os.tmpname", +"os.getenv", +"os.exit", +"os.clock", +"os.date", +"os.time", +"os.difftime", +"os.setlocale", +"debug.getregistry", +"debug.getmetatable", +"debug.setmetatable", +"debug.getfenv", +"debug.setfenv", +"debug.getinfo", +"debug.getlocal", +"debug.setlocal", +"debug.getupvalue", +"debug.setupvalue", +"debug.upvalueid", +"debug.upvaluejoin", +"debug.sethook", +"debug.gethook", +"debug.debug", +"debug.traceback", +"jit.on", +"jit.off", +"jit.flush", +"jit.status", +"jit.security", +"jit.attach", +"jit.util.funcinfo", +"jit.util.funcbc", +"jit.util.funck", +"jit.util.funcuvname", +"jit.util.traceinfo", +"jit.util.traceir", +"jit.util.tracek", +"jit.util.tracesnap", +"jit.util.tracemc", +"jit.util.traceexitstub", +"jit.util.ircalladdr", +"jit.opt.start", +"jit.profile.start", +"jit.profile.stop", +"jit.profile.dumpstack", +"ffi.meta.__index", +"ffi.meta.__newindex", +"ffi.meta.__eq", +"ffi.meta.__len", +"ffi.meta.__lt", +"ffi.meta.__le", +"ffi.meta.__concat", +"ffi.meta.__call", +"ffi.meta.__add", +"ffi.meta.__sub", +"ffi.meta.__mul", +"ffi.meta.__div", +"ffi.meta.__mod", +"ffi.meta.__pow", +"ffi.meta.__unm", +"ffi.meta.__tostring", +"ffi.meta.__pairs", +"ffi.meta.__ipairs", +"ffi.clib.__index", +"ffi.clib.__newindex", +"ffi.clib.__gc", +"ffi.callback.free", +"ffi.callback.set", +"ffi.cdef", +"ffi.new", +"ffi.cast", +"ffi.typeof", +"ffi.typeinfo", +"ffi.istype", +"ffi.sizeof", +"ffi.alignof", +"ffi.offsetof", +"ffi.errno", +"ffi.string", +"ffi.copy", +"ffi.fill", +"ffi.abi", +"ffi.metatype", +"ffi.gc", +"ffi.load", +"buffer.method.free", +"buffer.method.reset", +"buffer.method.skip", +"buffer.method.set", +"buffer.method.put", +"buffer.method.putf", +"buffer.method.get", +"buffer.method.putcdata", +"buffer.method.reserve", +"buffer.method.commit", +"buffer.method.ref", +"buffer.method.encode", +"buffer.method.decode", +"buffer.method.__gc", +"buffer.method.__tostring", +"buffer.method.__len", +"buffer.new", +"buffer.encode", +"buffer.decode", +}, + +} + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/zone.lua b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/zone.lua new file mode 100644 index 00000000..94357854 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/jit/zone.lua @@ -0,0 +1,45 @@ +---------------------------------------------------------------------------- +-- LuaJIT profiler zones. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module implements a simple hierarchical zone model. +-- +-- Example usage: +-- +-- local zone = require("jit.zone") +-- zone("AI") +-- ... +-- zone("A*") +-- ... +-- print(zone:get()) --> "A*" +-- ... +-- zone() +-- ... +-- print(zone:get()) --> "AI" +-- ... +-- zone() +-- +---------------------------------------------------------------------------- + +local remove = table.remove + +return setmetatable({ + flush = function(t) + for i=#t,1,-1 do t[i] = nil end + end, + get = function(t) + return t[#t] + end +}, { + __call = function(t, zone) + if zone then + t[#t+1] = zone + else + return (assert(remove(t), "empty zone stack")) + end + end +}) + diff --git a/love/src/jni/LuaJIT-2.1/android/arm64-v8a/libluajit.a b/love/src/jni/LuaJIT-2.1/android/arm64-v8a/libluajit.a index 87646f436ac27ca2e6ca87824cf3ae47754e6b0d..d9dd4fef411cc2a3b7c20a05d5f3e202383d1a44 100644 GIT binary patch delta 257927 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�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≤cUitm zE?tIVP@k$vF2&a%(d8(2#p_b(&4JR8BU9eQ1SbY-w0t8JHBP6=llC_bfTRjpBp7@; z6wLpLGyiEYU!v<&XPlMaDk>aTtMIZ5)3k+VdqWAHJ1JkvHpNJd8d4XW zpVR@@J^7yOt#~WRN`rp6nf4!AEP~&d+HJ6@NMk&%|JL6ZNe4?y0&0%L};qa)jrq4{DyRA~<@b`1KA56=YgP44yUt+_= zhF>Xruv;of9%mkB?kAhY{R2FGBY!71H@7l(GKH95GnvdC%w6@LkMgT2+LX}nD^r3w zq2VEUkDSo(J=43U5GA2uoKlXzpSw*n;cGgRGNwq3}p=J#Gqg4tH*V51loTraOJ&R6Y

yIeK7P-c#;Pi2 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 z zrv5PW2OO6KQqg~6`3+_YqCLRJz!`v!#vRv6(9cA`>8I`!NrzOwG4?Ox-v|N6*aY(V zdEns&lKn|@6!Ls02}Pm!ZD`uKMvO^-xfCccwu$uCLYL3_#u;=>Hu7dIEj&x^E=@rzHVtw*KlN&;Ss` z(#mfq20BT5MXs$1oRgHidn(b_3N<2u9&jc=J~V}Q%IOejfDr^}d^~ZaHx>%xurepW z)sg4J(}}(YuB|kK5pV`3FZ&

-j%+ghNF+1nB_ajWmFMul>n5Y6|qpi=Ie2r2b2x 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

!4A{%PPVE}x~@GQ9Z z*M58J%Q#WwIE{wKzr?&X;C%jn;>&Dk4-C94zrs9X`0lSVj~agP3FcjfM;4gJ4395h zBM>)+G#vU2kKiVZgyF5<-~>s-OW-NPyB1kLlre@h3~9rs!AA|>1RpoN|C^j3Yxo#= z4!nN;KL^9KaTxg)2bwi}uFSk(c=k!=MZuupxFbdvic$Im^Yc+-*|GcO>Eob;LP6kE{ui>0b)bMVckL@zN3?B2j z8-H1T>C3r-xN+#kt>%4(XK^Q4!tkyuIZo2>HSm$lUpTyI^3x*%MmJ28vK93tiOKqIL zJ_Ms_b|@Q%3H%!9vf&XtVs^#w-S}C8HN&Ux=J=I5clDp^x_b9V*ifw-n74nFdCl;y zk1^jeeE5Fm9v+<_bE^Q}Xm}*^adv1mh8CRuYBzjqiuDo04?fB~YIy&*n0Fbzw#+;e zGlt|dY=|441Mf53TVZ{|@KNxj;fH>}`V{kE{~!Ay8-|QS+q2Bmh8I_vj~d?oW9H+A zH>@$wDt;cl|2&9C6y!n%uYO{3+VF>=pEVpK<`oS8BJ@SWi^OUDm5f2o-Ifi~%pwECu6sP6dh{s_>4NqLo*9p4}-vo~tK71v<3K=(sjdydPKEoq> zm?sP$PBBj!zHu${l;K;0%!e|@ki3x%X~Q?(!+g~6L41{Z-0+5B)@Kdx!B?qs;PvzW z|AOoG)5?M7gxp{-Yxwt}FBtwq@S@>A122X7rQYvgD2EN+pTU<6m&vta_|Anl{-35> zw=aDA7fly!%QyeB={Nafs!caGTtB?`y8KYJ>CAn%|3lltSF25*-?rn%8;A1u{<`U{ z3orgn)1})N?)Yufb=ww>|IenD?fG~AzUk!r-0z!q@B3Enr2N~TZ~EH8OaIU`vwh*f zADjAjEL`>9P3Jc(JoV?M(|7FL`<|hZ+XnaSz4@zuYQAJ!{_WeFU!MQ+_U6fj#E#~N zk6AdXxw-A={40-d9$HvAzWKG=ciw*M-jN$_-E-Y-3s<%^U$rg&?1{}kUHJ7$&5hfS z+55gdH|`z2A^)59=BaN&S}ke=YMfp z^T=`U8y<9VZcN`cvgg`#`i6zKo!)%gj{Mht*>r5a_Oj-8EL?X+^QX2g92;$Z)wcYt zuV_BM>ALH0c(03d$>ncd_|+?#6WbRq+0}ggwtdBGjy`Jc0?*sA@3YsO&{SC9o4x+A zH~-A5n@`#Hjr?z4-F)hffv1njA9rT+OLshRw3pxZ(9RQ^3b;WxS;=31X7efAzZ=ir zd}i}WP1E>3+{pR)`-xw8Vg9kM=972saag z?BDWYw730kE-d%j{N-KEryO;PJE`56Kl`j^SMxdSljfY;YZr0b3g_g%+vVE!diOV_ zT!wBUf9%=Kr*3P=zxwRvlbiax+4~7E|IAq~@DE?+_LJ0?JGQ^3(fxa3e*M+Wtqt?8 hi}SZUvh##jc#W@NkJ+2BPj>(G&>@Zg^xE<7{|6OZcTfNT diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/bc.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/bc.lua new file mode 100644 index 00000000..e58a3fef --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/bc.lua @@ -0,0 +1,190 @@ +---------------------------------------------------------------------------- +-- LuaJIT bytecode listing module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module lists the bytecode of a Lua function. If it's loaded by -jbc +-- it hooks into the parser and lists all functions of a chunk as they +-- are parsed. +-- +-- Example usage: +-- +-- luajit -jbc -e 'local x=0; for i=1,1e6 do x=x+i end; print(x)' +-- luajit -jbc=- foo.lua +-- luajit -jbc=foo.list foo.lua +-- +-- Default output is to stderr. To redirect the output to a file, pass a +-- filename as an argument (use '-' for stdout) or set the environment +-- variable LUAJIT_LISTFILE. The file is overwritten every time the module +-- is started. +-- +-- This module can also be used programmatically: +-- +-- local bc = require("jit.bc") +-- +-- local function foo() print("hello") end +-- +-- bc.dump(foo) --> -- BYTECODE -- [...] +-- print(bc.line(foo, 2)) --> 0002 KSTR 1 1 ; "hello" +-- +-- local out = { +-- -- Do something with each line: +-- write = function(t, ...) io.write(...) end, +-- close = function(t) end, +-- flush = function(t) end, +-- } +-- bc.dump(foo, out) +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local bit = require("bit") +local sub, gsub, format = string.sub, string.gsub, string.format +local byte, band, shr = string.byte, bit.band, bit.rshift +local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck +local funcuvname = jutil.funcuvname +local bcnames = vmdef.bcnames +local stdout, stderr = io.stdout, io.stderr + +------------------------------------------------------------------------------ + +local function ctlsub(c) + if c == "\n" then return "\\n" + elseif c == "\r" then return "\\r" + elseif c == "\t" then return "\\t" + else return format("\\%03d", byte(c)) + end +end + +-- Return one bytecode line. +local function bcline(func, pc, prefix) + local ins, m = funcbc(func, pc) + if not ins then return end + local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128) + local a = band(shr(ins, 8), 0xff) + local oidx = 6*band(ins, 0xff) + local op = sub(bcnames, oidx+1, oidx+6) + local s = format("%04d %s %-6s %3s ", + pc, prefix or " ", op, ma == 0 and "" or a) + local d = shr(ins, 16) + if mc == 13*128 then -- BCMjump + return format("%s=> %04d\n", s, pc+d-0x7fff) + end + if mb ~= 0 then + d = band(d, 0xff) + elseif mc == 0 then + return s.."\n" + end + local kc + if mc == 10*128 then -- BCMstr + kc = funck(func, -d-1) + kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub)) + elseif mc == 9*128 then -- BCMnum + kc = funck(func, d) + if op == "TSETM " then kc = kc - 2^52 end + elseif mc == 12*128 then -- BCMfunc + local fi = funcinfo(funck(func, -d-1)) + if fi.ffid then + kc = vmdef.ffnames[fi.ffid] + else + kc = fi.loc + end + elseif mc == 5*128 then -- BCMuv + kc = funcuvname(func, d) + end + if ma == 5 then -- BCMuv + local ka = funcuvname(func, a) + if kc then kc = ka.." ; "..kc else kc = ka end + end + if mb ~= 0 then + local b = shr(ins, 24) + if kc then return format("%s%3d %3d ; %s\n", s, b, d, kc) end + return format("%s%3d %3d\n", s, b, d) + end + if kc then return format("%s%3d ; %s\n", s, d, kc) end + if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits + return format("%s%3d\n", s, d) +end + +-- Collect branch targets of a function. +local function bctargets(func) + local target = {} + for pc=1,1000000000 do + local ins, m = funcbc(func, pc) + if not ins then break end + if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end + end + return target +end + +-- Dump bytecode instructions of a function. +local function bcdump(func, out, all) + if not out then out = stdout end + local fi = funcinfo(func) + if all and fi.children then + for n=-1,-1000000000,-1 do + local k = funck(func, n) + if not k then break end + if type(k) == "proto" then bcdump(k, out, true) end + end + end + out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined)) + local target = bctargets(func) + for pc=1,1000000000 do + local s = bcline(func, pc, target[pc] and "=>") + if not s then break end + out:write(s) + end + out:write("\n") + out:flush() +end + +------------------------------------------------------------------------------ + +-- Active flag and output file handle. +local active, out + +-- List handler. +local function h_list(func) + return bcdump(func, out) +end + +-- Detach list handler. +local function bclistoff() + if active then + active = false + jit.attach(h_list) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach list handler. +local function bcliston(outfile) + if active then bclistoff() end + if not outfile then outfile = os.getenv("LUAJIT_LISTFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stderr + end + jit.attach(h_list, "bc") + active = true +end + +-- Public module functions. +return { + line = bcline, + dump = bcdump, + targets = bctargets, + on = bcliston, + off = bclistoff, + start = bcliston -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/bcsave.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/bcsave.lua new file mode 100644 index 00000000..ab13667a --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/bcsave.lua @@ -0,0 +1,665 @@ +---------------------------------------------------------------------------- +-- LuaJIT module to save/list bytecode. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module saves or lists the bytecode for an input file. +-- It's run by the -b command line option. +-- +------------------------------------------------------------------------------ + +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local bit = require("bit") + +-- Symbol name prefix for LuaJIT bytecode. +local LJBC_PREFIX = "luaJIT_BC_" + +local type, assert = type, assert +local format = string.format +local tremove, tconcat = table.remove, table.concat + +------------------------------------------------------------------------------ + +local function usage() + io.stderr:write[[ +Save LuaJIT bytecode: luajit -b[options] input output + -l Only list bytecode. + -s Strip debug info (default). + -g Keep debug info. + -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). + -e chunk Use chunk string as input. + -- Stop handling options. + - Use stdin as input and/or stdout as output. + +File types: c h obj o raw (default) +]] + os.exit(1) +end + +local function check(ok, ...) + if ok then return ok, ... end + io.stderr:write("luajit: ", ...) + io.stderr:write("\n") + os.exit(1) +end + +local function readfile(input) + if type(input) == "function" then return input end + if input == "-" then input = nil end + return check(loadfile(input)) +end + +local function savefile(name, mode) + if name == "-" then return io.stdout end + return check(io.open(name, mode)) +end + +------------------------------------------------------------------------------ + +local map_type = { + raw = "raw", c = "c", h = "h", o = "obj", obj = "obj", +} + +local map_arch = { + x86 = { e = "le", b = 32, m = 3, p = 0x14c, }, + x64 = { e = "le", b = 64, m = 62, p = 0x8664, }, + arm = { e = "le", b = 32, m = 40, p = 0x1c0, }, + arm64 = { e = "le", b = 64, m = 183, p = 0xaa64, }, + arm64be = { e = "be", b = 64, m = 183, }, + ppc = { e = "be", b = 32, m = 20, }, + mips = { e = "be", b = 32, m = 8, f = 0x50001006, }, + mipsel = { e = "le", b = 32, m = 8, f = 0x50001006, }, + mips64 = { e = "be", b = 64, m = 8, f = 0x80000007, }, + mips64el = { e = "le", b = 64, m = 8, f = 0x80000007, }, + mips64r6 = { e = "be", b = 64, m = 8, f = 0xa0000407, }, + mips64r6el = { e = "le", b = 64, m = 8, f = 0xa0000407, }, +} + +local map_os = { + linux = true, windows = true, osx = true, freebsd = true, netbsd = true, + openbsd = true, dragonfly = true, solaris = true, +} + +local function checkarg(str, map, err) + str = str:lower() + local s = check(map[str], "unknown ", err) + return type(s) == "string" and s or str +end + +local function detecttype(str) + local ext = str:lower():match("%.(%a+)$") + return map_type[ext] or "raw" +end + +local function checkmodname(str) + check(str:match("^[%w_.%-]+$"), "bad module name") + return str:gsub("[%.%-]", "_") +end + +local function detectmodname(str) + if type(str) == "string" then + local tail = str:match("[^/\\]+$") + if tail then str = tail end + local head = str:match("^(.*)%.[^.]*$") + if head then str = head end + str = str:match("^[%w_.%-]+") + else + str = nil + end + check(str, "cannot derive module name, use -n name") + return str:gsub("[%.%-]", "_") +end + +------------------------------------------------------------------------------ + +local function bcsave_tail(fp, output, s) + local ok, err = fp:write(s) + if ok and output ~= "-" then ok, err = fp:close() end + check(ok, "cannot write ", output, ": ", err) +end + +local function bcsave_raw(output, s) + local fp = savefile(output, "wb") + bcsave_tail(fp, output, s) +end + +local function bcsave_c(ctx, output, s) + local fp = savefile(output, "w") + if ctx.type == "c" then + fp:write(format([[ +#ifdef __cplusplus +extern "C" +#endif +#ifdef _WIN32 +__declspec(dllexport) +#endif +const unsigned char %s%s[] = { +]], LJBC_PREFIX, ctx.modname)) + else + fp:write(format([[ +#define %s%s_SIZE %d +static const unsigned char %s%s[] = { +]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname)) + end + local t, n, m = {}, 0, 0 + for i=1,#s do + local b = tostring(string.byte(s, i)) + m = m + #b + 1 + if m > 78 then + fp:write(tconcat(t, ",", 1, n), ",\n") + n, m = 0, #b + 1 + end + n = n + 1 + t[n] = b + end + bcsave_tail(fp, output, tconcat(t, ",", 1, n).."\n};\n") +end + +local function bcsave_elfobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct { + uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; + uint16_t type, machine; + uint32_t version; + uint32_t entry, phofs, shofs; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; +} ELF32header; +typedef struct { + uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; + uint16_t type, machine; + uint32_t version; + uint64_t entry, phofs, shofs; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; +} ELF64header; +typedef struct { + uint32_t name, type, flags, addr, ofs, size, link, info, align, entsize; +} ELF32sectheader; +typedef struct { + uint32_t name, type; + uint64_t flags, addr, ofs, size; + uint32_t link, info; + uint64_t align, entsize; +} ELF64sectheader; +typedef struct { + uint32_t name, value, size; + uint8_t info, other; + uint16_t sectidx; +} ELF32symbol; +typedef struct { + uint32_t name; + uint8_t info, other; + uint16_t sectidx; + uint64_t value, size; +} ELF64symbol; +typedef struct { + ELF32header hdr; + ELF32sectheader sect[6]; + ELF32symbol sym[2]; + uint8_t space[4096]; +} ELF32obj; +typedef struct { + ELF64header hdr; + ELF64sectheader sect[6]; + ELF64symbol sym[2]; + uint8_t space[4096]; +} ELF64obj; +]] + local symname = LJBC_PREFIX..ctx.modname + local ai = assert(map_arch[ctx.arch]) + local is64, isbe = ai.b == 64, ai.e == "be" + + -- Handle different host/target endianess. + local function f32(x) return x end + local f16, fofs = f32, f32 + if ffi.abi("be") ~= isbe then + f32 = bit.bswap + function f16(x) return bit.rshift(bit.bswap(x), 16) end + if is64 then + local two32 = ffi.cast("int64_t", 2^32) + function fofs(x) return bit.bswap(x)*two32 end + else + fofs = f32 + end + end + + -- Create ELF object and fill in header. + local o = ffi.new(is64 and "ELF64obj" or "ELF32obj") + local hdr = o.hdr + if ctx.os == "bsd" or ctx.os == "other" then -- Determine native hdr.eosabi. + local bf = assert(io.open("/bin/ls", "rb")) + local bs = bf:read(9) + bf:close() + ffi.copy(o, bs, 9) + check(hdr.emagic[0] == 127, "no support for writing native object files") + else + hdr.emagic = "\127ELF" + hdr.eosabi = ({ freebsd=9, netbsd=2, openbsd=12, solaris=6 })[ctx.os] or 0 + end + hdr.eclass = is64 and 2 or 1 + hdr.eendian = isbe and 2 or 1 + hdr.eversion = 1 + hdr.type = f16(1) + hdr.machine = f16(ai.m) + hdr.flags = f32(ai.f or 0) + hdr.version = f32(1) + hdr.shofs = fofs(ffi.offsetof(o, "sect")) + hdr.ehsize = f16(ffi.sizeof(hdr)) + hdr.shentsize = f16(ffi.sizeof(o.sect[0])) + hdr.shnum = f16(6) + hdr.shstridx = f16(2) + + -- Fill in sections and symbols. + local sofs, ofs = ffi.offsetof(o, "space"), 1 + for i,name in ipairs{ + ".symtab", ".shstrtab", ".strtab", ".rodata", ".note.GNU-stack", + } do + local sect = o.sect[i] + sect.align = fofs(1) + sect.name = f32(ofs) + ffi.copy(o.space+ofs, name) + ofs = ofs + #name+1 + end + o.sect[1].type = f32(2) -- .symtab + o.sect[1].link = f32(3) + o.sect[1].info = f32(1) + o.sect[1].align = fofs(8) + o.sect[1].ofs = fofs(ffi.offsetof(o, "sym")) + o.sect[1].entsize = fofs(ffi.sizeof(o.sym[0])) + o.sect[1].size = fofs(ffi.sizeof(o.sym)) + o.sym[1].name = f32(1) + o.sym[1].sectidx = f16(4) + o.sym[1].size = fofs(#s) + o.sym[1].info = 17 + o.sect[2].type = f32(3) -- .shstrtab + o.sect[2].ofs = fofs(sofs) + o.sect[2].size = fofs(ofs) + o.sect[3].type = f32(3) -- .strtab + o.sect[3].ofs = fofs(sofs + ofs) + o.sect[3].size = fofs(#symname+2) + ffi.copy(o.space+ofs+1, symname) + ofs = ofs + #symname + 2 + o.sect[4].type = f32(1) -- .rodata + o.sect[4].flags = fofs(2) + o.sect[4].ofs = fofs(sofs + ofs) + o.sect[4].size = fofs(#s) + o.sect[5].type = f32(1) -- .note.GNU-stack + o.sect[5].ofs = fofs(sofs + ofs + #s) + + -- Write ELF object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) + bcsave_tail(fp, output, s) +end + +local function bcsave_peobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct { + uint16_t arch, nsects; + uint32_t time, symtabofs, nsyms; + uint16_t opthdrsz, flags; +} PEheader; +typedef struct { + char name[8]; + uint32_t vsize, vaddr, size, ofs, relocofs, lineofs; + uint16_t nreloc, nline; + uint32_t flags; +} PEsection; +typedef struct __attribute((packed)) { + union { + char name[8]; + uint32_t nameref[2]; + }; + uint32_t value; + int16_t sect; + uint16_t type; + uint8_t scl, naux; +} PEsym; +typedef struct __attribute((packed)) { + uint32_t size; + uint16_t nreloc, nline; + uint32_t cksum; + uint16_t assoc; + uint8_t comdatsel, unused[3]; +} PEsymaux; +typedef struct { + PEheader hdr; + PEsection sect[2]; + // Must be an even number of symbol structs. + PEsym sym0; + PEsymaux sym0aux; + PEsym sym1; + PEsymaux sym1aux; + PEsym sym2; + PEsym sym3; + uint32_t strtabsize; + uint8_t space[4096]; +} PEobj; +]] + local symname = LJBC_PREFIX..ctx.modname + local ai = assert(map_arch[ctx.arch]) + local is64 = ai.b == 64 + local symexport = " /EXPORT:"..symname..",DATA " + + -- The file format is always little-endian. Swap if the host is big-endian. + local function f32(x) return x end + local f16 = f32 + if ffi.abi("be") then + f32 = bit.bswap + function f16(x) return bit.rshift(bit.bswap(x), 16) end + end + + -- Create PE object and fill in header. + local o = ffi.new("PEobj") + local hdr = o.hdr + hdr.arch = f16(assert(ai.p)) + hdr.nsects = f16(2) + hdr.symtabofs = f32(ffi.offsetof(o, "sym0")) + hdr.nsyms = f32(6) + + -- Fill in sections and symbols. + o.sect[0].name = ".drectve" + o.sect[0].size = f32(#symexport) + o.sect[0].flags = f32(0x00100a00) + o.sym0.sect = f16(1) + o.sym0.scl = 3 + o.sym0.name = ".drectve" + o.sym0.naux = 1 + o.sym0aux.size = f32(#symexport) + o.sect[1].name = ".rdata" + o.sect[1].size = f32(#s) + o.sect[1].flags = f32(0x40300040) + o.sym1.sect = f16(2) + o.sym1.scl = 3 + o.sym1.name = ".rdata" + o.sym1.naux = 1 + o.sym1aux.size = f32(#s) + o.sym2.sect = f16(2) + o.sym2.scl = 2 + o.sym2.nameref[1] = f32(4) + o.sym3.sect = f16(-1) + o.sym3.scl = 2 + o.sym3.value = f32(1) + o.sym3.name = "@feat.00" -- Mark as SafeSEH compliant. + ffi.copy(o.space, symname) + local ofs = #symname + 1 + o.strtabsize = f32(ofs + 4) + o.sect[0].ofs = f32(ffi.offsetof(o, "space") + ofs) + ffi.copy(o.space + ofs, symexport) + ofs = ofs + #symexport + o.sect[1].ofs = f32(ffi.offsetof(o, "space") + ofs) + + -- Write PE object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) + bcsave_tail(fp, output, s) +end + +local function bcsave_machobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct +{ + uint32_t magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags; +} mach_header; +typedef struct +{ + mach_header; uint32_t reserved; +} mach_header_64; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint32_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint64_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command_64; +typedef struct { + char sectname[16], segname[16]; + uint32_t addr, size; + uint32_t offset, align, reloff, nreloc, flags; + uint32_t reserved1, reserved2; +} mach_section; +typedef struct { + char sectname[16], segname[16]; + uint64_t addr, size; + uint32_t offset, align, reloff, nreloc, flags; + uint32_t reserved1, reserved2, reserved3; +} mach_section_64; +typedef struct { + uint32_t cmd, cmdsize, symoff, nsyms, stroff, strsize; +} mach_symtab_command; +typedef struct { + int32_t strx; + uint8_t type, sect; + int16_t desc; + uint32_t value; +} mach_nlist; +typedef struct { + uint32_t strx; + uint8_t type, sect; + uint16_t desc; + uint64_t value; +} mach_nlist_64; +typedef struct +{ + uint32_t magic, nfat_arch; +} mach_fat_header; +typedef struct +{ + uint32_t cputype, cpusubtype, offset, size, align; +} mach_fat_arch; +typedef struct { + struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + } arch[1]; + mach_nlist sym_entry; + uint8_t space[4096]; +} mach_obj; +typedef struct { + struct { + mach_header_64 hdr; + mach_segment_command_64 seg; + mach_section_64 sec; + mach_symtab_command sym; + } arch[1]; + mach_nlist_64 sym_entry; + uint8_t space[4096]; +} mach_obj_64; +typedef struct { + mach_fat_header fat; + mach_fat_arch fat_arch[2]; + struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + } arch[2]; + mach_nlist sym_entry; + uint8_t space[4096]; +} mach_fat_obj; +]] + local symname = '_'..LJBC_PREFIX..ctx.modname + local isfat, is64, align, mobj = false, false, 4, "mach_obj" + if ctx.arch == "x64" then + is64, align, mobj = true, 8, "mach_obj_64" + elseif ctx.arch == "arm" then + isfat, mobj = true, "mach_fat_obj" + elseif ctx.arch == "arm64" then + is64, align, isfat, mobj = true, 8, true, "mach_fat_obj" + else + check(ctx.arch == "x86", "unsupported architecture for OSX") + end + local function aligned(v, a) return bit.band(v+a-1, -a) end + local be32 = bit.bswap -- Mach-O FAT is BE, supported archs are LE. + + -- Create Mach-O object and fill in header. + local o = ffi.new(mobj) + local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align) + local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12}, arm64={0x01000007,0x0100000c} })[ctx.arch] + local cpusubtype = ({ x86={3}, x64={3}, arm={3,9}, arm64={3,0} })[ctx.arch] + if isfat then + o.fat.magic = be32(0xcafebabe) + o.fat.nfat_arch = be32(#cpusubtype) + end + + -- Fill in sections and symbols. + for i=0,#cpusubtype-1 do + local ofs = 0 + if isfat then + local a = o.fat_arch[i] + a.cputype = be32(cputype[i+1]) + a.cpusubtype = be32(cpusubtype[i+1]) + -- Subsequent slices overlap each other to share data. + ofs = ffi.offsetof(o, "arch") + i*ffi.sizeof(o.arch[0]) + a.offset = be32(ofs) + a.size = be32(mach_size-ofs+#s) + end + local a = o.arch[i] + a.hdr.magic = is64 and 0xfeedfacf or 0xfeedface + a.hdr.cputype = cputype[i+1] + a.hdr.cpusubtype = cpusubtype[i+1] + a.hdr.filetype = 1 + a.hdr.ncmds = 2 + a.hdr.sizeofcmds = ffi.sizeof(a.seg)+ffi.sizeof(a.sec)+ffi.sizeof(a.sym) + a.seg.cmd = is64 and 0x19 or 0x1 + a.seg.cmdsize = ffi.sizeof(a.seg)+ffi.sizeof(a.sec) + a.seg.vmsize = #s + a.seg.fileoff = mach_size-ofs + a.seg.filesize = #s + a.seg.maxprot = 1 + a.seg.initprot = 1 + a.seg.nsects = 1 + ffi.copy(a.sec.sectname, "__data") + ffi.copy(a.sec.segname, "__DATA") + a.sec.size = #s + a.sec.offset = mach_size-ofs + a.sym.cmd = 2 + a.sym.cmdsize = ffi.sizeof(a.sym) + a.sym.symoff = ffi.offsetof(o, "sym_entry")-ofs + a.sym.nsyms = 1 + a.sym.stroff = ffi.offsetof(o, "sym_entry")+ffi.sizeof(o.sym_entry)-ofs + a.sym.strsize = aligned(#symname+2, align) + end + o.sym_entry.type = 0xf + o.sym_entry.sect = 1 + o.sym_entry.strx = 1 + ffi.copy(o.space+1, symname) + + -- Write Macho-O object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, mach_size)) + bcsave_tail(fp, output, s) +end + +local function bcsave_obj(ctx, output, s) + local ok, ffi = pcall(require, "ffi") + check(ok, "FFI library required to write this file type") + if ctx.os == "windows" then + return bcsave_peobj(ctx, output, s, ffi) + elseif ctx.os == "osx" then + return bcsave_machobj(ctx, output, s, ffi) + else + return bcsave_elfobj(ctx, output, s, ffi) + end +end + +------------------------------------------------------------------------------ + +local function bclist(input, output) + local f = readfile(input) + require("jit.bc").dump(f, savefile(output, "w"), true) +end + +local function bcsave(ctx, input, output) + local f = readfile(input) + local s = string.dump(f, ctx.strip) + local t = ctx.type + if not t then + t = detecttype(output) + ctx.type = t + end + if t == "raw" then + bcsave_raw(output, s) + else + if not ctx.modname then ctx.modname = detectmodname(input) end + if t == "obj" then + bcsave_obj(ctx, output, s) + else + bcsave_c(ctx, output, s) + end + end +end + +local function docmd(...) + local arg = {...} + local n = 1 + local list = false + local ctx = { + strip = true, arch = jit.arch, os = jit.os:lower(), + type = false, modname = false, + } + while n <= #arg do + local a = arg[n] + if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then + tremove(arg, n) + if a == "--" then break end + for m=2,#a do + local opt = a:sub(m, m) + if opt == "l" then + list = true + elseif opt == "s" then + ctx.strip = true + elseif opt == "g" then + ctx.strip = false + else + if arg[n] == nil or m ~= #a then usage() end + if opt == "e" then + if n ~= 1 then usage() end + arg[1] = check(loadstring(arg[1])) + elseif opt == "n" then + ctx.modname = checkmodname(tremove(arg, n)) + elseif opt == "t" then + ctx.type = checkarg(tremove(arg, n), map_type, "file type") + elseif opt == "a" then + ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture") + elseif opt == "o" then + ctx.os = checkarg(tremove(arg, n), map_os, "OS name") + else + usage() + end + end + end + else + n = n + 1 + end + end + if list then + if #arg == 0 or #arg > 2 then usage() end + bclist(arg[1], arg[2] or "-") + else + if #arg ~= 2 then usage() end + bcsave(ctx, arg[1], arg[2]) + end +end + +------------------------------------------------------------------------------ + +-- Public module functions. +return { + start = docmd -- Process -b command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm.lua new file mode 100644 index 00000000..ba79c47e --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm.lua @@ -0,0 +1,689 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles most user-mode ARMv7 instructions +-- NYI: Advanced SIMD and VFP instructions. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch = string.match, string.gmatch +local concat = table.concat +local bit = require("bit") +local band, bor, ror, tohex = bit.band, bit.bor, bit.ror, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Opcode maps +------------------------------------------------------------------------------ + +local map_loadc = { + shift = 8, mask = 15, + [10] = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "vmovFmDN", "vstmFNdr", + _ = { + shift = 21, mask = 1, + [0] = "vstrFdl", + { shift = 16, mask = 15, [13] = "vpushFdr", _ = "vstmdbFNdr", } + }, + }, + { + shift = 23, mask = 3, + [0] = "vmovFDNm", + { shift = 16, mask = 15, [13] = "vpopFdr", _ = "vldmFNdr", }, + _ = { + shift = 21, mask = 1, + [0] = "vldrFdl", "vldmdbFNdr", + }, + }, + }, + [11] = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "vmovGmDN", "vstmGNdr", + _ = { + shift = 21, mask = 1, + [0] = "vstrGdl", + { shift = 16, mask = 15, [13] = "vpushGdr", _ = "vstmdbGNdr", } + }, + }, + { + shift = 23, mask = 3, + [0] = "vmovGDNm", + { shift = 16, mask = 15, [13] = "vpopGdr", _ = "vldmGNdr", }, + _ = { + shift = 21, mask = 1, + [0] = "vldrGdl", "vldmdbGNdr", + }, + }, + }, + _ = { + shift = 0, mask = 0 -- NYI ldc, mcrr, mrrc. + }, +} + +local map_vfps = { + shift = 6, mask = 0x2c001, + [0] = "vmlaF.dnm", "vmlsF.dnm", + [0x04000] = "vnmlsF.dnm", [0x04001] = "vnmlaF.dnm", + [0x08000] = "vmulF.dnm", [0x08001] = "vnmulF.dnm", + [0x0c000] = "vaddF.dnm", [0x0c001] = "vsubF.dnm", + [0x20000] = "vdivF.dnm", + [0x24000] = "vfnmsF.dnm", [0x24001] = "vfnmaF.dnm", + [0x28000] = "vfmaF.dnm", [0x28001] = "vfmsF.dnm", + [0x2c000] = "vmovF.dY", + [0x2c001] = { + shift = 7, mask = 0x1e01, + [0] = "vmovF.dm", "vabsF.dm", + [0x0200] = "vnegF.dm", [0x0201] = "vsqrtF.dm", + [0x0800] = "vcmpF.dm", [0x0801] = "vcmpeF.dm", + [0x0a00] = "vcmpzF.d", [0x0a01] = "vcmpzeF.d", + [0x0e01] = "vcvtG.dF.m", + [0x1000] = "vcvt.f32.u32Fdm", [0x1001] = "vcvt.f32.s32Fdm", + [0x1800] = "vcvtr.u32F.dm", [0x1801] = "vcvt.u32F.dm", + [0x1a00] = "vcvtr.s32F.dm", [0x1a01] = "vcvt.s32F.dm", + }, +} + +local map_vfpd = { + shift = 6, mask = 0x2c001, + [0] = "vmlaG.dnm", "vmlsG.dnm", + [0x04000] = "vnmlsG.dnm", [0x04001] = "vnmlaG.dnm", + [0x08000] = "vmulG.dnm", [0x08001] = "vnmulG.dnm", + [0x0c000] = "vaddG.dnm", [0x0c001] = "vsubG.dnm", + [0x20000] = "vdivG.dnm", + [0x24000] = "vfnmsG.dnm", [0x24001] = "vfnmaG.dnm", + [0x28000] = "vfmaG.dnm", [0x28001] = "vfmsG.dnm", + [0x2c000] = "vmovG.dY", + [0x2c001] = { + shift = 7, mask = 0x1e01, + [0] = "vmovG.dm", "vabsG.dm", + [0x0200] = "vnegG.dm", [0x0201] = "vsqrtG.dm", + [0x0800] = "vcmpG.dm", [0x0801] = "vcmpeG.dm", + [0x0a00] = "vcmpzG.d", [0x0a01] = "vcmpzeG.d", + [0x0e01] = "vcvtF.dG.m", + [0x1000] = "vcvt.f64.u32GdFm", [0x1001] = "vcvt.f64.s32GdFm", + [0x1800] = "vcvtr.u32FdG.m", [0x1801] = "vcvt.u32FdG.m", + [0x1a00] = "vcvtr.s32FdG.m", [0x1a01] = "vcvt.s32FdG.m", + }, +} + +local map_datac = { + shift = 24, mask = 1, + [0] = { + shift = 4, mask = 1, + [0] = { + shift = 8, mask = 15, + [10] = map_vfps, + [11] = map_vfpd, + -- NYI cdp, mcr, mrc. + }, + { + shift = 8, mask = 15, + [10] = { + shift = 20, mask = 15, + [0] = "vmovFnD", "vmovFDn", + [14] = "vmsrD", + [15] = { shift = 12, mask = 15, [15] = "vmrs", _ = "vmrsD", }, + }, + }, + }, + "svcT", +} + +local map_loadcu = { + shift = 0, mask = 0, -- NYI unconditional CP load/store. +} + +local map_datacu = { + shift = 0, mask = 0, -- NYI unconditional CP data. +} + +local map_simddata = { + shift = 0, mask = 0, -- NYI SIMD data. +} + +local map_simdload = { + shift = 0, mask = 0, -- NYI SIMD load/store, preload. +} + +local map_preload = { + shift = 0, mask = 0, -- NYI preload. +} + +local map_media = { + shift = 20, mask = 31, + [0] = false, + { --01 + shift = 5, mask = 7, + [0] = "sadd16DNM", "sasxDNM", "ssaxDNM", "ssub16DNM", + "sadd8DNM", false, false, "ssub8DNM", + }, + { --02 + shift = 5, mask = 7, + [0] = "qadd16DNM", "qasxDNM", "qsaxDNM", "qsub16DNM", + "qadd8DNM", false, false, "qsub8DNM", + }, + { --03 + shift = 5, mask = 7, + [0] = "shadd16DNM", "shasxDNM", "shsaxDNM", "shsub16DNM", + "shadd8DNM", false, false, "shsub8DNM", + }, + false, + { --05 + shift = 5, mask = 7, + [0] = "uadd16DNM", "uasxDNM", "usaxDNM", "usub16DNM", + "uadd8DNM", false, false, "usub8DNM", + }, + { --06 + shift = 5, mask = 7, + [0] = "uqadd16DNM", "uqasxDNM", "uqsaxDNM", "uqsub16DNM", + "uqadd8DNM", false, false, "uqsub8DNM", + }, + { --07 + shift = 5, mask = 7, + [0] = "uhadd16DNM", "uhasxDNM", "uhsaxDNM", "uhsub16DNM", + "uhadd8DNM", false, false, "uhsub8DNM", + }, + { --08 + shift = 5, mask = 7, + [0] = "pkhbtDNMU", false, "pkhtbDNMU", + { shift = 16, mask = 15, [15] = "sxtb16DMU", _ = "sxtab16DNMU", }, + "pkhbtDNMU", "selDNM", "pkhtbDNMU", + }, + false, + { --0a + shift = 5, mask = 7, + [0] = "ssatDxMu", "ssat16DxM", "ssatDxMu", + { shift = 16, mask = 15, [15] = "sxtbDMU", _ = "sxtabDNMU", }, + "ssatDxMu", false, "ssatDxMu", + }, + { --0b + shift = 5, mask = 7, + [0] = "ssatDxMu", "revDM", "ssatDxMu", + { shift = 16, mask = 15, [15] = "sxthDMU", _ = "sxtahDNMU", }, + "ssatDxMu", "rev16DM", "ssatDxMu", + }, + { --0c + shift = 5, mask = 7, + [3] = { shift = 16, mask = 15, [15] = "uxtb16DMU", _ = "uxtab16DNMU", }, + }, + false, + { --0e + shift = 5, mask = 7, + [0] = "usatDwMu", "usat16DwM", "usatDwMu", + { shift = 16, mask = 15, [15] = "uxtbDMU", _ = "uxtabDNMU", }, + "usatDwMu", false, "usatDwMu", + }, + { --0f + shift = 5, mask = 7, + [0] = "usatDwMu", "rbitDM", "usatDwMu", + { shift = 16, mask = 15, [15] = "uxthDMU", _ = "uxtahDNMU", }, + "usatDwMu", "revshDM", "usatDwMu", + }, + { --10 + shift = 12, mask = 15, + [15] = { + shift = 5, mask = 7, + "smuadNMS", "smuadxNMS", "smusdNMS", "smusdxNMS", + }, + _ = { + shift = 5, mask = 7, + [0] = "smladNMSD", "smladxNMSD", "smlsdNMSD", "smlsdxNMSD", + }, + }, + false, false, false, + { --14 + shift = 5, mask = 7, + [0] = "smlaldDNMS", "smlaldxDNMS", "smlsldDNMS", "smlsldxDNMS", + }, + { --15 + shift = 5, mask = 7, + [0] = { shift = 12, mask = 15, [15] = "smmulNMS", _ = "smmlaNMSD", }, + { shift = 12, mask = 15, [15] = "smmulrNMS", _ = "smmlarNMSD", }, + false, false, false, false, + "smmlsNMSD", "smmlsrNMSD", + }, + false, false, + { --18 + shift = 5, mask = 7, + [0] = { shift = 12, mask = 15, [15] = "usad8NMS", _ = "usada8NMSD", }, + }, + false, + { --1a + shift = 5, mask = 3, [2] = "sbfxDMvw", + }, + { --1b + shift = 5, mask = 3, [2] = "sbfxDMvw", + }, + { --1c + shift = 5, mask = 3, + [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", }, + }, + { --1d + shift = 5, mask = 3, + [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", }, + }, + { --1e + shift = 5, mask = 3, [2] = "ubfxDMvw", + }, + { --1f + shift = 5, mask = 3, [2] = "ubfxDMvw", + }, +} + +local map_load = { + shift = 21, mask = 9, + { + shift = 20, mask = 5, + [0] = "strtDL", "ldrtDL", [4] = "strbtDL", [5] = "ldrbtDL", + }, + _ = { + shift = 20, mask = 5, + [0] = "strDL", "ldrDL", [4] = "strbDL", [5] = "ldrbDL", + } +} + +local map_load1 = { + shift = 4, mask = 1, + [0] = map_load, map_media, +} + +local map_loadm = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "stmdaNR", "stmNR", + { shift = 16, mask = 63, [45] = "pushR", _ = "stmdbNR", }, "stmibNR", + }, + { + shift = 23, mask = 3, + [0] = "ldmdaNR", { shift = 16, mask = 63, [61] = "popR", _ = "ldmNR", }, + "ldmdbNR", "ldmibNR", + }, +} + +local map_data = { + shift = 21, mask = 15, + [0] = "andDNPs", "eorDNPs", "subDNPs", "rsbDNPs", + "addDNPs", "adcDNPs", "sbcDNPs", "rscDNPs", + "tstNP", "teqNP", "cmpNP", "cmnNP", + "orrDNPs", "movDPs", "bicDNPs", "mvnDPs", +} + +local map_mul = { + shift = 21, mask = 7, + [0] = "mulNMSs", "mlaNMSDs", "umaalDNMS", "mlsDNMS", + "umullDNMSs", "umlalDNMSs", "smullDNMSs", "smlalDNMSs", +} + +local map_sync = { + shift = 20, mask = 15, -- NYI: brackets around N. R(D+1) for ldrexd/strexd. + [0] = "swpDMN", false, false, false, + "swpbDMN", false, false, false, + "strexDMN", "ldrexDN", "strexdDN", "ldrexdDN", + "strexbDMN", "ldrexbDN", "strexhDN", "ldrexhDN", +} + +local map_mulh = { + shift = 21, mask = 3, + [0] = { shift = 5, mask = 3, + [0] = "smlabbNMSD", "smlatbNMSD", "smlabtNMSD", "smlattNMSD", }, + { shift = 5, mask = 3, + [0] = "smlawbNMSD", "smulwbNMS", "smlawtNMSD", "smulwtNMS", }, + { shift = 5, mask = 3, + [0] = "smlalbbDNMS", "smlaltbDNMS", "smlalbtDNMS", "smlalttDNMS", }, + { shift = 5, mask = 3, + [0] = "smulbbNMS", "smultbNMS", "smulbtNMS", "smulttNMS", }, +} + +local map_misc = { + shift = 4, mask = 7, + -- NYI: decode PSR bits of msr. + [0] = { shift = 21, mask = 1, [0] = "mrsD", "msrM", }, + { shift = 21, mask = 3, "bxM", false, "clzDM", }, + { shift = 21, mask = 3, "bxjM", }, + { shift = 21, mask = 3, "blxM", }, + false, + { shift = 21, mask = 3, [0] = "qaddDMN", "qsubDMN", "qdaddDMN", "qdsubDMN", }, + false, + { shift = 21, mask = 3, "bkptK", }, +} + +local map_datar = { + shift = 4, mask = 9, + [9] = { + shift = 5, mask = 3, + [0] = { shift = 24, mask = 1, [0] = map_mul, map_sync, }, + { shift = 20, mask = 1, [0] = "strhDL", "ldrhDL", }, + { shift = 20, mask = 1, [0] = "ldrdDL", "ldrsbDL", }, + { shift = 20, mask = 1, [0] = "strdDL", "ldrshDL", }, + }, + _ = { + shift = 20, mask = 25, + [16] = { shift = 7, mask = 1, [0] = map_misc, map_mulh, }, + _ = { + shift = 0, mask = 0xffffffff, + [bor(0xe1a00000)] = "nop", + _ = map_data, + } + }, +} + +local map_datai = { + shift = 20, mask = 31, -- NYI: decode PSR bits of msr. Decode imm12. + [16] = "movwDW", [20] = "movtDW", + [18] = { shift = 0, mask = 0xf00ff, [0] = "nopv6", _ = "msrNW", }, + [22] = "msrNW", + _ = map_data, +} + +local map_branch = { + shift = 24, mask = 1, + [0] = "bB", "blB" +} + +local map_condins = { + [0] = map_datar, map_datai, map_load, map_load1, + map_loadm, map_branch, map_loadc, map_datac +} + +-- NYI: setend. +local map_uncondins = { + [0] = false, map_simddata, map_simdload, map_preload, + false, "blxB", map_loadcu, map_datacu, +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", +} + +local map_cond = { + [0] = "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", +} + +local map_shift = { [0] = "lsl", "lsr", "asr", "ror", } + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then + extra = "\t->"..sym + elseif band(ctx.op, 0x0e000000) ~= 0x0a000000 then + extra = "\t; 0x"..tohex(ctx.rel) + end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-5s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-5s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +-- Format operand 2 of load/store opcodes. +local function fmtload(ctx, op, pos) + local base = map_gpr[band(rshift(op, 16), 15)] + local x, ofs + local ext = (band(op, 0x04000000) == 0) + if not ext and band(op, 0x02000000) == 0 then + ofs = band(op, 4095) + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + ofs = "#"..ofs + elseif ext and band(op, 0x00400000) ~= 0 then + ofs = band(op, 15) + band(rshift(op, 4), 0xf0) + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + ofs = "#"..ofs + else + ofs = map_gpr[band(op, 15)] + if ext or band(op, 0xfe0) == 0 then + elseif band(op, 0xfe0) == 0x60 then + ofs = format("%s, rrx", ofs) + else + local sh = band(rshift(op, 7), 31) + if sh == 0 then sh = 32 end + ofs = format("%s, %s #%d", ofs, map_shift[band(rshift(op, 5), 3)], sh) + end + if band(op, 0x00800000) == 0 then ofs = "-"..ofs end + end + if ofs == "#0" then + x = format("[%s]", base) + elseif band(op, 0x01000000) == 0 then + x = format("[%s], %s", base, ofs) + else + x = format("[%s, %s]", base, ofs) + end + if band(op, 0x01200000) == 0x01200000 then x = x.."!" end + return x +end + +-- Format operand 2 of vector load/store opcodes. +local function fmtvload(ctx, op, pos) + local base = map_gpr[band(rshift(op, 16), 15)] + local ofs = band(op, 255)*4 + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + if ofs == 0 then + return format("[%s]", base) + else + return format("[%s, #%d]", base, ofs) + end +end + +local function fmtvr(op, vr, sh0, sh1) + if vr == "s" then + return format("s%d", 2*band(rshift(op, sh0), 15)+band(rshift(op, sh1), 1)) + else + return format("d%d", band(rshift(op, sh0), 15)+band(rshift(op, sh1-4), 16)) + end +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) + local operands = {} + local suffix = "" + local last, name, pat + local vr + ctx.op = op + ctx.rel = nil + + local cond = rshift(op, 28) + local opat + if cond == 15 then + opat = map_uncondins[band(rshift(op, 25), 7)] + else + if cond ~= 14 then suffix = map_cond[cond] end + opat = map_condins[band(rshift(op, 25), 7)] + end + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + name, pat = match(opat, "^([a-z0-9]*)(.*)") + if sub(pat, 1, 1) == "." then + local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") + suffix = suffix..s2 + pat = p2 + end + + for p in gmatch(pat, ".") do + local x = nil + if p == "D" then + x = map_gpr[band(rshift(op, 12), 15)] + elseif p == "N" then + x = map_gpr[band(rshift(op, 16), 15)] + elseif p == "S" then + x = map_gpr[band(rshift(op, 8), 15)] + elseif p == "M" then + x = map_gpr[band(op, 15)] + elseif p == "d" then + x = fmtvr(op, vr, 12, 22) + elseif p == "n" then + x = fmtvr(op, vr, 16, 7) + elseif p == "m" then + x = fmtvr(op, vr, 0, 5) + elseif p == "P" then + if band(op, 0x02000000) ~= 0 then + x = ror(band(op, 255), 2*band(rshift(op, 8), 15)) + else + x = map_gpr[band(op, 15)] + if band(op, 0xff0) ~= 0 then + operands[#operands+1] = x + local s = map_shift[band(rshift(op, 5), 3)] + local r = nil + if band(op, 0xf90) == 0 then + if s == "ror" then s = "rrx" else r = "#32" end + elseif band(op, 0x10) == 0 then + r = "#"..band(rshift(op, 7), 31) + else + r = map_gpr[band(rshift(op, 8), 15)] + end + if name == "mov" then name = s; x = r + elseif r then x = format("%s %s", s, r) + else x = s end + end + end + elseif p == "L" then + x = fmtload(ctx, op, pos) + elseif p == "l" then + x = fmtvload(ctx, op, pos) + elseif p == "B" then + local addr = ctx.addr + pos + 8 + arshift(lshift(op, 8), 6) + if cond == 15 then addr = addr + band(rshift(op, 23), 2) end + ctx.rel = addr + x = "0x"..tohex(addr) + elseif p == "F" then + vr = "s" + elseif p == "G" then + vr = "d" + elseif p == "." then + suffix = suffix..(vr == "s" and ".f32" or ".f64") + elseif p == "R" then + if band(op, 0x00200000) ~= 0 and #operands == 1 then + operands[1] = operands[1].."!" + end + local t = {} + for i=0,15 do + if band(rshift(op, i), 1) == 1 then t[#t+1] = map_gpr[i] end + end + x = "{"..concat(t, ", ").."}" + elseif p == "r" then + if band(op, 0x00200000) ~= 0 and #operands == 2 then + operands[1] = operands[1].."!" + end + local s = tonumber(sub(last, 2)) + local n = band(op, 255) + if vr == "d" then n = rshift(n, 1) end + operands[#operands] = format("{%s-%s%d}", last, vr, s+n-1) + elseif p == "W" then + x = band(op, 0x0fff) + band(rshift(op, 4), 0xf000) + elseif p == "T" then + x = "#0x"..tohex(band(op, 0x00ffffff), 6) + elseif p == "U" then + x = band(rshift(op, 7), 31) + if x == 0 then x = nil end + elseif p == "u" then + x = band(rshift(op, 7), 31) + if band(op, 0x40) == 0 then + if x == 0 then x = nil else x = "lsl #"..x end + else + if x == 0 then x = "asr #32" else x = "asr #"..x end + end + elseif p == "v" then + x = band(rshift(op, 7), 31) + elseif p == "w" then + x = band(rshift(op, 16), 31) + elseif p == "x" then + x = band(rshift(op, 16), 31) + 1 + elseif p == "X" then + x = band(rshift(op, 16), 31) - last + 1 + elseif p == "Y" then + x = band(rshift(op, 12), 0xf0) + band(op, 0x0f) + elseif p == "K" then + x = "#0x"..tohex(band(rshift(op, 4), 0x0000fff0) + band(op, 15), 4) + elseif p == "s" then + if band(op, 0x00100000) ~= 0 then suffix = "s"..suffix end + else + assert(false) + end + if x then + last = x + if type(x) == "number" then x = "#"..x end + operands[#operands+1] = x + end + end + + return putop(ctx, name..suffix, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ctx.pos = ofs + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 16 then return map_gpr[r] end + return "d"..(r-16) +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm64.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm64.lua new file mode 100644 index 00000000..ad909fbd --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm64.lua @@ -0,0 +1,1216 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM64 disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +-- +-- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com. +-- Sponsored by Cisco Systems, Inc. +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles most user-mode AArch64 instructions. +-- NYI: Advanced SIMD and VFP instructions. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local concat = table.concat +local bit = require("bit") +local band, bor, bxor, tohex = bit.band, bit.bor, bit.bxor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift +local ror = bit.ror + +------------------------------------------------------------------------------ +-- Opcode maps +------------------------------------------------------------------------------ + +local map_adr = { -- PC-relative addressing. + shift = 31, mask = 1, + [0] = "adrDBx", "adrpDBx" +} + +local map_addsubi = { -- Add/subtract immediate. + shift = 29, mask = 3, + [0] = "add|movDNIg", "adds|cmnD0NIg", "subDNIg", "subs|cmpD0NIg", +} + +local map_logi = { -- Logical immediate. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "andDNig", "orr|movDN0ig", "eorDNig", "ands|tstD0Nig" + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = "andDNig", "orr|movDN0ig", "eorDNig", "ands|tstD0Nig" + } +} + +local map_movwi = { -- Move wide immediate. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "movnDWRg", false, "movz|movDYRg", "movkDWRg" + }, false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = "movnDWRg", false, "movz|movDYRg", "movkDWRg" + }, +} + +local map_bitf = { -- Bitfield. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "sbfm|sbfiz|sbfx|asr|sxtw|sxth|sxtbDN12w", + "bfm|bfi|bfxilDN13w", + "ubfm|ubfiz|ubfx|lsr|lsl|uxth|uxtbDN12w" + } + }, + { + shift = 22, mask = 1, + { + shift = 29, mask = 3, + [0] = "sbfm|sbfiz|sbfx|asr|sxtw|sxth|sxtbDN12x", + "bfm|bfi|bfxilDN13x", + "ubfm|ubfiz|ubfx|lsr|lsl|uxth|uxtbDN12x" + } + } +} + +local map_datai = { -- Data processing - immediate. + shift = 23, mask = 7, + [0] = map_adr, map_adr, map_addsubi, false, + map_logi, map_movwi, map_bitf, + { + shift = 15, mask = 0x1c0c1, + [0] = "extr|rorDNM4w", [0x10080] = "extr|rorDNM4x", + [0x10081] = "extr|rorDNM4x" + } +} + +local map_logsr = { -- Logical, shifted register. + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = { + shift = 21, mask = 7, + [0] = "andDNMSg", "bicDNMSg", "andDNMSg", "bicDNMSg", + "andDNMSg", "bicDNMSg", "andDNMg", "bicDNMg" + }, + { + shift = 21, mask = 7, + [0] ="orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0MSg", "orn|mvnDN0MSg", + "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0Mg", "orn|mvnDN0Mg" + }, + { + shift = 21, mask = 7, + [0] = "eorDNMSg", "eonDNMSg", "eorDNMSg", "eonDNMSg", + "eorDNMSg", "eonDNMSg", "eorDNMg", "eonDNMg" + }, + { + shift = 21, mask = 7, + [0] = "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMSg", "bicsDNMSg", + "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMg", "bicsDNMg" + } + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = { + shift = 21, mask = 7, + [0] = "andDNMSg", "bicDNMSg", "andDNMSg", "bicDNMSg", + "andDNMSg", "bicDNMSg", "andDNMg", "bicDNMg" + }, + { + shift = 21, mask = 7, + [0] = "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0MSg", "orn|mvnDN0MSg", + "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0Mg", "orn|mvnDN0Mg" + }, + { + shift = 21, mask = 7, + [0] = "eorDNMSg", "eonDNMSg", "eorDNMSg", "eonDNMSg", + "eorDNMSg", "eonDNMSg", "eorDNMg", "eonDNMg" + }, + { + shift = 21, mask = 7, + [0] = "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMSg", "bicsDNMSg", + "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMg", "bicsDNMg" + } + } +} + +local map_assh = { + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "addDNMSg", "addDNMSg", "addDNMSg", "addDNMg" + }, + { + shift = 22, mask = 3, + [0] = "adds|cmnD0NMSg", "adds|cmnD0NMSg", + "adds|cmnD0NMSg", "adds|cmnD0NMg" + }, + { + shift = 22, mask = 3, + [0] = "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0Mg" + }, + { + shift = 22, mask = 3, + [0] = "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0MzSg", + "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0Mzg" + }, + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "addDNMSg", "addDNMSg", "addDNMSg", "addDNMg" + }, + { + shift = 22, mask = 3, + [0] = "adds|cmnD0NMSg", "adds|cmnD0NMSg", "adds|cmnD0NMSg", + "adds|cmnD0NMg" + }, + { + shift = 22, mask = 3, + [0] = "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0Mg" + }, + { + shift = 22, mask = 3, + [0] = "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0MzSg", + "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0Mzg" + } + } +} + +local map_addsubsh = { -- Add/subtract, shifted register. + shift = 22, mask = 3, + [0] = map_assh, map_assh, map_assh +} + +local map_addsubex = { -- Add/subtract, extended register. + shift = 22, mask = 3, + [0] = { + shift = 29, mask = 3, + [0] = "addDNMXg", "adds|cmnD0NMXg", "subDNMXg", "subs|cmpD0NMzXg", + } +} + +local map_addsubc = { -- Add/subtract, with carry. + shift = 10, mask = 63, + [0] = { + shift = 29, mask = 3, + [0] = "adcDNMg", "adcsDNMg", "sbc|ngcDN0Mg", "sbcs|ngcsDN0Mg", + } +} + +local map_ccomp = { + shift = 4, mask = 1, + [0] = { + shift = 10, mask = 3, + [0] = { -- Conditional compare register. + shift = 29, mask = 3, + "ccmnNMVCg", false, "ccmpNMVCg", + }, + [2] = { -- Conditional compare immediate. + shift = 29, mask = 3, + "ccmnN5VCg", false, "ccmpN5VCg", + } + } +} + +local map_csel = { -- Conditional select. + shift = 11, mask = 1, + [0] = { + shift = 10, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "cselDNMzCg", false, "csinv|cinv|csetmDNMcg", false, + }, + { + shift = 29, mask = 3, + [0] = "csinc|cinc|csetDNMcg", false, "csneg|cnegDNMcg", false, + } + } +} + +local map_data1s = { -- Data processing, 1 source. + shift = 29, mask = 1, + [0] = { + shift = 31, mask = 1, + [0] = { + shift = 10, mask = 0x7ff, + [0] = "rbitDNg", "rev16DNg", "revDNw", false, "clzDNg", "clsDNg" + }, + { + shift = 10, mask = 0x7ff, + [0] = "rbitDNg", "rev16DNg", "rev32DNx", "revDNx", "clzDNg", "clsDNg" + } + } +} + +local map_data2s = { -- Data processing, 2 sources. + shift = 29, mask = 1, + [0] = { + shift = 10, mask = 63, + false, "udivDNMg", "sdivDNMg", false, false, false, false, "lslDNMg", + "lsrDNMg", "asrDNMg", "rorDNMg" + } +} + +local map_data3s = { -- Data processing, 3 sources. + shift = 29, mask = 7, + [0] = { + shift = 21, mask = 7, + [0] = { + shift = 15, mask = 1, + [0] = "madd|mulDNMA0g", "msub|mnegDNMA0g" + } + }, false, false, false, + { + shift = 15, mask = 1, + [0] = { + shift = 21, mask = 7, + [0] = "madd|mulDNMA0g", "smaddl|smullDxNMwA0x", "smulhDNMx", false, + false, "umaddl|umullDxNMwA0x", "umulhDNMx" + }, + { + shift = 21, mask = 7, + [0] = "msub|mnegDNMA0g", "smsubl|smneglDxNMwA0x", false, false, + false, "umsubl|umneglDxNMwA0x" + } + } +} + +local map_datar = { -- Data processing, register. + shift = 28, mask = 1, + [0] = { + shift = 24, mask = 1, + [0] = map_logsr, + { + shift = 21, mask = 1, + [0] = map_addsubsh, map_addsubex + } + }, + { + shift = 21, mask = 15, + [0] = map_addsubc, false, map_ccomp, false, map_csel, false, + { + shift = 30, mask = 1, + [0] = map_data2s, map_data1s + }, + false, map_data3s, map_data3s, map_data3s, map_data3s, map_data3s, + map_data3s, map_data3s, map_data3s + } +} + +local map_lrl = { -- Load register, literal. + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = "ldrDwB", "ldrDxB", "ldrswDxB" + }, + { + shift = 30, mask = 3, + [0] = "ldrDsB", "ldrDdB" + } +} + +local map_lsriind = { -- Load/store register, immediate pre/post-indexed. + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwzL", "ldrbDwzL", "ldrsbDxzL", "ldrsbDwzL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strhDwzL", "ldrhDwzL", "ldrshDxzL", "ldrshDwzL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strDwzL", "ldrDwzL", "ldrswDxzL" + }, + { + shift = 22, mask = 3, + [0] = "strDszL", "ldrDszL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strDxzL", "ldrDxzL" + }, + { + shift = 22, mask = 3, + [0] = "strDdzL", "ldrDdzL" + } + } +} + +local map_lsriro = { + shift = 21, mask = 1, + [0] = { -- Load/store register immediate. + shift = 10, mask = 3, + [0] = { -- Unscaled immediate. + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "sturbDwK", "ldurbDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturhDwK", "ldurhDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturDwK", "ldurDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturDxK", "ldurDxK" + } + } + }, map_lsriind, false, map_lsriind + }, + { -- Load/store register, register offset. + shift = 10, mask = 3, + [2] = { + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwO", "ldrbDwO", "ldrsbDxO", "ldrsbDwO" + }, + { + shift = 22, mask = 3, + [0] = "strhDwO", "ldrhDwO", "ldrshDxO", "ldrshDwO" + }, + { + shift = 22, mask = 3, + [0] = "strDwO", "ldrDwO", "ldrswDxO" + }, + { + shift = 22, mask = 3, + [0] = "strDxO", "ldrDxO" + } + }, + { + shift = 30, mask = 3, + [2] = { + shift = 22, mask = 3, + [0] = "strDsO", "ldrDsO" + }, + [3] = { + shift = 22, mask = 3, + [0] = "strDdO", "ldrDdO" + } + } + } + } +} + +local map_lsp = { -- Load/store register pair, offset. + shift = 22, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = "stpDzAzwP", "stpDzAzsP", + }, + { + shift = 26, mask = 1, + "stpDzAzdP" + }, + { + shift = 26, mask = 1, + [0] = "stpDzAzxP" + } + }, + { + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = "ldpDzAzwP", "ldpDzAzsP", + }, + { + shift = 26, mask = 1, + [0] = "ldpswDAxP", "ldpDzAzdP" + }, + { + shift = 26, mask = 1, + [0] = "ldpDzAzxP" + } + } +} + +local map_ls = { -- Loads and stores. + shift = 24, mask = 0x31, + [0x10] = map_lrl, [0x30] = map_lsriro, + [0x20] = { + shift = 23, mask = 3, + map_lsp, map_lsp, map_lsp + }, + [0x21] = { + shift = 23, mask = 3, + map_lsp, map_lsp, map_lsp + }, + [0x31] = { + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwzU", "ldrbDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strhDwzU", "ldrhDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strDwzU", "ldrDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strDxzU", "ldrDxzU" + } + }, + { + shift = 30, mask = 3, + [2] = { + shift = 22, mask = 3, + [0] = "strDszU", "ldrDszU" + }, + [3] = { + shift = 22, mask = 3, + [0] = "strDdzU", "ldrDdzU" + } + } + }, +} + +local map_datafp = { -- Data processing, SIMD and FP. + shift = 28, mask = 7, + { -- 001 + shift = 24, mask = 1, + [0] = { + shift = 21, mask = 1, + { + shift = 10, mask = 3, + [0] = { + shift = 12, mask = 1, + [0] = { + shift = 13, mask = 1, + [0] = { + shift = 14, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { -- FP/int conversion. + shift = 31, mask = 1, + [0] = { + shift = 16, mask = 0xff, + [0x20] = "fcvtnsDwNs", [0x21] = "fcvtnuDwNs", + [0x22] = "scvtfDsNw", [0x23] = "ucvtfDsNw", + [0x24] = "fcvtasDwNs", [0x25] = "fcvtauDwNs", + [0x26] = "fmovDwNs", [0x27] = "fmovDsNw", + [0x28] = "fcvtpsDwNs", [0x29] = "fcvtpuDwNs", + [0x30] = "fcvtmsDwNs", [0x31] = "fcvtmuDwNs", + [0x38] = "fcvtzsDwNs", [0x39] = "fcvtzuDwNs", + [0x60] = "fcvtnsDwNd", [0x61] = "fcvtnuDwNd", + [0x62] = "scvtfDdNw", [0x63] = "ucvtfDdNw", + [0x64] = "fcvtasDwNd", [0x65] = "fcvtauDwNd", + [0x68] = "fcvtpsDwNd", [0x69] = "fcvtpuDwNd", + [0x70] = "fcvtmsDwNd", [0x71] = "fcvtmuDwNd", + [0x78] = "fcvtzsDwNd", [0x79] = "fcvtzuDwNd" + }, + { + shift = 16, mask = 0xff, + [0x20] = "fcvtnsDxNs", [0x21] = "fcvtnuDxNs", + [0x22] = "scvtfDsNx", [0x23] = "ucvtfDsNx", + [0x24] = "fcvtasDxNs", [0x25] = "fcvtauDxNs", + [0x28] = "fcvtpsDxNs", [0x29] = "fcvtpuDxNs", + [0x30] = "fcvtmsDxNs", [0x31] = "fcvtmuDxNs", + [0x38] = "fcvtzsDxNs", [0x39] = "fcvtzuDxNs", + [0x60] = "fcvtnsDxNd", [0x61] = "fcvtnuDxNd", + [0x62] = "scvtfDdNx", [0x63] = "ucvtfDdNx", + [0x64] = "fcvtasDxNd", [0x65] = "fcvtauDxNd", + [0x66] = "fmovDxNd", [0x67] = "fmovDdNx", + [0x68] = "fcvtpsDxNd", [0x69] = "fcvtpuDxNd", + [0x70] = "fcvtmsDxNd", [0x71] = "fcvtmuDxNd", + [0x78] = "fcvtzsDxNd", [0x79] = "fcvtzuDxNd" + } + } + }, + { -- FP data-processing, 1 source. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = { + shift = 15, mask = 63, + [0] = "fmovDNf", "fabsDNf", "fnegDNf", + "fsqrtDNf", false, "fcvtDdNs", false, false, + "frintnDNf", "frintpDNf", "frintmDNf", "frintzDNf", + "frintaDNf", false, "frintxDNf", "frintiDNf", + }, + { + shift = 15, mask = 63, + [0] = "fmovDNf", "fabsDNf", "fnegDNf", + "fsqrtDNf", "fcvtDsNd", false, false, false, + "frintnDNf", "frintpDNf", "frintmDNf", "frintzDNf", + "frintaDNf", false, "frintxDNf", "frintiDNf", + } + } + } + }, + { -- FP compare. + shift = 31, mask = 1, + [0] = { + shift = 14, mask = 3, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 0, mask = 31, + [0] = "fcmpNMf", [8] = "fcmpNZf", + [16] = "fcmpeNMf", [24] = "fcmpeNZf", + } + } + } + } + }, + { -- FP immediate. + shift = 31, mask = 1, + [0] = { + shift = 5, mask = 31, + [0] = { + shift = 23, mask = 1, + [0] = "fmovDFf" + } + } + } + }, + { -- FP conditional compare. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 4, mask = 1, + [0] = "fccmpNMVCf", "fccmpeNMVCf" + } + } + }, + { -- FP data-processing, 2 sources. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 12, mask = 15, + [0] = "fmulDNMf", "fdivDNMf", "faddDNMf", "fsubDNMf", + "fmaxDNMf", "fminDNMf", "fmaxnmDNMf", "fminnmDNMf", + "fnmulDNMf" + } + } + }, + { -- FP conditional select. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = "fcselDNMCf" + } + } + } + }, + { -- FP data-processing, 3 sources. + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 21, mask = 5, + [0] = "fmaddDNMAf", "fnmaddDNMAf" + }, + { + shift = 21, mask = 5, + [0] = "fmsubDNMAf", "fnmsubDNMAf" + } + } + } + } +} + +local map_br = { -- Branches, exception generating and system instructions. + shift = 29, mask = 7, + [0] = "bB", + { -- Compare & branch, immediate. + shift = 24, mask = 3, + [0] = "cbzDBg", "cbnzDBg", "tbzDTBw", "tbnzDTBw" + }, + { -- Conditional branch, immediate. + shift = 24, mask = 3, + [0] = { + shift = 4, mask = 1, + [0] = { + shift = 0, mask = 15, + [0] = "beqB", "bneB", "bhsB", "bloB", "bmiB", "bplB", "bvsB", "bvcB", + "bhiB", "blsB", "bgeB", "bltB", "bgtB", "bleB", "balB" + } + } + }, false, "blB", + { -- Compare & branch, immediate. + shift = 24, mask = 3, + [0] = "cbzDBg", "cbnzDBg", "tbzDTBx", "tbnzDTBx" + }, + { + shift = 24, mask = 3, + [0] = { -- Exception generation. + shift = 0, mask = 0xe0001f, + [0x200000] = "brkW" + }, + { -- System instructions. + shift = 0, mask = 0x3fffff, + [0x03201f] = "nop" + }, + { -- Unconditional branch, register. + shift = 0, mask = 0xfffc1f, + [0x1f0000] = "brNx", [0x3f0000] = "blrNx", + [0x5f0000] = "retNx" + }, + } +} + +local map_init = { + shift = 25, mask = 15, + [0] = false, false, false, false, map_ls, map_datar, map_ls, map_datafp, + map_datai, map_datai, map_br, map_br, map_ls, map_datar, map_ls, map_datafp +} + +------------------------------------------------------------------------------ + +local map_regs = { x = {}, w = {}, d = {}, s = {} } + +for i=0,30 do + map_regs.x[i] = "x"..i + map_regs.w[i] = "w"..i + map_regs.d[i] = "d"..i + map_regs.s[i] = "s"..i +end +map_regs.x[31] = "sp" +map_regs.w[31] = "wsp" +map_regs.d[31] = "d31" +map_regs.s[31] = "s31" + +local map_cond = { + [0] = "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", +} + +local map_shift = { [0] = "lsl", "lsr", "asr", } + +local map_extend = { + [0] = "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx", +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then + extra = "\t->"..sym + end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-5s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-5s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +local function match_reg(p, pat, regnum) + return map_regs[match(pat, p.."%w-([xwds])")][regnum] +end + +local function fmt_hex32(x) + if x < 0 then + return tohex(x) + else + return format("%x", x) + end +end + +local imm13_rep = { 0x55555555, 0x11111111, 0x01010101, 0x00010001, 0x00000001 } + +local function decode_imm13(op) + local imms = band(rshift(op, 10), 63) + local immr = band(rshift(op, 16), 63) + if band(op, 0x00400000) == 0 then + local len = 5 + if imms >= 56 then + if imms >= 60 then len = 1 else len = 2 end + elseif imms >= 48 then len = 3 elseif imms >= 32 then len = 4 end + local l = lshift(1, len)-1 + local s = band(imms, l) + local r = band(immr, l) + local imm = ror(rshift(-1, 31-s), r) + if len ~= 5 then imm = band(imm, lshift(1, l)-1) + rshift(imm, 31-l) end + imm = imm * imm13_rep[len] + local ix = fmt_hex32(imm) + if rshift(op, 31) ~= 0 then + return ix..tohex(imm) + else + return ix + end + else + local lo, hi = -1, 0 + if imms < 32 then lo = rshift(-1, 31-imms) else hi = rshift(-1, 63-imms) end + if immr ~= 0 then + lo, hi = ror(lo, immr), ror(hi, immr) + local x = immr == 32 and 0 or band(bxor(lo, hi), lshift(-1, 32-immr)) + lo, hi = bxor(lo, x), bxor(hi, x) + if immr >= 32 then lo, hi = hi, lo end + end + if hi ~= 0 then + return fmt_hex32(hi)..tohex(lo) + else + return fmt_hex32(lo) + end + end +end + +local function parse_immpc(op, name) + if name == "b" or name == "bl" then + return arshift(lshift(op, 6), 4) + elseif name == "adr" or name == "adrp" then + local immlo = band(rshift(op, 29), 3) + local immhi = lshift(arshift(lshift(op, 8), 13), 2) + return bor(immhi, immlo) + elseif name == "tbz" or name == "tbnz" then + return lshift(arshift(lshift(op, 13), 18), 2) + else + return lshift(arshift(lshift(op, 8), 13), 2) + end +end + +local function parse_fpimm8(op) + local sign = band(op, 0x100000) == 0 and 1 or -1 + local exp = bxor(rshift(arshift(lshift(op, 12), 5), 24), 0x80) - 131 + local frac = 16+band(rshift(op, 13), 15) + return sign * frac * 2^exp +end + +local function prefer_bfx(sf, uns, imms, immr) + if imms < immr or imms == 31 or imms == 63 then + return false + end + if immr == 0 then + if sf == 0 and (imms == 7 or imms == 15) then + return false + end + if sf ~= 0 and uns == 0 and (imms == 7 or imms == 15 or imms == 31) then + return false + end + end + return true +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) + local operands = {} + local suffix = "" + local last, name, pat + local map_reg + ctx.op = op + ctx.rel = nil + last = nil + local opat + opat = map_init[band(rshift(op, 25), 15)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + name, pat = match(opat, "^([a-z0-9]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") + if altname then pat = pat2 end + if sub(pat, 1, 1) == "." then + local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") + suffix = suffix..s2 + pat = p2 + end + + local rt = match(pat, "[gf]") + if rt then + if rt == "g" then + map_reg = band(op, 0x80000000) ~= 0 and map_regs.x or map_regs.w + else + map_reg = band(op, 0x400000) ~= 0 and map_regs.d or map_regs.s + end + end + + local second0, immr + + for p in gmatch(pat, ".") do + local x = nil + if p == "D" then + local regnum = band(op, 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "N" then + local regnum = band(rshift(op, 5), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "M" then + local regnum = band(rshift(op, 16), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "A" then + local regnum = band(rshift(op, 10), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "B" then + local addr = ctx.addr + pos + parse_immpc(op, name) + ctx.rel = addr + x = "0x"..tohex(addr) + elseif p == "T" then + x = bor(band(rshift(op, 26), 32), band(rshift(op, 19), 31)) + elseif p == "V" then + x = band(op, 15) + elseif p == "C" then + x = map_cond[band(rshift(op, 12), 15)] + elseif p == "c" then + local rn = band(rshift(op, 5), 31) + local rm = band(rshift(op, 16), 31) + local cond = band(rshift(op, 12), 15) + local invc = bxor(cond, 1) + x = map_cond[cond] + if altname and cond ~= 14 and cond ~= 15 then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if rn == rm then + local n = #operands + operands[n] = nil + x = map_cond[invc] + if rn ~= 31 then + if a1 then name = a1 else name = altname end + else + operands[n-1] = nil + name = a2 + end + end + end + elseif p == "W" then + x = band(rshift(op, 5), 0xffff) + elseif p == "Y" then + x = band(rshift(op, 5), 0xffff) + local hw = band(rshift(op, 21), 3) + if altname and (hw == 0 or x ~= 0) then + name = altname + end + elseif p == "L" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local imm9 = arshift(lshift(op, 11), 23) + if band(op, 0x800) ~= 0 then + x = "["..rn..", #"..imm9.."]!" + else + x = "["..rn.."], #"..imm9 + end + elseif p == "U" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local sz = band(rshift(op, 30), 3) + local imm12 = lshift(arshift(lshift(op, 10), 20), sz) + if imm12 ~= 0 then + x = "["..rn..", #"..imm12.."]" + else + x = "["..rn.."]" + end + elseif p == "K" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local imm9 = arshift(lshift(op, 11), 23) + if imm9 ~= 0 then + x = "["..rn..", #"..imm9.."]" + else + x = "["..rn.."]" + end + elseif p == "O" then + local rn, rm = map_regs.x[band(rshift(op, 5), 31)] + local m = band(rshift(op, 13), 1) + if m == 0 then + rm = map_regs.w[band(rshift(op, 16), 31)] + else + rm = map_regs.x[band(rshift(op, 16), 31)] + end + x = "["..rn..", "..rm + local opt = band(rshift(op, 13), 7) + local s = band(rshift(op, 12), 1) + local sz = band(rshift(op, 30), 3) + -- extension to be applied + if opt == 3 then + if s == 0 then x = x.."]" + else x = x..", lsl #"..sz.."]" end + elseif opt == 2 or opt == 6 or opt == 7 then + if s == 0 then x = x..", "..map_extend[opt].."]" + else x = x..", "..map_extend[opt].." #"..sz.."]" end + else + x = x.."]" + end + elseif p == "P" then + local opcv, sh = rshift(op, 26), 2 + if opcv >= 0x2a then sh = 4 elseif opcv >= 0x1b then sh = 3 end + local imm7 = lshift(arshift(lshift(op, 10), 25), sh) + local rn = map_regs.x[band(rshift(op, 5), 31)] + local ind = band(rshift(op, 23), 3) + if ind == 1 then + x = "["..rn.."], #"..imm7 + elseif ind == 2 then + if imm7 == 0 then + x = "["..rn.."]" + else + x = "["..rn..", #"..imm7.."]" + end + elseif ind == 3 then + x = "["..rn..", #"..imm7.."]!" + end + elseif p == "I" then + local shf = band(rshift(op, 22), 3) + local imm12 = band(rshift(op, 10), 0x0fff) + local rn, rd = band(rshift(op, 5), 31), band(op, 31) + if altname == "mov" and shf == 0 and imm12 == 0 and (rn == 31 or rd == 31) then + name = altname + x = nil + elseif shf == 0 then + x = imm12 + elseif shf == 1 then + x = imm12..", lsl #12" + end + elseif p == "i" then + x = "#0x"..decode_imm13(op) + elseif p == "1" then + immr = band(rshift(op, 16), 63) + x = immr + elseif p == "2" then + x = band(rshift(op, 10), 63) + if altname then + local a1, a2, a3, a4, a5, a6 = + match(altname, "([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)|(.*)") + local sf = band(rshift(op, 26), 32) + local uns = band(rshift(op, 30), 1) + if prefer_bfx(sf, uns, x, immr) then + name = a2 + x = x - immr + 1 + elseif immr == 0 and x == 7 then + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + name = a6 + x = nil + elseif immr == 0 and x == 15 then + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + name = a5 + x = nil + elseif x == 31 or x == 63 then + if x == 31 and immr == 0 and name == "sbfm" then + name = a4 + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + else + name = a3 + end + x = nil + elseif band(x, 31) ~= 31 and immr == x+1 and name == "ubfm" then + name = a4 + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = nil + elseif x < immr then + name = a1 + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = x + 1 + end + end + elseif p == "3" then + x = band(rshift(op, 10), 63) + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if x < immr then + name = a1 + local sf = band(rshift(op, 26), 32) + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = x + 1 + else + name = a2 + x = x - immr + 1 + end + end + elseif p == "4" then + x = band(rshift(op, 10), 63) + local rn = band(rshift(op, 5), 31) + local rm = band(rshift(op, 16), 31) + if altname and rn == rm then + local n = #operands + operands[n] = nil + last = operands[n-1] + name = altname + end + elseif p == "5" then + x = band(rshift(op, 16), 31) + elseif p == "S" then + x = band(rshift(op, 10), 63) + if x == 0 then x = nil + else x = map_shift[band(rshift(op, 22), 3)].." #"..x end + elseif p == "X" then + local opt = band(rshift(op, 13), 7) + -- Width specifier . + if opt ~= 3 and opt ~= 7 then + last = map_regs.w[band(rshift(op, 16), 31)] + operands[#operands] = last + end + x = band(rshift(op, 10), 7) + -- Extension. + if opt == 2 + band(rshift(op, 31), 1) and + band(rshift(op, second0 and 5 or 0), 31) == 31 then + if x == 0 then x = nil + else x = "lsl #"..x end + else + if x == 0 then x = map_extend[band(rshift(op, 13), 7)] + else x = map_extend[band(rshift(op, 13), 7)].." #"..x end + end + elseif p == "R" then + x = band(rshift(op,21), 3) + if x == 0 then x = nil + else x = "lsl #"..x*16 end + elseif p == "z" then + local n = #operands + if operands[n] == "sp" then operands[n] = "xzr" + elseif operands[n] == "wsp" then operands[n] = "wzr" + end + elseif p == "Z" then + x = 0 + elseif p == "F" then + x = parse_fpimm8(op) + elseif p == "g" or p == "f" or p == "x" or p == "w" or + p == "d" or p == "s" then + -- These are handled in D/N/M/A. + elseif p == "0" then + if last == "sp" or last == "wsp" then + local n = #operands + operands[n] = nil + last = operands[n-1] + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if not a1 then + name = altname + elseif second0 then + name, altname = a2, a1 + else + name, altname = a1, a2 + end + end + end + second0 = true + else + assert(false) + end + if x then + last = x + if type(x) == "number" then x = "#"..x end + operands[#operands+1] = x + end + end + + return putop(ctx, name..suffix, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ctx.pos = ofs + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_regs.x[r] end + return map_regs.d[r-32] +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm64be.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm64be.lua new file mode 100644 index 00000000..edcbffa8 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_arm64be.lua @@ -0,0 +1,12 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM64BE disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- ARM64 instructions are always little-endian. So just forward to the +-- common ARM64 disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +return require((string.match(..., ".*%.") or "").."dis_arm64") + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips.lua new file mode 100644 index 00000000..6ad17f54 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips.lua @@ -0,0 +1,694 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT/X license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles all standard MIPS32R1/R2 instructions. +-- Default mode is big-endian, but see: dis_mipsel.lua +------------------------------------------------------------------------------ + +local type = type +local byte, format = string.byte, string.format +local match, gmatch = string.match, string.gmatch +local concat = table.concat +local bit = require("bit") +local band, bor, tohex = bit.band, bit.bor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Extended opcode maps common to all MIPS releases +------------------------------------------------------------------------------ + +local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", } +local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", } + +local map_cop0 = { + shift = 25, mask = 1, + [0] = { + shift = 21, mask = 15, + [0] = "mfc0TDW", [4] = "mtc0TDW", + [10] = "rdpgprDT", + [11] = { shift = 5, mask = 1, [0] = "diT0", "eiT0", }, + [14] = "wrpgprDT", + }, { + shift = 0, mask = 63, + [1] = "tlbr", [2] = "tlbwi", [6] = "tlbwr", [8] = "tlbp", + [24] = "eret", [31] = "deret", + [32] = "wait", + }, +} + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps for MIPS R1-R5 +------------------------------------------------------------------------------ + +local map_movci = { shift = 16, mask = 1, [0] = "movfDSC", "movtDSC", } + +local map_special = { + shift = 0, mask = 63, + [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, + map_movci, map_srl, "sraDTA", + "sllvDTS", false, map_srlv, "sravDTS", + "jrS", "jalrD1S", "movzDST", "movnDST", + "syscallY", "breakY", false, "sync", + "mfhiD", "mthiS", "mfloD", "mtloS", + "dsllvDST", false, "dsrlvDST", "dsravDST", + "multST", "multuST", "divST", "divuST", + "dmultST", "dmultuST", "ddivST", "ddivuST", + "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", + "andDST", "or|moveDST0", "xorDST", "nor|notDST0", + false, false, "sltDST", "sltuDST", + "daddDST", "dadduDST", "dsubDST", "dsubuDST", + "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", + "teqSTZ", false, "tneSTZ", false, + "dsllDTA", false, "dsrlDTA", "dsraDTA", + "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", +} + +local map_special2 = { + shift = 0, mask = 63, + [0] = "maddST", "madduST", "mulDST", false, + "msubST", "msubuST", + [32] = "clzDS", [33] = "cloDS", + [63] = "sdbbpY", +} + +local map_bshfl = { + shift = 6, mask = 31, + [2] = "wsbhDT", + [16] = "sebDT", + [24] = "sehDT", +} + +local map_dbshfl = { + shift = 6, mask = 31, + [2] = "dsbhDT", + [5] = "dshdDT", +} + +local map_special3 = { + shift = 0, mask = 63, + [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", + [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", + [32] = map_bshfl, [36] = map_dbshfl, [59] = "rdhwrTD", +} + +local map_regimm = { + shift = 16, mask = 31, + [0] = "bltzSB", "bgezSB", "bltzlSB", "bgezlSB", + false, false, false, false, + "tgeiSI", "tgeiuSI", "tltiSI", "tltiuSI", + "teqiSI", false, "tneiSI", false, + "bltzalSB", "bgezalSB", "bltzallSB", "bgezallSB", + false, false, false, false, + false, false, false, false, + false, false, false, "synciSO", +} + +local map_cop1s = { + shift = 0, mask = 63, + [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", + "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG", + "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG", + "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG", + false, + { shift = 16, mask = 1, [0] = "movf.sFGC", "movt.sFGC" }, + "movz.sFGT", "movn.sFGT", + false, "recip.sFG", "rsqrt.sFG", false, + false, false, false, false, + false, false, false, false, + false, "cvt.d.sFG", false, false, + "cvt.w.sFG", "cvt.l.sFG", "cvt.ps.sFGH", false, + false, false, false, false, + false, false, false, false, + "c.f.sVGH", "c.un.sVGH", "c.eq.sVGH", "c.ueq.sVGH", + "c.olt.sVGH", "c.ult.sVGH", "c.ole.sVGH", "c.ule.sVGH", + "c.sf.sVGH", "c.ngle.sVGH", "c.seq.sVGH", "c.ngl.sVGH", + "c.lt.sVGH", "c.nge.sVGH", "c.le.sVGH", "c.ngt.sVGH", +} + +local map_cop1d = { + shift = 0, mask = 63, + [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH", + "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG", + "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG", + "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG", + false, + { shift = 16, mask = 1, [0] = "movf.dFGC", "movt.dFGC" }, + "movz.dFGT", "movn.dFGT", + false, "recip.dFG", "rsqrt.dFG", false, + false, false, false, false, + false, false, false, false, + "cvt.s.dFG", false, false, false, + "cvt.w.dFG", "cvt.l.dFG", false, false, + false, false, false, false, + false, false, false, false, + "c.f.dVGH", "c.un.dVGH", "c.eq.dVGH", "c.ueq.dVGH", + "c.olt.dVGH", "c.ult.dVGH", "c.ole.dVGH", "c.ule.dVGH", + "c.df.dVGH", "c.ngle.dVGH", "c.deq.dVGH", "c.ngl.dVGH", + "c.lt.dVGH", "c.nge.dVGH", "c.le.dVGH", "c.ngt.dVGH", +} + +local map_cop1ps = { + shift = 0, mask = 63, + [0] = "add.psFGH", "sub.psFGH", "mul.psFGH", false, + false, "abs.psFG", "mov.psFG", "neg.psFG", + false, false, false, false, + false, false, false, false, + false, + { shift = 16, mask = 1, [0] = "movf.psFGC", "movt.psFGC" }, + "movz.psFGT", "movn.psFGT", + false, false, false, false, + false, false, false, false, + false, false, false, false, + "cvt.s.puFG", false, false, false, + false, false, false, false, + "cvt.s.plFG", false, false, false, + "pll.psFGH", "plu.psFGH", "pul.psFGH", "puu.psFGH", + "c.f.psVGH", "c.un.psVGH", "c.eq.psVGH", "c.ueq.psVGH", + "c.olt.psVGH", "c.ult.psVGH", "c.ole.psVGH", "c.ule.psVGH", + "c.psf.psVGH", "c.ngle.psVGH", "c.pseq.psVGH", "c.ngl.psVGH", + "c.lt.psVGH", "c.nge.psVGH", "c.le.psVGH", "c.ngt.psVGH", +} + +local map_cop1w = { + shift = 0, mask = 63, + [32] = "cvt.s.wFG", [33] = "cvt.d.wFG", +} + +local map_cop1l = { + shift = 0, mask = 63, + [32] = "cvt.s.lFG", [33] = "cvt.d.lFG", +} + +local map_cop1bc = { + shift = 16, mask = 3, + [0] = "bc1fCB", "bc1tCB", "bc1flCB", "bc1tlCB", +} + +local map_cop1 = { + shift = 21, mask = 31, + [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", + "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", + map_cop1bc, false, false, false, + false, false, false, false, + map_cop1s, map_cop1d, false, false, + map_cop1w, map_cop1l, map_cop1ps, +} + +local map_cop1x = { + shift = 0, mask = 63, + [0] = "lwxc1FSX", "ldxc1FSX", false, false, + false, "luxc1FSX", false, false, + "swxc1FSX", "sdxc1FSX", false, false, + false, "suxc1FSX", false, "prefxMSX", + false, false, false, false, + false, false, false, false, + false, false, false, false, + false, false, "alnv.psFGHS", false, + "madd.sFRGH", "madd.dFRGH", false, false, + false, false, "madd.psFRGH", false, + "msub.sFRGH", "msub.dFRGH", false, false, + false, false, "msub.psFRGH", false, + "nmadd.sFRGH", "nmadd.dFRGH", false, false, + false, false, "nmadd.psFRGH", false, + "nmsub.sFRGH", "nmsub.dFRGH", false, false, + false, false, "nmsub.psFRGH", false, +} + +local map_pri = { + [0] = map_special, map_regimm, "jJ", "jalJ", + "beq|beqz|bST00B", "bne|bnezST0B", "blezSB", "bgtzSB", + "addiTSI", "addiu|liTS0I", "sltiTSI", "sltiuTSI", + "andiTSU", "ori|liTS0U", "xoriTSU", "luiTU", + map_cop0, map_cop1, false, map_cop1x, + "beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB", + "daddiTSI", "daddiuTSI", false, false, + map_special2, "jalxJ", false, map_special3, + "lbTSO", "lhTSO", "lwlTSO", "lwTSO", + "lbuTSO", "lhuTSO", "lwrTSO", false, + "sbTSO", "shTSO", "swlTSO", "swTSO", + false, false, "swrTSO", "cacheNSO", + "llTSO", "lwc1HSO", "lwc2TSO", "prefNSO", + false, "ldc1HSO", "ldc2TSO", "ldTSO", + "scTSO", "swc1HSO", "swc2TSO", false, + false, "sdc1HSO", "sdc2TSO", "sdTSO", +} + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps for MIPS R6 +------------------------------------------------------------------------------ + +local map_mul_r6 = { shift = 6, mask = 3, [2] = "mulDST", [3] = "muhDST" } +local map_mulu_r6 = { shift = 6, mask = 3, [2] = "muluDST", [3] = "muhuDST" } +local map_div_r6 = { shift = 6, mask = 3, [2] = "divDST", [3] = "modDST" } +local map_divu_r6 = { shift = 6, mask = 3, [2] = "divuDST", [3] = "moduDST" } +local map_dmul_r6 = { shift = 6, mask = 3, [2] = "dmulDST", [3] = "dmuhDST" } +local map_dmulu_r6 = { shift = 6, mask = 3, [2] = "dmuluDST", [3] = "dmuhuDST" } +local map_ddiv_r6 = { shift = 6, mask = 3, [2] = "ddivDST", [3] = "dmodDST" } +local map_ddivu_r6 = { shift = 6, mask = 3, [2] = "ddivuDST", [3] = "dmoduDST" } + +local map_special_r6 = { + shift = 0, mask = 63, + [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, + false, map_srl, "sraDTA", + "sllvDTS", false, map_srlv, "sravDTS", + "jrS", "jalrD1S", false, false, + "syscallY", "breakY", false, "sync", + "clzDS", "cloDS", "dclzDS", "dcloDS", + "dsllvDST", "dlsaDSTA", "dsrlvDST", "dsravDST", + map_mul_r6, map_mulu_r6, map_div_r6, map_divu_r6, + map_dmul_r6, map_dmulu_r6, map_ddiv_r6, map_ddivu_r6, + "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", + "andDST", "or|moveDST0", "xorDST", "nor|notDST0", + false, false, "sltDST", "sltuDST", + "daddDST", "dadduDST", "dsubDST", "dsubuDST", + "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", + "teqSTZ", "seleqzDST", "tneSTZ", "selnezDST", + "dsllDTA", false, "dsrlDTA", "dsraDTA", + "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", +} + +local map_bshfl_r6 = { + shift = 9, mask = 3, + [1] = "alignDSTa", + _ = { + shift = 6, mask = 31, + [0] = "bitswapDT", + [2] = "wsbhDT", + [16] = "sebDT", + [24] = "sehDT", + } +} + +local map_dbshfl_r6 = { + shift = 9, mask = 3, + [1] = "dalignDSTa", + _ = { + shift = 6, mask = 31, + [0] = "dbitswapDT", + [2] = "dsbhDT", + [5] = "dshdDT", + } +} + +local map_special3_r6 = { + shift = 0, mask = 63, + [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", + [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", + [32] = map_bshfl_r6, [36] = map_dbshfl_r6, [59] = "rdhwrTD", +} + +local map_regimm_r6 = { + shift = 16, mask = 31, + [0] = "bltzSB", [1] = "bgezSB", + [6] = "dahiSI", [30] = "datiSI", + [23] = "sigrieI", [31] = "synciSO", +} + +local map_pcrel_r6 = { + shift = 19, mask = 3, + [0] = "addiupcS2", "lwpcS2", "lwupcS2", { + shift = 18, mask = 1, + [0] = "ldpcS3", { shift = 16, mask = 3, [2] = "auipcSI", [3] = "aluipcSI" } + } +} + +local map_cop1s_r6 = { + shift = 0, mask = 63, + [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", + "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG", + "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG", + "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG", + "sel.sFGH", false, false, false, + "seleqz.sFGH", "recip.sFG", "rsqrt.sFG", "selnez.sFGH", + "maddf.sFGH", "msubf.sFGH", "rint.sFG", "class.sFG", + "min.sFGH", "mina.sFGH", "max.sFGH", "maxa.sFGH", + false, "cvt.d.sFG", false, false, + "cvt.w.sFG", "cvt.l.sFG", +} + +local map_cop1d_r6 = { + shift = 0, mask = 63, + [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH", + "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG", + "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG", + "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG", + "sel.dFGH", false, false, false, + "seleqz.dFGH", "recip.dFG", "rsqrt.dFG", "selnez.dFGH", + "maddf.dFGH", "msubf.dFGH", "rint.dFG", "class.dFG", + "min.dFGH", "mina.dFGH", "max.dFGH", "maxa.dFGH", + "cvt.s.dFG", false, false, false, + "cvt.w.dFG", "cvt.l.dFG", +} + +local map_cop1w_r6 = { + shift = 0, mask = 63, + [0] = "cmp.af.sFGH", "cmp.un.sFGH", "cmp.eq.sFGH", "cmp.ueq.sFGH", + "cmp.lt.sFGH", "cmp.ult.sFGH", "cmp.le.sFGH", "cmp.ule.sFGH", + "cmp.saf.sFGH", "cmp.sun.sFGH", "cmp.seq.sFGH", "cmp.sueq.sFGH", + "cmp.slt.sFGH", "cmp.sult.sFGH", "cmp.sle.sFGH", "cmp.sule.sFGH", + false, "cmp.or.sFGH", "cmp.une.sFGH", "cmp.ne.sFGH", + false, false, false, false, + false, "cmp.sor.sFGH", "cmp.sune.sFGH", "cmp.sne.sFGH", + false, false, false, false, + "cvt.s.wFG", "cvt.d.wFG", +} + +local map_cop1l_r6 = { + shift = 0, mask = 63, + [0] = "cmp.af.dFGH", "cmp.un.dFGH", "cmp.eq.dFGH", "cmp.ueq.dFGH", + "cmp.lt.dFGH", "cmp.ult.dFGH", "cmp.le.dFGH", "cmp.ule.dFGH", + "cmp.saf.dFGH", "cmp.sun.dFGH", "cmp.seq.dFGH", "cmp.sueq.dFGH", + "cmp.slt.dFGH", "cmp.sult.dFGH", "cmp.sle.dFGH", "cmp.sule.dFGH", + false, "cmp.or.dFGH", "cmp.une.dFGH", "cmp.ne.dFGH", + false, false, false, false, + false, "cmp.sor.dFGH", "cmp.sune.dFGH", "cmp.sne.dFGH", + false, false, false, false, + "cvt.s.lFG", "cvt.d.lFG", +} + +local map_cop1_r6 = { + shift = 21, mask = 31, + [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", + "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", + false, "bc1eqzHB", false, false, + false, "bc1nezHB", false, false, + map_cop1s_r6, map_cop1d_r6, false, false, + map_cop1w_r6, map_cop1l_r6, +} + +local function maprs_popTS(rs, rt) + if rt == 0 then return 0 elseif rs == 0 then return 1 + elseif rs == rt then return 2 else return 3 end +end + +local map_pop06_r6 = { + maprs = maprs_popTS, [0] = "blezSB", "blezalcTB", "bgezalcTB", "bgeucSTB" +} +local map_pop07_r6 = { + maprs = maprs_popTS, [0] = "bgtzSB", "bgtzalcTB", "bltzalcTB", "bltucSTB" +} +local map_pop26_r6 = { + maprs = maprs_popTS, "blezcTB", "bgezcTB", "bgecSTB" +} +local map_pop27_r6 = { + maprs = maprs_popTS, "bgtzcTB", "bltzcTB", "bltcSTB" +} + +local function maprs_popS(rs, rt) + if rs == 0 then return 0 else return 1 end +end + +local map_pop66_r6 = { + maprs = maprs_popS, [0] = "jicTI", "beqzcSb" +} +local map_pop76_r6 = { + maprs = maprs_popS, [0] = "jialcTI", "bnezcSb" +} + +local function maprs_popST(rs, rt) + if rs >= rt then return 0 elseif rs == 0 then return 1 else return 2 end +end + +local map_pop10_r6 = { + maprs = maprs_popST, [0] = "bovcSTB", "beqzalcTB", "beqcSTB" +} +local map_pop30_r6 = { + maprs = maprs_popST, [0] = "bnvcSTB", "bnezalcTB", "bnecSTB" +} + +local map_pri_r6 = { + [0] = map_special_r6, map_regimm_r6, "jJ", "jalJ", + "beq|beqz|bST00B", "bne|bnezST0B", map_pop06_r6, map_pop07_r6, + map_pop10_r6, "addiu|liTS0I", "sltiTSI", "sltiuTSI", + "andiTSU", "ori|liTS0U", "xoriTSU", "aui|luiTS0U", + map_cop0, map_cop1_r6, false, false, + false, false, map_pop26_r6, map_pop27_r6, + map_pop30_r6, "daddiuTSI", false, false, + false, "dauiTSI", false, map_special3_r6, + "lbTSO", "lhTSO", false, "lwTSO", + "lbuTSO", "lhuTSO", false, false, + "sbTSO", "shTSO", false, "swTSO", + false, false, false, false, + false, "lwc1HSO", "bc#", false, + false, "ldc1HSO", map_pop66_r6, "ldTSO", + false, "swc1HSO", "balc#", map_pcrel_r6, + false, "sdc1HSO", map_pop76_r6, "sdTSO", +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "sp", "r30", "ra", +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then extra = "\t->"..sym end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-7s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-7s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +local function get_be(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + return bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3) +end + +local function get_le(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + return bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local op = ctx:get() + local operands = {} + local last = nil + ctx.op = op + ctx.rel = nil + + local opat = ctx.map_pri[rshift(op, 26)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + if opat.maprs then + opat = opat[opat.maprs(band(rshift(op,21),31), band(rshift(op,16),31))] + else + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + end + local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") + if altname then pat = pat2 end + + for p in gmatch(pat, ".") do + local x = nil + if p == "S" then + x = map_gpr[band(rshift(op, 21), 31)] + elseif p == "T" then + x = map_gpr[band(rshift(op, 16), 31)] + elseif p == "D" then + x = map_gpr[band(rshift(op, 11), 31)] + elseif p == "F" then + x = "f"..band(rshift(op, 6), 31) + elseif p == "G" then + x = "f"..band(rshift(op, 11), 31) + elseif p == "H" then + x = "f"..band(rshift(op, 16), 31) + elseif p == "R" then + x = "f"..band(rshift(op, 21), 31) + elseif p == "A" then + x = band(rshift(op, 6), 31) + elseif p == "a" then + x = band(rshift(op, 6), 7) + elseif p == "E" then + x = band(rshift(op, 6), 31) + 32 + elseif p == "M" then + x = band(rshift(op, 11), 31) + elseif p == "N" then + x = band(rshift(op, 16), 31) + elseif p == "C" then + x = band(rshift(op, 18), 7) + if x == 0 then x = nil end + elseif p == "K" then + x = band(rshift(op, 11), 31) + 1 + elseif p == "P" then + x = band(rshift(op, 11), 31) + 33 + elseif p == "L" then + x = band(rshift(op, 11), 31) - last + 1 + elseif p == "Q" then + x = band(rshift(op, 11), 31) - last + 33 + elseif p == "I" then + x = arshift(lshift(op, 16), 16) + elseif p == "2" then + x = arshift(lshift(op, 13), 11) + elseif p == "3" then + x = arshift(lshift(op, 14), 11) + elseif p == "U" then + x = band(op, 0xffff) + elseif p == "O" then + local disp = arshift(lshift(op, 16), 16) + operands[#operands] = format("%d(%s)", disp, last) + elseif p == "X" then + local index = map_gpr[band(rshift(op, 16), 31)] + operands[#operands] = format("%s(%s)", index, last) + elseif p == "B" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 14) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "b" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 11), 9) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "#" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 6), 4) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "J" then + local a = ctx.addr + ctx.pos + x = a - band(a, 0x0fffffff) + band(op, 0x03ffffff)*4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "V" then + x = band(rshift(op, 8), 7) + if x == 0 then x = nil end + elseif p == "W" then + x = band(op, 7) + if x == 0 then x = nil end + elseif p == "Y" then + x = band(rshift(op, 6), 0x000fffff) + if x == 0 then x = nil end + elseif p == "Z" then + x = band(rshift(op, 6), 1023) + if x == 0 then x = nil end + elseif p == "0" then + if last == "r0" or last == 0 then + local n = #operands + operands[n] = nil + last = operands[n-1] + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if a1 then name, altname = a1, a2 + else name = altname end + end + end + elseif p == "1" then + if last == "ra" then + operands[#operands] = nil + end + else + assert(false) + end + if x then operands[#operands+1] = x; last = x end + end + + return putop(ctx, name, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + stop = stop - stop % 4 + ctx.pos = ofs - ofs % 4 + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + ctx.get = get_be + ctx.map_pri = map_pri + return ctx +end + +local function create_el(code, addr, out) + local ctx = create(code, addr, out) + ctx.get = get_le + return ctx +end + +local function create_r6(code, addr, out) + local ctx = create(code, addr, out) + ctx.map_pri = map_pri_r6 + return ctx +end + +local function create_r6_el(code, addr, out) + local ctx = create(code, addr, out) + ctx.get = get_le + ctx.map_pri = map_pri_r6 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +local function disass_el(code, addr, out) + create_el(code, addr, out):disass() +end + +local function disass_r6(code, addr, out) + create_r6(code, addr, out):disass() +end + +local function disass_r6_el(code, addr, out) + create_r6_el(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_gpr[r] end + return "f"..(r-32) +end + +-- Public module functions. +return { + create = create, + create_el = create_el, + create_r6 = create_r6, + create_r6_el = create_r6_el, + disass = disass, + disass_el = disass_el, + disass_r6 = disass_r6, + disass_r6_el = disass_r6_el, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64.lua new file mode 100644 index 00000000..5ad48f8f --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the big-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create, + disass = dis_mips.disass, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64el.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64el.lua new file mode 100644 index 00000000..d50e3a18 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64el.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64EL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_el, + disass = dis_mips.disass_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64r6.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64r6.lua new file mode 100644 index 00000000..921b3cbe --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64r6.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64R6 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the r6 big-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_r6, + disass = dis_mips.disass_r6, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64r6el.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64r6el.lua new file mode 100644 index 00000000..aadef9f3 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mips64r6el.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64R6EL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the r6 little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_r6_el, + disass = dis_mips.disass_r6_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mipsel.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mipsel.lua new file mode 100644 index 00000000..52cebefb --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_mipsel.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPSEL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_el, + disass = dis_mips.disass_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_ppc.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_ppc.lua new file mode 100644 index 00000000..08d742f1 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_ppc.lua @@ -0,0 +1,591 @@ +---------------------------------------------------------------------------- +-- LuaJIT PPC disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT/X license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles all common, non-privileged 32/64 bit PowerPC instructions +-- plus the e500 SPE instructions and some Cell/Xenon extensions. +-- +-- NYI: VMX, VMX128 +------------------------------------------------------------------------------ + +local type = type +local byte, format = string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local concat = table.concat +local bit = require("bit") +local band, bor, tohex = bit.band, bit.bor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps +------------------------------------------------------------------------------ + +local map_crops = { + shift = 1, mask = 1023, + [0] = "mcrfXX", + [33] = "crnor|crnotCCC=", [129] = "crandcCCC", + [193] = "crxor|crclrCCC%", [225] = "crnandCCC", + [257] = "crandCCC", [289] = "creqv|crsetCCC%", + [417] = "crorcCCC", [449] = "cror|crmoveCCC=", + [16] = "b_lrKB", [528] = "b_ctrKB", + [150] = "isync", +} + +local map_rlwinm = setmetatable({ + shift = 0, mask = -1, +}, +{ __index = function(t, x) + local rot = band(rshift(x, 11), 31) + local mb = band(rshift(x, 6), 31) + local me = band(rshift(x, 1), 31) + if mb == 0 and me == 31-rot then + return "slwiRR~A." + elseif me == 31 and mb == 32-rot then + return "srwiRR~-A." + else + return "rlwinmRR~AAA." + end + end +}) + +local map_rld = { + shift = 2, mask = 7, + [0] = "rldiclRR~HM.", "rldicrRR~HM.", "rldicRR~HM.", "rldimiRR~HM.", + { + shift = 1, mask = 1, + [0] = "rldclRR~RM.", "rldcrRR~RM.", + }, +} + +local map_ext = setmetatable({ + shift = 1, mask = 1023, + + [0] = "cmp_YLRR", [32] = "cmpl_YLRR", + [4] = "twARR", [68] = "tdARR", + + [8] = "subfcRRR.", [40] = "subfRRR.", + [104] = "negRR.", [136] = "subfeRRR.", + [200] = "subfzeRR.", [232] = "subfmeRR.", + [520] = "subfcoRRR.", [552] = "subfoRRR.", + [616] = "negoRR.", [648] = "subfeoRRR.", + [712] = "subfzeoRR.", [744] = "subfmeoRR.", + + [9] = "mulhduRRR.", [73] = "mulhdRRR.", [233] = "mulldRRR.", + [457] = "divduRRR.", [489] = "divdRRR.", + [745] = "mulldoRRR.", + [969] = "divduoRRR.", [1001] = "divdoRRR.", + + [10] = "addcRRR.", [138] = "addeRRR.", + [202] = "addzeRR.", [234] = "addmeRR.", [266] = "addRRR.", + [522] = "addcoRRR.", [650] = "addeoRRR.", + [714] = "addzeoRR.", [746] = "addmeoRR.", [778] = "addoRRR.", + + [11] = "mulhwuRRR.", [75] = "mulhwRRR.", [235] = "mullwRRR.", + [459] = "divwuRRR.", [491] = "divwRRR.", + [747] = "mullwoRRR.", + [971] = "divwouRRR.", [1003] = "divwoRRR.", + + [15] = "iselltRRR", [47] = "iselgtRRR", [79] = "iseleqRRR", + + [144] = { shift = 20, mask = 1, [0] = "mtcrfRZ~", "mtocrfRZ~", }, + [19] = { shift = 20, mask = 1, [0] = "mfcrR", "mfocrfRZ", }, + [371] = { shift = 11, mask = 1023, [392] = "mftbR", [424] = "mftbuR", }, + [339] = { + shift = 11, mask = 1023, + [32] = "mferR", [256] = "mflrR", [288] = "mfctrR", [16] = "mfspefscrR", + }, + [467] = { + shift = 11, mask = 1023, + [32] = "mtxerR", [256] = "mtlrR", [288] = "mtctrR", [16] = "mtspefscrR", + }, + + [20] = "lwarxRR0R", [84] = "ldarxRR0R", + + [21] = "ldxRR0R", [53] = "lduxRRR", + [149] = "stdxRR0R", [181] = "stduxRRR", + [341] = "lwaxRR0R", [373] = "lwauxRRR", + + [23] = "lwzxRR0R", [55] = "lwzuxRRR", + [87] = "lbzxRR0R", [119] = "lbzuxRRR", + [151] = "stwxRR0R", [183] = "stwuxRRR", + [215] = "stbxRR0R", [247] = "stbuxRRR", + [279] = "lhzxRR0R", [311] = "lhzuxRRR", + [343] = "lhaxRR0R", [375] = "lhauxRRR", + [407] = "sthxRR0R", [439] = "sthuxRRR", + + [54] = "dcbst-R0R", [86] = "dcbf-R0R", + [150] = "stwcxRR0R.", [214] = "stdcxRR0R.", + [246] = "dcbtst-R0R", [278] = "dcbt-R0R", + [310] = "eciwxRR0R", [438] = "ecowxRR0R", + [470] = "dcbi-RR", + + [598] = { + shift = 21, mask = 3, + [0] = "sync", "lwsync", "ptesync", + }, + [758] = "dcba-RR", + [854] = "eieio", [982] = "icbi-R0R", [1014] = "dcbz-R0R", + + [26] = "cntlzwRR~", [58] = "cntlzdRR~", + [122] = "popcntbRR~", + [154] = "prtywRR~", [186] = "prtydRR~", + + [28] = "andRR~R.", [60] = "andcRR~R.", [124] = "nor|notRR~R=.", + [284] = "eqvRR~R.", [316] = "xorRR~R.", + [412] = "orcRR~R.", [444] = "or|mrRR~R=.", [476] = "nandRR~R.", + [508] = "cmpbRR~R", + + [512] = "mcrxrX", + + [532] = "ldbrxRR0R", [660] = "stdbrxRR0R", + + [533] = "lswxRR0R", [597] = "lswiRR0A", + [661] = "stswxRR0R", [725] = "stswiRR0A", + + [534] = "lwbrxRR0R", [662] = "stwbrxRR0R", + [790] = "lhbrxRR0R", [918] = "sthbrxRR0R", + + [535] = "lfsxFR0R", [567] = "lfsuxFRR", + [599] = "lfdxFR0R", [631] = "lfduxFRR", + [663] = "stfsxFR0R", [695] = "stfsuxFRR", + [727] = "stfdxFR0R", [759] = "stfduxFR0R", + [855] = "lfiwaxFR0R", + [983] = "stfiwxFR0R", + + [24] = "slwRR~R.", + + [27] = "sldRR~R.", [536] = "srwRR~R.", + [792] = "srawRR~R.", [824] = "srawiRR~A.", + + [794] = "sradRR~R.", [826] = "sradiRR~H.", [827] = "sradiRR~H.", + [922] = "extshRR~.", [954] = "extsbRR~.", [986] = "extswRR~.", + + [539] = "srdRR~R.", +}, +{ __index = function(t, x) + if band(x, 31) == 15 then return "iselRRRC" end + end +}) + +local map_ld = { + shift = 0, mask = 3, + [0] = "ldRRE", "lduRRE", "lwaRRE", +} + +local map_std = { + shift = 0, mask = 3, + [0] = "stdRRE", "stduRRE", +} + +local map_fps = { + shift = 5, mask = 1, + { + shift = 1, mask = 15, + [0] = false, false, "fdivsFFF.", false, + "fsubsFFF.", "faddsFFF.", "fsqrtsF-F.", false, + "fresF-F.", "fmulsFF-F.", "frsqrtesF-F.", false, + "fmsubsFFFF~.", "fmaddsFFFF~.", "fnmsubsFFFF~.", "fnmaddsFFFF~.", + } +} + +local map_fpd = { + shift = 5, mask = 1, + [0] = { + shift = 1, mask = 1023, + [0] = "fcmpuXFF", [32] = "fcmpoXFF", [64] = "mcrfsXX", + [38] = "mtfsb1A.", [70] = "mtfsb0A.", [134] = "mtfsfiA>>-A>", + [8] = "fcpsgnFFF.", [40] = "fnegF-F.", [72] = "fmrF-F.", + [136] = "fnabsF-F.", [264] = "fabsF-F.", + [12] = "frspF-F.", + [14] = "fctiwF-F.", [15] = "fctiwzF-F.", + [583] = "mffsF.", [711] = "mtfsfZF.", + [392] = "frinF-F.", [424] = "frizF-F.", + [456] = "fripF-F.", [488] = "frimF-F.", + [814] = "fctidF-F.", [815] = "fctidzF-F.", [846] = "fcfidF-F.", + }, + { + shift = 1, mask = 15, + [0] = false, false, "fdivFFF.", false, + "fsubFFF.", "faddFFF.", "fsqrtF-F.", "fselFFFF~.", + "freF-F.", "fmulFF-F.", "frsqrteF-F.", false, + "fmsubFFFF~.", "fmaddFFFF~.", "fnmsubFFFF~.", "fnmaddFFFF~.", + } +} + +local map_spe = { + shift = 0, mask = 2047, + + [512] = "evaddwRRR", [514] = "evaddiwRAR~", + [516] = "evsubwRRR~", [518] = "evsubiwRAR~", + [520] = "evabsRR", [521] = "evnegRR", + [522] = "evextsbRR", [523] = "evextshRR", [524] = "evrndwRR", + [525] = "evcntlzwRR", [526] = "evcntlswRR", + + [527] = "brincRRR", + + [529] = "evandRRR", [530] = "evandcRRR", [534] = "evxorRRR", + [535] = "evor|evmrRRR=", [536] = "evnor|evnotRRR=", + [537] = "eveqvRRR", [539] = "evorcRRR", [542] = "evnandRRR", + + [544] = "evsrwuRRR", [545] = "evsrwsRRR", + [546] = "evsrwiuRRA", [547] = "evsrwisRRA", + [548] = "evslwRRR", [550] = "evslwiRRA", + [552] = "evrlwRRR", [553] = "evsplatiRS", + [554] = "evrlwiRRA", [555] = "evsplatfiRS", + [556] = "evmergehiRRR", [557] = "evmergeloRRR", + [558] = "evmergehiloRRR", [559] = "evmergelohiRRR", + + [560] = "evcmpgtuYRR", [561] = "evcmpgtsYRR", + [562] = "evcmpltuYRR", [563] = "evcmpltsYRR", + [564] = "evcmpeqYRR", + + [632] = "evselRRR", [633] = "evselRRRW", + [634] = "evselRRRW", [635] = "evselRRRW", + [636] = "evselRRRW", [637] = "evselRRRW", + [638] = "evselRRRW", [639] = "evselRRRW", + + [640] = "evfsaddRRR", [641] = "evfssubRRR", + [644] = "evfsabsRR", [645] = "evfsnabsRR", [646] = "evfsnegRR", + [648] = "evfsmulRRR", [649] = "evfsdivRRR", + [652] = "evfscmpgtYRR", [653] = "evfscmpltYRR", [654] = "evfscmpeqYRR", + [656] = "evfscfuiR-R", [657] = "evfscfsiR-R", + [658] = "evfscfufR-R", [659] = "evfscfsfR-R", + [660] = "evfsctuiR-R", [661] = "evfsctsiR-R", + [662] = "evfsctufR-R", [663] = "evfsctsfR-R", + [664] = "evfsctuizR-R", [666] = "evfsctsizR-R", + [668] = "evfststgtYRR", [669] = "evfststltYRR", [670] = "evfststeqYRR", + + [704] = "efsaddRRR", [705] = "efssubRRR", + [708] = "efsabsRR", [709] = "efsnabsRR", [710] = "efsnegRR", + [712] = "efsmulRRR", [713] = "efsdivRRR", + [716] = "efscmpgtYRR", [717] = "efscmpltYRR", [718] = "efscmpeqYRR", + [719] = "efscfdR-R", + [720] = "efscfuiR-R", [721] = "efscfsiR-R", + [722] = "efscfufR-R", [723] = "efscfsfR-R", + [724] = "efsctuiR-R", [725] = "efsctsiR-R", + [726] = "efsctufR-R", [727] = "efsctsfR-R", + [728] = "efsctuizR-R", [730] = "efsctsizR-R", + [732] = "efststgtYRR", [733] = "efststltYRR", [734] = "efststeqYRR", + + [736] = "efdaddRRR", [737] = "efdsubRRR", + [738] = "efdcfuidR-R", [739] = "efdcfsidR-R", + [740] = "efdabsRR", [741] = "efdnabsRR", [742] = "efdnegRR", + [744] = "efdmulRRR", [745] = "efddivRRR", + [746] = "efdctuidzR-R", [747] = "efdctsidzR-R", + [748] = "efdcmpgtYRR", [749] = "efdcmpltYRR", [750] = "efdcmpeqYRR", + [751] = "efdcfsR-R", + [752] = "efdcfuiR-R", [753] = "efdcfsiR-R", + [754] = "efdcfufR-R", [755] = "efdcfsfR-R", + [756] = "efdctuiR-R", [757] = "efdctsiR-R", + [758] = "efdctufR-R", [759] = "efdctsfR-R", + [760] = "efdctuizR-R", [762] = "efdctsizR-R", + [764] = "efdtstgtYRR", [765] = "efdtstltYRR", [766] = "efdtsteqYRR", + + [768] = "evlddxRR0R", [769] = "evlddRR8", + [770] = "evldwxRR0R", [771] = "evldwRR8", + [772] = "evldhxRR0R", [773] = "evldhRR8", + [776] = "evlhhesplatxRR0R", [777] = "evlhhesplatRR2", + [780] = "evlhhousplatxRR0R", [781] = "evlhhousplatRR2", + [782] = "evlhhossplatxRR0R", [783] = "evlhhossplatRR2", + [784] = "evlwhexRR0R", [785] = "evlwheRR4", + [788] = "evlwhouxRR0R", [789] = "evlwhouRR4", + [790] = "evlwhosxRR0R", [791] = "evlwhosRR4", + [792] = "evlwwsplatxRR0R", [793] = "evlwwsplatRR4", + [796] = "evlwhsplatxRR0R", [797] = "evlwhsplatRR4", + + [800] = "evstddxRR0R", [801] = "evstddRR8", + [802] = "evstdwxRR0R", [803] = "evstdwRR8", + [804] = "evstdhxRR0R", [805] = "evstdhRR8", + [816] = "evstwhexRR0R", [817] = "evstwheRR4", + [820] = "evstwhoxRR0R", [821] = "evstwhoRR4", + [824] = "evstwwexRR0R", [825] = "evstwweRR4", + [828] = "evstwwoxRR0R", [829] = "evstwwoRR4", + + [1027] = "evmhessfRRR", [1031] = "evmhossfRRR", [1032] = "evmheumiRRR", + [1033] = "evmhesmiRRR", [1035] = "evmhesmfRRR", [1036] = "evmhoumiRRR", + [1037] = "evmhosmiRRR", [1039] = "evmhosmfRRR", [1059] = "evmhessfaRRR", + [1063] = "evmhossfaRRR", [1064] = "evmheumiaRRR", [1065] = "evmhesmiaRRR", + [1067] = "evmhesmfaRRR", [1068] = "evmhoumiaRRR", [1069] = "evmhosmiaRRR", + [1071] = "evmhosmfaRRR", [1095] = "evmwhssfRRR", [1096] = "evmwlumiRRR", + [1100] = "evmwhumiRRR", [1101] = "evmwhsmiRRR", [1103] = "evmwhsmfRRR", + [1107] = "evmwssfRRR", [1112] = "evmwumiRRR", [1113] = "evmwsmiRRR", + [1115] = "evmwsmfRRR", [1127] = "evmwhssfaRRR", [1128] = "evmwlumiaRRR", + [1132] = "evmwhumiaRRR", [1133] = "evmwhsmiaRRR", [1135] = "evmwhsmfaRRR", + [1139] = "evmwssfaRRR", [1144] = "evmwumiaRRR", [1145] = "evmwsmiaRRR", + [1147] = "evmwsmfaRRR", + + [1216] = "evaddusiaawRR", [1217] = "evaddssiaawRR", + [1218] = "evsubfusiaawRR", [1219] = "evsubfssiaawRR", + [1220] = "evmraRR", + [1222] = "evdivwsRRR", [1223] = "evdivwuRRR", + [1224] = "evaddumiaawRR", [1225] = "evaddsmiaawRR", + [1226] = "evsubfumiaawRR", [1227] = "evsubfsmiaawRR", + + [1280] = "evmheusiaawRRR", [1281] = "evmhessiaawRRR", + [1283] = "evmhessfaawRRR", [1284] = "evmhousiaawRRR", + [1285] = "evmhossiaawRRR", [1287] = "evmhossfaawRRR", + [1288] = "evmheumiaawRRR", [1289] = "evmhesmiaawRRR", + [1291] = "evmhesmfaawRRR", [1292] = "evmhoumiaawRRR", + [1293] = "evmhosmiaawRRR", [1295] = "evmhosmfaawRRR", + [1320] = "evmhegumiaaRRR", [1321] = "evmhegsmiaaRRR", + [1323] = "evmhegsmfaaRRR", [1324] = "evmhogumiaaRRR", + [1325] = "evmhogsmiaaRRR", [1327] = "evmhogsmfaaRRR", + [1344] = "evmwlusiaawRRR", [1345] = "evmwlssiaawRRR", + [1352] = "evmwlumiaawRRR", [1353] = "evmwlsmiaawRRR", + [1363] = "evmwssfaaRRR", [1368] = "evmwumiaaRRR", + [1369] = "evmwsmiaaRRR", [1371] = "evmwsmfaaRRR", + [1408] = "evmheusianwRRR", [1409] = "evmhessianwRRR", + [1411] = "evmhessfanwRRR", [1412] = "evmhousianwRRR", + [1413] = "evmhossianwRRR", [1415] = "evmhossfanwRRR", + [1416] = "evmheumianwRRR", [1417] = "evmhesmianwRRR", + [1419] = "evmhesmfanwRRR", [1420] = "evmhoumianwRRR", + [1421] = "evmhosmianwRRR", [1423] = "evmhosmfanwRRR", + [1448] = "evmhegumianRRR", [1449] = "evmhegsmianRRR", + [1451] = "evmhegsmfanRRR", [1452] = "evmhogumianRRR", + [1453] = "evmhogsmianRRR", [1455] = "evmhogsmfanRRR", + [1472] = "evmwlusianwRRR", [1473] = "evmwlssianwRRR", + [1480] = "evmwlumianwRRR", [1481] = "evmwlsmianwRRR", + [1491] = "evmwssfanRRR", [1496] = "evmwumianRRR", + [1497] = "evmwsmianRRR", [1499] = "evmwsmfanRRR", +} + +local map_pri = { + [0] = false, false, "tdiARI", "twiARI", + map_spe, false, false, "mulliRRI", + "subficRRI", false, "cmpl_iYLRU", "cmp_iYLRI", + "addicRRI", "addic.RRI", "addi|liRR0I", "addis|lisRR0I", + "b_KBJ", "sc", "bKJ", map_crops, + "rlwimiRR~AAA.", map_rlwinm, false, "rlwnmRR~RAA.", + "oriNRR~U", "orisRR~U", "xoriRR~U", "xorisRR~U", + "andi.RR~U", "andis.RR~U", map_rld, map_ext, + "lwzRRD", "lwzuRRD", "lbzRRD", "lbzuRRD", + "stwRRD", "stwuRRD", "stbRRD", "stbuRRD", + "lhzRRD", "lhzuRRD", "lhaRRD", "lhauRRD", + "sthRRD", "sthuRRD", "lmwRRD", "stmwRRD", + "lfsFRD", "lfsuFRD", "lfdFRD", "lfduFRD", + "stfsFRD", "stfsuFRD", "stfdFRD", "stfduFRD", + false, false, map_ld, map_fps, + false, false, map_std, map_fpd, +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "sp", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", +} + +local map_cond = { [0] = "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", } + +-- Format a condition bit. +local function condfmt(cond) + if cond <= 3 then + return map_cond[band(cond, 3)] + else + return format("4*cr%d+%s", rshift(cond, 2), map_cond[band(cond, 3)]) + end +end + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then extra = "\t->"..sym end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-7s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-7s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3) + local operands = {} + local last = nil + local rs = 21 + ctx.op = op + ctx.rel = nil + + local opat = map_pri[rshift(b0, 2)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] + end + local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.]*)(.*)") + if altname then pat = pat2 end + + for p in gmatch(pat, ".") do + local x = nil + if p == "R" then + x = map_gpr[band(rshift(op, rs), 31)] + rs = rs - 5 + elseif p == "F" then + x = "f"..band(rshift(op, rs), 31) + rs = rs - 5 + elseif p == "A" then + x = band(rshift(op, rs), 31) + rs = rs - 5 + elseif p == "S" then + x = arshift(lshift(op, 27-rs), 27) + rs = rs - 5 + elseif p == "I" then + x = arshift(lshift(op, 16), 16) + elseif p == "U" then + x = band(op, 0xffff) + elseif p == "D" or p == "E" then + local disp = arshift(lshift(op, 16), 16) + if p == "E" then disp = band(disp, -4) end + if last == "r0" then last = "0" end + operands[#operands] = format("%d(%s)", disp, last) + elseif p >= "2" and p <= "8" then + local disp = band(rshift(op, rs), 31) * p + if last == "r0" then last = "0" end + operands[#operands] = format("%d(%s)", disp, last) + elseif p == "H" then + x = band(rshift(op, rs), 31) + lshift(band(op, 2), 4) + rs = rs - 5 + elseif p == "M" then + x = band(rshift(op, rs), 31) + band(op, 0x20) + elseif p == "C" then + x = condfmt(band(rshift(op, rs), 31)) + rs = rs - 5 + elseif p == "B" then + local bo = rshift(op, 21) + local cond = band(rshift(op, 16), 31) + local cn = "" + rs = rs - 10 + if band(bo, 4) == 0 then + cn = band(bo, 2) == 0 and "dnz" or "dz" + if band(bo, 0x10) == 0 then + cn = cn..(band(bo, 8) == 0 and "f" or "t") + end + if band(bo, 0x10) == 0 then x = condfmt(cond) end + name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+") + elseif band(bo, 0x10) == 0 then + cn = map_cond[band(cond, 3) + (band(bo, 8) == 0 and 4 or 0)] + if cond > 3 then x = "cr"..rshift(cond, 2) end + name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+") + end + name = gsub(name, "_", cn) + elseif p == "J" then + x = arshift(lshift(op, 27-rs), 29-rs)*4 + if band(op, 2) == 0 then x = ctx.addr + pos + x end + ctx.rel = x + x = "0x"..tohex(x) + elseif p == "K" then + if band(op, 1) ~= 0 then name = name.."l" end + if band(op, 2) ~= 0 then name = name.."a" end + elseif p == "X" or p == "Y" then + x = band(rshift(op, rs+2), 7) + if x == 0 and p == "Y" then x = nil else x = "cr"..x end + rs = rs - 5 + elseif p == "W" then + x = "cr"..band(op, 7) + elseif p == "Z" then + x = band(rshift(op, rs-4), 255) + rs = rs - 10 + elseif p == ">" then + operands[#operands] = rshift(operands[#operands], 1) + elseif p == "0" then + if last == "r0" then + operands[#operands] = nil + if altname then name = altname end + end + elseif p == "L" then + name = gsub(name, "_", band(op, 0x00200000) ~= 0 and "d" or "w") + elseif p == "." then + if band(op, 1) == 1 then name = name.."." end + elseif p == "N" then + if op == 0x60000000 then name = "nop"; break end + elseif p == "~" then + local n = #operands + operands[n-1], operands[n] = operands[n], operands[n-1] + elseif p == "=" then + local n = #operands + if last == operands[n-1] then + operands[n] = nil + name = altname + end + elseif p == "%" then + local n = #operands + if last == operands[n-1] and last == operands[n-2] then + operands[n] = nil + operands[n-1] = nil + name = altname + end + elseif p == "-" then + rs = rs - 5 + else + assert(false) + end + if x then operands[#operands+1] = x; last = x end + end + + return putop(ctx, name, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + stop = stop - stop % 4 + ctx.pos = ofs - ofs % 4 + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_gpr[r] end + return "f"..(r-32) +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_x64.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_x64.lua new file mode 100644 index 00000000..2d37423e --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_x64.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT x64 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the 64 bit functions from the combined +-- x86/x64 disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_x86 = require((string.match(..., ".*%.") or "").."dis_x86") +return { + create = dis_x86.create64, + disass = dis_x86.disass64, + regname = dis_x86.regname64 +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_x86.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_x86.lua new file mode 100644 index 00000000..5480854c --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dis_x86.lua @@ -0,0 +1,953 @@ +---------------------------------------------------------------------------- +-- LuaJIT x86/x64 disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- Sending small code snippets to an external disassembler and mixing the +-- output with our own stuff was too fragile. So I had to bite the bullet +-- and write yet another x86 disassembler. Oh well ... +-- +-- The output format is very similar to what ndisasm generates. But it has +-- been developed independently by looking at the opcode tables from the +-- Intel and AMD manuals. The supported instruction set is quite extensive +-- and reflects what a current generation Intel or AMD CPU implements in +-- 32 bit and 64 bit mode. Yes, this includes MMX, SSE, SSE2, SSE3, SSSE3, +-- SSE4.1, SSE4.2, SSE4a, AVX, AVX2 and even privileged and hypervisor +-- (VMX/SVM) instructions. +-- +-- Notes: +-- * The (useless) a16 prefix, 3DNow and pre-586 opcodes are unsupported. +-- * No attempt at optimization has been made -- it's fast enough for my needs. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local lower, rep = string.lower, string.rep +local bit = require("bit") +local tohex = bit.tohex + +-- Map for 1st opcode byte in 32 bit mode. Ugly? Well ... read on. +local map_opc1_32 = { +--0x +[0]="addBmr","addVmr","addBrm","addVrm","addBai","addVai","push es","pop es", +"orBmr","orVmr","orBrm","orVrm","orBai","orVai","push cs","opc2*", +--1x +"adcBmr","adcVmr","adcBrm","adcVrm","adcBai","adcVai","push ss","pop ss", +"sbbBmr","sbbVmr","sbbBrm","sbbVrm","sbbBai","sbbVai","push ds","pop ds", +--2x +"andBmr","andVmr","andBrm","andVrm","andBai","andVai","es:seg","daa", +"subBmr","subVmr","subBrm","subVrm","subBai","subVai","cs:seg","das", +--3x +"xorBmr","xorVmr","xorBrm","xorVrm","xorBai","xorVai","ss:seg","aaa", +"cmpBmr","cmpVmr","cmpBrm","cmpVrm","cmpBai","cmpVai","ds:seg","aas", +--4x +"incVR","incVR","incVR","incVR","incVR","incVR","incVR","incVR", +"decVR","decVR","decVR","decVR","decVR","decVR","decVR","decVR", +--5x +"pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR", +"popUR","popUR","popUR","popUR","popUR","popUR","popUR","popUR", +--6x +"sz*pushaw,pusha","sz*popaw,popa","boundVrm","arplWmr", +"fs:seg","gs:seg","o16:","a16", +"pushUi","imulVrmi","pushBs","imulVrms", +"insb","insVS","outsb","outsVS", +--7x +"joBj","jnoBj","jbBj","jnbBj","jzBj","jnzBj","jbeBj","jaBj", +"jsBj","jnsBj","jpeBj","jpoBj","jlBj","jgeBj","jleBj","jgBj", +--8x +"arith!Bmi","arith!Vmi","arith!Bmi","arith!Vms", +"testBmr","testVmr","xchgBrm","xchgVrm", +"movBmr","movVmr","movBrm","movVrm", +"movVmg","leaVrm","movWgm","popUm", +--9x +"nop*xchgVaR|pause|xchgWaR|repne nop","xchgVaR","xchgVaR","xchgVaR", +"xchgVaR","xchgVaR","xchgVaR","xchgVaR", +"sz*cbw,cwde,cdqe","sz*cwd,cdq,cqo","call farViw","wait", +"sz*pushfw,pushf","sz*popfw,popf","sahf","lahf", +--Ax +"movBao","movVao","movBoa","movVoa", +"movsb","movsVS","cmpsb","cmpsVS", +"testBai","testVai","stosb","stosVS", +"lodsb","lodsVS","scasb","scasVS", +--Bx +"movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi", +"movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI", +--Cx +"shift!Bmu","shift!Vmu","retBw","ret","vex*3$lesVrm","vex*2$ldsVrm","movBmi","movVmi", +"enterBwu","leave","retfBw","retf","int3","intBu","into","iretVS", +--Dx +"shift!Bm1","shift!Vm1","shift!Bmc","shift!Vmc","aamBu","aadBu","salc","xlatb", +"fp*0","fp*1","fp*2","fp*3","fp*4","fp*5","fp*6","fp*7", +--Ex +"loopneBj","loopeBj","loopBj","sz*jcxzBj,jecxzBj,jrcxzBj", +"inBau","inVau","outBua","outVua", +"callVj","jmpVj","jmp farViw","jmpBj","inBad","inVad","outBda","outVda", +--Fx +"lock:","int1","repne:rep","rep:","hlt","cmc","testb!Bm","testv!Vm", +"clc","stc","cli","sti","cld","std","incb!Bm","incd!Vm", +} +assert(#map_opc1_32 == 255) + +-- Map for 1st opcode byte in 64 bit mode (overrides only). +local map_opc1_64 = setmetatable({ + [0x06]=false, [0x07]=false, [0x0e]=false, + [0x16]=false, [0x17]=false, [0x1e]=false, [0x1f]=false, + [0x27]=false, [0x2f]=false, [0x37]=false, [0x3f]=false, + [0x60]=false, [0x61]=false, [0x62]=false, [0x63]="movsxdVrDmt", [0x67]="a32:", + [0x40]="rex*", [0x41]="rex*b", [0x42]="rex*x", [0x43]="rex*xb", + [0x44]="rex*r", [0x45]="rex*rb", [0x46]="rex*rx", [0x47]="rex*rxb", + [0x48]="rex*w", [0x49]="rex*wb", [0x4a]="rex*wx", [0x4b]="rex*wxb", + [0x4c]="rex*wr", [0x4d]="rex*wrb", [0x4e]="rex*wrx", [0x4f]="rex*wrxb", + [0x82]=false, [0x9a]=false, [0xc4]="vex*3", [0xc5]="vex*2", [0xce]=false, + [0xd4]=false, [0xd5]=false, [0xd6]=false, [0xea]=false, +}, { __index = map_opc1_32 }) + +-- Map for 2nd opcode byte (0F xx). True CISC hell. Hey, I told you. +-- Prefix dependent MMX/SSE opcodes: (none)|rep|o16|repne, -|F3|66|F2 +local map_opc2 = { +--0x +[0]="sldt!Dmp","sgdt!Ump","larVrm","lslVrm",nil,"syscall","clts","sysret", +"invd","wbinvd",nil,"ud1",nil,"$prefetch!Bm","femms","3dnowMrmu", +--1x +"movupsXrm|movssXrvm|movupdXrm|movsdXrvm", +"movupsXmr|movssXmvr|movupdXmr|movsdXmvr", +"movhlpsXrm$movlpsXrm|movsldupXrm|movlpdXrm|movddupXrm", +"movlpsXmr||movlpdXmr", +"unpcklpsXrvm||unpcklpdXrvm", +"unpckhpsXrvm||unpckhpdXrvm", +"movlhpsXrm$movhpsXrm|movshdupXrm|movhpdXrm", +"movhpsXmr||movhpdXmr", +"$prefetcht!Bm","hintnopVm","hintnopVm","hintnopVm", +"hintnopVm","hintnopVm","hintnopVm","hintnopVm", +--2x +"movUmx$","movUmy$","movUxm$","movUym$","movUmz$",nil,"movUzm$",nil, +"movapsXrm||movapdXrm", +"movapsXmr||movapdXmr", +"cvtpi2psXrMm|cvtsi2ssXrvVmt|cvtpi2pdXrMm|cvtsi2sdXrvVmt", +"movntpsXmr|movntssXmr|movntpdXmr|movntsdXmr", +"cvttps2piMrXm|cvttss2siVrXm|cvttpd2piMrXm|cvttsd2siVrXm", +"cvtps2piMrXm|cvtss2siVrXm|cvtpd2piMrXm|cvtsd2siVrXm", +"ucomissXrm||ucomisdXrm", +"comissXrm||comisdXrm", +--3x +"wrmsr","rdtsc","rdmsr","rdpmc","sysenter","sysexit",nil,"getsec", +"opc3*38",nil,"opc3*3a",nil,nil,nil,nil,nil, +--4x +"cmovoVrm","cmovnoVrm","cmovbVrm","cmovnbVrm", +"cmovzVrm","cmovnzVrm","cmovbeVrm","cmovaVrm", +"cmovsVrm","cmovnsVrm","cmovpeVrm","cmovpoVrm", +"cmovlVrm","cmovgeVrm","cmovleVrm","cmovgVrm", +--5x +"movmskpsVrXm$||movmskpdVrXm$","sqrtpsXrm|sqrtssXrm|sqrtpdXrm|sqrtsdXrm", +"rsqrtpsXrm|rsqrtssXrvm","rcppsXrm|rcpssXrvm", +"andpsXrvm||andpdXrvm","andnpsXrvm||andnpdXrvm", +"orpsXrvm||orpdXrvm","xorpsXrvm||xorpdXrvm", +"addpsXrvm|addssXrvm|addpdXrvm|addsdXrvm","mulpsXrvm|mulssXrvm|mulpdXrvm|mulsdXrvm", +"cvtps2pdXrm|cvtss2sdXrvm|cvtpd2psXrm|cvtsd2ssXrvm", +"cvtdq2psXrm|cvttps2dqXrm|cvtps2dqXrm", +"subpsXrvm|subssXrvm|subpdXrvm|subsdXrvm","minpsXrvm|minssXrvm|minpdXrvm|minsdXrvm", +"divpsXrvm|divssXrvm|divpdXrvm|divsdXrvm","maxpsXrvm|maxssXrvm|maxpdXrvm|maxsdXrvm", +--6x +"punpcklbwPrvm","punpcklwdPrvm","punpckldqPrvm","packsswbPrvm", +"pcmpgtbPrvm","pcmpgtwPrvm","pcmpgtdPrvm","packuswbPrvm", +"punpckhbwPrvm","punpckhwdPrvm","punpckhdqPrvm","packssdwPrvm", +"||punpcklqdqXrvm","||punpckhqdqXrvm", +"movPrVSm","movqMrm|movdquXrm|movdqaXrm", +--7x +"pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pvmu", +"pshiftd!Pvmu","pshiftq!Mvmu||pshiftdq!Xvmu", +"pcmpeqbPrvm","pcmpeqwPrvm","pcmpeqdPrvm","emms*|", +"vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$", +nil,nil, +"||haddpdXrvm|haddpsXrvm","||hsubpdXrvm|hsubpsXrvm", +"movVSmMr|movqXrm|movVSmXr","movqMmr|movdquXmr|movdqaXmr", +--8x +"joVj","jnoVj","jbVj","jnbVj","jzVj","jnzVj","jbeVj","jaVj", +"jsVj","jnsVj","jpeVj","jpoVj","jlVj","jgeVj","jleVj","jgVj", +--9x +"setoBm","setnoBm","setbBm","setnbBm","setzBm","setnzBm","setbeBm","setaBm", +"setsBm","setnsBm","setpeBm","setpoBm","setlBm","setgeBm","setleBm","setgBm", +--Ax +"push fs","pop fs","cpuid","btVmr","shldVmru","shldVmrc",nil,nil, +"push gs","pop gs","rsm","btsVmr","shrdVmru","shrdVmrc","fxsave!Dmp","imulVrm", +--Bx +"cmpxchgBmr","cmpxchgVmr","$lssVrm","btrVmr", +"$lfsVrm","$lgsVrm","movzxVrBmt","movzxVrWmt", +"|popcntVrm","ud2Dp","bt!Vmu","btcVmr", +"bsfVrm","bsrVrm|lzcntVrm|bsrWrm","movsxVrBmt","movsxVrWmt", +--Cx +"xaddBmr","xaddVmr", +"cmppsXrvmu|cmpssXrvmu|cmppdXrvmu|cmpsdXrvmu","$movntiVmr|", +"pinsrwPrvWmu","pextrwDrPmu", +"shufpsXrvmu||shufpdXrvmu","$cmpxchg!Qmp", +"bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR", +--Dx +"||addsubpdXrvm|addsubpsXrvm","psrlwPrvm","psrldPrvm","psrlqPrvm", +"paddqPrvm","pmullwPrvm", +"|movq2dqXrMm|movqXmr|movdq2qMrXm$","pmovmskbVrMm||pmovmskbVrXm", +"psubusbPrvm","psubuswPrvm","pminubPrvm","pandPrvm", +"paddusbPrvm","padduswPrvm","pmaxubPrvm","pandnPrvm", +--Ex +"pavgbPrvm","psrawPrvm","psradPrvm","pavgwPrvm", +"pmulhuwPrvm","pmulhwPrvm", +"|cvtdq2pdXrm|cvttpd2dqXrm|cvtpd2dqXrm","$movntqMmr||$movntdqXmr", +"psubsbPrvm","psubswPrvm","pminswPrvm","porPrvm", +"paddsbPrvm","paddswPrvm","pmaxswPrvm","pxorPrvm", +--Fx +"|||lddquXrm","psllwPrvm","pslldPrvm","psllqPrvm", +"pmuludqPrvm","pmaddwdPrvm","psadbwPrvm","maskmovqMrm||maskmovdquXrm$", +"psubbPrvm","psubwPrvm","psubdPrvm","psubqPrvm", +"paddbPrvm","paddwPrvm","padddPrvm","ud", +} +assert(map_opc2[255] == "ud") + +-- Map for three-byte opcodes. Can't wait for their next invention. +local map_opc3 = { +["38"] = { -- [66] 0f 38 xx +--0x +[0]="pshufbPrvm","phaddwPrvm","phadddPrvm","phaddswPrvm", +"pmaddubswPrvm","phsubwPrvm","phsubdPrvm","phsubswPrvm", +"psignbPrvm","psignwPrvm","psigndPrvm","pmulhrswPrvm", +"||permilpsXrvm","||permilpdXrvm",nil,nil, +--1x +"||pblendvbXrma",nil,nil,nil, +"||blendvpsXrma","||blendvpdXrma","||permpsXrvm","||ptestXrm", +"||broadcastssXrm","||broadcastsdXrm","||broadcastf128XrlXm",nil, +"pabsbPrm","pabswPrm","pabsdPrm",nil, +--2x +"||pmovsxbwXrm","||pmovsxbdXrm","||pmovsxbqXrm","||pmovsxwdXrm", +"||pmovsxwqXrm","||pmovsxdqXrm",nil,nil, +"||pmuldqXrvm","||pcmpeqqXrvm","||$movntdqaXrm","||packusdwXrvm", +"||maskmovpsXrvm","||maskmovpdXrvm","||maskmovpsXmvr","||maskmovpdXmvr", +--3x +"||pmovzxbwXrm","||pmovzxbdXrm","||pmovzxbqXrm","||pmovzxwdXrm", +"||pmovzxwqXrm","||pmovzxdqXrm","||permdXrvm","||pcmpgtqXrvm", +"||pminsbXrvm","||pminsdXrvm","||pminuwXrvm","||pminudXrvm", +"||pmaxsbXrvm","||pmaxsdXrvm","||pmaxuwXrvm","||pmaxudXrvm", +--4x +"||pmulddXrvm","||phminposuwXrm",nil,nil, +nil,"||psrlvVSXrvm","||psravdXrvm","||psllvVSXrvm", +--5x +[0x58] = "||pbroadcastdXrlXm",[0x59] = "||pbroadcastqXrlXm", +[0x5a] = "||broadcasti128XrlXm", +--7x +[0x78] = "||pbroadcastbXrlXm",[0x79] = "||pbroadcastwXrlXm", +--8x +[0x8c] = "||pmaskmovXrvVSm", +[0x8e] = "||pmaskmovVSmXvr", +--9x +[0x96] = "||fmaddsub132pHXrvm",[0x97] = "||fmsubadd132pHXrvm", +[0x98] = "||fmadd132pHXrvm",[0x99] = "||fmadd132sHXrvm", +[0x9a] = "||fmsub132pHXrvm",[0x9b] = "||fmsub132sHXrvm", +[0x9c] = "||fnmadd132pHXrvm",[0x9d] = "||fnmadd132sHXrvm", +[0x9e] = "||fnmsub132pHXrvm",[0x9f] = "||fnmsub132sHXrvm", +--Ax +[0xa6] = "||fmaddsub213pHXrvm",[0xa7] = "||fmsubadd213pHXrvm", +[0xa8] = "||fmadd213pHXrvm",[0xa9] = "||fmadd213sHXrvm", +[0xaa] = "||fmsub213pHXrvm",[0xab] = "||fmsub213sHXrvm", +[0xac] = "||fnmadd213pHXrvm",[0xad] = "||fnmadd213sHXrvm", +[0xae] = "||fnmsub213pHXrvm",[0xaf] = "||fnmsub213sHXrvm", +--Bx +[0xb6] = "||fmaddsub231pHXrvm",[0xb7] = "||fmsubadd231pHXrvm", +[0xb8] = "||fmadd231pHXrvm",[0xb9] = "||fmadd231sHXrvm", +[0xba] = "||fmsub231pHXrvm",[0xbb] = "||fmsub231sHXrvm", +[0xbc] = "||fnmadd231pHXrvm",[0xbd] = "||fnmadd231sHXrvm", +[0xbe] = "||fnmsub231pHXrvm",[0xbf] = "||fnmsub231sHXrvm", +--Dx +[0xdc] = "||aesencXrvm", [0xdd] = "||aesenclastXrvm", +[0xde] = "||aesdecXrvm", [0xdf] = "||aesdeclastXrvm", +--Fx +[0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt", +[0xf7] = "| sarxVrmv| shlxVrmv| shrxVrmv", +}, + +["3a"] = { -- [66] 0f 3a xx +--0x +[0x00]="||permqXrmu","||permpdXrmu","||pblenddXrvmu",nil, +"||permilpsXrmu","||permilpdXrmu","||perm2f128Xrvmu",nil, +"||roundpsXrmu","||roundpdXrmu","||roundssXrvmu","||roundsdXrvmu", +"||blendpsXrvmu","||blendpdXrvmu","||pblendwXrvmu","palignrPrvmu", +--1x +nil,nil,nil,nil, +"||pextrbVmXru","||pextrwVmXru","||pextrVmSXru","||extractpsVmXru", +"||insertf128XrvlXmu","||extractf128XlXmYru",nil,nil, +nil,nil,nil,nil, +--2x +"||pinsrbXrvVmu","||insertpsXrvmu","||pinsrXrvVmuS",nil, +--3x +[0x38] = "||inserti128Xrvmu",[0x39] = "||extracti128XlXmYru", +--4x +[0x40] = "||dppsXrvmu", +[0x41] = "||dppdXrvmu", +[0x42] = "||mpsadbwXrvmu", +[0x44] = "||pclmulqdqXrvmu", +[0x46] = "||perm2i128Xrvmu", +[0x4a] = "||blendvpsXrvmb",[0x4b] = "||blendvpdXrvmb", +[0x4c] = "||pblendvbXrvmb", +--6x +[0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu", +[0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu", +[0xdf] = "||aeskeygenassistXrmu", +--Fx +[0xf0] = "||| rorxVrmu", +}, +} + +-- Map for VMX/SVM opcodes 0F 01 C0-FF (sgdt group with register operands). +local map_opcvm = { +[0xc1]="vmcall",[0xc2]="vmlaunch",[0xc3]="vmresume",[0xc4]="vmxoff", +[0xc8]="monitor",[0xc9]="mwait", +[0xd8]="vmrun",[0xd9]="vmmcall",[0xda]="vmload",[0xdb]="vmsave", +[0xdc]="stgi",[0xdd]="clgi",[0xde]="skinit",[0xdf]="invlpga", +[0xf8]="swapgs",[0xf9]="rdtscp", +} + +-- Map for FP opcodes. And you thought stack machines are simple? +local map_opcfp = { +-- D8-DF 00-BF: opcodes with a memory operand. +-- D8 +[0]="faddFm","fmulFm","fcomFm","fcompFm","fsubFm","fsubrFm","fdivFm","fdivrFm", +"fldFm",nil,"fstFm","fstpFm","fldenvVm","fldcwWm","fnstenvVm","fnstcwWm", +-- DA +"fiaddDm","fimulDm","ficomDm","ficompDm", +"fisubDm","fisubrDm","fidivDm","fidivrDm", +-- DB +"fildDm","fisttpDm","fistDm","fistpDm",nil,"fld twordFmp",nil,"fstp twordFmp", +-- DC +"faddGm","fmulGm","fcomGm","fcompGm","fsubGm","fsubrGm","fdivGm","fdivrGm", +-- DD +"fldGm","fisttpQm","fstGm","fstpGm","frstorDmp",nil,"fnsaveDmp","fnstswWm", +-- DE +"fiaddWm","fimulWm","ficomWm","ficompWm", +"fisubWm","fisubrWm","fidivWm","fidivrWm", +-- DF +"fildWm","fisttpWm","fistWm","fistpWm", +"fbld twordFmp","fildQm","fbstp twordFmp","fistpQm", +-- xx C0-FF: opcodes with a pseudo-register operand. +-- D8 +"faddFf","fmulFf","fcomFf","fcompFf","fsubFf","fsubrFf","fdivFf","fdivrFf", +-- D9 +"fldFf","fxchFf",{"fnop"},nil, +{"fchs","fabs",nil,nil,"ftst","fxam"}, +{"fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz"}, +{"f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp"}, +{"fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"}, +-- DA +"fcmovbFf","fcmoveFf","fcmovbeFf","fcmovuFf",nil,{nil,"fucompp"},nil,nil, +-- DB +"fcmovnbFf","fcmovneFf","fcmovnbeFf","fcmovnuFf", +{nil,nil,"fnclex","fninit"},"fucomiFf","fcomiFf",nil, +-- DC +"fadd toFf","fmul toFf",nil,nil, +"fsub toFf","fsubr toFf","fdivr toFf","fdiv toFf", +-- DD +"ffreeFf",nil,"fstFf","fstpFf","fucomFf","fucompFf",nil,nil, +-- DE +"faddpFf","fmulpFf",nil,{nil,"fcompp"}, +"fsubrpFf","fsubpFf","fdivrpFf","fdivpFf", +-- DF +nil,nil,nil,nil,{"fnstsw ax"},"fucomipFf","fcomipFf",nil, +} +assert(map_opcfp[126] == "fcomipFf") + +-- Map for opcode groups. The subkey is sp from the ModRM byte. +local map_opcgroup = { + arith = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" }, + shift = { "rol", "ror", "rcl", "rcr", "shl", "shr", "sal", "sar" }, + testb = { "testBmi", "testBmi", "not", "neg", "mul", "imul", "div", "idiv" }, + testv = { "testVmi", "testVmi", "not", "neg", "mul", "imul", "div", "idiv" }, + incb = { "inc", "dec" }, + incd = { "inc", "dec", "callUmp", "$call farDmp", + "jmpUmp", "$jmp farDmp", "pushUm" }, + sldt = { "sldt", "str", "lldt", "ltr", "verr", "verw" }, + sgdt = { "vm*$sgdt", "vm*$sidt", "$lgdt", "vm*$lidt", + "smsw", nil, "lmsw", "vm*$invlpg" }, + bt = { nil, nil, nil, nil, "bt", "bts", "btr", "btc" }, + cmpxchg = { nil, "sz*,cmpxchg8bQmp,cmpxchg16bXmp", nil, nil, + nil, nil, "vmptrld|vmxon|vmclear", "vmptrst" }, + pshiftw = { nil, nil, "psrlw", nil, "psraw", nil, "psllw" }, + pshiftd = { nil, nil, "psrld", nil, "psrad", nil, "pslld" }, + pshiftq = { nil, nil, "psrlq", nil, nil, nil, "psllq" }, + pshiftdq = { nil, nil, "psrlq", "psrldq", nil, nil, "psllq", "pslldq" }, + fxsave = { "$fxsave", "$fxrstor", "$ldmxcsr", "$stmxcsr", + nil, "lfenceDp$", "mfenceDp$", "sfenceDp$clflush" }, + prefetch = { "prefetch", "prefetchw" }, + prefetcht = { "prefetchnta", "prefetcht0", "prefetcht1", "prefetcht2" }, +} + +------------------------------------------------------------------------------ + +-- Maps for register names. +local map_regs = { + B = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + B64 = { "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + W = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }, + D = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }, + Q = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }, + M = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", + "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, -- No x64 ext! + X = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" }, + Y = { "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15" }, +} +local map_segregs = { "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7" } + +-- Maps for size names. +local map_sz2n = { + B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16, Y = 32, +} +local map_sz2prefix = { + B = "byte", W = "word", D = "dword", + Q = "qword", + M = "qword", X = "xword", Y = "yword", + F = "dword", G = "qword", -- No need for sizes/register names for these two. +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local code, pos, hex = ctx.code, ctx.pos, "" + local hmax = ctx.hexdump + if hmax > 0 then + for i=ctx.start,pos-1 do + hex = hex..format("%02X", byte(code, i, i)) + end + if #hex > hmax then hex = sub(hex, 1, hmax)..". " + else hex = hex..rep(" ", hmax-#hex+2) end + end + if operands then text = text.." "..operands end + if ctx.o16 then text = "o16 "..text; ctx.o16 = false end + if ctx.a32 then text = "a32 "..text; ctx.a32 = false end + if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end + if ctx.rex then + local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "").. + (ctx.rexx and "x" or "")..(ctx.rexb and "b" or "").. + (ctx.vexl and "l" or "") + if ctx.vexv and ctx.vexv ~= 0 then t = t.."v"..ctx.vexv end + if t ~= "" then text = ctx.rex.."."..t.." "..gsub(text, "^ ", "") + elseif ctx.rex == "vex" then text = gsub("v"..text, "^v ", "") end + ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false + ctx.rex = false; ctx.vexl = false; ctx.vexv = false + end + if ctx.seg then + local text2, n = gsub(text, "%[", "["..ctx.seg..":") + if n == 0 then text = ctx.seg.." "..text else text = text2 end + ctx.seg = false + end + if ctx.lock then text = "lock "..text; ctx.lock = false end + local imm = ctx.imm + if imm then + local sym = ctx.symtab[imm] + if sym then text = text.."\t->"..sym end + end + ctx.out(format("%08x %s%s\n", ctx.addr+ctx.start, hex, text)) + ctx.mrm = false + ctx.vexv = false + ctx.start = pos + ctx.imm = nil +end + +-- Clear all prefix flags. +local function clearprefixes(ctx) + ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false + ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false + ctx.rex = false; ctx.a32 = false; ctx.vexl = false +end + +-- Fallback for incomplete opcodes at the end. +local function incomplete(ctx) + ctx.pos = ctx.stop+1 + clearprefixes(ctx) + return putop(ctx, "(incomplete)") +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + clearprefixes(ctx) + return putop(ctx, "(unknown)") +end + +-- Return an immediate of the specified size. +local function getimm(ctx, pos, n) + if pos+n-1 > ctx.stop then return incomplete(ctx) end + local code = ctx.code + if n == 1 then + local b1 = byte(code, pos, pos) + return b1 + elseif n == 2 then + local b1, b2 = byte(code, pos, pos+1) + return b1+b2*256 + else + local b1, b2, b3, b4 = byte(code, pos, pos+3) + local imm = b1+b2*256+b3*65536+b4*16777216 + ctx.imm = imm + return imm + end +end + +-- Process pattern string and generate the operands. +local function putpat(ctx, name, pat) + local operands, regs, sz, mode, sp, rm, sc, rx, sdisp + local code, pos, stop, vexl = ctx.code, ctx.pos, ctx.stop, ctx.vexl + + -- Chars used: 1DFGHIMPQRSTUVWXYabcdfgijlmoprstuvwxyz + for p in gmatch(pat, ".") do + local x = nil + if p == "V" or p == "U" then + if ctx.rexw then sz = "Q"; ctx.rexw = false + elseif ctx.o16 then sz = "W"; ctx.o16 = false + elseif p == "U" and ctx.x64 then sz = "Q" + else sz = "D" end + regs = map_regs[sz] + elseif p == "T" then + if ctx.rexw then sz = "Q"; ctx.rexw = false else sz = "D" end + regs = map_regs[sz] + elseif p == "B" then + sz = "B" + regs = ctx.rex and map_regs.B64 or map_regs.B + elseif match(p, "[WDQMXYFG]") then + sz = p + if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end + regs = map_regs[sz] + elseif p == "P" then + sz = ctx.o16 and "X" or "M"; ctx.o16 = false + if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end + regs = map_regs[sz] + elseif p == "H" then + name = name..(ctx.rexw and "d" or "s") + ctx.rexw = false + elseif p == "S" then + name = name..lower(sz) + elseif p == "s" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = imm <= 127 and format("+0x%02x", imm) + or format("-0x%02x", 256-imm) + pos = pos+1 + elseif p == "u" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = format("0x%02x", imm) + pos = pos+1 + elseif p == "b" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = regs[imm/16+1] + pos = pos+1 + elseif p == "w" then + local imm = getimm(ctx, pos, 2); if not imm then return end + x = format("0x%x", imm) + pos = pos+2 + elseif p == "o" then -- [offset] + if ctx.x64 then + local imm1 = getimm(ctx, pos, 4); if not imm1 then return end + local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end + x = format("[0x%08x%08x]", imm2, imm1) + pos = pos+8 + else + local imm = getimm(ctx, pos, 4); if not imm then return end + x = format("[0x%08x]", imm) + pos = pos+4 + end + elseif p == "i" or p == "I" then + local n = map_sz2n[sz] + if n == 8 and ctx.x64 and p == "I" then + local imm1 = getimm(ctx, pos, 4); if not imm1 then return end + local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end + x = format("0x%08x%08x", imm2, imm1) + else + if n == 8 then n = 4 end + local imm = getimm(ctx, pos, n); if not imm then return end + if sz == "Q" and (imm < 0 or imm > 0x7fffffff) then + imm = (0xffffffff+1)-imm + x = format(imm > 65535 and "-0x%08x" or "-0x%x", imm) + else + x = format(imm > 65535 and "0x%08x" or "0x%x", imm) + end + end + pos = pos+n + elseif p == "j" then + local n = map_sz2n[sz] + if n == 8 then n = 4 end + local imm = getimm(ctx, pos, n); if not imm then return end + if sz == "B" and imm > 127 then imm = imm-256 + elseif imm > 2147483647 then imm = imm-4294967296 end + pos = pos+n + imm = imm + pos + ctx.addr + if imm > 4294967295 and not ctx.x64 then imm = imm-4294967296 end + ctx.imm = imm + if sz == "W" then + x = format("word 0x%04x", imm%65536) + elseif ctx.x64 then + local lo = imm % 0x1000000 + x = format("0x%02x%06x", (imm-lo) / 0x1000000, lo) + else + x = "0x"..tohex(imm) + end + elseif p == "R" then + local r = byte(code, pos-1, pos-1)%8 + if ctx.rexb then r = r + 8; ctx.rexb = false end + x = regs[r+1] + elseif p == "a" then x = regs[1] + elseif p == "c" then x = "cl" + elseif p == "d" then x = "dx" + elseif p == "1" then x = "1" + else + if not mode then + mode = ctx.mrm + if not mode then + if pos > stop then return incomplete(ctx) end + mode = byte(code, pos, pos) + pos = pos+1 + end + rm = mode%8; mode = (mode-rm)/8 + sp = mode%8; mode = (mode-sp)/8 + sdisp = "" + if mode < 3 then + if rm == 4 then + if pos > stop then return incomplete(ctx) end + sc = byte(code, pos, pos) + pos = pos+1 + rm = sc%8; sc = (sc-rm)/8 + rx = sc%8; sc = (sc-rx)/8 + if ctx.rexx then rx = rx + 8; ctx.rexx = false end + if rx == 4 then rx = nil end + end + if mode > 0 or rm == 5 then + local dsz = mode + if dsz ~= 1 then dsz = 4 end + local disp = getimm(ctx, pos, dsz); if not disp then return end + if mode == 0 then rm = nil end + if rm or rx or (not sc and ctx.x64 and not ctx.a32) then + if dsz == 1 and disp > 127 then + sdisp = format("-0x%x", 256-disp) + elseif disp >= 0 and disp <= 0x7fffffff then + sdisp = format("+0x%x", disp) + else + sdisp = format("-0x%x", (0xffffffff+1)-disp) + end + else + sdisp = format(ctx.x64 and not ctx.a32 and + not (disp >= 0 and disp <= 0x7fffffff) + and "0xffffffff%08x" or "0x%08x", disp) + end + pos = pos+dsz + end + end + if rm and ctx.rexb then rm = rm + 8; ctx.rexb = false end + if ctx.rexr then sp = sp + 8; ctx.rexr = false end + end + if p == "m" then + if mode == 3 then x = regs[rm+1] + else + local aregs = ctx.a32 and map_regs.D or ctx.aregs + local srm, srx = "", "" + if rm then srm = aregs[rm+1] + elseif not sc and ctx.x64 and not ctx.a32 then srm = "rip" end + ctx.a32 = false + if rx then + if rm then srm = srm.."+" end + srx = aregs[rx+1] + if sc > 0 then srx = srx.."*"..(2^sc) end + end + x = format("[%s%s%s]", srm, srx, sdisp) + end + if mode < 3 and + (not match(pat, "[aRrgp]") or match(pat, "t")) then -- Yuck. + x = map_sz2prefix[sz].." "..x + end + elseif p == "r" then x = regs[sp+1] + elseif p == "g" then x = map_segregs[sp+1] + elseif p == "p" then -- Suppress prefix. + elseif p == "f" then x = "st"..rm + elseif p == "x" then + if sp == 0 and ctx.lock and not ctx.x64 then + x = "CR8"; ctx.lock = false + else + x = "CR"..sp + end + elseif p == "v" then + if ctx.vexv then + x = regs[ctx.vexv+1]; ctx.vexv = false + end + elseif p == "y" then x = "DR"..sp + elseif p == "z" then x = "TR"..sp + elseif p == "l" then vexl = false + elseif p == "t" then + else + error("bad pattern `"..pat.."'") + end + end + if x then operands = operands and operands..", "..x or x end + end + ctx.pos = pos + return putop(ctx, name, operands) +end + +-- Forward declaration. +local map_act + +-- Fetch and cache MRM byte. +local function getmrm(ctx) + local mrm = ctx.mrm + if not mrm then + local pos = ctx.pos + if pos > ctx.stop then return nil end + mrm = byte(ctx.code, pos, pos) + ctx.pos = pos+1 + ctx.mrm = mrm + end + return mrm +end + +-- Dispatch to handler depending on pattern. +local function dispatch(ctx, opat, patgrp) + if not opat then return unknown(ctx) end + if match(opat, "%|") then -- MMX/SSE variants depending on prefix. + local p + if ctx.rep then + p = ctx.rep=="rep" and "%|([^%|]*)" or "%|[^%|]*%|[^%|]*%|([^%|]*)" + ctx.rep = false + elseif ctx.o16 then p = "%|[^%|]*%|([^%|]*)"; ctx.o16 = false + else p = "^[^%|]*" end + opat = match(opat, p) + if not opat then return unknown(ctx) end +-- ctx.rep = false; ctx.o16 = false + --XXX fails for 66 f2 0f 38 f1 06 crc32 eax,WORD PTR [esi] + --XXX remove in branches? + end + if match(opat, "%$") then -- reg$mem variants. + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + opat = match(opat, mrm >= 192 and "^[^%$]*" or "%$(.*)") + if opat == "" then return unknown(ctx) end + end + if opat == "" then return unknown(ctx) end + local name, pat = match(opat, "^([a-z0-9 ]*)(.*)") + if pat == "" and patgrp then pat = patgrp end + return map_act[sub(pat, 1, 1)](ctx, name, pat) +end + +-- Get a pattern from an opcode map and dispatch to handler. +local function dispatchmap(ctx, opcmap) + local pos = ctx.pos + local opat = opcmap[byte(ctx.code, pos, pos)] + pos = pos + 1 + ctx.pos = pos + return dispatch(ctx, opat) +end + +-- Map for action codes. The key is the first char after the name. +map_act = { + -- Simple opcodes without operands. + [""] = function(ctx, name, pat) + return putop(ctx, name) + end, + + -- Operand size chars fall right through. + B = putpat, W = putpat, D = putpat, Q = putpat, + V = putpat, U = putpat, T = putpat, + M = putpat, X = putpat, P = putpat, + F = putpat, G = putpat, Y = putpat, + H = putpat, + + -- Collect prefixes. + [":"] = function(ctx, name, pat) + ctx[pat == ":" and name or sub(pat, 2)] = name + if ctx.pos - ctx.start > 5 then return unknown(ctx) end -- Limit #prefixes. + end, + + -- Chain to special handler specified by name. + ["*"] = function(ctx, name, pat) + return map_act[name](ctx, name, sub(pat, 2)) + end, + + -- Use named subtable for opcode group. + ["!"] = function(ctx, name, pat) + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + return dispatch(ctx, map_opcgroup[name][((mrm-(mrm%8))/8)%8+1], sub(pat, 2)) + end, + + -- o16,o32[,o64] variants. + sz = function(ctx, name, pat) + if ctx.o16 then ctx.o16 = false + else + pat = match(pat, ",(.*)") + if ctx.rexw then + local p = match(pat, ",(.*)") + if p then pat = p; ctx.rexw = false end + end + end + pat = match(pat, "^[^,]*") + return dispatch(ctx, pat) + end, + + -- Two-byte opcode dispatch. + opc2 = function(ctx, name, pat) + return dispatchmap(ctx, map_opc2) + end, + + -- Three-byte opcode dispatch. + opc3 = function(ctx, name, pat) + return dispatchmap(ctx, map_opc3[pat]) + end, + + -- VMX/SVM dispatch. + vm = function(ctx, name, pat) + return dispatch(ctx, map_opcvm[ctx.mrm]) + end, + + -- Floating point opcode dispatch. + fp = function(ctx, name, pat) + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + local rm = mrm%8 + local idx = pat*8 + ((mrm-rm)/8)%8 + if mrm >= 192 then idx = idx + 64 end + local opat = map_opcfp[idx] + if type(opat) == "table" then opat = opat[rm+1] end + return dispatch(ctx, opat) + end, + + -- REX prefix. + rex = function(ctx, name, pat) + if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. + for p in gmatch(pat, ".") do ctx["rex"..p] = true end + ctx.rex = "rex" + end, + + -- VEX prefix. + vex = function(ctx, name, pat) + if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. + ctx.rex = "vex" + local pos = ctx.pos + if ctx.mrm then + ctx.mrm = nil + pos = pos-1 + end + local b = byte(ctx.code, pos, pos) + if not b then return incomplete(ctx) end + pos = pos+1 + if b < 128 then ctx.rexr = true end + local m = 1 + if pat == "3" then + m = b%32; b = (b-m)/32 + local nb = b%2; b = (b-nb)/2 + if nb == 0 then ctx.rexb = true end + local nx = b%2 + if nx == 0 then ctx.rexx = true end + b = byte(ctx.code, pos, pos) + if not b then return incomplete(ctx) end + pos = pos+1 + if b >= 128 then ctx.rexw = true end + end + ctx.pos = pos + local map + if m == 1 then map = map_opc2 + elseif m == 2 then map = map_opc3["38"] + elseif m == 3 then map = map_opc3["3a"] + else return unknown(ctx) end + local p = b%4; b = (b-p)/4 + if p == 1 then ctx.o16 = "o16" + elseif p == 2 then ctx.rep = "rep" + elseif p == 3 then ctx.rep = "repne" end + local l = b%2; b = (b-l)/2 + if l ~= 0 then ctx.vexl = true end + ctx.vexv = (-1-b)%16 + return dispatchmap(ctx, map) + end, + + -- Special case for nop with REX prefix. + nop = function(ctx, name, pat) + return dispatch(ctx, ctx.rex and pat or "nop") + end, + + -- Special case for 0F 77. + emms = function(ctx, name, pat) + if ctx.rex ~= "vex" then + return putop(ctx, "emms") + elseif ctx.vexl then + ctx.vexl = false + return putop(ctx, "zeroall") + else + return putop(ctx, "zeroupper") + end + end, +} + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ofs = ofs + 1 + ctx.start = ofs + ctx.pos = ofs + ctx.stop = stop + ctx.imm = nil + ctx.mrm = false + clearprefixes(ctx) + while ctx.pos <= stop do dispatchmap(ctx, ctx.map1) end + if ctx.pos ~= ctx.start then incomplete(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = (addr or 0) - 1 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 16 + ctx.x64 = false + ctx.map1 = map_opc1_32 + ctx.aregs = map_regs.D + return ctx +end + +local function create64(code, addr, out) + local ctx = create(code, addr, out) + ctx.x64 = true + ctx.map1 = map_opc1_64 + ctx.aregs = map_regs.Q + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +local function disass64(code, addr, out) + create64(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 8 then return map_regs.D[r+1] end + return map_regs.X[r-7] +end + +local function regname64(r) + if r < 16 then return map_regs.Q[r+1] end + return map_regs.X[r-15] +end + +-- Public module functions. +return { + create = create, + create64 = create64, + disass = disass, + disass64 = disass64, + regname = regname, + regname64 = regname64 +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dump.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dump.lua new file mode 100644 index 00000000..9eda08c4 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/dump.lua @@ -0,0 +1,726 @@ +---------------------------------------------------------------------------- +-- LuaJIT compiler dump module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module can be used to debug the JIT compiler itself. It dumps the +-- code representations and structures used in various compiler stages. +-- +-- Example usage: +-- +-- luajit -jdump -e "local x=0; for i=1,1e6 do x=x+i end; print(x)" +-- luajit -jdump=im -e "for i=1,1000 do for j=1,1000 do end end" | less -R +-- luajit -jdump=is myapp.lua | less -R +-- luajit -jdump=-b myapp.lua +-- luajit -jdump=+aH,myapp.html myapp.lua +-- luajit -jdump=ixT,myapp.dump myapp.lua +-- +-- The first argument specifies the dump mode. The second argument gives +-- the output file name. Default output is to stdout, unless the environment +-- variable LUAJIT_DUMPFILE is set. The file is overwritten every time the +-- module is started. +-- +-- Different features can be turned on or off with the dump mode. If the +-- mode starts with a '+', the following features are added to the default +-- set of features; a '-' removes them. Otherwise the features are replaced. +-- +-- The following dump features are available (* marks the default): +-- +-- * t Print a line for each started, ended or aborted trace (see also -jv). +-- * b Dump the traced bytecode. +-- * i Dump the IR (intermediate representation). +-- r Augment the IR with register/stack slots. +-- s Dump the snapshot map. +-- * m Dump the generated machine code. +-- x Print each taken trace exit. +-- X Print each taken trace exit and the contents of all registers. +-- a Print the IR of aborted traces, too. +-- +-- The output format can be set with the following characters: +-- +-- T Plain text output. +-- A ANSI-colored text output +-- H Colorized HTML + CSS output. +-- +-- The default output format is plain text. It's set to ANSI-colored text +-- if the COLORTERM variable is set. Note: this is independent of any output +-- redirection, which is actually considered a feature. +-- +-- You probably want to use less -R to enjoy viewing ANSI-colored text from +-- a pipe or a file. Add this to your ~/.bashrc: export LESS="-R" +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc +local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek +local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap +local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr +local bit = require("bit") +local band, shr, tohex = bit.band, bit.rshift, bit.tohex +local sub, gsub, format = string.sub, string.gsub, string.format +local byte, rep = string.byte, string.rep +local type, tostring = type, tostring +local stdout, stderr = io.stdout, io.stderr + +-- Load other modules on-demand. +local bcline, disass + +-- Active flag, output file handle and dump mode. +local active, out, dumpmode + +------------------------------------------------------------------------------ + +local symtabmt = { __index = false } +local symtab = {} +local nexitsym = 0 + +-- Fill nested symbol table with per-trace exit stub addresses. +local function fillsymtab_tr(tr, nexit) + local t = {} + symtabmt.__index = t + if jit.arch:sub(1, 4) == "mips" then + t[traceexitstub(tr, 0)] = "exit" + return + end + for i=0,nexit-1 do + local addr = traceexitstub(tr, i) + if addr < 0 then addr = addr + 2^32 end + t[addr] = tostring(i) + end + local addr = traceexitstub(tr, nexit) + if addr then t[addr] = "stack_check" end +end + +-- Fill symbol table with trace exit stub addresses. +local function fillsymtab(tr, nexit) + local t = symtab + if nexitsym == 0 then + local maskaddr = jit.arch == "arm" and -2 + local ircall = vmdef.ircall + for i=0,#ircall do + local addr = ircalladdr(i) + if addr ~= 0 then + if maskaddr then addr = band(addr, maskaddr) end + if addr < 0 then addr = addr + 2^32 end + t[addr] = ircall[i] + end + end + end + if nexitsym == 1000000 then -- Per-trace exit stubs. + fillsymtab_tr(tr, nexit) + elseif nexit > nexitsym then -- Shared exit stubs. + for i=nexitsym,nexit-1 do + local addr = traceexitstub(i) + if addr == nil then -- Fall back to per-trace exit stubs. + fillsymtab_tr(tr, nexit) + setmetatable(symtab, symtabmt) + nexit = 1000000 + break + end + if addr < 0 then addr = addr + 2^32 end + t[addr] = tostring(i) + end + nexitsym = nexit + end + return t +end + +local function dumpwrite(s) + out:write(s) +end + +-- Disassemble machine code. +local function dump_mcode(tr) + local info = traceinfo(tr) + if not info then return end + local mcode, addr, loop = tracemc(tr) + if not mcode then return end + if not disass then disass = require("jit.dis_"..jit.arch) end + if addr < 0 then addr = addr + 2^32 end + out:write("---- TRACE ", tr, " mcode ", #mcode, "\n") + local ctx = disass.create(mcode, addr, dumpwrite) + ctx.hexdump = 0 + ctx.symtab = fillsymtab(tr, info.nexit) + if loop ~= 0 then + symtab[addr+loop] = "LOOP" + ctx:disass(0, loop) + out:write("->LOOP:\n") + ctx:disass(loop, #mcode-loop) + symtab[addr+loop] = nil + else + ctx:disass(0, #mcode) + end +end + +------------------------------------------------------------------------------ + +local irtype_text = { + [0] = "nil", + "fal", + "tru", + "lud", + "str", + "p32", + "thr", + "pro", + "fun", + "p64", + "cdt", + "tab", + "udt", + "flt", + "num", + "i8 ", + "u8 ", + "i16", + "u16", + "int", + "u32", + "i64", + "u64", + "sfp", +} + +local colortype_ansi = { + [0] = "%s", + "%s", + "%s", + "\027[36m%s\027[m", + "\027[32m%s\027[m", + "%s", + "\027[1m%s\027[m", + "%s", + "\027[1m%s\027[m", + "%s", + "\027[33m%s\027[m", + "\027[31m%s\027[m", + "\027[36m%s\027[m", + "\027[34m%s\027[m", + "\027[34m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", +} + +local function colorize_text(s) + return s +end + +local function colorize_ansi(s, t, extra) + local out = format(colortype_ansi[t], s) + if extra then out = "\027[3m"..out end + return out +end + +local irtype_ansi = setmetatable({}, + { __index = function(tab, t) + local s = colorize_ansi(irtype_text[t], t); tab[t] = s; return s; end }) + +local html_escape = { ["<"] = "<", [">"] = ">", ["&"] = "&", } + +local function colorize_html(s, t, extra) + s = gsub(s, "[<>&]", html_escape) + return format('%s', + irtype_text[t], extra and " irt_extra" or "", s) +end + +local irtype_html = setmetatable({}, + { __index = function(tab, t) + local s = colorize_html(irtype_text[t], t); tab[t] = s; return s; end }) + +local header_html = [[ + +]] + +local colorize, irtype + +-- Lookup tables to convert some literals into names. +local litname = { + ["SLOAD "] = setmetatable({}, { __index = function(t, mode) + local s = "" + if band(mode, 1) ~= 0 then s = s.."P" end + if band(mode, 2) ~= 0 then s = s.."F" end + if band(mode, 4) ~= 0 then s = s.."T" end + if band(mode, 8) ~= 0 then s = s.."C" end + if band(mode, 16) ~= 0 then s = s.."R" end + if band(mode, 32) ~= 0 then s = s.."I" end + if band(mode, 64) ~= 0 then s = s.."K" end + t[mode] = s + return s + end}), + ["XLOAD "] = { [0] = "", "R", "V", "RV", "U", "RU", "VU", "RVU", }, + ["CONV "] = setmetatable({}, { __index = function(t, mode) + local s = irtype[band(mode, 31)] + s = irtype[band(shr(mode, 5), 31)].."."..s + if band(mode, 0x800) ~= 0 then s = s.." sext" end + local c = shr(mode, 12) + if c == 1 then s = s.." none" + elseif c == 2 then s = s.." index" + elseif c == 3 then s = s.." check" end + t[mode] = s + return s + end}), + ["FLOAD "] = vmdef.irfield, + ["FREF "] = vmdef.irfield, + ["FPMATH"] = vmdef.irfpm, + ["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" }, + ["BUFHDR"] = { [0] = "RESET", "APPEND", "WRITE" }, + ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, +} + +local function ctlsub(c) + if c == "\n" then return "\\n" + elseif c == "\r" then return "\\r" + elseif c == "\t" then return "\\t" + else return format("\\%03d", byte(c)) + end +end + +local function fmtfunc(func, pc) + local fi = funcinfo(func, pc) + if fi.loc then + return fi.loc + elseif fi.ffid then + return vmdef.ffnames[fi.ffid] + elseif fi.addr then + return format("C:%x", fi.addr) + else + return "(?)" + end +end + +local function formatk(tr, idx, sn) + local k, t, slot = tracek(tr, idx) + local tn = type(k) + local s + if tn == "number" then + if t < 12 then + s = k == 0 and "NULL" or format("[0x%08x]", k) + elseif band(sn or 0, 0x30000) ~= 0 then + s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz" + elseif k == 2^52+2^51 then + s = "bias" + else + s = format(0 < k and k < 0x1p-1026 and "%+a" or "%+.14g", k) + end + elseif tn == "string" then + s = format(#k > 20 and '"%.20s"~' or '"%s"', gsub(k, "%c", ctlsub)) + elseif tn == "function" then + s = fmtfunc(k) + elseif tn == "table" then + s = format("{%p}", k) + elseif tn == "userdata" then + if t == 12 then + s = format("userdata:%p", k) + else + s = format("[%p]", k) + if s == "[NULL]" then s = "NULL" end + end + elseif t == 21 then -- int64_t + s = sub(tostring(k), 1, -3) + if sub(s, 1, 1) ~= "-" then s = "+"..s end + elseif sn == 0x1057fff then -- SNAP(1, SNAP_FRAME | SNAP_NORESTORE, REF_NIL) + return "----" -- Special case for LJ_FR2 slot 1. + else + s = tostring(k) -- For primitives. + end + s = colorize(format("%-4s", s), t, band(sn or 0, 0x100000) ~= 0) + if slot then + s = format("%s @%d", s, slot) + end + return s +end + +local function printsnap(tr, snap) + local n = 2 + for s=0,snap[1]-1 do + local sn = snap[n] + if shr(sn, 24) == s then + n = n + 1 + local ref = band(sn, 0xffff) - 0x8000 -- REF_BIAS + if ref < 0 then + out:write(formatk(tr, ref, sn)) + elseif band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM + out:write(colorize(format("%04d/%04d", ref, ref+1), 14)) + else + local m, ot, op1, op2 = traceir(tr, ref) + out:write(colorize(format("%04d", ref), band(ot, 31), band(sn, 0x100000) ~= 0)) + end + out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME + else + out:write("---- ") + end + end + out:write("]\n") +end + +-- Dump snapshots (not interleaved with IR). +local function dump_snap(tr) + out:write("---- TRACE ", tr, " snapshots\n") + for i=0,1000000000 do + local snap = tracesnap(tr, i) + if not snap then break end + out:write(format("#%-3d %04d [ ", i, snap[0])) + printsnap(tr, snap) + end +end + +-- Return a register name or stack slot for a rid/sp location. +local function ridsp_name(ridsp, ins) + if not disass then disass = require("jit.dis_"..jit.arch) end + local rid, slot = band(ridsp, 0xff), shr(ridsp, 8) + if rid == 253 or rid == 254 then + return (slot == 0 or slot == 255) and " {sink" or format(" {%04d", ins-slot) + end + if ridsp > 255 then return format("[%x]", slot*4) end + if rid < 128 then return disass.regname(rid) end + return "" +end + +-- Dump CALL* function ref and return optional ctype. +local function dumpcallfunc(tr, ins) + local ctype + if ins > 0 then + local m, ot, op1, op2 = traceir(tr, ins) + if band(ot, 31) == 0 then -- nil type means CARG(func, ctype). + ins = op1 + ctype = formatk(tr, op2) + end + end + if ins < 0 then + out:write(format("[0x%x](", tonumber((tracek(tr, ins))))) + else + out:write(format("%04d (", ins)) + end + return ctype +end + +-- Recursively gather CALL* args and dump them. +local function dumpcallargs(tr, ins) + if ins < 0 then + out:write(formatk(tr, ins)) + else + local m, ot, op1, op2 = traceir(tr, ins) + local oidx = 6*shr(ot, 8) + local op = sub(vmdef.irnames, oidx+1, oidx+6) + if op == "CARG " then + dumpcallargs(tr, op1) + if op2 < 0 then + out:write(" ", formatk(tr, op2)) + else + out:write(" ", format("%04d", op2)) + end + else + out:write(format("%04d", ins)) + end + end +end + +-- Dump IR and interleaved snapshots. +local function dump_ir(tr, dumpsnap, dumpreg) + local info = traceinfo(tr) + if not info then return end + local nins = info.nins + out:write("---- TRACE ", tr, " IR\n") + local irnames = vmdef.irnames + local snapref = 65536 + local snap, snapno + if dumpsnap then + snap = tracesnap(tr, 0) + snapref = snap[0] + snapno = 0 + end + for ins=1,nins do + if ins >= snapref then + if dumpreg then + out:write(format(".... SNAP #%-3d [ ", snapno)) + else + out:write(format(".... SNAP #%-3d [ ", snapno)) + end + printsnap(tr, snap) + snapno = snapno + 1 + snap = tracesnap(tr, snapno) + snapref = snap and snap[0] or 65536 + end + local m, ot, op1, op2, ridsp = traceir(tr, ins) + local oidx, t = 6*shr(ot, 8), band(ot, 31) + local op = sub(irnames, oidx+1, oidx+6) + if op == "LOOP " then + if dumpreg then + out:write(format("%04d ------------ LOOP ------------\n", ins)) + else + out:write(format("%04d ------ LOOP ------------\n", ins)) + end + elseif op ~= "NOP " and op ~= "CARG " and + (dumpreg or op ~= "RENAME") then + local rid = band(ridsp, 255) + if dumpreg then + out:write(format("%04d %-6s", ins, ridsp_name(ridsp, ins))) + else + out:write(format("%04d ", ins)) + end + out:write(format("%s%s %s %s ", + (rid == 254 or rid == 253) and "}" or + (band(ot, 128) == 0 and " " or ">"), + band(ot, 64) == 0 and " " or "+", + irtype[t], op)) + local m1, m2 = band(m, 3), band(m, 3*4) + if sub(op, 1, 4) == "CALL" then + local ctype + if m2 == 1*4 then -- op2 == IRMlit + out:write(format("%-10s (", vmdef.ircall[op2])) + else + ctype = dumpcallfunc(tr, op2) + end + if op1 ~= -1 then dumpcallargs(tr, op1) end + out:write(")") + if ctype then out:write(" ctype ", ctype) end + elseif op == "CNEW " and op2 == -1 then + out:write(formatk(tr, op1)) + elseif m1 ~= 3 then -- op1 != IRMnone + if op1 < 0 then + out:write(formatk(tr, op1)) + else + out:write(format(m1 == 0 and "%04d" or "#%-3d", op1)) + end + if m2 ~= 3*4 then -- op2 != IRMnone + if m2 == 1*4 then -- op2 == IRMlit + local litn = litname[op] + if litn and litn[op2] then + out:write(" ", litn[op2]) + elseif op == "UREFO " or op == "UREFC " then + out:write(format(" #%-3d", shr(op2, 8))) + else + out:write(format(" #%-3d", op2)) + end + elseif op2 < 0 then + out:write(" ", formatk(tr, op2)) + else + out:write(format(" %04d", op2)) + end + end + end + out:write("\n") + end + end + if snap then + if dumpreg then + out:write(format(".... SNAP #%-3d [ ", snapno)) + else + out:write(format(".... SNAP #%-3d [ ", snapno)) + end + printsnap(tr, snap) + end +end + +------------------------------------------------------------------------------ + +local recprefix = "" +local recdepth = 0 + +-- Format trace error message. +local function fmterr(err, info) + if type(err) == "number" then + if type(info) == "function" then info = fmtfunc(info) end + err = format(vmdef.traceerr[err], info) + end + return err +end + +-- Dump trace states. +local function dump_trace(what, tr, func, pc, otr, oex) + if what == "stop" or (what == "abort" and dumpmode.a) then + if dumpmode.i then dump_ir(tr, dumpmode.s, dumpmode.r and what == "stop") + elseif dumpmode.s then dump_snap(tr) end + if dumpmode.m then dump_mcode(tr) end + end + if what == "start" then + if dumpmode.H then out:write('

\n') end
+    out:write("---- TRACE ", tr, " ", what)
+    if otr then out:write(" ", otr, "/", oex == -1 and "stitch" or oex) end
+    out:write(" ", fmtfunc(func, pc), "\n")
+  elseif what == "stop" or what == "abort" then
+    out:write("---- TRACE ", tr, " ", what)
+    if what == "abort" then
+      out:write(" ", fmtfunc(func, pc), " -- ", fmterr(otr, oex), "\n")
+    else
+      local info = traceinfo(tr)
+      local link, ltype = info.link, info.linktype
+      if link == tr or link == 0 then
+	out:write(" -> ", ltype, "\n")
+      elseif ltype == "root" then
+	out:write(" -> ", link, "\n")
+      else
+	out:write(" -> ", link, " ", ltype, "\n")
+      end
+    end
+    if dumpmode.H then out:write("
\n\n") else out:write("\n") end + else + if what == "flush" then symtab, nexitsym = {}, 0 end + out:write("---- TRACE ", what, "\n\n") + end + out:flush() +end + +-- Dump recorded bytecode. +local function dump_record(tr, func, pc, depth) + if depth ~= recdepth then + recdepth = depth + recprefix = rep(" .", depth) + end + local line + if pc >= 0 then + line = bcline(func, pc, recprefix) + if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end + else + line = "0000 "..recprefix.." FUNCC \n" + end + if pc <= 0 then + out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n") + else + out:write(line) + end + if pc >= 0 and band(funcbc(func, pc), 0xff) < 16 then -- ORDER BC + out:write(bcline(func, pc+1, recprefix)) -- Write JMP for cond. + end +end + +------------------------------------------------------------------------------ + +local gpr64 = jit.arch:match("64") +local fprmips32 = jit.arch == "mips" or jit.arch == "mipsel" + +-- Dump taken trace exits. +local function dump_texit(tr, ex, ngpr, nfpr, ...) + out:write("---- TRACE ", tr, " exit ", ex, "\n") + if dumpmode.X then + local regs = {...} + if gpr64 then + for i=1,ngpr do + out:write(format(" %016x", regs[i])) + if i % 4 == 0 then out:write("\n") end + end + else + for i=1,ngpr do + out:write(" ", tohex(regs[i])) + if i % 8 == 0 then out:write("\n") end + end + end + if fprmips32 then + for i=1,nfpr,2 do + out:write(format(" %+17.14g", regs[ngpr+i])) + if i % 8 == 7 then out:write("\n") end + end + else + for i=1,nfpr do + out:write(format(" %+17.14g", regs[ngpr+i])) + if i % 4 == 0 then out:write("\n") end + end + end + end +end + +------------------------------------------------------------------------------ + +-- Detach dump handlers. +local function dumpoff() + if active then + active = false + jit.attach(dump_texit) + jit.attach(dump_record) + jit.attach(dump_trace) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handlers. +local function dumpon(opt, outfile) + if active then dumpoff() end + + local term = os.getenv("TERM") + local colormode = (term and term:match("color") or os.getenv("COLORTERM")) and "A" or "T" + if opt then + opt = gsub(opt, "[TAH]", function(mode) colormode = mode; return ""; end) + end + + local m = { t=true, b=true, i=true, m=true, } + if opt and opt ~= "" then + local o = sub(opt, 1, 1) + if o ~= "+" and o ~= "-" then m = {} end + for i=1,#opt do m[sub(opt, i, i)] = (o ~= "-") end + end + dumpmode = m + + if m.t or m.b or m.i or m.s or m.m then + jit.attach(dump_trace, "trace") + end + if m.b then + jit.attach(dump_record, "record") + if not bcline then bcline = require("jit.bc").line end + end + if m.x or m.X then + jit.attach(dump_texit, "texit") + end + + if not outfile then outfile = os.getenv("LUAJIT_DUMPFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stdout + end + + m[colormode] = true + if colormode == "A" then + colorize = colorize_ansi + irtype = irtype_ansi + elseif colormode == "H" then + colorize = colorize_html + irtype = irtype_html + out:write(header_html) + else + colorize = colorize_text + irtype = irtype_text + end + + active = true +end + +-- Public module functions. +return { + on = dumpon, + off = dumpoff, + start = dumpon -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/p.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/p.lua new file mode 100644 index 00000000..c9ec1d8b --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/p.lua @@ -0,0 +1,312 @@ +---------------------------------------------------------------------------- +-- LuaJIT profiler. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module is a simple command line interface to the built-in +-- low-overhead profiler of LuaJIT. +-- +-- The lower-level API of the profiler is accessible via the "jit.profile" +-- module or the luaJIT_profile_* C API. +-- +-- Example usage: +-- +-- luajit -jp myapp.lua +-- luajit -jp=s myapp.lua +-- luajit -jp=-s myapp.lua +-- luajit -jp=vl myapp.lua +-- luajit -jp=G,profile.txt myapp.lua +-- +-- The following dump features are available: +-- +-- f Stack dump: function name, otherwise module:line. Default mode. +-- F Stack dump: ditto, but always prepend module. +-- l Stack dump: module:line. +-- stack dump depth (callee < caller). Default: 1. +-- - Inverse stack dump depth (caller > callee). +-- s Split stack dump after first stack level. Implies abs(depth) >= 2. +-- p Show full path for module names. +-- v Show VM states. Can be combined with stack dumps, e.g. vf or fv. +-- z Show zones. Can be combined with stack dumps, e.g. zf or fz. +-- 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 (e.g. flame graphs). +-- m Minimum sample percentage to be shown. Default: 3. +-- i Sampling interval in milliseconds. Default: 10. +-- +---------------------------------------------------------------------------- + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local profile = require("jit.profile") +local vmdef = require("jit.vmdef") +local math = math +local pairs, ipairs, tonumber, floor = pairs, ipairs, tonumber, math.floor +local sort, format = table.sort, string.format +local stdout = io.stdout +local zone -- Load jit.zone module on demand. + +-- Output file handle. +local out + +------------------------------------------------------------------------------ + +local prof_ud +local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth +local prof_ann, prof_count1, prof_count2, prof_samples + +local map_vmmode = { + N = "Compiled", + I = "Interpreted", + C = "C code", + G = "Garbage Collector", + J = "JIT Compiler", +} + +-- Profiler callback. +local function prof_cb(th, samples, vmmode) + prof_samples = prof_samples + samples + local key_stack, key_stack2, key_state + -- Collect keys for sample. + if prof_states then + if prof_states == "v" then + key_state = map_vmmode[vmmode] or vmmode + else + key_state = zone:get() or "(none)" + end + end + if prof_fmt then + key_stack = profile.dumpstack(th, prof_fmt, prof_depth) + key_stack = key_stack:gsub("%[builtin#(%d+)%]", function(x) + return vmdef.ffnames[tonumber(x)] + end) + if prof_split == 2 then + local k1, k2 = key_stack:match("(.-) [<>] (.*)") + if k2 then key_stack, key_stack2 = k1, k2 end + elseif prof_split == 3 then + key_stack2 = profile.dumpstack(th, "l", 1) + end + end + -- Order keys. + local k1, k2 + if prof_split == 1 then + if key_state then + k1 = key_state + if key_stack then k2 = key_stack end + end + elseif key_stack then + k1 = key_stack + if key_stack2 then k2 = key_stack2 elseif key_state then k2 = key_state end + end + -- Coalesce samples in one or two levels. + if k1 then + local t1 = prof_count1 + t1[k1] = (t1[k1] or 0) + samples + if k2 then + local t2 = prof_count2 + local t3 = t2[k1] + if not t3 then t3 = {}; t2[k1] = t3 end + t3[k2] = (t3[k2] or 0) + samples + end + end +end + +------------------------------------------------------------------------------ + +-- Show top N list. +local function prof_top(count1, count2, samples, indent) + local t, n = {}, 0 + for k in pairs(count1) do + n = n + 1 + t[n] = k + end + sort(t, function(a, b) return count1[a] > count1[b] end) + for i=1,n do + local k = t[i] + local v = count1[k] + local pct = floor(v*100/samples + 0.5) + if pct < prof_min then break end + if not prof_raw then + out:write(format("%s%2d%% %s\n", indent, pct, k)) + elseif prof_raw == "r" then + out:write(format("%s%5d %s\n", indent, v, k)) + else + out:write(format("%s %d\n", k, v)) + end + if count2 then + local r = count2[k] + if r then + prof_top(r, nil, v, (prof_split == 3 or prof_split == 1) and " -- " or + (prof_depth < 0 and " -> " or " <- ")) + end + end + end +end + +-- Annotate source code +local function prof_annotate(count1, samples) + local files = {} + local ms = 0 + for k, v in pairs(count1) do + local pct = floor(v*100/samples + 0.5) + ms = math.max(ms, v) + if pct >= prof_min then + local file, line = k:match("^(.*):(%d+)$") + if not file then file = k; line = 0 end + local fl = files[file] + if not fl then fl = {}; files[file] = fl; files[#files+1] = file end + line = tonumber(line) + fl[line] = prof_raw and v or pct + end + end + sort(files) + local fmtv, fmtn = " %3d%% | %s\n", " | %s\n" + if prof_raw then + local n = math.max(5, math.ceil(math.log10(ms))) + fmtv = "%"..n.."d | %s\n" + fmtn = (" "):rep(n).." | %s\n" + end + local ann = prof_ann + for _, file in ipairs(files) do + local f0 = file:byte() + if f0 == 40 or f0 == 91 then + out:write(format("\n====== %s ======\n[Cannot annotate non-file]\n", file)) + break + end + local fp, err = io.open(file) + if not fp then + out:write(format("====== ERROR: %s: %s\n", file, err)) + break + end + out:write(format("\n====== %s ======\n", file)) + local fl = files[file] + local n, show = 1, false + if ann ~= 0 then + for i=1,ann do + if fl[i] then show = true; out:write("@@ 1 @@\n"); break end + end + end + for line in fp:lines() do + if line:byte() == 27 then + out:write("[Cannot annotate bytecode file]\n") + break + end + local v = fl[n] + if ann ~= 0 then + local v2 = fl[n+ann] + if show then + if v2 then show = n+ann elseif v then show = n + elseif show+ann < n then show = false end + elseif v2 then + show = n+ann + out:write(format("@@ %d @@\n", n)) + end + if not show then goto next end + end + if v then + out:write(format(fmtv, v, line)) + else + out:write(format(fmtn, line)) + end + ::next:: + n = n + 1 + end + fp:close() + end +end + +------------------------------------------------------------------------------ + +-- Finish profiling and dump result. +local function prof_finish() + if prof_ud then + profile.stop() + local samples = prof_samples + if samples == 0 then + if prof_raw ~= true then out:write("[No samples collected]\n") end + return + end + if prof_ann then + prof_annotate(prof_count1, samples) + else + prof_top(prof_count1, prof_count2, samples, "") + end + prof_count1 = nil + prof_count2 = nil + prof_ud = nil + if out ~= stdout then out:close() end + end +end + +-- Start profiling. +local function prof_start(mode) + local interval = "" + mode = mode:gsub("i%d*", function(s) interval = s; return "" end) + prof_min = 3 + mode = mode:gsub("m(%d+)", function(s) prof_min = tonumber(s); return "" end) + prof_depth = 1 + mode = mode:gsub("%-?%d+", function(s) prof_depth = tonumber(s); return "" end) + local m = {} + for c in mode:gmatch(".") do m[c] = c end + prof_states = m.z or m.v + if prof_states == "z" then zone = require("jit.zone") end + local scope = m.l or m.f or m.F or (prof_states and "" or "f") + local flags = (m.p or "") + prof_raw = m.r + if m.s then + prof_split = 2 + if prof_depth == -1 or m["-"] then prof_depth = -2 + elseif prof_depth == 1 then prof_depth = 2 end + elseif mode:find("[fF].*l") then + scope = "l" + prof_split = 3 + else + prof_split = (scope == "" or mode:find("[zv].*[lfF]")) and 1 or 0 + end + prof_ann = m.A and 0 or (m.a and 3) + if prof_ann then + scope = "l" + prof_fmt = "pl" + prof_split = 0 + prof_depth = 1 + elseif m.G and scope ~= "" then + prof_fmt = flags..scope.."Z;" + prof_depth = -100 + prof_raw = true + prof_min = 0 + elseif scope == "" then + prof_fmt = false + else + local sc = prof_split == 3 and m.f or m.F or scope + prof_fmt = flags..sc..(prof_depth >= 0 and "Z < " or "Z > ") + end + prof_count1 = {} + prof_count2 = {} + prof_samples = 0 + profile.start(scope:lower()..interval, prof_cb) + prof_ud = newproxy(true) + getmetatable(prof_ud).__gc = prof_finish +end + +------------------------------------------------------------------------------ + +local function start(mode, outfile) + if not outfile then outfile = os.getenv("LUAJIT_PROFILEFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stdout + end + prof_start(mode or "f") +end + +-- Public module functions. +return { + start = start, -- For -j command line option. + stop = prof_finish +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/v.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/v.lua new file mode 100644 index 00000000..83589143 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/v.lua @@ -0,0 +1,170 @@ +---------------------------------------------------------------------------- +-- Verbose mode of the LuaJIT compiler. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module shows verbose information about the progress of the +-- JIT compiler. It prints one line for each generated trace. This module +-- is useful to see which code has been compiled or where the compiler +-- punts and falls back to the interpreter. +-- +-- Example usage: +-- +-- luajit -jv -e "for i=1,1000 do for j=1,1000 do end end" +-- luajit -jv=myapp.out myapp.lua +-- +-- Default output is to stderr. To redirect the output to a file, pass a +-- filename as an argument (use '-' for stdout) or set the environment +-- variable LUAJIT_VERBOSEFILE. The file is overwritten every time the +-- module is started. +-- +-- The output from the first example should look like this: +-- +-- [TRACE 1 (command line):1 loop] +-- [TRACE 2 (1/3) (command line):1 -> 1] +-- +-- The first number in each line is the internal trace number. Next are +-- the file name ('(command line)') and the line number (':1') where the +-- trace has started. Side traces also show the parent trace number and +-- the exit number where they are attached to in parentheses ('(1/3)'). +-- An arrow at the end shows where the trace links to ('-> 1'), unless +-- it loops to itself. +-- +-- In this case the inner loop gets hot and is traced first, generating +-- a root trace. Then the last exit from the 1st trace gets hot, too, +-- and triggers generation of the 2nd trace. The side trace follows the +-- path along the outer loop and *around* the inner loop, back to its +-- start, and then links to the 1st trace. Yes, this may seem unusual, +-- if you know how traditional compilers work. Trace compilers are full +-- of surprises like this -- have fun! :-) +-- +-- Aborted traces are shown like this: +-- +-- [TRACE --- foo.lua:44 -- leaving loop in root trace at foo:lua:50] +-- +-- Don't worry -- trace aborts are quite common, even in programs which +-- can be fully compiled. The compiler may retry several times until it +-- finds a suitable trace. +-- +-- Of course this doesn't work with features that are not-yet-implemented +-- (NYI error messages). The VM simply falls back to the interpreter. This +-- may not matter at all if the particular trace is not very high up in +-- the CPU usage profile. Oh, and the interpreter is quite fast, too. +-- +-- Also check out the -jdump module, which prints all the gory details. +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo +local type, format = type, string.format +local stdout, stderr = io.stdout, io.stderr + +-- Active flag and output file handle. +local active, out + +------------------------------------------------------------------------------ + +local startloc, startex + +local function fmtfunc(func, pc) + local fi = funcinfo(func, pc) + if fi.loc then + return fi.loc + elseif fi.ffid then + return vmdef.ffnames[fi.ffid] + elseif fi.addr then + return format("C:%x", fi.addr) + else + return "(?)" + end +end + +-- Format trace error message. +local function fmterr(err, info) + if type(err) == "number" then + if type(info) == "function" then info = fmtfunc(info) end + err = format(vmdef.traceerr[err], info) + end + return err +end + +-- Dump trace states. +local function dump_trace(what, tr, func, pc, otr, oex) + if what == "start" then + startloc = fmtfunc(func, pc) + startex = otr and "("..otr.."/"..(oex == -1 and "stitch" or oex)..") " or "" + else + if what == "abort" then + local loc = fmtfunc(func, pc) + if loc ~= startloc then + out:write(format("[TRACE --- %s%s -- %s at %s]\n", + startex, startloc, fmterr(otr, oex), loc)) + else + out:write(format("[TRACE --- %s%s -- %s]\n", + startex, startloc, fmterr(otr, oex))) + end + elseif what == "stop" then + local info = traceinfo(tr) + local link, ltype = info.link, info.linktype + if ltype == "interpreter" then + out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n", + tr, startex, startloc)) + elseif ltype == "stitch" then + out:write(format("[TRACE %3s %s%s %s %s]\n", + tr, startex, startloc, ltype, fmtfunc(func, pc))) + elseif link == tr or link == 0 then + out:write(format("[TRACE %3s %s%s %s]\n", + tr, startex, startloc, ltype)) + elseif ltype == "root" then + out:write(format("[TRACE %3s %s%s -> %d]\n", + tr, startex, startloc, link)) + else + out:write(format("[TRACE %3s %s%s -> %d %s]\n", + tr, startex, startloc, link, ltype)) + end + else + out:write(format("[TRACE %s]\n", what)) + end + out:flush() + end +end + +------------------------------------------------------------------------------ + +-- Detach dump handlers. +local function dumpoff() + if active then + active = false + jit.attach(dump_trace) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handlers. +local function dumpon(outfile) + if active then dumpoff() end + if not outfile then outfile = os.getenv("LUAJIT_VERBOSEFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stderr + end + jit.attach(dump_trace, "trace") + active = true +end + +-- Public module functions. +return { + on = dumpon, + off = dumpoff, + start = dumpon -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/vmdef.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/vmdef.lua new file mode 100644 index 00000000..68ff7ba2 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/vmdef.lua @@ -0,0 +1,395 @@ +-- This is a generated file. DO NOT EDIT! + +return { + +bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF ISTYPEISNUM MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TGETR TSETV TSETS TSETB TSETM TSETR CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW", + +irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEPROF KPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF TMPREFSTRREFLREF ALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ALEN ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI BUFHDRBUFPUTBUFSTRTBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLA CALLL CALLS CALLXSCARG ", + +irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "log", "log2", "other", }, + +irfield = { [0]="str.len", "func.env", "func.pc", "func.ffid", "thread.env", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "sbuf.w", "sbuf.e", "sbuf.b", "sbuf.l", "sbuf.ref", "sbuf.r", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", }, + +ircall = { +[0]="lj_str_cmp", +"lj_str_find", +"lj_str_new", +"lj_strscan_num", +"lj_strfmt_int", +"lj_strfmt_num", +"lj_strfmt_char", +"lj_strfmt_putint", +"lj_strfmt_putnum", +"lj_strfmt_putquoted", +"lj_strfmt_putfxint", +"lj_strfmt_putfnum_int", +"lj_strfmt_putfnum_uint", +"lj_strfmt_putfnum", +"lj_strfmt_putfstr", +"lj_strfmt_putfchar", +"lj_buf_putmem", +"lj_buf_putstr", +"lj_buf_putchar", +"lj_buf_putstr_reverse", +"lj_buf_putstr_lower", +"lj_buf_putstr_upper", +"lj_buf_putstr_rep", +"lj_buf_puttab", +"lj_bufx_set", +"lj_bufx_more", +"lj_serialize_put", +"lj_serialize_get", +"lj_serialize_encode", +"lj_serialize_decode", +"lj_buf_tostr", +"lj_tab_new_ah", +"lj_tab_new1", +"lj_tab_dup", +"lj_tab_clear", +"lj_tab_newkey", +"lj_tab_keyindex", +"lj_vm_next", +"lj_tab_len", +"lj_tab_len_hint", +"lj_gc_step_jit", +"lj_gc_barrieruv", +"lj_mem_newgco", +"lj_prng_u64d", +"lj_vm_modi", +"log10", +"exp", +"sin", +"cos", +"tan", +"asin", +"acos", +"atan", +"sinh", +"cosh", +"tanh", +"fputc", +"fwrite", +"fflush", +"lj_vm_floor", +"lj_vm_ceil", +"lj_vm_trunc", +"sqrt", +"log", +"lj_vm_log2", +"lj_vm_powi", +"pow", +"atan2", +"ldexp", +"lj_vm_tobit", +"softfp_add", +"softfp_sub", +"softfp_mul", +"softfp_div", +"softfp_cmp", +"softfp_i2d", +"softfp_d2i", +"lj_vm_sfmin", +"lj_vm_sfmax", +"lj_vm_tointg", +"softfp_ui2d", +"softfp_f2d", +"softfp_d2ui", +"softfp_d2f", +"softfp_i2f", +"softfp_ui2f", +"softfp_f2i", +"softfp_f2ui", +"fp64_l2d", +"fp64_ul2d", +"fp64_l2f", +"fp64_ul2f", +"fp64_d2l", +"fp64_d2ul", +"fp64_f2l", +"fp64_f2ul", +"lj_carith_divi64", +"lj_carith_divu64", +"lj_carith_modi64", +"lj_carith_modu64", +"lj_carith_powi64", +"lj_carith_powu64", +"lj_cdata_newv", +"lj_cdata_setfin", +"strlen", +"memcpy", +"memset", +"lj_vm_errno", +"lj_carith_mul64", +"lj_carith_shl64", +"lj_carith_shr64", +"lj_carith_sar64", +"lj_carith_rol64", +"lj_carith_ror64", +}, + +traceerr = { +[0]="error thrown or hook called during recording", +"trace too short", +"trace too long", +"trace too deep", +"too many snapshots", +"blacklisted", +"retry recording", +"NYI: bytecode %d", +"leaving loop in root trace", +"inner loop in root trace", +"loop unroll limit reached", +"bad argument type", +"JIT compilation disabled for function", +"call unroll limit reached", +"down-recursion, restarting", +"NYI: unsupported variant of FastFunc %s", +"NYI: return to lower frame", +"store with nil or NaN key", +"missing metamethod", +"looping index lookup", +"NYI: mixed sparse/dense table", +"symbol not in cache", +"NYI: unsupported C type conversion", +"NYI: unsupported C function type", +"guard would always fail", +"too many PHIs", +"persistent type instability", +"failed to allocate mcode memory", +"machine code too long", +"hit mcode limit (retrying)", +"too many spill slots", +"inconsistent register allocation", +"NYI: cannot assemble IR instruction %d", +"NYI: PHI shuffling too complex", +"NYI: register coalescing too complex", +}, + +ffnames = { +[0]="Lua", +"C", +"assert", +"type", +"next", +"pairs", +"ipairs_aux", +"ipairs", +"getmetatable", +"setmetatable", +"getfenv", +"setfenv", +"rawget", +"rawset", +"rawequal", +"unpack", +"select", +"tonumber", +"tostring", +"error", +"pcall", +"xpcall", +"loadfile", +"load", +"loadstring", +"dofile", +"gcinfo", +"collectgarbage", +"newproxy", +"print", +"coroutine.status", +"coroutine.running", +"coroutine.isyieldable", +"coroutine.create", +"coroutine.yield", +"coroutine.resume", +"coroutine.wrap_aux", +"coroutine.wrap", +"math.abs", +"math.floor", +"math.ceil", +"math.sqrt", +"math.log10", +"math.exp", +"math.sin", +"math.cos", +"math.tan", +"math.asin", +"math.acos", +"math.atan", +"math.sinh", +"math.cosh", +"math.tanh", +"math.frexp", +"math.modf", +"math.log", +"math.atan2", +"math.pow", +"math.fmod", +"math.ldexp", +"math.min", +"math.max", +"math.random", +"math.randomseed", +"bit.tobit", +"bit.bnot", +"bit.bswap", +"bit.lshift", +"bit.rshift", +"bit.arshift", +"bit.rol", +"bit.ror", +"bit.band", +"bit.bor", +"bit.bxor", +"bit.tohex", +"string.byte", +"string.char", +"string.sub", +"string.rep", +"string.reverse", +"string.lower", +"string.upper", +"string.dump", +"string.find", +"string.match", +"string.gmatch_aux", +"string.gmatch", +"string.gsub", +"string.format", +"table.maxn", +"table.insert", +"table.concat", +"table.sort", +"table.new", +"table.clear", +"io.method.close", +"io.method.read", +"io.method.write", +"io.method.flush", +"io.method.seek", +"io.method.setvbuf", +"io.method.lines", +"io.method.__gc", +"io.method.__tostring", +"io.open", +"io.popen", +"io.tmpfile", +"io.close", +"io.read", +"io.write", +"io.flush", +"io.input", +"io.output", +"io.lines", +"io.type", +"os.execute", +"os.remove", +"os.rename", +"os.tmpname", +"os.getenv", +"os.exit", +"os.clock", +"os.date", +"os.time", +"os.difftime", +"os.setlocale", +"debug.getregistry", +"debug.getmetatable", +"debug.setmetatable", +"debug.getfenv", +"debug.setfenv", +"debug.getinfo", +"debug.getlocal", +"debug.setlocal", +"debug.getupvalue", +"debug.setupvalue", +"debug.upvalueid", +"debug.upvaluejoin", +"debug.sethook", +"debug.gethook", +"debug.debug", +"debug.traceback", +"jit.on", +"jit.off", +"jit.flush", +"jit.status", +"jit.security", +"jit.attach", +"jit.util.funcinfo", +"jit.util.funcbc", +"jit.util.funck", +"jit.util.funcuvname", +"jit.util.traceinfo", +"jit.util.traceir", +"jit.util.tracek", +"jit.util.tracesnap", +"jit.util.tracemc", +"jit.util.traceexitstub", +"jit.util.ircalladdr", +"jit.opt.start", +"jit.profile.start", +"jit.profile.stop", +"jit.profile.dumpstack", +"ffi.meta.__index", +"ffi.meta.__newindex", +"ffi.meta.__eq", +"ffi.meta.__len", +"ffi.meta.__lt", +"ffi.meta.__le", +"ffi.meta.__concat", +"ffi.meta.__call", +"ffi.meta.__add", +"ffi.meta.__sub", +"ffi.meta.__mul", +"ffi.meta.__div", +"ffi.meta.__mod", +"ffi.meta.__pow", +"ffi.meta.__unm", +"ffi.meta.__tostring", +"ffi.meta.__pairs", +"ffi.meta.__ipairs", +"ffi.clib.__index", +"ffi.clib.__newindex", +"ffi.clib.__gc", +"ffi.callback.free", +"ffi.callback.set", +"ffi.cdef", +"ffi.new", +"ffi.cast", +"ffi.typeof", +"ffi.typeinfo", +"ffi.istype", +"ffi.sizeof", +"ffi.alignof", +"ffi.offsetof", +"ffi.errno", +"ffi.string", +"ffi.copy", +"ffi.fill", +"ffi.abi", +"ffi.metatype", +"ffi.gc", +"ffi.load", +"buffer.method.free", +"buffer.method.reset", +"buffer.method.skip", +"buffer.method.set", +"buffer.method.put", +"buffer.method.putf", +"buffer.method.get", +"buffer.method.putcdata", +"buffer.method.reserve", +"buffer.method.commit", +"buffer.method.ref", +"buffer.method.encode", +"buffer.method.decode", +"buffer.method.__gc", +"buffer.method.__tostring", +"buffer.method.__len", +"buffer.new", +"buffer.encode", +"buffer.decode", +}, + +} + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/zone.lua b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/zone.lua new file mode 100644 index 00000000..94357854 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/jit/zone.lua @@ -0,0 +1,45 @@ +---------------------------------------------------------------------------- +-- LuaJIT profiler zones. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module implements a simple hierarchical zone model. +-- +-- Example usage: +-- +-- local zone = require("jit.zone") +-- zone("AI") +-- ... +-- zone("A*") +-- ... +-- print(zone:get()) --> "A*" +-- ... +-- zone() +-- ... +-- print(zone:get()) --> "AI" +-- ... +-- zone() +-- +---------------------------------------------------------------------------- + +local remove = table.remove + +return setmetatable({ + flush = function(t) + for i=#t,1,-1 do t[i] = nil end + end, + get = function(t) + return t[#t] + end +}, { + __call = function(t, zone) + if zone then + t[#t+1] = zone + else + return (assert(remove(t), "empty zone stack")) + end + end +}) + diff --git a/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/libluajit.a b/love/src/jni/LuaJIT-2.1/android/armeabi-v7a/libluajit.a index 0d4e76a56ce6181442fec49522e8e6b366325f22..54b753964c0bed4dcf0615fb4e0d24fd8e779df7 100644 GIT binary patch delta 272787 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
w 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%0A2Nyjpx}U{ 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�!%aPkgj^A|43&VycHe_VHPQK-E?4qVe-Q7`bo7-M|Q{f(aK*GtB z_li9%dOE{-i!XS}S$mc=L$1=u2+Db>!I4^r8F49)00G4fv5G!^dv9$C{5! zC+-`2+kLd_gxc=JTW-I3`kB8ytNrBKePeGuvxVL5t{vj!^Bxp?%^59sH+}u_=^w>o zH@EzLv(tSKiJfysShvRV$)`Ld_LxIYZ4BOx!?#|~s*)PH^Y~38$Bt`o{(rmbjrZ7T z*7#)kVX?8(x_-aaQ+xRFWA|L@T@R1_&t>;qfPLeRWB1sUcF5y*O#kNLv4baQubSkGdc>(fYq<$Mh#Jh`sF( z=f$yGj@~--zdCSt+}(Sw$4-Cb@>u_Qm!}@9@MVEZ1Koj3rq4~q zE9xnjUVp0SMbrH~vG1G;T{3G^c*ZK^(fRjB@hSH+G|{bke9C&v0OygYSTr1N?PqQRws?!YB*s+tgU z@pS2lvGdfI=_k^cM?Q(Zl=PC+)oqp}rvHsr6QJD52clD@|esM^+C=mWn_s)58?1^VO=k&mn zV^>ap;K{Mqoz2)>+h3B6Z3P0fKvA1fUs60Isu0K7N zJk{Ps)8{>-F_tGUeManz(;78Qr?RnE-kssI*;q-{J?5FAy0<XuJ4OAv*k7J1ammSr=XyvM z2EsZ#=y|dCsmy1e7s^DRAN$Fv>=#Y{8`&MKRYY(&$r$cjPM~}aa5Ek9P?Fpu)vZ zpVi2x&#sl{RE70xLI+Qk&!5f*Zu)%Mf2X>7O(x_EE6vNz1RpV;YD{@gEkB8jzrQA< z-#x3*b2ZFL-qrAfhC_uHt1y3E)b|D+x;XWxQPaP}+-M11AO=l delta 240567 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 diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/bc.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/bc.lua new file mode 100644 index 00000000..e58a3fef --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/bc.lua @@ -0,0 +1,190 @@ +---------------------------------------------------------------------------- +-- LuaJIT bytecode listing module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module lists the bytecode of a Lua function. If it's loaded by -jbc +-- it hooks into the parser and lists all functions of a chunk as they +-- are parsed. +-- +-- Example usage: +-- +-- luajit -jbc -e 'local x=0; for i=1,1e6 do x=x+i end; print(x)' +-- luajit -jbc=- foo.lua +-- luajit -jbc=foo.list foo.lua +-- +-- Default output is to stderr. To redirect the output to a file, pass a +-- filename as an argument (use '-' for stdout) or set the environment +-- variable LUAJIT_LISTFILE. The file is overwritten every time the module +-- is started. +-- +-- This module can also be used programmatically: +-- +-- local bc = require("jit.bc") +-- +-- local function foo() print("hello") end +-- +-- bc.dump(foo) --> -- BYTECODE -- [...] +-- print(bc.line(foo, 2)) --> 0002 KSTR 1 1 ; "hello" +-- +-- local out = { +-- -- Do something with each line: +-- write = function(t, ...) io.write(...) end, +-- close = function(t) end, +-- flush = function(t) end, +-- } +-- bc.dump(foo, out) +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local bit = require("bit") +local sub, gsub, format = string.sub, string.gsub, string.format +local byte, band, shr = string.byte, bit.band, bit.rshift +local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck +local funcuvname = jutil.funcuvname +local bcnames = vmdef.bcnames +local stdout, stderr = io.stdout, io.stderr + +------------------------------------------------------------------------------ + +local function ctlsub(c) + if c == "\n" then return "\\n" + elseif c == "\r" then return "\\r" + elseif c == "\t" then return "\\t" + else return format("\\%03d", byte(c)) + end +end + +-- Return one bytecode line. +local function bcline(func, pc, prefix) + local ins, m = funcbc(func, pc) + if not ins then return end + local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128) + local a = band(shr(ins, 8), 0xff) + local oidx = 6*band(ins, 0xff) + local op = sub(bcnames, oidx+1, oidx+6) + local s = format("%04d %s %-6s %3s ", + pc, prefix or " ", op, ma == 0 and "" or a) + local d = shr(ins, 16) + if mc == 13*128 then -- BCMjump + return format("%s=> %04d\n", s, pc+d-0x7fff) + end + if mb ~= 0 then + d = band(d, 0xff) + elseif mc == 0 then + return s.."\n" + end + local kc + if mc == 10*128 then -- BCMstr + kc = funck(func, -d-1) + kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub)) + elseif mc == 9*128 then -- BCMnum + kc = funck(func, d) + if op == "TSETM " then kc = kc - 2^52 end + elseif mc == 12*128 then -- BCMfunc + local fi = funcinfo(funck(func, -d-1)) + if fi.ffid then + kc = vmdef.ffnames[fi.ffid] + else + kc = fi.loc + end + elseif mc == 5*128 then -- BCMuv + kc = funcuvname(func, d) + end + if ma == 5 then -- BCMuv + local ka = funcuvname(func, a) + if kc then kc = ka.." ; "..kc else kc = ka end + end + if mb ~= 0 then + local b = shr(ins, 24) + if kc then return format("%s%3d %3d ; %s\n", s, b, d, kc) end + return format("%s%3d %3d\n", s, b, d) + end + if kc then return format("%s%3d ; %s\n", s, d, kc) end + if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits + return format("%s%3d\n", s, d) +end + +-- Collect branch targets of a function. +local function bctargets(func) + local target = {} + for pc=1,1000000000 do + local ins, m = funcbc(func, pc) + if not ins then break end + if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end + end + return target +end + +-- Dump bytecode instructions of a function. +local function bcdump(func, out, all) + if not out then out = stdout end + local fi = funcinfo(func) + if all and fi.children then + for n=-1,-1000000000,-1 do + local k = funck(func, n) + if not k then break end + if type(k) == "proto" then bcdump(k, out, true) end + end + end + out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined)) + local target = bctargets(func) + for pc=1,1000000000 do + local s = bcline(func, pc, target[pc] and "=>") + if not s then break end + out:write(s) + end + out:write("\n") + out:flush() +end + +------------------------------------------------------------------------------ + +-- Active flag and output file handle. +local active, out + +-- List handler. +local function h_list(func) + return bcdump(func, out) +end + +-- Detach list handler. +local function bclistoff() + if active then + active = false + jit.attach(h_list) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach list handler. +local function bcliston(outfile) + if active then bclistoff() end + if not outfile then outfile = os.getenv("LUAJIT_LISTFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stderr + end + jit.attach(h_list, "bc") + active = true +end + +-- Public module functions. +return { + line = bcline, + dump = bcdump, + targets = bctargets, + on = bcliston, + off = bclistoff, + start = bcliston -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/bcsave.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/bcsave.lua new file mode 100644 index 00000000..ab13667a --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/bcsave.lua @@ -0,0 +1,665 @@ +---------------------------------------------------------------------------- +-- LuaJIT module to save/list bytecode. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module saves or lists the bytecode for an input file. +-- It's run by the -b command line option. +-- +------------------------------------------------------------------------------ + +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local bit = require("bit") + +-- Symbol name prefix for LuaJIT bytecode. +local LJBC_PREFIX = "luaJIT_BC_" + +local type, assert = type, assert +local format = string.format +local tremove, tconcat = table.remove, table.concat + +------------------------------------------------------------------------------ + +local function usage() + io.stderr:write[[ +Save LuaJIT bytecode: luajit -b[options] input output + -l Only list bytecode. + -s Strip debug info (default). + -g Keep debug info. + -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). + -e chunk Use chunk string as input. + -- Stop handling options. + - Use stdin as input and/or stdout as output. + +File types: c h obj o raw (default) +]] + os.exit(1) +end + +local function check(ok, ...) + if ok then return ok, ... end + io.stderr:write("luajit: ", ...) + io.stderr:write("\n") + os.exit(1) +end + +local function readfile(input) + if type(input) == "function" then return input end + if input == "-" then input = nil end + return check(loadfile(input)) +end + +local function savefile(name, mode) + if name == "-" then return io.stdout end + return check(io.open(name, mode)) +end + +------------------------------------------------------------------------------ + +local map_type = { + raw = "raw", c = "c", h = "h", o = "obj", obj = "obj", +} + +local map_arch = { + x86 = { e = "le", b = 32, m = 3, p = 0x14c, }, + x64 = { e = "le", b = 64, m = 62, p = 0x8664, }, + arm = { e = "le", b = 32, m = 40, p = 0x1c0, }, + arm64 = { e = "le", b = 64, m = 183, p = 0xaa64, }, + arm64be = { e = "be", b = 64, m = 183, }, + ppc = { e = "be", b = 32, m = 20, }, + mips = { e = "be", b = 32, m = 8, f = 0x50001006, }, + mipsel = { e = "le", b = 32, m = 8, f = 0x50001006, }, + mips64 = { e = "be", b = 64, m = 8, f = 0x80000007, }, + mips64el = { e = "le", b = 64, m = 8, f = 0x80000007, }, + mips64r6 = { e = "be", b = 64, m = 8, f = 0xa0000407, }, + mips64r6el = { e = "le", b = 64, m = 8, f = 0xa0000407, }, +} + +local map_os = { + linux = true, windows = true, osx = true, freebsd = true, netbsd = true, + openbsd = true, dragonfly = true, solaris = true, +} + +local function checkarg(str, map, err) + str = str:lower() + local s = check(map[str], "unknown ", err) + return type(s) == "string" and s or str +end + +local function detecttype(str) + local ext = str:lower():match("%.(%a+)$") + return map_type[ext] or "raw" +end + +local function checkmodname(str) + check(str:match("^[%w_.%-]+$"), "bad module name") + return str:gsub("[%.%-]", "_") +end + +local function detectmodname(str) + if type(str) == "string" then + local tail = str:match("[^/\\]+$") + if tail then str = tail end + local head = str:match("^(.*)%.[^.]*$") + if head then str = head end + str = str:match("^[%w_.%-]+") + else + str = nil + end + check(str, "cannot derive module name, use -n name") + return str:gsub("[%.%-]", "_") +end + +------------------------------------------------------------------------------ + +local function bcsave_tail(fp, output, s) + local ok, err = fp:write(s) + if ok and output ~= "-" then ok, err = fp:close() end + check(ok, "cannot write ", output, ": ", err) +end + +local function bcsave_raw(output, s) + local fp = savefile(output, "wb") + bcsave_tail(fp, output, s) +end + +local function bcsave_c(ctx, output, s) + local fp = savefile(output, "w") + if ctx.type == "c" then + fp:write(format([[ +#ifdef __cplusplus +extern "C" +#endif +#ifdef _WIN32 +__declspec(dllexport) +#endif +const unsigned char %s%s[] = { +]], LJBC_PREFIX, ctx.modname)) + else + fp:write(format([[ +#define %s%s_SIZE %d +static const unsigned char %s%s[] = { +]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname)) + end + local t, n, m = {}, 0, 0 + for i=1,#s do + local b = tostring(string.byte(s, i)) + m = m + #b + 1 + if m > 78 then + fp:write(tconcat(t, ",", 1, n), ",\n") + n, m = 0, #b + 1 + end + n = n + 1 + t[n] = b + end + bcsave_tail(fp, output, tconcat(t, ",", 1, n).."\n};\n") +end + +local function bcsave_elfobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct { + uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; + uint16_t type, machine; + uint32_t version; + uint32_t entry, phofs, shofs; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; +} ELF32header; +typedef struct { + uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; + uint16_t type, machine; + uint32_t version; + uint64_t entry, phofs, shofs; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; +} ELF64header; +typedef struct { + uint32_t name, type, flags, addr, ofs, size, link, info, align, entsize; +} ELF32sectheader; +typedef struct { + uint32_t name, type; + uint64_t flags, addr, ofs, size; + uint32_t link, info; + uint64_t align, entsize; +} ELF64sectheader; +typedef struct { + uint32_t name, value, size; + uint8_t info, other; + uint16_t sectidx; +} ELF32symbol; +typedef struct { + uint32_t name; + uint8_t info, other; + uint16_t sectidx; + uint64_t value, size; +} ELF64symbol; +typedef struct { + ELF32header hdr; + ELF32sectheader sect[6]; + ELF32symbol sym[2]; + uint8_t space[4096]; +} ELF32obj; +typedef struct { + ELF64header hdr; + ELF64sectheader sect[6]; + ELF64symbol sym[2]; + uint8_t space[4096]; +} ELF64obj; +]] + local symname = LJBC_PREFIX..ctx.modname + local ai = assert(map_arch[ctx.arch]) + local is64, isbe = ai.b == 64, ai.e == "be" + + -- Handle different host/target endianess. + local function f32(x) return x end + local f16, fofs = f32, f32 + if ffi.abi("be") ~= isbe then + f32 = bit.bswap + function f16(x) return bit.rshift(bit.bswap(x), 16) end + if is64 then + local two32 = ffi.cast("int64_t", 2^32) + function fofs(x) return bit.bswap(x)*two32 end + else + fofs = f32 + end + end + + -- Create ELF object and fill in header. + local o = ffi.new(is64 and "ELF64obj" or "ELF32obj") + local hdr = o.hdr + if ctx.os == "bsd" or ctx.os == "other" then -- Determine native hdr.eosabi. + local bf = assert(io.open("/bin/ls", "rb")) + local bs = bf:read(9) + bf:close() + ffi.copy(o, bs, 9) + check(hdr.emagic[0] == 127, "no support for writing native object files") + else + hdr.emagic = "\127ELF" + hdr.eosabi = ({ freebsd=9, netbsd=2, openbsd=12, solaris=6 })[ctx.os] or 0 + end + hdr.eclass = is64 and 2 or 1 + hdr.eendian = isbe and 2 or 1 + hdr.eversion = 1 + hdr.type = f16(1) + hdr.machine = f16(ai.m) + hdr.flags = f32(ai.f or 0) + hdr.version = f32(1) + hdr.shofs = fofs(ffi.offsetof(o, "sect")) + hdr.ehsize = f16(ffi.sizeof(hdr)) + hdr.shentsize = f16(ffi.sizeof(o.sect[0])) + hdr.shnum = f16(6) + hdr.shstridx = f16(2) + + -- Fill in sections and symbols. + local sofs, ofs = ffi.offsetof(o, "space"), 1 + for i,name in ipairs{ + ".symtab", ".shstrtab", ".strtab", ".rodata", ".note.GNU-stack", + } do + local sect = o.sect[i] + sect.align = fofs(1) + sect.name = f32(ofs) + ffi.copy(o.space+ofs, name) + ofs = ofs + #name+1 + end + o.sect[1].type = f32(2) -- .symtab + o.sect[1].link = f32(3) + o.sect[1].info = f32(1) + o.sect[1].align = fofs(8) + o.sect[1].ofs = fofs(ffi.offsetof(o, "sym")) + o.sect[1].entsize = fofs(ffi.sizeof(o.sym[0])) + o.sect[1].size = fofs(ffi.sizeof(o.sym)) + o.sym[1].name = f32(1) + o.sym[1].sectidx = f16(4) + o.sym[1].size = fofs(#s) + o.sym[1].info = 17 + o.sect[2].type = f32(3) -- .shstrtab + o.sect[2].ofs = fofs(sofs) + o.sect[2].size = fofs(ofs) + o.sect[3].type = f32(3) -- .strtab + o.sect[3].ofs = fofs(sofs + ofs) + o.sect[3].size = fofs(#symname+2) + ffi.copy(o.space+ofs+1, symname) + ofs = ofs + #symname + 2 + o.sect[4].type = f32(1) -- .rodata + o.sect[4].flags = fofs(2) + o.sect[4].ofs = fofs(sofs + ofs) + o.sect[4].size = fofs(#s) + o.sect[5].type = f32(1) -- .note.GNU-stack + o.sect[5].ofs = fofs(sofs + ofs + #s) + + -- Write ELF object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) + bcsave_tail(fp, output, s) +end + +local function bcsave_peobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct { + uint16_t arch, nsects; + uint32_t time, symtabofs, nsyms; + uint16_t opthdrsz, flags; +} PEheader; +typedef struct { + char name[8]; + uint32_t vsize, vaddr, size, ofs, relocofs, lineofs; + uint16_t nreloc, nline; + uint32_t flags; +} PEsection; +typedef struct __attribute((packed)) { + union { + char name[8]; + uint32_t nameref[2]; + }; + uint32_t value; + int16_t sect; + uint16_t type; + uint8_t scl, naux; +} PEsym; +typedef struct __attribute((packed)) { + uint32_t size; + uint16_t nreloc, nline; + uint32_t cksum; + uint16_t assoc; + uint8_t comdatsel, unused[3]; +} PEsymaux; +typedef struct { + PEheader hdr; + PEsection sect[2]; + // Must be an even number of symbol structs. + PEsym sym0; + PEsymaux sym0aux; + PEsym sym1; + PEsymaux sym1aux; + PEsym sym2; + PEsym sym3; + uint32_t strtabsize; + uint8_t space[4096]; +} PEobj; +]] + local symname = LJBC_PREFIX..ctx.modname + local ai = assert(map_arch[ctx.arch]) + local is64 = ai.b == 64 + local symexport = " /EXPORT:"..symname..",DATA " + + -- The file format is always little-endian. Swap if the host is big-endian. + local function f32(x) return x end + local f16 = f32 + if ffi.abi("be") then + f32 = bit.bswap + function f16(x) return bit.rshift(bit.bswap(x), 16) end + end + + -- Create PE object and fill in header. + local o = ffi.new("PEobj") + local hdr = o.hdr + hdr.arch = f16(assert(ai.p)) + hdr.nsects = f16(2) + hdr.symtabofs = f32(ffi.offsetof(o, "sym0")) + hdr.nsyms = f32(6) + + -- Fill in sections and symbols. + o.sect[0].name = ".drectve" + o.sect[0].size = f32(#symexport) + o.sect[0].flags = f32(0x00100a00) + o.sym0.sect = f16(1) + o.sym0.scl = 3 + o.sym0.name = ".drectve" + o.sym0.naux = 1 + o.sym0aux.size = f32(#symexport) + o.sect[1].name = ".rdata" + o.sect[1].size = f32(#s) + o.sect[1].flags = f32(0x40300040) + o.sym1.sect = f16(2) + o.sym1.scl = 3 + o.sym1.name = ".rdata" + o.sym1.naux = 1 + o.sym1aux.size = f32(#s) + o.sym2.sect = f16(2) + o.sym2.scl = 2 + o.sym2.nameref[1] = f32(4) + o.sym3.sect = f16(-1) + o.sym3.scl = 2 + o.sym3.value = f32(1) + o.sym3.name = "@feat.00" -- Mark as SafeSEH compliant. + ffi.copy(o.space, symname) + local ofs = #symname + 1 + o.strtabsize = f32(ofs + 4) + o.sect[0].ofs = f32(ffi.offsetof(o, "space") + ofs) + ffi.copy(o.space + ofs, symexport) + ofs = ofs + #symexport + o.sect[1].ofs = f32(ffi.offsetof(o, "space") + ofs) + + -- Write PE object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) + bcsave_tail(fp, output, s) +end + +local function bcsave_machobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct +{ + uint32_t magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags; +} mach_header; +typedef struct +{ + mach_header; uint32_t reserved; +} mach_header_64; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint32_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint64_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command_64; +typedef struct { + char sectname[16], segname[16]; + uint32_t addr, size; + uint32_t offset, align, reloff, nreloc, flags; + uint32_t reserved1, reserved2; +} mach_section; +typedef struct { + char sectname[16], segname[16]; + uint64_t addr, size; + uint32_t offset, align, reloff, nreloc, flags; + uint32_t reserved1, reserved2, reserved3; +} mach_section_64; +typedef struct { + uint32_t cmd, cmdsize, symoff, nsyms, stroff, strsize; +} mach_symtab_command; +typedef struct { + int32_t strx; + uint8_t type, sect; + int16_t desc; + uint32_t value; +} mach_nlist; +typedef struct { + uint32_t strx; + uint8_t type, sect; + uint16_t desc; + uint64_t value; +} mach_nlist_64; +typedef struct +{ + uint32_t magic, nfat_arch; +} mach_fat_header; +typedef struct +{ + uint32_t cputype, cpusubtype, offset, size, align; +} mach_fat_arch; +typedef struct { + struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + } arch[1]; + mach_nlist sym_entry; + uint8_t space[4096]; +} mach_obj; +typedef struct { + struct { + mach_header_64 hdr; + mach_segment_command_64 seg; + mach_section_64 sec; + mach_symtab_command sym; + } arch[1]; + mach_nlist_64 sym_entry; + uint8_t space[4096]; +} mach_obj_64; +typedef struct { + mach_fat_header fat; + mach_fat_arch fat_arch[2]; + struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + } arch[2]; + mach_nlist sym_entry; + uint8_t space[4096]; +} mach_fat_obj; +]] + local symname = '_'..LJBC_PREFIX..ctx.modname + local isfat, is64, align, mobj = false, false, 4, "mach_obj" + if ctx.arch == "x64" then + is64, align, mobj = true, 8, "mach_obj_64" + elseif ctx.arch == "arm" then + isfat, mobj = true, "mach_fat_obj" + elseif ctx.arch == "arm64" then + is64, align, isfat, mobj = true, 8, true, "mach_fat_obj" + else + check(ctx.arch == "x86", "unsupported architecture for OSX") + end + local function aligned(v, a) return bit.band(v+a-1, -a) end + local be32 = bit.bswap -- Mach-O FAT is BE, supported archs are LE. + + -- Create Mach-O object and fill in header. + local o = ffi.new(mobj) + local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align) + local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12}, arm64={0x01000007,0x0100000c} })[ctx.arch] + local cpusubtype = ({ x86={3}, x64={3}, arm={3,9}, arm64={3,0} })[ctx.arch] + if isfat then + o.fat.magic = be32(0xcafebabe) + o.fat.nfat_arch = be32(#cpusubtype) + end + + -- Fill in sections and symbols. + for i=0,#cpusubtype-1 do + local ofs = 0 + if isfat then + local a = o.fat_arch[i] + a.cputype = be32(cputype[i+1]) + a.cpusubtype = be32(cpusubtype[i+1]) + -- Subsequent slices overlap each other to share data. + ofs = ffi.offsetof(o, "arch") + i*ffi.sizeof(o.arch[0]) + a.offset = be32(ofs) + a.size = be32(mach_size-ofs+#s) + end + local a = o.arch[i] + a.hdr.magic = is64 and 0xfeedfacf or 0xfeedface + a.hdr.cputype = cputype[i+1] + a.hdr.cpusubtype = cpusubtype[i+1] + a.hdr.filetype = 1 + a.hdr.ncmds = 2 + a.hdr.sizeofcmds = ffi.sizeof(a.seg)+ffi.sizeof(a.sec)+ffi.sizeof(a.sym) + a.seg.cmd = is64 and 0x19 or 0x1 + a.seg.cmdsize = ffi.sizeof(a.seg)+ffi.sizeof(a.sec) + a.seg.vmsize = #s + a.seg.fileoff = mach_size-ofs + a.seg.filesize = #s + a.seg.maxprot = 1 + a.seg.initprot = 1 + a.seg.nsects = 1 + ffi.copy(a.sec.sectname, "__data") + ffi.copy(a.sec.segname, "__DATA") + a.sec.size = #s + a.sec.offset = mach_size-ofs + a.sym.cmd = 2 + a.sym.cmdsize = ffi.sizeof(a.sym) + a.sym.symoff = ffi.offsetof(o, "sym_entry")-ofs + a.sym.nsyms = 1 + a.sym.stroff = ffi.offsetof(o, "sym_entry")+ffi.sizeof(o.sym_entry)-ofs + a.sym.strsize = aligned(#symname+2, align) + end + o.sym_entry.type = 0xf + o.sym_entry.sect = 1 + o.sym_entry.strx = 1 + ffi.copy(o.space+1, symname) + + -- Write Macho-O object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, mach_size)) + bcsave_tail(fp, output, s) +end + +local function bcsave_obj(ctx, output, s) + local ok, ffi = pcall(require, "ffi") + check(ok, "FFI library required to write this file type") + if ctx.os == "windows" then + return bcsave_peobj(ctx, output, s, ffi) + elseif ctx.os == "osx" then + return bcsave_machobj(ctx, output, s, ffi) + else + return bcsave_elfobj(ctx, output, s, ffi) + end +end + +------------------------------------------------------------------------------ + +local function bclist(input, output) + local f = readfile(input) + require("jit.bc").dump(f, savefile(output, "w"), true) +end + +local function bcsave(ctx, input, output) + local f = readfile(input) + local s = string.dump(f, ctx.strip) + local t = ctx.type + if not t then + t = detecttype(output) + ctx.type = t + end + if t == "raw" then + bcsave_raw(output, s) + else + if not ctx.modname then ctx.modname = detectmodname(input) end + if t == "obj" then + bcsave_obj(ctx, output, s) + else + bcsave_c(ctx, output, s) + end + end +end + +local function docmd(...) + local arg = {...} + local n = 1 + local list = false + local ctx = { + strip = true, arch = jit.arch, os = jit.os:lower(), + type = false, modname = false, + } + while n <= #arg do + local a = arg[n] + if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then + tremove(arg, n) + if a == "--" then break end + for m=2,#a do + local opt = a:sub(m, m) + if opt == "l" then + list = true + elseif opt == "s" then + ctx.strip = true + elseif opt == "g" then + ctx.strip = false + else + if arg[n] == nil or m ~= #a then usage() end + if opt == "e" then + if n ~= 1 then usage() end + arg[1] = check(loadstring(arg[1])) + elseif opt == "n" then + ctx.modname = checkmodname(tremove(arg, n)) + elseif opt == "t" then + ctx.type = checkarg(tremove(arg, n), map_type, "file type") + elseif opt == "a" then + ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture") + elseif opt == "o" then + ctx.os = checkarg(tremove(arg, n), map_os, "OS name") + else + usage() + end + end + end + else + n = n + 1 + end + end + if list then + if #arg == 0 or #arg > 2 then usage() end + bclist(arg[1], arg[2] or "-") + else + if #arg ~= 2 then usage() end + bcsave(ctx, arg[1], arg[2]) + end +end + +------------------------------------------------------------------------------ + +-- Public module functions. +return { + start = docmd -- Process -b command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm.lua new file mode 100644 index 00000000..ba79c47e --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm.lua @@ -0,0 +1,689 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles most user-mode ARMv7 instructions +-- NYI: Advanced SIMD and VFP instructions. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch = string.match, string.gmatch +local concat = table.concat +local bit = require("bit") +local band, bor, ror, tohex = bit.band, bit.bor, bit.ror, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Opcode maps +------------------------------------------------------------------------------ + +local map_loadc = { + shift = 8, mask = 15, + [10] = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "vmovFmDN", "vstmFNdr", + _ = { + shift = 21, mask = 1, + [0] = "vstrFdl", + { shift = 16, mask = 15, [13] = "vpushFdr", _ = "vstmdbFNdr", } + }, + }, + { + shift = 23, mask = 3, + [0] = "vmovFDNm", + { shift = 16, mask = 15, [13] = "vpopFdr", _ = "vldmFNdr", }, + _ = { + shift = 21, mask = 1, + [0] = "vldrFdl", "vldmdbFNdr", + }, + }, + }, + [11] = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "vmovGmDN", "vstmGNdr", + _ = { + shift = 21, mask = 1, + [0] = "vstrGdl", + { shift = 16, mask = 15, [13] = "vpushGdr", _ = "vstmdbGNdr", } + }, + }, + { + shift = 23, mask = 3, + [0] = "vmovGDNm", + { shift = 16, mask = 15, [13] = "vpopGdr", _ = "vldmGNdr", }, + _ = { + shift = 21, mask = 1, + [0] = "vldrGdl", "vldmdbGNdr", + }, + }, + }, + _ = { + shift = 0, mask = 0 -- NYI ldc, mcrr, mrrc. + }, +} + +local map_vfps = { + shift = 6, mask = 0x2c001, + [0] = "vmlaF.dnm", "vmlsF.dnm", + [0x04000] = "vnmlsF.dnm", [0x04001] = "vnmlaF.dnm", + [0x08000] = "vmulF.dnm", [0x08001] = "vnmulF.dnm", + [0x0c000] = "vaddF.dnm", [0x0c001] = "vsubF.dnm", + [0x20000] = "vdivF.dnm", + [0x24000] = "vfnmsF.dnm", [0x24001] = "vfnmaF.dnm", + [0x28000] = "vfmaF.dnm", [0x28001] = "vfmsF.dnm", + [0x2c000] = "vmovF.dY", + [0x2c001] = { + shift = 7, mask = 0x1e01, + [0] = "vmovF.dm", "vabsF.dm", + [0x0200] = "vnegF.dm", [0x0201] = "vsqrtF.dm", + [0x0800] = "vcmpF.dm", [0x0801] = "vcmpeF.dm", + [0x0a00] = "vcmpzF.d", [0x0a01] = "vcmpzeF.d", + [0x0e01] = "vcvtG.dF.m", + [0x1000] = "vcvt.f32.u32Fdm", [0x1001] = "vcvt.f32.s32Fdm", + [0x1800] = "vcvtr.u32F.dm", [0x1801] = "vcvt.u32F.dm", + [0x1a00] = "vcvtr.s32F.dm", [0x1a01] = "vcvt.s32F.dm", + }, +} + +local map_vfpd = { + shift = 6, mask = 0x2c001, + [0] = "vmlaG.dnm", "vmlsG.dnm", + [0x04000] = "vnmlsG.dnm", [0x04001] = "vnmlaG.dnm", + [0x08000] = "vmulG.dnm", [0x08001] = "vnmulG.dnm", + [0x0c000] = "vaddG.dnm", [0x0c001] = "vsubG.dnm", + [0x20000] = "vdivG.dnm", + [0x24000] = "vfnmsG.dnm", [0x24001] = "vfnmaG.dnm", + [0x28000] = "vfmaG.dnm", [0x28001] = "vfmsG.dnm", + [0x2c000] = "vmovG.dY", + [0x2c001] = { + shift = 7, mask = 0x1e01, + [0] = "vmovG.dm", "vabsG.dm", + [0x0200] = "vnegG.dm", [0x0201] = "vsqrtG.dm", + [0x0800] = "vcmpG.dm", [0x0801] = "vcmpeG.dm", + [0x0a00] = "vcmpzG.d", [0x0a01] = "vcmpzeG.d", + [0x0e01] = "vcvtF.dG.m", + [0x1000] = "vcvt.f64.u32GdFm", [0x1001] = "vcvt.f64.s32GdFm", + [0x1800] = "vcvtr.u32FdG.m", [0x1801] = "vcvt.u32FdG.m", + [0x1a00] = "vcvtr.s32FdG.m", [0x1a01] = "vcvt.s32FdG.m", + }, +} + +local map_datac = { + shift = 24, mask = 1, + [0] = { + shift = 4, mask = 1, + [0] = { + shift = 8, mask = 15, + [10] = map_vfps, + [11] = map_vfpd, + -- NYI cdp, mcr, mrc. + }, + { + shift = 8, mask = 15, + [10] = { + shift = 20, mask = 15, + [0] = "vmovFnD", "vmovFDn", + [14] = "vmsrD", + [15] = { shift = 12, mask = 15, [15] = "vmrs", _ = "vmrsD", }, + }, + }, + }, + "svcT", +} + +local map_loadcu = { + shift = 0, mask = 0, -- NYI unconditional CP load/store. +} + +local map_datacu = { + shift = 0, mask = 0, -- NYI unconditional CP data. +} + +local map_simddata = { + shift = 0, mask = 0, -- NYI SIMD data. +} + +local map_simdload = { + shift = 0, mask = 0, -- NYI SIMD load/store, preload. +} + +local map_preload = { + shift = 0, mask = 0, -- NYI preload. +} + +local map_media = { + shift = 20, mask = 31, + [0] = false, + { --01 + shift = 5, mask = 7, + [0] = "sadd16DNM", "sasxDNM", "ssaxDNM", "ssub16DNM", + "sadd8DNM", false, false, "ssub8DNM", + }, + { --02 + shift = 5, mask = 7, + [0] = "qadd16DNM", "qasxDNM", "qsaxDNM", "qsub16DNM", + "qadd8DNM", false, false, "qsub8DNM", + }, + { --03 + shift = 5, mask = 7, + [0] = "shadd16DNM", "shasxDNM", "shsaxDNM", "shsub16DNM", + "shadd8DNM", false, false, "shsub8DNM", + }, + false, + { --05 + shift = 5, mask = 7, + [0] = "uadd16DNM", "uasxDNM", "usaxDNM", "usub16DNM", + "uadd8DNM", false, false, "usub8DNM", + }, + { --06 + shift = 5, mask = 7, + [0] = "uqadd16DNM", "uqasxDNM", "uqsaxDNM", "uqsub16DNM", + "uqadd8DNM", false, false, "uqsub8DNM", + }, + { --07 + shift = 5, mask = 7, + [0] = "uhadd16DNM", "uhasxDNM", "uhsaxDNM", "uhsub16DNM", + "uhadd8DNM", false, false, "uhsub8DNM", + }, + { --08 + shift = 5, mask = 7, + [0] = "pkhbtDNMU", false, "pkhtbDNMU", + { shift = 16, mask = 15, [15] = "sxtb16DMU", _ = "sxtab16DNMU", }, + "pkhbtDNMU", "selDNM", "pkhtbDNMU", + }, + false, + { --0a + shift = 5, mask = 7, + [0] = "ssatDxMu", "ssat16DxM", "ssatDxMu", + { shift = 16, mask = 15, [15] = "sxtbDMU", _ = "sxtabDNMU", }, + "ssatDxMu", false, "ssatDxMu", + }, + { --0b + shift = 5, mask = 7, + [0] = "ssatDxMu", "revDM", "ssatDxMu", + { shift = 16, mask = 15, [15] = "sxthDMU", _ = "sxtahDNMU", }, + "ssatDxMu", "rev16DM", "ssatDxMu", + }, + { --0c + shift = 5, mask = 7, + [3] = { shift = 16, mask = 15, [15] = "uxtb16DMU", _ = "uxtab16DNMU", }, + }, + false, + { --0e + shift = 5, mask = 7, + [0] = "usatDwMu", "usat16DwM", "usatDwMu", + { shift = 16, mask = 15, [15] = "uxtbDMU", _ = "uxtabDNMU", }, + "usatDwMu", false, "usatDwMu", + }, + { --0f + shift = 5, mask = 7, + [0] = "usatDwMu", "rbitDM", "usatDwMu", + { shift = 16, mask = 15, [15] = "uxthDMU", _ = "uxtahDNMU", }, + "usatDwMu", "revshDM", "usatDwMu", + }, + { --10 + shift = 12, mask = 15, + [15] = { + shift = 5, mask = 7, + "smuadNMS", "smuadxNMS", "smusdNMS", "smusdxNMS", + }, + _ = { + shift = 5, mask = 7, + [0] = "smladNMSD", "smladxNMSD", "smlsdNMSD", "smlsdxNMSD", + }, + }, + false, false, false, + { --14 + shift = 5, mask = 7, + [0] = "smlaldDNMS", "smlaldxDNMS", "smlsldDNMS", "smlsldxDNMS", + }, + { --15 + shift = 5, mask = 7, + [0] = { shift = 12, mask = 15, [15] = "smmulNMS", _ = "smmlaNMSD", }, + { shift = 12, mask = 15, [15] = "smmulrNMS", _ = "smmlarNMSD", }, + false, false, false, false, + "smmlsNMSD", "smmlsrNMSD", + }, + false, false, + { --18 + shift = 5, mask = 7, + [0] = { shift = 12, mask = 15, [15] = "usad8NMS", _ = "usada8NMSD", }, + }, + false, + { --1a + shift = 5, mask = 3, [2] = "sbfxDMvw", + }, + { --1b + shift = 5, mask = 3, [2] = "sbfxDMvw", + }, + { --1c + shift = 5, mask = 3, + [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", }, + }, + { --1d + shift = 5, mask = 3, + [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", }, + }, + { --1e + shift = 5, mask = 3, [2] = "ubfxDMvw", + }, + { --1f + shift = 5, mask = 3, [2] = "ubfxDMvw", + }, +} + +local map_load = { + shift = 21, mask = 9, + { + shift = 20, mask = 5, + [0] = "strtDL", "ldrtDL", [4] = "strbtDL", [5] = "ldrbtDL", + }, + _ = { + shift = 20, mask = 5, + [0] = "strDL", "ldrDL", [4] = "strbDL", [5] = "ldrbDL", + } +} + +local map_load1 = { + shift = 4, mask = 1, + [0] = map_load, map_media, +} + +local map_loadm = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "stmdaNR", "stmNR", + { shift = 16, mask = 63, [45] = "pushR", _ = "stmdbNR", }, "stmibNR", + }, + { + shift = 23, mask = 3, + [0] = "ldmdaNR", { shift = 16, mask = 63, [61] = "popR", _ = "ldmNR", }, + "ldmdbNR", "ldmibNR", + }, +} + +local map_data = { + shift = 21, mask = 15, + [0] = "andDNPs", "eorDNPs", "subDNPs", "rsbDNPs", + "addDNPs", "adcDNPs", "sbcDNPs", "rscDNPs", + "tstNP", "teqNP", "cmpNP", "cmnNP", + "orrDNPs", "movDPs", "bicDNPs", "mvnDPs", +} + +local map_mul = { + shift = 21, mask = 7, + [0] = "mulNMSs", "mlaNMSDs", "umaalDNMS", "mlsDNMS", + "umullDNMSs", "umlalDNMSs", "smullDNMSs", "smlalDNMSs", +} + +local map_sync = { + shift = 20, mask = 15, -- NYI: brackets around N. R(D+1) for ldrexd/strexd. + [0] = "swpDMN", false, false, false, + "swpbDMN", false, false, false, + "strexDMN", "ldrexDN", "strexdDN", "ldrexdDN", + "strexbDMN", "ldrexbDN", "strexhDN", "ldrexhDN", +} + +local map_mulh = { + shift = 21, mask = 3, + [0] = { shift = 5, mask = 3, + [0] = "smlabbNMSD", "smlatbNMSD", "smlabtNMSD", "smlattNMSD", }, + { shift = 5, mask = 3, + [0] = "smlawbNMSD", "smulwbNMS", "smlawtNMSD", "smulwtNMS", }, + { shift = 5, mask = 3, + [0] = "smlalbbDNMS", "smlaltbDNMS", "smlalbtDNMS", "smlalttDNMS", }, + { shift = 5, mask = 3, + [0] = "smulbbNMS", "smultbNMS", "smulbtNMS", "smulttNMS", }, +} + +local map_misc = { + shift = 4, mask = 7, + -- NYI: decode PSR bits of msr. + [0] = { shift = 21, mask = 1, [0] = "mrsD", "msrM", }, + { shift = 21, mask = 3, "bxM", false, "clzDM", }, + { shift = 21, mask = 3, "bxjM", }, + { shift = 21, mask = 3, "blxM", }, + false, + { shift = 21, mask = 3, [0] = "qaddDMN", "qsubDMN", "qdaddDMN", "qdsubDMN", }, + false, + { shift = 21, mask = 3, "bkptK", }, +} + +local map_datar = { + shift = 4, mask = 9, + [9] = { + shift = 5, mask = 3, + [0] = { shift = 24, mask = 1, [0] = map_mul, map_sync, }, + { shift = 20, mask = 1, [0] = "strhDL", "ldrhDL", }, + { shift = 20, mask = 1, [0] = "ldrdDL", "ldrsbDL", }, + { shift = 20, mask = 1, [0] = "strdDL", "ldrshDL", }, + }, + _ = { + shift = 20, mask = 25, + [16] = { shift = 7, mask = 1, [0] = map_misc, map_mulh, }, + _ = { + shift = 0, mask = 0xffffffff, + [bor(0xe1a00000)] = "nop", + _ = map_data, + } + }, +} + +local map_datai = { + shift = 20, mask = 31, -- NYI: decode PSR bits of msr. Decode imm12. + [16] = "movwDW", [20] = "movtDW", + [18] = { shift = 0, mask = 0xf00ff, [0] = "nopv6", _ = "msrNW", }, + [22] = "msrNW", + _ = map_data, +} + +local map_branch = { + shift = 24, mask = 1, + [0] = "bB", "blB" +} + +local map_condins = { + [0] = map_datar, map_datai, map_load, map_load1, + map_loadm, map_branch, map_loadc, map_datac +} + +-- NYI: setend. +local map_uncondins = { + [0] = false, map_simddata, map_simdload, map_preload, + false, "blxB", map_loadcu, map_datacu, +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", +} + +local map_cond = { + [0] = "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", +} + +local map_shift = { [0] = "lsl", "lsr", "asr", "ror", } + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then + extra = "\t->"..sym + elseif band(ctx.op, 0x0e000000) ~= 0x0a000000 then + extra = "\t; 0x"..tohex(ctx.rel) + end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-5s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-5s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +-- Format operand 2 of load/store opcodes. +local function fmtload(ctx, op, pos) + local base = map_gpr[band(rshift(op, 16), 15)] + local x, ofs + local ext = (band(op, 0x04000000) == 0) + if not ext and band(op, 0x02000000) == 0 then + ofs = band(op, 4095) + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + ofs = "#"..ofs + elseif ext and band(op, 0x00400000) ~= 0 then + ofs = band(op, 15) + band(rshift(op, 4), 0xf0) + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + ofs = "#"..ofs + else + ofs = map_gpr[band(op, 15)] + if ext or band(op, 0xfe0) == 0 then + elseif band(op, 0xfe0) == 0x60 then + ofs = format("%s, rrx", ofs) + else + local sh = band(rshift(op, 7), 31) + if sh == 0 then sh = 32 end + ofs = format("%s, %s #%d", ofs, map_shift[band(rshift(op, 5), 3)], sh) + end + if band(op, 0x00800000) == 0 then ofs = "-"..ofs end + end + if ofs == "#0" then + x = format("[%s]", base) + elseif band(op, 0x01000000) == 0 then + x = format("[%s], %s", base, ofs) + else + x = format("[%s, %s]", base, ofs) + end + if band(op, 0x01200000) == 0x01200000 then x = x.."!" end + return x +end + +-- Format operand 2 of vector load/store opcodes. +local function fmtvload(ctx, op, pos) + local base = map_gpr[band(rshift(op, 16), 15)] + local ofs = band(op, 255)*4 + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + if ofs == 0 then + return format("[%s]", base) + else + return format("[%s, #%d]", base, ofs) + end +end + +local function fmtvr(op, vr, sh0, sh1) + if vr == "s" then + return format("s%d", 2*band(rshift(op, sh0), 15)+band(rshift(op, sh1), 1)) + else + return format("d%d", band(rshift(op, sh0), 15)+band(rshift(op, sh1-4), 16)) + end +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) + local operands = {} + local suffix = "" + local last, name, pat + local vr + ctx.op = op + ctx.rel = nil + + local cond = rshift(op, 28) + local opat + if cond == 15 then + opat = map_uncondins[band(rshift(op, 25), 7)] + else + if cond ~= 14 then suffix = map_cond[cond] end + opat = map_condins[band(rshift(op, 25), 7)] + end + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + name, pat = match(opat, "^([a-z0-9]*)(.*)") + if sub(pat, 1, 1) == "." then + local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") + suffix = suffix..s2 + pat = p2 + end + + for p in gmatch(pat, ".") do + local x = nil + if p == "D" then + x = map_gpr[band(rshift(op, 12), 15)] + elseif p == "N" then + x = map_gpr[band(rshift(op, 16), 15)] + elseif p == "S" then + x = map_gpr[band(rshift(op, 8), 15)] + elseif p == "M" then + x = map_gpr[band(op, 15)] + elseif p == "d" then + x = fmtvr(op, vr, 12, 22) + elseif p == "n" then + x = fmtvr(op, vr, 16, 7) + elseif p == "m" then + x = fmtvr(op, vr, 0, 5) + elseif p == "P" then + if band(op, 0x02000000) ~= 0 then + x = ror(band(op, 255), 2*band(rshift(op, 8), 15)) + else + x = map_gpr[band(op, 15)] + if band(op, 0xff0) ~= 0 then + operands[#operands+1] = x + local s = map_shift[band(rshift(op, 5), 3)] + local r = nil + if band(op, 0xf90) == 0 then + if s == "ror" then s = "rrx" else r = "#32" end + elseif band(op, 0x10) == 0 then + r = "#"..band(rshift(op, 7), 31) + else + r = map_gpr[band(rshift(op, 8), 15)] + end + if name == "mov" then name = s; x = r + elseif r then x = format("%s %s", s, r) + else x = s end + end + end + elseif p == "L" then + x = fmtload(ctx, op, pos) + elseif p == "l" then + x = fmtvload(ctx, op, pos) + elseif p == "B" then + local addr = ctx.addr + pos + 8 + arshift(lshift(op, 8), 6) + if cond == 15 then addr = addr + band(rshift(op, 23), 2) end + ctx.rel = addr + x = "0x"..tohex(addr) + elseif p == "F" then + vr = "s" + elseif p == "G" then + vr = "d" + elseif p == "." then + suffix = suffix..(vr == "s" and ".f32" or ".f64") + elseif p == "R" then + if band(op, 0x00200000) ~= 0 and #operands == 1 then + operands[1] = operands[1].."!" + end + local t = {} + for i=0,15 do + if band(rshift(op, i), 1) == 1 then t[#t+1] = map_gpr[i] end + end + x = "{"..concat(t, ", ").."}" + elseif p == "r" then + if band(op, 0x00200000) ~= 0 and #operands == 2 then + operands[1] = operands[1].."!" + end + local s = tonumber(sub(last, 2)) + local n = band(op, 255) + if vr == "d" then n = rshift(n, 1) end + operands[#operands] = format("{%s-%s%d}", last, vr, s+n-1) + elseif p == "W" then + x = band(op, 0x0fff) + band(rshift(op, 4), 0xf000) + elseif p == "T" then + x = "#0x"..tohex(band(op, 0x00ffffff), 6) + elseif p == "U" then + x = band(rshift(op, 7), 31) + if x == 0 then x = nil end + elseif p == "u" then + x = band(rshift(op, 7), 31) + if band(op, 0x40) == 0 then + if x == 0 then x = nil else x = "lsl #"..x end + else + if x == 0 then x = "asr #32" else x = "asr #"..x end + end + elseif p == "v" then + x = band(rshift(op, 7), 31) + elseif p == "w" then + x = band(rshift(op, 16), 31) + elseif p == "x" then + x = band(rshift(op, 16), 31) + 1 + elseif p == "X" then + x = band(rshift(op, 16), 31) - last + 1 + elseif p == "Y" then + x = band(rshift(op, 12), 0xf0) + band(op, 0x0f) + elseif p == "K" then + x = "#0x"..tohex(band(rshift(op, 4), 0x0000fff0) + band(op, 15), 4) + elseif p == "s" then + if band(op, 0x00100000) ~= 0 then suffix = "s"..suffix end + else + assert(false) + end + if x then + last = x + if type(x) == "number" then x = "#"..x end + operands[#operands+1] = x + end + end + + return putop(ctx, name..suffix, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ctx.pos = ofs + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 16 then return map_gpr[r] end + return "d"..(r-16) +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm64.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm64.lua new file mode 100644 index 00000000..ad909fbd --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm64.lua @@ -0,0 +1,1216 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM64 disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +-- +-- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com. +-- Sponsored by Cisco Systems, Inc. +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles most user-mode AArch64 instructions. +-- NYI: Advanced SIMD and VFP instructions. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local concat = table.concat +local bit = require("bit") +local band, bor, bxor, tohex = bit.band, bit.bor, bit.bxor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift +local ror = bit.ror + +------------------------------------------------------------------------------ +-- Opcode maps +------------------------------------------------------------------------------ + +local map_adr = { -- PC-relative addressing. + shift = 31, mask = 1, + [0] = "adrDBx", "adrpDBx" +} + +local map_addsubi = { -- Add/subtract immediate. + shift = 29, mask = 3, + [0] = "add|movDNIg", "adds|cmnD0NIg", "subDNIg", "subs|cmpD0NIg", +} + +local map_logi = { -- Logical immediate. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "andDNig", "orr|movDN0ig", "eorDNig", "ands|tstD0Nig" + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = "andDNig", "orr|movDN0ig", "eorDNig", "ands|tstD0Nig" + } +} + +local map_movwi = { -- Move wide immediate. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "movnDWRg", false, "movz|movDYRg", "movkDWRg" + }, false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = "movnDWRg", false, "movz|movDYRg", "movkDWRg" + }, +} + +local map_bitf = { -- Bitfield. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "sbfm|sbfiz|sbfx|asr|sxtw|sxth|sxtbDN12w", + "bfm|bfi|bfxilDN13w", + "ubfm|ubfiz|ubfx|lsr|lsl|uxth|uxtbDN12w" + } + }, + { + shift = 22, mask = 1, + { + shift = 29, mask = 3, + [0] = "sbfm|sbfiz|sbfx|asr|sxtw|sxth|sxtbDN12x", + "bfm|bfi|bfxilDN13x", + "ubfm|ubfiz|ubfx|lsr|lsl|uxth|uxtbDN12x" + } + } +} + +local map_datai = { -- Data processing - immediate. + shift = 23, mask = 7, + [0] = map_adr, map_adr, map_addsubi, false, + map_logi, map_movwi, map_bitf, + { + shift = 15, mask = 0x1c0c1, + [0] = "extr|rorDNM4w", [0x10080] = "extr|rorDNM4x", + [0x10081] = "extr|rorDNM4x" + } +} + +local map_logsr = { -- Logical, shifted register. + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = { + shift = 21, mask = 7, + [0] = "andDNMSg", "bicDNMSg", "andDNMSg", "bicDNMSg", + "andDNMSg", "bicDNMSg", "andDNMg", "bicDNMg" + }, + { + shift = 21, mask = 7, + [0] ="orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0MSg", "orn|mvnDN0MSg", + "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0Mg", "orn|mvnDN0Mg" + }, + { + shift = 21, mask = 7, + [0] = "eorDNMSg", "eonDNMSg", "eorDNMSg", "eonDNMSg", + "eorDNMSg", "eonDNMSg", "eorDNMg", "eonDNMg" + }, + { + shift = 21, mask = 7, + [0] = "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMSg", "bicsDNMSg", + "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMg", "bicsDNMg" + } + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = { + shift = 21, mask = 7, + [0] = "andDNMSg", "bicDNMSg", "andDNMSg", "bicDNMSg", + "andDNMSg", "bicDNMSg", "andDNMg", "bicDNMg" + }, + { + shift = 21, mask = 7, + [0] = "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0MSg", "orn|mvnDN0MSg", + "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0Mg", "orn|mvnDN0Mg" + }, + { + shift = 21, mask = 7, + [0] = "eorDNMSg", "eonDNMSg", "eorDNMSg", "eonDNMSg", + "eorDNMSg", "eonDNMSg", "eorDNMg", "eonDNMg" + }, + { + shift = 21, mask = 7, + [0] = "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMSg", "bicsDNMSg", + "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMg", "bicsDNMg" + } + } +} + +local map_assh = { + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "addDNMSg", "addDNMSg", "addDNMSg", "addDNMg" + }, + { + shift = 22, mask = 3, + [0] = "adds|cmnD0NMSg", "adds|cmnD0NMSg", + "adds|cmnD0NMSg", "adds|cmnD0NMg" + }, + { + shift = 22, mask = 3, + [0] = "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0Mg" + }, + { + shift = 22, mask = 3, + [0] = "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0MzSg", + "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0Mzg" + }, + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "addDNMSg", "addDNMSg", "addDNMSg", "addDNMg" + }, + { + shift = 22, mask = 3, + [0] = "adds|cmnD0NMSg", "adds|cmnD0NMSg", "adds|cmnD0NMSg", + "adds|cmnD0NMg" + }, + { + shift = 22, mask = 3, + [0] = "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0Mg" + }, + { + shift = 22, mask = 3, + [0] = "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0MzSg", + "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0Mzg" + } + } +} + +local map_addsubsh = { -- Add/subtract, shifted register. + shift = 22, mask = 3, + [0] = map_assh, map_assh, map_assh +} + +local map_addsubex = { -- Add/subtract, extended register. + shift = 22, mask = 3, + [0] = { + shift = 29, mask = 3, + [0] = "addDNMXg", "adds|cmnD0NMXg", "subDNMXg", "subs|cmpD0NMzXg", + } +} + +local map_addsubc = { -- Add/subtract, with carry. + shift = 10, mask = 63, + [0] = { + shift = 29, mask = 3, + [0] = "adcDNMg", "adcsDNMg", "sbc|ngcDN0Mg", "sbcs|ngcsDN0Mg", + } +} + +local map_ccomp = { + shift = 4, mask = 1, + [0] = { + shift = 10, mask = 3, + [0] = { -- Conditional compare register. + shift = 29, mask = 3, + "ccmnNMVCg", false, "ccmpNMVCg", + }, + [2] = { -- Conditional compare immediate. + shift = 29, mask = 3, + "ccmnN5VCg", false, "ccmpN5VCg", + } + } +} + +local map_csel = { -- Conditional select. + shift = 11, mask = 1, + [0] = { + shift = 10, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "cselDNMzCg", false, "csinv|cinv|csetmDNMcg", false, + }, + { + shift = 29, mask = 3, + [0] = "csinc|cinc|csetDNMcg", false, "csneg|cnegDNMcg", false, + } + } +} + +local map_data1s = { -- Data processing, 1 source. + shift = 29, mask = 1, + [0] = { + shift = 31, mask = 1, + [0] = { + shift = 10, mask = 0x7ff, + [0] = "rbitDNg", "rev16DNg", "revDNw", false, "clzDNg", "clsDNg" + }, + { + shift = 10, mask = 0x7ff, + [0] = "rbitDNg", "rev16DNg", "rev32DNx", "revDNx", "clzDNg", "clsDNg" + } + } +} + +local map_data2s = { -- Data processing, 2 sources. + shift = 29, mask = 1, + [0] = { + shift = 10, mask = 63, + false, "udivDNMg", "sdivDNMg", false, false, false, false, "lslDNMg", + "lsrDNMg", "asrDNMg", "rorDNMg" + } +} + +local map_data3s = { -- Data processing, 3 sources. + shift = 29, mask = 7, + [0] = { + shift = 21, mask = 7, + [0] = { + shift = 15, mask = 1, + [0] = "madd|mulDNMA0g", "msub|mnegDNMA0g" + } + }, false, false, false, + { + shift = 15, mask = 1, + [0] = { + shift = 21, mask = 7, + [0] = "madd|mulDNMA0g", "smaddl|smullDxNMwA0x", "smulhDNMx", false, + false, "umaddl|umullDxNMwA0x", "umulhDNMx" + }, + { + shift = 21, mask = 7, + [0] = "msub|mnegDNMA0g", "smsubl|smneglDxNMwA0x", false, false, + false, "umsubl|umneglDxNMwA0x" + } + } +} + +local map_datar = { -- Data processing, register. + shift = 28, mask = 1, + [0] = { + shift = 24, mask = 1, + [0] = map_logsr, + { + shift = 21, mask = 1, + [0] = map_addsubsh, map_addsubex + } + }, + { + shift = 21, mask = 15, + [0] = map_addsubc, false, map_ccomp, false, map_csel, false, + { + shift = 30, mask = 1, + [0] = map_data2s, map_data1s + }, + false, map_data3s, map_data3s, map_data3s, map_data3s, map_data3s, + map_data3s, map_data3s, map_data3s + } +} + +local map_lrl = { -- Load register, literal. + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = "ldrDwB", "ldrDxB", "ldrswDxB" + }, + { + shift = 30, mask = 3, + [0] = "ldrDsB", "ldrDdB" + } +} + +local map_lsriind = { -- Load/store register, immediate pre/post-indexed. + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwzL", "ldrbDwzL", "ldrsbDxzL", "ldrsbDwzL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strhDwzL", "ldrhDwzL", "ldrshDxzL", "ldrshDwzL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strDwzL", "ldrDwzL", "ldrswDxzL" + }, + { + shift = 22, mask = 3, + [0] = "strDszL", "ldrDszL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strDxzL", "ldrDxzL" + }, + { + shift = 22, mask = 3, + [0] = "strDdzL", "ldrDdzL" + } + } +} + +local map_lsriro = { + shift = 21, mask = 1, + [0] = { -- Load/store register immediate. + shift = 10, mask = 3, + [0] = { -- Unscaled immediate. + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "sturbDwK", "ldurbDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturhDwK", "ldurhDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturDwK", "ldurDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturDxK", "ldurDxK" + } + } + }, map_lsriind, false, map_lsriind + }, + { -- Load/store register, register offset. + shift = 10, mask = 3, + [2] = { + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwO", "ldrbDwO", "ldrsbDxO", "ldrsbDwO" + }, + { + shift = 22, mask = 3, + [0] = "strhDwO", "ldrhDwO", "ldrshDxO", "ldrshDwO" + }, + { + shift = 22, mask = 3, + [0] = "strDwO", "ldrDwO", "ldrswDxO" + }, + { + shift = 22, mask = 3, + [0] = "strDxO", "ldrDxO" + } + }, + { + shift = 30, mask = 3, + [2] = { + shift = 22, mask = 3, + [0] = "strDsO", "ldrDsO" + }, + [3] = { + shift = 22, mask = 3, + [0] = "strDdO", "ldrDdO" + } + } + } + } +} + +local map_lsp = { -- Load/store register pair, offset. + shift = 22, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = "stpDzAzwP", "stpDzAzsP", + }, + { + shift = 26, mask = 1, + "stpDzAzdP" + }, + { + shift = 26, mask = 1, + [0] = "stpDzAzxP" + } + }, + { + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = "ldpDzAzwP", "ldpDzAzsP", + }, + { + shift = 26, mask = 1, + [0] = "ldpswDAxP", "ldpDzAzdP" + }, + { + shift = 26, mask = 1, + [0] = "ldpDzAzxP" + } + } +} + +local map_ls = { -- Loads and stores. + shift = 24, mask = 0x31, + [0x10] = map_lrl, [0x30] = map_lsriro, + [0x20] = { + shift = 23, mask = 3, + map_lsp, map_lsp, map_lsp + }, + [0x21] = { + shift = 23, mask = 3, + map_lsp, map_lsp, map_lsp + }, + [0x31] = { + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwzU", "ldrbDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strhDwzU", "ldrhDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strDwzU", "ldrDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strDxzU", "ldrDxzU" + } + }, + { + shift = 30, mask = 3, + [2] = { + shift = 22, mask = 3, + [0] = "strDszU", "ldrDszU" + }, + [3] = { + shift = 22, mask = 3, + [0] = "strDdzU", "ldrDdzU" + } + } + }, +} + +local map_datafp = { -- Data processing, SIMD and FP. + shift = 28, mask = 7, + { -- 001 + shift = 24, mask = 1, + [0] = { + shift = 21, mask = 1, + { + shift = 10, mask = 3, + [0] = { + shift = 12, mask = 1, + [0] = { + shift = 13, mask = 1, + [0] = { + shift = 14, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { -- FP/int conversion. + shift = 31, mask = 1, + [0] = { + shift = 16, mask = 0xff, + [0x20] = "fcvtnsDwNs", [0x21] = "fcvtnuDwNs", + [0x22] = "scvtfDsNw", [0x23] = "ucvtfDsNw", + [0x24] = "fcvtasDwNs", [0x25] = "fcvtauDwNs", + [0x26] = "fmovDwNs", [0x27] = "fmovDsNw", + [0x28] = "fcvtpsDwNs", [0x29] = "fcvtpuDwNs", + [0x30] = "fcvtmsDwNs", [0x31] = "fcvtmuDwNs", + [0x38] = "fcvtzsDwNs", [0x39] = "fcvtzuDwNs", + [0x60] = "fcvtnsDwNd", [0x61] = "fcvtnuDwNd", + [0x62] = "scvtfDdNw", [0x63] = "ucvtfDdNw", + [0x64] = "fcvtasDwNd", [0x65] = "fcvtauDwNd", + [0x68] = "fcvtpsDwNd", [0x69] = "fcvtpuDwNd", + [0x70] = "fcvtmsDwNd", [0x71] = "fcvtmuDwNd", + [0x78] = "fcvtzsDwNd", [0x79] = "fcvtzuDwNd" + }, + { + shift = 16, mask = 0xff, + [0x20] = "fcvtnsDxNs", [0x21] = "fcvtnuDxNs", + [0x22] = "scvtfDsNx", [0x23] = "ucvtfDsNx", + [0x24] = "fcvtasDxNs", [0x25] = "fcvtauDxNs", + [0x28] = "fcvtpsDxNs", [0x29] = "fcvtpuDxNs", + [0x30] = "fcvtmsDxNs", [0x31] = "fcvtmuDxNs", + [0x38] = "fcvtzsDxNs", [0x39] = "fcvtzuDxNs", + [0x60] = "fcvtnsDxNd", [0x61] = "fcvtnuDxNd", + [0x62] = "scvtfDdNx", [0x63] = "ucvtfDdNx", + [0x64] = "fcvtasDxNd", [0x65] = "fcvtauDxNd", + [0x66] = "fmovDxNd", [0x67] = "fmovDdNx", + [0x68] = "fcvtpsDxNd", [0x69] = "fcvtpuDxNd", + [0x70] = "fcvtmsDxNd", [0x71] = "fcvtmuDxNd", + [0x78] = "fcvtzsDxNd", [0x79] = "fcvtzuDxNd" + } + } + }, + { -- FP data-processing, 1 source. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = { + shift = 15, mask = 63, + [0] = "fmovDNf", "fabsDNf", "fnegDNf", + "fsqrtDNf", false, "fcvtDdNs", false, false, + "frintnDNf", "frintpDNf", "frintmDNf", "frintzDNf", + "frintaDNf", false, "frintxDNf", "frintiDNf", + }, + { + shift = 15, mask = 63, + [0] = "fmovDNf", "fabsDNf", "fnegDNf", + "fsqrtDNf", "fcvtDsNd", false, false, false, + "frintnDNf", "frintpDNf", "frintmDNf", "frintzDNf", + "frintaDNf", false, "frintxDNf", "frintiDNf", + } + } + } + }, + { -- FP compare. + shift = 31, mask = 1, + [0] = { + shift = 14, mask = 3, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 0, mask = 31, + [0] = "fcmpNMf", [8] = "fcmpNZf", + [16] = "fcmpeNMf", [24] = "fcmpeNZf", + } + } + } + } + }, + { -- FP immediate. + shift = 31, mask = 1, + [0] = { + shift = 5, mask = 31, + [0] = { + shift = 23, mask = 1, + [0] = "fmovDFf" + } + } + } + }, + { -- FP conditional compare. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 4, mask = 1, + [0] = "fccmpNMVCf", "fccmpeNMVCf" + } + } + }, + { -- FP data-processing, 2 sources. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 12, mask = 15, + [0] = "fmulDNMf", "fdivDNMf", "faddDNMf", "fsubDNMf", + "fmaxDNMf", "fminDNMf", "fmaxnmDNMf", "fminnmDNMf", + "fnmulDNMf" + } + } + }, + { -- FP conditional select. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = "fcselDNMCf" + } + } + } + }, + { -- FP data-processing, 3 sources. + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 21, mask = 5, + [0] = "fmaddDNMAf", "fnmaddDNMAf" + }, + { + shift = 21, mask = 5, + [0] = "fmsubDNMAf", "fnmsubDNMAf" + } + } + } + } +} + +local map_br = { -- Branches, exception generating and system instructions. + shift = 29, mask = 7, + [0] = "bB", + { -- Compare & branch, immediate. + shift = 24, mask = 3, + [0] = "cbzDBg", "cbnzDBg", "tbzDTBw", "tbnzDTBw" + }, + { -- Conditional branch, immediate. + shift = 24, mask = 3, + [0] = { + shift = 4, mask = 1, + [0] = { + shift = 0, mask = 15, + [0] = "beqB", "bneB", "bhsB", "bloB", "bmiB", "bplB", "bvsB", "bvcB", + "bhiB", "blsB", "bgeB", "bltB", "bgtB", "bleB", "balB" + } + } + }, false, "blB", + { -- Compare & branch, immediate. + shift = 24, mask = 3, + [0] = "cbzDBg", "cbnzDBg", "tbzDTBx", "tbnzDTBx" + }, + { + shift = 24, mask = 3, + [0] = { -- Exception generation. + shift = 0, mask = 0xe0001f, + [0x200000] = "brkW" + }, + { -- System instructions. + shift = 0, mask = 0x3fffff, + [0x03201f] = "nop" + }, + { -- Unconditional branch, register. + shift = 0, mask = 0xfffc1f, + [0x1f0000] = "brNx", [0x3f0000] = "blrNx", + [0x5f0000] = "retNx" + }, + } +} + +local map_init = { + shift = 25, mask = 15, + [0] = false, false, false, false, map_ls, map_datar, map_ls, map_datafp, + map_datai, map_datai, map_br, map_br, map_ls, map_datar, map_ls, map_datafp +} + +------------------------------------------------------------------------------ + +local map_regs = { x = {}, w = {}, d = {}, s = {} } + +for i=0,30 do + map_regs.x[i] = "x"..i + map_regs.w[i] = "w"..i + map_regs.d[i] = "d"..i + map_regs.s[i] = "s"..i +end +map_regs.x[31] = "sp" +map_regs.w[31] = "wsp" +map_regs.d[31] = "d31" +map_regs.s[31] = "s31" + +local map_cond = { + [0] = "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", +} + +local map_shift = { [0] = "lsl", "lsr", "asr", } + +local map_extend = { + [0] = "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx", +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then + extra = "\t->"..sym + end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-5s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-5s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +local function match_reg(p, pat, regnum) + return map_regs[match(pat, p.."%w-([xwds])")][regnum] +end + +local function fmt_hex32(x) + if x < 0 then + return tohex(x) + else + return format("%x", x) + end +end + +local imm13_rep = { 0x55555555, 0x11111111, 0x01010101, 0x00010001, 0x00000001 } + +local function decode_imm13(op) + local imms = band(rshift(op, 10), 63) + local immr = band(rshift(op, 16), 63) + if band(op, 0x00400000) == 0 then + local len = 5 + if imms >= 56 then + if imms >= 60 then len = 1 else len = 2 end + elseif imms >= 48 then len = 3 elseif imms >= 32 then len = 4 end + local l = lshift(1, len)-1 + local s = band(imms, l) + local r = band(immr, l) + local imm = ror(rshift(-1, 31-s), r) + if len ~= 5 then imm = band(imm, lshift(1, l)-1) + rshift(imm, 31-l) end + imm = imm * imm13_rep[len] + local ix = fmt_hex32(imm) + if rshift(op, 31) ~= 0 then + return ix..tohex(imm) + else + return ix + end + else + local lo, hi = -1, 0 + if imms < 32 then lo = rshift(-1, 31-imms) else hi = rshift(-1, 63-imms) end + if immr ~= 0 then + lo, hi = ror(lo, immr), ror(hi, immr) + local x = immr == 32 and 0 or band(bxor(lo, hi), lshift(-1, 32-immr)) + lo, hi = bxor(lo, x), bxor(hi, x) + if immr >= 32 then lo, hi = hi, lo end + end + if hi ~= 0 then + return fmt_hex32(hi)..tohex(lo) + else + return fmt_hex32(lo) + end + end +end + +local function parse_immpc(op, name) + if name == "b" or name == "bl" then + return arshift(lshift(op, 6), 4) + elseif name == "adr" or name == "adrp" then + local immlo = band(rshift(op, 29), 3) + local immhi = lshift(arshift(lshift(op, 8), 13), 2) + return bor(immhi, immlo) + elseif name == "tbz" or name == "tbnz" then + return lshift(arshift(lshift(op, 13), 18), 2) + else + return lshift(arshift(lshift(op, 8), 13), 2) + end +end + +local function parse_fpimm8(op) + local sign = band(op, 0x100000) == 0 and 1 or -1 + local exp = bxor(rshift(arshift(lshift(op, 12), 5), 24), 0x80) - 131 + local frac = 16+band(rshift(op, 13), 15) + return sign * frac * 2^exp +end + +local function prefer_bfx(sf, uns, imms, immr) + if imms < immr or imms == 31 or imms == 63 then + return false + end + if immr == 0 then + if sf == 0 and (imms == 7 or imms == 15) then + return false + end + if sf ~= 0 and uns == 0 and (imms == 7 or imms == 15 or imms == 31) then + return false + end + end + return true +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) + local operands = {} + local suffix = "" + local last, name, pat + local map_reg + ctx.op = op + ctx.rel = nil + last = nil + local opat + opat = map_init[band(rshift(op, 25), 15)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + name, pat = match(opat, "^([a-z0-9]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") + if altname then pat = pat2 end + if sub(pat, 1, 1) == "." then + local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") + suffix = suffix..s2 + pat = p2 + end + + local rt = match(pat, "[gf]") + if rt then + if rt == "g" then + map_reg = band(op, 0x80000000) ~= 0 and map_regs.x or map_regs.w + else + map_reg = band(op, 0x400000) ~= 0 and map_regs.d or map_regs.s + end + end + + local second0, immr + + for p in gmatch(pat, ".") do + local x = nil + if p == "D" then + local regnum = band(op, 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "N" then + local regnum = band(rshift(op, 5), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "M" then + local regnum = band(rshift(op, 16), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "A" then + local regnum = band(rshift(op, 10), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "B" then + local addr = ctx.addr + pos + parse_immpc(op, name) + ctx.rel = addr + x = "0x"..tohex(addr) + elseif p == "T" then + x = bor(band(rshift(op, 26), 32), band(rshift(op, 19), 31)) + elseif p == "V" then + x = band(op, 15) + elseif p == "C" then + x = map_cond[band(rshift(op, 12), 15)] + elseif p == "c" then + local rn = band(rshift(op, 5), 31) + local rm = band(rshift(op, 16), 31) + local cond = band(rshift(op, 12), 15) + local invc = bxor(cond, 1) + x = map_cond[cond] + if altname and cond ~= 14 and cond ~= 15 then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if rn == rm then + local n = #operands + operands[n] = nil + x = map_cond[invc] + if rn ~= 31 then + if a1 then name = a1 else name = altname end + else + operands[n-1] = nil + name = a2 + end + end + end + elseif p == "W" then + x = band(rshift(op, 5), 0xffff) + elseif p == "Y" then + x = band(rshift(op, 5), 0xffff) + local hw = band(rshift(op, 21), 3) + if altname and (hw == 0 or x ~= 0) then + name = altname + end + elseif p == "L" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local imm9 = arshift(lshift(op, 11), 23) + if band(op, 0x800) ~= 0 then + x = "["..rn..", #"..imm9.."]!" + else + x = "["..rn.."], #"..imm9 + end + elseif p == "U" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local sz = band(rshift(op, 30), 3) + local imm12 = lshift(arshift(lshift(op, 10), 20), sz) + if imm12 ~= 0 then + x = "["..rn..", #"..imm12.."]" + else + x = "["..rn.."]" + end + elseif p == "K" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local imm9 = arshift(lshift(op, 11), 23) + if imm9 ~= 0 then + x = "["..rn..", #"..imm9.."]" + else + x = "["..rn.."]" + end + elseif p == "O" then + local rn, rm = map_regs.x[band(rshift(op, 5), 31)] + local m = band(rshift(op, 13), 1) + if m == 0 then + rm = map_regs.w[band(rshift(op, 16), 31)] + else + rm = map_regs.x[band(rshift(op, 16), 31)] + end + x = "["..rn..", "..rm + local opt = band(rshift(op, 13), 7) + local s = band(rshift(op, 12), 1) + local sz = band(rshift(op, 30), 3) + -- extension to be applied + if opt == 3 then + if s == 0 then x = x.."]" + else x = x..", lsl #"..sz.."]" end + elseif opt == 2 or opt == 6 or opt == 7 then + if s == 0 then x = x..", "..map_extend[opt].."]" + else x = x..", "..map_extend[opt].." #"..sz.."]" end + else + x = x.."]" + end + elseif p == "P" then + local opcv, sh = rshift(op, 26), 2 + if opcv >= 0x2a then sh = 4 elseif opcv >= 0x1b then sh = 3 end + local imm7 = lshift(arshift(lshift(op, 10), 25), sh) + local rn = map_regs.x[band(rshift(op, 5), 31)] + local ind = band(rshift(op, 23), 3) + if ind == 1 then + x = "["..rn.."], #"..imm7 + elseif ind == 2 then + if imm7 == 0 then + x = "["..rn.."]" + else + x = "["..rn..", #"..imm7.."]" + end + elseif ind == 3 then + x = "["..rn..", #"..imm7.."]!" + end + elseif p == "I" then + local shf = band(rshift(op, 22), 3) + local imm12 = band(rshift(op, 10), 0x0fff) + local rn, rd = band(rshift(op, 5), 31), band(op, 31) + if altname == "mov" and shf == 0 and imm12 == 0 and (rn == 31 or rd == 31) then + name = altname + x = nil + elseif shf == 0 then + x = imm12 + elseif shf == 1 then + x = imm12..", lsl #12" + end + elseif p == "i" then + x = "#0x"..decode_imm13(op) + elseif p == "1" then + immr = band(rshift(op, 16), 63) + x = immr + elseif p == "2" then + x = band(rshift(op, 10), 63) + if altname then + local a1, a2, a3, a4, a5, a6 = + match(altname, "([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)|(.*)") + local sf = band(rshift(op, 26), 32) + local uns = band(rshift(op, 30), 1) + if prefer_bfx(sf, uns, x, immr) then + name = a2 + x = x - immr + 1 + elseif immr == 0 and x == 7 then + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + name = a6 + x = nil + elseif immr == 0 and x == 15 then + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + name = a5 + x = nil + elseif x == 31 or x == 63 then + if x == 31 and immr == 0 and name == "sbfm" then + name = a4 + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + else + name = a3 + end + x = nil + elseif band(x, 31) ~= 31 and immr == x+1 and name == "ubfm" then + name = a4 + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = nil + elseif x < immr then + name = a1 + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = x + 1 + end + end + elseif p == "3" then + x = band(rshift(op, 10), 63) + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if x < immr then + name = a1 + local sf = band(rshift(op, 26), 32) + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = x + 1 + else + name = a2 + x = x - immr + 1 + end + end + elseif p == "4" then + x = band(rshift(op, 10), 63) + local rn = band(rshift(op, 5), 31) + local rm = band(rshift(op, 16), 31) + if altname and rn == rm then + local n = #operands + operands[n] = nil + last = operands[n-1] + name = altname + end + elseif p == "5" then + x = band(rshift(op, 16), 31) + elseif p == "S" then + x = band(rshift(op, 10), 63) + if x == 0 then x = nil + else x = map_shift[band(rshift(op, 22), 3)].." #"..x end + elseif p == "X" then + local opt = band(rshift(op, 13), 7) + -- Width specifier . + if opt ~= 3 and opt ~= 7 then + last = map_regs.w[band(rshift(op, 16), 31)] + operands[#operands] = last + end + x = band(rshift(op, 10), 7) + -- Extension. + if opt == 2 + band(rshift(op, 31), 1) and + band(rshift(op, second0 and 5 or 0), 31) == 31 then + if x == 0 then x = nil + else x = "lsl #"..x end + else + if x == 0 then x = map_extend[band(rshift(op, 13), 7)] + else x = map_extend[band(rshift(op, 13), 7)].." #"..x end + end + elseif p == "R" then + x = band(rshift(op,21), 3) + if x == 0 then x = nil + else x = "lsl #"..x*16 end + elseif p == "z" then + local n = #operands + if operands[n] == "sp" then operands[n] = "xzr" + elseif operands[n] == "wsp" then operands[n] = "wzr" + end + elseif p == "Z" then + x = 0 + elseif p == "F" then + x = parse_fpimm8(op) + elseif p == "g" or p == "f" or p == "x" or p == "w" or + p == "d" or p == "s" then + -- These are handled in D/N/M/A. + elseif p == "0" then + if last == "sp" or last == "wsp" then + local n = #operands + operands[n] = nil + last = operands[n-1] + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if not a1 then + name = altname + elseif second0 then + name, altname = a2, a1 + else + name, altname = a1, a2 + end + end + end + second0 = true + else + assert(false) + end + if x then + last = x + if type(x) == "number" then x = "#"..x end + operands[#operands+1] = x + end + end + + return putop(ctx, name..suffix, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ctx.pos = ofs + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_regs.x[r] end + return map_regs.d[r-32] +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm64be.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm64be.lua new file mode 100644 index 00000000..edcbffa8 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_arm64be.lua @@ -0,0 +1,12 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM64BE disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- ARM64 instructions are always little-endian. So just forward to the +-- common ARM64 disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +return require((string.match(..., ".*%.") or "").."dis_arm64") + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips.lua new file mode 100644 index 00000000..6ad17f54 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips.lua @@ -0,0 +1,694 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT/X license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles all standard MIPS32R1/R2 instructions. +-- Default mode is big-endian, but see: dis_mipsel.lua +------------------------------------------------------------------------------ + +local type = type +local byte, format = string.byte, string.format +local match, gmatch = string.match, string.gmatch +local concat = table.concat +local bit = require("bit") +local band, bor, tohex = bit.band, bit.bor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Extended opcode maps common to all MIPS releases +------------------------------------------------------------------------------ + +local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", } +local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", } + +local map_cop0 = { + shift = 25, mask = 1, + [0] = { + shift = 21, mask = 15, + [0] = "mfc0TDW", [4] = "mtc0TDW", + [10] = "rdpgprDT", + [11] = { shift = 5, mask = 1, [0] = "diT0", "eiT0", }, + [14] = "wrpgprDT", + }, { + shift = 0, mask = 63, + [1] = "tlbr", [2] = "tlbwi", [6] = "tlbwr", [8] = "tlbp", + [24] = "eret", [31] = "deret", + [32] = "wait", + }, +} + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps for MIPS R1-R5 +------------------------------------------------------------------------------ + +local map_movci = { shift = 16, mask = 1, [0] = "movfDSC", "movtDSC", } + +local map_special = { + shift = 0, mask = 63, + [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, + map_movci, map_srl, "sraDTA", + "sllvDTS", false, map_srlv, "sravDTS", + "jrS", "jalrD1S", "movzDST", "movnDST", + "syscallY", "breakY", false, "sync", + "mfhiD", "mthiS", "mfloD", "mtloS", + "dsllvDST", false, "dsrlvDST", "dsravDST", + "multST", "multuST", "divST", "divuST", + "dmultST", "dmultuST", "ddivST", "ddivuST", + "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", + "andDST", "or|moveDST0", "xorDST", "nor|notDST0", + false, false, "sltDST", "sltuDST", + "daddDST", "dadduDST", "dsubDST", "dsubuDST", + "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", + "teqSTZ", false, "tneSTZ", false, + "dsllDTA", false, "dsrlDTA", "dsraDTA", + "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", +} + +local map_special2 = { + shift = 0, mask = 63, + [0] = "maddST", "madduST", "mulDST", false, + "msubST", "msubuST", + [32] = "clzDS", [33] = "cloDS", + [63] = "sdbbpY", +} + +local map_bshfl = { + shift = 6, mask = 31, + [2] = "wsbhDT", + [16] = "sebDT", + [24] = "sehDT", +} + +local map_dbshfl = { + shift = 6, mask = 31, + [2] = "dsbhDT", + [5] = "dshdDT", +} + +local map_special3 = { + shift = 0, mask = 63, + [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", + [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", + [32] = map_bshfl, [36] = map_dbshfl, [59] = "rdhwrTD", +} + +local map_regimm = { + shift = 16, mask = 31, + [0] = "bltzSB", "bgezSB", "bltzlSB", "bgezlSB", + false, false, false, false, + "tgeiSI", "tgeiuSI", "tltiSI", "tltiuSI", + "teqiSI", false, "tneiSI", false, + "bltzalSB", "bgezalSB", "bltzallSB", "bgezallSB", + false, false, false, false, + false, false, false, false, + false, false, false, "synciSO", +} + +local map_cop1s = { + shift = 0, mask = 63, + [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", + "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG", + "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG", + "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG", + false, + { shift = 16, mask = 1, [0] = "movf.sFGC", "movt.sFGC" }, + "movz.sFGT", "movn.sFGT", + false, "recip.sFG", "rsqrt.sFG", false, + false, false, false, false, + false, false, false, false, + false, "cvt.d.sFG", false, false, + "cvt.w.sFG", "cvt.l.sFG", "cvt.ps.sFGH", false, + false, false, false, false, + false, false, false, false, + "c.f.sVGH", "c.un.sVGH", "c.eq.sVGH", "c.ueq.sVGH", + "c.olt.sVGH", "c.ult.sVGH", "c.ole.sVGH", "c.ule.sVGH", + "c.sf.sVGH", "c.ngle.sVGH", "c.seq.sVGH", "c.ngl.sVGH", + "c.lt.sVGH", "c.nge.sVGH", "c.le.sVGH", "c.ngt.sVGH", +} + +local map_cop1d = { + shift = 0, mask = 63, + [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH", + "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG", + "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG", + "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG", + false, + { shift = 16, mask = 1, [0] = "movf.dFGC", "movt.dFGC" }, + "movz.dFGT", "movn.dFGT", + false, "recip.dFG", "rsqrt.dFG", false, + false, false, false, false, + false, false, false, false, + "cvt.s.dFG", false, false, false, + "cvt.w.dFG", "cvt.l.dFG", false, false, + false, false, false, false, + false, false, false, false, + "c.f.dVGH", "c.un.dVGH", "c.eq.dVGH", "c.ueq.dVGH", + "c.olt.dVGH", "c.ult.dVGH", "c.ole.dVGH", "c.ule.dVGH", + "c.df.dVGH", "c.ngle.dVGH", "c.deq.dVGH", "c.ngl.dVGH", + "c.lt.dVGH", "c.nge.dVGH", "c.le.dVGH", "c.ngt.dVGH", +} + +local map_cop1ps = { + shift = 0, mask = 63, + [0] = "add.psFGH", "sub.psFGH", "mul.psFGH", false, + false, "abs.psFG", "mov.psFG", "neg.psFG", + false, false, false, false, + false, false, false, false, + false, + { shift = 16, mask = 1, [0] = "movf.psFGC", "movt.psFGC" }, + "movz.psFGT", "movn.psFGT", + false, false, false, false, + false, false, false, false, + false, false, false, false, + "cvt.s.puFG", false, false, false, + false, false, false, false, + "cvt.s.plFG", false, false, false, + "pll.psFGH", "plu.psFGH", "pul.psFGH", "puu.psFGH", + "c.f.psVGH", "c.un.psVGH", "c.eq.psVGH", "c.ueq.psVGH", + "c.olt.psVGH", "c.ult.psVGH", "c.ole.psVGH", "c.ule.psVGH", + "c.psf.psVGH", "c.ngle.psVGH", "c.pseq.psVGH", "c.ngl.psVGH", + "c.lt.psVGH", "c.nge.psVGH", "c.le.psVGH", "c.ngt.psVGH", +} + +local map_cop1w = { + shift = 0, mask = 63, + [32] = "cvt.s.wFG", [33] = "cvt.d.wFG", +} + +local map_cop1l = { + shift = 0, mask = 63, + [32] = "cvt.s.lFG", [33] = "cvt.d.lFG", +} + +local map_cop1bc = { + shift = 16, mask = 3, + [0] = "bc1fCB", "bc1tCB", "bc1flCB", "bc1tlCB", +} + +local map_cop1 = { + shift = 21, mask = 31, + [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", + "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", + map_cop1bc, false, false, false, + false, false, false, false, + map_cop1s, map_cop1d, false, false, + map_cop1w, map_cop1l, map_cop1ps, +} + +local map_cop1x = { + shift = 0, mask = 63, + [0] = "lwxc1FSX", "ldxc1FSX", false, false, + false, "luxc1FSX", false, false, + "swxc1FSX", "sdxc1FSX", false, false, + false, "suxc1FSX", false, "prefxMSX", + false, false, false, false, + false, false, false, false, + false, false, false, false, + false, false, "alnv.psFGHS", false, + "madd.sFRGH", "madd.dFRGH", false, false, + false, false, "madd.psFRGH", false, + "msub.sFRGH", "msub.dFRGH", false, false, + false, false, "msub.psFRGH", false, + "nmadd.sFRGH", "nmadd.dFRGH", false, false, + false, false, "nmadd.psFRGH", false, + "nmsub.sFRGH", "nmsub.dFRGH", false, false, + false, false, "nmsub.psFRGH", false, +} + +local map_pri = { + [0] = map_special, map_regimm, "jJ", "jalJ", + "beq|beqz|bST00B", "bne|bnezST0B", "blezSB", "bgtzSB", + "addiTSI", "addiu|liTS0I", "sltiTSI", "sltiuTSI", + "andiTSU", "ori|liTS0U", "xoriTSU", "luiTU", + map_cop0, map_cop1, false, map_cop1x, + "beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB", + "daddiTSI", "daddiuTSI", false, false, + map_special2, "jalxJ", false, map_special3, + "lbTSO", "lhTSO", "lwlTSO", "lwTSO", + "lbuTSO", "lhuTSO", "lwrTSO", false, + "sbTSO", "shTSO", "swlTSO", "swTSO", + false, false, "swrTSO", "cacheNSO", + "llTSO", "lwc1HSO", "lwc2TSO", "prefNSO", + false, "ldc1HSO", "ldc2TSO", "ldTSO", + "scTSO", "swc1HSO", "swc2TSO", false, + false, "sdc1HSO", "sdc2TSO", "sdTSO", +} + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps for MIPS R6 +------------------------------------------------------------------------------ + +local map_mul_r6 = { shift = 6, mask = 3, [2] = "mulDST", [3] = "muhDST" } +local map_mulu_r6 = { shift = 6, mask = 3, [2] = "muluDST", [3] = "muhuDST" } +local map_div_r6 = { shift = 6, mask = 3, [2] = "divDST", [3] = "modDST" } +local map_divu_r6 = { shift = 6, mask = 3, [2] = "divuDST", [3] = "moduDST" } +local map_dmul_r6 = { shift = 6, mask = 3, [2] = "dmulDST", [3] = "dmuhDST" } +local map_dmulu_r6 = { shift = 6, mask = 3, [2] = "dmuluDST", [3] = "dmuhuDST" } +local map_ddiv_r6 = { shift = 6, mask = 3, [2] = "ddivDST", [3] = "dmodDST" } +local map_ddivu_r6 = { shift = 6, mask = 3, [2] = "ddivuDST", [3] = "dmoduDST" } + +local map_special_r6 = { + shift = 0, mask = 63, + [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, + false, map_srl, "sraDTA", + "sllvDTS", false, map_srlv, "sravDTS", + "jrS", "jalrD1S", false, false, + "syscallY", "breakY", false, "sync", + "clzDS", "cloDS", "dclzDS", "dcloDS", + "dsllvDST", "dlsaDSTA", "dsrlvDST", "dsravDST", + map_mul_r6, map_mulu_r6, map_div_r6, map_divu_r6, + map_dmul_r6, map_dmulu_r6, map_ddiv_r6, map_ddivu_r6, + "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", + "andDST", "or|moveDST0", "xorDST", "nor|notDST0", + false, false, "sltDST", "sltuDST", + "daddDST", "dadduDST", "dsubDST", "dsubuDST", + "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", + "teqSTZ", "seleqzDST", "tneSTZ", "selnezDST", + "dsllDTA", false, "dsrlDTA", "dsraDTA", + "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", +} + +local map_bshfl_r6 = { + shift = 9, mask = 3, + [1] = "alignDSTa", + _ = { + shift = 6, mask = 31, + [0] = "bitswapDT", + [2] = "wsbhDT", + [16] = "sebDT", + [24] = "sehDT", + } +} + +local map_dbshfl_r6 = { + shift = 9, mask = 3, + [1] = "dalignDSTa", + _ = { + shift = 6, mask = 31, + [0] = "dbitswapDT", + [2] = "dsbhDT", + [5] = "dshdDT", + } +} + +local map_special3_r6 = { + shift = 0, mask = 63, + [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", + [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", + [32] = map_bshfl_r6, [36] = map_dbshfl_r6, [59] = "rdhwrTD", +} + +local map_regimm_r6 = { + shift = 16, mask = 31, + [0] = "bltzSB", [1] = "bgezSB", + [6] = "dahiSI", [30] = "datiSI", + [23] = "sigrieI", [31] = "synciSO", +} + +local map_pcrel_r6 = { + shift = 19, mask = 3, + [0] = "addiupcS2", "lwpcS2", "lwupcS2", { + shift = 18, mask = 1, + [0] = "ldpcS3", { shift = 16, mask = 3, [2] = "auipcSI", [3] = "aluipcSI" } + } +} + +local map_cop1s_r6 = { + shift = 0, mask = 63, + [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", + "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG", + "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG", + "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG", + "sel.sFGH", false, false, false, + "seleqz.sFGH", "recip.sFG", "rsqrt.sFG", "selnez.sFGH", + "maddf.sFGH", "msubf.sFGH", "rint.sFG", "class.sFG", + "min.sFGH", "mina.sFGH", "max.sFGH", "maxa.sFGH", + false, "cvt.d.sFG", false, false, + "cvt.w.sFG", "cvt.l.sFG", +} + +local map_cop1d_r6 = { + shift = 0, mask = 63, + [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH", + "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG", + "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG", + "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG", + "sel.dFGH", false, false, false, + "seleqz.dFGH", "recip.dFG", "rsqrt.dFG", "selnez.dFGH", + "maddf.dFGH", "msubf.dFGH", "rint.dFG", "class.dFG", + "min.dFGH", "mina.dFGH", "max.dFGH", "maxa.dFGH", + "cvt.s.dFG", false, false, false, + "cvt.w.dFG", "cvt.l.dFG", +} + +local map_cop1w_r6 = { + shift = 0, mask = 63, + [0] = "cmp.af.sFGH", "cmp.un.sFGH", "cmp.eq.sFGH", "cmp.ueq.sFGH", + "cmp.lt.sFGH", "cmp.ult.sFGH", "cmp.le.sFGH", "cmp.ule.sFGH", + "cmp.saf.sFGH", "cmp.sun.sFGH", "cmp.seq.sFGH", "cmp.sueq.sFGH", + "cmp.slt.sFGH", "cmp.sult.sFGH", "cmp.sle.sFGH", "cmp.sule.sFGH", + false, "cmp.or.sFGH", "cmp.une.sFGH", "cmp.ne.sFGH", + false, false, false, false, + false, "cmp.sor.sFGH", "cmp.sune.sFGH", "cmp.sne.sFGH", + false, false, false, false, + "cvt.s.wFG", "cvt.d.wFG", +} + +local map_cop1l_r6 = { + shift = 0, mask = 63, + [0] = "cmp.af.dFGH", "cmp.un.dFGH", "cmp.eq.dFGH", "cmp.ueq.dFGH", + "cmp.lt.dFGH", "cmp.ult.dFGH", "cmp.le.dFGH", "cmp.ule.dFGH", + "cmp.saf.dFGH", "cmp.sun.dFGH", "cmp.seq.dFGH", "cmp.sueq.dFGH", + "cmp.slt.dFGH", "cmp.sult.dFGH", "cmp.sle.dFGH", "cmp.sule.dFGH", + false, "cmp.or.dFGH", "cmp.une.dFGH", "cmp.ne.dFGH", + false, false, false, false, + false, "cmp.sor.dFGH", "cmp.sune.dFGH", "cmp.sne.dFGH", + false, false, false, false, + "cvt.s.lFG", "cvt.d.lFG", +} + +local map_cop1_r6 = { + shift = 21, mask = 31, + [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", + "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", + false, "bc1eqzHB", false, false, + false, "bc1nezHB", false, false, + map_cop1s_r6, map_cop1d_r6, false, false, + map_cop1w_r6, map_cop1l_r6, +} + +local function maprs_popTS(rs, rt) + if rt == 0 then return 0 elseif rs == 0 then return 1 + elseif rs == rt then return 2 else return 3 end +end + +local map_pop06_r6 = { + maprs = maprs_popTS, [0] = "blezSB", "blezalcTB", "bgezalcTB", "bgeucSTB" +} +local map_pop07_r6 = { + maprs = maprs_popTS, [0] = "bgtzSB", "bgtzalcTB", "bltzalcTB", "bltucSTB" +} +local map_pop26_r6 = { + maprs = maprs_popTS, "blezcTB", "bgezcTB", "bgecSTB" +} +local map_pop27_r6 = { + maprs = maprs_popTS, "bgtzcTB", "bltzcTB", "bltcSTB" +} + +local function maprs_popS(rs, rt) + if rs == 0 then return 0 else return 1 end +end + +local map_pop66_r6 = { + maprs = maprs_popS, [0] = "jicTI", "beqzcSb" +} +local map_pop76_r6 = { + maprs = maprs_popS, [0] = "jialcTI", "bnezcSb" +} + +local function maprs_popST(rs, rt) + if rs >= rt then return 0 elseif rs == 0 then return 1 else return 2 end +end + +local map_pop10_r6 = { + maprs = maprs_popST, [0] = "bovcSTB", "beqzalcTB", "beqcSTB" +} +local map_pop30_r6 = { + maprs = maprs_popST, [0] = "bnvcSTB", "bnezalcTB", "bnecSTB" +} + +local map_pri_r6 = { + [0] = map_special_r6, map_regimm_r6, "jJ", "jalJ", + "beq|beqz|bST00B", "bne|bnezST0B", map_pop06_r6, map_pop07_r6, + map_pop10_r6, "addiu|liTS0I", "sltiTSI", "sltiuTSI", + "andiTSU", "ori|liTS0U", "xoriTSU", "aui|luiTS0U", + map_cop0, map_cop1_r6, false, false, + false, false, map_pop26_r6, map_pop27_r6, + map_pop30_r6, "daddiuTSI", false, false, + false, "dauiTSI", false, map_special3_r6, + "lbTSO", "lhTSO", false, "lwTSO", + "lbuTSO", "lhuTSO", false, false, + "sbTSO", "shTSO", false, "swTSO", + false, false, false, false, + false, "lwc1HSO", "bc#", false, + false, "ldc1HSO", map_pop66_r6, "ldTSO", + false, "swc1HSO", "balc#", map_pcrel_r6, + false, "sdc1HSO", map_pop76_r6, "sdTSO", +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "sp", "r30", "ra", +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then extra = "\t->"..sym end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-7s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-7s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +local function get_be(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + return bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3) +end + +local function get_le(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + return bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local op = ctx:get() + local operands = {} + local last = nil + ctx.op = op + ctx.rel = nil + + local opat = ctx.map_pri[rshift(op, 26)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + if opat.maprs then + opat = opat[opat.maprs(band(rshift(op,21),31), band(rshift(op,16),31))] + else + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + end + local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") + if altname then pat = pat2 end + + for p in gmatch(pat, ".") do + local x = nil + if p == "S" then + x = map_gpr[band(rshift(op, 21), 31)] + elseif p == "T" then + x = map_gpr[band(rshift(op, 16), 31)] + elseif p == "D" then + x = map_gpr[band(rshift(op, 11), 31)] + elseif p == "F" then + x = "f"..band(rshift(op, 6), 31) + elseif p == "G" then + x = "f"..band(rshift(op, 11), 31) + elseif p == "H" then + x = "f"..band(rshift(op, 16), 31) + elseif p == "R" then + x = "f"..band(rshift(op, 21), 31) + elseif p == "A" then + x = band(rshift(op, 6), 31) + elseif p == "a" then + x = band(rshift(op, 6), 7) + elseif p == "E" then + x = band(rshift(op, 6), 31) + 32 + elseif p == "M" then + x = band(rshift(op, 11), 31) + elseif p == "N" then + x = band(rshift(op, 16), 31) + elseif p == "C" then + x = band(rshift(op, 18), 7) + if x == 0 then x = nil end + elseif p == "K" then + x = band(rshift(op, 11), 31) + 1 + elseif p == "P" then + x = band(rshift(op, 11), 31) + 33 + elseif p == "L" then + x = band(rshift(op, 11), 31) - last + 1 + elseif p == "Q" then + x = band(rshift(op, 11), 31) - last + 33 + elseif p == "I" then + x = arshift(lshift(op, 16), 16) + elseif p == "2" then + x = arshift(lshift(op, 13), 11) + elseif p == "3" then + x = arshift(lshift(op, 14), 11) + elseif p == "U" then + x = band(op, 0xffff) + elseif p == "O" then + local disp = arshift(lshift(op, 16), 16) + operands[#operands] = format("%d(%s)", disp, last) + elseif p == "X" then + local index = map_gpr[band(rshift(op, 16), 31)] + operands[#operands] = format("%s(%s)", index, last) + elseif p == "B" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 14) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "b" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 11), 9) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "#" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 6), 4) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "J" then + local a = ctx.addr + ctx.pos + x = a - band(a, 0x0fffffff) + band(op, 0x03ffffff)*4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "V" then + x = band(rshift(op, 8), 7) + if x == 0 then x = nil end + elseif p == "W" then + x = band(op, 7) + if x == 0 then x = nil end + elseif p == "Y" then + x = band(rshift(op, 6), 0x000fffff) + if x == 0 then x = nil end + elseif p == "Z" then + x = band(rshift(op, 6), 1023) + if x == 0 then x = nil end + elseif p == "0" then + if last == "r0" or last == 0 then + local n = #operands + operands[n] = nil + last = operands[n-1] + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if a1 then name, altname = a1, a2 + else name = altname end + end + end + elseif p == "1" then + if last == "ra" then + operands[#operands] = nil + end + else + assert(false) + end + if x then operands[#operands+1] = x; last = x end + end + + return putop(ctx, name, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + stop = stop - stop % 4 + ctx.pos = ofs - ofs % 4 + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + ctx.get = get_be + ctx.map_pri = map_pri + return ctx +end + +local function create_el(code, addr, out) + local ctx = create(code, addr, out) + ctx.get = get_le + return ctx +end + +local function create_r6(code, addr, out) + local ctx = create(code, addr, out) + ctx.map_pri = map_pri_r6 + return ctx +end + +local function create_r6_el(code, addr, out) + local ctx = create(code, addr, out) + ctx.get = get_le + ctx.map_pri = map_pri_r6 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +local function disass_el(code, addr, out) + create_el(code, addr, out):disass() +end + +local function disass_r6(code, addr, out) + create_r6(code, addr, out):disass() +end + +local function disass_r6_el(code, addr, out) + create_r6_el(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_gpr[r] end + return "f"..(r-32) +end + +-- Public module functions. +return { + create = create, + create_el = create_el, + create_r6 = create_r6, + create_r6_el = create_r6_el, + disass = disass, + disass_el = disass_el, + disass_r6 = disass_r6, + disass_r6_el = disass_r6_el, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64.lua new file mode 100644 index 00000000..5ad48f8f --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the big-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create, + disass = dis_mips.disass, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64el.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64el.lua new file mode 100644 index 00000000..d50e3a18 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64el.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64EL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_el, + disass = dis_mips.disass_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64r6.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64r6.lua new file mode 100644 index 00000000..921b3cbe --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64r6.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64R6 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the r6 big-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_r6, + disass = dis_mips.disass_r6, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64r6el.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64r6el.lua new file mode 100644 index 00000000..aadef9f3 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mips64r6el.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64R6EL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the r6 little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_r6_el, + disass = dis_mips.disass_r6_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mipsel.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mipsel.lua new file mode 100644 index 00000000..52cebefb --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_mipsel.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPSEL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_el, + disass = dis_mips.disass_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_ppc.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_ppc.lua new file mode 100644 index 00000000..08d742f1 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_ppc.lua @@ -0,0 +1,591 @@ +---------------------------------------------------------------------------- +-- LuaJIT PPC disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT/X license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles all common, non-privileged 32/64 bit PowerPC instructions +-- plus the e500 SPE instructions and some Cell/Xenon extensions. +-- +-- NYI: VMX, VMX128 +------------------------------------------------------------------------------ + +local type = type +local byte, format = string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local concat = table.concat +local bit = require("bit") +local band, bor, tohex = bit.band, bit.bor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps +------------------------------------------------------------------------------ + +local map_crops = { + shift = 1, mask = 1023, + [0] = "mcrfXX", + [33] = "crnor|crnotCCC=", [129] = "crandcCCC", + [193] = "crxor|crclrCCC%", [225] = "crnandCCC", + [257] = "crandCCC", [289] = "creqv|crsetCCC%", + [417] = "crorcCCC", [449] = "cror|crmoveCCC=", + [16] = "b_lrKB", [528] = "b_ctrKB", + [150] = "isync", +} + +local map_rlwinm = setmetatable({ + shift = 0, mask = -1, +}, +{ __index = function(t, x) + local rot = band(rshift(x, 11), 31) + local mb = band(rshift(x, 6), 31) + local me = band(rshift(x, 1), 31) + if mb == 0 and me == 31-rot then + return "slwiRR~A." + elseif me == 31 and mb == 32-rot then + return "srwiRR~-A." + else + return "rlwinmRR~AAA." + end + end +}) + +local map_rld = { + shift = 2, mask = 7, + [0] = "rldiclRR~HM.", "rldicrRR~HM.", "rldicRR~HM.", "rldimiRR~HM.", + { + shift = 1, mask = 1, + [0] = "rldclRR~RM.", "rldcrRR~RM.", + }, +} + +local map_ext = setmetatable({ + shift = 1, mask = 1023, + + [0] = "cmp_YLRR", [32] = "cmpl_YLRR", + [4] = "twARR", [68] = "tdARR", + + [8] = "subfcRRR.", [40] = "subfRRR.", + [104] = "negRR.", [136] = "subfeRRR.", + [200] = "subfzeRR.", [232] = "subfmeRR.", + [520] = "subfcoRRR.", [552] = "subfoRRR.", + [616] = "negoRR.", [648] = "subfeoRRR.", + [712] = "subfzeoRR.", [744] = "subfmeoRR.", + + [9] = "mulhduRRR.", [73] = "mulhdRRR.", [233] = "mulldRRR.", + [457] = "divduRRR.", [489] = "divdRRR.", + [745] = "mulldoRRR.", + [969] = "divduoRRR.", [1001] = "divdoRRR.", + + [10] = "addcRRR.", [138] = "addeRRR.", + [202] = "addzeRR.", [234] = "addmeRR.", [266] = "addRRR.", + [522] = "addcoRRR.", [650] = "addeoRRR.", + [714] = "addzeoRR.", [746] = "addmeoRR.", [778] = "addoRRR.", + + [11] = "mulhwuRRR.", [75] = "mulhwRRR.", [235] = "mullwRRR.", + [459] = "divwuRRR.", [491] = "divwRRR.", + [747] = "mullwoRRR.", + [971] = "divwouRRR.", [1003] = "divwoRRR.", + + [15] = "iselltRRR", [47] = "iselgtRRR", [79] = "iseleqRRR", + + [144] = { shift = 20, mask = 1, [0] = "mtcrfRZ~", "mtocrfRZ~", }, + [19] = { shift = 20, mask = 1, [0] = "mfcrR", "mfocrfRZ", }, + [371] = { shift = 11, mask = 1023, [392] = "mftbR", [424] = "mftbuR", }, + [339] = { + shift = 11, mask = 1023, + [32] = "mferR", [256] = "mflrR", [288] = "mfctrR", [16] = "mfspefscrR", + }, + [467] = { + shift = 11, mask = 1023, + [32] = "mtxerR", [256] = "mtlrR", [288] = "mtctrR", [16] = "mtspefscrR", + }, + + [20] = "lwarxRR0R", [84] = "ldarxRR0R", + + [21] = "ldxRR0R", [53] = "lduxRRR", + [149] = "stdxRR0R", [181] = "stduxRRR", + [341] = "lwaxRR0R", [373] = "lwauxRRR", + + [23] = "lwzxRR0R", [55] = "lwzuxRRR", + [87] = "lbzxRR0R", [119] = "lbzuxRRR", + [151] = "stwxRR0R", [183] = "stwuxRRR", + [215] = "stbxRR0R", [247] = "stbuxRRR", + [279] = "lhzxRR0R", [311] = "lhzuxRRR", + [343] = "lhaxRR0R", [375] = "lhauxRRR", + [407] = "sthxRR0R", [439] = "sthuxRRR", + + [54] = "dcbst-R0R", [86] = "dcbf-R0R", + [150] = "stwcxRR0R.", [214] = "stdcxRR0R.", + [246] = "dcbtst-R0R", [278] = "dcbt-R0R", + [310] = "eciwxRR0R", [438] = "ecowxRR0R", + [470] = "dcbi-RR", + + [598] = { + shift = 21, mask = 3, + [0] = "sync", "lwsync", "ptesync", + }, + [758] = "dcba-RR", + [854] = "eieio", [982] = "icbi-R0R", [1014] = "dcbz-R0R", + + [26] = "cntlzwRR~", [58] = "cntlzdRR~", + [122] = "popcntbRR~", + [154] = "prtywRR~", [186] = "prtydRR~", + + [28] = "andRR~R.", [60] = "andcRR~R.", [124] = "nor|notRR~R=.", + [284] = "eqvRR~R.", [316] = "xorRR~R.", + [412] = "orcRR~R.", [444] = "or|mrRR~R=.", [476] = "nandRR~R.", + [508] = "cmpbRR~R", + + [512] = "mcrxrX", + + [532] = "ldbrxRR0R", [660] = "stdbrxRR0R", + + [533] = "lswxRR0R", [597] = "lswiRR0A", + [661] = "stswxRR0R", [725] = "stswiRR0A", + + [534] = "lwbrxRR0R", [662] = "stwbrxRR0R", + [790] = "lhbrxRR0R", [918] = "sthbrxRR0R", + + [535] = "lfsxFR0R", [567] = "lfsuxFRR", + [599] = "lfdxFR0R", [631] = "lfduxFRR", + [663] = "stfsxFR0R", [695] = "stfsuxFRR", + [727] = "stfdxFR0R", [759] = "stfduxFR0R", + [855] = "lfiwaxFR0R", + [983] = "stfiwxFR0R", + + [24] = "slwRR~R.", + + [27] = "sldRR~R.", [536] = "srwRR~R.", + [792] = "srawRR~R.", [824] = "srawiRR~A.", + + [794] = "sradRR~R.", [826] = "sradiRR~H.", [827] = "sradiRR~H.", + [922] = "extshRR~.", [954] = "extsbRR~.", [986] = "extswRR~.", + + [539] = "srdRR~R.", +}, +{ __index = function(t, x) + if band(x, 31) == 15 then return "iselRRRC" end + end +}) + +local map_ld = { + shift = 0, mask = 3, + [0] = "ldRRE", "lduRRE", "lwaRRE", +} + +local map_std = { + shift = 0, mask = 3, + [0] = "stdRRE", "stduRRE", +} + +local map_fps = { + shift = 5, mask = 1, + { + shift = 1, mask = 15, + [0] = false, false, "fdivsFFF.", false, + "fsubsFFF.", "faddsFFF.", "fsqrtsF-F.", false, + "fresF-F.", "fmulsFF-F.", "frsqrtesF-F.", false, + "fmsubsFFFF~.", "fmaddsFFFF~.", "fnmsubsFFFF~.", "fnmaddsFFFF~.", + } +} + +local map_fpd = { + shift = 5, mask = 1, + [0] = { + shift = 1, mask = 1023, + [0] = "fcmpuXFF", [32] = "fcmpoXFF", [64] = "mcrfsXX", + [38] = "mtfsb1A.", [70] = "mtfsb0A.", [134] = "mtfsfiA>>-A>", + [8] = "fcpsgnFFF.", [40] = "fnegF-F.", [72] = "fmrF-F.", + [136] = "fnabsF-F.", [264] = "fabsF-F.", + [12] = "frspF-F.", + [14] = "fctiwF-F.", [15] = "fctiwzF-F.", + [583] = "mffsF.", [711] = "mtfsfZF.", + [392] = "frinF-F.", [424] = "frizF-F.", + [456] = "fripF-F.", [488] = "frimF-F.", + [814] = "fctidF-F.", [815] = "fctidzF-F.", [846] = "fcfidF-F.", + }, + { + shift = 1, mask = 15, + [0] = false, false, "fdivFFF.", false, + "fsubFFF.", "faddFFF.", "fsqrtF-F.", "fselFFFF~.", + "freF-F.", "fmulFF-F.", "frsqrteF-F.", false, + "fmsubFFFF~.", "fmaddFFFF~.", "fnmsubFFFF~.", "fnmaddFFFF~.", + } +} + +local map_spe = { + shift = 0, mask = 2047, + + [512] = "evaddwRRR", [514] = "evaddiwRAR~", + [516] = "evsubwRRR~", [518] = "evsubiwRAR~", + [520] = "evabsRR", [521] = "evnegRR", + [522] = "evextsbRR", [523] = "evextshRR", [524] = "evrndwRR", + [525] = "evcntlzwRR", [526] = "evcntlswRR", + + [527] = "brincRRR", + + [529] = "evandRRR", [530] = "evandcRRR", [534] = "evxorRRR", + [535] = "evor|evmrRRR=", [536] = "evnor|evnotRRR=", + [537] = "eveqvRRR", [539] = "evorcRRR", [542] = "evnandRRR", + + [544] = "evsrwuRRR", [545] = "evsrwsRRR", + [546] = "evsrwiuRRA", [547] = "evsrwisRRA", + [548] = "evslwRRR", [550] = "evslwiRRA", + [552] = "evrlwRRR", [553] = "evsplatiRS", + [554] = "evrlwiRRA", [555] = "evsplatfiRS", + [556] = "evmergehiRRR", [557] = "evmergeloRRR", + [558] = "evmergehiloRRR", [559] = "evmergelohiRRR", + + [560] = "evcmpgtuYRR", [561] = "evcmpgtsYRR", + [562] = "evcmpltuYRR", [563] = "evcmpltsYRR", + [564] = "evcmpeqYRR", + + [632] = "evselRRR", [633] = "evselRRRW", + [634] = "evselRRRW", [635] = "evselRRRW", + [636] = "evselRRRW", [637] = "evselRRRW", + [638] = "evselRRRW", [639] = "evselRRRW", + + [640] = "evfsaddRRR", [641] = "evfssubRRR", + [644] = "evfsabsRR", [645] = "evfsnabsRR", [646] = "evfsnegRR", + [648] = "evfsmulRRR", [649] = "evfsdivRRR", + [652] = "evfscmpgtYRR", [653] = "evfscmpltYRR", [654] = "evfscmpeqYRR", + [656] = "evfscfuiR-R", [657] = "evfscfsiR-R", + [658] = "evfscfufR-R", [659] = "evfscfsfR-R", + [660] = "evfsctuiR-R", [661] = "evfsctsiR-R", + [662] = "evfsctufR-R", [663] = "evfsctsfR-R", + [664] = "evfsctuizR-R", [666] = "evfsctsizR-R", + [668] = "evfststgtYRR", [669] = "evfststltYRR", [670] = "evfststeqYRR", + + [704] = "efsaddRRR", [705] = "efssubRRR", + [708] = "efsabsRR", [709] = "efsnabsRR", [710] = "efsnegRR", + [712] = "efsmulRRR", [713] = "efsdivRRR", + [716] = "efscmpgtYRR", [717] = "efscmpltYRR", [718] = "efscmpeqYRR", + [719] = "efscfdR-R", + [720] = "efscfuiR-R", [721] = "efscfsiR-R", + [722] = "efscfufR-R", [723] = "efscfsfR-R", + [724] = "efsctuiR-R", [725] = "efsctsiR-R", + [726] = "efsctufR-R", [727] = "efsctsfR-R", + [728] = "efsctuizR-R", [730] = "efsctsizR-R", + [732] = "efststgtYRR", [733] = "efststltYRR", [734] = "efststeqYRR", + + [736] = "efdaddRRR", [737] = "efdsubRRR", + [738] = "efdcfuidR-R", [739] = "efdcfsidR-R", + [740] = "efdabsRR", [741] = "efdnabsRR", [742] = "efdnegRR", + [744] = "efdmulRRR", [745] = "efddivRRR", + [746] = "efdctuidzR-R", [747] = "efdctsidzR-R", + [748] = "efdcmpgtYRR", [749] = "efdcmpltYRR", [750] = "efdcmpeqYRR", + [751] = "efdcfsR-R", + [752] = "efdcfuiR-R", [753] = "efdcfsiR-R", + [754] = "efdcfufR-R", [755] = "efdcfsfR-R", + [756] = "efdctuiR-R", [757] = "efdctsiR-R", + [758] = "efdctufR-R", [759] = "efdctsfR-R", + [760] = "efdctuizR-R", [762] = "efdctsizR-R", + [764] = "efdtstgtYRR", [765] = "efdtstltYRR", [766] = "efdtsteqYRR", + + [768] = "evlddxRR0R", [769] = "evlddRR8", + [770] = "evldwxRR0R", [771] = "evldwRR8", + [772] = "evldhxRR0R", [773] = "evldhRR8", + [776] = "evlhhesplatxRR0R", [777] = "evlhhesplatRR2", + [780] = "evlhhousplatxRR0R", [781] = "evlhhousplatRR2", + [782] = "evlhhossplatxRR0R", [783] = "evlhhossplatRR2", + [784] = "evlwhexRR0R", [785] = "evlwheRR4", + [788] = "evlwhouxRR0R", [789] = "evlwhouRR4", + [790] = "evlwhosxRR0R", [791] = "evlwhosRR4", + [792] = "evlwwsplatxRR0R", [793] = "evlwwsplatRR4", + [796] = "evlwhsplatxRR0R", [797] = "evlwhsplatRR4", + + [800] = "evstddxRR0R", [801] = "evstddRR8", + [802] = "evstdwxRR0R", [803] = "evstdwRR8", + [804] = "evstdhxRR0R", [805] = "evstdhRR8", + [816] = "evstwhexRR0R", [817] = "evstwheRR4", + [820] = "evstwhoxRR0R", [821] = "evstwhoRR4", + [824] = "evstwwexRR0R", [825] = "evstwweRR4", + [828] = "evstwwoxRR0R", [829] = "evstwwoRR4", + + [1027] = "evmhessfRRR", [1031] = "evmhossfRRR", [1032] = "evmheumiRRR", + [1033] = "evmhesmiRRR", [1035] = "evmhesmfRRR", [1036] = "evmhoumiRRR", + [1037] = "evmhosmiRRR", [1039] = "evmhosmfRRR", [1059] = "evmhessfaRRR", + [1063] = "evmhossfaRRR", [1064] = "evmheumiaRRR", [1065] = "evmhesmiaRRR", + [1067] = "evmhesmfaRRR", [1068] = "evmhoumiaRRR", [1069] = "evmhosmiaRRR", + [1071] = "evmhosmfaRRR", [1095] = "evmwhssfRRR", [1096] = "evmwlumiRRR", + [1100] = "evmwhumiRRR", [1101] = "evmwhsmiRRR", [1103] = "evmwhsmfRRR", + [1107] = "evmwssfRRR", [1112] = "evmwumiRRR", [1113] = "evmwsmiRRR", + [1115] = "evmwsmfRRR", [1127] = "evmwhssfaRRR", [1128] = "evmwlumiaRRR", + [1132] = "evmwhumiaRRR", [1133] = "evmwhsmiaRRR", [1135] = "evmwhsmfaRRR", + [1139] = "evmwssfaRRR", [1144] = "evmwumiaRRR", [1145] = "evmwsmiaRRR", + [1147] = "evmwsmfaRRR", + + [1216] = "evaddusiaawRR", [1217] = "evaddssiaawRR", + [1218] = "evsubfusiaawRR", [1219] = "evsubfssiaawRR", + [1220] = "evmraRR", + [1222] = "evdivwsRRR", [1223] = "evdivwuRRR", + [1224] = "evaddumiaawRR", [1225] = "evaddsmiaawRR", + [1226] = "evsubfumiaawRR", [1227] = "evsubfsmiaawRR", + + [1280] = "evmheusiaawRRR", [1281] = "evmhessiaawRRR", + [1283] = "evmhessfaawRRR", [1284] = "evmhousiaawRRR", + [1285] = "evmhossiaawRRR", [1287] = "evmhossfaawRRR", + [1288] = "evmheumiaawRRR", [1289] = "evmhesmiaawRRR", + [1291] = "evmhesmfaawRRR", [1292] = "evmhoumiaawRRR", + [1293] = "evmhosmiaawRRR", [1295] = "evmhosmfaawRRR", + [1320] = "evmhegumiaaRRR", [1321] = "evmhegsmiaaRRR", + [1323] = "evmhegsmfaaRRR", [1324] = "evmhogumiaaRRR", + [1325] = "evmhogsmiaaRRR", [1327] = "evmhogsmfaaRRR", + [1344] = "evmwlusiaawRRR", [1345] = "evmwlssiaawRRR", + [1352] = "evmwlumiaawRRR", [1353] = "evmwlsmiaawRRR", + [1363] = "evmwssfaaRRR", [1368] = "evmwumiaaRRR", + [1369] = "evmwsmiaaRRR", [1371] = "evmwsmfaaRRR", + [1408] = "evmheusianwRRR", [1409] = "evmhessianwRRR", + [1411] = "evmhessfanwRRR", [1412] = "evmhousianwRRR", + [1413] = "evmhossianwRRR", [1415] = "evmhossfanwRRR", + [1416] = "evmheumianwRRR", [1417] = "evmhesmianwRRR", + [1419] = "evmhesmfanwRRR", [1420] = "evmhoumianwRRR", + [1421] = "evmhosmianwRRR", [1423] = "evmhosmfanwRRR", + [1448] = "evmhegumianRRR", [1449] = "evmhegsmianRRR", + [1451] = "evmhegsmfanRRR", [1452] = "evmhogumianRRR", + [1453] = "evmhogsmianRRR", [1455] = "evmhogsmfanRRR", + [1472] = "evmwlusianwRRR", [1473] = "evmwlssianwRRR", + [1480] = "evmwlumianwRRR", [1481] = "evmwlsmianwRRR", + [1491] = "evmwssfanRRR", [1496] = "evmwumianRRR", + [1497] = "evmwsmianRRR", [1499] = "evmwsmfanRRR", +} + +local map_pri = { + [0] = false, false, "tdiARI", "twiARI", + map_spe, false, false, "mulliRRI", + "subficRRI", false, "cmpl_iYLRU", "cmp_iYLRI", + "addicRRI", "addic.RRI", "addi|liRR0I", "addis|lisRR0I", + "b_KBJ", "sc", "bKJ", map_crops, + "rlwimiRR~AAA.", map_rlwinm, false, "rlwnmRR~RAA.", + "oriNRR~U", "orisRR~U", "xoriRR~U", "xorisRR~U", + "andi.RR~U", "andis.RR~U", map_rld, map_ext, + "lwzRRD", "lwzuRRD", "lbzRRD", "lbzuRRD", + "stwRRD", "stwuRRD", "stbRRD", "stbuRRD", + "lhzRRD", "lhzuRRD", "lhaRRD", "lhauRRD", + "sthRRD", "sthuRRD", "lmwRRD", "stmwRRD", + "lfsFRD", "lfsuFRD", "lfdFRD", "lfduFRD", + "stfsFRD", "stfsuFRD", "stfdFRD", "stfduFRD", + false, false, map_ld, map_fps, + false, false, map_std, map_fpd, +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "sp", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", +} + +local map_cond = { [0] = "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", } + +-- Format a condition bit. +local function condfmt(cond) + if cond <= 3 then + return map_cond[band(cond, 3)] + else + return format("4*cr%d+%s", rshift(cond, 2), map_cond[band(cond, 3)]) + end +end + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then extra = "\t->"..sym end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-7s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-7s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3) + local operands = {} + local last = nil + local rs = 21 + ctx.op = op + ctx.rel = nil + + local opat = map_pri[rshift(b0, 2)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] + end + local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.]*)(.*)") + if altname then pat = pat2 end + + for p in gmatch(pat, ".") do + local x = nil + if p == "R" then + x = map_gpr[band(rshift(op, rs), 31)] + rs = rs - 5 + elseif p == "F" then + x = "f"..band(rshift(op, rs), 31) + rs = rs - 5 + elseif p == "A" then + x = band(rshift(op, rs), 31) + rs = rs - 5 + elseif p == "S" then + x = arshift(lshift(op, 27-rs), 27) + rs = rs - 5 + elseif p == "I" then + x = arshift(lshift(op, 16), 16) + elseif p == "U" then + x = band(op, 0xffff) + elseif p == "D" or p == "E" then + local disp = arshift(lshift(op, 16), 16) + if p == "E" then disp = band(disp, -4) end + if last == "r0" then last = "0" end + operands[#operands] = format("%d(%s)", disp, last) + elseif p >= "2" and p <= "8" then + local disp = band(rshift(op, rs), 31) * p + if last == "r0" then last = "0" end + operands[#operands] = format("%d(%s)", disp, last) + elseif p == "H" then + x = band(rshift(op, rs), 31) + lshift(band(op, 2), 4) + rs = rs - 5 + elseif p == "M" then + x = band(rshift(op, rs), 31) + band(op, 0x20) + elseif p == "C" then + x = condfmt(band(rshift(op, rs), 31)) + rs = rs - 5 + elseif p == "B" then + local bo = rshift(op, 21) + local cond = band(rshift(op, 16), 31) + local cn = "" + rs = rs - 10 + if band(bo, 4) == 0 then + cn = band(bo, 2) == 0 and "dnz" or "dz" + if band(bo, 0x10) == 0 then + cn = cn..(band(bo, 8) == 0 and "f" or "t") + end + if band(bo, 0x10) == 0 then x = condfmt(cond) end + name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+") + elseif band(bo, 0x10) == 0 then + cn = map_cond[band(cond, 3) + (band(bo, 8) == 0 and 4 or 0)] + if cond > 3 then x = "cr"..rshift(cond, 2) end + name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+") + end + name = gsub(name, "_", cn) + elseif p == "J" then + x = arshift(lshift(op, 27-rs), 29-rs)*4 + if band(op, 2) == 0 then x = ctx.addr + pos + x end + ctx.rel = x + x = "0x"..tohex(x) + elseif p == "K" then + if band(op, 1) ~= 0 then name = name.."l" end + if band(op, 2) ~= 0 then name = name.."a" end + elseif p == "X" or p == "Y" then + x = band(rshift(op, rs+2), 7) + if x == 0 and p == "Y" then x = nil else x = "cr"..x end + rs = rs - 5 + elseif p == "W" then + x = "cr"..band(op, 7) + elseif p == "Z" then + x = band(rshift(op, rs-4), 255) + rs = rs - 10 + elseif p == ">" then + operands[#operands] = rshift(operands[#operands], 1) + elseif p == "0" then + if last == "r0" then + operands[#operands] = nil + if altname then name = altname end + end + elseif p == "L" then + name = gsub(name, "_", band(op, 0x00200000) ~= 0 and "d" or "w") + elseif p == "." then + if band(op, 1) == 1 then name = name.."." end + elseif p == "N" then + if op == 0x60000000 then name = "nop"; break end + elseif p == "~" then + local n = #operands + operands[n-1], operands[n] = operands[n], operands[n-1] + elseif p == "=" then + local n = #operands + if last == operands[n-1] then + operands[n] = nil + name = altname + end + elseif p == "%" then + local n = #operands + if last == operands[n-1] and last == operands[n-2] then + operands[n] = nil + operands[n-1] = nil + name = altname + end + elseif p == "-" then + rs = rs - 5 + else + assert(false) + end + if x then operands[#operands+1] = x; last = x end + end + + return putop(ctx, name, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + stop = stop - stop % 4 + ctx.pos = ofs - ofs % 4 + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_gpr[r] end + return "f"..(r-32) +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_x64.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_x64.lua new file mode 100644 index 00000000..2d37423e --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_x64.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT x64 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the 64 bit functions from the combined +-- x86/x64 disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_x86 = require((string.match(..., ".*%.") or "").."dis_x86") +return { + create = dis_x86.create64, + disass = dis_x86.disass64, + regname = dis_x86.regname64 +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_x86.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_x86.lua new file mode 100644 index 00000000..5480854c --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dis_x86.lua @@ -0,0 +1,953 @@ +---------------------------------------------------------------------------- +-- LuaJIT x86/x64 disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- Sending small code snippets to an external disassembler and mixing the +-- output with our own stuff was too fragile. So I had to bite the bullet +-- and write yet another x86 disassembler. Oh well ... +-- +-- The output format is very similar to what ndisasm generates. But it has +-- been developed independently by looking at the opcode tables from the +-- Intel and AMD manuals. The supported instruction set is quite extensive +-- and reflects what a current generation Intel or AMD CPU implements in +-- 32 bit and 64 bit mode. Yes, this includes MMX, SSE, SSE2, SSE3, SSSE3, +-- SSE4.1, SSE4.2, SSE4a, AVX, AVX2 and even privileged and hypervisor +-- (VMX/SVM) instructions. +-- +-- Notes: +-- * The (useless) a16 prefix, 3DNow and pre-586 opcodes are unsupported. +-- * No attempt at optimization has been made -- it's fast enough for my needs. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local lower, rep = string.lower, string.rep +local bit = require("bit") +local tohex = bit.tohex + +-- Map for 1st opcode byte in 32 bit mode. Ugly? Well ... read on. +local map_opc1_32 = { +--0x +[0]="addBmr","addVmr","addBrm","addVrm","addBai","addVai","push es","pop es", +"orBmr","orVmr","orBrm","orVrm","orBai","orVai","push cs","opc2*", +--1x +"adcBmr","adcVmr","adcBrm","adcVrm","adcBai","adcVai","push ss","pop ss", +"sbbBmr","sbbVmr","sbbBrm","sbbVrm","sbbBai","sbbVai","push ds","pop ds", +--2x +"andBmr","andVmr","andBrm","andVrm","andBai","andVai","es:seg","daa", +"subBmr","subVmr","subBrm","subVrm","subBai","subVai","cs:seg","das", +--3x +"xorBmr","xorVmr","xorBrm","xorVrm","xorBai","xorVai","ss:seg","aaa", +"cmpBmr","cmpVmr","cmpBrm","cmpVrm","cmpBai","cmpVai","ds:seg","aas", +--4x +"incVR","incVR","incVR","incVR","incVR","incVR","incVR","incVR", +"decVR","decVR","decVR","decVR","decVR","decVR","decVR","decVR", +--5x +"pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR", +"popUR","popUR","popUR","popUR","popUR","popUR","popUR","popUR", +--6x +"sz*pushaw,pusha","sz*popaw,popa","boundVrm","arplWmr", +"fs:seg","gs:seg","o16:","a16", +"pushUi","imulVrmi","pushBs","imulVrms", +"insb","insVS","outsb","outsVS", +--7x +"joBj","jnoBj","jbBj","jnbBj","jzBj","jnzBj","jbeBj","jaBj", +"jsBj","jnsBj","jpeBj","jpoBj","jlBj","jgeBj","jleBj","jgBj", +--8x +"arith!Bmi","arith!Vmi","arith!Bmi","arith!Vms", +"testBmr","testVmr","xchgBrm","xchgVrm", +"movBmr","movVmr","movBrm","movVrm", +"movVmg","leaVrm","movWgm","popUm", +--9x +"nop*xchgVaR|pause|xchgWaR|repne nop","xchgVaR","xchgVaR","xchgVaR", +"xchgVaR","xchgVaR","xchgVaR","xchgVaR", +"sz*cbw,cwde,cdqe","sz*cwd,cdq,cqo","call farViw","wait", +"sz*pushfw,pushf","sz*popfw,popf","sahf","lahf", +--Ax +"movBao","movVao","movBoa","movVoa", +"movsb","movsVS","cmpsb","cmpsVS", +"testBai","testVai","stosb","stosVS", +"lodsb","lodsVS","scasb","scasVS", +--Bx +"movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi", +"movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI", +--Cx +"shift!Bmu","shift!Vmu","retBw","ret","vex*3$lesVrm","vex*2$ldsVrm","movBmi","movVmi", +"enterBwu","leave","retfBw","retf","int3","intBu","into","iretVS", +--Dx +"shift!Bm1","shift!Vm1","shift!Bmc","shift!Vmc","aamBu","aadBu","salc","xlatb", +"fp*0","fp*1","fp*2","fp*3","fp*4","fp*5","fp*6","fp*7", +--Ex +"loopneBj","loopeBj","loopBj","sz*jcxzBj,jecxzBj,jrcxzBj", +"inBau","inVau","outBua","outVua", +"callVj","jmpVj","jmp farViw","jmpBj","inBad","inVad","outBda","outVda", +--Fx +"lock:","int1","repne:rep","rep:","hlt","cmc","testb!Bm","testv!Vm", +"clc","stc","cli","sti","cld","std","incb!Bm","incd!Vm", +} +assert(#map_opc1_32 == 255) + +-- Map for 1st opcode byte in 64 bit mode (overrides only). +local map_opc1_64 = setmetatable({ + [0x06]=false, [0x07]=false, [0x0e]=false, + [0x16]=false, [0x17]=false, [0x1e]=false, [0x1f]=false, + [0x27]=false, [0x2f]=false, [0x37]=false, [0x3f]=false, + [0x60]=false, [0x61]=false, [0x62]=false, [0x63]="movsxdVrDmt", [0x67]="a32:", + [0x40]="rex*", [0x41]="rex*b", [0x42]="rex*x", [0x43]="rex*xb", + [0x44]="rex*r", [0x45]="rex*rb", [0x46]="rex*rx", [0x47]="rex*rxb", + [0x48]="rex*w", [0x49]="rex*wb", [0x4a]="rex*wx", [0x4b]="rex*wxb", + [0x4c]="rex*wr", [0x4d]="rex*wrb", [0x4e]="rex*wrx", [0x4f]="rex*wrxb", + [0x82]=false, [0x9a]=false, [0xc4]="vex*3", [0xc5]="vex*2", [0xce]=false, + [0xd4]=false, [0xd5]=false, [0xd6]=false, [0xea]=false, +}, { __index = map_opc1_32 }) + +-- Map for 2nd opcode byte (0F xx). True CISC hell. Hey, I told you. +-- Prefix dependent MMX/SSE opcodes: (none)|rep|o16|repne, -|F3|66|F2 +local map_opc2 = { +--0x +[0]="sldt!Dmp","sgdt!Ump","larVrm","lslVrm",nil,"syscall","clts","sysret", +"invd","wbinvd",nil,"ud1",nil,"$prefetch!Bm","femms","3dnowMrmu", +--1x +"movupsXrm|movssXrvm|movupdXrm|movsdXrvm", +"movupsXmr|movssXmvr|movupdXmr|movsdXmvr", +"movhlpsXrm$movlpsXrm|movsldupXrm|movlpdXrm|movddupXrm", +"movlpsXmr||movlpdXmr", +"unpcklpsXrvm||unpcklpdXrvm", +"unpckhpsXrvm||unpckhpdXrvm", +"movlhpsXrm$movhpsXrm|movshdupXrm|movhpdXrm", +"movhpsXmr||movhpdXmr", +"$prefetcht!Bm","hintnopVm","hintnopVm","hintnopVm", +"hintnopVm","hintnopVm","hintnopVm","hintnopVm", +--2x +"movUmx$","movUmy$","movUxm$","movUym$","movUmz$",nil,"movUzm$",nil, +"movapsXrm||movapdXrm", +"movapsXmr||movapdXmr", +"cvtpi2psXrMm|cvtsi2ssXrvVmt|cvtpi2pdXrMm|cvtsi2sdXrvVmt", +"movntpsXmr|movntssXmr|movntpdXmr|movntsdXmr", +"cvttps2piMrXm|cvttss2siVrXm|cvttpd2piMrXm|cvttsd2siVrXm", +"cvtps2piMrXm|cvtss2siVrXm|cvtpd2piMrXm|cvtsd2siVrXm", +"ucomissXrm||ucomisdXrm", +"comissXrm||comisdXrm", +--3x +"wrmsr","rdtsc","rdmsr","rdpmc","sysenter","sysexit",nil,"getsec", +"opc3*38",nil,"opc3*3a",nil,nil,nil,nil,nil, +--4x +"cmovoVrm","cmovnoVrm","cmovbVrm","cmovnbVrm", +"cmovzVrm","cmovnzVrm","cmovbeVrm","cmovaVrm", +"cmovsVrm","cmovnsVrm","cmovpeVrm","cmovpoVrm", +"cmovlVrm","cmovgeVrm","cmovleVrm","cmovgVrm", +--5x +"movmskpsVrXm$||movmskpdVrXm$","sqrtpsXrm|sqrtssXrm|sqrtpdXrm|sqrtsdXrm", +"rsqrtpsXrm|rsqrtssXrvm","rcppsXrm|rcpssXrvm", +"andpsXrvm||andpdXrvm","andnpsXrvm||andnpdXrvm", +"orpsXrvm||orpdXrvm","xorpsXrvm||xorpdXrvm", +"addpsXrvm|addssXrvm|addpdXrvm|addsdXrvm","mulpsXrvm|mulssXrvm|mulpdXrvm|mulsdXrvm", +"cvtps2pdXrm|cvtss2sdXrvm|cvtpd2psXrm|cvtsd2ssXrvm", +"cvtdq2psXrm|cvttps2dqXrm|cvtps2dqXrm", +"subpsXrvm|subssXrvm|subpdXrvm|subsdXrvm","minpsXrvm|minssXrvm|minpdXrvm|minsdXrvm", +"divpsXrvm|divssXrvm|divpdXrvm|divsdXrvm","maxpsXrvm|maxssXrvm|maxpdXrvm|maxsdXrvm", +--6x +"punpcklbwPrvm","punpcklwdPrvm","punpckldqPrvm","packsswbPrvm", +"pcmpgtbPrvm","pcmpgtwPrvm","pcmpgtdPrvm","packuswbPrvm", +"punpckhbwPrvm","punpckhwdPrvm","punpckhdqPrvm","packssdwPrvm", +"||punpcklqdqXrvm","||punpckhqdqXrvm", +"movPrVSm","movqMrm|movdquXrm|movdqaXrm", +--7x +"pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pvmu", +"pshiftd!Pvmu","pshiftq!Mvmu||pshiftdq!Xvmu", +"pcmpeqbPrvm","pcmpeqwPrvm","pcmpeqdPrvm","emms*|", +"vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$", +nil,nil, +"||haddpdXrvm|haddpsXrvm","||hsubpdXrvm|hsubpsXrvm", +"movVSmMr|movqXrm|movVSmXr","movqMmr|movdquXmr|movdqaXmr", +--8x +"joVj","jnoVj","jbVj","jnbVj","jzVj","jnzVj","jbeVj","jaVj", +"jsVj","jnsVj","jpeVj","jpoVj","jlVj","jgeVj","jleVj","jgVj", +--9x +"setoBm","setnoBm","setbBm","setnbBm","setzBm","setnzBm","setbeBm","setaBm", +"setsBm","setnsBm","setpeBm","setpoBm","setlBm","setgeBm","setleBm","setgBm", +--Ax +"push fs","pop fs","cpuid","btVmr","shldVmru","shldVmrc",nil,nil, +"push gs","pop gs","rsm","btsVmr","shrdVmru","shrdVmrc","fxsave!Dmp","imulVrm", +--Bx +"cmpxchgBmr","cmpxchgVmr","$lssVrm","btrVmr", +"$lfsVrm","$lgsVrm","movzxVrBmt","movzxVrWmt", +"|popcntVrm","ud2Dp","bt!Vmu","btcVmr", +"bsfVrm","bsrVrm|lzcntVrm|bsrWrm","movsxVrBmt","movsxVrWmt", +--Cx +"xaddBmr","xaddVmr", +"cmppsXrvmu|cmpssXrvmu|cmppdXrvmu|cmpsdXrvmu","$movntiVmr|", +"pinsrwPrvWmu","pextrwDrPmu", +"shufpsXrvmu||shufpdXrvmu","$cmpxchg!Qmp", +"bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR", +--Dx +"||addsubpdXrvm|addsubpsXrvm","psrlwPrvm","psrldPrvm","psrlqPrvm", +"paddqPrvm","pmullwPrvm", +"|movq2dqXrMm|movqXmr|movdq2qMrXm$","pmovmskbVrMm||pmovmskbVrXm", +"psubusbPrvm","psubuswPrvm","pminubPrvm","pandPrvm", +"paddusbPrvm","padduswPrvm","pmaxubPrvm","pandnPrvm", +--Ex +"pavgbPrvm","psrawPrvm","psradPrvm","pavgwPrvm", +"pmulhuwPrvm","pmulhwPrvm", +"|cvtdq2pdXrm|cvttpd2dqXrm|cvtpd2dqXrm","$movntqMmr||$movntdqXmr", +"psubsbPrvm","psubswPrvm","pminswPrvm","porPrvm", +"paddsbPrvm","paddswPrvm","pmaxswPrvm","pxorPrvm", +--Fx +"|||lddquXrm","psllwPrvm","pslldPrvm","psllqPrvm", +"pmuludqPrvm","pmaddwdPrvm","psadbwPrvm","maskmovqMrm||maskmovdquXrm$", +"psubbPrvm","psubwPrvm","psubdPrvm","psubqPrvm", +"paddbPrvm","paddwPrvm","padddPrvm","ud", +} +assert(map_opc2[255] == "ud") + +-- Map for three-byte opcodes. Can't wait for their next invention. +local map_opc3 = { +["38"] = { -- [66] 0f 38 xx +--0x +[0]="pshufbPrvm","phaddwPrvm","phadddPrvm","phaddswPrvm", +"pmaddubswPrvm","phsubwPrvm","phsubdPrvm","phsubswPrvm", +"psignbPrvm","psignwPrvm","psigndPrvm","pmulhrswPrvm", +"||permilpsXrvm","||permilpdXrvm",nil,nil, +--1x +"||pblendvbXrma",nil,nil,nil, +"||blendvpsXrma","||blendvpdXrma","||permpsXrvm","||ptestXrm", +"||broadcastssXrm","||broadcastsdXrm","||broadcastf128XrlXm",nil, +"pabsbPrm","pabswPrm","pabsdPrm",nil, +--2x +"||pmovsxbwXrm","||pmovsxbdXrm","||pmovsxbqXrm","||pmovsxwdXrm", +"||pmovsxwqXrm","||pmovsxdqXrm",nil,nil, +"||pmuldqXrvm","||pcmpeqqXrvm","||$movntdqaXrm","||packusdwXrvm", +"||maskmovpsXrvm","||maskmovpdXrvm","||maskmovpsXmvr","||maskmovpdXmvr", +--3x +"||pmovzxbwXrm","||pmovzxbdXrm","||pmovzxbqXrm","||pmovzxwdXrm", +"||pmovzxwqXrm","||pmovzxdqXrm","||permdXrvm","||pcmpgtqXrvm", +"||pminsbXrvm","||pminsdXrvm","||pminuwXrvm","||pminudXrvm", +"||pmaxsbXrvm","||pmaxsdXrvm","||pmaxuwXrvm","||pmaxudXrvm", +--4x +"||pmulddXrvm","||phminposuwXrm",nil,nil, +nil,"||psrlvVSXrvm","||psravdXrvm","||psllvVSXrvm", +--5x +[0x58] = "||pbroadcastdXrlXm",[0x59] = "||pbroadcastqXrlXm", +[0x5a] = "||broadcasti128XrlXm", +--7x +[0x78] = "||pbroadcastbXrlXm",[0x79] = "||pbroadcastwXrlXm", +--8x +[0x8c] = "||pmaskmovXrvVSm", +[0x8e] = "||pmaskmovVSmXvr", +--9x +[0x96] = "||fmaddsub132pHXrvm",[0x97] = "||fmsubadd132pHXrvm", +[0x98] = "||fmadd132pHXrvm",[0x99] = "||fmadd132sHXrvm", +[0x9a] = "||fmsub132pHXrvm",[0x9b] = "||fmsub132sHXrvm", +[0x9c] = "||fnmadd132pHXrvm",[0x9d] = "||fnmadd132sHXrvm", +[0x9e] = "||fnmsub132pHXrvm",[0x9f] = "||fnmsub132sHXrvm", +--Ax +[0xa6] = "||fmaddsub213pHXrvm",[0xa7] = "||fmsubadd213pHXrvm", +[0xa8] = "||fmadd213pHXrvm",[0xa9] = "||fmadd213sHXrvm", +[0xaa] = "||fmsub213pHXrvm",[0xab] = "||fmsub213sHXrvm", +[0xac] = "||fnmadd213pHXrvm",[0xad] = "||fnmadd213sHXrvm", +[0xae] = "||fnmsub213pHXrvm",[0xaf] = "||fnmsub213sHXrvm", +--Bx +[0xb6] = "||fmaddsub231pHXrvm",[0xb7] = "||fmsubadd231pHXrvm", +[0xb8] = "||fmadd231pHXrvm",[0xb9] = "||fmadd231sHXrvm", +[0xba] = "||fmsub231pHXrvm",[0xbb] = "||fmsub231sHXrvm", +[0xbc] = "||fnmadd231pHXrvm",[0xbd] = "||fnmadd231sHXrvm", +[0xbe] = "||fnmsub231pHXrvm",[0xbf] = "||fnmsub231sHXrvm", +--Dx +[0xdc] = "||aesencXrvm", [0xdd] = "||aesenclastXrvm", +[0xde] = "||aesdecXrvm", [0xdf] = "||aesdeclastXrvm", +--Fx +[0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt", +[0xf7] = "| sarxVrmv| shlxVrmv| shrxVrmv", +}, + +["3a"] = { -- [66] 0f 3a xx +--0x +[0x00]="||permqXrmu","||permpdXrmu","||pblenddXrvmu",nil, +"||permilpsXrmu","||permilpdXrmu","||perm2f128Xrvmu",nil, +"||roundpsXrmu","||roundpdXrmu","||roundssXrvmu","||roundsdXrvmu", +"||blendpsXrvmu","||blendpdXrvmu","||pblendwXrvmu","palignrPrvmu", +--1x +nil,nil,nil,nil, +"||pextrbVmXru","||pextrwVmXru","||pextrVmSXru","||extractpsVmXru", +"||insertf128XrvlXmu","||extractf128XlXmYru",nil,nil, +nil,nil,nil,nil, +--2x +"||pinsrbXrvVmu","||insertpsXrvmu","||pinsrXrvVmuS",nil, +--3x +[0x38] = "||inserti128Xrvmu",[0x39] = "||extracti128XlXmYru", +--4x +[0x40] = "||dppsXrvmu", +[0x41] = "||dppdXrvmu", +[0x42] = "||mpsadbwXrvmu", +[0x44] = "||pclmulqdqXrvmu", +[0x46] = "||perm2i128Xrvmu", +[0x4a] = "||blendvpsXrvmb",[0x4b] = "||blendvpdXrvmb", +[0x4c] = "||pblendvbXrvmb", +--6x +[0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu", +[0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu", +[0xdf] = "||aeskeygenassistXrmu", +--Fx +[0xf0] = "||| rorxVrmu", +}, +} + +-- Map for VMX/SVM opcodes 0F 01 C0-FF (sgdt group with register operands). +local map_opcvm = { +[0xc1]="vmcall",[0xc2]="vmlaunch",[0xc3]="vmresume",[0xc4]="vmxoff", +[0xc8]="monitor",[0xc9]="mwait", +[0xd8]="vmrun",[0xd9]="vmmcall",[0xda]="vmload",[0xdb]="vmsave", +[0xdc]="stgi",[0xdd]="clgi",[0xde]="skinit",[0xdf]="invlpga", +[0xf8]="swapgs",[0xf9]="rdtscp", +} + +-- Map for FP opcodes. And you thought stack machines are simple? +local map_opcfp = { +-- D8-DF 00-BF: opcodes with a memory operand. +-- D8 +[0]="faddFm","fmulFm","fcomFm","fcompFm","fsubFm","fsubrFm","fdivFm","fdivrFm", +"fldFm",nil,"fstFm","fstpFm","fldenvVm","fldcwWm","fnstenvVm","fnstcwWm", +-- DA +"fiaddDm","fimulDm","ficomDm","ficompDm", +"fisubDm","fisubrDm","fidivDm","fidivrDm", +-- DB +"fildDm","fisttpDm","fistDm","fistpDm",nil,"fld twordFmp",nil,"fstp twordFmp", +-- DC +"faddGm","fmulGm","fcomGm","fcompGm","fsubGm","fsubrGm","fdivGm","fdivrGm", +-- DD +"fldGm","fisttpQm","fstGm","fstpGm","frstorDmp",nil,"fnsaveDmp","fnstswWm", +-- DE +"fiaddWm","fimulWm","ficomWm","ficompWm", +"fisubWm","fisubrWm","fidivWm","fidivrWm", +-- DF +"fildWm","fisttpWm","fistWm","fistpWm", +"fbld twordFmp","fildQm","fbstp twordFmp","fistpQm", +-- xx C0-FF: opcodes with a pseudo-register operand. +-- D8 +"faddFf","fmulFf","fcomFf","fcompFf","fsubFf","fsubrFf","fdivFf","fdivrFf", +-- D9 +"fldFf","fxchFf",{"fnop"},nil, +{"fchs","fabs",nil,nil,"ftst","fxam"}, +{"fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz"}, +{"f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp"}, +{"fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"}, +-- DA +"fcmovbFf","fcmoveFf","fcmovbeFf","fcmovuFf",nil,{nil,"fucompp"},nil,nil, +-- DB +"fcmovnbFf","fcmovneFf","fcmovnbeFf","fcmovnuFf", +{nil,nil,"fnclex","fninit"},"fucomiFf","fcomiFf",nil, +-- DC +"fadd toFf","fmul toFf",nil,nil, +"fsub toFf","fsubr toFf","fdivr toFf","fdiv toFf", +-- DD +"ffreeFf",nil,"fstFf","fstpFf","fucomFf","fucompFf",nil,nil, +-- DE +"faddpFf","fmulpFf",nil,{nil,"fcompp"}, +"fsubrpFf","fsubpFf","fdivrpFf","fdivpFf", +-- DF +nil,nil,nil,nil,{"fnstsw ax"},"fucomipFf","fcomipFf",nil, +} +assert(map_opcfp[126] == "fcomipFf") + +-- Map for opcode groups. The subkey is sp from the ModRM byte. +local map_opcgroup = { + arith = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" }, + shift = { "rol", "ror", "rcl", "rcr", "shl", "shr", "sal", "sar" }, + testb = { "testBmi", "testBmi", "not", "neg", "mul", "imul", "div", "idiv" }, + testv = { "testVmi", "testVmi", "not", "neg", "mul", "imul", "div", "idiv" }, + incb = { "inc", "dec" }, + incd = { "inc", "dec", "callUmp", "$call farDmp", + "jmpUmp", "$jmp farDmp", "pushUm" }, + sldt = { "sldt", "str", "lldt", "ltr", "verr", "verw" }, + sgdt = { "vm*$sgdt", "vm*$sidt", "$lgdt", "vm*$lidt", + "smsw", nil, "lmsw", "vm*$invlpg" }, + bt = { nil, nil, nil, nil, "bt", "bts", "btr", "btc" }, + cmpxchg = { nil, "sz*,cmpxchg8bQmp,cmpxchg16bXmp", nil, nil, + nil, nil, "vmptrld|vmxon|vmclear", "vmptrst" }, + pshiftw = { nil, nil, "psrlw", nil, "psraw", nil, "psllw" }, + pshiftd = { nil, nil, "psrld", nil, "psrad", nil, "pslld" }, + pshiftq = { nil, nil, "psrlq", nil, nil, nil, "psllq" }, + pshiftdq = { nil, nil, "psrlq", "psrldq", nil, nil, "psllq", "pslldq" }, + fxsave = { "$fxsave", "$fxrstor", "$ldmxcsr", "$stmxcsr", + nil, "lfenceDp$", "mfenceDp$", "sfenceDp$clflush" }, + prefetch = { "prefetch", "prefetchw" }, + prefetcht = { "prefetchnta", "prefetcht0", "prefetcht1", "prefetcht2" }, +} + +------------------------------------------------------------------------------ + +-- Maps for register names. +local map_regs = { + B = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + B64 = { "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + W = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }, + D = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }, + Q = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }, + M = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", + "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, -- No x64 ext! + X = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" }, + Y = { "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15" }, +} +local map_segregs = { "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7" } + +-- Maps for size names. +local map_sz2n = { + B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16, Y = 32, +} +local map_sz2prefix = { + B = "byte", W = "word", D = "dword", + Q = "qword", + M = "qword", X = "xword", Y = "yword", + F = "dword", G = "qword", -- No need for sizes/register names for these two. +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local code, pos, hex = ctx.code, ctx.pos, "" + local hmax = ctx.hexdump + if hmax > 0 then + for i=ctx.start,pos-1 do + hex = hex..format("%02X", byte(code, i, i)) + end + if #hex > hmax then hex = sub(hex, 1, hmax)..". " + else hex = hex..rep(" ", hmax-#hex+2) end + end + if operands then text = text.." "..operands end + if ctx.o16 then text = "o16 "..text; ctx.o16 = false end + if ctx.a32 then text = "a32 "..text; ctx.a32 = false end + if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end + if ctx.rex then + local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "").. + (ctx.rexx and "x" or "")..(ctx.rexb and "b" or "").. + (ctx.vexl and "l" or "") + if ctx.vexv and ctx.vexv ~= 0 then t = t.."v"..ctx.vexv end + if t ~= "" then text = ctx.rex.."."..t.." "..gsub(text, "^ ", "") + elseif ctx.rex == "vex" then text = gsub("v"..text, "^v ", "") end + ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false + ctx.rex = false; ctx.vexl = false; ctx.vexv = false + end + if ctx.seg then + local text2, n = gsub(text, "%[", "["..ctx.seg..":") + if n == 0 then text = ctx.seg.." "..text else text = text2 end + ctx.seg = false + end + if ctx.lock then text = "lock "..text; ctx.lock = false end + local imm = ctx.imm + if imm then + local sym = ctx.symtab[imm] + if sym then text = text.."\t->"..sym end + end + ctx.out(format("%08x %s%s\n", ctx.addr+ctx.start, hex, text)) + ctx.mrm = false + ctx.vexv = false + ctx.start = pos + ctx.imm = nil +end + +-- Clear all prefix flags. +local function clearprefixes(ctx) + ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false + ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false + ctx.rex = false; ctx.a32 = false; ctx.vexl = false +end + +-- Fallback for incomplete opcodes at the end. +local function incomplete(ctx) + ctx.pos = ctx.stop+1 + clearprefixes(ctx) + return putop(ctx, "(incomplete)") +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + clearprefixes(ctx) + return putop(ctx, "(unknown)") +end + +-- Return an immediate of the specified size. +local function getimm(ctx, pos, n) + if pos+n-1 > ctx.stop then return incomplete(ctx) end + local code = ctx.code + if n == 1 then + local b1 = byte(code, pos, pos) + return b1 + elseif n == 2 then + local b1, b2 = byte(code, pos, pos+1) + return b1+b2*256 + else + local b1, b2, b3, b4 = byte(code, pos, pos+3) + local imm = b1+b2*256+b3*65536+b4*16777216 + ctx.imm = imm + return imm + end +end + +-- Process pattern string and generate the operands. +local function putpat(ctx, name, pat) + local operands, regs, sz, mode, sp, rm, sc, rx, sdisp + local code, pos, stop, vexl = ctx.code, ctx.pos, ctx.stop, ctx.vexl + + -- Chars used: 1DFGHIMPQRSTUVWXYabcdfgijlmoprstuvwxyz + for p in gmatch(pat, ".") do + local x = nil + if p == "V" or p == "U" then + if ctx.rexw then sz = "Q"; ctx.rexw = false + elseif ctx.o16 then sz = "W"; ctx.o16 = false + elseif p == "U" and ctx.x64 then sz = "Q" + else sz = "D" end + regs = map_regs[sz] + elseif p == "T" then + if ctx.rexw then sz = "Q"; ctx.rexw = false else sz = "D" end + regs = map_regs[sz] + elseif p == "B" then + sz = "B" + regs = ctx.rex and map_regs.B64 or map_regs.B + elseif match(p, "[WDQMXYFG]") then + sz = p + if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end + regs = map_regs[sz] + elseif p == "P" then + sz = ctx.o16 and "X" or "M"; ctx.o16 = false + if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end + regs = map_regs[sz] + elseif p == "H" then + name = name..(ctx.rexw and "d" or "s") + ctx.rexw = false + elseif p == "S" then + name = name..lower(sz) + elseif p == "s" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = imm <= 127 and format("+0x%02x", imm) + or format("-0x%02x", 256-imm) + pos = pos+1 + elseif p == "u" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = format("0x%02x", imm) + pos = pos+1 + elseif p == "b" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = regs[imm/16+1] + pos = pos+1 + elseif p == "w" then + local imm = getimm(ctx, pos, 2); if not imm then return end + x = format("0x%x", imm) + pos = pos+2 + elseif p == "o" then -- [offset] + if ctx.x64 then + local imm1 = getimm(ctx, pos, 4); if not imm1 then return end + local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end + x = format("[0x%08x%08x]", imm2, imm1) + pos = pos+8 + else + local imm = getimm(ctx, pos, 4); if not imm then return end + x = format("[0x%08x]", imm) + pos = pos+4 + end + elseif p == "i" or p == "I" then + local n = map_sz2n[sz] + if n == 8 and ctx.x64 and p == "I" then + local imm1 = getimm(ctx, pos, 4); if not imm1 then return end + local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end + x = format("0x%08x%08x", imm2, imm1) + else + if n == 8 then n = 4 end + local imm = getimm(ctx, pos, n); if not imm then return end + if sz == "Q" and (imm < 0 or imm > 0x7fffffff) then + imm = (0xffffffff+1)-imm + x = format(imm > 65535 and "-0x%08x" or "-0x%x", imm) + else + x = format(imm > 65535 and "0x%08x" or "0x%x", imm) + end + end + pos = pos+n + elseif p == "j" then + local n = map_sz2n[sz] + if n == 8 then n = 4 end + local imm = getimm(ctx, pos, n); if not imm then return end + if sz == "B" and imm > 127 then imm = imm-256 + elseif imm > 2147483647 then imm = imm-4294967296 end + pos = pos+n + imm = imm + pos + ctx.addr + if imm > 4294967295 and not ctx.x64 then imm = imm-4294967296 end + ctx.imm = imm + if sz == "W" then + x = format("word 0x%04x", imm%65536) + elseif ctx.x64 then + local lo = imm % 0x1000000 + x = format("0x%02x%06x", (imm-lo) / 0x1000000, lo) + else + x = "0x"..tohex(imm) + end + elseif p == "R" then + local r = byte(code, pos-1, pos-1)%8 + if ctx.rexb then r = r + 8; ctx.rexb = false end + x = regs[r+1] + elseif p == "a" then x = regs[1] + elseif p == "c" then x = "cl" + elseif p == "d" then x = "dx" + elseif p == "1" then x = "1" + else + if not mode then + mode = ctx.mrm + if not mode then + if pos > stop then return incomplete(ctx) end + mode = byte(code, pos, pos) + pos = pos+1 + end + rm = mode%8; mode = (mode-rm)/8 + sp = mode%8; mode = (mode-sp)/8 + sdisp = "" + if mode < 3 then + if rm == 4 then + if pos > stop then return incomplete(ctx) end + sc = byte(code, pos, pos) + pos = pos+1 + rm = sc%8; sc = (sc-rm)/8 + rx = sc%8; sc = (sc-rx)/8 + if ctx.rexx then rx = rx + 8; ctx.rexx = false end + if rx == 4 then rx = nil end + end + if mode > 0 or rm == 5 then + local dsz = mode + if dsz ~= 1 then dsz = 4 end + local disp = getimm(ctx, pos, dsz); if not disp then return end + if mode == 0 then rm = nil end + if rm or rx or (not sc and ctx.x64 and not ctx.a32) then + if dsz == 1 and disp > 127 then + sdisp = format("-0x%x", 256-disp) + elseif disp >= 0 and disp <= 0x7fffffff then + sdisp = format("+0x%x", disp) + else + sdisp = format("-0x%x", (0xffffffff+1)-disp) + end + else + sdisp = format(ctx.x64 and not ctx.a32 and + not (disp >= 0 and disp <= 0x7fffffff) + and "0xffffffff%08x" or "0x%08x", disp) + end + pos = pos+dsz + end + end + if rm and ctx.rexb then rm = rm + 8; ctx.rexb = false end + if ctx.rexr then sp = sp + 8; ctx.rexr = false end + end + if p == "m" then + if mode == 3 then x = regs[rm+1] + else + local aregs = ctx.a32 and map_regs.D or ctx.aregs + local srm, srx = "", "" + if rm then srm = aregs[rm+1] + elseif not sc and ctx.x64 and not ctx.a32 then srm = "rip" end + ctx.a32 = false + if rx then + if rm then srm = srm.."+" end + srx = aregs[rx+1] + if sc > 0 then srx = srx.."*"..(2^sc) end + end + x = format("[%s%s%s]", srm, srx, sdisp) + end + if mode < 3 and + (not match(pat, "[aRrgp]") or match(pat, "t")) then -- Yuck. + x = map_sz2prefix[sz].." "..x + end + elseif p == "r" then x = regs[sp+1] + elseif p == "g" then x = map_segregs[sp+1] + elseif p == "p" then -- Suppress prefix. + elseif p == "f" then x = "st"..rm + elseif p == "x" then + if sp == 0 and ctx.lock and not ctx.x64 then + x = "CR8"; ctx.lock = false + else + x = "CR"..sp + end + elseif p == "v" then + if ctx.vexv then + x = regs[ctx.vexv+1]; ctx.vexv = false + end + elseif p == "y" then x = "DR"..sp + elseif p == "z" then x = "TR"..sp + elseif p == "l" then vexl = false + elseif p == "t" then + else + error("bad pattern `"..pat.."'") + end + end + if x then operands = operands and operands..", "..x or x end + end + ctx.pos = pos + return putop(ctx, name, operands) +end + +-- Forward declaration. +local map_act + +-- Fetch and cache MRM byte. +local function getmrm(ctx) + local mrm = ctx.mrm + if not mrm then + local pos = ctx.pos + if pos > ctx.stop then return nil end + mrm = byte(ctx.code, pos, pos) + ctx.pos = pos+1 + ctx.mrm = mrm + end + return mrm +end + +-- Dispatch to handler depending on pattern. +local function dispatch(ctx, opat, patgrp) + if not opat then return unknown(ctx) end + if match(opat, "%|") then -- MMX/SSE variants depending on prefix. + local p + if ctx.rep then + p = ctx.rep=="rep" and "%|([^%|]*)" or "%|[^%|]*%|[^%|]*%|([^%|]*)" + ctx.rep = false + elseif ctx.o16 then p = "%|[^%|]*%|([^%|]*)"; ctx.o16 = false + else p = "^[^%|]*" end + opat = match(opat, p) + if not opat then return unknown(ctx) end +-- ctx.rep = false; ctx.o16 = false + --XXX fails for 66 f2 0f 38 f1 06 crc32 eax,WORD PTR [esi] + --XXX remove in branches? + end + if match(opat, "%$") then -- reg$mem variants. + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + opat = match(opat, mrm >= 192 and "^[^%$]*" or "%$(.*)") + if opat == "" then return unknown(ctx) end + end + if opat == "" then return unknown(ctx) end + local name, pat = match(opat, "^([a-z0-9 ]*)(.*)") + if pat == "" and patgrp then pat = patgrp end + return map_act[sub(pat, 1, 1)](ctx, name, pat) +end + +-- Get a pattern from an opcode map and dispatch to handler. +local function dispatchmap(ctx, opcmap) + local pos = ctx.pos + local opat = opcmap[byte(ctx.code, pos, pos)] + pos = pos + 1 + ctx.pos = pos + return dispatch(ctx, opat) +end + +-- Map for action codes. The key is the first char after the name. +map_act = { + -- Simple opcodes without operands. + [""] = function(ctx, name, pat) + return putop(ctx, name) + end, + + -- Operand size chars fall right through. + B = putpat, W = putpat, D = putpat, Q = putpat, + V = putpat, U = putpat, T = putpat, + M = putpat, X = putpat, P = putpat, + F = putpat, G = putpat, Y = putpat, + H = putpat, + + -- Collect prefixes. + [":"] = function(ctx, name, pat) + ctx[pat == ":" and name or sub(pat, 2)] = name + if ctx.pos - ctx.start > 5 then return unknown(ctx) end -- Limit #prefixes. + end, + + -- Chain to special handler specified by name. + ["*"] = function(ctx, name, pat) + return map_act[name](ctx, name, sub(pat, 2)) + end, + + -- Use named subtable for opcode group. + ["!"] = function(ctx, name, pat) + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + return dispatch(ctx, map_opcgroup[name][((mrm-(mrm%8))/8)%8+1], sub(pat, 2)) + end, + + -- o16,o32[,o64] variants. + sz = function(ctx, name, pat) + if ctx.o16 then ctx.o16 = false + else + pat = match(pat, ",(.*)") + if ctx.rexw then + local p = match(pat, ",(.*)") + if p then pat = p; ctx.rexw = false end + end + end + pat = match(pat, "^[^,]*") + return dispatch(ctx, pat) + end, + + -- Two-byte opcode dispatch. + opc2 = function(ctx, name, pat) + return dispatchmap(ctx, map_opc2) + end, + + -- Three-byte opcode dispatch. + opc3 = function(ctx, name, pat) + return dispatchmap(ctx, map_opc3[pat]) + end, + + -- VMX/SVM dispatch. + vm = function(ctx, name, pat) + return dispatch(ctx, map_opcvm[ctx.mrm]) + end, + + -- Floating point opcode dispatch. + fp = function(ctx, name, pat) + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + local rm = mrm%8 + local idx = pat*8 + ((mrm-rm)/8)%8 + if mrm >= 192 then idx = idx + 64 end + local opat = map_opcfp[idx] + if type(opat) == "table" then opat = opat[rm+1] end + return dispatch(ctx, opat) + end, + + -- REX prefix. + rex = function(ctx, name, pat) + if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. + for p in gmatch(pat, ".") do ctx["rex"..p] = true end + ctx.rex = "rex" + end, + + -- VEX prefix. + vex = function(ctx, name, pat) + if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. + ctx.rex = "vex" + local pos = ctx.pos + if ctx.mrm then + ctx.mrm = nil + pos = pos-1 + end + local b = byte(ctx.code, pos, pos) + if not b then return incomplete(ctx) end + pos = pos+1 + if b < 128 then ctx.rexr = true end + local m = 1 + if pat == "3" then + m = b%32; b = (b-m)/32 + local nb = b%2; b = (b-nb)/2 + if nb == 0 then ctx.rexb = true end + local nx = b%2 + if nx == 0 then ctx.rexx = true end + b = byte(ctx.code, pos, pos) + if not b then return incomplete(ctx) end + pos = pos+1 + if b >= 128 then ctx.rexw = true end + end + ctx.pos = pos + local map + if m == 1 then map = map_opc2 + elseif m == 2 then map = map_opc3["38"] + elseif m == 3 then map = map_opc3["3a"] + else return unknown(ctx) end + local p = b%4; b = (b-p)/4 + if p == 1 then ctx.o16 = "o16" + elseif p == 2 then ctx.rep = "rep" + elseif p == 3 then ctx.rep = "repne" end + local l = b%2; b = (b-l)/2 + if l ~= 0 then ctx.vexl = true end + ctx.vexv = (-1-b)%16 + return dispatchmap(ctx, map) + end, + + -- Special case for nop with REX prefix. + nop = function(ctx, name, pat) + return dispatch(ctx, ctx.rex and pat or "nop") + end, + + -- Special case for 0F 77. + emms = function(ctx, name, pat) + if ctx.rex ~= "vex" then + return putop(ctx, "emms") + elseif ctx.vexl then + ctx.vexl = false + return putop(ctx, "zeroall") + else + return putop(ctx, "zeroupper") + end + end, +} + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ofs = ofs + 1 + ctx.start = ofs + ctx.pos = ofs + ctx.stop = stop + ctx.imm = nil + ctx.mrm = false + clearprefixes(ctx) + while ctx.pos <= stop do dispatchmap(ctx, ctx.map1) end + if ctx.pos ~= ctx.start then incomplete(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = (addr or 0) - 1 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 16 + ctx.x64 = false + ctx.map1 = map_opc1_32 + ctx.aregs = map_regs.D + return ctx +end + +local function create64(code, addr, out) + local ctx = create(code, addr, out) + ctx.x64 = true + ctx.map1 = map_opc1_64 + ctx.aregs = map_regs.Q + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +local function disass64(code, addr, out) + create64(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 8 then return map_regs.D[r+1] end + return map_regs.X[r-7] +end + +local function regname64(r) + if r < 16 then return map_regs.Q[r+1] end + return map_regs.X[r-15] +end + +-- Public module functions. +return { + create = create, + create64 = create64, + disass = disass, + disass64 = disass64, + regname = regname, + regname64 = regname64 +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/dump.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/dump.lua new file mode 100644 index 00000000..9eda08c4 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/dump.lua @@ -0,0 +1,726 @@ +---------------------------------------------------------------------------- +-- LuaJIT compiler dump module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module can be used to debug the JIT compiler itself. It dumps the +-- code representations and structures used in various compiler stages. +-- +-- Example usage: +-- +-- luajit -jdump -e "local x=0; for i=1,1e6 do x=x+i end; print(x)" +-- luajit -jdump=im -e "for i=1,1000 do for j=1,1000 do end end" | less -R +-- luajit -jdump=is myapp.lua | less -R +-- luajit -jdump=-b myapp.lua +-- luajit -jdump=+aH,myapp.html myapp.lua +-- luajit -jdump=ixT,myapp.dump myapp.lua +-- +-- The first argument specifies the dump mode. The second argument gives +-- the output file name. Default output is to stdout, unless the environment +-- variable LUAJIT_DUMPFILE is set. The file is overwritten every time the +-- module is started. +-- +-- Different features can be turned on or off with the dump mode. If the +-- mode starts with a '+', the following features are added to the default +-- set of features; a '-' removes them. Otherwise the features are replaced. +-- +-- The following dump features are available (* marks the default): +-- +-- * t Print a line for each started, ended or aborted trace (see also -jv). +-- * b Dump the traced bytecode. +-- * i Dump the IR (intermediate representation). +-- r Augment the IR with register/stack slots. +-- s Dump the snapshot map. +-- * m Dump the generated machine code. +-- x Print each taken trace exit. +-- X Print each taken trace exit and the contents of all registers. +-- a Print the IR of aborted traces, too. +-- +-- The output format can be set with the following characters: +-- +-- T Plain text output. +-- A ANSI-colored text output +-- H Colorized HTML + CSS output. +-- +-- The default output format is plain text. It's set to ANSI-colored text +-- if the COLORTERM variable is set. Note: this is independent of any output +-- redirection, which is actually considered a feature. +-- +-- You probably want to use less -R to enjoy viewing ANSI-colored text from +-- a pipe or a file. Add this to your ~/.bashrc: export LESS="-R" +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc +local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek +local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap +local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr +local bit = require("bit") +local band, shr, tohex = bit.band, bit.rshift, bit.tohex +local sub, gsub, format = string.sub, string.gsub, string.format +local byte, rep = string.byte, string.rep +local type, tostring = type, tostring +local stdout, stderr = io.stdout, io.stderr + +-- Load other modules on-demand. +local bcline, disass + +-- Active flag, output file handle and dump mode. +local active, out, dumpmode + +------------------------------------------------------------------------------ + +local symtabmt = { __index = false } +local symtab = {} +local nexitsym = 0 + +-- Fill nested symbol table with per-trace exit stub addresses. +local function fillsymtab_tr(tr, nexit) + local t = {} + symtabmt.__index = t + if jit.arch:sub(1, 4) == "mips" then + t[traceexitstub(tr, 0)] = "exit" + return + end + for i=0,nexit-1 do + local addr = traceexitstub(tr, i) + if addr < 0 then addr = addr + 2^32 end + t[addr] = tostring(i) + end + local addr = traceexitstub(tr, nexit) + if addr then t[addr] = "stack_check" end +end + +-- Fill symbol table with trace exit stub addresses. +local function fillsymtab(tr, nexit) + local t = symtab + if nexitsym == 0 then + local maskaddr = jit.arch == "arm" and -2 + local ircall = vmdef.ircall + for i=0,#ircall do + local addr = ircalladdr(i) + if addr ~= 0 then + if maskaddr then addr = band(addr, maskaddr) end + if addr < 0 then addr = addr + 2^32 end + t[addr] = ircall[i] + end + end + end + if nexitsym == 1000000 then -- Per-trace exit stubs. + fillsymtab_tr(tr, nexit) + elseif nexit > nexitsym then -- Shared exit stubs. + for i=nexitsym,nexit-1 do + local addr = traceexitstub(i) + if addr == nil then -- Fall back to per-trace exit stubs. + fillsymtab_tr(tr, nexit) + setmetatable(symtab, symtabmt) + nexit = 1000000 + break + end + if addr < 0 then addr = addr + 2^32 end + t[addr] = tostring(i) + end + nexitsym = nexit + end + return t +end + +local function dumpwrite(s) + out:write(s) +end + +-- Disassemble machine code. +local function dump_mcode(tr) + local info = traceinfo(tr) + if not info then return end + local mcode, addr, loop = tracemc(tr) + if not mcode then return end + if not disass then disass = require("jit.dis_"..jit.arch) end + if addr < 0 then addr = addr + 2^32 end + out:write("---- TRACE ", tr, " mcode ", #mcode, "\n") + local ctx = disass.create(mcode, addr, dumpwrite) + ctx.hexdump = 0 + ctx.symtab = fillsymtab(tr, info.nexit) + if loop ~= 0 then + symtab[addr+loop] = "LOOP" + ctx:disass(0, loop) + out:write("->LOOP:\n") + ctx:disass(loop, #mcode-loop) + symtab[addr+loop] = nil + else + ctx:disass(0, #mcode) + end +end + +------------------------------------------------------------------------------ + +local irtype_text = { + [0] = "nil", + "fal", + "tru", + "lud", + "str", + "p32", + "thr", + "pro", + "fun", + "p64", + "cdt", + "tab", + "udt", + "flt", + "num", + "i8 ", + "u8 ", + "i16", + "u16", + "int", + "u32", + "i64", + "u64", + "sfp", +} + +local colortype_ansi = { + [0] = "%s", + "%s", + "%s", + "\027[36m%s\027[m", + "\027[32m%s\027[m", + "%s", + "\027[1m%s\027[m", + "%s", + "\027[1m%s\027[m", + "%s", + "\027[33m%s\027[m", + "\027[31m%s\027[m", + "\027[36m%s\027[m", + "\027[34m%s\027[m", + "\027[34m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", +} + +local function colorize_text(s) + return s +end + +local function colorize_ansi(s, t, extra) + local out = format(colortype_ansi[t], s) + if extra then out = "\027[3m"..out end + return out +end + +local irtype_ansi = setmetatable({}, + { __index = function(tab, t) + local s = colorize_ansi(irtype_text[t], t); tab[t] = s; return s; end }) + +local html_escape = { ["<"] = "<", [">"] = ">", ["&"] = "&", } + +local function colorize_html(s, t, extra) + s = gsub(s, "[<>&]", html_escape) + return format('%s', + irtype_text[t], extra and " irt_extra" or "", s) +end + +local irtype_html = setmetatable({}, + { __index = function(tab, t) + local s = colorize_html(irtype_text[t], t); tab[t] = s; return s; end }) + +local header_html = [[ + +]] + +local colorize, irtype + +-- Lookup tables to convert some literals into names. +local litname = { + ["SLOAD "] = setmetatable({}, { __index = function(t, mode) + local s = "" + if band(mode, 1) ~= 0 then s = s.."P" end + if band(mode, 2) ~= 0 then s = s.."F" end + if band(mode, 4) ~= 0 then s = s.."T" end + if band(mode, 8) ~= 0 then s = s.."C" end + if band(mode, 16) ~= 0 then s = s.."R" end + if band(mode, 32) ~= 0 then s = s.."I" end + if band(mode, 64) ~= 0 then s = s.."K" end + t[mode] = s + return s + end}), + ["XLOAD "] = { [0] = "", "R", "V", "RV", "U", "RU", "VU", "RVU", }, + ["CONV "] = setmetatable({}, { __index = function(t, mode) + local s = irtype[band(mode, 31)] + s = irtype[band(shr(mode, 5), 31)].."."..s + if band(mode, 0x800) ~= 0 then s = s.." sext" end + local c = shr(mode, 12) + if c == 1 then s = s.." none" + elseif c == 2 then s = s.." index" + elseif c == 3 then s = s.." check" end + t[mode] = s + return s + end}), + ["FLOAD "] = vmdef.irfield, + ["FREF "] = vmdef.irfield, + ["FPMATH"] = vmdef.irfpm, + ["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" }, + ["BUFHDR"] = { [0] = "RESET", "APPEND", "WRITE" }, + ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, +} + +local function ctlsub(c) + if c == "\n" then return "\\n" + elseif c == "\r" then return "\\r" + elseif c == "\t" then return "\\t" + else return format("\\%03d", byte(c)) + end +end + +local function fmtfunc(func, pc) + local fi = funcinfo(func, pc) + if fi.loc then + return fi.loc + elseif fi.ffid then + return vmdef.ffnames[fi.ffid] + elseif fi.addr then + return format("C:%x", fi.addr) + else + return "(?)" + end +end + +local function formatk(tr, idx, sn) + local k, t, slot = tracek(tr, idx) + local tn = type(k) + local s + if tn == "number" then + if t < 12 then + s = k == 0 and "NULL" or format("[0x%08x]", k) + elseif band(sn or 0, 0x30000) ~= 0 then + s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz" + elseif k == 2^52+2^51 then + s = "bias" + else + s = format(0 < k and k < 0x1p-1026 and "%+a" or "%+.14g", k) + end + elseif tn == "string" then + s = format(#k > 20 and '"%.20s"~' or '"%s"', gsub(k, "%c", ctlsub)) + elseif tn == "function" then + s = fmtfunc(k) + elseif tn == "table" then + s = format("{%p}", k) + elseif tn == "userdata" then + if t == 12 then + s = format("userdata:%p", k) + else + s = format("[%p]", k) + if s == "[NULL]" then s = "NULL" end + end + elseif t == 21 then -- int64_t + s = sub(tostring(k), 1, -3) + if sub(s, 1, 1) ~= "-" then s = "+"..s end + elseif sn == 0x1057fff then -- SNAP(1, SNAP_FRAME | SNAP_NORESTORE, REF_NIL) + return "----" -- Special case for LJ_FR2 slot 1. + else + s = tostring(k) -- For primitives. + end + s = colorize(format("%-4s", s), t, band(sn or 0, 0x100000) ~= 0) + if slot then + s = format("%s @%d", s, slot) + end + return s +end + +local function printsnap(tr, snap) + local n = 2 + for s=0,snap[1]-1 do + local sn = snap[n] + if shr(sn, 24) == s then + n = n + 1 + local ref = band(sn, 0xffff) - 0x8000 -- REF_BIAS + if ref < 0 then + out:write(formatk(tr, ref, sn)) + elseif band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM + out:write(colorize(format("%04d/%04d", ref, ref+1), 14)) + else + local m, ot, op1, op2 = traceir(tr, ref) + out:write(colorize(format("%04d", ref), band(ot, 31), band(sn, 0x100000) ~= 0)) + end + out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME + else + out:write("---- ") + end + end + out:write("]\n") +end + +-- Dump snapshots (not interleaved with IR). +local function dump_snap(tr) + out:write("---- TRACE ", tr, " snapshots\n") + for i=0,1000000000 do + local snap = tracesnap(tr, i) + if not snap then break end + out:write(format("#%-3d %04d [ ", i, snap[0])) + printsnap(tr, snap) + end +end + +-- Return a register name or stack slot for a rid/sp location. +local function ridsp_name(ridsp, ins) + if not disass then disass = require("jit.dis_"..jit.arch) end + local rid, slot = band(ridsp, 0xff), shr(ridsp, 8) + if rid == 253 or rid == 254 then + return (slot == 0 or slot == 255) and " {sink" or format(" {%04d", ins-slot) + end + if ridsp > 255 then return format("[%x]", slot*4) end + if rid < 128 then return disass.regname(rid) end + return "" +end + +-- Dump CALL* function ref and return optional ctype. +local function dumpcallfunc(tr, ins) + local ctype + if ins > 0 then + local m, ot, op1, op2 = traceir(tr, ins) + if band(ot, 31) == 0 then -- nil type means CARG(func, ctype). + ins = op1 + ctype = formatk(tr, op2) + end + end + if ins < 0 then + out:write(format("[0x%x](", tonumber((tracek(tr, ins))))) + else + out:write(format("%04d (", ins)) + end + return ctype +end + +-- Recursively gather CALL* args and dump them. +local function dumpcallargs(tr, ins) + if ins < 0 then + out:write(formatk(tr, ins)) + else + local m, ot, op1, op2 = traceir(tr, ins) + local oidx = 6*shr(ot, 8) + local op = sub(vmdef.irnames, oidx+1, oidx+6) + if op == "CARG " then + dumpcallargs(tr, op1) + if op2 < 0 then + out:write(" ", formatk(tr, op2)) + else + out:write(" ", format("%04d", op2)) + end + else + out:write(format("%04d", ins)) + end + end +end + +-- Dump IR and interleaved snapshots. +local function dump_ir(tr, dumpsnap, dumpreg) + local info = traceinfo(tr) + if not info then return end + local nins = info.nins + out:write("---- TRACE ", tr, " IR\n") + local irnames = vmdef.irnames + local snapref = 65536 + local snap, snapno + if dumpsnap then + snap = tracesnap(tr, 0) + snapref = snap[0] + snapno = 0 + end + for ins=1,nins do + if ins >= snapref then + if dumpreg then + out:write(format(".... SNAP #%-3d [ ", snapno)) + else + out:write(format(".... SNAP #%-3d [ ", snapno)) + end + printsnap(tr, snap) + snapno = snapno + 1 + snap = tracesnap(tr, snapno) + snapref = snap and snap[0] or 65536 + end + local m, ot, op1, op2, ridsp = traceir(tr, ins) + local oidx, t = 6*shr(ot, 8), band(ot, 31) + local op = sub(irnames, oidx+1, oidx+6) + if op == "LOOP " then + if dumpreg then + out:write(format("%04d ------------ LOOP ------------\n", ins)) + else + out:write(format("%04d ------ LOOP ------------\n", ins)) + end + elseif op ~= "NOP " and op ~= "CARG " and + (dumpreg or op ~= "RENAME") then + local rid = band(ridsp, 255) + if dumpreg then + out:write(format("%04d %-6s", ins, ridsp_name(ridsp, ins))) + else + out:write(format("%04d ", ins)) + end + out:write(format("%s%s %s %s ", + (rid == 254 or rid == 253) and "}" or + (band(ot, 128) == 0 and " " or ">"), + band(ot, 64) == 0 and " " or "+", + irtype[t], op)) + local m1, m2 = band(m, 3), band(m, 3*4) + if sub(op, 1, 4) == "CALL" then + local ctype + if m2 == 1*4 then -- op2 == IRMlit + out:write(format("%-10s (", vmdef.ircall[op2])) + else + ctype = dumpcallfunc(tr, op2) + end + if op1 ~= -1 then dumpcallargs(tr, op1) end + out:write(")") + if ctype then out:write(" ctype ", ctype) end + elseif op == "CNEW " and op2 == -1 then + out:write(formatk(tr, op1)) + elseif m1 ~= 3 then -- op1 != IRMnone + if op1 < 0 then + out:write(formatk(tr, op1)) + else + out:write(format(m1 == 0 and "%04d" or "#%-3d", op1)) + end + if m2 ~= 3*4 then -- op2 != IRMnone + if m2 == 1*4 then -- op2 == IRMlit + local litn = litname[op] + if litn and litn[op2] then + out:write(" ", litn[op2]) + elseif op == "UREFO " or op == "UREFC " then + out:write(format(" #%-3d", shr(op2, 8))) + else + out:write(format(" #%-3d", op2)) + end + elseif op2 < 0 then + out:write(" ", formatk(tr, op2)) + else + out:write(format(" %04d", op2)) + end + end + end + out:write("\n") + end + end + if snap then + if dumpreg then + out:write(format(".... SNAP #%-3d [ ", snapno)) + else + out:write(format(".... SNAP #%-3d [ ", snapno)) + end + printsnap(tr, snap) + end +end + +------------------------------------------------------------------------------ + +local recprefix = "" +local recdepth = 0 + +-- Format trace error message. +local function fmterr(err, info) + if type(err) == "number" then + if type(info) == "function" then info = fmtfunc(info) end + err = format(vmdef.traceerr[err], info) + end + return err +end + +-- Dump trace states. +local function dump_trace(what, tr, func, pc, otr, oex) + if what == "stop" or (what == "abort" and dumpmode.a) then + if dumpmode.i then dump_ir(tr, dumpmode.s, dumpmode.r and what == "stop") + elseif dumpmode.s then dump_snap(tr) end + if dumpmode.m then dump_mcode(tr) end + end + if what == "start" then + if dumpmode.H then out:write('

\n') end
+    out:write("---- TRACE ", tr, " ", what)
+    if otr then out:write(" ", otr, "/", oex == -1 and "stitch" or oex) end
+    out:write(" ", fmtfunc(func, pc), "\n")
+  elseif what == "stop" or what == "abort" then
+    out:write("---- TRACE ", tr, " ", what)
+    if what == "abort" then
+      out:write(" ", fmtfunc(func, pc), " -- ", fmterr(otr, oex), "\n")
+    else
+      local info = traceinfo(tr)
+      local link, ltype = info.link, info.linktype
+      if link == tr or link == 0 then
+	out:write(" -> ", ltype, "\n")
+      elseif ltype == "root" then
+	out:write(" -> ", link, "\n")
+      else
+	out:write(" -> ", link, " ", ltype, "\n")
+      end
+    end
+    if dumpmode.H then out:write("
\n\n") else out:write("\n") end + else + if what == "flush" then symtab, nexitsym = {}, 0 end + out:write("---- TRACE ", what, "\n\n") + end + out:flush() +end + +-- Dump recorded bytecode. +local function dump_record(tr, func, pc, depth) + if depth ~= recdepth then + recdepth = depth + recprefix = rep(" .", depth) + end + local line + if pc >= 0 then + line = bcline(func, pc, recprefix) + if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end + else + line = "0000 "..recprefix.." FUNCC \n" + end + if pc <= 0 then + out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n") + else + out:write(line) + end + if pc >= 0 and band(funcbc(func, pc), 0xff) < 16 then -- ORDER BC + out:write(bcline(func, pc+1, recprefix)) -- Write JMP for cond. + end +end + +------------------------------------------------------------------------------ + +local gpr64 = jit.arch:match("64") +local fprmips32 = jit.arch == "mips" or jit.arch == "mipsel" + +-- Dump taken trace exits. +local function dump_texit(tr, ex, ngpr, nfpr, ...) + out:write("---- TRACE ", tr, " exit ", ex, "\n") + if dumpmode.X then + local regs = {...} + if gpr64 then + for i=1,ngpr do + out:write(format(" %016x", regs[i])) + if i % 4 == 0 then out:write("\n") end + end + else + for i=1,ngpr do + out:write(" ", tohex(regs[i])) + if i % 8 == 0 then out:write("\n") end + end + end + if fprmips32 then + for i=1,nfpr,2 do + out:write(format(" %+17.14g", regs[ngpr+i])) + if i % 8 == 7 then out:write("\n") end + end + else + for i=1,nfpr do + out:write(format(" %+17.14g", regs[ngpr+i])) + if i % 4 == 0 then out:write("\n") end + end + end + end +end + +------------------------------------------------------------------------------ + +-- Detach dump handlers. +local function dumpoff() + if active then + active = false + jit.attach(dump_texit) + jit.attach(dump_record) + jit.attach(dump_trace) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handlers. +local function dumpon(opt, outfile) + if active then dumpoff() end + + local term = os.getenv("TERM") + local colormode = (term and term:match("color") or os.getenv("COLORTERM")) and "A" or "T" + if opt then + opt = gsub(opt, "[TAH]", function(mode) colormode = mode; return ""; end) + end + + local m = { t=true, b=true, i=true, m=true, } + if opt and opt ~= "" then + local o = sub(opt, 1, 1) + if o ~= "+" and o ~= "-" then m = {} end + for i=1,#opt do m[sub(opt, i, i)] = (o ~= "-") end + end + dumpmode = m + + if m.t or m.b or m.i or m.s or m.m then + jit.attach(dump_trace, "trace") + end + if m.b then + jit.attach(dump_record, "record") + if not bcline then bcline = require("jit.bc").line end + end + if m.x or m.X then + jit.attach(dump_texit, "texit") + end + + if not outfile then outfile = os.getenv("LUAJIT_DUMPFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stdout + end + + m[colormode] = true + if colormode == "A" then + colorize = colorize_ansi + irtype = irtype_ansi + elseif colormode == "H" then + colorize = colorize_html + irtype = irtype_html + out:write(header_html) + else + colorize = colorize_text + irtype = irtype_text + end + + active = true +end + +-- Public module functions. +return { + on = dumpon, + off = dumpoff, + start = dumpon -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/p.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/p.lua new file mode 100644 index 00000000..c9ec1d8b --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/p.lua @@ -0,0 +1,312 @@ +---------------------------------------------------------------------------- +-- LuaJIT profiler. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module is a simple command line interface to the built-in +-- low-overhead profiler of LuaJIT. +-- +-- The lower-level API of the profiler is accessible via the "jit.profile" +-- module or the luaJIT_profile_* C API. +-- +-- Example usage: +-- +-- luajit -jp myapp.lua +-- luajit -jp=s myapp.lua +-- luajit -jp=-s myapp.lua +-- luajit -jp=vl myapp.lua +-- luajit -jp=G,profile.txt myapp.lua +-- +-- The following dump features are available: +-- +-- f Stack dump: function name, otherwise module:line. Default mode. +-- F Stack dump: ditto, but always prepend module. +-- l Stack dump: module:line. +-- stack dump depth (callee < caller). Default: 1. +-- - Inverse stack dump depth (caller > callee). +-- s Split stack dump after first stack level. Implies abs(depth) >= 2. +-- p Show full path for module names. +-- v Show VM states. Can be combined with stack dumps, e.g. vf or fv. +-- z Show zones. Can be combined with stack dumps, e.g. zf or fz. +-- 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 (e.g. flame graphs). +-- m Minimum sample percentage to be shown. Default: 3. +-- i Sampling interval in milliseconds. Default: 10. +-- +---------------------------------------------------------------------------- + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local profile = require("jit.profile") +local vmdef = require("jit.vmdef") +local math = math +local pairs, ipairs, tonumber, floor = pairs, ipairs, tonumber, math.floor +local sort, format = table.sort, string.format +local stdout = io.stdout +local zone -- Load jit.zone module on demand. + +-- Output file handle. +local out + +------------------------------------------------------------------------------ + +local prof_ud +local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth +local prof_ann, prof_count1, prof_count2, prof_samples + +local map_vmmode = { + N = "Compiled", + I = "Interpreted", + C = "C code", + G = "Garbage Collector", + J = "JIT Compiler", +} + +-- Profiler callback. +local function prof_cb(th, samples, vmmode) + prof_samples = prof_samples + samples + local key_stack, key_stack2, key_state + -- Collect keys for sample. + if prof_states then + if prof_states == "v" then + key_state = map_vmmode[vmmode] or vmmode + else + key_state = zone:get() or "(none)" + end + end + if prof_fmt then + key_stack = profile.dumpstack(th, prof_fmt, prof_depth) + key_stack = key_stack:gsub("%[builtin#(%d+)%]", function(x) + return vmdef.ffnames[tonumber(x)] + end) + if prof_split == 2 then + local k1, k2 = key_stack:match("(.-) [<>] (.*)") + if k2 then key_stack, key_stack2 = k1, k2 end + elseif prof_split == 3 then + key_stack2 = profile.dumpstack(th, "l", 1) + end + end + -- Order keys. + local k1, k2 + if prof_split == 1 then + if key_state then + k1 = key_state + if key_stack then k2 = key_stack end + end + elseif key_stack then + k1 = key_stack + if key_stack2 then k2 = key_stack2 elseif key_state then k2 = key_state end + end + -- Coalesce samples in one or two levels. + if k1 then + local t1 = prof_count1 + t1[k1] = (t1[k1] or 0) + samples + if k2 then + local t2 = prof_count2 + local t3 = t2[k1] + if not t3 then t3 = {}; t2[k1] = t3 end + t3[k2] = (t3[k2] or 0) + samples + end + end +end + +------------------------------------------------------------------------------ + +-- Show top N list. +local function prof_top(count1, count2, samples, indent) + local t, n = {}, 0 + for k in pairs(count1) do + n = n + 1 + t[n] = k + end + sort(t, function(a, b) return count1[a] > count1[b] end) + for i=1,n do + local k = t[i] + local v = count1[k] + local pct = floor(v*100/samples + 0.5) + if pct < prof_min then break end + if not prof_raw then + out:write(format("%s%2d%% %s\n", indent, pct, k)) + elseif prof_raw == "r" then + out:write(format("%s%5d %s\n", indent, v, k)) + else + out:write(format("%s %d\n", k, v)) + end + if count2 then + local r = count2[k] + if r then + prof_top(r, nil, v, (prof_split == 3 or prof_split == 1) and " -- " or + (prof_depth < 0 and " -> " or " <- ")) + end + end + end +end + +-- Annotate source code +local function prof_annotate(count1, samples) + local files = {} + local ms = 0 + for k, v in pairs(count1) do + local pct = floor(v*100/samples + 0.5) + ms = math.max(ms, v) + if pct >= prof_min then + local file, line = k:match("^(.*):(%d+)$") + if not file then file = k; line = 0 end + local fl = files[file] + if not fl then fl = {}; files[file] = fl; files[#files+1] = file end + line = tonumber(line) + fl[line] = prof_raw and v or pct + end + end + sort(files) + local fmtv, fmtn = " %3d%% | %s\n", " | %s\n" + if prof_raw then + local n = math.max(5, math.ceil(math.log10(ms))) + fmtv = "%"..n.."d | %s\n" + fmtn = (" "):rep(n).." | %s\n" + end + local ann = prof_ann + for _, file in ipairs(files) do + local f0 = file:byte() + if f0 == 40 or f0 == 91 then + out:write(format("\n====== %s ======\n[Cannot annotate non-file]\n", file)) + break + end + local fp, err = io.open(file) + if not fp then + out:write(format("====== ERROR: %s: %s\n", file, err)) + break + end + out:write(format("\n====== %s ======\n", file)) + local fl = files[file] + local n, show = 1, false + if ann ~= 0 then + for i=1,ann do + if fl[i] then show = true; out:write("@@ 1 @@\n"); break end + end + end + for line in fp:lines() do + if line:byte() == 27 then + out:write("[Cannot annotate bytecode file]\n") + break + end + local v = fl[n] + if ann ~= 0 then + local v2 = fl[n+ann] + if show then + if v2 then show = n+ann elseif v then show = n + elseif show+ann < n then show = false end + elseif v2 then + show = n+ann + out:write(format("@@ %d @@\n", n)) + end + if not show then goto next end + end + if v then + out:write(format(fmtv, v, line)) + else + out:write(format(fmtn, line)) + end + ::next:: + n = n + 1 + end + fp:close() + end +end + +------------------------------------------------------------------------------ + +-- Finish profiling and dump result. +local function prof_finish() + if prof_ud then + profile.stop() + local samples = prof_samples + if samples == 0 then + if prof_raw ~= true then out:write("[No samples collected]\n") end + return + end + if prof_ann then + prof_annotate(prof_count1, samples) + else + prof_top(prof_count1, prof_count2, samples, "") + end + prof_count1 = nil + prof_count2 = nil + prof_ud = nil + if out ~= stdout then out:close() end + end +end + +-- Start profiling. +local function prof_start(mode) + local interval = "" + mode = mode:gsub("i%d*", function(s) interval = s; return "" end) + prof_min = 3 + mode = mode:gsub("m(%d+)", function(s) prof_min = tonumber(s); return "" end) + prof_depth = 1 + mode = mode:gsub("%-?%d+", function(s) prof_depth = tonumber(s); return "" end) + local m = {} + for c in mode:gmatch(".") do m[c] = c end + prof_states = m.z or m.v + if prof_states == "z" then zone = require("jit.zone") end + local scope = m.l or m.f or m.F or (prof_states and "" or "f") + local flags = (m.p or "") + prof_raw = m.r + if m.s then + prof_split = 2 + if prof_depth == -1 or m["-"] then prof_depth = -2 + elseif prof_depth == 1 then prof_depth = 2 end + elseif mode:find("[fF].*l") then + scope = "l" + prof_split = 3 + else + prof_split = (scope == "" or mode:find("[zv].*[lfF]")) and 1 or 0 + end + prof_ann = m.A and 0 or (m.a and 3) + if prof_ann then + scope = "l" + prof_fmt = "pl" + prof_split = 0 + prof_depth = 1 + elseif m.G and scope ~= "" then + prof_fmt = flags..scope.."Z;" + prof_depth = -100 + prof_raw = true + prof_min = 0 + elseif scope == "" then + prof_fmt = false + else + local sc = prof_split == 3 and m.f or m.F or scope + prof_fmt = flags..sc..(prof_depth >= 0 and "Z < " or "Z > ") + end + prof_count1 = {} + prof_count2 = {} + prof_samples = 0 + profile.start(scope:lower()..interval, prof_cb) + prof_ud = newproxy(true) + getmetatable(prof_ud).__gc = prof_finish +end + +------------------------------------------------------------------------------ + +local function start(mode, outfile) + if not outfile then outfile = os.getenv("LUAJIT_PROFILEFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stdout + end + prof_start(mode or "f") +end + +-- Public module functions. +return { + start = start, -- For -j command line option. + stop = prof_finish +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/v.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/v.lua new file mode 100644 index 00000000..83589143 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/v.lua @@ -0,0 +1,170 @@ +---------------------------------------------------------------------------- +-- Verbose mode of the LuaJIT compiler. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module shows verbose information about the progress of the +-- JIT compiler. It prints one line for each generated trace. This module +-- is useful to see which code has been compiled or where the compiler +-- punts and falls back to the interpreter. +-- +-- Example usage: +-- +-- luajit -jv -e "for i=1,1000 do for j=1,1000 do end end" +-- luajit -jv=myapp.out myapp.lua +-- +-- Default output is to stderr. To redirect the output to a file, pass a +-- filename as an argument (use '-' for stdout) or set the environment +-- variable LUAJIT_VERBOSEFILE. The file is overwritten every time the +-- module is started. +-- +-- The output from the first example should look like this: +-- +-- [TRACE 1 (command line):1 loop] +-- [TRACE 2 (1/3) (command line):1 -> 1] +-- +-- The first number in each line is the internal trace number. Next are +-- the file name ('(command line)') and the line number (':1') where the +-- trace has started. Side traces also show the parent trace number and +-- the exit number where they are attached to in parentheses ('(1/3)'). +-- An arrow at the end shows where the trace links to ('-> 1'), unless +-- it loops to itself. +-- +-- In this case the inner loop gets hot and is traced first, generating +-- a root trace. Then the last exit from the 1st trace gets hot, too, +-- and triggers generation of the 2nd trace. The side trace follows the +-- path along the outer loop and *around* the inner loop, back to its +-- start, and then links to the 1st trace. Yes, this may seem unusual, +-- if you know how traditional compilers work. Trace compilers are full +-- of surprises like this -- have fun! :-) +-- +-- Aborted traces are shown like this: +-- +-- [TRACE --- foo.lua:44 -- leaving loop in root trace at foo:lua:50] +-- +-- Don't worry -- trace aborts are quite common, even in programs which +-- can be fully compiled. The compiler may retry several times until it +-- finds a suitable trace. +-- +-- Of course this doesn't work with features that are not-yet-implemented +-- (NYI error messages). The VM simply falls back to the interpreter. This +-- may not matter at all if the particular trace is not very high up in +-- the CPU usage profile. Oh, and the interpreter is quite fast, too. +-- +-- Also check out the -jdump module, which prints all the gory details. +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo +local type, format = type, string.format +local stdout, stderr = io.stdout, io.stderr + +-- Active flag and output file handle. +local active, out + +------------------------------------------------------------------------------ + +local startloc, startex + +local function fmtfunc(func, pc) + local fi = funcinfo(func, pc) + if fi.loc then + return fi.loc + elseif fi.ffid then + return vmdef.ffnames[fi.ffid] + elseif fi.addr then + return format("C:%x", fi.addr) + else + return "(?)" + end +end + +-- Format trace error message. +local function fmterr(err, info) + if type(err) == "number" then + if type(info) == "function" then info = fmtfunc(info) end + err = format(vmdef.traceerr[err], info) + end + return err +end + +-- Dump trace states. +local function dump_trace(what, tr, func, pc, otr, oex) + if what == "start" then + startloc = fmtfunc(func, pc) + startex = otr and "("..otr.."/"..(oex == -1 and "stitch" or oex)..") " or "" + else + if what == "abort" then + local loc = fmtfunc(func, pc) + if loc ~= startloc then + out:write(format("[TRACE --- %s%s -- %s at %s]\n", + startex, startloc, fmterr(otr, oex), loc)) + else + out:write(format("[TRACE --- %s%s -- %s]\n", + startex, startloc, fmterr(otr, oex))) + end + elseif what == "stop" then + local info = traceinfo(tr) + local link, ltype = info.link, info.linktype + if ltype == "interpreter" then + out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n", + tr, startex, startloc)) + elseif ltype == "stitch" then + out:write(format("[TRACE %3s %s%s %s %s]\n", + tr, startex, startloc, ltype, fmtfunc(func, pc))) + elseif link == tr or link == 0 then + out:write(format("[TRACE %3s %s%s %s]\n", + tr, startex, startloc, ltype)) + elseif ltype == "root" then + out:write(format("[TRACE %3s %s%s -> %d]\n", + tr, startex, startloc, link)) + else + out:write(format("[TRACE %3s %s%s -> %d %s]\n", + tr, startex, startloc, link, ltype)) + end + else + out:write(format("[TRACE %s]\n", what)) + end + out:flush() + end +end + +------------------------------------------------------------------------------ + +-- Detach dump handlers. +local function dumpoff() + if active then + active = false + jit.attach(dump_trace) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handlers. +local function dumpon(outfile) + if active then dumpoff() end + if not outfile then outfile = os.getenv("LUAJIT_VERBOSEFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stderr + end + jit.attach(dump_trace, "trace") + active = true +end + +-- Public module functions. +return { + on = dumpon, + off = dumpoff, + start = dumpon -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/vmdef.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/vmdef.lua new file mode 100644 index 00000000..68ff7ba2 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/vmdef.lua @@ -0,0 +1,395 @@ +-- This is a generated file. DO NOT EDIT! + +return { + +bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF ISTYPEISNUM MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TGETR TSETV TSETS TSETB TSETM TSETR CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW", + +irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEPROF KPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF TMPREFSTRREFLREF ALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ALEN ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI BUFHDRBUFPUTBUFSTRTBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLA CALLL CALLS CALLXSCARG ", + +irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "log", "log2", "other", }, + +irfield = { [0]="str.len", "func.env", "func.pc", "func.ffid", "thread.env", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "sbuf.w", "sbuf.e", "sbuf.b", "sbuf.l", "sbuf.ref", "sbuf.r", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", }, + +ircall = { +[0]="lj_str_cmp", +"lj_str_find", +"lj_str_new", +"lj_strscan_num", +"lj_strfmt_int", +"lj_strfmt_num", +"lj_strfmt_char", +"lj_strfmt_putint", +"lj_strfmt_putnum", +"lj_strfmt_putquoted", +"lj_strfmt_putfxint", +"lj_strfmt_putfnum_int", +"lj_strfmt_putfnum_uint", +"lj_strfmt_putfnum", +"lj_strfmt_putfstr", +"lj_strfmt_putfchar", +"lj_buf_putmem", +"lj_buf_putstr", +"lj_buf_putchar", +"lj_buf_putstr_reverse", +"lj_buf_putstr_lower", +"lj_buf_putstr_upper", +"lj_buf_putstr_rep", +"lj_buf_puttab", +"lj_bufx_set", +"lj_bufx_more", +"lj_serialize_put", +"lj_serialize_get", +"lj_serialize_encode", +"lj_serialize_decode", +"lj_buf_tostr", +"lj_tab_new_ah", +"lj_tab_new1", +"lj_tab_dup", +"lj_tab_clear", +"lj_tab_newkey", +"lj_tab_keyindex", +"lj_vm_next", +"lj_tab_len", +"lj_tab_len_hint", +"lj_gc_step_jit", +"lj_gc_barrieruv", +"lj_mem_newgco", +"lj_prng_u64d", +"lj_vm_modi", +"log10", +"exp", +"sin", +"cos", +"tan", +"asin", +"acos", +"atan", +"sinh", +"cosh", +"tanh", +"fputc", +"fwrite", +"fflush", +"lj_vm_floor", +"lj_vm_ceil", +"lj_vm_trunc", +"sqrt", +"log", +"lj_vm_log2", +"lj_vm_powi", +"pow", +"atan2", +"ldexp", +"lj_vm_tobit", +"softfp_add", +"softfp_sub", +"softfp_mul", +"softfp_div", +"softfp_cmp", +"softfp_i2d", +"softfp_d2i", +"lj_vm_sfmin", +"lj_vm_sfmax", +"lj_vm_tointg", +"softfp_ui2d", +"softfp_f2d", +"softfp_d2ui", +"softfp_d2f", +"softfp_i2f", +"softfp_ui2f", +"softfp_f2i", +"softfp_f2ui", +"fp64_l2d", +"fp64_ul2d", +"fp64_l2f", +"fp64_ul2f", +"fp64_d2l", +"fp64_d2ul", +"fp64_f2l", +"fp64_f2ul", +"lj_carith_divi64", +"lj_carith_divu64", +"lj_carith_modi64", +"lj_carith_modu64", +"lj_carith_powi64", +"lj_carith_powu64", +"lj_cdata_newv", +"lj_cdata_setfin", +"strlen", +"memcpy", +"memset", +"lj_vm_errno", +"lj_carith_mul64", +"lj_carith_shl64", +"lj_carith_shr64", +"lj_carith_sar64", +"lj_carith_rol64", +"lj_carith_ror64", +}, + +traceerr = { +[0]="error thrown or hook called during recording", +"trace too short", +"trace too long", +"trace too deep", +"too many snapshots", +"blacklisted", +"retry recording", +"NYI: bytecode %d", +"leaving loop in root trace", +"inner loop in root trace", +"loop unroll limit reached", +"bad argument type", +"JIT compilation disabled for function", +"call unroll limit reached", +"down-recursion, restarting", +"NYI: unsupported variant of FastFunc %s", +"NYI: return to lower frame", +"store with nil or NaN key", +"missing metamethod", +"looping index lookup", +"NYI: mixed sparse/dense table", +"symbol not in cache", +"NYI: unsupported C type conversion", +"NYI: unsupported C function type", +"guard would always fail", +"too many PHIs", +"persistent type instability", +"failed to allocate mcode memory", +"machine code too long", +"hit mcode limit (retrying)", +"too many spill slots", +"inconsistent register allocation", +"NYI: cannot assemble IR instruction %d", +"NYI: PHI shuffling too complex", +"NYI: register coalescing too complex", +}, + +ffnames = { +[0]="Lua", +"C", +"assert", +"type", +"next", +"pairs", +"ipairs_aux", +"ipairs", +"getmetatable", +"setmetatable", +"getfenv", +"setfenv", +"rawget", +"rawset", +"rawequal", +"unpack", +"select", +"tonumber", +"tostring", +"error", +"pcall", +"xpcall", +"loadfile", +"load", +"loadstring", +"dofile", +"gcinfo", +"collectgarbage", +"newproxy", +"print", +"coroutine.status", +"coroutine.running", +"coroutine.isyieldable", +"coroutine.create", +"coroutine.yield", +"coroutine.resume", +"coroutine.wrap_aux", +"coroutine.wrap", +"math.abs", +"math.floor", +"math.ceil", +"math.sqrt", +"math.log10", +"math.exp", +"math.sin", +"math.cos", +"math.tan", +"math.asin", +"math.acos", +"math.atan", +"math.sinh", +"math.cosh", +"math.tanh", +"math.frexp", +"math.modf", +"math.log", +"math.atan2", +"math.pow", +"math.fmod", +"math.ldexp", +"math.min", +"math.max", +"math.random", +"math.randomseed", +"bit.tobit", +"bit.bnot", +"bit.bswap", +"bit.lshift", +"bit.rshift", +"bit.arshift", +"bit.rol", +"bit.ror", +"bit.band", +"bit.bor", +"bit.bxor", +"bit.tohex", +"string.byte", +"string.char", +"string.sub", +"string.rep", +"string.reverse", +"string.lower", +"string.upper", +"string.dump", +"string.find", +"string.match", +"string.gmatch_aux", +"string.gmatch", +"string.gsub", +"string.format", +"table.maxn", +"table.insert", +"table.concat", +"table.sort", +"table.new", +"table.clear", +"io.method.close", +"io.method.read", +"io.method.write", +"io.method.flush", +"io.method.seek", +"io.method.setvbuf", +"io.method.lines", +"io.method.__gc", +"io.method.__tostring", +"io.open", +"io.popen", +"io.tmpfile", +"io.close", +"io.read", +"io.write", +"io.flush", +"io.input", +"io.output", +"io.lines", +"io.type", +"os.execute", +"os.remove", +"os.rename", +"os.tmpname", +"os.getenv", +"os.exit", +"os.clock", +"os.date", +"os.time", +"os.difftime", +"os.setlocale", +"debug.getregistry", +"debug.getmetatable", +"debug.setmetatable", +"debug.getfenv", +"debug.setfenv", +"debug.getinfo", +"debug.getlocal", +"debug.setlocal", +"debug.getupvalue", +"debug.setupvalue", +"debug.upvalueid", +"debug.upvaluejoin", +"debug.sethook", +"debug.gethook", +"debug.debug", +"debug.traceback", +"jit.on", +"jit.off", +"jit.flush", +"jit.status", +"jit.security", +"jit.attach", +"jit.util.funcinfo", +"jit.util.funcbc", +"jit.util.funck", +"jit.util.funcuvname", +"jit.util.traceinfo", +"jit.util.traceir", +"jit.util.tracek", +"jit.util.tracesnap", +"jit.util.tracemc", +"jit.util.traceexitstub", +"jit.util.ircalladdr", +"jit.opt.start", +"jit.profile.start", +"jit.profile.stop", +"jit.profile.dumpstack", +"ffi.meta.__index", +"ffi.meta.__newindex", +"ffi.meta.__eq", +"ffi.meta.__len", +"ffi.meta.__lt", +"ffi.meta.__le", +"ffi.meta.__concat", +"ffi.meta.__call", +"ffi.meta.__add", +"ffi.meta.__sub", +"ffi.meta.__mul", +"ffi.meta.__div", +"ffi.meta.__mod", +"ffi.meta.__pow", +"ffi.meta.__unm", +"ffi.meta.__tostring", +"ffi.meta.__pairs", +"ffi.meta.__ipairs", +"ffi.clib.__index", +"ffi.clib.__newindex", +"ffi.clib.__gc", +"ffi.callback.free", +"ffi.callback.set", +"ffi.cdef", +"ffi.new", +"ffi.cast", +"ffi.typeof", +"ffi.typeinfo", +"ffi.istype", +"ffi.sizeof", +"ffi.alignof", +"ffi.offsetof", +"ffi.errno", +"ffi.string", +"ffi.copy", +"ffi.fill", +"ffi.abi", +"ffi.metatype", +"ffi.gc", +"ffi.load", +"buffer.method.free", +"buffer.method.reset", +"buffer.method.skip", +"buffer.method.set", +"buffer.method.put", +"buffer.method.putf", +"buffer.method.get", +"buffer.method.putcdata", +"buffer.method.reserve", +"buffer.method.commit", +"buffer.method.ref", +"buffer.method.encode", +"buffer.method.decode", +"buffer.method.__gc", +"buffer.method.__tostring", +"buffer.method.__len", +"buffer.new", +"buffer.encode", +"buffer.decode", +}, + +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/jit/zone.lua b/love/src/jni/LuaJIT-2.1/android/x86/jit/zone.lua new file mode 100644 index 00000000..94357854 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86/jit/zone.lua @@ -0,0 +1,45 @@ +---------------------------------------------------------------------------- +-- LuaJIT profiler zones. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module implements a simple hierarchical zone model. +-- +-- Example usage: +-- +-- local zone = require("jit.zone") +-- zone("AI") +-- ... +-- zone("A*") +-- ... +-- print(zone:get()) --> "A*" +-- ... +-- zone() +-- ... +-- print(zone:get()) --> "AI" +-- ... +-- zone() +-- +---------------------------------------------------------------------------- + +local remove = table.remove + +return setmetatable({ + flush = function(t) + for i=#t,1,-1 do t[i] = nil end + end, + get = function(t) + return t[#t] + end +}, { + __call = function(t, zone) + if zone then + t[#t+1] = zone + else + return (assert(remove(t), "empty zone stack")) + end + end +}) + diff --git a/love/src/jni/LuaJIT-2.1/android/x86/libluajit.a b/love/src/jni/LuaJIT-2.1/android/x86/libluajit.a index ec49d56b042c55a317a92d570e86ce342a1ef2de..aea697079628a4a2529f25cadbd04ddb62d4a3cf 100644 GIT binary patch delta 256106 zcmeFad011&_dkAT2oN-opiv{D28{}e3KkdYQlJQ86~P6xb#2}2io~sIzyNx^Ms07~ zY2U4_cGd1JYFye1Q~|ZFZLM0{y0s=otEg3QA>Y^BBtVzv^L;+g^Z7jAKYqVFmAU84 z%$YN1&YU?jbMEch)1AvML~jVQJkqOopPs$qdm4=~M*eH~*J$k1v!@4PoY+VZ$Z0`{ z_~3u^pXGm=;D3{z<$ts{|INnHw&j0Tod0bGEdRsf`QK&W{~!PVw+i@Qj{nL(1mS=A zpXGnMf&UAA%>V!89{$(#E&ux>{x2D@{6FpeAHx6F$3No#I{wA42fiE>kd`)b;PCX~ zE}?6PYR;6!xy7F}nd>Jc9AU9{moM{uDHcy>8B}bTLo-}vf zlsOY}Cp|rDim+hLq?Pxi+QwQ>=+_6&( z*(Yb?uPm?b6w~x+LtPP_rowTc8z_F(vANtoDwxE|*E_{f!5~LOb|**W%*dFKH(Gd# zSKQQ&S6%UyjGkSO)@iOdiQDbg?zpPmQDR+og-diC^1Z?xF8>l46C6>GXx>6@71dqy zTl2aiXXLD?m=;^>5pUqp+mG?`q^J&>+4Xr(%SWQxYLe;^z2%yyskCwP;z^yy`_TxU zT-vp5V?iefeFqw}*1KByT(?KV_Gkq`yCeN!Me;!vn0333aQ5zN3*V9->lQ`^%TIQj z*5*P8FXZdSZEfK_Af)Ik3ZXybU%T}sU&yVxn`k4goY=hwiI;P`8yg!yS}CE`%5Qd0 zXmVJglK#-O&)dY8a#i<7$P;phm?`8pS&C^*D&(y(Q-aq7*Hd31w~9?9{p4}62dEG% zNA?&-BSPdQJvxzUd2^3$XJvbE1zyF2*s~G zvV$1&2Bet%%L4|w&PYR^nRM; z$rJjFA!Cbo^~qC(1ho=`s2@tN`Pl}#oxA1K{@utM^1}XKYcJk#yM3Z_UbrDYKHz8i z%gy3;kF6uBsw%fze!gFG`Cvl#;Ljj;X{O5huvTk*M-E7gZIm2{FODd&Op;cfFosk1a&S9q-==>Z=eZNUZk`NSS!pZbH`43GonZT?KenGeLIYUj)H z&x!3KK7i=0OH~-DO?Z+zTbJtuZQ+XwRs-xB*_afgZ-^j7yGW5zf=cWxCaHF!rr?~->n{%%azjO@_=8wh$B_A` zoR~bF+>$>?-cKgW^9JSwymj5pRmCyTPU7TEDboX%{Q<;_a!6_#c}pIhx;*OJn{Kxv zChPA(9^pEk1~;zPJ;>ue6)=NRZa$ zc0(wIJLT_3bRxgX4@Pt(JB!~`0C2H%kAJMqykizM0{R49}Js{1WwwSORS$ zd-$?1lAD}JMS>#u3FC_`+06*)DZezjJ#osrMi0Z^pfMweB##@@-O>!*^M{_tLYPe` z6@J19HHH%U;5Ri8GV=R*^DCfqc1(vTFPsB-4dAX`*amv%0AuJCdhY_h1bBlNz6>}^ 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 delta 225735 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䏩zSmwF<^@N$-$n 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 diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/bc.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/bc.lua new file mode 100644 index 00000000..e58a3fef --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/bc.lua @@ -0,0 +1,190 @@ +---------------------------------------------------------------------------- +-- LuaJIT bytecode listing module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module lists the bytecode of a Lua function. If it's loaded by -jbc +-- it hooks into the parser and lists all functions of a chunk as they +-- are parsed. +-- +-- Example usage: +-- +-- luajit -jbc -e 'local x=0; for i=1,1e6 do x=x+i end; print(x)' +-- luajit -jbc=- foo.lua +-- luajit -jbc=foo.list foo.lua +-- +-- Default output is to stderr. To redirect the output to a file, pass a +-- filename as an argument (use '-' for stdout) or set the environment +-- variable LUAJIT_LISTFILE. The file is overwritten every time the module +-- is started. +-- +-- This module can also be used programmatically: +-- +-- local bc = require("jit.bc") +-- +-- local function foo() print("hello") end +-- +-- bc.dump(foo) --> -- BYTECODE -- [...] +-- print(bc.line(foo, 2)) --> 0002 KSTR 1 1 ; "hello" +-- +-- local out = { +-- -- Do something with each line: +-- write = function(t, ...) io.write(...) end, +-- close = function(t) end, +-- flush = function(t) end, +-- } +-- bc.dump(foo, out) +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local bit = require("bit") +local sub, gsub, format = string.sub, string.gsub, string.format +local byte, band, shr = string.byte, bit.band, bit.rshift +local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck +local funcuvname = jutil.funcuvname +local bcnames = vmdef.bcnames +local stdout, stderr = io.stdout, io.stderr + +------------------------------------------------------------------------------ + +local function ctlsub(c) + if c == "\n" then return "\\n" + elseif c == "\r" then return "\\r" + elseif c == "\t" then return "\\t" + else return format("\\%03d", byte(c)) + end +end + +-- Return one bytecode line. +local function bcline(func, pc, prefix) + local ins, m = funcbc(func, pc) + if not ins then return end + local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128) + local a = band(shr(ins, 8), 0xff) + local oidx = 6*band(ins, 0xff) + local op = sub(bcnames, oidx+1, oidx+6) + local s = format("%04d %s %-6s %3s ", + pc, prefix or " ", op, ma == 0 and "" or a) + local d = shr(ins, 16) + if mc == 13*128 then -- BCMjump + return format("%s=> %04d\n", s, pc+d-0x7fff) + end + if mb ~= 0 then + d = band(d, 0xff) + elseif mc == 0 then + return s.."\n" + end + local kc + if mc == 10*128 then -- BCMstr + kc = funck(func, -d-1) + kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub)) + elseif mc == 9*128 then -- BCMnum + kc = funck(func, d) + if op == "TSETM " then kc = kc - 2^52 end + elseif mc == 12*128 then -- BCMfunc + local fi = funcinfo(funck(func, -d-1)) + if fi.ffid then + kc = vmdef.ffnames[fi.ffid] + else + kc = fi.loc + end + elseif mc == 5*128 then -- BCMuv + kc = funcuvname(func, d) + end + if ma == 5 then -- BCMuv + local ka = funcuvname(func, a) + if kc then kc = ka.." ; "..kc else kc = ka end + end + if mb ~= 0 then + local b = shr(ins, 24) + if kc then return format("%s%3d %3d ; %s\n", s, b, d, kc) end + return format("%s%3d %3d\n", s, b, d) + end + if kc then return format("%s%3d ; %s\n", s, d, kc) end + if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits + return format("%s%3d\n", s, d) +end + +-- Collect branch targets of a function. +local function bctargets(func) + local target = {} + for pc=1,1000000000 do + local ins, m = funcbc(func, pc) + if not ins then break end + if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end + end + return target +end + +-- Dump bytecode instructions of a function. +local function bcdump(func, out, all) + if not out then out = stdout end + local fi = funcinfo(func) + if all and fi.children then + for n=-1,-1000000000,-1 do + local k = funck(func, n) + if not k then break end + if type(k) == "proto" then bcdump(k, out, true) end + end + end + out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined)) + local target = bctargets(func) + for pc=1,1000000000 do + local s = bcline(func, pc, target[pc] and "=>") + if not s then break end + out:write(s) + end + out:write("\n") + out:flush() +end + +------------------------------------------------------------------------------ + +-- Active flag and output file handle. +local active, out + +-- List handler. +local function h_list(func) + return bcdump(func, out) +end + +-- Detach list handler. +local function bclistoff() + if active then + active = false + jit.attach(h_list) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach list handler. +local function bcliston(outfile) + if active then bclistoff() end + if not outfile then outfile = os.getenv("LUAJIT_LISTFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stderr + end + jit.attach(h_list, "bc") + active = true +end + +-- Public module functions. +return { + line = bcline, + dump = bcdump, + targets = bctargets, + on = bcliston, + off = bclistoff, + start = bcliston -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/bcsave.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/bcsave.lua new file mode 100644 index 00000000..ab13667a --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/bcsave.lua @@ -0,0 +1,665 @@ +---------------------------------------------------------------------------- +-- LuaJIT module to save/list bytecode. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module saves or lists the bytecode for an input file. +-- It's run by the -b command line option. +-- +------------------------------------------------------------------------------ + +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local bit = require("bit") + +-- Symbol name prefix for LuaJIT bytecode. +local LJBC_PREFIX = "luaJIT_BC_" + +local type, assert = type, assert +local format = string.format +local tremove, tconcat = table.remove, table.concat + +------------------------------------------------------------------------------ + +local function usage() + io.stderr:write[[ +Save LuaJIT bytecode: luajit -b[options] input output + -l Only list bytecode. + -s Strip debug info (default). + -g Keep debug info. + -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). + -e chunk Use chunk string as input. + -- Stop handling options. + - Use stdin as input and/or stdout as output. + +File types: c h obj o raw (default) +]] + os.exit(1) +end + +local function check(ok, ...) + if ok then return ok, ... end + io.stderr:write("luajit: ", ...) + io.stderr:write("\n") + os.exit(1) +end + +local function readfile(input) + if type(input) == "function" then return input end + if input == "-" then input = nil end + return check(loadfile(input)) +end + +local function savefile(name, mode) + if name == "-" then return io.stdout end + return check(io.open(name, mode)) +end + +------------------------------------------------------------------------------ + +local map_type = { + raw = "raw", c = "c", h = "h", o = "obj", obj = "obj", +} + +local map_arch = { + x86 = { e = "le", b = 32, m = 3, p = 0x14c, }, + x64 = { e = "le", b = 64, m = 62, p = 0x8664, }, + arm = { e = "le", b = 32, m = 40, p = 0x1c0, }, + arm64 = { e = "le", b = 64, m = 183, p = 0xaa64, }, + arm64be = { e = "be", b = 64, m = 183, }, + ppc = { e = "be", b = 32, m = 20, }, + mips = { e = "be", b = 32, m = 8, f = 0x50001006, }, + mipsel = { e = "le", b = 32, m = 8, f = 0x50001006, }, + mips64 = { e = "be", b = 64, m = 8, f = 0x80000007, }, + mips64el = { e = "le", b = 64, m = 8, f = 0x80000007, }, + mips64r6 = { e = "be", b = 64, m = 8, f = 0xa0000407, }, + mips64r6el = { e = "le", b = 64, m = 8, f = 0xa0000407, }, +} + +local map_os = { + linux = true, windows = true, osx = true, freebsd = true, netbsd = true, + openbsd = true, dragonfly = true, solaris = true, +} + +local function checkarg(str, map, err) + str = str:lower() + local s = check(map[str], "unknown ", err) + return type(s) == "string" and s or str +end + +local function detecttype(str) + local ext = str:lower():match("%.(%a+)$") + return map_type[ext] or "raw" +end + +local function checkmodname(str) + check(str:match("^[%w_.%-]+$"), "bad module name") + return str:gsub("[%.%-]", "_") +end + +local function detectmodname(str) + if type(str) == "string" then + local tail = str:match("[^/\\]+$") + if tail then str = tail end + local head = str:match("^(.*)%.[^.]*$") + if head then str = head end + str = str:match("^[%w_.%-]+") + else + str = nil + end + check(str, "cannot derive module name, use -n name") + return str:gsub("[%.%-]", "_") +end + +------------------------------------------------------------------------------ + +local function bcsave_tail(fp, output, s) + local ok, err = fp:write(s) + if ok and output ~= "-" then ok, err = fp:close() end + check(ok, "cannot write ", output, ": ", err) +end + +local function bcsave_raw(output, s) + local fp = savefile(output, "wb") + bcsave_tail(fp, output, s) +end + +local function bcsave_c(ctx, output, s) + local fp = savefile(output, "w") + if ctx.type == "c" then + fp:write(format([[ +#ifdef __cplusplus +extern "C" +#endif +#ifdef _WIN32 +__declspec(dllexport) +#endif +const unsigned char %s%s[] = { +]], LJBC_PREFIX, ctx.modname)) + else + fp:write(format([[ +#define %s%s_SIZE %d +static const unsigned char %s%s[] = { +]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname)) + end + local t, n, m = {}, 0, 0 + for i=1,#s do + local b = tostring(string.byte(s, i)) + m = m + #b + 1 + if m > 78 then + fp:write(tconcat(t, ",", 1, n), ",\n") + n, m = 0, #b + 1 + end + n = n + 1 + t[n] = b + end + bcsave_tail(fp, output, tconcat(t, ",", 1, n).."\n};\n") +end + +local function bcsave_elfobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct { + uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; + uint16_t type, machine; + uint32_t version; + uint32_t entry, phofs, shofs; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; +} ELF32header; +typedef struct { + uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; + uint16_t type, machine; + uint32_t version; + uint64_t entry, phofs, shofs; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; +} ELF64header; +typedef struct { + uint32_t name, type, flags, addr, ofs, size, link, info, align, entsize; +} ELF32sectheader; +typedef struct { + uint32_t name, type; + uint64_t flags, addr, ofs, size; + uint32_t link, info; + uint64_t align, entsize; +} ELF64sectheader; +typedef struct { + uint32_t name, value, size; + uint8_t info, other; + uint16_t sectidx; +} ELF32symbol; +typedef struct { + uint32_t name; + uint8_t info, other; + uint16_t sectidx; + uint64_t value, size; +} ELF64symbol; +typedef struct { + ELF32header hdr; + ELF32sectheader sect[6]; + ELF32symbol sym[2]; + uint8_t space[4096]; +} ELF32obj; +typedef struct { + ELF64header hdr; + ELF64sectheader sect[6]; + ELF64symbol sym[2]; + uint8_t space[4096]; +} ELF64obj; +]] + local symname = LJBC_PREFIX..ctx.modname + local ai = assert(map_arch[ctx.arch]) + local is64, isbe = ai.b == 64, ai.e == "be" + + -- Handle different host/target endianess. + local function f32(x) return x end + local f16, fofs = f32, f32 + if ffi.abi("be") ~= isbe then + f32 = bit.bswap + function f16(x) return bit.rshift(bit.bswap(x), 16) end + if is64 then + local two32 = ffi.cast("int64_t", 2^32) + function fofs(x) return bit.bswap(x)*two32 end + else + fofs = f32 + end + end + + -- Create ELF object and fill in header. + local o = ffi.new(is64 and "ELF64obj" or "ELF32obj") + local hdr = o.hdr + if ctx.os == "bsd" or ctx.os == "other" then -- Determine native hdr.eosabi. + local bf = assert(io.open("/bin/ls", "rb")) + local bs = bf:read(9) + bf:close() + ffi.copy(o, bs, 9) + check(hdr.emagic[0] == 127, "no support for writing native object files") + else + hdr.emagic = "\127ELF" + hdr.eosabi = ({ freebsd=9, netbsd=2, openbsd=12, solaris=6 })[ctx.os] or 0 + end + hdr.eclass = is64 and 2 or 1 + hdr.eendian = isbe and 2 or 1 + hdr.eversion = 1 + hdr.type = f16(1) + hdr.machine = f16(ai.m) + hdr.flags = f32(ai.f or 0) + hdr.version = f32(1) + hdr.shofs = fofs(ffi.offsetof(o, "sect")) + hdr.ehsize = f16(ffi.sizeof(hdr)) + hdr.shentsize = f16(ffi.sizeof(o.sect[0])) + hdr.shnum = f16(6) + hdr.shstridx = f16(2) + + -- Fill in sections and symbols. + local sofs, ofs = ffi.offsetof(o, "space"), 1 + for i,name in ipairs{ + ".symtab", ".shstrtab", ".strtab", ".rodata", ".note.GNU-stack", + } do + local sect = o.sect[i] + sect.align = fofs(1) + sect.name = f32(ofs) + ffi.copy(o.space+ofs, name) + ofs = ofs + #name+1 + end + o.sect[1].type = f32(2) -- .symtab + o.sect[1].link = f32(3) + o.sect[1].info = f32(1) + o.sect[1].align = fofs(8) + o.sect[1].ofs = fofs(ffi.offsetof(o, "sym")) + o.sect[1].entsize = fofs(ffi.sizeof(o.sym[0])) + o.sect[1].size = fofs(ffi.sizeof(o.sym)) + o.sym[1].name = f32(1) + o.sym[1].sectidx = f16(4) + o.sym[1].size = fofs(#s) + o.sym[1].info = 17 + o.sect[2].type = f32(3) -- .shstrtab + o.sect[2].ofs = fofs(sofs) + o.sect[2].size = fofs(ofs) + o.sect[3].type = f32(3) -- .strtab + o.sect[3].ofs = fofs(sofs + ofs) + o.sect[3].size = fofs(#symname+2) + ffi.copy(o.space+ofs+1, symname) + ofs = ofs + #symname + 2 + o.sect[4].type = f32(1) -- .rodata + o.sect[4].flags = fofs(2) + o.sect[4].ofs = fofs(sofs + ofs) + o.sect[4].size = fofs(#s) + o.sect[5].type = f32(1) -- .note.GNU-stack + o.sect[5].ofs = fofs(sofs + ofs + #s) + + -- Write ELF object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) + bcsave_tail(fp, output, s) +end + +local function bcsave_peobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct { + uint16_t arch, nsects; + uint32_t time, symtabofs, nsyms; + uint16_t opthdrsz, flags; +} PEheader; +typedef struct { + char name[8]; + uint32_t vsize, vaddr, size, ofs, relocofs, lineofs; + uint16_t nreloc, nline; + uint32_t flags; +} PEsection; +typedef struct __attribute((packed)) { + union { + char name[8]; + uint32_t nameref[2]; + }; + uint32_t value; + int16_t sect; + uint16_t type; + uint8_t scl, naux; +} PEsym; +typedef struct __attribute((packed)) { + uint32_t size; + uint16_t nreloc, nline; + uint32_t cksum; + uint16_t assoc; + uint8_t comdatsel, unused[3]; +} PEsymaux; +typedef struct { + PEheader hdr; + PEsection sect[2]; + // Must be an even number of symbol structs. + PEsym sym0; + PEsymaux sym0aux; + PEsym sym1; + PEsymaux sym1aux; + PEsym sym2; + PEsym sym3; + uint32_t strtabsize; + uint8_t space[4096]; +} PEobj; +]] + local symname = LJBC_PREFIX..ctx.modname + local ai = assert(map_arch[ctx.arch]) + local is64 = ai.b == 64 + local symexport = " /EXPORT:"..symname..",DATA " + + -- The file format is always little-endian. Swap if the host is big-endian. + local function f32(x) return x end + local f16 = f32 + if ffi.abi("be") then + f32 = bit.bswap + function f16(x) return bit.rshift(bit.bswap(x), 16) end + end + + -- Create PE object and fill in header. + local o = ffi.new("PEobj") + local hdr = o.hdr + hdr.arch = f16(assert(ai.p)) + hdr.nsects = f16(2) + hdr.symtabofs = f32(ffi.offsetof(o, "sym0")) + hdr.nsyms = f32(6) + + -- Fill in sections and symbols. + o.sect[0].name = ".drectve" + o.sect[0].size = f32(#symexport) + o.sect[0].flags = f32(0x00100a00) + o.sym0.sect = f16(1) + o.sym0.scl = 3 + o.sym0.name = ".drectve" + o.sym0.naux = 1 + o.sym0aux.size = f32(#symexport) + o.sect[1].name = ".rdata" + o.sect[1].size = f32(#s) + o.sect[1].flags = f32(0x40300040) + o.sym1.sect = f16(2) + o.sym1.scl = 3 + o.sym1.name = ".rdata" + o.sym1.naux = 1 + o.sym1aux.size = f32(#s) + o.sym2.sect = f16(2) + o.sym2.scl = 2 + o.sym2.nameref[1] = f32(4) + o.sym3.sect = f16(-1) + o.sym3.scl = 2 + o.sym3.value = f32(1) + o.sym3.name = "@feat.00" -- Mark as SafeSEH compliant. + ffi.copy(o.space, symname) + local ofs = #symname + 1 + o.strtabsize = f32(ofs + 4) + o.sect[0].ofs = f32(ffi.offsetof(o, "space") + ofs) + ffi.copy(o.space + ofs, symexport) + ofs = ofs + #symexport + o.sect[1].ofs = f32(ffi.offsetof(o, "space") + ofs) + + -- Write PE object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) + bcsave_tail(fp, output, s) +end + +local function bcsave_machobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct +{ + uint32_t magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags; +} mach_header; +typedef struct +{ + mach_header; uint32_t reserved; +} mach_header_64; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint32_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint64_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command_64; +typedef struct { + char sectname[16], segname[16]; + uint32_t addr, size; + uint32_t offset, align, reloff, nreloc, flags; + uint32_t reserved1, reserved2; +} mach_section; +typedef struct { + char sectname[16], segname[16]; + uint64_t addr, size; + uint32_t offset, align, reloff, nreloc, flags; + uint32_t reserved1, reserved2, reserved3; +} mach_section_64; +typedef struct { + uint32_t cmd, cmdsize, symoff, nsyms, stroff, strsize; +} mach_symtab_command; +typedef struct { + int32_t strx; + uint8_t type, sect; + int16_t desc; + uint32_t value; +} mach_nlist; +typedef struct { + uint32_t strx; + uint8_t type, sect; + uint16_t desc; + uint64_t value; +} mach_nlist_64; +typedef struct +{ + uint32_t magic, nfat_arch; +} mach_fat_header; +typedef struct +{ + uint32_t cputype, cpusubtype, offset, size, align; +} mach_fat_arch; +typedef struct { + struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + } arch[1]; + mach_nlist sym_entry; + uint8_t space[4096]; +} mach_obj; +typedef struct { + struct { + mach_header_64 hdr; + mach_segment_command_64 seg; + mach_section_64 sec; + mach_symtab_command sym; + } arch[1]; + mach_nlist_64 sym_entry; + uint8_t space[4096]; +} mach_obj_64; +typedef struct { + mach_fat_header fat; + mach_fat_arch fat_arch[2]; + struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + } arch[2]; + mach_nlist sym_entry; + uint8_t space[4096]; +} mach_fat_obj; +]] + local symname = '_'..LJBC_PREFIX..ctx.modname + local isfat, is64, align, mobj = false, false, 4, "mach_obj" + if ctx.arch == "x64" then + is64, align, mobj = true, 8, "mach_obj_64" + elseif ctx.arch == "arm" then + isfat, mobj = true, "mach_fat_obj" + elseif ctx.arch == "arm64" then + is64, align, isfat, mobj = true, 8, true, "mach_fat_obj" + else + check(ctx.arch == "x86", "unsupported architecture for OSX") + end + local function aligned(v, a) return bit.band(v+a-1, -a) end + local be32 = bit.bswap -- Mach-O FAT is BE, supported archs are LE. + + -- Create Mach-O object and fill in header. + local o = ffi.new(mobj) + local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align) + local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12}, arm64={0x01000007,0x0100000c} })[ctx.arch] + local cpusubtype = ({ x86={3}, x64={3}, arm={3,9}, arm64={3,0} })[ctx.arch] + if isfat then + o.fat.magic = be32(0xcafebabe) + o.fat.nfat_arch = be32(#cpusubtype) + end + + -- Fill in sections and symbols. + for i=0,#cpusubtype-1 do + local ofs = 0 + if isfat then + local a = o.fat_arch[i] + a.cputype = be32(cputype[i+1]) + a.cpusubtype = be32(cpusubtype[i+1]) + -- Subsequent slices overlap each other to share data. + ofs = ffi.offsetof(o, "arch") + i*ffi.sizeof(o.arch[0]) + a.offset = be32(ofs) + a.size = be32(mach_size-ofs+#s) + end + local a = o.arch[i] + a.hdr.magic = is64 and 0xfeedfacf or 0xfeedface + a.hdr.cputype = cputype[i+1] + a.hdr.cpusubtype = cpusubtype[i+1] + a.hdr.filetype = 1 + a.hdr.ncmds = 2 + a.hdr.sizeofcmds = ffi.sizeof(a.seg)+ffi.sizeof(a.sec)+ffi.sizeof(a.sym) + a.seg.cmd = is64 and 0x19 or 0x1 + a.seg.cmdsize = ffi.sizeof(a.seg)+ffi.sizeof(a.sec) + a.seg.vmsize = #s + a.seg.fileoff = mach_size-ofs + a.seg.filesize = #s + a.seg.maxprot = 1 + a.seg.initprot = 1 + a.seg.nsects = 1 + ffi.copy(a.sec.sectname, "__data") + ffi.copy(a.sec.segname, "__DATA") + a.sec.size = #s + a.sec.offset = mach_size-ofs + a.sym.cmd = 2 + a.sym.cmdsize = ffi.sizeof(a.sym) + a.sym.symoff = ffi.offsetof(o, "sym_entry")-ofs + a.sym.nsyms = 1 + a.sym.stroff = ffi.offsetof(o, "sym_entry")+ffi.sizeof(o.sym_entry)-ofs + a.sym.strsize = aligned(#symname+2, align) + end + o.sym_entry.type = 0xf + o.sym_entry.sect = 1 + o.sym_entry.strx = 1 + ffi.copy(o.space+1, symname) + + -- Write Macho-O object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, mach_size)) + bcsave_tail(fp, output, s) +end + +local function bcsave_obj(ctx, output, s) + local ok, ffi = pcall(require, "ffi") + check(ok, "FFI library required to write this file type") + if ctx.os == "windows" then + return bcsave_peobj(ctx, output, s, ffi) + elseif ctx.os == "osx" then + return bcsave_machobj(ctx, output, s, ffi) + else + return bcsave_elfobj(ctx, output, s, ffi) + end +end + +------------------------------------------------------------------------------ + +local function bclist(input, output) + local f = readfile(input) + require("jit.bc").dump(f, savefile(output, "w"), true) +end + +local function bcsave(ctx, input, output) + local f = readfile(input) + local s = string.dump(f, ctx.strip) + local t = ctx.type + if not t then + t = detecttype(output) + ctx.type = t + end + if t == "raw" then + bcsave_raw(output, s) + else + if not ctx.modname then ctx.modname = detectmodname(input) end + if t == "obj" then + bcsave_obj(ctx, output, s) + else + bcsave_c(ctx, output, s) + end + end +end + +local function docmd(...) + local arg = {...} + local n = 1 + local list = false + local ctx = { + strip = true, arch = jit.arch, os = jit.os:lower(), + type = false, modname = false, + } + while n <= #arg do + local a = arg[n] + if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then + tremove(arg, n) + if a == "--" then break end + for m=2,#a do + local opt = a:sub(m, m) + if opt == "l" then + list = true + elseif opt == "s" then + ctx.strip = true + elseif opt == "g" then + ctx.strip = false + else + if arg[n] == nil or m ~= #a then usage() end + if opt == "e" then + if n ~= 1 then usage() end + arg[1] = check(loadstring(arg[1])) + elseif opt == "n" then + ctx.modname = checkmodname(tremove(arg, n)) + elseif opt == "t" then + ctx.type = checkarg(tremove(arg, n), map_type, "file type") + elseif opt == "a" then + ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture") + elseif opt == "o" then + ctx.os = checkarg(tremove(arg, n), map_os, "OS name") + else + usage() + end + end + end + else + n = n + 1 + end + end + if list then + if #arg == 0 or #arg > 2 then usage() end + bclist(arg[1], arg[2] or "-") + else + if #arg ~= 2 then usage() end + bcsave(ctx, arg[1], arg[2]) + end +end + +------------------------------------------------------------------------------ + +-- Public module functions. +return { + start = docmd -- Process -b command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm.lua new file mode 100644 index 00000000..ba79c47e --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm.lua @@ -0,0 +1,689 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles most user-mode ARMv7 instructions +-- NYI: Advanced SIMD and VFP instructions. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch = string.match, string.gmatch +local concat = table.concat +local bit = require("bit") +local band, bor, ror, tohex = bit.band, bit.bor, bit.ror, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Opcode maps +------------------------------------------------------------------------------ + +local map_loadc = { + shift = 8, mask = 15, + [10] = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "vmovFmDN", "vstmFNdr", + _ = { + shift = 21, mask = 1, + [0] = "vstrFdl", + { shift = 16, mask = 15, [13] = "vpushFdr", _ = "vstmdbFNdr", } + }, + }, + { + shift = 23, mask = 3, + [0] = "vmovFDNm", + { shift = 16, mask = 15, [13] = "vpopFdr", _ = "vldmFNdr", }, + _ = { + shift = 21, mask = 1, + [0] = "vldrFdl", "vldmdbFNdr", + }, + }, + }, + [11] = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "vmovGmDN", "vstmGNdr", + _ = { + shift = 21, mask = 1, + [0] = "vstrGdl", + { shift = 16, mask = 15, [13] = "vpushGdr", _ = "vstmdbGNdr", } + }, + }, + { + shift = 23, mask = 3, + [0] = "vmovGDNm", + { shift = 16, mask = 15, [13] = "vpopGdr", _ = "vldmGNdr", }, + _ = { + shift = 21, mask = 1, + [0] = "vldrGdl", "vldmdbGNdr", + }, + }, + }, + _ = { + shift = 0, mask = 0 -- NYI ldc, mcrr, mrrc. + }, +} + +local map_vfps = { + shift = 6, mask = 0x2c001, + [0] = "vmlaF.dnm", "vmlsF.dnm", + [0x04000] = "vnmlsF.dnm", [0x04001] = "vnmlaF.dnm", + [0x08000] = "vmulF.dnm", [0x08001] = "vnmulF.dnm", + [0x0c000] = "vaddF.dnm", [0x0c001] = "vsubF.dnm", + [0x20000] = "vdivF.dnm", + [0x24000] = "vfnmsF.dnm", [0x24001] = "vfnmaF.dnm", + [0x28000] = "vfmaF.dnm", [0x28001] = "vfmsF.dnm", + [0x2c000] = "vmovF.dY", + [0x2c001] = { + shift = 7, mask = 0x1e01, + [0] = "vmovF.dm", "vabsF.dm", + [0x0200] = "vnegF.dm", [0x0201] = "vsqrtF.dm", + [0x0800] = "vcmpF.dm", [0x0801] = "vcmpeF.dm", + [0x0a00] = "vcmpzF.d", [0x0a01] = "vcmpzeF.d", + [0x0e01] = "vcvtG.dF.m", + [0x1000] = "vcvt.f32.u32Fdm", [0x1001] = "vcvt.f32.s32Fdm", + [0x1800] = "vcvtr.u32F.dm", [0x1801] = "vcvt.u32F.dm", + [0x1a00] = "vcvtr.s32F.dm", [0x1a01] = "vcvt.s32F.dm", + }, +} + +local map_vfpd = { + shift = 6, mask = 0x2c001, + [0] = "vmlaG.dnm", "vmlsG.dnm", + [0x04000] = "vnmlsG.dnm", [0x04001] = "vnmlaG.dnm", + [0x08000] = "vmulG.dnm", [0x08001] = "vnmulG.dnm", + [0x0c000] = "vaddG.dnm", [0x0c001] = "vsubG.dnm", + [0x20000] = "vdivG.dnm", + [0x24000] = "vfnmsG.dnm", [0x24001] = "vfnmaG.dnm", + [0x28000] = "vfmaG.dnm", [0x28001] = "vfmsG.dnm", + [0x2c000] = "vmovG.dY", + [0x2c001] = { + shift = 7, mask = 0x1e01, + [0] = "vmovG.dm", "vabsG.dm", + [0x0200] = "vnegG.dm", [0x0201] = "vsqrtG.dm", + [0x0800] = "vcmpG.dm", [0x0801] = "vcmpeG.dm", + [0x0a00] = "vcmpzG.d", [0x0a01] = "vcmpzeG.d", + [0x0e01] = "vcvtF.dG.m", + [0x1000] = "vcvt.f64.u32GdFm", [0x1001] = "vcvt.f64.s32GdFm", + [0x1800] = "vcvtr.u32FdG.m", [0x1801] = "vcvt.u32FdG.m", + [0x1a00] = "vcvtr.s32FdG.m", [0x1a01] = "vcvt.s32FdG.m", + }, +} + +local map_datac = { + shift = 24, mask = 1, + [0] = { + shift = 4, mask = 1, + [0] = { + shift = 8, mask = 15, + [10] = map_vfps, + [11] = map_vfpd, + -- NYI cdp, mcr, mrc. + }, + { + shift = 8, mask = 15, + [10] = { + shift = 20, mask = 15, + [0] = "vmovFnD", "vmovFDn", + [14] = "vmsrD", + [15] = { shift = 12, mask = 15, [15] = "vmrs", _ = "vmrsD", }, + }, + }, + }, + "svcT", +} + +local map_loadcu = { + shift = 0, mask = 0, -- NYI unconditional CP load/store. +} + +local map_datacu = { + shift = 0, mask = 0, -- NYI unconditional CP data. +} + +local map_simddata = { + shift = 0, mask = 0, -- NYI SIMD data. +} + +local map_simdload = { + shift = 0, mask = 0, -- NYI SIMD load/store, preload. +} + +local map_preload = { + shift = 0, mask = 0, -- NYI preload. +} + +local map_media = { + shift = 20, mask = 31, + [0] = false, + { --01 + shift = 5, mask = 7, + [0] = "sadd16DNM", "sasxDNM", "ssaxDNM", "ssub16DNM", + "sadd8DNM", false, false, "ssub8DNM", + }, + { --02 + shift = 5, mask = 7, + [0] = "qadd16DNM", "qasxDNM", "qsaxDNM", "qsub16DNM", + "qadd8DNM", false, false, "qsub8DNM", + }, + { --03 + shift = 5, mask = 7, + [0] = "shadd16DNM", "shasxDNM", "shsaxDNM", "shsub16DNM", + "shadd8DNM", false, false, "shsub8DNM", + }, + false, + { --05 + shift = 5, mask = 7, + [0] = "uadd16DNM", "uasxDNM", "usaxDNM", "usub16DNM", + "uadd8DNM", false, false, "usub8DNM", + }, + { --06 + shift = 5, mask = 7, + [0] = "uqadd16DNM", "uqasxDNM", "uqsaxDNM", "uqsub16DNM", + "uqadd8DNM", false, false, "uqsub8DNM", + }, + { --07 + shift = 5, mask = 7, + [0] = "uhadd16DNM", "uhasxDNM", "uhsaxDNM", "uhsub16DNM", + "uhadd8DNM", false, false, "uhsub8DNM", + }, + { --08 + shift = 5, mask = 7, + [0] = "pkhbtDNMU", false, "pkhtbDNMU", + { shift = 16, mask = 15, [15] = "sxtb16DMU", _ = "sxtab16DNMU", }, + "pkhbtDNMU", "selDNM", "pkhtbDNMU", + }, + false, + { --0a + shift = 5, mask = 7, + [0] = "ssatDxMu", "ssat16DxM", "ssatDxMu", + { shift = 16, mask = 15, [15] = "sxtbDMU", _ = "sxtabDNMU", }, + "ssatDxMu", false, "ssatDxMu", + }, + { --0b + shift = 5, mask = 7, + [0] = "ssatDxMu", "revDM", "ssatDxMu", + { shift = 16, mask = 15, [15] = "sxthDMU", _ = "sxtahDNMU", }, + "ssatDxMu", "rev16DM", "ssatDxMu", + }, + { --0c + shift = 5, mask = 7, + [3] = { shift = 16, mask = 15, [15] = "uxtb16DMU", _ = "uxtab16DNMU", }, + }, + false, + { --0e + shift = 5, mask = 7, + [0] = "usatDwMu", "usat16DwM", "usatDwMu", + { shift = 16, mask = 15, [15] = "uxtbDMU", _ = "uxtabDNMU", }, + "usatDwMu", false, "usatDwMu", + }, + { --0f + shift = 5, mask = 7, + [0] = "usatDwMu", "rbitDM", "usatDwMu", + { shift = 16, mask = 15, [15] = "uxthDMU", _ = "uxtahDNMU", }, + "usatDwMu", "revshDM", "usatDwMu", + }, + { --10 + shift = 12, mask = 15, + [15] = { + shift = 5, mask = 7, + "smuadNMS", "smuadxNMS", "smusdNMS", "smusdxNMS", + }, + _ = { + shift = 5, mask = 7, + [0] = "smladNMSD", "smladxNMSD", "smlsdNMSD", "smlsdxNMSD", + }, + }, + false, false, false, + { --14 + shift = 5, mask = 7, + [0] = "smlaldDNMS", "smlaldxDNMS", "smlsldDNMS", "smlsldxDNMS", + }, + { --15 + shift = 5, mask = 7, + [0] = { shift = 12, mask = 15, [15] = "smmulNMS", _ = "smmlaNMSD", }, + { shift = 12, mask = 15, [15] = "smmulrNMS", _ = "smmlarNMSD", }, + false, false, false, false, + "smmlsNMSD", "smmlsrNMSD", + }, + false, false, + { --18 + shift = 5, mask = 7, + [0] = { shift = 12, mask = 15, [15] = "usad8NMS", _ = "usada8NMSD", }, + }, + false, + { --1a + shift = 5, mask = 3, [2] = "sbfxDMvw", + }, + { --1b + shift = 5, mask = 3, [2] = "sbfxDMvw", + }, + { --1c + shift = 5, mask = 3, + [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", }, + }, + { --1d + shift = 5, mask = 3, + [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", }, + }, + { --1e + shift = 5, mask = 3, [2] = "ubfxDMvw", + }, + { --1f + shift = 5, mask = 3, [2] = "ubfxDMvw", + }, +} + +local map_load = { + shift = 21, mask = 9, + { + shift = 20, mask = 5, + [0] = "strtDL", "ldrtDL", [4] = "strbtDL", [5] = "ldrbtDL", + }, + _ = { + shift = 20, mask = 5, + [0] = "strDL", "ldrDL", [4] = "strbDL", [5] = "ldrbDL", + } +} + +local map_load1 = { + shift = 4, mask = 1, + [0] = map_load, map_media, +} + +local map_loadm = { + shift = 20, mask = 1, + [0] = { + shift = 23, mask = 3, + [0] = "stmdaNR", "stmNR", + { shift = 16, mask = 63, [45] = "pushR", _ = "stmdbNR", }, "stmibNR", + }, + { + shift = 23, mask = 3, + [0] = "ldmdaNR", { shift = 16, mask = 63, [61] = "popR", _ = "ldmNR", }, + "ldmdbNR", "ldmibNR", + }, +} + +local map_data = { + shift = 21, mask = 15, + [0] = "andDNPs", "eorDNPs", "subDNPs", "rsbDNPs", + "addDNPs", "adcDNPs", "sbcDNPs", "rscDNPs", + "tstNP", "teqNP", "cmpNP", "cmnNP", + "orrDNPs", "movDPs", "bicDNPs", "mvnDPs", +} + +local map_mul = { + shift = 21, mask = 7, + [0] = "mulNMSs", "mlaNMSDs", "umaalDNMS", "mlsDNMS", + "umullDNMSs", "umlalDNMSs", "smullDNMSs", "smlalDNMSs", +} + +local map_sync = { + shift = 20, mask = 15, -- NYI: brackets around N. R(D+1) for ldrexd/strexd. + [0] = "swpDMN", false, false, false, + "swpbDMN", false, false, false, + "strexDMN", "ldrexDN", "strexdDN", "ldrexdDN", + "strexbDMN", "ldrexbDN", "strexhDN", "ldrexhDN", +} + +local map_mulh = { + shift = 21, mask = 3, + [0] = { shift = 5, mask = 3, + [0] = "smlabbNMSD", "smlatbNMSD", "smlabtNMSD", "smlattNMSD", }, + { shift = 5, mask = 3, + [0] = "smlawbNMSD", "smulwbNMS", "smlawtNMSD", "smulwtNMS", }, + { shift = 5, mask = 3, + [0] = "smlalbbDNMS", "smlaltbDNMS", "smlalbtDNMS", "smlalttDNMS", }, + { shift = 5, mask = 3, + [0] = "smulbbNMS", "smultbNMS", "smulbtNMS", "smulttNMS", }, +} + +local map_misc = { + shift = 4, mask = 7, + -- NYI: decode PSR bits of msr. + [0] = { shift = 21, mask = 1, [0] = "mrsD", "msrM", }, + { shift = 21, mask = 3, "bxM", false, "clzDM", }, + { shift = 21, mask = 3, "bxjM", }, + { shift = 21, mask = 3, "blxM", }, + false, + { shift = 21, mask = 3, [0] = "qaddDMN", "qsubDMN", "qdaddDMN", "qdsubDMN", }, + false, + { shift = 21, mask = 3, "bkptK", }, +} + +local map_datar = { + shift = 4, mask = 9, + [9] = { + shift = 5, mask = 3, + [0] = { shift = 24, mask = 1, [0] = map_mul, map_sync, }, + { shift = 20, mask = 1, [0] = "strhDL", "ldrhDL", }, + { shift = 20, mask = 1, [0] = "ldrdDL", "ldrsbDL", }, + { shift = 20, mask = 1, [0] = "strdDL", "ldrshDL", }, + }, + _ = { + shift = 20, mask = 25, + [16] = { shift = 7, mask = 1, [0] = map_misc, map_mulh, }, + _ = { + shift = 0, mask = 0xffffffff, + [bor(0xe1a00000)] = "nop", + _ = map_data, + } + }, +} + +local map_datai = { + shift = 20, mask = 31, -- NYI: decode PSR bits of msr. Decode imm12. + [16] = "movwDW", [20] = "movtDW", + [18] = { shift = 0, mask = 0xf00ff, [0] = "nopv6", _ = "msrNW", }, + [22] = "msrNW", + _ = map_data, +} + +local map_branch = { + shift = 24, mask = 1, + [0] = "bB", "blB" +} + +local map_condins = { + [0] = map_datar, map_datai, map_load, map_load1, + map_loadm, map_branch, map_loadc, map_datac +} + +-- NYI: setend. +local map_uncondins = { + [0] = false, map_simddata, map_simdload, map_preload, + false, "blxB", map_loadcu, map_datacu, +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", +} + +local map_cond = { + [0] = "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", +} + +local map_shift = { [0] = "lsl", "lsr", "asr", "ror", } + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then + extra = "\t->"..sym + elseif band(ctx.op, 0x0e000000) ~= 0x0a000000 then + extra = "\t; 0x"..tohex(ctx.rel) + end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-5s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-5s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +-- Format operand 2 of load/store opcodes. +local function fmtload(ctx, op, pos) + local base = map_gpr[band(rshift(op, 16), 15)] + local x, ofs + local ext = (band(op, 0x04000000) == 0) + if not ext and band(op, 0x02000000) == 0 then + ofs = band(op, 4095) + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + ofs = "#"..ofs + elseif ext and band(op, 0x00400000) ~= 0 then + ofs = band(op, 15) + band(rshift(op, 4), 0xf0) + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + ofs = "#"..ofs + else + ofs = map_gpr[band(op, 15)] + if ext or band(op, 0xfe0) == 0 then + elseif band(op, 0xfe0) == 0x60 then + ofs = format("%s, rrx", ofs) + else + local sh = band(rshift(op, 7), 31) + if sh == 0 then sh = 32 end + ofs = format("%s, %s #%d", ofs, map_shift[band(rshift(op, 5), 3)], sh) + end + if band(op, 0x00800000) == 0 then ofs = "-"..ofs end + end + if ofs == "#0" then + x = format("[%s]", base) + elseif band(op, 0x01000000) == 0 then + x = format("[%s], %s", base, ofs) + else + x = format("[%s, %s]", base, ofs) + end + if band(op, 0x01200000) == 0x01200000 then x = x.."!" end + return x +end + +-- Format operand 2 of vector load/store opcodes. +local function fmtvload(ctx, op, pos) + local base = map_gpr[band(rshift(op, 16), 15)] + local ofs = band(op, 255)*4 + if band(op, 0x00800000) == 0 then ofs = -ofs end + if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end + if ofs == 0 then + return format("[%s]", base) + else + return format("[%s, #%d]", base, ofs) + end +end + +local function fmtvr(op, vr, sh0, sh1) + if vr == "s" then + return format("s%d", 2*band(rshift(op, sh0), 15)+band(rshift(op, sh1), 1)) + else + return format("d%d", band(rshift(op, sh0), 15)+band(rshift(op, sh1-4), 16)) + end +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) + local operands = {} + local suffix = "" + local last, name, pat + local vr + ctx.op = op + ctx.rel = nil + + local cond = rshift(op, 28) + local opat + if cond == 15 then + opat = map_uncondins[band(rshift(op, 25), 7)] + else + if cond ~= 14 then suffix = map_cond[cond] end + opat = map_condins[band(rshift(op, 25), 7)] + end + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + name, pat = match(opat, "^([a-z0-9]*)(.*)") + if sub(pat, 1, 1) == "." then + local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") + suffix = suffix..s2 + pat = p2 + end + + for p in gmatch(pat, ".") do + local x = nil + if p == "D" then + x = map_gpr[band(rshift(op, 12), 15)] + elseif p == "N" then + x = map_gpr[band(rshift(op, 16), 15)] + elseif p == "S" then + x = map_gpr[band(rshift(op, 8), 15)] + elseif p == "M" then + x = map_gpr[band(op, 15)] + elseif p == "d" then + x = fmtvr(op, vr, 12, 22) + elseif p == "n" then + x = fmtvr(op, vr, 16, 7) + elseif p == "m" then + x = fmtvr(op, vr, 0, 5) + elseif p == "P" then + if band(op, 0x02000000) ~= 0 then + x = ror(band(op, 255), 2*band(rshift(op, 8), 15)) + else + x = map_gpr[band(op, 15)] + if band(op, 0xff0) ~= 0 then + operands[#operands+1] = x + local s = map_shift[band(rshift(op, 5), 3)] + local r = nil + if band(op, 0xf90) == 0 then + if s == "ror" then s = "rrx" else r = "#32" end + elseif band(op, 0x10) == 0 then + r = "#"..band(rshift(op, 7), 31) + else + r = map_gpr[band(rshift(op, 8), 15)] + end + if name == "mov" then name = s; x = r + elseif r then x = format("%s %s", s, r) + else x = s end + end + end + elseif p == "L" then + x = fmtload(ctx, op, pos) + elseif p == "l" then + x = fmtvload(ctx, op, pos) + elseif p == "B" then + local addr = ctx.addr + pos + 8 + arshift(lshift(op, 8), 6) + if cond == 15 then addr = addr + band(rshift(op, 23), 2) end + ctx.rel = addr + x = "0x"..tohex(addr) + elseif p == "F" then + vr = "s" + elseif p == "G" then + vr = "d" + elseif p == "." then + suffix = suffix..(vr == "s" and ".f32" or ".f64") + elseif p == "R" then + if band(op, 0x00200000) ~= 0 and #operands == 1 then + operands[1] = operands[1].."!" + end + local t = {} + for i=0,15 do + if band(rshift(op, i), 1) == 1 then t[#t+1] = map_gpr[i] end + end + x = "{"..concat(t, ", ").."}" + elseif p == "r" then + if band(op, 0x00200000) ~= 0 and #operands == 2 then + operands[1] = operands[1].."!" + end + local s = tonumber(sub(last, 2)) + local n = band(op, 255) + if vr == "d" then n = rshift(n, 1) end + operands[#operands] = format("{%s-%s%d}", last, vr, s+n-1) + elseif p == "W" then + x = band(op, 0x0fff) + band(rshift(op, 4), 0xf000) + elseif p == "T" then + x = "#0x"..tohex(band(op, 0x00ffffff), 6) + elseif p == "U" then + x = band(rshift(op, 7), 31) + if x == 0 then x = nil end + elseif p == "u" then + x = band(rshift(op, 7), 31) + if band(op, 0x40) == 0 then + if x == 0 then x = nil else x = "lsl #"..x end + else + if x == 0 then x = "asr #32" else x = "asr #"..x end + end + elseif p == "v" then + x = band(rshift(op, 7), 31) + elseif p == "w" then + x = band(rshift(op, 16), 31) + elseif p == "x" then + x = band(rshift(op, 16), 31) + 1 + elseif p == "X" then + x = band(rshift(op, 16), 31) - last + 1 + elseif p == "Y" then + x = band(rshift(op, 12), 0xf0) + band(op, 0x0f) + elseif p == "K" then + x = "#0x"..tohex(band(rshift(op, 4), 0x0000fff0) + band(op, 15), 4) + elseif p == "s" then + if band(op, 0x00100000) ~= 0 then suffix = "s"..suffix end + else + assert(false) + end + if x then + last = x + if type(x) == "number" then x = "#"..x end + operands[#operands+1] = x + end + end + + return putop(ctx, name..suffix, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ctx.pos = ofs + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 16 then return map_gpr[r] end + return "d"..(r-16) +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm64.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm64.lua new file mode 100644 index 00000000..ad909fbd --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm64.lua @@ -0,0 +1,1216 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM64 disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +-- +-- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com. +-- Sponsored by Cisco Systems, Inc. +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles most user-mode AArch64 instructions. +-- NYI: Advanced SIMD and VFP instructions. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local concat = table.concat +local bit = require("bit") +local band, bor, bxor, tohex = bit.band, bit.bor, bit.bxor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift +local ror = bit.ror + +------------------------------------------------------------------------------ +-- Opcode maps +------------------------------------------------------------------------------ + +local map_adr = { -- PC-relative addressing. + shift = 31, mask = 1, + [0] = "adrDBx", "adrpDBx" +} + +local map_addsubi = { -- Add/subtract immediate. + shift = 29, mask = 3, + [0] = "add|movDNIg", "adds|cmnD0NIg", "subDNIg", "subs|cmpD0NIg", +} + +local map_logi = { -- Logical immediate. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "andDNig", "orr|movDN0ig", "eorDNig", "ands|tstD0Nig" + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = "andDNig", "orr|movDN0ig", "eorDNig", "ands|tstD0Nig" + } +} + +local map_movwi = { -- Move wide immediate. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "movnDWRg", false, "movz|movDYRg", "movkDWRg" + }, false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = "movnDWRg", false, "movz|movDYRg", "movkDWRg" + }, +} + +local map_bitf = { -- Bitfield. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "sbfm|sbfiz|sbfx|asr|sxtw|sxth|sxtbDN12w", + "bfm|bfi|bfxilDN13w", + "ubfm|ubfiz|ubfx|lsr|lsl|uxth|uxtbDN12w" + } + }, + { + shift = 22, mask = 1, + { + shift = 29, mask = 3, + [0] = "sbfm|sbfiz|sbfx|asr|sxtw|sxth|sxtbDN12x", + "bfm|bfi|bfxilDN13x", + "ubfm|ubfiz|ubfx|lsr|lsl|uxth|uxtbDN12x" + } + } +} + +local map_datai = { -- Data processing - immediate. + shift = 23, mask = 7, + [0] = map_adr, map_adr, map_addsubi, false, + map_logi, map_movwi, map_bitf, + { + shift = 15, mask = 0x1c0c1, + [0] = "extr|rorDNM4w", [0x10080] = "extr|rorDNM4x", + [0x10081] = "extr|rorDNM4x" + } +} + +local map_logsr = { -- Logical, shifted register. + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = { + shift = 21, mask = 7, + [0] = "andDNMSg", "bicDNMSg", "andDNMSg", "bicDNMSg", + "andDNMSg", "bicDNMSg", "andDNMg", "bicDNMg" + }, + { + shift = 21, mask = 7, + [0] ="orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0MSg", "orn|mvnDN0MSg", + "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0Mg", "orn|mvnDN0Mg" + }, + { + shift = 21, mask = 7, + [0] = "eorDNMSg", "eonDNMSg", "eorDNMSg", "eonDNMSg", + "eorDNMSg", "eonDNMSg", "eorDNMg", "eonDNMg" + }, + { + shift = 21, mask = 7, + [0] = "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMSg", "bicsDNMSg", + "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMg", "bicsDNMg" + } + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = { + shift = 21, mask = 7, + [0] = "andDNMSg", "bicDNMSg", "andDNMSg", "bicDNMSg", + "andDNMSg", "bicDNMSg", "andDNMg", "bicDNMg" + }, + { + shift = 21, mask = 7, + [0] = "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0MSg", "orn|mvnDN0MSg", + "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0Mg", "orn|mvnDN0Mg" + }, + { + shift = 21, mask = 7, + [0] = "eorDNMSg", "eonDNMSg", "eorDNMSg", "eonDNMSg", + "eorDNMSg", "eonDNMSg", "eorDNMg", "eonDNMg" + }, + { + shift = 21, mask = 7, + [0] = "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMSg", "bicsDNMSg", + "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMg", "bicsDNMg" + } + } +} + +local map_assh = { + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "addDNMSg", "addDNMSg", "addDNMSg", "addDNMg" + }, + { + shift = 22, mask = 3, + [0] = "adds|cmnD0NMSg", "adds|cmnD0NMSg", + "adds|cmnD0NMSg", "adds|cmnD0NMg" + }, + { + shift = 22, mask = 3, + [0] = "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0Mg" + }, + { + shift = 22, mask = 3, + [0] = "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0MzSg", + "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0Mzg" + }, + }, + false -- unallocated + }, + { + shift = 29, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "addDNMSg", "addDNMSg", "addDNMSg", "addDNMg" + }, + { + shift = 22, mask = 3, + [0] = "adds|cmnD0NMSg", "adds|cmnD0NMSg", "adds|cmnD0NMSg", + "adds|cmnD0NMg" + }, + { + shift = 22, mask = 3, + [0] = "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0Mg" + }, + { + shift = 22, mask = 3, + [0] = "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0MzSg", + "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0Mzg" + } + } +} + +local map_addsubsh = { -- Add/subtract, shifted register. + shift = 22, mask = 3, + [0] = map_assh, map_assh, map_assh +} + +local map_addsubex = { -- Add/subtract, extended register. + shift = 22, mask = 3, + [0] = { + shift = 29, mask = 3, + [0] = "addDNMXg", "adds|cmnD0NMXg", "subDNMXg", "subs|cmpD0NMzXg", + } +} + +local map_addsubc = { -- Add/subtract, with carry. + shift = 10, mask = 63, + [0] = { + shift = 29, mask = 3, + [0] = "adcDNMg", "adcsDNMg", "sbc|ngcDN0Mg", "sbcs|ngcsDN0Mg", + } +} + +local map_ccomp = { + shift = 4, mask = 1, + [0] = { + shift = 10, mask = 3, + [0] = { -- Conditional compare register. + shift = 29, mask = 3, + "ccmnNMVCg", false, "ccmpNMVCg", + }, + [2] = { -- Conditional compare immediate. + shift = 29, mask = 3, + "ccmnN5VCg", false, "ccmpN5VCg", + } + } +} + +local map_csel = { -- Conditional select. + shift = 11, mask = 1, + [0] = { + shift = 10, mask = 1, + [0] = { + shift = 29, mask = 3, + [0] = "cselDNMzCg", false, "csinv|cinv|csetmDNMcg", false, + }, + { + shift = 29, mask = 3, + [0] = "csinc|cinc|csetDNMcg", false, "csneg|cnegDNMcg", false, + } + } +} + +local map_data1s = { -- Data processing, 1 source. + shift = 29, mask = 1, + [0] = { + shift = 31, mask = 1, + [0] = { + shift = 10, mask = 0x7ff, + [0] = "rbitDNg", "rev16DNg", "revDNw", false, "clzDNg", "clsDNg" + }, + { + shift = 10, mask = 0x7ff, + [0] = "rbitDNg", "rev16DNg", "rev32DNx", "revDNx", "clzDNg", "clsDNg" + } + } +} + +local map_data2s = { -- Data processing, 2 sources. + shift = 29, mask = 1, + [0] = { + shift = 10, mask = 63, + false, "udivDNMg", "sdivDNMg", false, false, false, false, "lslDNMg", + "lsrDNMg", "asrDNMg", "rorDNMg" + } +} + +local map_data3s = { -- Data processing, 3 sources. + shift = 29, mask = 7, + [0] = { + shift = 21, mask = 7, + [0] = { + shift = 15, mask = 1, + [0] = "madd|mulDNMA0g", "msub|mnegDNMA0g" + } + }, false, false, false, + { + shift = 15, mask = 1, + [0] = { + shift = 21, mask = 7, + [0] = "madd|mulDNMA0g", "smaddl|smullDxNMwA0x", "smulhDNMx", false, + false, "umaddl|umullDxNMwA0x", "umulhDNMx" + }, + { + shift = 21, mask = 7, + [0] = "msub|mnegDNMA0g", "smsubl|smneglDxNMwA0x", false, false, + false, "umsubl|umneglDxNMwA0x" + } + } +} + +local map_datar = { -- Data processing, register. + shift = 28, mask = 1, + [0] = { + shift = 24, mask = 1, + [0] = map_logsr, + { + shift = 21, mask = 1, + [0] = map_addsubsh, map_addsubex + } + }, + { + shift = 21, mask = 15, + [0] = map_addsubc, false, map_ccomp, false, map_csel, false, + { + shift = 30, mask = 1, + [0] = map_data2s, map_data1s + }, + false, map_data3s, map_data3s, map_data3s, map_data3s, map_data3s, + map_data3s, map_data3s, map_data3s + } +} + +local map_lrl = { -- Load register, literal. + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = "ldrDwB", "ldrDxB", "ldrswDxB" + }, + { + shift = 30, mask = 3, + [0] = "ldrDsB", "ldrDdB" + } +} + +local map_lsriind = { -- Load/store register, immediate pre/post-indexed. + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwzL", "ldrbDwzL", "ldrsbDxzL", "ldrsbDwzL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strhDwzL", "ldrhDwzL", "ldrshDxzL", "ldrshDwzL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strDwzL", "ldrDwzL", "ldrswDxzL" + }, + { + shift = 22, mask = 3, + [0] = "strDszL", "ldrDszL" + } + }, + { + shift = 26, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = "strDxzL", "ldrDxzL" + }, + { + shift = 22, mask = 3, + [0] = "strDdzL", "ldrDdzL" + } + } +} + +local map_lsriro = { + shift = 21, mask = 1, + [0] = { -- Load/store register immediate. + shift = 10, mask = 3, + [0] = { -- Unscaled immediate. + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "sturbDwK", "ldurbDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturhDwK", "ldurhDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturDwK", "ldurDwK" + }, + { + shift = 22, mask = 3, + [0] = "sturDxK", "ldurDxK" + } + } + }, map_lsriind, false, map_lsriind + }, + { -- Load/store register, register offset. + shift = 10, mask = 3, + [2] = { + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwO", "ldrbDwO", "ldrsbDxO", "ldrsbDwO" + }, + { + shift = 22, mask = 3, + [0] = "strhDwO", "ldrhDwO", "ldrshDxO", "ldrshDwO" + }, + { + shift = 22, mask = 3, + [0] = "strDwO", "ldrDwO", "ldrswDxO" + }, + { + shift = 22, mask = 3, + [0] = "strDxO", "ldrDxO" + } + }, + { + shift = 30, mask = 3, + [2] = { + shift = 22, mask = 3, + [0] = "strDsO", "ldrDsO" + }, + [3] = { + shift = 22, mask = 3, + [0] = "strDdO", "ldrDdO" + } + } + } + } +} + +local map_lsp = { -- Load/store register pair, offset. + shift = 22, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = "stpDzAzwP", "stpDzAzsP", + }, + { + shift = 26, mask = 1, + "stpDzAzdP" + }, + { + shift = 26, mask = 1, + [0] = "stpDzAzxP" + } + }, + { + shift = 30, mask = 3, + [0] = { + shift = 26, mask = 1, + [0] = "ldpDzAzwP", "ldpDzAzsP", + }, + { + shift = 26, mask = 1, + [0] = "ldpswDAxP", "ldpDzAzdP" + }, + { + shift = 26, mask = 1, + [0] = "ldpDzAzxP" + } + } +} + +local map_ls = { -- Loads and stores. + shift = 24, mask = 0x31, + [0x10] = map_lrl, [0x30] = map_lsriro, + [0x20] = { + shift = 23, mask = 3, + map_lsp, map_lsp, map_lsp + }, + [0x21] = { + shift = 23, mask = 3, + map_lsp, map_lsp, map_lsp + }, + [0x31] = { + shift = 26, mask = 1, + [0] = { + shift = 30, mask = 3, + [0] = { + shift = 22, mask = 3, + [0] = "strbDwzU", "ldrbDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strhDwzU", "ldrhDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strDwzU", "ldrDwzU" + }, + { + shift = 22, mask = 3, + [0] = "strDxzU", "ldrDxzU" + } + }, + { + shift = 30, mask = 3, + [2] = { + shift = 22, mask = 3, + [0] = "strDszU", "ldrDszU" + }, + [3] = { + shift = 22, mask = 3, + [0] = "strDdzU", "ldrDdzU" + } + } + }, +} + +local map_datafp = { -- Data processing, SIMD and FP. + shift = 28, mask = 7, + { -- 001 + shift = 24, mask = 1, + [0] = { + shift = 21, mask = 1, + { + shift = 10, mask = 3, + [0] = { + shift = 12, mask = 1, + [0] = { + shift = 13, mask = 1, + [0] = { + shift = 14, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { -- FP/int conversion. + shift = 31, mask = 1, + [0] = { + shift = 16, mask = 0xff, + [0x20] = "fcvtnsDwNs", [0x21] = "fcvtnuDwNs", + [0x22] = "scvtfDsNw", [0x23] = "ucvtfDsNw", + [0x24] = "fcvtasDwNs", [0x25] = "fcvtauDwNs", + [0x26] = "fmovDwNs", [0x27] = "fmovDsNw", + [0x28] = "fcvtpsDwNs", [0x29] = "fcvtpuDwNs", + [0x30] = "fcvtmsDwNs", [0x31] = "fcvtmuDwNs", + [0x38] = "fcvtzsDwNs", [0x39] = "fcvtzuDwNs", + [0x60] = "fcvtnsDwNd", [0x61] = "fcvtnuDwNd", + [0x62] = "scvtfDdNw", [0x63] = "ucvtfDdNw", + [0x64] = "fcvtasDwNd", [0x65] = "fcvtauDwNd", + [0x68] = "fcvtpsDwNd", [0x69] = "fcvtpuDwNd", + [0x70] = "fcvtmsDwNd", [0x71] = "fcvtmuDwNd", + [0x78] = "fcvtzsDwNd", [0x79] = "fcvtzuDwNd" + }, + { + shift = 16, mask = 0xff, + [0x20] = "fcvtnsDxNs", [0x21] = "fcvtnuDxNs", + [0x22] = "scvtfDsNx", [0x23] = "ucvtfDsNx", + [0x24] = "fcvtasDxNs", [0x25] = "fcvtauDxNs", + [0x28] = "fcvtpsDxNs", [0x29] = "fcvtpuDxNs", + [0x30] = "fcvtmsDxNs", [0x31] = "fcvtmuDxNs", + [0x38] = "fcvtzsDxNs", [0x39] = "fcvtzuDxNs", + [0x60] = "fcvtnsDxNd", [0x61] = "fcvtnuDxNd", + [0x62] = "scvtfDdNx", [0x63] = "ucvtfDdNx", + [0x64] = "fcvtasDxNd", [0x65] = "fcvtauDxNd", + [0x66] = "fmovDxNd", [0x67] = "fmovDdNx", + [0x68] = "fcvtpsDxNd", [0x69] = "fcvtpuDxNd", + [0x70] = "fcvtmsDxNd", [0x71] = "fcvtmuDxNd", + [0x78] = "fcvtzsDxNd", [0x79] = "fcvtzuDxNd" + } + } + }, + { -- FP data-processing, 1 source. + shift = 31, mask = 1, + [0] = { + shift = 22, mask = 3, + [0] = { + shift = 15, mask = 63, + [0] = "fmovDNf", "fabsDNf", "fnegDNf", + "fsqrtDNf", false, "fcvtDdNs", false, false, + "frintnDNf", "frintpDNf", "frintmDNf", "frintzDNf", + "frintaDNf", false, "frintxDNf", "frintiDNf", + }, + { + shift = 15, mask = 63, + [0] = "fmovDNf", "fabsDNf", "fnegDNf", + "fsqrtDNf", "fcvtDsNd", false, false, false, + "frintnDNf", "frintpDNf", "frintmDNf", "frintzDNf", + "frintaDNf", false, "frintxDNf", "frintiDNf", + } + } + } + }, + { -- FP compare. + shift = 31, mask = 1, + [0] = { + shift = 14, mask = 3, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 0, mask = 31, + [0] = "fcmpNMf", [8] = "fcmpNZf", + [16] = "fcmpeNMf", [24] = "fcmpeNZf", + } + } + } + } + }, + { -- FP immediate. + shift = 31, mask = 1, + [0] = { + shift = 5, mask = 31, + [0] = { + shift = 23, mask = 1, + [0] = "fmovDFf" + } + } + } + }, + { -- FP conditional compare. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 4, mask = 1, + [0] = "fccmpNMVCf", "fccmpeNMVCf" + } + } + }, + { -- FP data-processing, 2 sources. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = { + shift = 12, mask = 15, + [0] = "fmulDNMf", "fdivDNMf", "faddDNMf", "fsubDNMf", + "fmaxDNMf", "fminDNMf", "fmaxnmDNMf", "fminnmDNMf", + "fnmulDNMf" + } + } + }, + { -- FP conditional select. + shift = 31, mask = 1, + [0] = { + shift = 23, mask = 1, + [0] = "fcselDNMCf" + } + } + } + }, + { -- FP data-processing, 3 sources. + shift = 31, mask = 1, + [0] = { + shift = 15, mask = 1, + [0] = { + shift = 21, mask = 5, + [0] = "fmaddDNMAf", "fnmaddDNMAf" + }, + { + shift = 21, mask = 5, + [0] = "fmsubDNMAf", "fnmsubDNMAf" + } + } + } + } +} + +local map_br = { -- Branches, exception generating and system instructions. + shift = 29, mask = 7, + [0] = "bB", + { -- Compare & branch, immediate. + shift = 24, mask = 3, + [0] = "cbzDBg", "cbnzDBg", "tbzDTBw", "tbnzDTBw" + }, + { -- Conditional branch, immediate. + shift = 24, mask = 3, + [0] = { + shift = 4, mask = 1, + [0] = { + shift = 0, mask = 15, + [0] = "beqB", "bneB", "bhsB", "bloB", "bmiB", "bplB", "bvsB", "bvcB", + "bhiB", "blsB", "bgeB", "bltB", "bgtB", "bleB", "balB" + } + } + }, false, "blB", + { -- Compare & branch, immediate. + shift = 24, mask = 3, + [0] = "cbzDBg", "cbnzDBg", "tbzDTBx", "tbnzDTBx" + }, + { + shift = 24, mask = 3, + [0] = { -- Exception generation. + shift = 0, mask = 0xe0001f, + [0x200000] = "brkW" + }, + { -- System instructions. + shift = 0, mask = 0x3fffff, + [0x03201f] = "nop" + }, + { -- Unconditional branch, register. + shift = 0, mask = 0xfffc1f, + [0x1f0000] = "brNx", [0x3f0000] = "blrNx", + [0x5f0000] = "retNx" + }, + } +} + +local map_init = { + shift = 25, mask = 15, + [0] = false, false, false, false, map_ls, map_datar, map_ls, map_datafp, + map_datai, map_datai, map_br, map_br, map_ls, map_datar, map_ls, map_datafp +} + +------------------------------------------------------------------------------ + +local map_regs = { x = {}, w = {}, d = {}, s = {} } + +for i=0,30 do + map_regs.x[i] = "x"..i + map_regs.w[i] = "w"..i + map_regs.d[i] = "d"..i + map_regs.s[i] = "s"..i +end +map_regs.x[31] = "sp" +map_regs.w[31] = "wsp" +map_regs.d[31] = "d31" +map_regs.s[31] = "s31" + +local map_cond = { + [0] = "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", +} + +local map_shift = { [0] = "lsl", "lsr", "asr", } + +local map_extend = { + [0] = "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx", +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then + extra = "\t->"..sym + end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-5s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-5s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +local function match_reg(p, pat, regnum) + return map_regs[match(pat, p.."%w-([xwds])")][regnum] +end + +local function fmt_hex32(x) + if x < 0 then + return tohex(x) + else + return format("%x", x) + end +end + +local imm13_rep = { 0x55555555, 0x11111111, 0x01010101, 0x00010001, 0x00000001 } + +local function decode_imm13(op) + local imms = band(rshift(op, 10), 63) + local immr = band(rshift(op, 16), 63) + if band(op, 0x00400000) == 0 then + local len = 5 + if imms >= 56 then + if imms >= 60 then len = 1 else len = 2 end + elseif imms >= 48 then len = 3 elseif imms >= 32 then len = 4 end + local l = lshift(1, len)-1 + local s = band(imms, l) + local r = band(immr, l) + local imm = ror(rshift(-1, 31-s), r) + if len ~= 5 then imm = band(imm, lshift(1, l)-1) + rshift(imm, 31-l) end + imm = imm * imm13_rep[len] + local ix = fmt_hex32(imm) + if rshift(op, 31) ~= 0 then + return ix..tohex(imm) + else + return ix + end + else + local lo, hi = -1, 0 + if imms < 32 then lo = rshift(-1, 31-imms) else hi = rshift(-1, 63-imms) end + if immr ~= 0 then + lo, hi = ror(lo, immr), ror(hi, immr) + local x = immr == 32 and 0 or band(bxor(lo, hi), lshift(-1, 32-immr)) + lo, hi = bxor(lo, x), bxor(hi, x) + if immr >= 32 then lo, hi = hi, lo end + end + if hi ~= 0 then + return fmt_hex32(hi)..tohex(lo) + else + return fmt_hex32(lo) + end + end +end + +local function parse_immpc(op, name) + if name == "b" or name == "bl" then + return arshift(lshift(op, 6), 4) + elseif name == "adr" or name == "adrp" then + local immlo = band(rshift(op, 29), 3) + local immhi = lshift(arshift(lshift(op, 8), 13), 2) + return bor(immhi, immlo) + elseif name == "tbz" or name == "tbnz" then + return lshift(arshift(lshift(op, 13), 18), 2) + else + return lshift(arshift(lshift(op, 8), 13), 2) + end +end + +local function parse_fpimm8(op) + local sign = band(op, 0x100000) == 0 and 1 or -1 + local exp = bxor(rshift(arshift(lshift(op, 12), 5), 24), 0x80) - 131 + local frac = 16+band(rshift(op, 13), 15) + return sign * frac * 2^exp +end + +local function prefer_bfx(sf, uns, imms, immr) + if imms < immr or imms == 31 or imms == 63 then + return false + end + if immr == 0 then + if sf == 0 and (imms == 7 or imms == 15) then + return false + end + if sf ~= 0 and uns == 0 and (imms == 7 or imms == 15 or imms == 31) then + return false + end + end + return true +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) + local operands = {} + local suffix = "" + local last, name, pat + local map_reg + ctx.op = op + ctx.rel = nil + last = nil + local opat + opat = map_init[band(rshift(op, 25), 15)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + name, pat = match(opat, "^([a-z0-9]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") + if altname then pat = pat2 end + if sub(pat, 1, 1) == "." then + local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") + suffix = suffix..s2 + pat = p2 + end + + local rt = match(pat, "[gf]") + if rt then + if rt == "g" then + map_reg = band(op, 0x80000000) ~= 0 and map_regs.x or map_regs.w + else + map_reg = band(op, 0x400000) ~= 0 and map_regs.d or map_regs.s + end + end + + local second0, immr + + for p in gmatch(pat, ".") do + local x = nil + if p == "D" then + local regnum = band(op, 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "N" then + local regnum = band(rshift(op, 5), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "M" then + local regnum = band(rshift(op, 16), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "A" then + local regnum = band(rshift(op, 10), 31) + x = rt and map_reg[regnum] or match_reg(p, pat, regnum) + elseif p == "B" then + local addr = ctx.addr + pos + parse_immpc(op, name) + ctx.rel = addr + x = "0x"..tohex(addr) + elseif p == "T" then + x = bor(band(rshift(op, 26), 32), band(rshift(op, 19), 31)) + elseif p == "V" then + x = band(op, 15) + elseif p == "C" then + x = map_cond[band(rshift(op, 12), 15)] + elseif p == "c" then + local rn = band(rshift(op, 5), 31) + local rm = band(rshift(op, 16), 31) + local cond = band(rshift(op, 12), 15) + local invc = bxor(cond, 1) + x = map_cond[cond] + if altname and cond ~= 14 and cond ~= 15 then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if rn == rm then + local n = #operands + operands[n] = nil + x = map_cond[invc] + if rn ~= 31 then + if a1 then name = a1 else name = altname end + else + operands[n-1] = nil + name = a2 + end + end + end + elseif p == "W" then + x = band(rshift(op, 5), 0xffff) + elseif p == "Y" then + x = band(rshift(op, 5), 0xffff) + local hw = band(rshift(op, 21), 3) + if altname and (hw == 0 or x ~= 0) then + name = altname + end + elseif p == "L" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local imm9 = arshift(lshift(op, 11), 23) + if band(op, 0x800) ~= 0 then + x = "["..rn..", #"..imm9.."]!" + else + x = "["..rn.."], #"..imm9 + end + elseif p == "U" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local sz = band(rshift(op, 30), 3) + local imm12 = lshift(arshift(lshift(op, 10), 20), sz) + if imm12 ~= 0 then + x = "["..rn..", #"..imm12.."]" + else + x = "["..rn.."]" + end + elseif p == "K" then + local rn = map_regs.x[band(rshift(op, 5), 31)] + local imm9 = arshift(lshift(op, 11), 23) + if imm9 ~= 0 then + x = "["..rn..", #"..imm9.."]" + else + x = "["..rn.."]" + end + elseif p == "O" then + local rn, rm = map_regs.x[band(rshift(op, 5), 31)] + local m = band(rshift(op, 13), 1) + if m == 0 then + rm = map_regs.w[band(rshift(op, 16), 31)] + else + rm = map_regs.x[band(rshift(op, 16), 31)] + end + x = "["..rn..", "..rm + local opt = band(rshift(op, 13), 7) + local s = band(rshift(op, 12), 1) + local sz = band(rshift(op, 30), 3) + -- extension to be applied + if opt == 3 then + if s == 0 then x = x.."]" + else x = x..", lsl #"..sz.."]" end + elseif opt == 2 or opt == 6 or opt == 7 then + if s == 0 then x = x..", "..map_extend[opt].."]" + else x = x..", "..map_extend[opt].." #"..sz.."]" end + else + x = x.."]" + end + elseif p == "P" then + local opcv, sh = rshift(op, 26), 2 + if opcv >= 0x2a then sh = 4 elseif opcv >= 0x1b then sh = 3 end + local imm7 = lshift(arshift(lshift(op, 10), 25), sh) + local rn = map_regs.x[band(rshift(op, 5), 31)] + local ind = band(rshift(op, 23), 3) + if ind == 1 then + x = "["..rn.."], #"..imm7 + elseif ind == 2 then + if imm7 == 0 then + x = "["..rn.."]" + else + x = "["..rn..", #"..imm7.."]" + end + elseif ind == 3 then + x = "["..rn..", #"..imm7.."]!" + end + elseif p == "I" then + local shf = band(rshift(op, 22), 3) + local imm12 = band(rshift(op, 10), 0x0fff) + local rn, rd = band(rshift(op, 5), 31), band(op, 31) + if altname == "mov" and shf == 0 and imm12 == 0 and (rn == 31 or rd == 31) then + name = altname + x = nil + elseif shf == 0 then + x = imm12 + elseif shf == 1 then + x = imm12..", lsl #12" + end + elseif p == "i" then + x = "#0x"..decode_imm13(op) + elseif p == "1" then + immr = band(rshift(op, 16), 63) + x = immr + elseif p == "2" then + x = band(rshift(op, 10), 63) + if altname then + local a1, a2, a3, a4, a5, a6 = + match(altname, "([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)|(.*)") + local sf = band(rshift(op, 26), 32) + local uns = band(rshift(op, 30), 1) + if prefer_bfx(sf, uns, x, immr) then + name = a2 + x = x - immr + 1 + elseif immr == 0 and x == 7 then + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + name = a6 + x = nil + elseif immr == 0 and x == 15 then + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + name = a5 + x = nil + elseif x == 31 or x == 63 then + if x == 31 and immr == 0 and name == "sbfm" then + name = a4 + local n = #operands + operands[n] = nil + if sf ~= 0 then + operands[n-1] = gsub(operands[n-1], "x", "w") + end + last = operands[n-1] + else + name = a3 + end + x = nil + elseif band(x, 31) ~= 31 and immr == x+1 and name == "ubfm" then + name = a4 + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = nil + elseif x < immr then + name = a1 + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = x + 1 + end + end + elseif p == "3" then + x = band(rshift(op, 10), 63) + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if x < immr then + name = a1 + local sf = band(rshift(op, 26), 32) + last = "#"..(sf+32 - immr) + operands[#operands] = last + x = x + 1 + else + name = a2 + x = x - immr + 1 + end + end + elseif p == "4" then + x = band(rshift(op, 10), 63) + local rn = band(rshift(op, 5), 31) + local rm = band(rshift(op, 16), 31) + if altname and rn == rm then + local n = #operands + operands[n] = nil + last = operands[n-1] + name = altname + end + elseif p == "5" then + x = band(rshift(op, 16), 31) + elseif p == "S" then + x = band(rshift(op, 10), 63) + if x == 0 then x = nil + else x = map_shift[band(rshift(op, 22), 3)].." #"..x end + elseif p == "X" then + local opt = band(rshift(op, 13), 7) + -- Width specifier . + if opt ~= 3 and opt ~= 7 then + last = map_regs.w[band(rshift(op, 16), 31)] + operands[#operands] = last + end + x = band(rshift(op, 10), 7) + -- Extension. + if opt == 2 + band(rshift(op, 31), 1) and + band(rshift(op, second0 and 5 or 0), 31) == 31 then + if x == 0 then x = nil + else x = "lsl #"..x end + else + if x == 0 then x = map_extend[band(rshift(op, 13), 7)] + else x = map_extend[band(rshift(op, 13), 7)].." #"..x end + end + elseif p == "R" then + x = band(rshift(op,21), 3) + if x == 0 then x = nil + else x = "lsl #"..x*16 end + elseif p == "z" then + local n = #operands + if operands[n] == "sp" then operands[n] = "xzr" + elseif operands[n] == "wsp" then operands[n] = "wzr" + end + elseif p == "Z" then + x = 0 + elseif p == "F" then + x = parse_fpimm8(op) + elseif p == "g" or p == "f" or p == "x" or p == "w" or + p == "d" or p == "s" then + -- These are handled in D/N/M/A. + elseif p == "0" then + if last == "sp" or last == "wsp" then + local n = #operands + operands[n] = nil + last = operands[n-1] + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if not a1 then + name = altname + elseif second0 then + name, altname = a2, a1 + else + name, altname = a1, a2 + end + end + end + second0 = true + else + assert(false) + end + if x then + last = x + if type(x) == "number" then x = "#"..x end + operands[#operands+1] = x + end + end + + return putop(ctx, name..suffix, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ctx.pos = ofs + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_regs.x[r] end + return map_regs.d[r-32] +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm64be.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm64be.lua new file mode 100644 index 00000000..edcbffa8 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_arm64be.lua @@ -0,0 +1,12 @@ +---------------------------------------------------------------------------- +-- LuaJIT ARM64BE disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- ARM64 instructions are always little-endian. So just forward to the +-- common ARM64 disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +return require((string.match(..., ".*%.") or "").."dis_arm64") + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips.lua new file mode 100644 index 00000000..6ad17f54 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips.lua @@ -0,0 +1,694 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT/X license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles all standard MIPS32R1/R2 instructions. +-- Default mode is big-endian, but see: dis_mipsel.lua +------------------------------------------------------------------------------ + +local type = type +local byte, format = string.byte, string.format +local match, gmatch = string.match, string.gmatch +local concat = table.concat +local bit = require("bit") +local band, bor, tohex = bit.band, bit.bor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Extended opcode maps common to all MIPS releases +------------------------------------------------------------------------------ + +local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", } +local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", } + +local map_cop0 = { + shift = 25, mask = 1, + [0] = { + shift = 21, mask = 15, + [0] = "mfc0TDW", [4] = "mtc0TDW", + [10] = "rdpgprDT", + [11] = { shift = 5, mask = 1, [0] = "diT0", "eiT0", }, + [14] = "wrpgprDT", + }, { + shift = 0, mask = 63, + [1] = "tlbr", [2] = "tlbwi", [6] = "tlbwr", [8] = "tlbp", + [24] = "eret", [31] = "deret", + [32] = "wait", + }, +} + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps for MIPS R1-R5 +------------------------------------------------------------------------------ + +local map_movci = { shift = 16, mask = 1, [0] = "movfDSC", "movtDSC", } + +local map_special = { + shift = 0, mask = 63, + [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, + map_movci, map_srl, "sraDTA", + "sllvDTS", false, map_srlv, "sravDTS", + "jrS", "jalrD1S", "movzDST", "movnDST", + "syscallY", "breakY", false, "sync", + "mfhiD", "mthiS", "mfloD", "mtloS", + "dsllvDST", false, "dsrlvDST", "dsravDST", + "multST", "multuST", "divST", "divuST", + "dmultST", "dmultuST", "ddivST", "ddivuST", + "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", + "andDST", "or|moveDST0", "xorDST", "nor|notDST0", + false, false, "sltDST", "sltuDST", + "daddDST", "dadduDST", "dsubDST", "dsubuDST", + "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", + "teqSTZ", false, "tneSTZ", false, + "dsllDTA", false, "dsrlDTA", "dsraDTA", + "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", +} + +local map_special2 = { + shift = 0, mask = 63, + [0] = "maddST", "madduST", "mulDST", false, + "msubST", "msubuST", + [32] = "clzDS", [33] = "cloDS", + [63] = "sdbbpY", +} + +local map_bshfl = { + shift = 6, mask = 31, + [2] = "wsbhDT", + [16] = "sebDT", + [24] = "sehDT", +} + +local map_dbshfl = { + shift = 6, mask = 31, + [2] = "dsbhDT", + [5] = "dshdDT", +} + +local map_special3 = { + shift = 0, mask = 63, + [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", + [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", + [32] = map_bshfl, [36] = map_dbshfl, [59] = "rdhwrTD", +} + +local map_regimm = { + shift = 16, mask = 31, + [0] = "bltzSB", "bgezSB", "bltzlSB", "bgezlSB", + false, false, false, false, + "tgeiSI", "tgeiuSI", "tltiSI", "tltiuSI", + "teqiSI", false, "tneiSI", false, + "bltzalSB", "bgezalSB", "bltzallSB", "bgezallSB", + false, false, false, false, + false, false, false, false, + false, false, false, "synciSO", +} + +local map_cop1s = { + shift = 0, mask = 63, + [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", + "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG", + "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG", + "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG", + false, + { shift = 16, mask = 1, [0] = "movf.sFGC", "movt.sFGC" }, + "movz.sFGT", "movn.sFGT", + false, "recip.sFG", "rsqrt.sFG", false, + false, false, false, false, + false, false, false, false, + false, "cvt.d.sFG", false, false, + "cvt.w.sFG", "cvt.l.sFG", "cvt.ps.sFGH", false, + false, false, false, false, + false, false, false, false, + "c.f.sVGH", "c.un.sVGH", "c.eq.sVGH", "c.ueq.sVGH", + "c.olt.sVGH", "c.ult.sVGH", "c.ole.sVGH", "c.ule.sVGH", + "c.sf.sVGH", "c.ngle.sVGH", "c.seq.sVGH", "c.ngl.sVGH", + "c.lt.sVGH", "c.nge.sVGH", "c.le.sVGH", "c.ngt.sVGH", +} + +local map_cop1d = { + shift = 0, mask = 63, + [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH", + "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG", + "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG", + "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG", + false, + { shift = 16, mask = 1, [0] = "movf.dFGC", "movt.dFGC" }, + "movz.dFGT", "movn.dFGT", + false, "recip.dFG", "rsqrt.dFG", false, + false, false, false, false, + false, false, false, false, + "cvt.s.dFG", false, false, false, + "cvt.w.dFG", "cvt.l.dFG", false, false, + false, false, false, false, + false, false, false, false, + "c.f.dVGH", "c.un.dVGH", "c.eq.dVGH", "c.ueq.dVGH", + "c.olt.dVGH", "c.ult.dVGH", "c.ole.dVGH", "c.ule.dVGH", + "c.df.dVGH", "c.ngle.dVGH", "c.deq.dVGH", "c.ngl.dVGH", + "c.lt.dVGH", "c.nge.dVGH", "c.le.dVGH", "c.ngt.dVGH", +} + +local map_cop1ps = { + shift = 0, mask = 63, + [0] = "add.psFGH", "sub.psFGH", "mul.psFGH", false, + false, "abs.psFG", "mov.psFG", "neg.psFG", + false, false, false, false, + false, false, false, false, + false, + { shift = 16, mask = 1, [0] = "movf.psFGC", "movt.psFGC" }, + "movz.psFGT", "movn.psFGT", + false, false, false, false, + false, false, false, false, + false, false, false, false, + "cvt.s.puFG", false, false, false, + false, false, false, false, + "cvt.s.plFG", false, false, false, + "pll.psFGH", "plu.psFGH", "pul.psFGH", "puu.psFGH", + "c.f.psVGH", "c.un.psVGH", "c.eq.psVGH", "c.ueq.psVGH", + "c.olt.psVGH", "c.ult.psVGH", "c.ole.psVGH", "c.ule.psVGH", + "c.psf.psVGH", "c.ngle.psVGH", "c.pseq.psVGH", "c.ngl.psVGH", + "c.lt.psVGH", "c.nge.psVGH", "c.le.psVGH", "c.ngt.psVGH", +} + +local map_cop1w = { + shift = 0, mask = 63, + [32] = "cvt.s.wFG", [33] = "cvt.d.wFG", +} + +local map_cop1l = { + shift = 0, mask = 63, + [32] = "cvt.s.lFG", [33] = "cvt.d.lFG", +} + +local map_cop1bc = { + shift = 16, mask = 3, + [0] = "bc1fCB", "bc1tCB", "bc1flCB", "bc1tlCB", +} + +local map_cop1 = { + shift = 21, mask = 31, + [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", + "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", + map_cop1bc, false, false, false, + false, false, false, false, + map_cop1s, map_cop1d, false, false, + map_cop1w, map_cop1l, map_cop1ps, +} + +local map_cop1x = { + shift = 0, mask = 63, + [0] = "lwxc1FSX", "ldxc1FSX", false, false, + false, "luxc1FSX", false, false, + "swxc1FSX", "sdxc1FSX", false, false, + false, "suxc1FSX", false, "prefxMSX", + false, false, false, false, + false, false, false, false, + false, false, false, false, + false, false, "alnv.psFGHS", false, + "madd.sFRGH", "madd.dFRGH", false, false, + false, false, "madd.psFRGH", false, + "msub.sFRGH", "msub.dFRGH", false, false, + false, false, "msub.psFRGH", false, + "nmadd.sFRGH", "nmadd.dFRGH", false, false, + false, false, "nmadd.psFRGH", false, + "nmsub.sFRGH", "nmsub.dFRGH", false, false, + false, false, "nmsub.psFRGH", false, +} + +local map_pri = { + [0] = map_special, map_regimm, "jJ", "jalJ", + "beq|beqz|bST00B", "bne|bnezST0B", "blezSB", "bgtzSB", + "addiTSI", "addiu|liTS0I", "sltiTSI", "sltiuTSI", + "andiTSU", "ori|liTS0U", "xoriTSU", "luiTU", + map_cop0, map_cop1, false, map_cop1x, + "beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB", + "daddiTSI", "daddiuTSI", false, false, + map_special2, "jalxJ", false, map_special3, + "lbTSO", "lhTSO", "lwlTSO", "lwTSO", + "lbuTSO", "lhuTSO", "lwrTSO", false, + "sbTSO", "shTSO", "swlTSO", "swTSO", + false, false, "swrTSO", "cacheNSO", + "llTSO", "lwc1HSO", "lwc2TSO", "prefNSO", + false, "ldc1HSO", "ldc2TSO", "ldTSO", + "scTSO", "swc1HSO", "swc2TSO", false, + false, "sdc1HSO", "sdc2TSO", "sdTSO", +} + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps for MIPS R6 +------------------------------------------------------------------------------ + +local map_mul_r6 = { shift = 6, mask = 3, [2] = "mulDST", [3] = "muhDST" } +local map_mulu_r6 = { shift = 6, mask = 3, [2] = "muluDST", [3] = "muhuDST" } +local map_div_r6 = { shift = 6, mask = 3, [2] = "divDST", [3] = "modDST" } +local map_divu_r6 = { shift = 6, mask = 3, [2] = "divuDST", [3] = "moduDST" } +local map_dmul_r6 = { shift = 6, mask = 3, [2] = "dmulDST", [3] = "dmuhDST" } +local map_dmulu_r6 = { shift = 6, mask = 3, [2] = "dmuluDST", [3] = "dmuhuDST" } +local map_ddiv_r6 = { shift = 6, mask = 3, [2] = "ddivDST", [3] = "dmodDST" } +local map_ddivu_r6 = { shift = 6, mask = 3, [2] = "ddivuDST", [3] = "dmoduDST" } + +local map_special_r6 = { + shift = 0, mask = 63, + [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, + false, map_srl, "sraDTA", + "sllvDTS", false, map_srlv, "sravDTS", + "jrS", "jalrD1S", false, false, + "syscallY", "breakY", false, "sync", + "clzDS", "cloDS", "dclzDS", "dcloDS", + "dsllvDST", "dlsaDSTA", "dsrlvDST", "dsravDST", + map_mul_r6, map_mulu_r6, map_div_r6, map_divu_r6, + map_dmul_r6, map_dmulu_r6, map_ddiv_r6, map_ddivu_r6, + "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", + "andDST", "or|moveDST0", "xorDST", "nor|notDST0", + false, false, "sltDST", "sltuDST", + "daddDST", "dadduDST", "dsubDST", "dsubuDST", + "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", + "teqSTZ", "seleqzDST", "tneSTZ", "selnezDST", + "dsllDTA", false, "dsrlDTA", "dsraDTA", + "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", +} + +local map_bshfl_r6 = { + shift = 9, mask = 3, + [1] = "alignDSTa", + _ = { + shift = 6, mask = 31, + [0] = "bitswapDT", + [2] = "wsbhDT", + [16] = "sebDT", + [24] = "sehDT", + } +} + +local map_dbshfl_r6 = { + shift = 9, mask = 3, + [1] = "dalignDSTa", + _ = { + shift = 6, mask = 31, + [0] = "dbitswapDT", + [2] = "dsbhDT", + [5] = "dshdDT", + } +} + +local map_special3_r6 = { + shift = 0, mask = 63, + [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", + [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", + [32] = map_bshfl_r6, [36] = map_dbshfl_r6, [59] = "rdhwrTD", +} + +local map_regimm_r6 = { + shift = 16, mask = 31, + [0] = "bltzSB", [1] = "bgezSB", + [6] = "dahiSI", [30] = "datiSI", + [23] = "sigrieI", [31] = "synciSO", +} + +local map_pcrel_r6 = { + shift = 19, mask = 3, + [0] = "addiupcS2", "lwpcS2", "lwupcS2", { + shift = 18, mask = 1, + [0] = "ldpcS3", { shift = 16, mask = 3, [2] = "auipcSI", [3] = "aluipcSI" } + } +} + +local map_cop1s_r6 = { + shift = 0, mask = 63, + [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", + "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG", + "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG", + "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG", + "sel.sFGH", false, false, false, + "seleqz.sFGH", "recip.sFG", "rsqrt.sFG", "selnez.sFGH", + "maddf.sFGH", "msubf.sFGH", "rint.sFG", "class.sFG", + "min.sFGH", "mina.sFGH", "max.sFGH", "maxa.sFGH", + false, "cvt.d.sFG", false, false, + "cvt.w.sFG", "cvt.l.sFG", +} + +local map_cop1d_r6 = { + shift = 0, mask = 63, + [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH", + "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG", + "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG", + "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG", + "sel.dFGH", false, false, false, + "seleqz.dFGH", "recip.dFG", "rsqrt.dFG", "selnez.dFGH", + "maddf.dFGH", "msubf.dFGH", "rint.dFG", "class.dFG", + "min.dFGH", "mina.dFGH", "max.dFGH", "maxa.dFGH", + "cvt.s.dFG", false, false, false, + "cvt.w.dFG", "cvt.l.dFG", +} + +local map_cop1w_r6 = { + shift = 0, mask = 63, + [0] = "cmp.af.sFGH", "cmp.un.sFGH", "cmp.eq.sFGH", "cmp.ueq.sFGH", + "cmp.lt.sFGH", "cmp.ult.sFGH", "cmp.le.sFGH", "cmp.ule.sFGH", + "cmp.saf.sFGH", "cmp.sun.sFGH", "cmp.seq.sFGH", "cmp.sueq.sFGH", + "cmp.slt.sFGH", "cmp.sult.sFGH", "cmp.sle.sFGH", "cmp.sule.sFGH", + false, "cmp.or.sFGH", "cmp.une.sFGH", "cmp.ne.sFGH", + false, false, false, false, + false, "cmp.sor.sFGH", "cmp.sune.sFGH", "cmp.sne.sFGH", + false, false, false, false, + "cvt.s.wFG", "cvt.d.wFG", +} + +local map_cop1l_r6 = { + shift = 0, mask = 63, + [0] = "cmp.af.dFGH", "cmp.un.dFGH", "cmp.eq.dFGH", "cmp.ueq.dFGH", + "cmp.lt.dFGH", "cmp.ult.dFGH", "cmp.le.dFGH", "cmp.ule.dFGH", + "cmp.saf.dFGH", "cmp.sun.dFGH", "cmp.seq.dFGH", "cmp.sueq.dFGH", + "cmp.slt.dFGH", "cmp.sult.dFGH", "cmp.sle.dFGH", "cmp.sule.dFGH", + false, "cmp.or.dFGH", "cmp.une.dFGH", "cmp.ne.dFGH", + false, false, false, false, + false, "cmp.sor.dFGH", "cmp.sune.dFGH", "cmp.sne.dFGH", + false, false, false, false, + "cvt.s.lFG", "cvt.d.lFG", +} + +local map_cop1_r6 = { + shift = 21, mask = 31, + [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", + "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", + false, "bc1eqzHB", false, false, + false, "bc1nezHB", false, false, + map_cop1s_r6, map_cop1d_r6, false, false, + map_cop1w_r6, map_cop1l_r6, +} + +local function maprs_popTS(rs, rt) + if rt == 0 then return 0 elseif rs == 0 then return 1 + elseif rs == rt then return 2 else return 3 end +end + +local map_pop06_r6 = { + maprs = maprs_popTS, [0] = "blezSB", "blezalcTB", "bgezalcTB", "bgeucSTB" +} +local map_pop07_r6 = { + maprs = maprs_popTS, [0] = "bgtzSB", "bgtzalcTB", "bltzalcTB", "bltucSTB" +} +local map_pop26_r6 = { + maprs = maprs_popTS, "blezcTB", "bgezcTB", "bgecSTB" +} +local map_pop27_r6 = { + maprs = maprs_popTS, "bgtzcTB", "bltzcTB", "bltcSTB" +} + +local function maprs_popS(rs, rt) + if rs == 0 then return 0 else return 1 end +end + +local map_pop66_r6 = { + maprs = maprs_popS, [0] = "jicTI", "beqzcSb" +} +local map_pop76_r6 = { + maprs = maprs_popS, [0] = "jialcTI", "bnezcSb" +} + +local function maprs_popST(rs, rt) + if rs >= rt then return 0 elseif rs == 0 then return 1 else return 2 end +end + +local map_pop10_r6 = { + maprs = maprs_popST, [0] = "bovcSTB", "beqzalcTB", "beqcSTB" +} +local map_pop30_r6 = { + maprs = maprs_popST, [0] = "bnvcSTB", "bnezalcTB", "bnecSTB" +} + +local map_pri_r6 = { + [0] = map_special_r6, map_regimm_r6, "jJ", "jalJ", + "beq|beqz|bST00B", "bne|bnezST0B", map_pop06_r6, map_pop07_r6, + map_pop10_r6, "addiu|liTS0I", "sltiTSI", "sltiuTSI", + "andiTSU", "ori|liTS0U", "xoriTSU", "aui|luiTS0U", + map_cop0, map_cop1_r6, false, false, + false, false, map_pop26_r6, map_pop27_r6, + map_pop30_r6, "daddiuTSI", false, false, + false, "dauiTSI", false, map_special3_r6, + "lbTSO", "lhTSO", false, "lwTSO", + "lbuTSO", "lhuTSO", false, false, + "sbTSO", "shTSO", false, "swTSO", + false, false, false, false, + false, "lwc1HSO", "bc#", false, + false, "ldc1HSO", map_pop66_r6, "ldTSO", + false, "swc1HSO", "balc#", map_pcrel_r6, + false, "sdc1HSO", map_pop76_r6, "sdTSO", +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "sp", "r30", "ra", +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then extra = "\t->"..sym end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-7s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-7s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +local function get_be(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + return bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3) +end + +local function get_le(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + return bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local op = ctx:get() + local operands = {} + local last = nil + ctx.op = op + ctx.rel = nil + + local opat = ctx.map_pri[rshift(op, 26)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + if opat.maprs then + opat = opat[opat.maprs(band(rshift(op,21),31), band(rshift(op,16),31))] + else + opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ + end + end + local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") + if altname then pat = pat2 end + + for p in gmatch(pat, ".") do + local x = nil + if p == "S" then + x = map_gpr[band(rshift(op, 21), 31)] + elseif p == "T" then + x = map_gpr[band(rshift(op, 16), 31)] + elseif p == "D" then + x = map_gpr[band(rshift(op, 11), 31)] + elseif p == "F" then + x = "f"..band(rshift(op, 6), 31) + elseif p == "G" then + x = "f"..band(rshift(op, 11), 31) + elseif p == "H" then + x = "f"..band(rshift(op, 16), 31) + elseif p == "R" then + x = "f"..band(rshift(op, 21), 31) + elseif p == "A" then + x = band(rshift(op, 6), 31) + elseif p == "a" then + x = band(rshift(op, 6), 7) + elseif p == "E" then + x = band(rshift(op, 6), 31) + 32 + elseif p == "M" then + x = band(rshift(op, 11), 31) + elseif p == "N" then + x = band(rshift(op, 16), 31) + elseif p == "C" then + x = band(rshift(op, 18), 7) + if x == 0 then x = nil end + elseif p == "K" then + x = band(rshift(op, 11), 31) + 1 + elseif p == "P" then + x = band(rshift(op, 11), 31) + 33 + elseif p == "L" then + x = band(rshift(op, 11), 31) - last + 1 + elseif p == "Q" then + x = band(rshift(op, 11), 31) - last + 33 + elseif p == "I" then + x = arshift(lshift(op, 16), 16) + elseif p == "2" then + x = arshift(lshift(op, 13), 11) + elseif p == "3" then + x = arshift(lshift(op, 14), 11) + elseif p == "U" then + x = band(op, 0xffff) + elseif p == "O" then + local disp = arshift(lshift(op, 16), 16) + operands[#operands] = format("%d(%s)", disp, last) + elseif p == "X" then + local index = map_gpr[band(rshift(op, 16), 31)] + operands[#operands] = format("%s(%s)", index, last) + elseif p == "B" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 14) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "b" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 11), 9) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "#" then + x = ctx.addr + ctx.pos + arshift(lshift(op, 6), 4) + 4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "J" then + local a = ctx.addr + ctx.pos + x = a - band(a, 0x0fffffff) + band(op, 0x03ffffff)*4 + ctx.rel = x + x = format("0x%08x", x) + elseif p == "V" then + x = band(rshift(op, 8), 7) + if x == 0 then x = nil end + elseif p == "W" then + x = band(op, 7) + if x == 0 then x = nil end + elseif p == "Y" then + x = band(rshift(op, 6), 0x000fffff) + if x == 0 then x = nil end + elseif p == "Z" then + x = band(rshift(op, 6), 1023) + if x == 0 then x = nil end + elseif p == "0" then + if last == "r0" or last == 0 then + local n = #operands + operands[n] = nil + last = operands[n-1] + if altname then + local a1, a2 = match(altname, "([^|]*)|(.*)") + if a1 then name, altname = a1, a2 + else name = altname end + end + end + elseif p == "1" then + if last == "ra" then + operands[#operands] = nil + end + else + assert(false) + end + if x then operands[#operands+1] = x; last = x end + end + + return putop(ctx, name, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + stop = stop - stop % 4 + ctx.pos = ofs - ofs % 4 + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + ctx.get = get_be + ctx.map_pri = map_pri + return ctx +end + +local function create_el(code, addr, out) + local ctx = create(code, addr, out) + ctx.get = get_le + return ctx +end + +local function create_r6(code, addr, out) + local ctx = create(code, addr, out) + ctx.map_pri = map_pri_r6 + return ctx +end + +local function create_r6_el(code, addr, out) + local ctx = create(code, addr, out) + ctx.get = get_le + ctx.map_pri = map_pri_r6 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +local function disass_el(code, addr, out) + create_el(code, addr, out):disass() +end + +local function disass_r6(code, addr, out) + create_r6(code, addr, out):disass() +end + +local function disass_r6_el(code, addr, out) + create_r6_el(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_gpr[r] end + return "f"..(r-32) +end + +-- Public module functions. +return { + create = create, + create_el = create_el, + create_r6 = create_r6, + create_r6_el = create_r6_el, + disass = disass, + disass_el = disass_el, + disass_r6 = disass_r6, + disass_r6_el = disass_r6_el, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64.lua new file mode 100644 index 00000000..5ad48f8f --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the big-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create, + disass = dis_mips.disass, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64el.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64el.lua new file mode 100644 index 00000000..d50e3a18 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64el.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64EL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_el, + disass = dis_mips.disass_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64r6.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64r6.lua new file mode 100644 index 00000000..921b3cbe --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64r6.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64R6 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the r6 big-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_r6, + disass = dis_mips.disass_r6, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64r6el.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64r6el.lua new file mode 100644 index 00000000..aadef9f3 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mips64r6el.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPS64R6EL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the r6 little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_r6_el, + disass = dis_mips.disass_r6_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mipsel.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mipsel.lua new file mode 100644 index 00000000..52cebefb --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_mipsel.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT MIPSEL disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the little-endian functions from the +-- MIPS disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") +return { + create = dis_mips.create_el, + disass = dis_mips.disass_el, + regname = dis_mips.regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_ppc.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_ppc.lua new file mode 100644 index 00000000..08d742f1 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_ppc.lua @@ -0,0 +1,591 @@ +---------------------------------------------------------------------------- +-- LuaJIT PPC disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT/X license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- It disassembles all common, non-privileged 32/64 bit PowerPC instructions +-- plus the e500 SPE instructions and some Cell/Xenon extensions. +-- +-- NYI: VMX, VMX128 +------------------------------------------------------------------------------ + +local type = type +local byte, format = string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local concat = table.concat +local bit = require("bit") +local band, bor, tohex = bit.band, bit.bor, bit.tohex +local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift + +------------------------------------------------------------------------------ +-- Primary and extended opcode maps +------------------------------------------------------------------------------ + +local map_crops = { + shift = 1, mask = 1023, + [0] = "mcrfXX", + [33] = "crnor|crnotCCC=", [129] = "crandcCCC", + [193] = "crxor|crclrCCC%", [225] = "crnandCCC", + [257] = "crandCCC", [289] = "creqv|crsetCCC%", + [417] = "crorcCCC", [449] = "cror|crmoveCCC=", + [16] = "b_lrKB", [528] = "b_ctrKB", + [150] = "isync", +} + +local map_rlwinm = setmetatable({ + shift = 0, mask = -1, +}, +{ __index = function(t, x) + local rot = band(rshift(x, 11), 31) + local mb = band(rshift(x, 6), 31) + local me = band(rshift(x, 1), 31) + if mb == 0 and me == 31-rot then + return "slwiRR~A." + elseif me == 31 and mb == 32-rot then + return "srwiRR~-A." + else + return "rlwinmRR~AAA." + end + end +}) + +local map_rld = { + shift = 2, mask = 7, + [0] = "rldiclRR~HM.", "rldicrRR~HM.", "rldicRR~HM.", "rldimiRR~HM.", + { + shift = 1, mask = 1, + [0] = "rldclRR~RM.", "rldcrRR~RM.", + }, +} + +local map_ext = setmetatable({ + shift = 1, mask = 1023, + + [0] = "cmp_YLRR", [32] = "cmpl_YLRR", + [4] = "twARR", [68] = "tdARR", + + [8] = "subfcRRR.", [40] = "subfRRR.", + [104] = "negRR.", [136] = "subfeRRR.", + [200] = "subfzeRR.", [232] = "subfmeRR.", + [520] = "subfcoRRR.", [552] = "subfoRRR.", + [616] = "negoRR.", [648] = "subfeoRRR.", + [712] = "subfzeoRR.", [744] = "subfmeoRR.", + + [9] = "mulhduRRR.", [73] = "mulhdRRR.", [233] = "mulldRRR.", + [457] = "divduRRR.", [489] = "divdRRR.", + [745] = "mulldoRRR.", + [969] = "divduoRRR.", [1001] = "divdoRRR.", + + [10] = "addcRRR.", [138] = "addeRRR.", + [202] = "addzeRR.", [234] = "addmeRR.", [266] = "addRRR.", + [522] = "addcoRRR.", [650] = "addeoRRR.", + [714] = "addzeoRR.", [746] = "addmeoRR.", [778] = "addoRRR.", + + [11] = "mulhwuRRR.", [75] = "mulhwRRR.", [235] = "mullwRRR.", + [459] = "divwuRRR.", [491] = "divwRRR.", + [747] = "mullwoRRR.", + [971] = "divwouRRR.", [1003] = "divwoRRR.", + + [15] = "iselltRRR", [47] = "iselgtRRR", [79] = "iseleqRRR", + + [144] = { shift = 20, mask = 1, [0] = "mtcrfRZ~", "mtocrfRZ~", }, + [19] = { shift = 20, mask = 1, [0] = "mfcrR", "mfocrfRZ", }, + [371] = { shift = 11, mask = 1023, [392] = "mftbR", [424] = "mftbuR", }, + [339] = { + shift = 11, mask = 1023, + [32] = "mferR", [256] = "mflrR", [288] = "mfctrR", [16] = "mfspefscrR", + }, + [467] = { + shift = 11, mask = 1023, + [32] = "mtxerR", [256] = "mtlrR", [288] = "mtctrR", [16] = "mtspefscrR", + }, + + [20] = "lwarxRR0R", [84] = "ldarxRR0R", + + [21] = "ldxRR0R", [53] = "lduxRRR", + [149] = "stdxRR0R", [181] = "stduxRRR", + [341] = "lwaxRR0R", [373] = "lwauxRRR", + + [23] = "lwzxRR0R", [55] = "lwzuxRRR", + [87] = "lbzxRR0R", [119] = "lbzuxRRR", + [151] = "stwxRR0R", [183] = "stwuxRRR", + [215] = "stbxRR0R", [247] = "stbuxRRR", + [279] = "lhzxRR0R", [311] = "lhzuxRRR", + [343] = "lhaxRR0R", [375] = "lhauxRRR", + [407] = "sthxRR0R", [439] = "sthuxRRR", + + [54] = "dcbst-R0R", [86] = "dcbf-R0R", + [150] = "stwcxRR0R.", [214] = "stdcxRR0R.", + [246] = "dcbtst-R0R", [278] = "dcbt-R0R", + [310] = "eciwxRR0R", [438] = "ecowxRR0R", + [470] = "dcbi-RR", + + [598] = { + shift = 21, mask = 3, + [0] = "sync", "lwsync", "ptesync", + }, + [758] = "dcba-RR", + [854] = "eieio", [982] = "icbi-R0R", [1014] = "dcbz-R0R", + + [26] = "cntlzwRR~", [58] = "cntlzdRR~", + [122] = "popcntbRR~", + [154] = "prtywRR~", [186] = "prtydRR~", + + [28] = "andRR~R.", [60] = "andcRR~R.", [124] = "nor|notRR~R=.", + [284] = "eqvRR~R.", [316] = "xorRR~R.", + [412] = "orcRR~R.", [444] = "or|mrRR~R=.", [476] = "nandRR~R.", + [508] = "cmpbRR~R", + + [512] = "mcrxrX", + + [532] = "ldbrxRR0R", [660] = "stdbrxRR0R", + + [533] = "lswxRR0R", [597] = "lswiRR0A", + [661] = "stswxRR0R", [725] = "stswiRR0A", + + [534] = "lwbrxRR0R", [662] = "stwbrxRR0R", + [790] = "lhbrxRR0R", [918] = "sthbrxRR0R", + + [535] = "lfsxFR0R", [567] = "lfsuxFRR", + [599] = "lfdxFR0R", [631] = "lfduxFRR", + [663] = "stfsxFR0R", [695] = "stfsuxFRR", + [727] = "stfdxFR0R", [759] = "stfduxFR0R", + [855] = "lfiwaxFR0R", + [983] = "stfiwxFR0R", + + [24] = "slwRR~R.", + + [27] = "sldRR~R.", [536] = "srwRR~R.", + [792] = "srawRR~R.", [824] = "srawiRR~A.", + + [794] = "sradRR~R.", [826] = "sradiRR~H.", [827] = "sradiRR~H.", + [922] = "extshRR~.", [954] = "extsbRR~.", [986] = "extswRR~.", + + [539] = "srdRR~R.", +}, +{ __index = function(t, x) + if band(x, 31) == 15 then return "iselRRRC" end + end +}) + +local map_ld = { + shift = 0, mask = 3, + [0] = "ldRRE", "lduRRE", "lwaRRE", +} + +local map_std = { + shift = 0, mask = 3, + [0] = "stdRRE", "stduRRE", +} + +local map_fps = { + shift = 5, mask = 1, + { + shift = 1, mask = 15, + [0] = false, false, "fdivsFFF.", false, + "fsubsFFF.", "faddsFFF.", "fsqrtsF-F.", false, + "fresF-F.", "fmulsFF-F.", "frsqrtesF-F.", false, + "fmsubsFFFF~.", "fmaddsFFFF~.", "fnmsubsFFFF~.", "fnmaddsFFFF~.", + } +} + +local map_fpd = { + shift = 5, mask = 1, + [0] = { + shift = 1, mask = 1023, + [0] = "fcmpuXFF", [32] = "fcmpoXFF", [64] = "mcrfsXX", + [38] = "mtfsb1A.", [70] = "mtfsb0A.", [134] = "mtfsfiA>>-A>", + [8] = "fcpsgnFFF.", [40] = "fnegF-F.", [72] = "fmrF-F.", + [136] = "fnabsF-F.", [264] = "fabsF-F.", + [12] = "frspF-F.", + [14] = "fctiwF-F.", [15] = "fctiwzF-F.", + [583] = "mffsF.", [711] = "mtfsfZF.", + [392] = "frinF-F.", [424] = "frizF-F.", + [456] = "fripF-F.", [488] = "frimF-F.", + [814] = "fctidF-F.", [815] = "fctidzF-F.", [846] = "fcfidF-F.", + }, + { + shift = 1, mask = 15, + [0] = false, false, "fdivFFF.", false, + "fsubFFF.", "faddFFF.", "fsqrtF-F.", "fselFFFF~.", + "freF-F.", "fmulFF-F.", "frsqrteF-F.", false, + "fmsubFFFF~.", "fmaddFFFF~.", "fnmsubFFFF~.", "fnmaddFFFF~.", + } +} + +local map_spe = { + shift = 0, mask = 2047, + + [512] = "evaddwRRR", [514] = "evaddiwRAR~", + [516] = "evsubwRRR~", [518] = "evsubiwRAR~", + [520] = "evabsRR", [521] = "evnegRR", + [522] = "evextsbRR", [523] = "evextshRR", [524] = "evrndwRR", + [525] = "evcntlzwRR", [526] = "evcntlswRR", + + [527] = "brincRRR", + + [529] = "evandRRR", [530] = "evandcRRR", [534] = "evxorRRR", + [535] = "evor|evmrRRR=", [536] = "evnor|evnotRRR=", + [537] = "eveqvRRR", [539] = "evorcRRR", [542] = "evnandRRR", + + [544] = "evsrwuRRR", [545] = "evsrwsRRR", + [546] = "evsrwiuRRA", [547] = "evsrwisRRA", + [548] = "evslwRRR", [550] = "evslwiRRA", + [552] = "evrlwRRR", [553] = "evsplatiRS", + [554] = "evrlwiRRA", [555] = "evsplatfiRS", + [556] = "evmergehiRRR", [557] = "evmergeloRRR", + [558] = "evmergehiloRRR", [559] = "evmergelohiRRR", + + [560] = "evcmpgtuYRR", [561] = "evcmpgtsYRR", + [562] = "evcmpltuYRR", [563] = "evcmpltsYRR", + [564] = "evcmpeqYRR", + + [632] = "evselRRR", [633] = "evselRRRW", + [634] = "evselRRRW", [635] = "evselRRRW", + [636] = "evselRRRW", [637] = "evselRRRW", + [638] = "evselRRRW", [639] = "evselRRRW", + + [640] = "evfsaddRRR", [641] = "evfssubRRR", + [644] = "evfsabsRR", [645] = "evfsnabsRR", [646] = "evfsnegRR", + [648] = "evfsmulRRR", [649] = "evfsdivRRR", + [652] = "evfscmpgtYRR", [653] = "evfscmpltYRR", [654] = "evfscmpeqYRR", + [656] = "evfscfuiR-R", [657] = "evfscfsiR-R", + [658] = "evfscfufR-R", [659] = "evfscfsfR-R", + [660] = "evfsctuiR-R", [661] = "evfsctsiR-R", + [662] = "evfsctufR-R", [663] = "evfsctsfR-R", + [664] = "evfsctuizR-R", [666] = "evfsctsizR-R", + [668] = "evfststgtYRR", [669] = "evfststltYRR", [670] = "evfststeqYRR", + + [704] = "efsaddRRR", [705] = "efssubRRR", + [708] = "efsabsRR", [709] = "efsnabsRR", [710] = "efsnegRR", + [712] = "efsmulRRR", [713] = "efsdivRRR", + [716] = "efscmpgtYRR", [717] = "efscmpltYRR", [718] = "efscmpeqYRR", + [719] = "efscfdR-R", + [720] = "efscfuiR-R", [721] = "efscfsiR-R", + [722] = "efscfufR-R", [723] = "efscfsfR-R", + [724] = "efsctuiR-R", [725] = "efsctsiR-R", + [726] = "efsctufR-R", [727] = "efsctsfR-R", + [728] = "efsctuizR-R", [730] = "efsctsizR-R", + [732] = "efststgtYRR", [733] = "efststltYRR", [734] = "efststeqYRR", + + [736] = "efdaddRRR", [737] = "efdsubRRR", + [738] = "efdcfuidR-R", [739] = "efdcfsidR-R", + [740] = "efdabsRR", [741] = "efdnabsRR", [742] = "efdnegRR", + [744] = "efdmulRRR", [745] = "efddivRRR", + [746] = "efdctuidzR-R", [747] = "efdctsidzR-R", + [748] = "efdcmpgtYRR", [749] = "efdcmpltYRR", [750] = "efdcmpeqYRR", + [751] = "efdcfsR-R", + [752] = "efdcfuiR-R", [753] = "efdcfsiR-R", + [754] = "efdcfufR-R", [755] = "efdcfsfR-R", + [756] = "efdctuiR-R", [757] = "efdctsiR-R", + [758] = "efdctufR-R", [759] = "efdctsfR-R", + [760] = "efdctuizR-R", [762] = "efdctsizR-R", + [764] = "efdtstgtYRR", [765] = "efdtstltYRR", [766] = "efdtsteqYRR", + + [768] = "evlddxRR0R", [769] = "evlddRR8", + [770] = "evldwxRR0R", [771] = "evldwRR8", + [772] = "evldhxRR0R", [773] = "evldhRR8", + [776] = "evlhhesplatxRR0R", [777] = "evlhhesplatRR2", + [780] = "evlhhousplatxRR0R", [781] = "evlhhousplatRR2", + [782] = "evlhhossplatxRR0R", [783] = "evlhhossplatRR2", + [784] = "evlwhexRR0R", [785] = "evlwheRR4", + [788] = "evlwhouxRR0R", [789] = "evlwhouRR4", + [790] = "evlwhosxRR0R", [791] = "evlwhosRR4", + [792] = "evlwwsplatxRR0R", [793] = "evlwwsplatRR4", + [796] = "evlwhsplatxRR0R", [797] = "evlwhsplatRR4", + + [800] = "evstddxRR0R", [801] = "evstddRR8", + [802] = "evstdwxRR0R", [803] = "evstdwRR8", + [804] = "evstdhxRR0R", [805] = "evstdhRR8", + [816] = "evstwhexRR0R", [817] = "evstwheRR4", + [820] = "evstwhoxRR0R", [821] = "evstwhoRR4", + [824] = "evstwwexRR0R", [825] = "evstwweRR4", + [828] = "evstwwoxRR0R", [829] = "evstwwoRR4", + + [1027] = "evmhessfRRR", [1031] = "evmhossfRRR", [1032] = "evmheumiRRR", + [1033] = "evmhesmiRRR", [1035] = "evmhesmfRRR", [1036] = "evmhoumiRRR", + [1037] = "evmhosmiRRR", [1039] = "evmhosmfRRR", [1059] = "evmhessfaRRR", + [1063] = "evmhossfaRRR", [1064] = "evmheumiaRRR", [1065] = "evmhesmiaRRR", + [1067] = "evmhesmfaRRR", [1068] = "evmhoumiaRRR", [1069] = "evmhosmiaRRR", + [1071] = "evmhosmfaRRR", [1095] = "evmwhssfRRR", [1096] = "evmwlumiRRR", + [1100] = "evmwhumiRRR", [1101] = "evmwhsmiRRR", [1103] = "evmwhsmfRRR", + [1107] = "evmwssfRRR", [1112] = "evmwumiRRR", [1113] = "evmwsmiRRR", + [1115] = "evmwsmfRRR", [1127] = "evmwhssfaRRR", [1128] = "evmwlumiaRRR", + [1132] = "evmwhumiaRRR", [1133] = "evmwhsmiaRRR", [1135] = "evmwhsmfaRRR", + [1139] = "evmwssfaRRR", [1144] = "evmwumiaRRR", [1145] = "evmwsmiaRRR", + [1147] = "evmwsmfaRRR", + + [1216] = "evaddusiaawRR", [1217] = "evaddssiaawRR", + [1218] = "evsubfusiaawRR", [1219] = "evsubfssiaawRR", + [1220] = "evmraRR", + [1222] = "evdivwsRRR", [1223] = "evdivwuRRR", + [1224] = "evaddumiaawRR", [1225] = "evaddsmiaawRR", + [1226] = "evsubfumiaawRR", [1227] = "evsubfsmiaawRR", + + [1280] = "evmheusiaawRRR", [1281] = "evmhessiaawRRR", + [1283] = "evmhessfaawRRR", [1284] = "evmhousiaawRRR", + [1285] = "evmhossiaawRRR", [1287] = "evmhossfaawRRR", + [1288] = "evmheumiaawRRR", [1289] = "evmhesmiaawRRR", + [1291] = "evmhesmfaawRRR", [1292] = "evmhoumiaawRRR", + [1293] = "evmhosmiaawRRR", [1295] = "evmhosmfaawRRR", + [1320] = "evmhegumiaaRRR", [1321] = "evmhegsmiaaRRR", + [1323] = "evmhegsmfaaRRR", [1324] = "evmhogumiaaRRR", + [1325] = "evmhogsmiaaRRR", [1327] = "evmhogsmfaaRRR", + [1344] = "evmwlusiaawRRR", [1345] = "evmwlssiaawRRR", + [1352] = "evmwlumiaawRRR", [1353] = "evmwlsmiaawRRR", + [1363] = "evmwssfaaRRR", [1368] = "evmwumiaaRRR", + [1369] = "evmwsmiaaRRR", [1371] = "evmwsmfaaRRR", + [1408] = "evmheusianwRRR", [1409] = "evmhessianwRRR", + [1411] = "evmhessfanwRRR", [1412] = "evmhousianwRRR", + [1413] = "evmhossianwRRR", [1415] = "evmhossfanwRRR", + [1416] = "evmheumianwRRR", [1417] = "evmhesmianwRRR", + [1419] = "evmhesmfanwRRR", [1420] = "evmhoumianwRRR", + [1421] = "evmhosmianwRRR", [1423] = "evmhosmfanwRRR", + [1448] = "evmhegumianRRR", [1449] = "evmhegsmianRRR", + [1451] = "evmhegsmfanRRR", [1452] = "evmhogumianRRR", + [1453] = "evmhogsmianRRR", [1455] = "evmhogsmfanRRR", + [1472] = "evmwlusianwRRR", [1473] = "evmwlssianwRRR", + [1480] = "evmwlumianwRRR", [1481] = "evmwlsmianwRRR", + [1491] = "evmwssfanRRR", [1496] = "evmwumianRRR", + [1497] = "evmwsmianRRR", [1499] = "evmwsmfanRRR", +} + +local map_pri = { + [0] = false, false, "tdiARI", "twiARI", + map_spe, false, false, "mulliRRI", + "subficRRI", false, "cmpl_iYLRU", "cmp_iYLRI", + "addicRRI", "addic.RRI", "addi|liRR0I", "addis|lisRR0I", + "b_KBJ", "sc", "bKJ", map_crops, + "rlwimiRR~AAA.", map_rlwinm, false, "rlwnmRR~RAA.", + "oriNRR~U", "orisRR~U", "xoriRR~U", "xorisRR~U", + "andi.RR~U", "andis.RR~U", map_rld, map_ext, + "lwzRRD", "lwzuRRD", "lbzRRD", "lbzuRRD", + "stwRRD", "stwuRRD", "stbRRD", "stbuRRD", + "lhzRRD", "lhzuRRD", "lhaRRD", "lhauRRD", + "sthRRD", "sthuRRD", "lmwRRD", "stmwRRD", + "lfsFRD", "lfsuFRD", "lfdFRD", "lfduFRD", + "stfsFRD", "stfsuFRD", "stfdFRD", "stfduFRD", + false, false, map_ld, map_fps, + false, false, map_std, map_fpd, +} + +------------------------------------------------------------------------------ + +local map_gpr = { + [0] = "r0", "sp", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", +} + +local map_cond = { [0] = "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", } + +-- Format a condition bit. +local function condfmt(cond) + if cond <= 3 then + return map_cond[band(cond, 3)] + else + return format("4*cr%d+%s", rshift(cond, 2), map_cond[band(cond, 3)]) + end +end + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local pos = ctx.pos + local extra = "" + if ctx.rel then + local sym = ctx.symtab[ctx.rel] + if sym then extra = "\t->"..sym end + end + if ctx.hexdump > 0 then + ctx.out(format("%08x %s %-7s %s%s\n", + ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) + else + ctx.out(format("%08x %-7s %s%s\n", + ctx.addr+pos, text, concat(operands, ", "), extra)) + end + ctx.pos = pos + 4 +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) +end + +-- Disassemble a single instruction. +local function disass_ins(ctx) + local pos = ctx.pos + local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) + local op = bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3) + local operands = {} + local last = nil + local rs = 21 + ctx.op = op + ctx.rel = nil + + local opat = map_pri[rshift(b0, 2)] + while type(opat) ~= "string" do + if not opat then return unknown(ctx) end + opat = opat[band(rshift(op, opat.shift), opat.mask)] + end + local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") + local altname, pat2 = match(pat, "|([a-z0-9_.]*)(.*)") + if altname then pat = pat2 end + + for p in gmatch(pat, ".") do + local x = nil + if p == "R" then + x = map_gpr[band(rshift(op, rs), 31)] + rs = rs - 5 + elseif p == "F" then + x = "f"..band(rshift(op, rs), 31) + rs = rs - 5 + elseif p == "A" then + x = band(rshift(op, rs), 31) + rs = rs - 5 + elseif p == "S" then + x = arshift(lshift(op, 27-rs), 27) + rs = rs - 5 + elseif p == "I" then + x = arshift(lshift(op, 16), 16) + elseif p == "U" then + x = band(op, 0xffff) + elseif p == "D" or p == "E" then + local disp = arshift(lshift(op, 16), 16) + if p == "E" then disp = band(disp, -4) end + if last == "r0" then last = "0" end + operands[#operands] = format("%d(%s)", disp, last) + elseif p >= "2" and p <= "8" then + local disp = band(rshift(op, rs), 31) * p + if last == "r0" then last = "0" end + operands[#operands] = format("%d(%s)", disp, last) + elseif p == "H" then + x = band(rshift(op, rs), 31) + lshift(band(op, 2), 4) + rs = rs - 5 + elseif p == "M" then + x = band(rshift(op, rs), 31) + band(op, 0x20) + elseif p == "C" then + x = condfmt(band(rshift(op, rs), 31)) + rs = rs - 5 + elseif p == "B" then + local bo = rshift(op, 21) + local cond = band(rshift(op, 16), 31) + local cn = "" + rs = rs - 10 + if band(bo, 4) == 0 then + cn = band(bo, 2) == 0 and "dnz" or "dz" + if band(bo, 0x10) == 0 then + cn = cn..(band(bo, 8) == 0 and "f" or "t") + end + if band(bo, 0x10) == 0 then x = condfmt(cond) end + name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+") + elseif band(bo, 0x10) == 0 then + cn = map_cond[band(cond, 3) + (band(bo, 8) == 0 and 4 or 0)] + if cond > 3 then x = "cr"..rshift(cond, 2) end + name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+") + end + name = gsub(name, "_", cn) + elseif p == "J" then + x = arshift(lshift(op, 27-rs), 29-rs)*4 + if band(op, 2) == 0 then x = ctx.addr + pos + x end + ctx.rel = x + x = "0x"..tohex(x) + elseif p == "K" then + if band(op, 1) ~= 0 then name = name.."l" end + if band(op, 2) ~= 0 then name = name.."a" end + elseif p == "X" or p == "Y" then + x = band(rshift(op, rs+2), 7) + if x == 0 and p == "Y" then x = nil else x = "cr"..x end + rs = rs - 5 + elseif p == "W" then + x = "cr"..band(op, 7) + elseif p == "Z" then + x = band(rshift(op, rs-4), 255) + rs = rs - 10 + elseif p == ">" then + operands[#operands] = rshift(operands[#operands], 1) + elseif p == "0" then + if last == "r0" then + operands[#operands] = nil + if altname then name = altname end + end + elseif p == "L" then + name = gsub(name, "_", band(op, 0x00200000) ~= 0 and "d" or "w") + elseif p == "." then + if band(op, 1) == 1 then name = name.."." end + elseif p == "N" then + if op == 0x60000000 then name = "nop"; break end + elseif p == "~" then + local n = #operands + operands[n-1], operands[n] = operands[n], operands[n-1] + elseif p == "=" then + local n = #operands + if last == operands[n-1] then + operands[n] = nil + name = altname + end + elseif p == "%" then + local n = #operands + if last == operands[n-1] and last == operands[n-2] then + operands[n] = nil + operands[n-1] = nil + name = altname + end + elseif p == "-" then + rs = rs - 5 + else + assert(false) + end + if x then operands[#operands+1] = x; last = x end + end + + return putop(ctx, name, operands) +end + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + stop = stop - stop % 4 + ctx.pos = ofs - ofs % 4 + ctx.rel = nil + while ctx.pos < stop do disass_ins(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = addr or 0 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 8 + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 32 then return map_gpr[r] end + return "f"..(r-32) +end + +-- Public module functions. +return { + create = create, + disass = disass, + regname = regname +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_x64.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_x64.lua new file mode 100644 index 00000000..2d37423e --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_x64.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT x64 disassembler wrapper module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This module just exports the 64 bit functions from the combined +-- x86/x64 disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_x86 = require((string.match(..., ".*%.") or "").."dis_x86") +return { + create = dis_x86.create64, + disass = dis_x86.disass64, + regname = dis_x86.regname64 +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_x86.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_x86.lua new file mode 100644 index 00000000..5480854c --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dis_x86.lua @@ -0,0 +1,953 @@ +---------------------------------------------------------------------------- +-- LuaJIT x86/x64 disassembler module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- This is a helper module used by the LuaJIT machine code dumper module. +-- +-- Sending small code snippets to an external disassembler and mixing the +-- output with our own stuff was too fragile. So I had to bite the bullet +-- and write yet another x86 disassembler. Oh well ... +-- +-- The output format is very similar to what ndisasm generates. But it has +-- been developed independently by looking at the opcode tables from the +-- Intel and AMD manuals. The supported instruction set is quite extensive +-- and reflects what a current generation Intel or AMD CPU implements in +-- 32 bit and 64 bit mode. Yes, this includes MMX, SSE, SSE2, SSE3, SSSE3, +-- SSE4.1, SSE4.2, SSE4a, AVX, AVX2 and even privileged and hypervisor +-- (VMX/SVM) instructions. +-- +-- Notes: +-- * The (useless) a16 prefix, 3DNow and pre-586 opcodes are unsupported. +-- * No attempt at optimization has been made -- it's fast enough for my needs. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local lower, rep = string.lower, string.rep +local bit = require("bit") +local tohex = bit.tohex + +-- Map for 1st opcode byte in 32 bit mode. Ugly? Well ... read on. +local map_opc1_32 = { +--0x +[0]="addBmr","addVmr","addBrm","addVrm","addBai","addVai","push es","pop es", +"orBmr","orVmr","orBrm","orVrm","orBai","orVai","push cs","opc2*", +--1x +"adcBmr","adcVmr","adcBrm","adcVrm","adcBai","adcVai","push ss","pop ss", +"sbbBmr","sbbVmr","sbbBrm","sbbVrm","sbbBai","sbbVai","push ds","pop ds", +--2x +"andBmr","andVmr","andBrm","andVrm","andBai","andVai","es:seg","daa", +"subBmr","subVmr","subBrm","subVrm","subBai","subVai","cs:seg","das", +--3x +"xorBmr","xorVmr","xorBrm","xorVrm","xorBai","xorVai","ss:seg","aaa", +"cmpBmr","cmpVmr","cmpBrm","cmpVrm","cmpBai","cmpVai","ds:seg","aas", +--4x +"incVR","incVR","incVR","incVR","incVR","incVR","incVR","incVR", +"decVR","decVR","decVR","decVR","decVR","decVR","decVR","decVR", +--5x +"pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR", +"popUR","popUR","popUR","popUR","popUR","popUR","popUR","popUR", +--6x +"sz*pushaw,pusha","sz*popaw,popa","boundVrm","arplWmr", +"fs:seg","gs:seg","o16:","a16", +"pushUi","imulVrmi","pushBs","imulVrms", +"insb","insVS","outsb","outsVS", +--7x +"joBj","jnoBj","jbBj","jnbBj","jzBj","jnzBj","jbeBj","jaBj", +"jsBj","jnsBj","jpeBj","jpoBj","jlBj","jgeBj","jleBj","jgBj", +--8x +"arith!Bmi","arith!Vmi","arith!Bmi","arith!Vms", +"testBmr","testVmr","xchgBrm","xchgVrm", +"movBmr","movVmr","movBrm","movVrm", +"movVmg","leaVrm","movWgm","popUm", +--9x +"nop*xchgVaR|pause|xchgWaR|repne nop","xchgVaR","xchgVaR","xchgVaR", +"xchgVaR","xchgVaR","xchgVaR","xchgVaR", +"sz*cbw,cwde,cdqe","sz*cwd,cdq,cqo","call farViw","wait", +"sz*pushfw,pushf","sz*popfw,popf","sahf","lahf", +--Ax +"movBao","movVao","movBoa","movVoa", +"movsb","movsVS","cmpsb","cmpsVS", +"testBai","testVai","stosb","stosVS", +"lodsb","lodsVS","scasb","scasVS", +--Bx +"movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi", +"movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI", +--Cx +"shift!Bmu","shift!Vmu","retBw","ret","vex*3$lesVrm","vex*2$ldsVrm","movBmi","movVmi", +"enterBwu","leave","retfBw","retf","int3","intBu","into","iretVS", +--Dx +"shift!Bm1","shift!Vm1","shift!Bmc","shift!Vmc","aamBu","aadBu","salc","xlatb", +"fp*0","fp*1","fp*2","fp*3","fp*4","fp*5","fp*6","fp*7", +--Ex +"loopneBj","loopeBj","loopBj","sz*jcxzBj,jecxzBj,jrcxzBj", +"inBau","inVau","outBua","outVua", +"callVj","jmpVj","jmp farViw","jmpBj","inBad","inVad","outBda","outVda", +--Fx +"lock:","int1","repne:rep","rep:","hlt","cmc","testb!Bm","testv!Vm", +"clc","stc","cli","sti","cld","std","incb!Bm","incd!Vm", +} +assert(#map_opc1_32 == 255) + +-- Map for 1st opcode byte in 64 bit mode (overrides only). +local map_opc1_64 = setmetatable({ + [0x06]=false, [0x07]=false, [0x0e]=false, + [0x16]=false, [0x17]=false, [0x1e]=false, [0x1f]=false, + [0x27]=false, [0x2f]=false, [0x37]=false, [0x3f]=false, + [0x60]=false, [0x61]=false, [0x62]=false, [0x63]="movsxdVrDmt", [0x67]="a32:", + [0x40]="rex*", [0x41]="rex*b", [0x42]="rex*x", [0x43]="rex*xb", + [0x44]="rex*r", [0x45]="rex*rb", [0x46]="rex*rx", [0x47]="rex*rxb", + [0x48]="rex*w", [0x49]="rex*wb", [0x4a]="rex*wx", [0x4b]="rex*wxb", + [0x4c]="rex*wr", [0x4d]="rex*wrb", [0x4e]="rex*wrx", [0x4f]="rex*wrxb", + [0x82]=false, [0x9a]=false, [0xc4]="vex*3", [0xc5]="vex*2", [0xce]=false, + [0xd4]=false, [0xd5]=false, [0xd6]=false, [0xea]=false, +}, { __index = map_opc1_32 }) + +-- Map for 2nd opcode byte (0F xx). True CISC hell. Hey, I told you. +-- Prefix dependent MMX/SSE opcodes: (none)|rep|o16|repne, -|F3|66|F2 +local map_opc2 = { +--0x +[0]="sldt!Dmp","sgdt!Ump","larVrm","lslVrm",nil,"syscall","clts","sysret", +"invd","wbinvd",nil,"ud1",nil,"$prefetch!Bm","femms","3dnowMrmu", +--1x +"movupsXrm|movssXrvm|movupdXrm|movsdXrvm", +"movupsXmr|movssXmvr|movupdXmr|movsdXmvr", +"movhlpsXrm$movlpsXrm|movsldupXrm|movlpdXrm|movddupXrm", +"movlpsXmr||movlpdXmr", +"unpcklpsXrvm||unpcklpdXrvm", +"unpckhpsXrvm||unpckhpdXrvm", +"movlhpsXrm$movhpsXrm|movshdupXrm|movhpdXrm", +"movhpsXmr||movhpdXmr", +"$prefetcht!Bm","hintnopVm","hintnopVm","hintnopVm", +"hintnopVm","hintnopVm","hintnopVm","hintnopVm", +--2x +"movUmx$","movUmy$","movUxm$","movUym$","movUmz$",nil,"movUzm$",nil, +"movapsXrm||movapdXrm", +"movapsXmr||movapdXmr", +"cvtpi2psXrMm|cvtsi2ssXrvVmt|cvtpi2pdXrMm|cvtsi2sdXrvVmt", +"movntpsXmr|movntssXmr|movntpdXmr|movntsdXmr", +"cvttps2piMrXm|cvttss2siVrXm|cvttpd2piMrXm|cvttsd2siVrXm", +"cvtps2piMrXm|cvtss2siVrXm|cvtpd2piMrXm|cvtsd2siVrXm", +"ucomissXrm||ucomisdXrm", +"comissXrm||comisdXrm", +--3x +"wrmsr","rdtsc","rdmsr","rdpmc","sysenter","sysexit",nil,"getsec", +"opc3*38",nil,"opc3*3a",nil,nil,nil,nil,nil, +--4x +"cmovoVrm","cmovnoVrm","cmovbVrm","cmovnbVrm", +"cmovzVrm","cmovnzVrm","cmovbeVrm","cmovaVrm", +"cmovsVrm","cmovnsVrm","cmovpeVrm","cmovpoVrm", +"cmovlVrm","cmovgeVrm","cmovleVrm","cmovgVrm", +--5x +"movmskpsVrXm$||movmskpdVrXm$","sqrtpsXrm|sqrtssXrm|sqrtpdXrm|sqrtsdXrm", +"rsqrtpsXrm|rsqrtssXrvm","rcppsXrm|rcpssXrvm", +"andpsXrvm||andpdXrvm","andnpsXrvm||andnpdXrvm", +"orpsXrvm||orpdXrvm","xorpsXrvm||xorpdXrvm", +"addpsXrvm|addssXrvm|addpdXrvm|addsdXrvm","mulpsXrvm|mulssXrvm|mulpdXrvm|mulsdXrvm", +"cvtps2pdXrm|cvtss2sdXrvm|cvtpd2psXrm|cvtsd2ssXrvm", +"cvtdq2psXrm|cvttps2dqXrm|cvtps2dqXrm", +"subpsXrvm|subssXrvm|subpdXrvm|subsdXrvm","minpsXrvm|minssXrvm|minpdXrvm|minsdXrvm", +"divpsXrvm|divssXrvm|divpdXrvm|divsdXrvm","maxpsXrvm|maxssXrvm|maxpdXrvm|maxsdXrvm", +--6x +"punpcklbwPrvm","punpcklwdPrvm","punpckldqPrvm","packsswbPrvm", +"pcmpgtbPrvm","pcmpgtwPrvm","pcmpgtdPrvm","packuswbPrvm", +"punpckhbwPrvm","punpckhwdPrvm","punpckhdqPrvm","packssdwPrvm", +"||punpcklqdqXrvm","||punpckhqdqXrvm", +"movPrVSm","movqMrm|movdquXrm|movdqaXrm", +--7x +"pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pvmu", +"pshiftd!Pvmu","pshiftq!Mvmu||pshiftdq!Xvmu", +"pcmpeqbPrvm","pcmpeqwPrvm","pcmpeqdPrvm","emms*|", +"vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$", +nil,nil, +"||haddpdXrvm|haddpsXrvm","||hsubpdXrvm|hsubpsXrvm", +"movVSmMr|movqXrm|movVSmXr","movqMmr|movdquXmr|movdqaXmr", +--8x +"joVj","jnoVj","jbVj","jnbVj","jzVj","jnzVj","jbeVj","jaVj", +"jsVj","jnsVj","jpeVj","jpoVj","jlVj","jgeVj","jleVj","jgVj", +--9x +"setoBm","setnoBm","setbBm","setnbBm","setzBm","setnzBm","setbeBm","setaBm", +"setsBm","setnsBm","setpeBm","setpoBm","setlBm","setgeBm","setleBm","setgBm", +--Ax +"push fs","pop fs","cpuid","btVmr","shldVmru","shldVmrc",nil,nil, +"push gs","pop gs","rsm","btsVmr","shrdVmru","shrdVmrc","fxsave!Dmp","imulVrm", +--Bx +"cmpxchgBmr","cmpxchgVmr","$lssVrm","btrVmr", +"$lfsVrm","$lgsVrm","movzxVrBmt","movzxVrWmt", +"|popcntVrm","ud2Dp","bt!Vmu","btcVmr", +"bsfVrm","bsrVrm|lzcntVrm|bsrWrm","movsxVrBmt","movsxVrWmt", +--Cx +"xaddBmr","xaddVmr", +"cmppsXrvmu|cmpssXrvmu|cmppdXrvmu|cmpsdXrvmu","$movntiVmr|", +"pinsrwPrvWmu","pextrwDrPmu", +"shufpsXrvmu||shufpdXrvmu","$cmpxchg!Qmp", +"bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR", +--Dx +"||addsubpdXrvm|addsubpsXrvm","psrlwPrvm","psrldPrvm","psrlqPrvm", +"paddqPrvm","pmullwPrvm", +"|movq2dqXrMm|movqXmr|movdq2qMrXm$","pmovmskbVrMm||pmovmskbVrXm", +"psubusbPrvm","psubuswPrvm","pminubPrvm","pandPrvm", +"paddusbPrvm","padduswPrvm","pmaxubPrvm","pandnPrvm", +--Ex +"pavgbPrvm","psrawPrvm","psradPrvm","pavgwPrvm", +"pmulhuwPrvm","pmulhwPrvm", +"|cvtdq2pdXrm|cvttpd2dqXrm|cvtpd2dqXrm","$movntqMmr||$movntdqXmr", +"psubsbPrvm","psubswPrvm","pminswPrvm","porPrvm", +"paddsbPrvm","paddswPrvm","pmaxswPrvm","pxorPrvm", +--Fx +"|||lddquXrm","psllwPrvm","pslldPrvm","psllqPrvm", +"pmuludqPrvm","pmaddwdPrvm","psadbwPrvm","maskmovqMrm||maskmovdquXrm$", +"psubbPrvm","psubwPrvm","psubdPrvm","psubqPrvm", +"paddbPrvm","paddwPrvm","padddPrvm","ud", +} +assert(map_opc2[255] == "ud") + +-- Map for three-byte opcodes. Can't wait for their next invention. +local map_opc3 = { +["38"] = { -- [66] 0f 38 xx +--0x +[0]="pshufbPrvm","phaddwPrvm","phadddPrvm","phaddswPrvm", +"pmaddubswPrvm","phsubwPrvm","phsubdPrvm","phsubswPrvm", +"psignbPrvm","psignwPrvm","psigndPrvm","pmulhrswPrvm", +"||permilpsXrvm","||permilpdXrvm",nil,nil, +--1x +"||pblendvbXrma",nil,nil,nil, +"||blendvpsXrma","||blendvpdXrma","||permpsXrvm","||ptestXrm", +"||broadcastssXrm","||broadcastsdXrm","||broadcastf128XrlXm",nil, +"pabsbPrm","pabswPrm","pabsdPrm",nil, +--2x +"||pmovsxbwXrm","||pmovsxbdXrm","||pmovsxbqXrm","||pmovsxwdXrm", +"||pmovsxwqXrm","||pmovsxdqXrm",nil,nil, +"||pmuldqXrvm","||pcmpeqqXrvm","||$movntdqaXrm","||packusdwXrvm", +"||maskmovpsXrvm","||maskmovpdXrvm","||maskmovpsXmvr","||maskmovpdXmvr", +--3x +"||pmovzxbwXrm","||pmovzxbdXrm","||pmovzxbqXrm","||pmovzxwdXrm", +"||pmovzxwqXrm","||pmovzxdqXrm","||permdXrvm","||pcmpgtqXrvm", +"||pminsbXrvm","||pminsdXrvm","||pminuwXrvm","||pminudXrvm", +"||pmaxsbXrvm","||pmaxsdXrvm","||pmaxuwXrvm","||pmaxudXrvm", +--4x +"||pmulddXrvm","||phminposuwXrm",nil,nil, +nil,"||psrlvVSXrvm","||psravdXrvm","||psllvVSXrvm", +--5x +[0x58] = "||pbroadcastdXrlXm",[0x59] = "||pbroadcastqXrlXm", +[0x5a] = "||broadcasti128XrlXm", +--7x +[0x78] = "||pbroadcastbXrlXm",[0x79] = "||pbroadcastwXrlXm", +--8x +[0x8c] = "||pmaskmovXrvVSm", +[0x8e] = "||pmaskmovVSmXvr", +--9x +[0x96] = "||fmaddsub132pHXrvm",[0x97] = "||fmsubadd132pHXrvm", +[0x98] = "||fmadd132pHXrvm",[0x99] = "||fmadd132sHXrvm", +[0x9a] = "||fmsub132pHXrvm",[0x9b] = "||fmsub132sHXrvm", +[0x9c] = "||fnmadd132pHXrvm",[0x9d] = "||fnmadd132sHXrvm", +[0x9e] = "||fnmsub132pHXrvm",[0x9f] = "||fnmsub132sHXrvm", +--Ax +[0xa6] = "||fmaddsub213pHXrvm",[0xa7] = "||fmsubadd213pHXrvm", +[0xa8] = "||fmadd213pHXrvm",[0xa9] = "||fmadd213sHXrvm", +[0xaa] = "||fmsub213pHXrvm",[0xab] = "||fmsub213sHXrvm", +[0xac] = "||fnmadd213pHXrvm",[0xad] = "||fnmadd213sHXrvm", +[0xae] = "||fnmsub213pHXrvm",[0xaf] = "||fnmsub213sHXrvm", +--Bx +[0xb6] = "||fmaddsub231pHXrvm",[0xb7] = "||fmsubadd231pHXrvm", +[0xb8] = "||fmadd231pHXrvm",[0xb9] = "||fmadd231sHXrvm", +[0xba] = "||fmsub231pHXrvm",[0xbb] = "||fmsub231sHXrvm", +[0xbc] = "||fnmadd231pHXrvm",[0xbd] = "||fnmadd231sHXrvm", +[0xbe] = "||fnmsub231pHXrvm",[0xbf] = "||fnmsub231sHXrvm", +--Dx +[0xdc] = "||aesencXrvm", [0xdd] = "||aesenclastXrvm", +[0xde] = "||aesdecXrvm", [0xdf] = "||aesdeclastXrvm", +--Fx +[0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt", +[0xf7] = "| sarxVrmv| shlxVrmv| shrxVrmv", +}, + +["3a"] = { -- [66] 0f 3a xx +--0x +[0x00]="||permqXrmu","||permpdXrmu","||pblenddXrvmu",nil, +"||permilpsXrmu","||permilpdXrmu","||perm2f128Xrvmu",nil, +"||roundpsXrmu","||roundpdXrmu","||roundssXrvmu","||roundsdXrvmu", +"||blendpsXrvmu","||blendpdXrvmu","||pblendwXrvmu","palignrPrvmu", +--1x +nil,nil,nil,nil, +"||pextrbVmXru","||pextrwVmXru","||pextrVmSXru","||extractpsVmXru", +"||insertf128XrvlXmu","||extractf128XlXmYru",nil,nil, +nil,nil,nil,nil, +--2x +"||pinsrbXrvVmu","||insertpsXrvmu","||pinsrXrvVmuS",nil, +--3x +[0x38] = "||inserti128Xrvmu",[0x39] = "||extracti128XlXmYru", +--4x +[0x40] = "||dppsXrvmu", +[0x41] = "||dppdXrvmu", +[0x42] = "||mpsadbwXrvmu", +[0x44] = "||pclmulqdqXrvmu", +[0x46] = "||perm2i128Xrvmu", +[0x4a] = "||blendvpsXrvmb",[0x4b] = "||blendvpdXrvmb", +[0x4c] = "||pblendvbXrvmb", +--6x +[0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu", +[0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu", +[0xdf] = "||aeskeygenassistXrmu", +--Fx +[0xf0] = "||| rorxVrmu", +}, +} + +-- Map for VMX/SVM opcodes 0F 01 C0-FF (sgdt group with register operands). +local map_opcvm = { +[0xc1]="vmcall",[0xc2]="vmlaunch",[0xc3]="vmresume",[0xc4]="vmxoff", +[0xc8]="monitor",[0xc9]="mwait", +[0xd8]="vmrun",[0xd9]="vmmcall",[0xda]="vmload",[0xdb]="vmsave", +[0xdc]="stgi",[0xdd]="clgi",[0xde]="skinit",[0xdf]="invlpga", +[0xf8]="swapgs",[0xf9]="rdtscp", +} + +-- Map for FP opcodes. And you thought stack machines are simple? +local map_opcfp = { +-- D8-DF 00-BF: opcodes with a memory operand. +-- D8 +[0]="faddFm","fmulFm","fcomFm","fcompFm","fsubFm","fsubrFm","fdivFm","fdivrFm", +"fldFm",nil,"fstFm","fstpFm","fldenvVm","fldcwWm","fnstenvVm","fnstcwWm", +-- DA +"fiaddDm","fimulDm","ficomDm","ficompDm", +"fisubDm","fisubrDm","fidivDm","fidivrDm", +-- DB +"fildDm","fisttpDm","fistDm","fistpDm",nil,"fld twordFmp",nil,"fstp twordFmp", +-- DC +"faddGm","fmulGm","fcomGm","fcompGm","fsubGm","fsubrGm","fdivGm","fdivrGm", +-- DD +"fldGm","fisttpQm","fstGm","fstpGm","frstorDmp",nil,"fnsaveDmp","fnstswWm", +-- DE +"fiaddWm","fimulWm","ficomWm","ficompWm", +"fisubWm","fisubrWm","fidivWm","fidivrWm", +-- DF +"fildWm","fisttpWm","fistWm","fistpWm", +"fbld twordFmp","fildQm","fbstp twordFmp","fistpQm", +-- xx C0-FF: opcodes with a pseudo-register operand. +-- D8 +"faddFf","fmulFf","fcomFf","fcompFf","fsubFf","fsubrFf","fdivFf","fdivrFf", +-- D9 +"fldFf","fxchFf",{"fnop"},nil, +{"fchs","fabs",nil,nil,"ftst","fxam"}, +{"fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz"}, +{"f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp"}, +{"fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"}, +-- DA +"fcmovbFf","fcmoveFf","fcmovbeFf","fcmovuFf",nil,{nil,"fucompp"},nil,nil, +-- DB +"fcmovnbFf","fcmovneFf","fcmovnbeFf","fcmovnuFf", +{nil,nil,"fnclex","fninit"},"fucomiFf","fcomiFf",nil, +-- DC +"fadd toFf","fmul toFf",nil,nil, +"fsub toFf","fsubr toFf","fdivr toFf","fdiv toFf", +-- DD +"ffreeFf",nil,"fstFf","fstpFf","fucomFf","fucompFf",nil,nil, +-- DE +"faddpFf","fmulpFf",nil,{nil,"fcompp"}, +"fsubrpFf","fsubpFf","fdivrpFf","fdivpFf", +-- DF +nil,nil,nil,nil,{"fnstsw ax"},"fucomipFf","fcomipFf",nil, +} +assert(map_opcfp[126] == "fcomipFf") + +-- Map for opcode groups. The subkey is sp from the ModRM byte. +local map_opcgroup = { + arith = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" }, + shift = { "rol", "ror", "rcl", "rcr", "shl", "shr", "sal", "sar" }, + testb = { "testBmi", "testBmi", "not", "neg", "mul", "imul", "div", "idiv" }, + testv = { "testVmi", "testVmi", "not", "neg", "mul", "imul", "div", "idiv" }, + incb = { "inc", "dec" }, + incd = { "inc", "dec", "callUmp", "$call farDmp", + "jmpUmp", "$jmp farDmp", "pushUm" }, + sldt = { "sldt", "str", "lldt", "ltr", "verr", "verw" }, + sgdt = { "vm*$sgdt", "vm*$sidt", "$lgdt", "vm*$lidt", + "smsw", nil, "lmsw", "vm*$invlpg" }, + bt = { nil, nil, nil, nil, "bt", "bts", "btr", "btc" }, + cmpxchg = { nil, "sz*,cmpxchg8bQmp,cmpxchg16bXmp", nil, nil, + nil, nil, "vmptrld|vmxon|vmclear", "vmptrst" }, + pshiftw = { nil, nil, "psrlw", nil, "psraw", nil, "psllw" }, + pshiftd = { nil, nil, "psrld", nil, "psrad", nil, "pslld" }, + pshiftq = { nil, nil, "psrlq", nil, nil, nil, "psllq" }, + pshiftdq = { nil, nil, "psrlq", "psrldq", nil, nil, "psllq", "pslldq" }, + fxsave = { "$fxsave", "$fxrstor", "$ldmxcsr", "$stmxcsr", + nil, "lfenceDp$", "mfenceDp$", "sfenceDp$clflush" }, + prefetch = { "prefetch", "prefetchw" }, + prefetcht = { "prefetchnta", "prefetcht0", "prefetcht1", "prefetcht2" }, +} + +------------------------------------------------------------------------------ + +-- Maps for register names. +local map_regs = { + B = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + B64 = { "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + W = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }, + D = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }, + Q = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }, + M = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", + "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, -- No x64 ext! + X = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" }, + Y = { "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15" }, +} +local map_segregs = { "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7" } + +-- Maps for size names. +local map_sz2n = { + B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16, Y = 32, +} +local map_sz2prefix = { + B = "byte", W = "word", D = "dword", + Q = "qword", + M = "qword", X = "xword", Y = "yword", + F = "dword", G = "qword", -- No need for sizes/register names for these two. +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local code, pos, hex = ctx.code, ctx.pos, "" + local hmax = ctx.hexdump + if hmax > 0 then + for i=ctx.start,pos-1 do + hex = hex..format("%02X", byte(code, i, i)) + end + if #hex > hmax then hex = sub(hex, 1, hmax)..". " + else hex = hex..rep(" ", hmax-#hex+2) end + end + if operands then text = text.." "..operands end + if ctx.o16 then text = "o16 "..text; ctx.o16 = false end + if ctx.a32 then text = "a32 "..text; ctx.a32 = false end + if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end + if ctx.rex then + local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "").. + (ctx.rexx and "x" or "")..(ctx.rexb and "b" or "").. + (ctx.vexl and "l" or "") + if ctx.vexv and ctx.vexv ~= 0 then t = t.."v"..ctx.vexv end + if t ~= "" then text = ctx.rex.."."..t.." "..gsub(text, "^ ", "") + elseif ctx.rex == "vex" then text = gsub("v"..text, "^v ", "") end + ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false + ctx.rex = false; ctx.vexl = false; ctx.vexv = false + end + if ctx.seg then + local text2, n = gsub(text, "%[", "["..ctx.seg..":") + if n == 0 then text = ctx.seg.." "..text else text = text2 end + ctx.seg = false + end + if ctx.lock then text = "lock "..text; ctx.lock = false end + local imm = ctx.imm + if imm then + local sym = ctx.symtab[imm] + if sym then text = text.."\t->"..sym end + end + ctx.out(format("%08x %s%s\n", ctx.addr+ctx.start, hex, text)) + ctx.mrm = false + ctx.vexv = false + ctx.start = pos + ctx.imm = nil +end + +-- Clear all prefix flags. +local function clearprefixes(ctx) + ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false + ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false + ctx.rex = false; ctx.a32 = false; ctx.vexl = false +end + +-- Fallback for incomplete opcodes at the end. +local function incomplete(ctx) + ctx.pos = ctx.stop+1 + clearprefixes(ctx) + return putop(ctx, "(incomplete)") +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + clearprefixes(ctx) + return putop(ctx, "(unknown)") +end + +-- Return an immediate of the specified size. +local function getimm(ctx, pos, n) + if pos+n-1 > ctx.stop then return incomplete(ctx) end + local code = ctx.code + if n == 1 then + local b1 = byte(code, pos, pos) + return b1 + elseif n == 2 then + local b1, b2 = byte(code, pos, pos+1) + return b1+b2*256 + else + local b1, b2, b3, b4 = byte(code, pos, pos+3) + local imm = b1+b2*256+b3*65536+b4*16777216 + ctx.imm = imm + return imm + end +end + +-- Process pattern string and generate the operands. +local function putpat(ctx, name, pat) + local operands, regs, sz, mode, sp, rm, sc, rx, sdisp + local code, pos, stop, vexl = ctx.code, ctx.pos, ctx.stop, ctx.vexl + + -- Chars used: 1DFGHIMPQRSTUVWXYabcdfgijlmoprstuvwxyz + for p in gmatch(pat, ".") do + local x = nil + if p == "V" or p == "U" then + if ctx.rexw then sz = "Q"; ctx.rexw = false + elseif ctx.o16 then sz = "W"; ctx.o16 = false + elseif p == "U" and ctx.x64 then sz = "Q" + else sz = "D" end + regs = map_regs[sz] + elseif p == "T" then + if ctx.rexw then sz = "Q"; ctx.rexw = false else sz = "D" end + regs = map_regs[sz] + elseif p == "B" then + sz = "B" + regs = ctx.rex and map_regs.B64 or map_regs.B + elseif match(p, "[WDQMXYFG]") then + sz = p + if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end + regs = map_regs[sz] + elseif p == "P" then + sz = ctx.o16 and "X" or "M"; ctx.o16 = false + if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end + regs = map_regs[sz] + elseif p == "H" then + name = name..(ctx.rexw and "d" or "s") + ctx.rexw = false + elseif p == "S" then + name = name..lower(sz) + elseif p == "s" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = imm <= 127 and format("+0x%02x", imm) + or format("-0x%02x", 256-imm) + pos = pos+1 + elseif p == "u" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = format("0x%02x", imm) + pos = pos+1 + elseif p == "b" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = regs[imm/16+1] + pos = pos+1 + elseif p == "w" then + local imm = getimm(ctx, pos, 2); if not imm then return end + x = format("0x%x", imm) + pos = pos+2 + elseif p == "o" then -- [offset] + if ctx.x64 then + local imm1 = getimm(ctx, pos, 4); if not imm1 then return end + local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end + x = format("[0x%08x%08x]", imm2, imm1) + pos = pos+8 + else + local imm = getimm(ctx, pos, 4); if not imm then return end + x = format("[0x%08x]", imm) + pos = pos+4 + end + elseif p == "i" or p == "I" then + local n = map_sz2n[sz] + if n == 8 and ctx.x64 and p == "I" then + local imm1 = getimm(ctx, pos, 4); if not imm1 then return end + local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end + x = format("0x%08x%08x", imm2, imm1) + else + if n == 8 then n = 4 end + local imm = getimm(ctx, pos, n); if not imm then return end + if sz == "Q" and (imm < 0 or imm > 0x7fffffff) then + imm = (0xffffffff+1)-imm + x = format(imm > 65535 and "-0x%08x" or "-0x%x", imm) + else + x = format(imm > 65535 and "0x%08x" or "0x%x", imm) + end + end + pos = pos+n + elseif p == "j" then + local n = map_sz2n[sz] + if n == 8 then n = 4 end + local imm = getimm(ctx, pos, n); if not imm then return end + if sz == "B" and imm > 127 then imm = imm-256 + elseif imm > 2147483647 then imm = imm-4294967296 end + pos = pos+n + imm = imm + pos + ctx.addr + if imm > 4294967295 and not ctx.x64 then imm = imm-4294967296 end + ctx.imm = imm + if sz == "W" then + x = format("word 0x%04x", imm%65536) + elseif ctx.x64 then + local lo = imm % 0x1000000 + x = format("0x%02x%06x", (imm-lo) / 0x1000000, lo) + else + x = "0x"..tohex(imm) + end + elseif p == "R" then + local r = byte(code, pos-1, pos-1)%8 + if ctx.rexb then r = r + 8; ctx.rexb = false end + x = regs[r+1] + elseif p == "a" then x = regs[1] + elseif p == "c" then x = "cl" + elseif p == "d" then x = "dx" + elseif p == "1" then x = "1" + else + if not mode then + mode = ctx.mrm + if not mode then + if pos > stop then return incomplete(ctx) end + mode = byte(code, pos, pos) + pos = pos+1 + end + rm = mode%8; mode = (mode-rm)/8 + sp = mode%8; mode = (mode-sp)/8 + sdisp = "" + if mode < 3 then + if rm == 4 then + if pos > stop then return incomplete(ctx) end + sc = byte(code, pos, pos) + pos = pos+1 + rm = sc%8; sc = (sc-rm)/8 + rx = sc%8; sc = (sc-rx)/8 + if ctx.rexx then rx = rx + 8; ctx.rexx = false end + if rx == 4 then rx = nil end + end + if mode > 0 or rm == 5 then + local dsz = mode + if dsz ~= 1 then dsz = 4 end + local disp = getimm(ctx, pos, dsz); if not disp then return end + if mode == 0 then rm = nil end + if rm or rx or (not sc and ctx.x64 and not ctx.a32) then + if dsz == 1 and disp > 127 then + sdisp = format("-0x%x", 256-disp) + elseif disp >= 0 and disp <= 0x7fffffff then + sdisp = format("+0x%x", disp) + else + sdisp = format("-0x%x", (0xffffffff+1)-disp) + end + else + sdisp = format(ctx.x64 and not ctx.a32 and + not (disp >= 0 and disp <= 0x7fffffff) + and "0xffffffff%08x" or "0x%08x", disp) + end + pos = pos+dsz + end + end + if rm and ctx.rexb then rm = rm + 8; ctx.rexb = false end + if ctx.rexr then sp = sp + 8; ctx.rexr = false end + end + if p == "m" then + if mode == 3 then x = regs[rm+1] + else + local aregs = ctx.a32 and map_regs.D or ctx.aregs + local srm, srx = "", "" + if rm then srm = aregs[rm+1] + elseif not sc and ctx.x64 and not ctx.a32 then srm = "rip" end + ctx.a32 = false + if rx then + if rm then srm = srm.."+" end + srx = aregs[rx+1] + if sc > 0 then srx = srx.."*"..(2^sc) end + end + x = format("[%s%s%s]", srm, srx, sdisp) + end + if mode < 3 and + (not match(pat, "[aRrgp]") or match(pat, "t")) then -- Yuck. + x = map_sz2prefix[sz].." "..x + end + elseif p == "r" then x = regs[sp+1] + elseif p == "g" then x = map_segregs[sp+1] + elseif p == "p" then -- Suppress prefix. + elseif p == "f" then x = "st"..rm + elseif p == "x" then + if sp == 0 and ctx.lock and not ctx.x64 then + x = "CR8"; ctx.lock = false + else + x = "CR"..sp + end + elseif p == "v" then + if ctx.vexv then + x = regs[ctx.vexv+1]; ctx.vexv = false + end + elseif p == "y" then x = "DR"..sp + elseif p == "z" then x = "TR"..sp + elseif p == "l" then vexl = false + elseif p == "t" then + else + error("bad pattern `"..pat.."'") + end + end + if x then operands = operands and operands..", "..x or x end + end + ctx.pos = pos + return putop(ctx, name, operands) +end + +-- Forward declaration. +local map_act + +-- Fetch and cache MRM byte. +local function getmrm(ctx) + local mrm = ctx.mrm + if not mrm then + local pos = ctx.pos + if pos > ctx.stop then return nil end + mrm = byte(ctx.code, pos, pos) + ctx.pos = pos+1 + ctx.mrm = mrm + end + return mrm +end + +-- Dispatch to handler depending on pattern. +local function dispatch(ctx, opat, patgrp) + if not opat then return unknown(ctx) end + if match(opat, "%|") then -- MMX/SSE variants depending on prefix. + local p + if ctx.rep then + p = ctx.rep=="rep" and "%|([^%|]*)" or "%|[^%|]*%|[^%|]*%|([^%|]*)" + ctx.rep = false + elseif ctx.o16 then p = "%|[^%|]*%|([^%|]*)"; ctx.o16 = false + else p = "^[^%|]*" end + opat = match(opat, p) + if not opat then return unknown(ctx) end +-- ctx.rep = false; ctx.o16 = false + --XXX fails for 66 f2 0f 38 f1 06 crc32 eax,WORD PTR [esi] + --XXX remove in branches? + end + if match(opat, "%$") then -- reg$mem variants. + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + opat = match(opat, mrm >= 192 and "^[^%$]*" or "%$(.*)") + if opat == "" then return unknown(ctx) end + end + if opat == "" then return unknown(ctx) end + local name, pat = match(opat, "^([a-z0-9 ]*)(.*)") + if pat == "" and patgrp then pat = patgrp end + return map_act[sub(pat, 1, 1)](ctx, name, pat) +end + +-- Get a pattern from an opcode map and dispatch to handler. +local function dispatchmap(ctx, opcmap) + local pos = ctx.pos + local opat = opcmap[byte(ctx.code, pos, pos)] + pos = pos + 1 + ctx.pos = pos + return dispatch(ctx, opat) +end + +-- Map for action codes. The key is the first char after the name. +map_act = { + -- Simple opcodes without operands. + [""] = function(ctx, name, pat) + return putop(ctx, name) + end, + + -- Operand size chars fall right through. + B = putpat, W = putpat, D = putpat, Q = putpat, + V = putpat, U = putpat, T = putpat, + M = putpat, X = putpat, P = putpat, + F = putpat, G = putpat, Y = putpat, + H = putpat, + + -- Collect prefixes. + [":"] = function(ctx, name, pat) + ctx[pat == ":" and name or sub(pat, 2)] = name + if ctx.pos - ctx.start > 5 then return unknown(ctx) end -- Limit #prefixes. + end, + + -- Chain to special handler specified by name. + ["*"] = function(ctx, name, pat) + return map_act[name](ctx, name, sub(pat, 2)) + end, + + -- Use named subtable for opcode group. + ["!"] = function(ctx, name, pat) + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + return dispatch(ctx, map_opcgroup[name][((mrm-(mrm%8))/8)%8+1], sub(pat, 2)) + end, + + -- o16,o32[,o64] variants. + sz = function(ctx, name, pat) + if ctx.o16 then ctx.o16 = false + else + pat = match(pat, ",(.*)") + if ctx.rexw then + local p = match(pat, ",(.*)") + if p then pat = p; ctx.rexw = false end + end + end + pat = match(pat, "^[^,]*") + return dispatch(ctx, pat) + end, + + -- Two-byte opcode dispatch. + opc2 = function(ctx, name, pat) + return dispatchmap(ctx, map_opc2) + end, + + -- Three-byte opcode dispatch. + opc3 = function(ctx, name, pat) + return dispatchmap(ctx, map_opc3[pat]) + end, + + -- VMX/SVM dispatch. + vm = function(ctx, name, pat) + return dispatch(ctx, map_opcvm[ctx.mrm]) + end, + + -- Floating point opcode dispatch. + fp = function(ctx, name, pat) + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + local rm = mrm%8 + local idx = pat*8 + ((mrm-rm)/8)%8 + if mrm >= 192 then idx = idx + 64 end + local opat = map_opcfp[idx] + if type(opat) == "table" then opat = opat[rm+1] end + return dispatch(ctx, opat) + end, + + -- REX prefix. + rex = function(ctx, name, pat) + if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. + for p in gmatch(pat, ".") do ctx["rex"..p] = true end + ctx.rex = "rex" + end, + + -- VEX prefix. + vex = function(ctx, name, pat) + if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. + ctx.rex = "vex" + local pos = ctx.pos + if ctx.mrm then + ctx.mrm = nil + pos = pos-1 + end + local b = byte(ctx.code, pos, pos) + if not b then return incomplete(ctx) end + pos = pos+1 + if b < 128 then ctx.rexr = true end + local m = 1 + if pat == "3" then + m = b%32; b = (b-m)/32 + local nb = b%2; b = (b-nb)/2 + if nb == 0 then ctx.rexb = true end + local nx = b%2 + if nx == 0 then ctx.rexx = true end + b = byte(ctx.code, pos, pos) + if not b then return incomplete(ctx) end + pos = pos+1 + if b >= 128 then ctx.rexw = true end + end + ctx.pos = pos + local map + if m == 1 then map = map_opc2 + elseif m == 2 then map = map_opc3["38"] + elseif m == 3 then map = map_opc3["3a"] + else return unknown(ctx) end + local p = b%4; b = (b-p)/4 + if p == 1 then ctx.o16 = "o16" + elseif p == 2 then ctx.rep = "rep" + elseif p == 3 then ctx.rep = "repne" end + local l = b%2; b = (b-l)/2 + if l ~= 0 then ctx.vexl = true end + ctx.vexv = (-1-b)%16 + return dispatchmap(ctx, map) + end, + + -- Special case for nop with REX prefix. + nop = function(ctx, name, pat) + return dispatch(ctx, ctx.rex and pat or "nop") + end, + + -- Special case for 0F 77. + emms = function(ctx, name, pat) + if ctx.rex ~= "vex" then + return putop(ctx, "emms") + elseif ctx.vexl then + ctx.vexl = false + return putop(ctx, "zeroall") + else + return putop(ctx, "zeroupper") + end + end, +} + +------------------------------------------------------------------------------ + +-- Disassemble a block of code. +local function disass_block(ctx, ofs, len) + if not ofs then ofs = 0 end + local stop = len and ofs+len or #ctx.code + ofs = ofs + 1 + ctx.start = ofs + ctx.pos = ofs + ctx.stop = stop + ctx.imm = nil + ctx.mrm = false + clearprefixes(ctx) + while ctx.pos <= stop do dispatchmap(ctx, ctx.map1) end + if ctx.pos ~= ctx.start then incomplete(ctx) end +end + +-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). +local function create(code, addr, out) + local ctx = {} + ctx.code = code + ctx.addr = (addr or 0) - 1 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 16 + ctx.x64 = false + ctx.map1 = map_opc1_32 + ctx.aregs = map_regs.D + return ctx +end + +local function create64(code, addr, out) + local ctx = create(code, addr, out) + ctx.x64 = true + ctx.map1 = map_opc1_64 + ctx.aregs = map_regs.Q + return ctx +end + +-- Simple API: disassemble code (a string) at address and output via out. +local function disass(code, addr, out) + create(code, addr, out):disass() +end + +local function disass64(code, addr, out) + create64(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 8 then return map_regs.D[r+1] end + return map_regs.X[r-7] +end + +local function regname64(r) + if r < 16 then return map_regs.Q[r+1] end + return map_regs.X[r-15] +end + +-- Public module functions. +return { + create = create, + create64 = create64, + disass = disass, + disass64 = disass64, + regname = regname, + regname64 = regname64 +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dump.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dump.lua new file mode 100644 index 00000000..9eda08c4 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/dump.lua @@ -0,0 +1,726 @@ +---------------------------------------------------------------------------- +-- LuaJIT compiler dump module. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module can be used to debug the JIT compiler itself. It dumps the +-- code representations and structures used in various compiler stages. +-- +-- Example usage: +-- +-- luajit -jdump -e "local x=0; for i=1,1e6 do x=x+i end; print(x)" +-- luajit -jdump=im -e "for i=1,1000 do for j=1,1000 do end end" | less -R +-- luajit -jdump=is myapp.lua | less -R +-- luajit -jdump=-b myapp.lua +-- luajit -jdump=+aH,myapp.html myapp.lua +-- luajit -jdump=ixT,myapp.dump myapp.lua +-- +-- The first argument specifies the dump mode. The second argument gives +-- the output file name. Default output is to stdout, unless the environment +-- variable LUAJIT_DUMPFILE is set. The file is overwritten every time the +-- module is started. +-- +-- Different features can be turned on or off with the dump mode. If the +-- mode starts with a '+', the following features are added to the default +-- set of features; a '-' removes them. Otherwise the features are replaced. +-- +-- The following dump features are available (* marks the default): +-- +-- * t Print a line for each started, ended or aborted trace (see also -jv). +-- * b Dump the traced bytecode. +-- * i Dump the IR (intermediate representation). +-- r Augment the IR with register/stack slots. +-- s Dump the snapshot map. +-- * m Dump the generated machine code. +-- x Print each taken trace exit. +-- X Print each taken trace exit and the contents of all registers. +-- a Print the IR of aborted traces, too. +-- +-- The output format can be set with the following characters: +-- +-- T Plain text output. +-- A ANSI-colored text output +-- H Colorized HTML + CSS output. +-- +-- The default output format is plain text. It's set to ANSI-colored text +-- if the COLORTERM variable is set. Note: this is independent of any output +-- redirection, which is actually considered a feature. +-- +-- You probably want to use less -R to enjoy viewing ANSI-colored text from +-- a pipe or a file. Add this to your ~/.bashrc: export LESS="-R" +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc +local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek +local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap +local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr +local bit = require("bit") +local band, shr, tohex = bit.band, bit.rshift, bit.tohex +local sub, gsub, format = string.sub, string.gsub, string.format +local byte, rep = string.byte, string.rep +local type, tostring = type, tostring +local stdout, stderr = io.stdout, io.stderr + +-- Load other modules on-demand. +local bcline, disass + +-- Active flag, output file handle and dump mode. +local active, out, dumpmode + +------------------------------------------------------------------------------ + +local symtabmt = { __index = false } +local symtab = {} +local nexitsym = 0 + +-- Fill nested symbol table with per-trace exit stub addresses. +local function fillsymtab_tr(tr, nexit) + local t = {} + symtabmt.__index = t + if jit.arch:sub(1, 4) == "mips" then + t[traceexitstub(tr, 0)] = "exit" + return + end + for i=0,nexit-1 do + local addr = traceexitstub(tr, i) + if addr < 0 then addr = addr + 2^32 end + t[addr] = tostring(i) + end + local addr = traceexitstub(tr, nexit) + if addr then t[addr] = "stack_check" end +end + +-- Fill symbol table with trace exit stub addresses. +local function fillsymtab(tr, nexit) + local t = symtab + if nexitsym == 0 then + local maskaddr = jit.arch == "arm" and -2 + local ircall = vmdef.ircall + for i=0,#ircall do + local addr = ircalladdr(i) + if addr ~= 0 then + if maskaddr then addr = band(addr, maskaddr) end + if addr < 0 then addr = addr + 2^32 end + t[addr] = ircall[i] + end + end + end + if nexitsym == 1000000 then -- Per-trace exit stubs. + fillsymtab_tr(tr, nexit) + elseif nexit > nexitsym then -- Shared exit stubs. + for i=nexitsym,nexit-1 do + local addr = traceexitstub(i) + if addr == nil then -- Fall back to per-trace exit stubs. + fillsymtab_tr(tr, nexit) + setmetatable(symtab, symtabmt) + nexit = 1000000 + break + end + if addr < 0 then addr = addr + 2^32 end + t[addr] = tostring(i) + end + nexitsym = nexit + end + return t +end + +local function dumpwrite(s) + out:write(s) +end + +-- Disassemble machine code. +local function dump_mcode(tr) + local info = traceinfo(tr) + if not info then return end + local mcode, addr, loop = tracemc(tr) + if not mcode then return end + if not disass then disass = require("jit.dis_"..jit.arch) end + if addr < 0 then addr = addr + 2^32 end + out:write("---- TRACE ", tr, " mcode ", #mcode, "\n") + local ctx = disass.create(mcode, addr, dumpwrite) + ctx.hexdump = 0 + ctx.symtab = fillsymtab(tr, info.nexit) + if loop ~= 0 then + symtab[addr+loop] = "LOOP" + ctx:disass(0, loop) + out:write("->LOOP:\n") + ctx:disass(loop, #mcode-loop) + symtab[addr+loop] = nil + else + ctx:disass(0, #mcode) + end +end + +------------------------------------------------------------------------------ + +local irtype_text = { + [0] = "nil", + "fal", + "tru", + "lud", + "str", + "p32", + "thr", + "pro", + "fun", + "p64", + "cdt", + "tab", + "udt", + "flt", + "num", + "i8 ", + "u8 ", + "i16", + "u16", + "int", + "u32", + "i64", + "u64", + "sfp", +} + +local colortype_ansi = { + [0] = "%s", + "%s", + "%s", + "\027[36m%s\027[m", + "\027[32m%s\027[m", + "%s", + "\027[1m%s\027[m", + "%s", + "\027[1m%s\027[m", + "%s", + "\027[33m%s\027[m", + "\027[31m%s\027[m", + "\027[36m%s\027[m", + "\027[34m%s\027[m", + "\027[34m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", +} + +local function colorize_text(s) + return s +end + +local function colorize_ansi(s, t, extra) + local out = format(colortype_ansi[t], s) + if extra then out = "\027[3m"..out end + return out +end + +local irtype_ansi = setmetatable({}, + { __index = function(tab, t) + local s = colorize_ansi(irtype_text[t], t); tab[t] = s; return s; end }) + +local html_escape = { ["<"] = "<", [">"] = ">", ["&"] = "&", } + +local function colorize_html(s, t, extra) + s = gsub(s, "[<>&]", html_escape) + return format('%s', + irtype_text[t], extra and " irt_extra" or "", s) +end + +local irtype_html = setmetatable({}, + { __index = function(tab, t) + local s = colorize_html(irtype_text[t], t); tab[t] = s; return s; end }) + +local header_html = [[ + +]] + +local colorize, irtype + +-- Lookup tables to convert some literals into names. +local litname = { + ["SLOAD "] = setmetatable({}, { __index = function(t, mode) + local s = "" + if band(mode, 1) ~= 0 then s = s.."P" end + if band(mode, 2) ~= 0 then s = s.."F" end + if band(mode, 4) ~= 0 then s = s.."T" end + if band(mode, 8) ~= 0 then s = s.."C" end + if band(mode, 16) ~= 0 then s = s.."R" end + if band(mode, 32) ~= 0 then s = s.."I" end + if band(mode, 64) ~= 0 then s = s.."K" end + t[mode] = s + return s + end}), + ["XLOAD "] = { [0] = "", "R", "V", "RV", "U", "RU", "VU", "RVU", }, + ["CONV "] = setmetatable({}, { __index = function(t, mode) + local s = irtype[band(mode, 31)] + s = irtype[band(shr(mode, 5), 31)].."."..s + if band(mode, 0x800) ~= 0 then s = s.." sext" end + local c = shr(mode, 12) + if c == 1 then s = s.." none" + elseif c == 2 then s = s.." index" + elseif c == 3 then s = s.." check" end + t[mode] = s + return s + end}), + ["FLOAD "] = vmdef.irfield, + ["FREF "] = vmdef.irfield, + ["FPMATH"] = vmdef.irfpm, + ["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" }, + ["BUFHDR"] = { [0] = "RESET", "APPEND", "WRITE" }, + ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, +} + +local function ctlsub(c) + if c == "\n" then return "\\n" + elseif c == "\r" then return "\\r" + elseif c == "\t" then return "\\t" + else return format("\\%03d", byte(c)) + end +end + +local function fmtfunc(func, pc) + local fi = funcinfo(func, pc) + if fi.loc then + return fi.loc + elseif fi.ffid then + return vmdef.ffnames[fi.ffid] + elseif fi.addr then + return format("C:%x", fi.addr) + else + return "(?)" + end +end + +local function formatk(tr, idx, sn) + local k, t, slot = tracek(tr, idx) + local tn = type(k) + local s + if tn == "number" then + if t < 12 then + s = k == 0 and "NULL" or format("[0x%08x]", k) + elseif band(sn or 0, 0x30000) ~= 0 then + s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz" + elseif k == 2^52+2^51 then + s = "bias" + else + s = format(0 < k and k < 0x1p-1026 and "%+a" or "%+.14g", k) + end + elseif tn == "string" then + s = format(#k > 20 and '"%.20s"~' or '"%s"', gsub(k, "%c", ctlsub)) + elseif tn == "function" then + s = fmtfunc(k) + elseif tn == "table" then + s = format("{%p}", k) + elseif tn == "userdata" then + if t == 12 then + s = format("userdata:%p", k) + else + s = format("[%p]", k) + if s == "[NULL]" then s = "NULL" end + end + elseif t == 21 then -- int64_t + s = sub(tostring(k), 1, -3) + if sub(s, 1, 1) ~= "-" then s = "+"..s end + elseif sn == 0x1057fff then -- SNAP(1, SNAP_FRAME | SNAP_NORESTORE, REF_NIL) + return "----" -- Special case for LJ_FR2 slot 1. + else + s = tostring(k) -- For primitives. + end + s = colorize(format("%-4s", s), t, band(sn or 0, 0x100000) ~= 0) + if slot then + s = format("%s @%d", s, slot) + end + return s +end + +local function printsnap(tr, snap) + local n = 2 + for s=0,snap[1]-1 do + local sn = snap[n] + if shr(sn, 24) == s then + n = n + 1 + local ref = band(sn, 0xffff) - 0x8000 -- REF_BIAS + if ref < 0 then + out:write(formatk(tr, ref, sn)) + elseif band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM + out:write(colorize(format("%04d/%04d", ref, ref+1), 14)) + else + local m, ot, op1, op2 = traceir(tr, ref) + out:write(colorize(format("%04d", ref), band(ot, 31), band(sn, 0x100000) ~= 0)) + end + out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME + else + out:write("---- ") + end + end + out:write("]\n") +end + +-- Dump snapshots (not interleaved with IR). +local function dump_snap(tr) + out:write("---- TRACE ", tr, " snapshots\n") + for i=0,1000000000 do + local snap = tracesnap(tr, i) + if not snap then break end + out:write(format("#%-3d %04d [ ", i, snap[0])) + printsnap(tr, snap) + end +end + +-- Return a register name or stack slot for a rid/sp location. +local function ridsp_name(ridsp, ins) + if not disass then disass = require("jit.dis_"..jit.arch) end + local rid, slot = band(ridsp, 0xff), shr(ridsp, 8) + if rid == 253 or rid == 254 then + return (slot == 0 or slot == 255) and " {sink" or format(" {%04d", ins-slot) + end + if ridsp > 255 then return format("[%x]", slot*4) end + if rid < 128 then return disass.regname(rid) end + return "" +end + +-- Dump CALL* function ref and return optional ctype. +local function dumpcallfunc(tr, ins) + local ctype + if ins > 0 then + local m, ot, op1, op2 = traceir(tr, ins) + if band(ot, 31) == 0 then -- nil type means CARG(func, ctype). + ins = op1 + ctype = formatk(tr, op2) + end + end + if ins < 0 then + out:write(format("[0x%x](", tonumber((tracek(tr, ins))))) + else + out:write(format("%04d (", ins)) + end + return ctype +end + +-- Recursively gather CALL* args and dump them. +local function dumpcallargs(tr, ins) + if ins < 0 then + out:write(formatk(tr, ins)) + else + local m, ot, op1, op2 = traceir(tr, ins) + local oidx = 6*shr(ot, 8) + local op = sub(vmdef.irnames, oidx+1, oidx+6) + if op == "CARG " then + dumpcallargs(tr, op1) + if op2 < 0 then + out:write(" ", formatk(tr, op2)) + else + out:write(" ", format("%04d", op2)) + end + else + out:write(format("%04d", ins)) + end + end +end + +-- Dump IR and interleaved snapshots. +local function dump_ir(tr, dumpsnap, dumpreg) + local info = traceinfo(tr) + if not info then return end + local nins = info.nins + out:write("---- TRACE ", tr, " IR\n") + local irnames = vmdef.irnames + local snapref = 65536 + local snap, snapno + if dumpsnap then + snap = tracesnap(tr, 0) + snapref = snap[0] + snapno = 0 + end + for ins=1,nins do + if ins >= snapref then + if dumpreg then + out:write(format(".... SNAP #%-3d [ ", snapno)) + else + out:write(format(".... SNAP #%-3d [ ", snapno)) + end + printsnap(tr, snap) + snapno = snapno + 1 + snap = tracesnap(tr, snapno) + snapref = snap and snap[0] or 65536 + end + local m, ot, op1, op2, ridsp = traceir(tr, ins) + local oidx, t = 6*shr(ot, 8), band(ot, 31) + local op = sub(irnames, oidx+1, oidx+6) + if op == "LOOP " then + if dumpreg then + out:write(format("%04d ------------ LOOP ------------\n", ins)) + else + out:write(format("%04d ------ LOOP ------------\n", ins)) + end + elseif op ~= "NOP " and op ~= "CARG " and + (dumpreg or op ~= "RENAME") then + local rid = band(ridsp, 255) + if dumpreg then + out:write(format("%04d %-6s", ins, ridsp_name(ridsp, ins))) + else + out:write(format("%04d ", ins)) + end + out:write(format("%s%s %s %s ", + (rid == 254 or rid == 253) and "}" or + (band(ot, 128) == 0 and " " or ">"), + band(ot, 64) == 0 and " " or "+", + irtype[t], op)) + local m1, m2 = band(m, 3), band(m, 3*4) + if sub(op, 1, 4) == "CALL" then + local ctype + if m2 == 1*4 then -- op2 == IRMlit + out:write(format("%-10s (", vmdef.ircall[op2])) + else + ctype = dumpcallfunc(tr, op2) + end + if op1 ~= -1 then dumpcallargs(tr, op1) end + out:write(")") + if ctype then out:write(" ctype ", ctype) end + elseif op == "CNEW " and op2 == -1 then + out:write(formatk(tr, op1)) + elseif m1 ~= 3 then -- op1 != IRMnone + if op1 < 0 then + out:write(formatk(tr, op1)) + else + out:write(format(m1 == 0 and "%04d" or "#%-3d", op1)) + end + if m2 ~= 3*4 then -- op2 != IRMnone + if m2 == 1*4 then -- op2 == IRMlit + local litn = litname[op] + if litn and litn[op2] then + out:write(" ", litn[op2]) + elseif op == "UREFO " or op == "UREFC " then + out:write(format(" #%-3d", shr(op2, 8))) + else + out:write(format(" #%-3d", op2)) + end + elseif op2 < 0 then + out:write(" ", formatk(tr, op2)) + else + out:write(format(" %04d", op2)) + end + end + end + out:write("\n") + end + end + if snap then + if dumpreg then + out:write(format(".... SNAP #%-3d [ ", snapno)) + else + out:write(format(".... SNAP #%-3d [ ", snapno)) + end + printsnap(tr, snap) + end +end + +------------------------------------------------------------------------------ + +local recprefix = "" +local recdepth = 0 + +-- Format trace error message. +local function fmterr(err, info) + if type(err) == "number" then + if type(info) == "function" then info = fmtfunc(info) end + err = format(vmdef.traceerr[err], info) + end + return err +end + +-- Dump trace states. +local function dump_trace(what, tr, func, pc, otr, oex) + if what == "stop" or (what == "abort" and dumpmode.a) then + if dumpmode.i then dump_ir(tr, dumpmode.s, dumpmode.r and what == "stop") + elseif dumpmode.s then dump_snap(tr) end + if dumpmode.m then dump_mcode(tr) end + end + if what == "start" then + if dumpmode.H then out:write('
\n') end
+    out:write("---- TRACE ", tr, " ", what)
+    if otr then out:write(" ", otr, "/", oex == -1 and "stitch" or oex) end
+    out:write(" ", fmtfunc(func, pc), "\n")
+  elseif what == "stop" or what == "abort" then
+    out:write("---- TRACE ", tr, " ", what)
+    if what == "abort" then
+      out:write(" ", fmtfunc(func, pc), " -- ", fmterr(otr, oex), "\n")
+    else
+      local info = traceinfo(tr)
+      local link, ltype = info.link, info.linktype
+      if link == tr or link == 0 then
+	out:write(" -> ", ltype, "\n")
+      elseif ltype == "root" then
+	out:write(" -> ", link, "\n")
+      else
+	out:write(" -> ", link, " ", ltype, "\n")
+      end
+    end
+    if dumpmode.H then out:write("
\n\n") else out:write("\n") end + else + if what == "flush" then symtab, nexitsym = {}, 0 end + out:write("---- TRACE ", what, "\n\n") + end + out:flush() +end + +-- Dump recorded bytecode. +local function dump_record(tr, func, pc, depth) + if depth ~= recdepth then + recdepth = depth + recprefix = rep(" .", depth) + end + local line + if pc >= 0 then + line = bcline(func, pc, recprefix) + if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end + else + line = "0000 "..recprefix.." FUNCC \n" + end + if pc <= 0 then + out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n") + else + out:write(line) + end + if pc >= 0 and band(funcbc(func, pc), 0xff) < 16 then -- ORDER BC + out:write(bcline(func, pc+1, recprefix)) -- Write JMP for cond. + end +end + +------------------------------------------------------------------------------ + +local gpr64 = jit.arch:match("64") +local fprmips32 = jit.arch == "mips" or jit.arch == "mipsel" + +-- Dump taken trace exits. +local function dump_texit(tr, ex, ngpr, nfpr, ...) + out:write("---- TRACE ", tr, " exit ", ex, "\n") + if dumpmode.X then + local regs = {...} + if gpr64 then + for i=1,ngpr do + out:write(format(" %016x", regs[i])) + if i % 4 == 0 then out:write("\n") end + end + else + for i=1,ngpr do + out:write(" ", tohex(regs[i])) + if i % 8 == 0 then out:write("\n") end + end + end + if fprmips32 then + for i=1,nfpr,2 do + out:write(format(" %+17.14g", regs[ngpr+i])) + if i % 8 == 7 then out:write("\n") end + end + else + for i=1,nfpr do + out:write(format(" %+17.14g", regs[ngpr+i])) + if i % 4 == 0 then out:write("\n") end + end + end + end +end + +------------------------------------------------------------------------------ + +-- Detach dump handlers. +local function dumpoff() + if active then + active = false + jit.attach(dump_texit) + jit.attach(dump_record) + jit.attach(dump_trace) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handlers. +local function dumpon(opt, outfile) + if active then dumpoff() end + + local term = os.getenv("TERM") + local colormode = (term and term:match("color") or os.getenv("COLORTERM")) and "A" or "T" + if opt then + opt = gsub(opt, "[TAH]", function(mode) colormode = mode; return ""; end) + end + + local m = { t=true, b=true, i=true, m=true, } + if opt and opt ~= "" then + local o = sub(opt, 1, 1) + if o ~= "+" and o ~= "-" then m = {} end + for i=1,#opt do m[sub(opt, i, i)] = (o ~= "-") end + end + dumpmode = m + + if m.t or m.b or m.i or m.s or m.m then + jit.attach(dump_trace, "trace") + end + if m.b then + jit.attach(dump_record, "record") + if not bcline then bcline = require("jit.bc").line end + end + if m.x or m.X then + jit.attach(dump_texit, "texit") + end + + if not outfile then outfile = os.getenv("LUAJIT_DUMPFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stdout + end + + m[colormode] = true + if colormode == "A" then + colorize = colorize_ansi + irtype = irtype_ansi + elseif colormode == "H" then + colorize = colorize_html + irtype = irtype_html + out:write(header_html) + else + colorize = colorize_text + irtype = irtype_text + end + + active = true +end + +-- Public module functions. +return { + on = dumpon, + off = dumpoff, + start = dumpon -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/p.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/p.lua new file mode 100644 index 00000000..c9ec1d8b --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/p.lua @@ -0,0 +1,312 @@ +---------------------------------------------------------------------------- +-- LuaJIT profiler. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module is a simple command line interface to the built-in +-- low-overhead profiler of LuaJIT. +-- +-- The lower-level API of the profiler is accessible via the "jit.profile" +-- module or the luaJIT_profile_* C API. +-- +-- Example usage: +-- +-- luajit -jp myapp.lua +-- luajit -jp=s myapp.lua +-- luajit -jp=-s myapp.lua +-- luajit -jp=vl myapp.lua +-- luajit -jp=G,profile.txt myapp.lua +-- +-- The following dump features are available: +-- +-- f Stack dump: function name, otherwise module:line. Default mode. +-- F Stack dump: ditto, but always prepend module. +-- l Stack dump: module:line. +-- stack dump depth (callee < caller). Default: 1. +-- - Inverse stack dump depth (caller > callee). +-- s Split stack dump after first stack level. Implies abs(depth) >= 2. +-- p Show full path for module names. +-- v Show VM states. Can be combined with stack dumps, e.g. vf or fv. +-- z Show zones. Can be combined with stack dumps, e.g. zf or fz. +-- 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 (e.g. flame graphs). +-- m Minimum sample percentage to be shown. Default: 3. +-- i Sampling interval in milliseconds. Default: 10. +-- +---------------------------------------------------------------------------- + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local profile = require("jit.profile") +local vmdef = require("jit.vmdef") +local math = math +local pairs, ipairs, tonumber, floor = pairs, ipairs, tonumber, math.floor +local sort, format = table.sort, string.format +local stdout = io.stdout +local zone -- Load jit.zone module on demand. + +-- Output file handle. +local out + +------------------------------------------------------------------------------ + +local prof_ud +local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth +local prof_ann, prof_count1, prof_count2, prof_samples + +local map_vmmode = { + N = "Compiled", + I = "Interpreted", + C = "C code", + G = "Garbage Collector", + J = "JIT Compiler", +} + +-- Profiler callback. +local function prof_cb(th, samples, vmmode) + prof_samples = prof_samples + samples + local key_stack, key_stack2, key_state + -- Collect keys for sample. + if prof_states then + if prof_states == "v" then + key_state = map_vmmode[vmmode] or vmmode + else + key_state = zone:get() or "(none)" + end + end + if prof_fmt then + key_stack = profile.dumpstack(th, prof_fmt, prof_depth) + key_stack = key_stack:gsub("%[builtin#(%d+)%]", function(x) + return vmdef.ffnames[tonumber(x)] + end) + if prof_split == 2 then + local k1, k2 = key_stack:match("(.-) [<>] (.*)") + if k2 then key_stack, key_stack2 = k1, k2 end + elseif prof_split == 3 then + key_stack2 = profile.dumpstack(th, "l", 1) + end + end + -- Order keys. + local k1, k2 + if prof_split == 1 then + if key_state then + k1 = key_state + if key_stack then k2 = key_stack end + end + elseif key_stack then + k1 = key_stack + if key_stack2 then k2 = key_stack2 elseif key_state then k2 = key_state end + end + -- Coalesce samples in one or two levels. + if k1 then + local t1 = prof_count1 + t1[k1] = (t1[k1] or 0) + samples + if k2 then + local t2 = prof_count2 + local t3 = t2[k1] + if not t3 then t3 = {}; t2[k1] = t3 end + t3[k2] = (t3[k2] or 0) + samples + end + end +end + +------------------------------------------------------------------------------ + +-- Show top N list. +local function prof_top(count1, count2, samples, indent) + local t, n = {}, 0 + for k in pairs(count1) do + n = n + 1 + t[n] = k + end + sort(t, function(a, b) return count1[a] > count1[b] end) + for i=1,n do + local k = t[i] + local v = count1[k] + local pct = floor(v*100/samples + 0.5) + if pct < prof_min then break end + if not prof_raw then + out:write(format("%s%2d%% %s\n", indent, pct, k)) + elseif prof_raw == "r" then + out:write(format("%s%5d %s\n", indent, v, k)) + else + out:write(format("%s %d\n", k, v)) + end + if count2 then + local r = count2[k] + if r then + prof_top(r, nil, v, (prof_split == 3 or prof_split == 1) and " -- " or + (prof_depth < 0 and " -> " or " <- ")) + end + end + end +end + +-- Annotate source code +local function prof_annotate(count1, samples) + local files = {} + local ms = 0 + for k, v in pairs(count1) do + local pct = floor(v*100/samples + 0.5) + ms = math.max(ms, v) + if pct >= prof_min then + local file, line = k:match("^(.*):(%d+)$") + if not file then file = k; line = 0 end + local fl = files[file] + if not fl then fl = {}; files[file] = fl; files[#files+1] = file end + line = tonumber(line) + fl[line] = prof_raw and v or pct + end + end + sort(files) + local fmtv, fmtn = " %3d%% | %s\n", " | %s\n" + if prof_raw then + local n = math.max(5, math.ceil(math.log10(ms))) + fmtv = "%"..n.."d | %s\n" + fmtn = (" "):rep(n).." | %s\n" + end + local ann = prof_ann + for _, file in ipairs(files) do + local f0 = file:byte() + if f0 == 40 or f0 == 91 then + out:write(format("\n====== %s ======\n[Cannot annotate non-file]\n", file)) + break + end + local fp, err = io.open(file) + if not fp then + out:write(format("====== ERROR: %s: %s\n", file, err)) + break + end + out:write(format("\n====== %s ======\n", file)) + local fl = files[file] + local n, show = 1, false + if ann ~= 0 then + for i=1,ann do + if fl[i] then show = true; out:write("@@ 1 @@\n"); break end + end + end + for line in fp:lines() do + if line:byte() == 27 then + out:write("[Cannot annotate bytecode file]\n") + break + end + local v = fl[n] + if ann ~= 0 then + local v2 = fl[n+ann] + if show then + if v2 then show = n+ann elseif v then show = n + elseif show+ann < n then show = false end + elseif v2 then + show = n+ann + out:write(format("@@ %d @@\n", n)) + end + if not show then goto next end + end + if v then + out:write(format(fmtv, v, line)) + else + out:write(format(fmtn, line)) + end + ::next:: + n = n + 1 + end + fp:close() + end +end + +------------------------------------------------------------------------------ + +-- Finish profiling and dump result. +local function prof_finish() + if prof_ud then + profile.stop() + local samples = prof_samples + if samples == 0 then + if prof_raw ~= true then out:write("[No samples collected]\n") end + return + end + if prof_ann then + prof_annotate(prof_count1, samples) + else + prof_top(prof_count1, prof_count2, samples, "") + end + prof_count1 = nil + prof_count2 = nil + prof_ud = nil + if out ~= stdout then out:close() end + end +end + +-- Start profiling. +local function prof_start(mode) + local interval = "" + mode = mode:gsub("i%d*", function(s) interval = s; return "" end) + prof_min = 3 + mode = mode:gsub("m(%d+)", function(s) prof_min = tonumber(s); return "" end) + prof_depth = 1 + mode = mode:gsub("%-?%d+", function(s) prof_depth = tonumber(s); return "" end) + local m = {} + for c in mode:gmatch(".") do m[c] = c end + prof_states = m.z or m.v + if prof_states == "z" then zone = require("jit.zone") end + local scope = m.l or m.f or m.F or (prof_states and "" or "f") + local flags = (m.p or "") + prof_raw = m.r + if m.s then + prof_split = 2 + if prof_depth == -1 or m["-"] then prof_depth = -2 + elseif prof_depth == 1 then prof_depth = 2 end + elseif mode:find("[fF].*l") then + scope = "l" + prof_split = 3 + else + prof_split = (scope == "" or mode:find("[zv].*[lfF]")) and 1 or 0 + end + prof_ann = m.A and 0 or (m.a and 3) + if prof_ann then + scope = "l" + prof_fmt = "pl" + prof_split = 0 + prof_depth = 1 + elseif m.G and scope ~= "" then + prof_fmt = flags..scope.."Z;" + prof_depth = -100 + prof_raw = true + prof_min = 0 + elseif scope == "" then + prof_fmt = false + else + local sc = prof_split == 3 and m.f or m.F or scope + prof_fmt = flags..sc..(prof_depth >= 0 and "Z < " or "Z > ") + end + prof_count1 = {} + prof_count2 = {} + prof_samples = 0 + profile.start(scope:lower()..interval, prof_cb) + prof_ud = newproxy(true) + getmetatable(prof_ud).__gc = prof_finish +end + +------------------------------------------------------------------------------ + +local function start(mode, outfile) + if not outfile then outfile = os.getenv("LUAJIT_PROFILEFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stdout + end + prof_start(mode or "f") +end + +-- Public module functions. +return { + start = start, -- For -j command line option. + stop = prof_finish +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/v.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/v.lua new file mode 100644 index 00000000..83589143 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/v.lua @@ -0,0 +1,170 @@ +---------------------------------------------------------------------------- +-- Verbose mode of the LuaJIT compiler. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module shows verbose information about the progress of the +-- JIT compiler. It prints one line for each generated trace. This module +-- is useful to see which code has been compiled or where the compiler +-- punts and falls back to the interpreter. +-- +-- Example usage: +-- +-- luajit -jv -e "for i=1,1000 do for j=1,1000 do end end" +-- luajit -jv=myapp.out myapp.lua +-- +-- Default output is to stderr. To redirect the output to a file, pass a +-- filename as an argument (use '-' for stdout) or set the environment +-- variable LUAJIT_VERBOSEFILE. The file is overwritten every time the +-- module is started. +-- +-- The output from the first example should look like this: +-- +-- [TRACE 1 (command line):1 loop] +-- [TRACE 2 (1/3) (command line):1 -> 1] +-- +-- The first number in each line is the internal trace number. Next are +-- the file name ('(command line)') and the line number (':1') where the +-- trace has started. Side traces also show the parent trace number and +-- the exit number where they are attached to in parentheses ('(1/3)'). +-- An arrow at the end shows where the trace links to ('-> 1'), unless +-- it loops to itself. +-- +-- In this case the inner loop gets hot and is traced first, generating +-- a root trace. Then the last exit from the 1st trace gets hot, too, +-- and triggers generation of the 2nd trace. The side trace follows the +-- path along the outer loop and *around* the inner loop, back to its +-- start, and then links to the 1st trace. Yes, this may seem unusual, +-- if you know how traditional compilers work. Trace compilers are full +-- of surprises like this -- have fun! :-) +-- +-- Aborted traces are shown like this: +-- +-- [TRACE --- foo.lua:44 -- leaving loop in root trace at foo:lua:50] +-- +-- Don't worry -- trace aborts are quite common, even in programs which +-- can be fully compiled. The compiler may retry several times until it +-- finds a suitable trace. +-- +-- Of course this doesn't work with features that are not-yet-implemented +-- (NYI error messages). The VM simply falls back to the interpreter. This +-- may not matter at all if the particular trace is not very high up in +-- the CPU usage profile. Oh, and the interpreter is quite fast, too. +-- +-- Also check out the -jdump module, which prints all the gory details. +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo +local type, format = type, string.format +local stdout, stderr = io.stdout, io.stderr + +-- Active flag and output file handle. +local active, out + +------------------------------------------------------------------------------ + +local startloc, startex + +local function fmtfunc(func, pc) + local fi = funcinfo(func, pc) + if fi.loc then + return fi.loc + elseif fi.ffid then + return vmdef.ffnames[fi.ffid] + elseif fi.addr then + return format("C:%x", fi.addr) + else + return "(?)" + end +end + +-- Format trace error message. +local function fmterr(err, info) + if type(err) == "number" then + if type(info) == "function" then info = fmtfunc(info) end + err = format(vmdef.traceerr[err], info) + end + return err +end + +-- Dump trace states. +local function dump_trace(what, tr, func, pc, otr, oex) + if what == "start" then + startloc = fmtfunc(func, pc) + startex = otr and "("..otr.."/"..(oex == -1 and "stitch" or oex)..") " or "" + else + if what == "abort" then + local loc = fmtfunc(func, pc) + if loc ~= startloc then + out:write(format("[TRACE --- %s%s -- %s at %s]\n", + startex, startloc, fmterr(otr, oex), loc)) + else + out:write(format("[TRACE --- %s%s -- %s]\n", + startex, startloc, fmterr(otr, oex))) + end + elseif what == "stop" then + local info = traceinfo(tr) + local link, ltype = info.link, info.linktype + if ltype == "interpreter" then + out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n", + tr, startex, startloc)) + elseif ltype == "stitch" then + out:write(format("[TRACE %3s %s%s %s %s]\n", + tr, startex, startloc, ltype, fmtfunc(func, pc))) + elseif link == tr or link == 0 then + out:write(format("[TRACE %3s %s%s %s]\n", + tr, startex, startloc, ltype)) + elseif ltype == "root" then + out:write(format("[TRACE %3s %s%s -> %d]\n", + tr, startex, startloc, link)) + else + out:write(format("[TRACE %3s %s%s -> %d %s]\n", + tr, startex, startloc, link, ltype)) + end + else + out:write(format("[TRACE %s]\n", what)) + end + out:flush() + end +end + +------------------------------------------------------------------------------ + +-- Detach dump handlers. +local function dumpoff() + if active then + active = false + jit.attach(dump_trace) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handlers. +local function dumpon(outfile) + if active then dumpoff() end + if not outfile then outfile = os.getenv("LUAJIT_VERBOSEFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stderr + end + jit.attach(dump_trace, "trace") + active = true +end + +-- Public module functions. +return { + on = dumpon, + off = dumpoff, + start = dumpon -- For -j command line option. +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/vmdef.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/vmdef.lua new file mode 100644 index 00000000..68ff7ba2 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/vmdef.lua @@ -0,0 +1,395 @@ +-- This is a generated file. DO NOT EDIT! + +return { + +bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF ISTYPEISNUM MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TGETR TSETV TSETS TSETB TSETM TSETR CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW", + +irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEPROF KPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF TMPREFSTRREFLREF ALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ALEN ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI BUFHDRBUFPUTBUFSTRTBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLA CALLL CALLS CALLXSCARG ", + +irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "log", "log2", "other", }, + +irfield = { [0]="str.len", "func.env", "func.pc", "func.ffid", "thread.env", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "sbuf.w", "sbuf.e", "sbuf.b", "sbuf.l", "sbuf.ref", "sbuf.r", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", }, + +ircall = { +[0]="lj_str_cmp", +"lj_str_find", +"lj_str_new", +"lj_strscan_num", +"lj_strfmt_int", +"lj_strfmt_num", +"lj_strfmt_char", +"lj_strfmt_putint", +"lj_strfmt_putnum", +"lj_strfmt_putquoted", +"lj_strfmt_putfxint", +"lj_strfmt_putfnum_int", +"lj_strfmt_putfnum_uint", +"lj_strfmt_putfnum", +"lj_strfmt_putfstr", +"lj_strfmt_putfchar", +"lj_buf_putmem", +"lj_buf_putstr", +"lj_buf_putchar", +"lj_buf_putstr_reverse", +"lj_buf_putstr_lower", +"lj_buf_putstr_upper", +"lj_buf_putstr_rep", +"lj_buf_puttab", +"lj_bufx_set", +"lj_bufx_more", +"lj_serialize_put", +"lj_serialize_get", +"lj_serialize_encode", +"lj_serialize_decode", +"lj_buf_tostr", +"lj_tab_new_ah", +"lj_tab_new1", +"lj_tab_dup", +"lj_tab_clear", +"lj_tab_newkey", +"lj_tab_keyindex", +"lj_vm_next", +"lj_tab_len", +"lj_tab_len_hint", +"lj_gc_step_jit", +"lj_gc_barrieruv", +"lj_mem_newgco", +"lj_prng_u64d", +"lj_vm_modi", +"log10", +"exp", +"sin", +"cos", +"tan", +"asin", +"acos", +"atan", +"sinh", +"cosh", +"tanh", +"fputc", +"fwrite", +"fflush", +"lj_vm_floor", +"lj_vm_ceil", +"lj_vm_trunc", +"sqrt", +"log", +"lj_vm_log2", +"lj_vm_powi", +"pow", +"atan2", +"ldexp", +"lj_vm_tobit", +"softfp_add", +"softfp_sub", +"softfp_mul", +"softfp_div", +"softfp_cmp", +"softfp_i2d", +"softfp_d2i", +"lj_vm_sfmin", +"lj_vm_sfmax", +"lj_vm_tointg", +"softfp_ui2d", +"softfp_f2d", +"softfp_d2ui", +"softfp_d2f", +"softfp_i2f", +"softfp_ui2f", +"softfp_f2i", +"softfp_f2ui", +"fp64_l2d", +"fp64_ul2d", +"fp64_l2f", +"fp64_ul2f", +"fp64_d2l", +"fp64_d2ul", +"fp64_f2l", +"fp64_f2ul", +"lj_carith_divi64", +"lj_carith_divu64", +"lj_carith_modi64", +"lj_carith_modu64", +"lj_carith_powi64", +"lj_carith_powu64", +"lj_cdata_newv", +"lj_cdata_setfin", +"strlen", +"memcpy", +"memset", +"lj_vm_errno", +"lj_carith_mul64", +"lj_carith_shl64", +"lj_carith_shr64", +"lj_carith_sar64", +"lj_carith_rol64", +"lj_carith_ror64", +}, + +traceerr = { +[0]="error thrown or hook called during recording", +"trace too short", +"trace too long", +"trace too deep", +"too many snapshots", +"blacklisted", +"retry recording", +"NYI: bytecode %d", +"leaving loop in root trace", +"inner loop in root trace", +"loop unroll limit reached", +"bad argument type", +"JIT compilation disabled for function", +"call unroll limit reached", +"down-recursion, restarting", +"NYI: unsupported variant of FastFunc %s", +"NYI: return to lower frame", +"store with nil or NaN key", +"missing metamethod", +"looping index lookup", +"NYI: mixed sparse/dense table", +"symbol not in cache", +"NYI: unsupported C type conversion", +"NYI: unsupported C function type", +"guard would always fail", +"too many PHIs", +"persistent type instability", +"failed to allocate mcode memory", +"machine code too long", +"hit mcode limit (retrying)", +"too many spill slots", +"inconsistent register allocation", +"NYI: cannot assemble IR instruction %d", +"NYI: PHI shuffling too complex", +"NYI: register coalescing too complex", +}, + +ffnames = { +[0]="Lua", +"C", +"assert", +"type", +"next", +"pairs", +"ipairs_aux", +"ipairs", +"getmetatable", +"setmetatable", +"getfenv", +"setfenv", +"rawget", +"rawset", +"rawequal", +"unpack", +"select", +"tonumber", +"tostring", +"error", +"pcall", +"xpcall", +"loadfile", +"load", +"loadstring", +"dofile", +"gcinfo", +"collectgarbage", +"newproxy", +"print", +"coroutine.status", +"coroutine.running", +"coroutine.isyieldable", +"coroutine.create", +"coroutine.yield", +"coroutine.resume", +"coroutine.wrap_aux", +"coroutine.wrap", +"math.abs", +"math.floor", +"math.ceil", +"math.sqrt", +"math.log10", +"math.exp", +"math.sin", +"math.cos", +"math.tan", +"math.asin", +"math.acos", +"math.atan", +"math.sinh", +"math.cosh", +"math.tanh", +"math.frexp", +"math.modf", +"math.log", +"math.atan2", +"math.pow", +"math.fmod", +"math.ldexp", +"math.min", +"math.max", +"math.random", +"math.randomseed", +"bit.tobit", +"bit.bnot", +"bit.bswap", +"bit.lshift", +"bit.rshift", +"bit.arshift", +"bit.rol", +"bit.ror", +"bit.band", +"bit.bor", +"bit.bxor", +"bit.tohex", +"string.byte", +"string.char", +"string.sub", +"string.rep", +"string.reverse", +"string.lower", +"string.upper", +"string.dump", +"string.find", +"string.match", +"string.gmatch_aux", +"string.gmatch", +"string.gsub", +"string.format", +"table.maxn", +"table.insert", +"table.concat", +"table.sort", +"table.new", +"table.clear", +"io.method.close", +"io.method.read", +"io.method.write", +"io.method.flush", +"io.method.seek", +"io.method.setvbuf", +"io.method.lines", +"io.method.__gc", +"io.method.__tostring", +"io.open", +"io.popen", +"io.tmpfile", +"io.close", +"io.read", +"io.write", +"io.flush", +"io.input", +"io.output", +"io.lines", +"io.type", +"os.execute", +"os.remove", +"os.rename", +"os.tmpname", +"os.getenv", +"os.exit", +"os.clock", +"os.date", +"os.time", +"os.difftime", +"os.setlocale", +"debug.getregistry", +"debug.getmetatable", +"debug.setmetatable", +"debug.getfenv", +"debug.setfenv", +"debug.getinfo", +"debug.getlocal", +"debug.setlocal", +"debug.getupvalue", +"debug.setupvalue", +"debug.upvalueid", +"debug.upvaluejoin", +"debug.sethook", +"debug.gethook", +"debug.debug", +"debug.traceback", +"jit.on", +"jit.off", +"jit.flush", +"jit.status", +"jit.security", +"jit.attach", +"jit.util.funcinfo", +"jit.util.funcbc", +"jit.util.funck", +"jit.util.funcuvname", +"jit.util.traceinfo", +"jit.util.traceir", +"jit.util.tracek", +"jit.util.tracesnap", +"jit.util.tracemc", +"jit.util.traceexitstub", +"jit.util.ircalladdr", +"jit.opt.start", +"jit.profile.start", +"jit.profile.stop", +"jit.profile.dumpstack", +"ffi.meta.__index", +"ffi.meta.__newindex", +"ffi.meta.__eq", +"ffi.meta.__len", +"ffi.meta.__lt", +"ffi.meta.__le", +"ffi.meta.__concat", +"ffi.meta.__call", +"ffi.meta.__add", +"ffi.meta.__sub", +"ffi.meta.__mul", +"ffi.meta.__div", +"ffi.meta.__mod", +"ffi.meta.__pow", +"ffi.meta.__unm", +"ffi.meta.__tostring", +"ffi.meta.__pairs", +"ffi.meta.__ipairs", +"ffi.clib.__index", +"ffi.clib.__newindex", +"ffi.clib.__gc", +"ffi.callback.free", +"ffi.callback.set", +"ffi.cdef", +"ffi.new", +"ffi.cast", +"ffi.typeof", +"ffi.typeinfo", +"ffi.istype", +"ffi.sizeof", +"ffi.alignof", +"ffi.offsetof", +"ffi.errno", +"ffi.string", +"ffi.copy", +"ffi.fill", +"ffi.abi", +"ffi.metatype", +"ffi.gc", +"ffi.load", +"buffer.method.free", +"buffer.method.reset", +"buffer.method.skip", +"buffer.method.set", +"buffer.method.put", +"buffer.method.putf", +"buffer.method.get", +"buffer.method.putcdata", +"buffer.method.reserve", +"buffer.method.commit", +"buffer.method.ref", +"buffer.method.encode", +"buffer.method.decode", +"buffer.method.__gc", +"buffer.method.__tostring", +"buffer.method.__len", +"buffer.new", +"buffer.encode", +"buffer.decode", +}, + +} + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/jit/zone.lua b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/zone.lua new file mode 100644 index 00000000..94357854 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/android/x86_64/jit/zone.lua @@ -0,0 +1,45 @@ +---------------------------------------------------------------------------- +-- LuaJIT profiler zones. +-- +-- Copyright (C) 2005-2021 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module implements a simple hierarchical zone model. +-- +-- Example usage: +-- +-- local zone = require("jit.zone") +-- zone("AI") +-- ... +-- zone("A*") +-- ... +-- print(zone:get()) --> "A*" +-- ... +-- zone() +-- ... +-- print(zone:get()) --> "AI" +-- ... +-- zone() +-- +---------------------------------------------------------------------------- + +local remove = table.remove + +return setmetatable({ + flush = function(t) + for i=#t,1,-1 do t[i] = nil end + end, + get = function(t) + return t[#t] + end +}, { + __call = function(t, zone) + if zone then + t[#t+1] = zone + else + return (assert(remove(t), "empty zone stack")) + end + end +}) + diff --git a/love/src/jni/LuaJIT-2.1/android/x86_64/libluajit.a b/love/src/jni/LuaJIT-2.1/android/x86_64/libluajit.a index e208906374d78e59cb0eed3822179848ce8f3db3..3275e35c1917845362d5f6ba51c04fcfb95460d9 100644 GIT binary patch delta 356151 zcmeFa3v^RO*FT&&Ewn)Kv`|RPHH82zEzojpxi&PVCy>frDi;B{h=K^E<)TPh(gMd2 z1dlqXsNfZEh*k*#Vnd-Vs93;DMS6j8jdeOw zuG1OT|5yKP|80W*LwdIVYHR+7m7{Lke^;FUV+L&h<^KGiGVuTR|NmVD{Kx)(DNLvP zU;4BCZ&mbf>cRN`Uux+;*JJzN6ZJnbVEez?`Y_%9?f#$q|7QOeWreJ0)X-uXmp?l?)1kN%$h$nXZnNlX6Y8qpT1yf?xI<_i*>Bz;zzqb)P+4@ zB}I9_5EaxjrLVHg&_l>uqP%P9**LhPPG`S)QM6xI{xFPbytM;=d{r45Gp4cC|Cpw{ zg2$Q|j{Q@)7PFyAJswT=>zBoXzm?}ZBm}>NXC<*iZ{=EtE=}g#LO!4*bnGDrG0K#V z_mY#!`yEG;b;^y7nIsk8MrFP+j$BkW8V9u9(O##Mu2e{lghP`1W)I0;5}a}%r-l6{ zYIyPW8Y3aQl?$DWp}DI4*9Lpj!^f26z3?L6UOWuD-E;QDlz1hQJWH?}{qDspUpA)<|PAU1`3 zulN9ZN$DTg#UQuV>8y@6`z-G3J_lFlAB*>b$97g zN?6yF=5PKBTv4(BzyDw08Oj@7J4YJ+1%6K}i%FhW8k-Q>vx27a? zeT~m&8L)1na)0-QP1%DaPc}xWkRQ5#K+2WE9vvIM(M+cske(>oUs68q(ZA_5JXRk= z1FwsPx8w$d&sgH$N9lR7qj z-=E=iMM+9+`XC;w4`~GNQ>v08LyH+(^0s2-Mp6&5Pf6%GlT1-I^lS%O+j|bWjlSG7 zzOfL_YrCp+?UmYMr^txq%?iDq>3IGY9a}GYyHva0-N~a$X7BjhpuFC(P@Q*r4Pxhcn0)XamO@o z&x=ToV7KH*&5|7RjNumf`ML{g`==?N4H!(4i|PgpC9RSHtM~bQCf^T|W4r<4sR6`P zwklZ}H)uk;+vw*j0lz!T!9kCZWTp4uKhXcJhjhm8p+hKsA0N^w^cJ0v)D_M1AU{c- zH7bz)##FflgIgU>j4!y5w+BvkUtORZFdHXA$5ACkvO30$3?P=wNEK`=HPj2x_b5>6)t9*hF zqk7T)lyWA$TVr1cY)c(vKURquHmLD-|6`akXINtNVmwMab?WDuPio|mGLb(6sv^6Y!N|BOLFati*5cLOk2+ zg2a{M6hlV4us%?I$^N84Cl+>9hG(=%Zpr|1ra^K{th35vYHHI%gL7Ik?L*am?Nf(U zdX)ExhO7Y~_Cth{KVBdFw^+Da`7EPj@180`5DV8~BuI{~7P6kZnH?%Q$JBV3NG179VX^r1W&9M^JkK(e4Fy$5 zC=o2+A(TB-Z&mwer4nIjM`kFAmXz>=!Mx1|R>;v+8I{zcc`$xk9TP)uHPU`j*<_T%Sn(Nv1oMN&LGt4wJ<_Y_SWUJkmU1VPd@BtOe!qSJ*)%`FC-C) zJiG&mQQjZ^dz-!(iRy5Y9BqtukA@FM%xx(C1@7A_?X17I*^jRNw|U!VW;NV?26^`? zPi9Ua`<3r9U+Y(L-sgjs-flpHCaR?uJhPbnS$hZ0i}f#N0m1V|(YAZv3Fbz3+eT&T z*cG=QejoeE?T0Pnx)VvM7}w`EsOfkO)G2BL%z!HBj*v+}H!I8hS&F_MKQ=i0{XdvJ zKOxzFuan}=cwbf$Cr%g;0pqaMkejtNJU4l3SWa(~Z(TV+)$t~A$0`*Wo;#qrZNO7E zWQ$|jlzkH)4b6gv!8TMX{U&`pJoirw7tu9$4!+VJN%4pUGXR066n=0@&1QsFXp)u3 z8zlLp#kto{0Ccn-gfa6bD7_|kBlXJk$=y{$$IKeIx`E;*c@?8#lGhoOcP2mFiCHU) z!*3!hK}J$(|KX=ywyN%e(r?P7usY;q%B$MQSEh^#kxQXFS56jPn9@M7IYuU?99|SF zIVOZlj>wCW{hANDAgfhw=_x$%7|4J zw1IQnJsS2mXXHIv(Xv!^B$RwL)-=I%pJe|l*6RFJwW*Gm^9V+dt5~*IfGI^kZ7!^^ zecDi>Q%a{9;Z{^nQ-b<*PgGV;?~dv6qvcJro}nj?DAVWbNdo&F{RkEa%>+TW3}%jf255;cQTYhi zzoD@V>kQSvR*r3>oCdb+9u0dC=9qm_)o-2d7bRk*KKdG`Y>CvsdpUNXVw$P94CC0Y zoU*^(Fix``MvQ&@@Cwe!!bTe0&&f_@%S^p(5C#mGD}sI6RxfALjY9;Fz(GpUyh16lkyR;=Q(8#)cLW?l+(ao=4JJqvcLNmD-jRrEh~B1hJsf51y1A>4nNsa z13b;)PjfkEVE$pBPFkXKD+?deM}N#)G3KsTJgsbbNN@X`V?$bKg~s!;wVdV(E?d7U zjN|ahJii|9%tv=+6-^@kk4Z~(4=72%8ad4^sFQu()DqnX%5-3>xI&oVzp{_t z>b#|F0M^MVKf;a6R4tQkjN+cFw?uKuD|x*o97}lXE(6a#1GGffnNyR|1MHKiCA!a* zn0fkWiI>{IOZioKyE1y7e%3HvHjZQG@Umf?htD|81spz(x2q|)7DqUIGkTr%=7&Qx zfPa9kMK`IFs8TgAN+=C_?pzZ+W>))@=nklhCB;&J5yu;(~2zp>8eG!G~-3-z`i?<$+dHSA$t zmA}SuT!=?GH9kG*rt(&Q!N+ns=P-uTN#`nUR+ki)aMwwA_efK(1Y&*_A6Iu;IZ z&jsz!W`3pLq6phuE)9QKkqh@d4)+UvGw-}ny)|OSEYjQ7cGAEZ9LqL4n4lZ-?0lT-c5#uN;?+a$ z>SuC@mfyn%@)8bDgQd~ZX0evz@_>*!{M)T6Xc(_4snLA zaJl-Ge=~=#;hF;RsGljk;)%R((RKLPbh_RgVdn+>oHpR_KD+=Il#cR_aPa(o$*t!~ z(wsK{{iuE_IYZ64|04(B9Sp_*+%MAvvtWd(p$wCmL`&w zYR-A=J7U^BT8A!Zp|St6vTSJ=Qle~Gs*mns&|ui5S3ifjDw&ldz)s~ol*+O9aMgHO zAR|Y;rYB7lQ?`RhqF<_n%#iIEgT*MWo2*=?-4Mgewf?K z;FmP`P@TjPk8!!q8ms~QlU+Nmyra3iAK>||oY8H{X*A;}Ug|-PZOhquk@rRnhmYa4 z9OoLrxzm+$A$Dl5Wn9biU*xr1;rXG0>gQ43yyr9mHr-f`xXCM6&M8N8xSPvw42O5+ z@C!VD2yXxf>xOZL{BVD>yYXHf(oV|>KJWoB=$6Kl<@)HyINIOoHC!Hxl_X&A=h&7S z4c#l8i2=&=<$7C`Q3E&S*gm|iemDo~CUJN(p5L!R(p_+W{#WsXb$xf9e-KA>;Q2Y+ z=FhKtn#*i1FA&8sPxDTBpTlQz_$n@&w>cbi)z3GUpA@%-MR9D`9g^P2ki*Ir%saw+I@$ zk`l2(Z&}Yvaqm)>$*IlerTo+`@lrQAybGt+pTm=sg)8)N%Q!ZbV;gZ1bmGjSA?oKL z#q_AY!8%L?+`_N;g!C$U&eohnmvgOwP<1Eq$M#y;CrNSV>7(az)neF{0obz)Yum{i z!>~UGU?VtN4E}2Xd`kfQL;yUJcMQw#4S)|1fPWtVFVo=4>ih`H9|3tP1M)O5;sGB< z^Em$e?V1<>KNbLgSvj4rw;T$Msgb&01 zi9bIN_bLm4-4@Sq8a7b!CzUNL^_B~o`l@9Eu|2rY$!I2$+cc*Hz>@;t4u#nD(Vqoi zdk0|uRFZ&g!JS}6vu^-4O_>ht!T>DG;cvyO$_8M+4#4&aD0^LT+x3>XL=?b>mFpLP zogV=26#y>^fWyY!s;f?kDbQQy@)63Yg#}<;0q~vy)WlxMgb&Mq3V(jihbZ|4`sfVJ zkyWwT0oeDHkAN-uH(0%L8rb%H{4&acWfdi&5UWEzy)f*N0LncT6R?!etqfZofGt%P z0-MLDIEKv+z`m<&Db!n@<8BATo(aHaa_h_B_5gVAR6O9r;EV9*m%wuhSv8kjRUTcH zL9P~kx+;MLFMf3D{G#KlM+6rouB{9X^#_#{1#M^^%#fC%rq3-D$Xq3#>Kl1xGpah> zv&t4aB&eH7N89H#ZTrl|C}HDNrPap4!lNdfN#LwvV>k|U^Ec`l;KhxDan$_d#vwxL zY^Bu;gGrTg{|iHe&9jvkU+7F0Def2ajk1Pngj1E%FC>NfLrW2m(z0Q4a&ph)WaV)~ z_n>KOnif6u;t3)ccPYa*nT2h;l(m}*gsnwNvzPk{sb46=UmhmJ7AeoX+`W0-#{@^B zwq#xI1*_~!s`cnsDaT%(BCPpX>G{e5!TphP^_306{O-!ySEGcPyNlj>wWlD|>@GUK zWf*BFu6BSQrNiq++cp?Q$+0NBc35aoPN-GB;@Jd9-V=?3awpWLNkWbu*ilkpZO%Qn zvn zEO@<3I6G8Ajk=tYyb+AwtkDWy0G%grlD+ zYu>(h{Lp4P-R$+_P4|s8$+Z#=dmWF3+uz(Dq|==*&1j;NoT~PCnB>I?#bTUJj7v4( zFWfTYu(V6pbDU+kX}ncxbO=Xck~{||cx4_P-R%xdvW>FW3%LzEY;N`}0C%VZF$48h zM@G2CzH=!CBhI0jrdk|}4Hn0}$&$Ua&g!&;T2l^-tJvVMI95PvIFH|t2dh(E4OB-- z4x2%;|B4gKlgPOw$@>XvnsX4od+n66xktB_Jk7ez`lCWJ|a zN0%*AOBecbk5(^|9PQ*vdsT>KM(|22sqj@f(r!p@PlHZ%urE?vDfp>jHB?kfl6{4T zGDD<}Gd9B3G2+4ucL@xrpj>n?gDE z3gFi>4M(&V#{;n@`({XjAF1CJoTVIM`1MRq^k=(@C6< zDrR>V+ZTX}PPbn9`JE1=zv6qxBBZ*M;qML?esd|$zZ)aCUCL+gRtw+mD0=I?6cYZz zr$h%O#|f(>AM&)`p`3p|yY)kR2)bA`SSs$g?9G&Gl8Qa`pA;?sKp;Z@&y~Dw7UBG! zqA#~)5uwFUrPKBfLd1q5%l7G{%luD>&Kr7@DgSa~sC?2h1prAt;Jx=2?3~B)iE`wl z=8?Tw-iv4zlK_-X=jrf?Quk3G1l4r^xR3DrBxTme-P?pqTr+axRNZ!ts*@a2U9CGP zH$mC*u|6?4>0r`PNj~K{c$FRNp7Kn;?DNUr*#8WX>^>p4iDX||MRFS@9jrbs$w#V> zDc^rA3Dpi7zK^t2h7~mrpA5Y#{7EcGL27ljiBjekwHI#al(j|iSi$Zr>O_txCyUx+ zJ2dQ*5}V~CSO~eqLVohT1m17UU2LDKW9PSHE%Fs8wc~+E$4K;1NSr(6OL28~bTO-> zDN>1)Nb--8a{-Z3E?DG?Rx#s<#W^9$61UG{zh)3u9snmmNn*wYNxmY*m05{TvX@0k zDRn7}8c8YNi>qHpmQ1{S>)OTr!cxQnpN)lKM@4xz1!zWOXg5YpdQzS~WOuosp2d%6gVHW$%7 zpAlisyG3L6CJ92}CZ(|0Ak5fQ^mg%*5aG3e{H{hVM+UoVuBli5yi8`?&Y}=kBg=hvoUdTsJ)nYw?Zu}YH*c|Usm}~t6V=@ z{N8E|^?Y^3=es1Xz|ZPtY+PAWyg8W&b_++`PR@fE|FE8j=DgNpwj|DXryS2!zCPN^ zW;PZWb z!{uVhK5(Be*8~C>mF3wrapfi;dZ$z@iM1eW>|Lsfun_0K#VB;umuo%P!%xG90ovre( zehGfXB-oBg(3CPPadG4=IW~S=72wmV0B`tmaxj=Q;e{DJ!)sO9g&C_OFa=suPUj5r zOKy~3at{ZH?jHN~8%tUvmTl3u)nT*Ov!J#L`?ZTpzC@R~a}PXTVu>I2FLE9BZ^XJ^ zvhNR_WSXq{B4T^9uIS5SiNV5@gGD!g_)uuE_5hn19u4=N^iKz#hw~NpajWptUq#|i zCyDSxm2&>)b3%Nfa_U4hk(H|_+Tgq8$q~Y8Z_$jC6Ns?wgtF&Up>V~kq*ZMREBM*x z+xsE};d%ULrKai$1h&jOJ&dd^DmpC$q2!L={^;Yg?19Nqr(yZKD<@?1w`e^h$-NQd z)lfogVpMh3?e3kuUUDFyM{)n&!glc}`27sjb-KKp2oNl{$PKM1m$%#)sk=>;MJpM^ zf>)Srhhn(vd)VtQrHap#+3T<8w8QW0XnY~^Rn6eG#+=Su))-ElnLRtgz=j1gx~kCj zYu9t4?AI=3Hx~=L*nq#4xfLEhGk_D2%4rJ9xlz`bDu)zV9gY;PMNn>tLrRR7vewIo zp>{^7a-IEvPxh|2$fcMB9AIuA8#Ee~YnO8Ls4cexr_$=S2>kRW-6B{nk<-?a;Va%I#>Q__F~^GbFMyQI#z^IxKjLhm z4!Hs?!W4NyTp6NHX@6S>^foT;WpPZ=c}Pgn za=cK^Sg16mlr4D}{(~f+v&z?0|JF*bS8rU;Xny8bAStGtiCQe24T$8JlW27;&9cVb z^pgyvnBvKfmCu4C#wLOxRgw~^_6|i+G{`L5>OGs6GmBkPy&3@doM!`nJcvh60Uo@6 zp=C*^Da>efnCdcRM2cTSq&Rx7A-@04jkU`AtTDex_I-xxREuLO0@Kp)Hv-N=xoBSu znI;u`ry;Q*Xzg?6Fq`APW94^uWakW$n05k|>9~}?Z!0oMj#inDkubAA<&3g8Hh2JX z%;KLTgKGL)(e5+GW!#0-0^hEVtbk~SdlY%(7K=UE z0%@q9y?c9i91ivpEE;$7W2+lu1m9vP7YtpH+*f6UUPtq5)OC>T+w~#%^CTehR7w0gQu*Xes-a*R)1L#?Uj_CE zT&J;ExnZ!pSrl2_iwOBOMV7y=hYG>j%CO5%M!va(=nw$g9jYmx+l2wC^ITMZxSZDP z6$=FK(FOr}#M2IO^tG`OzkLkW)V#qer^}RCwX>U_m6$HosQQhC;y%wjw{o(!E&00W zMr{`&y!o5bscyLN<9uad-3a0R9A$4^58;U%<$PVwUKu%zfgFRjW@Y~WL0C7>X2f~3 zhjZ*f;SWu~pJ!ExGVbajVb?yza4ku2y{C-5cAxOY?4tLsO%4{OKd3bFWeKaNDKmT% zg!yxd_W0Tb35QGR&jMMepO3N2gsiSQH@v1kc%rjh`9b8127>fD9omRU!YfbHwT;M| zf_@wA)tKxO2CSp!8V#vCi6r-t;q+7_k;ydra0@cj#v*rSi^;vmNx{(KwO?+JWY6DL;NjUXYk*XL6syqW z-c~6T$Z|EOE?h;f{j%Z~GVB&I+>fjRQnI^4CHvK^T)V_Vff!$o%~;hTAq!}HOJXEj z>8O^ZWz`V25PiyXY z+IYv));ped-tkm^$5Z7UPo6uT>h!w%1F8>2hu>x<>W-(_JD!s7c#`l`X3xU+3y@uD zT9bz8lKJ$6p6E$mdRb4}C)`>Gu9vWiYsw62Gk750lc6EHQJzX1eI*s&k5%en@20DC za1{ASu)IMpM3IMuldrS1GhG=?#LAQF--1hM-qbIAk%^E$XsEei@wv2+#riwZ?z|>g!H6;8pzb9H+Yp8cAgz{ zYz+CFB-4lvXMtKDFB z;1{C_$!qK|hYst(1;u6%^AolEiHe2w;M9aoHL>6sP%_n)go}k`%mx&$xAU}^ zrxiS{;%N;}xuvvoqiAP$S6KTJdCEdh*z+i!PUGnUEw$P6IAA?bH}iBmPm6h4!P6?9 z*6>uP^^QH9rv{!T@-&sFqj)-vrwgYjmP`8q3pUEw$Mt4#?u^9G))a=^CDH7F2M0sPhu7$@s0>PHfAp_5i66Ay`{2UAFQ(wx?%kl`_JO%>3E0sM8fItOh4 zaDAEmFG!-LYes+gHpu?O0Mc7Xd4PU2fHW744+uB~N`)_^W}?RikVlYb@IW%G$IK~r zkxa(aI}*UaCYzZbrBzTgkhCIX5$$y9ry?B;xpufeco8o^e!ev?--rK5P;* zY8>oDYCv3FN~yTI24l|TKG)uKE0{YFT38=N8e<$@Ms{Gh?1_L91kk|mdsE1AA$CP`58 z6K0awED_t_m~qR9$?m=+L1U6>`*e)OWZEyCSdc3}oh<3Qxf5F_xS225#v*&X3*b>| z%7m&p9}qa>h2@!pnP+KG4qay^En9qvT0zz%*Ax_sg}t$5;_Y*jP8>$s+Daj~{EPFa z&)22PC!ufH5&Oenvey%nx~XBZANOH-liMmirNS(Ke@jW5#FaB8ox{2ggA<8Z$lPO- zbB+&L#Z_$3p&t$M8FSoG?5q(Bwom16RE0~If6tWnTjgUOU1wyo$j4#a%(BNEhdPd2 zIYJI?g@Q5v#4MkaYs|3~lw^y z!Cm1RV7*V_%WgJ?)m{|uX9i#A&Bqa^NgX@h>u{pfDXAn={#qSCO!GX2ZHP`2Bl#mJKZ_d2QmhV zh~Cc0^IDXBeGeA;~SApqb=@@XaZIE^f)^71z5K5=?r2$4t+jLn&_2eiT2Cospk4 zZb$yOa_^teBZ~V6Q(8PNLJ{6mV~cVE3B>Ly?~=Ill;9ZVJ4`;8i+DI z$>*(8(^@Zkmfg2nmY!7WJpoXfGuVfrG>Vj@%LmM)#ER}rrn^Rw_Sh9VK8nOeC!12- zi$ZBvCd5g9gP2xH@FxfN9fE{k2z3-r%cVzVD(}zaG=lg)}8x1KX zQZ%&%SxWU|NNhjm#(7_F%)0bPQ~qf-v6$?24aJpx(F>?jEbONKI4Twx@dIbp=AfCz zrLJXTNIW4YTyKtrTS%!C%9iI&~SNN2rKrp<<(SPf#~XDaxh zSg>9FffMjvF7tTOj0}FZAy%eC&<1ndMQ87$^1ir>)!}>-0rpZXScDAreZIWqkQjhVAwo9J}zYD~G`@+mi`F`GdR z-liB?m}y6`X-b8dn2mdz$pYY|jJh<`85vH_sA@+pVvMY3y)B<%bNn3Wk16gzI!+DZ z&YI#btMiYEogo~+WIP@mTZdpm;pUM~!C;<=2lMY~bKDVZg2s8{t;SURg|YhP;Fv7V zjj1@N8=HpdjVyR1n55j*_h6D@YFnM5idW^=QK0gJ!(7ZzH$$@ZY=-h5psH32lhd&! zmo4&TGx3<@Vn#rcZ?ZA76t(536FIYQMEBFJnR_Ri=obr>-tXafzhM`%H2BP4?eHauQ5eeoiXB z-9k2>@6Wx0uo0$mOiUu?pz8i6`RD2+E+?o6n>DFrB55D`y-EI?34tz{NLmYRBdBvC z=|YlSpH3v($>;=oeIr}r(lmhubOcog<6D4b_r#00XX#A2idhVU-=Y^@h4Oo6Vpy1D zcXeuhnXd1w{qkUQ%5|||J$+*`=}aQ&my?OfmQ!$0d~P2+RCP=y)tVcXGYgk0K8H6c zEH`F3gY~z3OKATcde8k!D|0z>;g{U0_n{^LLM@JgM$OBd0B+3kiFElZD1H9#s+(D0 ztKhw8C^!iBO=P}F{!PtU+X@t$DVR7joCDQymSrMkCh~(>E-}Y_ zX^yLoI~G3~?pEBfxDtCwy*kfI&avD9)w&nfQSD&#O{zJ_Hq$sQJx=XvN$p)z+*d5k zVm&Js1ff>7cLNmI-@OMkmk3ViFJLrNE;Bo38WX(t_!-p(uqG36)knw!BM+`&N=P~E zh&rxpXiU0XmLB&_dfa(a+z;k>n3wdpA53xInCxX*3lMA+;6kg+tG*y3r43oHIu3BC z6X%Y{n8g@IlBN32ZDHtC-#Jh}Q{1_A;*Pb(JRKcwCShzWmw7K@1~K8BleMCH7zVbt z4a#!A56w^!<{M9GV z3Wj{-$}5%db*;{@O_qH3cKX~@5+1_MJAHpD`8ln+fjWg|%5_$>GFeq_)$#Zd#Y;(d zW*u;J$-J+EYp8)uQtK|@M^f=;_v>9p;0U{ZnnoIs-nW^Yy_o$U%RmKg|$ z^7~Rb3(T0m7EU2RWXOPa3t?}Zf>e4$f`&EoB9p4#!K( z@^_we_~9n`3}ZoM4&JI&zRrAWbbA}-vo3=3D>?S4GaoD;%6Y<3NOf$OZ!7<5g{G+s z2;_Hr&*C*NCT9k*R}CpE(EK#k8RU5yF_W|m?I(a4;PadKl z&m_Z18+vmld9~@}VXD84iOciRaQe?F9`LU>FAB5rTBcZT39;?ynm$Y!aOor5GJL#Mm|QOiICUN^~eI!M-Wo3(Jk2| zL1=Q#^-VSjX(;@X?W$Z#h6p6a74-x`G*(EB>)3KEtb{%1TJc3BpSEdA{x9qwe%Z&FQtLNfG&wZd*_Gi0fLZ;*ig=91B~zmTe%flIG#>`+PW0 z*0!%0=4m61S4cbIiy^KN3JGo?EX&oz8PPOAoZoh&i#L*K!o?g~xsk+)OTq$>{X5d| z7jU{dAxA5DzDWS`;|_G=3uFjsODkW%8BpOOn*Jgg6%#xro`F^n*^1JoQMjDoM09y)H8M$ z{b4hiD!kU3CT}5clSZ^^3z;C~*V2^NNVa%Z2oS~gXu9h)oZnrH_B}UGFw&;4lZS+v zk#zCvB)^rZ6U$j5*$4P?zfcd%cfrK#JO`s(5pR$XB2>(wt==S^#Vo`tu}+%9u&wp3 zk#CYm2}z)zzeUCey>&tBU**Hs8g%mNu%2ayfbSGBhwh5juVMA|45*d=CeroN+gO{D zI9j}wOc7o>&op5c9r=+EO4q(aS{h56X|V?@Fmpr6H5#X}j%N=l4{tQ1rSFhB(!=$| zyTn9-Dx3Id{$3K*NL_c=d*13sf#^f;f1jk|i2v31Nqg~lUH$Dwye!hM-zPVPcG0e{ zK49iz#shS65mvCTen{fQ!| zLe|kqMa2Bb)e8Zc_TYv=;AA*{EHvr5q^_k|%zI(&iY{u*HZBIJFK8>SlLn;4iYwX5 ze`g)jh@iA^FLS%|>n~LLe9Ob783>=NLXc4!jVT4+?LHw1P1ubFsYZ&qnqN=HeS)*+ z#N8yEmV7~4Sf!3wXN*O7;ywh>eeZdzHT3&HVeyKts25Ni2FXYVq$OqpkTvLcA8xjc z8}u`h>~MQ=oLpMnKDVD_Pm8Uq?m}aBhqiqF-O%8{r?N1oJ&~p6?uh6wgqcm6g46I* zdyB!VCpARV8+gPz&y1P?iF5{LwyWQ#8cy4~b8Va;E(=N@uh_^G|C$LC}u5r$u-d3%W=Xiht*!{X2k z*O|Q}hzO3RuJd1z!$g=H;`+jkP4naL5`wo#Yg5j*|-9tnQ5@w&He}4_D+3N>7;V@Yl zl7^Og9{-+J9mas%GMJ`(Lpq4vz7Np;n!j9+d_#tTb{YM+g6xe?F002|-gacf1m7Ge zWS=#aX2f7Gu>cZN4WlQD;qz=UxM)MCzeZx{o+IRkM(n(u9W*s{Z8}O4iLmxv*WqKN zmmoYO)1dG1lxbYM>1U4^b~#I zM-tsPADd|MaqlS>Z>pWc?`6gS4#z_bbH@8y00w7w43qg3{oqH^yRBZ$!CVhtKqf4+ zb)FkCt^bkeqkfg)QM6@SaRJ0VU(2-HaiVYi39zjA=XYm#Nv2be6R8E-~3FTA#czJPmq2{aFeMwdBgS12^cG3QzadIimVgDD(T@< zq>FH=8@+Oh%s{qDxb#3irbnuX8A;32H6)r=`~nLVUqpNSN@9dqHy!gU zX13pp>2tqArtv?~FMcJN!rD*hJ-?ACvWa&24K=?^r~ZaT6oG(Y)NuDLO{;%l|pfzHyFdr z^G&X5B9m%&Jqs9apLBm&vzamIJkN!X@s_ZEBA_zy?H8!3QH>-AF`Ah5Pyis4V@Yoq z+Feg*1W#^KHBDpn2rDB0sTtvCzjuBAJ9$IUuSU_k13z`SITTTm$%1b-{nA6)1RZ$NVBU?us~FdUG6+t%4z<2(ng3cr>~wTo!YzsyxJ}{gZfR9s*kO5 zXccnW299K=2`#UjRKm9I9rq#NwKU56+Y3b9%D;Umi`NWh$u;&WF+HgmFBrux6ZT}+ zuozs^&Uk!ZDP^Ztxy|74o7`2ACd9Uz@~aFCFJCsf&qkT#3)tE7VXM((KTFKw(8E%p z?PyM>sn(q+7F0uc_!XWzBk64593fX2L&6f*m=pT4BVWmVCMfqW(-pV6eOHhM>ZL$o zU*Z6E`SFxqcov&+_+ggII~l@tx1@(jFZL{Oo~=ckIq9H_B*f;{82}U0 z-AQNRA)OY*9butsthZ_m&h;i0vpSJWe74wK)u3q>n##F=$5ZTOC#uqwn57;v?vkmx2GZvcKSr6mOfXuh~Qfp(Y>bMH9h*fn?N1A$- zL^4mj%I0IyUi31(KvoE|U&6L@0=I z5!%S&*RQ~0)U_8^8QHVbYV0Sae7Q)^ZlT3_5uTg?2MVA=;!3tZWs!@udu5}l;8aQO za}8iahXOq1SS>RdT498;TfU{@)>Otqu( zAsSmt<~KW-(_O*|u0g_XvwdF|>B^6EYb|M$>dyV$N=hu)m@8NbidJ%fDKTT6?Gm@U zwOc0c7#9qOt(dH7&NPngz2sKo70opG3K<*a#(sbl5-f*+H*;M@=a~1c`WolC5o#Ue`h6S~z-m4^4m^zonUnBK>r#_-0s}J6m z44PjjIYeo|$k0V$scVwh?vf;jvWU?#&tn^i?*0<`*mcs{hFy3}E9?5gzFOqJ&5rqz z%%T@`X7*P8L7H*VB7S%ocS8uwmS|4`*pUu7O~EvnQX{Sm2SAb&jG1`FZWQ+ZNp265 zbAnH&0-KHLIi5-*qvY2I(wPVR_onK5K%e884T?%j>>fA7^AHzHMj&= zGs0!KLEa?&*nN>H>iD=blpl_R$MujVk}9Uojwd1YKkGdE9$*LT^u|rnv1u>xhRr%N z&K95ULKEt-;qnuGw4N*_57IyCNe427Hu90aWDiaCk@)Uoyx*Y@Zi{fez3zgzx|G2X z4_T_Nf&EupOeXq*kF;()-;(mPSirP}?(&i3<|~nh8mR$^N24ZVy zGhT3w|J$H$v4*l;v~XMvU^EJsBFl3rLI)dj3N$BR94@LJHnA-@xEr|Tjk|&J0ruYK ztqpUd)t74H{<>pqXxv39ZdADBSQ?si&zkO(xR;L6POa7h((Z*m0;U4ZH4{Hxqi278)PKoE&VP;<5uSGhQ#tNCg6|AHssf zTn@HFthqwBsM+8Jp@5pd{#JfltoQgcB%pJ~!aIVFGotK{djyVkB^+N%pbqjGc;EP% za`w}?qydY0FtAxM7NN3v6@a2Y`?thF1>rvuwI5{!;dr>C7|sZ(d_p5bJOf7GOsTV{_lgdDdRVqC@E=F0halw)`#qN&khl_OkhQ^RCn?i=Hm zstnc)W9S{#vu(E17_ZU*Fr3>^s}*eQorkbi&)f0%&ji~2-Ldk;{6C;XI`^3<&lkHt zoh$SqLS+SgjR>y@<daw7M=sEkKYoXjjKEhMr5zomgGyguBuuL z#Me1=nb=j%L(io<-Z!!rOT$LNC%{YjO=Sft05}$@7mEvDb=4u7n}rnvcD&U8eF6V- zF3zIZ#0K?duZ>^@(9)1AmEL|qxMu~5IigCzDIt(=Bv`<;(v0xDoh%#@@5jFYYof&g zhKdEh;el-m*`GWAtmic>C)CRxhXG|%Gx)IJMdTLeW3f02l=80@WAd=IW(AT#i$z3* zdcuOR*`ytpWyIPL6o$c>sl%1jt_8+&G!ZWkX7Kv+1C6Azz28+FU<3+wVl)f!p~X zaK--tSN7(pu#CQEbGtKx`XAt6-G^FWRw7j!)Uy zxIsYJntUk#QzK&Xt~SVNly?=cCddO~YpPht!n+)H)}gX3*jT3i!d&iiq|G74SczFa z#{=9B3@V&F78YB@bdSXDPR6H2Ee?@LS{7y=u<4Q3*5f@Y*uE78K%Ja`t`&4tf*V z&owPgDbE_0!xq`*Guy>tR}l|xgxz@Gs1Cx8rW%W^#Z%xOD=6HD>TpAJ0-;CxhIXWh zPh(vZY?M`TIWl#5S1067vLFJ3v8CQoJ_BDMxWX}Nlr!6vnpYp3-5~GUFt&+WJj!I> zqgEM#`3yHr@=?19F|1YKoH0;|)S;8pb*9n+qYFq<9n5mFbI4FR5hFz0QSKb=?s?=8 zR&97!Omk& zc>`JoQU&U{BP_j$2|F;NSu8jJj|@@Gwee5k2$M@40gmWRZCX)tTV*dBvzQfffAT(C zPxp2ZT2r~HU?Gj^v8IAEqLJhbtC0p|CbC6%D4b!s@E)N#d5IR@Bcudb8LEIfibp|CkINdf*l zZ6gY8jLy*?#ofy)+-Dl7tYG9AYZVP~W=XeOGl_*}BiMi&4+JI$A88 z50w&Kx%e9|ctYQ!hgJz)+A~KsN-W3#PJQn}(ovQAY;my~5JQ)S3x?oGVCj}{Aql2t zxpA6U@DTkD@LpJqx3@4)6?Y_YLS^NeZt{iWs6VHXI*lG;y9Ay z-m#kro3$euC+S#$d4AYQgPIE+ZAULO(0OaoD{%eoCFp5QXxI@zyb|Q4ifWDOaqO4K z6pZ=wSc@ENw92z$pGr3vgG_5MXieC5YSb9bNSy2-Vjmc=*ZQ11cWs|p}!MNN+ zOJnQe!_9@5pmc8$z1Upn)Vi%7rS?alBo@)WkwQ1J zgU*Z;7By)Hfnd>75$cVizeEaIB$N(lAr!VRX9rv8Ds|V0xi1FqlXcpPDa-Rx8a>rQ z=qohe?9#Us5{Qs~$(61b96@;R2|e0MxGFqaL%(h`owu{482kdJ%eT9C| z2AQ5YN4K^W;)Dqs*-=e2JFvsr-IMz{z1&vF>-=d5o8~TJBm1fuHN(Hgo|?`xxiElK z`%SKw+6kSAP=1E)YcISc#Gj#44Z;>-jh6~B!YHBhP}jH^A(H5e6%=dak<{*Bd&TU1 z1=TyLt%EQ~*puplX~E6rFNacFtZ-8J=@&XRPUs}gd_17CE*q#4C)9`ZE2#H*epyC0 zb`|;w_dDp3uEI!R&L-L+UPuzYdzvQo7CO@>;)U@-)>HIoyl`*y9K7|2ov!kWD9{kJ z?26}t>`F-x77}5_8v1@W!60nLI)qHDfI9 zR-{Ty^>Jff!aU0&E4qzzo$VoPBZ9MlzMLdHEOaQKp*@9T!p)8JL{GsaJn}3x^b+Pp z{?&=iMyK}P7VPmJbaOA^Y2oTB#`HnUx@YP^`QBLd-5N1Js&|dSE7L>vW-=T|HLl0& z(_*ELS#`WIlA{H3u;ySGs4uVG$?QyO?_fP`wGS6)cJvXZ#LUWr0PehU6NY_+U%(EQ zww_gQvM$f0`F&yE+th}H(%nml=02ltxgA4$D&xA)Ytgs843oF!Sk%` zKi2Z;8}+oyGogdx{51V{u5sDMvjH!_Vw}Tdu$Qqspq>QKgg!!BVd`Z%qK^<`V{Zmz z)%>l_acQyEjtg!{!P#Q4hPBEUJjamX4q95c(kSrjK{O!WdEbS75iA#HG}Nhi?=NBa z@>#d>QyG5sEj<0Huh5G8O>6rK2^|`)_>WEP^19Ykn%@s)F40Z>grmZ)<#a)^U8~lmBf_K^bYy>_ zOVBS{8q&-Zp%qp73!Q?dz0RM$>krb$0-hr831SVvA6ndJ*c-I>03lQV_OgGd=jbb} zo=p1t0AY`QHR9m^g_Dn8);OsfD7>JjOa39pzD-&V&mf_zzU4pVFsV82rAr12G5Yn3 z|AEHtml%!5^o{=s+28`)JGkPT)m*vPkCr~n$VtjXkwbsM|hzj zeJD-nEG%qDpH35u(bG{;9{zAgF4R(%5ssf2$5>a;uhN7bjWJ9A!L~X&Eu;<1!ULG~ zXPSj45hO4V|G5kQKh7%eWd5zyF)P-Btwwki>WL)IAK5VSw9kERu3+t8*~`c>8)A{C z#v+u(BDaBto%d(^C`WZ+=;m}GB~{Idmj>NlW~f_q*ge9TCtGumjAb55qYGF=XTm=) zaH;Krf2Z?AJVu)i6QXR*Z@U1JV-jZNpK>}t#3+7 zwVX{3*lAKXB>Z47%KU-`%zWLp->R9wcIUeJOoy<)6vXEA##b`shrrRqz+O;W>iPaR z*2(E`2r^aM%4(O_Y{fiqXP;@gx3b)K^rZ%0{~N6z1~-IV(%-F$3R10ZN4W4~@NQJ0 z*RhQkt7Ab;W(*|tWaww95vZE^iil)V9i9<_V*6r94^~EU7OG2S7C$1VAjvbOkplFjjK0T~Emb_6gQGe~GLn(Y)F{6$@PK%RK}DR42> z{^IZ%)Z+c-)%zSHdUurYmYXoVB3?+=ZL)O19heouN1ELR0c&q#uiWKhu}=o@FNAsIf;Bljrb z@9Jqki?B<`c!YU5Z9>?5H|yzo>R1zMp;Lzo*}|Wr>9OI$4xz_r>KGx|gl(f}m{rIS zW{slbt%6s0d?ZcH6o$3$IZ_P|8P=q_oW1L_cG%{ioG>h6H~v3_y$f7a#rr?LduD+J z(SwSLiVC_aC@K^cDB7+rxT}jonzw{*U<;F3TWlKpNUJolD%_wJbihteA$FuaF_$8`LdzReDd7{yFR}SkDYOXfUXWi9x{k5nSOhV?!Dax9 z0YgLd+9%PIJK`*wAxuv8DD{sW4$;>hLY zWN^V!6PCW{BZVrk%LHGDh7j8FsDPO=B~GakFDzes0%{LE%IWNKCdhM=O?eQI)!LM& z^#2lGQCzPETr+x|u9H05oAV&fE8R-Xpv~^PA#oscwj-FTj2-?XL&Xm1FB;yo^xL%OPyF81@DD3y+DrML{*TjxqY>Ur)Wsej@-s2ah5gB$xPe@8FnP4~`)=yj))dH8#2C zr$adJ!K2laYZRE9@1CColuZdV3l@O-5RWd2E>6|{2%C1R@_34ad_rrXSBaHfWXh87 zE*y&F(qWA^fYz@~4zY z9*}4w#qdk@Te7#xu4PCfZEX)=j`m0NIaaC4-ab=;#u|MA97bb+*;PedQ9oewn^-r> zUp8$$#&2}wEAx|7n4Ai@$NA}qU{$I`iva{E#3F=TBG#WL(yIupD)dc_h@+OMDNHg| z=ceP06k#_Cf9JzgxQZtAY|!Xz1FqE#9!eJ7ckh|yQb5v<z-{}T3QNvseCM9R zvGJ=05Za8NO^zE8)>NSItd|`6qqgQ}Vk?p>U`<6gAZ- zSP)NaF|__qS}Gt)X@s&6*4=`9V}pS2Dmaw`An*>u43d2%K}T;l+y}#QmrrsXyGEp6 z?->pA*m}|6s>*e+LL}G9>4u4vh~*-0*dg0$_TyMRhRlkBc*IPH40*% zZUeTF+fK2-BzVwVq6L;TRQB?VFGy`2X7`kM6KrtA0`kL^u86Fa63ohwe3NV^s z(biDzG}AmpjFmy0`d>6L~Xx zC_4pHpd4`SaE80&I~AquEpBMMU85;F0sn$fPYGFKQ+>fN3d(l1J5dFi5C2*uQc9LcAy+?ZuP~#n* z#DVVNM)LE8mAeftGO1P7bl}sNdBuxTCr7R_G}fftHO-2}Z z+00ljAFyew$i>u&sx)$(*{7G|Y(7VVT;(gLrxZDEj4w;B+F6dsHs+G)_-iYf2UQ5_ zt}6WAtW>7%A>%Mn5jZJk@6v3qa;L$`WcqW{L|bsLE<9s#HL#hPVG8BWM85sGX>R*o zJv~gvLmVCoo|}Oun3md~v*TNxHG5Ct5ANYPgSCP#y^lF{-(f7i5`29Hue5%$`i?P7 zCOVOouiTqtQif)llo9C&z3!fo4n73ok1cT-`&{$(>NNHQ+A8?Km!)3DzmXj{V8wZg z{7qAU2q|Xwv`ml>Ym>Gv&=zO>Z3W9spa;3xXXHf)dH{2`OCvq8v-zhlONLY*7VR$L zr>xr3w&ZP=%X{dHOT%#Q!#LC8p?a9Wj1sG#*S{V`}#Cp&boOeNV6hRN+43Tju5YOkmBH8Yl zVbdP8Do^9g3yToY;Bof>8FQ?j4O8j3u7!%^N3myH75IB%N1RoAIbU0Cqfhd+-#5pldFNwOt4-y% zlM$j7mY#@zKNGI%uv$gkR%Px4qPkfYEspo5$rf-~?y<(y3;D|TVr(=pEb?KYC`(#< z4zZpI-(c(AR|rCajT3Sp{@AOML7Gy;m%l1?8$PF*HGYr`Vb(SNpM61cGn`x=@juQa zXgNi>ATRq0`G`9rdO;6xxjm3T2}tT+M7~}l<*6G?oG+sb{7s0RI;nO5KyC%U-C0=N)JgBe&%<*C3V+k^1`>Ik&qtx z-jaq&?`+`_Z%cipIfwa8Z%bpe-T9)orT)@3na6%4b>j!#mh95fByL+R-6OG|_?p$y z=hCP{eBwL6k(5KcVOUBjh!r3alG zM0gUKDQbYM!Tf8Hh%F{A@aDfVmaXTVKae_Q&k7Y#;pf(@cjDvm;XDW?{+&07Kk|1KYks*`(tT<)a!d*`muDY_6+~>W9c^N1OLX4 zv|u++`$QTc-L#v}`2@Lj{1d#6=oUn_tldFGd1IGoePb8EMJ)qtr~~d$B2oLmEJ~Rh zN; z+U4MqAXN`1b?iBa{=Dn>5XzzmU=_ph5i3*R<`($*>il z^qJIhP{_Sy`?tX(MiRQPIVw2fbuz6weJ^w9V^O-ae?nb)LrRQ3= z*$IsKz=Bu{0%80TU-P+?uJw5jeJ-_tmNcIKxn4@S^_BP0kGBauJkJ<|CCe#ky*Skz zspv{Ad=YG+5eIJ)?=5awVJowAT5&OtNF?e(gY)B4r5=*Vj7EvnM^m#*cBUTKV!RmEp|rP6Mn!Q%nzP8o(^LG`inG6+ksng}PM zc6ebsRoQ{3ZIlMI&0m9@pM&HfSQqegqclj{$lu>6nc3pHdVYSRv_!hE1$S(clH#M^ z#RuO5`I;KP{0{$o6TUdi&u)^Q=<_SawYds^WHWf7BLbX&ET3a$uIoO0co1lUHo?Q79EsY$vAf|JRwc&Qh-_VC&LSQnh{nw28;x)YU`mzh-%=^N}`=&PQ} zz)XdB2frH^3DL0{p%pa#iVtwHLIEG`moi#Xh2-3z#}^;)rGDvFtLW|RAX8SiLti1@ zGQ``0&|43@5n@~XKRq6Nn&AJQo-i-fp_DBDSC6l0sY=@Dkeiobg}41FX|1-G7-=qO z3=jqbXx`;X&rx+b2LFl2_#Xl3QfvlxnV?{4%(LDTry->cR~NC2-*Q$OsLw+QbbTu? zIxF?)(7dwemInJ4=TGpiJ1d>mYDaosJ1?z_lP*^ATP1dv^hT9;vBXYFl6RYTRs?%c zD~;LeJrK!y>PCuD>t7%kVAP_^bt}XOufx3KtY8C46&18Y9!CCkh(l2e3{v#Nt^h$GJ8fkzR_!mV{>p5i`TogHA|GF5nu45ZP`_6*Bbt7Jln5b zz}K~7GqnZW(4LJP04sh#8HRgjE1scg{R!{xLg3@s%`}lXVq(S@nqbwf3w~ zE5Q%5T>|@BTKzIVkiZ_1UirX#dq<{^kdD3YwRUCQv|79O(QYhL+bWL+Qs4+K=C1sM zB-SGg@G1B6gGsDgtL7lS^?t5PW~tIEx9|bUtlNlFj(VEaptIdaE9(J)FwVTb06hToRK-^3t56Z{$87n50mB=vb`gMlrOr1#(QI(spLwzHU*NplDa zXDhl9GT${l`0^qDx;N|7@5%A>Dj<|X5SoPd|AJ7ikX0JSdE2M3bgj0)J3N)0)Jk=) zdei$drj`C##cxStE2K%Q__t|rPA%YX^e+?oGwO%G~{9x8wk_DF5Ovb0~XRuPeBW`CC2KE4311Jv@d6aHK-zw~b`Rz83dToMP^cgRtSJ;wu^*$ZE;om>nELU=sD9 zF&DMRn>YDsFV5(99lYZZ+>T_WOHg+K#KuE3h0!WWejx9CMo9I7H!m6E z6g6XC1>zyX&(Z>ZCy;pktW&VuJ8=|Spp`0Q?=N?-NL?EVTfA~kxYcP%#C72czj!zM zPx~cTXogPuTjyYpdc8LIV&H{iSTF5+eAO7%UHdfudJLP?ns5fAqqtERo*7(F-?3Ps zBVsT@xF*wylA0aMUeLB)qepG7;BcWqcv0__#xtEHeOB+)-@^vR7@m(M`VkW2KU!Z8 zkxawpU?TW=x+cz$>MfYUZjIEo_rCfl>&c{d^Ss|oXYHe7yAGwL4h-@CaFm}YWZlx> zJ_UoVR9Hp^@8>vQbeC(Fv=ItNOo@yunMgk7iT9as1m+pDS%U5&2nWxf%|<%(8%d{W z@k})6RjhR2Up<1jy?{j5m1}Zo3s4W&mCMi^i4@$u4l%s2x3R)Xt>jX zo5FNJ3v>$JwEl;wDGE;4iDwkCgiI~HyL>v?TZsrm>P7(A8cJAJ1Taf-uD52(h4 z9+Vw~&X@Y%CAG=nV4006K`sR5tAev?r|L5HHd{9=sOhUJ!g7 zqH|yziGS5@Gz3IPDzgF8L`uuhIAC!ZL)UZ(t3R1F zMi|5xyJ~_lZ3$qdPQ-Vv90Py>fiD1wR|@V`mV{}yfk~iqHA3f|l^5Q$@@dw^5sv}_ z3&?RsG({Lk7@$^QWay?tJRlf~Pu+wRqH9!y3?TqD^+lxRV)D$&PQ=S4T&Tm}B!nIW z!7@R2q0`G{AK^JTjpR2A$%}U{1mbs@-TalOS!cvJ_CC#wgR)QxSJObJ@0wSG&ldHj zDlYqggfIv1gcrE9$fYD&09FNB$=)%0^djkfe$z9|lJNxwso-9*rV3Ug!Q`ry`6f}w9KOmi>|7x)PWz)*4A__H5V4)J$fF|<5R^hI_>;IGy7 zHQD21bW)U--#d@>Y4t5o->NL4x)mj??)(YC zMY$d%uL9=A=ykOShAr^K;J+_LwovxmcZiHJazraMH% zh*Fj-6o}i9gg|f^f7v`e@u&%OtR(~A zXE?9M*d4o^S0~zQoL9Tsw++2y?g4&uD{66Gol?{hB7%SExwqQ5J*R^ z%zd7_SINTDe}5_#iHzY z)z;7KV#;0sv{(#yT77>FFkSl5Ts|Pwk$~G(dl45x0AQ}#f9!>>+G}#z5o{1(zJMBZ zRizOE6z~Tsl;*}6d~FAPE610iK?`H4=xxnLnpc3vR7L5`!EVE2 zvt9+G)0mGo;OCC}>?|N_ic_pX6U;;U<|m&8&7Kqk9snvDPugs^PF1!B>AmcA91=9& zY5xP#=(xeCiOGvz0*Jw@%qA@Zc7VlrHMz&>Q|nxHfZW&U4lv(|QEESJov0~~!WM5) zhHKT21T&Cl1iP@b9R`j$r10HJp3&qUn~qJ2T%a+geRc<^AIQ}ni=%Ac0+@o0hH8AC zueQ;C+JsksRzjfh=+IN24mYdJ z!fP0Uaq_~~K&Gpr+L&a7Pi!q>ox=~kUOfyR1D7da-_9&^RDMbA*}J1dDH%U!?1LJ} zlQ|m!FkCt38xiLdDn{2cf=kO8!XTf1+Zhp zmgj=y*{-FpvuOwM`6YAq(OLbVGKH}a9RH!SsX=57Pa<|KNYcrV4Xfdj-$U$yvfY;b z`^*!;+Q-t6QQR10cpgs4cRQYd7wcbz4}jOg&I{(Fumw&ce(`AkhvL(RtGiuPSB;v< zvLho{Il@#HA{1wyQL8RON>vmPauRMs#WVFCn;mKmSNE3{t)M#i_|UC}SLL!@fx1Ssel^4EhZXMURM`)8UyBrYVmY%i#zJPy>c=wGzs7!Gbm? zD+E~@|INf;Dcfm~6mhvM9xF!>$mSqxg+hU0Rs}c7UiLq`pNPu#fP$+1@jxGXS>Xug zR)EfE{7(jpsJEgr(Ggsu_?utFTBfqDAa$yM*hAwti=x%)Kr|6b7lb-3n2vR?-giAq ze9}6YB^c>1kXIGORFi`WxyL36vzZJmjF3sH@GSt_Q-z2bNf{S>Ct!rK-QxS}rs#iC zPx=1DG*eDL*NJY?XEF}>wzfU7=1kwR3GE^Y4j`oA=tL!&qs275{!s=#6FdIt* z1eY?~Vj%85;q@6Y`_`(cR>k#%7)3^7xghwGYNi?-oRVtD#zTXE} zF7LNOcXpphlMAQjXP=f`eNYP+t9XNe0$lfs>yBbbvdd9`Ed!$gjfc)1EaPz834+sZ zcYH8tbh_;7hzHuZL1EpxnxuQYbqA*tKB>eFVI|n-s zdC^4-30vLOHV8Lm^`w0RLKU2;9jFcze7hb6;06UeIu656oJ`>&fW4kfgWQk7C@gHA z0y70uqa$RjejXn~ghLg##t!Pb8t2iKfw|XgB4Q!u))2K$vBF#yyB?hPqF|7hVhTC$ z4TlNK@aP!0?cEWR?|BkT7RWT5nz4Bah7g@CObZjXTC6)bK#EILFU)l4h_A;%CLx@H z1Vj%JM>_~m8m-ZYNIXQ12SssR1)OfCDZxYO_vn}FDm;UKrSalWud`+Q;00q@+;DwAIZQ)q>H(~!3b0iFM0%K_$m`#kM z5mRo(IS^|%Ai;_xL>T;Q^&pTzf&inBAVE<70S%-H(koj@r-=vJ6u;Wzx^UFBH5ue! zW>1hiY?q_4y7t-I010p!J}0U4OWO%%XlsZW67;CS|1HS|ly6|rA($ZmVVn&i zOOi;)MCwCfuzJD28pW{Dghy+0(EZ65{G)CG?Q>;epZ^p675o(}zqk5l2WurRXiL*_ zcMS(Ow3{jdJ%q4H&_hx~iRCK{RRIZPsdETy%?h2Q%3;It6nZKOoTKfTN`%R3Rj9;h zDuJb}_M=S<1rkH;yn_NXPEd-nmw>Z@UX%-YiRi_m(C4k`bC4%7_3GCs7anoN-Lw@s zo~M&KkkDaqXNeu^c1nH}$xQ_%q+lca@!Mu;VjmmUywo4q?v%qQ_YumG#5CRiwvW6L zG;V2dBf3-A%HkOg3ygC`y&xuy*=EVUJS)+4w43j!Ufv)(aCK6#?Z(PQ1p$>=I zaMiYv%bo&xZ}tuDoufDg0$U!2018=00XrZa<{6&`gShA*suz7eS@CpT&lP?zToMH? zBSLE@7BPck!;9!B?q@BK9gyM6 zWgYO{X4-PpZlVS;9~RU=CT!IxOElaHN$99-pPhq9vL z4?IWMCtBSbG}u3`%hRwTI+U$P4fs@)!N<+vo&t@^9P~{teG@rw=bna@m~6^kSdMmP zBLIMSu)3G>LFFvNurf=mnu>J%;0Be(m4tNG>byDBr)Kru#B0i#?6~BryHM1d5X^T$ zPCMsn=z_RZxYM4T^Fk9sQdzYdYJq`X1%hLLvBXR+(7{o%dila0^9SB1W>T(W0wL zXWDxPS79wE7+PJLo`TA8U7}K@>SMUp%{ubVZuStU6k(21YIsBRJde&~gSAd{q+}}^ zB<)M=c5tMcKwlF0$=)1@L)KqJ0Zjoh{}W^CFc~26zS_YWq{<83$ii*{%k7CV4VShh z74~(0I~j)GF(51?d(d=G9OAq>Y4&ng&L>rfG$aW z2yfKS3Hd`m9uugzX!hN1ns_Um>_Leq z(+vYjAyf^~J52%qsf?xYdp)exJp~Z}4{$LPbF3-sNsko!PE**49<#)wOpgQUQ7)zH zkO(KI;n(DTAQsyq7;>EEA4m!`GpL1H^Ggrw95GH_bgPypb=Acu;oRbZF@qQR#3W2!*oe<*#JD@E>H=~qydlO)4u%GWvu_rv{57G33{3U zO-YSZTqkOnpgyB>SCX;(KRT86!2*{l zQmeizo`&IR6`nA2f+Q4nQVDF=(YIhZMZhebheVuFlW>maOO~^uSm>@j#kB4r4dn8( zELUsdW1nUJ!Bq&pXW66LJl^*?mK?S16X#V(5&7NEu?+1vUiKWbjtjK}&Mz+=q-InM zX?m*6y zv3hjnvRAh;xO__*p>82I-)Zw<>7BFzQpKQy{ zus;SWpaT^!ifea&7R;g9{dN)&U2w*9`-bA8Hwp&gI|{AddY0q>`>@f1?yDs37cL&~ z8c7fIZF)ql+5oQcfb$3C;8hB=Z2rn1*bG%E+LXPeEG5L1Scq$y=8wgcBET^X0f#Kh z;0I4(Iis?fJt=Z)q^mZsaHOd!G8dDjLkyi(J+C30)6l9?ocLGpPek`BA71%$h~SXp{TE-X%Y!Kt2EjUC2khz`8n~BmMgXGVg+zygExPmh@fX-+$I>_e5RTdyDXFwA{y=DyC{24bBC}TO zYVa9|%xhuBLOc-QrcrgE$#BC?sdY6#Mo>6_k^uZrYtAeyF6~1i?)nuh0@ZY#2aF|RR2tl(8%Em$lnq7KFlGXFE<1XODO zGb0;SQL`8JFpYXUeIDczt~f9UCifEnR9=!Nzj5)H8U)vhw*=!308I7-XI-qlZS#E- z#{$3^UIAlj>QUByflB;kQbxrpyG-uaMgxM`zsjzzw?G_`4@D=^Kg6wo7zF(GGi$IM z4GDOo-{sn_^l(1ky}^lrncWZKp3w(W+@>@Ve#>4f@A4w+pIDNHQrc(Y3aWGUnrQqL za{z!7(R<`Y*3E%7@?(ihBT7`DM7d^MF04ZZm&@$^ z!(1-do*;vO#Z(rXC6I!cTuLYN*vtM~zGJjjYN;J!lth(F&xzM1hEMToL3FdVpCOBj}G>1z2Oc1+{-M*L0|#^_940& z#d${GADFZ8?APS*_(Ubn52c1ANUT)aqe6~9Htpk>#$jR_hc%luaB?b$P6q1e^B4#^Z{|dW3lVF>%15xF~w96}ev;|tUyC6Wj8fbHU_oeNL(h%0m z$x~Oc?rD`&8(Q5+fWSX`u4(pM8hS><^LWuJmXtb&zM!~Z_%$y!%{05Mv2scfW^(IN zLki`CzdXb%SFxGVMPtAIY0_j(pe?`kRahKc=Hp*wV@)Pl!W_0xPXH*XzB3CMqp{RK0o`Q>`IK}uf557IL_tVEibAB+Q50#GDTNn z(e7zHDhfLh)D)=fL>^$9hK^Rt5T3k&$cI^YF%~WZdJLBe$|~oU5nSVt=$z+6Ou7;h zK3AE2k;S5hw^4(0iKszRVTsu&Qaz&HzD*UYLy!Z`*&+2TYzK@mqB`bifu`vRg*CkH zP1ZZFrNy(#K=NC&q6Ru3o1Q7kqX`6+@-p!b(*_q}MV8!#PjN{AypdOk{#`;?*|I9C zYu#J07BW?!O)!~Njq0mN#Qo1YLpR;uIrwr8F@rQd#pgQK4R;?GhzcJ>GDa*bQ$a@5 zyQ$FP;q|&Vb9C~eT)gGL+G{YC0k|8SL8zB#)Qn(3)SlByE^Pn?P+N}RYpYQC$PmO2 zA-gyTuWFpl)qikw2@c34_J8{*PhJCX&DFG#%ibt3?_0sV3qZ)`D?>eLw<BP8Q$G1=fy>buQ&g#hogH+WN&4F)zhvhlepdx{(QqfJJ z)qtbRP>6`c!dXrW#~v4&Lik&2)PBgrVpV(6FEU#+&2Q5;YBch~D@rcE2nHT+Q3Bac z;w8Mq;Pia&yR6kDlHNkPKRi;c!4p-!3BO^e$= z-&eE|eW}MEIEyu#X*iB%@39YdFIkb!zk8QW%c9A&cWBnx@Kj&G@!>l4QGdtlb%KKk z>J!&6!<|md32ghe7@YW(%c7xjt)LpiR9Nuq7(coa(v~%ASv$n|{Aw+;#YFoU$);?p^xn4b;SlH`Sq`qF$LXIs zMUCaUhgf|lB^#TQMUL!{oW=#x*Gc6g8mopjRAV226n#ag`zu1-&+0||MHR$Fuy}n6 zl?`_rycFUebg}RR;E#hrtWa*B%8J5s&Z3azk^q>5SfP^0MV=Gw#ANB!cF=<4+im}ogaVG7J7i0M} zkkHD;%|_ItCL`rKCO~Yr{bJK}cr4edjn^6}@*TEinxUqO$ezYrJ`J%dE3d8_s+Qpu zaXOsnri+}IsEP#fJ76OcK}FUJ;y~)y#o&bqqi7$1Yy{wbl)8w9LG&~EUg~tHyDO0q zZsoI~>a+B!Oshqswd+dCEg%D<8>)<$h0qMZH)A^=n)NjBM_=_e`PW@FT9ai`Bx~{1PoG) z7|S06RJS&6G$Kch6wM8bEUlb7;KtS(zPw?I27kzUv^+wUVf?;h^5wl;`w>g%5uUIw zP?5R(F~E5%!TD3XB2If8%ulEC)gQ9K5BNxVf=R%Q7tyEg8#a68`9cp#e7+tjxK0S^PsjeDz4O02F4_VjF z+b=c^RYfID{TZSD!EgD9b&nc@qA0>2_=t7w4)l{3jYJ9%EsP(zcn#0oXC-3UP7;V( zKDtp%U~sy^^GFb$PvkWShN4(h1!v~UE9-^^qLpc2&MPmiE1_}TgHmSYF`&d&LW$s_ z475fPkN%itX|M62A2VAAA4sk5OkDK2@}c!8TCc80!a7NG2NoYx!VCfqoJVEDY zc~No_nqP02NO|N$hTo=sLoHyxh4w}qEKvX8zXbGr$uPljK{7EJRm2#LvZsNY~MisJ=y7*9n0;} z=zsBl7x=adrk_51kw3MLb#mY&0n&(W(mZPHPstmMv$BIbg(Nfldib;dq_AFqI{5d~qB;V23Ztf1Oh01Emlf8cXAQ>N*0 z9XnT`SPJCQE-m?y&spa-J0N)>>W?J@2D{j$e#2wev(9&72(;n5{aG6rPEn=k65h6m z^+n82aii9W9+z~)rr=rB=m3Uzz%hU{Rn%1hbNcBRQY5p7qrJ#9v#_ zOz;vo3Q1|)yT~+`--FhDjh`FUH+kF_ETf&dbl*mrEwY)Etu!#Y|gXuKdA|>hJu`FWBpSPA6b-K~e-&(S{3V+<{e^gu*IpkDD!?<Ys} z_<4UL8=Tip5J+)kfY2{a&OHx#DQ@9Ho0dUg2B|&5v76-2zfph3St&g8Va^jq0T$k4 z6YGZvO-<j?Ga(l?M(e1V<={lX|fRL=sk z7o;}pLrhv+J08E8^~EvWYuXHV&W>?IJ+Xh%+++48z$kUE>N=*w^E|%yOO`b?39R^D zzw4+DtgnUqNN^E26!UZi{pdiaAW8Z+z4@aJ`Wf60lp1q#ja*iXsS)RCx~V{@D2USc zAhapn)`mZ^g)N5f&;(w$g{5XR4FGje=ap*L$*30d3=@pb?<g5!QkAGC# z!i=7d`HBrp%tp~%5_BvFB7v?Dn0kQqmP;45=I?*S9_^hJtY85u$fF8W<~pWr0kOPm zhtYM#SQrJ6)dvu-yMp!5qjA~^7@u6hdbRy<25njxGhNm-jrCl2>W}>h)SX1q0TXxb zj!fWNDp}{`;Oep%7h79U9UmGpQ6mhCJE^OI6qsOswGxu0Lp;$3r>(?slww}@R`!sE!oMPBp}=qUggWE-H9MUm@3rh^>ZH+_vb0t8FUOji&>Cdc8Bz0)gnkX{p4 zQlOYCB8%&(&7xh+cn5TV&`&JRvW{qorj~Hos?4519U`&`7t`}Fm4}=r7jcNjO~&5m zM6$--l1i+_qxuJ4aY!2VSksi>0Rli-vUf%SHoBokxuPMvq3{liXJ|dx+slEGu7=KH zmJ3Oj;V-+hJ}lR7#J`Zr0oBq*ueQ+f0o&Mp4yv));4yAXwr^%cm3DamjCHUx;UT1+ z1GLA4Psh-?fQy(LqtxLTAeWNR0YD{qr=C}SytGwY*ixx0a5YMW{Zu+Wd5Rzu%ABoy zThMpnr;&Jk9Eo7dv}XzwN zV2qd^w>7m!7&O-Osn2^4A+~T@tuhC#I|zz#w#&_n?edAs91z; z2W(9X%*y1)0=+Ge=z;yND*a3YP2MPYLX^iK>mf<@T82O1epi!wgT(S1Ly1 z$+UQ>1wXhi%~XDeu;Gjb9HCVa!g`w)#}?llbRfyjaEn{Od=CcJQNhc z%kqMW!pAlThVqUql*|HYNy9Ri#E>Db%A1Dqhi!Di0GGXYOtUFDHKxT2t>}ynV$Gr? zNG$bhnLWX9%~Xyc-0p>wMaPFHpy%Sz{hAYix*m!N5!L<)-fl-;;Ms52tn}~65@u5N z*;YiUbw7h(+{5+!{B{-}Pw@)>t={CFs#t%ArG;lX)k_-0BgD(M8`#iTT}DP(^slwhbTm5m~BFL0a}dGn1PK7$rp_$kqghK}Xg< zT6n?yGppNT7z7-HW4H5)5ys2K^CF}yXf+EDIOj!ZstdoTGV>|sP&XP@daB=5S*PS8 zw(nVgT=RPFk-fPfySOj-95#t7vJ*BW-C?Y5?_!yfFIlvz=%0NvC`(p|krs!z9Dm_@ z%amL#4a8N6^Iv`xM2zi|fhO5|Y_eGmyb#p&X20g=6KWvJNwOPh)2e?3M~hp-%i2tC zz;MD08o1H4VDhgo>)qg!n=R`bCm%Lqu%xyk65`6>6-@DWRhge{ftC2ctbr4sjh;=m z7SCcTqRZikc)NGhbPG`;mvO2V7d1vs~#6#-HqOhu<~vTY~w;c zKNn#9$e-Q8;vKz2HW0_X6tLHL?rc<6(gTz?OJiu@viEzyw$>yp+2NFyGSs8fhEQ!> zI-+xA$r~Pvai@I(1UJICt0aacmMCejo0WpJ0%cT8)k2CIsUfXk4Fc543+YTwhG2-G zVY=+tYtrrjUC0@MT9t3jDSzYexZmVD&N5&u0+$5^^5=OMa3Zl^h`^zx5En6$9u)^3 zT;!R3xbTQ2^(U~xCU}C%CCAZ_)uYp+K!f<&GXq5Z-=BMC0Q8~65lxl;uZCQ{YqHnA z6RpqNiGu6rhg!d8&OTqX8qEgmgiTMs1V#NL{I~B|XUBHju3;%27Dr5lz&&6NO-?Nc z<(COgbiUfBcha#`DBl4zm|`rn5KI)XP!$9#A{T0T4P<6OEgN89ij}=eFHjUy_U7C%@T9Mi4@p_s)oA0#2ii> z)hy8#P8`=PaZEVzf$NEml8NEeg6pXzQ^Sc*G)tTwPMqB=(H>4*&@6FYIB{XK#L{r$ z(q@UKCE?VS%~Dr{6JHA@wi0kHs4iY5a!k>8zb0>EBfOq&Lo2&++0T@VVi=Rkpz2sldHh~6JXuOEi;>Q>@~bT`2~NOLvnNaTf& z1O9B3CLu=x>aOUHYW+DyV5*vu5-I6nq@bms`e=v`Ox?5&+XZMmM`zngW` zzQK!jvp!lYe``0pOPj&}+09J1u19tB4Kc-ZA(Wv;9=`*uiOn!s{3V7Z)*v2@;_qns z%cp!qQ!`sml$Yz#RH*)cpxki4}^H)VNCeJ9Dc|QKN#>}^}yT!znh8JA=0baUX)f+{>Tb z&jv-(U3yV6|8zg=(Kd!Yza~B=6M#yDA>k+Xv(z?-%;%(JqHVV9ZF1>c-s=Ze7iZlV>3OOlGN^8E+c-3Zs$`yd-39jxQC z4zexU(>(nU8`x#(e^9jq1`Z}=38u@XE2u+_ji=#IGNpm{Kg@2Ca{lA3IK&dP5tL}; z{SLER6HY#g&+2F?-uM|$J&4*dCloic?Jq%Gz zi)bG6GjmD^thVH5G`Q#z-}WEJ1mfaZa$FxWIfMcwEBxZ3>;SheuF?Mr& zheyP`VdPll2s-S12E+g77gTzvfOr3u-7LLbz{mf}vb$}BcbJ$Xni@hJnwkCDR`(GO zj4a@v{K|SsFb6vLE1L{hW&Or1{qL2_9tLQf^CRw-%kIOIz+{?a&An6wRYm`(3fsf{ zF&Sz<=@!b(#IG0sv{U|(o}x<2+NTEn!;NiWu2tt3q18Gs|NhfA4T@J4~aqH zHSZY9k!L>y$VEePLRDV5hd+Ca-P0QJ8R&k;4?`_=%jZ{*v1G@GBZG^E$OpI!n*khA zYz^$krkb*s7^Y(>E$D}H5;&^xt(Nh))zbEC3rcVz+r)yGSmHwZWkIK^B|!sj-0(TR zuq(J?IPB|ca0ew_J=sd$a0!!59eZdj#(W221)>rtuKdrBN3Y4mzzQkAi%7#+bQ&CI zFKEJc^ zeUqsZo_G)H)C6v`k~|1cIH<;iAp#afrxMlWe;sEz_l~4RN04$`bUw8eqM&1*B~9v1 zN+)WBbky0Z_!wECLY-_W_UUnYwF1CLkxkP|n-U~^f)Y{9)W3g5@U_1qR8Zn*zV~<5 zy=6iyGVqVeC$0R0CAR(Ke!3e0f-$7}-x>#OTh4R-06DoS3&orj;&g$?RkYx%7K%4; zzyexCx+qp~uDgP|4w(`)>l`?-um!XPF{bQlvpgIZhrt95>Daswh0A|AU8^x?*TRDo zU*ZHyHC-|dhUE)cikl&}5F~Mh18+9BH7NtWEl(0Zt_ifJi=Z(_AdXdX=`1mE)>`LW zTn7E8yx|_iJ^tDLi^ctDiu0;|R#Zl#N}@;Q2)u9MI1xuD7?%$bh`*OhNh692xyR%~ zBXxF1f&B2!0{Q1X1#(vA;R1PJ{7x9RI<)qd@GeE1}_3W(7UqrT!vj6+rQ6e+)|Nd6r^sS?L!~0H(k7NE{AH%&5y^d}A7)E~KP9wb) z(&bVL#VY!|uc^=KU!c~A`&-yfMClX|q6o@Y<ccYSOJH? zFEI5{>P)Fnbk`uDwYUH!(YYmG{%kjy<10z!B}>_m15VT6wYQ9|Gxp|n+5 zNA%k_G`gMD0=7(w6Y)C!mTL&ObWA(xlhT{O1$wR)qO!bCQjK z&f)%(thaXf3%hiEq#eWfx|6JDrzF%p8F${G3ZFj;2IsEIdRJ|fyy!K4?j#$ap9WO4 zD2WE1;%9wP@fbf#N{kqW6a7^M6e5k4J&3b zujsh_6zd){3@eVP!jn4w#wpgj_qpB}#})WavlM*42^c7B%q+<;X0RsFsUBg{PWI+! zPO*-!{?a)qWX;hFm`r4fBuwSB>H7)`EgwukLlc2{2idAN{XhMyE2e zH5vl4u5c81t%{9!1eOvKYcxwApqdYi!MwT8vEDJ?PHku;I3^6?Th74&L}WiRhNu6< z3|$ICnOjkt$#Z`f0?4^#5JBji11ma@B*s1^O zO@JkCVut5iM?8$FljX9u$-u2cs49qCuw2wq%1`0xJny=KPJNvu_?y?7fg{M>;Fit( z{s(XmD6Di4R&je0|M?8-GCTo0ON43A!Vgie>{7DCVy2e@9B7u{7bcn|NF{~S)A+?+ z^#)RvpOpA=)1cSHXC)72@yTacM=39hUj#(cj$~?Svgoo8oT%gc1K=5IQJ{o|ggjhp z>0IEhdg(Ua@+`}X8ctx)=kR;avaWJ2y|ldxtzfCEPQK_Y>k-qr$<~2?c$RgOE@tsv z^yS#A02lAYJ7Hc&&A&O+@R?x4yRd$2xH(2S-mGEr=~P$T`u~SL+B>;&j-|$2njFNP zVFR1t&by-p?!>$i%KR&vw>b~qRnFp{M(A$i-=1e}^WVRN=AwEbaf)sGsT|XVpqb5Q z@P*Elbmhh=yc3C5&qA8Pf=&Ci1)E#lr;hE+|GdBq(FvP@7#j7Bw%ovUqe0#_H6qyS z!Yuv<(;1|a_B_9Vb?*FE9K=6sEfG3!G@HZ+Q`*zS!=-!WWi~zvvfFq=;e0;nGV2i{ zuk&u>pWtnByaCJ$g%Q_-I`2VSU~K-t5BO?~G-N+Hm?J-)I{`C6y-gn`>FGi1wsVpKv$LQ=Lx zJ26Kf@JAC;{SkspZ$bj0#oM6ds1u^&B()DP$l^{ksDCG7p%43qrAQ^W@vpA1K~a~} z0j1hZ{_;O8y?rHKls&M@6N~o(#la}~Fr6R82f1H^!vlJ#4|O2`{Yc%1*f#;(?6?j= z+I!mojF|Kd%0d!WsJ-zX;@B=32kYgsM>BbAN!PAZ|4d{k2O)494HNyPv^31wdu7-A z9l24`B}mSW{IsO&)ni`*xMlb!!~d}pR<}ABe{QJo;LX7bSKa)-EBq!@;mg4a$C05y zsKQLDa6JAr+l4@sCbkV>J9>*p9Dr65dNt9@wz=y1t~5+R2XItg=dHITvr*EhbpB{P8yt186Ls(a)vSPwFobc6Bc% zTA(qXUB~)JC)4>`b!zK9QlbC$7wz{~Hwtm@_gV)^b zZ)Mjf9cbz8uqr#Psi&+IH>||nfj@MW^~yhh#R6kc*ou~QM=8~UKk&W6qDX)uuZ*-@ zP}pHum~FCE(D*-Y6Q(xPDw;>!M1s1t9i)n&vb;Tj&8sS)lY(o*MiK1Qn>81-x_y7gQ?j*7CRg1-EFt!{wy zV>`a;5=$R7Bko`5j$M8t(wcU8nYz5@7gVtyYy>Pi;vSSso=+1C0EoDp0JXsqLwcJl zzj50IHcN`=&3zYGm#8i}jO|!2{_<7UDgLycJ~`kSeF0k)!dA))59@i&Rh)HR{uz~5 zfmtyl{2i1#s4>K83R5PxF$r<8EpFTe?Yqjzc!NqhGP+KWEN#DwdH`L7jB81HmzkzX!4ZBc6;C51X!OUe2 z$ypNkQx{pgo*LvztZT-IK3H?EYoK?TAZ5g098EB%9t~2wWF&=mSl4IRHPr1bc$-UXY%V4r zEB73Y7XPe+7FM>vxXX4%h!spwFtLRsPm{|wAPreaZplTt`NJ; zqY=FE3Nt!xHb4V1RI9!fAf+ntkHJNxoB=h_wFuJJxYIQBTG_jzObYfQ7^LwBkW=+< z@#T*p973G6B+uQ5eW}|k!h1Cga5Y?(%T5E)EEND(h#5ZToD%~p#UHaN-EH2hZwfiI zjZzRaFb+%Gi)X9y3#xttz;WxAmsJ)%Y?*Qxwg1E?FlWfd_iYjhg6*%%Ju0rkp(a;`3tUvDW*XmleR)$SO-u*=WkM;NU7HOb-bdp zuDA5Op1&C#8Q(VmYVws*omCfnjL?E}Cgu1Zfh`UY@ zln2k>$Qv+^qBm~cOPI%^An6?qrYJm%MuUJAg8yLcquTcX*KTs@7mQe@emW=-G<-3T zd>jq_I#-QDQl#t}+XIuJ{Ft!=6QyYd&$uvKr@J3mA((C2tHd6a5Cn%nV&#Yv$wACG?Wn&u+fm2%!}zbS6hN7zWjHf_A?TgF-+eqIC36AomKeo`8QCd~JuLJG8@VA!(y&x88>CY$q!q zCsNIDqri{G6Tcl?3#{J2L6XA=-BP>szE~8UZb$=xr}8hNfF;|Uk7huj<1BJM#1Lpy zUNQ<`G{fyGgzp~*@%=A*TiLtIoSjo+ANv1TvkhJOZ@VK>BMUY@uT{tJ(kNX@a(t9H zQK&C~?Ey%evr&zXwpMitzelg@8)Jd)iRN}kH@;M_n}jRS&**jgC3h0v7Ol&6w8qye z1IL90RZK%{Tf9qy0Lx0+OPEn$6v4mQ#7;VfiTwp^oyC*eSV6WH=F~G8J0P|z>G>Bx z?eizeWu5T^zW*)kiti)Xl#I*kfIl8x8kC|X;)>BzNPuh7g_}Tf36nu2mtbnchmFlk zANcJm z=}KFr3!}9(3rSFGOR1ltn>Rv(mROVj_uMy=MEm>w|9_u0^WJ@TzvrHF?zv|H`=kwJ zxIpg?rCg|tl# zp)&db5mk#tM|DP}0T`&$CUATwo!VL~(z)g!W~Ys0E{^&3U^@Yv>i{^_?E3-8t{VXD zrg-?r^amh%Unkla21NU6AfLapt(#!_v}6C+2LV~Zt5ga$`-qPmZxDpk*m+u$rPUVU zu`^hNpC#K!$0LBAs2#={^}0yswJJodZiS6a0s_tJ2H63D+J_v~UDxf&Tv!v%V82AN zcq)uFZWRnzhH&r%5boX#9i$T8N#a}u<)HtPd@MeMwKsU`+%Oy^zNjUR*I^%o{u&G1 zI{asd$xqZ_tHpzLSnU1LNW)3nzggXg_$RICaVt)ql-z@cYGz*xg$Q~Rv9=CNsHp(e zqJZzPN&FPXHg>z+f=qa5msTCt|2T!QPmaVe{=3jAYjYj(w#u4zIv?(*>i@xc4TOv; zde-K7F?KEB4e$ge_Em5j*c;iGsLu6u#3hyWu7UfPGQDqm(J7qWZ@koNFD8bw){QO# zp=fZHR#L4yML(gaRjdtXO-xZ@XE^H;ITQ;+b*zb!@WP}Futr_hbON067Fk?n41qq) zCaY?_VacorRdZU_C7JaLK)3h{Nt|CuIdF2=HrxkPoJ&{R=c!BXf^qiU!JkavE`%=p zMa`KEd{S9ZEUL?*OwGjWby-JKw%A{nwFplpD9vTAyy&FEvwroB5O?dcX3^pBd#PP> z{jMCj)&H4m~%1*$2A%LfrYfiz#BwBwwKijpP{bs zI569zBxNP3ol%dkw%BnWYufnr0)uB8P89)z!*3jHEEP3tz)#}ZeJr8r4V=rO$>FnlVwiX#l67|CA|dtl zXu3{#y`#nBXo|^phJArQBfkj8Un_mXUwA1g2q(>yjEz1r%_sC;Z5vwM&)oob^Z$?S zw*nrBLleIps33gv@@0CvJmd`1MGW+F0P%&f;6jDp-TkaQWmvIMj}6n~T$ ztA8||@V^Po2belPb7<8P#A7uWC{JTn!xTd{f$wP#2WEQmW~k#$Kb_aa+>(*eJ&n)pT z=?Qr!F$b<2S7))Z!wCMR*Uq#_>?;LZA~A+VIQ9Llk>##3cV%^{O$kiV(Hvs-(#eU$ zp5gYS?+7YY&oM9>X$J32j%9H03-%Ln@_xQ}9X{K&JiF`M4ZCM1G_A^Pd8NT5N78P) ze#Jw16wH8#o>Ab9T59%#DByb(f5hYlEVg50tlY3_jtBH3aQ`qlY`xstmOQ<=Z!SJS z@kx5FyHT6mJatnBd?Oxe#(H%r_plK9#uiJV(^J5Zn42i<90RA9tBWT93;5+FQsE-4 zw%Ff{#VIXoi)+nT^k@^lvkJ>nc?;uPN&u?;h)ULCF5PT1nADlorW>sNWuxk=WryW_ ztNnBhl;9e)y8d}?R7R;%LcmD)CO(Z~&71>T$sT5+a{uD`56tc+FB|@jheiW%fqfU& zm-uGsb}TB?KDAr6$+{6;LOT%a0fn<79nlE&j=AwUjjQV0!@R(GrMwYS$0Si2~p(=Wb(}bO0nRgAqkQi z^(6(JkWKFdV^q-=G~2&1-!?eFQ#RZMQ#r?ds&{`9_9r&2&>FFNN^_$#4_=e|D!{2k z#G}~+!ifLuQX0+&FpSFF5u1tnaDrMS9=Q_SS^2#dG3{L%m}pS{EVR9an0N&y%V(m2 zESuL7x1(8?R;~V9&Ien_>cLVFr7(vWqm~HWz!)qyEaMQyaM#{7u#ChURQ6gJe4 zq_oH?93>vE8B)JtL9_%sYFJV$Z2NFq+mVoztZK^QTKf5Unz}#}Gf+Z1xoEE+m%Joy zn?oAKq##vZ)YSur~~3H zU;F{_TyxeNw_e+tgZCV~Mx1WWx*!x&L^Mn69&Sl2U6hZ0Mr

^!WlXqpQoyVG8;W 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%0DCQie&G8oJ^=iH#Rq}sSv(E=aFA2^c^Hg@;8;)~ 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%0D<&_}9#Jb(Lc!aAk_x5dEpQ+CrnjYh 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

}!AVc^@PysNvC4t6k~O=o;0q3I�WCdQPg=VNN~cO@&vq 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 z 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�o4_(*9;=XdF}kC6bGPj{ual9r!C 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ϞBE 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

  • +String Buffers +
  • jit.* Library
  • Lua/C API diff --git a/love/src/jni/LuaJIT-2.1/doc/ext_buffer.html b/love/src/jni/LuaJIT-2.1/doc/ext_buffer.html new file mode 100644 index 00000000..63c2efe3 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/doc/ext_buffer.html @@ -0,0 +1,693 @@ + + + +String Buffer Library + + + + + + + + +
    +Lua +
    + + +
    +

    +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 libary also includes a high-performance +serializer for Lua objects. +

    + +

    Work in Progress

    +

    +This library is a work in progress. More +functionality will be added soon. +

    + +

    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 de-serializes (decodes) the string +str, the buffer method de-serializes 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. +

    + +

    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 inbetween). 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. +

    + +

    Serialization Format Specification

    +

    +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 a*object h.U h*{object object}      // Mixed
    +          | 0x0c a.U (a-1)*object                // 1-based array
    +          | 0x0d a.U (a-1)*object h.U 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/love/src/jni/LuaJIT-2.1/doc/ext_c_api.html b/love/src/jni/LuaJIT-2.1/doc/ext_c_api.html index e204459a..9f1ad212 100644 --- a/love/src/jni/LuaJIT-2.1/doc/ext_c_api.html +++ b/love/src/jni/LuaJIT-2.1/doc/ext_c_api.html @@ -1,8 +1,8 @@ - + Lua/C API Extensions - + @@ -37,6 +37,8 @@ FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API diff --git a/love/src/jni/LuaJIT-2.1/doc/ext_ffi.html b/love/src/jni/LuaJIT-2.1/doc/ext_ffi.html index 115a77fe..b934dc78 100644 --- a/love/src/jni/LuaJIT-2.1/doc/ext_ffi.html +++ b/love/src/jni/LuaJIT-2.1/doc/ext_ffi.html @@ -1,8 +1,8 @@ - + FFI Library - + @@ -37,6 +37,8 @@ FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API diff --git a/love/src/jni/LuaJIT-2.1/doc/ext_ffi_api.html b/love/src/jni/LuaJIT-2.1/doc/ext_ffi_api.html index 65761aa7..061cc42a 100644 --- a/love/src/jni/LuaJIT-2.1/doc/ext_ffi_api.html +++ b/love/src/jni/LuaJIT-2.1/doc/ext_ffi_api.html @@ -1,8 +1,8 @@ - + ffi.* API Functions - + @@ -42,6 +42,8 @@ td.abiparam { font-weight: bold; width: 6em; } FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API diff --git a/love/src/jni/LuaJIT-2.1/doc/ext_ffi_semantics.html b/love/src/jni/LuaJIT-2.1/doc/ext_ffi_semantics.html index 16f87739..fef39c32 100644 --- a/love/src/jni/LuaJIT-2.1/doc/ext_ffi_semantics.html +++ b/love/src/jni/LuaJIT-2.1/doc/ext_ffi_semantics.html @@ -1,8 +1,8 @@ - + FFI Semantics - + @@ -42,6 +42,8 @@ td.convop { font-style: italic; width: 40%; } FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API diff --git a/love/src/jni/LuaJIT-2.1/doc/ext_ffi_tutorial.html b/love/src/jni/LuaJIT-2.1/doc/ext_ffi_tutorial.html index c7d453ae..ca71be4d 100644 --- a/love/src/jni/LuaJIT-2.1/doc/ext_ffi_tutorial.html +++ b/love/src/jni/LuaJIT-2.1/doc/ext_ffi_tutorial.html @@ -1,8 +1,8 @@ - + FFI Tutorial - + @@ -44,6 +44,8 @@ td.idiomlua b { font-weight: normal; color: #2142bf; } FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API diff --git a/love/src/jni/LuaJIT-2.1/doc/ext_jit.html b/love/src/jni/LuaJIT-2.1/doc/ext_jit.html index 17362d6a..6dd54c70 100644 --- a/love/src/jni/LuaJIT-2.1/doc/ext_jit.html +++ b/love/src/jni/LuaJIT-2.1/doc/ext_jit.html @@ -1,8 +1,8 @@ - + jit.* Library - + @@ -37,6 +37,8 @@ FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API diff --git a/love/src/jni/LuaJIT-2.1/doc/ext_profiler.html b/love/src/jni/LuaJIT-2.1/doc/ext_profiler.html index a2f9cab0..2783abdb 100644 --- a/love/src/jni/LuaJIT-2.1/doc/ext_profiler.html +++ b/love/src/jni/LuaJIT-2.1/doc/ext_profiler.html @@ -1,8 +1,8 @@ - + Profiler - + @@ -37,6 +37,8 @@ FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API diff --git a/love/src/jni/LuaJIT-2.1/doc/extensions.html b/love/src/jni/LuaJIT-2.1/doc/extensions.html index d0c3ca7a..748c1793 100644 --- a/love/src/jni/LuaJIT-2.1/doc/extensions.html +++ b/love/src/jni/LuaJIT-2.1/doc/extensions.html @@ -1,8 +1,8 @@ - + Extensions - + @@ -54,6 +54,8 @@ td.excinterop { FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API @@ -392,29 +394,19 @@ the toolchain used to compile LuaJIT: Interoperability -POSIX/x64, DWARF2 unwinding -GCC 4.3+, Clang +External frame unwinding +GCC, Clang, MSVC Full -ARM -DLUAJIT_UNWIND_EXTERNAL -GCC, Clang -Full - - -Other platforms, DWARF2 unwinding +Internal frame unwinding + DWARF2 GCC, Clang Limited - -Windows/x64 -MSVC -Full - -Windows/x86 -Any -Full +Windows 64 bit +non-MSVC +Limited Other platforms @@ -435,7 +427,9 @@ the toolchain used to compile LuaJIT: 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.
  • +The corresponding Lua error message can be retrieved from the Lua stack.
    +For MSVC for Windows 64 bit this requires compilation of your C++ code +with /EHa.
  • Throwing Lua errors across C++ frames is safe. C++ destructors will be called.
  • diff --git a/love/src/jni/LuaJIT-2.1/doc/faq.html b/love/src/jni/LuaJIT-2.1/doc/faq.html index 891a3402..1b7cb371 100644 --- a/love/src/jni/LuaJIT-2.1/doc/faq.html +++ b/love/src/jni/LuaJIT-2.1/doc/faq.html @@ -1,8 +1,8 @@ - + Frequently Asked Questions (FAQ) - + @@ -40,6 +40,8 @@ dd { margin-left: 1.5em; } FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API @@ -74,7 +76,7 @@ about LuaJIT.
  • and links to books and papers about Lua.
  • The community-managed » Lua Wiki has information about diverse topics.
  • - +
    @@ -119,8 +121,7 @@ Consider testing your application with older versions, too.
    Similarly, the Borland/Delphi runtime modifies the FPU control word and enables FP exceptions. Of course this violates the Windows ABI, too. -Please check the Delphi docs for the Set8087CW method. - +Please check the Delphi docs for the Set8087CW method.
    @@ -133,6 +134,19 @@ You have to press Ctrl-C twice to get stop your program. That's similar to when it's stuck running inside a C function under the Lua interpreter.
    +
    +
    Q: Table iteration with pairs() does not result in the same order?
    +
    The order of table iteration is explicitly undefined by +the Lua language standard.
    +Different Lua implementations or versions may use different orders for +otherwise identical tables. Different ways of constructing a table may +result in different orders, too.
    +Due to improved VM security, LuaJIT 2.1 may even use a different order +on separate VM invocations or when string keys are newly interned.

    +If your program relies on a deterministic order, it has a bug. Rewrite it, +so it doesn't rely on the key order. Or sort the table keys, if you must.
    +
    +
    Q: Can Lua code be safely sandboxed?
    diff --git a/love/src/jni/LuaJIT-2.1/doc/install.html b/love/src/jni/LuaJIT-2.1/doc/install.html index b7217537..e4af9dde 100644 --- a/love/src/jni/LuaJIT-2.1/doc/install.html +++ b/love/src/jni/LuaJIT-2.1/doc/install.html @@ -1,8 +1,8 @@ - + Installation - + @@ -65,6 +65,8 @@ td.compatno { FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API @@ -186,14 +188,18 @@ Debian/Ubuntu, install libc6-dev with the package manager.

    The recommended way to fetch the latest version is to do a pull from -the git repository. Alternatively download the latest source package of -LuaJIT (pick the .tar.gz). Move it to a directory of your choice, -open a terminal window and change to this directory. Now unpack the archive -and change to the newly created directory: +the git repository. +

    +

    +Alternatively download the latest source package of LuaJIT (pick the .tar.gz). +Move it to a directory of your choice, open a terminal window and change +to this directory. Now unpack the archive and change to the newly created +directory (replace XX.YY.ZZ with the version you downloaded):

    -tar zxf LuaJIT-2.1.0-beta3.tar.gz
    -cd LuaJIT-2.1.0-beta3
    +tar zxf LuaJIT-XX.YY.ZZ.tar.gz +cd LuaJIT-XX.YY.ZZ +

    Building LuaJIT

    The supplied Makefiles try to auto-detect the settings needed for your @@ -217,9 +223,12 @@ You can add an extra prefix to the search paths by appending the make PREFIX=/home/myself/lj2

    -Note for macOS: you must set the MACOSX_DEPLOYMENT_TARGET -environment variable to a value supported by your toolchain. +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 diff --git a/love/src/jni/LuaJIT-2.1/doc/luajit.html b/love/src/jni/LuaJIT-2.1/doc/luajit.html index 0d3bf31c..a25267a6 100644 --- a/love/src/jni/LuaJIT-2.1/doc/luajit.html +++ b/love/src/jni/LuaJIT-2.1/doc/luajit.html @@ -1,8 +1,8 @@ - + LuaJIT - + @@ -122,6 +122,8 @@ table.feature small { FFI Semantics

  • +String Buffers +
  • jit.* Library
  • Lua/C API diff --git a/love/src/jni/LuaJIT-2.1/doc/running.html b/love/src/jni/LuaJIT-2.1/doc/running.html index 6dd3f196..b55b8439 100644 --- a/love/src/jni/LuaJIT-2.1/doc/running.html +++ b/love/src/jni/LuaJIT-2.1/doc/running.html @@ -1,8 +1,8 @@ - + Running LuaJIT - + @@ -59,6 +59,8 @@ td.param_default { FFI Semantics
  • +String Buffers +
  • jit.* Library
  • Lua/C API @@ -183,8 +185,8 @@ 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-2.1.0-beta3/jit on POSIX -systems. +this is /usr/local/share/luajit-XX.YY.ZZ>/jit on POSIX +systems (replace XX.YY.ZZ by the installed version).

    -O[level]
    diff --git a/love/src/jni/LuaJIT-2.1/doc/status.html b/love/src/jni/LuaJIT-2.1/doc/status.html index f607f5cb..1d3ba984 100644 --- a/love/src/jni/LuaJIT-2.1/doc/status.html +++ b/love/src/jni/LuaJIT-2.1/doc/status.html @@ -1,8 +1,8 @@ - + Status - + @@ -40,6 +40,8 @@ ul li { padding-bottom: 0.3em; } FFI Semantics

  • +String Buffers +
  • jit.* Library
  • Lua/C API @@ -90,12 +92,6 @@ The Lua debug API is missing a couple of features (return hooks for non-Lua functions) and shows slightly different behavior in LuaJIT (no per-coroutine hooks, no tail call counting).
  • -
  • -Currently some out-of-memory errors from on-trace code are not -handled correctly. The error may fall through an on-trace -pcall or it may be passed on to the function set with -lua_atpanic on x64. -

  • diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm.h b/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm.h index a7295663..ebcf4ac0 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm.h +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm.h @@ -294,7 +294,7 @@ int dasm_link(Dst_DECL, size_t *szp) { /* Handle globals not defined in this translation unit. */ int idx; - for (idx = 20; idx*sizeof(int) < D->lgsize; 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; } @@ -371,7 +371,10 @@ int dasm_encode(Dst_DECL, void *buffer) ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; break; case DASM_REL_LG: - CK(n >= 0, UNDEF_LG); + if (n < 0) { + n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp - 4); + goto patchrel; + } /* fallthrough */ case DASM_REL_PC: CK(n >= 0, UNDEF_PC); diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm.lua b/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm.lua index acc8b48d..0c775ae2 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm.lua +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm.lua @@ -9,9 +9,9 @@ local _info = { arch = "arm", description = "DynASM ARM module", - version = "1.4.0", - vernum = 10400, - release = "2015-10-18", + version = "1.5.0", + vernum = 10500, + release = "2021-05-02", author = "Mike Pall", license = "MIT", } diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm64.h b/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm64.h index 577b54bc..d6da4528 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm64.h +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm64.h @@ -21,8 +21,9 @@ enum { /* 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_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 }; @@ -39,6 +40,7 @@ enum { #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 @@ -247,7 +249,7 @@ void dasm_put(Dst_DECL, int start, ...) 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_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; @@ -268,6 +270,11 @@ void dasm_put(Dst_DECL, int start, ...) *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; @@ -312,13 +319,21 @@ void dasm_put(Dst_DECL, int start, ...) } case DASM_IMML: { #ifdef DASM_CHECKS - int scale = (p[-2] >> 30); + 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; } } } @@ -348,7 +363,7 @@ int dasm_link(Dst_DECL, size_t *szp) { /* Handle globals not defined in this translation unit. */ int idx; - for (idx = 20; idx*sizeof(int) < D->lgsize; 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; } @@ -375,8 +390,8 @@ int dasm_link(Dst_DECL, size_t *szp) 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: pos++; break; - case DASM_IMM13X: pos += 2; break; + case DASM_IMML: case DASM_IMMV: case DASM_VREG: pos++; break; + case DASM_IMM13X: case DASM_REL_A: pos += 2; break; } } stop: (void)0; @@ -426,7 +441,12 @@ int dasm_encode(Dst_DECL, void *buffer) ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; break; case DASM_REL_LG: - CK(n >= 0, UNDEF_LG); + if (n < 0) { + ptrdiff_t na = (ptrdiff_t)D->globals[-n] - (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); @@ -446,8 +466,24 @@ int dasm_encode(Dst_DECL, void *buffer) } 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-10] = (void *)(base + n); break; @@ -468,11 +504,17 @@ int dasm_encode(Dst_DECL, void *buffer) cp[-1] |= (dasm_imm13(n, *b++) << 10); break; case DASM_IMML: { - int scale = (p[-2] >> 30); + 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; } } diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm64.lua b/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm64.lua index 861ff2b2..cb82dc4a 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm64.lua +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_arm64.lua @@ -9,9 +9,9 @@ local _info = { arch = "arm", description = "DynASM ARM64 module", - version = "1.4.0", - vernum = 10400, - release = "2015-10-18", + version = "1.5.0", + vernum = 10500, + release = "2021-05-02", author = "Mike Pall", license = "MIT", } @@ -23,12 +23,12 @@ local _M = { _info = _info } 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 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 = bit.ror, bit.tohex +local ror, tohex, tobit = bit.ror, bit.tohex, bit.tobit -- Inherited tables and callbacks. local g_opt, g_arch @@ -39,7 +39,9 @@ local wline, werror, wfatal, wwarn local action_names = { "STOP", "SECTION", "ESC", "REL_EXT", "ALIGN", "REL_LG", "LABEL_LG", - "REL_PC", "LABEL_PC", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", + "REL_PC", "LABEL_PC", "REL_A", + "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", "IMMV", + "VREG", } -- Maximum number of section buffer positions for dasm_put(). @@ -246,9 +248,12 @@ local map_cond = { local parse_reg_type -local function parse_reg(expr) +local function parse_reg(expr, shift) 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 @@ -266,18 +271,28 @@ local function parse_reg(expr) elseif parse_reg_type ~= rt then werror("register size mismatch") end - return r, tp + 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 shift 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) + local base, tp = parse_reg(expr, 5) if parse_reg_type ~= "x" then werror("bad register type") end parse_reg_type = false - return shl(base, 5), tp + return base, tp end local parse_ctx = {} @@ -297,7 +312,7 @@ local function parse_number(n) local code = loadenv("return "..n) if code then local ok, y = pcall(code) - if ok then return y end + if ok and type(y) == "number" then return y end end return nil end @@ -403,7 +418,7 @@ local function parse_imm_load(imm, scale) end werror("out of range immediate `"..imm.."'") else - waction("IMML", 0, imm) + waction("IMML", scale, imm) return 0 end end @@ -462,6 +477,7 @@ 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 @@ -470,14 +486,13 @@ local function parse_load(params, nparams, n, op) if reg and tailr ~= "" then local base, tp = parse_reg_base(reg) if tp then - waction("IMML", 0, format(tp.ctypefmt, tailr)) + waction("IMML", scale, format(tp.ctypefmt, tailr)) return op + base end end end werror("expected address operand") end - local scale = shr(op, 30) 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 @@ -494,7 +509,7 @@ local function parse_load(params, nparams, n, op) op = op + parse_imm_load(imm, scale) else local p2b, p3b, p3s = match(p2a, "^,%s*([^,%s]*)%s*,?%s*(%S*)%s*(.*)$") - op = op + shl(parse_reg(p2b), 16) + 0x00200800 + op = op + parse_reg(p2b, 16) + 0x00200800 if parse_reg_type ~= "x" and parse_reg_type ~= "w" then werror("bad index register type") end @@ -561,14 +576,14 @@ local function parse_load_pair(params, nparams, n, op) end local function parse_label(label, def) - local prefix = sub(label, 1, 2) + local prefix = label:sub(1, 2) -- =>label (pc label reference) if prefix == "=>" then - return "PC", 0, sub(label, 3) + return "PC", 0, label:sub(3) end -- ->name (global label reference) if prefix == "->" then - return "LG", map_global[sub(label, 3)] + return "LG", map_global[label:sub(3)] end if def then -- [1-9] (local label definition) @@ -586,8 +601,11 @@ local function parse_label(label, def) 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 - werror("bad label `"..label.."'") end local function branch_type(op) @@ -620,24 +638,24 @@ local function alias_bfx(p) end local function alias_bfiz(p) - parse_reg(p[1]) + parse_reg(p[1], 0) if parse_reg_type == "w" then - p[3] = "#-("..p[3]:sub(2)..")%32" + p[3] = "#(32-("..p[3]:sub(2).."))%32" p[4] = "#("..p[4]:sub(2)..")-1" else - p[3] = "#-("..p[3]:sub(2)..")%64" + 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]) + parse_reg(p[1], 0) local sh = p[3]:sub(2) if parse_reg_type == "w" then - p[3] = "#-("..sh..")%32" + p[3] = "#(32-("..sh.."))%32" p[4] = "#31-("..sh..")" else - p[3] = "#-("..sh..")%64" + p[3] = "#(64-("..sh.."))%64" p[4] = "#63-("..sh..")" end end) @@ -881,25 +899,25 @@ end -- Handle opcodes defined with template strings. local function parse_template(params, template, nparams, pos) - local op = tonumber(sub(template, 1, 8), 16) + local op = tonumber(template:sub(1, 8), 16) local n = 1 local rtt = {} parse_reg_type = false -- Process each character. - for p in gmatch(sub(template, 9), ".") do + for p in gmatch(template:sub(9), ".") do local q = params[n] if p == "D" then - op = op + parse_reg(q); n = n + 1 + op = op + parse_reg(q, 0); n = n + 1 elseif p == "N" then - op = op + shl(parse_reg(q), 5); n = n + 1 + op = op + parse_reg(q, 5); n = n + 1 elseif p == "M" then - op = op + shl(parse_reg(q), 16); n = n + 1 + op = op + parse_reg(q, 16); n = n + 1 elseif p == "A" then - op = op + shl(parse_reg(q), 10); n = n + 1 + op = op + parse_reg(q, 10); n = n + 1 elseif p == "m" then - op = op + shl(parse_reg(params[n-1]), 16) + op = op + parse_reg(params[n-1], 16) elseif p == "p" then if q == "sp" then params[n] = "@x31" end @@ -930,8 +948,14 @@ local function parse_template(params, template, nparams, pos) 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) - waction("REL_"..mode, v+m, s, 1) + 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 @@ -977,8 +1001,8 @@ 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 3 positions. - if secpos+3 > maxsecpos then wflush() end + -- 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 @@ -990,9 +1014,11 @@ function op_template(params, template, nparams) 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 @@ -1036,23 +1062,50 @@ 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 + if not mode or 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) +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 n = tonumber(p) - if not n then werror("bad immediate `"..p.."'") end - if n < 0 then n = n + 2^32 end - wputw(n) + 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) diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_mips.h b/love/src/jni/LuaJIT-2.1/dynasm/dasm_mips.h index 2fd7d71f..b99b56b0 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_mips.h +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_mips.h @@ -273,7 +273,7 @@ int dasm_link(Dst_DECL, size_t *szp) { /* Handle globals not defined in this translation unit. */ int idx; - for (idx = 20; idx*sizeof(int) < D->lgsize; 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; } @@ -349,7 +349,10 @@ int dasm_encode(Dst_DECL, void *buffer) ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; break; case DASM_REL_LG: - CK(n >= 0, UNDEF_LG); + if (n < 0) { + n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp); + goto patchrel; + } /* fallthrough */ case DASM_REL_PC: CK(n >= 0, UNDEF_PC); diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_mips.lua b/love/src/jni/LuaJIT-2.1/dynasm/dasm_mips.lua index 45b82755..59147015 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_mips.lua +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_mips.lua @@ -12,9 +12,9 @@ local mipsr6 = _map_def.MIPSR6 local _info = { arch = mips64 and "mips64" or "mips", description = "DynASM MIPS32/MIPS64 module", - version = "1.4.0", - vernum = 10400, - release = "2020-01-20", + version = "1.5.0", + vernum = 10500, + release = "2021-05-02", author = "Mike Pall", license = "MIT", } diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_ppc.h b/love/src/jni/LuaJIT-2.1/dynasm/dasm_ppc.h index ae540e46..35264f2e 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_ppc.h +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_ppc.h @@ -277,7 +277,7 @@ int dasm_link(Dst_DECL, size_t *szp) { /* Handle globals not defined in this translation unit. */ int idx; - for (idx = 20; idx*sizeof(int) < D->lgsize; 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; } @@ -353,7 +353,10 @@ int dasm_encode(Dst_DECL, void *buffer) ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; break; case DASM_REL_LG: - CK(n >= 0, UNDEF_LG); + if (n < 0) { + n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp); + goto patchrel; + } /* fallthrough */ case DASM_REL_PC: CK(n >= 0, UNDEF_PC); diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_ppc.lua b/love/src/jni/LuaJIT-2.1/dynasm/dasm_ppc.lua index d295ef62..ee2afb2e 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_ppc.lua +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_ppc.lua @@ -11,9 +11,9 @@ local _info = { arch = "ppc", description = "DynASM PPC module", - version = "1.4.0", - vernum = 10400, - release = "2015-10-18", + version = "1.5.0", + vernum = 10500, + release = "2021-05-02", author = "Mike Pall", license = "MIT", } diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_proto.h b/love/src/jni/LuaJIT-2.1/dynasm/dasm_proto.h index ea2cc260..8914596a 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_proto.h +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_proto.h @@ -10,8 +10,8 @@ #include #include -#define DASM_IDENT "DynASM 1.4.0" -#define DASM_VERSION 10400 /* 1.4.0 */ +#define DASM_IDENT "DynASM 1.5.0" +#define DASM_VERSION 10500 /* 1.5.0 */ #ifndef Dst_DECL #define Dst_DECL dasm_State **Dst diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_x86.h b/love/src/jni/LuaJIT-2.1/dynasm/dasm_x86.h index 2e2f2334..d8d4928c 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_x86.h +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_x86.h @@ -239,8 +239,11 @@ void dasm_put(Dst_DECL, int start, ...) } pos++; ofs += 4; /* Maximum offset needed. */ - if (action == DASM_REL_LG || action == DASM_REL_PC) + 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); @@ -365,10 +368,22 @@ int dasm_link(Dst_DECL, size_t *szp) 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) @@ -443,12 +458,13 @@ int dasm_encode(Dst_DECL, void *buffer) goto wb; } case DASM_IMM_LG: - p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; } + p++; + if (n < 0) { dasma((ptrdiff_t)D->globals[-n]); break; } /* fallthrough */ case DASM_IMM_PC: { int *pb = DASM_POS2PTR(D, n); - n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base); - goto wd; + dasma(*pb < 0 ? (ptrdiff_t)pb[1] : (*pb + (ptrdiff_t)base)); + break; } case DASM_LABEL_LG: { int idx = *p++; diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dasm_x86.lua b/love/src/jni/LuaJIT-2.1/dynasm/dasm_x86.lua index bc9a0001..fe2cf579 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dasm_x86.lua +++ b/love/src/jni/LuaJIT-2.1/dynasm/dasm_x86.lua @@ -11,9 +11,9 @@ local x64 = x64 local _info = { arch = x64 and "x64" or "x86", description = "DynASM x86/x64 module", - version = "1.4.0", - vernum = 10400, - release = "2015-10-18", + version = "1.5.0", + vernum = 10500, + release = "2021-05-02", author = "Mike Pall", license = "MIT", } @@ -484,6 +484,22 @@ local function wputdarg(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) @@ -663,10 +679,16 @@ local function opmodestr(op, args) end -- Convert number to valid integer or nil. -local function toint(expr) +local function toint(expr, isqword) local n = tonumber(expr) if n then - if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 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 @@ -749,7 +771,7 @@ local function rtexpr(expr) end -- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }. -local function parseoperand(param) +local function parseoperand(param, isqword) local t = {} local expr = param @@ -810,7 +832,7 @@ local function parseoperand(param) if t.disp then break end -- [reg+xreg...] - local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$") + local xreg, tailx = match(tailr, "^%+%s*([@%w_:]+)%s*(.*)$") xreg, t.xreg, tp = rtexpr(xreg) if not t.xreg then -- [reg+-expr] @@ -837,7 +859,7 @@ local function parseoperand(param) t.disp = dispexpr(tailx) else -- imm or opsize*imm - local imm = toint(expr) + 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 @@ -1952,7 +1974,7 @@ local function dopattern(pat, args, sz, op, needrex) local a = args[narg] narg = narg + 1 local mode, imm = a.mode, a.imm - if mode == "iJ" and not match("iIJ", c) then + if mode == "iJ" and not match(x64 and "J" or "iIJ", c) then werror("bad operand size for label") end if c == "S" then @@ -2144,14 +2166,16 @@ end local function op_data(params) if not params then return "imm..." end local sz = sub(params.op, 2, 2) - if sz == "a" then sz = addrsize end + if sz == "l" then sz = "d" elseif sz == "a" then sz = addrsize end for _,p in ipairs(params) do - local a = parseoperand(p) + 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 @@ -2163,7 +2187,11 @@ 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 ------------------------------------------------------------------------------ diff --git a/love/src/jni/LuaJIT-2.1/dynasm/dynasm.lua b/love/src/jni/LuaJIT-2.1/dynasm/dynasm.lua index 92d109f2..f4e71eca 100644 --- a/love/src/jni/LuaJIT-2.1/dynasm/dynasm.lua +++ b/love/src/jni/LuaJIT-2.1/dynasm/dynasm.lua @@ -10,9 +10,9 @@ local _info = { name = "DynASM", description = "A dynamic assembler for code generation engines", - version = "1.4.0", - vernum = 10400, - release = "2015-10-18", + version = "1.5.0", + vernum = 10500, + release = "2021-05-02", author = "Mike Pall", url = "https://luajit.org/dynasm.html", license = "MIT", diff --git a/love/src/jni/LuaJIT-2.1/src/Makefile b/love/src/jni/LuaJIT-2.1/src/Makefile index 2e1a2888..2538503f 100644 --- a/love/src/jni/LuaJIT-2.1/src/Makefile +++ b/love/src/jni/LuaJIT-2.1/src/Makefile @@ -211,7 +211,7 @@ TARGET_CC= $(STATIC_CC) TARGET_STCC= $(STATIC_CC) TARGET_DYNCC= $(DYNAMIC_CC) TARGET_LD= $(CROSS)$(CC) -TARGET_AR= $(CROSS)ar rcus 2>/dev/null +TARGET_AR= $(CROSS)ar rcus TARGET_STRIP= $(CROSS)strip TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib) @@ -311,6 +311,7 @@ ifeq (Windows,$(TARGET_SYS)) TARGET_XSHLDFLAGS= -shared -Wl,--out-implib,$(TARGET_DLLDOTANAME) TARGET_DYNXLDOPTS= else + TARGET_AR+= 2>/dev/null ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1)) TARGET_XCFLAGS+= -fno-stack-protector endif @@ -319,13 +320,10 @@ ifeq (Darwin,$(TARGET_SYS)) $(error missing: export MACOSX_DEPLOYMENT_TARGET=XX.YY) endif TARGET_STRIP+= -x + TARGET_XCFLAGS+= -DLUAJIT_UNWIND_EXTERNAL TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC TARGET_DYNXLDOPTS= TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER) - ifeq (x64,$(TARGET_LJARCH)) - TARGET_XLDFLAGS+= -pagezero_size 10000 -image_base 100000000 - TARGET_XSHLDFLAGS+= -image_base 7fff04c4a000 - endif else ifeq (iOS,$(TARGET_SYS)) TARGET_STRIP+= -x @@ -336,6 +334,13 @@ ifeq (iOS,$(TARGET_SYS)) TARGET_XCFLAGS+= -fno-omit-frame-pointer endif else + ifeq (,$(findstring LJ_NO_UNWIND 1,$(TARGET_TESTARCH))) + # Find out whether the target toolchain always generates unwind tables. + TARGET_TESTUNWIND=$(shell exec 2>/dev/null; echo 'extern void b(void);int a(void){b();return 0;}' | $(TARGET_CC) -c -x c - -o tmpunwind.o && { grep -qa -e eh_frame -e __unwind_info tmpunwind.o || grep -qU -e eh_frame -e __unwind_info tmpunwind.o; } && echo E; rm -f tmpunwind.o) + ifneq (,$(findstring E,$(TARGET_TESTUNWIND))) + TARGET_XCFLAGS+= -DLUAJIT_UNWIND_EXTERNAL + endif + endif ifneq (SunOS,$(TARGET_SYS)) ifneq (PS3,$(TARGET_SYS)) TARGET_XLDFLAGS+= -Wl,-E @@ -479,13 +484,15 @@ LJVM_BOUT= $(LJVM_S) LJVM_MODE= elfasm LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \ - lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o + lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o \ + lib_buffer.o LJLIB_C= $(LJLIB_O:.o=.c) LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \ lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \ - lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \ + lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_serialize.o \ + lj_api.o lj_profile.o \ lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \ lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ diff --git a/love/src/jni/LuaJIT-2.1/src/Makefile.dep b/love/src/jni/LuaJIT-2.1/src/Makefile.dep index 3f26599e..1ad6701a 100644 --- a/love/src/jni/LuaJIT-2.1/src/Makefile.dep +++ b/love/src/jni/LuaJIT-2.1/src/Makefile.dep @@ -2,14 +2,18 @@ lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \ lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ - lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \ - lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \ - lj_ff.h lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \ - lj_strfmt.h lj_lib.h lj_libdef.h + lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h \ + lj_str.h lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h \ + lj_cconv.h lj_ff.h lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h \ + lj_strscan.h lj_strfmt.h lj_lib.h lj_libdef.h lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_strscan.h \ lj_strfmt.h lj_ctype.h lj_cdata.h lj_cconv.h lj_carith.h lj_ff.h \ lj_ffdef.h lj_lib.h lj_libdef.h +lib_buffer.o: lib_buffer.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ + lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \ + lj_tab.h lj_udata.h lj_meta.h lj_ctype.h lj_cdata.h lj_cconv.h \ + lj_strfmt.h lj_serialize.h lj_lib.h lj_libdef.h lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \ lj_libdef.h @@ -48,10 +52,10 @@ lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \ lj_dispatch.h lj_traceerr.h lj_vm.h lj_strscan.h lj_strfmt.h lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ - lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h \ - lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h lj_traceerr.h \ - lj_snap.h lj_asm.h lj_vm.h lj_target.h lj_target_*.h lj_emit_*.h \ - lj_asm_*.h + lj_buf.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h \ + lj_jit.h lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h \ + lj_traceerr.h lj_snap.h lj_asm.h lj_vm.h lj_target.h lj_target_*.h \ + lj_emit_*.h lj_asm_*.h lj_assert.o: lj_assert.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \ lj_bcdef.h @@ -77,8 +81,8 @@ lj_ccallback.o: lj_ccallback.c lj_obj.h lua.h luaconf.h lj_def.h \ lj_target_*.h lj_mcode.h lj_jit.h lj_ir.h lj_trace.h lj_dispatch.h \ lj_traceerr.h lj_vm.h lj_cconv.o: lj_cconv.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ - lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_gc.h lj_cdata.h lj_cconv.h \ - lj_ccallback.h + lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h lj_ctype.h \ + lj_cdata.h lj_cconv.h lj_ccallback.h lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_cconv.h lj_cdata.h lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h @@ -110,10 +114,10 @@ lj_err.o: lj_err.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_err.h \ lj_ff.h lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ lj_traceerr.h lj_vm.h lj_strfmt.h lj_ffrecord.o: lj_ffrecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ - lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ff.h \ - lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ - lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h lj_crecord.h \ - lj_vm.h lj_strscan.h lj_strfmt.h lj_recdef.h + lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h lj_frame.h \ + lj_bc.h lj_ff.h lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ + lj_trace.h lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h \ + lj_crecord.h lj_vm.h lj_strscan.h lj_strfmt.h lj_serialize.h lj_recdef.h lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_func.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ lj_traceerr.h lj_vm.h @@ -127,15 +131,15 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \ - lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_prng.h + lj_carith.h lj_vm.h lj_strscan.h lj_serialize.h lj_strfmt.h lj_prng.h lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \ lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \ lj_strfmt.h lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \ lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \ - lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lex.h \ - lj_bcdump.h lj_lib.h + lj_dispatch.h lj_jit.h lj_ir.h lj_ctype.h lj_vm.h lj_strscan.h \ + lj_strfmt.h lj_lex.h lj_bcdump.h lj_lib.h lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_func.h \ lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h @@ -170,15 +174,18 @@ lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_str.h lj_tab.h \ lj_func.h lj_state.h lj_bc.h lj_ctype.h lj_strfmt.h lj_lex.h lj_parse.h \ lj_vm.h lj_vmevent.h +lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \ lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h -lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \ lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \ lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h +lj_serialize.o: lj_serialize.c lj_obj.h lua.h luaconf.h lj_def.h \ + lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \ + lj_udata.h lj_ctype.h lj_cdata.h lj_ir.h lj_serialize.h lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \ lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \ @@ -189,9 +196,10 @@ lj_state.o: lj_state.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \ lj_alloc.h luajit.h lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ - lj_err.h lj_errmsg.h lj_str.h lj_char.h + lj_err.h lj_errmsg.h lj_str.h lj_char.h lj_prng.h lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ - lj_buf.h lj_gc.h lj_str.h lj_state.h lj_char.h lj_strfmt.h + lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_meta.h lj_state.h \ + lj_char.h lj_strfmt.h lj_ctype.h lj_lib.h lj_strfmt_num.o: lj_strfmt_num.c lj_obj.h lua.h luaconf.h lj_def.h \ lj_arch.h lj_buf.h lj_gc.h lj_str.h lj_strfmt.h lj_strscan.o: lj_strscan.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ @@ -204,7 +212,7 @@ lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \ lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ - lj_gc.h lj_udata.h + lj_gc.h lj_err.h lj_errmsg.h lj_udata.h lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_str.h lj_tab.h lj_state.h lj_dispatch.h lj_bc.h lj_jit.h lj_ir.h \ lj_vm.h lj_vmevent.h @@ -216,23 +224,23 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_assert.c lj_obj.h \ lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \ lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \ - lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \ - lj_prng.c lj_prng.h lj_state.c lj_lex.h lj_alloc.h luajit.h \ + lj_prng.h lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h \ + lj_debug.c lj_prng.c lj_state.c lj_lex.h lj_alloc.h luajit.h \ lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \ - lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_api.c \ - lj_profile.c lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c \ - lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h \ - lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h \ - lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h \ - lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h lj_iropt.h \ - lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \ - lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \ - lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ + lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_serialize.c \ + lj_serialize.h lj_api.c lj_profile.c lj_lex.c lualib.h lj_parse.h \ + lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c \ + lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c \ + lj_target.h lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c \ + lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h \ + lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c \ + lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c \ + lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \ lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \ lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \ lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \ - lib_init.c + lib_buffer.c lib_init.c luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ diff --git a/love/src/jni/LuaJIT-2.1/src/host/buildvm_lib.c b/love/src/jni/LuaJIT-2.1/src/host/buildvm_lib.c index 17e0111c..20bb77cd 100644 --- a/love/src/jni/LuaJIT-2.1/src/host/buildvm_lib.c +++ b/love/src/jni/LuaJIT-2.1/src/host/buildvm_lib.c @@ -385,6 +385,8 @@ void emit_lib(BuildCtx *ctx) ok = LJ_HASJIT; else if (!strcmp(buf, "#if LJ_HASFFI\n")) ok = LJ_HASFFI; + else if (!strcmp(buf, "#if LJ_HASBUFFER\n")) + ok = LJ_HASBUFFER; if (!ok) { int lvl = 1; while (fgets(buf, sizeof(buf), fp) != NULL) { diff --git a/love/src/jni/LuaJIT-2.1/src/host/minilua.c b/love/src/jni/LuaJIT-2.1/src/host/minilua.c index 79150286..cfc7491d 100644 --- a/love/src/jni/LuaJIT-2.1/src/host/minilua.c +++ b/love/src/jni/LuaJIT-2.1/src/host/minilua.c @@ -1134,7 +1134,7 @@ if(!cl->isC){ CallInfo*ci; StkId st,base; Proto*p=cl->p; -luaD_checkstack(L,p->maxstacksize); +luaD_checkstack(L,p->maxstacksize+p->numparams); func=restorestack(L,funcr); if(!p->is_vararg){ base=func+1; diff --git a/love/src/jni/LuaJIT-2.1/src/jit/dis_arm64.lua b/love/src/jni/LuaJIT-2.1/src/jit/dis_arm64.lua index ea7ca828..ad909fbd 100644 --- a/love/src/jni/LuaJIT-2.1/src/jit/dis_arm64.lua +++ b/love/src/jni/LuaJIT-2.1/src/jit/dis_arm64.lua @@ -1089,7 +1089,7 @@ local function disass_ins(ctx) last = "#"..(sf+32 - immr) operands[#operands] = last x = x + 1 - elseif x >= immr then + else name = a2 x = x - immr + 1 end diff --git a/love/src/jni/LuaJIT-2.1/src/jit/dump.lua b/love/src/jni/LuaJIT-2.1/src/jit/dump.lua index 4800a6b8..9eda08c4 100644 --- a/love/src/jni/LuaJIT-2.1/src/jit/dump.lua +++ b/love/src/jni/LuaJIT-2.1/src/jit/dump.lua @@ -102,10 +102,12 @@ end local function fillsymtab(tr, nexit) local t = symtab if nexitsym == 0 then + local maskaddr = jit.arch == "arm" and -2 local ircall = vmdef.ircall for i=0,#ircall do local addr = ircalladdr(i) if addr ~= 0 then + if maskaddr then addr = band(addr, maskaddr) end if addr < 0 then addr = addr + 2^32 end t[addr] = ircall[i] end @@ -217,8 +219,10 @@ local function colorize_text(s) return s end -local function colorize_ansi(s, t) - return format(colortype_ansi[t], s) +local function colorize_ansi(s, t, extra) + local out = format(colortype_ansi[t], s) + if extra then out = "\027[3m"..out end + return out end local irtype_ansi = setmetatable({}, @@ -227,9 +231,10 @@ local irtype_ansi = setmetatable({}, local html_escape = { ["<"] = "<", [">"] = ">", ["&"] = "&", } -local function colorize_html(s, t) +local function colorize_html(s, t, extra) s = gsub(s, "[<>&]", html_escape) - return format('%s', irtype_text[t], s) + return format('%s', + irtype_text[t], extra and " irt_extra" or "", s) end local irtype_html = setmetatable({}, @@ -254,6 +259,7 @@ span.irt_tab { color: #c00000; } span.irt_udt, span.irt_lud { color: #00c0c0; } span.irt_num { color: #4040c0; } span.irt_int, span.irt_i8, span.irt_u8, span.irt_i16, span.irt_u16 { color: #b040b0; } +span.irt_extra { font-style: italic; } ]] @@ -269,6 +275,7 @@ local litname = { if band(mode, 8) ~= 0 then s = s.."C" end if band(mode, 16) ~= 0 then s = s.."R" end if band(mode, 32) ~= 0 then s = s.."I" end + if band(mode, 64) ~= 0 then s = s.."K" end t[mode] = s return s end}), @@ -277,15 +284,18 @@ local litname = { local s = irtype[band(mode, 31)] s = irtype[band(shr(mode, 5), 31)].."."..s if band(mode, 0x800) ~= 0 then s = s.." sext" end - local c = shr(mode, 14) - if c == 2 then s = s.." index" elseif c == 3 then s = s.." check" end + local c = shr(mode, 12) + if c == 1 then s = s.." none" + elseif c == 2 then s = s.." index" + elseif c == 3 then s = s.." check" end t[mode] = s return s end}), ["FLOAD "] = vmdef.irfield, ["FREF "] = vmdef.irfield, ["FPMATH"] = vmdef.irfpm, - ["BUFHDR"] = { [0] = "RESET", "APPEND" }, + ["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" }, + ["BUFHDR"] = { [0] = "RESET", "APPEND", "WRITE" }, ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, } @@ -345,7 +355,7 @@ local function formatk(tr, idx, sn) else s = tostring(k) -- For primitives. end - s = colorize(format("%-4s", s), t) + s = colorize(format("%-4s", s), t, band(sn or 0, 0x100000) ~= 0) if slot then s = format("%s @%d", s, slot) end @@ -365,7 +375,7 @@ local function printsnap(tr, snap) out:write(colorize(format("%04d/%04d", ref, ref+1), 14)) else local m, ot, op1, op2 = traceir(tr, ref) - out:write(colorize(format("%04d", ref), band(ot, 31))) + out:write(colorize(format("%04d", ref), band(ot, 31), band(sn, 0x100000) ~= 0)) end out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME else diff --git a/love/src/jni/LuaJIT-2.1/src/jit/p.lua b/love/src/jni/LuaJIT-2.1/src/jit/p.lua index c0ad6c0e..c9ec1d8b 100644 --- a/love/src/jni/LuaJIT-2.1/src/jit/p.lua +++ b/love/src/jni/LuaJIT-2.1/src/jit/p.lua @@ -238,6 +238,7 @@ local function prof_finish() prof_count1 = nil prof_count2 = nil prof_ud = nil + if out ~= stdout then out:close() end end end diff --git a/love/src/jni/LuaJIT-2.1/src/lib_base.c b/love/src/jni/LuaJIT-2.1/src/lib_base.c index cb2e244e..55e3c6b8 100644 --- a/love/src/jni/LuaJIT-2.1/src/lib_base.c +++ b/love/src/jni/LuaJIT-2.1/src/lib_base.c @@ -19,6 +19,7 @@ #include "lj_gc.h" #include "lj_err.h" #include "lj_debug.h" +#include "lj_buf.h" #include "lj_str.h" #include "lj_tab.h" #include "lj_meta.h" @@ -75,9 +76,10 @@ LJLIB_ASM_(type) LJLIB_REC(.) /* This solves a circular dependency problem -- change FF_next_N as needed. */ LJ_STATIC_ASSERT((int)FF_next == FF_next_N); -LJLIB_ASM(next) +LJLIB_ASM(next) LJLIB_REC(.) { lj_lib_checktab(L, 1); + lj_err_msg(L, LJ_ERR_NEXTIDX); return FFH_UNREACHABLE; } @@ -406,10 +408,22 @@ LJLIB_CF(load) GCstr *name = lj_lib_optstr(L, 2); GCstr *mode = lj_lib_optstr(L, 3); int status; - if (L->base < L->top && (tvisstr(L->base) || tvisnumber(L->base))) { - GCstr *s = lj_lib_checkstr(L, 1); + if (L->base < L->top && + (tvisstr(L->base) || tvisnumber(L->base) || tvisbuf(L->base))) { + const char *s; + MSize len; + if (tvisbuf(L->base)) { + SBufExt *sbx = bufV(L->base); + s = sbx->r; + len = sbufxlen(sbx); + if (!name) name = &G(L)->strempty; /* Buffers are not NUL-terminated. */ + } else { + GCstr *str = lj_lib_checkstr(L, 1); + s = strdata(str); + len = str->len; + } lua_settop(L, 4); /* Ensure env arg exists. */ - status = luaL_loadbufferx(L, strdata(s), s->len, strdata(name ? name : s), + status = luaL_loadbufferx(L, s, len, name ? strdata(name) : s, mode ? strdata(mode) : NULL); } else { lj_lib_checkfunc(L, 1); diff --git a/love/src/jni/LuaJIT-2.1/src/lib_buffer.c b/love/src/jni/LuaJIT-2.1/src/lib_buffer.c new file mode 100644 index 00000000..2e364861 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/src/lib_buffer.c @@ -0,0 +1,356 @@ +/* +** Buffer library. +** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h +*/ + +#define lib_buffer_c +#define LUA_LIB + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + +#include "lj_obj.h" + +#if LJ_HASBUFFER +#include "lj_gc.h" +#include "lj_err.h" +#include "lj_buf.h" +#include "lj_str.h" +#include "lj_tab.h" +#include "lj_udata.h" +#include "lj_meta.h" +#if LJ_HASFFI +#include "lj_ctype.h" +#include "lj_cdata.h" +#include "lj_cconv.h" +#endif +#include "lj_strfmt.h" +#include "lj_serialize.h" +#include "lj_lib.h" + +/* -- Helper functions ---------------------------------------------------- */ + +/* Check that the first argument is a string buffer. */ +static SBufExt *buffer_tobuf(lua_State *L) +{ + if (!(L->base < L->top && tvisbuf(L->base))) + lj_err_argtype(L, 1, "buffer"); + return bufV(L->base); +} + +/* Ditto, but for writers. */ +static LJ_AINLINE SBufExt *buffer_tobufw(lua_State *L) +{ + SBufExt *sbx = buffer_tobuf(L); + setsbufXL_(sbx, L); + return sbx; +} + +#define buffer_toudata(sbx) ((GCudata *)(sbx)-1) + +/* -- Buffer methods ------------------------------------------------------ */ + +#define LJLIB_MODULE_buffer_method + +LJLIB_CF(buffer_method_free) +{ + SBufExt *sbx = buffer_tobuf(L); + lj_bufx_free(L, sbx); + L->top = L->base+1; /* Chain buffer object. */ + return 1; +} + +LJLIB_CF(buffer_method_reset) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobuf(L); + lj_bufx_reset(sbx); + L->top = L->base+1; /* Chain buffer object. */ + return 1; +} + +LJLIB_CF(buffer_method_skip) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobuf(L); + MSize n = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); + MSize len = sbufxlen(sbx); + if (n < len) { + sbx->r += n; + } else { + sbx->r = sbx->w = sbx->b; + } + L->top = L->base+1; /* Chain buffer object. */ + return 1; +} + +LJLIB_CF(buffer_method_set) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobuf(L); + GCobj *ref; + const char *p; + MSize len; +#if LJ_HASFFI + if (tviscdata(L->base+1)) { + CTState *cts = ctype_cts(L); + lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, + L->base+1, CCF_ARG(2)); + len = (MSize)lj_lib_checkintrange(L, 3, 0, LJ_MAX_BUF); + } else +#endif + { + GCstr *str = lj_lib_checkstrx(L, 2); + p = strdata(str); + len = str->len; + } + lj_bufx_free(L, sbx); + lj_bufx_set_cow(L, sbx, p, len); + ref = gcV(L->base+1); + setgcref(sbx->cowref, ref); + lj_gc_objbarrier(L, buffer_toudata(sbx), ref); + L->top = L->base+1; /* Chain buffer object. */ + return 1; +} + +LJLIB_CF(buffer_method_put) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobufw(L); + ptrdiff_t arg, narg = L->top - L->base; + for (arg = 1; arg < narg; arg++) { + cTValue *o = &L->base[arg], *mo = NULL; + retry: + if (tvisstr(o)) { + lj_buf_putstr((SBuf *)sbx, strV(o)); + } else if (tvisint(o)) { + lj_strfmt_putint((SBuf *)sbx, intV(o)); + } else if (tvisnum(o)) { + lj_strfmt_putfnum((SBuf *)sbx, STRFMT_G14, numV(o)); + } else if (tvisbuf(o)) { + SBufExt *sbx2 = bufV(o); + if (sbx2 == sbx) lj_err_arg(L, arg+1, LJ_ERR_BUFFER_SELF); + lj_buf_putmem((SBuf *)sbx, sbx2->r, sbufxlen(sbx2)); + } else if (!mo && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { + /* Call __tostring metamethod inline. */ + copyTV(L, L->top++, mo); + copyTV(L, L->top++, o); + lua_call(L, 1, 1); + o = &L->base[arg]; /* The stack may have been reallocated. */ + copyTV(L, &L->base[arg], L->top-1); + L->top = L->base + narg; + goto retry; /* Retry with the result. */ + } else { + lj_err_argtype(L, arg+1, "string/number/__tostring"); + } + /* Probably not useful to inline other __tostring MMs, e.g. FFI numbers. */ + } + L->top = L->base+1; /* Chain buffer object. */ + lj_gc_check(L); + return 1; +} + +LJLIB_CF(buffer_method_putf) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobufw(L); + lj_strfmt_putarg(L, (SBuf *)sbx, 2, 2); + L->top = L->base+1; /* Chain buffer object. */ + lj_gc_check(L); + return 1; +} + +LJLIB_CF(buffer_method_get) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobuf(L); + ptrdiff_t arg, narg = L->top - L->base; + if (narg == 1) { + narg++; + setnilV(L->top++); /* get() is the same as get(nil). */ + } + for (arg = 1; arg < narg; arg++) { + TValue *o = &L->base[arg]; + MSize n = tvisnil(o) ? LJ_MAX_BUF : + (MSize) lj_lib_checkintrange(L, arg+1, 0, LJ_MAX_BUF); + MSize len = sbufxlen(sbx); + if (n > len) n = len; + setstrV(L, o, lj_str_new(L, sbx->r, n)); + sbx->r += n; + } + if (sbx->r == sbx->w) sbx->r = sbx->w = sbx->b; + lj_gc_check(L); + return narg-1; +} + +#if LJ_HASFFI +LJLIB_CF(buffer_method_putcdata) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobufw(L); + const char *p; + MSize len; + if (tviscdata(L->base+1)) { + CTState *cts = ctype_cts(L); + lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, + L->base+1, CCF_ARG(2)); + } else { + lj_err_argtype(L, 2, "cdata"); + } + len = (MSize)lj_lib_checkintrange(L, 3, 0, LJ_MAX_BUF); + lj_buf_putmem((SBuf *)sbx, p, len); + L->top = L->base+1; /* Chain buffer object. */ + return 1; +} + +LJLIB_CF(buffer_method_reserve) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobufw(L); + MSize sz = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); + GCcdata *cd; + lj_buf_more((SBuf *)sbx, sz); + ctype_loadffi(L); + cd = lj_cdata_new_(L, CTID_P_UINT8, CTSIZE_PTR); + *(void **)cdataptr(cd) = sbx->w; + setcdataV(L, L->top++, cd); + setintV(L->top++, sbufleft(sbx)); + return 2; +} + +LJLIB_CF(buffer_method_commit) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobuf(L); + MSize len = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); + if (len > sbufleft(sbx)) lj_err_arg(L, 2, LJ_ERR_NUMRNG); + sbx->w += len; + L->top = L->base+1; /* Chain buffer object. */ + return 1; +} + +LJLIB_CF(buffer_method_ref) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobuf(L); + GCcdata *cd; + ctype_loadffi(L); + cd = lj_cdata_new_(L, CTID_P_UINT8, CTSIZE_PTR); + *(void **)cdataptr(cd) = sbx->r; + setcdataV(L, L->top++, cd); + setintV(L->top++, sbufxlen(sbx)); + return 2; +} +#endif + +LJLIB_CF(buffer_method_encode) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobufw(L); + cTValue *o = lj_lib_checkany(L, 2); + lj_serialize_put(sbx, o); + lj_gc_check(L); + L->top = L->base+1; /* Chain buffer object. */ + return 1; +} + +LJLIB_CF(buffer_method_decode) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobufw(L); + setnilV(L->top++); + sbx->r = lj_serialize_get(sbx, L->top-1); + lj_gc_check(L); + return 1; +} + +LJLIB_CF(buffer_method___gc) +{ + SBufExt *sbx = buffer_tobuf(L); + lj_bufx_free(L, sbx); + return 0; +} + +LJLIB_CF(buffer_method___tostring) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobuf(L); + setstrV(L, L->top-1, lj_str_new(L, sbx->r, sbufxlen(sbx))); + lj_gc_check(L); + return 1; +} + +LJLIB_CF(buffer_method___len) LJLIB_REC(.) +{ + SBufExt *sbx = buffer_tobuf(L); + setintV(L->top-1, (int32_t)sbufxlen(sbx)); + return 1; +} + +LJLIB_PUSH("buffer") LJLIB_SET(__metatable) +LJLIB_PUSH(top-1) LJLIB_SET(__index) + +/* -- Buffer library functions -------------------------------------------- */ + +#define LJLIB_MODULE_buffer + +LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */ + +LJLIB_CF(buffer_new) +{ + MSize sz = 0; + int targ = 1; + GCtab *env, *dict_str = NULL, *dict_mt = NULL; + GCudata *ud; + SBufExt *sbx; + if (L->base < L->top && !tvistab(L->base)) { + targ = 2; + if (!tvisnil(L->base)) + sz = (MSize)lj_lib_checkintrange(L, 1, 0, LJ_MAX_BUF); + } + if (L->base+targ-1 < L->top) { + GCtab *options = lj_lib_checktab(L, targ); + cTValue *opt_dict, *opt_mt; + opt_dict = lj_tab_getstr(options, lj_str_newlit(L, "dict")); + if (opt_dict && tvistab(opt_dict)) { + dict_str = tabV(opt_dict); + lj_serialize_dict_prep_str(L, dict_str); + } + opt_mt = lj_tab_getstr(options, lj_str_newlit(L, "metatable")); + if (opt_mt && tvistab(opt_mt)) { + dict_mt = tabV(opt_mt); + lj_serialize_dict_prep_mt(L, dict_mt); + } + } + env = tabref(curr_func(L)->c.env); + ud = lj_udata_new(L, sizeof(SBufExt), env); + ud->udtype = UDTYPE_BUFFER; + /* NOBARRIER: The GCudata is new (marked white). */ + setgcref(ud->metatable, obj2gco(env)); + setudataV(L, L->top++, ud); + sbx = (SBufExt *)uddata(ud); + lj_bufx_init(L, sbx); + setgcref(sbx->dict_str, obj2gco(dict_str)); + setgcref(sbx->dict_mt, obj2gco(dict_mt)); + if (sz > 0) lj_buf_need2((SBuf *)sbx, sz); + return 1; +} + +LJLIB_CF(buffer_encode) LJLIB_REC(.) +{ + cTValue *o = lj_lib_checkany(L, 1); + setstrV(L, L->top++, lj_serialize_encode(L, o)); + lj_gc_check(L); + return 1; +} + +LJLIB_CF(buffer_decode) LJLIB_REC(.) +{ + GCstr *str = lj_lib_checkstrx(L, 1); + setnilV(L->top++); + lj_serialize_decode(L, L->top-1, str); + return 1; +} + +/* ------------------------------------------------------------------------ */ + +#include "lj_libdef.h" + +int luaopen_string_buffer(lua_State *L) +{ + LJ_LIB_REG(L, NULL, buffer_method); + lua_getfield(L, -1, "__tostring"); + lua_setfield(L, -2, "tostring"); + LJ_LIB_REG(L, NULL, buffer); + return 1; +} + +#endif diff --git a/love/src/jni/LuaJIT-2.1/src/lib_ffi.c b/love/src/jni/LuaJIT-2.1/src/lib_ffi.c index a29014e5..b4321048 100644 --- a/love/src/jni/LuaJIT-2.1/src/lib_ffi.c +++ b/love/src/jni/LuaJIT-2.1/src/lib_ffi.c @@ -573,6 +573,7 @@ LJLIB_CF(ffi_typeinfo) setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "sib")), (int32_t)ct->sib); if (gcref(ct->name)) { GCstr *s = gco2str(gcref(ct->name)); + if (isdead(G(L), obj2gco(s))) flipwhite(obj2gco(s)); setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "name")), s); } lj_gc_check(L); diff --git a/love/src/jni/LuaJIT-2.1/src/lib_io.c b/love/src/jni/LuaJIT-2.1/src/lib_io.c index a5163e01..b9d8cc75 100644 --- a/love/src/jni/LuaJIT-2.1/src/lib_io.c +++ b/love/src/jni/LuaJIT-2.1/src/lib_io.c @@ -60,12 +60,12 @@ static IOFileUD *io_tofile(lua_State *L) return iof; } -static FILE *io_stdfile(lua_State *L, ptrdiff_t id) +static IOFileUD *io_stdfile(lua_State *L, ptrdiff_t id) { IOFileUD *iof = IOSTDF_IOF(L, id); if (iof->fp == NULL) lj_err_caller(L, LJ_ERR_IOSTDCL); - return iof->fp; + return iof; } static IOFileUD *io_file_new(lua_State *L) @@ -178,7 +178,7 @@ static int io_file_readlen(lua_State *L, FILE *fp, MSize m) MSize n = (MSize)fread(buf, 1, m, fp); setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n)); lj_gc_check(L); - return (n > 0 || m == 0); + return n > 0; } else { int c = getc(fp); ungetc(c, fp); @@ -187,8 +187,9 @@ static int io_file_readlen(lua_State *L, FILE *fp, MSize m) } } -static int io_file_read(lua_State *L, FILE *fp, int start) +static int io_file_read(lua_State *L, IOFileUD *iof, int start) { + FILE *fp = iof->fp; int ok, n, nargs = (int)(L->top - L->base) - start; clearerr(fp); if (nargs == 0) { @@ -224,8 +225,9 @@ static int io_file_read(lua_State *L, FILE *fp, int start) return n - start; } -static int io_file_write(lua_State *L, FILE *fp, int start) +static int io_file_write(lua_State *L, IOFileUD *iof, int start) { + FILE *fp = iof->fp; cTValue *tv; int status = 1; for (tv = L->base+start; tv < L->top; tv++) { @@ -253,13 +255,11 @@ static int io_file_iter(lua_State *L) lj_err_caller(L, LJ_ERR_IOCLFL); L->top = L->base; if (n) { /* Copy upvalues with options to stack. */ - if (n > LUAI_MAXCSTACK) - lj_err_caller(L, LJ_ERR_STKOV); lj_state_checkstack(L, (MSize)n); memcpy(L->top, &fn->c.upvalue[1], n*sizeof(TValue)); L->top += n; } - n = io_file_read(L, iof->fp, 0); + n = io_file_read(L, iof, 0); if (ferror(iof->fp)) lj_err_callermsg(L, strVdata(L->top-2)); if (tvisnil(L->base) && (iof->type & IOFILE_FLAG_CLOSE)) { @@ -284,19 +284,25 @@ static int io_file_lines(lua_State *L) LJLIB_CF(io_method_close) { - IOFileUD *iof = L->base < L->top ? io_tofile(L) : - IOSTDF_IOF(L, GCROOT_IO_OUTPUT); + IOFileUD *iof; + if (L->base < L->top) { + iof = io_tofile(L); + } else { + iof = IOSTDF_IOF(L, GCROOT_IO_OUTPUT); + if (iof->fp == NULL) + lj_err_caller(L, LJ_ERR_IOCLFL); + } return io_file_close(L, iof); } LJLIB_CF(io_method_read) { - return io_file_read(L, io_tofile(L)->fp, 1); + return io_file_read(L, io_tofile(L), 1); } LJLIB_CF(io_method_write) LJLIB_REC(io_write 0) { - return io_file_write(L, io_tofile(L)->fp, 1); + return io_file_write(L, io_tofile(L), 1); } LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0) @@ -458,7 +464,7 @@ LJLIB_CF(io_write) LJLIB_REC(io_write GCROOT_IO_OUTPUT) LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT) { - return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)) == 0, NULL); + return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)->fp) == 0, NULL); } static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode) diff --git a/love/src/jni/LuaJIT-2.1/src/lib_jit.c b/love/src/jni/LuaJIT-2.1/src/lib_jit.c index 12f51d75..817c2967 100644 --- a/love/src/jni/LuaJIT-2.1/src/lib_jit.c +++ b/love/src/jni/LuaJIT-2.1/src/lib_jit.c @@ -346,11 +346,7 @@ LJLIB_CF(jit_util_tracek) ir = &T->ir[ir->op1]; } #if LJ_HASFFI - if (ir->o == IR_KINT64 && !ctype_ctsG(G(L))) { - ptrdiff_t oldtop = savestack(L, L->top); - luaopen_ffi(L); /* Load FFI library on-demand. */ - L->top = restorestack(L, oldtop); - } + if (ir->o == IR_KINT64) ctype_loadffi(L); #endif lj_ir_kvalue(L, L->top-2, ir); setintV(L->top-1, (int32_t)irt_type(ir->t)); diff --git a/love/src/jni/LuaJIT-2.1/src/lib_string.c b/love/src/jni/LuaJIT-2.1/src/lib_string.c index 51d1c4b0..75d855d6 100644 --- a/love/src/jni/LuaJIT-2.1/src/lib_string.c +++ b/love/src/jni/LuaJIT-2.1/src/lib_string.c @@ -640,89 +640,14 @@ LJLIB_CF(string_gsub) /* ------------------------------------------------------------------------ */ -/* Emulate tostring() inline. */ -static GCstr *string_fmt_tostring(lua_State *L, int arg, int retry) -{ - TValue *o = L->base+arg-1; - cTValue *mo; - lj_assertL(o < L->top, "bad usage"); /* Caller already checks for existence. */ - if (LJ_LIKELY(tvisstr(o))) - return strV(o); - if (retry != 2 && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { - copyTV(L, L->top++, mo); - copyTV(L, L->top++, o); - lua_call(L, 1, 1); - copyTV(L, L->base+arg-1, --L->top); - return NULL; /* Buffer may be overwritten, retry. */ - } - return lj_strfmt_obj(L, o); -} - LJLIB_CF(string_format) LJLIB_REC(.) { - int arg, top = (int)(L->top - L->base); - GCstr *fmt; - SBuf *sb; - FormatState fs; - SFormat sf; int retry = 0; -again: - arg = 1; - sb = lj_buf_tmp_(L); - fmt = lj_lib_checkstr(L, arg); - lj_strfmt_init(&fs, strdata(fmt), fmt->len); - while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { - if (sf == STRFMT_LIT) { - lj_buf_putmem(sb, fs.str, fs.len); - } else if (sf == STRFMT_ERR) { - lj_err_callerv(L, LJ_ERR_STRFMT, strdata(lj_str_new(L, fs.str, fs.len))); - } else { - if (++arg > top) - luaL_argerror(L, arg, lj_obj_typename[0]); - switch (STRFMT_TYPE(sf)) { - case STRFMT_INT: - if (tvisint(L->base+arg-1)) { - int32_t k = intV(L->base+arg-1); - if (sf == STRFMT_INT) - lj_strfmt_putint(sb, k); /* Shortcut for plain %d. */ - else - lj_strfmt_putfxint(sb, sf, k); - } else { - lj_strfmt_putfnum_int(sb, sf, lj_lib_checknum(L, arg)); - } - break; - case STRFMT_UINT: - if (tvisint(L->base+arg-1)) - lj_strfmt_putfxint(sb, sf, intV(L->base+arg-1)); - else - lj_strfmt_putfnum_uint(sb, sf, lj_lib_checknum(L, arg)); - break; - case STRFMT_NUM: - lj_strfmt_putfnum(sb, sf, lj_lib_checknum(L, arg)); - break; - case STRFMT_STR: { - GCstr *str = string_fmt_tostring(L, arg, retry); - if (str == NULL) - retry = 1; - else if ((sf & STRFMT_T_QUOTED)) - lj_strfmt_putquoted(sb, str); /* No formatting. */ - else - lj_strfmt_putfstr(sb, sf, str); - break; - } - case STRFMT_CHAR: - lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg)); - break; - case STRFMT_PTR: /* No formatting. */ - lj_strfmt_putptr(sb, lj_obj_ptr(G(L), L->base+arg-1)); - break; - default: - lj_assertL(0, "bad string format type"); - break; - } - } - } - if (retry++ == 1) goto again; + SBuf *sb; + do { + sb = lj_buf_tmp_(L); + retry = lj_strfmt_putarg(L, sb, 1, -retry); + } while (retry > 0); setstrV(L, L->top-1, lj_buf_str(L, sb)); lj_gc_check(L); return 1; @@ -743,6 +668,9 @@ LUALIB_API int luaopen_string(lua_State *L) setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt)); settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1)); mt->nomm = (uint8_t)(~(1u<top-1)); +#endif return 1; } diff --git a/love/src/jni/LuaJIT-2.1/src/lib_table.c b/love/src/jni/LuaJIT-2.1/src/lib_table.c index 63a6a4c6..0214bb40 100644 --- a/love/src/jni/LuaJIT-2.1/src/lib_table.c +++ b/love/src/jni/LuaJIT-2.1/src/lib_table.c @@ -159,7 +159,7 @@ LJLIB_CF(table_concat) LJLIB_REC(.) SBuf *sb = lj_buf_tmp_(L); SBuf *sbx = lj_buf_puttab(sb, t, sep, i, e); if (LJ_UNLIKELY(!sbx)) { /* Error: bad element type. */ - int32_t idx = (int32_t)(intptr_t)sbufP(sb); + int32_t idx = (int32_t)(intptr_t)sb->w; cTValue *o = lj_tab_getint(t, idx); lj_err_callerv(L, LJ_ERR_TABCAT, lj_obj_itypename[o ? itypemap(o) : ~LJ_TNIL], idx); diff --git a/love/src/jni/LuaJIT-2.1/src/lj_alloc.c b/love/src/jni/LuaJIT-2.1/src/lj_alloc.c index 21fb7af5..165203fa 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_alloc.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_alloc.c @@ -365,7 +365,7 @@ static void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, int flags) #define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv)) #define CALL_MREMAP_NOMOVE 0 #define CALL_MREMAP_MAYMOVE 1 -#if LJ_64 && !LJ_GC64 +#if LJ_64 && (!LJ_GC64 || LJ_TARGET_ARM64) #define CALL_MREMAP_MV CALL_MREMAP_NOMOVE #else #define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE diff --git a/love/src/jni/LuaJIT-2.1/src/lj_api.c b/love/src/jni/LuaJIT-2.1/src/lj_api.c index 8b00436d..8c60c058 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_api.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_api.c @@ -707,36 +707,10 @@ LUA_API void lua_pushboolean(lua_State *L, int b) incr_top(L); } -#if LJ_64 -static void *lightud_intern(lua_State *L, void *p) -{ - global_State *g = G(L); - uint64_t u = (uint64_t)p; - uint32_t up = lightudup(u); - uint32_t *segmap = mref(g->gc.lightudseg, uint32_t); - MSize segnum = g->gc.lightudnum; - if (segmap) { - MSize seg; - for (seg = 0; seg <= segnum; seg++) - if (segmap[seg] == up) /* Fast path. */ - return (void *)(((uint64_t)seg << LJ_LIGHTUD_BITS_LO) | lightudlo(u)); - segnum++; - } - if (!((segnum-1) & segnum) && segnum != 1) { - if (segnum >= (1 << LJ_LIGHTUD_BITS_SEG)) lj_err_msg(L, LJ_ERR_BADLU); - lj_mem_reallocvec(L, segmap, segnum, segnum ? 2*segnum : 2u, uint32_t); - setmref(g->gc.lightudseg, segmap); - } - g->gc.lightudnum = segnum; - segmap[segnum] = up; - return (void *)(((uint64_t)segnum << LJ_LIGHTUD_BITS_LO) | lightudlo(u)); -} -#endif - LUA_API void lua_pushlightuserdata(lua_State *L, void *p) { #if LJ_64 - p = lightud_intern(L, p); + p = lj_lightud_intern(L, p); #endif setrawlightudV(L->top, p); incr_top(L); @@ -919,11 +893,13 @@ LUA_API int lua_next(lua_State *L, int idx) cTValue *t = index2adr(L, idx); int more; lj_checkapi(tvistab(t), "stack slot %d is not a table", idx); - more = lj_tab_next(L, tabV(t), L->top-1); - if (more) { + more = lj_tab_next(tabV(t), L->top-1, L->top-1); + if (more > 0) { incr_top(L); /* Return new key and value slot. */ - } else { /* End of traversal. */ + } else if (!more) { /* End of traversal. */ L->top--; /* Remove key slot. */ + } else { + lj_err_msg(L, LJ_ERR_NEXTIDX); } return more; } @@ -1179,7 +1155,7 @@ static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud) setfuncV(L, top++, fn); if (LJ_FR2) setnilV(top++); #if LJ_64 - ud = lightud_intern(L, ud); + ud = lj_lightud_intern(L, ud); #endif setrawlightudV(top++, ud); cframe_nres(L->cframe) = 1+0; /* Zero results. */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_arch.h b/love/src/jni/LuaJIT-2.1/src/lj_arch.h index d4fd9c9d..ae999467 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_arch.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_arch.h @@ -170,14 +170,10 @@ #define LJ_ARCH_NAME "x86" #define LJ_ARCH_BITS 32 #define LJ_ARCH_ENDIAN LUAJIT_LE -#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN -#define LJ_ABI_WIN 1 -#else -#define LJ_ABI_WIN 0 -#endif #define LJ_TARGET_X86 1 #define LJ_TARGET_X86ORX64 1 #define LJ_TARGET_EHRETREG 0 +#define LJ_TARGET_EHRAREG 8 #define LJ_TARGET_MASKSHIFT 1 #define LJ_TARGET_MASKROT 1 #define LJ_TARGET_UNALIGNED 1 @@ -188,14 +184,10 @@ #define LJ_ARCH_NAME "x64" #define LJ_ARCH_BITS 64 #define LJ_ARCH_ENDIAN LUAJIT_LE -#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN -#define LJ_ABI_WIN 1 -#else -#define LJ_ABI_WIN 0 -#endif #define LJ_TARGET_X64 1 #define LJ_TARGET_X86ORX64 1 #define LJ_TARGET_EHRETREG 0 +#define LJ_TARGET_EHRAREG 16 #define LJ_TARGET_JUMPRANGE 31 /* +-2^31 = +-2GB */ #define LJ_TARGET_MASKSHIFT 1 #define LJ_TARGET_MASKROT 1 @@ -203,6 +195,8 @@ #define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE_DUAL #ifndef LUAJIT_DISABLE_GC64 #define LJ_TARGET_GC64 1 +#elif LJ_TARGET_OSX +#error "macOS requires GC64 -- don't disable it" #endif #elif LUAJIT_TARGET == LUAJIT_ARCH_ARM @@ -219,6 +213,7 @@ #define LJ_ABI_EABI 1 #define LJ_TARGET_ARM 1 #define LJ_TARGET_EHRETREG 0 +#define LJ_TARGET_EHRAREG 14 #define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */ #define LJ_TARGET_MASKSHIFT 0 #define LJ_TARGET_MASKROT 1 @@ -249,6 +244,7 @@ #endif #define LJ_TARGET_ARM64 1 #define LJ_TARGET_EHRETREG 0 +#define LJ_TARGET_EHRAREG 30 #define LJ_TARGET_JUMPRANGE 27 /* +-2^27 = +-128MB */ #define LJ_TARGET_MASKSHIFT 1 #define LJ_TARGET_MASKROT 1 @@ -304,6 +300,7 @@ #define LJ_TARGET_PPC 1 #define LJ_TARGET_EHRETREG 3 +#define LJ_TARGET_EHRAREG 65 #define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */ #define LJ_TARGET_MASKSHIFT 0 #define LJ_TARGET_MASKROT 1 @@ -406,6 +403,7 @@ #endif #define LJ_TARGET_MIPS 1 #define LJ_TARGET_EHRETREG 4 +#define LJ_TARGET_EHRAREG 31 #define LJ_TARGET_JUMPRANGE 27 /* 2*2^27 = 256MB-aligned region */ #define LJ_TARGET_MASKSHIFT 1 #define LJ_TARGET_MASKROT 1 @@ -551,6 +549,13 @@ #define LJ_HASFFI 1 #endif +/* Disable or enable the string buffer extension. */ +#if defined(LUAJIT_DISABLE_BUFFER) +#define LJ_HASBUFFER 0 +#else +#define LJ_HASBUFFER 1 +#endif + #if defined(LUAJIT_DISABLE_PROFILE) #define LJ_HASPROFILE 0 #elif LJ_TARGET_POSIX @@ -611,13 +616,10 @@ #define LJ_NO_SYSTEM 1 #endif -#if !defined(LUAJIT_NO_UNWIND) && __GNU_COMPACT_EH__ -/* NYI: no support for compact unwind specification, yet. */ -#define LUAJIT_NO_UNWIND 1 -#endif - -#if defined(LUAJIT_NO_UNWIND) || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4 -#define LJ_NO_UNWIND 1 +#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN +#define LJ_ABI_WIN 1 +#else +#define LJ_ABI_WIN 0 #endif #if LJ_TARGET_WINDOWS @@ -632,6 +634,22 @@ extern void *LJ_WIN_LOADLIBA(const char *path); #endif #endif +#if defined(LUAJIT_NO_UNWIND) || __GNU_COMPACT_EH__ || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4 +#define LJ_NO_UNWIND 1 +#endif + +#if !LJ_NO_UNWIND && !defined(LUAJIT_UNWIND_INTERNAL) && (LJ_ABI_WIN || (defined(LUAJIT_UNWIND_EXTERNAL) && (defined(__GNUC__) || defined(__clang__)))) +#define LJ_UNWIND_EXT 1 +#else +#define LJ_UNWIND_EXT 0 +#endif + +#if LJ_UNWIND_EXT && LJ_HASJIT && !LJ_TARGET_ARM && !(LJ_ABI_WIN && LJ_TARGET_X86) +#define LJ_UNWIND_JIT 1 +#else +#define LJ_UNWIND_JIT 0 +#endif + /* Compatibility with Lua 5.1 vs. 5.2. */ #ifdef LUAJIT_ENABLE_LUA52COMPAT #define LJ_52 1 diff --git a/love/src/jni/LuaJIT-2.1/src/lj_asm.c b/love/src/jni/LuaJIT-2.1/src/lj_asm.c index 7c9a4237..5968c5e3 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_asm.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_asm.c @@ -11,6 +11,7 @@ #if LJ_HASJIT #include "lj_gc.h" +#include "lj_buf.h" #include "lj_str.h" #include "lj_tab.h" #include "lj_frame.h" @@ -71,6 +72,8 @@ typedef struct ASMState { IRRef snaprename; /* Rename highwater mark for snapshot check. */ SnapNo snapno; /* Current snapshot number. */ SnapNo loopsnapno; /* Loop snapshot number. */ + int snapalloc; /* Current snapshot needs allocation. */ + BloomFilter snapfilt1, snapfilt2; /* Filled with snapshot refs. */ IRRef fuseref; /* Fusion limit (loopref, 0 or FUSE_DISABLED). */ IRRef sectref; /* Section base reference (loopref or 0). */ @@ -84,6 +87,7 @@ typedef struct ASMState { MCode *mcbot; /* Bottom of reserved MCode. */ MCode *mctop; /* Top of generated MCode. */ + MCode *mctoporig; /* Original top of generated MCode. */ MCode *mcloop; /* Pointer to loop MCode (or NULL). */ MCode *invmcp; /* Points to invertible loop branch (or NULL). */ MCode *flagmcp; /* Pending opportunity to merge flag setting ins. */ @@ -694,7 +698,14 @@ static void ra_rename(ASMState *as, Reg down, Reg up) RA_DBGX((as, "rename $f $r $r", regcost_ref(as->cost[up]), down, up)); emit_movrr(as, ir, down, up); /* Backwards codegen needs inverse move. */ if (!ra_hasspill(IR(ref)->s)) { /* Add the rename to the IR. */ - ra_addrename(as, down, ref, as->snapno); + /* + ** The rename is effective at the subsequent (already emitted) exit + ** branch. This is for the current snapshot (as->snapno). Except if we + ** haven't yet allocated any refs for the snapshot (as->snapalloc == 1), + ** then it belongs to the next snapshot. + ** See also the discussion at asm_snap_checkrename(). + */ + ra_addrename(as, down, ref, as->snapno + as->snapalloc); } } @@ -807,11 +818,11 @@ static void ra_leftov(ASMState *as, Reg dest, IRRef lref) } #endif -#if !LJ_64 /* Force a RID_RETLO/RID_RETHI destination register pair (marked as free). */ static void ra_destpair(ASMState *as, IRIns *ir) { Reg destlo = ir->r, desthi = (ir+1)->r; + IRIns *irx = (LJ_64 && !irt_is64(ir->t)) ? ir+1 : ir; /* First spill unrelated refs blocking the destination registers. */ if (!rset_test(as->freeset, RID_RETLO) && destlo != RID_RETLO && desthi != RID_RETLO) @@ -835,29 +846,28 @@ static void ra_destpair(ASMState *as, IRIns *ir) /* Check for conflicts and shuffle the registers as needed. */ if (destlo == RID_RETHI) { if (desthi == RID_RETLO) { -#if LJ_TARGET_X86 - *--as->mcp = XI_XCHGa + RID_RETHI; +#if LJ_TARGET_X86ORX64 + *--as->mcp = REX_64IR(irx, XI_XCHGa + RID_RETHI); #else - emit_movrr(as, ir, RID_RETHI, RID_TMP); - emit_movrr(as, ir, RID_RETLO, RID_RETHI); - emit_movrr(as, ir, RID_TMP, RID_RETLO); + emit_movrr(as, irx, RID_RETHI, RID_TMP); + emit_movrr(as, irx, RID_RETLO, RID_RETHI); + emit_movrr(as, irx, RID_TMP, RID_RETLO); #endif } else { - emit_movrr(as, ir, RID_RETHI, RID_RETLO); - if (desthi != RID_RETHI) emit_movrr(as, ir, desthi, RID_RETHI); + emit_movrr(as, irx, RID_RETHI, RID_RETLO); + if (desthi != RID_RETHI) emit_movrr(as, irx, desthi, RID_RETHI); } } else if (desthi == RID_RETLO) { - emit_movrr(as, ir, RID_RETLO, RID_RETHI); - if (destlo != RID_RETLO) emit_movrr(as, ir, destlo, RID_RETLO); + emit_movrr(as, irx, RID_RETLO, RID_RETHI); + if (destlo != RID_RETLO) emit_movrr(as, irx, destlo, RID_RETLO); } else { - if (desthi != RID_RETHI) emit_movrr(as, ir, desthi, RID_RETHI); - if (destlo != RID_RETLO) emit_movrr(as, ir, destlo, RID_RETLO); + if (desthi != RID_RETHI) emit_movrr(as, irx, desthi, RID_RETHI); + if (destlo != RID_RETLO) emit_movrr(as, irx, destlo, RID_RETLO); } /* Restore spill slots (if any). */ if (ra_hasspill((ir+1)->s)) ra_save(as, ir+1, RID_RETHI); if (ra_hasspill(ir->s)) ra_save(as, ir, RID_RETLO); } -#endif /* -- Snapshot handling --------- ----------------------------------------- */ @@ -892,7 +902,10 @@ static int asm_sunk_store(ASMState *as, IRIns *ira, IRIns *irs) static void asm_snap_alloc1(ASMState *as, IRRef ref) { IRIns *ir = IR(ref); - if (!irref_isk(ref) && (!(ra_used(ir) || ir->r == RID_SUNK))) { + if (!irref_isk(ref) && ir->r != RID_SUNK) { + bloomset(as->snapfilt1, ref); + bloomset(as->snapfilt2, hashrot(ref, ref + HASH_BIAS)); + if (ra_used(ir)) return; if (ir->r == RID_SINK) { ir->r = RID_SUNK; #if LJ_HASFFI @@ -947,11 +960,12 @@ static void asm_snap_alloc1(ASMState *as, IRRef ref) } /* Allocate refs escaping to a snapshot. */ -static void asm_snap_alloc(ASMState *as) +static void asm_snap_alloc(ASMState *as, int snapno) { - SnapShot *snap = &as->T->snap[as->snapno]; + SnapShot *snap = &as->T->snap[snapno]; SnapEntry *map = &as->T->snapmap[snap->mapofs]; MSize n, nent = snap->nent; + as->snapfilt1 = as->snapfilt2 = 0; for (n = 0; n < nent; n++) { SnapEntry sn = map[n]; IRRef ref = snap_ref(sn); @@ -960,7 +974,7 @@ static void asm_snap_alloc(ASMState *as) if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) { lj_assertA(irt_type(IR(ref+1)->t) == IRT_SOFTFP, "snap %d[%d] points to bad SOFTFP IR %04d", - as->snapno, n, ref - REF_BIAS); + snapno, n, ref - REF_BIAS); asm_snap_alloc1(as, ref+1); } } @@ -976,35 +990,26 @@ static void asm_snap_alloc(ASMState *as) */ static int asm_snap_checkrename(ASMState *as, IRRef ren) { - SnapShot *snap = &as->T->snap[as->snapno]; - SnapEntry *map = &as->T->snapmap[snap->mapofs]; - MSize n, nent = snap->nent; - for (n = 0; n < nent; n++) { - SnapEntry sn = map[n]; - IRRef ref = snap_ref(sn); - if (ref == ren || (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM) && ++ref == ren)) { - IRIns *ir = IR(ref); - ra_spill(as, ir); /* Register renamed, so force a spill slot. */ - RA_DBGX((as, "snaprensp $f $s", ref, ir->s)); - return 1; /* Found. */ - } + if (bloomtest(as->snapfilt1, ren) && + bloomtest(as->snapfilt2, hashrot(ren, ren + HASH_BIAS))) { + IRIns *ir = IR(ren); + ra_spill(as, ir); /* Register renamed, so force a spill slot. */ + RA_DBGX((as, "snaprensp $f $s", ren, ir->s)); + return 1; /* Found. */ } return 0; /* Not found. */ } -/* Prepare snapshot for next guard instruction. */ +/* Prepare snapshot for next guard or throwing instruction. */ static void asm_snap_prep(ASMState *as) { - if (as->curins < as->snapref) { - do { - if (as->snapno == 0) return; /* Called by sunk stores before snap #0. */ - as->snapno--; - as->snapref = as->T->snap[as->snapno].ref; - } while (as->curins < as->snapref); - asm_snap_alloc(as); + if (as->snapalloc) { + /* Alloc on first invocation for each snapshot. */ + as->snapalloc = 0; + asm_snap_alloc(as, as->snapno); as->snaprename = as->T->nins; } else { - /* Process any renames above the highwater mark. */ + /* Check any renames above the highwater mark. */ for (; as->snaprename < as->T->nins; as->snaprename++) { IRIns *ir = &as->T->ir[as->snaprename]; if (asm_snap_checkrename(as, ir->op1)) @@ -1013,6 +1018,35 @@ static void asm_snap_prep(ASMState *as) } } +/* Move to previous snapshot when we cross the current snapshot ref. */ +static void asm_snap_prev(ASMState *as) +{ + if (as->curins < as->snapref) { + uintptr_t ofs = (uintptr_t)(as->mctoporig - as->mcp); + if (ofs >= 0x10000) lj_trace_err(as->J, LJ_TRERR_MCODEOV); + do { + if (as->snapno == 0) return; + as->snapno--; + as->snapref = as->T->snap[as->snapno].ref; + as->T->snap[as->snapno].mcofs = (uint16_t)ofs; /* Remember mcode ofs. */ + } while (as->curins < as->snapref); /* May have no ins inbetween. */ + as->snapalloc = 1; + } +} + +/* Fixup snapshot mcode offsetst. */ +static void asm_snap_fixup_mcofs(ASMState *as) +{ + uint32_t sz = (uint32_t)(as->mctoporig - as->mcp); + SnapShot *snap = as->T->snap; + SnapNo i; + for (i = as->T->nsnap-1; i > 0; i--) { + /* Compute offset from mcode start and store in correct snapshot. */ + snap[i].mcofs = (uint16_t)(sz - snap[i-1].mcofs); + } + snap[0].mcofs = 0; +} + /* -- Miscellaneous helpers ----------------------------------------------- */ /* Calculate stack adjustment. */ @@ -1057,6 +1091,7 @@ static void asm_snew(ASMState *as, IRIns *ir) { const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_new]; IRRef args[3]; + asm_snap_prep(as); args[0] = ASMREF_L; /* lua_State *L */ args[1] = ir->op1; /* const char *str */ args[2] = ir->op2; /* size_t len */ @@ -1069,6 +1104,7 @@ static void asm_tnew(ASMState *as, IRIns *ir) { const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_new1]; IRRef args[2]; + asm_snap_prep(as); args[0] = ASMREF_L; /* lua_State *L */ args[1] = ASMREF_TMP1; /* uint32_t ahsize */ as->gcsteps++; @@ -1081,6 +1117,7 @@ static void asm_tdup(ASMState *as, IRIns *ir) { const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_dup]; IRRef args[2]; + asm_snap_prep(as); args[0] = ASMREF_L; /* lua_State *L */ args[1] = ir->op1; /* const GCtab *kt */ as->gcsteps++; @@ -1106,28 +1143,43 @@ static void asm_gcstep(ASMState *as, IRIns *ir) /* -- Buffer operations --------------------------------------------------- */ -static void asm_tvptr(ASMState *as, Reg dest, IRRef ref); +static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode); +#if LJ_HASBUFFER +static void asm_bufhdr_write(ASMState *as, Reg sb); +#endif static void asm_bufhdr(ASMState *as, IRIns *ir) { Reg sb = ra_dest(as, ir, RSET_GPR); - if ((ir->op2 & IRBUFHDR_APPEND)) { + switch (ir->op2) { + case IRBUFHDR_RESET: { + Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb)); + IRIns irbp; + irbp.ot = IRT(0, IRT_PTR); /* Buffer data pointer type. */ + emit_storeofs(as, &irbp, tmp, sb, offsetof(SBuf, w)); + emit_loadofs(as, &irbp, tmp, sb, offsetof(SBuf, b)); + break; + } + case IRBUFHDR_APPEND: { /* Rematerialize const buffer pointer instead of likely spill. */ IRIns *irp = IR(ir->op1); if (!(ra_hasreg(irp->r) || irp == ir-1 || (irp == ir-2 && !ra_used(ir-1)))) { - while (!(irp->o == IR_BUFHDR && !(irp->op2 & IRBUFHDR_APPEND))) + while (!(irp->o == IR_BUFHDR && irp->op2 == IRBUFHDR_RESET)) irp = IR(irp->op1); if (irref_isk(irp->op1)) { ra_weak(as, ra_allocref(as, ir->op1, RSET_GPR)); ir = irp; } } - } else { - Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb)); - /* Passing ir isn't strictly correct, but it's an IRT_PGC, too. */ - emit_storeofs(as, ir, tmp, sb, offsetof(SBuf, p)); - emit_loadofs(as, ir, tmp, sb, offsetof(SBuf, b)); + break; + } +#if LJ_HASBUFFER + case IRBUFHDR_WRITE: + asm_bufhdr_write(as, sb); + break; +#endif + default: lj_assertA(0, "bad BUFHDR op2 %d", ir->op2); break; } #if LJ_TARGET_X86ORX64 ra_left(as, sb, ir->op1); @@ -1179,7 +1231,7 @@ static void asm_bufput(ASMState *as, IRIns *ir) if (args[1] == ASMREF_TMP1) { Reg tmp = ra_releasetmp(as, ASMREF_TMP1); if (kchar == -129) - asm_tvptr(as, tmp, irs->op1); + asm_tvptr(as, tmp, irs->op1, IRTMPREF_IN1); else ra_allockreg(as, kchar, tmp); } @@ -1201,6 +1253,7 @@ static void asm_tostr(ASMState *as, IRIns *ir) { const CCallInfo *ci; IRRef args[2]; + asm_snap_prep(as); args[0] = ASMREF_L; as->gcsteps++; if (ir->op2 == IRTOSTR_NUM) { @@ -1216,7 +1269,7 @@ static void asm_tostr(ASMState *as, IRIns *ir) asm_setupresult(as, ir, ci); /* GCstr * */ asm_gencall(as, ci, args); if (ir->op2 == IRTOSTR_NUM) - asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1); + asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1, IRTMPREF_IN1); } #if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86 @@ -1257,12 +1310,19 @@ static void asm_newref(ASMState *as, IRIns *ir) IRRef args[3]; if (ir->r == RID_SINK) return; + asm_snap_prep(as); args[0] = ASMREF_L; /* lua_State *L */ args[1] = ir->op1; /* GCtab *t */ args[2] = ASMREF_TMP1; /* cTValue *key */ asm_setupresult(as, ir, ci); /* TValue * */ asm_gencall(as, ci, args); - asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2); + asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2, IRTMPREF_IN1); +} + +static void asm_tmpref(ASMState *as, IRIns *ir) +{ + Reg r = ra_dest(as, ir, RSET_GPR); + asm_tvptr(as, r, ir->op1, ir->op2); } static void asm_lref(ASMState *as, IRIns *ir) @@ -1744,6 +1804,7 @@ static void asm_ir(ASMState *as, IRIns *ir) case IR_NEWREF: asm_newref(as, ir); break; case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break; case IR_FREF: asm_fref(as, ir); break; + case IR_TMPREF: asm_tmpref(as, ir); break; case IR_STRREF: asm_strref(as, ir); break; case IR_LREF: asm_lref(as, ir); break; @@ -1838,8 +1899,7 @@ static void asm_head_side(ASMState *as) if (as->snapno && as->topslot > as->parent->topslot) { /* Force snap #0 alloc to prevent register overwrite in stack check. */ - as->snapno = 0; - asm_snap_alloc(as); + asm_snap_alloc(as, 0); } allow = asm_head_side_base(as, irp, allow); @@ -2078,6 +2138,9 @@ static void asm_setup_regsp(ASMState *as) #endif ra_setup(as); +#if LJ_TARGET_ARM64 + ra_setkref(as, RID_GL, (intptr_t)J2G(as->J)); +#endif /* Clear reg/sp for constants. */ for (ir = IR(T->nk), lastir = IR(REF_BASE); ir < lastir; ir++) { @@ -2100,6 +2163,7 @@ static void asm_setup_regsp(ASMState *as) as->snaprename = nins; as->snapref = nins; as->snapno = T->nsnap; + as->snapalloc = 0; as->stopins = REF_BASE; as->orignins = nins; @@ -2148,6 +2212,10 @@ static void asm_setup_regsp(ASMState *as) ir->prev = (uint16_t)REGSP_HINT((rload & 15)); rload = lj_ror(rload, 4); continue; + case IR_TMPREF: + if ((ir->op2 & IRTMPREF_OUT2) && as->evenspill < 4) + as->evenspill = 4; /* TMPREF OUT2 needs two TValues on the stack. */ + break; #endif case IR_CALLXS: { CCallInfo ci; @@ -2157,7 +2225,17 @@ static void asm_setup_regsp(ASMState *as) as->modset |= RSET_SCRATCH; continue; } - case IR_CALLN: case IR_CALLA: case IR_CALLL: case IR_CALLS: { + case IR_CALLL: + /* lj_vm_next needs two TValues on the stack. */ +#if LJ_TARGET_X64 && LJ_ABI_WIN + if (ir->op2 == IRCALL_lj_vm_next && as->evenspill < SPS_FIRST + 4) + as->evenspill = SPS_FIRST + 4; +#else + if (SPS_FIRST < 4 && ir->op2 == IRCALL_lj_vm_next && as->evenspill < 4) + as->evenspill = 4; +#endif + /* fallthrough */ + case IR_CALLN: case IR_CALLA: case IR_CALLS: { const CCallInfo *ci = &lj_ir_callinfo[ir->op2]; ir->prev = asm_setup_call_slots(as, ir, ci); if (inloop) @@ -2165,7 +2243,6 @@ static void asm_setup_regsp(ASMState *as) (RSET_SCRATCH & ~RSET_FPR) : RSET_SCRATCH; continue; } -#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI) case IR_HIOP: switch ((ir-1)->o) { #if LJ_SOFTFP && LJ_TARGET_ARM @@ -2176,7 +2253,7 @@ static void asm_setup_regsp(ASMState *as) } break; #endif -#if !LJ_SOFTFP && LJ_NEED_FP64 +#if !LJ_SOFTFP && LJ_NEED_FP64 && LJ_32 && LJ_HASFFI case IR_CONV: if (irt_isfp((ir-1)->t)) { ir->prev = REGSP_HINT(RID_FPRET); @@ -2184,7 +2261,7 @@ static void asm_setup_regsp(ASMState *as) } #endif /* fallthrough */ - case IR_CALLN: case IR_CALLXS: + case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS: #if LJ_SOFTFP case IR_MIN: case IR_MAX: #endif @@ -2195,7 +2272,6 @@ static void asm_setup_regsp(ASMState *as) break; } break; -#endif #if LJ_SOFTFP case IR_MIN: case IR_MAX: if ((ir+1)->o != IR_HIOP) break; @@ -2250,13 +2326,23 @@ static void asm_setup_regsp(ASMState *as) } /* fallthrough */ /* for integer POW */ case IR_DIV: case IR_MOD: - if (!irt_isnum(ir->t)) { + if ((LJ_64 && LJ_SOFTFP) || !irt_isnum(ir->t)) { ir->prev = REGSP_HINT(RID_RET); if (inloop) as->modset |= (RSET_SCRATCH & RSET_GPR); continue; } break; +#if LJ_64 && LJ_SOFTFP + case IR_ADD: case IR_SUB: case IR_MUL: + if (irt_isnum(ir->t)) { + ir->prev = REGSP_HINT(RID_RET); + if (inloop) + as->modset |= (RSET_SCRATCH & RSET_GPR); + continue; + } + break; +#endif case IR_FPMATH: #if LJ_TARGET_X86ORX64 if (ir->op2 <= IRFPM_TRUNC) { @@ -2327,7 +2413,6 @@ void lj_asm_trace(jit_State *J, GCtrace *T) { ASMState as_; ASMState *as = &as_; - MCode *origtop; /* Remove nops/renames left over from ASM restart due to LJ_TRERR_MCODELM. */ { @@ -2355,7 +2440,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T) as->parent = J->parent ? traceref(J, J->parent) : NULL; /* Reserve MCode memory. */ - as->mctop = origtop = lj_mcode_reserve(J, &as->mcbot); + as->mctop = as->mctoporig = lj_mcode_reserve(J, &as->mcbot); as->mcp = as->mctop; as->mclim = as->mcbot + MCLIM_REDZONE; asm_setup_target(as); @@ -2417,6 +2502,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T) lj_assertA(!(LJ_32 && irt_isint64(ir->t)), "IR %04d has unsplit 64 bit type", (int)(ir - as->ir) - REF_BIAS); + asm_snap_prev(as); if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE)) continue; /* Dead-code elimination can be soooo easy. */ if (irt_isguard(ir->t)) @@ -2450,6 +2536,9 @@ void lj_asm_trace(jit_State *J, GCtrace *T) memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins, (T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */ T->nins = J->curfinal->nins; + /* Fill mcofs of any unprocessed snapshots. */ + as->curins = REF_FIRST; + asm_snap_prev(as); break; /* Done. */ } @@ -2468,13 +2557,16 @@ void lj_asm_trace(jit_State *J, GCtrace *T) /* Set trace entry point before fixing up tail to allow link to self. */ T->mcode = as->mcp; T->mcloop = as->mcloop ? (MSize)((char *)as->mcloop - (char *)as->mcp) : 0; - if (!as->loopref) + if (as->loopref) + asm_loop_tail_fixup(as); + else asm_tail_fixup(as, T->link); /* Note: this may change as->mctop! */ T->szmcode = (MSize)((char *)as->mctop - (char *)as->mcp); + asm_snap_fixup_mcofs(as); #if LJ_TARGET_MCODE_FIXUP asm_mcode_fixup(T->mcode, T->szmcode); #endif - lj_mcode_sync(T->mcode, origtop); + lj_mcode_sync(T->mcode, as->mctoporig); } #undef IR diff --git a/love/src/jni/LuaJIT-2.1/src/lj_asm_arm.h b/love/src/jni/LuaJIT-2.1/src/lj_asm_arm.h index c93c99c9..cc608c0d 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_asm_arm.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_asm_arm.h @@ -185,6 +185,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow, *ofsp = (ofs & 255); /* Mask out less bits to allow LDRD. */ return ra_allock(as, (ofs & ~255), allow); } + } else if (ir->o == IR_TMPREF) { + *ofsp = 0; + return RID_SP; } } *ofsp = 0; @@ -498,6 +501,30 @@ static void asm_retf(ASMState *as, IRIns *ir) emit_lso(as, ARMI_LDR, RID_TMP, base, -4); } +/* -- Buffer operations --------------------------------------------------- */ + +#if LJ_HASBUFFER +static void asm_bufhdr_write(ASMState *as, Reg sb) +{ + Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb)); + IRIns irgc; + int32_t addr = i32ptr((void *)&J2G(as->J)->cur_L); + irgc.ot = IRT(0, IRT_PGC); /* GC type. */ + emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L)); + if ((as->flags & JIT_F_ARMV6T2)) { + emit_dnm(as, ARMI_BFI, RID_TMP, lj_fls(SBUF_MASK_FLAG), tmp); + } else { + emit_dnm(as, ARMI_ORR, RID_TMP, RID_TMP, tmp); + emit_dn(as, ARMI_AND|ARMI_K12|SBUF_MASK_FLAG, tmp, tmp); + } + emit_lso(as, ARMI_LDR, RID_TMP, + ra_allock(as, (addr & ~4095), + rset_exclude(rset_exclude(RSET_GPR, sb), tmp)), + (addr & 4095)); + emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L)); +} +#endif + /* -- Type conversions ---------------------------------------------------- */ #if !LJ_SOFTFP @@ -666,35 +693,55 @@ static void asm_strto(ASMState *as, IRIns *ir) /* -- Memory references --------------------------------------------------- */ /* Get pointer to TValue. */ -static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) +static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode) { - IRIns *ir = IR(ref); - if (irt_isnum(ir->t)) { - if (irref_isk(ref)) { - /* Use the number constant itself as a TValue. */ - ra_allockreg(as, i32ptr(ir_knum(ir)), dest); - } else { + if ((mode & IRTMPREF_IN1)) { + IRIns *ir = IR(ref); + if (irt_isnum(ir->t)) { + if ((mode & IRTMPREF_OUT1)) { #if LJ_SOFTFP - lj_assertA(0, "unsplit FP op"); + lj_assertA(irref_isk(ref), "unsplit FP op"); + emit_dm(as, ARMI_MOV, dest, RID_SP); + emit_lso(as, ARMI_STR, + ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR), + RID_SP, 0); + emit_lso(as, ARMI_STR, + ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR), + RID_SP, 4); #else - /* Otherwise force a spill and use the spill slot. */ - emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR); + Reg src = ra_alloc1(as, ref, RSET_FPR); + emit_dm(as, ARMI_MOV, dest, RID_SP); + emit_vlso(as, ARMI_VSTR_D, src, RID_SP, 0); #endif + } else if (irref_isk(ref)) { + /* Use the number constant itself as a TValue. */ + ra_allockreg(as, i32ptr(ir_knum(ir)), dest); + } else { +#if LJ_SOFTFP + lj_assertA(0, "unsplit FP op"); +#else + /* Otherwise force a spill and use the spill slot. */ + emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR); +#endif + } + } else { + /* Otherwise use [sp] and [sp+4] to hold the TValue. + ** This assumes the following call has max. 4 args. + */ + Reg type; + emit_dm(as, ARMI_MOV, dest, RID_SP); + if (!irt_ispri(ir->t)) { + Reg src = ra_alloc1(as, ref, RSET_GPR); + emit_lso(as, ARMI_STR, src, RID_SP, 0); + } + if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)) + type = ra_alloc1(as, ref+1, RSET_GPR); + else + type = ra_allock(as, irt_toitype(ir->t), RSET_GPR); + emit_lso(as, ARMI_STR, type, RID_SP, 4); } } else { - /* Otherwise use [sp] and [sp+4] to hold the TValue. */ - RegSet allow = rset_exclude(RSET_GPR, dest); - Reg type; emit_dm(as, ARMI_MOV, dest, RID_SP); - if (!irt_ispri(ir->t)) { - Reg src = ra_alloc1(as, ref, allow); - emit_lso(as, ARMI_STR, src, RID_SP, 0); - } - if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) - type = ra_alloc1(as, ref+1, allow); - else - type = ra_allock(as, irt_toitype(ir->t), allow); - emit_lso(as, ARMI_STR, type, RID_SP, 4); } } @@ -1086,6 +1133,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir) } idx = asm_fuseahuref(as, ir->op1, &ofs, allow, (!LJ_SOFTFP && t == IRT_NUM) ? 1024 : 4096); + if (ir->o == IR_VLOAD) ofs += 8 * ir->op2; if (!hiop || type == RID_NONE) { rset_clear(allow, idx); if (ofs < 256 && ra_hasreg(dest) && (dest & 1) == 0 && @@ -1837,15 +1885,15 @@ static void asm_int64comp(ASMState *as, IRIns *ir) } #endif -/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */ +/* -- Split register ops -------------------------------------------------- */ -/* Hiword op of a split 64 bit op. Previous op must be the loword op. */ +/* Hiword op of a split 32/32 bit op. Previous op is the loword op. */ static void asm_hiop(ASMState *as, IRIns *ir) { -#if LJ_HASFFI || LJ_SOFTFP /* HIOP is marked as a store because it needs its own DCE logic. */ int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; +#if LJ_HASFFI || LJ_SOFTFP if ((ir-1)->o <= IR_NE) { /* 64 bit integer or FP comparisons. ORDER IR. */ as->curins--; /* Always skip the loword comparison. */ #if LJ_SOFTFP @@ -1876,6 +1924,7 @@ static void asm_hiop(ASMState *as, IRIns *ir) asm_xstore_(as, ir, 4); return; } +#endif if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ switch ((ir-1)->o) { #if LJ_HASFFI @@ -1894,6 +1943,9 @@ static void asm_hiop(ASMState *as, IRIns *ir) asm_intneg(as, ir, ARMI_RSC); asm_intneg(as, ir-1, ARMI_RSB|ARMI_S); break; + case IR_CNEWI: + /* Nothing to do here. Handled by lo op itself. */ + break; #endif #if LJ_SOFTFP case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: @@ -1901,25 +1953,16 @@ static void asm_hiop(ASMState *as, IRIns *ir) if (!uselo) ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */ break; + case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF: + /* Nothing to do here. Handled by lo op itself. */ + break; #endif - case IR_CALLN: - case IR_CALLS: - case IR_CALLXS: + case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS: if (!uselo) ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ break; -#if LJ_SOFTFP - case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: -#endif - case IR_CNEWI: - /* Nothing to do here. Handled by lo op itself. */ - break; default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break; } -#else - /* Unused without SOFTFP or FFI. */ - UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP"); -#endif } /* -- Profiling ----------------------------------------------------------- */ @@ -2021,6 +2064,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) } else if ((sn & SNAP_SOFTFPNUM)) { type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPRODD, RID_BASE)); #endif + } else if ((sn & SNAP_KEYINDEX)) { + type = ra_allock(as, (int32_t)LJ_KEYINDEX, odd); } else { type = ra_allock(as, (int32_t)irt_toitype(ir->t), odd); } @@ -2082,6 +2127,12 @@ static void asm_loop_fixup(ASMState *as) } } +/* Fixup the tail of the loop. */ +static void asm_loop_tail_fixup(ASMState *as) +{ + UNUSED(as); /* Nothing to do. */ +} + /* -- Head of trace ------------------------------------------------------- */ /* Reload L register from g->cur_L. */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_asm_arm64.h b/love/src/jni/LuaJIT-2.1/src/lj_asm_arm64.h index b346b034..67c53ee2 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_asm_arm64.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_asm_arm64.h @@ -198,6 +198,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow, return RID_GL; } } + } else if (ir->o == IR_TMPREF) { + *ofsp = (int32_t)glofs(as, &J2G(as->J)->tmptv); + return RID_GL; } } *ofsp = 0; @@ -457,8 +460,11 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) { RegSet drop = RSET_SCRATCH; + int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); if (ra_hasreg(ir->r)) rset_clear(drop, ir->r); /* Dest reg handled below. */ + if (hiop && ra_hasreg((ir+1)->r)) + rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */ ra_evictset(as, drop); /* Evictions must be performed first. */ if (ra_used(ir)) { lj_assertA(!irt_ispri(ir->t), "PRI dest"); @@ -470,6 +476,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) } else { ra_destreg(as, ir, RID_FPRET); } + } else if (hiop) { + ra_destpair(as, ir); } else { ra_destreg(as, ir, RID_RET); } @@ -519,6 +527,21 @@ static void asm_retf(ASMState *as, IRIns *ir) emit_lso(as, A64I_LDRx, RID_TMP, base, -8); } +/* -- Buffer operations --------------------------------------------------- */ + +#if LJ_HASBUFFER +static void asm_bufhdr_write(ASMState *as, Reg sb) +{ + Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb)); + IRIns irgc; + irgc.ot = IRT(0, IRT_PGC); /* GC type. */ + emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L)); + emit_dn(as, A64I_BFMx | A64F_IMMS(lj_fls(SBUF_MASK_FLAG)) | A64F_IMMR(0), RID_TMP, tmp); + emit_getgl(as, RID_TMP, cur_L); + emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L)); +} +#endif + /* -- Type conversions ---------------------------------------------------- */ static void asm_tointg(ASMState *as, IRIns *ir, Reg left) @@ -602,7 +625,7 @@ static void asm_conv(ASMState *as, IRIns *ir) emit_dn(as, A64I_SXTW, dest, left); } } else { - if (st64) { + if (st64 && !(ir->op2 & IRCONV_NONE)) { /* This is either a 32 bit reg/reg mov which zeroes the hiword ** or a load of the loword from a 64 bit address. */ @@ -675,22 +698,23 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref) } /* Get pointer to TValue. */ -static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) +static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode) { - IRIns *ir = IR(ref); - if (irt_isnum(ir->t)) { - if (irref_isk(ref)) { - /* Use the number constant itself as a TValue. */ - ra_allockreg(as, i64ptr(ir_knum(ir)), dest); + if ((mode & IRTMPREF_IN1)) { + IRIns *ir = IR(ref); + if (irt_isnum(ir->t)) { + if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) { + /* Use the number constant itself as a TValue. */ + ra_allockreg(as, i64ptr(ir_knum(ir)), dest); + return; + } + emit_lso(as, A64I_STRd, (ra_alloc1(as, ref, RSET_FPR) & 31), dest, 0); } else { - /* Otherwise force a spill and use the spill slot. */ - emit_opk(as, A64I_ADDx, dest, RID_SP, ra_spill(as, ir), RSET_GPR); + asm_tvstore64(as, dest, 0, ref); } - } else { - /* Otherwise use g->tmptv to hold the TValue. */ - asm_tvstore64(as, dest, 0, ref); - ra_allockreg(as, i64ptr(&J2G(as->J)->tmptv), dest); } + /* g->tmptv holds the TValue(s). */ + emit_dn(as, A64I_ADDx^emit_isk12(glofs(as, &J2G(as->J)->tmptv)), dest, RID_GL); } static void asm_aref(ASMState *as, IRIns *ir) @@ -767,7 +791,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) } } else if (irt_isaddr(kt)) { if (isk) { - int64_t kk = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64; + int64_t kk = ((int64_t)irt_toitype(kt) << 47) | irkey[1].tv.u64; scr = ra_allock(as, kk, allow); } else { scr = ra_scratch(as, allow); @@ -775,7 +799,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) rset_clear(allow, scr); } else { lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type"); - type = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow); + type = ra_allock(as, ~((int64_t)~irt_toitype(kt) << 47), allow); scr = ra_scratch(as, rset_clear(allow, type)); rset_clear(allow, scr); } @@ -824,7 +848,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key.u64)); } } else { - emit_nm(as, A64I_CMPw, scr, type); + emit_nm(as, A64I_CMPx, scr, type); emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key)); } @@ -1059,6 +1083,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir) } type = ra_scratch(as, rset_clear(gpr, tmp)); idx = asm_fuseahuref(as, ir->op1, &ofs, rset_clear(gpr, type), A64I_LDRx); + if (ir->o == IR_VLOAD) ofs += 8 * ir->op2; /* Always do the type check, even if the load result is unused. */ asm_guardcc(as, irt_isnum(ir->t) ? CC_LS : CC_NE); if (irt_type(ir->t) >= IRT_NUM) { @@ -1261,17 +1286,13 @@ static void asm_tbar(ASMState *as, IRIns *ir) { Reg tab = ra_alloc1(as, ir->op1, RSET_GPR); Reg link = ra_scratch(as, rset_exclude(RSET_GPR, tab)); - Reg gr = ra_allock(as, i64ptr(J2G(as->J)), - rset_exclude(rset_exclude(RSET_GPR, tab), link)); Reg mark = RID_TMP; MCLabel l_end = emit_label(as); emit_lso(as, A64I_STRx, link, tab, (int32_t)offsetof(GCtab, gclist)); emit_lso(as, A64I_STRB, mark, tab, (int32_t)offsetof(GCtab, marked)); - emit_lso(as, A64I_STRx, tab, gr, - (int32_t)offsetof(global_State, gc.grayagain)); + emit_setgl(as, tab, gc.grayagain); emit_dn(as, A64I_ANDw^emit_isk13(~LJ_GC_BLACK, 0), mark, mark); - emit_lso(as, A64I_LDRx, link, gr, - (int32_t)offsetof(global_State, gc.grayagain)); + emit_getgl(as, link, gc.grayagain); emit_cond_branch(as, CC_EQ, l_end); emit_n(as, A64I_TSTw^emit_isk13(LJ_GC_BLACK, 0), mark); emit_lso(as, A64I_LDRB, mark, tab, (int32_t)offsetof(GCtab, marked)); @@ -1291,7 +1312,7 @@ static void asm_obar(ASMState *as, IRIns *ir) args[0] = ASMREF_TMP1; /* global_State *g */ args[1] = ir->op1; /* TValue *tv */ asm_gencall(as, ci, args); - ra_allockreg(as, i64ptr(J2G(as->J)), ra_releasetmp(as, ASMREF_TMP1) ); + emit_dm(as, A64I_MOVx, ra_releasetmp(as, ASMREF_TMP1), RID_GL); obj = IR(ir->op1)->r; tmp = ra_scratch(as, rset_exclude(allow, obj)); emit_cond_branch(as, CC_EQ, l_end); @@ -1704,13 +1725,25 @@ static void asm_comp(ASMState *as, IRIns *ir) #define asm_equal(as, ir) asm_comp(as, ir) -/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */ +/* -- Split register ops -------------------------------------------------- */ -/* Hiword op of a split 64 bit op. Previous op must be the loword op. */ +/* Hiword op of a split 64/64 bit op. Previous op is the loword op. */ static void asm_hiop(ASMState *as, IRIns *ir) { - UNUSED(as); UNUSED(ir); - lj_assertA(0, "unexpected HIOP"); /* Unused on 64 bit. */ + /* HIOP is marked as a store because it needs its own DCE logic. */ + int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ + if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; + if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ + switch ((ir-1)->o) { + case IR_CALLN: + case IR_CALLL: + case IR_CALLS: + case IR_CALLXS: + if (!uselo) + ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ + break; + default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break; + } } /* -- Profiling ----------------------------------------------------------- */ @@ -1781,7 +1814,14 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) IRIns *ir = IR(ref); if ((sn & SNAP_NORESTORE)) continue; - if (irt_isnum(ir->t)) { + if ((sn & SNAP_KEYINDEX)) { + RegSet allow = rset_exclude(RSET_GPR, RID_BASE); + Reg r = irref_isk(ref) ? ra_allock(as, ir->i, allow) : + ra_alloc1(as, ref, allow); + rset_clear(allow, r); + emit_lso(as, A64I_STRw, r, RID_BASE, ofs); + emit_lso(as, A64I_STRw, ra_allock(as, LJ_KEYINDEX, allow), RID_BASE, ofs+4); + } else if (irt_isnum(ir->t)) { Reg src = ra_alloc1(as, ref, RSET_FPR); emit_lso(as, A64I_STRd, (src & 31), RID_BASE, ofs); } else { @@ -1804,7 +1844,7 @@ static void asm_gc_check(ASMState *as) const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_step_jit]; IRRef args[2]; MCLabel l_end; - Reg tmp1, tmp2; + Reg tmp2; ra_evictset(as, RSET_SCRATCH); l_end = emit_label(as); /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */ @@ -1813,17 +1853,14 @@ static void asm_gc_check(ASMState *as) args[0] = ASMREF_TMP1; /* global_State *g */ args[1] = ASMREF_TMP2; /* MSize steps */ asm_gencall(as, ci, args); - tmp1 = ra_releasetmp(as, ASMREF_TMP1); + emit_dm(as, A64I_MOVx, ra_releasetmp(as, ASMREF_TMP1), RID_GL); tmp2 = ra_releasetmp(as, ASMREF_TMP2); emit_loadi(as, tmp2, as->gcsteps); /* Jump around GC step if GC total < GC threshold. */ emit_cond_branch(as, CC_LS, l_end); emit_nm(as, A64I_CMPx, RID_TMP, tmp2); - emit_lso(as, A64I_LDRx, tmp2, tmp1, - (int32_t)offsetof(global_State, gc.threshold)); - emit_lso(as, A64I_LDRx, RID_TMP, tmp1, - (int32_t)offsetof(global_State, gc.total)); - ra_allockreg(as, i64ptr(J2G(as->J)), tmp1); + emit_getgl(as, tmp2, gc.threshold); + emit_getgl(as, RID_TMP, gc.total); as->gcsteps = 0; checkmclim(as); } @@ -1846,6 +1883,12 @@ static void asm_loop_fixup(ASMState *as) } } +/* Fixup the tail of the loop. */ +static void asm_loop_tail_fixup(ASMState *as) +{ + UNUSED(as); /* Nothing to do. */ +} + /* -- Head of trace ------------------------------------------------------- */ /* Reload L register from g->cur_L. */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_asm_mips.h b/love/src/jni/LuaJIT-2.1/src/lj_asm_mips.h index 321d63c0..1497ad9c 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_asm_mips.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_asm_mips.h @@ -64,19 +64,31 @@ static Reg ra_alloc2(ASMState *as, IRIns *ir, RegSet allow) /* Setup spare long-range jump slots per mcarea. */ static void asm_sparejump_setup(ASMState *as) { - MCode *mxp = as->mcbot; - if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == sizeof(MCLink)) { + MCode *mxp = as->mctop; + if ((char *)mxp == (char *)as->J->mcarea + as->J->szmcarea) { + mxp -= MIPS_SPAREJUMP*2; lj_assertA(MIPSI_NOP == 0, "bad NOP"); memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode)); - mxp += MIPS_SPAREJUMP*2; - lj_assertA(mxp < as->mctop, "MIPS_SPAREJUMP too big"); - lj_mcode_sync(as->mcbot, mxp); - lj_mcode_commitbot(as->J, mxp); - as->mcbot = mxp; - as->mclim = as->mcbot + MCLIM_REDZONE; + as->mctop = mxp; } } +static MCode *asm_sparejump_use(MCode *mcarea, MCode tjump) +{ + MCode *mxp = (MCode *)((char *)mcarea + ((MCLink *)mcarea)->size); + int slot = MIPS_SPAREJUMP; + while (slot--) { + mxp -= 2; + if (*mxp == tjump) { + return mxp; + } else if (*mxp == MIPSI_NOP) { + *mxp = tjump; + return mxp; + } + } + return NULL; +} + /* Setup exit stub after the end of each trace. */ static void asm_exitstub_setup(ASMState *as) { @@ -181,6 +193,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow) return ra_allock(as, ofs-(int16_t)ofs, allow); } } + } else if (ir->o == IR_TMPREF) { + *ofsp = (int32_t)(offsetof(global_State, tmptv)-32768); + return RID_JGL; } } *ofsp = 0; @@ -336,19 +351,15 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) { RegSet drop = RSET_SCRATCH; -#if LJ_32 int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); -#endif #if !LJ_SOFTFP if ((ci->flags & CCI_NOFPRCLOBBER)) drop &= ~RSET_FPR; #endif if (ra_hasreg(ir->r)) rset_clear(drop, ir->r); /* Dest reg handled below. */ -#if LJ_32 if (hiop && ra_hasreg((ir+1)->r)) rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */ -#endif ra_evictset(as, drop); /* Evictions must be performed first. */ if (ra_used(ir)) { lj_assertA(!irt_ispri(ir->t), "PRI dest"); @@ -377,10 +388,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) } else { ra_destreg(as, ir, RID_FPRET); } -#if LJ_32 } else if (hiop) { ra_destpair(as, ir); -#endif } else { ra_destreg(as, ir, RID_RET); } @@ -450,6 +459,27 @@ static void asm_retf(ASMState *as, IRIns *ir) emit_tsi(as, MIPSI_AL, RID_TMP, base, -8); } +/* -- Buffer operations --------------------------------------------------- */ + +#if LJ_HASBUFFER +static void asm_bufhdr_write(ASMState *as, Reg sb) +{ + Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb)); + IRIns irgc; + irgc.ot = IRT(0, IRT_PGC); /* GC type. */ + emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L)); + if ((as->flags & JIT_F_MIPSXXR2)) { + emit_tsml(as, LJ_64 ? MIPSI_DINS : MIPSI_INS, RID_TMP, tmp, + lj_fls(SBUF_MASK_FLAG), 0); + } else { + emit_dst(as, MIPSI_OR, RID_TMP, RID_TMP, tmp); + emit_tsi(as, MIPSI_ANDI, tmp, tmp, SBUF_MASK_FLAG); + } + emit_getgl(as, RID_TMP, cur_L); + emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L)); +} +#endif + /* -- Type conversions ---------------------------------------------------- */ #if !LJ_SOFTFP @@ -739,7 +769,7 @@ static void asm_conv(ASMState *as, IRIns *ir) } } } else { - if (st64) { + if (st64 && !(ir->op2 & IRCONV_NONE)) { /* This is either a 32 bit reg/reg mov which zeroes the hiword ** or a load of the loword from a 64 bit address. */ @@ -827,34 +857,63 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref) #endif /* Get pointer to TValue. */ -static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) +static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode) { - IRIns *ir = IR(ref); - if (irt_isnum(ir->t)) { - if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ - ra_allockreg(as, igcptr(ir_knum(ir)), dest); - else /* Otherwise force a spill and use the spill slot. */ - emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir)); - } else { - /* Otherwise use g->tmptv to hold the TValue. */ -#if LJ_32 - RegSet allow = rset_exclude(RSET_GPR, dest); - Reg type; - emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768)); - if (!irt_ispri(ir->t)) { - Reg src = ra_alloc1(as, ref, allow); - emit_setgl(as, src, tmptv.gcr); - } - if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) - type = ra_alloc1(as, ref+1, allow); - else - type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); - emit_setgl(as, type, tmptv.it); + int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768); + if ((mode & IRTMPREF_IN1)) { + IRIns *ir = IR(ref); + if (irt_isnum(ir->t)) { + if ((mode & IRTMPREF_OUT1)) { +#if LJ_SOFTFP + emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs); +#if LJ_64 + emit_setgl(as, ra_alloc1(as, ref, RSET_GPR), tmptv.u64); #else - asm_tvstore64(as, dest, 0, ref); - emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, - (int32_t)(offsetof(global_State, tmptv)-32768)); + lj_assertA(irref_isk(ref), "unsplit FP op"); + emit_setgl(as, + ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR), + tmptv.u32.lo); + emit_setgl(as, + ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR), + tmptv.u32.hi); #endif +#else + Reg src = ra_alloc1(as, ref, RSET_FPR); + emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs); + emit_tsi(as, MIPSI_SDC1, (src & 31), RID_JGL, tmpofs); +#endif + } else if (irref_isk(ref)) { + /* Use the number constant itself as a TValue. */ + ra_allockreg(as, igcptr(ir_knum(ir)), dest); + } else { +#if LJ_SOFTFP32 + lj_assertA(0, "unsplit FP op"); +#else + /* Otherwise force a spill and use the spill slot. */ + emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir)); +#endif + } + } else { + /* Otherwise use g->tmptv to hold the TValue. */ +#if LJ_32 + Reg type; + emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, tmpofs); + if (!irt_ispri(ir->t)) { + Reg src = ra_alloc1(as, ref, RSET_GPR); + emit_setgl(as, src, tmptv.gcr); + } + if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)) + type = ra_alloc1(as, ref+1, RSET_GPR); + else + type = ra_allock(as, (int32_t)irt_toitype(ir->t), RSET_GPR); + emit_setgl(as, type, tmptv.it); +#else + asm_tvstore64(as, dest, 0, ref); + emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, tmpofs); +#endif + } + } else { + emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs); } } @@ -909,11 +968,16 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) MCLabel l_end, l_loop, l_next; rset_clear(allow, tab); -#if LJ_SOFTFP32 - if (!isk) { - key = ra_alloc1(as, refkey, allow); - rset_clear(allow, key); - if (irkey[1].o == IR_HIOP) { + if (!LJ_SOFTFP && irt_isnum(kt)) { + key = ra_alloc1(as, refkey, RSET_FPR); + tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key)); + } else { + if (!irt_ispri(kt)) { + key = ra_alloc1(as, refkey, allow); + rset_clear(allow, key); + } +#if LJ_32 + if (LJ_SOFTFP && irkey[1].o == IR_HIOP) { if (ra_hasreg((irkey+1)->r)) { type = tmpnum = (irkey+1)->r; tmp1 = ra_scratch(as, allow); @@ -924,23 +988,11 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) } rset_clear(allow, tmpnum); } else { - type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow); + type = ra_allock(as, (int32_t)irt_toitype(kt), allow); rset_clear(allow, type); } - } -#else - if (!LJ_SOFTFP && irt_isnum(kt)) { - key = ra_alloc1(as, refkey, RSET_FPR); - tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key)); - } else if (!irt_ispri(kt)) { - key = ra_alloc1(as, refkey, allow); - rset_clear(allow, key); -#if LJ_32 - type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow); - rset_clear(allow, type); #endif } -#endif tmp2 = ra_scratch(as, allow); rset_clear(allow, tmp2); #if LJ_64 @@ -953,10 +1005,10 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) } else { int64_t k; if (isk && irt_isaddr(kt)) { - k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64; + k = ((int64_t)irt_toitype(kt) << 47) | irkey[1].tv.u64; } else { lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type"); - k = ~((int64_t)~irt_toitype(ir->t) << 47); + k = ~((int64_t)~irt_toitype(kt) << 47); } cmp64 = ra_allock(as, k, allow); rset_clear(allow, cmp64); @@ -1352,6 +1404,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir) #endif } idx = asm_fuseahuref(as, ir->op1, &ofs, allow); + if (ir->o == IR_VLOAD) ofs += 8 * ir->op2; rset_clear(allow, idx); if (irt_isnum(t)) { asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); @@ -2327,15 +2380,15 @@ static void asm_comp64eq(ASMState *as, IRIns *ir) } #endif -/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */ +/* -- Split register ops -------------------------------------------------- */ -/* Hiword op of a split 64 bit op. Previous op must be the loword op. */ +/* Hiword op of a split 32/32 or 64/64 bit op. Previous op is the loword op. */ static void asm_hiop(ASMState *as, IRIns *ir) { -#if LJ_32 && (LJ_HASFFI || LJ_SOFTFP) /* HIOP is marked as a store because it needs its own DCE logic. */ int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; +#if LJ_32 && (LJ_HASFFI || LJ_SOFTFP) if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ as->curins--; /* Always skip the CONV. */ #if LJ_HASFFI && !LJ_SOFTFP @@ -2382,38 +2435,33 @@ static void asm_hiop(ASMState *as, IRIns *ir) } return; } +#endif if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ switch ((ir-1)->o) { -#if LJ_HASFFI +#if LJ_32 && LJ_HASFFI case IR_ADD: as->curins--; asm_add64(as, ir); break; case IR_SUB: as->curins--; asm_sub64(as, ir); break; case IR_NEG: as->curins--; asm_neg64(as, ir); break; + case IR_CNEWI: + /* Nothing to do here. Handled by lo op itself. */ + break; #endif -#if LJ_SOFTFP +#if LJ_32 && LJ_SOFTFP case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: case IR_STRTO: if (!uselo) ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */ break; + case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF: + /* Nothing to do here. Handled by lo op itself. */ + break; #endif - case IR_CALLN: - case IR_CALLS: - case IR_CALLXS: + case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS: if (!uselo) ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ break; -#if LJ_SOFTFP - case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: -#endif - case IR_CNEWI: - /* Nothing to do here. Handled by lo op itself. */ - break; default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break; } -#else - /* Unused on MIPS64 or without SOFTFP or FFI. */ - UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP"); -#endif } /* -- Profiling ----------------------------------------------------------- */ @@ -2513,6 +2561,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) } else if ((sn & SNAP_SOFTFPNUM)) { type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE)); #endif + } else if ((sn & SNAP_KEYINDEX)) { + type = ra_allock(as, (int32_t)LJ_KEYINDEX, allow); } else { type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); } @@ -2575,6 +2625,12 @@ static void asm_loop_fixup(ASMState *as) } } +/* Fixup the tail of the loop. */ +static void asm_loop_tail_fixup(ASMState *as) +{ + if (as->loopinv) as->mctop--; +} + /* -- Head of trace ------------------------------------------------------- */ /* Coalesce BASE register for a root trace. */ @@ -2582,7 +2638,6 @@ static void asm_head_root_base(ASMState *as) { IRIns *ir = IR(REF_BASE); Reg r = ir->r; - if (as->loopinv) as->mctop--; if (ra_hasreg(r)) { ra_free(as, r); if (rset_test(as->modset, r) || irt_ismarked(ir->t)) @@ -2597,7 +2652,6 @@ static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow) { IRIns *ir = IR(REF_BASE); Reg r = ir->r; - if (as->loopinv) as->mctop--; if (ra_hasreg(r)) { ra_free(as, r); if (rset_test(as->modset, r) || irt_ismarked(ir->t)) @@ -2704,21 +2758,17 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target) patchbranch: p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu); *p = MIPSI_NOP; /* Replace the load of the exit number. */ - cstop = p; + cstop = p+1; if (!cstart) cstart = p-1; } else { /* Branch out of range. Use spare jump slot in mcarea. */ - int i; - for (i = (int)(sizeof(MCLink)/sizeof(MCode)); - i < (int)(sizeof(MCLink)/sizeof(MCode)+MIPS_SPAREJUMP*2); - i += 2) { - if (mcarea[i] == tjump) { - delta = mcarea+i - p; - goto patchbranch; - } else if (mcarea[i] == MIPSI_NOP) { - mcarea[i] = tjump; - cstart = mcarea+i; - delta = mcarea+i - p; + MCode *mcjump = asm_sparejump_use(mcarea, tjump); + if (mcjump) { + lj_mcode_sync(mcjump, mcjump+1); + delta = mcjump - p; + if (((delta + 0x8000) >> 16) == 0) { goto patchbranch; + } else { + lj_assertJ(0, "spare jump out of range: -Osizemcode too big"); } } /* Ignore jump slot overflow. Child trace is simply not attached. */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_asm_ppc.h b/love/src/jni/LuaJIT-2.1/src/lj_asm_ppc.h index 579f8e2a..ac5d88ce 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_asm_ppc.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_asm_ppc.h @@ -156,6 +156,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow) return ra_allock(as, ofs-(int16_t)ofs, allow); } } + } else if (ir->o == IR_TMPREF) { + *ofsp = (int32_t)(offsetof(global_State, tmptv)-32768); + return RID_JGL; } } *ofsp = 0; @@ -337,10 +340,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) } else { ra_destreg(as, ir, RID_FPRET); } -#if LJ_32 } else if (hiop) { ra_destpair(as, ir); -#endif } else { ra_destreg(as, ir, RID_RET); } @@ -389,6 +390,21 @@ static void asm_retf(ASMState *as, IRIns *ir) emit_tai(as, PPCI_LWZ, RID_TMP, base, -8); } +/* -- Buffer operations --------------------------------------------------- */ + +#if LJ_HASBUFFER +static void asm_bufhdr_write(ASMState *as, Reg sb) +{ + Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb)); + IRIns irgc; + irgc.ot = IRT(0, IRT_PGC); /* GC type. */ + emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L)); + emit_rot(as, PPCI_RLWIMI, RID_TMP, tmp, 0, 31-lj_fls(SBUF_MASK_FLAG), 31); + emit_getgl(as, RID_TMP, cur_L); + emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L)); +} +#endif + /* -- Type conversions ---------------------------------------------------- */ #if !LJ_SOFTFP @@ -567,28 +583,54 @@ static void asm_strto(ASMState *as, IRIns *ir) /* -- Memory references --------------------------------------------------- */ /* Get pointer to TValue. */ -static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) +static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode) { - IRIns *ir = IR(ref); - if (irt_isnum(ir->t)) { - if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ - ra_allockreg(as, i32ptr(ir_knum(ir)), dest); - else /* Otherwise force a spill and use the spill slot. */ - emit_tai(as, PPCI_ADDI, dest, RID_SP, ra_spill(as, ir)); - } else { - /* Otherwise use g->tmptv to hold the TValue. */ - RegSet allow = rset_exclude(RSET_GPR, dest); - Reg type; - emit_tai(as, PPCI_ADDI, dest, RID_JGL, (int32_t)offsetof(global_State, tmptv)-32768); - if (!irt_ispri(ir->t)) { - Reg src = ra_alloc1(as, ref, allow); - emit_setgl(as, src, tmptv.gcr); + int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768); + if ((mode & IRTMPREF_IN1)) { + IRIns *ir = IR(ref); + if (irt_isnum(ir->t)) { + if ((mode & IRTMPREF_OUT1)) { +#if LJ_SOFTFP + lj_assertA(irref_isk(ref), "unsplit FP op"); + emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs); + emit_setgl(as, + ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR), + tmptv.u32.lo); + emit_setgl(as, + ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR), + tmptv.u32.hi); +#else + Reg src = ra_alloc1(as, ref, RSET_FPR); + emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs); + emit_fai(as, PPCI_STFD, src, RID_JGL, tmpofs); +#endif + } else if (irref_isk(ref)) { + /* Use the number constant itself as a TValue. */ + ra_allockreg(as, i32ptr(ir_knum(ir)), dest); + } else { +#if LJ_SOFTFP + lj_assertA(0, "unsplit FP op"); +#else + /* Otherwise force a spill and use the spill slot. */ + emit_tai(as, PPCI_ADDI, dest, RID_SP, ra_spill(as, ir)); +#endif + } + } else { + /* Otherwise use g->tmptv to hold the TValue. */ + Reg type; + emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs); + if (!irt_ispri(ir->t)) { + Reg src = ra_alloc1(as, ref, RSET_GPR); + emit_setgl(as, src, tmptv.gcr); + } + if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)) + type = ra_alloc1(as, ref+1, RSET_GPR); + else + type = ra_allock(as, irt_toitype(ir->t), RSET_GPR); + emit_setgl(as, type, tmptv.it); } - if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) - type = ra_alloc1(as, ref+1, allow); - else - type = ra_allock(as, irt_toitype(ir->t), allow); - emit_setgl(as, type, tmptv.it); + } else { + emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs); } } @@ -894,7 +936,7 @@ static void asm_fload(ASMState *as, IRIns *ir) int32_t ofs; if (ir->op1 == REF_NIL) { /* FLOAD from GG_State with offset. */ idx = RID_JGL; - ofs = (ir->op2 << 2) - 32768; + ofs = (ir->op2 << 2) - 32768 - GG_OFS(g); } else { idx = ra_alloc1(as, ir->op1, RSET_GPR); if (ir->op2 == IRFL_TAB_ARRAY) { @@ -975,6 +1017,10 @@ static void asm_ahuvload(ASMState *as, IRIns *ir) rset_clear(allow, dest); } idx = asm_fuseahuref(as, ir->op1, &ofs, allow); + if (ir->o == IR_VLOAD) { + ofs = ofs != AHUREF_LSX ? ofs + 8 * ir->op2 : + ir->op2 ? 8 * ir->op2 : AHUREF_LSX; + } if (irt_isnum(t)) { Reg tisnum = ra_allock(as, (int32_t)LJ_TISNUM, rset_exclude(allow, idx)); asm_guardcc(as, CC_GE); @@ -1057,7 +1103,8 @@ static void asm_sload(ASMState *as, IRIns *ir) lj_assertA(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK), "inconsistent SLOAD variant"); lj_assertA(LJ_DUALNUM || - !irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)), + !irt_isint(t) || + (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME|IRSLOAD_KEYINDEX)), "bad SLOAD type"); #if LJ_SOFTFP lj_assertA(!(ir->op2 & IRSLOAD_CONVERT), @@ -1894,15 +1941,15 @@ static void asm_comp64(ASMState *as, IRIns *ir) } #endif -/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */ +/* -- Split register ops -------------------------------------------------- */ -/* Hiword op of a split 64 bit op. Previous op must be the loword op. */ +/* Hiword op of a split 32/32 bit op. Previous op is be the loword op. */ static void asm_hiop(ASMState *as, IRIns *ir) { -#if LJ_HASFFI || LJ_SOFTFP /* HIOP is marked as a store because it needs its own DCE logic. */ int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; +#if LJ_HASFFI || LJ_SOFTFP if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ as->curins--; /* Always skip the CONV. */ #if LJ_HASFFI && !LJ_SOFTFP @@ -1937,12 +1984,16 @@ static void asm_hiop(ASMState *as, IRIns *ir) } return; } +#endif if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ switch ((ir-1)->o) { #if LJ_HASFFI case IR_ADD: as->curins--; asm_add64(as, ir); break; case IR_SUB: as->curins--; asm_sub64(as, ir); break; case IR_NEG: as->curins--; asm_neg64(as, ir); break; + case IR_CNEWI: + /* Nothing to do here. Handled by lo op itself. */ + break; #endif #if LJ_SOFTFP case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: @@ -1950,25 +2001,16 @@ static void asm_hiop(ASMState *as, IRIns *ir) if (!uselo) ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */ break; + case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF: + /* Nothing to do here. Handled by lo op itself. */ + break; #endif - case IR_CALLN: - case IR_CALLS: - case IR_CALLXS: + case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS: if (!uselo) ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ break; -#if LJ_SOFTFP - case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: -#endif - case IR_CNEWI: - /* Nothing to do here. Handled by lo op itself. */ - break; default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break; } -#else - /* Unused without SOFTFP or FFI. */ - UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP"); -#endif } /* -- Profiling ----------------------------------------------------------- */ @@ -2055,6 +2097,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) } else if ((sn & SNAP_SOFTFPNUM)) { type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE)); #endif + } else if ((sn & SNAP_KEYINDEX)) { + type = ra_allock(as, (int32_t)LJ_KEYINDEX, allow); } else { type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); } @@ -2113,6 +2157,12 @@ static void asm_loop_fixup(ASMState *as) } } +/* Fixup the tail of the loop. */ +static void asm_loop_tail_fixup(ASMState *as) +{ + UNUSED(as); /* Nothing to do. */ +} + /* -- Head of trace ------------------------------------------------------- */ /* Coalesce BASE register for a root trace. */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_asm_x86.h b/love/src/jni/LuaJIT-2.1/src/lj_asm_x86.h index 060ed974..5eb18365 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_asm_x86.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_asm_x86.h @@ -216,10 +216,17 @@ static void asm_fuseahuref(ASMState *as, IRRef ref, RegSet allow) #endif } break; + case IR_TMPREF: +#if LJ_GC64 + as->mrm.ofs = (int32_t)dispofs(as, &J2G(as->J)->tmptv); + as->mrm.base = RID_DISPATCH; + as->mrm.idx = RID_NONE; +#else + as->mrm.ofs = igcptr(&J2G(as->J)->tmptv); + as->mrm.base = as->mrm.idx = RID_NONE; +#endif + return; default: - lj_assertA(ir->o == IR_HREF || ir->o == IR_NEWREF || ir->o == IR_UREFO || - ir->o == IR_KKPTR, - "bad IR op %d", ir->o); break; } } @@ -480,6 +487,7 @@ static Reg asm_fuseload(ASMState *as, IRRef ref, RegSet allow) } } else if (ir->o == IR_VLOAD && !(LJ_GC64 && irt_isaddr(ir->t))) { asm_fuseahuref(as, ir->op1, xallow); + as->mrm.ofs += 8 * ir->op2; return RID_MRM; } } @@ -651,7 +659,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) { RegSet drop = RSET_SCRATCH; - int hiop = (LJ_32 && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); + int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); if ((ci->flags & CCI_NOFPRCLOBBER)) drop &= ~RSET_FPR; if (ra_hasreg(ir->r)) @@ -691,10 +699,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) irt_isnum(ir->t) ? XOg_FSTPq : XOg_FSTPd, RID_ESP, ofs); } #endif -#if LJ_32 } else if (hiop) { ra_destpair(as, ir); -#endif } else { lj_assertA(!irt_ispri(ir->t), "PRI dest"); ra_destreg(as, ir, RID_RET); @@ -781,6 +787,21 @@ static void asm_retf(ASMState *as, IRIns *ir) #endif } +/* -- Buffer operations --------------------------------------------------- */ + +#if LJ_HASBUFFER +static void asm_bufhdr_write(ASMState *as, Reg sb) +{ + Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb)); + IRIns irgc; + irgc.ot = IRT(0, IRT_PGC); /* GC type. */ + emit_storeofs(as, &irgc, tmp, sb, offsetof(SBuf, L)); + emit_opgl(as, XO_ARITH(XOg_OR), tmp|REX_GC64, cur_L); + emit_gri(as, XG_ARITHi(XOg_AND), tmp, SBUF_MASK_FLAG); + emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L)); +} +#endif + /* -- Type conversions ---------------------------------------------------- */ static void asm_tointg(ASMState *as, IRIns *ir, Reg left) @@ -924,7 +945,7 @@ static void asm_conv(ASMState *as, IRIns *ir) } } else { Reg dest = ra_dest(as, ir, RSET_GPR); - if (st64) { + if (st64 && !(ir->op2 & IRCONV_NONE)) { Reg left = asm_fuseload(as, lref, RSET_GPR); /* This is either a 32 bit reg/reg mov which zeroes the hiword ** or a load of the loword from a 64 bit address. @@ -1050,47 +1071,48 @@ static void asm_strto(ASMState *as, IRIns *ir) /* -- Memory references --------------------------------------------------- */ /* Get pointer to TValue. */ -static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) +static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode) { - IRIns *ir = IR(ref); - if (irt_isnum(ir->t)) { - /* For numbers use the constant itself or a spill slot as a TValue. */ - if (irref_isk(ref)) - emit_loada(as, dest, ir_knum(ir)); - else - emit_rmro(as, XO_LEA, dest|REX_64, RID_ESP, ra_spill(as, ir)); - } else { - /* Otherwise use g->tmptv to hold the TValue. */ -#if LJ_GC64 - if (irref_isk(ref)) { - TValue k; - lj_ir_kvalue(as->J->L, &k, ir); - emit_movmroi(as, dest, 4, k.u32.hi); - emit_movmroi(as, dest, 0, k.u32.lo); - } else { - /* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */ - Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); - if (irt_is64(ir->t)) { - emit_u32(as, irt_toitype(ir->t) << 15); - emit_rmro(as, XO_ARITHi, XOg_OR, dest, 4); - } else { - /* Currently, no caller passes integers that might end up here. */ - emit_movmroi(as, dest, 4, (irt_toitype(ir->t) << 15)); + if ((mode & IRTMPREF_IN1)) { + IRIns *ir = IR(ref); + if (irt_isnum(ir->t)) { + if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) { + /* Use the number constant itself as a TValue. */ + emit_loada(as, dest, ir_knum(ir)); + return; + } + emit_rmro(as, XO_MOVSDto, ra_alloc1(as, ref, RSET_FPR), dest, 0); + } else { +#if LJ_GC64 + if (irref_isk(ref)) { + TValue k; + lj_ir_kvalue(as->J->L, &k, ir); + emit_movmroi(as, dest, 4, k.u32.hi); + emit_movmroi(as, dest, 0, k.u32.lo); + } else { + /* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */ + Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); + if (irt_is64(ir->t)) { + emit_u32(as, irt_toitype(ir->t) << 15); + emit_rmro(as, XO_ARITHi, XOg_OR, dest, 4); + } else { + emit_movmroi(as, dest, 4, (irt_toitype(ir->t) << 15)); + } + emit_movtomro(as, REX_64IR(ir, src), dest, 0); } - emit_movtomro(as, REX_64IR(ir, src), dest, 0); - } #else - if (!irref_isk(ref)) { - Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); - emit_movtomro(as, REX_64IR(ir, src), dest, 0); - } else if (!irt_ispri(ir->t)) { - emit_movmroi(as, dest, 0, ir->i); - } - if (!(LJ_64 && irt_islightud(ir->t))) - emit_movmroi(as, dest, 4, irt_toitype(ir->t)); + if (!irref_isk(ref)) { + Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); + emit_movtomro(as, REX_64IR(ir, src), dest, 0); + } else if (!irt_ispri(ir->t)) { + emit_movmroi(as, dest, 0, ir->i); + } + if (!(LJ_64 && irt_islightud(ir->t))) + emit_movmroi(as, dest, 4, irt_toitype(ir->t)); #endif - emit_loada(as, dest, &J2G(as->J)->tmptv); + } } + emit_loada(as, dest, &J2G(as->J)->tmptv); /* g->tmptv holds the TValue(s). */ } static void asm_aref(ASMState *as, IRIns *ir) @@ -1524,6 +1546,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir) Reg dest = asm_load_lightud64(as, ir, 1); if (ra_hasreg(dest)) { asm_fuseahuref(as, ir->op1, RSET_GPR); + if (ir->o == IR_VLOAD) as->mrm.ofs += 8 * ir->op2; emit_mrm(as, XO_MOV, dest|REX_64, RID_MRM); } return; @@ -1533,6 +1556,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir) RegSet allow = irt_isnum(ir->t) ? RSET_FPR : RSET_GPR; Reg dest = ra_dest(as, ir, allow); asm_fuseahuref(as, ir->op1, RSET_GPR); + if (ir->o == IR_VLOAD) as->mrm.ofs += 8 * ir->op2; #if LJ_GC64 if (irt_isaddr(ir->t)) { emit_shifti(as, XOg_SHR|REX_64, dest, 17); @@ -1560,6 +1584,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir) } #endif asm_fuseahuref(as, ir->op1, gpr); + if (ir->o == IR_VLOAD) as->mrm.ofs += 8 * ir->op2; } /* Always do the type check, even if the load result is unused. */ as->mrm.ofs += 4; @@ -1675,7 +1700,8 @@ static void asm_sload(ASMState *as, IRIns *ir) lj_assertA(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK), "inconsistent SLOAD variant"); lj_assertA(LJ_DUALNUM || - !irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)), + !irt_isint(t) || + (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME|IRSLOAD_KEYINDEX)), "bad SLOAD type"); if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) { Reg left = ra_scratch(as, RSET_FPR); @@ -2584,15 +2610,15 @@ static void asm_comp_int64(ASMState *as, IRIns *ir) } #endif -/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */ +/* -- Split register ops -------------------------------------------------- */ -/* Hiword op of a split 64 bit op. Previous op must be the loword op. */ +/* Hiword op of a split 32/32 or 64/64 bit op. Previous op is the loword op. */ static void asm_hiop(ASMState *as, IRIns *ir) { -#if LJ_32 && LJ_HASFFI /* HIOP is marked as a store because it needs its own DCE logic. */ int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; +#if LJ_32 && LJ_HASFFI if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ as->curins--; /* Always skip the CONV. */ if (usehi || uselo) @@ -2606,8 +2632,10 @@ static void asm_hiop(ASMState *as, IRIns *ir) asm_fxstore(as, ir); return; } +#endif if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ switch ((ir-1)->o) { +#if LJ_32 && LJ_HASFFI case IR_ADD: as->flagmcp = NULL; as->curins--; @@ -2630,20 +2658,16 @@ static void asm_hiop(ASMState *as, IRIns *ir) asm_neg_not(as, ir-1, XOg_NEG); break; } - case IR_CALLN: - case IR_CALLXS: - if (!uselo) - ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ - break; case IR_CNEWI: /* Nothing to do here. Handled by CNEWI itself. */ break; +#endif + case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS: + if (!uselo) + ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ + break; default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break; } -#else - /* Unused on x64 or without FFI. */ - UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP"); -#endif } /* -- Profiling ----------------------------------------------------------- */ @@ -2704,7 +2728,15 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) IRIns *ir = IR(ref); if ((sn & SNAP_NORESTORE)) continue; - if (irt_isnum(ir->t)) { + if ((sn & SNAP_KEYINDEX)) { + emit_movmroi(as, RID_BASE, ofs+4, LJ_KEYINDEX); + if (irref_isk(ref)) { + emit_movmroi(as, RID_BASE, ofs, ir->i); + } else { + Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, RID_BASE)); + emit_movtomro(as, src, RID_BASE, ofs); + } + } else if (irt_isnum(ir->t)) { Reg src = ra_alloc1(as, ref, RSET_FPR); emit_rmro(as, XO_MOVSDto, src, RID_BASE, ofs); } else { @@ -2837,6 +2869,12 @@ static void asm_loop_fixup(ASMState *as) } } +/* Fixup the tail of the loop. */ +static void asm_loop_tail_fixup(ASMState *as) +{ + UNUSED(as); /* Nothing to do. */ +} + /* -- Head of trace ------------------------------------------------------- */ /* Coalesce BASE register for a root trace. */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_bcread.c b/love/src/jni/LuaJIT-2.1/src/lj_bcread.c index 047f98df..298e6c45 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_bcread.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_bcread.c @@ -53,11 +53,11 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need) do { const char *buf; size_t sz; - char *p = sbufB(&ls->sb); + char *p = ls->sb.b; MSize n = (MSize)(ls->pe - ls->p); if (n) { /* Copy remainder to buffer. */ if (sbuflen(&ls->sb)) { /* Move down in buffer. */ - lj_assertLS(ls->pe == sbufP(&ls->sb), "bad buffer pointer"); + lj_assertLS(ls->pe == ls->sb.w, "bad buffer pointer"); if (ls->p != p) memmove(p, ls->p, n); } else { /* Copy from buffer provided by reader. */ p = lj_buf_need(&ls->sb, len); @@ -66,7 +66,7 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need) ls->p = p; ls->pe = p + n; } - setsbufP(&ls->sb, p + n); + ls->sb.w = p + n; buf = ls->rfunc(ls->L, ls->rdata, &sz); /* Get more data from reader. */ if (buf == NULL || sz == 0) { /* EOF? */ if (need) bcread_error(ls, LJ_ERR_BCBAD); @@ -77,8 +77,8 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need) if (n) { /* Append to buffer. */ n += (MSize)sz; p = lj_buf_need(&ls->sb, n < len ? len : n); - memcpy(sbufP(&ls->sb), buf, sz); - setsbufP(&ls->sb, p + n); + memcpy(ls->sb.w, buf, sz); + ls->sb.w = p + n; ls->p = p; ls->pe = p + n; } else { /* Return buffer provided by reader. */ @@ -399,11 +399,7 @@ static int bcread_header(LexState *ls) if ((flags & BCDUMP_F_FFI)) { #if LJ_HASFFI lua_State *L = ls->L; - if (!ctype_ctsG(G(L))) { - ptrdiff_t oldtop = savestack(L, L->top); - luaopen_ffi(L); /* Load FFI library on-demand. */ - L->top = restorestack(L, oldtop); - } + ctype_loadffi(L); #else return 0; #endif diff --git a/love/src/jni/LuaJIT-2.1/src/lj_bcwrite.c b/love/src/jni/LuaJIT-2.1/src/lj_bcwrite.c index 7580a8ea..c5c042e0 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_bcwrite.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_bcwrite.c @@ -62,7 +62,7 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow) if (num == (lua_Number)k) { /* -0 is never a constant. */ *p++ = BCDUMP_KTAB_INT; p = lj_strfmt_wuleb128(p, k); - setsbufP(&ctx->sb, p); + ctx->sb.w = p; return; } } @@ -73,7 +73,7 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow) lj_assertBCW(tvispri(o), "unhandled type %d", itype(o)); *p++ = BCDUMP_KTAB_NIL+~itype(o); } - setsbufP(&ctx->sb, p); + ctx->sb.w = p; } /* Write a template table. */ @@ -97,7 +97,7 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t) /* Write number of array slots and hash slots. */ p = lj_strfmt_wuleb128(p, narray); p = lj_strfmt_wuleb128(p, nhash); - setsbufP(&ctx->sb, p); + ctx->sb.w = p; if (narray) { /* Write array entries (may contain nil). */ MSize i; TValue *o = tvref(t->array); @@ -172,7 +172,7 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt) } #endif } - setsbufP(&ctx->sb, p); + ctx->sb.w = p; } } @@ -206,7 +206,7 @@ static void bcwrite_knum(BCWriteCtx *ctx, GCproto *pt) p = lj_strfmt_wuleb128(p, o->u32.hi); } } - setsbufP(&ctx->sb, p); + ctx->sb.w = p; } /* Write bytecode instructions. */ @@ -281,7 +281,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) /* Write bytecode instructions and upvalue refs. */ p = bcwrite_bytecode(ctx, p, pt); p = lj_buf_wmem(p, proto_uv(pt), pt->sizeuv*2); - setsbufP(&ctx->sb, p); + ctx->sb.w = p; /* Write constants. */ bcwrite_kgc(ctx, pt); @@ -291,16 +291,16 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) if (sizedbg) { p = lj_buf_more(&ctx->sb, sizedbg); p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg); - setsbufP(&ctx->sb, p); + ctx->sb.w = p; } /* Pass buffer to writer function. */ if (ctx->status == 0) { MSize n = sbuflen(&ctx->sb) - 5; MSize nn = (lj_fls(n)+8)*9 >> 6; - char *q = sbufB(&ctx->sb) + (5 - nn); + char *q = ctx->sb.b + (5 - nn); p = lj_strfmt_wuleb128(q, n); /* Fill in final size. */ - lj_assertBCW(p == sbufB(&ctx->sb) + 5, "bad ULEB128 write"); + lj_assertBCW(p == ctx->sb.b + 5, "bad ULEB128 write"); ctx->status = ctx->wfunc(sbufL(&ctx->sb), q, nn+n, ctx->wdata); } } @@ -324,8 +324,8 @@ static void bcwrite_header(BCWriteCtx *ctx) p = lj_strfmt_wuleb128(p, len); p = lj_buf_wmem(p, name, len); } - ctx->status = ctx->wfunc(sbufL(&ctx->sb), sbufB(&ctx->sb), - (MSize)(p - sbufB(&ctx->sb)), ctx->wdata); + ctx->status = ctx->wfunc(sbufL(&ctx->sb), ctx->sb.b, + (MSize)(p - ctx->sb.b), ctx->wdata); } /* Write footer of bytecode dump. */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_buf.c b/love/src/jni/LuaJIT-2.1/src/lj_buf.c index 731470f4..d31bd99e 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_buf.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_buf.c @@ -20,12 +20,32 @@ static void buf_grow(SBuf *sb, MSize sz) { MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz; char *b; + GCSize flag; if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF; while (nsz < sz) nsz += nsz; - b = (char *)lj_mem_realloc(sbufL(sb), sbufB(sb), osz, nsz); - setmref(sb->b, b); - setmref(sb->p, b + len); - setmref(sb->e, b + nsz); + flag = sbufflag(sb); + if ((flag & SBUF_FLAG_COW)) { /* Copy-on-write semantics. */ + lj_assertG_(G(sbufL(sb)), sb->w == sb->e, "bad SBuf COW"); + b = (char *)lj_mem_new(sbufL(sb), nsz); + setsbufflag(sb, flag & ~(GCSize)SBUF_FLAG_COW); + setgcrefnull(sbufX(sb)->cowref); + memcpy(b, sb->b, osz); + } else { + b = (char *)lj_mem_realloc(sbufL(sb), sb->b, osz, nsz); + } + if ((flag & SBUF_FLAG_EXT)) { + sbufX(sb)->r = sbufX(sb)->r - sb->b + b; /* Adjust read pointer, too. */ + } + /* Adjust buffer pointers. */ + sb->b = b; + sb->w = b + len; + sb->e = b + nsz; + if ((flag & SBUF_FLAG_BORROW)) { /* Adjust borrowed buffer pointers. */ + SBuf *bsb = mref(sbufX(sb)->bsb, SBuf); + bsb->b = b; + bsb->w = b + len; + bsb->e = b + nsz; + } } LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz) @@ -34,30 +54,51 @@ LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz) if (LJ_UNLIKELY(sz > LJ_MAX_BUF)) lj_err_mem(sbufL(sb)); buf_grow(sb, sz); - return sbufB(sb); + return sb->b; } LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz) { - MSize len = sbuflen(sb); - lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow"); - if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF)) - lj_err_mem(sbufL(sb)); - buf_grow(sb, len + sz); - return sbufP(sb); + if (sbufisext(sb)) { + SBufExt *sbx = (SBufExt *)sb; + MSize len = sbufxlen(sbx); + if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF)) + lj_err_mem(sbufL(sbx)); + if (len + sz > sbufsz(sbx)) { /* Must grow. */ + buf_grow((SBuf *)sbx, len + sz); + } else if (sbufxslack(sbx) < (sbufsz(sbx) >> 3)) { + /* Also grow to avoid excessive compactions, if slack < size/8. */ + buf_grow((SBuf *)sbx, sbuflen(sbx) + sz); /* Not sbufxlen! */ + return sbx->w; + } + if (sbx->r != sbx->b) { /* Compact by moving down. */ + memmove(sbx->b, sbx->r, len); + sbx->r = sbx->b; + sbx->w = sbx->b + len; + lj_assertG_(G(sbufL(sbx)), len + sz <= sbufsz(sbx), "bad SBuf compact"); + } + } else { + MSize len = sbuflen(sb); + lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow"); + if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF)) + lj_err_mem(sbufL(sb)); + buf_grow(sb, len + sz); + } + return sb->w; } void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb) { - char *b = sbufB(sb); - MSize osz = (MSize)(sbufE(sb) - b); + char *b = sb->b; + MSize osz = (MSize)(sb->e - b); if (osz > 2*LJ_MIN_SBUF) { - MSize n = (MSize)(sbufP(sb) - b); + MSize n = (MSize)(sb->w - b); b = lj_mem_realloc(L, b, osz, (osz >> 1)); - setmref(sb->b, b); - setmref(sb->p, b + n); - setmref(sb->e, b + (osz >> 1)); + sb->b = b; + sb->w = b + n; + sb->e = b + (osz >> 1); } + lj_assertG_(G(sbufL(sb)), !sbufisext(sb), "YAGNI shrink SBufExt"); } char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz) @@ -67,30 +108,62 @@ char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz) return lj_buf_need(sb, sz); } +#if LJ_HASBUFFER && LJ_HASJIT +void lj_bufx_set(SBufExt *sbx, const char *p, MSize len, GCobj *ref) +{ + lua_State *L = sbufL(sbx); + lj_bufx_free(L, sbx); + lj_bufx_set_cow(L, sbx, p, len); + setgcref(sbx->cowref, ref); + lj_gc_objbarrier(L, (GCudata *)sbx - 1, ref); +} + +#if LJ_HASFFI +MSize LJ_FASTCALL lj_bufx_more(SBufExt *sbx, MSize sz) +{ + lj_buf_more((SBuf *)sbx, sz); + return sbufleft(sbx); +} +#endif +#endif + /* -- Low-level buffer put operations ------------------------------------- */ SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len) { - char *p = lj_buf_more(sb, len); - p = lj_buf_wmem(p, q, len); - setsbufP(sb, p); + char *w = lj_buf_more(sb, len); + w = lj_buf_wmem(w, q, len); + sb->w = w; + return sb; +} + +#if LJ_HASJIT || LJ_HASFFI +static LJ_NOINLINE SBuf * LJ_FASTCALL lj_buf_putchar2(SBuf *sb, int c) +{ + char *w = lj_buf_more2(sb, 1); + *w++ = (char)c; + sb->w = w; return sb; } SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c) { - char *p = lj_buf_more(sb, 1); - *p++ = (char)c; - setsbufP(sb, p); - return sb; + char *w = sb->w; + if (LJ_LIKELY(w < sb->e)) { + *w++ = (char)c; + sb->w = w; + return sb; + } + return lj_buf_putchar2(sb, c); } +#endif SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s) { MSize len = s->len; - char *p = lj_buf_more(sb, len); - p = lj_buf_wmem(p, strdata(s), len); - setsbufP(sb, p); + char *w = lj_buf_more(sb, len); + w = lj_buf_wmem(w, strdata(s), len); + sb->w = w; return sb; } @@ -99,47 +172,47 @@ SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s) SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s) { MSize len = s->len; - char *p = lj_buf_more(sb, len), *e = p+len; + char *w = lj_buf_more(sb, len), *e = w+len; const char *q = strdata(s)+len-1; - while (p < e) - *p++ = *q--; - setsbufP(sb, p); + while (w < e) + *w++ = *q--; + sb->w = w; return sb; } SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s) { MSize len = s->len; - char *p = lj_buf_more(sb, len), *e = p+len; + char *w = lj_buf_more(sb, len), *e = w+len; const char *q = strdata(s); - for (; p < e; p++, q++) { + for (; w < e; w++, q++) { uint32_t c = *(unsigned char *)q; #if LJ_TARGET_PPC - *p = c + ((c >= 'A' && c <= 'Z') << 5); + *w = c + ((c >= 'A' && c <= 'Z') << 5); #else if (c >= 'A' && c <= 'Z') c += 0x20; - *p = c; + *w = c; #endif } - setsbufP(sb, p); + sb->w = w; return sb; } SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s) { MSize len = s->len; - char *p = lj_buf_more(sb, len), *e = p+len; + char *w = lj_buf_more(sb, len), *e = w+len; const char *q = strdata(s); - for (; p < e; p++, q++) { + for (; w < e; w++, q++) { uint32_t c = *(unsigned char *)q; #if LJ_TARGET_PPC - *p = c - ((c >= 'a' && c <= 'z') << 5); + *w = c - ((c >= 'a' && c <= 'z') << 5); #else if (c >= 'a' && c <= 'z') c -= 0x20; - *p = c; + *w = c; #endif } - setsbufP(sb, p); + sb->w = w; return sb; } @@ -148,21 +221,21 @@ SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep) MSize len = s->len; if (rep > 0 && len) { uint64_t tlen = (uint64_t)rep * len; - char *p; + char *w; if (LJ_UNLIKELY(tlen > LJ_MAX_STR)) lj_err_mem(sbufL(sb)); - p = lj_buf_more(sb, (MSize)tlen); + w = lj_buf_more(sb, (MSize)tlen); if (len == 1) { /* Optimize a common case. */ uint32_t c = strdata(s)[0]; - do { *p++ = c; } while (--rep > 0); + do { *w++ = c; } while (--rep > 0); } else { const char *e = strdata(s) + len; do { const char *q = strdata(s); - do { *p++ = *q++; } while (q < e); + do { *w++ = *q++; } while (q < e); } while (--rep > 0); } - setsbufP(sb, p); + sb->w = w; } return sb; } @@ -173,27 +246,27 @@ SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, int32_t i, int32_t e) if (i <= e) { for (;;) { cTValue *o = lj_tab_getint(t, i); - char *p; + char *w; if (!o) { badtype: /* Error: bad element type. */ - setsbufP(sb, (void *)(intptr_t)i); /* Store failing index. */ + sb->w = (char *)(intptr_t)i; /* Store failing index. */ return NULL; } else if (tvisstr(o)) { MSize len = strV(o)->len; - p = lj_buf_wmem(lj_buf_more(sb, len + seplen), strVdata(o), len); + w = lj_buf_wmem(lj_buf_more(sb, len + seplen), strVdata(o), len); } else if (tvisint(o)) { - p = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT+seplen), intV(o)); + w = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT+seplen), intV(o)); } else if (tvisnum(o)) { - p = lj_buf_more(lj_strfmt_putfnum(sb, STRFMT_G14, numV(o)), seplen); + w = lj_buf_more(lj_strfmt_putfnum(sb, STRFMT_G14, numV(o)), seplen); } else { goto badtype; } if (i++ == e) { - setsbufP(sb, p); + sb->w = w; break; } - if (seplen) p = lj_buf_wmem(p, strdata(sep), seplen); - setsbufP(sb, p); + if (seplen) w = lj_buf_wmem(w, strdata(sep), seplen); + sb->w = w; } } return sb; @@ -203,7 +276,7 @@ SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, int32_t i, int32_t e) GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb) { - return lj_str_new(sbufL(sb), sbufB(sb), sbuflen(sb)); + return lj_str_new(sbufL(sb), sb->b, sbuflen(sb)); } /* Concatenate two strings. */ @@ -219,14 +292,14 @@ GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2) /* Read ULEB128 from buffer. */ uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp) { - const uint8_t *p = (const uint8_t *)*pp; - uint32_t v = *p++; + const uint8_t *w = (const uint8_t *)*pp; + uint32_t v = *w++; if (LJ_UNLIKELY(v >= 0x80)) { int sh = 0; v &= 0x7f; - do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80); + do { v |= ((*w & 0x7f) << (sh += 7)); } while (*w++ >= 0x80); } - *pp = (const char *)p; + *pp = (const char *)w; return v; } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_buf.h b/love/src/jni/LuaJIT-2.1/src/lj_buf.h index ae875298..e2ac922e 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_buf.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_buf.h @@ -10,16 +10,60 @@ #include "lj_gc.h" #include "lj_str.h" -/* Resizable string buffers. Struct definition in lj_obj.h. */ -#define sbufB(sb) (mref((sb)->b, char)) -#define sbufP(sb) (mref((sb)->p, char)) -#define sbufE(sb) (mref((sb)->e, char)) -#define sbufL(sb) (mref((sb)->L, lua_State)) -#define sbufsz(sb) ((MSize)(sbufE((sb)) - sbufB((sb)))) -#define sbuflen(sb) ((MSize)(sbufP((sb)) - sbufB((sb)))) -#define sbufleft(sb) ((MSize)(sbufE((sb)) - sbufP((sb)))) -#define setsbufP(sb, q) (setmref((sb)->p, (q))) -#define setsbufL(sb, l) (setmref((sb)->L, (l))) +/* Resizable string buffers. */ + +/* The SBuf struct definition is in lj_obj.h: +** char *w; Write pointer. +** char *e; End pointer. +** char *b; Base pointer. +** MRef L; lua_State, used for buffer resizing. Extension bits in 3 LSB. +*/ + +/* Extended string buffer. */ +typedef struct SBufExt { + SBufHeader; + union { + GCRef cowref; /* Copy-on-write object reference. */ + MRef bsb; /* Borrowed string buffer. */ + }; + char *r; /* Read pointer. */ + GCRef dict_str; /* Serialization string dictionary table. */ + GCRef dict_mt; /* Serialization metatable dictionary table. */ + int depth; /* Remaining recursion depth. */ +} SBufExt; + +#define sbufsz(sb) ((MSize)((sb)->e - (sb)->b)) +#define sbuflen(sb) ((MSize)((sb)->w - (sb)->b)) +#define sbufleft(sb) ((MSize)((sb)->e - (sb)->w)) +#define sbufxlen(sbx) ((MSize)((sbx)->w - (sbx)->r)) +#define sbufxslack(sbx) ((MSize)((sbx)->r - (sbx)->b)) + +#define SBUF_MASK_FLAG (7) +#define SBUF_MASK_L (~(GCSize)SBUF_MASK_FLAG) +#define SBUF_FLAG_EXT 1 /* Extended string buffer. */ +#define SBUF_FLAG_COW 2 /* Copy-on-write buffer. */ +#define SBUF_FLAG_BORROW 4 /* Borrowed string buffer. */ + +#define sbufL(sb) \ + ((lua_State *)(void *)(uintptr_t)(mrefu((sb)->L) & SBUF_MASK_L)) +#define setsbufL(sb, l) (setmref((sb)->L, (l))) +#define setsbufXL(sb, l, flag) \ + (setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) + (flag))) +#define setsbufXL_(sb, l) \ + (setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) | (mrefu((sb)->L) & SBUF_MASK_FLAG))) + +#define sbufflag(sb) (mrefu((sb)->L)) +#define sbufisext(sb) (sbufflag((sb)) & SBUF_FLAG_EXT) +#define sbufiscow(sb) (sbufflag((sb)) & SBUF_FLAG_COW) +#define sbufisborrow(sb) (sbufflag((sb)) & SBUF_FLAG_BORROW) +#define sbufiscoworborrow(sb) (sbufflag((sb)) & (SBUF_FLAG_COW|SBUF_FLAG_BORROW)) +#define sbufX(sb) \ + (lj_assertG_(G(sbufL(sb)), sbufisext(sb), "not an SBufExt"), (SBufExt *)(sb)) +#define setsbufflag(sb, flag) (setmrefu((sb)->L, (flag))) + +#define tvisbuf(o) \ + (LJ_HASBUFFER && tvisudata(o) && udataV(o)->udtype == UDTYPE_BUFFER) +#define bufV(o) check_exp(tvisbuf(o), ((SBufExt *)uddata(udataV(o)))) /* Buffer management */ LJ_FUNC char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz); @@ -30,12 +74,12 @@ LJ_FUNC char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz); static LJ_AINLINE void lj_buf_init(lua_State *L, SBuf *sb) { setsbufL(sb, L); - setmref(sb->p, NULL); setmref(sb->e, NULL); setmref(sb->b, NULL); + sb->w = sb->e = sb->b = NULL; } static LJ_AINLINE void lj_buf_reset(SBuf *sb) { - setmrefr(sb->p, sb->b); + sb->w = sb->b; } static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L) @@ -48,26 +92,77 @@ static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L) static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb) { - lj_mem_free(g, sbufB(sb), sbufsz(sb)); + lj_assertG(!sbufisext(sb), "bad free of SBufExt"); + lj_mem_free(g, sb->b, sbufsz(sb)); } static LJ_AINLINE char *lj_buf_need(SBuf *sb, MSize sz) { if (LJ_UNLIKELY(sz > sbufsz(sb))) return lj_buf_need2(sb, sz); - return sbufB(sb); + return sb->b; } static LJ_AINLINE char *lj_buf_more(SBuf *sb, MSize sz) { if (LJ_UNLIKELY(sz > sbufleft(sb))) return lj_buf_more2(sb, sz); - return sbufP(sb); + return sb->w; } +/* Extended buffer management */ +static LJ_AINLINE void lj_bufx_init(lua_State *L, SBufExt *sbx) +{ + memset(sbx, 0, sizeof(SBufExt)); + setsbufXL(sbx, L, SBUF_FLAG_EXT); +} + +static LJ_AINLINE void lj_bufx_set_borrow(lua_State *L, SBufExt *sbx, SBuf *sb) +{ + setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_BORROW); + setmref(sbx->bsb, sb); + sbx->r = sbx->w = sbx->b = sb->b; + sbx->e = sb->e; +} + +static LJ_AINLINE void lj_bufx_set_cow(lua_State *L, SBufExt *sbx, + const char *p, MSize len) +{ + setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_COW); + sbx->r = sbx->b = (char *)p; + sbx->w = sbx->e = (char *)p + len; +} + +static LJ_AINLINE void lj_bufx_reset(SBufExt *sbx) +{ + if (sbufiscow(sbx)) { + setmrefu(sbx->L, (mrefu(sbx->L) & ~(GCSize)SBUF_FLAG_COW)); + setgcrefnull(sbx->cowref); + sbx->b = sbx->e = NULL; + } + sbx->r = sbx->w = sbx->b; +} + +static LJ_AINLINE void lj_bufx_free(lua_State *L, SBufExt *sbx) +{ + if (!sbufiscoworborrow(sbx)) lj_mem_free(G(L), sbx->b, sbufsz(sbx)); + setsbufXL(sbx, L, SBUF_FLAG_EXT); + setgcrefnull(sbx->cowref); + sbx->r = sbx->w = sbx->b = sbx->e = NULL; +} + +#if LJ_HASBUFFER && LJ_HASJIT +LJ_FUNC void lj_bufx_set(SBufExt *sbx, const char *p, MSize len, GCobj *o); +#if LJ_HASFFI +LJ_FUNC MSize LJ_FASTCALL lj_bufx_more(SBufExt *sbx, MSize sz); +#endif +#endif + /* Low-level buffer put operations */ LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len); +#if LJ_HASJIT || LJ_HASFFI LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c); +#endif LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s); static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len) @@ -77,9 +172,9 @@ static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len) static LJ_AINLINE void lj_buf_putb(SBuf *sb, int c) { - char *p = lj_buf_more(sb, 1); - *p++ = (char)c; - setsbufP(sb, p); + char *w = lj_buf_more(sb, 1); + *w++ = (char)c; + sb->w = w; } /* High-level buffer put operations */ @@ -97,7 +192,7 @@ LJ_FUNC uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp); static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb) { - return lj_str_new(L, sbufB(sb), sbuflen(sb)); + return lj_str_new(L, sb->b, sbuflen(sb)); } #endif diff --git a/love/src/jni/LuaJIT-2.1/src/lj_ccall.c b/love/src/jni/LuaJIT-2.1/src/lj_ccall.c index a91ffc7e..3c029823 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_ccall.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_ccall.c @@ -334,7 +334,7 @@ isfp = sz == 2*sizeof(float) ? 2 : 1; #define CCALL_HANDLE_REGARG \ - if (LJ_TARGET_IOS && isva) { \ + if (LJ_TARGET_OSX && isva) { \ /* IOS: All variadic arguments are on the stack. */ \ } else if (isfp) { /* Try to pass argument in FPRs. */ \ int n2 = ctype_isvector(d->info) ? 1 : \ @@ -345,10 +345,10 @@ goto done; \ } else { \ nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \ - if (LJ_TARGET_IOS && d->size < 8) goto err_nyi; \ + if (LJ_TARGET_OSX && d->size < 8) goto err_nyi; \ } \ } else { /* Try to pass argument in GPRs. */ \ - if (!LJ_TARGET_IOS && (d->info & CTF_ALIGN) > CTALIGN_PTR) \ + if (!LJ_TARGET_OSX && (d->info & CTF_ALIGN) > CTALIGN_PTR) \ ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \ if (ngpr + n <= maxgpr) { \ dp = &cc->gpr[ngpr]; \ @@ -356,7 +356,7 @@ goto done; \ } else { \ ngpr = maxgpr; /* Prevent reordering. */ \ - if (LJ_TARGET_IOS && d->size < 8) goto err_nyi; \ + if (LJ_TARGET_OSX && d->size < 8) goto err_nyi; \ } \ } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_ccallback.c b/love/src/jni/LuaJIT-2.1/src/lj_ccallback.c index 9de86258..80d738c6 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_ccallback.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_ccallback.c @@ -256,6 +256,11 @@ static void *callback_mcode_init(global_State *g, uint32_t *page) #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif +#ifdef PROT_MPROTECT +#define CCPROT_CREATE (PROT_MPROTECT(PROT_EXEC)) +#else +#define CCPROT_CREATE 0 +#endif #endif @@ -271,7 +276,7 @@ static void callback_mcode_new(CTState *cts) if (!p) lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV); #elif LJ_TARGET_POSIX - p = mmap(NULL, sz, (PROT_READ|PROT_WRITE), MAP_PRIVATE|MAP_ANONYMOUS, + p = mmap(NULL, sz, (PROT_READ|PROT_WRITE|CCPROT_CREATE), MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (p == MAP_FAILED) lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV); @@ -409,7 +414,7 @@ void lj_ccallback_mcode_free(CTState *cts) nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \ } \ } else { \ - if (!LJ_TARGET_IOS && n > 1) \ + if (!LJ_TARGET_OSX && n > 1) \ ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \ if (ngpr + n <= maxgpr) { \ sp = &cts->cb.gpr[ngpr]; \ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_cconv.c b/love/src/jni/LuaJIT-2.1/src/lj_cconv.c index 353786b9..613f66e2 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_cconv.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_cconv.c @@ -8,6 +8,7 @@ #if LJ_HASFFI #include "lj_err.h" +#include "lj_buf.h" #include "lj_tab.h" #include "lj_ctype.h" #include "lj_cdata.h" @@ -568,7 +569,9 @@ void lj_cconv_ct_tv(CTState *cts, CType *d, } s = ctype_raw(cts, sid); if (ctype_isfunc(s->info)) { + CTypeID did = ctype_typeid(cts, d); sid = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|sid), CTSIZE_PTR); + d = ctype_get(cts, did); /* cts->tab may have been reallocated. */ } else { if (ctype_isenum(s->info)) s = ctype_child(cts, s); goto doconv; @@ -619,6 +622,8 @@ void lj_cconv_ct_tv(CTState *cts, CType *d, tmpptr = uddata(ud); if (ud->udtype == UDTYPE_IO_FILE) tmpptr = *(void **)tmpptr; + else if (ud->udtype == UDTYPE_BUFFER) + tmpptr = ((SBufExt *)tmpptr)->r; } else if (tvislightud(o)) { tmpptr = lightudV(cts->g, o); } else if (tvisfunc(o)) { diff --git a/love/src/jni/LuaJIT-2.1/src/lj_cparse.c b/love/src/jni/LuaJIT-2.1/src/lj_cparse.c index 16a1d7b7..efe80759 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_cparse.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_cparse.c @@ -133,9 +133,9 @@ LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...) tokstr = NULL; } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || tok >= CTOK_FIRSTDECL) { - if (sbufP(&cp->sb) == sbufB(&cp->sb)) cp_save(cp, '$'); + if (cp->sb.w == cp->sb.b) cp_save(cp, '$'); cp_save(cp, '\0'); - tokstr = sbufB(&cp->sb); + tokstr = cp->sb.b; } else { tokstr = cp_tok2str(cp, tok); } @@ -175,7 +175,7 @@ static CPToken cp_number(CPState *cp) TValue o; do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); cp_save(cp, '\0'); - fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), sbuflen(&cp->sb)-1, + fmt = lj_strscan_scan((const uint8_t *)(cp->sb.b), sbuflen(&cp->sb)-1, &o, STRSCAN_OPT_C); if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32; else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32; @@ -279,7 +279,7 @@ static CPToken cp_string(CPState *cp) return CTOK_STRING; } else { if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\''); - cp->val.i32 = (int32_t)(char)*sbufB(&cp->sb); + cp->val.i32 = (int32_t)(char)*cp->sb.b; cp->val.id = CTID_INT32; return CTOK_INTEGER; } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_crecord.c b/love/src/jni/LuaJIT-2.1/src/lj_crecord.c index c7b60b3a..165f95d9 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_crecord.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_crecord.c @@ -78,7 +78,7 @@ static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o) /* Specialize to the string containing the C type declaration. */ emitir(IRTG(IR_EQ, IRT_STR), tr, lj_ir_kstr(J, s)); cp.L = J->L; - cp.cts = ctype_ctsG(J2G(J)); + cp.cts = ctype_cts(J->L); oldtop = cp.cts->top; cp.srcname = strdata(s); cp.p = strdata(s); @@ -616,10 +616,12 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval) sp = lj_ir_kptr(J, NULL); } else if (tref_isudata(sp)) { GCudata *ud = udataV(sval); - if (ud->udtype == UDTYPE_IO_FILE) { + if (ud->udtype == UDTYPE_IO_FILE || ud->udtype == UDTYPE_BUFFER) { TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), sp, IRFL_UDATA_UDTYPE); - emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, UDTYPE_IO_FILE)); - sp = emitir(IRT(IR_FLOAD, IRT_PTR), sp, IRFL_UDATA_FILE); + emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, ud->udtype)); + sp = emitir(IRT(IR_FLOAD, IRT_PTR), sp, + ud->udtype == UDTYPE_IO_FILE ? IRFL_UDATA_FILE : + IRFL_SBUF_R); } else { sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCudata))); } @@ -1024,8 +1026,26 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) crec_ct_tv(J, dc, dp, sp, sval); } } else if (ctype_isstruct(d->info)) { - CTypeID fid = d->sib; + CTypeID fid; MSize i = 1; + if (!J->base[1]) { /* Handle zero-fill of struct-of-NYI. */ + fid = d->sib; + while (fid) { + CType *df = ctype_get(cts, fid); + fid = df->sib; + if (ctype_isfield(df->info)) { + CType *dc; + if (!gcref(df->name)) continue; /* Ignore unnamed fields. */ + dc = ctype_rawchild(cts, df); /* Field type. */ + if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info) || + ctype_isenum(dc->info))) + goto special; + } else if (!ctype_isconstval(df->info)) { + goto special; + } + } + } + fid = d->sib; while (fid) { CType *df = ctype_get(cts, fid); fid = df->sib; @@ -1893,6 +1913,30 @@ void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd) } } +TRef lj_crecord_loadiu64(jit_State *J, TRef tr, cTValue *o) +{ + CTypeID id = argv2cdata(J, tr, o)->ctypeid; + if (!(id == CTID_INT64 || id == CTID_UINT64)) + lj_trace_err(J, LJ_TRERR_BADTYPE); + lj_needsplit(J); + return emitir(IRT(IR_FLOAD, id == CTID_INT64 ? IRT_I64 : IRT_U64), tr, + IRFL_CDATA_INT64); +} + +#if LJ_HASBUFFER +TRef lj_crecord_topcvoid(jit_State *J, TRef tr, cTValue *o) +{ + CTState *cts = ctype_ctsG(J2G(J)); + if (!tref_iscdata(tr)) lj_trace_err(J, LJ_TRERR_BADTYPE); + return crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, tr, o); +} + +TRef lj_crecord_topuint8(jit_State *J, TRef tr) +{ + return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, CTID_P_UINT8), tr); +} +#endif + #undef IR #undef emitir #undef emitconv diff --git a/love/src/jni/LuaJIT-2.1/src/lj_crecord.h b/love/src/jni/LuaJIT-2.1/src/lj_crecord.h index c6f39a67..e1a2d9c0 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_crecord.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_crecord.h @@ -33,6 +33,11 @@ LJ_FUNC int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd); LJ_FUNC TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr); LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); +LJ_FUNC TRef lj_crecord_loadiu64(jit_State *J, TRef tr, cTValue *o); +#if LJ_HASBUFFER +LJ_FUNC TRef lj_crecord_topcvoid(jit_State *J, TRef tr, cTValue *o); +LJ_FUNC TRef lj_crecord_topuint8(jit_State *J, TRef tr); +#endif #endif #endif diff --git a/love/src/jni/LuaJIT-2.1/src/lj_ctype.c b/love/src/jni/LuaJIT-2.1/src/lj_ctype.c index 4e913556..6741437c 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_ctype.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_ctype.c @@ -583,7 +583,7 @@ GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size) lj_strfmt_putfnum(sb, STRFMT_G14, re.n); if (!(im.u32.hi & 0x80000000u) || im.n != im.n) lj_buf_putchar(sb, '+'); lj_strfmt_putfnum(sb, STRFMT_G14, im.n); - lj_buf_putchar(sb, sbufP(sb)[-1] >= 'a' ? 'I' : 'i'); + lj_buf_putchar(sb, sb->w[-1] >= 'a' ? 'I' : 'i'); return lj_buf_str(L, sb); } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_ctype.h b/love/src/jni/LuaJIT-2.1/src/lj_ctype.h index 49ec71da..700250df 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_ctype.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_ctype.h @@ -298,6 +298,7 @@ typedef struct CTState { _(P_VOID, CTSIZE_PTR, CT_PTR, CTALIGN_PTR|CTID_VOID) \ _(P_CVOID, CTSIZE_PTR, CT_PTR, CTALIGN_PTR|CTID_CVOID) \ _(P_CCHAR, CTSIZE_PTR, CT_PTR, CTALIGN_PTR|CTID_CCHAR) \ + _(P_UINT8, CTSIZE_PTR, CT_PTR, CTALIGN_PTR|CTID_UINT8) \ _(A_CCHAR, -1, CT_ARRAY, CTF_CONST|CTALIGN(0)|CTID_CCHAR) \ _(CTYPEID, 4, CT_ENUM, CTALIGN(2)|CTID_INT32) \ CTTYDEFP(_) \ @@ -389,6 +390,16 @@ static LJ_AINLINE CTState *ctype_cts(lua_State *L) return cts; } +/* Load FFI library on-demand. */ +#define ctype_loadffi(L) \ + do { \ + if (!ctype_ctsG(G(L))) { \ + ptrdiff_t oldtop = (char *)L->top - mref(L->stack, char); \ + luaopen_ffi(L); \ + L->top = (TValue *)(mref(L->stack, char) + oldtop); \ + } \ + } while (0) + /* Save and restore state of C type table. */ #define LJ_CTYPE_SAVE(cts) CTState savects_ = *(cts) #define LJ_CTYPE_RESTORE(cts) \ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_debug.c b/love/src/jni/LuaJIT-2.1/src/lj_debug.c index 0b4e2c87..3dffad90 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_debug.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_debug.c @@ -648,7 +648,7 @@ void lj_debug_dumpstack(lua_State *L, SBuf *sb, const char *fmt, int depth) level += dir; } if (lastlen) - setsbufP(sb, sbufB(sb) + lastlen); /* Zap trailing separator. */ + sb->w = sb->b + lastlen; /* Zap trailing separator. */ } #endif diff --git a/love/src/jni/LuaJIT-2.1/src/lj_dispatch.c b/love/src/jni/LuaJIT-2.1/src/lj_dispatch.c index bf8d8812..7b73d3dd 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_dispatch.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_dispatch.c @@ -68,6 +68,8 @@ void lj_dispatch_init(GG_State *GG) /* The JIT engine is off by default. luaopen_jit() turns it on. */ disp[BC_FORL] = disp[BC_IFORL]; disp[BC_ITERL] = disp[BC_IITERL]; + /* Workaround for stable v2.1 bytecode. TODO: Replace with BC_IITERN. */ + disp[BC_ITERN] = &lj_vm_IITERN; disp[BC_LOOP] = disp[BC_ILOOP]; disp[BC_FUNCF] = disp[BC_IFUNCF]; disp[BC_FUNCV] = disp[BC_IFUNCV]; @@ -118,19 +120,21 @@ void lj_dispatch_update(global_State *g) mode |= (g->hookmask & LUA_MASKRET) ? DISPMODE_RET : 0; if (oldmode != mode) { /* Mode changed? */ ASMFunction *disp = G2GG(g)->dispatch; - ASMFunction f_forl, f_iterl, f_loop, f_funcf, f_funcv; + ASMFunction f_forl, f_iterl, f_itern, f_loop, f_funcf, f_funcv; g->dispatchmode = mode; /* Hotcount if JIT is on, but not while recording. */ if ((mode & (DISPMODE_JIT|DISPMODE_REC)) == DISPMODE_JIT) { f_forl = makeasmfunc(lj_bc_ofs[BC_FORL]); f_iterl = makeasmfunc(lj_bc_ofs[BC_ITERL]); + f_itern = makeasmfunc(lj_bc_ofs[BC_ITERN]); f_loop = makeasmfunc(lj_bc_ofs[BC_LOOP]); f_funcf = makeasmfunc(lj_bc_ofs[BC_FUNCF]); f_funcv = makeasmfunc(lj_bc_ofs[BC_FUNCV]); } else { /* Otherwise use the non-hotcounting instructions. */ f_forl = disp[GG_LEN_DDISP+BC_IFORL]; f_iterl = disp[GG_LEN_DDISP+BC_IITERL]; + f_itern = &lj_vm_IITERN; f_loop = disp[GG_LEN_DDISP+BC_ILOOP]; f_funcf = makeasmfunc(lj_bc_ofs[BC_IFUNCF]); f_funcv = makeasmfunc(lj_bc_ofs[BC_IFUNCV]); @@ -138,6 +142,7 @@ void lj_dispatch_update(global_State *g) /* Init static counting instruction dispatch first (may be copied below). */ disp[GG_LEN_DDISP+BC_FORL] = f_forl; disp[GG_LEN_DDISP+BC_ITERL] = f_iterl; + disp[GG_LEN_DDISP+BC_ITERN] = f_itern; disp[GG_LEN_DDISP+BC_LOOP] = f_loop; /* Set dynamic instruction dispatch. */ @@ -165,6 +170,7 @@ void lj_dispatch_update(global_State *g) /* Otherwise set dynamic counting ins. */ disp[BC_FORL] = f_forl; disp[BC_ITERL] = f_iterl; + disp[BC_ITERN] = f_itern; disp[BC_LOOP] = f_loop; /* Set dynamic return dispatch. */ if ((mode & DISPMODE_RET)) { diff --git a/love/src/jni/LuaJIT-2.1/src/lj_dispatch.h b/love/src/jni/LuaJIT-2.1/src/lj_dispatch.h index be7c410a..2331bd42 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_dispatch.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_dispatch.h @@ -31,7 +31,7 @@ extern double __divdf3(double a, double b); #define SFGOTDEF(_) #endif #if LJ_HASJIT -#define JITGOTDEF(_) _(lj_trace_exit) _(lj_trace_hot) +#define JITGOTDEF(_) _(lj_err_trace) _(lj_trace_exit) _(lj_trace_hot) #else #define JITGOTDEF(_) #endif @@ -46,7 +46,7 @@ extern double __divdf3(double a, double b); _(asin) _(acos) _(atan) _(sinh) _(cosh) _(tanh) _(frexp) _(modf) _(atan2) \ _(pow) _(fmod) _(ldexp) _(lj_vm_modi) \ _(lj_dispatch_call) _(lj_dispatch_ins) _(lj_dispatch_stitch) \ - _(lj_dispatch_profile) _(lj_err_throw) _(lj_err_run) \ + _(lj_dispatch_profile) _(lj_err_throw) \ _(lj_ffh_coroutine_wrap_err) _(lj_func_closeuv) _(lj_func_newL_gc) \ _(lj_gc_barrieruv) _(lj_gc_step) _(lj_gc_step_fixtop) _(lj_meta_arith) \ _(lj_meta_call) _(lj_meta_cat) _(lj_meta_comp) _(lj_meta_equal) \ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_emit_arm64.h b/love/src/jni/LuaJIT-2.1/src/lj_emit_arm64.h index abc32be7..00086e8a 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_emit_arm64.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_emit_arm64.h @@ -163,7 +163,7 @@ nopair: /* Try to find an N-step delta relative to other consts with N < lim. */ static int emit_kdelta(ASMState *as, Reg rd, uint64_t k, int lim) { - RegSet work = ~as->freeset & RSET_GPR; + RegSet work = (~as->freeset & RSET_GPR) | RID2RSET(RID_GL); if (lim <= 1) return 0; /* Can't beat that. */ while (work) { Reg r = rset_picktop(work); @@ -194,39 +194,41 @@ static int emit_kdelta(ASMState *as, Reg rd, uint64_t k, int lim) static void emit_loadk(ASMState *as, Reg rd, uint64_t u64, int is64) { - uint32_t k13 = emit_isk13(u64, is64); - if (k13) { /* Can the constant be represented as a bitmask immediate? */ - emit_dn(as, (is64|A64I_ORRw)^k13, rd, RID_ZERO); - } else { - int i, zeros = 0, ones = 0, neg; - if (!is64) u64 = (int64_t)(int32_t)u64; /* Sign-extend. */ - /* Count homogeneous 16 bit fragments. */ - for (i = 0; i < 4; i++) { - uint64_t frag = (u64 >> i*16) & 0xffff; - zeros += (frag == 0); - ones += (frag == 0xffff); + int i, zeros = 0, ones = 0, neg; + if (!is64) u64 = (int64_t)(int32_t)u64; /* Sign-extend. */ + /* Count homogeneous 16 bit fragments. */ + for (i = 0; i < 4; i++) { + uint64_t frag = (u64 >> i*16) & 0xffff; + zeros += (frag == 0); + ones += (frag == 0xffff); + } + neg = ones > zeros; /* Use MOVN if it pays off. */ + if ((neg ? ones : zeros) < 3) { /* Need 2+ ins. Try shorter K13 encoding. */ + uint32_t k13 = emit_isk13(u64, is64); + if (k13) { + emit_dn(as, (is64|A64I_ORRw)^k13, rd, RID_ZERO); + return; } - neg = ones > zeros; /* Use MOVN if it pays off. */ - if (!emit_kdelta(as, rd, u64, 4 - (neg ? ones : zeros))) { - int shift = 0, lshift = 0; - uint64_t n64 = neg ? ~u64 : u64; - if (n64 != 0) { - /* Find first/last fragment to be filled. */ - shift = (63-emit_clz64(n64)) & ~15; - lshift = emit_ctz64(n64) & ~15; - } - /* MOVK requires the original value (u64). */ - while (shift > lshift) { - uint32_t u16 = (u64 >> shift) & 0xffff; - /* Skip fragments that are correctly filled by MOVN/MOVZ. */ - if (u16 != (neg ? 0xffff : 0)) - emit_d(as, is64 | A64I_MOVKw | A64F_U16(u16) | A64F_LSL16(shift), rd); - shift -= 16; - } - /* But MOVN needs an inverted value (n64). */ - emit_d(as, (neg ? A64I_MOVNx : A64I_MOVZx) | - A64F_U16((n64 >> lshift) & 0xffff) | A64F_LSL16(lshift), rd); + } + if (!emit_kdelta(as, rd, u64, 4 - (neg ? ones : zeros))) { + int shift = 0, lshift = 0; + uint64_t n64 = neg ? ~u64 : u64; + if (n64 != 0) { + /* Find first/last fragment to be filled. */ + shift = (63-emit_clz64(n64)) & ~15; + lshift = emit_ctz64(n64) & ~15; } + /* MOVK requires the original value (u64). */ + while (shift > lshift) { + uint32_t u16 = (u64 >> shift) & 0xffff; + /* Skip fragments that are correctly filled by MOVN/MOVZ. */ + if (u16 != (neg ? 0xffff : 0)) + emit_d(as, is64 | A64I_MOVKw | A64F_U16(u16) | A64F_LSL16(shift), rd); + shift -= 16; + } + /* But MOVN needs an inverted value (n64). */ + emit_d(as, (neg ? A64I_MOVNx : A64I_MOVZx) | + A64F_U16((n64 >> lshift) & 0xffff) | A64F_LSL16(lshift), rd); } } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_emit_mips.h b/love/src/jni/LuaJIT-2.1/src/lj_emit_mips.h index 7825eabb..c13615dd 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_emit_mips.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_emit_mips.h @@ -70,7 +70,7 @@ static void emit_rotr(ASMState *as, Reg dest, Reg src, Reg tmp, uint32_t shift) } } -#if LJ_64 +#if LJ_64 || LJ_HASBUFFER static void emit_tsml(ASMState *as, MIPSIns mi, Reg rt, Reg rs, uint32_t msb, uint32_t lsb) { diff --git a/love/src/jni/LuaJIT-2.1/src/lj_err.c b/love/src/jni/LuaJIT-2.1/src/lj_err.c index c0bf38c2..fda4a59c 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_err.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_err.c @@ -29,12 +29,18 @@ ** Pros and Cons: ** ** - EXT requires unwind tables for *all* functions on the C stack between -** the pcall/catch and the error/throw. This is the default on x64, -** but needs to be manually enabled on x86/PPC for non-C++ code. +** the pcall/catch and the error/throw. C modules used by Lua code can +** throw errors, so these need to have unwind tables, too. Transitively +** this applies to all system libraries used by C modules -- at least +** when they have callbacks which may throw an error. ** -** - INT is faster when actually throwing errors (but this happens rarely). +** - INT is faster when actually throwing errors, but this happens rarely. ** Setting up error handlers is zero-cost in any case. ** +** - INT needs to save *all* callee-saved registers when entering the +** interpreter. EXT only needs to save those actually used inside the +** interpreter. JIT-compiled code may need to save some more. +** ** - EXT provides full interoperability with C++ exceptions. You can throw ** Lua errors or C++ exceptions through a mix of Lua frames and C++ frames. ** C++ destructors are called as needed. C++ exceptions caught by pcall @@ -46,27 +52,38 @@ ** the wrapper function feature. Lua errors thrown through C++ frames ** cannot be caught by C++ code and C++ destructors are not run. ** -** EXT is the default on x64 systems and on Windows, INT is the default on all -** other systems. +** - EXT can handle errors from internal helper functions that are called +** from JIT-compiled code (except for Windows/x86 and 32 bit ARM). +** INT has no choice but to call the panic handler, if this happens. +** Note: this is mainly relevant for out-of-memory errors. ** -** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack -** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled -** with -funwind-tables (or -fexceptions). This includes LuaJIT itself (set -** TARGET_CFLAGS), all of your C/Lua binding code, all loadable C modules -** and all C libraries that have callbacks which may be used to call back -** into Lua. C++ code must *not* be compiled with -fno-exceptions. +** EXT is the default on all systems where the toolchain produces unwind +** tables by default (*). This is hard-coded and/or detected in src/Makefile. +** You can thwart the detection with: TARGET_XCFLAGS=-DLUAJIT_UNWIND_INTERNAL ** -** EXT is mandatory on WIN64 since the calling convention has an abundance -** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15). -** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4). +** INT is the default on all other systems. +** +** EXT can be manually enabled for toolchains that are able to produce +** conforming unwind tables: +** "TARGET_XCFLAGS=-funwind-tables -DLUAJIT_UNWIND_EXTERNAL" +** As explained above, *all* C code used directly or indirectly by LuaJIT +** must be compiled with -funwind-tables (or -fexceptions). C++ code must +** *not* be compiled with -fno-exceptions. +** +** If you're unsure whether error handling inside the VM works correctly, +** try running this and check whether it prints "OK": +** +** luajit -e "print(select(2, load('OK')):match('OK'))" +** +** (*) Originally, toolchains only generated unwind tables for C++ code. For +** interoperability reasons, this can be manually enabled for plain C code, +** too (with -funwind-tables). With the introduction of the x64 architecture, +** the corresponding POSIX and Windows ABIs mandated unwind tables for all +** code. Over the following years most desktop and server platforms have +** enabled unwind tables by default on all architectures. OTOH mobile and +** embedded platforms do not consistently mandate unwind tables. */ -#if (defined(__GNUC__) || defined(__clang__)) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND -#define LJ_UNWIND_EXT 1 -#elif LJ_TARGET_WINDOWS -#define LJ_UNWIND_EXT 1 -#endif - /* -- Error messages ------------------------------------------------------ */ /* Error message strings. */ @@ -184,7 +201,172 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) /* -- External frame unwinding -------------------------------------------- */ -#if (defined(__GNUC__) || defined(__clang__)) && !LJ_NO_UNWIND && !LJ_ABI_WIN +#if LJ_ABI_WIN + +/* +** Someone in Redmond owes me several days of my life. A lot of this is +** undocumented or just plain wrong on MSDN. Some of it can be gathered +** from 3rd party docs or must be found by trial-and-error. They really +** don't want you to write your own language-specific exception handler +** or to interact gracefully with MSVC. :-( +** +** Apparently MSVC doesn't call C++ destructors for foreign exceptions +** unless you compile your C++ code with /EHa. Unfortunately this means +** catch (...) also catches things like access violations. The use of +** _set_se_translator doesn't really help, because it requires /EHa, too. +*/ + +#define WIN32_LEAN_AND_MEAN +#include + +#if LJ_TARGET_X86 +typedef void *UndocumentedDispatcherContext; /* Unused on x86. */ +#else +/* Taken from: http://www.nynaeve.net/?p=99 */ +typedef struct UndocumentedDispatcherContext { + ULONG64 ControlPc; + ULONG64 ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + ULONG64 EstablisherFrame; + ULONG64 TargetIp; + PCONTEXT ContextRecord; + void (*LanguageHandler)(void); + PVOID HandlerData; + PUNWIND_HISTORY_TABLE HistoryTable; + ULONG ScopeIndex; + ULONG Fill0; +} UndocumentedDispatcherContext; +#endif + +/* Another wild guess. */ +extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); + +#if LJ_TARGET_X64 && defined(MINGW_SDK_INIT) +/* Workaround for broken MinGW64 declaration. */ +VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); +#define RtlUnwindEx RtlUnwindEx_FIXED +#endif + +#define LJ_MSVC_EXCODE ((DWORD)0xe06d7363) +#define LJ_GCC_EXCODE ((DWORD)0x20474343) + +#define LJ_EXCODE ((DWORD)0xe24c4a00) +#define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c)) +#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) +#define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) + +/* Windows exception handler for interpreter frame. */ +LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, + void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) +{ +#if LJ_TARGET_X86 + void *cf = (char *)f - CFRAME_OFS_SEH; +#else + void *cf = f; +#endif + lua_State *L = cframe_L(cf); + int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? + LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; + if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */ + /* Unwind internal frames. */ + err_unwind(L, cf, errcode); + } else { + void *cf2 = err_unwind(L, cf, 0); + if (cf2) { /* We catch it, so start unwinding the upper frames. */ + if (rec->ExceptionCode == LJ_MSVC_EXCODE || + rec->ExceptionCode == LJ_GCC_EXCODE) { +#if !LJ_TARGET_CYGWIN + __DestructExceptionObject(rec, 1); +#endif + setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); + } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { + /* Don't catch access violations etc. */ + return 1; /* ExceptionContinueSearch */ + } +#if LJ_TARGET_X86 + UNUSED(ctx); + UNUSED(dispatch); + /* Call all handlers for all lower C frames (including ourselves) again + ** with EH_UNWINDING set. Then call the specified function, passing cf + ** and errcode. + */ + lj_vm_rtlunwind(cf, (void *)rec, + (cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? + (void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode); + /* lj_vm_rtlunwind does not return. */ +#else + /* Unwind the stack and call all handlers for all lower C frames + ** (including ourselves) again with EH_UNWINDING set. Then set + ** stack pointer = cf, result = errcode and jump to the specified target. + */ + RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? + lj_vm_unwind_ff_eh : + lj_vm_unwind_c_eh), + rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); + /* RtlUnwindEx should never return. */ +#endif + } + } + return 1; /* ExceptionContinueSearch */ +} + +#if LJ_UNWIND_JIT + +#if LJ_TARGET_X64 +#define CONTEXT_REG_PC Rip +#elif LJ_TARGET_ARM64 +#define CONTEXT_REG_PC Pc +#else +#error "NYI: Windows arch-specific unwinder for JIT-compiled code" +#endif + +/* Windows unwinder for JIT-compiled code. */ +static void err_unwind_win_jit(global_State *g, int errcode) +{ + CONTEXT ctx; + UNWIND_HISTORY_TABLE hist; + + memset(&hist, 0, sizeof(hist)); + RtlCaptureContext(&ctx); + while (1) { + uintptr_t frame, base, addr = ctx.CONTEXT_REG_PC; + void *hdata; + PRUNTIME_FUNCTION func = RtlLookupFunctionEntry(addr, &base, &hist); + if (!func) { /* Found frame without .pdata: must be JIT-compiled code. */ + ExitNo exitno; + uintptr_t stub = lj_trace_unwind(G2J(g), addr - sizeof(MCode), &exitno); + if (stub) { /* Jump to side exit to unwind the trace. */ + ctx.CONTEXT_REG_PC = stub; + G2J(g)->exitcode = errcode; + RtlRestoreContext(&ctx, NULL); /* Does not return. */ + } + break; + } + RtlVirtualUnwind(UNW_FLAG_NHANDLER, base, addr, func, + &ctx, &hdata, &frame, NULL); + if (!addr) break; + } + /* Unwinding failed, if we end up here. */ +} +#endif + +/* Raise Windows exception. */ +static void err_raise_ext(global_State *g, int errcode) +{ +#if LJ_UNWIND_JIT + if (tvref(g->jit_base)) { + err_unwind_win_jit(g, errcode); + return; /* Unwinding failed. */ + } +#elif LJ_HASJIT + /* Cannot catch on-trace errors for Windows/x86 SEH. Unwind to interpreter. */ + setmref(g->jit_base, NULL); +#endif + UNUSED(g); + RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL); +} + +#elif !LJ_NO_UNWIND && (defined(__GNUC__) || defined(__clang__)) /* ** We have to use our own definitions instead of the mandatory (!) unwind.h, @@ -194,6 +376,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) typedef struct _Unwind_Context _Unwind_Context; #define _URC_OK 0 +#define _URC_FATAL_PHASE2_ERROR 2 #define _URC_FATAL_PHASE1_ERROR 3 #define _URC_HANDLER_FOUND 6 #define _URC_INSTALL_CONTEXT 7 @@ -213,9 +396,11 @@ typedef struct _Unwind_Exception void (*excleanup)(int, struct _Unwind_Exception *); uintptr_t p1, p2; } __attribute__((__aligned__)) _Unwind_Exception; +#define UNWIND_EXCEPTION_TYPE _Unwind_Exception extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); +extern uintptr_t _Unwind_GetIP(_Unwind_Context *); extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); extern void _Unwind_DeleteException(_Unwind_Exception *); extern int _Unwind_RaiseException(_Unwind_Exception *); @@ -233,7 +418,6 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, lua_State *L; if (version != 1) return _URC_FATAL_PHASE1_ERROR; - UNUSED(uexclass); cf = (void *)_Unwind_GetCFA(ctx); L = cframe_L(cf); if ((actions & _UA_SEARCH_PHASE)) { @@ -281,20 +465,139 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, ** it on non-x64 because the interpreter restores all callee-saved regs. */ lj_err_throw(L, errcode); +#if LJ_TARGET_X64 +#error "Broken build system -- only use the provided Makefiles!" +#endif #endif } return _URC_CONTINUE_UNWIND; } -#if LJ_UNWIND_EXT -static __thread _Unwind_Exception static_uex; +#if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT) +struct dwarf_eh_bases { void *tbase, *dbase, *func; }; +extern const void *_Unwind_Find_FDE(void *pc, struct dwarf_eh_bases *bases); -/* Raise DWARF2 exception. */ -static void err_raise_ext(int errcode) +/* Verify that external error handling actually has a chance to work. */ +void lj_err_verify(void) { - static_uex.exclass = LJ_UEXCLASS_MAKE(errcode); - static_uex.excleanup = NULL; - _Unwind_RaiseException(&static_uex); + struct dwarf_eh_bases ehb; + lj_assertX(_Unwind_Find_FDE((void *)lj_err_throw, &ehb), "broken build: external frame unwinding enabled, but missing -funwind-tables"); + /* Check disabled, because of broken Fedora/ARM64. See #722. + lj_assertX(_Unwind_Find_FDE((void *)_Unwind_RaiseException, &ehb), "broken build: external frame unwinding enabled, but system libraries have no unwind tables"); + */ +} +#endif + +#if LJ_UNWIND_JIT +/* DWARF2 personality handler for JIT-compiled code. */ +static int err_unwind_jit(int version, int actions, + uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) +{ + /* NYI: FFI C++ exception interoperability. */ + if (version != 1 || !LJ_UEXCLASS_CHECK(uexclass)) + return _URC_FATAL_PHASE1_ERROR; + if ((actions & _UA_SEARCH_PHASE)) { + return _URC_HANDLER_FOUND; + } + if ((actions & _UA_CLEANUP_PHASE)) { + global_State *g = *(global_State **)(uex+1); + ExitNo exitno; + uintptr_t addr = _Unwind_GetIP(ctx); /* Return address _after_ call. */ + uintptr_t stub = lj_trace_unwind(G2J(g), addr - sizeof(MCode), &exitno); + lj_assertG(tvref(g->jit_base), "unexpected throw across mcode frame"); + if (stub) { /* Jump to side exit to unwind the trace. */ + G2J(g)->exitcode = LJ_UEXCLASS_ERRCODE(uexclass); +#ifdef LJ_TARGET_MIPS + _Unwind_SetGR(ctx, 4, stub); + _Unwind_SetGR(ctx, 5, exitno); + _Unwind_SetIP(ctx, (uintptr_t)(void *)lj_vm_unwind_stub); +#else + _Unwind_SetIP(ctx, stub); +#endif + return _URC_INSTALL_CONTEXT; + } + return _URC_FATAL_PHASE2_ERROR; + } + return _URC_FATAL_PHASE1_ERROR; +} + +/* DWARF2 template frame info for JIT-compiled code. +** +** After copying the template to the start of the mcode segment, +** the frame handler function and the code size is patched. +** The frame handler always installs a new context to jump to the exit, +** so don't bother to add any unwind opcodes. +*/ +static const uint8_t err_frame_jit_template[] = { +#if LJ_BE + 0,0,0, +#endif + LJ_64 ? 0x1c : 0x14, /* CIE length. */ +#if LJ_LE + 0,0,0, +#endif + 0,0,0,0, 1, 'z','P','R',0, /* CIE mark, CIE version, augmentation. */ + 1, LJ_64 ? 0x78 : 0x7c, LJ_TARGET_EHRAREG, /* Code/data align, RA. */ +#if LJ_64 + 10, 0, 0,0,0,0,0,0,0,0, 0x1b, /* Aug. data ABS handler, PCREL|SDATA4 code. */ + 0,0,0,0,0, /* Alignment. */ +#else + 6, 0, 0,0,0,0, 0x1b, /* Aug. data ABS handler, PCREL|SDATA4 code. */ + 0, /* Alignment. */ +#endif +#if LJ_BE + 0,0,0, +#endif + LJ_64 ? 0x14 : 0x10, /* FDE length. */ + 0,0,0, + LJ_64 ? 0x24 : 0x1c, /* CIE offset. */ + 0,0,0, + LJ_64 ? 0x14 : 0x10, /* Code offset. After Final FDE. */ +#if LJ_LE + 0,0,0, +#endif + 0,0,0,0, 0, 0,0,0, /* Code size, augmentation length, alignment. */ +#if LJ_64 + 0,0,0,0, /* Alignment. */ +#endif + 0,0,0,0 /* Final FDE. */ +}; + +#define ERR_FRAME_JIT_OFS_HANDLER 0x12 +#define ERR_FRAME_JIT_OFS_FDE (LJ_64 ? 0x20 : 0x18) +#define ERR_FRAME_JIT_OFS_CODE_SIZE (LJ_64 ? 0x2c : 0x24) +#if LJ_TARGET_OSX +#define ERR_FRAME_JIT_OFS_REGISTER ERR_FRAME_JIT_OFS_FDE +#else +#define ERR_FRAME_JIT_OFS_REGISTER 0 +#endif + +extern void __register_frame(const void *); +extern void __deregister_frame(const void *); + +uint8_t *lj_err_register_mcode(void *base, size_t sz, uint8_t *info) +{ + void **handler; + memcpy(info, err_frame_jit_template, sizeof(err_frame_jit_template)); + handler = (void *)err_unwind_jit; + memcpy(info + ERR_FRAME_JIT_OFS_HANDLER, &handler, sizeof(handler)); + *(uint32_t *)(info + ERR_FRAME_JIT_OFS_CODE_SIZE) = + (uint32_t)(sz - sizeof(err_frame_jit_template) - (info - (uint8_t *)base)); + __register_frame(info + ERR_FRAME_JIT_OFS_REGISTER); +#ifdef LUA_USE_ASSERT + { + struct dwarf_eh_bases ehb; + lj_assertX(_Unwind_Find_FDE(info + sizeof(err_frame_jit_template)+1, &ehb), + "bad JIT unwind table registration"); + } +#endif + return info + sizeof(err_frame_jit_template); +} + +void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info) +{ + UNUSED(base); UNUSED(sz); + __deregister_frame(info + ERR_FRAME_JIT_OFS_REGISTER); } #endif @@ -306,6 +609,7 @@ static void err_raise_ext(int errcode) #define _US_FORCE_UNWIND 8 typedef struct _Unwind_Control_Block _Unwind_Control_Block; +#define UNWIND_EXCEPTION_TYPE _Unwind_Control_Block struct _Unwind_Control_Block { uint64_t exclass; @@ -364,136 +668,63 @@ LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb, } if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) return _URC_FAILURE; +#ifdef LUA_USE_ASSERT + /* We should never get here unless this is a forced unwind aka backtrace. */ + if (_Unwind_GetGR(ctx, 0) == 0xff33aa77) { + _Unwind_SetGR(ctx, 0, 0xff33aa88); + } +#endif return _URC_CONTINUE_UNWIND; } -#if LJ_UNWIND_EXT -static __thread _Unwind_Control_Block static_uex; +#if LJ_UNWIND_EXT && defined(LUA_USE_ASSERT) +typedef int (*_Unwind_Trace_Fn)(_Unwind_Context *, void *); +extern int _Unwind_Backtrace(_Unwind_Trace_Fn, void *); -static void err_raise_ext(int errcode) +static int err_verify_bt(_Unwind_Context *ctx, int *got) { - memset(&static_uex, 0, sizeof(static_uex)); - static_uex.exclass = LJ_UEXCLASS_MAKE(errcode); - _Unwind_RaiseException(&static_uex); + if (_Unwind_GetGR(ctx, 0) == 0xff33aa88) { *got = 2; } + else if (*got == 0) { *got = 1; _Unwind_SetGR(ctx, 0, 0xff33aa77); } + return _URC_OK; +} + +/* Verify that external error handling actually has a chance to work. */ +void lj_err_verify(void) +{ + int got = 0; + _Unwind_Backtrace((_Unwind_Trace_Fn)err_verify_bt, &got); + lj_assertX(got == 2, "broken build: external frame unwinding enabled, but missing -funwind-tables"); } #endif +/* +** Note: LJ_UNWIND_JIT is not implemented for 32 bit ARM. +** +** The quirky ARM unwind API doesn't have __register_frame(). +** A potential workaround might involve _Unwind_Backtrace. +** But most 32 bit ARM targets don't qualify for LJ_UNWIND_EXT, anyway, +** since they are built without unwind tables by default. +*/ + #endif /* LJ_TARGET_ARM */ -#elif LJ_ABI_WIN -/* -** Someone in Redmond owes me several days of my life. A lot of this is -** undocumented or just plain wrong on MSDN. Some of it can be gathered -** from 3rd party docs or must be found by trial-and-error. They really -** don't want you to write your own language-specific exception handler -** or to interact gracefully with MSVC. :-( -** -** Apparently MSVC doesn't call C++ destructors for foreign exceptions -** unless you compile your C++ code with /EHa. Unfortunately this means -** catch (...) also catches things like access violations. The use of -** _set_se_translator doesn't really help, because it requires /EHa, too. -*/ +#if LJ_UNWIND_EXT +static __thread struct { + UNWIND_EXCEPTION_TYPE ex; + global_State *g; +} static_uex; -#define WIN32_LEAN_AND_MEAN -#include - -#if LJ_TARGET_X64 -/* Taken from: http://www.nynaeve.net/?p=99 */ -typedef struct UndocumentedDispatcherContext { - ULONG64 ControlPc; - ULONG64 ImageBase; - PRUNTIME_FUNCTION FunctionEntry; - ULONG64 EstablisherFrame; - ULONG64 TargetIp; - PCONTEXT ContextRecord; - void (*LanguageHandler)(void); - PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; - ULONG ScopeIndex; - ULONG Fill0; -} UndocumentedDispatcherContext; -#else -typedef void *UndocumentedDispatcherContext; -#endif - -/* Another wild guess. */ -extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); - -#if LJ_TARGET_X64 && defined(MINGW_SDK_INIT) -/* Workaround for broken MinGW64 declaration. */ -VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); -#define RtlUnwindEx RtlUnwindEx_FIXED -#endif - -#define LJ_MSVC_EXCODE ((DWORD)0xe06d7363) -#define LJ_GCC_EXCODE ((DWORD)0x20474343) - -#define LJ_EXCODE ((DWORD)0xe24c4a00) -#define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c)) -#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) -#define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) - -/* Windows exception handler for interpreter frame. */ -LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec, - void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) +/* Raise external exception. */ +static void err_raise_ext(global_State *g, int errcode) { -#if LJ_TARGET_X64 - void *cf = f; -#else - void *cf = (char *)f - CFRAME_OFS_SEH; -#endif - lua_State *L = cframe_L(cf); - int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? - LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; - if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */ - /* Unwind internal frames. */ - err_unwind(L, cf, errcode); - } else { - void *cf2 = err_unwind(L, cf, 0); - if (cf2) { /* We catch it, so start unwinding the upper frames. */ - if (rec->ExceptionCode == LJ_MSVC_EXCODE || - rec->ExceptionCode == LJ_GCC_EXCODE) { -#if LJ_TARGET_WINDOWS - __DestructExceptionObject(rec, 1); -#endif - setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); - } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { - /* Don't catch access violations etc. */ - return 1; /* ExceptionContinueSearch */ - } -#if LJ_TARGET_X64 - /* Unwind the stack and call all handlers for all lower C frames - ** (including ourselves) again with EH_UNWINDING set. Then set - ** rsp = cf, rax = errcode and jump to the specified target. - */ - RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? - lj_vm_unwind_ff_eh : - lj_vm_unwind_c_eh), - rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); - /* RtlUnwindEx should never return. */ -#else - UNUSED(ctx); - UNUSED(dispatch); - /* Call all handlers for all lower C frames (including ourselves) again - ** with EH_UNWINDING set. Then call the specified function, passing cf - ** and errcode. - */ - lj_vm_rtlunwind(cf, (void *)rec, - (cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? - (void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode); - /* lj_vm_rtlunwind does not return. */ -#endif - } - } - return 1; /* ExceptionContinueSearch */ + memset(&static_uex, 0, sizeof(static_uex)); + static_uex.ex.exclass = LJ_UEXCLASS_MAKE(errcode); + static_uex.g = g; + _Unwind_RaiseException(&static_uex.ex); } -/* Raise Windows exception. */ -static void err_raise_ext(int errcode) -{ - RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL); -} +#endif #endif @@ -504,22 +735,23 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode) { global_State *g = G(L); lj_trace_abort(g); - setmref(g->jit_base, NULL); L->status = LUA_OK; #if LJ_UNWIND_EXT - err_raise_ext(errcode); + err_raise_ext(g, errcode); /* ** A return from this function signals a corrupt C stack that cannot be ** unwound. We have no choice but to call the panic function and exit. ** ** Usually this is caused by a C function without unwind information. - ** This should never happen on x64, but may happen if you've manually - ** enabled LUAJIT_UNWIND_EXTERNAL and forgot to recompile *every* - ** non-C++ file with -funwind-tables. + ** This may happen if you've manually enabled LUAJIT_UNWIND_EXTERNAL + ** and forgot to recompile *every* non-C++ file with -funwind-tables. */ if (G(L)->panic) G(L)->panic(L); #else +#if LJ_HASJIT + setmref(g->jit_base, NULL); +#endif { void *cf = err_unwind(L, NULL, errcode); if (cframe_unwind_ff(cf)) @@ -600,7 +832,7 @@ static ptrdiff_t finderrfunc(lua_State *L) /* Runtime error. */ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) { - ptrdiff_t ef = finderrfunc(L); + ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L); if (ef) { TValue *errfunc = restorestack(L, ef); TValue *top = L->top; @@ -619,6 +851,16 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) lj_err_throw(L, LUA_ERRRUN); } +#if LJ_HASJIT +LJ_NOINLINE void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode) +{ + if (errcode == LUA_ERRRUN) + lj_err_run(L); + else + lj_err_throw(L, errcode); +} +#endif + /* Formatted runtime error message. */ LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...) { @@ -699,25 +941,27 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) /* Error in context of caller. */ LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) { - TValue *frame = L->base-1; - TValue *pframe = NULL; - if (frame_islua(frame)) { - pframe = frame_prevl(frame); - } else if (frame_iscont(frame)) { - if (frame_iscont_fficb(frame)) { - pframe = frame; - frame = NULL; - } else { - pframe = frame_prevd(frame); + TValue *frame = NULL, *pframe = NULL; + if (!(LJ_HASJIT && tvref(G(L)->jit_base))) { + frame = L->base-1; + if (frame_islua(frame)) { + pframe = frame_prevl(frame); + } else if (frame_iscont(frame)) { + if (frame_iscont_fficb(frame)) { + pframe = frame; + frame = NULL; + } else { + pframe = frame_prevd(frame); #if LJ_HASFFI - /* Remove frame for FFI metamethods. */ - if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && - frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { - L->base = pframe+1; - L->top = frame; - setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame)); - } + /* Remove frame for FFI metamethods. */ + if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && + frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { + L->base = pframe+1; + L->top = frame; + setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame)); + } #endif + } } } lj_debug_addloc(L, msg, pframe, frame); diff --git a/love/src/jni/LuaJIT-2.1/src/lj_err.h b/love/src/jni/LuaJIT-2.1/src/lj_err.h index 770553fc..2e8a251f 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_err.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_err.h @@ -23,7 +23,10 @@ LJ_DATA const char *lj_err_allmsg; LJ_FUNC GCstr *lj_err_str(lua_State *L, ErrMsg em); LJ_FUNCA_NORET void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode); LJ_FUNC_NORET void lj_err_mem(lua_State *L); -LJ_FUNCA_NORET void LJ_FASTCALL lj_err_run(lua_State *L); +LJ_FUNC_NORET void LJ_FASTCALL lj_err_run(lua_State *L); +#if LJ_HASJIT +LJ_FUNCA_NORET void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode); +#endif LJ_FUNC_NORET void lj_err_msg(lua_State *L, ErrMsg em); LJ_FUNC_NORET void lj_err_lex(lua_State *L, GCstr *src, const char *tok, BCLine line, ErrMsg em, va_list argp); @@ -38,4 +41,18 @@ LJ_FUNC_NORET void lj_err_argv(lua_State *L, int narg, ErrMsg em, ...); LJ_FUNC_NORET void lj_err_argtype(lua_State *L, int narg, const char *xname); LJ_FUNC_NORET void lj_err_argt(lua_State *L, int narg, int tt); +#if LJ_UNWIND_JIT && !LJ_ABI_WIN +LJ_FUNC uint8_t *lj_err_register_mcode(void *base, size_t sz, uint8_t *info); +LJ_FUNC void lj_err_deregister_mcode(void *base, size_t sz, uint8_t *info); +#else +#define lj_err_register_mcode(base, sz, info) (info) +#define lj_err_deregister_mcode(base, sz, info) UNUSED(base) +#endif + +#if LJ_UNWIND_EXT && !LJ_ABI_WIN && defined(LUA_USE_ASSERT) +LJ_FUNC void lj_err_verify(void); +#else +#define lj_err_verify() ((void)0) +#endif + #endif diff --git a/love/src/jni/LuaJIT-2.1/src/lj_errmsg.h b/love/src/jni/LuaJIT-2.1/src/lj_errmsg.h index 9ff4553d..89e67496 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_errmsg.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_errmsg.h @@ -67,6 +67,7 @@ ERRDEF(PROTMT, "cannot change a protected metatable") ERRDEF(UNPACK, "too many results to unpack") ERRDEF(RDRSTR, "reader function must return a string") ERRDEF(PRTOSTR, LUA_QL("tostring") " must return a string to " LUA_QL("print")) +ERRDEF(NUMRNG, "number out of range") ERRDEF(IDXRNG, "index out of range") ERRDEF(BASERNG, "base out of range") ERRDEF(LVLRNG, "level out of range") @@ -179,6 +180,19 @@ ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields") ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)") #endif +#if LJ_HASBUFFER +/* String buffer errors. */ +ERRDEF(BUFFER_SELF, "cannot put buffer into itself") +ERRDEF(BUFFER_BADOPT, "bad options table") +ERRDEF(BUFFER_BADENC, "cannot serialize " LUA_QS) +ERRDEF(BUFFER_BADDEC, "cannot deserialize tag 0x%02x") +ERRDEF(BUFFER_BADDICTX, "cannot deserialize dictionary index %d") +ERRDEF(BUFFER_DEPTH, "too deep to serialize") +ERRDEF(BUFFER_DUPKEY, "duplicate table key") +ERRDEF(BUFFER_EOB, "unexpected end of buffer") +ERRDEF(BUFFER_LEFTOV, "left-over data in buffer") +#endif + #undef ERRDEF /* Detecting unused error messages: diff --git a/love/src/jni/LuaJIT-2.1/src/lj_ffrecord.c b/love/src/jni/LuaJIT-2.1/src/lj_ffrecord.c index baf7279d..97b40f98 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_ffrecord.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_ffrecord.c @@ -11,6 +11,7 @@ #if LJ_HASJIT #include "lj_err.h" +#include "lj_buf.h" #include "lj_str.h" #include "lj_tab.h" #include "lj_frame.h" @@ -28,6 +29,7 @@ #include "lj_vm.h" #include "lj_strscan.h" #include "lj_strfmt.h" +#include "lj_serialize.h" /* Some local macros to save typing. Undef'd at the end. */ #define IR(ref) (&J->cur.ir[(ref)]) @@ -107,6 +109,10 @@ static void recff_stitch(jit_State *J) const BCIns *pc = frame_pc(base-1); TValue *pframe = frame_prevl(base-1); + /* Check for this now. Throwing in lj_record_stop messes up the stack. */ + if (J->cur.nsnap >= (MSize)J->param[JIT_P_maxsnap]) + lj_trace_err(J, LJ_TRERR_SNAPOV); + /* Move func + args up in Lua stack and insert continuation. */ memmove(&base[1], &base[-1-LJ_FR2], sizeof(TValue)*nslot); setframe_ftsz(nframe, ((char *)nframe - (char *)pframe) + FRAME_CONT); @@ -182,6 +188,14 @@ static TRef recff_bufhdr(jit_State *J) lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET); } +/* Emit TMPREF. */ +static TRef recff_tmpref(jit_State *J, TRef tr, int mode) +{ + if (!LJ_DUALNUM && tref_isinteger(tr)) + tr = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT); + return emitir(IRT(IR_TMPREF, IRT_PGC), tr, mode); +} + /* -- Base library fast functions ----------------------------------------- */ static void LJ_FASTCALL recff_assert(jit_State *J, RecordFFData *rd) @@ -296,7 +310,7 @@ int32_t lj_ffrecord_select_mode(jit_State *J, TRef tr, TValue *tv) } else { TRef trptr = emitir(IRT(IR_STRREF, IRT_PGC), tr, lj_ir_kint(J, 0)); TRef trchar = emitir(IRT(IR_XLOAD, IRT_U8), trptr, IRXLOAD_READONLY); - emitir(IRTG(IR_EQ, IRT_INT), trchar, lj_ir_kint(J, '#')); + emitir(IRTGI(IR_EQ), trchar, lj_ir_kint(J, '#')); } return 0; } else { /* select(n, ...) */ @@ -317,9 +331,9 @@ static void LJ_FASTCALL recff_select(jit_State *J, RecordFFData *rd) ptrdiff_t n = (ptrdiff_t)J->maxslot; if (start < 0) start += n; else if (start > n) start = n; - rd->nres = n - start; if (start >= 1) { ptrdiff_t i; + rd->nres = n - start; for (i = 0; i < n - start; i++) J->base[i] = J->base[start+i]; } /* else: Interpreter will throw. */ @@ -455,6 +469,7 @@ static void LJ_FASTCALL recff_pcall(jit_State *J, RecordFFData *rd) #endif lj_record_call(J, 0, J->maxslot - 1); rd->nres = -1; /* Pending call. */ + J->needsnap = 1; /* Start catching on-trace errors. */ } /* else: Interpreter will throw. */ } @@ -490,6 +505,7 @@ static void LJ_FASTCALL recff_xpcall(jit_State *J, RecordFFData *rd) if (errcode) lj_err_throw(J->L, errcode); /* Propagate errors. */ rd->nres = -1; /* Pending call. */ + J->needsnap = 1; /* Start catching on-trace errors. */ } /* else: Interpreter will throw. */ } @@ -505,6 +521,40 @@ static void LJ_FASTCALL recff_getfenv(jit_State *J, RecordFFData *rd) recff_nyiu(J, rd); } +static void LJ_FASTCALL recff_next(jit_State *J, RecordFFData *rd) +{ +#if LJ_BE + /* YAGNI: Disabled on big-endian due to issues with lj_vm_next, + ** IR_HIOP, RID_RETLO/RID_RETHI and ra_destpair. + */ + recff_nyi(J, rd); +#else + TRef tab = J->base[0]; + if (tref_istab(tab)) { + RecordIndex ix; + cTValue *keyv; + ix.tab = tab; + if (tref_isnil(J->base[1])) { /* Shortcut for start of traversal. */ + ix.key = lj_ir_kint(J, 0); + keyv = niltvg(J2G(J)); + } else { + TRef tmp = recff_tmpref(J, J->base[1], IRTMPREF_IN1); + ix.key = lj_ir_call(J, IRCALL_lj_tab_keyindex, tab, tmp); + keyv = &rd->argv[1]; + } + copyTV(J->L, &ix.tabv, &rd->argv[0]); + ix.keyv.u32.lo = lj_tab_keyindex(tabV(&ix.tabv), keyv); + /* Omit the value, if not used by the caller. */ + ix.idxchain = (J->framedepth && frame_islua(J->L->base-1) && + bc_b(frame_pc(J->L->base-1)[-1])-1 < 2); + ix.mobj = 0; /* We don't need the next index. */ + rd->nres = lj_record_next(J, &ix); + J->base[0] = ix.key; + J->base[1] = ix.val; + } /* else: Interpreter will throw. */ +#endif +} + /* -- Math library fast functions ----------------------------------------- */ static void LJ_FASTCALL recff_math_abs(jit_State *J, RecordFFData *rd) @@ -707,7 +757,7 @@ static void LJ_FASTCALL recff_bit_tohex(jit_State *J, RecordFFData *rd) #if LJ_HASFFI TRef hdr = recff_bufhdr(J); TRef tr = recff_bit64_tohex(J, rd, hdr); - J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); + J->base[0] = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); #else recff_nyiu(J, rd); /* Don't bother working around this NYI. */ #endif @@ -833,8 +883,8 @@ static void LJ_FASTCALL recff_string_char(jit_State *J, RecordFFData *rd) if (i > 1) { /* Concatenate the strings, if there's more than one. */ TRef hdr = recff_bufhdr(J), tr = hdr; for (i = 0; J->base[i] != 0; i++) - tr = emitir(IRT(IR_BUFPUT, IRT_PGC), tr, J->base[i]); - J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); + tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, J->base[i]); + J->base[0] = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); } else if (i == 0) { J->base[0] = lj_ir_kstr(J, &J2G(J)->strempty); } @@ -852,19 +902,19 @@ static void LJ_FASTCALL recff_string_rep(jit_State *J, RecordFFData *rd) emitir(IRTGI(vrep > 1 ? IR_GT : IR_LE), rep, lj_ir_kint(J, 1)); if (vrep > 1) { TRef hdr2 = recff_bufhdr(J); - TRef tr2 = emitir(IRT(IR_BUFPUT, IRT_PGC), hdr2, sep); - tr2 = emitir(IRT(IR_BUFPUT, IRT_PGC), tr2, str); - str2 = emitir(IRT(IR_BUFSTR, IRT_STR), tr2, hdr2); + TRef tr2 = emitir(IRTG(IR_BUFPUT, IRT_PGC), hdr2, sep); + tr2 = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr2, str); + str2 = emitir(IRTG(IR_BUFSTR, IRT_STR), tr2, hdr2); } } tr = hdr = recff_bufhdr(J); if (str2) { - tr = emitir(IRT(IR_BUFPUT, IRT_PGC), tr, str); + tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, str); str = str2; rep = emitir(IRTI(IR_ADD), rep, lj_ir_kint(J, -1)); } tr = lj_ir_call(J, IRCALL_lj_buf_putstr_rep, tr, str, rep); - J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); + J->base[0] = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); } static void LJ_FASTCALL recff_string_op(jit_State *J, RecordFFData *rd) @@ -872,7 +922,7 @@ static void LJ_FASTCALL recff_string_op(jit_State *J, RecordFFData *rd) TRef str = lj_ir_tostr(J, J->base[0]); TRef hdr = recff_bufhdr(J); TRef tr = lj_ir_call(J, rd->data, hdr, str); - J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); + J->base[0] = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); } static void LJ_FASTCALL recff_string_find(jit_State *J, RecordFFData *rd) @@ -935,34 +985,40 @@ static void LJ_FASTCALL recff_string_find(jit_State *J, RecordFFData *rd) } } -static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) +static void recff_format(jit_State *J, RecordFFData *rd, TRef hdr, int sbufx) { - TRef trfmt = lj_ir_tostr(J, J->base[0]); - GCstr *fmt = argv2str(J, &rd->argv[0]); - int arg = 1; - TRef hdr, tr; + ptrdiff_t arg = sbufx; + TRef tr = hdr, trfmt = lj_ir_tostr(J, J->base[arg]); + GCstr *fmt = argv2str(J, &rd->argv[arg]); FormatState fs; SFormat sf; /* Specialize to the format string. */ emitir(IRTG(IR_EQ, IRT_STR), trfmt, lj_ir_kstr(J, fmt)); - tr = hdr = recff_bufhdr(J); lj_strfmt_init(&fs, strdata(fmt), fmt->len); while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { /* Parse format. */ - TRef tra = sf == STRFMT_LIT ? 0 : J->base[arg++]; + TRef tra = sf == STRFMT_LIT ? 0 : J->base[++arg]; TRef trsf = lj_ir_kint(J, (int32_t)sf); IRCallID id; switch (STRFMT_TYPE(sf)) { case STRFMT_LIT: - tr = emitir(IRT(IR_BUFPUT, IRT_PGC), tr, + tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, lj_ir_kstr(J, lj_str_new(J->L, fs.str, fs.len))); break; case STRFMT_INT: id = IRCALL_lj_strfmt_putfnum_int; handle_int: - if (!tref_isinteger(tra)) + if (!tref_isinteger(tra)) { +#if LJ_HASFFI + if (tref_iscdata(tra)) { + tra = lj_crecord_loadiu64(J, tra, &rd->argv[arg]); + tr = lj_ir_call(J, IRCALL_lj_strfmt_putfxint, tr, trsf, tra); + break; + } +#endif goto handle_num; + } if (sf == STRFMT_INT) { /* Shortcut for plain %d. */ - tr = emitir(IRT(IR_BUFPUT, IRT_PGC), tr, + tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, emitir(IRT(IR_TOSTR, IRT_STR), tra, IRTOSTR_INT)); } else { #if LJ_HASFFI @@ -989,10 +1045,11 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) case STRFMT_STR: if (!tref_isstr(tra)) { recff_nyiu(J, rd); /* NYI: __tostring and non-string types for %s. */ + /* NYI: also buffers. */ return; } if (sf == STRFMT_STR) /* Shortcut for plain %s. */ - tr = emitir(IRT(IR_BUFPUT, IRT_PGC), tr, tra); + tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, tra); else if ((sf & STRFMT_T_QUOTED)) tr = lj_ir_call(J, IRCALL_lj_strfmt_putquoted, tr, tra); else @@ -1001,7 +1058,7 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) case STRFMT_CHAR: tra = lj_opt_narrow_toint(J, tra); if (sf == STRFMT_CHAR) /* Shortcut for plain %c. */ - tr = emitir(IRT(IR_BUFPUT, IRT_PGC), tr, + tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, emitir(IRT(IR_TOSTR, IRT_STR), tra, IRTOSTR_CHAR)); else tr = lj_ir_call(J, IRCALL_lj_strfmt_putfchar, tr, trsf, tra); @@ -1013,9 +1070,326 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) return; } } - J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); + if (sbufx) { + emitir(IRT(IR_USE, IRT_NIL), tr, 0); + } else { + J->base[0] = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); + } } +static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) +{ + recff_format(J, rd, recff_bufhdr(J), 0); +} + +/* -- Buffer library fast functions --------------------------------------- */ + +#if LJ_HASBUFFER + +static LJ_AINLINE TRef recff_sbufx_get_L(jit_State *J, TRef ud) +{ + return emitir(IRT(IR_FLOAD, IRT_PGC), ud, IRFL_SBUF_L); +} + +static LJ_AINLINE void recff_sbufx_set_L(jit_State *J, TRef ud, TRef val) +{ + TRef fref = emitir(IRT(IR_FREF, IRT_PGC), ud, IRFL_SBUF_L); + emitir(IRT(IR_FSTORE, IRT_PGC), fref, val); +} + +static LJ_AINLINE TRef recff_sbufx_get_ptr(jit_State *J, TRef ud, IRFieldID fl) +{ + return emitir(IRT(IR_FLOAD, IRT_PTR), ud, fl); +} + +static LJ_AINLINE void recff_sbufx_set_ptr(jit_State *J, TRef ud, IRFieldID fl, TRef val) +{ + TRef fref = emitir(IRT(IR_FREF, IRT_PTR), ud, fl); + emitir(IRT(IR_FSTORE, IRT_PTR), fref, val); +} + +static LJ_AINLINE TRef recff_sbufx_len(jit_State *J, TRef trr, TRef trw) +{ + TRef len = emitir(IRT(IR_SUB, IRT_INTP), trw, trr); + if (LJ_64) + len = emitir(IRTI(IR_CONV), len, (IRT_INT<<5)|IRT_INTP|IRCONV_NONE); + return len; +} + +/* Emit typecheck for string buffer. */ +static TRef recff_sbufx_check(jit_State *J, RecordFFData *rd, int arg) +{ + TRef trtype, ud = J->base[arg]; + if (!tvisbuf(&rd->argv[arg])) lj_trace_err(J, LJ_TRERR_BADTYPE); + trtype = emitir(IRT(IR_FLOAD, IRT_U8), ud, IRFL_UDATA_UDTYPE); + emitir(IRTGI(IR_EQ), trtype, lj_ir_kint(J, UDTYPE_BUFFER)); + J->needsnap = 1; + return ud; +} + +/* Emit BUFHDR for write to extended string buffer. */ +static TRef recff_sbufx_write(jit_State *J, TRef ud) +{ + TRef trbuf = emitir(IRT(IR_ADD, IRT_PGC), ud, lj_ir_kint(J, sizeof(GCudata))); + return emitir(IRT(IR_BUFHDR, IRT_PGC), trbuf, IRBUFHDR_WRITE); +} + +/* Check for integer in range for the buffer API. */ +static TRef recff_sbufx_checkint(jit_State *J, RecordFFData *rd, int arg) +{ + TRef tr = J->base[arg]; + TRef trlim = lj_ir_kint(J, LJ_MAX_BUF); + if (tref_isinteger(tr)) { + emitir(IRTGI(IR_ULE), tr, trlim); + } else if (tref_isnum(tr)) { + tr = emitir(IRTI(IR_CONV), tr, IRCONV_INT_NUM|IRCONV_ANY); + emitir(IRTGI(IR_ULE), tr, trlim); +#if LJ_HASFFI + } else if (tref_iscdata(tr)) { + tr = lj_crecord_loadiu64(J, tr, &rd->argv[arg]); + emitir(IRTG(IR_ULE, IRT_U64), tr, lj_ir_kint64(J, LJ_MAX_BUF)); + tr = emitir(IRTI(IR_CONV), tr, (IRT_INT<<5)|IRT_I64|IRCONV_NONE); +#else + UNUSED(rd); +#endif + } else { + lj_trace_err(J, LJ_TRERR_BADTYPE); + } + return tr; +} + +static void LJ_FASTCALL recff_buffer_method_reset(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + SBufExt *sbx = bufV(&rd->argv[0]); + int iscow = (int)sbufiscow(sbx); + TRef trl = recff_sbufx_get_L(J, ud); + TRef trcow = emitir(IRT(IR_BAND, IRT_IGC), trl, lj_ir_kint(J, SBUF_FLAG_COW)); + TRef zero = lj_ir_kint(J, 0); + emitir(IRTG(iscow ? IR_NE : IR_EQ, IRT_IGC), trcow, zero); + if (iscow) { + trl = emitir(IRT(IR_BXOR, IRT_IGC), trl, + LJ_GC64 ? lj_ir_kint64(J, SBUF_FLAG_COW) : + lj_ir_kint(J, SBUF_FLAG_COW)); + recff_sbufx_set_ptr(J, ud, IRFL_SBUF_W, zero); + recff_sbufx_set_ptr(J, ud, IRFL_SBUF_E, zero); + recff_sbufx_set_ptr(J, ud, IRFL_SBUF_B, zero); + recff_sbufx_set_L(J, ud, trl); + emitir(IRT(IR_FSTORE, IRT_PGC), + emitir(IRT(IR_FREF, IRT_PGC), ud, IRFL_SBUF_REF), zero); + recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, zero); + } else { + TRef trb = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_B); + recff_sbufx_set_ptr(J, ud, IRFL_SBUF_W, trb); + recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, trb); + } +} + +static void LJ_FASTCALL recff_buffer_method_skip(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trr = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_R); + TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); + TRef len = recff_sbufx_len(J, trr, trw); + TRef trn = recff_sbufx_checkint(J, rd, 1); + len = emitir(IRTI(IR_MIN), len, trn); + trr = emitir(IRT(IR_ADD, IRT_PTR), trr, len); + recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, trr); +} + +static void LJ_FASTCALL recff_buffer_method_set(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trbuf = recff_sbufx_write(J, ud); + TRef tr = J->base[1]; + if (tref_isstr(tr)) { + TRef trp = emitir(IRT(IR_STRREF, IRT_PGC), tr, lj_ir_kint(J, 0)); + TRef len = emitir(IRTI(IR_FLOAD), tr, IRFL_STR_LEN); + lj_ir_call(J, IRCALL_lj_bufx_set, trbuf, trp, len, tr); +#if LJ_HASFFI + } else if (tref_iscdata(tr)) { + TRef trp = lj_crecord_topcvoid(J, tr, &rd->argv[1]); + TRef len = recff_sbufx_checkint(J, rd, 2); + lj_ir_call(J, IRCALL_lj_bufx_set, trbuf, trp, len, tr); +#endif + } /* else: Interpreter will throw. */ +} + +static void LJ_FASTCALL recff_buffer_method_put(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trbuf = recff_sbufx_write(J, ud); + TRef tr; + ptrdiff_t arg; + if (!J->base[1]) return; + for (arg = 1; (tr = J->base[arg]); arg++) { + if (tref_isstr(tr)) { + trbuf = emitir(IRTG(IR_BUFPUT, IRT_PGC), trbuf, tr); + } else if (tref_isnumber(tr)) { + trbuf = emitir(IRTG(IR_BUFPUT, IRT_PGC), trbuf, + emitir(IRT(IR_TOSTR, IRT_STR), tr, + tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT)); + } else if (tref_isudata(tr)) { + TRef ud2 = recff_sbufx_check(J, rd, arg); + TRef trr = recff_sbufx_get_ptr(J, ud2, IRFL_SBUF_R); + TRef trw = recff_sbufx_get_ptr(J, ud2, IRFL_SBUF_W); + TRef len = recff_sbufx_len(J, trr, trw); + emitir(IRTG(IR_NE, IRT_PGC), ud, ud2); + trbuf = lj_ir_call(J, IRCALL_lj_buf_putmem, trbuf, trr, len); + } else { + recff_nyiu(J, rd); + } + } + emitir(IRT(IR_USE, IRT_NIL), trbuf, 0); +} + +static void LJ_FASTCALL recff_buffer_method_putf(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trbuf = recff_sbufx_write(J, ud); + recff_format(J, rd, trbuf, 1); +} + +static void LJ_FASTCALL recff_buffer_method_get(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trr = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_R); + TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); + TRef tr; + ptrdiff_t arg; + if (!J->base[1]) { J->base[1] = TREF_NIL; J->base[2] = 0; } + for (arg = 0; (tr = J->base[arg+1]); arg++) { + TRef len = recff_sbufx_len(J, trr, trw); + if (tref_isnil(tr)) { + J->base[arg] = emitir(IRT(IR_XSNEW, IRT_STR), trr, len); + trr = trw; + } else { + TRef trn = recff_sbufx_checkint(J, rd, arg+1); + TRef tru; + len = emitir(IRTI(IR_MIN), len, trn); + tru = emitir(IRT(IR_ADD, IRT_PTR), trr, len); + J->base[arg] = emitir(IRT(IR_XSNEW, IRT_STR), trr, len); + trr = tru; /* Doing the ADD before the SNEW generates better code. */ + } + recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, trr); + } + rd->nres = arg; +} + +static void LJ_FASTCALL recff_buffer_method___tostring(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trr = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_R); + TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); + J->base[0] = emitir(IRT(IR_XSNEW, IRT_STR), trr, recff_sbufx_len(J, trr, trw)); +} + +static void LJ_FASTCALL recff_buffer_method___len(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trr = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_R); + TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); + J->base[0] = recff_sbufx_len(J, trr, trw); +} + +#if LJ_HASFFI +static void LJ_FASTCALL recff_buffer_method_putcdata(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trbuf = recff_sbufx_write(J, ud); + TRef tr = lj_crecord_topcvoid(J, J->base[1], &rd->argv[1]); + TRef len = recff_sbufx_checkint(J, rd, 2); + trbuf = lj_ir_call(J, IRCALL_lj_buf_putmem, trbuf, tr, len); + emitir(IRT(IR_USE, IRT_NIL), trbuf, 0); +} + +static void LJ_FASTCALL recff_buffer_method_reserve(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trbuf = recff_sbufx_write(J, ud); + TRef trsz = recff_sbufx_checkint(J, rd, 1); + J->base[1] = lj_ir_call(J, IRCALL_lj_bufx_more, trbuf, trsz); + J->base[0] = lj_crecord_topuint8(J, recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W)); + rd->nres = 2; +} + +static void LJ_FASTCALL recff_buffer_method_commit(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef len = recff_sbufx_checkint(J, rd, 1); + TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); + TRef tre = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_E); + TRef left = emitir(IRT(IR_SUB, IRT_INTP), tre, trw); + if (LJ_64) + left = emitir(IRTI(IR_CONV), left, (IRT_INT<<5)|IRT_INTP|IRCONV_NONE); + emitir(IRTGI(IR_ULE), len, left); + trw = emitir(IRT(IR_ADD, IRT_PTR), trw, len); + recff_sbufx_set_ptr(J, ud, IRFL_SBUF_W, trw); +} + +static void LJ_FASTCALL recff_buffer_method_ref(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trr = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_R); + TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); + J->base[0] = lj_crecord_topuint8(J, trr); + J->base[1] = recff_sbufx_len(J, trr, trw); + rd->nres = 2; +} +#endif + +static void LJ_FASTCALL recff_buffer_method_encode(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trbuf = recff_sbufx_write(J, ud); + TRef tmp = recff_tmpref(J, J->base[1], IRTMPREF_IN1); + lj_ir_call(J, IRCALL_lj_serialize_put, trbuf, tmp); + /* No IR_USE needed, since the call is a store. */ +} + +static void LJ_FASTCALL recff_buffer_method_decode(jit_State *J, RecordFFData *rd) +{ + TRef ud = recff_sbufx_check(J, rd, 0); + TRef trbuf = recff_sbufx_write(J, ud); + TRef tmp = recff_tmpref(J, TREF_NIL, IRTMPREF_OUT1); + TRef trr = lj_ir_call(J, IRCALL_lj_serialize_get, trbuf, tmp); + IRType t = (IRType)lj_serialize_peektype(bufV(&rd->argv[0])); + /* No IR_USE needed, since the call is a store. */ + J->base[0] = lj_record_vload(J, tmp, 0, t); + /* The sbx->r store must be after the VLOAD type check, in case it fails. */ + recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, trr); +} + +static void LJ_FASTCALL recff_buffer_encode(jit_State *J, RecordFFData *rd) +{ + TRef tmp = recff_tmpref(J, J->base[0], IRTMPREF_IN1); + J->base[0] = lj_ir_call(J, IRCALL_lj_serialize_encode, tmp); + /* IR_USE needed for IR_CALLA, because the encoder may throw non-OOM. */ + emitir(IRT(IR_USE, IRT_NIL), J->base[0], 0); + UNUSED(rd); +} + +static void LJ_FASTCALL recff_buffer_decode(jit_State *J, RecordFFData *rd) +{ + if (tvisstr(&rd->argv[0])) { + GCstr *str = strV(&rd->argv[0]); + SBufExt sbx; + IRType t; + TRef tmp = recff_tmpref(J, TREF_NIL, IRTMPREF_OUT1); + TRef tr = lj_ir_call(J, IRCALL_lj_serialize_decode, tmp, J->base[0]); + /* IR_USE needed for IR_CALLA, because the decoder may throw non-OOM. + ** That's why IRCALL_lj_serialize_decode needs a fake INT result. + */ + emitir(IRT(IR_USE, IRT_NIL), tr, 0); + memset(&sbx, 0, sizeof(SBufExt)); + lj_bufx_set_cow(J->L, &sbx, strdata(str), str->len); + t = (IRType)lj_serialize_peektype(&sbx); + J->base[0] = lj_record_vload(J, tmp, 0, t); + } /* else: Interpreter will throw. */ +} + +#endif + /* -- Table library fast functions ---------------------------------------- */ static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd) @@ -1054,7 +1428,7 @@ static void LJ_FASTCALL recff_table_concat(jit_State *J, RecordFFData *rd) TRef hdr = recff_bufhdr(J); TRef tr = lj_ir_call(J, IRCALL_lj_buf_puttab, hdr, tab, sep, tri, tre); emitir(IRTG(IR_NE, IRT_PTR), tr, lj_ir_kptr(J, NULL)); - J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); + J->base[0] = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); } /* else: Interpreter will throw. */ UNUSED(rd); } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_frame.h b/love/src/jni/LuaJIT-2.1/src/lj_frame.h index f67a2332..b6146454 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_frame.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_frame.h @@ -192,12 +192,12 @@ enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */ #endif #define CFRAME_SHIFT_MULTRES 3 #elif LJ_TARGET_ARM64 -#define CFRAME_OFS_ERRF 196 -#define CFRAME_OFS_NRES 200 -#define CFRAME_OFS_PREV 160 -#define CFRAME_OFS_L 176 -#define CFRAME_OFS_PC 168 -#define CFRAME_OFS_MULTRES 192 +#define CFRAME_OFS_ERRF 36 +#define CFRAME_OFS_NRES 40 +#define CFRAME_OFS_PREV 0 +#define CFRAME_OFS_L 16 +#define CFRAME_OFS_PC 8 +#define CFRAME_OFS_MULTRES 32 #define CFRAME_SIZE 208 #define CFRAME_SHIFT_MULTRES 3 #elif LJ_TARGET_PPC diff --git a/love/src/jni/LuaJIT-2.1/src/lj_gc.c b/love/src/jni/LuaJIT-2.1/src/lj_gc.c index cfbce037..5a238542 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_gc.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_gc.c @@ -65,6 +65,15 @@ static void gc_mark(global_State *g, GCobj *o) gray2black(o); /* Userdata are never gray. */ if (mt) gc_markobj(g, mt); gc_markobj(g, tabref(gco2ud(o)->env)); + if (LJ_HASBUFFER && gco2ud(o)->udtype == UDTYPE_BUFFER) { + SBufExt *sbx = (SBufExt *)uddata(gco2ud(o)); + if (sbufiscow(sbx) && gcref(sbx->cowref)) + gc_markobj(g, gcref(sbx->cowref)); + if (gcref(sbx->dict_str)) + gc_markobj(g, gcref(sbx->dict_str)); + if (gcref(sbx->dict_mt)) + gc_markobj(g, gcref(sbx->dict_mt)); + } } else if (LJ_UNLIKELY(gct == ~LJ_TUPVAL)) { GCupval *uv = gco2uv(o); gc_marktv(g, uvval(uv)); diff --git a/love/src/jni/LuaJIT-2.1/src/lj_ir.c b/love/src/jni/LuaJIT-2.1/src/lj_ir.c index 4be11a61..71bf8855 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_ir.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_ir.c @@ -30,6 +30,7 @@ #endif #include "lj_vm.h" #include "lj_strscan.h" +#include "lj_serialize.h" #include "lj_strfmt.h" #include "lj_prng.h" @@ -147,7 +148,7 @@ TRef lj_ir_call(jit_State *J, IRCallID id, ...) } /* Load field of type t from GG_State + offset. Must be 32 bit aligned. */ -LJ_FUNC TRef lj_ir_ggfload(jit_State *J, IRType t, uintptr_t ofs) +TRef lj_ir_ggfload(jit_State *J, IRType t, uintptr_t ofs) { lj_assertJ((ofs & 3) == 0, "unaligned GG_State field offset"); ofs >>= 2; diff --git a/love/src/jni/LuaJIT-2.1/src/lj_ir.h b/love/src/jni/LuaJIT-2.1/src/lj_ir.h index 1aedfd0e..2b127f6c 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_ir.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_ir.h @@ -95,6 +95,7 @@ _(UREFO, LW, ref, lit) \ _(UREFC, LW, ref, lit) \ _(FREF, R , ref, lit) \ + _(TMPREF, S , ref, lit) \ _(STRREF, N , ref, ref) \ _(LREF, L , ___, ___) \ \ @@ -105,7 +106,7 @@ _(FLOAD, L , ref, lit) \ _(XLOAD, L , ref, lit) \ _(SLOAD, L , lit, lit) \ - _(VLOAD, L , ref, ___) \ + _(VLOAD, L , ref, lit) \ _(ALEN, L , ref, ref) \ \ _(ASTORE, S , ref, ref) \ @@ -124,8 +125,8 @@ \ /* Buffer operations. */ \ _(BUFHDR, L , ref, lit) \ - _(BUFPUT, L , ref, ref) \ - _(BUFSTR, A , ref, ref) \ + _(BUFPUT, LW, ref, ref) \ + _(BUFSTR, AW, ref, ref) \ \ /* Barriers. */ \ _(TBAR, S , ref, ___) \ @@ -139,9 +140,9 @@ _(STRTO, N , ref, ___) \ \ /* Calls. */ \ - _(CALLN, N , ref, lit) \ - _(CALLA, A , ref, lit) \ - _(CALLL, L , ref, lit) \ + _(CALLN, NW, ref, lit) \ + _(CALLA, AW, ref, lit) \ + _(CALLL, LW, ref, lit) \ _(CALLS, S , ref, lit) \ _(CALLXS, S , ref, ref) \ _(CARG, N , ref, ref) \ @@ -204,9 +205,15 @@ IRFPMDEF(FPMENUM) _(UDATA_META, offsetof(GCudata, metatable)) \ _(UDATA_UDTYPE, offsetof(GCudata, udtype)) \ _(UDATA_FILE, sizeof(GCudata)) \ + _(SBUF_W, sizeof(GCudata) + offsetof(SBufExt, w)) \ + _(SBUF_E, sizeof(GCudata) + offsetof(SBufExt, e)) \ + _(SBUF_B, sizeof(GCudata) + offsetof(SBufExt, b)) \ + _(SBUF_L, sizeof(GCudata) + offsetof(SBufExt, L)) \ + _(SBUF_REF, sizeof(GCudata) + offsetof(SBufExt, cowref)) \ + _(SBUF_R, sizeof(GCudata) + offsetof(SBufExt, r)) \ _(CDATA_CTYPEID, offsetof(GCcdata, ctypeid)) \ _(CDATA_PTR, sizeof(GCcdata)) \ - _(CDATA_INT, sizeof(GCcdata)) \ + _(CDATA_INT, sizeof(GCcdata)) \ _(CDATA_INT64, sizeof(GCcdata)) \ _(CDATA_INT64_4, sizeof(GCcdata) + 4) @@ -217,6 +224,11 @@ IRFLDEF(FLENUM) IRFL__MAX } IRFieldID; +/* TMPREF mode bits, stored in op2. */ +#define IRTMPREF_IN1 0x01 /* First input value. */ +#define IRTMPREF_OUT1 0x02 /* First output value. */ +#define IRTMPREF_OUT2 0x04 /* Second output value. */ + /* SLOAD mode bits, stored in op2. */ #define IRSLOAD_PARENT 0x01 /* Coalesce with parent trace. */ #define IRSLOAD_FRAME 0x02 /* Load 32 bits of ftsz. */ @@ -224,15 +236,17 @@ IRFLDEF(FLENUM) #define IRSLOAD_CONVERT 0x08 /* Number to integer conversion. */ #define IRSLOAD_READONLY 0x10 /* Read-only, omit slot store. */ #define IRSLOAD_INHERIT 0x20 /* Inherited by exits/side traces. */ +#define IRSLOAD_KEYINDEX 0x40 /* Table traversal key index. */ -/* XLOAD mode, stored in op2. */ -#define IRXLOAD_READONLY 1 /* Load from read-only data. */ -#define IRXLOAD_VOLATILE 2 /* Load from volatile data. */ -#define IRXLOAD_UNALIGNED 4 /* Unaligned load. */ +/* XLOAD mode bits, stored in op2. */ +#define IRXLOAD_READONLY 0x01 /* Load from read-only data. */ +#define IRXLOAD_VOLATILE 0x02 /* Load from volatile data. */ +#define IRXLOAD_UNALIGNED 0x04 /* Unaligned load. */ /* BUFHDR mode, stored in op2. */ #define IRBUFHDR_RESET 0 /* Reset buffer. */ #define IRBUFHDR_APPEND 1 /* Append to buffer. */ +#define IRBUFHDR_WRITE 2 /* Write to string buffer. */ /* CONV mode, stored in op2. */ #define IRCONV_SRCMASK 0x001f /* Source IRType. */ @@ -249,6 +263,7 @@ IRFLDEF(FLENUM) #define IRCONV_ANY (1<sb), sbuflen(&ls->sb)-1, tv, + fmt = lj_strscan_scan((const uint8_t *)ls->sb.b, sbuflen(&ls->sb)-1, tv, (LJ_DUALNUM ? STRSCAN_OPT_TOINT : STRSCAN_OPT_TONUM) | (LJ_HASFFI ? (STRSCAN_OPT_LL|STRSCAN_OPT_IMAG) : 0)); if (LJ_DUALNUM && fmt == STRSCAN_INT) { @@ -118,11 +118,7 @@ static void lex_number(LexState *ls, TValue *tv) GCcdata *cd; lj_assertLS(fmt == STRSCAN_I64 || fmt == STRSCAN_U64 || fmt == STRSCAN_IMAG, "unexpected number format %d", fmt); - if (!ctype_ctsG(G(L))) { - ptrdiff_t oldtop = savestack(L, L->top); - luaopen_ffi(L); /* Load FFI library on-demand. */ - L->top = restorestack(L, oldtop); - } + ctype_loadffi(L); if (fmt == STRSCAN_IMAG) { cd = lj_cdata_new_(L, CTID_COMPLEX_DOUBLE, 2*sizeof(double)); ((double *)cdataptr(cd))[0] = 0; @@ -180,7 +176,7 @@ static void lex_longstring(LexState *ls, TValue *tv, int sep) } } endloop: if (tv) { - GCstr *str = lj_parse_keepstr(ls, sbufB(&ls->sb) + (2 + (MSize)sep), + GCstr *str = lj_parse_keepstr(ls, ls->sb.b + (2 + (MSize)sep), sbuflen(&ls->sb) - 2*(2 + (MSize)sep)); setstrV(ls->L, tv, str); } @@ -286,7 +282,7 @@ static void lex_string(LexState *ls, TValue *tv) } lex_savenext(ls); /* Skip trailing delimiter. */ setstrV(ls->L, tv, - lj_parse_keepstr(ls, sbufB(&ls->sb)+1, sbuflen(&ls->sb)-2)); + lj_parse_keepstr(ls, ls->sb.b+1, sbuflen(&ls->sb)-2)); } /* -- Main lexical scanner ------------------------------------------------ */ @@ -306,7 +302,7 @@ static LexToken lex_scan(LexState *ls, TValue *tv) do { lex_savenext(ls); } while (lj_char_isident(ls->c)); - s = lj_parse_keepstr(ls, sbufB(&ls->sb), sbuflen(&ls->sb)); + s = lj_parse_keepstr(ls, ls->sb.b, sbuflen(&ls->sb)); setstrV(ls->L, tv, s); if (s->reserved > 0) /* Reserved word? */ return TK_OFS + s->reserved; @@ -496,7 +492,7 @@ void lj_lex_error(LexState *ls, LexToken tok, ErrMsg em, ...) tokstr = NULL; } else if (tok == TK_name || tok == TK_string || tok == TK_number) { lex_save(ls, '\0'); - tokstr = sbufB(&ls->sb); + tokstr = ls->sb.b; } else { tokstr = lj_lex_token2str(ls, tok); } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_lib.c b/love/src/jni/LuaJIT-2.1/src/lj_lib.c index a962ddc1..438056d8 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_lib.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_lib.c @@ -16,6 +16,9 @@ #include "lj_func.h" #include "lj_bc.h" #include "lj_dispatch.h" +#if LJ_HASFFI +#include "lj_ctype.h" +#endif #include "lj_vm.h" #include "lj_strscan.h" #include "lj_strfmt.h" @@ -301,3 +304,56 @@ int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst) return def; } +/* -- Strict type checks -------------------------------------------------- */ + +/* The following type checks do not coerce between strings and numbers. +** And they handle plain int64_t/uint64_t FFI numbers, too. +*/ + +#if LJ_HASBUFFER +GCstr *lj_lib_checkstrx(lua_State *L, int narg) +{ + TValue *o = L->base + narg-1; + if (!(o < L->top && tvisstr(o))) lj_err_argt(L, narg, LUA_TSTRING); + return strV(o); +} + +int32_t lj_lib_checkintrange(lua_State *L, int narg, int32_t a, int32_t b) +{ + TValue *o = L->base + narg-1; + lj_assertL(b >= 0, "expected range must be non-negative"); + if (o < L->top) { + if (LJ_LIKELY(tvisint(o))) { + int32_t i = intV(o); + if (i >= a && i <= b) return i; + } else if (LJ_LIKELY(tvisnum(o))) { + /* For performance reasons, this doesn't check for integerness or + ** integer overflow. Overflow detection still works, since all FPUs + ** return either MININT or MAXINT, which is then out of range. + */ + int32_t i = (int32_t)numV(o); + if (i >= a && i <= b) return i; +#if LJ_HASFFI + } else if (tviscdata(o)) { + GCcdata *cd = cdataV(o); + if (cd->ctypeid == CTID_INT64) { + int64_t i = *(int64_t *)cdataptr(cd); + if (i >= (int64_t)a && i <= (int64_t)b) return (int32_t)i; + } else if (cd->ctypeid == CTID_UINT64) { + uint64_t i = *(uint64_t *)cdataptr(cd); + if ((a < 0 || i >= (uint64_t)a) && i <= (uint64_t)b) return (int32_t)i; + } else { + goto badtype; + } +#endif + } else { + goto badtype; + } + lj_err_arg(L, narg, LJ_ERR_NUMRNG); + } +badtype: + lj_err_argt(L, narg, LUA_TNUMBER); + return 0; /* unreachable */ +} +#endif + diff --git a/love/src/jni/LuaJIT-2.1/src/lj_lib.h b/love/src/jni/LuaJIT-2.1/src/lj_lib.h index 718d8eb4..f59e9ea2 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_lib.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_lib.h @@ -46,6 +46,12 @@ LJ_FUNC GCtab *lj_lib_checktab(lua_State *L, int narg); LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg); LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst); +#if LJ_HASBUFFER +LJ_FUNC GCstr *lj_lib_checkstrx(lua_State *L, int narg); +LJ_FUNC int32_t lj_lib_checkintrange(lua_State *L, int narg, + int32_t a, int32_t b); +#endif + /* Avoid including lj_frame.h. */ #if LJ_GC64 #define lj_lib_upvalue(L, n) \ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_mcode.c b/love/src/jni/LuaJIT-2.1/src/lj_mcode.c index 9ce1deec..b3efbc55 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_mcode.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_mcode.c @@ -97,10 +97,15 @@ static int mcode_setprot(void *p, size_t sz, DWORD prot) #define MCPROT_RW (PROT_READ|PROT_WRITE) #define MCPROT_RX (PROT_READ|PROT_EXEC) #define MCPROT_RWX (PROT_READ|PROT_WRITE|PROT_EXEC) +#ifdef PROT_MPROTECT +#define MCPROT_CREATE (PROT_MPROTECT(MCPROT_RWX)) +#else +#define MCPROT_CREATE 0 +#endif static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, int prot) { - void *p = mmap((void *)hint, sz, prot, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + void *p = mmap((void *)hint, sz, prot|MCPROT_CREATE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (p == MAP_FAILED) { if (!hint) lj_trace_err(J, LJ_TRERR_MCODEAL); p = NULL; @@ -238,7 +243,7 @@ static void *mcode_alloc(jit_State *J, size_t sz) /* All memory addresses are reachable by relative jumps. */ static void *mcode_alloc(jit_State *J, size_t sz) { -#if defined(__OpenBSD__) || LJ_TARGET_UWP +#if defined(__OpenBSD__) || defined(__NetBSD__) || LJ_TARGET_UWP /* Allow better executable memory allocation for OpenBSD W^X mode. */ void *p = mcode_alloc_at(J, 0, sz, MCPROT_RUN); if (p && mcode_setprot(p, sz, MCPROT_GEN)) { @@ -269,6 +274,7 @@ static void mcode_allocarea(jit_State *J) ((MCLink *)J->mcarea)->next = oldarea; ((MCLink *)J->mcarea)->size = sz; J->szallmcarea += sz; + J->mcbot = (MCode *)lj_err_register_mcode(J->mcarea, sz, (uint8_t *)J->mcbot); } /* Free all MCode areas. */ @@ -279,7 +285,9 @@ void lj_mcode_free(jit_State *J) J->szallmcarea = 0; while (mc) { MCode *next = ((MCLink *)mc)->next; - mcode_free(J, mc, ((MCLink *)mc)->size); + size_t sz = ((MCLink *)mc)->size; + lj_err_deregister_mcode(mc, sz, (uint8_t *)mc + sizeof(MCLink)); + mcode_free(J, mc, sz); mc = next; } } @@ -314,21 +322,21 @@ void lj_mcode_abort(jit_State *J) /* Set/reset protection to allow patching of MCode areas. */ MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) { -#if LUAJIT_SECURITY_MCODE == 0 - UNUSED(J); UNUSED(ptr); UNUSED(finish); - return NULL; -#else if (finish) { +#if LUAJIT_SECURITY_MCODE if (J->mcarea == ptr) mcode_protect(J, MCPROT_RUN); else if (LJ_UNLIKELY(mcode_setprot(ptr, ((MCLink *)ptr)->size, MCPROT_RUN))) mcode_protfail(J); +#endif return NULL; } else { MCode *mc = J->mcarea; /* Try current area first to use the protection cache. */ if (ptr >= mc && ptr < (MCode *)((char *)mc + J->szmcarea)) { +#if LUAJIT_SECURITY_MCODE mcode_protect(J, MCPROT_GEN); +#endif return mc; } /* Otherwise search through the list of MCode areas. */ @@ -336,13 +344,14 @@ MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) mc = ((MCLink *)mc)->next; lj_assertJ(mc != NULL, "broken MCode area chain"); if (ptr >= mc && ptr < (MCode *)((char *)mc + ((MCLink *)mc)->size)) { +#if LUAJIT_SECURITY_MCODE if (LJ_UNLIKELY(mcode_setprot(mc, ((MCLink *)mc)->size, MCPROT_GEN))) mcode_protfail(J); +#endif return mc; } } } -#endif } /* Limit of MCode reservation reached. */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_meta.c b/love/src/jni/LuaJIT-2.1/src/lj_meta.c index 07defa55..660dfec0 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_meta.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_meta.c @@ -240,8 +240,8 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left) int fromc = 0; if (left < 0) { left = -left; fromc = 1; } do { - if (!(tvisstr(top) || tvisnumber(top)) || - !(tvisstr(top-1) || tvisnumber(top-1))) { + if (!(tvisstr(top) || tvisnumber(top) || tvisbuf(top)) || + !(tvisstr(top-1) || tvisnumber(top-1) || tvisbuf(top-1))) { cTValue *mo = lj_meta_lookup(L, top-1, MM_concat); if (tvisnil(mo)) { mo = lj_meta_lookup(L, top, MM_concat); @@ -277,10 +277,12 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left) ** next step: [...][CAT stack ............] */ TValue *e, *o = top; - uint64_t tlen = tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM; + uint64_t tlen = tvisstr(o) ? strV(o)->len : + tvisbuf(o) ? sbufxlen(bufV(o)) : STRFMT_MAXBUF_NUM; SBuf *sb; do { - o--; tlen += tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM; + o--; tlen += tvisstr(o) ? strV(o)->len : + tvisbuf(o) ? sbufxlen(bufV(o)) : STRFMT_MAXBUF_NUM; } while (--left > 0 && (tvisstr(o-1) || tvisnumber(o-1))); if (tlen >= LJ_MAX_STR) lj_err_msg(L, LJ_ERR_STROV); sb = lj_buf_tmp_(L); @@ -290,6 +292,9 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left) GCstr *s = strV(o); MSize len = s->len; lj_buf_putmem(sb, strdata(s), len); + } else if (tvisbuf(o)) { + SBufExt *sbx = bufV(o); + lj_buf_putmem(sb, sbx->r, sbufxlen(sbx)); } else if (tvisint(o)) { lj_strfmt_putint(sb, intV(o)); } else { diff --git a/love/src/jni/LuaJIT-2.1/src/lj_obj.h b/love/src/jni/LuaJIT-2.1/src/lj_obj.h index 11434ce2..1a6445fc 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_obj.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_obj.h @@ -34,13 +34,17 @@ typedef struct MRef { #if LJ_GC64 #define mref(r, t) ((t *)(void *)(r).ptr64) +#define mrefu(r) ((r).ptr64) #define setmref(r, p) ((r).ptr64 = (uint64_t)(void *)(p)) +#define setmrefu(r, u) ((r).ptr64 = (uint64_t)(u)) #define setmrefr(r, v) ((r).ptr64 = (v).ptr64) #else #define mref(r, t) ((t *)(void *)(uintptr_t)(r).ptr32) +#define mrefu(r) ((r).ptr32) #define setmref(r, p) ((r).ptr32 = (uint32_t)(uintptr_t)(void *)(p)) +#define setmrefu(r, u) ((r).ptr32 = (uint32_t)(u)) #define setmrefr(r, v) ((r).ptr32 = (v).ptr32) #endif @@ -153,11 +157,9 @@ typedef int32_t BCLine; /* Bytecode line number. */ typedef void (*ASMFunction)(void); /* Resizable string buffer. Need this here, details in lj_buf.h. */ +#define SBufHeader char *w, *e, *b; MRef L typedef struct SBuf { - MRef p; /* String buffer pointer. */ - MRef e; /* String buffer end pointer. */ - MRef b; /* String buffer base. */ - MRef L; /* lua_State, used for buffer resizing. */ + SBufHeader; } SBuf; /* -- Tags and values ----------------------------------------------------- */ @@ -282,6 +284,9 @@ typedef const TValue cTValue; #define LJ_TISGCV (LJ_TSTR+1) #define LJ_TISTABUD LJ_TTAB +/* Type marker for slot holding a traversal index. Must be lightuserdata. */ +#define LJ_KEYINDEX 0xfffe7fffu + #if LJ_GC64 #define LJ_GCVMASK (((uint64_t)1 << 47) - 1) #endif @@ -330,6 +335,7 @@ enum { UDTYPE_USERDATA, /* Regular userdata. */ UDTYPE_IO_FILE, /* I/O library FILE. */ UDTYPE_FFI_CLIB, /* FFI C library namespace. */ + UDTYPE_BUFFER, /* String buffer. */ UDTYPE__MAX }; @@ -920,7 +926,7 @@ static LJ_AINLINE void setgcV(lua_State *L, TValue *o, GCobj *v, uint32_t it) } #define define_setV(name, type, tag) \ -static LJ_AINLINE void name(lua_State *L, TValue *o, type *v) \ +static LJ_AINLINE void name(lua_State *L, TValue *o, const type *v) \ { \ setgcV(L, o, obj2gco(v), tag); \ } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_opt_fold.c b/love/src/jni/LuaJIT-2.1/src/lj_opt_fold.c index 3cf448d6..2f903e27 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_opt_fold.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_opt_fold.c @@ -514,6 +514,7 @@ LJFOLDF(kfold_snew_kptr) } LJFOLD(SNEW any KINT) +LJFOLD(XSNEW any KINT) LJFOLDF(kfold_snew_empty) { if (fright->i == 0) @@ -577,22 +578,49 @@ LJFOLDF(kfold_strcmp) ** The compromise is to declare them as loads, emit them like stores and ** CSE whole chains manually when the BUFSTR is to be emitted. Any chain ** fragments left over from CSE are eliminated by DCE. +** +** The string buffer methods emit a USE instead of a BUFSTR to keep the +** chain alive. */ -/* BUFHDR is emitted like a store, see below. */ - -LJFOLD(BUFPUT BUFHDR BUFSTR) -LJFOLDF(bufput_append) +LJFOLD(BUFHDR any any) +LJFOLDF(bufhdr_merge) { - /* New buffer, no other buffer op inbetween and same buffer? */ - if ((J->flags & JIT_F_OPT_FWD) && - !(fleft->op2 & IRBUFHDR_APPEND) && - fleft->prev == fright->op2 && - fleft->op1 == IR(fright->op2)->op1) { - IRRef ref = fins->op1; - IR(ref)->op2 = (fleft->op2 | IRBUFHDR_APPEND); /* Modify BUFHDR. */ - IR(ref)->op1 = fright->op1; - return ref; + return fins->op2 == IRBUFHDR_WRITE ? CSEFOLD : EMITFOLD; +} + +LJFOLD(BUFPUT any BUFSTR) +LJFOLDF(bufput_bufstr) +{ + if ((J->flags & JIT_F_OPT_FWD)) { + IRRef hdr = fright->op2; + /* New buffer, no other buffer op inbetween and same buffer? */ + if (fleft->o == IR_BUFHDR && fleft->op2 == IRBUFHDR_RESET && + fleft->prev == hdr && + fleft->op1 == IR(hdr)->op1) { + IRRef ref = fins->op1; + IR(ref)->op2 = IRBUFHDR_APPEND; /* Modify BUFHDR. */ + IR(ref)->op1 = fright->op1; + return ref; + } + /* Replay puts to global temporary buffer. */ + if (IR(hdr)->op2 == IRBUFHDR_RESET) { + IRIns *ir = IR(fright->op1); + /* For now only handle single string.reverse .lower .upper .rep. */ + if (ir->o == IR_CALLL && + ir->op2 >= IRCALL_lj_buf_putstr_reverse && + ir->op2 <= IRCALL_lj_buf_putstr_rep) { + IRIns *carg1 = IR(ir->op1); + if (ir->op2 == IRCALL_lj_buf_putstr_rep) { + IRIns *carg2 = IR(carg1->op1); + if (carg2->op1 == hdr) { + return lj_ir_call(J, ir->op2, fins->op1, carg2->op2, carg1->op2); + } + } else if (carg1->op1 == hdr) { + return lj_ir_call(J, ir->op2, fins->op1, carg1->op2); + } + } + } } return EMITFOLD; /* Always emit, CSE later. */ } @@ -626,14 +654,14 @@ LJFOLDF(bufstr_kfold_cse) "bad buffer constructor IR op %d", fleft->o); if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) { if (fleft->o == IR_BUFHDR) { /* No put operations? */ - if (!(fleft->op2 & IRBUFHDR_APPEND)) /* Empty buffer? */ + if (fleft->op2 == IRBUFHDR_RESET) /* Empty buffer? */ return lj_ir_kstr(J, &J2G(J)->strempty); fins->op1 = fleft->op1; fins->op2 = fleft->prev; /* Relies on checks in bufput_append. */ return CSEFOLD; } else if (fleft->o == IR_BUFPUT) { IRIns *irb = IR(fleft->op1); - if (irb->o == IR_BUFHDR && !(irb->op2 & IRBUFHDR_APPEND)) + if (irb->o == IR_BUFHDR && irb->op2 == IRBUFHDR_RESET) return fleft->op2; /* Shortcut for a single put operation. */ } } @@ -646,7 +674,7 @@ LJFOLDF(bufstr_kfold_cse) lj_assertJ(ira->o == IR_BUFHDR || ira->o == IR_BUFPUT || ira->o == IR_CALLL || ira->o == IR_CARG, "bad buffer constructor IR op %d", ira->o); - if (ira->o == IR_BUFHDR && !(ira->op2 & IRBUFHDR_APPEND)) + if (ira->o == IR_BUFHDR && ira->op2 == IRBUFHDR_RESET) return ref; /* CSE succeeded. */ if (ira->o == IR_CALLL && ira->op2 == IRCALL_lj_buf_puttab) break; @@ -1297,6 +1325,10 @@ LJFOLD(CONV SUB IRCONV_U32_U64) LJFOLD(CONV MUL IRCONV_U32_U64) LJFOLDF(simplify_conv_narrow) { +#if LJ_64 + UNUSED(J); + return NEXTFOLD; +#else IROp op = (IROp)fleft->o; IRType t = irt_type(fins->t); IRRef op1 = fleft->op1, op2 = fleft->op2, mode = fins->op2; @@ -1307,6 +1339,7 @@ LJFOLDF(simplify_conv_narrow) fins->op1 = op1; fins->op2 = op2; return RETRYFOLD; +#endif } /* Special CSE rule for CONV. */ @@ -2275,6 +2308,27 @@ LJFOLDF(fload_str_len_tostr) return NEXTFOLD; } +LJFOLD(FLOAD any IRFL_SBUF_W) +LJFOLD(FLOAD any IRFL_SBUF_E) +LJFOLD(FLOAD any IRFL_SBUF_B) +LJFOLD(FLOAD any IRFL_SBUF_L) +LJFOLD(FLOAD any IRFL_SBUF_REF) +LJFOLD(FLOAD any IRFL_SBUF_R) +LJFOLDF(fload_sbuf) +{ + TRef tr = lj_opt_fwd_fload(J); + return lj_opt_fwd_sbuf(J, tref_ref(tr)) ? tr : EMITFOLD; +} + +/* The fast function ID of function objects is immutable. */ +LJFOLD(FLOAD KGC IRFL_FUNC_FFID) +LJFOLDF(fload_func_ffid_kgc) +{ + if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) + return INTFOLD((int32_t)ir_kfunc(fleft)->c.ffid); + return NEXTFOLD; +} + /* The C type ID of cdata objects is immutable. */ LJFOLD(FLOAD KGC IRFL_CDATA_CTYPEID) LJFOLDF(fload_cdata_typeid_kgc) @@ -2421,6 +2475,7 @@ LJFOLD(XSTORE any any) LJFOLDX(lj_opt_dse_xstore) LJFOLD(NEWREF any any) /* Treated like a store. */ +LJFOLD(TMPREF any any) LJFOLD(CALLA any any) LJFOLD(CALLL any any) /* Safeguard fallback. */ LJFOLD(CALLS any any) @@ -2431,7 +2486,6 @@ LJFOLD(TNEW any any) LJFOLD(TDUP any) LJFOLD(CNEW any any) LJFOLD(XSNEW any any) -LJFOLD(BUFHDR any any) LJFOLDX(lj_ir_emit) /* ------------------------------------------------------------------------ */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_opt_loop.c b/love/src/jni/LuaJIT-2.1/src/lj_opt_loop.c index 4c709c63..df5811a9 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_opt_loop.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_opt_loop.c @@ -225,6 +225,7 @@ static void loop_subst_snap(jit_State *J, SnapShot *osnap, /* Setup new snapshot. */ snap->mapofs = (uint32_t)nmapofs; snap->ref = (IRRef1)J->cur.nins; + snap->mcofs = 0; snap->nslots = nslots; snap->topslot = osnap->topslot; snap->count = 0; diff --git a/love/src/jni/LuaJIT-2.1/src/lj_opt_mem.c b/love/src/jni/LuaJIT-2.1/src/lj_opt_mem.c index f430fc37..d6a419e4 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_opt_mem.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_opt_mem.c @@ -364,7 +364,10 @@ TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J) /* Different value: try to eliminate the redundant store. */ if (ref > J->chain[IR_LOOP]) { /* Quick check to avoid crossing LOOP. */ IRIns *ir; - /* Check for any intervening guards (includes conflicting loads). */ + /* Check for any intervening guards (includes conflicting loads). + ** Note that lj_tab_keyindex and lj_vm_next don't need guards, + ** since they are followed by at least one guarded VLOAD. + */ for (ir = IR(J->cur.nins-1); ir > store; ir--) if (irt_isguard(ir->t) || ir->o == IR_ALEN) goto doemit; /* No elimination possible. */ @@ -620,8 +623,9 @@ TRef LJ_FASTCALL lj_opt_dse_fstore(jit_State *J) goto doemit; break; /* Otherwise continue searching. */ case ALIAS_MUST: - if (store->op2 == val) /* Same value: drop the new store. */ - return DROPFOLD; + if (store->op2 == val && + !(xr->op2 >= IRFL_SBUF_W && xr->op2 <= IRFL_SBUF_R)) + return DROPFOLD; /* Same value: drop the new store. */ /* Different value: try to eliminate the redundant store. */ if (ref > J->chain[IR_LOOP]) { /* Quick check to avoid crossing LOOP. */ IRIns *ir; @@ -642,6 +646,29 @@ doemit: return EMITFOLD; /* Otherwise we have a conflict or simply no match. */ } +/* Check whether there's no aliasing buffer op between IRFL_SBUF_*. */ +int LJ_FASTCALL lj_opt_fwd_sbuf(jit_State *J, IRRef lim) +{ + IRRef ref; + if (J->chain[IR_BUFPUT] > lim) + return 0; /* Conflict. */ + ref = J->chain[IR_CALLS]; + while (ref > lim) { + IRIns *ir = IR(ref); + if (ir->op2 >= IRCALL_lj_strfmt_putint && ir->op2 < IRCALL_lj_buf_tostr) + return 0; /* Conflict. */ + ref = ir->prev; + } + ref = J->chain[IR_CALLL]; + while (ref > lim) { + IRIns *ir = IR(ref); + if (ir->op2 >= IRCALL_lj_strfmt_putint && ir->op2 < IRCALL_lj_buf_tostr) + return 0; /* Conflict. */ + ref = ir->prev; + } + return 1; /* No conflict. Can safely FOLD/CSE. */ +} + /* -- XLOAD forwarding and XSTORE elimination ----------------------------- */ /* Find cdata allocation for a reference (if any). */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_opt_split.c b/love/src/jni/LuaJIT-2.1/src/lj_opt_split.c index 3a02abd4..25c1c234 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_opt_split.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_opt_split.c @@ -645,7 +645,7 @@ static void split_ir(jit_State *J) tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hisubst[op1], oir[op1].prev); #endif ir->prev = split_emit(J, IRTI(IR_CALLN), tmp, IRCALL_lj_vm_tobit); - } else if (ir->o == IR_TOSTR) { + } else if (ir->o == IR_TOSTR || ir->o == IR_TMPREF) { if (hisubst[ir->op1]) { if (irref_isk(ir->op1)) nir->op1 = ir->op1; diff --git a/love/src/jni/LuaJIT-2.1/src/lj_parse.c b/love/src/jni/LuaJIT-2.1/src/lj_parse.c index 27fcf53c..ea64677f 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_parse.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_parse.c @@ -1465,7 +1465,7 @@ static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) MSize len = s->len+1; char *p = lj_buf_more(&ls->sb, len); p = lj_buf_wmem(p, strdata(s), len); - setsbufP(&ls->sb, p); + ls->sb.w = p; } *ofsvar = sbuflen(&ls->sb); lastpc = 0; @@ -1486,7 +1486,7 @@ static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) startpc = vs->startpc; p = lj_strfmt_wuleb128(p, startpc-lastpc); p = lj_strfmt_wuleb128(p, vs->endpc-startpc); - setsbufP(&ls->sb, p); + ls->sb.w = p; lastpc = startpc; } } @@ -1499,7 +1499,7 @@ static void fs_fixup_var(LexState *ls, GCproto *pt, uint8_t *p, size_t ofsvar) { setmref(pt->uvinfo, p); setmref(pt->varinfo, (char *)p + ofsvar); - memcpy(p, sbufB(&ls->sb), sbuflen(&ls->sb)); /* Copy from temp. buffer. */ + memcpy(p, ls->sb.b, sbuflen(&ls->sb)); /* Copy from temp. buffer. */ } #else diff --git a/love/src/jni/LuaJIT-2.1/src/lj_prng.c b/love/src/jni/LuaJIT-2.1/src/lj_prng.c index f09aaffa..bb32da8b 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_prng.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_prng.c @@ -109,13 +109,19 @@ static PRGR libfunc_rgr; #include #else -#if LJ_TARGET_OSX +#if LJ_TARGET_OSX && !LJ_TARGET_IOS +/* +** In their infinite wisdom Apple decided to disallow getentropy() in the +** iOS App Store. Even though the call is common to all BSD-ish OS, it's +** recommended by Apple in their own security-related docs, and, to top +** off the foolery, /dev/urandom is handled by the same kernel code, +** yet accessing it is actually permitted (but less efficient). +*/ #include -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 || \ - __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 #define LJ_TARGET_HAS_GETENTROPY 1 #endif -#elif LJ_TARGET_BSD || LJ_TARGET_SOLARIS || LJ_TARGET_CYGWIN +#elif (LJ_TARGET_BSD && !defined(__NetBSD__)) || LJ_TARGET_SOLARIS || LJ_TARGET_CYGWIN #define LJ_TARGET_HAS_GETENTROPY 1 #endif @@ -167,7 +173,7 @@ int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs) #elif LJ_TARGET_PS4 || LJ_TARGET_PSVITA - if (sceRandomGetRandomNumber(rs->u, sizeof(rs->u) == 0) + if (sceRandomGetRandomNumber(rs->u, sizeof(rs->u)) == 0) goto ok; #elif LJ_TARGET_UWP || LJ_TARGET_XBOXONE diff --git a/love/src/jni/LuaJIT-2.1/src/lj_profile.c b/love/src/jni/LuaJIT-2.1/src/lj_profile.c index 00fdd6da..fbcb9878 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_profile.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_profile.c @@ -346,8 +346,7 @@ LUA_API void luaJIT_profile_stop(lua_State *L) lj_trace_flushall(L); #endif lj_buf_free(g, &ps->sb); - setmref(ps->sb.b, NULL); - setmref(ps->sb.e, NULL); + ps->sb.w = ps->sb.e = NULL; ps->g = NULL; } } @@ -362,7 +361,7 @@ LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt, lj_buf_reset(sb); lj_debug_dumpstack(L, sb, fmt, depth); *len = (size_t)sbuflen(sb); - return sbufB(sb); + return sb->b; } #endif diff --git a/love/src/jni/LuaJIT-2.1/src/lj_record.c b/love/src/jni/LuaJIT-2.1/src/lj_record.c index c1adaa74..30722814 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_record.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_record.c @@ -156,6 +156,9 @@ static void rec_check_slots(jit_State *J) lj_assertJ((J->slot[s+1+LJ_FR2] & TREF_FRAME), "cont slot %d not followed by frame", s); depth++; + } else if ((tr & TREF_KEYINDEX)) { + lj_assertJ(tref_isint(tr), "keyindex slot %d bad type %d", + s, tref_type(tr)); } else { /* Number repr. may differ, but other types must be the same. */ lj_assertJ(tvisnumber(tv) ? tref_isnumber(tr) : @@ -259,6 +262,14 @@ TRef lj_record_constify(jit_State *J, cTValue *o) return 0; /* Can't represent lightuserdata (pointless). */ } +/* Emit a VLOAD with the correct type. */ +TRef lj_record_vload(jit_State *J, TRef ref, MSize idx, IRType t) +{ + TRef tr = emitir(IRTG(IR_VLOAD, t), ref, idx); + if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ + return tr; +} + /* -- Record loop ops ----------------------------------------------------- */ /* Loop event. */ @@ -275,9 +286,9 @@ static void canonicalize_slots(jit_State *J) if (LJ_DUALNUM) return; for (s = J->baseslot+J->maxslot-1; s >= 1; s--) { TRef tr = J->slot[s]; - if (tref_isinteger(tr)) { + if (tref_isinteger(tr) && !(tr & TREF_KEYINDEX)) { IRIns *ir = IR(tref_ref(tr)); - if (!(ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_READONLY))) + if (!(ir->o == IR_SLOAD && (ir->op2 & (IRSLOAD_READONLY)))) J->slot[s] = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT); } } @@ -598,6 +609,7 @@ static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev) { if (J->parent == 0 && J->exitno == 0) { if (pc == J->startpc && J->framedepth + J->retdepth == 0) { + if (bc_op(J->cur.startins) == BC_ITERN) return; /* See rec_itern(). */ /* Same loop? */ if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */ lj_trace_err(J, LJ_TRERR_LLEAVE); @@ -638,6 +650,70 @@ static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev) } /* Side trace continues across a loop that's left or not entered. */ } +/* Record ITERN. */ +static LoopEvent rec_itern(jit_State *J, BCReg ra, BCReg rb) +{ +#if LJ_BE + /* YAGNI: Disabled on big-endian due to issues with lj_vm_next, + ** IR_HIOP, RID_RETLO/RID_RETHI and ra_destpair. + */ + UNUSED(ra); UNUSED(rb); + setintV(&J->errinfo, (int32_t)BC_ITERN); + lj_trace_err_info(J, LJ_TRERR_NYIBC); +#else + RecordIndex ix; + /* Since ITERN is recorded at the start, we need our own loop detection. */ + if (J->pc == J->startpc && + (J->cur.nins > REF_FIRST+1 || + (J->cur.nins == REF_FIRST+1 && J->cur.ir[REF_FIRST].o != IR_PROF)) && + J->framedepth + J->retdepth == 0 && J->parent == 0 && J->exitno == 0) { + lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */ + return LOOPEV_ENTER; + } + J->maxslot = ra; + lj_snap_add(J); /* Required to make JLOOP the first ins in a side-trace. */ + ix.tab = getslot(J, ra-2); + ix.key = J->base[ra-1] ? J->base[ra-1] : + sloadt(J, (int32_t)(ra-1), IRT_INT, IRSLOAD_KEYINDEX); + copyTV(J->L, &ix.tabv, &J->L->base[ra-2]); + copyTV(J->L, &ix.keyv, &J->L->base[ra-1]); + ix.idxchain = (rb < 3); /* Omit value type check, if unused. */ + ix.mobj = 1; /* We need the next index, too. */ + J->maxslot = ra + lj_record_next(J, &ix); + J->needsnap = 1; + if (!tref_isnil(ix.key)) { /* Looping back? */ + J->base[ra-1] = ix.mobj | TREF_KEYINDEX; /* Control var has next index. */ + J->base[ra] = ix.key; + J->base[ra+1] = ix.val; + J->pc += bc_j(J->pc[1])+2; + return LOOPEV_ENTER; + } else { + J->maxslot = ra-3; + J->pc += 2; + return LOOPEV_LEAVE; + } +#endif +} + +/* Record ISNEXT. */ +static void rec_isnext(jit_State *J, BCReg ra) +{ + cTValue *b = &J->L->base[ra-3]; + if (tvisfunc(b) && funcV(b)->c.ffid == FF_next && + tvistab(b+1) && tvisnil(b+2)) { + /* These checks are folded away for a compiled pairs(). */ + TRef func = getslot(J, ra-3); + TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), func, IRFL_FUNC_FFID); + emitir(IRTGI(IR_EQ), trid, lj_ir_kint(J, FF_next)); + (void)getslot(J, ra-2); /* Type check for table. */ + (void)getslot(J, ra-1); /* Type check for nil key. */ + J->base[ra-1] = lj_ir_kint(J, 0) | TREF_KEYINDEX; + J->maxslot = ra; + } else { /* Abort trace. Interpreter will despecialize bytecode. */ + lj_trace_err(J, LJ_TRERR_RECERR); + } +} + /* -- Record profiler hook checks ----------------------------------------- */ #if LJ_HASPROFILE @@ -708,7 +784,7 @@ static TRef rec_call_specialize(jit_State *J, GCfunc *fn, TRef tr) /* NYI: io_file_iter doesn't have an ffid, yet. */ { /* Specialize to the ffid. */ TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), tr, IRFL_FUNC_FFID); - emitir(IRTG(IR_EQ, IRT_INT), trid, lj_ir_kint(J, fn->c.ffid)); + emitir(IRTGI(IR_EQ), trid, lj_ir_kint(J, fn->c.ffid)); } return tr; default: @@ -832,6 +908,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) J->base -= cbase; J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */ frame = frame_prevd(frame); + J->needsnap = 1; /* Stop catching on-trace errors. */ } /* Return to lower frame via interpreter for unhandled cases. */ if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && @@ -918,6 +995,9 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) TRef tr = gotresults ? J->base[cbase+rbase] : TREF_NIL; if (bslot != J->maxslot) { /* Concatenate the remainder. */ TValue *b = J->L->base, save; /* Simulate lower frame and result. */ + /* Can't handle MM_concat + CALLT + fast func side-effects. */ + if (J->postproc != LJ_POST_NONE) + lj_trace_err(J, LJ_TRERR_NYIRETL); J->base[J->maxslot] = tr; copyTV(J->L, &save, b-(2<mt == TREF_NIL && !ix->val && + tref_isudata(ix->tab) && udataV(&ix->tabv)->udtype == UDTYPE_BUFFER && + tref_istab(ix->mobj) && tref_isstr(ix->key) && tref_isk(ix->key)) { + cTValue *val = lj_tab_getstr(tabV(&ix->mobjv), strV(&ix->keyv)); + TRef tr = lj_record_constify(J, val); + if (tr) return tr; /* Specialize to the value, i.e. a method. */ + } +#endif /* Otherwise retry lookup with metaobject. */ ix->tab = ix->mobj; copyTV(J->L, &ix->tabv, &ix->mobjv); @@ -1543,6 +1633,47 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) } } +/* Determine result type of table traversal. */ +static IRType rec_next_types(GCtab *t, uint32_t idx) +{ + for (; idx < t->asize; idx++) { + cTValue *a = arrayslot(t, idx); + if (LJ_LIKELY(!tvisnil(a))) + return (LJ_DUALNUM ? IRT_INT : IRT_NUM) + (itype2irt(a) << 8); + } + idx -= t->asize; + for (; idx <= t->hmask; idx++) { + Node *n = &noderef(t->node)[idx]; + if (!tvisnil(&n->val)) + return itype2irt(&n->key) + (itype2irt(&n->val) << 8); + } + return IRT_NIL + (IRT_NIL << 8); +} + +/* Record a table traversal step aka next(). */ +int lj_record_next(jit_State *J, RecordIndex *ix) +{ + IRType t, tkey, tval; + TRef trvk; + t = rec_next_types(tabV(&ix->tabv), ix->keyv.u32.lo); + tkey = (t & 0xff); tval = (t >> 8); + trvk = lj_ir_call(J, IRCALL_lj_vm_next, ix->tab, ix->key); + if (ix->mobj || tkey == IRT_NIL) { + TRef idx = emitir(IRTI(IR_HIOP), trvk, trvk); + /* Always check for invalid key from next() for nil result. */ + if (!ix->mobj) emitir(IRTGI(IR_NE), idx, lj_ir_kint(J, -1)); + ix->mobj = idx; + } + ix->key = lj_record_vload(J, trvk, 1, tkey); + if (tkey == IRT_NIL || ix->idxchain) { /* Omit value type check. */ + ix->val = TREF_NIL; + return 1; + } else { /* Need value. */ + ix->val = lj_record_vload(J, trvk, 0, tval); + return 2; + } +} + static void rec_tsetm(jit_State *J, BCReg ra, BCReg rn, int32_t i) { RecordIndex ix; @@ -1826,11 +1957,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, lj_ir_kint(J, frofs-8)); for (i = 0; i < nload; i++) { IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]); - TRef aref = emitir(IRT(IR_AREF, IRT_PGC), - vbase, lj_ir_kint(J, (int32_t)i)); - TRef tr = emitir(IRTG(IR_VLOAD, t), aref, 0); - if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ - J->base[dst+i] = tr; + J->base[dst+i] = lj_record_vload(J, vbase, i, t); } } else { emitir(IRTGI(IR_LE), fr, lj_ir_kint(J, frofs)); @@ -1877,8 +2004,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) lj_ir_kint(J, frofs-(8<L->base[idx-2-LJ_FR2-nvararg]); aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx); - tr = emitir(IRTG(IR_VLOAD, t), aref, 0); - if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ + tr = lj_record_vload(J, aref, 0, t); } J->base[dst-2-LJ_FR2] = tr; J->maxslot = dst-1-LJ_FR2; @@ -1935,9 +2061,9 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) tr = hdr = emitir(IRT(IR_BUFHDR, IRT_PGC), lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET); do { - tr = emitir(IRT(IR_BUFPUT, IRT_PGC), tr, *trp++); + tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, *trp++); } while (trp <= top); - tr = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); + tr = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); J->maxslot = (BCReg)(xbase - J->base); if (xbase == base) return tr; /* Return simple concatenation result. */ /* Pass partial result. */ @@ -2050,7 +2176,7 @@ void lj_record_ins(jit_State *J) /* Need snapshot before recording next bytecode (e.g. after a store). */ if (J->needsnap) { J->needsnap = 0; - lj_snap_purge(J); + if (J->pt) lj_snap_purge(J); lj_snap_add(J); J->mergesnap = 1; } @@ -2423,6 +2549,9 @@ void lj_record_ins(jit_State *J) case BC_ITERL: rec_loop_interp(J, pc, rec_iterl(J, *pc)); break; + case BC_ITERN: + rec_loop_interp(J, pc, rec_itern(J, ra, rb)); + break; case BC_LOOP: rec_loop_interp(J, pc, rec_loop(J, ra, 1)); break; @@ -2451,6 +2580,10 @@ void lj_record_ins(jit_State *J) J->maxslot = ra; /* Shrink used slots. */ break; + case BC_ISNEXT: + rec_isnext(J, ra); + break; + /* -- Function headers -------------------------------------------------- */ case BC_FUNCF: @@ -2480,8 +2613,6 @@ void lj_record_ins(jit_State *J) break; } /* fallthrough */ - case BC_ITERN: - case BC_ISNEXT: case BC_UCLO: case BC_FNEW: setintV(&J->errinfo, (int32_t)op); @@ -2533,6 +2664,13 @@ static const BCIns *rec_setup_root(jit_State *J) lj_assertJ(bc_op(pc[-1]) == BC_JMP, "ITERL does not point to JMP+1"); J->bc_min = pc; break; + case BC_ITERN: + lj_assertJ(bc_op(pc[1]) == BC_ITERL, "no ITERL after ITERN"); + J->maxslot = ra; + J->bc_extent = (MSize)(-bc_j(pc[1]))*sizeof(BCIns); + J->bc_min = pc+2 + bc_j(pc[1]); + J->state = LJ_TRACE_RECORD_1ST; /* Record the first ITERN, too. */ + break; case BC_LOOP: /* Only check BC range for real loops, but not for "repeat until true". */ pcj = pc + bc_j(ins); @@ -2629,9 +2767,14 @@ void lj_record_setup(jit_State *J) } lj_snap_replay(J, T); sidecheck: - if (traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] || - T->snap[J->exitno].count >= J->param[JIT_P_hotexit] + - J->param[JIT_P_tryside]) { + if ((traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] || + T->snap[J->exitno].count >= J->param[JIT_P_hotexit] + + J->param[JIT_P_tryside])) { + if (bc_op(*J->pc) == BC_JLOOP) { + BCIns startins = traceref(J, bc_d(*J->pc))->startins; + if (bc_op(startins) == BC_ITERN) + rec_itern(J, bc_a(startins), bc_b(startins)); + } lj_record_stop(J, LJ_TRLINK_INTERP, 0); } } else { /* Root trace. */ @@ -2640,6 +2783,7 @@ void lj_record_setup(jit_State *J) J->pc = rec_setup_root(J); /* Note: the loop instruction itself is recorded at the end and not ** at the start! So snapshot #0 needs to point to the *next* instruction. + ** The one exception is BC_ITERN, which sets LJ_TRACE_RECORD_1ST. */ lj_snap_add(J); if (bc_op(J->cur.startins) == BC_FORL) diff --git a/love/src/jni/LuaJIT-2.1/src/lj_record.h b/love/src/jni/LuaJIT-2.1/src/lj_record.h index de74277e..01cc6041 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_record.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_record.h @@ -30,6 +30,7 @@ LJ_FUNC int lj_record_objcmp(jit_State *J, TRef a, TRef b, cTValue *av, cTValue *bv); LJ_FUNC void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk); LJ_FUNC TRef lj_record_constify(jit_State *J, cTValue *o); +LJ_FUNC TRef lj_record_vload(jit_State *J, TRef ref, MSize idx, IRType t); LJ_FUNC void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs); LJ_FUNC void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs); @@ -37,6 +38,7 @@ LJ_FUNC void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults); LJ_FUNC int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm); LJ_FUNC TRef lj_record_idx(jit_State *J, RecordIndex *ix); +LJ_FUNC int lj_record_next(jit_State *J, RecordIndex *ix); LJ_FUNC void lj_record_ins(jit_State *J); LJ_FUNC void lj_record_setup(jit_State *J); diff --git a/love/src/jni/LuaJIT-2.1/src/lj_serialize.c b/love/src/jni/LuaJIT-2.1/src/lj_serialize.c new file mode 100644 index 00000000..d6551b11 --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/src/lj_serialize.c @@ -0,0 +1,538 @@ +/* +** Object de/serialization. +** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h +*/ + +#define lj_serialize_c +#define LUA_CORE + +#include "lj_obj.h" + +#if LJ_HASBUFFER +#include "lj_err.h" +#include "lj_buf.h" +#include "lj_str.h" +#include "lj_tab.h" +#include "lj_udata.h" +#if LJ_HASFFI +#include "lj_ctype.h" +#include "lj_cdata.h" +#endif +#if LJ_HASJIT +#include "lj_ir.h" +#endif +#include "lj_serialize.h" + +/* Tags for internal serialization format. */ +enum { + SER_TAG_NIL, /* 0x00 */ + SER_TAG_FALSE, + SER_TAG_TRUE, + SER_TAG_NULL, + SER_TAG_LIGHTUD32, + SER_TAG_LIGHTUD64, + SER_TAG_INT, + SER_TAG_NUM, + SER_TAG_TAB, /* 0x08 */ + SER_TAG_DICT_MT = SER_TAG_TAB+6, + SER_TAG_DICT_STR, + SER_TAG_INT64, /* 0x10 */ + SER_TAG_UINT64, + SER_TAG_COMPLEX, + SER_TAG_0x13, + SER_TAG_0x14, + SER_TAG_0x15, + SER_TAG_0x16, + SER_TAG_0x17, + SER_TAG_0x18, /* 0x18 */ + SER_TAG_0x19, + SER_TAG_0x1a, + SER_TAG_0x1b, + SER_TAG_0x1c, + SER_TAG_0x1d, + SER_TAG_0x1e, + SER_TAG_0x1f, + SER_TAG_STR, /* 0x20 + str->len */ +}; +LJ_STATIC_ASSERT((SER_TAG_TAB & 7) == 0); + +/* -- Helper functions ---------------------------------------------------- */ + +static LJ_AINLINE char *serialize_more(char *w, SBufExt *sbx, MSize sz) +{ + if (LJ_UNLIKELY(sz > (MSize)(sbx->e - w))) { + sbx->w = w; + w = lj_buf_more2((SBuf *)sbx, sz); + } + return w; +} + +/* Write U124 to buffer. */ +static LJ_NOINLINE char *serialize_wu124_(char *w, uint32_t v) +{ + if (v < 0x1fe0) { + v -= 0xe0; + *w++ = (char)(0xe0 | (v >> 8)); *w++ = (char)v; + } else { + *w++ = (char)0xff; +#if LJ_BE + v = lj_bswap(v); +#endif + memcpy(w, &v, 4); w += 4; + } + return w; +} + +static LJ_AINLINE char *serialize_wu124(char *w, uint32_t v) +{ + if (LJ_LIKELY(v < 0xe0)) { + *w++ = (char)v; + return w; + } else { + return serialize_wu124_(w, v); + } +} + +static LJ_NOINLINE char *serialize_ru124_(char *r, char *w, uint32_t *pv) +{ + uint32_t v = *pv; + if (v != 0xff) { + if (r >= w) return NULL; + v = ((v & 0x1f) << 8) + *(uint8_t *)r + 0xe0; r++; + } else { + if (r + 4 > w) return NULL; + v = lj_getu32(r); r += 4; +#if LJ_BE + v = lj_bswap(v); +#endif + } + *pv = v; + return r; +} + +static LJ_AINLINE char *serialize_ru124(char *r, char *w, uint32_t *pv) +{ + if (LJ_LIKELY(r < w)) { + uint32_t v = *(uint8_t *)r; r++; + *pv = v; + if (LJ_UNLIKELY(v >= 0xe0)) { + r = serialize_ru124_(r, w, pv); + } + return r; + } + return NULL; +} + +/* Prepare string dictionary for use (once). */ +void LJ_FASTCALL lj_serialize_dict_prep_str(lua_State *L, GCtab *dict) +{ + if (!dict->hmask) { /* No hash part means not prepared, yet. */ + MSize i, len = lj_tab_len(dict); + if (!len) return; + lj_tab_resize(L, dict, dict->asize, hsize2hbits(len)); + for (i = 1; i <= len && i < dict->asize; i++) { + cTValue *o = arrayslot(dict, i); + if (tvisstr(o)) { + if (!lj_tab_getstr(dict, strV(o))) { /* Ignore dups. */ + lj_tab_newkey(L, dict, o)->u64 = (uint64_t)(i-1); + } + } else if (!tvisfalse(o)) { + lj_err_caller(L, LJ_ERR_BUFFER_BADOPT); + } + } + } +} + +/* Prepare metatable dictionary for use (once). */ +void LJ_FASTCALL lj_serialize_dict_prep_mt(lua_State *L, GCtab *dict) +{ + if (!dict->hmask) { /* No hash part means not prepared, yet. */ + MSize i, len = lj_tab_len(dict); + if (!len) return; + lj_tab_resize(L, dict, dict->asize, hsize2hbits(len)); + for (i = 1; i <= len && i < dict->asize; i++) { + cTValue *o = arrayslot(dict, i); + if (tvistab(o)) { + if (tvisnil(lj_tab_get(L, dict, o))) { /* Ignore dups. */ + lj_tab_newkey(L, dict, o)->u64 = (uint64_t)(i-1); + } + } else if (!tvisfalse(o)) { + lj_err_caller(L, LJ_ERR_BUFFER_BADOPT); + } + } + } +} + +/* -- Internal serializer ------------------------------------------------- */ + +/* Put serialized object into buffer. */ +static char *serialize_put(char *w, SBufExt *sbx, cTValue *o) +{ + if (LJ_LIKELY(tvisstr(o))) { + const GCstr *str = strV(o); + MSize len = str->len; + w = serialize_more(w, sbx, 5+len); + w = serialize_wu124(w, SER_TAG_STR + len); + w = lj_buf_wmem(w, strdata(str), len); + } else if (tvisint(o)) { + uint32_t x = LJ_BE ? lj_bswap((uint32_t)intV(o)) : (uint32_t)intV(o); + w = serialize_more(w, sbx, 1+4); + *w++ = SER_TAG_INT; memcpy(w, &x, 4); w += 4; + } else if (tvisnum(o)) { + uint64_t x = LJ_BE ? lj_bswap64(o->u64) : o->u64; + w = serialize_more(w, sbx, 1+sizeof(lua_Number)); + *w++ = SER_TAG_NUM; memcpy(w, &x, 8); w += 8; + } else if (tvispri(o)) { + w = serialize_more(w, sbx, 1); + *w++ = (char)(SER_TAG_NIL + ~itype(o)); + } else if (tvistab(o)) { + const GCtab *t = tabV(o); + uint32_t narray = 0, nhash = 0, one = 2; + if (sbx->depth <= 0) lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DEPTH); + sbx->depth--; + if (t->asize > 0) { /* Determine max. length of array part. */ + ptrdiff_t i; + TValue *array = tvref(t->array); + for (i = (ptrdiff_t)t->asize-1; i >= 0; i--) + if (!tvisnil(&array[i])) + break; + narray = (uint32_t)(i+1); + if (narray && tvisnil(&array[0])) one = 4; + } + if (t->hmask > 0) { /* Count number of used hash slots. */ + uint32_t i, hmask = t->hmask; + Node *node = noderef(t->node); + for (i = 0; i <= hmask; i++) + nhash += !tvisnil(&node[i].val); + } + /* Write metatable index. */ + if (LJ_UNLIKELY(tabref(sbx->dict_mt)) && tabref(t->metatable)) { + TValue mto; + Node *n; + settabV(sbufL(sbx), &mto, tabref(t->metatable)); + n = hashgcref(tabref(sbx->dict_mt), mto.gcr); + do { + if (n->key.u64 == mto.u64) { + uint32_t idx = n->val.u32.lo; + w = serialize_more(w, sbx, 1+5); + *w++ = SER_TAG_DICT_MT; + w = serialize_wu124(w, idx); + break; + } + } while ((n = nextnode(n))); + } + /* Write number of array slots and hash slots. */ + w = serialize_more(w, sbx, 1+2*5); + *w++ = (char)(SER_TAG_TAB + (nhash ? 1 : 0) + (narray ? one : 0)); + if (narray) w = serialize_wu124(w, narray); + if (nhash) w = serialize_wu124(w, nhash); + if (narray) { /* Write array entries. */ + cTValue *oa = tvref(t->array) + (one >> 2); + cTValue *oe = tvref(t->array) + narray; + while (oa < oe) w = serialize_put(w, sbx, oa++); + } + if (nhash) { /* Write hash entries. */ + const Node *node = noderef(t->node) + t->hmask; + GCtab *dict_str = tabref(sbx->dict_str); + if (LJ_UNLIKELY(dict_str)) { + for (;; node--) + if (!tvisnil(&node->val)) { + if (LJ_LIKELY(tvisstr(&node->key))) { + /* Inlined lj_tab_getstr is 30% faster. */ + const GCstr *str = strV(&node->key); + Node *n = hashstr(dict_str, str); + do { + if (tvisstr(&n->key) && strV(&n->key) == str) { + uint32_t idx = n->val.u32.lo; + w = serialize_more(w, sbx, 1+5); + *w++ = SER_TAG_DICT_STR; + w = serialize_wu124(w, idx); + break; + } + n = nextnode(n); + if (!n) { + MSize len = str->len; + w = serialize_more(w, sbx, 5+len); + w = serialize_wu124(w, SER_TAG_STR + len); + w = lj_buf_wmem(w, strdata(str), len); + break; + } + } while (1); + } else { + w = serialize_put(w, sbx, &node->key); + } + w = serialize_put(w, sbx, &node->val); + if (--nhash == 0) break; + } + } else { + for (;; node--) + if (!tvisnil(&node->val)) { + w = serialize_put(w, sbx, &node->key); + w = serialize_put(w, sbx, &node->val); + if (--nhash == 0) break; + } + } + } + sbx->depth++; +#if LJ_HASFFI + } else if (tviscdata(o)) { + CTState *cts = ctype_cts(sbufL(sbx)); + CType *s = ctype_raw(cts, cdataV(o)->ctypeid); + uint8_t *sp = cdataptr(cdataV(o)); + if (ctype_isinteger(s->info) && s->size == 8) { + w = serialize_more(w, sbx, 1+8); + *w++ = (s->info & CTF_UNSIGNED) ? SER_TAG_UINT64 : SER_TAG_INT64; +#if LJ_BE + { uint64_t u = lj_bswap64(*(uint64_t *)sp); memcpy(w, &u, 8); } +#else + memcpy(w, sp, 8); +#endif + w += 8; + } else if (ctype_iscomplex(s->info) && s->size == 16) { + w = serialize_more(w, sbx, 1+16); + *w++ = SER_TAG_COMPLEX; +#if LJ_BE + { /* Only swap the doubles. The re/im order stays the same. */ + uint64_t u = lj_bswap64(((uint64_t *)sp)[0]); memcpy(w, &u, 8); + u = lj_bswap64(((uint64_t *)sp)[1]); memcpy(w+8, &u, 8); + } +#else + memcpy(w, sp, 16); +#endif + w += 16; + } else { + goto badenc; /* NYI other cdata */ + } +#endif + } else if (tvislightud(o)) { + uintptr_t ud = (uintptr_t)lightudV(G(sbufL(sbx)), o); + w = serialize_more(w, sbx, 1+sizeof(ud)); + if (ud == 0) { + *w++ = SER_TAG_NULL; + } else if (LJ_32 || checku32(ud)) { +#if LJ_BE && LJ_64 + ud = lj_bswap64(ud); +#elif LJ_BE + ud = lj_bswap(ud); +#endif + *w++ = SER_TAG_LIGHTUD32; memcpy(w, &ud, 4); w += 4; +#if LJ_64 + } else { +#if LJ_BE + ud = lj_bswap64(ud); +#endif + *w++ = SER_TAG_LIGHTUD64; memcpy(w, &ud, 8); w += 8; +#endif + } + } else { + /* NYI userdata */ +#if LJ_HASFFI + badenc: +#endif + lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADENC, lj_typename(o)); + } + return w; +} + +/* Get serialized object from buffer. */ +static char *serialize_get(char *r, SBufExt *sbx, TValue *o) +{ + char *w = sbx->w; + uint32_t tp; + r = serialize_ru124(r, w, &tp); if (LJ_UNLIKELY(!r)) goto eob; + if (LJ_LIKELY(tp >= SER_TAG_STR)) { + uint32_t len = tp - SER_TAG_STR; + if (LJ_UNLIKELY(len > (uint32_t)(w - r))) goto eob; + setstrV(sbufL(sbx), o, lj_str_new(sbufL(sbx), r, len)); + r += len; + } else if (tp == SER_TAG_INT) { + if (LJ_UNLIKELY(r + 4 > w)) goto eob; + setintV(o, (int32_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r))); + r += 4; + } else if (tp == SER_TAG_NUM) { + if (LJ_UNLIKELY(r + 8 > w)) goto eob; + memcpy(o, r, 8); r += 8; +#if LJ_BE + o->u64 = lj_bswap64(o->u64); +#endif + if (!tvisnum(o)) setnanV(o); /* Fix non-canonical NaNs. */ + } else if (tp <= SER_TAG_TRUE) { + setpriV(o, ~tp); + } else if (tp == SER_TAG_DICT_STR) { + GCtab *dict_str; + uint32_t idx; + r = serialize_ru124(r, w, &idx); if (LJ_UNLIKELY(!r)) goto eob; + idx++; + dict_str = tabref(sbx->dict_str); + if (dict_str && idx < dict_str->asize && tvisstr(arrayslot(dict_str, idx))) + copyTV(sbufL(sbx), o, arrayslot(dict_str, idx)); + else + lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDICTX, idx); + } else if (tp >= SER_TAG_TAB && tp <= SER_TAG_DICT_MT) { + uint32_t narray = 0, nhash = 0; + GCtab *t, *mt = NULL; + if (sbx->depth <= 0) lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DEPTH); + sbx->depth--; + if (tp == SER_TAG_DICT_MT) { + GCtab *dict_mt; + uint32_t idx; + r = serialize_ru124(r, w, &idx); if (LJ_UNLIKELY(!r)) goto eob; + idx++; + dict_mt = tabref(sbx->dict_mt); + if (dict_mt && idx < dict_mt->asize && tvistab(arrayslot(dict_mt, idx))) + mt = tabV(arrayslot(dict_mt, idx)); + else + lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDICTX, idx); + r = serialize_ru124(r, w, &tp); if (LJ_UNLIKELY(!r)) goto eob; + if (!(tp >= SER_TAG_TAB && tp < SER_TAG_DICT_MT)) goto badtag; + } + if (tp >= SER_TAG_TAB+2) { + r = serialize_ru124(r, w, &narray); if (LJ_UNLIKELY(!r)) goto eob; + } + if ((tp & 1)) { + r = serialize_ru124(r, w, &nhash); if (LJ_UNLIKELY(!r)) goto eob; + } + t = lj_tab_new(sbufL(sbx), narray, hsize2hbits(nhash)); + /* NOBARRIER: The table is new (marked white). */ + setgcref(t->metatable, obj2gco(mt)); + settabV(sbufL(sbx), o, t); + if (narray) { + TValue *oa = tvref(t->array) + (tp >= SER_TAG_TAB+4); + TValue *oe = tvref(t->array) + narray; + while (oa < oe) r = serialize_get(r, sbx, oa++); + } + if (nhash) { + do { + TValue k, *v; + r = serialize_get(r, sbx, &k); + v = lj_tab_set(sbufL(sbx), t, &k); + if (LJ_UNLIKELY(!tvisnil(v))) + lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DUPKEY); + r = serialize_get(r, sbx, v); + } while (--nhash); + } + sbx->depth++; +#if LJ_HASFFI + } else if (tp >= SER_TAG_INT64 && tp <= SER_TAG_COMPLEX) { + uint32_t sz = tp == SER_TAG_COMPLEX ? 16 : 8; + GCcdata *cd; + if (LJ_UNLIKELY(r + sz > w)) goto eob; + cd = lj_cdata_new_(sbufL(sbx), + tp == SER_TAG_INT64 ? CTID_INT64 : + tp == SER_TAG_UINT64 ? CTID_UINT64 : CTID_COMPLEX_DOUBLE, + sz); + memcpy(cdataptr(cd), r, sz); r += sz; +#if LJ_BE + *(uint64_t *)cdataptr(cd) = lj_bswap64(*(uint64_t *)cdataptr(cd)); + if (sz == 16) + ((uint64_t *)cdataptr(cd))[1] = lj_bswap64(((uint64_t *)cdataptr(cd))[1]); +#endif + if (sz == 16) { /* Fix non-canonical NaNs. */ + TValue *cdo = (TValue *)cdataptr(cd); + if (!tvisnum(&cdo[0])) setnanV(&cdo[0]); + if (!tvisnum(&cdo[1])) setnanV(&cdo[1]); + } + setcdataV(sbufL(sbx), o, cd); +#endif + } else if (tp <= (LJ_64 ? SER_TAG_LIGHTUD64 : SER_TAG_LIGHTUD32)) { + uintptr_t ud = 0; + if (tp == SER_TAG_LIGHTUD32) { + if (LJ_UNLIKELY(r + 4 > w)) goto eob; + ud = (uintptr_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r)); + r += 4; + } +#if LJ_64 + else if (tp == SER_TAG_LIGHTUD64) { + if (LJ_UNLIKELY(r + 8 > w)) goto eob; + memcpy(&ud, r, 8); r += 8; +#if LJ_BE + ud = lj_bswap64(ud); +#endif + } + setrawlightudV(o, lj_lightud_intern(sbufL(sbx), (void *)ud)); +#else + setrawlightudV(o, (void *)ud); +#endif + } else { +badtag: + lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDEC, tp); + } + return r; +eob: + lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_EOB); + return NULL; +} + +/* -- External serialization API ------------------------------------------ */ + +/* Encode to buffer. */ +SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o) +{ + sbx->depth = LJ_SERIALIZE_DEPTH; + sbx->w = serialize_put(sbx->w, sbx, o); + return sbx; +} + +/* Decode from buffer. */ +char * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o) +{ + sbx->depth = LJ_SERIALIZE_DEPTH; + return serialize_get(sbx->r, sbx, o); +} + +/* Stand-alone encoding, borrowing from global temporary buffer. */ +GCstr * LJ_FASTCALL lj_serialize_encode(lua_State *L, cTValue *o) +{ + SBufExt sbx; + char *w; + memset(&sbx, 0, sizeof(SBufExt)); + lj_bufx_set_borrow(L, &sbx, &G(L)->tmpbuf); + sbx.depth = LJ_SERIALIZE_DEPTH; + w = serialize_put(sbx.w, &sbx, o); + return lj_str_new(L, sbx.b, (size_t)(w - sbx.b)); +} + +/* Stand-alone decoding, copy-on-write from string. */ +void lj_serialize_decode(lua_State *L, TValue *o, GCstr *str) +{ + SBufExt sbx; + char *r; + memset(&sbx, 0, sizeof(SBufExt)); + lj_bufx_set_cow(L, &sbx, strdata(str), str->len); + /* No need to set sbx.cowref here. */ + sbx.depth = LJ_SERIALIZE_DEPTH; + r = serialize_get(sbx.r, &sbx, o); + if (r != sbx.w) lj_err_caller(L, LJ_ERR_BUFFER_LEFTOV); +} + +#if LJ_HASJIT +/* Peek into buffer to find the result IRType for specialization purposes. */ +LJ_FUNC MSize LJ_FASTCALL lj_serialize_peektype(SBufExt *sbx) +{ + uint32_t tp; + if (serialize_ru124(sbx->r, sbx->w, &tp)) { + /* This must match the handling of all tags in the decoder above. */ + switch (tp) { + case SER_TAG_NIL: return IRT_NIL; + case SER_TAG_FALSE: return IRT_FALSE; + case SER_TAG_TRUE: return IRT_TRUE; + case SER_TAG_NULL: case SER_TAG_LIGHTUD32: case SER_TAG_LIGHTUD64: + return IRT_LIGHTUD; + case SER_TAG_INT: return LJ_DUALNUM ? IRT_INT : IRT_NUM; + case SER_TAG_NUM: return IRT_NUM; + case SER_TAG_TAB: case SER_TAG_TAB+1: case SER_TAG_TAB+2: + case SER_TAG_TAB+3: case SER_TAG_TAB+4: case SER_TAG_TAB+5: + case SER_TAG_DICT_MT: + return IRT_TAB; + case SER_TAG_INT64: case SER_TAG_UINT64: case SER_TAG_COMPLEX: + return IRT_CDATA; + case SER_TAG_DICT_STR: + default: + return IRT_STR; + } + } + return IRT_NIL; /* Will fail on actual decode. */ +} +#endif + +#endif diff --git a/love/src/jni/LuaJIT-2.1/src/lj_serialize.h b/love/src/jni/LuaJIT-2.1/src/lj_serialize.h new file mode 100644 index 00000000..1fda23eb --- /dev/null +++ b/love/src/jni/LuaJIT-2.1/src/lj_serialize.h @@ -0,0 +1,28 @@ +/* +** Object de/serialization. +** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h +*/ + +#ifndef _LJ_SERIALIZE_H +#define _LJ_SERIALIZE_H + +#include "lj_obj.h" +#include "lj_buf.h" + +#if LJ_HASBUFFER + +#define LJ_SERIALIZE_DEPTH 100 /* Default depth. */ + +LJ_FUNC void LJ_FASTCALL lj_serialize_dict_prep_str(lua_State *L, GCtab *dict); +LJ_FUNC void LJ_FASTCALL lj_serialize_dict_prep_mt(lua_State *L, GCtab *dict); +LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o); +LJ_FUNC char * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o); +LJ_FUNC GCstr * LJ_FASTCALL lj_serialize_encode(lua_State *L, cTValue *o); +LJ_FUNC void lj_serialize_decode(lua_State *L, TValue *o, GCstr *str); +#if LJ_HASJIT +LJ_FUNC MSize LJ_FASTCALL lj_serialize_peektype(SBufExt *sbx); +#endif + +#endif + +#endif diff --git a/love/src/jni/LuaJIT-2.1/src/lj_snap.c b/love/src/jni/LuaJIT-2.1/src/lj_snap.c index 21f27e1f..97097a5b 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_snap.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_snap.c @@ -171,6 +171,7 @@ static void snapshot_stack(jit_State *J, SnapShot *snap, MSize nsnapmap) nent += snapshot_framelinks(J, p + nent, &snap->topslot); snap->mapofs = (uint32_t)nsnapmap; snap->ref = (IRRef1)J->cur.nins; + snap->mcofs = 0; snap->nslots = (uint8_t)nslots; snap->count = 0; J->cur.nsnapmap = (uint32_t)(nsnapmap + nent); @@ -251,7 +252,12 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf, BCReg minslot = bc_a(ins); if (op >= BC_FORI && op <= BC_JFORL) minslot += FORL_EXT; else if (op >= BC_ITERL && op <= BC_JITERL) minslot += bc_b(pc[-2])-1; - else if (op == BC_UCLO) { pc += bc_j(ins); break; } + else if (op == BC_UCLO) { + ptrdiff_t delta = bc_j(ins); + if (delta < 0) return maxslot; /* Prevent loop. */ + pc += delta; + break; + } for (s = minslot; s < maxslot; s++) DEF_SLOT(s); return minslot < maxslot ? minslot : maxslot; } @@ -275,7 +281,7 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf, if (!(op == BC_ISTC || op == BC_ISFC)) DEF_SLOT(bc_a(ins)); break; case BCMbase: - if (op >= BC_CALLM && op <= BC_VARG) { + if (op >= BC_CALLM && op <= BC_ITERN) { BCReg top = (op == BC_CALLM || op == BC_CALLMT || bc_c(ins) == 0) ? maxslot : (bc_a(ins) + bc_c(ins)+LJ_FR2); if (LJ_FR2) DEF_SLOT(bc_a(ins)+1); @@ -286,6 +292,8 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf, for (s = 0; s < bc_a(ins); s++) DEF_SLOT(s); return 0; } + } else if (op == BC_VARG) { + return maxslot; /* NYI: punt. */ } else if (op == BC_KNIL) { for (s = bc_a(ins); s <= bc_d(ins); s++) DEF_SLOT(s); } else if (op == BC_TSETM) { @@ -304,15 +312,45 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf, return 0; /* unreachable */ } +/* Mark slots used by upvalues of child prototypes as used. */ +void snap_useuv(GCproto *pt, uint8_t *udf) +{ + /* This is a coarse check, because it's difficult to correlate the lifetime + ** of slots and closures. But the number of false positives is quite low. + ** A false positive may cause a slot not to be purged, which is just + ** a missed optimization. + */ + if ((pt->flags & PROTO_CHILD)) { + ptrdiff_t i, j, n = pt->sizekgc; + GCRef *kr = mref(pt->k, GCRef) - 1; + for (i = 0; i < n; i++, kr--) { + GCobj *o = gcref(*kr); + if (o->gch.gct == ~LJ_TPROTO) { + for (j = 0; j < gco2pt(o)->sizeuv; j++) { + uint32_t v = proto_uv(gco2pt(o))[j]; + if ((v & PROTO_UV_LOCAL)) { + udf[(v & 0xff)] = 0; + } + } + } + } + } +} + /* Purge dead slots before the next snapshot. */ void lj_snap_purge(jit_State *J) { uint8_t udf[SNAP_USEDEF_SLOTS]; - BCReg maxslot = J->maxslot; - BCReg s = snap_usedef(J, udf, J->pc, maxslot); - for (; s < maxslot; s++) - if (udf[s] != 0) - J->base[s] = 0; /* Purge dead slots. */ + BCReg s, maxslot = J->maxslot; + if (bc_op(*J->pc) == BC_FUNCV && maxslot > J->pt->numparams) + maxslot = J->pt->numparams; + s = snap_usedef(J, udf, J->pc, maxslot); + if (s < maxslot) { + snap_useuv(J->pt, udf); + for (; s < maxslot; s++) + if (udf[s] != 0) + J->base[s] = 0; /* Purge dead slots. */ + } } /* Shrink last snapshot. */ @@ -325,6 +363,7 @@ void lj_snap_shrink(jit_State *J) BCReg maxslot = J->maxslot; BCReg baseslot = J->baseslot; BCReg minslot = snap_usedef(J, udf, snap_pc(&map[nent]), maxslot); + if (minslot < maxslot) snap_useuv(J->pt, udf); maxslot += baseslot; minslot += baseslot; snap->nslots = (uint8_t)maxslot; @@ -424,7 +463,7 @@ static TRef snap_dedup(jit_State *J, SnapEntry *map, MSize nmax, IRRef ref) MSize j; for (j = 0; j < nmax; j++) if (snap_ref(map[j]) == ref) - return J->slot[snap_slot(map[j])] & ~(SNAP_CONT|SNAP_FRAME); + return J->slot[snap_slot(map[j])] & ~(SNAP_KEYINDEX|SNAP_CONT|SNAP_FRAME); return 0; } @@ -499,10 +538,12 @@ void lj_snap_replay(jit_State *J, GCtrace *T) uint32_t mode = IRSLOAD_INHERIT|IRSLOAD_PARENT; if (LJ_SOFTFP32 && (sn & SNAP_SOFTFPNUM)) t = IRT_NUM; if (ir->o == IR_SLOAD) mode |= (ir->op2 & IRSLOAD_READONLY); + if ((sn & SNAP_KEYINDEX)) mode |= IRSLOAD_KEYINDEX; tr = emitir_raw(IRT(IR_SLOAD, t), s, mode); } setslot: - J->slot[s] = tr | (sn&(SNAP_CONT|SNAP_FRAME)); /* Same as TREF_* flags. */ + /* Same as TREF_* flags. */ + J->slot[s] = tr | (sn&(SNAP_KEYINDEX|SNAP_CONT|SNAP_FRAME)); J->framedepth += ((sn & (SNAP_CONT|SNAP_FRAME)) && (s != LJ_FR2)); if ((sn & SNAP_FRAME)) J->baseslot = s+1; @@ -922,6 +963,10 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr) setframe_ftsz(o, snap_slot(sn) != 0 ? (int32_t)*flinks-- : ftsz0); L->base = o+1; #endif + } else if ((sn & SNAP_KEYINDEX)) { + /* A IRT_INT key index slot is restored as a number. Undo this. */ + o->u32.lo = (uint32_t)(LJ_DUALNUM ? intV(o) : lj_num2int(numV(o))); + o->u32.hi = LJ_KEYINDEX; } } } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_state.c b/love/src/jni/LuaJIT-2.1/src/lj_state.c index 9585c18a..e87b945a 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_state.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_state.c @@ -156,6 +156,7 @@ static TValue *cpluaopen(lua_State *L, lua_CFunction dummy, void *ud) fixstring(lj_err_str(L, LJ_ERR_ERRMEM)); /* Preallocate memory error msg. */ g->gc.threshold = 4*g->gc.total; lj_trace_initstate(g); + lj_err_verify(); return NULL; } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_strfmt.c b/love/src/jni/LuaJIT-2.1/src/lj_strfmt.c index b1c74f88..945954aa 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_strfmt.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_strfmt.c @@ -9,11 +9,17 @@ #define LUA_CORE #include "lj_obj.h" +#include "lj_err.h" #include "lj_buf.h" #include "lj_str.h" +#include "lj_meta.h" #include "lj_state.h" #include "lj_char.h" #include "lj_strfmt.h" +#if LJ_HASFFI +#include "lj_ctype.h" +#endif +#include "lj_lib.h" /* -- Format parser ------------------------------------------------------- */ @@ -161,6 +167,10 @@ const char *lj_strfmt_wstrnum(lua_State *L, cTValue *o, MSize *lenp) if (tvisstr(o)) { *lenp = strV(o)->len; return strVdata(o); + } else if (tvisbuf(o)) { + SBufExt *sbx = bufV(o); + *lenp = sbufxlen(sbx); + return sbx->r; } else if (tvisint(o)) { sb = lj_strfmt_putint(lj_buf_tmp_(L), intV(o)); } else if (tvisnum(o)) { @@ -169,7 +179,7 @@ const char *lj_strfmt_wstrnum(lua_State *L, cTValue *o, MSize *lenp) return NULL; } *lenp = sbuflen(sb); - return sbufB(sb); + return sb->b; } /* -- Unformatted conversions to buffer ----------------------------------- */ @@ -177,7 +187,7 @@ const char *lj_strfmt_wstrnum(lua_State *L, cTValue *o, MSize *lenp) /* Add integer to buffer. */ SBuf * LJ_FASTCALL lj_strfmt_putint(SBuf *sb, int32_t k) { - setsbufP(sb, lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT), k)); + sb->w = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT), k); return sb; } @@ -191,73 +201,86 @@ SBuf * LJ_FASTCALL lj_strfmt_putnum(SBuf *sb, cTValue *o) SBuf * LJ_FASTCALL lj_strfmt_putptr(SBuf *sb, const void *v) { - setsbufP(sb, lj_strfmt_wptr(lj_buf_more(sb, STRFMT_MAXBUF_PTR), v)); + sb->w = lj_strfmt_wptr(lj_buf_more(sb, STRFMT_MAXBUF_PTR), v); return sb; } /* Add quoted string to buffer. */ -SBuf * LJ_FASTCALL lj_strfmt_putquoted(SBuf *sb, GCstr *str) +static SBuf *strfmt_putquotedlen(SBuf *sb, const char *s, MSize len) { - const char *s = strdata(str); - MSize len = str->len; lj_buf_putb(sb, '"'); while (len--) { uint32_t c = (uint32_t)(uint8_t)*s++; - char *p = lj_buf_more(sb, 4); + char *w = lj_buf_more(sb, 4); if (c == '"' || c == '\\' || c == '\n') { - *p++ = '\\'; + *w++ = '\\'; } else if (lj_char_iscntrl(c)) { /* This can only be 0-31 or 127. */ uint32_t d; - *p++ = '\\'; + *w++ = '\\'; if (c >= 100 || lj_char_isdigit((uint8_t)*s)) { - *p++ = (char)('0'+(c >= 100)); if (c >= 100) c -= 100; + *w++ = (char)('0'+(c >= 100)); if (c >= 100) c -= 100; goto tens; } else if (c >= 10) { tens: - d = (c * 205) >> 11; c -= d * 10; *p++ = (char)('0'+d); + d = (c * 205) >> 11; c -= d * 10; *w++ = (char)('0'+d); } c += '0'; } - *p++ = (char)c; - setsbufP(sb, p); + *w++ = (char)c; + sb->w = w; } lj_buf_putb(sb, '"'); return sb; } +#if LJ_HASJIT +SBuf * LJ_FASTCALL lj_strfmt_putquoted(SBuf *sb, GCstr *str) +{ + return strfmt_putquotedlen(sb, strdata(str), str->len); +} +#endif + /* -- Formatted conversions to buffer ------------------------------------- */ /* Add formatted char to buffer. */ SBuf *lj_strfmt_putfchar(SBuf *sb, SFormat sf, int32_t c) { MSize width = STRFMT_WIDTH(sf); - char *p = lj_buf_more(sb, width > 1 ? width : 1); - if ((sf & STRFMT_F_LEFT)) *p++ = (char)c; - while (width-- > 1) *p++ = ' '; - if (!(sf & STRFMT_F_LEFT)) *p++ = (char)c; - setsbufP(sb, p); + char *w = lj_buf_more(sb, width > 1 ? width : 1); + if ((sf & STRFMT_F_LEFT)) *w++ = (char)c; + while (width-- > 1) *w++ = ' '; + if (!(sf & STRFMT_F_LEFT)) *w++ = (char)c; + sb->w = w; return sb; } /* Add formatted string to buffer. */ -SBuf *lj_strfmt_putfstr(SBuf *sb, SFormat sf, GCstr *str) +static SBuf *strfmt_putfstrlen(SBuf *sb, SFormat sf, const char *s, MSize len) { - MSize len = str->len <= STRFMT_PREC(sf) ? str->len : STRFMT_PREC(sf); MSize width = STRFMT_WIDTH(sf); - char *p = lj_buf_more(sb, width > len ? width : len); - if ((sf & STRFMT_F_LEFT)) p = lj_buf_wmem(p, strdata(str), len); - while (width-- > len) *p++ = ' '; - if (!(sf & STRFMT_F_LEFT)) p = lj_buf_wmem(p, strdata(str), len); - setsbufP(sb, p); + char *w; + if (len > STRFMT_PREC(sf)) len = STRFMT_PREC(sf); + w = lj_buf_more(sb, width > len ? width : len); + if ((sf & STRFMT_F_LEFT)) w = lj_buf_wmem(w, s, len); + while (width-- > len) *w++ = ' '; + if (!(sf & STRFMT_F_LEFT)) w = lj_buf_wmem(w, s, len); + sb->w = w; return sb; } +#if LJ_HASJIT +SBuf *lj_strfmt_putfstr(SBuf *sb, SFormat sf, GCstr *str) +{ + return strfmt_putfstrlen(sb, sf, strdata(str), str->len); +} +#endif + /* Add formatted signed/unsigned integer to buffer. */ SBuf *lj_strfmt_putfxint(SBuf *sb, SFormat sf, uint64_t k) { - char buf[STRFMT_MAXBUF_XINT], *q = buf + sizeof(buf), *p; + char buf[STRFMT_MAXBUF_XINT], *q = buf + sizeof(buf), *w; #ifdef LUA_USE_ASSERT - char *ps; + char *ws; #endif MSize prefix = 0, len, prec, pprec, width, need; @@ -301,27 +324,27 @@ SBuf *lj_strfmt_putfxint(SBuf *sb, SFormat sf, uint64_t k) width = STRFMT_WIDTH(sf); pprec = prec + (prefix >> 8); need = width > pprec ? width : pprec; - p = lj_buf_more(sb, need); + w = lj_buf_more(sb, need); #ifdef LUA_USE_ASSERT - ps = p; + ws = w; #endif /* Format number with leading/trailing whitespace and zeros. */ if ((sf & (STRFMT_F_LEFT|STRFMT_F_ZERO)) == 0) - while (width-- > pprec) *p++ = ' '; + while (width-- > pprec) *w++ = ' '; if (prefix) { - if ((char)prefix >= 'X') *p++ = '0'; - *p++ = (char)prefix; + if ((char)prefix >= 'X') *w++ = '0'; + *w++ = (char)prefix; } if ((sf & (STRFMT_F_LEFT|STRFMT_F_ZERO)) == STRFMT_F_ZERO) - while (width-- > pprec) *p++ = '0'; - while (prec-- > len) *p++ = '0'; - while (q < buf + sizeof(buf)) *p++ = *q++; /* Add number itself. */ + while (width-- > pprec) *w++ = '0'; + while (prec-- > len) *w++ = '0'; + while (q < buf + sizeof(buf)) *w++ = *q++; /* Add number itself. */ if ((sf & STRFMT_F_LEFT)) - while (width-- > pprec) *p++ = ' '; + while (width-- > pprec) *w++ = ' '; - lj_assertX(need == (MSize)(p - ps), "miscalculated format size"); - setsbufP(sb, p); + lj_assertX(need == (MSize)(w - ws), "miscalculated format size"); + sb->w = w; return sb; } @@ -346,6 +369,117 @@ SBuf *lj_strfmt_putfnum_uint(SBuf *sb, SFormat sf, lua_Number n) return lj_strfmt_putfxint(sb, sf, (uint64_t)k); } +/* Format stack arguments to buffer. */ +int lj_strfmt_putarg(lua_State *L, SBuf *sb, int arg, int retry) +{ + int narg = (int)(L->top - L->base); + GCstr *fmt = lj_lib_checkstr(L, arg); + FormatState fs; + SFormat sf; + lj_strfmt_init(&fs, strdata(fmt), fmt->len); + while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { + if (sf == STRFMT_LIT) { + lj_buf_putmem(sb, fs.str, fs.len); + } else if (sf == STRFMT_ERR) { + lj_err_callerv(L, LJ_ERR_STRFMT, + strdata(lj_str_new(L, fs.str, fs.len))); + } else { + TValue *o = &L->base[arg++]; + if (arg > narg) + lj_err_arg(L, arg, LJ_ERR_NOVAL); + switch (STRFMT_TYPE(sf)) { + case STRFMT_INT: + if (tvisint(o)) { + int32_t k = intV(o); + if (sf == STRFMT_INT) + lj_strfmt_putint(sb, k); /* Shortcut for plain %d. */ + else + lj_strfmt_putfxint(sb, sf, k); + break; + } +#if LJ_HASFFI + if (tviscdata(o)) { + GCcdata *cd = cdataV(o); + if (cd->ctypeid == CTID_INT64 || cd->ctypeid == CTID_UINT64) { + lj_strfmt_putfxint(sb, sf, *(uint64_t *)cdataptr(cd)); + break; + } + } +#endif + lj_strfmt_putfnum_int(sb, sf, lj_lib_checknum(L, arg)); + break; + case STRFMT_UINT: + if (tvisint(o)) { + lj_strfmt_putfxint(sb, sf, intV(o)); + break; + } +#if LJ_HASFFI + if (tviscdata(o)) { + GCcdata *cd = cdataV(o); + if (cd->ctypeid == CTID_INT64 || cd->ctypeid == CTID_UINT64) { + lj_strfmt_putfxint(sb, sf, *(uint64_t *)cdataptr(cd)); + break; + } + } +#endif + lj_strfmt_putfnum_uint(sb, sf, lj_lib_checknum(L, arg)); + break; + case STRFMT_NUM: + lj_strfmt_putfnum(sb, sf, lj_lib_checknum(L, arg)); + break; + case STRFMT_STR: { + MSize len; + const char *s; + cTValue *mo; + if (LJ_UNLIKELY(!tvisstr(o) && !tvisbuf(o)) && retry >= 0 && + !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { + /* Call __tostring metamethod once. */ + copyTV(L, L->top++, mo); + copyTV(L, L->top++, o); + lua_call(L, 1, 1); + o = &L->base[arg-1]; /* Stack may have been reallocated. */ + copyTV(L, o, --L->top); /* Replace inline for retry. */ + if (retry < 2) { /* Global buffer may have been overwritten. */ + retry = 1; + break; + } + } + if (LJ_LIKELY(tvisstr(o))) { + len = strV(o)->len; + s = strVdata(o); +#if LJ_HASBUFFER + } else if (tvisbuf(o)) { + SBufExt *sbx = bufV(o); + if (sbx == (SBufExt *)sb) lj_err_arg(L, arg+1, LJ_ERR_BUFFER_SELF); + len = sbufxlen(sbx); + s = sbx->r; +#endif + } else { + GCstr *str = lj_strfmt_obj(L, o); + len = str->len; + s = strdata(str); + } + if ((sf & STRFMT_T_QUOTED)) + strfmt_putquotedlen(sb, s, len); /* No formatting. */ + else + strfmt_putfstrlen(sb, sf, s, len); + break; + } + case STRFMT_CHAR: + lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg)); + break; + case STRFMT_PTR: /* No formatting. */ + lj_strfmt_putptr(sb, lj_obj_ptr(G(L), o)); + break; + default: + lj_assertL(0, "bad string format type"); + break; + } + } + } + return retry; +} + /* -- Conversions to strings ---------------------------------------------- */ /* Convert integer to string. */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_strfmt.h b/love/src/jni/LuaJIT-2.1/src/lj_strfmt.h index fa25dcd0..cb2c7360 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_strfmt.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_strfmt.h @@ -95,7 +95,9 @@ LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putint(SBuf *sb, int32_t k); LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putnum(SBuf *sb, cTValue *o); #endif LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putptr(SBuf *sb, const void *v); +#if LJ_HASJIT LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putquoted(SBuf *sb, GCstr *str); +#endif /* Formatted conversions to buffer. */ LJ_FUNC SBuf *lj_strfmt_putfxint(SBuf *sb, SFormat sf, uint64_t k); @@ -103,7 +105,10 @@ LJ_FUNC SBuf *lj_strfmt_putfnum_int(SBuf *sb, SFormat sf, lua_Number n); LJ_FUNC SBuf *lj_strfmt_putfnum_uint(SBuf *sb, SFormat sf, lua_Number n); LJ_FUNC SBuf *lj_strfmt_putfnum(SBuf *sb, SFormat, lua_Number n); LJ_FUNC SBuf *lj_strfmt_putfchar(SBuf *sb, SFormat, int32_t c); +#if LJ_HASJIT LJ_FUNC SBuf *lj_strfmt_putfstr(SBuf *sb, SFormat, GCstr *str); +#endif +LJ_FUNC int lj_strfmt_putarg(lua_State *L, SBuf *sb, int arg, int retry); /* Conversions to strings. */ LJ_FUNC GCstr * LJ_FASTCALL lj_strfmt_int(lua_State *L, int32_t k); diff --git a/love/src/jni/LuaJIT-2.1/src/lj_strfmt_num.c b/love/src/jni/LuaJIT-2.1/src/lj_strfmt_num.c index 66f83af3..dfd56bd4 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_strfmt_num.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_strfmt_num.c @@ -576,7 +576,7 @@ static char *lj_strfmt_wfnum(SBuf *sb, SFormat sf, lua_Number n, char *p) /* Add formatted floating-point number to buffer. */ SBuf *lj_strfmt_putfnum(SBuf *sb, SFormat sf, lua_Number n) { - setsbufP(sb, lj_strfmt_wfnum(sb, sf, n, NULL)); + sb->w = lj_strfmt_wfnum(sb, sf, n, NULL); return sb; } diff --git a/love/src/jni/LuaJIT-2.1/src/lj_tab.c b/love/src/jni/LuaJIT-2.1/src/lj_tab.c index 27e58f0a..4113839f 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_tab.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_tab.c @@ -16,25 +16,6 @@ /* -- Object hashing ------------------------------------------------------ */ -/* Hash values are masked with the table hash mask and used as an index. */ -static LJ_AINLINE Node *hashmask(const GCtab *t, uint32_t hash) -{ - Node *n = noderef(t->node); - return &n[hash & t->hmask]; -} - -/* String IDs are generated when a string is interned. */ -#define hashstr(t, s) hashmask(t, (s)->sid) - -#define hashlohi(t, lo, hi) hashmask((t), hashrot((lo), (hi))) -#define hashnum(t, o) hashlohi((t), (o)->u32.lo, ((o)->u32.hi << 1)) -#if LJ_GC64 -#define hashgcref(t, r) \ - hashlohi((t), (uint32_t)gcrefu(r), (uint32_t)(gcrefu(r) >> 32)) -#else -#define hashgcref(t, r) hashlohi((t), gcrefu(r), gcrefu(r) + HASH_BIAS) -#endif - /* Hash an arbitrary key and return its anchor position in the hash table. */ static Node *hashkey(const GCtab *t, cTValue *key) { @@ -413,7 +394,7 @@ cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key) return NULL; } -cTValue *lj_tab_getstr(GCtab *t, GCstr *key) +cTValue *lj_tab_getstr(GCtab *t, const GCstr *key) { Node *n = hashstr(t, key); do { @@ -546,7 +527,7 @@ TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key) return lj_tab_newkey(L, t, &k); } -TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key) +TValue *lj_tab_setstr(lua_State *L, GCtab *t, const GCstr *key) { TValue k; Node *n = hashstr(t, key); @@ -587,56 +568,66 @@ TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key) /* -- Table traversal ----------------------------------------------------- */ -/* Get the traversal index of a key. */ -static uint32_t keyindex(lua_State *L, GCtab *t, cTValue *key) +/* Table traversal indexes: +** +** Array key index: [0 .. t->asize-1] +** Hash key index: [t->asize .. t->asize+t->hmask] +** Invalid key: ~0 +*/ + +/* Get the successor traversal index of a key. */ +uint32_t LJ_FASTCALL lj_tab_keyindex(GCtab *t, cTValue *key) { TValue tmp; if (tvisint(key)) { int32_t k = intV(key); if ((uint32_t)k < t->asize) - return (uint32_t)k; /* Array key indexes: [0..t->asize-1] */ + return (uint32_t)k + 1; setnumV(&tmp, (lua_Number)k); key = &tmp; } else if (tvisnum(key)) { lua_Number nk = numV(key); int32_t k = lj_num2int(nk); if ((uint32_t)k < t->asize && nk == (lua_Number)k) - return (uint32_t)k; /* Array key indexes: [0..t->asize-1] */ + return (uint32_t)k + 1; } if (!tvisnil(key)) { Node *n = hashkey(t, key); do { if (lj_obj_equal(&n->key, key)) - return t->asize + (uint32_t)(n - noderef(t->node)); - /* Hash key indexes: [t->asize..t->asize+t->nmask] */ + return t->asize + (uint32_t)((n+1) - noderef(t->node)); } while ((n = nextnode(n))); - if (key->u32.hi == 0xfffe7fff) /* ITERN was despecialized while running. */ - return key->u32.lo - 1; - lj_err_msg(L, LJ_ERR_NEXTIDX); - return 0; /* unreachable */ + if (key->u32.hi == LJ_KEYINDEX) /* Despecialized ITERN while running. */ + return key->u32.lo; + return ~0u; /* Invalid key to next. */ } - return ~0u; /* A nil key starts the traversal. */ + return 0; /* A nil key starts the traversal. */ } -/* Advance to the next step in a table traversal. */ -int lj_tab_next(lua_State *L, GCtab *t, TValue *key) +/* Get the next key/value pair of a table traversal. */ +int lj_tab_next(GCtab *t, cTValue *key, TValue *o) { - uint32_t i = keyindex(L, t, key); /* Find predecessor key index. */ - for (i++; i < t->asize; i++) /* First traverse the array keys. */ - if (!tvisnil(arrayslot(t, i))) { - setintV(key, i); - copyTV(L, key+1, arrayslot(t, i)); - return 1; - } - for (i -= t->asize; i <= t->hmask; i++) { /* Then traverse the hash keys. */ - Node *n = &noderef(t->node)[i]; - if (!tvisnil(&n->val)) { - copyTV(L, key, &n->key); - copyTV(L, key+1, &n->val); + uint32_t idx = lj_tab_keyindex(t, key); /* Find successor index of key. */ + /* First traverse the array part. */ + for (; idx < t->asize; idx++) { + cTValue *a = arrayslot(t, idx); + if (LJ_LIKELY(!tvisnil(a))) { + setintV(o, idx); + o[1] = *a; return 1; } } - return 0; /* End of traversal. */ + idx -= t->asize; + /* Then traverse the hash part. */ + for (; idx <= t->hmask; idx++) { + Node *n = &noderef(t->node)[idx]; + if (!tvisnil(&n->val)) { + o[0] = n->key; + o[1] = n->val; + return 1; + } + } + return (int32_t)idx < 0 ? -1 : 0; /* Invalid key or end of traversal. */ } /* -- Table length calculation -------------------------------------------- */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_tab.h b/love/src/jni/LuaJIT-2.1/src/lj_tab.h index 97436cc0..e0e81ff7 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_tab.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_tab.h @@ -31,6 +31,25 @@ static LJ_AINLINE uint32_t hashrot(uint32_t lo, uint32_t hi) return hi; } +/* Hash values are masked with the table hash mask and used as an index. */ +static LJ_AINLINE Node *hashmask(const GCtab *t, uint32_t hash) +{ + Node *n = noderef(t->node); + return &n[hash & t->hmask]; +} + +/* String IDs are generated when a string is interned. */ +#define hashstr(t, s) hashmask(t, (s)->sid) + +#define hashlohi(t, lo, hi) hashmask((t), hashrot((lo), (hi))) +#define hashnum(t, o) hashlohi((t), (o)->u32.lo, ((o)->u32.hi << 1)) +#if LJ_GC64 +#define hashgcref(t, r) \ + hashlohi((t), (uint32_t)gcrefu(r), (uint32_t)(gcrefu(r) >> 32)) +#else +#define hashgcref(t, r) hashlohi((t), gcrefu(r), gcrefu(r) + HASH_BIAS) +#endif + #define hsize2hbits(s) ((s) ? ((s)==1 ? 1 : 1+lj_fls((uint32_t)((s)-1))) : 0) LJ_FUNCA GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits); @@ -50,14 +69,14 @@ LJ_FUNCA void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize); /* Caveat: all getters except lj_tab_get() can return NULL! */ LJ_FUNCA cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key); -LJ_FUNC cTValue *lj_tab_getstr(GCtab *t, GCstr *key); +LJ_FUNC cTValue *lj_tab_getstr(GCtab *t, const GCstr *key); LJ_FUNCA cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key); /* Caveat: all setters require a write barrier for the stored value. */ LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key); LJ_FUNCA TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key); -LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key); +LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, const GCstr *key); LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key); #define inarray(t, key) ((MSize)(key) < (MSize)(t)->asize) @@ -67,7 +86,8 @@ LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key); #define lj_tab_setint(L, t, key) \ (inarray((t), (key)) ? arrayslot((t), (key)) : lj_tab_setinth(L, (t), (key))) -LJ_FUNCA int lj_tab_next(lua_State *L, GCtab *t, TValue *key); +LJ_FUNC uint32_t LJ_FASTCALL lj_tab_keyindex(GCtab *t, cTValue *key); +LJ_FUNCA int lj_tab_next(GCtab *t, cTValue *key, TValue *o); LJ_FUNCA MSize LJ_FASTCALL lj_tab_len(GCtab *t); #if LJ_HASJIT LJ_FUNC MSize LJ_FASTCALL lj_tab_len_hint(GCtab *t, size_t hint); diff --git a/love/src/jni/LuaJIT-2.1/src/lj_target_arm.h b/love/src/jni/LuaJIT-2.1/src/lj_target_arm.h index f41f53e9..72516bc2 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_target_arm.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_target_arm.h @@ -211,6 +211,7 @@ typedef enum ARMIns { /* ARMv6T2 */ ARMI_MOVW = 0xe3000000, ARMI_MOVT = 0xe3400000, + ARMI_BFI = 0xe7c00010, /* VFP */ ARMI_VMOV_D = 0xeeb00b40, diff --git a/love/src/jni/LuaJIT-2.1/src/lj_target_arm64.h b/love/src/jni/LuaJIT-2.1/src/lj_target_arm64.h index c2f71153..6d39ffb8 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_target_arm64.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_target_arm64.h @@ -31,6 +31,8 @@ enum { /* Calling conventions. */ RID_RET = RID_X0, + RID_RETLO = RID_X0, + RID_RETHI = RID_X1, RID_FPRET = RID_D0, /* These definitions must match with the *.dasc file(s): */ @@ -210,6 +212,8 @@ typedef enum A64Ins { A64I_EXTRw = 0x13800000, A64I_EXTRx = 0x93c00000, + A64I_BFMw = 0x33000000, + A64I_BFMx = 0xb3400000, A64I_SBFMw = 0x13000000, A64I_SBFMx = 0x93400000, A64I_SXTBw = 0x13001c00, diff --git a/love/src/jni/LuaJIT-2.1/src/lj_target_mips.h b/love/src/jni/LuaJIT-2.1/src/lj_target_mips.h index 8d8f68ec..5da94605 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_target_mips.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_target_mips.h @@ -256,6 +256,8 @@ typedef enum MIPSIns { MIPSI_ROTRV = 0x00000046, /* MIPSXXR2 */ MIPSI_DROTRV = 0x00000056, + MIPSI_INS = 0x7c000004, /* MIPSXXR2 */ + MIPSI_SEB = 0x7c000420, /* MIPSXXR2 */ MIPSI_SEH = 0x7c000620, /* MIPSXXR2 */ MIPSI_WSBH = 0x7c0000a0, /* MIPSXXR2 */ diff --git a/love/src/jni/LuaJIT-2.1/src/lj_target_x86.h b/love/src/jni/LuaJIT-2.1/src/lj_target_x86.h index 4be5f04c..d0ce196c 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_target_x86.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_target_x86.h @@ -38,10 +38,9 @@ enum { RID_RET = RID_EAX, #if LJ_64 RID_FPRET = RID_XMM0, -#else +#endif RID_RETLO = RID_EAX, RID_RETHI = RID_EDX, -#endif /* These definitions must match with the *.dasc file(s): */ RID_BASE = RID_EDX, /* Interpreter BASE. */ @@ -165,6 +164,8 @@ typedef struct { #define EXITSTUB_SPACING (2+2) #define EXITSTUBS_PER_GROUP 32 +#define EXITTRACE_VMSTATE 1 /* g->vmstate has traceno on exit. */ + /* -- x86 ModRM operand encoding ------------------------------------------ */ typedef enum { diff --git a/love/src/jni/LuaJIT-2.1/src/lj_trace.c b/love/src/jni/LuaJIT-2.1/src/lj_trace.c index 4608f81f..43b86e4f 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_trace.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_trace.c @@ -215,8 +215,8 @@ static void trace_unpatch(jit_State *J, GCtrace *T) break; case BC_JITERL: case BC_JLOOP: - lj_assertJ(op == BC_ITERL || op == BC_LOOP || bc_isret(op), - "bad original bytecode %d", op); + lj_assertJ(op == BC_ITERL || op == BC_ITERN || op == BC_LOOP || + bc_isret(op), "bad original bytecode %d", op); *pc = T->startins; break; case BC_JMP: @@ -373,8 +373,13 @@ void lj_trace_freestate(global_State *g) /* Blacklist a bytecode instruction. */ static void blacklist_pc(GCproto *pt, BCIns *pc) { - setbc_op(pc, (int)bc_op(*pc)+(int)BC_ILOOP-(int)BC_LOOP); - pt->flags |= PROTO_ILOOP; + if (bc_op(*pc) == BC_ITERN) { + setbc_op(pc, BC_ITERC); + setbc_op(pc+1+bc_j(pc[1]), BC_JMP); + } else { + setbc_op(pc, (int)bc_op(*pc)+(int)BC_ILOOP-(int)BC_LOOP); + pt->flags |= PROTO_ILOOP; + } } /* Penalize a bytecode instruction. */ @@ -411,7 +416,7 @@ static void trace_start(jit_State *J) TraceNo traceno; if ((J->pt->flags & PROTO_NOJIT)) { /* JIT disabled for this proto? */ - if (J->parent == 0 && J->exitno == 0) { + if (J->parent == 0 && J->exitno == 0 && bc_op(*J->pc) != BC_ITERN) { /* Lazy bytecode patching to disable hotcount events. */ lj_assertJ(bc_op(*J->pc) == BC_FORL || bc_op(*J->pc) == BC_ITERL || bc_op(*J->pc) == BC_LOOP || bc_op(*J->pc) == BC_FUNCF, @@ -496,6 +501,7 @@ static void trace_stop(jit_State *J) J->cur.nextroot = pt->trace; pt->trace = (TraceNo1)traceno; break; + case BC_ITERN: case BC_RET: case BC_RET0: case BC_RET1: @@ -506,7 +512,11 @@ static void trace_stop(jit_State *J) lj_assertJ(J->parent != 0 && J->cur.root != 0, "not a side trace"); lj_asm_patchexit(J, traceref(J, J->parent), J->exitno, J->cur.mcode); /* Avoid compiling a side trace twice (stack resizing uses parent exit). */ - traceref(J, J->parent)->snap[J->exitno].count = SNAPCOUNT_DONE; + { + SnapShot *snap = &traceref(J, J->parent)->snap[J->exitno]; + snap->count = SNAPCOUNT_DONE; + if (J->cur.topslot > snap->topslot) snap->topslot = J->cur.topslot; + } /* Add to side trace chain in root trace. */ { GCtrace *root = traceref(J, J->cur.root); @@ -651,8 +661,13 @@ static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud) J->state = LJ_TRACE_RECORD; /* trace_start() may change state. */ trace_start(J); lj_dispatch_update(J2G(J)); - break; + if (J->state != LJ_TRACE_RECORD_1ST) + break; + /* fallthrough */ + case LJ_TRACE_RECORD_1ST: + J->state = LJ_TRACE_RECORD; + /* fallthrough */ case LJ_TRACE_RECORD: trace_pendpatch(J, 0); setvmstate(J2G(J), RECORD); @@ -821,7 +836,7 @@ static void trace_exit_regs(lua_State *L, ExitState *ex) } #endif -#ifdef EXITSTATE_PCREG +#if defined(EXITSTATE_PCREG) || (LJ_UNWIND_JIT && !EXITTRACE_VMSTATE) /* Determine trace number from pc of exit instruction. */ static TraceNo trace_exit_find(jit_State *J, MCode *pc) { @@ -843,10 +858,18 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) lua_State *L = J->L; ExitState *ex = (ExitState *)exptr; ExitDataCP exd; - int errcode; + int errcode, exitcode = J->exitcode; + TValue exiterr; const BCIns *pc; void *cf; GCtrace *T; + + setnilV(&exiterr); + if (exitcode) { /* Trace unwound with error code. */ + J->exitcode = 0; + copyTV(L, &exiterr, L->top-1); + } + #ifdef EXITSTATE_PCREG J->parent = trace_exit_find(J, (MCode *)(intptr_t)ex->gpr[EXITSTATE_PCREG]); #endif @@ -866,6 +889,8 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) if (errcode) return -errcode; /* Return negated error code. */ + if (exitcode) copyTV(L, L->top++, &exiterr); /* Anchor the error object. */ + if (!(LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE))) lj_vmevent_send(L, TEXIT, lj_state_checkstack(L, 4+RID_NUM_GPR+RID_NUM_FPR+LUA_MINSTACK); @@ -877,7 +902,9 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) pc = exd.pc; cf = cframe_raw(L->cframe); setcframe_pc(cf, pc); - if (LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE)) { + if (exitcode) { + return -exitcode; + } else if (LJ_HASPROFILE && (G(L)->hookmask & HOOK_PROFILE)) { /* Just exit to interpreter. */ } else if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) { if (!(G(L)->hookmask & HOOK_GC)) @@ -887,13 +914,14 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) } if (bc_op(*pc) == BC_JLOOP) { BCIns *retpc = &traceref(J, bc_d(*pc))->startins; - if (bc_isret(bc_op(*retpc))) { + int isret = bc_isret(bc_op(*retpc)); + if (isret || bc_op(*retpc) == BC_ITERN) { if (J->state == LJ_TRACE_RECORD) { J->patchins = *pc; J->patchpc = (BCIns *)pc; *J->patchpc = *retpc; J->bcskip = 1; - } else { + } else if (isret) { pc = retpc; setcframe_pc(cf, pc); } @@ -915,4 +943,41 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) } } +#if LJ_UNWIND_JIT +/* Given an mcode address determine trace exit address for unwinding. */ +uintptr_t LJ_FASTCALL lj_trace_unwind(jit_State *J, uintptr_t addr, ExitNo *ep) +{ +#if EXITTRACE_VMSTATE + TraceNo traceno = J2G(J)->vmstate; +#else + TraceNo traceno = trace_exit_find(J, (MCode *)addr); +#endif + GCtrace *T = traceref(J, traceno); + if (T +#if EXITTRACE_VMSTATE + && addr >= (uintptr_t)T->mcode && addr < (uintptr_t)T->mcode + T->szmcode +#endif + ) { + SnapShot *snap = T->snap; + SnapNo lo = 0, exitno = T->nsnap; + uintptr_t ofs = (uintptr_t)((MCode *)addr - T->mcode); /* MCode units! */ + /* Rightmost binary search for mcode offset to determine exit number. */ + do { + SnapNo mid = (lo+exitno) >> 1; + if (ofs < snap[mid].mcofs) exitno = mid; else lo = mid + 1; + } while (lo < exitno); + exitno--; + *ep = exitno; +#ifdef EXITSTUBS_PER_GROUP + return (uintptr_t)exitstub_addr(J, exitno); +#else + return (uintptr_t)exitstub_trace_addr(T, exitno); +#endif + } + /* Cannot correlate addr with trace/exit. This will be fatal. */ + lj_assertJ(0, "bad exit pc"); + return 0; +} +#endif + #endif diff --git a/love/src/jni/LuaJIT-2.1/src/lj_trace.h b/love/src/jni/LuaJIT-2.1/src/lj_trace.h index 7e86d963..e4cf2dc4 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_trace.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_trace.h @@ -37,6 +37,9 @@ LJ_FUNC void lj_trace_ins(jit_State *J, const BCIns *pc); LJ_FUNCA void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc); LJ_FUNCA void LJ_FASTCALL lj_trace_stitch(jit_State *J, const BCIns *pc); LJ_FUNCA int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr); +#if LJ_UNWIND_EXT +LJ_FUNC uintptr_t LJ_FASTCALL lj_trace_unwind(jit_State *J, uintptr_t addr, ExitNo *ep); +#endif /* Signal asynchronous abort of trace or end of trace. */ #define lj_trace_abort(g) (G2J(g)->state &= ~LJ_TRACE_ACTIVE) diff --git a/love/src/jni/LuaJIT-2.1/src/lj_udata.c b/love/src/jni/LuaJIT-2.1/src/lj_udata.c index ec3478c8..a0edd0df 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_udata.c +++ b/love/src/jni/LuaJIT-2.1/src/lj_udata.c @@ -8,6 +8,7 @@ #include "lj_obj.h" #include "lj_gc.h" +#include "lj_err.h" #include "lj_udata.h" GCudata *lj_udata_new(lua_State *L, MSize sz, GCtab *env) @@ -32,3 +33,30 @@ void LJ_FASTCALL lj_udata_free(global_State *g, GCudata *ud) lj_mem_free(g, ud, sizeudata(ud)); } +#if LJ_64 +void *lj_lightud_intern(lua_State *L, void *p) +{ + global_State *g = G(L); + uint64_t u = (uint64_t)p; + uint32_t up = lightudup(u); + uint32_t *segmap = mref(g->gc.lightudseg, uint32_t); + MSize segnum = g->gc.lightudnum; + if (segmap) { + MSize seg; + for (seg = 0; seg <= segnum; seg++) + if (segmap[seg] == up) /* Fast path. */ + return (void *)(((uint64_t)seg << LJ_LIGHTUD_BITS_LO) | lightudlo(u)); + segnum++; + /* Leave last segment unused to avoid clash with ITERN key. */ + if (segnum >= (1 << LJ_LIGHTUD_BITS_SEG)-1) lj_err_msg(L, LJ_ERR_BADLU); + } + if (!((segnum-1) & segnum) && segnum != 1) { + lj_mem_reallocvec(L, segmap, segnum, segnum ? 2*segnum : 2u, uint32_t); + setmref(g->gc.lightudseg, segmap); + } + g->gc.lightudnum = segnum; + segmap[segnum] = up; + return (void *)(((uint64_t)segnum << LJ_LIGHTUD_BITS_LO) | lightudlo(u)); +} +#endif + diff --git a/love/src/jni/LuaJIT-2.1/src/lj_udata.h b/love/src/jni/LuaJIT-2.1/src/lj_udata.h index 1873b694..78522ecc 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_udata.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_udata.h @@ -10,5 +10,8 @@ LJ_FUNC GCudata *lj_udata_new(lua_State *L, MSize sz, GCtab *env); LJ_FUNC void LJ_FASTCALL lj_udata_free(global_State *g, GCudata *ud); +#if LJ_64 +LJ_FUNC void * LJ_FASTCALL lj_lightud_intern(lua_State *L, void *p); +#endif #endif diff --git a/love/src/jni/LuaJIT-2.1/src/lj_vm.h b/love/src/jni/LuaJIT-2.1/src/lj_vm.h index 6358dc58..81ee8e28 100644 --- a/love/src/jni/LuaJIT-2.1/src/lj_vm.h +++ b/love/src/jni/LuaJIT-2.1/src/lj_vm.h @@ -26,6 +26,9 @@ LJ_ASMF void lj_vm_unwind_ff_eh(void); #if LJ_TARGET_X86ORX64 LJ_ASMF void lj_vm_unwind_rethrow(void); #endif +#if LJ_TARGET_MIPS +LJ_ASMF void lj_vm_unwind_stub(void); +#endif /* Miscellaneous functions. */ #if LJ_TARGET_X86ORX64 @@ -48,6 +51,7 @@ LJ_ASMF void lj_vm_inshook(void); LJ_ASMF void lj_vm_rethook(void); LJ_ASMF void lj_vm_callhook(void); LJ_ASMF void lj_vm_profhook(void); +LJ_ASMF void lj_vm_IITERN(void); /* Trace exit handling. */ LJ_ASMF void lj_vm_exit_handler(void); @@ -95,6 +99,7 @@ LJ_ASMF double lj_vm_trunc_sf(double); #if LJ_HASFFI LJ_ASMF int lj_vm_errno(void); #endif +LJ_ASMF TValue *lj_vm_next(GCtab *t, uint32_t idx); #endif /* Continuations for metamethods. */ diff --git a/love/src/jni/LuaJIT-2.1/src/ljamalg.c b/love/src/jni/LuaJIT-2.1/src/ljamalg.c index 8e2d4937..384b3cc1 100644 --- a/love/src/jni/LuaJIT-2.1/src/ljamalg.c +++ b/love/src/jni/LuaJIT-2.1/src/ljamalg.c @@ -39,6 +39,7 @@ #include "lj_strscan.c" #include "lj_strfmt.c" #include "lj_strfmt_num.c" +#include "lj_serialize.c" #include "lj_api.c" #include "lj_profile.c" #include "lj_lex.c" @@ -85,5 +86,6 @@ #include "lib_bit.c" #include "lib_jit.c" #include "lib_ffi.c" +#include "lib_buffer.c" #include "lib_init.c" diff --git a/love/src/jni/LuaJIT-2.1/src/lualib.h b/love/src/jni/LuaJIT-2.1/src/lualib.h index 9cd39880..5c18e9ec 100644 --- a/love/src/jni/LuaJIT-2.1/src/lualib.h +++ b/love/src/jni/LuaJIT-2.1/src/lualib.h @@ -33,6 +33,7 @@ LUALIB_API int luaopen_debug(lua_State *L); LUALIB_API int luaopen_bit(lua_State *L); LUALIB_API int luaopen_jit(lua_State *L); LUALIB_API int luaopen_ffi(lua_State *L); +LUALIB_API int luaopen_string_buffer(lua_State *L); LUALIB_API void luaL_openlibs(lua_State *L); diff --git a/love/src/jni/LuaJIT-2.1/src/msvcbuild.bat b/love/src/jni/LuaJIT-2.1/src/msvcbuild.bat index d0768948..7e1a6e04 100644 --- a/love/src/jni/LuaJIT-2.1/src/msvcbuild.bat +++ b/love/src/jni/LuaJIT-2.1/src/msvcbuild.bat @@ -25,7 +25,7 @@ @set LJDLLNAME=lua51.dll @set LJLIBNAME=lua51.lib @set BUILDTYPE=release -@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c +@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c %LJCOMPILE% host\minilua.c @if errorlevel 1 goto :BAD diff --git a/love/src/jni/LuaJIT-2.1/src/ps4build.bat b/love/src/jni/LuaJIT-2.1/src/ps4build.bat index e83c674a..fdd09d81 100644 --- a/love/src/jni/LuaJIT-2.1/src/ps4build.bat +++ b/love/src/jni/LuaJIT-2.1/src/ps4build.bat @@ -26,7 +26,7 @@ @set LJMT=mt /nologo @set DASMDIR=..\dynasm @set DASM=%DASMDIR%\dynasm.lua -@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c +@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c @set GC64= @set DASC=vm_x64.dasc diff --git a/love/src/jni/LuaJIT-2.1/src/psvitabuild.bat b/love/src/jni/LuaJIT-2.1/src/psvitabuild.bat index 3991dc65..2980e157 100644 --- a/love/src/jni/LuaJIT-2.1/src/psvitabuild.bat +++ b/love/src/jni/LuaJIT-2.1/src/psvitabuild.bat @@ -14,7 +14,7 @@ @set LJMT=mt /nologo @set DASMDIR=..\dynasm @set DASM=%DASMDIR%\dynasm.lua -@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c +@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c %LJCOMPILE% host\minilua.c @if errorlevel 1 goto :BAD diff --git a/love/src/jni/LuaJIT-2.1/src/vm_arm.dasc b/love/src/jni/LuaJIT-2.1/src/vm_arm.dasc index 5efda227..405be30a 100644 --- a/love/src/jni/LuaJIT-2.1/src/vm_arm.dasc +++ b/love/src/jni/LuaJIT-2.1/src/vm_arm.dasc @@ -539,13 +539,13 @@ static void build_subroutines(BuildCtx *ctx) | cmp CARG1, #1 |.endif | ldr PC, [CARG4, #-12] // Restore PC from [cont|PC]. - | ldr CARG3, LFUNC:CARG3->field_pc | mvn INS, #~LJ_TNIL | add CARG2, RA, RC | str INS, [CARG2, #-4] // Ensure one valid arg. |.if FFI | bls >1 |.endif + | ldr CARG3, LFUNC:CARG3->field_pc | ldr KBASE, [CARG3, #PC2PROTO(k)] | // BASE = base, RA = resultptr, CARG4 = meta base | bx CARG1 @@ -1111,24 +1111,18 @@ static void build_subroutines(BuildCtx *ctx) | checktab CARG2, ->fff_fallback | strd CARG34, [BASE, NARGS8:RC] // Set missing 2nd arg to nil. | ldr PC, [BASE, FRAME_PC] - | mov CARG2, CARG1 - | str BASE, L->base // Add frame since C call can throw. - | mov CARG1, L - | str BASE, L->top // Dummy frame length is ok. - | add CARG3, BASE, #8 - | str PC, SAVE_PC - | bl extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) - | // Returns 0 at end of traversal. + | add CARG2, BASE, #8 + | sub CARG3, BASE, #8 + | bl extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) + | // Returns 1=found, 0=end, -1=error. | .IOS ldr BASE, L->base | cmp CRET1, #0 - | mvneq CRET2, #~LJ_TNIL - | beq ->fff_restv // End of traversal: return nil. - | ldrd CARG12, [BASE, #8] // Copy key and value to results. - | ldrd CARG34, [BASE, #16] - | mov RC, #(2+1)*8 - | strd CARG12, [BASE, #-8] - | strd CARG34, [BASE] - | b ->fff_res + | mov RC, #(2+1)*8 + | bgt ->fff_res // Found key/value. + | bmi ->fff_fallback // Invalid key. + | // End of traversal: return nil. + | mvn CRET2, #~LJ_TNIL + | b ->fff_restv | |.ffunc_1 pairs | checktab CARG2, ->fff_fallback @@ -1810,7 +1804,7 @@ static void build_subroutines(BuildCtx *ctx) | str BASE, L->base | str PC, SAVE_PC | str L, SBUF:CARG1->L - | str CARG4, SBUF:CARG1->p + | str CARG4, SBUF:CARG1->w | bl extern lj_buf_putstr_ .. name | bl extern lj_buf_tostr | b ->fff_resstr @@ -2245,8 +2239,9 @@ static void build_subroutines(BuildCtx *ctx) | b <2 | |9: // Rethrow error from the right C frame. + | rsb CARG2, CARG1, #0 | mov CARG1, L - | bl extern lj_err_run // (lua_State *L) + | bl extern lj_err_trace // (lua_State *L, int errcode) |.endif | |//----------------------------------------------------------------------- @@ -2429,6 +2424,64 @@ static void build_subroutines(BuildCtx *ctx) |//-- Miscellaneous functions -------------------------------------------- |//----------------------------------------------------------------------- | + |.define NEXT_TAB, TAB:CARG1 + |.define NEXT_RES, CARG1 + |.define NEXT_IDX, CARG2 + |.define NEXT_TMP0, CARG3 + |.define NEXT_TMP1, CARG4 + |.define NEXT_LIM, r12 + |.define NEXT_RES_PTR, sp + |.define NEXT_RES_VAL, [sp] + |.define NEXT_RES_KEY_I, [sp, #8] + |.define NEXT_RES_KEY_IT, [sp, #12] + | + |// TValue *lj_vm_next(GCtab *t, uint32_t idx) + |// Next idx returned in CRET2. + |->vm_next: + |.if JIT + | ldr NEXT_TMP0, NEXT_TAB->array + | ldr NEXT_LIM, NEXT_TAB->asize + | add NEXT_TMP0, NEXT_TMP0, NEXT_IDX, lsl #3 + |1: // Traverse array part. + | subs NEXT_TMP1, NEXT_IDX, NEXT_LIM + | bhs >5 + | ldr NEXT_TMP1, [NEXT_TMP0, #4] + | str NEXT_IDX, NEXT_RES_KEY_I + | add NEXT_TMP0, NEXT_TMP0, #8 + | add NEXT_IDX, NEXT_IDX, #1 + | checktp NEXT_TMP1, LJ_TNIL + | beq <1 // Skip holes in array part. + | ldr NEXT_TMP0, [NEXT_TMP0, #-8] + | mov NEXT_RES, NEXT_RES_PTR + | strd NEXT_TMP0, NEXT_RES_VAL // Stores NEXT_TMP1, too. + | mvn NEXT_TMP0, #~LJ_TISNUM + | str NEXT_TMP0, NEXT_RES_KEY_IT + | bx lr + | + |5: // Traverse hash part. + | ldr NEXT_TMP0, NEXT_TAB->hmask + | ldr NODE:NEXT_RES, NEXT_TAB->node + | add NEXT_TMP1, NEXT_TMP1, NEXT_TMP1, lsl #1 + | add NEXT_LIM, NEXT_LIM, NEXT_TMP0 + | add NODE:NEXT_RES, NODE:NEXT_RES, NEXT_TMP1, lsl #3 + |6: + | cmp NEXT_IDX, NEXT_LIM + | bhi >9 + | ldr NEXT_TMP1, NODE:NEXT_RES->val.it + | checktp NEXT_TMP1, LJ_TNIL + | add NEXT_IDX, NEXT_IDX, #1 + | bxne lr + | // Skip holes in hash part. + | add NEXT_RES, NEXT_RES, #sizeof(Node) + | b <6 + | + |9: // End of iteration. Set the key to nil (not the value). + | mvn NEXT_TMP0, #0 + | mov NEXT_RES, NEXT_RES_PTR + | str NEXT_TMP0, NEXT_RES_KEY_IT + | bx lr + |.endif + | |//----------------------------------------------------------------------- |//-- FFI helper functions ----------------------------------------------- |//----------------------------------------------------------------------- @@ -3919,10 +3972,11 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) break; case BC_ITERN: - | // RA = base*8, (RB = nresults+1, RC = nargs+1 (2+1)) |.if JIT - | // NYI: add hotloop, record BC_ITERN. + | hotloop |.endif + |->vm_IITERN: + | // RA = base*8, (RB = nresults+1, RC = nargs+1 (2+1)) | add RA, BASE, RA | ldr TAB:RB, [RA, #-16] | ldr CARG1, [RA, #-8] // Get index from control var. @@ -3988,7 +4042,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | ins_next1 | ins_next2 | mov CARG1, #0 - | mvn CARG2, #0x00018000 + | mvn CARG2, #~LJ_KEYINDEX | strd CARG1, [RA, #-8] // Initialize control var. |1: | ins_next3 @@ -3997,9 +4051,25 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | mov OP, #BC_ITERC | strb CARG1, [PC, #-4] | sub PC, RC, #0x20000 + |.if JIT + | ldrb CARG1, [PC] + | cmp CARG1, #BC_ITERN + | bne >6 + |.endif | strb OP, [PC] // Subsumes ins_next1. | ins_next2 | b <1 + |.if JIT + |6: // Unpatch JLOOP. + | ldr CARG1, [DISPATCH, #DISPATCH_J(trace)] + | ldrh CARG2, [PC, #2] + | ldr TRACE:CARG1, [CARG1, CARG2, lsl #2] + | // Subsumes ins_next1 and ins_next2. + | ldr INS, TRACE:CARG1->startins + | bfi INS, OP, #0, #8 + | str INS, [PC], #4 + | b <1 + |.endif break; case BC_VARG: diff --git a/love/src/jni/LuaJIT-2.1/src/vm_arm64.dasc b/love/src/jni/LuaJIT-2.1/src/vm_arm64.dasc index 755d9a64..eb87857f 100644 --- a/love/src/jni/LuaJIT-2.1/src/vm_arm64.dasc +++ b/love/src/jni/LuaJIT-2.1/src/vm_arm64.dasc @@ -81,47 +81,48 @@ | |.define CFRAME_SPACE, 208 |//----- 16 byte aligned, <-- sp entering interpreter -|// Unused [sp, #204] // 32 bit values -|.define SAVE_NRES, [sp, #200] -|.define SAVE_ERRF, [sp, #196] -|.define SAVE_MULTRES, [sp, #192] -|.define TMPD, [sp, #184] // 64 bit values -|.define SAVE_L, [sp, #176] -|.define SAVE_PC, [sp, #168] -|.define SAVE_CFRAME, [sp, #160] -|.define SAVE_FPR_, 96 // 96+8*8: 64 bit FPR saves -|.define SAVE_GPR_, 16 // 16+10*8: 64 bit GPR saves -|.define SAVE_LR, [sp, #8] -|.define SAVE_FP, [sp] +|.define SAVE_FP_LR_, 192 +|.define SAVE_GPR_, 112 // 112+10*8: 64 bit GPR saves +|.define SAVE_FPR_, 48 // 48+8*8: 64 bit FPR saves +|// Unused [sp, #44] // 32 bit values +|.define SAVE_NRES, [sp, #40] +|.define SAVE_ERRF, [sp, #36] +|.define SAVE_MULTRES, [sp, #32] +|.define TMPD, [sp, #24] // 64 bit values +|.define SAVE_L, [sp, #16] +|.define SAVE_PC, [sp, #8] +|.define SAVE_CFRAME, [sp, #0] |//----- 16 byte aligned, <-- sp while in interpreter. | -|.define TMPDofs, #184 +|.define TMPDofs, #24 | |.macro save_, gpr1, gpr2, fpr1, fpr2 -| stp d..fpr1, d..fpr2, [sp, # SAVE_FPR_+(fpr1-8)*8] -| stp x..gpr1, x..gpr2, [sp, # SAVE_GPR_+(gpr1-19)*8] +| stp d..fpr2, d..fpr1, [sp, # SAVE_FPR_+(14-fpr1)*8] +| stp x..gpr2, x..gpr1, [sp, # SAVE_GPR_+(27-gpr1)*8] |.endmacro |.macro rest_, gpr1, gpr2, fpr1, fpr2 -| ldp d..fpr1, d..fpr2, [sp, # SAVE_FPR_+(fpr1-8)*8] -| ldp x..gpr1, x..gpr2, [sp, # SAVE_GPR_+(gpr1-19)*8] +| ldp d..fpr2, d..fpr1, [sp, # SAVE_FPR_+(14-fpr1)*8] +| ldp x..gpr2, x..gpr1, [sp, # SAVE_GPR_+(27-gpr1)*8] |.endmacro | |.macro saveregs -| stp fp, lr, [sp, #-CFRAME_SPACE]! -| add fp, sp, #0 -| stp x19, x20, [sp, # SAVE_GPR_] +| sub sp, sp, # CFRAME_SPACE +| stp fp, lr, [sp, # SAVE_FP_LR_] +| add fp, sp, # SAVE_FP_LR_ +| stp x20, x19, [sp, # SAVE_GPR_+(27-19)*8] | save_ 21, 22, 8, 9 | save_ 23, 24, 10, 11 | save_ 25, 26, 12, 13 | save_ 27, 28, 14, 15 |.endmacro |.macro restoreregs -| ldp x19, x20, [sp, # SAVE_GPR_] +| ldp x20, x19, [sp, # SAVE_GPR_+(27-19)*8] | rest_ 21, 22, 8, 9 | rest_ 23, 24, 10, 11 | rest_ 25, 26, 12, 13 | rest_ 27, 28, 14, 15 -| ldp fp, lr, [sp], # CFRAME_SPACE +| ldp fp, lr, [sp, # SAVE_FP_LR_] +| add sp, sp, # CFRAME_SPACE |.endmacro | |// Type definitions. Some of these are only used for documentation. @@ -500,8 +501,9 @@ static void build_subroutines(BuildCtx *ctx) | ldr GL, L->glref // Setup pointer to global state. | mov BASE, CARG2 | str CARG1, SAVE_PC // Any value outside of bytecode is ok. - | str RC, SAVE_CFRAME - | str fp, L->cframe // Add our C frame to cframe chain. + | add TMP0, sp, #0 + | str RC, SAVE_CFRAME + | str TMP0, L->cframe // Add our C frame to cframe chain. | |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype). | str L, GL->cur_L @@ -536,8 +538,9 @@ static void build_subroutines(BuildCtx *ctx) | sub RA, RA, RB // Compute -savestack(L, L->top). | str RAw, SAVE_NRES // Neg. delta means cframe w/o frame. | str wzr, SAVE_ERRF // No error function. - | str RC, SAVE_CFRAME - | str fp, L->cframe // Add our C frame to cframe chain. + | add TMP0, sp, #0 + | str RC, SAVE_CFRAME + | str TMP0, L->cframe // Add our C frame to cframe chain. | str L, GL->cur_L | blr CARG4 // (lua_State *L, lua_CFunction func, void *ud) | mov BASE, CRET1 @@ -562,12 +565,12 @@ static void build_subroutines(BuildCtx *ctx) | cmp CARG1, #1 |.endif | ldr PC, [CARG4, #-24] // Restore PC from [cont|PC]. - | ldr CARG3, LFUNC:CARG3->pc | add TMP0, RA, RC | str TISNIL, [TMP0, #-8] // Ensure one valid arg. |.if FFI | bls >1 |.endif + | ldr CARG3, LFUNC:CARG3->pc | ldr KBASE, [CARG3, #PC2PROTO(k)] | // BASE = base, RA = resultptr, CARG4 = meta base | br CARG1 @@ -1086,21 +1089,19 @@ static void build_subroutines(BuildCtx *ctx) |//-- Base library: iterators ------------------------------------------- | |.ffunc_1 next - | checktp CARG2, CARG1, LJ_TTAB, ->fff_fallback + | checktp CARG1, LJ_TTAB, ->fff_fallback | str TISNIL, [BASE, NARGS8:RC] // Set missing 2nd arg to nil. | ldr PC, [BASE, FRAME_PC] - | stp BASE, BASE, L->base // Add frame since C call can throw. - | mov CARG1, L - | add CARG3, BASE, #8 - | str PC, SAVE_PC - | bl extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) - | // Returns 0 at end of traversal. + | add CARG2, BASE, #8 + | sub CARG3, BASE, #16 + | bl extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) + | // Returns 1=found, 0=end, -1=error. + | mov RC, #(2+1)*8 + | tbnz CRET1w, #31, ->fff_fallback // Invalid key. + | cbnz CRET1, ->fff_res // Found key/value. + | // End of traversal: return nil. | str TISNIL, [BASE, #-16] - | cbz CRET1, ->fff_res1 // End of traversal: return nil. - | ldp CARG1, CARG2, [BASE, #8] // Copy key and value to results. - | mov RC, #(2+1)*8 - | stp CARG1, CARG2, [BASE, #-16] - | b ->fff_res + | b ->fff_res1 | |.ffunc_1 pairs | checktp TMP1, CARG1, LJ_TTAB, ->fff_fallback @@ -1163,9 +1164,10 @@ static void build_subroutines(BuildCtx *ctx) |//-- Base library: catch errors ---------------------------------------- | |.ffunc pcall + | cmp NARGS8:RC, #8 | ldrb TMP0w, GL->hookmask - | subs NARGS8:RC, NARGS8:RC, #8 | blo ->fff_fallback + | sub NARGS8:RC, NARGS8:RC, #8 | mov RB, BASE | add BASE, BASE, #16 | ubfx TMP0w, TMP0w, #HOOK_ACTIVE_SHIFT, #1 @@ -1589,7 +1591,7 @@ static void build_subroutines(BuildCtx *ctx) | str BASE, L->base | str PC, SAVE_PC | str L, GL->tmpbuf.L - | str TMP0, GL->tmpbuf.p + | str TMP0, GL->tmpbuf.w | bl extern lj_buf_putstr_ .. name | bl extern lj_buf_tostr | b ->fff_resstr @@ -2035,8 +2037,9 @@ static void build_subroutines(BuildCtx *ctx) | b <2 | |9: // Rethrow error from the right C frame. + | neg CARG2w, CARG1w | mov CARG1, L - | bl extern lj_err_run // (lua_State *L) + | bl extern lj_err_trace // (lua_State *L, int errcode) |.endif | |//----------------------------------------------------------------------- @@ -2065,6 +2068,63 @@ static void build_subroutines(BuildCtx *ctx) |//-- Miscellaneous functions -------------------------------------------- |//----------------------------------------------------------------------- | + |.define NEXT_TAB, TAB:CARG1 + |.define NEXT_RES, CARG1 + |.define NEXT_IDX, CARG2w + |.define NEXT_LIM, CARG3w + |.define NEXT_TMP0, TMP0 + |.define NEXT_TMP0w, TMP0w + |.define NEXT_TMP1, TMP1 + |.define NEXT_TMP1w, TMP1w + |.define NEXT_RES_PTR, sp + |.define NEXT_RES_VAL, [sp] + |.define NEXT_RES_KEY, [sp, #8] + | + |// TValue *lj_vm_next(GCtab *t, uint32_t idx) + |// Next idx returned in CRET2w. + |->vm_next: + |.if JIT + | ldr NEXT_LIM, NEXT_TAB->asize + | ldr NEXT_TMP1, NEXT_TAB->array + |1: // Traverse array part. + | subs NEXT_TMP0w, NEXT_IDX, NEXT_LIM + | bhs >5 // Index points after array part? + | ldr NEXT_TMP0, [NEXT_TMP1, NEXT_IDX, uxtw #3] + | cmn NEXT_TMP0, #-LJ_TNIL + | cinc NEXT_IDX, NEXT_IDX, eq + | beq <1 // Skip holes in array part. + | str NEXT_TMP0, NEXT_RES_VAL + | movz NEXT_TMP0w, #(LJ_TISNUM>>1)&0xffff, lsl #16 + | stp NEXT_IDX, NEXT_TMP0w, NEXT_RES_KEY + | add NEXT_IDX, NEXT_IDX, #1 + | mov NEXT_RES, NEXT_RES_PTR + |4: + | ret + | + |5: // Traverse hash part. + | ldr NEXT_TMP1w, NEXT_TAB->hmask + | ldr NODE:NEXT_RES, NEXT_TAB->node + | add NEXT_TMP0w, NEXT_TMP0w, NEXT_TMP0w, lsl #1 + | add NEXT_LIM, NEXT_LIM, NEXT_TMP1w + | add NODE:NEXT_RES, NODE:NEXT_RES, NEXT_TMP0w, uxtw #3 + |6: + | cmp NEXT_IDX, NEXT_LIM + | bhi >9 + | ldr NEXT_TMP0, NODE:NEXT_RES->val + | cmn NEXT_TMP0, #-LJ_TNIL + | add NEXT_IDX, NEXT_IDX, #1 + | bne <4 + | // Skip holes in hash part. + | add NODE:NEXT_RES, NODE:NEXT_RES, #sizeof(Node) + | b <6 + | + |9: // End of iteration. Set the key to nil (not the value). + | movn NEXT_TMP0, #0 + | str NEXT_TMP0, NEXT_RES_KEY + | mov NEXT_RES, NEXT_RES_PTR + | ret + |.endif + | |//----------------------------------------------------------------------- |//-- FFI helper functions ----------------------------------------------- |//----------------------------------------------------------------------- @@ -2122,16 +2182,16 @@ static void build_subroutines(BuildCtx *ctx) | // Caveat: needs special frame unwinding, see below. |.if FFI | .type CCSTATE, CCallState, x19 - | stp fp, lr, [sp, #-32]! - | add fp, sp, #0 - | str CCSTATE, [sp, #16] + | stp x20, CCSTATE, [sp, #-32]! + | stp fp, lr, [sp, #16] + | add fp, sp, #16 | mov CCSTATE, x0 | ldr TMP0w, CCSTATE:x0->spadj | ldrb TMP1w, CCSTATE->nsp | add TMP2, CCSTATE, #offsetof(CCallState, stack) | subs TMP1, TMP1, #1 | ldr TMP3, CCSTATE->func - | sub sp, fp, TMP0 + | sub sp, sp, TMP0 | bmi >2 |1: // Copy stack slots | ldr TMP0, [TMP2, TMP1, lsl #3] @@ -2149,12 +2209,12 @@ static void build_subroutines(BuildCtx *ctx) | ldp d6, d7, CCSTATE->fpr[6] | ldr x8, CCSTATE->retp | blr TMP3 - | mov sp, fp + | sub sp, fp, #16 | stp x0, x1, CCSTATE->gpr[0] | stp d0, d1, CCSTATE->fpr[0] | stp d2, d3, CCSTATE->fpr[2] - | ldr CCSTATE, [sp, #16] - | ldp fp, lr, [sp], #32 + | ldp fp, lr, [sp, #16] + | ldp x20, CCSTATE, [sp], #32 | ret |.endif |// Note: vm_ffi_call must be the last function in this object file! @@ -2884,7 +2944,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) case BC_GGET: | // RA = dst, RC = str_const (~) case BC_GSET: - | // RA = dst, RC = str_const (~) + | // RA = src, RC = str_const (~) | ldr LFUNC:CARG1, [BASE, FRAME_FUNC] | mvn RC, RC | and LFUNC:CARG1, CARG1, #LJ_GCVMASK @@ -3321,10 +3381,11 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) break; case BC_ITERN: - | // RA = base, (RB = nresults+1, RC = nargs+1 (2+1)) |.if JIT - | // NYI: add hotloop, record BC_ITERN. + | hotloop |.endif + |->vm_IITERN: + | // RA = base, (RB = nresults+1, RC = nargs+1 (2+1)) | add RA, BASE, RA, lsl #3 | ldr TAB:RB, [RA, #-16] | ldrh TMP3w, [PC, # OFS_RD] @@ -3383,7 +3444,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | ccmp CARG4, TISNIL, #0, eq | ccmp TMP1w, #FF_next_N, #0, eq | bne >5 - | mov TMP0w, #0xfffe7fff + | mov TMP0w, #0xfffe7fff // LJ_KEYINDEX | lsl TMP0, TMP0, #32 | str TMP0, [RA, #-8] // Initialize control var. |1: @@ -3391,11 +3452,28 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | ins_next | |5: // Despecialize bytecode if any of the checks fail. + |.if JIT + | ldrb TMP2w, [RC, # OFS_OP] + |.endif | mov TMP0, #BC_JMP | mov TMP1, #BC_ITERC | strb TMP0w, [PC, #-4+OFS_OP] + |.if JIT + | cmp TMP2w, #BC_ITERN + | bne >6 + |.endif | strb TMP1w, [RC, # OFS_OP] | b <1 + |.if JIT + |6: // Unpatch JLOOP. + | ldr RA, [GL, #GL_J(trace)] + | ldrh TMP2w, [RC, # OFS_RD] + | ldr TRACE:RA, [RA, TMP2, lsl #3] + | ldr TMP2w, TRACE:RA->startins + | bfxil TMP2w, TMP1w, #0, #8 + | str TMP2w, [RC] + | b <1 + |.endif break; case BC_VARG: @@ -3860,7 +3938,7 @@ static int build_backend(BuildCtx *ctx) static void emit_asm_debug(BuildCtx *ctx) { int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); - int i, cf = CFRAME_SIZE >> 3; + int i; switch (ctx->mode) { case BUILD_elfasm: fprintf(ctx->fp, "\t.section .debug_frame,\"\",%%progbits\n"); @@ -3874,7 +3952,7 @@ static void emit_asm_debug(BuildCtx *ctx) "\t.uleb128 0x1\n" "\t.sleb128 -8\n" "\t.byte 30\n" /* Return address is in lr. */ - "\t.byte 0xc\n\t.uleb128 31\n\t.uleb128 0\n" /* def_cfa sp */ + "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 16\n" /* def_cfa fp 16 */ "\t.align 3\n" ".LECIE0:\n\n"); fprintf(ctx->fp, @@ -3884,15 +3962,14 @@ static void emit_asm_debug(BuildCtx *ctx) "\t.long .Lframe0\n" "\t.quad .Lbegin\n" "\t.quad %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x9d\n\t.uleb128 %d\n" /* offset fp */ - "\t.byte 0x9e\n\t.uleb128 %d\n", /* offset lr */ - fcofs, CFRAME_SIZE, cf, cf-1); + "\t.byte 0x9e\n\t.uleb128 1\n" /* offset lr */ + "\t.byte 0x9d\n\t.uleb128 2\n", /* offset fp */ + fcofs); for (i = 19; i <= 28; i++) /* offset x19-x28 */ - fprintf(ctx->fp, "\t.byte 0x%x\n\t.uleb128 %d\n", 0x80+i, cf-i+17); + fprintf(ctx->fp, "\t.byte 0x%x\n\t.uleb128 %d\n", 0x80+i, i+(3-19)); for (i = 8; i <= 15; i++) /* offset d8-d15 */ fprintf(ctx->fp, "\t.byte 5\n\t.uleb128 0x%x\n\t.uleb128 %d\n", - 64+i, cf-i-4); + 64+i, i+(3+(28-19+1)-8)); fprintf(ctx->fp, "\t.align 3\n" ".LEFDE0:\n\n"); @@ -3904,10 +3981,10 @@ static void emit_asm_debug(BuildCtx *ctx) "\t.long .Lframe0\n" "\t.quad lj_vm_ffi_call\n" "\t.quad %d\n" - "\t.byte 0xe\n\t.uleb128 32\n" /* def_cfa_offset */ - "\t.byte 0x9d\n\t.uleb128 4\n" /* offset fp */ - "\t.byte 0x9e\n\t.uleb128 3\n" /* offset lr */ - "\t.byte 0x93\n\t.uleb128 2\n" /* offset x19 */ + "\t.byte 0x9e\n\t.uleb128 1\n" /* offset lr */ + "\t.byte 0x9d\n\t.uleb128 2\n" /* offset fp */ + "\t.byte 0x93\n\t.uleb128 3\n" /* offset x19 */ + "\t.byte 0x94\n\t.uleb128 4\n" /* offset x20 */ "\t.align 3\n" ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); #endif @@ -3926,7 +4003,7 @@ static void emit_asm_debug(BuildCtx *ctx) "\t.byte 0x1b\n" /* pcrel|sdata4 */ "\t.long lj_err_unwind_dwarf-.\n" "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.uleb128 31\n\t.uleb128 0\n" /* def_cfa sp */ + "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 16\n" /* def_cfa fp 16 */ "\t.align 3\n" ".LECIE1:\n\n"); fprintf(ctx->fp, @@ -3937,15 +4014,14 @@ static void emit_asm_debug(BuildCtx *ctx) "\t.long .Lbegin-.\n" "\t.long %d\n" "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x9d\n\t.uleb128 %d\n" /* offset fp */ - "\t.byte 0x9e\n\t.uleb128 %d\n", /* offset lr */ - fcofs, CFRAME_SIZE, cf, cf-1); + "\t.byte 0x9e\n\t.uleb128 1\n" /* offset lr */ + "\t.byte 0x9d\n\t.uleb128 2\n", /* offset fp */ + fcofs); for (i = 19; i <= 28; i++) /* offset x19-x28 */ - fprintf(ctx->fp, "\t.byte 0x%x\n\t.uleb128 %d\n", 0x80+i, cf-i+17); + fprintf(ctx->fp, "\t.byte 0x%x\n\t.uleb128 %d\n", 0x80+i, i+(3-19)); for (i = 8; i <= 15; i++) /* offset d8-d15 */ fprintf(ctx->fp, "\t.byte 5\n\t.uleb128 0x%x\n\t.uleb128 %d\n", - 64+i, cf-i-4); + 64+i, i+(3+(28-19+1)-8)); fprintf(ctx->fp, "\t.align 3\n" ".LEFDE2:\n\n"); @@ -3962,7 +4038,7 @@ static void emit_asm_debug(BuildCtx *ctx) "\t.byte 30\n" /* Return address is in lr. */ "\t.uleb128 1\n" /* augmentation length */ "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.uleb128 31\n\t.uleb128 0\n" /* def_cfa sp */ + "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 16\n" /* def_cfa fp 16 */ "\t.align 3\n" ".LECIE2:\n\n"); fprintf(ctx->fp, @@ -3973,14 +4049,106 @@ static void emit_asm_debug(BuildCtx *ctx) "\t.long lj_vm_ffi_call-.\n" "\t.long %d\n" "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 32\n" /* def_cfa_offset */ - "\t.byte 0x9d\n\t.uleb128 4\n" /* offset fp */ - "\t.byte 0x9e\n\t.uleb128 3\n" /* offset lr */ - "\t.byte 0x93\n\t.uleb128 2\n" /* offset x19 */ + "\t.byte 0x9e\n\t.uleb128 1\n" /* offset lr */ + "\t.byte 0x9d\n\t.uleb128 2\n" /* offset fp */ + "\t.byte 0x93\n\t.uleb128 3\n" /* offset x19 */ + "\t.byte 0x94\n\t.uleb128 4\n" /* offset x20 */ "\t.align 3\n" ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); #endif break; +#if !LJ_NO_UNWIND + case BUILD_machasm: { +#if LJ_HASFFI + int fcsize = 0; +#endif + int j; + fprintf(ctx->fp, "\t.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support\n"); + fprintf(ctx->fp, + "EH_frame1:\n" + "\t.set L$set$x,LECIEX-LSCIEX\n" + "\t.long L$set$x\n" + "LSCIEX:\n" + "\t.long 0\n" + "\t.byte 0x1\n" + "\t.ascii \"zPR\\0\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -8\n" + "\t.byte 30\n" /* Return address is in lr. */ + "\t.uleb128 6\n" /* augmentation length */ + "\t.byte 0x9b\n" /* indirect|pcrel|sdata4 */ + "\t.long _lj_err_unwind_dwarf@GOT-.\n" + "\t.byte 0x1b\n" /* pcrel|sdata4 */ + "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 16\n" /* def_cfa fp 16 */ + "\t.align 3\n" + "LECIEX:\n\n"); + for (j = 0; j < ctx->nsym; j++) { + const char *name = ctx->sym[j].name; + int32_t size = ctx->sym[j+1].ofs - ctx->sym[j].ofs; + if (size == 0) continue; +#if LJ_HASFFI + if (!strcmp(name, "_lj_vm_ffi_call")) { fcsize = size; continue; } +#endif + fprintf(ctx->fp, + "LSFDE%d:\n" + "\t.set L$set$%d,LEFDE%d-LASFDE%d\n" + "\t.long L$set$%d\n" + "LASFDE%d:\n" + "\t.long LASFDE%d-EH_frame1\n" + "\t.long %s-.\n" + "\t.long %d\n" + "\t.uleb128 0\n" /* augmentation length */ + "\t.byte 0x9e\n\t.uleb128 1\n" /* offset lr */ + "\t.byte 0x9d\n\t.uleb128 2\n", /* offset fp */ + j, j, j, j, j, j, j, name, size); + for (i = 19; i <= 28; i++) /* offset x19-x28 */ + fprintf(ctx->fp, "\t.byte 0x%x\n\t.uleb128 %d\n", 0x80+i, i+(3-19)); + for (i = 8; i <= 15; i++) /* offset d8-d15 */ + fprintf(ctx->fp, "\t.byte 5\n\t.uleb128 0x%x\n\t.uleb128 %d\n", + 64+i, i+(3+(28-19+1)-8)); + fprintf(ctx->fp, + "\t.align 3\n" + "LEFDE%d:\n\n", j); + } +#if LJ_HASFFI + if (fcsize) { + fprintf(ctx->fp, + "EH_frame2:\n" + "\t.set L$set$y,LECIEY-LSCIEY\n" + "\t.long L$set$y\n" + "LSCIEY:\n" + "\t.long 0\n" + "\t.byte 0x1\n" + "\t.ascii \"zR\\0\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -8\n" + "\t.byte 30\n" /* Return address is in lr. */ + "\t.uleb128 1\n" /* augmentation length */ + "\t.byte 0x1b\n" /* pcrel|sdata4 */ + "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 16\n" /* def_cfa fp 16 */ + "\t.align 3\n" + "LECIEY:\n\n"); + fprintf(ctx->fp, + "LSFDEY:\n" + "\t.set L$set$yy,LEFDEY-LASFDEY\n" + "\t.long L$set$yy\n" + "LASFDEY:\n" + "\t.long LASFDEY-EH_frame2\n" + "\t.long _lj_vm_ffi_call-.\n" + "\t.long %d\n" + "\t.uleb128 0\n" /* augmentation length */ + "\t.byte 0x9e\n\t.uleb128 1\n" /* offset lr */ + "\t.byte 0x9d\n\t.uleb128 2\n" /* offset fp */ + "\t.byte 0x93\n\t.uleb128 3\n" /* offset x19 */ + "\t.byte 0x94\n\t.uleb128 4\n" /* offset x20 */ + "\t.align 3\n" + "LEFDEY:\n\n", fcsize); + } +#endif + fprintf(ctx->fp, ".subsections_via_symbols\n"); + } + break; +#endif default: break; } diff --git a/love/src/jni/LuaJIT-2.1/src/vm_mips.dasc b/love/src/jni/LuaJIT-2.1/src/vm_mips.dasc index 7a6a83be..e3cc42a5 100644 --- a/love/src/jni/LuaJIT-2.1/src/vm_mips.dasc +++ b/love/src/jni/LuaJIT-2.1/src/vm_mips.dasc @@ -190,7 +190,7 @@ |//----------------------------------------------------------------------- | |// Trap for not-yet-implemented parts. -|.macro NYI; .long 0xf0f0f0f0; .endmacro +|.macro NYI; .long 0xec1cf0f0; .endmacro | |// Macros to mark delay slots. |.macro ., a; a; .endmacro @@ -501,6 +501,10 @@ static void build_subroutines(BuildCtx *ctx) | b ->vm_returnc |. li RD, 16 // 2 results: false + error message. | + |->vm_unwind_stub: // Jump to exit stub from unwinder. + | jr CARG1 + |. move ra, CARG2 + | |//----------------------------------------------------------------------- |//-- Grow stack for calls ----------------------------------------------- |//----------------------------------------------------------------------- @@ -669,11 +673,11 @@ static void build_subroutines(BuildCtx *ctx) |.endif | lw PC, -16+HI(RB) // Restore PC from [cont|PC]. | addu TMP2, RA, RD - | lw TMP1, LFUNC:TMP1->pc |.if FFI | bnez AT, >1 |.endif |. sw TISNIL, -8+HI(TMP2) // Ensure one valid arg. + | lw TMP1, LFUNC:TMP1->pc | // BASE = base, RA = resultptr, RB = meta base | jr TMP0 // Jump to continuation. |. lw KBASE, PC2PROTO(k)(TMP1) @@ -1258,35 +1262,27 @@ static void build_subroutines(BuildCtx *ctx) |//-- Base library: iterators ------------------------------------------- | |.ffunc next - | lw CARG1, HI(BASE) - | lw TAB:CARG2, LO(BASE) + | lw CARG2, HI(BASE) + | lw TAB:CARG1, LO(BASE) | beqz NARGS8:RC, ->fff_fallback |. addu TMP2, BASE, NARGS8:RC | li AT, LJ_TTAB | sw TISNIL, HI(TMP2) // Set missing 2nd arg to nil. - | bne CARG1, AT, ->fff_fallback + | bne CARG2, AT, ->fff_fallback |. lw PC, FRAME_PC(BASE) | load_got lj_tab_next - | sw BASE, L->base // Add frame since C call can throw. - | sw BASE, L->top // Dummy frame length is ok. - | addiu CARG3, BASE, 8 - | sw PC, SAVE_PC - | call_intern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) - |. move CARG1, L - | // Returns 0 at end of traversal. + | addiu CARG2, BASE, 8 + | call_intern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) + |. addiu CARG3, BASE, -8 + | // Returns 1=found, 0=end, -1=error. + | addiu RA, BASE, -8 + | bgtz CRET1, ->fff_res // Found key/value. + |. li RD, (2+1)*8 | beqz CRET1, ->fff_restv // End of traversal: return nil. |. li SFARG1HI, LJ_TNIL - | lw TMP0, 8+HI(BASE) - | lw TMP1, 8+LO(BASE) - | addiu RA, BASE, -8 - | lw TMP2, 16+HI(BASE) - | lw TMP3, 16+LO(BASE) - | sw TMP0, HI(RA) - | sw TMP1, LO(RA) - | sw TMP2, 8+HI(RA) - | sw TMP3, 8+LO(RA) - | b ->fff_res - |. li RD, (2+1)*8 + | lw CFUNC:RB, FRAME_FUNC(BASE) + | b ->fff_fallback // Invalid key. + |. li RC, 2*8 | |.ffunc_1 pairs | li AT, LJ_TTAB @@ -1967,7 +1963,7 @@ static void build_subroutines(BuildCtx *ctx) | lw TMP0, SBUF:CARG1->b | sw L, SBUF:CARG1->L | sw BASE, L->base - | sw TMP0, SBUF:CARG1->p + | sw TMP0, SBUF:CARG1->w | call_intern extern lj_buf_putstr_ .. name |. sw PC, SAVE_PC | load_got lj_buf_tostr @@ -2520,8 +2516,9 @@ static void build_subroutines(BuildCtx *ctx) |. addu RA, RA, BASE | |9: // Rethrow error from the right C frame. - | load_got lj_err_run - | call_intern lj_err_run // (lua_State *L) + | load_got lj_err_trace + | sub CARG2, r0, CRET1 + | call_intern lj_err_trace // (lua_State *L, int errcode) |. move CARG1, L |.endif | @@ -2801,6 +2798,73 @@ static void build_subroutines(BuildCtx *ctx) |//-- Miscellaneous functions -------------------------------------------- |//----------------------------------------------------------------------- | + |.define NEXT_TAB, TAB:CARG1 + |.define NEXT_IDX, CARG2 + |.define NEXT_ASIZE, CARG3 + |.define NEXT_NIL, CARG4 + |.define NEXT_TMP0, r12 + |.define NEXT_TMP1, r13 + |.define NEXT_TMP2, r14 + |.define NEXT_RES_VK, CRET1 + |.define NEXT_RES_IDX, CRET2 + |.define NEXT_RES_PTR, sp + |.define NEXT_RES_VAL_I, 0(sp) + |.define NEXT_RES_VAL_IT, 4(sp) + |.define NEXT_RES_KEY_I, 8(sp) + |.define NEXT_RES_KEY_IT, 12(sp) + | + |// TValue *lj_vm_next(GCtab *t, uint32_t idx) + |// Next idx returned in CRET2. + |->vm_next: + |.if JIT and ENDIAN_LE + | lw NEXT_ASIZE, NEXT_TAB->asize + | lw NEXT_TMP0, NEXT_TAB->array + | li NEXT_NIL, LJ_TNIL + |1: // Traverse array part. + | sltu AT, NEXT_IDX, NEXT_ASIZE + | sll NEXT_TMP1, NEXT_IDX, 3 + | beqz AT, >5 + |. addu NEXT_TMP1, NEXT_TMP0, NEXT_TMP1 + | lw NEXT_TMP2, 4(NEXT_TMP1) + | sw NEXT_IDX, NEXT_RES_KEY_I + | beq NEXT_TMP2, NEXT_NIL, <1 + |. addiu NEXT_IDX, NEXT_IDX, 1 + | lw NEXT_TMP0, 0(NEXT_TMP1) + | li AT, LJ_TISNUM + | sw NEXT_TMP2, NEXT_RES_VAL_IT + | sw AT, NEXT_RES_KEY_IT + | sw NEXT_TMP0, NEXT_RES_VAL_I + | move NEXT_RES_VK, NEXT_RES_PTR + | jr ra + |. move NEXT_RES_IDX, NEXT_IDX + | + |5: // Traverse hash part. + | subu NEXT_RES_IDX, NEXT_IDX, NEXT_ASIZE + | lw NODE:NEXT_RES_VK, NEXT_TAB->node + | sll NEXT_TMP2, NEXT_RES_IDX, 5 + | lw NEXT_TMP0, NEXT_TAB->hmask + | sll AT, NEXT_RES_IDX, 3 + | subu AT, NEXT_TMP2, AT + | addu NODE:NEXT_RES_VK, NODE:NEXT_RES_VK, AT + |6: + | sltu AT, NEXT_TMP0, NEXT_RES_IDX + | bnez AT, >8 + |. nop + | lw NEXT_TMP2, NODE:NEXT_RES_VK->val.it + | bne NEXT_TMP2, NEXT_NIL, >9 + |. addiu NEXT_RES_IDX, NEXT_RES_IDX, 1 + | // Skip holes in hash part. + | b <6 + |. addiu NODE:NEXT_RES_VK, NODE:NEXT_RES_VK, sizeof(Node) + | + |8: // End of iteration. Set the key to nil (not the value). + | sw NEXT_NIL, NEXT_RES_KEY_IT + | move NEXT_RES_VK, NEXT_RES_PTR + |9: + | jr ra + |. addu NEXT_RES_IDX, NEXT_RES_IDX, NEXT_ASIZE + |.endif + | |//----------------------------------------------------------------------- |//-- FFI helper functions ----------------------------------------------- |//----------------------------------------------------------------------- @@ -4524,10 +4588,11 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) break; case BC_ITERN: - | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) - |.if JIT - | // NYI: add hotloop, record BC_ITERN. + |.if JIT and ENDIAN_LE + | hotloop |.endif + |->vm_IITERN: + | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) | addu RA, BASE, RA | lw TAB:RB, -16+LO(RA) | lw RC, -8+LO(RA) // Get index from control var. @@ -4606,9 +4671,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | addiu CARG2, CARG2, -FF_next_N | or CARG2, CARG2, CARG3 | bnez CARG2, >5 - |. lui TMP1, 0xfffe + |. lui TMP1, (LJ_KEYINDEX >> 16) | addu PC, TMP0, TMP2 - | ori TMP1, TMP1, 0x7fff + | ori TMP1, TMP1, (LJ_KEYINDEX & 0xffff) | sw r0, -8+LO(RA) // Initialize control var. | sw TMP1, -8+HI(RA) |1: @@ -4617,9 +4682,28 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | li TMP3, BC_JMP | li TMP1, BC_ITERC | sb TMP3, -4+OFS_OP(PC) - | addu PC, TMP0, TMP2 + | addu PC, TMP0, TMP2 + |.if JIT + | lb TMP0, OFS_OP(PC) + | li AT, BC_ITERN + | bne TMP0, AT, >6 + |. lhu TMP2, OFS_RD(PC) + |.endif | b <1 |. sb TMP1, OFS_OP(PC) + |.if JIT + |6: // Unpatch JLOOP. + | lw TMP0, DISPATCH_J(trace)(DISPATCH) + | sll TMP2, TMP2, 2 + | addu TMP0, TMP0, TMP2 + | lw TRACE:TMP2, 0(TMP0) + | lw TMP0, TRACE:TMP2->startins + | li AT, -256 + | and TMP0, TMP0, AT + | or TMP0, TMP0, TMP1 + | b <1 + |. sw TMP0, 0(PC) + |.endif break; case BC_VARG: diff --git a/love/src/jni/LuaJIT-2.1/src/vm_mips64.dasc b/love/src/jni/LuaJIT-2.1/src/vm_mips64.dasc index 0b642095..4ddb2f9c 100644 --- a/love/src/jni/LuaJIT-2.1/src/vm_mips64.dasc +++ b/love/src/jni/LuaJIT-2.1/src/vm_mips64.dasc @@ -193,7 +193,7 @@ |//----------------------------------------------------------------------- | |// Trap for not-yet-implemented parts. -|.macro NYI; .long 0xf0f0f0f0; .endmacro +|.macro NYI; .long 0xec1cf0f0; .endmacro | |// Macros to mark delay slots. |.macro ., a; a; .endmacro @@ -556,6 +556,10 @@ static void build_subroutines(BuildCtx *ctx) | b ->vm_returnc |. li RD, 16 // 2 results: false + error message. | + |->vm_unwind_stub: // Jump to exit stub from unwinder. + | jr CARG1 + |. move ra, CARG2 + | |//----------------------------------------------------------------------- |//-- Grow stack for calls ----------------------------------------------- |//----------------------------------------------------------------------- @@ -724,11 +728,11 @@ static void build_subroutines(BuildCtx *ctx) | ld PC, -24(RB) // Restore PC from [cont|PC]. | cleartp LFUNC:TMP1 | daddu TMP2, RA, RD - | ld TMP1, LFUNC:TMP1->pc |.if FFI | bnez AT, >1 |.endif |. sd TISNIL, -8(TMP2) // Ensure one valid arg. + | ld TMP1, LFUNC:TMP1->pc | // BASE = base, RA = resultptr, RB = meta base | jr TMP0 // Jump to continuation. |. ld KBASE, PC2PROTO(k)(TMP1) @@ -1318,27 +1322,24 @@ static void build_subroutines(BuildCtx *ctx) |//-- Base library: iterators ------------------------------------------- | |.ffunc_1 next - | checktp CARG2, CARG1, -LJ_TTAB, ->fff_fallback + | checktp CARG1, -LJ_TTAB, ->fff_fallback | daddu TMP2, BASE, NARGS8:RC | sd TISNIL, 0(TMP2) // Set missing 2nd arg to nil. - | ld PC, FRAME_PC(BASE) | load_got lj_tab_next - | sd BASE, L->base // Add frame since C call can throw. - | sd BASE, L->top // Dummy frame length is ok. - | daddiu CARG3, BASE, 8 - | sd PC, SAVE_PC - | call_intern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) - |. move CARG1, L - | // Returns 0 at end of traversal. + | ld PC, FRAME_PC(BASE) + | daddiu CARG2, BASE, 8 + | call_intern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) + |. daddiu CARG3, BASE, -16 + | // Returns 1=found, 0=end, -1=error. + | daddiu RA, BASE, -16 + | bgtz CRET1, ->fff_res // Found key/value. + |. li RD, (2+1)*8 | beqz CRET1, ->fff_restv // End of traversal: return nil. |. move CARG1, TISNIL - | ld TMP0, 8(BASE) - | daddiu RA, BASE, -16 - | ld TMP2, 16(BASE) - | sd TMP0, 0(RA) - | sd TMP2, 8(RA) - | b ->fff_res - |. li RD, (2+1)*8 + | ld CFUNC:RB, FRAME_FUNC(BASE) + | cleartp CFUNC:RB + | b ->fff_fallback // Invalid key. + |. li RC, 2*8 | |.ffunc_1 pairs | checktp TAB:TMP1, CARG1, -LJ_TTAB, ->fff_fallback @@ -2037,7 +2038,7 @@ static void build_subroutines(BuildCtx *ctx) | ld TMP0, SBUF:CARG1->b | sd L, SBUF:CARG1->L | sd BASE, L->base - | sd TMP0, SBUF:CARG1->p + | sd TMP0, SBUF:CARG1->w | call_intern extern lj_buf_putstr_ .. name |. sd PC, SAVE_PC | load_got lj_buf_tostr @@ -2622,8 +2623,9 @@ static void build_subroutines(BuildCtx *ctx) |. daddu RA, RA, BASE | |9: // Rethrow error from the right C frame. - | load_got lj_err_run - | call_intern lj_err_run // (lua_State *L) + | load_got lj_err_trace + | sub CARG2, r0, CRET1 + | call_intern lj_err_trace // (lua_State *L, int errcode) |. move CARG1, L |.endif | @@ -2902,6 +2904,70 @@ static void build_subroutines(BuildCtx *ctx) |//-- Miscellaneous functions -------------------------------------------- |//----------------------------------------------------------------------- | + |.define NEXT_TAB, TAB:CARG1 + |.define NEXT_IDX, CARG2 + |.define NEXT_ASIZE, CARG3 + |.define NEXT_NIL, CARG4 + |.define NEXT_TMP0, r12 + |.define NEXT_TMP1, r13 + |.define NEXT_TMP2, r14 + |.define NEXT_RES_VK, CRET1 + |.define NEXT_RES_IDX, CRET2 + |.define NEXT_RES_PTR, sp + |.define NEXT_RES_VAL, 0(sp) + |.define NEXT_RES_KEY, 8(sp) + | + |// TValue *lj_vm_next(GCtab *t, uint32_t idx) + |// Next idx returned in CRET2. + |->vm_next: + |.if JIT and ENDIAN_LE + | lw NEXT_ASIZE, NEXT_TAB->asize + | ld NEXT_TMP0, NEXT_TAB->array + | li NEXT_NIL, LJ_TNIL + |1: // Traverse array part. + | sltu AT, NEXT_IDX, NEXT_ASIZE + | sll NEXT_TMP1, NEXT_IDX, 3 + | beqz AT, >5 + |. daddu NEXT_TMP1, NEXT_TMP0, NEXT_TMP1 + | li AT, LJ_TISNUM + | ld NEXT_TMP2, 0(NEXT_TMP1) + | dsll AT, AT, 47 + | or NEXT_TMP1, NEXT_IDX, AT + | beq NEXT_TMP2, NEXT_NIL, <1 + |. addiu NEXT_IDX, NEXT_IDX, 1 + | sd NEXT_TMP2, NEXT_RES_VAL + | sd NEXT_TMP1, NEXT_RES_KEY + | move NEXT_RES_VK, NEXT_RES_PTR + | jr ra + |. move NEXT_RES_IDX, NEXT_IDX + | + |5: // Traverse hash part. + | subu NEXT_RES_IDX, NEXT_IDX, NEXT_ASIZE + | ld NODE:NEXT_RES_VK, NEXT_TAB->node + | sll NEXT_TMP2, NEXT_RES_IDX, 5 + | lw NEXT_TMP0, NEXT_TAB->hmask + | sll AT, NEXT_RES_IDX, 3 + | subu AT, NEXT_TMP2, AT + | daddu NODE:NEXT_RES_VK, NODE:NEXT_RES_VK, AT + |6: + | sltu AT, NEXT_TMP0, NEXT_RES_IDX + | bnez AT, >8 + |. nop + | ld NEXT_TMP2, NODE:NEXT_RES_VK->val + | bne NEXT_TMP2, NEXT_NIL, >9 + |. addiu NEXT_RES_IDX, NEXT_RES_IDX, 1 + | // Skip holes in hash part. + | b <6 + |. daddiu NODE:NEXT_RES_VK, NODE:NEXT_RES_VK, sizeof(Node) + | + |8: // End of iteration. Set the key to nil (not the value). + | sd NEXT_NIL, NEXT_RES_KEY + | move NEXT_RES_VK, NEXT_RES_PTR + |9: + | jr ra + |. addu NEXT_RES_IDX, NEXT_RES_IDX, NEXT_ASIZE + |.endif + | |//----------------------------------------------------------------------- |//-- FFI helper functions ----------------------------------------------- |//----------------------------------------------------------------------- @@ -4698,10 +4764,11 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) break; case BC_ITERN: - | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) - |.if JIT - | // NYI: add hotloop, record BC_ITERN. + |.if JIT and ENDIAN_LE + | hotloop |.endif + |->vm_IITERN: + | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) | daddu RA, BASE, RA | ld TAB:RB, -16(RA) | lw RC, -8+LO(RA) // Get index from control var. @@ -4722,11 +4789,10 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) |. addiu RC, RC, 1 | sd TMP2, 0(RA) | sd CARG1, 8(RA) - | or TMP0, RC, CARG3 | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) | decode_RD4b RD | daddu RD, RD, TMP3 - | sw TMP0, -8+LO(RA) // Update control var. + | sw RC, -8+LO(RA) // Update control var. | daddu PC, PC, RD |3: | ins_next @@ -4776,9 +4842,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | daddiu TMP1, TMP1, -FF_next_N | or AT, AT, TMP1 | bnez AT, >5 - |. lui TMP1, 0xfffe + |. lui TMP1, (LJ_KEYINDEX >> 16) | daddu PC, TMP0, TMP2 - | ori TMP1, TMP1, 0x7fff + | ori TMP1, TMP1, (LJ_KEYINDEX & 0xffff) | dsll TMP1, TMP1, 32 | sd TMP1, -8(RA) |1: @@ -4788,8 +4854,27 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | li TMP1, BC_ITERC | sb TMP3, -4+OFS_OP(PC) | daddu PC, TMP0, TMP2 + |.if JIT + | lb TMP0, OFS_OP(PC) + | li AT, BC_ITERN + | bne TMP0, AT, >6 + |. lhu TMP2, OFS_RD(PC) + |.endif | b <1 |. sb TMP1, OFS_OP(PC) + |.if JIT + |6: // Unpatch JLOOP. + | ld TMP0, DISPATCH_J(trace)(DISPATCH) + | sll TMP2, TMP2, 3 + | daddu TMP0, TMP0, TMP2 + | ld TRACE:TMP2, 0(TMP0) + | lw TMP0, TRACE:TMP2->startins + | li AT, -256 + | and TMP0, TMP0, AT + | or TMP0, TMP0, TMP1 + | b <1 + |. sw TMP0, 0(PC) + |.endif break; case BC_VARG: diff --git a/love/src/jni/LuaJIT-2.1/src/vm_ppc.dasc b/love/src/jni/LuaJIT-2.1/src/vm_ppc.dasc index f4ebb9db..a376c849 100644 --- a/love/src/jni/LuaJIT-2.1/src/vm_ppc.dasc +++ b/love/src/jni/LuaJIT-2.1/src/vm_ppc.dasc @@ -859,11 +859,11 @@ static void build_subroutines(BuildCtx *ctx) |.endif | lwz PC, -16(RB) // Restore PC from [cont|PC]. | subi TMP2, RD, 8 - | lwz TMP1, LFUNC:TMP1->pc | stwx TISNIL, RA, TMP2 // Ensure one valid arg. |.if FFI | ble >1 |.endif + | lwz TMP1, LFUNC:TMP1->pc | lwz KBASE, PC2PROTO(k)(TMP1) | // BASE = base, RA = resultptr, RB = meta base | mtctr TMP0 @@ -1559,43 +1559,24 @@ static void build_subroutines(BuildCtx *ctx) | |//-- Base library: iterators ------------------------------------------- | - |.ffunc next - | cmplwi NARGS8:RC, 8 - | lwz CARG1, 0(BASE) - | lwz TAB:CARG2, 4(BASE) - | blt ->fff_fallback + |.ffunc_1 next | stwx TISNIL, BASE, NARGS8:RC // Set missing 2nd arg to nil. - | checktab CARG1 + | checktab CARG3 | lwz PC, FRAME_PC(BASE) | bne ->fff_fallback - | stp BASE, L->base // Add frame since C call can throw. - | mr CARG1, L - | stp BASE, L->top // Dummy frame length is ok. - | la CARG3, 8(BASE) - | stw PC, SAVE_PC - | bl extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) - | // Returns 0 at end of traversal. - | cmplwi CRET1, 0 + | la CARG2, 8(BASE) + | la CARG3, -8(BASE) + | bl extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) + | // Returns 1=found, 0=end, -1=error. + | cmpwi CRET1, 0 + | la RA, -8(BASE) + | li RD, (2+1)*8 + | bgt ->fff_res // Found key/value. | li CARG3, LJ_TNIL | beq ->fff_restv // End of traversal: return nil. - | la RA, -8(BASE) - |.if FPU - | lfd f0, 8(BASE) // Copy key and value to results. - | lfd f1, 16(BASE) - | stfd f0, 0(RA) - | stfd f1, 8(RA) - |.else - | lwz CARG1, 8(BASE) - | lwz CARG2, 12(BASE) - | lwz CARG3, 16(BASE) - | lwz CARG4, 20(BASE) - | stw CARG1, 0(RA) - | stw CARG2, 4(RA) - | stw CARG3, 8(RA) - | stw CARG4, 12(RA) - |.endif - | li RD, (2+1)*8 - | b ->fff_res + | lwz CFUNC:RB, FRAME_FUNC(BASE) + | li NARGS8:RC, 2*8 + | b ->fff_fallback // Invalid key. | |.ffunc_1 pairs | checktab CARG3 @@ -2516,7 +2497,7 @@ static void build_subroutines(BuildCtx *ctx) | stw L, SBUF:CARG1->L | stp BASE, L->base | stw PC, SAVE_PC - | stw TMP0, SBUF:CARG1->p + | stw TMP0, SBUF:CARG1->w | bl extern lj_buf_putstr_ .. name | bl extern lj_buf_tostr | b ->fff_resstr @@ -3090,8 +3071,9 @@ static void build_subroutines(BuildCtx *ctx) | bctr | |9: // Rethrow error from the right C frame. + | neg CARG2, CARG1 | mr CARG1, L - | bl extern lj_err_run // (lua_State *L) + | bl extern lj_err_trace // (lua_State *L, int errcode) |.endif | |//----------------------------------------------------------------------- @@ -3181,6 +3163,11 @@ static void build_subroutines(BuildCtx *ctx) | blr |.endif | + |->vm_next: + |.if JIT + | NYI // On big-endian. + |.endif + | |//----------------------------------------------------------------------- |//-- FFI helper functions ----------------------------------------------- |//----------------------------------------------------------------------- @@ -4100,8 +4087,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) |.macro addo32., y, a, b | // Need to check overflow for (a<<32) + (b<<32). | rldicr TMP0, a, 32, 31 - | rldicr TMP3, b, 32, 31 - | addo. TMP0, TMP0, TMP3 + | rldicr TMP1, b, 32, 31 + | addo. TMP0, TMP0, TMP1 | add y, a, b |.endmacro | ins_arith addo32., fadd, __adddf3 @@ -4114,8 +4101,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) |.macro subo32., y, a, b | // Need to check overflow for (a<<32) - (b<<32). | rldicr TMP0, a, 32, 31 - | rldicr TMP3, b, 32, 31 - | subo. TMP0, TMP0, TMP3 + | rldicr TMP1, b, 32, 31 + | subo. TMP0, TMP0, TMP1 | sub y, a, b |.endmacro | ins_arith subo32., fsub, __subdf3 @@ -5130,8 +5117,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) case BC_ITERN: | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) |.if JIT - | // NYI: add hotloop, record BC_ITERN. + | // NYI on big-endian |.endif + |->vm_IITERN: | add RA, BASE, RA | lwz TAB:RB, -12(RA) | lwz RC, -4(RA) // Get index from control var. @@ -5250,8 +5238,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq | add TMP3, PC, TMP0 | bne cr0, >5 - | lus TMP1, 0xfffe - | ori TMP1, TMP1, 0x7fff + | lus TMP1, (LJ_KEYINDEX >> 16) + | ori TMP1, TMP1, (LJ_KEYINDEX & 0xffff) | stw ZERO, -4(RA) // Initialize control var. | stw TMP1, -8(RA) | addis PC, TMP3, -(BCBIAS_J*4 >> 16) @@ -5262,6 +5250,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | li TMP1, BC_ITERC | stb TMP0, -1(PC) | addis PC, TMP3, -(BCBIAS_J*4 >> 16) + | // NYI on big-endian: unpatch JLOOP. | stb TMP1, 3(PC) | b <1 break; diff --git a/love/src/jni/LuaJIT-2.1/src/vm_x64.dasc b/love/src/jni/LuaJIT-2.1/src/vm_x64.dasc index 8ade0a6a..fdffd4b6 100644 --- a/love/src/jni/LuaJIT-2.1/src/vm_x64.dasc +++ b/love/src/jni/LuaJIT-2.1/src/vm_x64.dasc @@ -1346,44 +1346,28 @@ static void build_subroutines(BuildCtx *ctx) |.ffunc_1 next | je >2 // Missing 2nd arg? |1: - |.if X64WIN - | mov RA, [BASE] - | checktab RA, ->fff_fallback - |.else - | mov CARG2, [BASE] - | checktab CARG2, ->fff_fallback - |.endif - | mov L:RB, SAVE_L - | mov L:RB->base, BASE // Add frame since C call can throw. - | mov L:RB->top, BASE // Dummy frame length is ok. + | mov CARG1, [BASE] | mov PC, [BASE-8] + | checktab CARG1, ->fff_fallback + | mov RB, BASE // Save BASE. |.if X64WIN - | lea CARG3, [BASE+8] - | mov CARG2, RA // Caveat: CARG2 == BASE. - | mov CARG1, L:RB + | lea CARG3, [BASE-16] + | lea CARG2, [BASE+8] // Caveat: CARG2 == BASE. |.else - | lea CARG3, [BASE+8] // Caveat: CARG3 == BASE. - | mov CARG1, L:RB + | lea CARG2, [BASE+8] + | lea CARG3, [BASE-16] // Caveat: CARG3 == BASE. |.endif - | mov SAVE_PC, PC // Needed for ITERN fallback. - | call extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) - | // Flag returned in eax (RD). - | mov BASE, L:RB->base - | test RDd, RDd; jz >3 // End of traversal? - | // Copy key and value to results. - | mov RB, [BASE+8] - | mov RD, [BASE+16] - | mov [BASE-16], RB - | mov [BASE-8], RD - |->fff_res2: - | mov RDd, 1+2 - | jmp ->fff_res + | call extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) + | // 1=found, 0=end, -1=error returned in eax (RD). + | mov BASE, RB // Restore BASE. + | test RDd, RDd; jg ->fff_res2 // Found key/value. + | js ->fff_fallback_2 // Invalid key. + | // End of traversal: return nil. + | mov aword [BASE-16], LJ_TNIL + | jmp ->fff_res1 |2: // Set missing 2nd arg to nil. | mov aword [BASE+8], LJ_TNIL | jmp <1 - |3: // End of traversal: return nil. - | mov aword [BASE-16], LJ_TNIL - | jmp ->fff_res1 | |.ffunc_1 pairs | mov TAB:RB, [BASE] @@ -1432,7 +1416,9 @@ static void build_subroutines(BuildCtx *ctx) | // Copy array slot. | mov RB, [RD] | mov [BASE-8], RB - | jmp ->fff_res2 + |->fff_res2: + | mov RDd, 1+2 + | jmp ->fff_res |2: // Check for empty hash part first. Otherwise call C function. | cmp dword TAB:RB->hmask, 0; je ->fff_res0 |.if X64WIN @@ -2011,7 +1997,7 @@ static void build_subroutines(BuildCtx *ctx) |.endif | mov RC, SBUF:CARG1->b | mov SBUF:CARG1->L, L:RB - | mov SBUF:CARG1->p, RC + | mov SBUF:CARG1->w, RC | mov SAVE_PC, PC | call extern lj_buf_putstr_ .. name | mov CARG1, rax @@ -2509,8 +2495,10 @@ static void build_subroutines(BuildCtx *ctx) | jmp <2 | |9: // Rethrow error from the right C frame. + | mov CARG2d, RDd | mov CARG1, L:RB - | call extern lj_err_run // (lua_State *L) + | neg CARG2d + | call extern lj_err_trace // (lua_State *L, int errcode) |.endif | |//----------------------------------------------------------------------- @@ -2645,6 +2633,67 @@ static void build_subroutines(BuildCtx *ctx) | .if X64WIN; pop rsi; .endif | ret | + |.define NEXT_TAB, TAB:CARG1 + |.define NEXT_IDX, CARG2d + |.define NEXT_IDXa, CARG2 + |.define NEXT_PTR, RC + |.define NEXT_PTRd, RCd + |.define NEXT_TMP, CARG3 + |.define NEXT_ASIZE, CARG4d + |.macro NEXT_RES_IDXL, op2; lea edx, [NEXT_IDX+op2]; .endmacro + |.if X64WIN + |.define NEXT_RES_PTR, [rsp+aword*5] + |.macro NEXT_RES_IDX, op2; add NEXT_IDX, op2; .endmacro + |.else + |.define NEXT_RES_PTR, [rsp+aword*1] + |.macro NEXT_RES_IDX, op2; lea edx, [NEXT_IDX+op2]; .endmacro + |.endif + | + |// TValue *lj_vm_next(GCtab *t, uint32_t idx) + |// Next idx returned in edx. + |->vm_next: + |.if JIT + | mov NEXT_ASIZE, NEXT_TAB->asize + |1: // Traverse array part. + | cmp NEXT_IDX, NEXT_ASIZE; jae >5 + | mov NEXT_TMP, NEXT_TAB->array + | mov NEXT_TMP, qword [NEXT_TMP+NEXT_IDX*8] + | cmp NEXT_TMP, LJ_TNIL; je >2 + | lea NEXT_PTR, NEXT_RES_PTR + | mov qword [NEXT_PTR], NEXT_TMP + |.if DUALNUM + | setint NEXT_TMP, NEXT_IDXa + | mov qword [NEXT_PTR+qword*1], NEXT_TMP + |.else + | cvtsi2sd xmm0, NEXT_IDX + | movsd qword [NEXT_PTR+qword*1], xmm0 + |.endif + | NEXT_RES_IDX 1 + | ret + |2: // Skip holes in array part. + | add NEXT_IDX, 1 + | jmp <1 + | + |5: // Traverse hash part. + | sub NEXT_IDX, NEXT_ASIZE + |6: + | cmp NEXT_IDX, NEXT_TAB->hmask; ja >9 + | imul NEXT_PTRd, NEXT_IDX, #NODE + | add NODE:NEXT_PTR, NEXT_TAB->node + | cmp qword NODE:NEXT_PTR->val, LJ_TNIL; je >7 + | NEXT_RES_IDXL NEXT_ASIZE+1 + | ret + |7: // Skip holes in hash part. + | add NEXT_IDX, 1 + | jmp <6 + | + |9: // End of iteration. Set the key to nil (not the value). + | NEXT_RES_IDX NEXT_ASIZE + | lea NEXT_PTR, NEXT_RES_PTR + | mov qword [NEXT_PTR+qword*1], LJ_TNIL + | ret + |.endif + | |//----------------------------------------------------------------------- |//-- Assertions --------------------------------------------------------- |//----------------------------------------------------------------------- @@ -4056,10 +4105,11 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) break; case BC_ITERN: - | ins_A // RA = base, (RB = nresults+1, RC = nargs+1 (2+1)) |.if JIT - | // NYI: add hotloop, record BC_ITERN. + | hotloop RBd |.endif + |->vm_IITERN: + | ins_A // RA = base, (RB = nresults+1, RC = nargs+1 (2+1)) | mov TAB:RB, [BASE+RA*8-16] | cleartp TAB:RB | mov RCd, [BASE+RA*8-8] // Get index from control var. @@ -4123,15 +4173,29 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | cmp aword [BASE+RA*8-8], LJ_TNIL; jne >5 | cmp byte CFUNC:RB->ffid, FF_next_N; jne >5 | branchPC RD - | mov64 TMPR, U64x(fffe7fff, 00000000) + | mov64 TMPR, ((uint64_t)LJ_KEYINDEX << 32) | mov [BASE+RA*8-8], TMPR // Initialize control var. |1: | ins_next |5: // Despecialize bytecode if any of the checks fail. | mov PC_OP, BC_JMP | branchPC RD + |.if JIT + | cmp byte [PC], BC_ITERN + | jne >6 + |.endif | mov byte [PC], BC_ITERC | jmp <1 + |.if JIT + |6: // Unpatch JLOOP. + | mov RA, [DISPATCH+DISPATCH_J(trace)] + | movzx RCd, word [PC+2] + | mov TRACE:RA, [RA+RC*8] + | mov eax, TRACE:RA->startins + | mov al, BC_ITERC + | mov dword [PC], eax + | jmp <1 + |.endif break; case BC_VARG: diff --git a/love/src/jni/LuaJIT-2.1/src/vm_x86.dasc b/love/src/jni/LuaJIT-2.1/src/vm_x86.dasc index 1fee4a2a..cbf0810c 100644 --- a/love/src/jni/LuaJIT-2.1/src/vm_x86.dasc +++ b/love/src/jni/LuaJIT-2.1/src/vm_x86.dasc @@ -1673,55 +1673,35 @@ static void build_subroutines(BuildCtx *ctx) | je >2 // Missing 2nd arg? |1: | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback - | mov L:RB, SAVE_L - | mov L:RB->base, BASE // Add frame since C call can throw. - | mov L:RB->top, BASE // Dummy frame length is ok. | mov PC, [BASE-4] + | mov RB, BASE // Save BASE. |.if X64WIN - | lea CARG3d, [BASE+8] - | mov CARG2d, [BASE] // Caveat: CARG2d == BASE. - | mov CARG1d, L:RB + | mov CARG1d, [BASE] + | lea CARG3d, [BASE-8] + | lea CARG2d, [BASE+8] // Caveat: CARG2d == BASE. |.elif X64 - | mov CARG2d, [BASE] - | lea CARG3d, [BASE+8] // Caveat: CARG3d == BASE. - | mov CARG1d, L:RB + | mov CARG1d, [BASE] + | lea CARG2d, [BASE+8] + | lea CARG3d, [BASE-8] // Caveat: CARG3d == BASE. |.else | mov TAB:RD, [BASE] - | mov ARG2, TAB:RD - | mov ARG1, L:RB + | mov ARG1, TAB:RD | add BASE, 8 + | mov ARG2, BASE + | sub BASE, 8+8 | mov ARG3, BASE |.endif - | mov SAVE_PC, PC // Needed for ITERN fallback. - | call extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key) - | // Flag returned in eax (RD). - | mov BASE, L:RB->base - | test RD, RD; jz >3 // End of traversal? - | // Copy key and value to results. - |.if X64 - | mov RBa, [BASE+8] - | mov RDa, [BASE+16] - | mov [BASE-8], RBa - | mov [BASE], RDa - |.else - | mov RB, [BASE+8] - | mov RD, [BASE+12] - | mov [BASE-8], RB - | mov [BASE-4], RD - | mov RB, [BASE+16] - | mov RD, [BASE+20] - | mov [BASE], RB - | mov [BASE+4], RD - |.endif - |->fff_res2: - | mov RD, 1+2 - | jmp ->fff_res + | call extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o) + | // 1=found, 0=end, -1=error returned in eax (RD). + | mov BASE, RB // Restore BASE. + | test RD, RD; jg ->fff_res2 // Found key/value. + | js ->fff_fallback_2 // Invalid key. + | // End of traversal: return nil. + | mov dword [BASE-4], LJ_TNIL + | jmp ->fff_res1 |2: // Set missing 2nd arg to nil. | mov dword [BASE+12], LJ_TNIL | jmp <1 - |3: // End of traversal: return nil. - | mov dword [BASE-4], LJ_TNIL - | jmp ->fff_res1 | |.ffunc_1 pairs | mov TAB:RB, [BASE] @@ -1775,7 +1755,9 @@ static void build_subroutines(BuildCtx *ctx) | mov [BASE], RB | mov [BASE+4], RD |.endif - | jmp ->fff_res2 + |->fff_res2: + | mov RD, 1+2 + | jmp ->fff_res |2: // Check for empty hash part first. Otherwise call C function. | cmp dword TAB:RB->hmask, 0; je ->fff_res0 | mov FCARG1, TAB:RB @@ -2423,9 +2405,9 @@ static void build_subroutines(BuildCtx *ctx) | lea SBUF:FCARG1, [DISPATCH+DISPATCH_GL(tmpbuf)] | mov L:RB->base, BASE | mov STR:FCARG2, [BASE] // Caveat: FCARG2 == BASE - | mov RC, SBUF:FCARG1->b + | mov RCa, SBUF:FCARG1->b | mov SBUF:FCARG1->L, L:RB - | mov SBUF:FCARG1->p, RC + | mov SBUF:FCARG1->w, RCa | mov SAVE_PC, PC | call extern lj_buf_putstr_ .. name .. @8 | mov FCARG1, eax @@ -2964,8 +2946,10 @@ static void build_subroutines(BuildCtx *ctx) | jmp <2 | |9: // Rethrow error from the right C frame. + | mov FCARG2, RD | mov FCARG1, L:RB - | call extern lj_err_run@4 // (lua_State *L) + | neg FCARG2 + | call extern lj_err_trace@8 // (lua_State *L, int errcode) |.endif | |//----------------------------------------------------------------------- @@ -3136,6 +3120,86 @@ static void build_subroutines(BuildCtx *ctx) | ret |.endif | + |.define NEXT_TAB, TAB:FCARG1 + |.define NEXT_IDX, FCARG2 + |.define NEXT_PTR, RCa + |.define NEXT_PTRd, RC + |.macro NEXT_RES_IDXL, op2; lea edx, [NEXT_IDX+op2]; .endmacro + |.if X64 + |.define NEXT_TMP, CARG3d + |.define NEXT_TMPq, CARG3 + |.define NEXT_ASIZE, CARG4d + |.macro NEXT_ENTER; .endmacro + |.macro NEXT_LEAVE; ret; .endmacro + |.if X64WIN + |.define NEXT_RES_PTR, [rsp+aword*5] + |.macro NEXT_RES_IDX, op2; add NEXT_IDX, op2; .endmacro + |.else + |.define NEXT_RES_PTR, [rsp+aword*1] + |.macro NEXT_RES_IDX, op2; lea edx, [NEXT_IDX+op2]; .endmacro + |.endif + |.else + |.define NEXT_ASIZE, esi + |.define NEXT_TMP, edi + |.macro NEXT_ENTER; push esi; push edi; .endmacro + |.macro NEXT_LEAVE; pop edi; pop esi; ret; .endmacro + |.define NEXT_RES_PTR, [esp+dword*3] + |.macro NEXT_RES_IDX, op2; add NEXT_IDX, op2; .endmacro + |.endif + | + |// TValue *lj_vm_next(GCtab *t, uint32_t idx) + |// Next idx returned in edx. + |->vm_next: + |.if JIT + | NEXT_ENTER + | mov NEXT_ASIZE, NEXT_TAB->asize + |1: // Traverse array part. + | cmp NEXT_IDX, NEXT_ASIZE; jae >5 + | mov NEXT_TMP, NEXT_TAB->array + | cmp dword [NEXT_TMP+NEXT_IDX*8+4], LJ_TNIL; je >2 + | lea NEXT_PTR, NEXT_RES_PTR + |.if X64 + | mov NEXT_TMPq, qword [NEXT_TMP+NEXT_IDX*8] + | mov qword [NEXT_PTR], NEXT_TMPq + |.else + | mov NEXT_ASIZE, dword [NEXT_TMP+NEXT_IDX*8+4] + | mov NEXT_TMP, dword [NEXT_TMP+NEXT_IDX*8] + | mov dword [NEXT_PTR+4], NEXT_ASIZE + | mov dword [NEXT_PTR], NEXT_TMP + |.endif + |.if DUALNUM + | mov dword [NEXT_PTR+dword*3], LJ_TISNUM + | mov dword [NEXT_PTR+dword*2], NEXT_IDX + |.else + | cvtsi2sd xmm0, NEXT_IDX + | movsd qword [NEXT_PTR+dword*2], xmm0 + |.endif + | NEXT_RES_IDX 1 + | NEXT_LEAVE + |2: // Skip holes in array part. + | add NEXT_IDX, 1 + | jmp <1 + | + |5: // Traverse hash part. + | sub NEXT_IDX, NEXT_ASIZE + |6: + | cmp NEXT_IDX, NEXT_TAB->hmask; ja >9 + | imul NEXT_PTRd, NEXT_IDX, #NODE + | add NODE:NEXT_PTRd, dword NEXT_TAB->node + | cmp dword NODE:NEXT_PTR->val.it, LJ_TNIL; je >7 + | NEXT_RES_IDXL NEXT_ASIZE+1 + | NEXT_LEAVE + |7: // Skip holes in hash part. + | add NEXT_IDX, 1 + | jmp <6 + | + |9: // End of iteration. Set the key to nil (not the value). + | NEXT_RES_IDX NEXT_ASIZE + | lea NEXT_PTR, NEXT_RES_PTR + | mov dword [NEXT_PTR+dword*3], LJ_TNIL + | NEXT_LEAVE + |.endif + | |//----------------------------------------------------------------------- |//-- Assertions --------------------------------------------------------- |//----------------------------------------------------------------------- @@ -4787,10 +4851,11 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) break; case BC_ITERN: - | ins_A // RA = base, (RB = nresults+1, RC = nargs+1 (2+1)) |.if JIT - | // NYI: add hotloop, record BC_ITERN. + | hotloop RB |.endif + |->vm_IITERN: + | ins_A // RA = base, (RB = nresults+1, RC = nargs+1 (2+1)) | mov TMP1, KBASE // Need two more free registers. | mov TMP2, DISPATCH | mov TAB:RB, [BASE+RA*8-16] @@ -4878,14 +4943,28 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | cmp byte CFUNC:RB->ffid, FF_next_N; jne >5 | branchPC RD | mov dword [BASE+RA*8-8], 0 // Initialize control var. - | mov dword [BASE+RA*8-4], 0xfffe7fff + | mov dword [BASE+RA*8-4], LJ_KEYINDEX |1: | ins_next |5: // Despecialize bytecode if any of the checks fail. | mov PC_OP, BC_JMP | branchPC RD + |.if JIT + | cmp byte [PC], BC_ITERN + | jne >6 + |.endif | mov byte [PC], BC_ITERC | jmp <1 + |.if JIT + |6: // Unpatch JLOOP. + | mov RA, [DISPATCH+DISPATCH_J(trace)] + | movzx RC, word [PC+2] + | mov TRACE:RA, [RA+RC*4] + | mov eax, TRACE:RA->startins + | mov al, BC_ITERC + | mov dword [PC], eax + | jmp <1 + |.endif break; case BC_VARG: diff --git a/love/src/jni/LuaJIT-2.1/src/xb1build.bat b/love/src/jni/LuaJIT-2.1/src/xb1build.bat index 12c73dd6..2eb68171 100644 --- a/love/src/jni/LuaJIT-2.1/src/xb1build.bat +++ b/love/src/jni/LuaJIT-2.1/src/xb1build.bat @@ -14,7 +14,7 @@ @set LJMT=mt /nologo @set DASMDIR=..\dynasm @set DASM=%DASMDIR%\dynasm.lua -@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c +@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c %LJCOMPILE% host\minilua.c @if errorlevel 1 goto :BAD diff --git a/love/src/jni/LuaJIT-2.1/src/xedkbuild.bat b/love/src/jni/LuaJIT-2.1/src/xedkbuild.bat index 240ec878..37322d03 100644 --- a/love/src/jni/LuaJIT-2.1/src/xedkbuild.bat +++ b/love/src/jni/LuaJIT-2.1/src/xedkbuild.bat @@ -14,7 +14,7 @@ @set LJMT=mt /nologo @set DASMDIR=..\dynasm @set DASM=%DASMDIR%\dynasm.lua -@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c +@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c %LJCOMPILE% host\minilua.c @if errorlevel 1 goto :BAD diff --git a/love/src/jni/love b/love/src/jni/love index 1bb22d2e..0f9e598e 160000 --- a/love/src/jni/love +++ b/love/src/jni/love @@ -1 +1 @@ -Subproject commit 1bb22d2e90eb43146b4e577055064260b4649c2d +Subproject commit 0f9e598ebb5f77a38124ab7ac8c4a92a1403ee47

    JlS#kwBc`wXB;s=)^_&;B9O9*U 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 diff --git a/love/src/jni/LuaJIT-2.1/build_instructions.bat b/love/src/jni/LuaJIT-2.1/build_instructions.bat index 8f04ba16..c3003340 100644 --- a/love/src/jni/LuaJIT-2.1/build_instructions.bat +++ b/love/src/jni/LuaJIT-2.1/build_instructions.bat @@ -28,6 +28,8 @@ wsl make HOST_LUA=luajit.exe "HOST_CC=clang.exe -m32" HOST_CFLAGS=-D_CRT_SECURE_ if not "%ERRORLEVEL%" == "0" goto :error copy src\libluajit.a android\armeabi-v7a\libluajit.a if not "%ERRORLEVEL%" == "0" goto :error +xcopy src\jit android\armeabi-v7a\jit /I +del android\armeabi-v7a\jit\.gitignore :x86 rem x86 @@ -48,6 +50,8 @@ wsl make HOST_LUA=luajit.exe "HOST_CC=clang.exe %4" HOST_CFLAGS=-D_CRT_SECURE_NO if not "%ERRORLEVEL%" == "0" goto :error copy src\libluajit.a android\%1\libluajit.a if not "%ERRORLEVEL%" == "0" goto :error +xcopy src\jit android\%1\jit /I +del android\%1\jit\.gitignore goto :done :error diff --git a/love/src/jni/LuaJIT-2.1/doc/contact.html b/love/src/jni/LuaJIT-2.1/doc/contact.html index 0c775f98..c253a08b 100644 --- a/love/src/jni/LuaJIT-2.1/doc/contact.html +++ b/love/src/jni/LuaJIT-2.1/doc/contact.html @@ -1,8 +1,8 @@ - + Contact - + @@ -37,6 +37,8 @@ FFI Semantics

    Diu6T$pd2fq&X4Nf)W`Fgi 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 z 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