From 9a9509c66a98d0bf42003ad5d06e8f275c5ff1f5 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Sat, 9 Jun 2012 15:04:03 +0200 Subject: Reorganize build process. Drop pre-translated buildvm_*.h. Rename buildvm_*.dasc to vm_*.dasc. Move buildvm* to host directory. Build minilua, unless HOST_LUA is set. Use HOST_LUA to run DynASM. Translate only vm_*.dasc for target architecture. --- src/.gitignore | 1 - src/Makefile | 167 +- src/Makefile.dep | 26 +- src/buildvm.c | 513 --- src/buildvm.h | 104 - src/buildvm_arm.dasc | 4121 ------------------- src/buildvm_arm.h | 7494 ----------------------------------- src/buildvm_asm.c | 283 -- src/buildvm_fold.c | 229 -- src/buildvm_lib.c | 377 -- src/buildvm_mips.dasc | 4224 -------------------- src/buildvm_mips.h | 7495 ----------------------------------- src/buildvm_peobj.c | 352 -- src/buildvm_ppc.dasc | 4888 ----------------------- src/buildvm_ppc.h | 9797 ---------------------------------------------- src/buildvm_ppcspe.dasc | 3705 ------------------ src/buildvm_ppcspe.h | 6094 ---------------------------- src/buildvm_x64.h | 3406 ---------------- src/buildvm_x64win.h | 3401 ---------------- src/buildvm_x86.dasc | 6458 ------------------------------ src/buildvm_x86.h | 3561 ----------------- src/host/.gitignore | 3 + src/host/buildvm.c | 504 +++ src/host/buildvm.h | 104 + src/host/buildvm_asm.c | 283 ++ src/host/buildvm_fold.c | 229 ++ src/host/buildvm_lib.c | 377 ++ src/host/buildvm_peobj.c | 352 ++ src/msvcbuild.bat | 25 +- src/vm_arm.dasc | 4121 +++++++++++++++++++ src/vm_mips.dasc | 4224 ++++++++++++++++++++ src/vm_ppc.dasc | 4888 +++++++++++++++++++++++ src/vm_ppcspe.dasc | 3705 ++++++++++++++++++ src/vm_x86.dasc | 6458 ++++++++++++++++++++++++++++++ 34 files changed, 25355 insertions(+), 66614 deletions(-) delete mode 100644 src/buildvm.c delete mode 100644 src/buildvm.h delete mode 100644 src/buildvm_arm.dasc delete mode 100644 src/buildvm_arm.h delete mode 100644 src/buildvm_asm.c delete mode 100644 src/buildvm_fold.c delete mode 100644 src/buildvm_lib.c delete mode 100644 src/buildvm_mips.dasc delete mode 100644 src/buildvm_mips.h delete mode 100644 src/buildvm_peobj.c delete mode 100644 src/buildvm_ppc.dasc delete mode 100644 src/buildvm_ppc.h delete mode 100644 src/buildvm_ppcspe.dasc delete mode 100644 src/buildvm_ppcspe.h delete mode 100644 src/buildvm_x64.h delete mode 100644 src/buildvm_x64win.h delete mode 100644 src/buildvm_x86.dasc delete mode 100644 src/buildvm_x86.h create mode 100644 src/host/.gitignore create mode 100644 src/host/buildvm.c create mode 100644 src/host/buildvm.h create mode 100644 src/host/buildvm_asm.c create mode 100644 src/host/buildvm_fold.c create mode 100644 src/host/buildvm_lib.c create mode 100644 src/host/buildvm_peobj.c create mode 100644 src/vm_arm.dasc create mode 100644 src/vm_mips.dasc create mode 100644 src/vm_ppc.dasc create mode 100644 src/vm_ppcspe.dasc create mode 100644 src/vm_x86.dasc (limited to 'src') diff --git a/src/.gitignore b/src/.gitignore index 8373308b..fc94e82c 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,5 +1,4 @@ luajit -buildvm lj_bcdef.h lj_ffdef.h lj_libdef.h diff --git a/src/Makefile b/src/Makefile index 5977c373..86b8b4fa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -49,12 +49,12 @@ CCOPT= -O2 -fomit-frame-pointer # x86/x64 only: For GCC 4.2 or higher and if you don't intend to distribute # the binaries to a different machine you could also use: -march=native # -CCOPT_X86= -march=i686 -CCOPT_X64= -CCOPT_ARM= -CCOPT_PPC= -CCOPT_PPCSPE= -CCOPT_MIPS= +CCOPT_x86= -march=i686 +CCOPT_x64= +CCOPT_arm= +CCOPT_ppc= +CCOPT_ppcspe= +CCOPT_mips= # CCDEBUG= # Uncomment the next line to generate debug information: @@ -182,13 +182,11 @@ LDOPTIONS= $(CCDEBUG) $(LDFLAGS) HOST_CC= $(CC) HOST_RM= rm -f -# NOTE: The LuaJIT distribution comes with pre-generated buildvm_*.h files. -# You DO NOT NEED an installed copy of (plain) Lua 5.1 to run DynASM unless -# you want to MODIFY the corresponding *.dasc file. You can also use LuaJIT -# itself (bootstrapped from a pre-generated file) to run DynASM of course. -HOST_LUA= lua +# If left blank, minilua is built and used. You can supply an installed +# copy of (plain) Lua 5.1 or 5.2, e.g. with: HOST_LUA=lua +HOST_LUA= -HOST_XCFLAGS= +HOST_XCFLAGS= -I. HOST_XLDFLAGS= HOST_XLIBS= HOST_ACFLAGS= $(CCOPTIONS) $(HOST_XCFLAGS) $(TARGET_ARCH) $(HOST_CFLAGS) @@ -223,31 +221,25 @@ TARGET_ALIBS= $(TARGET_XLIBS) $(LIBS) $(TARGET_LIBS) TARGET_TESTARCH=$(shell $(TARGET_CC) $(TARGET_TCFLAGS) -E lj_arch.h -dM) ifneq (,$(findstring LJ_TARGET_X64 ,$(TARGET_TESTARCH))) - TARGET_CCARCH= x64 - TARGET_XCFLAGS+= $(CCOPT_X64) + TARGET_LJARCH= x64 else ifneq (,$(findstring LJ_TARGET_X86 ,$(TARGET_TESTARCH))) - TARGET_CCARCH= x86 - TARGET_XCFLAGS+= $(CCOPT_X86) + TARGET_LJARCH= x86 else ifneq (,$(findstring LJ_TARGET_ARM ,$(TARGET_TESTARCH))) - TARGET_CCARCH= arm - TARGET_XCFLAGS+= $(CCOPT_ARM) + TARGET_LJARCH= arm else ifneq (,$(findstring LJ_TARGET_PPC ,$(TARGET_TESTARCH))) - TARGET_CCARCH= ppc - TARGET_XCFLAGS+= $(CCOPT_PPC) + TARGET_LJARCH= ppc else ifneq (,$(findstring LJ_TARGET_PPCSPE ,$(TARGET_TESTARCH))) - TARGET_CCARCH= ppcspe - TARGET_XCFLAGS+= $(CCOPT_PPCSPE) + TARGET_LJARCH= ppcspe else ifneq (,$(findstring LJ_TARGET_MIPS ,$(TARGET_TESTARCH))) ifneq (,$(findstring MIPSEL ,$(TARGET_TESTARCH))) TARGET_ARCH= -D__MIPSEL__=1 endif - TARGET_CCARCH= mips - TARGET_XCFLAGS+= $(CCOPT_MIPS) + TARGET_LJARCH= mips else $(error Unsupported target architecture) endif @@ -257,7 +249,8 @@ endif endif endif -TARGET_ARCH+= $(patsubst %,-DLUAJIT_TARGET=LUAJIT_ARCH_%,$(TARGET_CCARCH)) +TARGET_XCFLAGS+= $(CCOPT_$(TARGET_LJARCH)) +TARGET_ARCH+= $(patsubst %,-DLUAJIT_TARGET=LUAJIT_ARCH_%,$(TARGET_LJARCH)) ifneq (,$(PREFIX)) ifneq (/usr/local,$(PREFIX)) @@ -300,7 +293,7 @@ ifeq (Darwin,$(TARGET_SYS)) 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_CCARCH)) + ifeq (x64,$(TARGET_LJARCH)) TARGET_XLDFLAGS+= -pagezero_size 10000 -image_base 100000000 TARGET_XSHLDFLAGS+= -image_base 7fff04c4a000 endif @@ -357,24 +350,41 @@ endif # Files and pathnames. ############################################################################## +MINILUA_O= host/minilua.o +MINILUA_LIBS= -lm +MINILUA_T= host/minilua +MINILUA_X= $(MINILUA_T) + +ifeq (,$(HOST_LUA)) + HOST_LUA= $(MINILUA_X) + DASM_DEP= $(MINILUA_T) +endif + DASM_DIR= ../dynasm DASM= $(HOST_LUA) $(DASM_DIR)/dynasm.lua -DASM_FLAGS= -DASM_DISTFLAGS= -LN -DASM_FLAGS_X86= -DASM_FLAGS_X64= -D X64 -DASM_FLAGS_X64WIN= -D X64 -D X64WIN -DASM_FLAGS_ARM= -DASM_FLAGS_PPC= -DASM_FLAGS_PPCSPE= -DASM_FLAGS_MIPS= - -BUILDVM_O= buildvm.o buildvm_asm.o buildvm_peobj.o buildvm_lib.o buildvm_fold.o -BUILDVM_T= buildvm -BUILDVM_X= ./$(BUILDVM_T) - -HOST_O= $(BUILDVM_O) -HOST_T= $(BUILDVM_T) +DASM_XFLAGS= +DASM_AFLAGS= +DASM_ARCH= $(TARGET_LJARCH) + +ifeq (x64,$(TARGET_LJARCH)) + DASM_ARCH= x86 + ifeq (Windows,$(TARGET_SYS)) + DASM_AFLAGS+= -D X64 -D X64WIN + else + DASM_AFLAGS+= -D X64 + endif +endif + +DASM_FLAGS= $(DASM_XFLAGS) $(DASM_AFLAGS) +DASM_DASC= vm_$(DASM_ARCH).dasc + +BUILDVM_O= host/buildvm.o host/buildvm_asm.o host/buildvm_peobj.o \ + host/buildvm_lib.o host/buildvm_fold.o +BUILDVM_T= host/buildvm +BUILDVM_X= $(BUILDVM_T) + +HOST_O= $(MINILUA_O) $(BUILDVM_O) +HOST_T= $(MINILUA_T) $(BUILDVM_T) LJVM_S= lj_vm.s LJVM_O= lj_vm.o @@ -409,13 +419,12 @@ LUAJIT_A= libluajit.a LUAJIT_SO= libluajit.so LUAJIT_T= luajit -ALL_T= $(LUAJIT_T) $(LUAJIT_A) $(LUAJIT_SO) $(BUILDVM_T) -ALL_HDRGEN= lj_bcdef.h lj_ffdef.h lj_libdef.h lj_recdef.h lj_folddef.h +ALL_T= $(LUAJIT_T) $(LUAJIT_A) $(LUAJIT_SO) $(HOST_T) +ALL_HDRGEN= lj_bcdef.h lj_ffdef.h lj_libdef.h lj_recdef.h lj_folddef.h \ + host/buildvm_arch.h ALL_GEN= $(LJVM_S) $(ALL_HDRGEN) $(LIB_VMDEFP) -ALL_DYNGEN= buildvm_x86.h buildvm_x64.h buildvm_x64win.h buildvm_arm.h \ - buildvm_ppc.h buildvm_ppcspe.h buildvm_mips.h WIN_RM= *.obj *.lib *.exp *.dll *.exe *.manifest *.pdb *.ilk -ALL_RM= $(ALL_T) $(ALL_GEN) *.o $(WIN_RM) +ALL_RM= $(ALL_T) $(ALL_GEN) *.o host/*.o $(WIN_RM) ############################################################################## # Build mode handling. @@ -427,8 +436,11 @@ TARGET_T= $(LUAJIT_T) $(LUAJIT_SO) TARGET_DEP= $(LIB_VMDEF) $(LUAJIT_SO) ifeq (Windows,$(HOST_SYS)) - BUILDVM_T= buildvm.exe - LIB_VMDEFP= $(subst /,\\,$(LIB_VMDEF)) + MINILUA_T= host/minilua.exe + MINILUA_X= host\minilua + BUILDVM_T= host/buildvm.exe + BUILDVM_X= host\buildvm + ALL_RM:= $(subst /,\,$(ALL_RM)) endif ifeq (Windows,$(TARGET_SYS)) TARGET_DYNCC= $(STATIC_CC) @@ -495,68 +507,39 @@ amalg: clean: $(HOST_RM) $(ALL_RM) -cleaner: - $(HOST_RM) $(ALL_RM) $(ALL_DYNGEN) - -distclean: clean - $(E) "DYNASM $@" - $(Q)$(DASM) $(DASM_DISTFLAGS) $(DASM_FLAGS_X86) -o buildvm_x86.h buildvm_x86.dasc - $(Q)$(DASM) $(DASM_DISTFLAGS) $(DASM_FLAGS_X64) -o buildvm_x64.h buildvm_x86.dasc - $(Q)$(DASM) $(DASM_DISTFLAGS) $(DASM_FLAGS_X64WIN) -o buildvm_x64win.h buildvm_x86.dasc - $(Q)$(DASM) $(DASM_DISTFLAGS) $(DASM_FLAGS_ARM) -o buildvm_arm.h buildvm_arm.dasc - $(Q)$(DASM) $(DASM_DISTFLAGS) $(DASM_FLAGS_PPC) -o buildvm_ppc.h buildvm_ppc.dasc - $(Q)$(DASM) $(DASM_DISTFLAGS) $(DASM_FLAGS_PPCSPE) -o buildvm_ppcspe.h buildvm_ppcspe.dasc - $(Q)$(DASM) $(DASM_DISTFLAGS) $(DASM_FLAGS_MIPS) -o buildvm_mips.h buildvm_mips.dasc +# Temporary rule for migration from old file layout. +cleaner: clean + $(HOST_RM) buildvm* depend: - @for file in $(ALL_HDRGEN) $(ALL_DYNGEN); do \ + @for file in $(ALL_HDRGEN); do \ test -f $$file || touch $$file; \ done - @$(HOST_CC) $(HOST_ACFLAGS) -MM *.c | \ + @$(HOST_CC) $(HOST_ACFLAGS) -MM *.c host/*.c | \ sed -e "s| [^ ]*/dasm_\S*\.h||g" \ - -e "s| buildvm_\S*\.h||g" \ + -e "s|^\([^l ]\)|host/\1|" \ -e "s| lj_target_\S*\.h| lj_target_*.h|g" \ -e "s| lj_emit_\S*\.h| lj_emit_*.h|g" \ -e "s| lj_asm_\S*\.h| lj_asm_*.h|g" >Makefile.dep - @for file in $(ALL_HDRGEN) $(ALL_DYNGEN); do \ + @for file in $(ALL_HDRGEN); do \ test -s $$file || $(HOST_RM) $$file; \ done -.PHONY: default all amalg clean cleaner distclean depend +.PHONY: default all amalg clean cleaner depend ############################################################################## # Rules for generated files. ############################################################################## -buildvm_x86.h: buildvm_x86.dasc - $(E) "DYNASM $@" - $(Q)$(DASM) $(DASM_FLAGS) $(DASM_FLAGS_X86) -o $@ buildvm_x86.dasc - -buildvm_x64.h: buildvm_x86.dasc - $(E) "DYNASM $@" - $(Q)$(DASM) $(DASM_FLAGS) $(DASM_FLAGS_X64) -o $@ buildvm_x86.dasc - -buildvm_x64win.h: buildvm_x86.dasc - $(E) "DYNASM $@" - $(Q)$(DASM) $(DASM_FLAGS) $(DASM_FLAGS_X64WIN) -o $@ buildvm_x86.dasc - -buildvm_arm.h: buildvm_arm.dasc - $(E) "DYNASM $@" - $(Q)$(DASM) $(DASM_FLAGS) $(DASM_FLAGS_ARM) -o $@ buildvm_arm.dasc - -buildvm_ppc.h: buildvm_ppc.dasc - $(E) "DYNASM $@" - $(Q)$(DASM) $(DASM_FLAGS) $(DASM_FLAGS_PPC) -o $@ buildvm_ppc.dasc - -buildvm_ppcspe.h: buildvm_ppcspe.dasc - $(E) "DYNASM $@" - $(Q)$(DASM) $(DASM_FLAGS) $(DASM_FLAGS_PPCSPE) -o $@ buildvm_ppcspe.dasc +$(MINILUA_T): $(MINILUA_O) + $(E) "HOSTLINK $@" + $(Q)$(HOST_CC) $(HOST_ALDFLAGS) -o $@ $(MINILUA_O) $(MINILUA_LIBS) $(HOST_ALIBS) -buildvm_mips.h: buildvm_mips.dasc +host/buildvm_arch.h: $(DASM_DASC) $(DASM_DEP) $(E) "DYNASM $@" - $(Q)$(DASM) $(DASM_FLAGS) $(DASM_FLAGS_MIPS) -o $@ buildvm_mips.dasc + $(Q)$(DASM) $(DASM_FLAGS) -o $@ $(DASM_DASC) -buildvm.o: $(ALL_DYNGEN) $(DASM_DIR)/dasm_*.h +host/buildvm.o: $(DASM_DIR)/dasm_*.h $(BUILDVM_T): $(BUILDVM_O) $(E) "HOSTLINK $@" diff --git a/src/Makefile.dep b/src/Makefile.dep index 82cdc0d7..ff4492fb 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,15 +1,3 @@ -buildvm.o: buildvm.c buildvm.h lj_def.h lua.h luaconf.h lj_arch.h \ - lj_obj.h lj_gc.h lj_bc.h lj_ir.h lj_ircall.h lj_jit.h lj_frame.h \ - lj_dispatch.h lj_ctype.h lj_ccall.h luajit.h \ - lj_traceerr.h -buildvm_asm.o: buildvm_asm.c buildvm.h lj_def.h lua.h luaconf.h lj_arch.h \ - lj_bc.h -buildvm_fold.o: buildvm_fold.c buildvm.h lj_def.h lua.h luaconf.h \ - lj_arch.h lj_obj.h lj_ir.h -buildvm_lib.o: buildvm_lib.c buildvm.h lj_def.h lua.h luaconf.h lj_arch.h \ - lj_obj.h lj_lib.h -buildvm_peobj.o: buildvm_peobj.c buildvm.h lj_def.h lua.h luaconf.h \ - lj_arch.h lj_bc.h 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_lib.h lj_alloc.h lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ @@ -207,3 +195,17 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \ 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 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 \ + lj_ircall.h lj_ir.h lj_jit.h lj_frame.h lj_bc.h lj_dispatch.h lj_ctype.h \ + lj_gc.h lj_ccall.h lj_ctype.h luajit.h \ + host/buildvm_arch.h lj_traceerr.h +host/buildvm_asm.o: host/buildvm_asm.c host/buildvm.h lj_def.h lua.h luaconf.h \ + lj_arch.h lj_bc.h lj_def.h lj_arch.h +host/buildvm_fold.o: host/buildvm_fold.c host/buildvm.h lj_def.h lua.h \ + luaconf.h lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_ir.h lj_obj.h +host/buildvm_lib.o: host/buildvm_lib.c host/buildvm.h lj_def.h lua.h luaconf.h \ + lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_lib.h lj_obj.h +host/buildvm_peobj.o: host/buildvm_peobj.c host/buildvm.h lj_def.h lua.h \ + luaconf.h lj_arch.h lj_bc.h lj_def.h lj_arch.h +host/minilua.o: host/minilua.c diff --git a/src/buildvm.c b/src/buildvm.c deleted file mode 100644 index 29cf7378..00000000 --- a/src/buildvm.c +++ /dev/null @@ -1,513 +0,0 @@ -/* -** LuaJIT VM builder. -** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -** -** This is a tool to build the hand-tuned assembler code required for -** LuaJIT's bytecode interpreter. It supports a variety of output formats -** to feed different toolchains (see usage() below). -** -** This tool is not particularly optimized because it's only used while -** _building_ LuaJIT. There's no point in distributing or installing it. -** Only the object code generated by this tool is linked into LuaJIT. -** -** Caveat: some memory is not free'd, error handling is lazy. -** It's a one-shot tool -- any effort fixing this would be wasted. -*/ - -#include "buildvm.h" -#include "lj_obj.h" -#include "lj_gc.h" -#include "lj_bc.h" -#include "lj_ir.h" -#include "lj_ircall.h" -#include "lj_frame.h" -#include "lj_dispatch.h" -#if LJ_HASFFI -#include "lj_ctype.h" -#include "lj_ccall.h" -#endif -#include "luajit.h" - -#if defined(_WIN32) -#include -#include -#endif - -/* ------------------------------------------------------------------------ */ - -/* DynASM glue definitions. */ -#define Dst ctx -#define Dst_DECL BuildCtx *ctx -#define Dst_REF (ctx->D) -#define DASM_CHECKS 1 - -#include "../dynasm/dasm_proto.h" - -/* Glue macros for DynASM. */ -static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type); - -#define DASM_EXTERN(ctx, addr, idx, type) \ - collect_reloc(ctx, addr, idx, type) - -/* ------------------------------------------------------------------------ */ - -/* Avoid trouble if cross-compiling for an x86 target. Speed doesn't matter. */ -#define DASM_ALIGNED_WRITES 1 - -/* Embed architecture-specific DynASM encoder and backend. */ -#if LJ_TARGET_X86 -#include "../dynasm/dasm_x86.h" -#include "buildvm_x86.h" -#elif LJ_TARGET_X64 -#include "../dynasm/dasm_x86.h" -#if LJ_ABI_WIN -#include "buildvm_x64win.h" -#else -#include "buildvm_x64.h" -#endif -#elif LJ_TARGET_ARM -#include "../dynasm/dasm_arm.h" -#include "buildvm_arm.h" -#elif LJ_TARGET_PPC -#include "../dynasm/dasm_ppc.h" -#include "buildvm_ppc.h" -#elif LJ_TARGET_PPCSPE -#include "../dynasm/dasm_ppc.h" -#include "buildvm_ppcspe.h" -#elif LJ_TARGET_MIPS -#include "../dynasm/dasm_mips.h" -#include "buildvm_mips.h" -#else -#error "No support for this architecture (yet)" -#endif - -/* ------------------------------------------------------------------------ */ - -void owrite(BuildCtx *ctx, const void *ptr, size_t sz) -{ - if (fwrite(ptr, 1, sz, ctx->fp) != sz) { - fprintf(stderr, "Error: cannot write to output file: %s\n", - strerror(errno)); - exit(1); - } -} - -/* ------------------------------------------------------------------------ */ - -/* Emit code as raw bytes. Only used for DynASM debugging. */ -static void emit_raw(BuildCtx *ctx) -{ - owrite(ctx, ctx->code, ctx->codesz); -} - -/* -- Build machine code -------------------------------------------------- */ - -static const char *sym_decorate(BuildCtx *ctx, - const char *prefix, const char *suffix) -{ - char name[256]; - char *p; -#if LJ_64 - const char *symprefix = ctx->mode == BUILD_machasm ? "_" : ""; -#else - const char *symprefix = ctx->mode != BUILD_elfasm ? "_" : ""; -#endif - sprintf(name, "%s%s%s", symprefix, prefix, suffix); - p = strchr(name, '@'); - if (p) { - if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj)) - name[0] = '@'; - else - *p = '\0'; - } - p = (char *)malloc(strlen(name)+1); /* MSVC doesn't like strdup. */ - strcpy(p, name); - return p; -} - -#define NRELOCSYM (sizeof(extnames)/sizeof(extnames[0])-1) - -static int relocmap[NRELOCSYM]; - -/* Collect external relocations. */ -static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type) -{ - if (ctx->nreloc >= BUILD_MAX_RELOC) { - fprintf(stderr, "Error: too many relocations, increase BUILD_MAX_RELOC.\n"); - exit(1); - } - if (relocmap[idx] < 0) { - relocmap[idx] = ctx->nrelocsym; - ctx->relocsym[ctx->nrelocsym] = sym_decorate(ctx, "", extnames[idx]); - ctx->nrelocsym++; - } - ctx->reloc[ctx->nreloc].ofs = (int32_t)(addr - ctx->code); - ctx->reloc[ctx->nreloc].sym = relocmap[idx]; - ctx->reloc[ctx->nreloc].type = type; - ctx->nreloc++; - return 0; /* Encode symbol offset of 0. */ -} - -/* Naive insertion sort. Performance doesn't matter here. */ -static void sym_insert(BuildCtx *ctx, int32_t ofs, - const char *prefix, const char *suffix) -{ - ptrdiff_t i = ctx->nsym++; - while (i > 0) { - if (ctx->sym[i-1].ofs <= ofs) - break; - ctx->sym[i] = ctx->sym[i-1]; - i--; - } - ctx->sym[i].ofs = ofs; - ctx->sym[i].name = sym_decorate(ctx, prefix, suffix); -} - -/* Build the machine code. */ -static int build_code(BuildCtx *ctx) -{ - int status; - int i; - - /* Initialize DynASM structures. */ - ctx->nglob = GLOB__MAX; - ctx->glob = (void **)malloc(ctx->nglob*sizeof(void *)); - memset(ctx->glob, 0, ctx->nglob*sizeof(void *)); - ctx->nreloc = 0; - - ctx->globnames = globnames; - ctx->relocsym = (const char **)malloc(NRELOCSYM*sizeof(const char *)); - ctx->nrelocsym = 0; - for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1; - - ctx->dasm_ident = DASM_IDENT; - ctx->dasm_arch = DASM_ARCH; - - dasm_init(Dst, DASM_MAXSECTION); - dasm_setupglobal(Dst, ctx->glob, ctx->nglob); - dasm_setup(Dst, build_actionlist); - - /* Call arch-specific backend to emit the code. */ - ctx->npc = build_backend(ctx); - - /* Finalize the code. */ - (void)dasm_checkstep(Dst, -1); - if ((status = dasm_link(Dst, &ctx->codesz))) return status; - ctx->code = (uint8_t *)malloc(ctx->codesz); - if ((status = dasm_encode(Dst, (void *)ctx->code))) return status; - - /* Allocate symbol table and bytecode offsets. */ - ctx->beginsym = sym_decorate(ctx, "", LABEL_PREFIX "vm_asm_begin"); - ctx->sym = (BuildSym *)malloc((ctx->npc+ctx->nglob+1)*sizeof(BuildSym)); - ctx->nsym = 0; - ctx->bc_ofs = (int32_t *)malloc(ctx->npc*sizeof(int32_t)); - - /* Collect the opcodes (PC labels). */ - for (i = 0; i < ctx->npc; i++) { - int32_t ofs = dasm_getpclabel(Dst, i); - if (ofs < 0) return 0x22000000|i; - ctx->bc_ofs[i] = ofs; - if ((LJ_HASJIT || - !(i == BC_JFORI || i == BC_JFORL || i == BC_JITERL || i == BC_JLOOP || - i == BC_IFORL || i == BC_IITERL || i == BC_ILOOP)) && - (LJ_HASFFI || i != BC_KCDATA)) - sym_insert(ctx, ofs, LABEL_PREFIX_BC, bc_names[i]); - } - - /* Collect the globals (named labels). */ - for (i = 0; i < ctx->nglob; i++) { - const char *gl = globnames[i]; - int len = (int)strlen(gl); - if (!ctx->glob[i]) { - fprintf(stderr, "Error: undefined global %s\n", gl); - exit(2); - } - /* Skip the _Z symbols. */ - if (!(len >= 2 && gl[len-2] == '_' && gl[len-1] == 'Z')) - sym_insert(ctx, (int32_t)((uint8_t *)(ctx->glob[i]) - ctx->code), - LABEL_PREFIX, globnames[i]); - } - - /* Close the address range. */ - sym_insert(ctx, (int32_t)ctx->codesz, "", ""); - ctx->nsym--; - - dasm_free(Dst); - - return 0; -} - -/* -- Generate VM enums --------------------------------------------------- */ - -const char *const bc_names[] = { -#define BCNAME(name, ma, mb, mc, mt) #name, -BCDEF(BCNAME) -#undef BCNAME - NULL -}; - -const char *const ir_names[] = { -#define IRNAME(name, m, m1, m2) #name, -IRDEF(IRNAME) -#undef IRNAME - NULL -}; - -const char *const irt_names[] = { -#define IRTNAME(name) #name, -IRTDEF(IRTNAME) -#undef IRTNAME - NULL -}; - -const char *const irfpm_names[] = { -#define FPMNAME(name) #name, -IRFPMDEF(FPMNAME) -#undef FPMNAME - NULL -}; - -const char *const irfield_names[] = { -#define FLNAME(name, ofs) #name, -IRFLDEF(FLNAME) -#undef FLNAME - NULL -}; - -const char *const ircall_names[] = { -#define IRCALLNAME(cond, name, nargs, kind, type, flags) #name, -IRCALLDEF(IRCALLNAME) -#undef IRCALLNAME - NULL -}; - -static const char *const trace_errors[] = { -#define TREDEF(name, msg) msg, -#include "lj_traceerr.h" - NULL -}; - -static const char *lower(char *buf, const char *s) -{ - char *p = buf; - while (*s) { - *p++ = (*s >= 'A' && *s <= 'Z') ? *s+0x20 : *s; - s++; - } - *p = '\0'; - return buf; -} - -/* Emit C source code for bytecode-related definitions. */ -static void emit_bcdef(BuildCtx *ctx) -{ - int i; - fprintf(ctx->fp, "/* This is a generated file. DO NOT EDIT! */\n\n"); - fprintf(ctx->fp, "LJ_DATADEF const uint16_t lj_bc_ofs[] = {\n"); - for (i = 0; i < ctx->npc; i++) { - if (i != 0) - fprintf(ctx->fp, ",\n"); - fprintf(ctx->fp, "%d", ctx->bc_ofs[i]); - } -} - -/* Emit VM definitions as Lua code for debug modules. */ -static void emit_vmdef(BuildCtx *ctx) -{ - char buf[80]; - int i; - fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\n\n"); - fprintf(ctx->fp, "module(...)\n\n"); - - fprintf(ctx->fp, "bcnames = \""); - for (i = 0; bc_names[i]; i++) fprintf(ctx->fp, "%-6s", bc_names[i]); - fprintf(ctx->fp, "\"\n\n"); - - fprintf(ctx->fp, "irnames = \""); - for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]); - fprintf(ctx->fp, "\"\n\n"); - - fprintf(ctx->fp, "irfpm = { [0]="); - for (i = 0; irfpm_names[i]; i++) - fprintf(ctx->fp, "\"%s\", ", lower(buf, irfpm_names[i])); - fprintf(ctx->fp, "}\n\n"); - - fprintf(ctx->fp, "irfield = { [0]="); - for (i = 0; irfield_names[i]; i++) { - char *p; - lower(buf, irfield_names[i]); - p = strchr(buf, '_'); - if (p) *p = '.'; - fprintf(ctx->fp, "\"%s\", ", buf); - } - fprintf(ctx->fp, "}\n\n"); - - fprintf(ctx->fp, "ircall = {\n[0]="); - for (i = 0; ircall_names[i]; i++) - fprintf(ctx->fp, "\"%s\",\n", ircall_names[i]); - fprintf(ctx->fp, "}\n\n"); - - fprintf(ctx->fp, "traceerr = {\n[0]="); - for (i = 0; trace_errors[i]; i++) - fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]); - fprintf(ctx->fp, "}\n\n"); -} - -/* -- Argument parsing ---------------------------------------------------- */ - -/* Build mode names. */ -static const char *const modenames[] = { -#define BUILDNAME(name) #name, -BUILDDEF(BUILDNAME) -#undef BUILDNAME - NULL -}; - -/* Print usage information and exit. */ -static void usage(void) -{ - int i; - fprintf(stderr, LUAJIT_VERSION " VM builder.\n"); - fprintf(stderr, LUAJIT_COPYRIGHT ", " LUAJIT_URL "\n"); - fprintf(stderr, "Target architecture: " LJ_ARCH_NAME "\n\n"); - fprintf(stderr, "Usage: buildvm -m mode [-o outfile] [infiles...]\n\n"); - fprintf(stderr, "Available modes:\n"); - for (i = 0; i < BUILD__MAX; i++) - fprintf(stderr, " %s\n", modenames[i]); - exit(1); -} - -/* Parse the output mode name. */ -static BuildMode parsemode(const char *mode) -{ - int i; - for (i = 0; modenames[i]; i++) - if (!strcmp(mode, modenames[i])) - return (BuildMode)i; - usage(); - return (BuildMode)-1; -} - -/* Parse arguments. */ -static void parseargs(BuildCtx *ctx, char **argv) -{ - const char *a; - int i; - ctx->mode = (BuildMode)-1; - ctx->outname = "-"; - for (i = 1; (a = argv[i]) != NULL; i++) { - if (a[0] != '-') - break; - switch (a[1]) { - case '-': - if (a[2]) goto err; - i++; - goto ok; - case '\0': - goto ok; - case 'm': - i++; - if (a[2] || argv[i] == NULL) goto err; - ctx->mode = parsemode(argv[i]); - break; - case 'o': - i++; - if (a[2] || argv[i] == NULL) goto err; - ctx->outname = argv[i]; - break; - default: err: - usage(); - break; - } - } -ok: - ctx->args = argv+i; - if (ctx->mode == (BuildMode)-1) goto err; -} - -int main(int argc, char **argv) -{ - BuildCtx ctx_; - BuildCtx *ctx = &ctx_; - int status, binmode; - - if (sizeof(void *) != 4*LJ_32+8*LJ_64) { - fprintf(stderr,"Error: pointer size mismatch in cross-build.\n"); - fprintf(stderr,"Try: make HOST_CC=\"gcc -m32\" CROSS=... TARGET=...\n\n"); - return 1; - } - - UNUSED(argc); - parseargs(ctx, argv); - - if ((status = build_code(ctx))) { - fprintf(stderr,"Error: DASM error %08x\n", status); - return 1; - } - - switch (ctx->mode) { - case BUILD_peobj: - case BUILD_raw: - binmode = 1; - break; - default: - binmode = 0; - break; - } - - if (ctx->outname[0] == '-' && ctx->outname[1] == '\0') { - ctx->fp = stdout; -#if defined(_WIN32) - if (binmode) - _setmode(_fileno(stdout), _O_BINARY); /* Yuck. */ -#endif - } else if (!(ctx->fp = fopen(ctx->outname, binmode ? "wb" : "w"))) { - fprintf(stderr, "Error: cannot open output file '%s': %s\n", - ctx->outname, strerror(errno)); - exit(1); - } - - switch (ctx->mode) { - case BUILD_elfasm: - case BUILD_coffasm: - case BUILD_machasm: - emit_asm(ctx); - emit_asm_debug(ctx); - break; - case BUILD_peobj: - emit_peobj(ctx); - break; - case BUILD_raw: - emit_raw(ctx); - break; - case BUILD_bcdef: - emit_bcdef(ctx); - emit_lib(ctx); - break; - case BUILD_vmdef: - emit_vmdef(ctx); - emit_lib(ctx); - break; - case BUILD_ffdef: - case BUILD_libdef: - case BUILD_recdef: - emit_lib(ctx); - break; - case BUILD_folddef: - emit_fold(ctx); - break; - default: - break; - } - - fflush(ctx->fp); - if (ferror(ctx->fp)) { - fprintf(stderr, "Error: cannot write to output file: %s\n", - strerror(errno)); - exit(1); - } - fclose(ctx->fp); - - return 0; -} - diff --git a/src/buildvm.h b/src/buildvm.h deleted file mode 100644 index 2b7168ed..00000000 --- a/src/buildvm.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -** LuaJIT VM builder. -** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -*/ - -#ifndef _BUILDVM_H -#define _BUILDVM_H - -#include -#include -#include -#include -#include - -#include "lj_def.h" -#include "lj_arch.h" - -/* Hardcoded limits. Increase as needed. */ -#define BUILD_MAX_RELOC 200 /* Max. number of relocations. */ -#define BUILD_MAX_FOLD 4096 /* Max. number of fold rules. */ - -/* Prefix for scanned library definitions. */ -#define LIBDEF_PREFIX "LJLIB_" - -/* Prefix for scanned fold definitions. */ -#define FOLDDEF_PREFIX "LJFOLD" - -/* Prefixes for generated labels. */ -#define LABEL_PREFIX "lj_" -#define LABEL_PREFIX_BC LABEL_PREFIX "BC_" -#define LABEL_PREFIX_FF LABEL_PREFIX "ff_" -#define LABEL_PREFIX_CF LABEL_PREFIX "cf_" -#define LABEL_PREFIX_FFH LABEL_PREFIX "ffh_" -#define LABEL_PREFIX_LIBCF LABEL_PREFIX "lib_cf_" -#define LABEL_PREFIX_LIBINIT LABEL_PREFIX "lib_init_" - -/* Forward declaration. */ -struct dasm_State; - -/* Build modes. */ -#define BUILDDEF(_) \ - _(elfasm) _(coffasm) _(machasm) _(peobj) _(raw) \ - _(bcdef) _(ffdef) _(libdef) _(recdef) _(vmdef) \ - _(folddef) - -typedef enum { -#define BUILDENUM(name) BUILD_##name, -BUILDDEF(BUILDENUM) -#undef BUILDENUM - BUILD__MAX -} BuildMode; - -/* Code relocation. */ -typedef struct BuildReloc { - int32_t ofs; - int sym; - int type; -} BuildReloc; - -typedef struct BuildSym { - const char *name; - int32_t ofs; -} BuildSym; - -/* Build context structure. */ -typedef struct BuildCtx { - /* DynASM state pointer. Should be first member. */ - struct dasm_State *D; - /* Parsed command line. */ - BuildMode mode; - FILE *fp; - const char *outname; - char **args; - /* Code and symbols generated by DynASM. */ - uint8_t *code; - size_t codesz; - int npc, nglob, nsym, nreloc, nrelocsym; - void **glob; - BuildSym *sym; - const char **relocsym; - int32_t *bc_ofs; - const char *beginsym; - /* Strings generated by DynASM. */ - const char *const *globnames; - const char *dasm_ident; - const char *dasm_arch; - /* Relocations. */ - BuildReloc reloc[BUILD_MAX_RELOC]; -} BuildCtx; - -extern void owrite(BuildCtx *ctx, const void *ptr, size_t sz); -extern void emit_asm(BuildCtx *ctx); -extern void emit_peobj(BuildCtx *ctx); -extern void emit_lib(BuildCtx *ctx); -extern void emit_fold(BuildCtx *ctx); - -extern const char *const bc_names[]; -extern const char *const ir_names[]; -extern const char *const irt_names[]; -extern const char *const irfpm_names[]; -extern const char *const irfield_names[]; -extern const char *const ircall_names[]; - -#endif diff --git a/src/buildvm_arm.dasc b/src/buildvm_arm.dasc deleted file mode 100644 index 3a039402..00000000 --- a/src/buildvm_arm.dasc +++ /dev/null @@ -1,4121 +0,0 @@ -|// Low-level VM code for ARM CPUs. -|// Bytecode interpreter, fast functions and helper functions. -|// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -| -|.arch arm -|.section code_op, code_sub -| -|.actionlist build_actionlist -|.globals GLOB_ -|.globalnames globnames -|.externnames extnames -| -|// Note: The ragged indentation of the instructions is intentional. -|// The starting columns indicate data dependencies. -| -|//----------------------------------------------------------------------- -| -|// Fixed register assignments for the interpreter. -| -|// The following must be C callee-save. -|.define MASKR8, r4 // 255*8 constant for fast bytecode decoding. -|.define KBASE, r5 // Constants of current Lua function. -|.define PC, r6 // Next PC. -|.define DISPATCH, r7 // Opcode dispatch table. -|.define LREG, r8 // Register holding lua_State (also in SAVE_L). -| -|// C callee-save in EABI, but often refetched. Temporary in iOS 3.0+. -|.define BASE, r9 // Base of current Lua stack frame. -| -|// The following temporaries are not saved across C calls, except for RA/RC. -|.define RA, r10 // Callee-save. -|.define RC, r11 // Callee-save. -|.define RB, r12 -|.define OP, r12 // Overlaps RB, must not be lr. -|.define INS, lr -| -|// Calling conventions. Also used as temporaries. -|.define CARG1, r0 -|.define CARG2, r1 -|.define CARG3, r2 -|.define CARG4, r3 -|.define CARG12, r0 // For 1st soft-fp double. -|.define CARG34, r2 // For 2nd soft-fp double. -| -|.define CRET1, r0 -|.define CRET2, r1 -| -|// Stack layout while in interpreter. Must match with lj_frame.h. -|.define CFRAME_SPACE, #28 -|.define SAVE_ERRF, [sp, #24] -|.define SAVE_NRES, [sp, #20] -|.define SAVE_CFRAME, [sp, #16] -|.define SAVE_L, [sp, #12] -|.define SAVE_PC, [sp, #8] -|.define SAVE_MULTRES, [sp, #4] -|.define ARG5, [sp] -| -|.define TMPDhi, [sp, #4] -|.define TMPDlo, [sp] -|.define TMPD, [sp] -|.define TMPDp, sp -| -|.macro saveregs -| push {r4, r5, r6, r7, r8, r9, r10, r11, lr} -| sub sp, sp, CFRAME_SPACE -|.endmacro -|.macro restoreregs_ret -| add sp, sp, CFRAME_SPACE -| pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} -|.endmacro -| -|// Type definitions. Some of these are only used for documentation. -|.type L, lua_State, LREG -|.type GL, global_State -|.type TVALUE, TValue -|.type GCOBJ, GCobj -|.type STR, GCstr -|.type TAB, GCtab -|.type LFUNC, GCfuncL -|.type CFUNC, GCfuncC -|.type PROTO, GCproto -|.type UPVAL, GCupval -|.type NODE, Node -|.type NARGS8, int -|.type TRACE, GCtrace -| -|//----------------------------------------------------------------------- -| -|// Trap for not-yet-implemented parts. -|.macro NYI; ud; .endmacro -| -|//----------------------------------------------------------------------- -| -|// Access to frame relative to BASE. -|.define FRAME_FUNC, #-8 -|.define FRAME_PC, #-4 -| -|.macro decode_RA8, dst, ins; and dst, MASKR8, ins, lsr #5; .endmacro -|.macro decode_RB8, dst, ins; and dst, MASKR8, ins, lsr #21; .endmacro -|.macro decode_RC8, dst, ins; and dst, MASKR8, ins, lsr #13; .endmacro -|.macro decode_RD, dst, ins; lsr dst, ins, #16; .endmacro -|.macro decode_OP, dst, ins; and dst, ins, #255; .endmacro -| -|// Instruction fetch. -|.macro ins_NEXT1 -| ldrb OP, [PC] -|.endmacro -|.macro ins_NEXT2 -| ldr INS, [PC], #4 -|.endmacro -|// Instruction decode+dispatch. -|.macro ins_NEXT3 -| ldr OP, [DISPATCH, OP, lsl #2] -| decode_RA8 RA, INS -| decode_RD RC, INS -| bx OP -|.endmacro -|.macro ins_NEXT -| ins_NEXT1 -| ins_NEXT2 -| ins_NEXT3 -|.endmacro -| -|// Instruction footer. -|.if 1 -| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use. -| .define ins_next, ins_NEXT -| .define ins_next_, ins_NEXT -| .define ins_next1, ins_NEXT1 -| .define ins_next2, ins_NEXT2 -| .define ins_next3, ins_NEXT3 -|.else -| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch. -| // Affects only certain kinds of benchmarks (and only with -j off). -| .macro ins_next -| b ->ins_next -| .endmacro -| .macro ins_next1 -| .endmacro -| .macro ins_next2 -| .endmacro -| .macro ins_next3 -| b ->ins_next -| .endmacro -| .macro ins_next_ -| ->ins_next: -| ins_NEXT -| .endmacro -|.endif -| -|// Avoid register name substitution for field name. -#define field_pc pc -| -|// Call decode and dispatch. -|.macro ins_callt -| // BASE = new base, CARG3 = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC -| ldr PC, LFUNC:CARG3->field_pc -| ldrb OP, [PC] // STALL: load PC. early PC. -| ldr INS, [PC], #4 -| ldr OP, [DISPATCH, OP, lsl #2] // STALL: load OP. early OP. -| decode_RA8 RA, INS -| add RA, RA, BASE -| bx OP -|.endmacro -| -|.macro ins_call -| // BASE = new base, CARG3 = LFUNC/CFUNC, RC = nargs*8, PC = caller PC -| str PC, [BASE, FRAME_PC] -| ins_callt // STALL: locked PC. -|.endmacro -| -|//----------------------------------------------------------------------- -| -|// Macros to test operand types. -|.macro checktp, reg, tp; cmn reg, #-tp; .endmacro -|.macro checktpeq, reg, tp; cmneq reg, #-tp; .endmacro -|.macro checktpne, reg, tp; cmnne reg, #-tp; .endmacro -|.macro checkstr, reg, target; checktp reg, LJ_TSTR; bne target; .endmacro -|.macro checktab, reg, target; checktp reg, LJ_TTAB; bne target; .endmacro -|.macro checkfunc, reg, target; checktp reg, LJ_TFUNC; bne target; .endmacro -| -|// Assumes DISPATCH is relative to GL. -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -| -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) -| -|.macro hotcheck, delta -| lsr CARG1, PC, #1 -| and CARG1, CARG1, #126 -| sub CARG1, CARG1, #-GG_DISP2HOT -| ldrh CARG2, [DISPATCH, CARG1] -| subs CARG2, CARG2, #delta -| strh CARG2, [DISPATCH, CARG1] -|.endmacro -| -|.macro hotloop -| hotcheck HOTCOUNT_LOOP -| blo ->vm_hotloop -|.endmacro -| -|.macro hotcall -| hotcheck HOTCOUNT_CALL -| blo ->vm_hotcall -|.endmacro -| -|// Set current VM state. -|.macro mv_vmstate, reg, st; mvn reg, #LJ_VMST_..st; .endmacro -|.macro st_vmstate, reg; str reg, [DISPATCH, #DISPATCH_GL(vmstate)]; .endmacro -| -|// Move table write barrier back. Overwrites mark and tmp. -|.macro barrierback, tab, mark, tmp -| ldr tmp, [DISPATCH, #DISPATCH_GL(gc.grayagain)] -| bic mark, mark, #LJ_GC_BLACK // black2gray(tab) -| str tab, [DISPATCH, #DISPATCH_GL(gc.grayagain)] -| strb mark, tab->marked -| str tmp, tab->gclist -|.endmacro -| -|.macro IOS, a, b -||if (LJ_TARGET_IOS) { -| a, b -||} -|.endmacro -| -|//----------------------------------------------------------------------- - -#if !LJ_DUALNUM -#error "Only dual-number mode supported for ARM target" -#endif - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx) -{ - |.code_sub - | - |//----------------------------------------------------------------------- - |//-- Return handling ---------------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_returnp: - | // See vm_return. Also: RB = previous base. - | tst PC, #FRAME_P - | beq ->cont_dispatch - | - | // Return from pcall or xpcall fast func. - | ldr PC, [RB, FRAME_PC] // Fetch PC of previous frame. - | mvn CARG2, #~LJ_TTRUE - | mov BASE, RB - | // Prepending may overwrite the pcall frame, so do it at the end. - | str CARG2, [RA, FRAME_PC] // Prepend true to results. - | sub RA, RA, #8 - | - |->vm_returnc: - | add RC, RC, #8 // RC = (nresults+1)*8. - | ands CARG1, PC, #FRAME_TYPE - | str RC, SAVE_MULTRES - | beq ->BC_RET_Z // Handle regular return to Lua. - | - |->vm_return: - | // BASE = base, RA = resultptr, RC/MULTRES = (nresults+1)*8, PC = return - | // CARG1 = PC & FRAME_TYPE - | bic RB, PC, #FRAME_TYPEP - | cmp CARG1, #FRAME_C - | sub RB, BASE, RB // RB = previous base. - | bne ->vm_returnp - | - | str RB, L->base - | ldr KBASE, SAVE_NRES - | mv_vmstate CARG4, C - | sub BASE, BASE, #8 - | subs CARG3, RC, #8 - | lsl KBASE, KBASE, #3 // KBASE = (nresults_wanted+1)*8 - | st_vmstate CARG4 - | beq >2 - |1: - | subs CARG3, CARG3, #8 - | ldrd CARG12, [RA], #8 - | strd CARG12, [BASE], #8 - | bne <1 - |2: - | cmp KBASE, RC // More/less results wanted? - | bne >6 - |3: - | str BASE, L->top // Store new top. - | - |->vm_leave_cp: - | ldr RC, SAVE_CFRAME // Restore previous C frame. - | mov CRET1, #0 // Ok return status for vm_pcall. - | str RC, L->cframe - | - |->vm_leave_unw: - | restoreregs_ret - | - |6: - | blt >7 // Less results wanted? - | // More results wanted. Check stack size and fill up results with nil. - | ldr CARG3, L->maxstack - | mvn CARG2, #~LJ_TNIL - | cmp BASE, CARG3 - | bhs >8 - | str CARG2, [BASE, #4] - | add RC, RC, #8 - | add BASE, BASE, #8 - | b <2 - | - |7: // Less results wanted. - | sub CARG1, RC, KBASE - | cmp KBASE, #0 // LUA_MULTRET+1 case? - | subne BASE, BASE, CARG1 // Either keep top or shrink it. - | b <3 - | - |8: // Corner case: need to grow stack for filling up results. - | // This can happen if: - | // - A C function grows the stack (a lot). - | // - The GC shrinks the stack in between. - | // - A return back from a lua_call() with (high) nresults adjustment. - | str BASE, L->top // Save current top held in BASE (yes). - | mov CARG2, KBASE - | mov CARG1, L - | bl extern lj_state_growstack // (lua_State *L, int n) - | ldr BASE, L->top // Need the (realloced) L->top in BASE. - | b <2 - | - |->vm_unwind_c: // Unwind C stack, return from vm_pcall. - | // (void *cframe, int errcode) - | mov sp, CARG1 - | mov CRET1, CARG2 - |->vm_unwind_c_eh: // Landing pad for external unwinder. - | ldr L, SAVE_L - | mv_vmstate CARG4, C - | ldr GL:CARG3, L->glref - | str CARG4, GL:CARG3->vmstate - | b ->vm_leave_unw - | - |->vm_unwind_ff: // Unwind C stack, return from ff pcall. - | // (void *cframe) - | bic CARG1, CARG1, #~CFRAME_RAWMASK // Use two steps: bic sp is deprecated. - | mov sp, CARG1 - |->vm_unwind_ff_eh: // Landing pad for external unwinder. - | ldr L, SAVE_L - | mov MASKR8, #255 - | mov RC, #16 // 2 results: false + error message. - | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. - | ldr BASE, L->base - | ldr DISPATCH, L->glref // Setup pointer to dispatch table. - | mvn CARG1, #~LJ_TFALSE - | sub RA, BASE, #8 // Results start at BASE-8. - | ldr PC, [BASE, FRAME_PC] // Fetch PC of previous frame. - | add DISPATCH, DISPATCH, #GG_G2DISP - | mv_vmstate CARG2, INTERP - | str CARG1, [BASE, #-4] // Prepend false to error message. - | st_vmstate CARG2 - | b ->vm_returnc - | - |//----------------------------------------------------------------------- - |//-- Grow stack for calls ----------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_growstack_c: // Grow stack for C function. - | // CARG1 = L - | mov CARG2, #LUA_MINSTACK - | b >2 - | - |->vm_growstack_l: // Grow stack for Lua function. - | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC - | add RC, BASE, RC - | sub RA, RA, BASE - | mov CARG1, L - | str BASE, L->base - | add PC, PC, #4 // Must point after first instruction. - | str RC, L->top - | lsr CARG3, RA, #3 - |2: - | // L->base = new base, L->top = top - | str PC, SAVE_PC - | bl extern lj_state_growstack // (lua_State *L, int n) - | ldr BASE, L->base - | ldr RC, L->top - | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] - | sub NARGS8:RC, RC, BASE - | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC - | ins_callt // Just retry the call. - | - |//----------------------------------------------------------------------- - |//-- Entry points into the assembler VM --------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_resume: // Setup C frame and resume thread. - | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0) - | saveregs - | mov L, CARG1 - | ldr DISPATCH, L:CARG1->glref // Setup pointer to dispatch table. - | mov BASE, CARG2 - | add DISPATCH, DISPATCH, #GG_G2DISP - | str L, SAVE_L - | mov PC, #FRAME_CP - | str CARG3, SAVE_NRES - | add CARG2, sp, #CFRAME_RESUME - | ldrb CARG1, L->status - | str CARG3, SAVE_ERRF - | str CARG2, L->cframe - | str CARG3, SAVE_CFRAME - | cmp CARG1, #0 - | str L, SAVE_PC // Any value outside of bytecode is ok. - | beq >3 - | - | // Resume after yield (like a return). - | mov RA, BASE - | ldr BASE, L->base - | ldr CARG1, L->top - | mov MASKR8, #255 - | strb CARG3, L->status - | sub RC, CARG1, BASE - | ldr PC, [BASE, FRAME_PC] - | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. - | mv_vmstate CARG2, INTERP - | add RC, RC, #8 - | ands CARG1, PC, #FRAME_TYPE - | st_vmstate CARG2 - | str RC, SAVE_MULTRES - | beq ->BC_RET_Z - | b ->vm_return - | - |->vm_pcall: // Setup protected C frame and enter VM. - | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef) - | saveregs - | mov PC, #FRAME_CP - | str CARG4, SAVE_ERRF - | b >1 - | - |->vm_call: // Setup C frame and enter VM. - | // (lua_State *L, TValue *base, int nres1) - | saveregs - | mov PC, #FRAME_C - | - |1: // Entry point for vm_pcall above (PC = ftype). - | ldr RC, L:CARG1->cframe - | str CARG3, SAVE_NRES - | mov L, CARG1 - | str CARG1, SAVE_L - | mov BASE, CARG2 - | str sp, L->cframe // Add our C frame to cframe chain. - | ldr DISPATCH, L->glref // Setup pointer to dispatch table. - | str CARG1, SAVE_PC // Any value outside of bytecode is ok. - | str RC, SAVE_CFRAME - | add DISPATCH, DISPATCH, #GG_G2DISP - | - |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype). - | ldr RB, L->base // RB = old base (for vmeta_call). - | ldr CARG1, L->top - | mov MASKR8, #255 - | add PC, PC, BASE - | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. - | sub PC, PC, RB // PC = frame delta + frame type - | mv_vmstate CARG2, INTERP - | sub NARGS8:RC, CARG1, BASE - | st_vmstate CARG2 - | - |->vm_call_dispatch: - | // RB = old base, BASE = new base, RC = nargs*8, PC = caller PC - | ldrd CARG34, [BASE, FRAME_FUNC] - | checkfunc CARG4, ->vmeta_call - | - |->vm_call_dispatch_f: - | ins_call - | // BASE = new base, CARG3 = func, RC = nargs*8, PC = caller PC - | - |->vm_cpcall: // Setup protected C frame, call C. - | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp) - | saveregs - | mov L, CARG1 - | ldr RA, L:CARG1->stack - | str CARG1, SAVE_L - | ldr RB, L->top - | str CARG1, SAVE_PC // Any value outside of bytecode is ok. - | ldr RC, L->cframe - | sub RA, RA, RB // Compute -savestack(L, L->top). - | str sp, L->cframe // Add our C frame to cframe chain. - | mov RB, #0 - | str RA, SAVE_NRES // Neg. delta means cframe w/o frame. - | str RB, SAVE_ERRF // No error function. - | str RC, SAVE_CFRAME - | blx CARG4 // (lua_State *L, lua_CFunction func, void *ud) - | ldr DISPATCH, L->glref // Setup pointer to dispatch table. - | movs BASE, CRET1 - | mov PC, #FRAME_CP - | add DISPATCH, DISPATCH, #GG_G2DISP - | bne <3 // Else continue with the call. - | b ->vm_leave_cp // No base? Just remove C frame. - | - |//----------------------------------------------------------------------- - |//-- Metamethod handling ------------------------------------------------ - |//----------------------------------------------------------------------- - | - |//-- Continuation dispatch ---------------------------------------------- - | - |->cont_dispatch: - | // BASE = meta base, RA = resultptr, RC = (nresults+1)*8 - | ldr LFUNC:CARG3, [RB, FRAME_FUNC] - | ldr CARG1, [BASE, #-16] // Get continuation. - | mov CARG4, BASE - | mov BASE, RB // Restore caller BASE. -#if LJ_HASFFI - | 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 LJ_HASFFI - | bls >1 -#endif - | ldr KBASE, [CARG3, #PC2PROTO(k)] - | // BASE = base, RA = resultptr, CARG4 = meta base - | bx CARG1 - | -#if LJ_HASFFI - |1: - | beq ->cont_ffi_callback // cont = 1: return from FFI callback. - | // cont = 0: tailcall from C function. - | ldr CARG3, [BASE, FRAME_FUNC] - | sub CARG4, CARG4, #16 - | sub RC, CARG4, BASE - | b ->vm_call_tail -#endif - | - |->cont_cat: // RA = resultptr, CARG4 = meta base - | ldr INS, [PC, #-4] - | sub CARG2, CARG4, #16 - | ldrd CARG34, [RA] - | str BASE, L->base - | decode_RB8 RC, INS - | decode_RA8 RA, INS - | add CARG1, BASE, RC - | subs CARG1, CARG2, CARG1 - | strdne CARG34, [CARG2] - | movne CARG3, CARG1 - | bne ->BC_CAT_Z - | strd CARG34, [BASE, RA] - | b ->cont_nop - | - |//-- Table indexing metamethods ----------------------------------------- - | - |->vmeta_tgets1: - | add CARG2, BASE, RB - | b >2 - | - |->vmeta_tgets: - | sub CARG2, DISPATCH, #-DISPATCH_GL(tmptv) - | mvn CARG4, #~LJ_TTAB - | str TAB:RB, [CARG2] - | str CARG4, [CARG2, #4] - |2: - | mvn CARG4, #~LJ_TSTR - | str STR:RC, TMPDlo - | str CARG4, TMPDhi - | mov CARG3, TMPDp - | b >1 - | - |->vmeta_tgetb: // RC = index - | decode_RB8 RB, INS - | str RC, TMPDlo - | mvn CARG4, #~LJ_TISNUM - | add CARG2, BASE, RB - | str CARG4, TMPDhi - | mov CARG3, TMPDp - | b >1 - | - |->vmeta_tgetv: - | add CARG2, BASE, RB - | add CARG3, BASE, RC - |1: - | str BASE, L->base - | mov CARG1, L - | str PC, SAVE_PC - | bl extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k) - | // Returns TValue * (finished) or NULL (metamethod). - | IOS ldr BASE, L->base - | cmp CRET1, #0 - | beq >3 - | ldrd CARG34, [CRET1] - | ins_next1 - | ins_next2 - | strd CARG34, [BASE, RA] - | ins_next3 - | - |3: // Call __index metamethod. - | // BASE = base, L->top = new base, stack = cont/func/t/k - | rsb CARG1, BASE, #FRAME_CONT - | ldr BASE, L->top - | mov NARGS8:RC, #16 // 2 args for func(t, k). - | str PC, [BASE, #-12] // [cont|PC] - | add PC, CARG1, BASE - | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. - | b ->vm_call_dispatch_f - | - |//----------------------------------------------------------------------- - | - |->vmeta_tsets1: - | add CARG2, BASE, RB - | b >2 - | - |->vmeta_tsets: - | sub CARG2, DISPATCH, #-DISPATCH_GL(tmptv) - | mvn CARG4, #~LJ_TTAB - | str TAB:RB, [CARG2] - | str CARG4, [CARG2, #4] - |2: - | mvn CARG4, #~LJ_TSTR - | str STR:RC, TMPDlo - | str CARG4, TMPDhi - | mov CARG3, TMPDp - | b >1 - | - |->vmeta_tsetb: // RC = index - | decode_RB8 RB, INS - | str RC, TMPDlo - | mvn CARG4, #~LJ_TISNUM - | add CARG2, BASE, RB - | str CARG4, TMPDhi - | mov CARG3, TMPDp - | b >1 - | - |->vmeta_tsetv: - | add CARG2, BASE, RB - | add CARG3, BASE, RC - |1: - | str BASE, L->base - | mov CARG1, L - | str PC, SAVE_PC - | bl extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k) - | // Returns TValue * (finished) or NULL (metamethod). - | IOS ldr BASE, L->base - | cmp CRET1, #0 - | ldrd CARG34, [BASE, RA] - | beq >3 - | ins_next1 - | // NOBARRIER: lj_meta_tset ensures the table is not black. - | strd CARG34, [CRET1] - | ins_next2 - | ins_next3 - | - |3: // Call __newindex metamethod. - | // BASE = base, L->top = new base, stack = cont/func/t/k/(v) - | rsb CARG1, BASE, #FRAME_CONT - | ldr BASE, L->top - | mov NARGS8:RC, #24 // 3 args for func(t, k, v). - | strd CARG34, [BASE, #16] // Copy value to third argument. - | str PC, [BASE, #-12] // [cont|PC] - | add PC, CARG1, BASE - | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. - | b ->vm_call_dispatch_f - | - |//-- Comparison metamethods --------------------------------------------- - | - |->vmeta_comp: - | mov CARG1, L - | sub PC, PC, #4 - | mov CARG2, RA - | str BASE, L->base - | mov CARG3, RC - | str PC, SAVE_PC - | decode_OP CARG4, INS - | bl extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op) - | // Returns 0/1 or TValue * (metamethod). - |3: - | IOS ldr BASE, L->base - | cmp CRET1, #1 - | bhi ->vmeta_binop - |4: - | ldrh RB, [PC, #2] - | add PC, PC, #4 - | add RB, PC, RB, lsl #2 - | subhs PC, RB, #0x20000 - |->cont_nop: - | ins_next - | - |->cont_ra: // RA = resultptr - | ldr INS, [PC, #-4] - | ldrd CARG12, [RA] - | decode_RA8 CARG3, INS - | strd CARG12, [BASE, CARG3] - | b ->cont_nop - | - |->cont_condt: // RA = resultptr - | ldr CARG2, [RA, #4] - | mvn CARG1, #~LJ_TTRUE - | cmp CARG1, CARG2 // Branch if result is true. - | b <4 - | - |->cont_condf: // RA = resultptr - | ldr CARG2, [RA, #4] - | checktp CARG2, LJ_TFALSE // Branch if result is false. - | b <4 - | - |->vmeta_equal: - | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV. - | sub PC, PC, #4 - | str BASE, L->base - | mov CARG1, L - | str PC, SAVE_PC - | bl extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne) - | // Returns 0/1 or TValue * (metamethod). - | b <3 - | - |->vmeta_equal_cd: -#if LJ_HASFFI - | sub PC, PC, #4 - | str BASE, L->base - | mov CARG1, L - | mov CARG2, INS - | str PC, SAVE_PC - | bl extern lj_meta_equal_cd // (lua_State *L, BCIns op) - | // Returns 0/1 or TValue * (metamethod). - | b <3 -#endif - | - |//-- Arithmetic metamethods --------------------------------------------- - | - |->vmeta_arith_vn: - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | add CARG3, BASE, RB - | add CARG4, KBASE, RC - | b >1 - | - |->vmeta_arith_nv: - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | add CARG4, BASE, RB - | add CARG3, KBASE, RC - | b >1 - | - |->vmeta_unm: - | ldr INS, [PC, #-8] - | sub PC, PC, #4 - | add CARG3, BASE, RC - | add CARG4, BASE, RC - | b >1 - | - |->vmeta_arith_vv: - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | add CARG3, BASE, RB - | add CARG4, BASE, RC - |1: - | decode_OP OP, INS - | add CARG2, BASE, RA - | str BASE, L->base - | mov CARG1, L - | str PC, SAVE_PC - | str OP, ARG5 - | bl extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op) - | // Returns NULL (finished) or TValue * (metamethod). - | IOS ldr BASE, L->base - | cmp CRET1, #0 - | beq ->cont_nop - | - | // Call metamethod for binary op. - |->vmeta_binop: - | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2 - | sub CARG2, CRET1, BASE - | str PC, [CRET1, #-12] // [cont|PC] - | add PC, CARG2, #FRAME_CONT - | mov BASE, CRET1 - | mov NARGS8:RC, #16 // 2 args for func(o1, o2). - | b ->vm_call_dispatch - | - |->vmeta_len: - | add CARG2, BASE, RC - | str BASE, L->base - | mov CARG1, L - | str PC, SAVE_PC - | bl extern lj_meta_len // (lua_State *L, TValue *o) - | // Returns NULL (retry) or TValue * (metamethod base). - | IOS ldr BASE, L->base -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | cmp CRET1, #0 - | bne ->vmeta_binop // Binop call for compatibility. - | ldr TAB:CARG1, [BASE, RC] - | b ->BC_LEN_Z -#else - | b ->vmeta_binop // Binop call for compatibility. -#endif - | - |//-- Call metamethod ---------------------------------------------------- - | - |->vmeta_call: // Resolve and call __call metamethod. - | // RB = old base, BASE = new base, RC = nargs*8 - | mov CARG1, L - | str RB, L->base // This is the callers base! - | sub CARG2, BASE, #8 - | str PC, SAVE_PC - | add CARG3, BASE, NARGS8:RC - | IOS mov RA, BASE - | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) - | IOS mov BASE, RA - | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. - | add NARGS8:RC, NARGS8:RC, #8 // Got one more argument now. - | ins_call - | - |->vmeta_callt: // Resolve __call for BC_CALLT. - | // BASE = old base, RA = new base, RC = nargs*8 - | mov CARG1, L - | str BASE, L->base - | sub CARG2, RA, #8 - | str PC, SAVE_PC - | add CARG3, RA, NARGS8:RC - | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) - | IOS ldr BASE, L->base - | ldr LFUNC:CARG3, [RA, FRAME_FUNC] // Guaranteed to be a function here. - | ldr PC, [BASE, FRAME_PC] - | add NARGS8:RC, NARGS8:RC, #8 // Got one more argument now. - | b ->BC_CALLT2_Z - | - |//-- Argument coercion for 'for' statement ------------------------------ - | - |->vmeta_for: - | mov CARG1, L - | str BASE, L->base - | mov CARG2, RA - | str PC, SAVE_PC - | bl extern lj_meta_for // (lua_State *L, TValue *base) - | IOS ldr BASE, L->base -#if LJ_HASJIT - | ldrb OP, [PC, #-4] -#endif - | ldr INS, [PC, #-4] -#if LJ_HASJIT - | cmp OP, #BC_JFORI -#endif - | decode_RA8 RA, INS - | decode_RD RC, INS -#if LJ_HASJIT - | beq =>BC_JFORI -#endif - | b =>BC_FORI - | - |//----------------------------------------------------------------------- - |//-- Fast functions ----------------------------------------------------- - |//----------------------------------------------------------------------- - | - |.macro .ffunc, name - |->ff_ .. name: - |.endmacro - | - |.macro .ffunc_1, name - |->ff_ .. name: - | ldrd CARG12, [BASE] - | cmp NARGS8:RC, #8 - | blo ->fff_fallback - |.endmacro - | - |.macro .ffunc_2, name - |->ff_ .. name: - | ldrd CARG12, [BASE] - | ldrd CARG34, [BASE, #8] - | cmp NARGS8:RC, #16 - | blo ->fff_fallback - |.endmacro - | - |.macro .ffunc_n, name - | .ffunc_1 name - | checktp CARG2, LJ_TISNUM - | bhs ->fff_fallback - |.endmacro - | - |.macro .ffunc_nn, name - | .ffunc_2 name - | checktp CARG2, LJ_TISNUM - | cmnlo CARG4, #-LJ_TISNUM - | bhs ->fff_fallback - |.endmacro - | - |// Inlined GC threshold check. Caveat: uses CARG1 and CARG2. - |.macro ffgccheck - | ldr CARG1, [DISPATCH, #DISPATCH_GL(gc.total)] - | ldr CARG2, [DISPATCH, #DISPATCH_GL(gc.threshold)] - | cmp CARG1, CARG2 - | blge ->fff_gcstep - |.endmacro - | - |//-- Base library: checks ----------------------------------------------- - | - |.ffunc_1 assert - | checktp CARG2, LJ_TTRUE - | bhi ->fff_fallback - | ldr PC, [BASE, FRAME_PC] - | strd CARG12, [BASE, #-8] - | mov RB, BASE - | subs RA, NARGS8:RC, #8 - | add RC, NARGS8:RC, #8 // Compute (nresults+1)*8. - | beq ->fff_res // Done if exactly 1 argument. - |1: - | ldrd CARG12, [RB, #8] - | subs RA, RA, #8 - | strd CARG12, [RB], #8 - | bne <1 - | b ->fff_res - | - |.ffunc type - | ldr CARG2, [BASE, #4] - | cmp NARGS8:RC, #8 - | blo ->fff_fallback - | checktp CARG2, LJ_TISNUM - | mvnlo CARG2, #~LJ_TISNUM - | rsb CARG4, CARG2, #(int)(offsetof(GCfuncC, upvalue)>>3)-1 - | lsl CARG4, CARG4, #3 - | ldrd CARG12, [CFUNC:CARG3, CARG4] - | b ->fff_restv - | - |//-- Base library: getters and setters --------------------------------- - | - |.ffunc_1 getmetatable - | checktp CARG2, LJ_TTAB - | cmnne CARG2, #-LJ_TUDATA - | bne >6 - |1: // Field metatable must be at same offset for GCtab and GCudata! - | ldr TAB:RB, TAB:CARG1->metatable - |2: - | mvn CARG2, #~LJ_TNIL - | ldr STR:RC, [DISPATCH, #DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])] - | cmp TAB:RB, #0 - | beq ->fff_restv - | ldr CARG3, TAB:RB->hmask - | ldr CARG4, STR:RC->hash - | ldr NODE:INS, TAB:RB->node - | and CARG3, CARG3, CARG4 // idx = str->hash & tab->hmask - | add CARG3, CARG3, CARG3, lsl #1 - | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8 - |3: // Rearranged logic, because we expect _not_ to find the key. - | ldrd CARG34, NODE:INS->key // STALL: early NODE:INS. - | ldrd CARG12, NODE:INS->val - | ldr NODE:INS, NODE:INS->next - | checktp CARG4, LJ_TSTR - | cmpeq CARG3, STR:RC - | beq >5 - | cmp NODE:INS, #0 - | bne <3 - |4: - | mov CARG1, RB // Use metatable as default result. - | mvn CARG2, #~LJ_TTAB - | b ->fff_restv - |5: - | checktp CARG2, LJ_TNIL - | bne ->fff_restv - | b <4 - | - |6: - | checktp CARG2, LJ_TISNUM - | mvnhs CARG2, CARG2 - | movlo CARG2, #~LJ_TISNUM - | add CARG4, DISPATCH, CARG2, lsl #2 - | ldr TAB:RB, [CARG4, #DISPATCH_GL(gcroot[GCROOT_BASEMT])] - | b <2 - | - |.ffunc_2 setmetatable - | // Fast path: no mt for table yet and not clearing the mt. - | checktp CARG2, LJ_TTAB - | ldreq TAB:RB, TAB:CARG1->metatable - | checktpeq CARG4, LJ_TTAB - | ldrbeq CARG4, TAB:CARG1->marked - | cmpeq TAB:RB, #0 - | bne ->fff_fallback - | tst CARG4, #LJ_GC_BLACK // isblack(table) - | str TAB:CARG3, TAB:CARG1->metatable - | beq ->fff_restv - | barrierback TAB:CARG1, CARG4, CARG3 - | b ->fff_restv - | - |.ffunc rawget - | ldrd CARG34, [BASE] - | cmp NARGS8:RC, #16 - | blo ->fff_fallback - | mov CARG2, CARG3 - | checktab CARG4, ->fff_fallback - | mov CARG1, L - | add CARG3, BASE, #8 - | IOS mov RA, BASE - | bl extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key) - | // Returns cTValue *. - | IOS mov BASE, RA - | ldrd CARG12, [CRET1] - | b ->fff_restv - | - |//-- Base library: conversions ------------------------------------------ - | - |.ffunc tonumber - | // Only handles the number case inline (without a base argument). - | ldrd CARG12, [BASE] - | cmp NARGS8:RC, #8 - | bne ->fff_fallback - | checktp CARG2, LJ_TISNUM - | bls ->fff_restv - | b ->fff_fallback - | - |.ffunc_1 tostring - | // Only handles the string or number case inline. - | checktp CARG2, LJ_TSTR - | // A __tostring method in the string base metatable is ignored. - | beq ->fff_restv - | // Handle numbers inline, unless a number base metatable is present. - | ldr CARG4, [DISPATCH, #DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])] - | str BASE, L->base - | checktp CARG2, LJ_TISNUM - | cmpls CARG4, #0 - | str PC, SAVE_PC // Redundant (but a defined value). - | bhi ->fff_fallback - | ffgccheck - | mov CARG1, L - | mov CARG2, BASE - | bl extern lj_str_fromnumber // (lua_State *L, cTValue *o) - | // Returns GCstr *. - | ldr BASE, L->base - | mvn CARG2, #~LJ_TSTR - | b ->fff_restv - | - |//-- Base library: iterators ------------------------------------------- - | - |.ffunc_1 next - | mvn CARG4, #~LJ_TNIL - | 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. - | 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 - | - |.ffunc_1 pairs - | checktab CARG2, ->fff_fallback -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | ldr TAB:RB, TAB:CARG1->metatable -#endif - | ldrd CFUNC:CARG34, CFUNC:CARG3->upvalue[0] - | ldr PC, [BASE, FRAME_PC] -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | cmp TAB:RB, #0 - | bne ->fff_fallback -#endif - | mvn CARG2, #~LJ_TNIL - | mov RC, #(3+1)*8 - | strd CFUNC:CARG34, [BASE, #-8] - | str CARG2, [BASE, #12] - | b ->fff_res - | - |.ffunc_2 ipairs_aux - | checktp CARG2, LJ_TTAB - | checktpeq CARG4, LJ_TISNUM - | bne ->fff_fallback - | ldr RB, TAB:CARG1->asize - | ldr RC, TAB:CARG1->array - | add CARG3, CARG3, #1 - | ldr PC, [BASE, FRAME_PC] - | cmp CARG3, RB - | add RC, RC, CARG3, lsl #3 - | strd CARG34, [BASE, #-8] - | ldrdlo CARG12, [RC] - | mov RC, #(0+1)*8 - | bhs >2 // Not in array part? - |1: - | checktp CARG2, LJ_TNIL - | movne RC, #(2+1)*8 - | strdne CARG12, [BASE] - | b ->fff_res - |2: // Check for empty hash part first. Otherwise call C function. - | ldr RB, TAB:CARG1->hmask - | mov CARG2, CARG3 - | cmp RB, #0 - | beq ->fff_res - | IOS mov RA, BASE - | bl extern lj_tab_getinth // (GCtab *t, int32_t key) - | // Returns cTValue * or NULL. - | IOS mov BASE, RA - | cmp CRET1, #0 - | beq ->fff_res - | ldrd CARG12, [CRET1] - | b <1 - | - |.ffunc_1 ipairs - | checktab CARG2, ->fff_fallback -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | ldr TAB:RB, TAB:CARG1->metatable -#endif - | ldrd CFUNC:CARG34, CFUNC:CARG3->upvalue[0] - | ldr PC, [BASE, FRAME_PC] -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | cmp TAB:RB, #0 - | bne ->fff_fallback -#endif - | mov CARG1, #0 - | mvn CARG2, #~LJ_TISNUM - | mov RC, #(3+1)*8 - | strd CFUNC:CARG34, [BASE, #-8] - | strd CARG12, [BASE, #8] - | b ->fff_res - | - |//-- Base library: catch errors ---------------------------------------- - | - |.ffunc pcall - | ldrb RA, [DISPATCH, #DISPATCH_GL(hookmask)] - | cmp NARGS8:RC, #8 - | blo ->fff_fallback - | tst RA, #HOOK_ACTIVE // Remember active hook before pcall. - | mov RB, BASE - | add BASE, BASE, #8 - | moveq PC, #8+FRAME_PCALL - | movne PC, #8+FRAME_PCALLH - | sub NARGS8:RC, NARGS8:RC, #8 - | b ->vm_call_dispatch - | - |.ffunc_2 xpcall - | ldrb RA, [DISPATCH, #DISPATCH_GL(hookmask)] - | checkfunc CARG4, ->fff_fallback // Traceback must be a function. - | mov RB, BASE - | strd CARG12, [BASE, #8] // Swap function and traceback. - | strd CARG34, [BASE] - | tst RA, #HOOK_ACTIVE // Remember active hook before pcall. - | add BASE, BASE, #16 - | moveq PC, #16+FRAME_PCALL - | movne PC, #16+FRAME_PCALLH - | sub NARGS8:RC, NARGS8:RC, #16 - | b ->vm_call_dispatch - | - |//-- Coroutine library -------------------------------------------------- - | - |.macro coroutine_resume_wrap, resume - |.if resume - |.ffunc_1 coroutine_resume - | checktp CARG2, LJ_TTHREAD - | bne ->fff_fallback - |.else - |.ffunc coroutine_wrap_aux - | ldr L:CARG1, CFUNC:CARG3->upvalue[0].gcr - |.endif - | ldr PC, [BASE, FRAME_PC] - | str BASE, L->base - | ldr CARG2, L:CARG1->top - | ldrb RA, L:CARG1->status - | ldr RB, L:CARG1->base - | add CARG3, CARG2, NARGS8:RC - | add CARG4, CARG2, RA - | str PC, SAVE_PC - | cmp CARG4, RB - | beq ->fff_fallback - | ldr CARG4, L:CARG1->maxstack - | ldr RB, L:CARG1->cframe - | cmp RA, #LUA_YIELD - | cmpls CARG3, CARG4 - | cmpls RB, #0 - | bhi ->fff_fallback - |1: - |.if resume - | sub CARG3, CARG3, #8 // Keep resumed thread in stack for GC. - | add BASE, BASE, #8 - | sub NARGS8:RC, NARGS8:RC, #8 - |.endif - | str CARG3, L:CARG1->top - | str BASE, L->top - |2: // Move args to coroutine. - | ldrd CARG34, [BASE, RB] - | cmp RB, NARGS8:RC - | strdne CARG34, [CARG2, RB] - | add RB, RB, #8 - | bne <2 - | - | mov CARG3, #0 - | mov L:RA, L:CARG1 - | mov CARG4, #0 - | bl ->vm_resume // (lua_State *L, TValue *base, 0, 0) - | // Returns thread status. - |4: - | ldr CARG3, L:RA->base - | mv_vmstate CARG2, INTERP - | ldr CARG4, L:RA->top - | st_vmstate CARG2 - | cmp CRET1, #LUA_YIELD - | ldr BASE, L->base - | bhi >8 - | subs RC, CARG4, CARG3 - | ldr CARG1, L->maxstack - | add CARG2, BASE, RC - | beq >6 // No results? - | cmp CARG2, CARG1 - | mov RB, #0 - | bhi >9 // Need to grow stack? - | - | sub CARG4, RC, #8 - | str CARG3, L:RA->top // Clear coroutine stack. - |5: // Move results from coroutine. - | ldrd CARG12, [CARG3, RB] - | cmp RB, CARG4 - | strd CARG12, [BASE, RB] - | add RB, RB, #8 - | bne <5 - |6: - |.if resume - | mvn CARG3, #~LJ_TTRUE - | add RC, RC, #16 - |7: - | str CARG3, [BASE, #-4] // Prepend true/false to results. - | sub RA, BASE, #8 - |.else - | mov RA, BASE - | add RC, RC, #8 - |.endif - | ands CARG1, PC, #FRAME_TYPE - | str PC, SAVE_PC - | str RC, SAVE_MULTRES - | beq ->BC_RET_Z - | b ->vm_return - | - |8: // Coroutine returned with error (at co->top-1). - |.if resume - | ldrd CARG12, [CARG4, #-8]! - | mvn CARG3, #~LJ_TFALSE - | mov RC, #(2+1)*8 - | str CARG4, L:RA->top // Remove error from coroutine stack. - | strd CARG12, [BASE] // Copy error message. - | b <7 - |.else - | mov CARG1, L - | mov CARG2, L:RA - | bl extern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co) - | // Never returns. - |.endif - | - |9: // Handle stack expansion on return from yield. - | mov CARG1, L - | lsr CARG2, RC, #3 - | bl extern lj_state_growstack // (lua_State *L, int n) - | mov CRET1, #0 - | b <4 - |.endmacro - | - | coroutine_resume_wrap 1 // coroutine.resume - | coroutine_resume_wrap 0 // coroutine.wrap - | - |.ffunc coroutine_yield - | ldr CARG1, L->cframe - | add CARG2, BASE, NARGS8:RC - | str BASE, L->base - | tst CARG1, #CFRAME_RESUME - | str CARG2, L->top - | mov CRET1, #LUA_YIELD - | mov CARG3, #0 - | beq ->fff_fallback - | str CARG3, L->cframe - | strb CRET1, L->status - | b ->vm_leave_unw - | - |//-- Math library ------------------------------------------------------- - | - |.macro math_round, func - | .ffunc_1 math_ .. func - | checktp CARG2, LJ_TISNUM - | beq ->fff_restv - | bhi ->fff_fallback - | // Round FP value and normalize result. - | lsl CARG3, CARG2, #1 - | adds RB, CARG3, #0x00200000 - | bpl >2 // |x| < 1? - | mvn CARG4, #0x3e0 - | subs RB, CARG4, RB, asr #21 - | lsl CARG4, CARG2, #11 - | lsl CARG3, CARG1, #11 - | orr CARG4, CARG4, #0x80000000 - | rsb INS, RB, #32 - | orr CARG4, CARG4, CARG1, lsr #21 - | bls >3 // |x| >= 2^31? - | orr CARG3, CARG3, CARG4, lsl INS - | lsr CARG1, CARG4, RB - |.if "func" == "floor" - | tst CARG3, CARG2, asr #31 - | addne CARG1, CARG1, #1 - |.else - | bics CARG3, CARG3, CARG2, asr #31 - | addsne CARG1, CARG1, #1 - | ldrdvs CARG12, >9 - | bvs ->fff_restv - |.endif - | cmp CARG2, #0 - | rsblt CARG1, CARG1, #0 - |1: - | mvn CARG2, #~LJ_TISNUM - | b ->fff_restv - | - |2: // |x| < 1 - | bcs ->fff_restv // |x| is not finite. - | orr CARG3, CARG3, CARG1 // ztest = abs(hi) | lo - |.if "func" == "floor" - | tst CARG3, CARG2, asr #31 // return (ztest & sign) == 0 ? 0 : -1 - | moveq CARG1, #0 - | mvnne CARG1, #0 - |.else - | bics CARG3, CARG3, CARG2, asr #31 // return (ztest & ~sign) == 0 ? 0 : 1 - | moveq CARG1, #0 - | movne CARG1, #1 - |.endif - | mvn CARG2, #~LJ_TISNUM - | b ->fff_restv - | - |3: // |x| >= 2^31. Check for x == -(2^31). - | cmpeq CARG4, #0x80000000 - |.if "func" == "floor" - | cmpeq CARG3, #0 - |.endif - | bne >4 - | cmp CARG2, #0 - | movmi CARG1, #0x80000000 - | bmi <1 - |4: - | bl ->vm_..func - | b ->fff_restv - |.endmacro - | - | math_round floor - | math_round ceil - | - |.align 8 - |9: - | .long 0x00000000, 0x41e00000 // 2^31. - | - |.ffunc_1 math_abs - | checktp CARG2, LJ_TISNUM - | bhi ->fff_fallback - | bicne CARG2, CARG2, #0x80000000 - | bne ->fff_restv - | cmp CARG1, #0 - | rsbslt CARG1, CARG1, #0 - | ldrdvs CARG12, <9 - | // Fallthrough. - | - |->fff_restv: - | // CARG12 = TValue result. - | ldr PC, [BASE, FRAME_PC] - | strd CARG12, [BASE, #-8] - |->fff_res1: - | // PC = return. - | mov RC, #(1+1)*8 - |->fff_res: - | // RC = (nresults+1)*8, PC = return. - | ands CARG1, PC, #FRAME_TYPE - | ldreq INS, [PC, #-4] - | str RC, SAVE_MULTRES - | sub RA, BASE, #8 - | bne ->vm_return - | decode_RB8 RB, INS - |5: - | cmp RB, RC // More results expected? - | bhi >6 - | decode_RA8 CARG1, INS - | ins_next1 - | ins_next2 - | // Adjust BASE. KBASE is assumed to be set for the calling frame. - | sub BASE, RA, CARG1 - | ins_next3 - | - |6: // Fill up results with nil. - | add CARG2, RA, RC - | mvn CARG1, #~LJ_TNIL - | add RC, RC, #8 - | str CARG1, [CARG2, #-4] - | b <5 - | - |.macro math_extern, func - | .ffunc_n math_ .. func - | IOS mov RA, BASE - | bl extern func - | IOS mov BASE, RA - | b ->fff_restv - |.endmacro - | - |.macro math_extern2, func - | .ffunc_nn math_ .. func - | IOS mov RA, BASE - | bl extern func - | IOS mov BASE, RA - | b ->fff_restv - |.endmacro - | - | math_extern sqrt - | math_extern log - | math_extern log10 - | math_extern exp - | math_extern sin - | math_extern cos - | math_extern tan - | math_extern asin - | math_extern acos - | math_extern atan - | math_extern sinh - | math_extern cosh - | math_extern tanh - | math_extern2 pow - | math_extern2 atan2 - | math_extern2 fmod - | - |->ff_math_deg: - |.ffunc_n math_rad - | ldrd CARG34, CFUNC:CARG3->upvalue[0] - | bl extern __aeabi_dmul - | b ->fff_restv - | - |.ffunc_2 math_ldexp - | checktp CARG2, LJ_TISNUM - | bhs ->fff_fallback - | checktp CARG4, LJ_TISNUM - | bne ->fff_fallback - | IOS mov RA, BASE - | bl extern ldexp // (double x, int exp) - | IOS mov BASE, RA - | b ->fff_restv - | - |.ffunc_n math_frexp - | mov CARG3, sp - | IOS mov RA, BASE - | bl extern frexp - | IOS mov BASE, RA - | ldr CARG3, [sp] - | mvn CARG4, #~LJ_TISNUM - | ldr PC, [BASE, FRAME_PC] - | strd CARG12, [BASE, #-8] - | mov RC, #(2+1)*8 - | strd CARG34, [BASE] - | b ->fff_res - | - |.ffunc_n math_modf - | sub CARG3, BASE, #8 - | ldr PC, [BASE, FRAME_PC] - | IOS mov RA, BASE - | bl extern modf - | IOS mov BASE, RA - | mov RC, #(2+1)*8 - | strd CARG12, [BASE] - | b ->fff_res - | - |.macro math_minmax, name, cond, fcond - | .ffunc_1 name - | checktp CARG2, LJ_TISNUM - | mov RA, #8 - | bne >4 - |1: // Handle integers. - | ldrd CARG34, [BASE, RA] - | cmp RA, RC - | bhs ->fff_restv - | checktp CARG4, LJ_TISNUM - | bne >3 - | cmp CARG1, CARG3 - | add RA, RA, #8 - | mov..cond CARG1, CARG3 - | b <1 - |3: - | bhi ->fff_fallback - | // Convert intermediate result to number and continue below. - | bl extern __aeabi_i2d - | ldrd CARG34, [BASE, RA] - | b >6 - | - |4: - | bhi ->fff_fallback - |5: // Handle numbers. - | ldrd CARG34, [BASE, RA] - | cmp RA, RC - | bhs ->fff_restv - | checktp CARG4, LJ_TISNUM - | bhs >7 - |6: - | bl extern __aeabi_cdcmple - | add RA, RA, #8 - | mov..fcond CARG1, CARG3 - | mov..fcond CARG2, CARG4 - | b <5 - |7: // Convert integer to number and continue above. - | bhi ->fff_fallback - | strd CARG12, TMPD - | mov CARG1, CARG3 - | bl extern __aeabi_i2d - | ldrd CARG34, TMPD - | b <6 - |.endmacro - | - | math_minmax math_min, gt, hi - | math_minmax math_max, lt, lo - | - |//-- String library ----------------------------------------------------- - | - |.ffunc_1 string_len - | checkstr CARG2, ->fff_fallback - | ldr CARG1, STR:CARG1->len - | mvn CARG2, #~LJ_TISNUM - | b ->fff_restv - | - |.ffunc string_byte // Only handle the 1-arg case here. - | ldrd CARG12, [BASE] - | ldr PC, [BASE, FRAME_PC] - | cmp NARGS8:RC, #8 - | checktpeq CARG2, LJ_TSTR // Need exactly 1 argument. - | bne ->fff_fallback - | ldr CARG3, STR:CARG1->len - | ldrb CARG1, STR:CARG1[1] // Access is always ok (NUL at end). - | mvn CARG2, #~LJ_TISNUM - | cmp CARG3, #0 - | moveq RC, #(0+1)*8 - | movne RC, #(1+1)*8 - | strd CARG12, [BASE, #-8] - | b ->fff_res - | - |.ffunc string_char // Only handle the 1-arg case here. - | ffgccheck - | ldrd CARG12, [BASE] - | ldr PC, [BASE, FRAME_PC] - | cmp NARGS8:RC, #8 // Need exactly 1 argument. - | checktpeq CARG2, LJ_TISNUM - | bicseq CARG4, CARG1, #255 - | mov CARG3, #1 - | bne ->fff_fallback - | str CARG1, TMPD - | mov CARG2, TMPDp // Points to stack. Little-endian. - |->fff_newstr: - | // CARG2 = str, CARG3 = len. - | str BASE, L->base - | mov CARG1, L - | str PC, SAVE_PC - | bl extern lj_str_new // (lua_State *L, char *str, size_t l) - | // Returns GCstr *. - | ldr BASE, L->base - | mvn CARG2, #~LJ_TSTR - | b ->fff_restv - | - |.ffunc string_sub - | ffgccheck - | ldrd CARG12, [BASE] - | ldrd CARG34, [BASE, #16] - | cmp NARGS8:RC, #16 - | mvn RB, #0 - | beq >1 - | blo ->fff_fallback - | checktp CARG4, LJ_TISNUM - | mov RB, CARG3 - | bne ->fff_fallback - |1: - | ldrd CARG34, [BASE, #8] - | checktp CARG2, LJ_TSTR - | ldreq CARG2, STR:CARG1->len - | checktpeq CARG4, LJ_TISNUM - | bne ->fff_fallback - | // CARG1 = str, CARG2 = str->len, CARG3 = start, RB = end - | add CARG4, CARG2, #1 - | cmp CARG3, #0 // if (start < 0) start += len+1 - | addlt CARG3, CARG3, CARG4 - | cmp CARG3, #1 // if (start < 1) start = 1 - | movlt CARG3, #1 - | cmp RB, #0 // if (end < 0) end += len+1 - | addlt RB, RB, CARG4 - | bic RB, RB, RB, asr #31 // if (end < 0) end = 0 - | cmp RB, CARG2 // if (end > len) end = len - | add CARG1, STR:CARG1, #sizeof(GCstr)-1 - | movgt RB, CARG2 - | add CARG2, CARG1, CARG3 - | subs CARG3, RB, CARG3 // len = end - start - | add CARG3, CARG3, #1 // len += 1 - | bge ->fff_newstr - |->fff_emptystr: - | sub STR:CARG1, DISPATCH, #-DISPATCH_GL(strempty) - | mvn CARG2, #~LJ_TSTR - | b ->fff_restv - | - |.ffunc string_rep // Only handle the 1-char case inline. - | ffgccheck - | ldrd CARG12, [BASE] - | ldrd CARG34, [BASE, #8] - | cmp NARGS8:RC, #16 - | blo ->fff_fallback - | checktp CARG2, LJ_TSTR - | checktpeq CARG4, LJ_TISNUM - | bne ->fff_fallback - | subs CARG4, CARG3, #1 - | ldr CARG2, STR:CARG1->len - | blt ->fff_emptystr // Count <= 0? - | cmp CARG2, #1 - | blo ->fff_emptystr // Zero-length string? - | bne ->fff_fallback // Fallback for > 1-char strings. - | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)] - | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)] - | ldr CARG1, STR:CARG1[1] - | cmp RB, CARG3 - | blo ->fff_fallback - |1: // Fill buffer with char. - | strb CARG1, [CARG2, CARG4] - | subs CARG4, CARG4, #1 - | bge <1 - | b ->fff_newstr - | - |.ffunc string_reverse - | ffgccheck - | ldrd CARG12, [BASE] - | cmp NARGS8:RC, #8 - | blo ->fff_fallback - | checkstr CARG2, ->fff_fallback - | ldr CARG3, STR:CARG1->len - | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)] - | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)] - | mov CARG4, CARG3 - | add CARG1, STR:CARG1, #sizeof(GCstr) - | cmp RB, CARG3 - | blo ->fff_fallback - |1: // Reverse string copy. - | ldrb RB, [CARG1], #1 - | subs CARG4, CARG4, #1 - | blt ->fff_newstr - | strb RB, [CARG2, CARG4] - | b <1 - | - |.macro ffstring_case, name, lo - | .ffunc name - | ffgccheck - | ldrd CARG12, [BASE] - | cmp NARGS8:RC, #8 - | blo ->fff_fallback - | checkstr CARG2, ->fff_fallback - | ldr CARG3, STR:CARG1->len - | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)] - | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)] - | mov CARG4, #0 - | add CARG1, STR:CARG1, #sizeof(GCstr) - | cmp RB, CARG3 - | blo ->fff_fallback - |1: // ASCII case conversion. - | ldrb RB, [CARG1, CARG4] - | cmp CARG4, CARG3 - | bhs ->fff_newstr - | sub RC, RB, #lo - | cmp RC, #26 - | eorlo RB, RB, #0x20 - | strb RB, [CARG2, CARG4] - | add CARG4, CARG4, #1 - | b <1 - |.endmacro - | - |ffstring_case string_lower, 65 - |ffstring_case string_upper, 97 - | - |//-- Table library ------------------------------------------------------ - | - |.ffunc_1 table_getn - | checktab CARG2, ->fff_fallback - | IOS mov RA, BASE - | bl extern lj_tab_len // (GCtab *t) - | // Returns uint32_t (but less than 2^31). - | IOS mov BASE, RA - | mvn CARG2, #~LJ_TISNUM - | b ->fff_restv - | - |//-- Bit library -------------------------------------------------------- - | - |// FP number to bit conversion for soft-float. Clobbers r0-r3. - |->vm_tobit_fb: - | bhi ->fff_fallback - |->vm_tobit: - | lsl RB, CARG2, #1 - | adds RB, RB, #0x00200000 - | movpl CARG1, #0 // |x| < 1? - | bxpl lr - | mvn CARG4, #0x3e0 - | subs RB, CARG4, RB, asr #21 - | bmi >1 // |x| >= 2^32? - | lsl CARG4, CARG2, #11 - | orr CARG4, CARG4, #0x80000000 - | orr CARG4, CARG4, CARG1, lsr #21 - | cmp CARG2, #0 - | lsr CARG1, CARG4, RB - | rsblt CARG1, CARG1, #0 - | bx lr - |1: - | add RB, RB, #21 - | lsr CARG4, CARG1, RB - | rsb RB, RB, #20 - | lsl CARG1, CARG2, #12 - | cmp CARG2, #0 - | orr CARG1, CARG4, CARG1, lsl RB - | rsblt CARG1, CARG1, #0 - | bx lr - | - |.macro .ffunc_bit, name - | .ffunc_1 bit_..name - | checktp CARG2, LJ_TISNUM - | blne ->vm_tobit_fb - |.endmacro - | - |.ffunc_bit tobit - | mvn CARG2, #~LJ_TISNUM - | b ->fff_restv - | - |.macro .ffunc_bit_op, name, ins - | .ffunc_bit name - | mov CARG3, CARG1 - | mov RA, #8 - |1: - | ldrd CARG12, [BASE, RA] - | cmp RA, NARGS8:RC - | add RA, RA, #8 - | bge >2 - | checktp CARG2, LJ_TISNUM - | blne ->vm_tobit_fb - | ins CARG3, CARG3, CARG1 - | b <1 - |.endmacro - | - |.ffunc_bit_op band, and - |.ffunc_bit_op bor, orr - |.ffunc_bit_op bxor, eor - | - |2: - | mvn CARG4, #~LJ_TISNUM - | ldr PC, [BASE, FRAME_PC] - | strd CARG34, [BASE, #-8] - | b ->fff_res1 - | - |.ffunc_bit bswap - | eor CARG3, CARG1, CARG1, ror #16 - | bic CARG3, CARG3, #0x00ff0000 - | ror CARG1, CARG1, #8 - | mvn CARG2, #~LJ_TISNUM - | eor CARG1, CARG1, CARG3, lsr #8 - | b ->fff_restv - | - |.ffunc_bit bnot - | mvn CARG1, CARG1 - | mvn CARG2, #~LJ_TISNUM - | b ->fff_restv - | - |.macro .ffunc_bit_sh, name, ins, shmod - | .ffunc bit_..name - | ldrd CARG12, [BASE, #8] - | cmp NARGS8:RC, #16 - | blo ->fff_fallback - | checktp CARG2, LJ_TISNUM - | blne ->vm_tobit_fb - |.if shmod == 0 - | and RA, CARG1, #31 - |.else - | rsb RA, CARG1, #0 - |.endif - | ldrd CARG12, [BASE] - | checktp CARG2, LJ_TISNUM - | blne ->vm_tobit_fb - | ins CARG1, CARG1, RA - | mvn CARG2, #~LJ_TISNUM - | b ->fff_restv - |.endmacro - | - |.ffunc_bit_sh lshift, lsl, 0 - |.ffunc_bit_sh rshift, lsr, 0 - |.ffunc_bit_sh arshift, asr, 0 - |.ffunc_bit_sh rol, ror, 1 - |.ffunc_bit_sh ror, ror, 0 - | - |//----------------------------------------------------------------------- - | - |->fff_fallback: // Call fast function fallback handler. - | // BASE = new base, RC = nargs*8 - | ldr CARG3, [BASE, FRAME_FUNC] - | ldr CARG2, L->maxstack - | add CARG1, BASE, NARGS8:RC - | ldr PC, [BASE, FRAME_PC] // Fallback may overwrite PC. - | str CARG1, L->top - | ldr CARG3, CFUNC:CARG3->f - | str BASE, L->base - | add CARG1, CARG1, #8*LUA_MINSTACK - | str PC, SAVE_PC // Redundant (but a defined value). - | cmp CARG1, CARG2 - | mov CARG1, L - | bhi >5 // Need to grow stack. - | blx CARG3 // (lua_State *L) - | // Either throws an error, or recovers and returns -1, 0 or nresults+1. - | ldr BASE, L->base - | cmp CRET1, #0 - | lsl RC, CRET1, #3 - | sub RA, BASE, #8 - | bgt ->fff_res // Returned nresults+1? - |1: // Returned 0 or -1: retry fast path. - | ldr CARG1, L->top - | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] - | sub NARGS8:RC, CARG1, BASE - | bne ->vm_call_tail // Returned -1? - | ins_callt // Returned 0: retry fast path. - | - |// Reconstruct previous base for vmeta_call during tailcall. - |->vm_call_tail: - | ands CARG1, PC, #FRAME_TYPE - | bic CARG2, PC, #FRAME_TYPEP - | ldreq INS, [PC, #-4] - | andeq CARG2, MASKR8, INS, lsr #5 // Conditional decode_RA8. - | addeq CARG2, CARG2, #8 - | sub RB, BASE, CARG2 - | b ->vm_call_dispatch // Resolve again for tailcall. - | - |5: // Grow stack for fallback handler. - | mov CARG2, #LUA_MINSTACK - | bl extern lj_state_growstack // (lua_State *L, int n) - | ldr BASE, L->base - | cmp CARG1, CARG1 // Set zero-flag to force retry. - | b <1 - | - |->fff_gcstep: // Call GC step function. - | // BASE = new base, RC = nargs*8 - | mov RA, lr - | str BASE, L->base - | add CARG2, BASE, NARGS8:RC - | str PC, SAVE_PC // Redundant (but a defined value). - | str CARG2, L->top - | mov CARG1, L - | bl extern lj_gc_step // (lua_State *L) - | ldr BASE, L->base - | mov lr, RA // Help return address predictor. - | ldr CFUNC:CARG3, [BASE, FRAME_FUNC] - | bx lr - | - |//----------------------------------------------------------------------- - |//-- Special dispatch targets ------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_record: // Dispatch target for recording phase. -#if LJ_HASJIT - | ldrb CARG1, [DISPATCH, #DISPATCH_GL(hookmask)] - | tst CARG1, #HOOK_VMEVENT // No recording while in vmevent. - | bne >5 - | // Decrement the hookcount for consistency, but always do the call. - | ldr CARG2, [DISPATCH, #DISPATCH_GL(hookcount)] - | tst CARG1, #HOOK_ACTIVE - | bne >1 - | sub CARG2, CARG2, #1 - | tst CARG1, #LUA_MASKLINE|LUA_MASKCOUNT - | strne CARG2, [DISPATCH, #DISPATCH_GL(hookcount)] - | b >1 -#endif - | - |->vm_rethook: // Dispatch target for return hooks. - | ldrb CARG1, [DISPATCH, #DISPATCH_GL(hookmask)] - | tst CARG1, #HOOK_ACTIVE // Hook already active? - | beq >1 - |5: // Re-dispatch to static ins. - | decode_OP OP, INS - | add OP, DISPATCH, OP, lsl #2 - | ldr pc, [OP, #GG_DISP2STATIC] - | - |->vm_inshook: // Dispatch target for instr/line hooks. - | ldrb CARG1, [DISPATCH, #DISPATCH_GL(hookmask)] - | ldr CARG2, [DISPATCH, #DISPATCH_GL(hookcount)] - | tst CARG1, #HOOK_ACTIVE // Hook already active? - | bne <5 - | tst CARG1, #LUA_MASKLINE|LUA_MASKCOUNT - | beq <5 - | subs CARG2, CARG2, #1 - | str CARG2, [DISPATCH, #DISPATCH_GL(hookcount)] - | beq >1 - | tst CARG1, #LUA_MASKLINE - | beq <5 - |1: - | mov CARG1, L - | str BASE, L->base - | mov CARG2, PC - | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. - | bl extern lj_dispatch_ins // (lua_State *L, const BCIns *pc) - |3: - | ldr BASE, L->base - |4: // Re-dispatch to static ins. - | ldrb OP, [PC, #-4] - | ldr INS, [PC, #-4] - | add OP, DISPATCH, OP, lsl #2 - | ldr OP, [OP, #GG_DISP2STATIC] - | decode_RA8 RA, INS - | decode_RD RC, INS - | bx OP - | - |->cont_hook: // Continue from hook yield. - | ldr CARG1, [CARG4, #-24] - | add PC, PC, #4 - | str CARG1, SAVE_MULTRES // Restore MULTRES for *M ins. - | b <4 - | - |->vm_hotloop: // Hot loop counter underflow. -#if LJ_HASJIT - | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Same as curr_topL(L). - | sub CARG1, DISPATCH, #-GG_DISP2J - | str PC, SAVE_PC - | ldr CARG3, LFUNC:CARG3->field_pc - | mov CARG2, PC - | str L, [DISPATCH, #DISPATCH_J(L)] - | ldrb CARG3, [CARG3, #PC2PROTO(framesize)] - | str BASE, L->base - | add CARG3, BASE, CARG3, lsl #3 - | str CARG3, L->top - | bl extern lj_trace_hot // (jit_State *J, const BCIns *pc) - | b <3 -#endif - | - |->vm_callhook: // Dispatch target for call hooks. - | mov CARG2, PC -#if LJ_HASJIT - | b >1 -#endif - | - |->vm_hotcall: // Hot call counter underflow. -#if LJ_HASJIT - | orr CARG2, PC, #1 - |1: -#endif - | add CARG4, BASE, RC - | str PC, SAVE_PC - | mov CARG1, L - | str BASE, L->base - | sub RA, RA, BASE - | str CARG4, L->top - | bl extern lj_dispatch_call // (lua_State *L, const BCIns *pc) - | // Returns ASMFunction. - | ldr BASE, L->base - | ldr CARG4, L->top - | mov CARG2, #0 - | add RA, BASE, RA - | sub NARGS8:RC, CARG4, BASE - | str CARG2, SAVE_PC // Invalidate for subsequent line hook. - | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] - | ldr INS, [PC, #-4] - | bx CRET1 - | - |//----------------------------------------------------------------------- - |//-- Trace exit handler ------------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_exit_handler: -#if LJ_HASJIT - | sub sp, sp, #12 - | push {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12} - | ldr CARG1, [sp, #64] // Load original value of lr. - | ldr DISPATCH, [lr] // Load DISPATCH. - | add CARG3, sp, #64 // Recompute original value of sp. - | mv_vmstate CARG4, EXIT - | str CARG3, [sp, #52] // Store sp in RID_SP - | st_vmstate CARG4 - | ldr CARG2, [CARG1, #-4]! // Get exit instruction. - | str CARG1, [sp, #56] // Store exit pc in RID_LR and RID_PC. - | str CARG1, [sp, #60] - | lsl CARG2, CARG2, #8 - | add CARG1, CARG1, CARG2, asr #6 - | ldr CARG2, [lr, #4] // Load exit stub group offset. - | sub CARG1, CARG1, lr - | ldr L, [DISPATCH, #DISPATCH_GL(jit_L)] - | add CARG1, CARG2, CARG1, lsr #2 // Compute exit number. - | ldr BASE, [DISPATCH, #DISPATCH_GL(jit_base)] - | str CARG1, [DISPATCH, #DISPATCH_J(exitno)] - | mov CARG4, #0 - | str L, [DISPATCH, #DISPATCH_J(L)] - | str BASE, L->base - | str CARG4, [DISPATCH, #DISPATCH_GL(jit_L)] - | sub CARG1, DISPATCH, #-GG_DISP2J - | mov CARG2, sp - | bl extern lj_trace_exit // (jit_State *J, ExitState *ex) - | // Returns MULTRES (unscaled) or negated error code. - | ldr CARG2, L->cframe - | ldr BASE, L->base - | bic CARG2, CARG2, #~CFRAME_RAWMASK // Use two steps: bic sp is deprecated. - | mov sp, CARG2 - | ldr PC, SAVE_PC // Get SAVE_PC. - | str L, SAVE_L // Set SAVE_L (on-trace resume/yield). - | b >1 -#endif - |->vm_exit_interp: - | // CARG1 = MULTRES or negated error code, BASE, PC and DISPATCH set. -#if LJ_HASJIT - | ldr L, SAVE_L - |1: - | cmp CARG1, #0 - | blt >3 // Check for error from exit. - | lsl RC, CARG1, #3 - | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] - | str RC, SAVE_MULTRES - | mov CARG3, #0 - | ldr CARG2, LFUNC:CARG2->field_pc - | str CARG3, [DISPATCH, #DISPATCH_GL(jit_L)] - | mv_vmstate CARG4, INTERP - | ldr KBASE, [CARG2, #PC2PROTO(k)] - | // Modified copy of ins_next which handles function header dispatch, too. - | ldrb OP, [PC] - | mov MASKR8, #255 - | ldr INS, [PC], #4 - | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. - | st_vmstate CARG4 - | cmp OP, #BC_FUNCF // Function header? - | ldr OP, [DISPATCH, OP, lsl #2] - | decode_RA8 RA, INS - | lsrlo RC, INS, #16 // No: Decode operands A*8 and D. - | subhs RC, RC, #8 - | addhs RA, RA, BASE // Yes: RA = BASE+framesize*8, RC = nargs*8 - | bx OP - | - |3: // Rethrow error from the right C frame. - | rsb CARG2, CARG1, #0 - | mov CARG1, L - | bl extern lj_err_throw // (lua_State *L, int errcode) -#endif - | - |//----------------------------------------------------------------------- - |//-- Math helper functions ---------------------------------------------- - |//----------------------------------------------------------------------- - | - |// FP value rounding. Called from JIT code. - |// - |// double lj_vm_floor/ceil/trunc(double x); - |.macro vm_round, func - |->vm_ .. func: - | lsl CARG3, CARG2, #1 - | adds RB, CARG3, #0x00200000 - | bpl >2 // |x| < 1? - | mvn CARG4, #0x3cc - | subs RB, CARG4, RB, asr #21 // 2^0: RB = 51, 2^51: RB = 0. - | bxlo lr // |x| >= 2^52: done. - | mvn CARG4, #1 - | bic CARG3, CARG1, CARG4, lsl RB // ztest = lo & ~lomask - | and CARG1, CARG1, CARG4, lsl RB // lo &= lomask - | subs RB, RB, #32 - | bicpl CARG4, CARG2, CARG4, lsl RB // |x| <= 2^20: ztest |= hi & ~himask - | orrpl CARG3, CARG3, CARG4 - | mvnpl CARG4, #1 - | andpl CARG2, CARG2, CARG4, lsl RB // |x| <= 2^20: hi &= himask - |.if "func" == "floor" - | tst CARG3, CARG2, asr #31 // iszero = ((ztest & signmask) == 0) - |.else - | bics CARG3, CARG3, CARG2, asr #31 // iszero = ((ztest & ~signmask) == 0) - |.endif - | bxeq lr // iszero: done. - | mvn CARG4, #1 - | cmp RB, #0 - | lslpl CARG3, CARG4, RB - | mvnmi CARG3, #0 - | add RB, RB, #32 - | subs CARG1, CARG1, CARG4, lsl RB // lo = lo-lomask - | sbc CARG2, CARG2, CARG3 // hi = hi-himask+carry - | bx lr - | - |2: // |x| < 1: - | bxcs lr // |x| is not finite. - | orr CARG3, CARG3, CARG1 // ztest = (2*hi) | lo - |.if "func" == "floor" - | tst CARG3, CARG2, asr #31 // iszero = ((ztest & signmask) == 0) - |.else - | bics CARG3, CARG3, CARG2, asr #31 // iszero = ((ztest & ~signmask) == 0) - |.endif - | mov CARG1, #0 // lo = 0 - | and CARG2, CARG2, #0x80000000 - | ldrne CARG4, <9 // hi = sign(x) | (iszero ? 0.0 : 1.0) - | orrne CARG2, CARG2, CARG4 - | bx lr - |.endmacro - | - |9: - | .long 0x3ff00000 // hiword(1.0) - | vm_round floor - | vm_round ceil - | - |->vm_trunc: -#if LJ_HASJIT - | lsl CARG3, CARG2, #1 - | adds RB, CARG3, #0x00200000 - | andpl CARG2, CARG2, #0x80000000 // |x| < 1? hi = sign(x), lo = 0. - | movpl CARG1, #0 - | bxpl lr - | mvn CARG4, #0x3cc - | subs RB, CARG4, RB, asr #21 // 2^0: RB = 51, 2^51: RB = 0. - | bxlo lr // |x| >= 2^52: already done. - | mvn CARG4, #1 - | and CARG1, CARG1, CARG4, lsl RB // lo &= lomask - | subs RB, RB, #32 - | andpl CARG2, CARG2, CARG4, lsl RB // |x| <= 2^20: hi &= himask - | bx lr -#endif - | - | // double lj_vm_mod(double dividend, double divisor); - |->vm_mod: - | push {r0, r1, r2, r3, r4, lr} - | bl extern __aeabi_ddiv - | bl ->vm_floor - | ldrd CARG34, [sp, #8] - | bl extern __aeabi_dmul - | ldrd CARG34, [sp] - | eor CARG2, CARG2, #0x80000000 - | bl extern __aeabi_dadd - | add sp, sp, #20 - | pop {pc} - | - | // int lj_vm_modi(int dividend, int divisor); - |->vm_modi: - | ands RB, CARG1, #0x80000000 - | rsbmi CARG1, CARG1, #0 // a = |dividend| - | eor RB, RB, CARG2, asr #1 // Keep signdiff and sign(divisor). - | cmp CARG2, #0 - | rsbmi CARG2, CARG2, #0 // b = |divisor| - | subs CARG4, CARG2, #1 - | cmpne CARG1, CARG2 - | moveq CARG1, #0 // if (b == 1 || a == b) a = 0 - | tsthi CARG2, CARG4 - | andeq CARG1, CARG1, CARG4 // else if ((b & (b-1)) == 0) a &= b-1 - | bls >1 - | // Use repeated subtraction to get the remainder. - | clz CARG3, CARG1 - | clz CARG4, CARG2 - | sub CARG4, CARG4, CARG3 - | rsbs CARG3, CARG4, #31 // entry = (31-(clz(b)-clz(a)))*8 - | addne pc, pc, CARG3, lsl #3 // Duff's device. - | nop - { - int i; - for (i = 31; i >= 0; i--) { - | cmp CARG1, CARG2, lsl #i - | subhs CARG1, CARG1, CARG2, lsl #i - } - } - |1: - | cmp CARG1, #0 - | cmpne RB, #0 - | submi CARG1, CARG1, CARG2 // if (y != 0 && signdiff) y = y - b - | eors CARG2, CARG1, RB, lsl #1 - | rsbmi CARG1, CARG1, #0 // if (sign(divisor) != sign(y)) y = -y - | bx lr - | - |// Callable from C: double lj_vm_foldarith(double x, double y, int op) - |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -) - |// and basic math functions. ORDER ARITH - |->vm_foldarith: - | ldr OP, [sp] - | cmp OP, #1 - | blo extern __aeabi_dadd - | beq extern __aeabi_dsub - | cmp OP, #3 - | blo extern __aeabi_dmul - | beq extern __aeabi_ddiv - | cmp OP, #5 - | blo ->vm_mod - | beq extern pow - | cmp OP, #7 - | eorlo CARG2, CARG2, #0x80000000 - | biceq CARG2, CARG2, #0x80000000 - | bxls lr -#if LJ_HASJIT - | cmp OP, #9 - | blo extern atan2 - | beq >9 // No support needed for IR_LDEXP. - | cmp OP, #11 - | bhi >9 - | push {r4, lr} - | beq >1 - | // IR_MIN - | bl extern __aeabi_cdcmple - | movhi CARG1, CARG3 - | movhi CARG2, CARG4 - | pop {r4, pc} - |9: - | NYI // Bad op. - | - |1: // IR_MAX - | bl extern __aeabi_cdcmple - | movlo CARG1, CARG3 - | movlo CARG2, CARG4 - | pop {r4, pc} -#else - | NYI // Other operations only needed by JIT compiler. -#endif - | - |//----------------------------------------------------------------------- - |//-- Miscellaneous functions -------------------------------------------- - |//----------------------------------------------------------------------- - | - |//----------------------------------------------------------------------- - |//-- FFI helper functions ----------------------------------------------- - |//----------------------------------------------------------------------- - | - |// Handler for callback functions. - |// Saveregs already performed. Callback slot number in [sp], g in r12. - |->vm_ffi_callback: -#if LJ_HASFFI - |.type CTSTATE, CTState, PC - | ldr CTSTATE, GL:r12->ctype_state - | add DISPATCH, r12, #GG_G2DISP - | strd CARG12, CTSTATE->cb.gpr[0] - | strd CARG34, CTSTATE->cb.gpr[2] - | ldr CARG4, [sp] - | add CARG3, sp, #CFRAME_SIZE - | mov CARG1, CTSTATE - | lsr CARG4, CARG4, #3 - | str CARG3, CTSTATE->cb.stack - | mov CARG2, sp - | str CARG4, CTSTATE->cb.slot - | str CTSTATE, SAVE_PC // Any value outside of bytecode is ok. - | bl extern lj_ccallback_enter // (CTState *cts, void *cf) - | // Returns lua_State *. - | ldr BASE, L:CRET1->base - | mv_vmstate CARG2, INTERP - | ldr RC, L:CRET1->top - | mov MASKR8, #255 - | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] - | mov L, CRET1 - | sub RC, RC, BASE - | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. - | st_vmstate CARG2 - | ins_callt -#endif - | - |->cont_ffi_callback: // Return from FFI callback. -#if LJ_HASFFI - | ldr CTSTATE, [DISPATCH, #DISPATCH_GL(ctype_state)] - | str BASE, L->base - | str CARG4, L->top - | str L, CTSTATE->L - | mov CARG1, CTSTATE - | mov CARG2, RA - | bl extern lj_ccallback_leave // (CTState *cts, TValue *o) - | ldrd CARG12, CTSTATE->cb.gpr[0] - | b ->vm_leave_unw -#endif - | - |->vm_ffi_call: // Call C function via FFI. - | // Caveat: needs special frame unwinding, see below. -#if LJ_HASFFI - | .type CCSTATE, CCallState, r4 - | push {CCSTATE, r5, r11, lr} - | mov CCSTATE, CARG1 - | ldr CARG1, CCSTATE:CARG1->spadj - | ldrb CARG2, CCSTATE->nsp - | add CARG3, CCSTATE, #offsetof(CCallState, stack) - | mov r11, sp - | sub sp, sp, CARG1 // Readjust stack. - | subs CARG2, CARG2, #1 - | ldr RB, CCSTATE->func - | bmi >2 - |1: // Copy stack slots. - | ldr CARG4, [CARG3, CARG2, lsl #2] - | str CARG4, [sp, CARG2, lsl #2] - | subs CARG2, CARG2, #1 - | bpl <1 - |2: - | ldr CARG1, CCSTATE->gpr[0] - | ldr CARG2, CCSTATE->gpr[1] - | ldr CARG3, CCSTATE->gpr[2] - | ldr CARG4, CCSTATE->gpr[3] - | blx RB - | mov sp, r11 - | str CRET1, CCSTATE->gpr[0] - | str CRET2, CCSTATE->gpr[1] - | pop {CCSTATE, r5, r11, pc} -#endif - |// Note: vm_ffi_call must be the last function in this object file! - | - |//----------------------------------------------------------------------- -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop) -{ - int vk = 0; - |=>defop: - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - | // RA = src1*8, RC = src2, JMP with RC = target - | lsl RC, RC, #3 - | ldrd CARG12, [RA, BASE]! - | ldrh RB, [PC, #2] - | ldrd CARG34, [RC, BASE]! - | add PC, PC, #4 - | add RB, PC, RB, lsl #2 - | checktp CARG2, LJ_TISNUM - | bne >3 - | checktp CARG4, LJ_TISNUM - | bne >4 - | cmp CARG1, CARG3 - if (op == BC_ISLT) { - | sublt PC, RB, #0x20000 - } else if (op == BC_ISGE) { - | subge PC, RB, #0x20000 - } else if (op == BC_ISLE) { - | suble PC, RB, #0x20000 - } else { - | subgt PC, RB, #0x20000 - } - |1: - | ins_next - | - |3: // CARG12 is not an integer. - | bhi ->vmeta_comp - | // CARG12 is a number. - | checktp CARG4, LJ_TISNUM - | movlo RA, RB // Save RB. - | blo >5 - | // CARG12 is a number, CARG3 is an integer. - | mov CARG1, CARG3 - | mov RC, RA - | mov RA, RB // Save RB. - | bl extern __aeabi_i2d - | mov CARG3, CARG1 - | mov CARG4, CARG2 - | ldrd CARG12, [RC] // Restore first operand. - | b >5 - |4: // CARG1 is an integer, CARG34 is not an integer. - | bhi ->vmeta_comp - | // CARG1 is an integer, CARG34 is a number - | mov RA, RB // Save RB. - | bl extern __aeabi_i2d - | ldrd CARG34, [RC] // Restore second operand. - |5: // CARG12 and CARG34 are numbers. - | bl extern __aeabi_cdcmple - | // To preserve NaN semantics GE/GT branch on unordered, but LT/LE don't. - if (op == BC_ISLT) { - | sublo PC, RA, #0x20000 - } else if (op == BC_ISGE) { - | subhs PC, RA, #0x20000 - } else if (op == BC_ISLE) { - | subls PC, RA, #0x20000 - } else { - | subhi PC, RA, #0x20000 - } - | b <1 - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - | // RA = src1*8, RC = src2, JMP with RC = target - | lsl RC, RC, #3 - | ldrd CARG12, [RA, BASE]! - | ldrh RB, [PC, #2] - | ldrd CARG34, [RC, BASE]! - | add PC, PC, #4 - | add RB, PC, RB, lsl #2 - | checktp CARG2, LJ_TISNUM - | cmnls CARG4, #-LJ_TISNUM - if (vk) { - | bls ->BC_ISEQN_Z - } else { - | bls ->BC_ISNEN_Z - } - | // Either or both types are not numbers. - if (LJ_HASFFI) { - | checktp CARG2, LJ_TCDATA - | checktpne CARG4, LJ_TCDATA - | beq ->vmeta_equal_cd - } - | cmp CARG2, CARG4 // Compare types. - | bne >2 // Not the same type? - | checktp CARG2, LJ_TISPRI - | bhs >1 // Same type and primitive type? - | - | // Same types and not a primitive type. Compare GCobj or pvalue. - | cmp CARG1, CARG3 - if (vk) { - | bne >3 // Different GCobjs or pvalues? - |1: // Branch if same. - | sub PC, RB, #0x20000 - |2: // Different. - | ins_next - |3: - | checktp CARG2, LJ_TISTABUD - | bhi <2 // Different objects and not table/ud? - } else { - | beq >1 // Same GCobjs or pvalues? - | checktp CARG2, LJ_TISTABUD - | bhi >2 // Different objects and not table/ud? - } - | // Different tables or userdatas. Need to check __eq metamethod. - | // Field metatable must be at same offset for GCtab and GCudata! - | ldr TAB:RA, TAB:CARG1->metatable - | cmp TAB:RA, #0 - if (vk) { - | beq <2 // No metatable? - } else { - | beq >2 // No metatable? - } - | ldrb RA, TAB:RA->nomm - | mov CARG4, #1-vk // ne = 0 or 1. - | mov CARG2, CARG1 - | tst RA, #1<vmeta_equal // 'no __eq' flag not set? - if (vk) { - | b <2 - } else { - |2: // Branch if different. - | sub PC, RB, #0x20000 - |1: // Same. - | ins_next - } - break; - - case BC_ISEQS: case BC_ISNES: - vk = op == BC_ISEQS; - | // RA = src*8, RC = str_const (~), JMP with RC = target - | mvn RC, RC - | ldrd CARG12, [BASE, RA] - | ldrh RB, [PC, #2] - | ldr STR:CARG3, [KBASE, RC, lsl #2] - | add PC, PC, #4 - | add RB, PC, RB, lsl #2 - | checktp CARG2, LJ_TSTR - if (LJ_HASFFI) { - | bne >7 - | cmp CARG1, CARG3 - } else { - | cmpeq CARG1, CARG3 - } - if (vk) { - | subeq PC, RB, #0x20000 - |1: - } else { - |1: - | subne PC, RB, #0x20000 - } - | ins_next - | - if (LJ_HASFFI) { - |7: - | checktp CARG2, LJ_TCDATA - | bne <1 - | b ->vmeta_equal_cd - } - break; - - case BC_ISEQN: case BC_ISNEN: - vk = op == BC_ISEQN; - | // RA = src*8, RC = num_const (~), JMP with RC = target - | lsl RC, RC, #3 - | ldrd CARG12, [RA, BASE]! - | ldrh RB, [PC, #2] - | ldrd CARG34, [RC, KBASE]! - | add PC, PC, #4 - | add RB, PC, RB, lsl #2 - if (vk) { - |->BC_ISEQN_Z: - } else { - |->BC_ISNEN_Z: - } - | checktp CARG2, LJ_TISNUM - | bne >3 - | checktp CARG4, LJ_TISNUM - | bne >4 - | cmp CARG1, CARG3 - if (vk) { - | subeq PC, RB, #0x20000 - |1: - } else { - |1: - | subne PC, RB, #0x20000 - } - |2: - | ins_next - | - |3: // CARG12 is not an integer. - if (LJ_HASFFI) { - | bhi >7 - } else { - if (!vk) { - | subhi PC, RB, #0x20000 - } - | bhi <2 - } - | // CARG12 is a number. - | checktp CARG4, LJ_TISNUM - | movlo RA, RB // Save RB. - | blo >5 - | // CARG12 is a number, CARG3 is an integer. - | mov CARG1, CARG3 - | mov RC, RA - |4: // CARG1 is an integer, CARG34 is a number. - | mov RA, RB // Save RB. - | bl extern __aeabi_i2d - | ldrd CARG34, [RC] // Restore other operand. - |5: // CARG12 and CARG34 are numbers. - | bl extern __aeabi_cdcmpeq - if (vk) { - | subeq PC, RA, #0x20000 - } else { - | subne PC, RA, #0x20000 - } - | b <2 - | - if (LJ_HASFFI) { - |7: - | checktp CARG2, LJ_TCDATA - | bne <1 - | b ->vmeta_equal_cd - } - break; - - case BC_ISEQP: case BC_ISNEP: - vk = op == BC_ISEQP; - | // RA = src*8, RC = primitive_type (~), JMP with RC = target - | ldrd CARG12, [BASE, RA] - | ldrh RB, [PC, #2] - | add PC, PC, #4 - | mvn RC, RC - | add RB, PC, RB, lsl #2 - if (LJ_HASFFI) { - | checktp CARG2, LJ_TCDATA - | beq ->vmeta_equal_cd - } - | cmp CARG2, RC - if (vk) { - | subeq PC, RB, #0x20000 - } else { - | subne PC, RB, #0x20000 - } - | ins_next - break; - - /* -- Unary test and copy ops ------------------------------------------- */ - - case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: - | // RA = dst*8 or unused, RC = src, JMP with RC = target - | add RC, BASE, RC, lsl #3 - | ldrh RB, [PC, #2] - | ldrd CARG12, [RC] - | add PC, PC, #4 - | add RB, PC, RB, lsl #2 - | checktp CARG2, LJ_TTRUE - if (op == BC_ISTC || op == BC_IST) { - | subls PC, RB, #0x20000 - if (op == BC_ISTC) { - | strdls CARG12, [BASE, RA] - } - } else { - | subhi PC, RB, #0x20000 - if (op == BC_ISFC) { - | strdhi CARG12, [BASE, RA] - } - } - | ins_next - break; - - /* -- Unary ops --------------------------------------------------------- */ - - case BC_MOV: - | // RA = dst*8, RC = src - | lsl RC, RC, #3 - | ins_next1 - | ldrd CARG12, [BASE, RC] - | ins_next2 - | strd CARG12, [BASE, RA] - | ins_next3 - break; - case BC_NOT: - | // RA = dst*8, RC = src - | add RC, BASE, RC, lsl #3 - | ins_next1 - | ldr CARG1, [RC, #4] - | add RA, BASE, RA - | ins_next2 - | checktp CARG1, LJ_TTRUE - | mvnls CARG2, #~LJ_TFALSE - | mvnhi CARG2, #~LJ_TTRUE - | str CARG2, [RA, #4] - | ins_next3 - break; - case BC_UNM: - | // RA = dst*8, RC = src - | lsl RC, RC, #3 - | ldrd CARG12, [BASE, RC] - | ins_next1 - | ins_next2 - | checktp CARG2, LJ_TISNUM - | bhi ->vmeta_unm - | eorne CARG2, CARG2, #0x80000000 - | bne >5 - | rsbseq CARG1, CARG1, #0 - | ldrdvs CARG12, >9 - |5: - | strd CARG12, [BASE, RA] - | ins_next3 - | - |.align 8 - |9: - | .long 0x00000000, 0x41e00000 // 2^31. - break; - case BC_LEN: - | // RA = dst*8, RC = src - | lsl RC, RC, #3 - | ldrd CARG12, [BASE, RC] - | checkstr CARG2, >2 - | ldr CARG1, STR:CARG1->len - |1: - | mvn CARG2, #~LJ_TISNUM - | ins_next1 - | ins_next2 - | strd CARG12, [BASE, RA] - | ins_next3 - |2: - | checktab CARG2, ->vmeta_len -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | ldr TAB:CARG3, TAB:CARG1->metatable - | cmp TAB:CARG3, #0 - | bne >9 - |3: -#endif - |->BC_LEN_Z: - | IOS mov RC, BASE - | bl extern lj_tab_len // (GCtab *t) - | // Returns uint32_t (but less than 2^31). - | IOS mov BASE, RC - | b <1 -#ifdef LUAJIT_ENABLE_LUA52COMPAT - |9: - | ldrb CARG4, TAB:CARG3->nomm - | tst CARG4, #1<vmeta_len -#endif - break; - - /* -- Binary ops -------------------------------------------------------- */ - - |.macro ins_arithcheck, cond, ncond, target - ||if (vk == 1) { - | cmn CARG4, #-LJ_TISNUM - | cmn..cond CARG2, #-LJ_TISNUM - ||} else { - | cmn CARG2, #-LJ_TISNUM - | cmn..cond CARG4, #-LJ_TISNUM - ||} - | b..ncond target - |.endmacro - |.macro ins_arithcheck_int, target - | ins_arithcheck eq, ne, target - |.endmacro - |.macro ins_arithcheck_num, target - | ins_arithcheck lo, hs, target - |.endmacro - | - |.macro ins_arithpre - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8 - ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); - ||switch (vk) { - ||case 0: - | ldrd CARG12, [BASE, RB] - | ldrd CARG34, [KBASE, RC] - || break; - ||case 1: - | ldrd CARG34, [BASE, RB] - | ldrd CARG12, [KBASE, RC] - || break; - ||default: - | ldrd CARG12, [BASE, RB] - | ldrd CARG34, [BASE, RC] - || break; - ||} - |.endmacro - | - |.macro ins_arithfallback, ins - ||switch (vk) { - ||case 0: - | ins ->vmeta_arith_vn - || break; - ||case 1: - | ins ->vmeta_arith_nv - || break; - ||default: - | ins ->vmeta_arith_vv - || break; - ||} - |.endmacro - | - |.macro ins_arithdn, intins, fpcall - | ins_arithpre - |.if "intins" ~= "vm_modi" - | ins_next1 - |.endif - | ins_arithcheck_int >5 - |.if "intins" == "smull" - | smull CARG1, RC, CARG3, CARG1 - | cmp RC, CARG1, asr #31 - | ins_arithfallback bne - |.elif "intins" == "vm_modi" - | movs CARG2, CARG3 - | ins_arithfallback beq - | bl ->vm_modi - | mvn CARG2, #~LJ_TISNUM - |.else - | intins CARG1, CARG1, CARG3 - | ins_arithfallback bvs - |.endif - |4: - |.if "intins" == "vm_modi" - | ins_next1 - |.endif - | ins_next2 - | strd CARG12, [BASE, RA] - | ins_next3 - |5: // FP variant. - | ins_arithfallback ins_arithcheck_num - |.if "intins" == "vm_modi" - | bl fpcall - |.else - | bl fpcall - | ins_next1 - |.endif - | b <4 - |.endmacro - | - |.macro ins_arithfp, fpcall - | ins_arithpre - | ins_arithfallback ins_arithcheck_num - |.if "fpcall" == "extern pow" - | IOS mov RC, BASE - | bl fpcall - | IOS mov BASE, RC - |.else - | bl fpcall - |.endif - | ins_next1 - | ins_next2 - | strd CARG12, [BASE, RA] - | ins_next3 - |.endmacro - - case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: - | ins_arithdn adds, extern __aeabi_dadd - break; - case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: - | ins_arithdn subs, extern __aeabi_dsub - break; - case BC_MULVN: case BC_MULNV: case BC_MULVV: - | ins_arithdn smull, extern __aeabi_dmul - break; - case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: - | ins_arithfp extern __aeabi_ddiv - break; - case BC_MODVN: case BC_MODNV: case BC_MODVV: - | ins_arithdn vm_modi, ->vm_mod - break; - case BC_POW: - | // NYI: (partial) integer arithmetic. - | ins_arithfp extern pow - break; - - case BC_CAT: - | decode_RB8 RC, INS - | decode_RC8 RB, INS - | // RA = dst*8, RC = src_start*8, RB = src_end*8 (note: RB/RC swapped!) - | sub CARG3, RB, RC - | str BASE, L->base - | add CARG2, BASE, RB - |->BC_CAT_Z: - | // RA = dst*8, RC = src_start*8, CARG2 = top-1 - | mov CARG1, L - | str PC, SAVE_PC - | lsr CARG3, CARG3, #3 - | bl extern lj_meta_cat // (lua_State *L, TValue *top, int left) - | // Returns NULL (finished) or TValue * (metamethod). - | ldr BASE, L->base - | cmp CRET1, #0 - | bne ->vmeta_binop - | ldrd CARG34, [BASE, RC] - | ins_next1 - | ins_next2 - | strd CARG34, [BASE, RA] // Copy result to RA. - | ins_next3 - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - | // RA = dst*8, RC = str_const (~) - | mvn RC, RC - | ins_next1 - | ldr CARG1, [KBASE, RC, lsl #2] - | mvn CARG2, #~LJ_TSTR - | ins_next2 - | strd CARG12, [BASE, RA] - | ins_next3 - break; - case BC_KCDATA: -#if LJ_HASFFI - | // RA = dst*8, RC = cdata_const (~) - | mvn RC, RC - | ins_next1 - | ldr CARG1, [KBASE, RC, lsl #2] - | mvn CARG2, #~LJ_TCDATA - | ins_next2 - | strd CARG12, [BASE, RA] - | ins_next3 -#endif - break; - case BC_KSHORT: - | // RA = dst*8, (RC = int16_literal) - | mov CARG1, INS, asr #16 // Refetch sign-extended reg. - | mvn CARG2, #~LJ_TISNUM - | ins_next1 - | ins_next2 - | strd CARG12, [BASE, RA] - | ins_next3 - break; - case BC_KNUM: - | // RA = dst*8, RC = num_const - | lsl RC, RC, #3 - | ins_next1 - | ldrd CARG12, [KBASE, RC] - | ins_next2 - | strd CARG12, [BASE, RA] - | ins_next3 - break; - case BC_KPRI: - | // RA = dst*8, RC = primitive_type (~) - | add RA, BASE, RA - | mvn RC, RC - | ins_next1 - | ins_next2 - | str RC, [RA, #4] - | ins_next3 - break; - case BC_KNIL: - | // RA = base*8, RC = end - | add RA, BASE, RA - | add RC, BASE, RC, lsl #3 - | mvn CARG1, #~LJ_TNIL - | str CARG1, [RA, #4] - | add RA, RA, #8 - |1: - | str CARG1, [RA, #4] - | cmp RA, RC - | add RA, RA, #8 - | blt <1 - | ins_next_ - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - | // RA = dst*8, RC = uvnum - | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] - | lsl RC, RC, #2 - | add RC, RC, #offsetof(GCfuncL, uvptr) - | ldr UPVAL:CARG2, [LFUNC:CARG2, RC] - | ldr CARG2, UPVAL:CARG2->v - | ldrd CARG34, [CARG2] - | ins_next1 - | ins_next2 - | strd CARG34, [BASE, RA] - | ins_next3 - break; - case BC_USETV: - | // RA = uvnum*8, RC = src - | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] - | lsr RA, RA, #1 - | add RA, RA, #offsetof(GCfuncL, uvptr) - | lsl RC, RC, #3 - | ldr UPVAL:CARG2, [LFUNC:CARG2, RA] - | ldrd CARG34, [BASE, RC] - | ldrb RB, UPVAL:CARG2->marked - | ldrb RC, UPVAL:CARG2->closed - | ldr CARG2, UPVAL:CARG2->v - | tst RB, #LJ_GC_BLACK // isblack(uv) - | add RB, CARG4, #-LJ_TISGCV - | cmpne RC, #0 - | strd CARG34, [CARG2] - | bne >2 // Upvalue is closed and black? - |1: - | ins_next - | - |2: // Check if new value is collectable. - | cmn RB, #-(LJ_TISNUM - LJ_TISGCV) - | ldrbhi RC, GCOBJ:CARG3->gch.marked - | bls <1 // tvisgcv(v) - | sub CARG1, DISPATCH, #-GG_DISP2G - | tst RC, #LJ_GC_WHITES - | // Crossed a write barrier. Move the barrier forward. - if (LJ_TARGET_IOS) { - | beq <1 - | mov RC, BASE - | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) - | mov BASE, RC - } else { - | blne extern lj_gc_barrieruv // (global_State *g, TValue *tv) - } - | b <1 - break; - case BC_USETS: - | // RA = uvnum*8, RC = str_const (~) - | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] - | lsr RA, RA, #1 - | add RA, RA, #offsetof(GCfuncL, uvptr) - | mvn RC, RC - | ldr UPVAL:CARG2, [LFUNC:CARG2, RA] - | ldr STR:CARG3, [KBASE, RC, lsl #2] - | mvn CARG4, #~LJ_TSTR - | ldrb RB, UPVAL:CARG2->marked - | ldr CARG2, UPVAL:CARG2->v - | ldrb RC, UPVAL:CARG2->closed - | tst RB, #LJ_GC_BLACK // isblack(uv) - | ldrb RB, STR:CARG3->marked - | strd CARG34, [CARG2] - | bne >2 - |1: - | ins_next - | - |2: // Check if string is white and ensure upvalue is closed. - | tst RB, #LJ_GC_WHITES // iswhite(str) - | cmpne RC, #0 - | sub CARG1, DISPATCH, #-GG_DISP2G - | // Crossed a write barrier. Move the barrier forward. - if (LJ_TARGET_IOS) { - | beq <1 - | mov RC, BASE - | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) - | mov BASE, RC - } else { - | blne extern lj_gc_barrieruv // (global_State *g, TValue *tv) - } - | b <1 - break; - case BC_USETN: - | // RA = uvnum*8, RC = num_const - | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] - | lsr RA, RA, #1 - | add RA, RA, #offsetof(GCfuncL, uvptr) - | lsl RC, RC, #3 - | ldr UPVAL:CARG2, [LFUNC:CARG2, RA] - | ldrd CARG34, [KBASE, RC] - | ldr CARG2, UPVAL:CARG2->v - | ins_next1 - | ins_next2 - | strd CARG34, [CARG2] - | ins_next3 - break; - case BC_USETP: - | // RA = uvnum*8, RC = primitive_type (~) - | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] - | lsr RA, RA, #1 - | add RA, RA, #offsetof(GCfuncL, uvptr) - | ldr UPVAL:CARG2, [LFUNC:CARG2, RA] - | mvn RC, RC - | ldr CARG2, UPVAL:CARG2->v - | ins_next1 - | ins_next2 - | str RC, [CARG2, #4] - | ins_next3 - break; - - case BC_UCLO: - | // RA = level*8, RC = target - | ldr CARG3, L->openupval - | add RC, PC, RC, lsl #2 - | str BASE, L->base - | cmp CARG3, #0 - | sub PC, RC, #0x20000 - | beq >1 - | mov CARG1, L - | add CARG2, BASE, RA - | bl extern lj_func_closeuv // (lua_State *L, TValue *level) - | ldr BASE, L->base - |1: - | ins_next - break; - - case BC_FNEW: - | // RA = dst*8, RC = proto_const (~) (holding function prototype) - | mvn RC, RC - | str BASE, L->base - | ldr CARG2, [KBASE, RC, lsl #2] - | str PC, SAVE_PC - | ldr CARG3, [BASE, FRAME_FUNC] - | mov CARG1, L - | // (lua_State *L, GCproto *pt, GCfuncL *parent) - | bl extern lj_func_newL_gc - | // Returns GCfuncL *. - | ldr BASE, L->base - | mvn CARG2, #~LJ_TFUNC - | ins_next1 - | ins_next2 - | strd CARG12, [BASE, RA] - | ins_next3 - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - case BC_TDUP: - | // RA = dst*8, RC = (hbits|asize) | tab_const (~) - if (op == BC_TDUP) { - | mvn RC, RC - } - | ldr CARG3, [DISPATCH, #DISPATCH_GL(gc.total)] - | ldr CARG4, [DISPATCH, #DISPATCH_GL(gc.threshold)] - | str BASE, L->base - | str PC, SAVE_PC - | cmp CARG3, CARG4 - | mov CARG1, L - | bhs >5 - |1: - if (op == BC_TNEW) { - | lsl CARG2, RC, #21 - | lsr CARG3, RC, #11 - | asr RC, CARG2, #21 - | lsr CARG2, CARG2, #21 - | cmn RC, #1 - | addeq CARG2, CARG2, #2 - | bl extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits) - | // Returns GCtab *. - } else { - | ldr CARG2, [KBASE, RC, lsl #2] - | bl extern lj_tab_dup // (lua_State *L, Table *kt) - | // Returns GCtab *. - } - | ldr BASE, L->base - | mvn CARG2, #~LJ_TTAB - | ins_next1 - | ins_next2 - | strd CARG12, [BASE, RA] - | ins_next3 - |5: - | bl extern lj_gc_step_fixtop // (lua_State *L) - | mov CARG1, L - | b <1 - break; - - case BC_GGET: - | // RA = dst*8, RC = str_const (~) - case BC_GSET: - | // RA = dst*8, RC = str_const (~) - | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] - | mvn RC, RC - | ldr TAB:CARG1, LFUNC:CARG2->env - | ldr STR:RC, [KBASE, RC, lsl #2] - if (op == BC_GGET) { - | b ->BC_TGETS_Z - } else { - | b ->BC_TSETS_Z - } - break; - - case BC_TGETV: - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | // RA = dst*8, RB = table*8, RC = key*8 - | ldrd TAB:CARG12, [BASE, RB] - | ldrd CARG34, [BASE, RC] - | checktab CARG2, ->vmeta_tgetv // STALL: load CARG12. - | checktp CARG4, LJ_TISNUM // Integer key? - | ldreq CARG4, TAB:CARG1->array - | ldreq CARG2, TAB:CARG1->asize - | bne >9 - | - | add CARG4, CARG4, CARG3, lsl #3 - | cmp CARG3, CARG2 // In array part? - | ldrdlo CARG34, [CARG4] - | bhs ->vmeta_tgetv - | ins_next1 // Overwrites RB! - | checktp CARG4, LJ_TNIL - | beq >5 - |1: - | ins_next2 - | strd CARG34, [BASE, RA] - | ins_next3 - | - |5: // Check for __index if table value is nil. - | ldr TAB:CARG2, TAB:CARG1->metatable - | cmp TAB:CARG2, #0 - | beq <1 // No metatable: done. - | ldrb CARG2, TAB:CARG2->nomm - | tst CARG2, #1<vmeta_tgetv - | - |9: - | checktp CARG4, LJ_TSTR // String key? - | moveq STR:RC, CARG3 - | beq ->BC_TGETS_Z - | b ->vmeta_tgetv - break; - case BC_TGETS: - | decode_RB8 RB, INS - | and RC, RC, #255 - | // RA = dst*8, RB = table*8, RC = str_const (~) - | ldrd CARG12, [BASE, RB] - | mvn RC, RC - | ldr STR:RC, [KBASE, RC, lsl #2] // STALL: early RC. - | checktab CARG2, ->vmeta_tgets1 - |->BC_TGETS_Z: - | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8 - | ldr CARG3, TAB:CARG1->hmask - | ldr CARG4, STR:RC->hash - | ldr NODE:INS, TAB:CARG1->node - | mov TAB:RB, TAB:CARG1 - | and CARG3, CARG3, CARG4 // idx = str->hash & tab->hmask - | add CARG3, CARG3, CARG3, lsl #1 - | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8 - |1: - | ldrd CARG12, NODE:INS->key // STALL: early NODE:INS. - | ldrd CARG34, NODE:INS->val - | ldr NODE:INS, NODE:INS->next - | checktp CARG2, LJ_TSTR - | cmpeq CARG1, STR:RC - | bne >4 - | checktp CARG4, LJ_TNIL - | beq >5 - |3: - | ins_next1 - | ins_next2 - | strd CARG34, [BASE, RA] - | ins_next3 - | - |4: // Follow hash chain. - | cmp NODE:INS, #0 - | bne <1 - | // End of hash chain: key not found, nil result. - | - |5: // Check for __index if table value is nil. - | ldr TAB:CARG1, TAB:RB->metatable - | mov CARG3, #0 // Optional clear of undef. value (during load stall). - | mvn CARG4, #~LJ_TNIL - | cmp TAB:CARG1, #0 - | beq <3 // No metatable: done. - | ldrb CARG2, TAB:CARG1->nomm - | tst CARG2, #1<vmeta_tgets - break; - case BC_TGETB: - | decode_RB8 RB, INS - | and RC, RC, #255 - | // RA = dst*8, RB = table*8, RC = index - | ldrd CARG12, [BASE, RB] - | checktab CARG2, ->vmeta_tgetb // STALL: load CARG12. - | ldr CARG3, TAB:CARG1->asize - | ldr CARG4, TAB:CARG1->array - | lsl CARG2, RC, #3 - | cmp RC, CARG3 - | ldrdlo CARG34, [CARG4, CARG2] - | bhs ->vmeta_tgetb - | ins_next1 // Overwrites RB! - | checktp CARG4, LJ_TNIL - | beq >5 - |1: - | ins_next2 - | strd CARG34, [BASE, RA] - | ins_next3 - | - |5: // Check for __index if table value is nil. - | ldr TAB:CARG2, TAB:CARG1->metatable - | cmp TAB:CARG2, #0 - | beq <1 // No metatable: done. - | ldrb CARG2, TAB:CARG2->nomm - | tst CARG2, #1<vmeta_tgetb - break; - - case BC_TSETV: - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | // RA = src*8, RB = table*8, RC = key*8 - | ldrd TAB:CARG12, [BASE, RB] - | ldrd CARG34, [BASE, RC] - | checktab CARG2, ->vmeta_tsetv // STALL: load CARG12. - | checktp CARG4, LJ_TISNUM // Integer key? - | ldreq CARG2, TAB:CARG1->array - | ldreq CARG4, TAB:CARG1->asize - | bne >9 - | - | add CARG2, CARG2, CARG3, lsl #3 - | cmp CARG3, CARG4 // In array part? - | ldrlo INS, [CARG2, #4] - | bhs ->vmeta_tsetv - | ins_next1 // Overwrites RB! - | checktp INS, LJ_TNIL - | ldrb INS, TAB:CARG1->marked - | ldrd CARG34, [BASE, RA] - | beq >5 - |1: - | tst INS, #LJ_GC_BLACK // isblack(table) - | strd CARG34, [CARG2] - | bne >7 - |2: - | ins_next2 - | ins_next3 - | - |5: // Check for __newindex if previous value is nil. - | ldr TAB:RA, TAB:CARG1->metatable - | cmp TAB:RA, #0 - | beq <1 // No metatable: done. - | ldrb RA, TAB:RA->nomm - | tst RA, #1<vmeta_tsetv - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:CARG1, INS, CARG3 - | b <2 - | - |9: - | checktp CARG4, LJ_TSTR // String key? - | moveq STR:RC, CARG3 - | beq ->BC_TSETS_Z - | b ->vmeta_tsetv - break; - case BC_TSETS: - | decode_RB8 RB, INS - | and RC, RC, #255 - | // RA = src*8, RB = table*8, RC = str_const (~) - | ldrd CARG12, [BASE, RB] - | mvn RC, RC - | ldr STR:RC, [KBASE, RC, lsl #2] // STALL: early RC. - | checktab CARG2, ->vmeta_tsets1 - |->BC_TSETS_Z: - | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8 - | ldr CARG3, TAB:CARG1->hmask - | ldr CARG4, STR:RC->hash - | ldr NODE:INS, TAB:CARG1->node - | mov TAB:RB, TAB:CARG1 - | and CARG3, CARG3, CARG4 // idx = str->hash & tab->hmask - | add CARG3, CARG3, CARG3, lsl #1 - | mov CARG4, #0 - | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8 - | strb CARG4, TAB:RB->nomm // Clear metamethod cache. - |1: - | ldrd CARG12, NODE:INS->key - | ldr CARG4, NODE:INS->val.it - | ldr NODE:CARG3, NODE:INS->next - | checktp CARG2, LJ_TSTR - | cmpeq CARG1, STR:RC - | bne >5 - | ldrb CARG2, TAB:RB->marked - | checktp CARG4, LJ_TNIL // Key found, but nil value? - | ldrd CARG34, [BASE, RA] - | beq >4 - |2: - | tst CARG2, #LJ_GC_BLACK // isblack(table) - | strd CARG34, NODE:INS->val - | bne >7 - |3: - | ins_next - | - |4: // Check for __newindex if previous value is nil. - | ldr TAB:CARG1, TAB:RB->metatable - | cmp TAB:CARG1, #0 - | beq <2 // No metatable: done. - | ldrb CARG1, TAB:CARG1->nomm - | tst CARG1, #1<vmeta_tsets - | - |5: // Follow hash chain. - | movs NODE:INS, NODE:CARG3 - | bne <1 - | // End of hash chain: key not found, add a new one. - | - | // But check for __newindex first. - | ldr TAB:CARG1, TAB:RB->metatable - | mov CARG3, TMPDp - | str PC, SAVE_PC - | cmp TAB:CARG1, #0 // No metatable: continue. - | str BASE, L->base - | ldrbne CARG2, TAB:CARG1->nomm - | mov CARG1, L - | beq >6 - | tst CARG2, #1<vmeta_tsets // 'no __newindex' flag NOT set: check. - |6: - | mvn CARG4, #~LJ_TSTR - | str STR:RC, TMPDlo - | mov CARG2, TAB:RB - | str CARG4, TMPDhi - | bl extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k) - | // Returns TValue *. - | ldr BASE, L->base - | ldrd CARG34, [BASE, RA] - | strd CARG34, [CRET1] - | b <3 // No 2nd write barrier needed. - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, CARG2, CARG3 - | b <3 - break; - case BC_TSETB: - | decode_RB8 RB, INS - | and RC, RC, #255 - | // RA = src*8, RB = table*8, RC = index - | ldrd CARG12, [BASE, RB] - | checktab CARG2, ->vmeta_tsetb // STALL: load CARG12. - | ldr CARG3, TAB:CARG1->asize - | ldr RB, TAB:CARG1->array - | lsl CARG2, RC, #3 - | cmp RC, CARG3 - | ldrdlo CARG34, [CARG2, RB]! - | bhs ->vmeta_tsetb - | ins_next1 // Overwrites RB! - | checktp CARG4, LJ_TNIL - | ldrb INS, TAB:CARG1->marked - | ldrd CARG34, [BASE, RA] - | beq >5 - |1: - | tst INS, #LJ_GC_BLACK // isblack(table) - | strd CARG34, [CARG2] - | bne >7 - |2: - | ins_next2 - | ins_next3 - | - |5: // Check for __newindex if previous value is nil. - | ldr TAB:RA, TAB:CARG1->metatable - | cmp TAB:RA, #0 - | beq <1 // No metatable: done. - | ldrb RA, TAB:RA->nomm - | tst RA, #1<vmeta_tsetb - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:CARG1, INS, CARG3 - | b <2 - break; - - case BC_TSETM: - | // RA = base*8 (table at base-1), RC = num_const (start index) - | add RA, BASE, RA - |1: - | ldr RB, SAVE_MULTRES - | ldr TAB:CARG2, [RA, #-8] // Guaranteed to be a table. - | ldr CARG1, [KBASE, RC, lsl #3] // Integer constant is in lo-word. - | subs RB, RB, #8 - | ldr CARG4, TAB:CARG2->asize - | beq >4 // Nothing to copy? - | add CARG3, CARG1, RB, lsr #3 - | cmp CARG3, CARG4 - | ldr CARG4, TAB:CARG2->array - | add RB, RA, RB - | bhi >5 - | add INS, CARG4, CARG1, lsl #3 - | ldrb CARG1, TAB:CARG2->marked - |3: // Copy result slots to table. - | ldrd CARG34, [RA], #8 - | strd CARG34, [INS], #8 - | cmp RA, RB - | blo <3 - | tst CARG1, #LJ_GC_BLACK // isblack(table) - | bne >7 - |4: - | ins_next - | - |5: // Need to resize array part. - | str BASE, L->base - | mov CARG1, L - | str PC, SAVE_PC - | bl extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize) - | // Must not reallocate the stack. - | IOS ldr BASE, L->base - | b <1 - | - |7: // Possible table write barrier for any value. Skip valiswhite check. - | barrierback TAB:CARG2, CARG1, CARG3 - | b <4 - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALLM: - | // RA = base*8, (RB = nresults+1,) RC = extra_nargs - | ldr CARG1, SAVE_MULTRES - | decode_RC8 NARGS8:RC, INS - | add NARGS8:RC, NARGS8:RC, CARG1 - | b ->BC_CALL_Z - break; - case BC_CALL: - | decode_RC8 NARGS8:RC, INS - | // RA = base*8, (RB = nresults+1,) RC = (nargs+1)*8 - |->BC_CALL_Z: - | mov RB, BASE // Save old BASE for vmeta_call. - | ldrd CARG34, [BASE, RA]! - | sub NARGS8:RC, NARGS8:RC, #8 - | add BASE, BASE, #8 - | checkfunc CARG4, ->vmeta_call - | ins_call - break; - - case BC_CALLMT: - | // RA = base*8, (RB = 0,) RC = extra_nargs - | ldr CARG1, SAVE_MULTRES - | add NARGS8:RC, CARG1, RC, lsl #3 - | b ->BC_CALLT1_Z - break; - case BC_CALLT: - | lsl NARGS8:RC, RC, #3 - | // RA = base*8, (RB = 0,) RC = (nargs+1)*8 - |->BC_CALLT1_Z: - | ldrd LFUNC:CARG34, [RA, BASE]! - | sub NARGS8:RC, NARGS8:RC, #8 - | add RA, RA, #8 - | checkfunc CARG4, ->vmeta_callt - | ldr PC, [BASE, FRAME_PC] - |->BC_CALLT2_Z: - | mov RB, #0 - | ldrb CARG4, LFUNC:CARG3->ffid - | tst PC, #FRAME_TYPE - | bne >7 - |1: - | str LFUNC:CARG3, [BASE, FRAME_FUNC] // Copy function down, but keep PC. - | cmp NARGS8:RC, #0 - | beq >3 - |2: - | ldrd CARG12, [RA, RB] - | add INS, RB, #8 - | cmp INS, NARGS8:RC - | strd CARG12, [BASE, RB] - | mov RB, INS - | bne <2 - |3: - | cmp CARG4, #1 // (> FF_C) Calling a fast function? - | bhi >5 - |4: - | ins_callt - | - |5: // Tailcall to a fast function with a Lua frame below. - | ldr INS, [PC, #-4] - | decode_RA8 RA, INS - | sub CARG1, BASE, RA - | ldr LFUNC:CARG1, [CARG1, #-16] - | ldr CARG1, LFUNC:CARG1->field_pc - | ldr KBASE, [CARG1, #PC2PROTO(k)] - | b <4 - | - |7: // Tailcall from a vararg function. - | eor PC, PC, #FRAME_VARG - | tst PC, #FRAME_TYPEP // Vararg frame below? - | movne CARG4, #0 // Clear ffid if no Lua function below. - | bne <1 - | sub BASE, BASE, PC - | ldr PC, [BASE, FRAME_PC] - | tst PC, #FRAME_TYPE - | movne CARG4, #0 // Clear ffid if no Lua function below. - | b <1 - break; - - case BC_ITERC: - | // RA = base*8, (RB = nresults+1, RC = nargs+1 (2+1)) - | add RA, BASE, RA - | mov RB, BASE // Save old BASE for vmeta_call. - | ldrd CARG34, [RA, #-16] - | ldrd CARG12, [RA, #-8] - | add BASE, RA, #8 - | strd CARG34, [RA, #8] // Copy state. - | strd CARG12, [RA, #16] // Copy control var. - | // STALL: locked CARG34. - | ldrd LFUNC:CARG34, [RA, #-24] - | mov NARGS8:RC, #16 // Iterators get 2 arguments. - | // STALL: load CARG34. - | strd LFUNC:CARG34, [RA] // Copy callable. - | checkfunc CARG4, ->vmeta_call - | ins_call - break; - - case BC_ITERN: - | // RA = base*8, (RB = nresults+1, RC = nargs+1 (2+1)) -#if LJ_HASJIT - | // NYI: add hotloop, record BC_ITERN. -#endif - | add RA, BASE, RA - | ldr TAB:RB, [RA, #-16] - | ldr CARG1, [RA, #-8] // Get index from control var. - | ldr INS, TAB:RB->asize - | ldr CARG2, TAB:RB->array - | add PC, PC, #4 - |1: // Traverse array part. - | subs RC, CARG1, INS - | add CARG3, CARG2, CARG1, lsl #3 - | bhs >5 // Index points after array part? - | ldrd CARG34, [CARG3] - | checktp CARG4, LJ_TNIL - | addeq CARG1, CARG1, #1 // Skip holes in array part. - | beq <1 - | ldrh RC, [PC, #-2] - | mvn CARG2, #~LJ_TISNUM - | strd CARG34, [RA, #8] - | add RC, PC, RC, lsl #2 - | add RB, CARG1, #1 - | strd CARG12, [RA] - | sub PC, RC, #0x20000 - | str RB, [RA, #-8] // Update control var. - |3: - | ins_next - | - |5: // Traverse hash part. - | ldr CARG4, TAB:RB->hmask - | ldr NODE:RB, TAB:RB->node - |6: - | add CARG1, RC, RC, lsl #1 - | cmp RC, CARG4 // End of iteration? Branch to ITERL+1. - | add NODE:CARG3, NODE:RB, CARG1, lsl #3 // node = tab->node + idx*3*8 - | bhi <3 - | ldrd CARG12, NODE:CARG3->val - | checktp CARG2, LJ_TNIL - | add RC, RC, #1 - | beq <6 // Skip holes in hash part. - | ldrh RB, [PC, #-2] - | add RC, RC, INS - | ldrd CARG34, NODE:CARG3->key - | str RC, [RA, #-8] // Update control var. - | strd CARG12, [RA, #8] - | add RC, PC, RB, lsl #2 - | sub PC, RC, #0x20000 - | strd CARG34, [RA] - | b <3 - break; - - case BC_ISNEXT: - | // RA = base*8, RC = target (points to ITERN) - | add RA, BASE, RA - | add RC, PC, RC, lsl #2 - | ldrd CFUNC:CARG12, [RA, #-24] - | ldr CARG3, [RA, #-12] - | ldr CARG4, [RA, #-4] - | checktp CARG2, LJ_TFUNC - | ldrbeq CARG1, CFUNC:CARG1->ffid - | checktpeq CARG3, LJ_TTAB - | checktpeq CARG4, LJ_TNIL - | cmpeq CARG1, #FF_next_N - | subeq PC, RC, #0x20000 - | bne >5 - | ins_next1 - | ins_next2 - | mov CARG1, #0 - | str CARG1, [RA, #-8] // Initialize control var. - |1: - | ins_next3 - |5: // Despecialize bytecode if any of the checks fail. - | mov CARG1, #BC_JMP - | mov OP, #BC_ITERC - | strb CARG1, [PC, #-4] - | sub PC, RC, #0x20000 - | strb OP, [PC] // Subsumes ins_next1. - | ins_next2 - | b <1 - break; - - case BC_VARG: - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8 - | ldr CARG1, [BASE, FRAME_PC] - | add RC, BASE, RC - | add RA, BASE, RA - | add RC, RC, #FRAME_VARG - | add CARG4, RA, RB - | sub CARG3, BASE, #8 // CARG3 = vtop - | sub RC, RC, CARG1 // RC = vbase - | // Note: RC may now be even _above_ BASE if nargs was < numparams. - | cmp RB, #0 - | sub CARG1, CARG3, RC - | beq >5 // Copy all varargs? - | sub CARG4, CARG4, #16 - |1: // Copy vararg slots to destination slots. - | cmp RC, CARG3 - | ldrdlo CARG12, [RC], #8 - | mvnhs CARG2, #~LJ_TNIL - | cmp RA, CARG4 - | strd CARG12, [RA], #8 - | blo <1 - |2: - | ins_next - | - |5: // Copy all varargs. - | ldr CARG4, L->maxstack - | cmp CARG1, #0 - | movle RB, #8 // MULTRES = (0+1)*8 - | addgt RB, CARG1, #8 - | add CARG2, RA, CARG1 - | str RB, SAVE_MULTRES - | ble <2 - | cmp CARG2, CARG4 - | bhi >7 - |6: - | ldrd CARG12, [RC], #8 - | strd CARG12, [RA], #8 - | cmp RC, CARG3 - | blo <6 - | b <2 - | - |7: // Grow stack for varargs. - | lsr CARG2, CARG1, #3 - | str RA, L->top - | mov CARG1, L - | str BASE, L->base - | sub RC, RC, BASE // Need delta, because BASE may change. - | str PC, SAVE_PC - | sub RA, RA, BASE - | bl extern lj_state_growstack // (lua_State *L, int n) - | ldr BASE, L->base - | add RA, BASE, RA - | add RC, BASE, RC - | sub CARG3, BASE, #8 - | b <6 - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - | // RA = results*8, RC = extra results - | ldr CARG1, SAVE_MULTRES - | ldr PC, [BASE, FRAME_PC] - | add RA, BASE, RA - | add RC, CARG1, RC, lsl #3 - | b ->BC_RETM_Z - break; - - case BC_RET: - | // RA = results*8, RC = nresults+1 - | ldr PC, [BASE, FRAME_PC] - | lsl RC, RC, #3 - | add RA, BASE, RA - |->BC_RETM_Z: - | str RC, SAVE_MULTRES - |1: - | ands CARG1, PC, #FRAME_TYPE - | eor CARG2, PC, #FRAME_VARG - | bne ->BC_RETV2_Z - | - |->BC_RET_Z: - | // BASE = base, RA = resultptr, RC = (nresults+1)*8, PC = return - | ldr INS, [PC, #-4] - | subs CARG4, RC, #8 - | sub CARG3, BASE, #8 - | beq >3 - |2: - | ldrd CARG12, [RA], #8 - | add BASE, BASE, #8 - | subs CARG4, CARG4, #8 - | strd CARG12, [BASE, #-16] - | bne <2 - |3: - | decode_RA8 RA, INS - | sub CARG4, CARG3, RA - | decode_RB8 RB, INS - | ldr LFUNC:CARG1, [CARG4, FRAME_FUNC] - |5: - | cmp RB, RC // More results expected? - | bhi >6 - | mov BASE, CARG4 - | ldr CARG2, LFUNC:CARG1->field_pc - | ins_next1 - | ins_next2 - | ldr KBASE, [CARG2, #PC2PROTO(k)] - | ins_next3 - | - |6: // Fill up results with nil. - | mvn CARG2, #~LJ_TNIL - | add BASE, BASE, #8 - | add RC, RC, #8 - | str CARG2, [BASE, #-12] - | b <5 - | - |->BC_RETV1_Z: // Non-standard return case. - | add RA, BASE, RA - |->BC_RETV2_Z: - | tst CARG2, #FRAME_TYPEP - | bne ->vm_return - | // Return from vararg function: relocate BASE down. - | sub BASE, BASE, CARG2 - | ldr PC, [BASE, FRAME_PC] - | b <1 - break; - - case BC_RET0: case BC_RET1: - | // RA = results*8, RC = nresults+1 - | ldr PC, [BASE, FRAME_PC] - | lsl RC, RC, #3 - | str RC, SAVE_MULTRES - | ands CARG1, PC, #FRAME_TYPE - | eor CARG2, PC, #FRAME_VARG - | ldreq INS, [PC, #-4] - | bne ->BC_RETV1_Z - if (op == BC_RET1) { - | ldrd CARG12, [BASE, RA] - } - | sub CARG4, BASE, #8 - | decode_RA8 RA, INS - if (op == BC_RET1) { - | strd CARG12, [CARG4] - } - | sub BASE, CARG4, RA - | decode_RB8 RB, INS - | ldr LFUNC:CARG1, [BASE, FRAME_FUNC] - |5: - | cmp RB, RC - | bhi >6 - | ldr CARG2, LFUNC:CARG1->field_pc - | ins_next1 - | ins_next2 - | ldr KBASE, [CARG2, #PC2PROTO(k)] - | ins_next3 - | - |6: // Fill up results with nil. - | sub CARG2, CARG4, #4 - | mvn CARG3, #~LJ_TNIL - | str CARG3, [CARG2, RC] - | add RC, RC, #8 - | b <5 - break; - - /* -- Loops and branches ------------------------------------------------ */ - - |.define FOR_IDX, [RA]; .define FOR_TIDX, [RA, #4] - |.define FOR_STOP, [RA, #8]; .define FOR_TSTOP, [RA, #12] - |.define FOR_STEP, [RA, #16]; .define FOR_TSTEP, [RA, #20] - |.define FOR_EXT, [RA, #24]; .define FOR_TEXT, [RA, #28] - - case BC_FORL: -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_IFORL follows. - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - | // RA = base*8, RC = target (after end of loop or start of loop) - vk = (op == BC_IFORL || op == BC_JFORL); - | ldrd CARG12, [RA, BASE]! - if (op != BC_JFORL) { - | add RC, PC, RC, lsl #2 - } - if (!vk) { - | ldrd CARG34, FOR_STOP - | checktp CARG2, LJ_TISNUM - | ldr RB, FOR_TSTEP - | bne >5 - | checktp CARG4, LJ_TISNUM - | ldr CARG4, FOR_STEP - | checktpeq RB, LJ_TISNUM - | bne ->vmeta_for - | cmp CARG4, #0 - | blt >4 - | cmp CARG1, CARG3 - } else { - | ldrd CARG34, FOR_STEP - | checktp CARG2, LJ_TISNUM - | bne >5 - | adds CARG1, CARG1, CARG3 - | ldr CARG4, FOR_STOP - if (op == BC_IFORL) { - | addvs RC, PC, #0x20000 // Overflow: prevent branch. - } else { - | bvs >2 // Overflow: do not enter mcode. - } - | cmp CARG3, #0 - | blt >4 - | cmp CARG1, CARG4 - } - |1: - if (op == BC_FORI) { - | subgt PC, RC, #0x20000 - } else if (op == BC_JFORI) { - | sub PC, RC, #0x20000 - | ldrhle RC, [PC, #-2] - } else if (op == BC_IFORL) { - | suble PC, RC, #0x20000 - } - if (vk) { - | strd CARG12, FOR_IDX - } - |2: - | ins_next1 - | ins_next2 - | strd CARG12, FOR_EXT - if (op == BC_JFORI || op == BC_JFORL) { - | ble =>BC_JLOOP - } - |3: - | ins_next3 - | - |4: // Invert check for negative step. - if (!vk) { - | cmp CARG3, CARG1 - } else { - | cmp CARG4, CARG1 - } - | b <1 - | - |5: // FP loop. - if (!vk) { - | cmnlo CARG4, #-LJ_TISNUM - | cmnlo RB, #-LJ_TISNUM - | bhs ->vmeta_for - | cmp RB, #0 - | strd CARG12, FOR_IDX - | strd CARG12, FOR_EXT - | blt >8 - } else { - | cmp CARG4, #0 - | blt >8 - | bl extern __aeabi_dadd - | strd CARG12, FOR_IDX - | ldrd CARG34, FOR_STOP - | strd CARG12, FOR_EXT - } - |6: - | bl extern __aeabi_cdcmple - if (op == BC_FORI) { - | subhi PC, RC, #0x20000 - } else if (op == BC_JFORI) { - | sub PC, RC, #0x20000 - | ldrhls RC, [PC, #-2] - | bls =>BC_JLOOP - } else if (op == BC_IFORL) { - | subls PC, RC, #0x20000 - } else { - | bls =>BC_JLOOP - } - | ins_next1 - | ins_next2 - | b <3 - | - |8: // Invert check for negative step. - if (vk) { - | bl extern __aeabi_dadd - | strd CARG12, FOR_IDX - | strd CARG12, FOR_EXT - } - | mov CARG3, CARG1 - | mov CARG4, CARG2 - | ldrd CARG12, FOR_STOP - | b <6 - break; - - case BC_ITERL: -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_IITERL follows. - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - | // RA = base*8, RC = target - | ldrd CARG12, [RA, BASE]! - if (op == BC_JITERL) { - | cmn CARG2, #-LJ_TNIL // Stop if iterator returned nil. - | strdne CARG12, [RA, #-8] - | bne =>BC_JLOOP - } else { - | add RC, PC, RC, lsl #2 - | // STALL: load CARG12. - | cmn CARG2, #-LJ_TNIL // Stop if iterator returned nil. - | subne PC, RC, #0x20000 // Otherwise save control var + branch. - | strdne CARG12, [RA, #-8] - } - | ins_next - break; - - case BC_LOOP: - | // RA = base*8, RC = target (loop extent) - | // Note: RA/RC is only used by trace recorder to determine scope/extent - | // This opcode does NOT jump, it's only purpose is to detect a hot loop. -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_ILOOP follows. - break; - - case BC_ILOOP: - | // RA = base*8, RC = target (loop extent) - | ins_next - break; - - case BC_JLOOP: -#if LJ_HASJIT - | // RA = base (ignored), RC = traceno - | ldr CARG1, [DISPATCH, #DISPATCH_J(trace)] - | mov CARG2, #0 // Traces on ARM don't store the trace number, so use 0. - | ldr TRACE:RC, [CARG1, RC, lsl #2] - | st_vmstate CARG2 - | ldr RA, TRACE:RC->mcode - | str BASE, [DISPATCH, #DISPATCH_GL(jit_base)] - | str L, [DISPATCH, #DISPATCH_GL(jit_L)] - | bx RA -#endif - break; - - case BC_JMP: - | // RA = base*8 (only used by trace recorder), RC = target - | add RC, PC, RC, lsl #2 - | sub PC, RC, #0x20000 - | ins_next - break; - - /* -- Function headers -------------------------------------------------- */ - - case BC_FUNCF: -#if LJ_HASJIT - | hotcall -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow. - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - | // BASE = new base, RA = BASE+framesize*8, CARG3 = LFUNC, RC = nargs*8 - | ldr CARG1, L->maxstack - | ldrb CARG2, [PC, #-4+PC2PROTO(numparams)] - | ldr KBASE, [PC, #-4+PC2PROTO(k)] - | cmp RA, CARG1 - | bhi ->vm_growstack_l - if (op != BC_JFUNCF) { - | ins_next1 - | ins_next2 - } - |2: - | cmp NARGS8:RC, CARG2, lsl #3 // Check for missing parameters. - | mvn CARG4, #~LJ_TNIL - | blo >3 - if (op == BC_JFUNCF) { - | decode_RD RC, INS - | b =>BC_JLOOP - } else { - | ins_next3 - } - | - |3: // Clear missing parameters. - | strd CARG34, [BASE, NARGS8:RC] - | add NARGS8:RC, NARGS8:RC, #8 - | b <2 - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - | NYI // NYI: compiled vararg functions - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - | // BASE = new base, RA = BASE+framesize*8, CARG3 = LFUNC, RC = nargs*8 - | ldr CARG1, L->maxstack - | add CARG4, BASE, RC - | add RA, RA, RC - | str LFUNC:CARG3, [CARG4] // Store copy of LFUNC. - | add CARG2, RC, #8+FRAME_VARG - | ldr KBASE, [PC, #-4+PC2PROTO(k)] - | cmp RA, CARG1 - | str CARG2, [CARG4, #4] // Store delta + FRAME_VARG. - | bhs ->vm_growstack_l - | ldrb RB, [PC, #-4+PC2PROTO(numparams)] - | mov RA, BASE - | mov RC, CARG4 - | cmp RB, #0 - | add BASE, CARG4, #8 - | beq >3 - | mvn CARG3, #~LJ_TNIL - |1: - | cmp RA, RC // Less args than parameters? - | ldrdlo CARG12, [RA], #8 - | movhs CARG2, CARG3 - | strlo CARG3, [RA, #-4] // Clear old fixarg slot (help the GC). - |2: - | subs RB, RB, #1 - | strd CARG12, [CARG4, #8]! - | bne <1 - |3: - | ins_next - break; - - case BC_FUNCC: - case BC_FUNCCW: - | // BASE = new base, RA = BASE+framesize*8, CARG3 = CFUNC, RC = nargs*8 - if (op == BC_FUNCC) { - | ldr CARG4, CFUNC:CARG3->f - } else { - | ldr CARG4, [DISPATCH, #DISPATCH_GL(wrapf)] - } - | add CARG2, RA, NARGS8:RC - | ldr CARG1, L->maxstack - | add RC, BASE, NARGS8:RC - | str BASE, L->base - | cmp CARG2, CARG1 - | str RC, L->top - if (op == BC_FUNCCW) { - | ldr CARG2, CFUNC:CARG3->f - } - | mv_vmstate CARG3, C - | mov CARG1, L - | bhi ->vm_growstack_c // Need to grow stack. - | st_vmstate CARG3 - | blx CARG4 // (lua_State *L [, lua_CFunction f]) - | // Returns nresults. - | ldr BASE, L->base - | mv_vmstate CARG3, INTERP - | ldr CRET2, L->top - | lsl RC, CRET1, #3 - | st_vmstate CARG3 - | ldr PC, [BASE, FRAME_PC] - | sub RA, CRET2, RC // RA = L->top - nresults*8 - | b ->vm_returnc - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx); - - |.code_op - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); - int i; - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",%%progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.long .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.long 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 0xe\n" /* Return address is in lr. */ - "\t.byte 0xc\n\t.uleb128 0xd\n\t.uleb128 0\n" /* def_cfa sp */ - "\t.align 2\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.long .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.long .Lframe0\n" - "\t.long .Lbegin\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x8e\n\t.uleb128 1\n", /* offset lr */ - fcofs, CFRAME_SIZE); - for (i = 11; i >= 4; i--) /* offset r4-r11 */ - fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 2+(11-i)); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE0:\n\n"); -#if LJ_HASFFI - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.long .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.long .Lframe0\n" - "\t.long lj_vm_ffi_call\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ - "\t.byte 0x8e\n\t.uleb128 1\n" /* offset lr */ - "\t.byte 0x8b\n\t.uleb128 2\n" /* offset r11 */ - "\t.byte 0x85\n\t.uleb128 3\n" /* offset r5 */ - "\t.byte 0x84\n\t.uleb128 4\n" /* offset r4 */ - "\t.byte 0xd\n\t.uleb128 0xb\n" /* def_cfa_register r11 */ - "\t.align 2\n" - ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); -#endif - break; - default: - break; - } -} - diff --git a/src/buildvm_arm.h b/src/buildvm_arm.h deleted file mode 100644 index bccefa57..00000000 --- a/src/buildvm_arm.h +++ /dev/null @@ -1,7494 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM arm version 1.3.0 -** DO NOT EDIT! The original file is in "buildvm_arm.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -#define DASM_SECTION_CODE_OP 0 -#define DASM_SECTION_CODE_SUB 1 -#define DASM_MAXSECTION 2 -static const unsigned int build_actionlist[5784] = { -0x00010001, -0x00060014, -0xe3160000, -0x000a0000, -0x0a000000, -0x00050015, -0xe51c6004, -0xe3e01000, -0x000a0000, -0xe1a0900c, -0xe50a1004, -0xe24aa008, -0x00060016, -0xe28bb008, -0xe2160000, -0x000a0000, -0xe58db004, -0x0a000000, -0x00050017, -0x00060018, -0xe3c6c000, -0x000a0000, -0xe3500000, -0x000a0000, -0xe049c00c, -0x1a000000, -0x00050014, -0xe508c000, -0x000d8180, -0xe59d5014, -0xe3e03000, -0x000a0000, -0xe2499008, -0xe25b2008, -0xe1a05185, -0xe5073000, -0x000d8180, -0x0a000000, -0x00050002, -0x0006000b, -0xe2522008, -0xe0ca00d8, -0xe0c900f8, -0x1a000000, -0x0005000b, -0x0006000c, -0xe155000b, -0x1a000000, -0x00050006, -0x0006000d, -0xe5089000, -0x000d8180, -0x00060019, -0x00000000, -0xe59db010, -0xe3a00000, -0xe508b000, -0x000d8180, -0x0006001a, -0xe28dd01c, -0xe8bd8ff0, -0x00060010, -0xba000000, -0x00050007, -0xe5182000, -0x000d8180, -0xe3e01000, -0x000a0000, -0xe1590002, -0x2a000000, -0x00050008, -0xe5891004, -0xe28bb008, -0xe2899008, -0xea000000, -0x0005000c, -0x00060011, -0xe04b0005, -0xe3550000, -0x10499000, -0xea000000, -0x0005000d, -0x00060012, -0xe5089000, -0x000d8180, -0xe1a01005, -0xe1a00008, -0xeb000000, -0x00030000, -0xe5189000, -0x000d8180, -0xea000000, -0x0005000c, -0x0006001b, -0xe1a0d000, -0xe1a00001, -0x0006001c, -0xe59d800c, -0xe3e03000, -0x000a0000, -0xe5182000, -0x000d8180, -0xe5023000, -0x000d8180, -0xea000000, -0x0005001a, -0x0006001d, -0x00000000, -0xe3c00000, -0x000a0000, -0xe1a0d000, -0x0006001e, -0xe59d800c, -0xe3a040ff, -0xe3a0b010, -0xe1a04184, -0xe5189000, -0x000d8180, -0xe5187000, -0x000d8180, -0xe3e00000, -0x000a0000, -0xe249a008, -0xe5196004, -0xe2877000, -0x000a0000, -0xe3e01000, -0x000a0000, -0xe5090004, -0xe5071000, -0x000d8180, -0xea000000, -0x00050016, -0x0006001f, -0xe3a01000, -0x000a0000, -0xea000000, -0x00050002, -0x00060020, -0xe089b00b, -0xe04aa009, -0xe1a00008, -0xe5089000, -0x000d8180, -0xe2866004, -0xe508b000, -0x000d8180, -0xe1a021aa, -0x0006000c, -0xe58d6008, -0xeb000000, -0x00030000, -0xe5189000, -0x000d8180, -0xe518b000, -0x000d8180, -0xe5192008, -0xe04bb009, -0xe5126000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe08aa009, -0xe12fff1c, -0x00060021, -0xe92d4ff0, -0xe24dd01c, -0xe1a08000, -0xe5107000, -0x000d8180, -0x00000000, -0xe1a09001, -0xe2877000, -0x000a0000, -0xe58d800c, -0xe3a06000, -0x000a0000, -0xe58d2014, -0xe28d1000, -0x000a0000, -0xe5580000, -0x000d8180, -0xe58d2018, -0xe5081000, -0x000d8180, -0xe58d2010, -0xe3500000, -0xe58d8008, -0x0a000000, -0x00050003, -0xe1a0a009, -0xe5189000, -0x000d8180, -0xe5180000, -0x000d8180, -0xe3a040ff, -0xe5482000, -0x000d8180, -0xe040b009, -0xe5196004, -0xe1a04184, -0xe3e01000, -0x000a0000, -0xe28bb008, -0xe2160000, -0x000a0000, -0xe5071000, -0x000d8180, -0xe58db004, -0x0a000000, -0x00050017, -0xea000000, -0x00050018, -0x00060022, -0xe92d4ff0, -0xe24dd01c, -0xe3a06000, -0x000a0000, -0xe58d3018, -0xea000000, -0x00050001, -0x00060023, -0xe92d4ff0, -0xe24dd01c, -0xe3a06000, -0x000a0000, -0x0006000b, -0xe510b000, -0x000d8180, -0xe58d2014, -0xe1a08000, -0xe58d000c, -0xe1a09001, -0xe508d000, -0x000d8180, -0x00000000, -0xe5187000, -0x000d8180, -0xe58d0008, -0xe58db010, -0xe2877000, -0x000a0000, -0x0006000d, -0xe518c000, -0x000d8180, -0xe5180000, -0x000d8180, -0xe3a040ff, -0xe0866009, -0xe1a04184, -0xe046600c, -0xe3e01000, -0x000a0000, -0xe040b009, -0xe5071000, -0x000d8180, -0x00060024, -0xe14920d8, -0xe3730000, -0x000a0000, -0x1a000000, -0x00050025, -0x00060026, -0xe5096004, -0xe5126000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe08aa009, -0xe12fff1c, -0x00060027, -0xe92d4ff0, -0xe24dd01c, -0xe1a08000, -0xe510a000, -0x000d8180, -0xe58d000c, -0xe518c000, -0x000d8180, -0xe58d0008, -0xe518b000, -0x000d8180, -0xe04aa00c, -0xe508d000, -0x000d8180, -0xe3a0c000, -0xe58da014, -0xe58dc018, -0xe58db010, -0xe12fff33, -0xe5187000, -0x000d8180, -0xe1b09000, -0xe3a06000, -0x000a0000, -0xe2877000, -0x000a0000, -0x1a000000, -0x0005000d, -0xea000000, -0x00050019, -0x00060015, -0x00000000, -0xe51c2008, -0xe5190010, -0xe1a03009, -0xe1a0900c, -0x00000000, -0xe3500001, -0x00000000, -0xe513600c, -0xe5122000, -0x000d8180, -0xe3e0e000, -0x000a0000, -0xe08a100b, -0xe501e004, -0x00000000, -0x9a000000, -0x00050001, -0x00000000, -0xe5125000, -0x000d8180, -0xe12fff10, -0x00000000, -0x0006000b, -0x0a000000, -0x00050028, -0xe5192008, -0xe2433010, -0xe043b009, -0xea000000, -0x00050029, -0x00000000, -0x0006002a, -0xe516e004, -0xe2431010, -0xe1ca20d0, -0xe5089000, -0x000d8180, -0xe004baae, -0xe004a2ae, -0xe089000b, -0xe0510000, -0x11c120f0, -0x11a02000, -0x1a000000, -0x0005002b, -0xe18920fa, -0xea000000, -0x0005002c, -0x0006002d, -0xe089100c, -0xea000000, -0x00050002, -0x0006002e, -0xe2471000, -0x000a0000, -0xe3e03000, -0x000a0000, -0xe581c000, -0xe5813004, -0x0006000c, -0xe3e03000, -0x000a0000, -0xe58db000, -0xe58d3004, -0xe1a0200d, -0xea000000, -0x00050001, -0x0006002f, -0xe004caae, -0xe58db000, -0xe3e03000, -0x000a0000, -0xe089100c, -0xe58d3004, -0xe1a0200d, -0xea000000, -0x00050001, -0x00060030, -0xe089100c, -0xe089200b, -0x0006000b, -0xe5089000, -0x000d8180, -0xe1a00008, -0xe58d6008, -0xeb000000, -0x00030001, -0x00000000, -0xe5189000, -0x000d8180, -0x00000000, -0xe3500000, -0x0a000000, -0x00050003, -0xe1c020d0, -0xe5d6c000, -0xe496e004, -0xe18920fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000d, -0xe2690000, -0x000a0000, -0xe5189000, -0x000d8180, -0xe3a0b010, -0xe509600c, -0xe0806009, -0xe5192008, -0xea000000, -0x00050026, -0x00060031, -0xe089100c, -0xea000000, -0x00050002, -0x00060032, -0xe2471000, -0x000a0000, -0xe3e03000, -0x000a0000, -0xe581c000, -0xe5813004, -0x0006000c, -0xe3e03000, -0x000a0000, -0xe58db000, -0xe58d3004, -0xe1a0200d, -0xea000000, -0x00050001, -0x00060033, -0xe004caae, -0xe58db000, -0xe3e03000, -0x000a0000, -0xe089100c, -0xe58d3004, -0xe1a0200d, -0xea000000, -0x00050001, -0x00060034, -0xe089100c, -0xe089200b, -0x0006000b, -0xe5089000, -0x000d8180, -0xe1a00008, -0xe58d6008, -0xeb000000, -0x00030002, -0x00000000, -0xe5189000, -0x000d8180, -0x00000000, -0xe3500000, -0xe18920da, -0x0a000000, -0x00050003, -0xe5d6c000, -0xe1c020f0, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000d, -0xe2690000, -0x000a0000, -0xe5189000, -0x000d8180, -0xe3a0b018, -0xe1c921f0, -0xe509600c, -0xe0806009, -0xe5192008, -0xea000000, -0x00050026, -0x00060035, -0xe1a00008, -0xe2466004, -0xe1a0100a, -0xe5089000, -0x000d8180, -0xe1a0200b, -0xe58d6008, -0xe20e30ff, -0xeb000000, -0x00030003, -0x0006000d, -0x00000000, -0xe5189000, -0x000d8180, -0x00000000, -0xe3500001, -0x8a000000, -0x00050036, -0x0006000e, -0xe1d6c0b2, -0xe2866004, -0xe086c10c, -0x224c6b80, -0x0006002c, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00060037, -0xe516e004, -0xe1ca00d0, -0xe00422ae, -0xe18900f2, -0xea000000, -0x0005002c, -0x00060038, -0xe59a1004, -0xe3e00000, -0x000a0000, -0xe1500001, -0xea000000, -0x0005000e, -0x00060039, -0xe59a1004, -0xe3710000, -0x000a0000, -0xea000000, -0x0005000e, -0x0006003a, -0xe2466004, -0xe5089000, -0x000d8180, -0xe1a00008, -0xe58d6008, -0xeb000000, -0x00030004, -0xea000000, -0x0005000d, -0x0006003b, -0x00000000, -0xe2466004, -0xe5089000, -0x000d8180, -0xe1a00008, -0xe1a0100e, -0xe58d6008, -0xeb000000, -0x00030005, -0xea000000, -0x0005000d, -0x00000000, -0x0006003c, -0xe004caae, -0xe004b6ae, -0xe089200c, -0xe085300b, -0xea000000, -0x00050001, -0x0006003d, -0xe004caae, -0xe004b6ae, -0xe089300c, -0xe085200b, -0xea000000, -0x00050001, -0x0006003e, -0xe516e008, -0xe2466004, -0xe089200b, -0xe089300b, -0xea000000, -0x00050001, -0x0006003f, -0xe004caae, -0xe004b6ae, -0xe089200c, -0xe089300b, -0x0006000b, -0xe20ec0ff, -0xe089100a, -0xe5089000, -0x000d8180, -0xe1a00008, -0xe58d6008, -0xe58dc000, -0xeb000000, -0x00030006, -0x00000000, -0xe5189000, -0x000d8180, -0x00000000, -0xe3500000, -0x0a000000, -0x0005002c, -0x00060036, -0xe0401009, -0xe500600c, -0xe2816000, -0x000a0000, -0xe1a09000, -0xe3a0b010, -0xea000000, -0x00050024, -0x00060040, -0xe089100b, -0xe5089000, -0x000d8180, -0xe1a00008, -0xe58d6008, -0xeb000000, -0x00030007, -0x00000000, -0xe5189000, -0x000d8180, -0x00000000, -0xe3500000, -0x1a000000, -0x00050036, -0xe799000b, -0xea000000, -0x00050041, -0x00000000, -0xea000000, -0x00050036, -0x00000000, -0x00060025, -0xe1a00008, -0xe508c000, -0x000d8180, -0xe2491008, -0xe58d6008, -0xe089200b, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030008, -0x00000000, -0xe1a0900a, -0x00000000, -0xe5192008, -0xe28bb008, -0xe5096004, -0xe5126000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe08aa009, -0xe12fff1c, -0x00060042, -0xe1a00008, -0xe5089000, -0x000d8180, -0xe24a1008, -0xe58d6008, -0xe08a200b, -0xeb000000, -0x00030008, -0x00000000, -0xe5189000, -0x000d8180, -0x00000000, -0xe51a2008, -0xe5196004, -0xe28bb008, -0xea000000, -0x00050043, -0x00060044, -0xe1a00008, -0xe5089000, -0x000d8180, -0xe1a0100a, -0xe58d6008, -0xeb000000, -0x00030009, -0x00000000, -0xe5189000, -0x000d8180, -0x00000000, -0xe556c004, -0x00000000, -0xe516e004, -0x00000000, -0xe35c0000, -0x000a0000, -0x00000000, -0xe004a2ae, -0xe1a0b82e, -0x00000000, -0x0a000000, -0x00070000, -0x00000000, -0xea000000, -0x00070000, -0x00060045, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x8a000000, -0x00050046, -0xe5196004, -0xe14900f8, -0xe1a0c009, -0xe25ba008, -0xe28bb008, -0x0a000000, -0x00050047, -0x0006000b, -0xe1cc00d8, -0xe25aa008, -0xe0cc00f8, -0x1a000000, -0x0005000b, -0xea000000, -0x00050047, -0x00060048, -0xe5991004, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x33e01000, -0x000a0000, -0xe2613000, -0x000a0000, -0xe1a03183, -0xe18200d3, -0xea000000, -0x00050049, -0x0006004a, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x13710000, -0x000a0000, -0x1a000000, -0x00050006, -0x0006000b, -0xe510c000, -0x000d8180, -0x0006000c, -0x00000000, -0xe3e01000, -0x000a0000, -0xe517b000, -0x000d8180, -0xe35c0000, -0x0a000000, -0x00050049, -0xe51c2000, -0x000d8180, -0xe51b3000, -0x000d8180, -0xe51ce000, -0x000d8180, -0xe0022003, -0xe0822082, -0xe08ee182, -0x0006000d, -0xe14e20d0, -0x000c8100, -0xe14e00d0, -0x000c8100, -0xe51ee000, -0x000d8180, -0xe3730000, -0x000a0000, -0x0152000b, -0x0a000000, -0x00050005, -0xe35e0000, -0x1a000000, -0x0005000d, -0x0006000e, -0xe1a0000c, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006000f, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050049, -0xea000000, -0x0005000e, -0x00060010, -0xe3710000, -0x000a0000, -0x00000000, -0x21e01001, -0x33a01000, -0x000a0000, -0xe0873101, -0xe513c000, -0x000d8180, -0xea000000, -0x0005000c, -0x0006004b, -0xe1c900d0, -0xe1c920d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x0510c000, -0x000d8180, -0x03730000, -0x000a0000, -0x05503000, -0x000d8180, -0x035c0000, -0x1a000000, -0x00050046, -0xe3130000, -0x000a0000, -0xe5002000, -0x000d8180, -0x0a000000, -0x00050049, -0xe5172000, -0x000d8180, -0xe3c33000, -0x000a0000, -0xe5070000, -0x000d8180, -0xe5403000, -0x000d8180, -0xe5002000, -0x000d8180, -0xea000000, -0x00050049, -0x0006004c, -0xe1c920d0, -0xe35b0010, -0x3a000000, -0x00050046, -0xe1a01002, -0xe3730000, -0x000a0000, -0x00000000, -0x1a000000, -0x00050046, -0xe1a00008, -0xe2892008, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x0003000a, -0x00000000, -0xe1a0900a, -0x00000000, -0xe1c000d0, -0xea000000, -0x00050049, -0x0006004d, -0xe1c900d0, -0xe35b0008, -0x1a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x9a000000, -0x00050049, -0xea000000, -0x00050046, -0x0006004e, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x0a000000, -0x00050049, -0xe5173000, -0x000d8180, -0xe5089000, -0x000d8180, -0xe3710000, -0x000a0000, -0x93530000, -0xe58d6008, -0x8a000000, -0x00050046, -0xe5170000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe1500001, -0xab000000, -0x0005004f, -0xe1a00008, -0xe1a01009, -0xeb000000, -0x0003000b, -0xe5189000, -0x000d8180, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x00060050, -0x00000000, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3e03000, -0x000a0000, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050046, -0xe18920fb, -0xe5196004, -0xe1a01000, -0xe5089000, -0x000d8180, -0xe1a00008, -0xe5089000, -0x000d8180, -0xe2892008, -0xe58d6008, -0xeb000000, -0x0003000c, -0x00000000, -0xe5189000, -0x000d8180, -0x00000000, -0xe3500000, -0x03e01000, -0x000a0000, -0x0a000000, -0x00050049, -0xe1c900d8, -0xe1c921d0, -0xe3a0b000, -0x000a0000, -0xe14900f8, -0xe1c920f0, -0xea000000, -0x00050047, -0x00060051, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050046, -0x00000000, -0xe510c000, -0x000d8180, -0x00000000, -0xe14220d0, -0x000c8100, -0xe5196004, -0x00000000, -0xe35c0000, -0x1a000000, -0x00050046, -0x00000000, -0xe3e01000, -0x000a0000, -0xe3a0b000, -0x000a0000, -0xe14920f8, -0xe589100c, -0xea000000, -0x00050047, -0x00060052, -0xe1c900d0, -0xe1c920d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x03730000, -0x000a0000, -0x1a000000, -0x00050046, -0xe510c000, -0x000d8180, -0xe510b000, -0x000d8180, -0xe2822001, -0xe5196004, -0xe152000c, -0xe08bb182, -0xe14920f8, -0x31cb00d0, -0xe3a0b000, -0x000a0000, -0x2a000000, -0x00050002, -0x0006000b, -0xe3710000, -0x000a0000, -0x13a0b000, -0x000a0000, -0x11c900f0, -0xea000000, -0x00050047, -0x0006000c, -0xe510c000, -0x000d8180, -0xe1a01002, -0xe35c0000, -0x0a000000, -0x00050047, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x0003000d, -0x00000000, -0xe1a0900a, -0x00000000, -0xe3500000, -0x0a000000, -0x00050047, -0xe1c000d0, -0xea000000, -0x0005000b, -0x00060053, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050046, -0x00000000, -0xe510c000, -0x000d8180, -0x00000000, -0xe14220d0, -0x000c8100, -0xe5196004, -0x00000000, -0xe35c0000, -0x1a000000, -0x00050046, -0x00000000, -0xe3a00000, -0xe3e01000, -0x000a0000, -0xe3a0b000, -0x000a0000, -0xe14920f8, -0xe1c900f8, -0xea000000, -0x00050047, -0x00060054, -0xe557a000, -0x000d8180, -0xe35b0008, -0x3a000000, -0x00050046, -0xe31a0000, -0x000a0000, -0xe1a0c009, -0xe2899008, -0x03a06000, -0x000a0000, -0x13a06000, -0x000a0000, -0xe24bb008, -0xea000000, -0x00050024, -0x00060055, -0xe1c900d0, -0xe1c920d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe557a000, -0x000d8180, -0xe3730000, -0x000a0000, -0x1a000000, -0x00050046, -0xe1a0c009, -0xe1c900f8, -0xe1c920f0, -0xe31a0000, -0x000a0000, -0xe2899010, -0x03a06000, -0x000a0000, -0x13a06000, -0x000a0000, -0xe24bb010, -0xea000000, -0x00050024, -0x00060056, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x00000000, -0x1a000000, -0x00050046, -0xe5196004, -0xe5089000, -0x000d8180, -0xe5101000, -0x000d8180, -0xe550a000, -0x000d8180, -0xe510c000, -0x000d8180, -0xe081200b, -0xe081300a, -0xe58d6008, -0xe153000c, -0x0a000000, -0x00050046, -0xe5103000, -0x000d8180, -0xe510c000, -0x000d8180, -0xe35a0000, -0x000a0000, -0x91520003, -0x935c0000, -0x8a000000, -0x00050046, -0x0006000b, -0xe2422008, -0xe2899008, -0xe24bb008, -0xe5002000, -0x000d8180, -0xe5089000, -0x000d8180, -0x0006000c, -0xe18920dc, -0xe15c000b, -0x118120fc, -0xe28cc008, -0x1a000000, -0x0005000c, -0xe3a02000, -0xe1a0a000, -0xe3a03000, -0xeb000000, -0x00050021, -0x0006000e, -0xe51a2000, -0x000d8180, -0xe3e01000, -0x000a0000, -0xe51a3000, -0x000d8180, -0xe5071000, -0x000d8180, -0xe3500000, -0x000a0000, -0x00000000, -0xe5189000, -0x000d8180, -0x8a000000, -0x00050008, -0xe053b002, -0xe5180000, -0x000d8180, -0xe089100b, -0x0a000000, -0x00050006, -0xe1510000, -0xe3a0c000, -0x8a000000, -0x00050009, -0xe24b3008, -0xe50a2000, -0x000d8180, -0x0006000f, -0xe18200dc, -0xe15c0003, -0xe18900fc, -0xe28cc008, -0x1a000000, -0x0005000f, -0x00060010, -0xe3e02000, -0x000a0000, -0xe28bb010, -0x00060011, -0xe5092004, -0xe249a008, -0xe2160000, -0x000a0000, -0xe58d6008, -0xe58db004, -0x0a000000, -0x00050017, -0xea000000, -0x00050018, -0x00060012, -0xe16300d8, -0xe3e02000, -0x000a0000, -0xe3a0b000, -0x000a0000, -0xe50a3000, -0x000d8180, -0xe1c900f0, -0xea000000, -0x00050011, -0x00060013, -0xe1a00008, -0xe1a011ab, -0xeb000000, -0x00030000, -0xe3a00000, -0xea000000, -0x0005000e, -0x00060057, -0x00000000, -0xe5120000, -0x000d8180, -0xe5196004, -0xe5089000, -0x000d8180, -0xe5101000, -0x000d8180, -0xe550a000, -0x000d8180, -0xe510c000, -0x000d8180, -0xe081200b, -0xe081300a, -0xe58d6008, -0xe153000c, -0x0a000000, -0x00050046, -0xe5103000, -0x000d8180, -0xe510c000, -0x000d8180, -0xe35a0000, -0x000a0000, -0x91520003, -0x935c0000, -0x8a000000, -0x00050046, -0x0006000b, -0xe5002000, -0x000d8180, -0xe5089000, -0x000d8180, -0x0006000c, -0xe18920dc, -0xe15c000b, -0x118120fc, -0xe28cc008, -0x1a000000, -0x0005000c, -0xe3a02000, -0xe1a0a000, -0xe3a03000, -0xeb000000, -0x00050021, -0x0006000e, -0xe51a2000, -0x000d8180, -0xe3e01000, -0x000a0000, -0xe51a3000, -0x000d8180, -0xe5071000, -0x000d8180, -0xe3500000, -0x000a0000, -0x00000000, -0xe5189000, -0x000d8180, -0x8a000000, -0x00050008, -0xe053b002, -0xe5180000, -0x000d8180, -0xe089100b, -0x0a000000, -0x00050006, -0xe1510000, -0xe3a0c000, -0x8a000000, -0x00050009, -0xe24b3008, -0xe50a2000, -0x000d8180, -0x0006000f, -0xe18200dc, -0xe15c0003, -0xe18900fc, -0xe28cc008, -0x1a000000, -0x0005000f, -0x00060010, -0xe1a0a009, -0xe28bb008, -0xe2160000, -0x000a0000, -0xe58d6008, -0xe58db004, -0x0a000000, -0x00050017, -0xea000000, -0x00050018, -0x00060012, -0xe1a00008, -0xe1a0100a, -0xeb000000, -0x0003000e, -0x00060013, -0xe1a00008, -0xe1a011ab, -0xeb000000, -0x00030000, -0xe3a00000, -0xea000000, -0x0005000e, -0x00060058, -0xe5180000, -0x000d8180, -0xe089100b, -0xe5089000, -0x000d8180, -0xe3100000, -0x000a0000, -0xe5081000, -0x000d8180, -0x00000000, -0xe3a00000, -0x000a0000, -0xe3a02000, -0x0a000000, -0x00050046, -0xe5082000, -0x000d8180, -0xe5480000, -0x000d8180, -0xea000000, -0x0005001a, -0x00060059, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x0a000000, -0x00050049, -0x8a000000, -0x00050046, -0xe1a02081, -0xe292c980, -0x5a000000, -0x00050002, -0xe3e03ff8, -0xe053cacc, -0xe1a03581, -0xe1a02580, -0xe3833480, -0xe26ce020, -0xe1833aa0, -0x9a000000, -0x00050003, -0xe1822e13, -0xe1a00c33, -0xe1120fc1, -0x12800001, -0xe3510000, -0xb2600000, -0x0006000b, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006000c, -0x2a000000, -0x00050049, -0xe1822000, -0xe1120fc1, -0x03a00000, -0x13e00000, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006000d, -0x03530480, -0x03520000, -0x1a000000, -0x00050004, -0xe3510000, -0x43a00480, -0x4a000000, -0x0005000b, -0x0006000e, -0x00000000, -0xeb000000, -0x0005005a, -0xea000000, -0x00050049, -0x0006005b, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x0a000000, -0x00050049, -0x8a000000, -0x00050046, -0xe1a02081, -0xe292c980, -0x5a000000, -0x00050002, -0xe3e03ff8, -0xe053cacc, -0xe1a03581, -0xe1a02580, -0xe3833480, -0xe26ce020, -0xe1833aa0, -0x9a000000, -0x00050003, -0xe1822e13, -0xe1a00c33, -0xe1d22fc1, -0x12900001, -0x614f00d0, -0x00051809, -0x6a000000, -0x00050049, -0xe3510000, -0xb2600000, -0x0006000b, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006000c, -0x2a000000, -0x00050049, -0xe1822000, -0xe1d22fc1, -0x03a00000, -0x13a00001, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006000d, -0x03530480, -0x1a000000, -0x00050004, -0xe3510000, -0x43a00480, -0x4a000000, -0x0005000b, -0x0006000e, -0x00000000, -0xeb000000, -0x0005005c, -0xea000000, -0x00050049, -0x00040007, -0x00060013, -0x00020000, -0x00000000, -0x41e00000, -0x0006005d, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x8a000000, -0x00050046, -0x13c11480, -0x1a000000, -0x00050049, -0xe3500000, -0xb2700000, -0x614f00d0, -0x00051813, -0x00060049, -0xe5196004, -0xe14900f8, -0x0006005e, -0xe3a0b000, -0x000a0000, -0x00060047, -0xe2160000, -0x000a0000, -0x0516e004, -0xe58db004, -0xe249a008, -0x1a000000, -0x00050018, -0xe004caae, -0x0006000f, -0xe15c000b, -0x8a000000, -0x00050006, -0xe00402ae, -0xe5d6c000, -0xe496e004, -0xe04a9000, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00060010, -0xe08a100b, -0xe3e00000, -0x000a0000, -0xe28bb008, -0xe5010004, -0xea000000, -0x0005000f, -0x0006005f, -0x00000000, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x0003000f, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060060, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030010, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060061, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030011, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060062, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030012, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060063, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030013, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060064, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030014, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060065, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030015, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060066, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030016, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060067, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030017, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060068, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030018, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060069, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030019, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x0006006a, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x0003001a, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x0006006b, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x0003001b, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x0006006c, -0xe1c900d0, -0xe1c920d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x0003001c, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x0006006d, -0xe1c900d0, -0xe1c920d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x0003001d, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x0006006e, -0xe1c900d0, -0xe1c920d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x2a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x0003001e, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x0006006f, -0x00060070, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0xe14220d0, -0x000c8100, -0xeb000000, -0x0003001f, -0xea000000, -0x00050049, -0x00060071, -0xe1c900d0, -0xe1c920d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0xe3730000, -0x000a0000, -0x1a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030020, -0x00000000, -0xe1a0900a, -0x00000000, -0xea000000, -0x00050049, -0x00060072, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0xe1a0200d, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030021, -0x00000000, -0xe1a0900a, -0x00000000, -0xe59d2000, -0xe3e03000, -0x000a0000, -0xe5196004, -0xe14900f8, -0xe3a0b000, -0x000a0000, -0xe1c920f0, -0xea000000, -0x00050047, -0x00060073, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050046, -0xe2492008, -0xe5196004, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030022, -0x00000000, -0xe1a0900a, -0x00000000, -0xe3a0b000, -0x000a0000, -0xe1c900f0, -0xea000000, -0x00050047, -0x00060074, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0xe3a0a008, -0x1a000000, -0x00050004, -0x0006000b, -0xe18920da, -0xe15a000b, -0x2a000000, -0x00050049, -0xe3730000, -0x000a0000, -0x1a000000, -0x00050003, -0xe1500002, -0xe28aa008, -0xc1a00002, -0xea000000, -0x0005000b, -0x0006000d, -0x8a000000, -0x00050046, -0xeb000000, -0x00030023, -0xe18920da, -0xea000000, -0x00050006, -0x0006000e, -0x8a000000, -0x00050046, -0x0006000f, -0xe18920da, -0xe15a000b, -0x2a000000, -0x00050049, -0xe3730000, -0x000a0000, -0x2a000000, -0x00050007, -0x00060010, -0x00000000, -0xeb000000, -0x00030024, -0xe28aa008, -0x81a00002, -0x81a01003, -0xea000000, -0x0005000f, -0x00060011, -0x8a000000, -0x00050046, -0xe1cd00f0, -0xe1a00002, -0xeb000000, -0x00030023, -0xe1cd20d0, -0xea000000, -0x00050010, -0x00060075, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0xe3a0a008, -0x1a000000, -0x00050004, -0x0006000b, -0xe18920da, -0xe15a000b, -0x2a000000, -0x00050049, -0xe3730000, -0x000a0000, -0x1a000000, -0x00050003, -0xe1500002, -0xe28aa008, -0xb1a00002, -0xea000000, -0x0005000b, -0x0006000d, -0x8a000000, -0x00050046, -0xeb000000, -0x00030023, -0xe18920da, -0xea000000, -0x00050006, -0x0006000e, -0x8a000000, -0x00050046, -0x0006000f, -0x00000000, -0xe18920da, -0xe15a000b, -0x2a000000, -0x00050049, -0xe3730000, -0x000a0000, -0x2a000000, -0x00050007, -0x00060010, -0xeb000000, -0x00030024, -0xe28aa008, -0x31a00002, -0x31a01003, -0xea000000, -0x0005000f, -0x00060011, -0x8a000000, -0x00050046, -0xe1cd00f0, -0xe1a00002, -0xeb000000, -0x00030023, -0xe1cd20d0, -0xea000000, -0x00050010, -0x00060076, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050046, -0xe5100000, -0x000d8180, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x00060077, -0xe1c900d0, -0xe5196004, -0xe35b0008, -0x03710000, -0x000a0000, -0x1a000000, -0x00050046, -0xe5102000, -0x000d8180, -0xe5500000, -0x000d8180, -0x00000000, -0xe3e01000, -0x000a0000, -0xe3520000, -0x03a0b000, -0x000a0000, -0x13a0b000, -0x000a0000, -0xe14900f8, -0xea000000, -0x00050047, -0x00060078, -0xe5170000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe1500001, -0xab000000, -0x0005004f, -0xe1c900d0, -0xe5196004, -0xe35b0008, -0x03710000, -0x000a0000, -0x03d030ff, -0xe3a02001, -0x1a000000, -0x00050046, -0xe58d0000, -0xe1a0100d, -0x00060079, -0xe5089000, -0x000d8180, -0xe1a00008, -0xe58d6008, -0xeb000000, -0x00030025, -0xe5189000, -0x000d8180, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006007a, -0xe5170000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe1500001, -0xab000000, -0x0005004f, -0xe1c900d0, -0xe1c921d0, -0xe35b0010, -0xe3e0c000, -0x0a000000, -0x00050001, -0x3a000000, -0x00050046, -0x00000000, -0xe3730000, -0x000a0000, -0xe1a0c002, -0x1a000000, -0x00050046, -0x0006000b, -0xe1c920d8, -0xe3710000, -0x000a0000, -0x05101000, -0x000d8180, -0x03730000, -0x000a0000, -0x1a000000, -0x00050046, -0xe2813001, -0xe3520000, -0xb0822003, -0xe3520001, -0xb3a02001, -0xe35c0000, -0xb08cc003, -0xe1cccfcc, -0xe15c0001, -0xe2800000, -0x000a0000, -0xc1a0c001, -0xe0801002, -0xe05c2002, -0xe2822001, -0xaa000000, -0x00050079, -0x0006007b, -0xe2470000, -0x000a0000, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006007c, -0xe5170000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe1500001, -0xab000000, -0x0005004f, -0xe1c900d0, -0xe1c920d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x03730000, -0x000a0000, -0x1a000000, -0x00050046, -0xe2523001, -0xe5101000, -0x000d8180, -0x00000000, -0xba000000, -0x0005007b, -0xe3510001, -0x3a000000, -0x0005007b, -0x1a000000, -0x00050046, -0xe517c000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe5100000, -0x000d8180, -0xe15c0002, -0x3a000000, -0x00050046, -0x0006000b, -0xe7c10003, -0xe2533001, -0xaa000000, -0x0005000b, -0xea000000, -0x00050079, -0x0006007d, -0xe5170000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe1500001, -0xab000000, -0x0005004f, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050046, -0xe5102000, -0x000d8180, -0xe517c000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe1a03002, -0xe2800000, -0x000a0000, -0xe15c0002, -0x3a000000, -0x00050046, -0x0006000b, -0x00000000, -0xe4d0c001, -0xe2533001, -0xba000000, -0x00050079, -0xe7c1c003, -0xea000000, -0x0005000b, -0x0006007e, -0xe5170000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe1500001, -0xab000000, -0x0005004f, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050046, -0xe5102000, -0x000d8180, -0xe517c000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe3a03000, -0xe2800000, -0x000a0000, -0xe15c0002, -0x3a000000, -0x00050046, -0x0006000b, -0xe7d0c003, -0xe1530002, -0x2a000000, -0x00050079, -0xe24cb041, -0xe35b001a, -0x322cc020, -0xe7c1c003, -0xe2833001, -0xea000000, -0x0005000b, -0x0006007f, -0xe5170000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe1500001, -0xab000000, -0x0005004f, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0x00000000, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050046, -0xe5102000, -0x000d8180, -0xe517c000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe3a03000, -0xe2800000, -0x000a0000, -0xe15c0002, -0x3a000000, -0x00050046, -0x0006000b, -0xe7d0c003, -0xe1530002, -0x2a000000, -0x00050079, -0xe24cb061, -0xe35b001a, -0x322cc020, -0xe7c1c003, -0xe2833001, -0xea000000, -0x0005000b, -0x00060080, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050046, -0x00000000, -0xe1a0a009, -0x00000000, -0xeb000000, -0x00030026, -0x00000000, -0xe1a0900a, -0x00000000, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x00060081, -0x8a000000, -0x00050046, -0x00060082, -0xe1a0c081, -0xe29cc980, -0x53a00000, -0x512fff1e, -0xe3e03ff8, -0xe053cacc, -0x4a000000, -0x00050001, -0xe1a03581, -0xe3833480, -0xe1833aa0, -0xe3510000, -0xe1a00c33, -0xb2600000, -0xe12fff1e, -0x0006000b, -0xe28cc015, -0xe1a03c30, -0xe26cc014, -0xe1a00601, -0xe3510000, -0xe1830c10, -0xb2600000, -0xe12fff1e, -0x00060083, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x00060084, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe1a02000, -0xe3a0a008, -0x0006000b, -0xe18900da, -0xe15a000b, -0xe28aa008, -0xaa000000, -0x00050002, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe0022000, -0xea000000, -0x0005000b, -0x00060085, -0x00000000, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe1a02000, -0xe3a0a008, -0x0006000b, -0xe18900da, -0xe15a000b, -0xe28aa008, -0xaa000000, -0x00050002, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe1822000, -0xea000000, -0x0005000b, -0x00060086, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe1a02000, -0xe3a0a008, -0x0006000b, -0xe18900da, -0xe15a000b, -0xe28aa008, -0xaa000000, -0x00050002, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe0222000, -0xea000000, -0x0005000b, -0x0006000c, -0xe3e03000, -0x000a0000, -0xe5196004, -0xe14920f8, -0xea000000, -0x0005005e, -0x00060087, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0x00000000, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe0202860, -0xe3c228ff, -0xe1a00460, -0xe3e01000, -0x000a0000, -0xe0200422, -0xea000000, -0x00050049, -0x00060088, -0xe1c900d0, -0xe35b0008, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe1e00000, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x00060089, -0xe1c900d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe200a01f, -0xe1c900d0, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe1a00a10, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006008a, -0xe1c900d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0x00000000, -0xe200a01f, -0xe1c900d0, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe1a00a30, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006008b, -0xe1c900d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe200a01f, -0xe1c900d0, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe1a00a50, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006008c, -0xe1c900d8, -0xe35b0010, -0x3a000000, -0x00050046, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe260a000, -0xe1c900d0, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe1a00a70, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x0006008d, -0xe1c900d8, -0xe35b0010, -0x3a000000, -0x00050046, -0x00000000, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe200a01f, -0xe1c900d0, -0xe3710000, -0x000a0000, -0x1b000000, -0x00050081, -0xe1a00a70, -0xe3e01000, -0x000a0000, -0xea000000, -0x00050049, -0x00060046, -0xe5192008, -0xe5181000, -0x000d8180, -0xe089000b, -0xe5196004, -0xe5080000, -0x000d8180, -0xe5122000, -0x000d8180, -0xe5089000, -0x000d8180, -0xe2800000, -0x000a0000, -0xe58d6008, -0xe1500001, -0xe1a00008, -0x8a000000, -0x00050005, -0xe12fff32, -0xe5189000, -0x000d8180, -0xe3500000, -0xe1a0b180, -0xe249a008, -0xca000000, -0x00050047, -0x0006000b, -0xe5180000, -0x000d8180, -0xe5192008, -0xe040b009, -0x1a000000, -0x00050029, -0xe5126000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe08aa009, -0xe12fff1c, -0x00060029, -0xe2160000, -0x000a0000, -0xe3c61000, -0x000a0000, -0x00000000, -0x0516e004, -0x00020000, -0x000412ae, -0x02811008, -0xe049c001, -0xea000000, -0x00050024, -0x0006000f, -0xe3a01000, -0x000a0000, -0xeb000000, -0x00030000, -0xe5189000, -0x000d8180, -0xe1500000, -0xea000000, -0x0005000b, -0x0006004f, -0xe1a0a00e, -0xe5089000, -0x000d8180, -0xe089100b, -0xe58d6008, -0xe5081000, -0x000d8180, -0xe1a00008, -0xeb000000, -0x00030027, -0xe5189000, -0x000d8180, -0xe1a0e00a, -0xe5192008, -0xe12fff1e, -0x0006008e, -0x00000000, -0xe5570000, -0x000d8180, -0xe3100000, -0x000a0000, -0x1a000000, -0x00050005, -0xe5171000, -0x000d8180, -0xe3100000, -0x000a0000, -0x1a000000, -0x00050001, -0xe2411001, -0xe3100000, -0x000a0000, -0x15071000, -0x000d8180, -0xea000000, -0x00050001, -0x00000000, -0x0006008f, -0xe5570000, -0x000d8180, -0xe3100000, -0x000a0000, -0x0a000000, -0x00050001, -0x0006000f, -0xe20ec0ff, -0xe087c10c, -0xe51cf000, -0x000d8180, -0x00060090, -0xe5570000, -0x000d8180, -0xe5171000, -0x000d8180, -0xe3100000, -0x000a0000, -0x1a000000, -0x0005000f, -0xe3100000, -0x000a0000, -0x0a000000, -0x0005000f, -0xe2511001, -0xe5071000, -0x000d8180, -0x0a000000, -0x00050001, -0xe3100000, -0x000a0000, -0x0a000000, -0x0005000f, -0x0006000b, -0xe1a00008, -0xe5089000, -0x000d8180, -0xe1a01006, -0xeb000000, -0x00030028, -0x0006000d, -0xe5189000, -0x000d8180, -0x0006000e, -0x00000000, -0xe556c004, -0xe516e004, -0xe087c10c, -0xe51cc000, -0x000d8180, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00060091, -0xe5130018, -0xe2866004, -0xe58d0004, -0xea000000, -0x0005000e, -0x00060092, -0x00000000, -0xe5192008, -0xe2470000, -0x000a0000, -0xe58d6008, -0xe5122000, -0x000d8180, -0xe1a01006, -0xe5078000, -0x000d8180, -0xe5522000, -0x000d8180, -0xe5089000, -0x000d8180, -0xe0892182, -0xe5082000, -0x000d8180, -0xeb000000, -0x00030029, -0xea000000, -0x0005000d, -0x00000000, -0x00060093, -0xe1a01006, -0x00000000, -0xea000000, -0x00050001, -0x00000000, -0x00060094, -0x00000000, -0xe3861001, -0x0006000b, -0x00000000, -0xe089300b, -0xe58d6008, -0xe1a00008, -0xe5089000, -0x000d8180, -0xe04aa009, -0xe5083000, -0x000d8180, -0xeb000000, -0x0003002a, -0xe5189000, -0x000d8180, -0xe5183000, -0x000d8180, -0xe3a01000, -0xe089a00a, -0xe043b009, -0xe58d1008, -0xe5192008, -0xe516e004, -0xe12fff10, -0x00060095, -0x00000000, -0xe24dd00c, -0xe92d1fff, -0xe59d0040, -0xe59e7000, -0xe28d2040, -0xe3e03000, -0x000a0000, -0xe58d2034, -0xe5073000, -0x000d8180, -0xe5301004, -0xe58d0038, -0xe58d003c, -0xe1a01401, -0xe0800341, -0xe59e1004, -0xe040000e, -0xe5178000, -0x000d8180, -0xe0810120, -0xe5179000, -0x000d8180, -0xe5070000, -0x000d8180, -0xe3a03000, -0xe5078000, -0x000d8180, -0xe5089000, -0x000d8180, -0xe5073000, -0x000d8180, -0xe2470000, -0x000a0000, -0xe1a0100d, -0xeb000000, -0x0003002b, -0xe5181000, -0x000d8180, -0xe5189000, -0x000d8180, -0xe3c11000, -0x000a0000, -0xe1a0d001, -0xe59d6008, -0xe58d800c, -0xea000000, -0x00050001, -0x00000000, -0x00060096, -0x00000000, -0xe59d800c, -0x0006000b, -0xe3500000, -0xba000000, -0x00050003, -0xe1a0b180, -0xe5191008, -0xe58db004, -0xe3a02000, -0xe5111000, -0x000d8180, -0xe5072000, -0x000d8180, -0xe3e03000, -0x000a0000, -0xe5115000, -0x000d8180, -0xe5d6c000, -0xe3a040ff, -0xe496e004, -0xe1a04184, -0xe5073000, -0x000d8180, -0xe35c0000, -0x000a0000, -0xe797c10c, -0xe004a2ae, -0x31a0b82e, -0x224bb008, -0x208aa009, -0xe12fff1c, -0x0006000d, -0xe2601000, -0xe1a00008, -0xeb000000, -0x0003002c, -0x00000000, -0x00060013, -0x3ff00000, -0x0006005a, -0xe1a02081, -0xe292c980, -0x5a000000, -0x00050002, -0xe3e03ff3, -0xe053cacc, -0x312fff1e, -0xe3e03001, -0xe1c02c13, -0xe0000c13, -0xe25cc020, -0x51c13c13, -0x51822003, -0x53e03001, -0x50011c13, -0xe1120fc1, -0x012fff1e, -0xe3e03001, -0xe35c0000, -0x51a02c13, -0x43e02000, -0xe28cc020, -0xe0500c13, -0xe0c11002, -0xe12fff1e, -0x0006000c, -0x212fff1e, -0xe1822000, -0xe1120fc1, -0xe3a00000, -0xe2011480, -0x151f3000, -0x00050813, -0x11811003, -0xe12fff1e, -0x0006005c, -0xe1a02081, -0xe292c980, -0x5a000000, -0x00050002, -0xe3e03ff3, -0xe053cacc, -0x312fff1e, -0xe3e03001, -0xe1c02c13, -0xe0000c13, -0xe25cc020, -0x51c13c13, -0x51822003, -0x53e03001, -0x50011c13, -0xe1d22fc1, -0x012fff1e, -0xe3e03001, -0xe35c0000, -0x51a02c13, -0x43e02000, -0xe28cc020, -0xe0500c13, -0xe0c11002, -0xe12fff1e, -0x0006000c, -0x212fff1e, -0xe1822000, -0xe1d22fc1, -0xe3a00000, -0xe2011480, -0x151f3000, -0x00050813, -0x11811003, -0xe12fff1e, -0x00060097, -0x00000000, -0xe1a02081, -0xe292c980, -0x52011480, -0x53a00000, -0x512fff1e, -0xe3e03ff3, -0xe053cacc, -0x312fff1e, -0xe3e03001, -0xe0000c13, -0xe25cc020, -0x50011c13, -0xe12fff1e, -0x00000000, -0x00060098, -0xe92d401f, -0xeb000000, -0x0003002d, -0xeb000000, -0x0005005a, -0xe1cd20d8, -0xeb000000, -0x0003001f, -0xe1cd20d0, -0xe2211480, -0xeb000000, -0x0003002e, -0xe28dd014, -0xe8bd8000, -0x00060099, -0xe210c480, -0x42600000, -0xe02cc0c1, -0xe3510000, -0x42611000, -0xe2513001, -0x11500001, -0x03a00000, -0x81110003, -0x00020000, -0x00000003, -0x9a000000, -0x00050001, -0xe16f2f10, -0xe16f3f11, -0xe0433002, -0xe273201f, -0x108ff182, -0xe1a00000, -0x00000000, -0xe1500001, -0x000900a7, -0x20400001, -0x000900a7, -0x00000000, -0x0006000b, -0xe3500000, -0x135c0000, -0x40400001, -0xe030108c, -0x42600000, -0xe12fff1e, -0x0006009a, -0xe59dc000, -0xe35c0001, -0x3a000000, -0x0003002e, -0x0a000000, -0x0003002f, -0xe35c0003, -0x3a000000, -0x0003001f, -0x0a000000, -0x0003002d, -0xe35c0005, -0x3a000000, -0x00050098, -0x0a000000, -0x0003001c, -0xe35c0007, -0x32211480, -0x03c11480, -0x912fff1e, -0x00000000, -0xe35c0009, -0x3a000000, -0x0003001d, -0x0a000000, -0x00050009, -0xe35c000b, -0x8a000000, -0x00050009, -0xe92d4010, -0x0a000000, -0x00050001, -0xeb000000, -0x00030024, -0x81a00002, -0x81a01003, -0xe8bd8010, -0x00060013, -0xe7f001f0, -0x0006000b, -0xeb000000, -0x00030024, -0x31a00002, -0x31a01003, -0xe8bd8010, -0x00000000, -0xe7f001f0, -0x00000000, -0x0006009b, -0x00000000, -0xe51c6000, -0x000d8180, -0xe28c7000, -0x000a0000, -0xe14600f0, -0x000c8100, -0xe14620f0, -0x000c8100, -0xe59d3000, -0xe28d2000, -0x000a0000, -0xe1a00006, -0xe1a031a3, -0xe5062000, -0x000d8180, -0xe1a0100d, -0xe5063000, -0x000d8180, -0xe58d6008, -0xeb000000, -0x00030030, -0xe5109000, -0x000d8180, -0xe3e01000, -0x000a0000, -0xe510b000, -0x000d8180, -0xe3a040ff, -0xe5192008, -0xe1a08000, -0xe04bb009, -0xe1a04184, -0xe5071000, -0x000d8180, -0xe5126000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe08aa009, -0xe12fff1c, -0x00000000, -0x00060028, -0x00000000, -0xe5176000, -0x000d8180, -0xe5089000, -0x000d8180, -0xe5083000, -0x000d8180, -0xe5068000, -0x000d8180, -0xe1a00006, -0xe1a0100a, -0xeb000000, -0x00030031, -0xe14600d0, -0x000c8100, -0xea000000, -0x0005001a, -0x00000000, -0x0006009c, -0x00000000, -0xe92d4830, -0xe1a04000, -0xe5100000, -0x000d8180, -0xe5541000, -0x000d8180, -0xe2842000, -0x000a0000, -0xe1a0b00d, -0xe04dd000, -0xe2511001, -0xe514c000, -0x000d8180, -0x4a000000, -0x00050002, -0x0006000b, -0xe7923101, -0xe78d3101, -0xe2511001, -0x5a000000, -0x0005000b, -0x0006000c, -0xe5140000, -0x000d8180, -0xe5141000, -0x000d8180, -0xe5142000, -0x000d8180, -0xe5143000, -0x000d8180, -0xe12fff3c, -0xe1a0d00b, -0xe5040000, -0x000d8180, -0xe5041000, -0x000d8180, -0xe8bd8830, -0x00000000, -0x00080000, -0x00000000, -0xe1a0b18b, -0xe1aa00d9, -0xe1d6c0b2, -0xe1ab20d9, -0xe2866004, -0xe086c10c, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050003, -0xe3730000, -0x000a0000, -0x1a000000, -0x00050004, -0xe1500002, -0x00000000, -0xb24c6b80, -0x00000000, -0xa24c6b80, -0x00000000, -0xd24c6b80, -0x00000000, -0xc24c6b80, -0x00000000, -0x0006000b, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000d, -0x8a000000, -0x00050035, -0xe3730000, -0x000a0000, -0x31a0a00c, -0x3a000000, -0x00050005, -0xe1a00002, -0xe1a0b00a, -0xe1a0a00c, -0xeb000000, -0x00030023, -0xe1a02000, -0xe1a03001, -0xe1cb00d0, -0xea000000, -0x00050005, -0x0006000e, -0x8a000000, -0x00050035, -0xe1a0a00c, -0xeb000000, -0x00030023, -0xe1cb20d0, -0x0006000f, -0xeb000000, -0x00030024, -0x00000000, -0x324a6b80, -0x00000000, -0x224a6b80, -0x00000000, -0x924a6b80, -0x00000000, -0x824a6b80, -0x00000000, -0xea000000, -0x0005000b, -0x00000000, -0xe1a0b18b, -0xe1aa00d9, -0xe1d6c0b2, -0xe1ab20d9, -0xe2866004, -0xe086c10c, -0xe3710000, -0x000a0000, -0x93730000, -0x000a0000, -0x00000000, -0x9a000000, -0x0005009d, -0x00000000, -0x9a000000, -0x0005009e, -0x00000000, -0xe3710000, -0x000a0000, -0x13730000, -0x000a0000, -0x0a000000, -0x0005003b, -0x00000000, -0xe1510003, -0x1a000000, -0x00050002, -0xe3710000, -0x000a0000, -0x2a000000, -0x00050001, -0xe1500002, -0x00000000, -0x1a000000, -0x00050003, -0x0006000b, -0xe24c6b80, -0x0006000c, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000d, -0xe3710000, -0x000a0000, -0x8a000000, -0x0005000c, -0x00000000, -0x0a000000, -0x00050001, -0xe3710000, -0x000a0000, -0x8a000000, -0x00050002, -0x00000000, -0xe510a000, -0x000d8180, -0xe35a0000, -0x00000000, -0x0a000000, -0x0005000c, -0x00000000, -0x0a000000, -0x00050002, -0x00000000, -0xe55aa000, -0x000d8180, -0xe3a03000, -0x000a0000, -0xe1a01000, -0xe31a0000, -0x000a0000, -0x0a000000, -0x0005003a, -0x00000000, -0xea000000, -0x0005000c, -0x00000000, -0x0006000c, -0xe24c6b80, -0x0006000b, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1e0b00b, -0xe18900da, -0xe1d6c0b2, -0xe795210b, -0xe2866004, -0xe086c10c, -0xe3710000, -0x000a0000, -0x00000000, -0x1a000000, -0x00050007, -0xe1500002, -0x00000000, -0x01500002, -0x00000000, -0x024c6b80, -0x0006000b, -0x00000000, -0x0006000b, -0x124c6b80, -0x00000000, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0x00060011, -0xe3710000, -0x000a0000, -0x1a000000, -0x0005000b, -0xea000000, -0x0005003b, -0x00000000, -0xe1a0b18b, -0xe1aa00d9, -0xe1d6c0b2, -0xe1ab20d5, -0xe2866004, -0xe086c10c, -0x00000000, -0x0006009d, -0x00000000, -0x0006009e, -0x00000000, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050003, -0xe3730000, -0x000a0000, -0x1a000000, -0x00050004, -0xe1500002, -0x00000000, -0x024c6b80, -0x0006000b, -0x00000000, -0x0006000b, -0x124c6b80, -0x00000000, -0x0006000c, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000d, -0x00000000, -0x8a000000, -0x00050007, -0x00000000, -0x824c6b80, -0x00000000, -0x8a000000, -0x0005000c, -0x00000000, -0xe3730000, -0x000a0000, -0x31a0a00c, -0x3a000000, -0x00050005, -0xe1a00002, -0xe1a0b00a, -0x0006000e, -0xe1a0a00c, -0xeb000000, -0x00030023, -0xe1cb20d0, -0x0006000f, -0xeb000000, -0x00030032, -0x00000000, -0x024a6b80, -0x00000000, -0x124a6b80, -0x00000000, -0xea000000, -0x0005000c, -0x00000000, -0x00060011, -0xe3710000, -0x000a0000, -0x1a000000, -0x0005000b, -0xea000000, -0x0005003b, -0x00000000, -0xe18900da, -0xe1d6c0b2, -0xe2866004, -0xe1e0b00b, -0xe086c10c, -0x00000000, -0xe3710000, -0x000a0000, -0x0a000000, -0x0005003b, -0x00000000, -0xe151000b, -0x00000000, -0x024c6b80, -0x00000000, -0x124c6b80, -0x00000000, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe089b18b, -0xe1d6c0b2, -0xe1cb00d0, -0xe2866004, -0xe086c10c, -0xe3710000, -0x000a0000, -0x00000000, -0x924c6b80, -0x00000000, -0x918900fa, -0x00000000, -0x824c6b80, -0x00000000, -0x818900fa, -0x00000000, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1a0b18b, -0xe5d6c000, -0xe18900db, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe089b18b, -0xe5d6c000, -0xe59b0004, -0xe089a00a, -0xe496e004, -0xe3700000, -0x000a0000, -0x93e01000, -0x000a0000, -0x83e01000, -0x000a0000, -0xe58a1004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1a0b18b, -0xe18900db, -0xe5d6c000, -0xe496e004, -0xe3710000, -0x000a0000, -0x8a000000, -0x0005003e, -0x12211480, -0x1a000000, -0x00050005, -0x02700000, -0x614f00d0, -0x00051809, -0x0006000f, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00040007, -0x00060013, -0x00020000, -0x00000000, -0x41e00000, -0x00000000, -0xe1a0b18b, -0xe18900db, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050002, -0xe5100000, -0x000d8180, -0x0006000b, -0xe3e01000, -0x000a0000, -0xe5d6c000, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000c, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050040, -0x00000000, -0xe5102000, -0x000d8180, -0xe3520000, -0x1a000000, -0x00050009, -0x0006000d, -0x00000000, -0x00060041, -0x00000000, -0xe1a0b009, -0x00000000, -0xeb000000, -0x00030026, -0x00000000, -0xe1a0900b, -0x00000000, -0xea000000, -0x0005000b, -0x00000000, -0x00060013, -0xe5523000, -0x000d8180, -0xe3130000, -0x000a0000, -0x1a000000, -0x0005000d, -0xea000000, -0x00050040, -0x00000000, -0xe004caae, -0xe004b6ae, -0x00000000, -0xe18900dc, -0xe18520db, -0x00000000, -0xe18920dc, -0xe18500db, -0x00000000, -0xe18900dc, -0xe18920db, -0x00000000, -0xe5d6c000, -0x00000000, -0xe3730000, -0x000a0000, -0x03710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x03730000, -0x000a0000, -0x00000000, -0x1a000000, -0x00050005, -0xe0900002, -0x00000000, -0x6a000000, -0x0005003c, -0x00000000, -0x6a000000, -0x0005003d, -0x00000000, -0x6a000000, -0x0005003f, -0x00000000, -0x0006000e, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003c, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003d, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003f, -0x00000000, -0xeb000000, -0x0003002e, -0xe5d6c000, -0xea000000, -0x0005000e, -0x00000000, -0xe004caae, -0xe004b6ae, -0x00000000, -0xe18900dc, -0xe18520db, -0x00000000, -0xe18920dc, -0xe18500db, -0x00000000, -0xe18900dc, -0xe18920db, -0x00000000, -0xe5d6c000, -0x00000000, -0xe3730000, -0x000a0000, -0x03710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x03730000, -0x000a0000, -0x00000000, -0x1a000000, -0x00050005, -0xe0500002, -0x00000000, -0x6a000000, -0x0005003c, -0x00000000, -0x6a000000, -0x0005003d, -0x00000000, -0x6a000000, -0x0005003f, -0x00000000, -0x0006000e, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003c, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003d, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003f, -0x00000000, -0xeb000000, -0x0003002f, -0xe5d6c000, -0xea000000, -0x0005000e, -0x00000000, -0xe004caae, -0xe004b6ae, -0x00000000, -0xe18900dc, -0xe18520db, -0x00000000, -0xe18920dc, -0xe18500db, -0x00000000, -0xe18900dc, -0xe18920db, -0x00000000, -0xe5d6c000, -0x00000000, -0xe3730000, -0x000a0000, -0x03710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x03730000, -0x000a0000, -0x00000000, -0x1a000000, -0x00050005, -0xe0cb0092, -0xe15b0fc0, -0x00000000, -0x1a000000, -0x0005003c, -0x00000000, -0x1a000000, -0x0005003d, -0x00000000, -0x1a000000, -0x0005003f, -0x00000000, -0x0006000e, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003c, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003d, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003f, -0x00000000, -0xeb000000, -0x0003001f, -0xe5d6c000, -0xea000000, -0x0005000e, -0x00000000, -0xe004caae, -0xe004b6ae, -0x00000000, -0xe18900dc, -0xe18520db, -0x00000000, -0xe18920dc, -0xe18500db, -0x00000000, -0xe18900dc, -0xe18920db, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003c, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003d, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003f, -0x00000000, -0xeb000000, -0x0003002d, -0xe5d6c000, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe004caae, -0xe004b6ae, -0x00000000, -0xe18900dc, -0xe18520db, -0x00000000, -0xe18920dc, -0xe18500db, -0x00000000, -0xe18900dc, -0xe18920db, -0x00000000, -0xe3730000, -0x000a0000, -0x03710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x03730000, -0x000a0000, -0x00000000, -0x1a000000, -0x00050005, -0xe1b01002, -0x00000000, -0x0a000000, -0x0005003c, -0x00000000, -0x0a000000, -0x0005003d, -0x00000000, -0x0a000000, -0x0005003f, -0x00000000, -0xeb000000, -0x00050099, -0xe3e01000, -0x000a0000, -0x0006000e, -0xe5d6c000, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003c, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003d, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003f, -0x00000000, -0xeb000000, -0x00050098, -0xea000000, -0x0005000e, -0x00000000, -0xe004caae, -0xe004b6ae, -0x00000000, -0xe18900dc, -0xe18520db, -0x00000000, -0xe18920dc, -0xe18500db, -0x00000000, -0xe18900dc, -0xe18920db, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003c, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003d, -0x00000000, -0xe3730000, -0x000a0000, -0x33710000, -0x000a0000, -0x00000000, -0xe3710000, -0x000a0000, -0x33730000, -0x000a0000, -0x00000000, -0x2a000000, -0x0005003f, -0x00000000, -0xe1a0b009, -0x00000000, -0xeb000000, -0x0003001c, -0x00000000, -0xe1a0900b, -0x00000000, -0xe5d6c000, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe004baae, -0xe004c6ae, -0xe04c200b, -0xe5089000, -0x000d8180, -0xe089100c, -0x0006002b, -0xe1a00008, -0xe58d6008, -0xe1a021a2, -0xeb000000, -0x00030033, -0xe5189000, -0x000d8180, -0xe3500000, -0x1a000000, -0x00050036, -0xe18920db, -0xe5d6c000, -0xe496e004, -0xe18920fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1e0b00b, -0xe5d6c000, -0xe795010b, -0xe3e01000, -0x000a0000, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1e0b00b, -0xe5d6c000, -0xe795010b, -0xe3e01000, -0x000a0000, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1a0084e, -0xe3e01000, -0x000a0000, -0xe5d6c000, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1a0b18b, -0xe5d6c000, -0xe18500db, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe089a00a, -0xe1e0b00b, -0xe5d6c000, -0xe496e004, -0xe58ab004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe089a00a, -0xe089b18b, -0xe3e00000, -0x000a0000, -0xe58a0004, -0xe28aa008, -0x0006000b, -0xe58a0004, -0xe15a000b, -0xe28aa008, -0xba000000, -0x0005000b, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe5191008, -0xe1a0b10b, -0xe28bb000, -0x000a0000, -0xe791100b, -0xe5111000, -0x000d8180, -0xe1c120d0, -0xe5d6c000, -0xe496e004, -0xe18920fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe5191008, -0xe1a0a0aa, -0xe28aa000, -0x000a0000, -0xe1a0b18b, -0xe791100a, -0xe18920db, -0xe551c000, -0x000d8180, -0xe551b000, -0x000d8180, -0xe5111000, -0x000d8180, -0xe31c0000, -0x000a0000, -0xe283c000, -0x000a0000, -0x135b0000, -0xe1c120f0, -0x1a000000, -0x00050002, -0x0006000b, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000c, -0xe37c0000, -0x000a0000, -0x8552b000, -0x000d8180, -0x9a000000, -0x0005000b, -0xe2470000, -0x000a0000, -0xe31b0000, -0x000a0000, -0x00000000, -0x0a000000, -0x0005000b, -0xe1a0b009, -0xeb000000, -0x00030034, -0xe1a0900b, -0x00000000, -0x1b000000, -0x00030034, -0x00000000, -0xea000000, -0x0005000b, -0x00000000, -0xe5191008, -0xe1a0a0aa, -0xe28aa000, -0x000a0000, -0xe1e0b00b, -0xe791100a, -0xe795210b, -0xe3e03000, -0x000a0000, -0xe551c000, -0x000d8180, -0xe5111000, -0x000d8180, -0xe551b000, -0x000d8180, -0xe31c0000, -0x000a0000, -0xe552c000, -0x000d8180, -0xe1c120f0, -0x1a000000, -0x00050002, -0x0006000b, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000c, -0xe31c0000, -0x000a0000, -0x135b0000, -0xe2470000, -0x000a0000, -0x00000000, -0x0a000000, -0x0005000b, -0xe1a0b009, -0xeb000000, -0x00030034, -0xe1a0900b, -0x00000000, -0x1b000000, -0x00030034, -0x00000000, -0xea000000, -0x0005000b, -0x00000000, -0xe5191008, -0xe1a0a0aa, -0xe28aa000, -0x000a0000, -0xe1a0b18b, -0xe791100a, -0xe18520db, -0xe5111000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe1c120f0, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe5191008, -0xe1a0a0aa, -0xe28aa000, -0x000a0000, -0xe791100a, -0xe1e0b00b, -0xe5111000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe581b004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe5182000, -0x000d8180, -0xe086b10b, -0xe5089000, -0x000d8180, -0xe3520000, -0xe24b6b80, -0x0a000000, -0x00050001, -0xe1a00008, -0xe089100a, -0xeb000000, -0x00030035, -0xe5189000, -0x000d8180, -0x0006000b, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1e0b00b, -0xe5089000, -0x000d8180, -0xe795110b, -0xe58d6008, -0xe5192008, -0xe1a00008, -0xeb000000, -0x00030036, -0xe5189000, -0x000d8180, -0xe3e01000, -0x000a0000, -0xe5d6c000, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1e0b00b, -0x00000000, -0xe5172000, -0x000d8180, -0xe5173000, -0x000d8180, -0xe5089000, -0x000d8180, -0xe58d6008, -0xe1520003, -0xe1a00008, -0x2a000000, -0x00050005, -0x0006000b, -0x00000000, -0xe1a01a8b, -0xe1a025ab, -0xe1a0bac1, -0xe1a01aa1, -0xe37b0001, -0x02811002, -0xeb000000, -0x00030037, -0x00000000, -0xe795110b, -0xeb000000, -0x00030038, -0x00000000, -0xe5189000, -0x000d8180, -0xe3e01000, -0x000a0000, -0xe5d6c000, -0xe496e004, -0xe18900fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0xeb000000, -0x00030039, -0xe1a00008, -0xea000000, -0x0005000b, -0x00000000, -0xe5191008, -0xe1e0b00b, -0xe5110000, -0x000d8180, -0xe795b10b, -0x00000000, -0xea000000, -0x0005009f, -0x00000000, -0xea000000, -0x000500a0, -0x00000000, -0xe004caae, -0xe004b6ae, -0xe18900dc, -0xe18920db, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050030, -0xe3730000, -0x000a0000, -0x05103000, -0x000d8180, -0x05101000, -0x000d8180, -0x1a000000, -0x00050009, -0xe0833182, -0xe1520001, -0x31c320d0, -0x2a000000, -0x00050030, -0xe5d6c000, -0xe3730000, -0x000a0000, -0x0a000000, -0x00050005, -0x0006000b, -0xe496e004, -0xe18920fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0xe5101000, -0x000d8180, -0xe3510000, -0x0a000000, -0x0005000b, -0xe5511000, -0x000d8180, -0xe3110000, -0x000a0000, -0x1a000000, -0x0005000b, -0xe004caae, -0xea000000, -0x00050030, -0x00060013, -0xe3730000, -0x000a0000, -0x01a0b002, -0x0a000000, -0x0005009f, -0xea000000, -0x00050030, -0x00000000, -0xe004caae, -0xe20bb0ff, -0xe18900dc, -0xe1e0b00b, -0xe795b10b, -0xe3710000, -0x000a0000, -0x1a000000, -0x0005002d, -0x0006009f, -0xe5102000, -0x000d8180, -0xe51b3000, -0x000d8180, -0xe510e000, -0x000d8180, -0xe1a0c000, -0xe0022003, -0xe0822082, -0xe08ee182, -0x0006000b, -0xe14e00d0, -0x000c8100, -0xe14e20d0, -0x000c8100, -0xe51ee000, -0x000d8180, -0xe3710000, -0x000a0000, -0x0150000b, -0x1a000000, -0x00050004, -0xe3730000, -0x000a0000, -0x0a000000, -0x00050005, -0x0006000d, -0xe5d6c000, -0xe496e004, -0xe18920fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000e, -0xe35e0000, -0x1a000000, -0x0005000b, -0x0006000f, -0xe51c0000, -0x000d8180, -0xe3a02000, -0xe3e03000, -0x000a0000, -0xe3500000, -0x0a000000, -0x0005000d, -0xe5501000, -0x000d8180, -0x00000000, -0xe3110000, -0x000a0000, -0x1a000000, -0x0005000d, -0xea000000, -0x0005002e, -0x00000000, -0xe004caae, -0xe20bb0ff, -0xe18900dc, -0xe3710000, -0x000a0000, -0x1a000000, -0x0005002f, -0xe5102000, -0x000d8180, -0xe5103000, -0x000d8180, -0xe1a0118b, -0xe15b0002, -0x318320d1, -0x2a000000, -0x0005002f, -0xe5d6c000, -0xe3730000, -0x000a0000, -0x0a000000, -0x00050005, -0x0006000b, -0xe496e004, -0xe18920fa, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0xe5101000, -0x000d8180, -0xe3510000, -0x0a000000, -0x0005000b, -0xe5511000, -0x000d8180, -0xe3110000, -0x000a0000, -0x1a000000, -0x0005000b, -0xea000000, -0x0005002f, -0x00000000, -0xe004caae, -0xe004b6ae, -0xe18900dc, -0xe18920db, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050034, -0xe3730000, -0x000a0000, -0x05101000, -0x000d8180, -0x05103000, -0x000d8180, -0x1a000000, -0x00050009, -0xe0811182, -0xe1520003, -0x3591e004, -0x2a000000, -0x00050034, -0xe5d6c000, -0xe37e0000, -0x000a0000, -0xe550e000, -0x000d8180, -0xe18920da, -0x0a000000, -0x00050005, -0x0006000b, -0xe31e0000, -0x000a0000, -0xe1c120f0, -0x1a000000, -0x00050007, -0x0006000c, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0xe510a000, -0x000d8180, -0xe35a0000, -0x0a000000, -0x0005000b, -0xe55aa000, -0x000d8180, -0xe31a0000, -0x000a0000, -0x1a000000, -0x0005000b, -0xe516e004, -0xe004caae, -0xe004a2ae, -0xea000000, -0x00050034, -0x00060011, -0x00000000, -0xe5172000, -0x000d8180, -0xe3cee000, -0x000a0000, -0xe5070000, -0x000d8180, -0xe540e000, -0x000d8180, -0xe5002000, -0x000d8180, -0xea000000, -0x0005000c, -0x00060013, -0xe3730000, -0x000a0000, -0x01a0b002, -0x0a000000, -0x000500a0, -0xea000000, -0x00050034, -0x00000000, -0xe004caae, -0xe20bb0ff, -0xe18900dc, -0xe1e0b00b, -0xe795b10b, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050031, -0x000600a0, -0xe5102000, -0x000d8180, -0xe51b3000, -0x000d8180, -0xe510e000, -0x000d8180, -0xe1a0c000, -0xe0022003, -0xe0822082, -0xe3a03000, -0xe08ee182, -0xe54c3000, -0x000d8180, -0x0006000b, -0xe14e00d0, -0x000c8100, -0xe51e3000, -0x000d8180, -0xe51e2000, -0x000d8180, -0xe3710000, -0x000a0000, -0x0150000b, -0x1a000000, -0x00050005, -0xe55c1000, -0x000d8180, -0xe3730000, -0x000a0000, -0xe18920da, -0x0a000000, -0x00050004, -0x0006000c, -0xe3110000, -0x000a0000, -0xe14e20f0, -0x000c8100, -0x1a000000, -0x00050007, -0x0006000d, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000e, -0x00000000, -0xe51c0000, -0x000d8180, -0xe3500000, -0x0a000000, -0x0005000c, -0xe5500000, -0x000d8180, -0xe3100000, -0x000a0000, -0x1a000000, -0x0005000c, -0xea000000, -0x00050032, -0x0006000f, -0xe1b0e002, -0x1a000000, -0x0005000b, -0xe51c0000, -0x000d8180, -0xe1a0200d, -0xe58d6008, -0xe3500000, -0xe5089000, -0x000d8180, -0x15501000, -0x000d8180, -0xe1a00008, -0x0a000000, -0x00050006, -0xe3110000, -0x000a0000, -0x0a000000, -0x00050032, -0x00060010, -0xe3e03000, -0x000a0000, -0xe58db000, -0xe1a0100c, -0xe58d3004, -0xeb000000, -0x0003003a, -0xe5189000, -0x000d8180, -0xe18920da, -0xe1c020f0, -0xea000000, -0x0005000d, -0x00060011, -0xe5172000, -0x000d8180, -0xe3c11000, -0x000a0000, -0x00000000, -0xe507c000, -0x000d8180, -0xe54c1000, -0x000d8180, -0xe50c2000, -0x000d8180, -0xea000000, -0x0005000d, -0x00000000, -0xe004caae, -0xe20bb0ff, -0xe18900dc, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050033, -0xe5102000, -0x000d8180, -0xe510c000, -0x000d8180, -0xe1a0118b, -0xe15b0002, -0x31a120dc, -0x2a000000, -0x00050033, -0xe5d6c000, -0xe3730000, -0x000a0000, -0xe550e000, -0x000d8180, -0xe18920da, -0x0a000000, -0x00050005, -0x0006000b, -0xe31e0000, -0x000a0000, -0xe1c120f0, -0x1a000000, -0x00050007, -0x0006000c, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0xe510a000, -0x000d8180, -0xe35a0000, -0x0a000000, -0x0005000b, -0xe55aa000, -0x000d8180, -0xe31a0000, -0x000a0000, -0x1a000000, -0x0005000b, -0xe516e004, -0xe004a2ae, -0xea000000, -0x00050033, -0x00060011, -0xe5172000, -0x000d8180, -0xe3cee000, -0x000a0000, -0x00000000, -0xe5070000, -0x000d8180, -0xe540e000, -0x000d8180, -0xe5002000, -0x000d8180, -0xea000000, -0x0005000c, -0x00000000, -0xe089a00a, -0x0006000b, -0xe59dc004, -0xe51a1008, -0xe795018b, -0xe25cc008, -0xe5113000, -0x000d8180, -0x0a000000, -0x00050004, -0xe08021ac, -0xe1520003, -0xe5113000, -0x000d8180, -0xe08ac00c, -0x8a000000, -0x00050005, -0xe083e180, -0xe5510000, -0x000d8180, -0x0006000d, -0xe0ca20d8, -0xe0ce20f8, -0xe15a000c, -0x3a000000, -0x0005000d, -0xe3100000, -0x000a0000, -0x1a000000, -0x00050007, -0x0006000e, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0xe5089000, -0x000d8180, -0xe1a00008, -0xe58d6008, -0xeb000000, -0x0003003b, -0x00000000, -0xe5189000, -0x000d8180, -0x00000000, -0xea000000, -0x0005000b, -0x00060011, -0xe5172000, -0x000d8180, -0xe3c00000, -0x000a0000, -0xe5071000, -0x000d8180, -0xe5410000, -0x000d8180, -0xe5012000, -0x000d8180, -0xea000000, -0x0005000e, -0x00000000, -0xe59d0004, -0xe004b6ae, -0xe08bb000, -0xea000000, -0x000500a1, -0x00000000, -0xe004b6ae, -0x000600a1, -0xe1a0c009, -0xe1a920da, -0xe24bb008, -0xe2899008, -0xe3730000, -0x000a0000, -0x1a000000, -0x00050025, -0xe5096004, -0xe5126000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe08aa009, -0xe12fff1c, -0x00000000, -0xe59d0004, -0xe080b18b, -0xea000000, -0x000500a2, -0x00000000, -0xe1a0b18b, -0x000600a2, -0xe1aa20d9, -0xe24bb008, -0xe28aa008, -0xe3730000, -0x000a0000, -0x1a000000, -0x00050042, -0xe5196004, -0x00060043, -0xe3a0c000, -0xe5523000, -0x000d8180, -0xe3160000, -0x000a0000, -0x1a000000, -0x00050007, -0x0006000b, -0xe5092008, -0xe35b0000, -0x0a000000, -0x00050003, -0x0006000c, -0xe18a00dc, -0xe28ce008, -0xe15e000b, -0xe18900fc, -0xe1a0c00e, -0x1a000000, -0x0005000c, -0x0006000d, -0xe3530001, -0x8a000000, -0x00050005, -0x0006000e, -0xe5126000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe08aa009, -0xe12fff1c, -0x0006000f, -0xe516e004, -0xe004a2ae, -0xe049000a, -0xe5100010, -0xe5100000, -0x000d8180, -0xe5105000, -0x000d8180, -0xea000000, -0x0005000e, -0x00060011, -0xe2266000, -0x000a0000, -0xe3160000, -0x000a0000, -0x00000000, -0x13a03000, -0x1a000000, -0x0005000b, -0xe0499006, -0xe5196004, -0xe3160000, -0x000a0000, -0x13a03000, -0xea000000, -0x0005000b, -0x00000000, -0xe089a00a, -0xe1a0c009, -0xe14a21d0, -0xe14a00d8, -0xe28a9008, -0xe1ca20f8, -0xe1ca01f0, -0xe14a21d8, -0xe3a0b010, -0xe1ca20f0, -0xe3730000, -0x000a0000, -0x1a000000, -0x00050025, -0xe5096004, -0xe5126000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe08aa009, -0xe12fff1c, -0x00000000, -0xe089a00a, -0xe51ac010, -0xe51a0008, -0xe51ce000, -0x000d8180, -0xe51c1000, -0x000d8180, -0xe2866004, -0x0006000b, -0xe050b00e, -0xe0812180, -0x2a000000, -0x00050005, -0xe1c220d0, -0xe3730000, -0x000a0000, -0x02800001, -0x0a000000, -0x0005000b, -0xe156b0b2, -0xe3e01000, -0x000a0000, -0xe1ca20f8, -0xe086b10b, -0xe280c001, -0xe1ca00f0, -0xe24b6b80, -0xe50ac008, -0x0006000d, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0xe51c3000, -0x000d8180, -0xe51cc000, -0x000d8180, -0x00060010, -0xe08b008b, -0xe15b0003, -0xe08c2180, -0x8a000000, -0x0005000d, -0xe14200d0, -0x000c8100, -0xe3710000, -0x000a0000, -0xe28bb001, -0x0a000000, -0x00050010, -0xe156c0b2, -0xe08bb00e, -0xe14220d0, -0x000c8100, -0xe50ab008, -0xe1ca00f8, -0xe086b10c, -0xe24b6b80, -0xe1ca20f0, -0xea000000, -0x0005000d, -0x00000000, -0xe089a00a, -0xe086b10b, -0xe14a01d8, -0xe51a200c, -0xe51a3004, -0xe3710000, -0x000a0000, -0x05500000, -0x000d8180, -0x03720000, -0x000a0000, -0x03730000, -0x000a0000, -0x03500000, -0x000a0000, -0x024b6b80, -0x1a000000, -0x00050005, -0xe5d6c000, -0xe496e004, -0xe3a00000, -0xe50a0008, -0x0006000b, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0xe3a00000, -0x000a0000, -0xe3a0c000, -0x000a0000, -0xe5460004, -0xe24b6b80, -0xe5c6c000, -0xe496e004, -0xea000000, -0x0005000b, -0x00000000, -0xe004caae, -0xe004b6ae, -0xe5190004, -0xe089b00b, -0xe089a00a, -0xe28bb000, -0x000a0000, -0xe08a300c, -0xe2492008, -0xe04bb000, -0xe35c0000, -0xe042000b, -0x0a000000, -0x00050005, -0xe2433010, -0x0006000b, -0xe15b0002, -0x30cb00d8, -0x23e01000, -0x000a0000, -0xe15a0003, -0xe0ca00f8, -0x3a000000, -0x0005000b, -0x0006000c, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000f, -0xe5183000, -0x000d8180, -0xe3500000, -0xd3a0c008, -0xc280c008, -0xe08a1000, -0xe58dc004, -0xda000000, -0x0005000c, -0xe1510003, -0x8a000000, -0x00050007, -0x00060010, -0xe0cb00d8, -0xe0ca00f8, -0xe15b0002, -0x3a000000, -0x00050010, -0xea000000, -0x0005000c, -0x00060011, -0xe1a011a0, -0xe508a000, -0x000d8180, -0xe1a00008, -0xe5089000, -0x000d8180, -0xe04bb009, -0xe58d6008, -0xe04aa009, -0xeb000000, -0x00030000, -0xe5189000, -0x000d8180, -0xe089a00a, -0xe089b00b, -0xe2492008, -0xea000000, -0x00050010, -0x00000000, -0xe59d0004, -0xe5196004, -0xe089a00a, -0xe080b18b, -0xea000000, -0x000500a3, -0x00000000, -0xe5196004, -0xe1a0b18b, -0xe089a00a, -0x000600a3, -0xe58db004, -0x0006000b, -0xe2160000, -0x000a0000, -0xe2261000, -0x000a0000, -0x1a000000, -0x000500a4, -0x00060017, -0xe516e004, -0xe25b3008, -0xe2492008, -0x0a000000, -0x00050003, -0x0006000c, -0xe0ca00d8, -0xe2899008, -0xe2533008, -0xe14901f0, -0x1a000000, -0x0005000c, -0x0006000d, -0xe004a2ae, -0xe042300a, -0xe004caae, -0xe5130008, -0x0006000f, -0xe15c000b, -0x8a000000, -0x00050006, -0xe1a09003, -0xe5101000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe5115000, -0x000d8180, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00060010, -0xe3e01000, -0x000a0000, -0xe2899008, -0xe28bb008, -0xe509100c, -0xea000000, -0x0005000f, -0x000600a5, -0xe089a00a, -0x000600a4, -0xe3110000, -0x000a0000, -0x1a000000, -0x00050018, -0xe0499001, -0xe5196004, -0xea000000, -0x0005000b, -0x00000000, -0xe5196004, -0xe1a0b18b, -0xe58db004, -0xe2160000, -0x000a0000, -0xe2261000, -0x000a0000, -0x0516e004, -0x1a000000, -0x000500a5, -0x00000000, -0xe18900da, -0x00000000, -0xe2493008, -0xe004a2ae, -0x00000000, -0xe1c300f0, -0x00000000, -0xe043900a, -0xe004caae, -0xe5190008, -0x0006000f, -0xe15c000b, -0x8a000000, -0x00050006, -0xe5101000, -0x000d8180, -0xe5d6c000, -0xe496e004, -0xe5115000, -0x000d8180, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00060010, -0xe2431004, -0xe3e02000, -0x000a0000, -0xe781200b, -0xe28bb008, -0xea000000, -0x0005000f, -0x00000000, -0xe1a000a6, -0xe200007e, -0xe2400000, -0x000a0000, -0xe19710b0, -0xe2511000, -0x000a0000, -0xe18710b0, -0x3a000000, -0x00050092, -0x00000000, -0xe1aa00d9, -0x00000000, -0xe086b10b, -0x00000000, -0xe1ca20d8, -0xe3710000, -0x000a0000, -0xe59ac014, -0x1a000000, -0x00050005, -0xe3730000, -0x000a0000, -0xe59a3010, -0x037c0000, -0x000a0000, -0x1a000000, -0x00050044, -0xe3530000, -0xba000000, -0x00050004, -0xe1500002, -0x00000000, -0xe1ca21d0, -0xe3710000, -0x000a0000, -0x1a000000, -0x00050005, -0xe0900002, -0xe59a3008, -0x00000000, -0x6286bb80, -0x00000000, -0x6a000000, -0x00050002, -0x00000000, -0xe3520000, -0xba000000, -0x00050004, -0xe1500003, -0x00000000, -0x0006000b, -0x00000000, -0xc24b6b80, -0x00000000, -0xe24b6b80, -0xd156b0b2, -0x00000000, -0xd24b6b80, -0x00000000, -0xe1ca00f0, -0x00000000, -0x0006000c, -0xe5d6c000, -0xe496e004, -0xe1ca01f8, -0x00000000, -0xda000000, -0x00070000, -0x00000000, -0x0006000d, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x0006000e, -0x00000000, -0xe1520000, -0x00000000, -0xe1530000, -0x00000000, -0xea000000, -0x0005000b, -0x0006000f, -0x00000000, -0x33730000, -0x000a0000, -0x337c0000, -0x000a0000, -0x2a000000, -0x00050044, -0xe35c0000, -0xe1ca00f0, -0xe1ca01f8, -0xba000000, -0x00050008, -0x00000000, -0xe3530000, -0xba000000, -0x00050008, -0xeb000000, -0x0003002e, -0xe1ca00f0, -0xe1ca20d8, -0xe1ca01f8, -0x00000000, -0x00060010, -0xeb000000, -0x00030024, -0x00000000, -0x824b6b80, -0x00000000, -0xe24b6b80, -0x9156b0b2, -0x9a000000, -0x00070000, -0x00000000, -0x924b6b80, -0x00000000, -0x9a000000, -0x00070000, -0x00000000, -0xe5d6c000, -0xe496e004, -0xea000000, -0x0005000d, -0x00060012, -0x00000000, -0xeb000000, -0x0003002e, -0xe1ca00f0, -0xe1ca01f8, -0x00000000, -0xe1a02000, -0xe1a03001, -0xe1ca00d8, -0xea000000, -0x00050010, -0x00000000, -0xe1a000a6, -0xe200007e, -0xe2400000, -0x000a0000, -0xe19710b0, -0xe2511000, -0x000a0000, -0xe18710b0, -0x3a000000, -0x00050092, -0x00000000, -0xe1aa00d9, -0x00000000, -0xe3710000, -0x000a0000, -0x114a00f8, -0x1a000000, -0x00070000, -0x00000000, -0xe086b10b, -0xe3710000, -0x000a0000, -0x124b6b80, -0x114a00f8, -0x00000000, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1a000a6, -0xe200007e, -0xe2400000, -0x000a0000, -0xe19710b0, -0xe2511000, -0x000a0000, -0xe18710b0, -0x3a000000, -0x00050092, -0x00000000, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe5170000, -0x000d8180, -0xe3a01000, -0xe790b10b, -0xe5071000, -0x000d8180, -0xe51ba000, -0x000d8180, -0xe5079000, -0x000d8180, -0xe5078000, -0x000d8180, -0xe12fff1a, -0x00000000, -0xe086b10b, -0xe24b6b80, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe1a000a6, -0xe200007e, -0xe2400000, -0x000a0000, -0xe19710b0, -0xe2511000, -0x000a0000, -0xe18710b0, -0x3a000000, -0x00050094, -0x00000000, -0xe5180000, -0x000d8180, -0xe5561000, -0x000d8180, -0xe5165000, -0x000d8180, -0xe15a0000, -0x8a000000, -0x00050020, -0x00000000, -0xe5d6c000, -0xe496e004, -0x00000000, -0x0006000c, -0xe15b0181, -0xe3e03000, -0x000a0000, -0x3a000000, -0x00050003, -0x00000000, -0xe1a0b82e, -0xea000000, -0x00070000, -0x00000000, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0x0006000d, -0xe18920fb, -0xe28bb008, -0xea000000, -0x0005000c, -0x00000000, -0xe7f001f0, -0x00000000, -0xe5180000, -0x000d8180, -0xe089300b, -0xe08aa00b, -0xe5832000, -0xe28b1000, -0x000a0000, -0xe5165000, -0x000d8180, -0xe15a0000, -0xe5831004, -0x2a000000, -0x00050020, -0xe556c000, -0x000d8180, -0xe1a0a009, -0xe1a0b003, -0xe35c0000, -0xe2839008, -0x0a000000, -0x00050003, -0xe3e02000, -0x000a0000, -0x0006000b, -0xe15a000b, -0x30ca00d8, -0x21a01002, -0x350a2004, -0x0006000c, -0xe25cc001, -0xe1e300f8, -0x1a000000, -0x0005000b, -0x0006000d, -0xe5d6c000, -0xe496e004, -0xe797c10c, -0xe004a2ae, -0xe1a0b82e, -0xe12fff1c, -0x00000000, -0xe5123000, -0x000d8180, -0x00000000, -0xe5173000, -0x000d8180, -0x00000000, -0xe08a100b, -0xe5180000, -0x000d8180, -0xe089b00b, -0xe5089000, -0x000d8180, -0xe1510000, -0xe508b000, -0x000d8180, -0x00000000, -0xe5121000, -0x000d8180, -0x00000000, -0xe3e02000, -0x000a0000, -0xe1a00008, -0x8a000000, -0x0005001f, -0xe5072000, -0x000d8180, -0xe12fff33, -0xe5189000, -0x000d8180, -0xe3e02000, -0x000a0000, -0xe5181000, -0x000d8180, -0xe1a0b180, -0xe5072000, -0x000d8180, -0xe5196004, -0xe041a00b, -0xea000000, -0x00050016, -0x00000000, -0x00010000 -}; - -enum { - GLOB_vm_returnp, - GLOB_cont_dispatch, - GLOB_vm_returnc, - GLOB_BC_RET_Z, - GLOB_vm_return, - GLOB_vm_leave_cp, - GLOB_vm_leave_unw, - GLOB_vm_unwind_c, - GLOB_vm_unwind_c_eh, - GLOB_vm_unwind_ff, - GLOB_vm_unwind_ff_eh, - GLOB_vm_growstack_c, - GLOB_vm_growstack_l, - GLOB_vm_resume, - GLOB_vm_pcall, - GLOB_vm_call, - GLOB_vm_call_dispatch, - GLOB_vmeta_call, - GLOB_vm_call_dispatch_f, - GLOB_vm_cpcall, - GLOB_cont_ffi_callback, - GLOB_vm_call_tail, - GLOB_cont_cat, - GLOB_BC_CAT_Z, - GLOB_cont_nop, - GLOB_vmeta_tgets1, - GLOB_vmeta_tgets, - GLOB_vmeta_tgetb, - GLOB_vmeta_tgetv, - GLOB_vmeta_tsets1, - GLOB_vmeta_tsets, - GLOB_vmeta_tsetb, - GLOB_vmeta_tsetv, - GLOB_vmeta_comp, - GLOB_vmeta_binop, - GLOB_cont_ra, - GLOB_cont_condt, - GLOB_cont_condf, - GLOB_vmeta_equal, - GLOB_vmeta_equal_cd, - GLOB_vmeta_arith_vn, - GLOB_vmeta_arith_nv, - GLOB_vmeta_unm, - GLOB_vmeta_arith_vv, - GLOB_vmeta_len, - GLOB_BC_LEN_Z, - GLOB_vmeta_callt, - GLOB_BC_CALLT2_Z, - GLOB_vmeta_for, - GLOB_ff_assert, - GLOB_fff_fallback, - GLOB_fff_res, - GLOB_ff_type, - GLOB_fff_restv, - GLOB_ff_getmetatable, - GLOB_ff_setmetatable, - GLOB_ff_rawget, - GLOB_ff_tonumber, - GLOB_ff_tostring, - GLOB_fff_gcstep, - GLOB_ff_next, - GLOB_ff_pairs, - GLOB_ff_ipairs_aux, - GLOB_ff_ipairs, - GLOB_ff_pcall, - GLOB_ff_xpcall, - GLOB_ff_coroutine_resume, - GLOB_ff_coroutine_wrap_aux, - GLOB_ff_coroutine_yield, - GLOB_ff_math_floor, - GLOB_vm_floor, - GLOB_ff_math_ceil, - GLOB_vm_ceil, - GLOB_ff_math_abs, - GLOB_fff_res1, - GLOB_ff_math_sqrt, - GLOB_ff_math_log, - GLOB_ff_math_log10, - GLOB_ff_math_exp, - GLOB_ff_math_sin, - GLOB_ff_math_cos, - GLOB_ff_math_tan, - GLOB_ff_math_asin, - GLOB_ff_math_acos, - GLOB_ff_math_atan, - GLOB_ff_math_sinh, - GLOB_ff_math_cosh, - GLOB_ff_math_tanh, - GLOB_ff_math_pow, - GLOB_ff_math_atan2, - GLOB_ff_math_fmod, - GLOB_ff_math_deg, - GLOB_ff_math_rad, - GLOB_ff_math_ldexp, - GLOB_ff_math_frexp, - GLOB_ff_math_modf, - GLOB_ff_math_min, - GLOB_ff_math_max, - GLOB_ff_string_len, - GLOB_ff_string_byte, - GLOB_ff_string_char, - GLOB_fff_newstr, - GLOB_ff_string_sub, - GLOB_fff_emptystr, - GLOB_ff_string_rep, - GLOB_ff_string_reverse, - GLOB_ff_string_lower, - GLOB_ff_string_upper, - GLOB_ff_table_getn, - GLOB_vm_tobit_fb, - GLOB_vm_tobit, - GLOB_ff_bit_tobit, - GLOB_ff_bit_band, - GLOB_ff_bit_bor, - GLOB_ff_bit_bxor, - GLOB_ff_bit_bswap, - GLOB_ff_bit_bnot, - GLOB_ff_bit_lshift, - GLOB_ff_bit_rshift, - GLOB_ff_bit_arshift, - GLOB_ff_bit_rol, - GLOB_ff_bit_ror, - GLOB_vm_record, - GLOB_vm_rethook, - GLOB_vm_inshook, - GLOB_cont_hook, - GLOB_vm_hotloop, - GLOB_vm_callhook, - GLOB_vm_hotcall, - GLOB_vm_exit_handler, - GLOB_vm_exit_interp, - GLOB_vm_trunc, - GLOB_vm_mod, - GLOB_vm_modi, - GLOB_vm_foldarith, - GLOB_vm_ffi_callback, - GLOB_vm_ffi_call, - GLOB_BC_ISEQN_Z, - GLOB_BC_ISNEN_Z, - GLOB_BC_TGETS_Z, - GLOB_BC_TSETS_Z, - GLOB_BC_CALL_Z, - GLOB_BC_CALLT1_Z, - GLOB_BC_RETM_Z, - GLOB_BC_RETV2_Z, - GLOB_BC_RETV1_Z, - GLOB__MAX -}; -static const char *const globnames[] = { - "vm_returnp", - "cont_dispatch", - "vm_returnc", - "BC_RET_Z", - "vm_return", - "vm_leave_cp", - "vm_leave_unw", - "vm_unwind_c", - "vm_unwind_c_eh", - "vm_unwind_ff", - "vm_unwind_ff_eh", - "vm_growstack_c", - "vm_growstack_l", - "vm_resume", - "vm_pcall", - "vm_call", - "vm_call_dispatch", - "vmeta_call", - "vm_call_dispatch_f", - "vm_cpcall", - "cont_ffi_callback", - "vm_call_tail", - "cont_cat", - "BC_CAT_Z", - "cont_nop", - "vmeta_tgets1", - "vmeta_tgets", - "vmeta_tgetb", - "vmeta_tgetv", - "vmeta_tsets1", - "vmeta_tsets", - "vmeta_tsetb", - "vmeta_tsetv", - "vmeta_comp", - "vmeta_binop", - "cont_ra", - "cont_condt", - "cont_condf", - "vmeta_equal", - "vmeta_equal_cd", - "vmeta_arith_vn", - "vmeta_arith_nv", - "vmeta_unm", - "vmeta_arith_vv", - "vmeta_len", - "BC_LEN_Z", - "vmeta_callt", - "BC_CALLT2_Z", - "vmeta_for", - "ff_assert", - "fff_fallback", - "fff_res", - "ff_type", - "fff_restv", - "ff_getmetatable", - "ff_setmetatable", - "ff_rawget", - "ff_tonumber", - "ff_tostring", - "fff_gcstep", - "ff_next", - "ff_pairs", - "ff_ipairs_aux", - "ff_ipairs", - "ff_pcall", - "ff_xpcall", - "ff_coroutine_resume", - "ff_coroutine_wrap_aux", - "ff_coroutine_yield", - "ff_math_floor", - "vm_floor", - "ff_math_ceil", - "vm_ceil", - "ff_math_abs", - "fff_res1", - "ff_math_sqrt", - "ff_math_log", - "ff_math_log10", - "ff_math_exp", - "ff_math_sin", - "ff_math_cos", - "ff_math_tan", - "ff_math_asin", - "ff_math_acos", - "ff_math_atan", - "ff_math_sinh", - "ff_math_cosh", - "ff_math_tanh", - "ff_math_pow", - "ff_math_atan2", - "ff_math_fmod", - "ff_math_deg", - "ff_math_rad", - "ff_math_ldexp", - "ff_math_frexp", - "ff_math_modf", - "ff_math_min", - "ff_math_max", - "ff_string_len", - "ff_string_byte", - "ff_string_char", - "fff_newstr", - "ff_string_sub", - "fff_emptystr", - "ff_string_rep", - "ff_string_reverse", - "ff_string_lower", - "ff_string_upper", - "ff_table_getn", - "vm_tobit_fb", - "vm_tobit", - "ff_bit_tobit", - "ff_bit_band", - "ff_bit_bor", - "ff_bit_bxor", - "ff_bit_bswap", - "ff_bit_bnot", - "ff_bit_lshift", - "ff_bit_rshift", - "ff_bit_arshift", - "ff_bit_rol", - "ff_bit_ror", - "vm_record", - "vm_rethook", - "vm_inshook", - "cont_hook", - "vm_hotloop", - "vm_callhook", - "vm_hotcall", - "vm_exit_handler", - "vm_exit_interp", - "vm_trunc", - "vm_mod", - "vm_modi", - "vm_foldarith", - "vm_ffi_callback", - "vm_ffi_call", - "BC_ISEQN_Z", - "BC_ISNEN_Z", - "BC_TGETS_Z", - "BC_TSETS_Z", - "BC_CALL_Z", - "BC_CALLT1_Z", - "BC_RETM_Z", - "BC_RETV2_Z", - "BC_RETV1_Z", - (const char *)0 -}; -static const char *const extnames[] = { - "lj_state_growstack", - "lj_meta_tget", - "lj_meta_tset", - "lj_meta_comp", - "lj_meta_equal", - "lj_meta_equal_cd", - "lj_meta_arith", - "lj_meta_len", - "lj_meta_call", - "lj_meta_for", - "lj_tab_get", - "lj_str_fromnumber", - "lj_tab_next", - "lj_tab_getinth", - "lj_ffh_coroutine_wrap_err", - "sqrt", - "log", - "log10", - "exp", - "sin", - "cos", - "tan", - "asin", - "acos", - "atan", - "sinh", - "cosh", - "tanh", - "pow", - "atan2", - "fmod", - "__aeabi_dmul", - "ldexp", - "frexp", - "modf", - "__aeabi_i2d", - "__aeabi_cdcmple", - "lj_str_new", - "lj_tab_len", - "lj_gc_step", - "lj_dispatch_ins", - "lj_trace_hot", - "lj_dispatch_call", - "lj_trace_exit", - "lj_err_throw", - "__aeabi_ddiv", - "__aeabi_dadd", - "__aeabi_dsub", - "lj_ccallback_enter", - "lj_ccallback_leave", - "__aeabi_cdcmpeq", - "lj_meta_cat", - "lj_gc_barrieruv", - "lj_func_closeuv", - "lj_func_newL_gc", - "lj_tab_new", - "lj_tab_dup", - "lj_gc_step_fixtop", - "lj_tab_newkey", - "lj_tab_reasize", - (const char *)0 -}; -#define Dt1(_V) (int)(ptrdiff_t)&(((lua_State *)0)_V) -#define Dt2(_V) (int)(ptrdiff_t)&(((global_State *)0)_V) -#define Dt3(_V) (int)(ptrdiff_t)&(((TValue *)0)_V) -#define Dt4(_V) (int)(ptrdiff_t)&(((GCobj *)0)_V) -#define Dt5(_V) (int)(ptrdiff_t)&(((GCstr *)0)_V) -#define Dt6(_V) (int)(ptrdiff_t)&(((GCtab *)0)_V) -#define Dt7(_V) (int)(ptrdiff_t)&(((GCfuncL *)0)_V) -#define Dt8(_V) (int)(ptrdiff_t)&(((GCfuncC *)0)_V) -#define Dt9(_V) (int)(ptrdiff_t)&(((GCproto *)0)_V) -#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V) -#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V) -#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V) -#define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V) -#define field_pc pc -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) - -#if !LJ_DUALNUM -#error "Only dual-number mode supported for ARM target" -#endif - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx) -{ - dasm_put(Dst, 0); - dasm_put(Dst, 1, FRAME_P, ~LJ_TTRUE, FRAME_TYPE, FRAME_TYPEP, FRAME_C, Dt1(->base), LJ_VMST_C, DISPATCH_GL(vmstate), Dt1(->top)); - dasm_put(Dst, 54, Dt1(->cframe), Dt1(->maxstack), ~LJ_TNIL, Dt1(->top), Dt1(->top), LJ_VMST_C, Dt1(->glref), Dt2(->vmstate)); - dasm_put(Dst, 108, ~CFRAME_RAWMASK, Dt1(->base), Dt1(->glref), ~LJ_TFALSE, GG_G2DISP, LJ_VMST_INTERP, DISPATCH_GL(vmstate), LUA_MINSTACK, Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top), Dt7(->field_pc), Dt1(->glref)); - dasm_put(Dst, 173, GG_G2DISP, FRAME_CP, CFRAME_RESUME, Dt1(->status), Dt1(->cframe), Dt1(->base), Dt1(->top), Dt1(->status), LJ_VMST_INTERP, FRAME_TYPE, DISPATCH_GL(vmstate), FRAME_CP, FRAME_C, Dt1(->cframe), Dt1(->cframe)); - dasm_put(Dst, 238, Dt1(->glref), GG_G2DISP, Dt1(->base), Dt1(->top), LJ_VMST_INTERP, DISPATCH_GL(vmstate), -LJ_TFUNC, Dt7(->field_pc), Dt1(->stack), Dt1(->top), Dt1(->cframe), Dt1(->cframe), Dt1(->glref), FRAME_CP, GG_G2DISP); - dasm_put(Dst, 307); -#if LJ_HASFFI - dasm_put(Dst, 312); -#endif - dasm_put(Dst, 314, Dt7(->field_pc), ~LJ_TNIL); -#if LJ_HASFFI - dasm_put(Dst, 322); -#endif - dasm_put(Dst, 325, PC2PROTO(k)); -#if LJ_HASFFI - dasm_put(Dst, 329); -#endif - dasm_put(Dst, 338, Dt1(->base), -DISPATCH_GL(tmptv), ~LJ_TTAB, ~LJ_TSTR, ~LJ_TISNUM, Dt1(->base)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 395, Dt1(->base)); - } - dasm_put(Dst, 398, FRAME_CONT, Dt1(->top), -DISPATCH_GL(tmptv), ~LJ_TTAB, ~LJ_TSTR, ~LJ_TISNUM, Dt1(->base)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 460, Dt1(->base)); - } - dasm_put(Dst, 463, FRAME_CONT, Dt1(->top), Dt1(->base)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 499, Dt1(->base)); - } - dasm_put(Dst, 502, ~LJ_TTRUE, -LJ_TFALSE, Dt1(->base)); -#if LJ_HASFFI - dasm_put(Dst, 549, Dt1(->base)); -#endif - dasm_put(Dst, 560, Dt1(->base)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 597, Dt1(->base)); - } - dasm_put(Dst, 600, FRAME_CONT, Dt1(->base)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 621, Dt1(->base)); - } -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 624); -#else - dasm_put(Dst, 631); -#endif - dasm_put(Dst, 634, Dt1(->base)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 642); - } - dasm_put(Dst, 644); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 647); - } - dasm_put(Dst, 649, Dt7(->field_pc), Dt1(->base)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 670, Dt1(->base)); - } - dasm_put(Dst, 673, Dt1(->base)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 687, Dt1(->base)); - } -#if LJ_HASJIT - dasm_put(Dst, 690); -#endif - dasm_put(Dst, 692); -#if LJ_HASJIT - dasm_put(Dst, 694, BC_JFORI); -#endif - dasm_put(Dst, 697); -#if LJ_HASJIT - dasm_put(Dst, 700, BC_JFORI); -#endif - dasm_put(Dst, 703, BC_FORI, -LJ_TTRUE, -LJ_TISNUM, ~LJ_TISNUM, (int)(offsetof(GCfuncC, upvalue)>>3)-1, -LJ_TTAB, -LJ_TUDATA, Dt6(->metatable)); - dasm_put(Dst, 760, ~LJ_TNIL, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable]), Dt6(->hmask), Dt5(->hash), Dt6(->node), DtB(->key), DtB(->val), DtB(->next), -LJ_TSTR, ~LJ_TTAB, -LJ_TNIL, -LJ_TISNUM); - dasm_put(Dst, 808, ~LJ_TISNUM, DISPATCH_GL(gcroot[GCROOT_BASEMT]), -LJ_TTAB, Dt6(->metatable), -LJ_TTAB, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), DISPATCH_GL(gc.grayagain), LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist), -LJ_TTAB); - dasm_put(Dst, 860); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 865); - } - dasm_put(Dst, 867); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 870); - } - dasm_put(Dst, 872, -LJ_TISNUM, -LJ_TSTR, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM]), Dt1(->base), -LJ_TISNUM, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), ~LJ_TSTR); - dasm_put(Dst, 924, ~LJ_TNIL, -LJ_TTAB, Dt1(->base), Dt1(->top)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 947, Dt1(->base)); - } - dasm_put(Dst, 950, ~LJ_TNIL, (2+1)*8, -LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 973, Dt6(->metatable)); -#endif - dasm_put(Dst, 976, Dt8(->upvalue[0])); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 980); -#endif - dasm_put(Dst, 984, ~LJ_TNIL, (3+1)*8, -LJ_TTAB, -LJ_TISNUM, Dt6(->asize), Dt6(->array), (0+1)*8, -LJ_TNIL, (2+1)*8, Dt6(->hmask)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1034); - } - dasm_put(Dst, 1036); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1039); - } - dasm_put(Dst, 1041, -LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1057, Dt6(->metatable)); -#endif - dasm_put(Dst, 1060, Dt8(->upvalue[0])); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1064); -#endif - dasm_put(Dst, 1068, ~LJ_TISNUM, (3+1)*8, DISPATCH_GL(hookmask), HOOK_ACTIVE, 8+FRAME_PCALL, 8+FRAME_PCALLH, DISPATCH_GL(hookmask), -LJ_TFUNC, HOOK_ACTIVE, 16+FRAME_PCALL, 16+FRAME_PCALLH, -LJ_TTHREAD); - dasm_put(Dst, 1127, Dt1(->base), Dt1(->top), Dt1(->status), Dt1(->base), Dt1(->maxstack), Dt1(->cframe), LUA_YIELD, Dt1(->top), Dt1(->top), Dt1(->base), LJ_VMST_INTERP, Dt1(->top), DISPATCH_GL(vmstate), LUA_YIELD); - dasm_put(Dst, 1186, Dt1(->base), Dt1(->maxstack), Dt1(->top), ~LJ_TTRUE, FRAME_TYPE, ~LJ_TFALSE, (2+1)*8, Dt1(->top)); - dasm_put(Dst, 1246, Dt8(->upvalue[0].gcr), Dt1(->base), Dt1(->top), Dt1(->status), Dt1(->base), Dt1(->maxstack), Dt1(->cframe), LUA_YIELD, Dt1(->top), Dt1(->top), Dt1(->base), LJ_VMST_INTERP, Dt1(->top), DISPATCH_GL(vmstate), LUA_YIELD); - dasm_put(Dst, 1302, Dt1(->base), Dt1(->maxstack), Dt1(->top), FRAME_TYPE, Dt1(->cframe), Dt1(->base), CFRAME_RESUME, Dt1(->top)); - dasm_put(Dst, 1361, LUA_YIELD, Dt1(->cframe), Dt1(->status), -LJ_TISNUM, ~LJ_TISNUM, ~LJ_TISNUM); - dasm_put(Dst, 1429, -LJ_TISNUM, ~LJ_TISNUM, ~LJ_TISNUM); - dasm_put(Dst, 1493, -LJ_TISNUM, (1+1)*8, FRAME_TYPE, ~LJ_TNIL); - dasm_put(Dst, 1555, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1564); - } - dasm_put(Dst, 1566); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1569); - } - dasm_put(Dst, 1571, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1583); - } - dasm_put(Dst, 1585); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1588); - } - dasm_put(Dst, 1590, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1602); - } - dasm_put(Dst, 1604); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1607); - } - dasm_put(Dst, 1609, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1621); - } - dasm_put(Dst, 1623); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1626); - } - dasm_put(Dst, 1628, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1640); - } - dasm_put(Dst, 1642); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1645); - } - dasm_put(Dst, 1647, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1659); - } - dasm_put(Dst, 1661); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1664); - } - dasm_put(Dst, 1666, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1678); - } - dasm_put(Dst, 1680); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1683); - } - dasm_put(Dst, 1685, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1697); - } - dasm_put(Dst, 1699); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1702); - } - dasm_put(Dst, 1704, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1716); - } - dasm_put(Dst, 1718); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1721); - } - dasm_put(Dst, 1723, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1735); - } - dasm_put(Dst, 1737); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1740); - } - dasm_put(Dst, 1742, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1754); - } - dasm_put(Dst, 1756); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1759); - } - dasm_put(Dst, 1761, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1773); - } - dasm_put(Dst, 1775); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1778); - } - dasm_put(Dst, 1780, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1792); - } - dasm_put(Dst, 1794); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1797); - } - dasm_put(Dst, 1799, -LJ_TISNUM, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1814); - } - dasm_put(Dst, 1816); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1819); - } - dasm_put(Dst, 1821, -LJ_TISNUM, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1836); - } - dasm_put(Dst, 1838); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1841); - } - dasm_put(Dst, 1843, -LJ_TISNUM, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1858); - } - dasm_put(Dst, 1860); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1863); - } - dasm_put(Dst, 1865, -LJ_TISNUM, Dt8(->upvalue[0]), -LJ_TISNUM, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1898); - } - dasm_put(Dst, 1900); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1903); - } - dasm_put(Dst, 1905, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1918); - } - dasm_put(Dst, 1920); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1923); - } - dasm_put(Dst, 1925, ~LJ_TISNUM, (2+1)*8, -LJ_TISNUM); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1947); - } - dasm_put(Dst, 1949); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 1952); - } - dasm_put(Dst, 1954, (2+1)*8, -LJ_TISNUM, -LJ_TISNUM, -LJ_TISNUM); - dasm_put(Dst, 2005, -LJ_TISNUM, -LJ_TISNUM); - dasm_put(Dst, 2059, -LJ_TISNUM, -LJ_TSTR, Dt5(->len), ~LJ_TISNUM, -LJ_TSTR, Dt5(->len), Dt5([1])); - dasm_put(Dst, 2113, ~LJ_TISNUM, (0+1)*8, (1+1)*8, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), -LJ_TISNUM, Dt1(->base), Dt1(->base), ~LJ_TSTR, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 2172, -LJ_TISNUM, -LJ_TSTR, Dt5(->len), -LJ_TISNUM, sizeof(GCstr)-1, -DISPATCH_GL(strempty), ~LJ_TSTR, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), -LJ_TSTR, -LJ_TISNUM, Dt5(->len)); - dasm_put(Dst, 2234, DISPATCH_GL(tmpbuf.sz), DISPATCH_GL(tmpbuf.buf), Dt5([1]), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), -LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz), DISPATCH_GL(tmpbuf.buf), sizeof(GCstr)); - dasm_put(Dst, 2287, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), -LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz), DISPATCH_GL(tmpbuf.buf), sizeof(GCstr), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 2347, -LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz), DISPATCH_GL(tmpbuf.buf), sizeof(GCstr), -LJ_TTAB); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 2385); - } - dasm_put(Dst, 2387); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 2390); - } - dasm_put(Dst, 2392, ~LJ_TISNUM, -LJ_TISNUM, ~LJ_TISNUM, -LJ_TISNUM, -LJ_TISNUM); - dasm_put(Dst, 2463, -LJ_TISNUM, -LJ_TISNUM, -LJ_TISNUM, -LJ_TISNUM, ~LJ_TISNUM); - dasm_put(Dst, 2523, -LJ_TISNUM, ~LJ_TISNUM, -LJ_TISNUM, ~LJ_TISNUM, -LJ_TISNUM, -LJ_TISNUM, ~LJ_TISNUM, -LJ_TISNUM); - dasm_put(Dst, 2579, -LJ_TISNUM, ~LJ_TISNUM, -LJ_TISNUM, -LJ_TISNUM, ~LJ_TISNUM, -LJ_TISNUM, -LJ_TISNUM, ~LJ_TISNUM); - dasm_put(Dst, 2636, -LJ_TISNUM, -LJ_TISNUM, ~LJ_TISNUM, Dt1(->maxstack), Dt1(->top), Dt8(->f), Dt1(->base), 8*LUA_MINSTACK, Dt1(->base), Dt1(->top), Dt7(->field_pc), FRAME_TYPE, FRAME_TYPEP); - dasm_put(Dst, 2699, LUA_MINSTACK, Dt1(->base), Dt1(->base), Dt1(->top), Dt1(->base)); -#if LJ_HASJIT - dasm_put(Dst, 2734, DISPATCH_GL(hookmask), HOOK_VMEVENT, DISPATCH_GL(hookcount), HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount)); -#endif - dasm_put(Dst, 2754, DISPATCH_GL(hookmask), HOOK_ACTIVE, GG_DISP2STATIC, DISPATCH_GL(hookmask), DISPATCH_GL(hookcount), HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount), LUA_MASKLINE, Dt1(->base), Dt1(->base)); - dasm_put(Dst, 2800, GG_DISP2STATIC); -#if LJ_HASJIT - dasm_put(Dst, 2816, -GG_DISP2J, Dt7(->field_pc), DISPATCH_J(L), PC2PROTO(framesize), Dt1(->base), Dt1(->top)); -#endif - dasm_put(Dst, 2837); -#if LJ_HASJIT - dasm_put(Dst, 2840); -#endif - dasm_put(Dst, 2843); -#if LJ_HASJIT - dasm_put(Dst, 2845); -#endif - dasm_put(Dst, 2848, Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 2871, LJ_VMST_EXIT, DISPATCH_GL(vmstate), DISPATCH_GL(jit_L), DISPATCH_GL(jit_base), DISPATCH_J(exitno), DISPATCH_J(L), Dt1(->base), DISPATCH_GL(jit_L), -GG_DISP2J, Dt1(->cframe), Dt1(->base), ~CFRAME_RAWMASK); -#endif - dasm_put(Dst, 2919); -#if LJ_HASJIT - dasm_put(Dst, 2921, Dt7(->field_pc), DISPATCH_GL(jit_L), LJ_VMST_INTERP, PC2PROTO(k), DISPATCH_GL(vmstate), BC_FUNCF); -#endif - dasm_put(Dst, 2958); -#if LJ_HASJIT - dasm_put(Dst, 3034); -#endif - dasm_put(Dst, 3048); - { - int i; - for (i = 31; i >= 0; i--) { - dasm_put(Dst, 3084, i, i); - } - } - dasm_put(Dst, 3089); -#if LJ_HASJIT - dasm_put(Dst, 3118); -#else - dasm_put(Dst, 3143); -#endif - dasm_put(Dst, 3145); -#if LJ_HASFFI -#define DtE(_V) (int)(ptrdiff_t)&(((CTState *)0)_V) - dasm_put(Dst, 3147, Dt2(->ctype_state), GG_G2DISP, DtE(->cb.gpr[0]), DtE(->cb.gpr[2]), CFRAME_SIZE, DtE(->cb.stack), DtE(->cb.slot), Dt1(->base), LJ_VMST_INTERP, Dt1(->top), DISPATCH_GL(vmstate), Dt7(->field_pc)); -#endif - dasm_put(Dst, 3190); -#if LJ_HASFFI - dasm_put(Dst, 3192, DISPATCH_GL(ctype_state), Dt1(->base), Dt1(->top), DtE(->L), DtE(->cb.gpr[0])); -#endif - dasm_put(Dst, 3209); -#if LJ_HASFFI -#define DtF(_V) (int)(ptrdiff_t)&(((CCallState *)0)_V) - dasm_put(Dst, 3211, DtF(->spadj), DtF(->nsp), offsetof(CCallState, stack), DtF(->func), DtF(->gpr[0]), DtF(->gpr[1]), DtF(->gpr[2]), DtF(->gpr[3]), DtF(->gpr[0]), DtF(->gpr[1])); -#endif -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop) -{ - int vk = 0; - dasm_put(Dst, 3249, defop); - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - dasm_put(Dst, 3251, -LJ_TISNUM, -LJ_TISNUM); - if (op == BC_ISLT) { - dasm_put(Dst, 3267); - } else if (op == BC_ISGE) { - dasm_put(Dst, 3269); - } else if (op == BC_ISLE) { - dasm_put(Dst, 3271); - } else { - dasm_put(Dst, 3273); - } - dasm_put(Dst, 3275, -LJ_TISNUM); - if (op == BC_ISLT) { - dasm_put(Dst, 3311); - } else if (op == BC_ISGE) { - dasm_put(Dst, 3313); - } else if (op == BC_ISLE) { - dasm_put(Dst, 3315); - } else { - dasm_put(Dst, 3317); - } - dasm_put(Dst, 3319); - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - dasm_put(Dst, 3322, -LJ_TISNUM, -LJ_TISNUM); - if (vk) { - dasm_put(Dst, 3333); - } else { - dasm_put(Dst, 3336); - } - if (LJ_HASFFI) { - dasm_put(Dst, 3339, -LJ_TCDATA, -LJ_TCDATA); - } - dasm_put(Dst, 3346, -LJ_TISPRI); - if (vk) { - dasm_put(Dst, 3355, -LJ_TISTABUD); - } else { - dasm_put(Dst, 3372, -LJ_TISTABUD); - } - dasm_put(Dst, 3379, Dt6(->metatable)); - if (vk) { - dasm_put(Dst, 3383); - } else { - dasm_put(Dst, 3386); - } - dasm_put(Dst, 3389, Dt6(->nomm), 1-vk, 1<len), ~LJ_TISNUM, -LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 3647, Dt6(->metatable)); -#endif - dasm_put(Dst, 3654); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 3656); - } - dasm_put(Dst, 3658); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 3661); - } - dasm_put(Dst, 3663); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 3666, Dt6(->nomm), 1<base), Dt1(->base)); - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - dasm_put(Dst, 4196, ~LJ_TSTR); - break; - case BC_KCDATA: -#if LJ_HASFFI - dasm_put(Dst, 4208, ~LJ_TCDATA); -#endif - break; - case BC_KSHORT: - dasm_put(Dst, 4220, ~LJ_TISNUM); - break; - case BC_KNUM: - dasm_put(Dst, 4231); - break; - case BC_KPRI: - dasm_put(Dst, 4241); - break; - case BC_KNIL: - dasm_put(Dst, 4251, ~LJ_TNIL); - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - dasm_put(Dst, 4270, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_USETV: - dasm_put(Dst, 4286, offsetof(GCfuncL, uvptr), DtA(->marked), DtA(->closed), DtA(->v), LJ_GC_BLACK, -LJ_TISGCV, -(LJ_TISNUM - LJ_TISGCV), Dt4(->gch.marked), -GG_DISP2G, LJ_GC_WHITES); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 4326); - } else { - dasm_put(Dst, 4333); - } - dasm_put(Dst, 4336); - break; - case BC_USETS: - dasm_put(Dst, 4339, offsetof(GCfuncL, uvptr), ~LJ_TSTR, DtA(->marked), DtA(->v), DtA(->closed), LJ_GC_BLACK, Dt5(->marked), LJ_GC_WHITES, -GG_DISP2G); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 4375); - } else { - dasm_put(Dst, 4382); - } - dasm_put(Dst, 4385); - break; - case BC_USETN: - dasm_put(Dst, 4388, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_USETP: - dasm_put(Dst, 4405, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - - case BC_UCLO: - dasm_put(Dst, 4421, Dt1(->openupval), Dt1(->base), Dt1(->base)); - break; - - case BC_FNEW: - dasm_put(Dst, 4444, Dt1(->base), Dt1(->base), ~LJ_TFUNC); - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - case BC_TDUP: - if (op == BC_TDUP) { - dasm_put(Dst, 4465); - } - dasm_put(Dst, 4467, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base)); - if (op == BC_TNEW) { - dasm_put(Dst, 4480); - } else { - dasm_put(Dst, 4489); - } - dasm_put(Dst, 4493, Dt1(->base), ~LJ_TTAB); - break; - - case BC_GGET: - case BC_GSET: - dasm_put(Dst, 4511, Dt7(->env)); - if (op == BC_GGET) { - dasm_put(Dst, 4517); - } else { - dasm_put(Dst, 4520); - } - break; - - case BC_TGETV: - dasm_put(Dst, 4523, -LJ_TTAB, -LJ_TISNUM, Dt6(->array), Dt6(->asize), -LJ_TNIL, Dt6(->metatable), Dt6(->nomm), 1<hmask), Dt5(->hash), Dt6(->node), DtB(->key), DtB(->val), DtB(->next), -LJ_TSTR, -LJ_TNIL, Dt6(->metatable), ~LJ_TNIL, Dt6(->nomm)); - dasm_put(Dst, 4640, 1<asize), Dt6(->array), -LJ_TNIL, Dt6(->metatable), Dt6(->nomm), 1<array), Dt6(->asize), -LJ_TNIL, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<marked), Dt6(->gclist), -LJ_TSTR); - break; - case BC_TSETS: - dasm_put(Dst, 4771, -LJ_TTAB, Dt6(->hmask), Dt5(->hash), Dt6(->node), Dt6(->nomm), DtB(->key), DtB(->val.it), DtB(->next), -LJ_TSTR, Dt6(->marked), -LJ_TNIL, LJ_GC_BLACK, DtB(->val)); - dasm_put(Dst, 4829, Dt6(->metatable), Dt6(->nomm), 1<metatable), Dt1(->base), Dt6(->nomm), 1<base), DISPATCH_GL(gc.grayagain), LJ_GC_BLACK); - dasm_put(Dst, 4882, DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist)); - break; - case BC_TSETB: - dasm_put(Dst, 4891, -LJ_TTAB, Dt6(->asize), Dt6(->array), -LJ_TNIL, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<marked), Dt6(->gclist)); - break; - - case BC_TSETM: - dasm_put(Dst, 4958, Dt6(->asize), Dt6(->array), Dt6(->marked), LJ_GC_BLACK, Dt1(->base)); - if (LJ_TARGET_IOS) { - dasm_put(Dst, 5003, Dt1(->base)); - } - dasm_put(Dst, 5006, DISPATCH_GL(gc.grayagain), LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist)); - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALLM: - dasm_put(Dst, 5022); - break; - case BC_CALL: - dasm_put(Dst, 5028, -LJ_TFUNC, Dt7(->field_pc)); - break; - - case BC_CALLMT: - dasm_put(Dst, 5048); - break; - case BC_CALLT: - dasm_put(Dst, 5053, -LJ_TFUNC, Dt7(->ffid), FRAME_TYPE, Dt7(->field_pc), Dt7(->field_pc), PC2PROTO(k), FRAME_VARG, FRAME_TYPEP); - dasm_put(Dst, 5114, FRAME_TYPE); - break; - - case BC_ITERC: - dasm_put(Dst, 5125, -LJ_TFUNC, Dt7(->field_pc)); - break; - - case BC_ITERN: -#if LJ_HASJIT -#endif - dasm_put(Dst, 5149, Dt6(->asize), Dt6(->array), -LJ_TNIL, ~LJ_TISNUM, Dt6(->hmask), Dt6(->node), DtB(->val), -LJ_TNIL, DtB(->key)); - break; - - case BC_ISNEXT: - dasm_put(Dst, 5214, -LJ_TFUNC, Dt8(->ffid), -LJ_TTAB, -LJ_TNIL, FF_next_N, BC_JMP, BC_ITERC); - break; - - case BC_VARG: - dasm_put(Dst, 5253, FRAME_VARG, ~LJ_TNIL, Dt1(->maxstack), Dt1(->top), Dt1(->base), Dt1(->base)); - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - dasm_put(Dst, 5325); - break; - - case BC_RET: - dasm_put(Dst, 5332, FRAME_TYPE, FRAME_VARG, Dt7(->field_pc), PC2PROTO(k), ~LJ_TNIL, FRAME_TYPEP); - break; - - case BC_RET0: case BC_RET1: - dasm_put(Dst, 5397, FRAME_TYPE, FRAME_VARG); - if (op == BC_RET1) { - dasm_put(Dst, 5408); - } - dasm_put(Dst, 5410); - if (op == BC_RET1) { - dasm_put(Dst, 5413); - } - dasm_put(Dst, 5415, Dt7(->field_pc), PC2PROTO(k), ~LJ_TNIL); - break; - - /* -- Loops and branches ------------------------------------------------ */ - - - case BC_FORL: -#if LJ_HASJIT - dasm_put(Dst, 5441, -GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - vk = (op == BC_IFORL || op == BC_JFORL); - dasm_put(Dst, 5452); - if (op != BC_JFORL) { - dasm_put(Dst, 5454); - } - if (!vk) { - dasm_put(Dst, 5456, -LJ_TISNUM, -LJ_TISNUM, -LJ_TISNUM); - } else { - dasm_put(Dst, 5474, -LJ_TISNUM); - if (op == BC_IFORL) { - dasm_put(Dst, 5482); - } else { - dasm_put(Dst, 5484); - } - dasm_put(Dst, 5487); - } - dasm_put(Dst, 5492); - if (op == BC_FORI) { - dasm_put(Dst, 5494); - } else if (op == BC_JFORI) { - dasm_put(Dst, 5496); - } else if (op == BC_IFORL) { - dasm_put(Dst, 5499); - } - if (vk) { - dasm_put(Dst, 5501); - } - dasm_put(Dst, 5503); - if (op == BC_JFORI || op == BC_JFORL) { - dasm_put(Dst, 5508, BC_JLOOP); - } - dasm_put(Dst, 5511); - if (!vk) { - dasm_put(Dst, 5518); - } else { - dasm_put(Dst, 5520); - } - dasm_put(Dst, 5522); - if (!vk) { - dasm_put(Dst, 5526, -LJ_TISNUM, -LJ_TISNUM); - } else { - dasm_put(Dst, 5538); - } - dasm_put(Dst, 5547); - if (op == BC_FORI) { - dasm_put(Dst, 5551); - } else if (op == BC_JFORI) { - dasm_put(Dst, 5553, BC_JLOOP); - } else if (op == BC_IFORL) { - dasm_put(Dst, 5558); - } else { - dasm_put(Dst, 5560, BC_JLOOP); - } - dasm_put(Dst, 5563); - if (vk) { - dasm_put(Dst, 5569); - } - dasm_put(Dst, 5574); - break; - - case BC_ITERL: -#if LJ_HASJIT - dasm_put(Dst, 5580, -GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - dasm_put(Dst, 5591); - if (op == BC_JITERL) { - dasm_put(Dst, 5593, -LJ_TNIL, BC_JLOOP); - } else { - dasm_put(Dst, 5599, -LJ_TNIL); - } - dasm_put(Dst, 5605); - break; - - case BC_LOOP: -#if LJ_HASJIT - dasm_put(Dst, 5612, -GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_ILOOP: - dasm_put(Dst, 5623); - break; - - case BC_JLOOP: -#if LJ_HASJIT - dasm_put(Dst, 5630, DISPATCH_J(trace), DISPATCH_GL(vmstate), DtD(->mcode), DISPATCH_GL(jit_base), DISPATCH_GL(jit_L)); -#endif - break; - - case BC_JMP: - dasm_put(Dst, 5644); - break; - - /* -- Function headers -------------------------------------------------- */ - - case BC_FUNCF: -#if LJ_HASJIT - dasm_put(Dst, 5653, -GG_DISP2HOT, HOTCOUNT_CALL); -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - dasm_put(Dst, 5664, Dt1(->maxstack), -4+PC2PROTO(numparams), -4+PC2PROTO(k)); - if (op != BC_JFUNCF) { - dasm_put(Dst, 5674); - } - dasm_put(Dst, 5677, ~LJ_TNIL); - if (op == BC_JFUNCF) { - dasm_put(Dst, 5684, BC_JLOOP); - } else { - dasm_put(Dst, 5688); - } - dasm_put(Dst, 5693); - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - dasm_put(Dst, 5699); - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - dasm_put(Dst, 5701, Dt1(->maxstack), 8+FRAME_VARG, -4+PC2PROTO(k), -4+PC2PROTO(numparams), ~LJ_TNIL); - break; - - case BC_FUNCC: - case BC_FUNCCW: - if (op == BC_FUNCC) { - dasm_put(Dst, 5742, Dt8(->f)); - } else { - dasm_put(Dst, 5745, DISPATCH_GL(wrapf)); - } - dasm_put(Dst, 5748, Dt1(->maxstack), Dt1(->base), Dt1(->top)); - if (op == BC_FUNCCW) { - dasm_put(Dst, 5758, Dt8(->f)); - } - dasm_put(Dst, 5761, LJ_VMST_C, DISPATCH_GL(vmstate), Dt1(->base), LJ_VMST_INTERP, Dt1(->top), DISPATCH_GL(vmstate)); - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx); - - dasm_put(Dst, 5783); - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); - int i; - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",%%progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.long .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.long 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 0xe\n" /* Return address is in lr. */ - "\t.byte 0xc\n\t.uleb128 0xd\n\t.uleb128 0\n" /* def_cfa sp */ - "\t.align 2\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.long .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.long .Lframe0\n" - "\t.long .Lbegin\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x8e\n\t.uleb128 1\n", /* offset lr */ - fcofs, CFRAME_SIZE); - for (i = 11; i >= 4; i--) /* offset r4-r11 */ - fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 2+(11-i)); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE0:\n\n"); -#if LJ_HASFFI - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.long .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.long .Lframe0\n" - "\t.long lj_vm_ffi_call\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ - "\t.byte 0x8e\n\t.uleb128 1\n" /* offset lr */ - "\t.byte 0x8b\n\t.uleb128 2\n" /* offset r11 */ - "\t.byte 0x85\n\t.uleb128 3\n" /* offset r5 */ - "\t.byte 0x84\n\t.uleb128 4\n" /* offset r4 */ - "\t.byte 0xd\n\t.uleb128 0xb\n" /* def_cfa_register r11 */ - "\t.align 2\n" - ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); -#endif - break; - default: - break; - } -} - diff --git a/src/buildvm_asm.c b/src/buildvm_asm.c deleted file mode 100644 index f975eadc..00000000 --- a/src/buildvm_asm.c +++ /dev/null @@ -1,283 +0,0 @@ -/* -** LuaJIT VM builder: Assembler source code emitter. -** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -*/ - -#include "buildvm.h" -#include "lj_bc.h" - -/* ------------------------------------------------------------------------ */ - -#if LJ_TARGET_X86ORX64 -/* Emit bytes piecewise as assembler text. */ -static void emit_asm_bytes(BuildCtx *ctx, uint8_t *p, int n) -{ - int i; - for (i = 0; i < n; i++) { - if ((i & 15) == 0) - fprintf(ctx->fp, "\t.byte %d", p[i]); - else - fprintf(ctx->fp, ",%d", p[i]); - if ((i & 15) == 15) putc('\n', ctx->fp); - } - if ((n & 15) != 0) putc('\n', ctx->fp); -} - -/* Emit relocation */ -static void emit_asm_reloc(BuildCtx *ctx, int type, const char *sym) -{ - switch (ctx->mode) { - case BUILD_elfasm: - if (type) - fprintf(ctx->fp, "\t.long %s-.-4\n", sym); - else - fprintf(ctx->fp, "\t.long %s\n", sym); - break; - case BUILD_coffasm: - fprintf(ctx->fp, "\t.def %s; .scl 3; .type 32; .endef\n", sym); - if (type) - fprintf(ctx->fp, "\t.long %s-.-4\n", sym); - else - fprintf(ctx->fp, "\t.long %s\n", sym); - break; - default: /* BUILD_machasm for relative relocations handled below. */ - fprintf(ctx->fp, "\t.long %s\n", sym); - break; - } -} - -static const char *const jccnames[] = { - "jo", "jno", "jb", "jnb", "jz", "jnz", "jbe", "ja", - "js", "jns", "jpe", "jpo", "jl", "jge", "jle", "jg" -}; - -/* Emit relocation for the incredibly stupid OSX assembler. */ -static void emit_asm_reloc_mach(BuildCtx *ctx, uint8_t *cp, int n, - const char *sym) -{ - const char *opname = NULL; - if (--n < 0) goto err; - if (cp[n] == 0xe8) { - opname = "call"; - } else if (cp[n] == 0xe9) { - opname = "jmp"; - } else if (cp[n] >= 0x80 && cp[n] <= 0x8f && n > 0 && cp[n-1] == 0x0f) { - opname = jccnames[cp[n]-0x80]; - n--; - } else { -err: - fprintf(stderr, "Error: unsupported opcode for %s symbol relocation.\n", - sym); - exit(1); - } - emit_asm_bytes(ctx, cp, n); - fprintf(ctx->fp, "\t%s %s\n", opname, sym); -} -#else -/* Emit words piecewise as assembler text. */ -static void emit_asm_words(BuildCtx *ctx, uint8_t *p, int n) -{ - int i; - for (i = 0; i < n; i += 4) { - if ((i & 15) == 0) - fprintf(ctx->fp, "\t.long 0x%08x", *(uint32_t *)(p+i)); - else - fprintf(ctx->fp, ",0x%08x", *(uint32_t *)(p+i)); - if ((i & 15) == 12) putc('\n', ctx->fp); - } - if ((n & 15) != 0) putc('\n', ctx->fp); -} - -/* Emit relocation as part of an instruction. */ -static void emit_asm_wordreloc(BuildCtx *ctx, uint8_t *p, int n, - const char *sym) -{ - uint32_t ins; - emit_asm_words(ctx, p, n-4); - ins = *(uint32_t *)(p+n-4); -#if LJ_TARGET_ARM - if ((ins & 0xff000000u) == 0xfa000000u) { - fprintf(ctx->fp, "\tblx %s\n", sym); - } else if ((ins & 0x0e000000u) == 0x0a000000u) { - fprintf(ctx->fp, "\t%s%.2s %s\n", (ins & 0x01000000u) ? "bl" : "b", - "eqnecsccmiplvsvchilsgeltgtle" + 2*(ins >> 28), sym); - } else { - fprintf(stderr, - "Error: unsupported opcode %08x for %s symbol relocation.\n", - ins, sym); - exit(1); - } -#elif LJ_TARGET_PPC || LJ_TARGET_PPCSPE - if ((ins >> 26) == 16) { - fprintf(ctx->fp, "\t%s %d, %d, %s\n", - (ins & 1) ? "bcl" : "bc", (ins >> 21) & 31, (ins >> 16) & 31, sym); - } else if ((ins >> 26) == 18) { - fprintf(ctx->fp, "\t%s %s\n", (ins & 1) ? "bl" : "b", sym); - } else { - fprintf(stderr, - "Error: unsupported opcode %08x for %s symbol relocation.\n", - ins, sym); - exit(1); - } -#elif LJ_TARGET_MIPS - fprintf(stderr, - "Error: unsupported opcode %08x for %s symbol relocation.\n", - ins, sym); - exit(1); -#else -#error "missing relocation support for this architecture" -#endif -} -#endif - -#if LJ_TARGET_ARM -#define ELFASM_PX "%%" -#else -#define ELFASM_PX "@" -#endif - -/* Emit an assembler label. */ -static void emit_asm_label(BuildCtx *ctx, const char *name, int size, int isfunc) -{ - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, - "\n\t.globl %s\n" - "\t.hidden %s\n" - "\t.type %s, " ELFASM_PX "%s\n" - "\t.size %s, %d\n" - "%s:\n", - name, name, name, isfunc ? "function" : "object", name, size, name); - break; - case BUILD_coffasm: - fprintf(ctx->fp, "\n\t.globl %s\n", name); - if (isfunc) - fprintf(ctx->fp, "\t.def %s; .scl 3; .type 32; .endef\n", name); - fprintf(ctx->fp, "%s:\n", name); - break; - case BUILD_machasm: - fprintf(ctx->fp, - "\n\t.private_extern %s\n" - "%s:\n", name, name); - break; - default: - break; - } -} - -/* Emit alignment. */ -static void emit_asm_align(BuildCtx *ctx, int bits) -{ - switch (ctx->mode) { - case BUILD_elfasm: - case BUILD_coffasm: - fprintf(ctx->fp, "\t.p2align %d\n", bits); - break; - case BUILD_machasm: - fprintf(ctx->fp, "\t.align %d\n", bits); - break; - default: - break; - } -} - -/* ------------------------------------------------------------------------ */ - -/* Emit assembler source code. */ -void emit_asm(BuildCtx *ctx) -{ - int i, rel; - - fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch); - fprintf(ctx->fp, "\t.text\n"); - emit_asm_align(ctx, 4); - - emit_asm_label(ctx, ctx->beginsym, 0, 0); - if (ctx->mode != BUILD_machasm) - fprintf(ctx->fp, ".Lbegin:\n"); - -#if LJ_TARGET_ARM && defined(__GNUC__) && !defined(LUAJIT_NO_UNWIND) - /* This should really be moved into buildvm_arm.dasc. */ - fprintf(ctx->fp, - ".fnstart\n" - ".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" - ".pad #28\n"); -#endif -#if LJ_TARGET_MIPS - fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n"); -#endif - - for (i = rel = 0; i < ctx->nsym; i++) { - int32_t ofs = ctx->sym[i].ofs; - int32_t next = ctx->sym[i+1].ofs; -#if LJ_TARGET_ARM && defined(__GNUC__) && !defined(LUAJIT_NO_UNWIND) && \ - LJ_HASFFI - if (!strcmp(ctx->sym[i].name, "lj_vm_ffi_call")) - fprintf(ctx->fp, - ".globl lj_err_unwind_arm\n" - ".personality lj_err_unwind_arm\n" - ".fnend\n" - ".fnstart\n" - ".save {r4, r5, r11, lr}\n" - ".setfp r11, sp\n"); -#endif - emit_asm_label(ctx, ctx->sym[i].name, next - ofs, 1); - while (rel < ctx->nreloc && ctx->reloc[rel].ofs <= next) { - BuildReloc *r = &ctx->reloc[rel]; - int n = r->ofs - ofs; -#if LJ_TARGET_X86ORX64 - if (ctx->mode == BUILD_machasm && r->type != 0) { - emit_asm_reloc_mach(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]); - } else { - emit_asm_bytes(ctx, ctx->code+ofs, n); - emit_asm_reloc(ctx, r->type, ctx->relocsym[r->sym]); - } - ofs += n+4; -#else - emit_asm_wordreloc(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]); - ofs += n; -#endif - rel++; - } -#if LJ_TARGET_X86ORX64 - emit_asm_bytes(ctx, ctx->code+ofs, next-ofs); -#else - emit_asm_words(ctx, ctx->code+ofs, next-ofs); -#endif - } - -#if LJ_TARGET_ARM && defined(__GNUC__) && !defined(LUAJIT_NO_UNWIND) - fprintf(ctx->fp, -#if !LJ_HASFFI - ".globl lj_err_unwind_arm\n" - ".personality lj_err_unwind_arm\n" -#endif - ".fnend\n"); -#endif - - fprintf(ctx->fp, "\n"); - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n"); -#if LJ_TARGET_PPCSPE - /* Soft-float ABI + SPE. */ - fprintf(ctx->fp, "\t.gnu_attribute 4, 2\n\t.gnu_attribute 8, 3\n"); -#elif LJ_TARGET_PPC - /* Hard-float ABI. */ - fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n"); -#endif - /* fallthrough */ - case BUILD_coffasm: - fprintf(ctx->fp, "\t.ident \"%s\"\n", ctx->dasm_ident); - break; - case BUILD_machasm: - fprintf(ctx->fp, - "\t.cstring\n" - "\t.ascii \"%s\\0\"\n", ctx->dasm_ident); - break; - default: - break; - } - fprintf(ctx->fp, "\n"); -} - diff --git a/src/buildvm_fold.c b/src/buildvm_fold.c deleted file mode 100644 index 73f4f80a..00000000 --- a/src/buildvm_fold.c +++ /dev/null @@ -1,229 +0,0 @@ -/* -** LuaJIT VM builder: IR folding hash table generator. -** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -*/ - -#include "buildvm.h" -#include "lj_obj.h" -#include "lj_ir.h" - -/* Context for the folding hash table generator. */ -static int lineno; -static int funcidx; -static uint32_t foldkeys[BUILD_MAX_FOLD]; -static uint32_t nkeys; - -/* Try to fill the hash table with keys using the hash parameters. */ -static int tryhash(uint32_t *htab, uint32_t sz, uint32_t r, int dorol) -{ - uint32_t i; - if (dorol && ((r & 31) == 0 || (r>>5) == 0)) - return 0; /* Avoid zero rotates. */ - memset(htab, 0xff, (sz+1)*sizeof(uint32_t)); - for (i = 0; i < nkeys; i++) { - uint32_t key = foldkeys[i]; - uint32_t k = key & 0xffffff; - uint32_t h = (dorol ? lj_rol(lj_rol(k, r>>5) - k, r&31) : - (((k << (r>>5)) - k) << (r&31))) % sz; - if (htab[h] != 0xffffffff) { /* Collision on primary slot. */ - if (htab[h+1] != 0xffffffff) { /* Collision on secondary slot. */ - /* Try to move the colliding key, if possible. */ - if (h < sz-1 && htab[h+2] == 0xffffffff) { - uint32_t k2 = htab[h+1] & 0xffffff; - uint32_t h2 = (dorol ? lj_rol(lj_rol(k2, r>>5) - k2, r&31) : - (((k2 << (r>>5)) - k2) << (r&31))) % sz; - if (h2 != h+1) return 0; /* Cannot resolve collision. */ - htab[h+2] = htab[h+1]; /* Move colliding key to secondary slot. */ - } else { - return 0; /* Collision. */ - } - } - htab[h+1] = key; - } else { - htab[h] = key; - } - } - return 1; /* Success, all keys could be stored. */ -} - -/* Print the generated hash table. */ -static void printhash(BuildCtx *ctx, uint32_t *htab, uint32_t sz) -{ - uint32_t i; - fprintf(ctx->fp, "static const uint32_t fold_hash[%d] = {\n0x%08x", - sz+1, htab[0]); - for (i = 1; i < sz+1; i++) - fprintf(ctx->fp, ",\n0x%08x", htab[i]); - fprintf(ctx->fp, "\n};\n\n"); -} - -/* Exhaustive search for the shortest semi-perfect hash table. */ -static void makehash(BuildCtx *ctx) -{ - uint32_t htab[BUILD_MAX_FOLD*2+1]; - uint32_t sz, r; - /* Search for the smallest hash table with an odd size. */ - for (sz = (nkeys|1); sz < BUILD_MAX_FOLD*2; sz += 2) { - /* First try all shift hash combinations. */ - for (r = 0; r < 32*32; r++) { - if (tryhash(htab, sz, r, 0)) { - printhash(ctx, htab, sz); - fprintf(ctx->fp, - "#define fold_hashkey(k)\t(((((k)<<%u)-(k))<<%u)%%%u)\n\n", - r>>5, r&31, sz); - return; - } - } - /* Then try all rotate hash combinations. */ - for (r = 0; r < 32*32; r++) { - if (tryhash(htab, sz, r, 1)) { - printhash(ctx, htab, sz); - fprintf(ctx->fp, - "#define fold_hashkey(k)\t(lj_rol(lj_rol((k),%u)-(k),%u)%%%u)\n\n", - r>>5, r&31, sz); - return; - } - } - } - fprintf(stderr, "Error: search for perfect hash failed\n"); - exit(1); -} - -/* Parse one token of a fold rule. */ -static uint32_t nexttoken(char **pp, int allowlit, int allowany) -{ - char *p = *pp; - if (p) { - uint32_t i; - char *q = strchr(p, ' '); - if (q) *q++ = '\0'; - *pp = q; - if (allowlit && !strncmp(p, "IRFPM_", 6)) { - for (i = 0; irfpm_names[i]; i++) - if (!strcmp(irfpm_names[i], p+6)) - return i; - } else if (allowlit && !strncmp(p, "IRFL_", 5)) { - for (i = 0; irfield_names[i]; i++) - if (!strcmp(irfield_names[i], p+5)) - return i; - } else if (allowlit && !strncmp(p, "IRCALL_", 7)) { - for (i = 0; ircall_names[i]; i++) - if (!strcmp(ircall_names[i], p+7)) - return i; - } else if (allowlit && !strncmp(p, "IRCONV_", 7)) { - for (i = 0; irt_names[i]; i++) { - const char *r = strchr(p+7, '_'); - if (r && !strncmp(irt_names[i], p+7, r-(p+7))) { - uint32_t j; - for (j = 0; irt_names[j]; j++) - if (!strcmp(irt_names[j], r+1)) - return (i << 5) + j; - } - } - } else if (allowlit && *p >= '0' && *p <= '9') { - for (i = 0; *p >= '0' && *p <= '9'; p++) - i = i*10 + (*p - '0'); - if (*p == '\0') - return i; - } else if (allowany && !strcmp("any", p)) { - return allowany; - } else { - for (i = 0; ir_names[i]; i++) - if (!strcmp(ir_names[i], p)) - return i; - } - fprintf(stderr, "Error: bad fold definition token \"%s\" at line %d\n", p, lineno); - exit(1); - } - return 0; -} - -/* Parse a fold rule. */ -static void foldrule(char *p) -{ - uint32_t op = nexttoken(&p, 0, 0); - uint32_t left = nexttoken(&p, 0, 0x7f); - uint32_t right = nexttoken(&p, 1, 0x3ff); - uint32_t key = (funcidx << 24) | (op << 17) | (left << 10) | right; - uint32_t i; - if (nkeys >= BUILD_MAX_FOLD) { - fprintf(stderr, "Error: too many fold rules, increase BUILD_MAX_FOLD.\n"); - exit(1); - } - /* Simple insertion sort to detect duplicates. */ - for (i = nkeys; i > 0; i--) { - if ((foldkeys[i-1]&0xffffff) < (key & 0xffffff)) - break; - if ((foldkeys[i-1]&0xffffff) == (key & 0xffffff)) { - fprintf(stderr, "Error: duplicate fold definition at line %d\n", lineno); - exit(1); - } - foldkeys[i] = foldkeys[i-1]; - } - foldkeys[i] = key; - nkeys++; -} - -/* Emit C source code for IR folding hash table. */ -void emit_fold(BuildCtx *ctx) -{ - char buf[256]; /* We don't care about analyzing lines longer than that. */ - const char *fname = ctx->args[0]; - FILE *fp; - - if (fname == NULL) { - fprintf(stderr, "Error: missing input filename\n"); - exit(1); - } - - if (fname[0] == '-' && fname[1] == '\0') { - fp = stdin; - } else { - fp = fopen(fname, "r"); - if (!fp) { - fprintf(stderr, "Error: cannot open input file '%s': %s\n", - fname, strerror(errno)); - exit(1); - } - } - - fprintf(ctx->fp, "/* This is a generated file. DO NOT EDIT! */\n\n"); - fprintf(ctx->fp, "static const FoldFunc fold_func[] = {\n"); - - lineno = 0; - funcidx = 0; - nkeys = 0; - while (fgets(buf, sizeof(buf), fp) != NULL) { - lineno++; - /* The prefix must be at the start of a line, otherwise it's ignored. */ - if (!strncmp(buf, FOLDDEF_PREFIX, sizeof(FOLDDEF_PREFIX)-1)) { - char *p = buf+sizeof(FOLDDEF_PREFIX)-1; - char *q = strchr(p, ')'); - if (p[0] == '(' && q) { - p++; - *q = '\0'; - foldrule(p); - } else if ((p[0] == 'F' || p[0] == 'X') && p[1] == '(' && q) { - p += 2; - *q = '\0'; - if (funcidx) - fprintf(ctx->fp, ",\n"); - if (p[-2] == 'X') - fprintf(ctx->fp, " %s", p); - else - fprintf(ctx->fp, " fold_%s", p); - funcidx++; - } else { - buf[strlen(buf)-1] = '\0'; - fprintf(stderr, "Error: unknown fold definition tag %s%s at line %d\n", - FOLDDEF_PREFIX, p, lineno); - exit(1); - } - } - } - fclose(fp); - fprintf(ctx->fp, "\n};\n\n"); - - makehash(ctx); -} - diff --git a/src/buildvm_lib.c b/src/buildvm_lib.c deleted file mode 100644 index 3231d3ad..00000000 --- a/src/buildvm_lib.c +++ /dev/null @@ -1,377 +0,0 @@ -/* -** LuaJIT VM builder: library definition compiler. -** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -*/ - -#include "buildvm.h" -#include "lj_obj.h" -#include "lj_lib.h" - -/* Context for library definitions. */ -static uint8_t obuf[8192]; -static uint8_t *optr; -static char modname[80]; -static size_t modnamelen; -static char funcname[80]; -static int modstate, regfunc; -static int ffid, recffid, ffasmfunc; - -enum { - REGFUNC_OK, - REGFUNC_NOREG, - REGFUNC_NOREGUV -}; - -static void libdef_name(const char *p, int kind) -{ - size_t n = strlen(p); - if (kind != LIBINIT_STRING) { - if (n > modnamelen && p[modnamelen] == '_' && - !strncmp(p, modname, modnamelen)) { - p += modnamelen+1; - n -= modnamelen+1; - } - } - if (n > LIBINIT_MAXSTR) { - fprintf(stderr, "Error: string too long: '%s'\n", p); - exit(1); - } - if (optr+1+n+2 > obuf+sizeof(obuf)) { /* +2 for caller. */ - fprintf(stderr, "Error: output buffer overflow\n"); - exit(1); - } - *optr++ = (uint8_t)(n | kind); - memcpy(optr, p, n); - optr += n; -} - -static void libdef_endmodule(BuildCtx *ctx) -{ - if (modstate != 0) { - char line[80]; - const uint8_t *p; - int n; - if (modstate == 1) - fprintf(ctx->fp, " (lua_CFunction)0"); - fprintf(ctx->fp, "\n};\n"); - fprintf(ctx->fp, "static const uint8_t %s%s[] = {\n", - LABEL_PREFIX_LIBINIT, modname); - line[0] = '\0'; - for (n = 0, p = obuf; p < optr; p++) { - n += sprintf(line+n, "%d,", *p); - if (n >= 75) { - fprintf(ctx->fp, "%s\n", line); - n = 0; - line[0] = '\0'; - } - } - fprintf(ctx->fp, "%s%d\n};\n#endif\n\n", line, LIBINIT_END); - } -} - -static void libdef_module(BuildCtx *ctx, char *p, int arg) -{ - UNUSED(arg); - if (ctx->mode == BUILD_libdef) { - libdef_endmodule(ctx); - optr = obuf; - *optr++ = (uint8_t)ffid; - *optr++ = (uint8_t)ffasmfunc; - *optr++ = 0; /* Hash table size. */ - modstate = 1; - fprintf(ctx->fp, "#ifdef %sMODULE_%s\n", LIBDEF_PREFIX, p); - fprintf(ctx->fp, "#undef %sMODULE_%s\n", LIBDEF_PREFIX, p); - fprintf(ctx->fp, "static const lua_CFunction %s%s[] = {\n", - LABEL_PREFIX_LIBCF, p); - } - modnamelen = strlen(p); - if (modnamelen > sizeof(modname)-1) { - fprintf(stderr, "Error: module name too long: '%s'\n", p); - exit(1); - } - strcpy(modname, p); -} - -static int find_ffofs(BuildCtx *ctx, const char *name) -{ - int i; - for (i = 0; i < ctx->nglob; i++) { - const char *gl = ctx->globnames[i]; - if (gl[0] == 'f' && gl[1] == 'f' && gl[2] == '_' && !strcmp(gl+3, name)) { - return (int)((uint8_t *)ctx->glob[i] - ctx->code); - } - } - fprintf(stderr, "Error: undefined fast function %s%s\n", - LABEL_PREFIX_FF, name); - exit(1); -} - -static void libdef_func(BuildCtx *ctx, char *p, int arg) -{ - if (arg != LIBINIT_CF) - ffasmfunc++; - if (ctx->mode == BUILD_libdef) { - if (modstate == 0) { - fprintf(stderr, "Error: no module for function definition %s\n", p); - exit(1); - } - if (regfunc == REGFUNC_NOREG) { - if (optr+1 > obuf+sizeof(obuf)) { - fprintf(stderr, "Error: output buffer overflow\n"); - exit(1); - } - *optr++ = LIBINIT_FFID; - } else { - if (arg != LIBINIT_ASM_) { - if (modstate != 1) fprintf(ctx->fp, ",\n"); - modstate = 2; - fprintf(ctx->fp, " %s%s", arg ? LABEL_PREFIX_FFH : LABEL_PREFIX_CF, p); - } - if (regfunc != REGFUNC_NOREGUV) obuf[2]++; /* Bump hash table size. */ - libdef_name(regfunc == REGFUNC_NOREGUV ? "" : p, arg); - } - } else if (ctx->mode == BUILD_ffdef) { - fprintf(ctx->fp, "FFDEF(%s)\n", p); - } else if (ctx->mode == BUILD_recdef) { - if (strlen(p) > sizeof(funcname)-1) { - fprintf(stderr, "Error: function name too long: '%s'\n", p); - exit(1); - } - strcpy(funcname, p); - } else if (ctx->mode == BUILD_vmdef) { - int i; - for (i = 1; p[i] && modname[i-1]; i++) - if (p[i] == '_') p[i] = '.'; - fprintf(ctx->fp, "\"%s\",\n", p); - } else if (ctx->mode == BUILD_bcdef) { - if (arg != LIBINIT_CF) - fprintf(ctx->fp, ",\n%d", find_ffofs(ctx, p)); - } - ffid++; - regfunc = REGFUNC_OK; -} - -static uint32_t find_rec(char *name) -{ - char *p = (char *)obuf; - uint32_t n; - for (n = 2; *p; n++) { - if (strcmp(p, name) == 0) - return n; - p += strlen(p)+1; - } - if (p+strlen(name)+1 >= (char *)obuf+sizeof(obuf)) { - fprintf(stderr, "Error: output buffer overflow\n"); - exit(1); - } - strcpy(p, name); - return n; -} - -static void libdef_rec(BuildCtx *ctx, char *p, int arg) -{ - UNUSED(arg); - if (ctx->mode == BUILD_recdef) { - char *q; - uint32_t n; - for (; recffid+1 < ffid; recffid++) - fprintf(ctx->fp, ",\n0"); - recffid = ffid; - if (*p == '.') p = funcname; - q = strchr(p, ' '); - if (q) *q++ = '\0'; - n = find_rec(p); - if (q) - fprintf(ctx->fp, ",\n0x%02x00+(%s)", n, q); - else - fprintf(ctx->fp, ",\n0x%02x00", n); - } -} - -static void memcpy_endian(void *dst, void *src, size_t n) -{ - union { uint8_t b; uint32_t u; } host_endian; - host_endian.u = 1; - if (host_endian.b == LJ_ENDIAN_SELECT(1, 0)) { - memcpy(dst, src, n); - } else { - size_t i; - for (i = 0; i < n; i++) - ((uint8_t *)dst)[i] = ((uint8_t *)src)[n-i-1]; - } -} - -static void libdef_push(BuildCtx *ctx, char *p, int arg) -{ - UNUSED(arg); - if (ctx->mode == BUILD_libdef) { - int len = (int)strlen(p); - if (*p == '"') { - if (len > 1 && p[len-1] == '"') { - p[len-1] = '\0'; - libdef_name(p+1, LIBINIT_STRING); - return; - } - } else if (*p >= '0' && *p <= '9') { - char *ep; - double d = strtod(p, &ep); - if (*ep == '\0') { - if (optr+1+sizeof(double) > obuf+sizeof(obuf)) { - fprintf(stderr, "Error: output buffer overflow\n"); - exit(1); - } - *optr++ = LIBINIT_NUMBER; - memcpy_endian(optr, &d, sizeof(double)); - optr += sizeof(double); - return; - } - } else if (!strcmp(p, "lastcl")) { - if (optr+1 > obuf+sizeof(obuf)) { - fprintf(stderr, "Error: output buffer overflow\n"); - exit(1); - } - *optr++ = LIBINIT_LASTCL; - return; - } else if (len > 4 && !strncmp(p, "top-", 4)) { - if (optr+2 > obuf+sizeof(obuf)) { - fprintf(stderr, "Error: output buffer overflow\n"); - exit(1); - } - *optr++ = LIBINIT_COPY; - *optr++ = (uint8_t)atoi(p+4); - return; - } - fprintf(stderr, "Error: bad value for %sPUSH(%s)\n", LIBDEF_PREFIX, p); - exit(1); - } -} - -static void libdef_set(BuildCtx *ctx, char *p, int arg) -{ - UNUSED(arg); - if (ctx->mode == BUILD_libdef) { - if (p[0] == '!' && p[1] == '\0') p[0] = '\0'; /* Set env. */ - libdef_name(p, LIBINIT_STRING); - *optr++ = LIBINIT_SET; - obuf[2]++; /* Bump hash table size. */ - } -} - -static void libdef_regfunc(BuildCtx *ctx, char *p, int arg) -{ - UNUSED(ctx); UNUSED(p); - regfunc = arg; -} - -typedef void (*LibDefFunc)(BuildCtx *ctx, char *p, int arg); - -typedef struct LibDefHandler { - const char *suffix; - const char *stop; - const LibDefFunc func; - const int arg; -} LibDefHandler; - -static const LibDefHandler libdef_handlers[] = { - { "MODULE_", " \t\r\n", libdef_module, 0 }, - { "CF(", ")", libdef_func, LIBINIT_CF }, - { "ASM(", ")", libdef_func, LIBINIT_ASM }, - { "ASM_(", ")", libdef_func, LIBINIT_ASM_ }, - { "REC(", ")", libdef_rec, 0 }, - { "PUSH(", ")", libdef_push, 0 }, - { "SET(", ")", libdef_set, 0 }, - { "NOREGUV", NULL, libdef_regfunc, REGFUNC_NOREGUV }, - { "NOREG", NULL, libdef_regfunc, REGFUNC_NOREG }, - { NULL, NULL, (LibDefFunc)0, 0 } -}; - -/* Emit C source code for library function definitions. */ -void emit_lib(BuildCtx *ctx) -{ - const char *fname; - - if (ctx->mode == BUILD_ffdef || ctx->mode == BUILD_libdef || - ctx->mode == BUILD_recdef) - fprintf(ctx->fp, "/* This is a generated file. DO NOT EDIT! */\n\n"); - else if (ctx->mode == BUILD_vmdef) - fprintf(ctx->fp, "ffnames = {\n[0]=\"Lua\",\n\"C\",\n"); - if (ctx->mode == BUILD_recdef) - fprintf(ctx->fp, "static const uint16_t recff_idmap[] = {\n0,\n0x0100"); - recffid = ffid = FF_C+1; - ffasmfunc = 0; - - while ((fname = *ctx->args++)) { - char buf[256]; /* We don't care about analyzing lines longer than that. */ - FILE *fp; - if (fname[0] == '-' && fname[1] == '\0') { - fp = stdin; - } else { - fp = fopen(fname, "r"); - if (!fp) { - fprintf(stderr, "Error: cannot open input file '%s': %s\n", - fname, strerror(errno)); - exit(1); - } - } - modstate = 0; - regfunc = REGFUNC_OK; - while (fgets(buf, sizeof(buf), fp) != NULL) { - char *p; - for (p = buf; (p = strstr(p, LIBDEF_PREFIX)) != NULL; ) { - const LibDefHandler *ldh; - p += sizeof(LIBDEF_PREFIX)-1; - for (ldh = libdef_handlers; ldh->suffix != NULL; ldh++) { - size_t n, len = strlen(ldh->suffix); - if (!strncmp(p, ldh->suffix, len)) { - p += len; - n = ldh->stop ? strcspn(p, ldh->stop) : 0; - if (!p[n]) break; - p[n] = '\0'; - ldh->func(ctx, p, ldh->arg); - p += n+1; - break; - } - } - if (ldh->suffix == NULL) { - buf[strlen(buf)-1] = '\0'; - fprintf(stderr, "Error: unknown library definition tag %s%s\n", - LIBDEF_PREFIX, p); - exit(1); - } - } - } - fclose(fp); - if (ctx->mode == BUILD_libdef) { - libdef_endmodule(ctx); - } - } - - if (ctx->mode == BUILD_ffdef) { - fprintf(ctx->fp, "\n#undef FFDEF\n\n"); - fprintf(ctx->fp, - "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n", - ffasmfunc); - } else if (ctx->mode == BUILD_vmdef) { - fprintf(ctx->fp, "}\n\n"); - } else if (ctx->mode == BUILD_bcdef) { - int i; - fprintf(ctx->fp, "\n};\n\n"); - fprintf(ctx->fp, "LJ_DATADEF const uint16_t lj_bc_mode[] = {\n"); - fprintf(ctx->fp, "BCDEF(BCMODE)\n"); - for (i = ffasmfunc-1; i > 0; i--) - fprintf(ctx->fp, "BCMODE_FF,\n"); - fprintf(ctx->fp, "BCMODE_FF\n};\n\n"); - } else if (ctx->mode == BUILD_recdef) { - char *p = (char *)obuf; - fprintf(ctx->fp, "\n};\n\n"); - fprintf(ctx->fp, "static const RecordFunc recff_func[] = {\n" - "recff_nyi,\n" - "recff_c"); - while (*p) { - fprintf(ctx->fp, ",\nrecff_%s", p); - p += strlen(p)+1; - } - fprintf(ctx->fp, "\n};\n\n"); - } -} - diff --git a/src/buildvm_mips.dasc b/src/buildvm_mips.dasc deleted file mode 100644 index a7c3b4ae..00000000 --- a/src/buildvm_mips.dasc +++ /dev/null @@ -1,4224 +0,0 @@ -|// Low-level VM code for MIPS CPUs. -|// Bytecode interpreter, fast functions and helper functions. -|// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -| -|.arch mips -|.section code_op, code_sub -| -|.actionlist build_actionlist -|.globals GLOB_ -|.globalnames globnames -|.externnames extnames -| -|// Note: The ragged indentation of the instructions is intentional. -|// The starting columns indicate data dependencies. -| -|//----------------------------------------------------------------------- -| -|// Fixed register assignments for the interpreter. -|// Don't use: r0 = 0, r26/r27 = reserved, r28 = gp, r29 = sp, r31 = ra -| -|// The following must be C callee-save (but BASE is often refetched). -|.define BASE, r16 // Base of current Lua stack frame. -|.define KBASE, r17 // Constants of current Lua function. -|.define PC, r18 // Next PC. -|.define DISPATCH, r19 // Opcode dispatch table. -|.define LREG, r20 // Register holding lua_State (also in SAVE_L). -|.define MULTRES, r21 // Size of multi-result: (nresults+1)*8. -|// NYI: r22 currently unused. -| -|.define JGL, r30 // On-trace: global_State + 32768. -| -|// Constants for type-comparisons, stores and conversions. C callee-save. -|.define TISNIL, r30 -|.define TOBIT, f30 // 2^52 + 2^51. -| -|// The following temporaries are not saved across C calls, except for RA. -|.define RA, r23 // Callee-save. -|.define RB, r8 -|.define RC, r9 -|.define RD, r10 -|.define INS, r11 -| -|.define AT, r1 // Assembler temporary. -|.define TMP0, r12 -|.define TMP1, r13 -|.define TMP2, r14 -|.define TMP3, r15 -| -|// Calling conventions. -|.define CFUNCADDR, r25 -|.define CARG1, r4 -|.define CARG2, r5 -|.define CARG3, r6 -|.define CARG4, r7 -| -|.define CRET1, r2 -|.define CRET2, r3 -| -|.define FARG1, f12 -|.define FARG2, f14 -| -|.define FRET1, f0 -|.define FRET2, f2 -| -|// Stack layout while in interpreter. Must match with lj_frame.h. -|.define CFRAME_SPACE, 112 // Delta for sp. -| -|.define SAVE_ERRF, 124(sp) // 32 bit C frame info. -|.define SAVE_NRES, 120(sp) -|.define SAVE_CFRAME, 116(sp) -|.define SAVE_L, 112(sp) -|//----- 8 byte aligned, ^^^^ 16 byte register save area, owned by interpreter. -|.define SAVE_GPR_, 72 // .. 72+10*4: 32 bit GPR saves. -|.define SAVE_FPR_, 24 // .. 24+6*8: 64 bit FPR saves. -|.define SAVE_PC, 20(sp) -|.define ARG5, 16(sp) -|.define CSAVE_4, 12(sp) -|.define CSAVE_3, 8(sp) -|.define CSAVE_2, 4(sp) -|.define CSAVE_1, 0(sp) -|//----- 8 byte aligned, ^^^^ 16 byte register save area, owned by callee. -| -|.define ARG5_OFS, 16 -|.define SAVE_MULTRES, ARG5 -| -|.macro saveregs -| addiu sp, sp, -CFRAME_SPACE -| sw ra, SAVE_GPR_+9*4(sp) -| sw r30, SAVE_GPR_+8*4(sp) -| sdc1 f30, SAVE_FPR_+5*8(sp) -| sw r23, SAVE_GPR_+7*4(sp) -| sw r22, SAVE_GPR_+6*4(sp) -| sdc1 f28, SAVE_FPR_+4*8(sp) -| sw r21, SAVE_GPR_+5*4(sp) -| sw r20, SAVE_GPR_+4*4(sp) -| sdc1 f26, SAVE_FPR_+3*8(sp) -| sw r19, SAVE_GPR_+3*4(sp) -| sw r18, SAVE_GPR_+2*4(sp) -| sdc1 f24, SAVE_FPR_+2*8(sp) -| sw r17, SAVE_GPR_+1*4(sp) -| sw r16, SAVE_GPR_+0*4(sp) -| sdc1 f22, SAVE_FPR_+1*8(sp) -| sdc1 f20, SAVE_FPR_+0*8(sp) -|.endmacro -| -|.macro restoreregs_ret -| lw ra, SAVE_GPR_+9*4(sp) -| lw r30, SAVE_GPR_+8*4(sp) -| ldc1 f30, SAVE_FPR_+5*8(sp) -| lw r23, SAVE_GPR_+7*4(sp) -| lw r22, SAVE_GPR_+6*4(sp) -| ldc1 f28, SAVE_FPR_+4*8(sp) -| lw r21, SAVE_GPR_+5*4(sp) -| lw r20, SAVE_GPR_+4*4(sp) -| ldc1 f26, SAVE_FPR_+3*8(sp) -| lw r19, SAVE_GPR_+3*4(sp) -| lw r18, SAVE_GPR_+2*4(sp) -| ldc1 f24, SAVE_FPR_+2*8(sp) -| lw r17, SAVE_GPR_+1*4(sp) -| lw r16, SAVE_GPR_+0*4(sp) -| ldc1 f22, SAVE_FPR_+1*8(sp) -| ldc1 f20, SAVE_FPR_+0*8(sp) -| jr ra -| addiu sp, sp, CFRAME_SPACE -|.endmacro -| -|// Type definitions. Some of these are only used for documentation. -|.type L, lua_State, LREG -|.type GL, global_State -|.type TVALUE, TValue -|.type GCOBJ, GCobj -|.type STR, GCstr -|.type TAB, GCtab -|.type LFUNC, GCfuncL -|.type CFUNC, GCfuncC -|.type PROTO, GCproto -|.type UPVAL, GCupval -|.type NODE, Node -|.type NARGS8, int -|.type TRACE, GCtrace -| -|//----------------------------------------------------------------------- -| -|// Trap for not-yet-implemented parts. -|.macro NYI; .long 0xf0f0f0f0; .endmacro -| -|// Macros to mark delay slots. -|.macro ., a; a; .endmacro -|.macro ., a,b; a,b; .endmacro -|.macro ., a,b,c; a,b,c; .endmacro -| -|//----------------------------------------------------------------------- -| -|// Endian-specific defines. -|.define FRAME_PC, LJ_ENDIAN_SELECT(-4,-8) -|.define FRAME_FUNC, LJ_ENDIAN_SELECT(-8,-4) -|.define HI, LJ_ENDIAN_SELECT(4,0) -|.define LO, LJ_ENDIAN_SELECT(0,4) -|.define OFS_RD, LJ_ENDIAN_SELECT(2,0) -|.define OFS_RA, LJ_ENDIAN_SELECT(1,2) -|.define OFS_OP, LJ_ENDIAN_SELECT(0,3) -| -|// Instruction decode. -|.macro decode_OP1, dst, ins; andi dst, ins, 0xff; .endmacro -|.macro decode_OP4a, dst, ins; andi dst, ins, 0xff; .endmacro -|.macro decode_OP4b, dst; sll dst, dst, 2; .endmacro -|.macro decode_RC4a, dst, ins; srl dst, ins, 14; .endmacro -|.macro decode_RC4b, dst; andi dst, dst, 0x3fc; .endmacro -|.macro decode_RD4b, dst; sll dst, dst, 2; .endmacro -|.macro decode_RA8a, dst, ins; srl dst, ins, 5; .endmacro -|.macro decode_RA8b, dst; andi dst, dst, 0x7f8; .endmacro -|.macro decode_RB8a, dst, ins; srl dst, ins, 21; .endmacro -|.macro decode_RB8b, dst; andi dst, dst, 0x7f8; .endmacro -|.macro decode_RD8a, dst, ins; srl dst, ins, 16; .endmacro -|.macro decode_RD8b, dst; sll dst, dst, 3; .endmacro -|.macro decode_RDtoRC8, dst, src; andi dst, src, 0x7f8; .endmacro -| -|// Instruction fetch. -|.macro ins_NEXT1 -| lw INS, 0(PC) -| addiu PC, PC, 4 -|.endmacro -|// Instruction decode+dispatch. -|.macro ins_NEXT2 -| decode_OP4a TMP1, INS -| decode_OP4b TMP1 -| addu TMP0, DISPATCH, TMP1 -| decode_RD8a RD, INS -| lw AT, 0(TMP0) -| decode_RA8a RA, INS -| decode_RD8b RD -| jr AT -| decode_RA8b RA -|.endmacro -|.macro ins_NEXT -| ins_NEXT1 -| ins_NEXT2 -|.endmacro -| -|// Instruction footer. -|.if 1 -| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use. -| .define ins_next, ins_NEXT -| .define ins_next_, ins_NEXT -| .define ins_next1, ins_NEXT1 -| .define ins_next2, ins_NEXT2 -|.else -| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch. -| // Affects only certain kinds of benchmarks (and only with -j off). -| .macro ins_next -| b ->ins_next -| .endmacro -| .macro ins_next1 -| .endmacro -| .macro ins_next2 -| b ->ins_next -| .endmacro -| .macro ins_next_ -| ->ins_next: -| ins_NEXT -| .endmacro -|.endif -| -|// Call decode and dispatch. -|.macro ins_callt -| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC -| lw PC, LFUNC:RB->pc -| lw INS, 0(PC) -| addiu PC, PC, 4 -| decode_OP4a TMP1, INS -| decode_RA8a RA, INS -| decode_OP4b TMP1 -| decode_RA8b RA -| addu TMP0, DISPATCH, TMP1 -| lw TMP0, 0(TMP0) -| jr TMP0 -| addu RA, RA, BASE -|.endmacro -| -|.macro ins_call -| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, PC = caller PC -| sw PC, FRAME_PC(BASE) -| ins_callt -|.endmacro -| -|//----------------------------------------------------------------------- -| -|.macro branch_RD -| srl TMP0, RD, 1 -| lui AT, (-(BCBIAS_J*4 >> 16) & 65535) -| addu TMP0, TMP0, AT -| addu PC, PC, TMP0 -|.endmacro -| -|// Assumes DISPATCH is relative to GL. -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -#define GG_DISP2GOT (GG_OFS(got) - GG_OFS(dispatch)) -#define DISPATCH_GOT(name) (GG_DISP2GOT + 4*LJ_GOT_##name) -| -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) -| -|.macro load_got, func -| lw CFUNCADDR, DISPATCH_GOT(func)(DISPATCH) -|.endmacro -|// Much faster. Sadly, there's no easy way to force the required code layout. -|// .macro call_intern, func; bal extern func; .endmacro -|.macro call_intern, func; jalr CFUNCADDR; .endmacro -|.macro call_extern; jalr CFUNCADDR; .endmacro -|.macro jmp_extern; jr CFUNCADDR; .endmacro -| -|.macro hotcheck, delta, target -| srl TMP1, PC, 1 -| andi TMP1, TMP1, 126 -| addu TMP1, TMP1, DISPATCH -| lhu TMP2, GG_DISP2HOT(TMP1) -| addiu TMP2, TMP2, -delta -| bltz TMP2, target -|. sh TMP2, GG_DISP2HOT(TMP1) -|.endmacro -| -|.macro hotloop -| hotcheck HOTCOUNT_LOOP, ->vm_hotloop -|.endmacro -| -|.macro hotcall -| hotcheck HOTCOUNT_CALL, ->vm_hotcall -|.endmacro -| -|// Set current VM state. Uses TMP0. -|.macro li_vmstate, st; li TMP0, ~LJ_VMST_..st; .endmacro -|.macro st_vmstate; sw TMP0, DISPATCH_GL(vmstate)(DISPATCH); .endmacro -| -|// Move table write barrier back. Overwrites mark and tmp. -|.macro barrierback, tab, mark, tmp, target -| lw tmp, DISPATCH_GL(gc.grayagain)(DISPATCH) -| andi mark, mark, ~LJ_GC_BLACK & 255 // black2gray(tab) -| sw tab, DISPATCH_GL(gc.grayagain)(DISPATCH) -| sb mark, tab->marked -| b target -|. sw tmp, tab->gclist -|.endmacro -| -|//----------------------------------------------------------------------- - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx) -{ - |.code_sub - | - |//----------------------------------------------------------------------- - |//-- Return handling ---------------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_returnp: - | // See vm_return. Also: TMP2 = previous base. - | andi AT, PC, FRAME_P - | beqz AT, ->cont_dispatch - |. li TMP1, LJ_TTRUE - | - | // Return from pcall or xpcall fast func. - | lw PC, FRAME_PC(TMP2) // Fetch PC of previous frame. - | move BASE, TMP2 // Restore caller base. - | // Prepending may overwrite the pcall frame, so do it at the end. - | sw TMP1, FRAME_PC(RA) // Prepend true to results. - | addiu RA, RA, -8 - | - |->vm_returnc: - | andi TMP0, PC, FRAME_TYPE - | addiu RD, RD, 8 // RD = (nresults+1)*8. - | beqz TMP0, ->BC_RET_Z // Handle regular return to Lua. - |. move MULTRES, RD - | - |->vm_return: - | // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return - | // TMP0 = PC & FRAME_TYPE - | li TMP2, -8 - | xori AT, TMP0, FRAME_C - | and TMP2, PC, TMP2 - | bnez AT, ->vm_returnp - | subu TMP2, BASE, TMP2 // TMP2 = previous base. - | - | addiu TMP1, RD, -8 - | sw TMP2, L->base - | li_vmstate C - | lw TMP2, SAVE_NRES - | addiu BASE, BASE, -8 - | st_vmstate - | beqz TMP1, >2 - |. sll TMP2, TMP2, 3 - |1: - | addiu TMP1, TMP1, -8 - | ldc1 f0, 0(RA) - | addiu RA, RA, 8 - | sdc1 f0, 0(BASE) - | bnez TMP1, <1 - |. addiu BASE, BASE, 8 - | - |2: - | bne TMP2, RD, >6 - |3: - |. sw BASE, L->top // Store new top. - | - |->vm_leave_cp: - | lw TMP0, SAVE_CFRAME // Restore previous C frame. - | move CRET1, r0 // Ok return status for vm_pcall. - | sw TMP0, L->cframe - | - |->vm_leave_unw: - | restoreregs_ret - | - |6: - | lw TMP1, L->maxstack - | slt AT, TMP2, RD - | bnez AT, >7 // Less results wanted? - | // More results wanted. Check stack size and fill up results with nil. - |. slt AT, BASE, TMP1 - | beqz AT, >8 - |. nop - | sw TISNIL, HI(BASE) - | addiu RD, RD, 8 - | b <2 - |. addiu BASE, BASE, 8 - | - |7: // Less results wanted. - | subu TMP0, RD, TMP2 - | subu TMP0, BASE, TMP0 // Either keep top or shrink it. - | b <3 - |. movn BASE, TMP0, TMP2 // LUA_MULTRET+1 case? - | - |8: // Corner case: need to grow stack for filling up results. - | // This can happen if: - | // - A C function grows the stack (a lot). - | // - The GC shrinks the stack in between. - | // - A return back from a lua_call() with (high) nresults adjustment. - | load_got lj_state_growstack - | move MULTRES, RD - | move CARG2, TMP2 - | call_intern lj_state_growstack // (lua_State *L, int n) - |. move CARG1, L - | lw TMP2, SAVE_NRES - | lw BASE, L->top // Need the (realloced) L->top in BASE. - | move RD, MULTRES - | b <2 - |. sll TMP2, TMP2, 3 - | - |->vm_unwind_c: // Unwind C stack, return from vm_pcall. - | // (void *cframe, int errcode) - | move sp, CARG1 - | move CRET1, CARG2 - |->vm_unwind_c_eh: // Landing pad for external unwinder. - | lw L, SAVE_L - | li TMP0, ~LJ_VMST_C - | lw GL:TMP1, L->glref - | b ->vm_leave_unw - |. sw TMP0, GL:TMP1->vmstate - | - |->vm_unwind_ff: // Unwind C stack, return from ff pcall. - | // (void *cframe) - | li AT, -4 - | and sp, CARG1, AT - |->vm_unwind_ff_eh: // Landing pad for external unwinder. - | lw L, SAVE_L - | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). - | li TISNIL, LJ_TNIL - | lw BASE, L->base - | lw DISPATCH, L->glref // Setup pointer to dispatch table. - | mtc1 TMP3, TOBIT - | li TMP1, LJ_TFALSE - | li_vmstate INTERP - | lw PC, FRAME_PC(BASE) // Fetch PC of previous frame. - | cvt.d.s TOBIT, TOBIT - | addiu RA, BASE, -8 // Results start at BASE-8. - | addiu DISPATCH, DISPATCH, GG_G2DISP - | sw TMP1, HI(RA) // Prepend false to error message. - | st_vmstate - | b ->vm_returnc - |. li RD, 16 // 2 results: false + error message. - | - |//----------------------------------------------------------------------- - |//-- Grow stack for calls ----------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_growstack_c: // Grow stack for C function. - | b >2 - |. li CARG2, LUA_MINSTACK - | - |->vm_growstack_l: // Grow stack for Lua function. - | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC - | addu RC, BASE, RC - | subu RA, RA, BASE - | sw BASE, L->base - | addiu PC, PC, 4 // Must point after first instruction. - | sw RC, L->top - | srl CARG2, RA, 3 - |2: - | // L->base = new base, L->top = top - | load_got lj_state_growstack - | sw PC, SAVE_PC - | call_intern lj_state_growstack // (lua_State *L, int n) - |. move CARG1, L - | lw BASE, L->base - | lw RC, L->top - | lw LFUNC:RB, FRAME_FUNC(BASE) - | subu RC, RC, BASE - | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC - | ins_callt // Just retry the call. - | - |//----------------------------------------------------------------------- - |//-- Entry points into the assembler VM --------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_resume: // Setup C frame and resume thread. - | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0) - | saveregs - | move L, CARG1 - | lw DISPATCH, L->glref // Setup pointer to dispatch table. - | move BASE, CARG2 - | lbu TMP1, L->status - | sw L, SAVE_L - | li PC, FRAME_CP - | addiu TMP0, sp, CFRAME_RESUME - | addiu DISPATCH, DISPATCH, GG_G2DISP - | sw r0, SAVE_NRES - | sw r0, SAVE_ERRF - | sw TMP0, L->cframe - | sw r0, SAVE_CFRAME - | beqz TMP1, >3 - |. sw CARG1, SAVE_PC // Any value outside of bytecode is ok. - | - | // Resume after yield (like a return). - | move RA, BASE - | lw BASE, L->base - | lw TMP1, L->top - | lw PC, FRAME_PC(BASE) - | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). - | subu RD, TMP1, BASE - | mtc1 TMP3, TOBIT - | sb r0, L->status - | cvt.d.s TOBIT, TOBIT - | li_vmstate INTERP - | addiu RD, RD, 8 - | st_vmstate - | move MULTRES, RD - | andi TMP0, PC, FRAME_TYPE - | beqz TMP0, ->BC_RET_Z - |. li TISNIL, LJ_TNIL - | b ->vm_return - |. nop - | - |->vm_pcall: // Setup protected C frame and enter VM. - | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef) - | saveregs - | sw CARG4, SAVE_ERRF - | b >1 - |. li PC, FRAME_CP - | - |->vm_call: // Setup C frame and enter VM. - | // (lua_State *L, TValue *base, int nres1) - | saveregs - | li PC, FRAME_C - | - |1: // Entry point for vm_pcall above (PC = ftype). - | lw TMP1, L:CARG1->cframe - | sw CARG3, SAVE_NRES - | move L, CARG1 - | sw CARG1, SAVE_L - | move BASE, CARG2 - | sw sp, L->cframe // Add our C frame to cframe chain. - | lw DISPATCH, L->glref // Setup pointer to dispatch table. - | sw CARG1, SAVE_PC // Any value outside of bytecode is ok. - | sw TMP1, SAVE_CFRAME - | addiu DISPATCH, DISPATCH, GG_G2DISP - | - |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype). - | lw TMP2, L->base // TMP2 = old base (used in vmeta_call). - | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). - | lw TMP1, L->top - | mtc1 TMP3, TOBIT - | addu PC, PC, BASE - | subu NARGS8:RC, TMP1, BASE - | subu PC, PC, TMP2 // PC = frame delta + frame type - | cvt.d.s TOBIT, TOBIT - | li_vmstate INTERP - | li TISNIL, LJ_TNIL - | st_vmstate - | - |->vm_call_dispatch: - | // TMP2 = old base, BASE = new base, RC = nargs*8, PC = caller PC - | lw TMP0, FRAME_PC(BASE) - | li AT, LJ_TFUNC - | bne TMP0, AT, ->vmeta_call - |. lw LFUNC:RB, FRAME_FUNC(BASE) - | - |->vm_call_dispatch_f: - | ins_call - | // BASE = new base, RB = func, RC = nargs*8, PC = caller PC - | - |->vm_cpcall: // Setup protected C frame, call C. - | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp) - | saveregs - | move L, CARG1 - | lw TMP0, L:CARG1->stack - | sw CARG1, SAVE_L - | lw TMP1, L->top - | sw CARG1, SAVE_PC // Any value outside of bytecode is ok. - | subu TMP0, TMP0, TMP1 // Compute -savestack(L, L->top). - | lw TMP1, L->cframe - | sw sp, L->cframe // Add our C frame to cframe chain. - | sw TMP0, SAVE_NRES // Neg. delta means cframe w/o frame. - | sw r0, SAVE_ERRF // No error function. - | move CFUNCADDR, CARG4 - | jalr CARG4 // (lua_State *L, lua_CFunction func, void *ud) - |. sw TMP1, SAVE_CFRAME - | move BASE, CRET1 - | lw DISPATCH, L->glref // Setup pointer to dispatch table. - | li PC, FRAME_CP - | bnez CRET1, <3 // Else continue with the call. - |. addiu DISPATCH, DISPATCH, GG_G2DISP - | b ->vm_leave_cp // No base? Just remove C frame. - |. nop - | - |//----------------------------------------------------------------------- - |//-- Metamethod handling ------------------------------------------------ - |//----------------------------------------------------------------------- - | - |// The lj_meta_* functions (except for lj_meta_cat) don't reallocate the - |// stack, so BASE doesn't need to be reloaded across these calls. - | - |//-- Continuation dispatch ---------------------------------------------- - | - |->cont_dispatch: - | // BASE = meta base, RA = resultptr, RD = (nresults+1)*8 - | lw TMP0, -16+LO(BASE) // Continuation. - | move RB, BASE - | move BASE, TMP2 // Restore caller BASE. - | lw LFUNC:TMP1, FRAME_FUNC(TMP2) -#if LJ_HASFFI - | sltiu AT, TMP0, 2 -#endif - | lw PC, -16+HI(RB) // Restore PC from [cont|PC]. - | addu TMP2, RA, RD - | lw TMP1, LFUNC:TMP1->pc -#if LJ_HASFFI - | bnez AT, >1 -#endif - |. sw TISNIL, -8+HI(TMP2) // Ensure one valid arg. - | // BASE = base, RA = resultptr, RB = meta base - | jr TMP0 // Jump to continuation. - |. lw KBASE, PC2PROTO(k)(TMP1) - | -#if LJ_HASFFI - |1: - | bnez TMP0, ->cont_ffi_callback // cont = 1: return from FFI callback. - | // cont = 0: tailcall from C function. - |. addiu TMP1, RB, -16 - | b ->vm_call_tail - |. subu RC, TMP1, BASE -#endif - | - |->cont_cat: // RA = resultptr, RB = meta base - | lw INS, -4(PC) - | addiu CARG2, RB, -16 - | ldc1 f0, 0(RA) - | decode_RB8a MULTRES, INS - | decode_RA8a RA, INS - | decode_RB8b MULTRES - | decode_RA8b RA - | addu TMP1, BASE, MULTRES - | sw BASE, L->base - | subu CARG3, CARG2, TMP1 - | bne TMP1, CARG2, ->BC_CAT_Z - |. sdc1 f0, 0(CARG2) - | addu RA, BASE, RA - | b ->cont_nop - |. sdc1 f0, 0(RA) - | - |//-- Table indexing metamethods ----------------------------------------- - | - |->vmeta_tgets1: - | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) - | li TMP0, LJ_TSTR - | sw STR:RC, LO(CARG3) - | b >1 - |. sw TMP0, HI(CARG3) - | - |->vmeta_tgets: - | addiu CARG2, DISPATCH, DISPATCH_GL(tmptv) - | li TMP0, LJ_TTAB - | sw TAB:RB, LO(CARG2) - | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv2) - | sw TMP0, HI(CARG2) - | li TMP1, LJ_TSTR - | sw STR:RC, LO(CARG3) - | b >1 - |. sw TMP1, HI(CARG3) - | - |->vmeta_tgetb: // TMP0 = index - | mtc1 TMP0, f0 - | cvt.d.w f0, f0 - | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) - | sdc1 f0, 0(CARG3) - | - |->vmeta_tgetv: - |1: - | load_got lj_meta_tget - | sw BASE, L->base - | sw PC, SAVE_PC - | call_intern lj_meta_tget // (lua_State *L, TValue *o, TValue *k) - |. move CARG1, L - | // Returns TValue * (finished) or NULL (metamethod). - | beqz CRET1, >3 - |. addiu TMP1, BASE, -FRAME_CONT - | ldc1 f0, 0(CRET1) - | ins_next1 - | sdc1 f0, 0(RA) - | ins_next2 - | - |3: // Call __index metamethod. - | // BASE = base, L->top = new base, stack = cont/func/t/k - | lw BASE, L->top - | sw PC, -16+HI(BASE) // [cont|PC] - | subu PC, BASE, TMP1 - | lw LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. - | b ->vm_call_dispatch_f - |. li NARGS8:RC, 16 // 2 args for func(t, k). - | - |//----------------------------------------------------------------------- - | - |->vmeta_tsets1: - | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) - | li TMP0, LJ_TSTR - | sw STR:RC, LO(CARG3) - | b >1 - |. sw TMP0, HI(CARG3) - | - |->vmeta_tsets: - | addiu CARG2, DISPATCH, DISPATCH_GL(tmptv) - | li TMP0, LJ_TTAB - | sw TAB:RB, LO(CARG2) - | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv2) - | sw TMP0, HI(CARG2) - | li TMP1, LJ_TSTR - | sw STR:RC, LO(CARG3) - | b >1 - |. sw TMP1, HI(CARG3) - | - |->vmeta_tsetb: // TMP0 = index - | mtc1 TMP0, f0 - | cvt.d.w f0, f0 - | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) - | sdc1 f0, 0(CARG3) - | - |->vmeta_tsetv: - |1: - | load_got lj_meta_tset - | sw BASE, L->base - | sw PC, SAVE_PC - | call_intern lj_meta_tset // (lua_State *L, TValue *o, TValue *k) - |. move CARG1, L - | // Returns TValue * (finished) or NULL (metamethod). - | beqz CRET1, >3 - |. ldc1 f0, 0(RA) - | // NOBARRIER: lj_meta_tset ensures the table is not black. - | ins_next1 - | sdc1 f0, 0(CRET1) - | ins_next2 - | - |3: // Call __newindex metamethod. - | // BASE = base, L->top = new base, stack = cont/func/t/k/(v) - | addiu TMP1, BASE, -FRAME_CONT - | lw BASE, L->top - | sw PC, -16+HI(BASE) // [cont|PC] - | subu PC, BASE, TMP1 - | lw LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. - | sdc1 f0, 16(BASE) // Copy value to third argument. - | b ->vm_call_dispatch_f - |. li NARGS8:RC, 24 // 3 args for func(t, k, v) - | - |//-- Comparison metamethods --------------------------------------------- - | - |->vmeta_comp: - | // CARG2, CARG3 are already set by BC_ISLT/BC_ISGE/BC_ISLE/BC_ISGT. - | load_got lj_meta_comp - | addiu PC, PC, -4 - | sw BASE, L->base - | sw PC, SAVE_PC - | decode_OP1 CARG4, INS - | call_intern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op) - |. move CARG1, L - | // Returns 0/1 or TValue * (metamethod). - |3: - | sltiu AT, CRET1, 2 - | beqz AT, ->vmeta_binop - | negu TMP2, CRET1 - |4: - | lhu RD, OFS_RD(PC) - | addiu PC, PC, 4 - | lui TMP1, (-(BCBIAS_J*4 >> 16) & 65535) - | sll RD, RD, 2 - | addu RD, RD, TMP1 - | and RD, RD, TMP2 - | addu PC, PC, RD - |->cont_nop: - | ins_next - | - |->cont_ra: // RA = resultptr - | lbu TMP1, -4+OFS_RA(PC) - | ldc1 f0, 0(RA) - | sll TMP1, TMP1, 3 - | addu TMP1, BASE, TMP1 - | b ->cont_nop - |. sdc1 f0, 0(TMP1) - | - |->cont_condt: // RA = resultptr - | lw TMP0, HI(RA) - | sltiu AT, TMP0, LJ_TISTRUECOND - | b <4 - |. negu TMP2, AT // Branch if result is true. - | - |->cont_condf: // RA = resultptr - | lw TMP0, HI(RA) - | sltiu AT, TMP0, LJ_TISTRUECOND - | b <4 - |. addiu TMP2, AT, -1 // Branch if result is false. - | - |->vmeta_equal: - | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV. - | load_got lj_meta_equal - | addiu PC, PC, -4 - | sw BASE, L->base - | sw PC, SAVE_PC - | call_intern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne) - |. move CARG1, L - | // Returns 0/1 or TValue * (metamethod). - | b <3 - |. nop - | - |->vmeta_equal_cd: -#if LJ_HASFFI - | load_got lj_meta_equal_cd - | move CARG2, INS - | addiu PC, PC, -4 - | sw BASE, L->base - | sw PC, SAVE_PC - | call_intern lj_meta_equal_cd // (lua_State *L, BCIns op) - |. move CARG1, L - | // Returns 0/1 or TValue * (metamethod). - | b <3 - |. nop -#endif - | - |//-- Arithmetic metamethods --------------------------------------------- - | - |->vmeta_unm: - | move CARG4, CARG3 - | - |->vmeta_arith: - | load_got lj_meta_arith - | decode_OP1 TMP0, INS - | sw BASE, L->base - | sw PC, SAVE_PC - | move CARG2, RA - | sw TMP0, ARG5 - | call_intern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op) - |. move CARG1, L - | // Returns NULL (finished) or TValue * (metamethod). - | beqz CRET1, ->cont_nop - |. nop - | - | // Call metamethod for binary op. - |->vmeta_binop: - | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2 - | subu TMP1, CRET1, BASE - | sw PC, -16+HI(CRET1) // [cont|PC] - | move TMP2, BASE - | addiu PC, TMP1, FRAME_CONT - | move BASE, CRET1 - | b ->vm_call_dispatch - |. li NARGS8:RC, 16 // 2 args for func(o1, o2). - | - |->vmeta_len: - | // CARG2 already set by BC_LEN. -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | move MULTRES, CARG1 -#endif - | load_got lj_meta_len - | sw BASE, L->base - | sw PC, SAVE_PC - | call_intern lj_meta_len // (lua_State *L, TValue *o) - |. move CARG1, L - | // Returns NULL (retry) or TValue * (metamethod base). -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | bnez CRET1, ->vmeta_binop // Binop call for compatibility. - |. nop - | b ->BC_LEN_Z - |. move CARG1, MULTRES -#else - | b ->vmeta_binop // Binop call for compatibility. - |. nop -#endif - | - |//-- Call metamethod ---------------------------------------------------- - | - |->vmeta_call: // Resolve and call __call metamethod. - | // TMP2 = old base, BASE = new base, RC = nargs*8 - | load_got lj_meta_call - | sw TMP2, L->base // This is the callers base! - | addiu CARG2, BASE, -8 - | sw PC, SAVE_PC - | addu CARG3, BASE, RC - | move MULTRES, NARGS8:RC - | call_intern lj_meta_call // (lua_State *L, TValue *func, TValue *top) - |. move CARG1, L - | lw LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. - | addiu NARGS8:RC, MULTRES, 8 // Got one more argument now. - | ins_call - | - |->vmeta_callt: // Resolve __call for BC_CALLT. - | // BASE = old base, RA = new base, RC = nargs*8 - | load_got lj_meta_call - | sw BASE, L->base - | addiu CARG2, RA, -8 - | sw PC, SAVE_PC - | addu CARG3, RA, RC - | move MULTRES, NARGS8:RC - | call_intern lj_meta_call // (lua_State *L, TValue *func, TValue *top) - |. move CARG1, L - | lw TMP1, FRAME_PC(BASE) - | lw LFUNC:RB, FRAME_FUNC(RA) // Guaranteed to be a function here. - | b ->BC_CALLT_Z - |. addiu NARGS8:RC, MULTRES, 8 // Got one more argument now. - | - |//-- Argument coercion for 'for' statement ------------------------------ - | - |->vmeta_for: - | load_got lj_meta_for - | sw BASE, L->base - | move CARG2, RA - | sw PC, SAVE_PC - | move MULTRES, INS - | call_intern lj_meta_for // (lua_State *L, TValue *base) - |. move CARG1, L -#if LJ_HASJIT - | decode_OP1 TMP0, MULTRES - | li AT, BC_JFORI -#endif - | decode_RA8a RA, MULTRES - | decode_RD8a RD, MULTRES - | decode_RA8b RA -#if LJ_HASJIT - | beq TMP0, AT, =>BC_JFORI - |. decode_RD8b RD - | b =>BC_FORI - |. nop -#else - | b =>BC_FORI - |. decode_RD8b RD -#endif - | - |//----------------------------------------------------------------------- - |//-- Fast functions ----------------------------------------------------- - |//----------------------------------------------------------------------- - | - |.macro .ffunc, name - |->ff_ .. name: - |.endmacro - | - |.macro .ffunc_1, name - |->ff_ .. name: - | beqz NARGS8:RC, ->fff_fallback - |. lw CARG3, HI(BASE) - | lw CARG1, LO(BASE) - |.endmacro - | - |.macro .ffunc_2, name - |->ff_ .. name: - | sltiu AT, NARGS8:RC, 16 - | lw CARG3, HI(BASE) - | bnez AT, ->fff_fallback - |. lw CARG4, 8+HI(BASE) - | lw CARG1, LO(BASE) - | lw CARG2, 8+LO(BASE) - |.endmacro - | - |.macro .ffunc_n, name // Caveat: has delay slot! - |->ff_ .. name: - | lw CARG3, HI(BASE) - | beqz NARGS8:RC, ->fff_fallback - |. ldc1 FARG1, 0(BASE) - | sltiu AT, CARG3, LJ_TISNUM - | beqz AT, ->fff_fallback - |.endmacro - | - |.macro .ffunc_nn, name // Caveat: has delay slot! - |->ff_ .. name: - | sltiu AT, NARGS8:RC, 16 - | lw CARG3, HI(BASE) - | bnez AT, ->fff_fallback - |. lw CARG4, 8+HI(BASE) - | ldc1 FARG1, 0(BASE) - | ldc1 FARG2, 8(BASE) - | sltiu TMP0, CARG3, LJ_TISNUM - | sltiu TMP1, CARG4, LJ_TISNUM - | and TMP0, TMP0, TMP1 - | beqz TMP0, ->fff_fallback - |.endmacro - | - |// Inlined GC threshold check. Caveat: uses TMP0 and TMP1 and has delay slot! - |.macro ffgccheck - | lw TMP0, DISPATCH_GL(gc.total)(DISPATCH) - | lw TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) - | subu AT, TMP0, TMP1 - | bgezal AT, ->fff_gcstep - |.endmacro - | - |//-- Base library: checks ----------------------------------------------- - | - |.ffunc_1 assert - | sltiu AT, CARG3, LJ_TISTRUECOND - | beqz AT, ->fff_fallback - |. addiu RA, BASE, -8 - | lw PC, FRAME_PC(BASE) - | addiu RD, NARGS8:RC, 8 // Compute (nresults+1)*8. - | addu TMP2, RA, NARGS8:RC - | sw CARG3, HI(RA) - | addiu TMP1, BASE, 8 - | beq BASE, TMP2, ->fff_res // Done if exactly 1 argument. - |. sw CARG1, LO(RA) - |1: - | ldc1 f0, 0(TMP1) - | sdc1 f0, -8(TMP1) - | bne TMP1, TMP2, <1 - |. addiu TMP1, TMP1, 8 - | b ->fff_res - |. nop - | - |.ffunc type - | lw CARG3, HI(BASE) - | li TMP1, LJ_TISNUM - | beqz NARGS8:RC, ->fff_fallback - |. sltiu TMP0, CARG3, LJ_TISNUM - | movz TMP1, CARG3, TMP0 - | not TMP1, TMP1 - | sll TMP1, TMP1, 3 - | addu TMP1, CFUNC:RB, TMP1 - | b ->fff_resn - |. ldc1 FRET1, CFUNC:TMP1->upvalue - | - |//-- Base library: getters and setters --------------------------------- - | - |.ffunc_1 getmetatable - | li AT, LJ_TTAB - | bne CARG3, AT, >6 - |. li AT, LJ_TUDATA - |1: // Field metatable must be at same offset for GCtab and GCudata! - | lw TAB:CARG1, TAB:CARG1->metatable - |2: - | lw STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH) - | beqz TAB:CARG1, ->fff_restv - |. li CARG3, LJ_TNIL - | lw TMP0, TAB:CARG1->hmask - | li CARG3, LJ_TTAB // Use metatable as default result. - | lw TMP1, STR:RC->hash - | lw NODE:TMP2, TAB:CARG1->node - | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask - | sll TMP0, TMP1, 5 - | sll TMP1, TMP1, 3 - | subu TMP1, TMP0, TMP1 - | addu NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) - | li AT, LJ_TSTR - |3: // Rearranged logic, because we expect _not_ to find the key. - | lw CARG4, offsetof(Node, key)+HI(NODE:TMP2) - | lw TMP0, offsetof(Node, key)+LO(NODE:TMP2) - | lw NODE:TMP3, NODE:TMP2->next - | bne CARG4, AT, >4 - |. lw CARG2, offsetof(Node, val)+HI(NODE:TMP2) - | beq TMP0, STR:RC, >5 - |. lw TMP1, offsetof(Node, val)+LO(NODE:TMP2) - |4: - | beqz NODE:TMP3, ->fff_restv // Not found, keep default result. - |. move NODE:TMP2, NODE:TMP3 - | b <3 - |. nop - |5: - | beq CARG2, TISNIL, ->fff_restv // Ditto for nil value. - |. nop - | move CARG3, CARG2 // Return value of mt.__metatable. - | b ->fff_restv - |. move CARG1, TMP1 - | - |6: - | beq CARG3, AT, <1 - |. sltiu TMP0, CARG3, LJ_TISNUM - | li TMP1, LJ_TISNUM - | movz TMP1, CARG3, TMP0 - | not TMP1, TMP1 - | sll TMP1, TMP1, 2 - | addu TMP1, DISPATCH, TMP1 - | b <2 - |. lw TAB:CARG1, DISPATCH_GL(gcroot[GCROOT_BASEMT])(TMP1) - | - |.ffunc_2 setmetatable - | // Fast path: no mt for table yet and not clearing the mt. - | li AT, LJ_TTAB - | bne CARG3, AT, ->fff_fallback - |. addiu CARG4, CARG4, -LJ_TTAB - | lw TAB:TMP1, TAB:CARG1->metatable - | lbu TMP3, TAB:CARG1->marked - | or AT, CARG4, TAB:TMP1 - | bnez AT, ->fff_fallback - |. andi AT, TMP3, LJ_GC_BLACK // isblack(table) - | beqz AT, ->fff_restv - |. sw TAB:CARG2, TAB:CARG1->metatable - | barrierback TAB:CARG1, TMP3, TMP0, ->fff_restv - | - |.ffunc rawget - | lw CARG4, HI(BASE) - | sltiu AT, NARGS8:RC, 16 - | lw TAB:CARG2, LO(BASE) - | load_got lj_tab_get - | addiu CARG4, CARG4, -LJ_TTAB - | or AT, AT, CARG4 - | bnez AT, ->fff_fallback - | addiu CARG3, BASE, 8 - | call_intern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key) - |. move CARG1, L - | // Returns cTValue *. - | b ->fff_resn - |. ldc1 FRET1, 0(CRET1) - | - |//-- Base library: conversions ------------------------------------------ - | - |.ffunc tonumber - | // Only handles the number case inline (without a base argument). - | lw CARG1, HI(BASE) - | xori AT, NARGS8:RC, 8 - | sltiu CARG1, CARG1, LJ_TISNUM - | movn CARG1, r0, AT - | beqz CARG1, ->fff_fallback // Exactly one number argument. - |. ldc1 FRET1, 0(BASE) - | b ->fff_resn - |. nop - | - |.ffunc_1 tostring - | // Only handles the string or number case inline. - | li AT, LJ_TSTR - | // A __tostring method in the string base metatable is ignored. - | beq CARG3, AT, ->fff_restv // String key? - | // Handle numbers inline, unless a number base metatable is present. - |. lw TMP1, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])(DISPATCH) - | sltiu TMP0, CARG3, LJ_TISNUM - | sltiu TMP1, TMP1, 1 - | and TMP0, TMP0, TMP1 - | beqz TMP0, ->fff_fallback - |. sw BASE, L->base // Add frame since C call can throw. - | ffgccheck - |. sw PC, SAVE_PC // Redundant (but a defined value). - | load_got lj_str_fromnum - | move CARG1, L - | call_intern lj_str_fromnum // (lua_State *L, lua_Number *np) - |. move CARG2, BASE - | // Returns GCstr *. - | li CARG3, LJ_TSTR - | b ->fff_restv - |. move CARG1, CRET1 - | - |//-- Base library: iterators ------------------------------------------- - | - |.ffunc next - | lw CARG1, HI(BASE) - | lw TAB:CARG2, 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 - |. 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. - | beqz CRET1, ->fff_restv // End of traversal: return nil. - |. li CARG3, LJ_TNIL - | ldc1 f0, 8(BASE) // Copy key and value to results. - | addiu RA, BASE, -8 - | ldc1 f2, 16(BASE) - | li RD, (2+1)*8 - | sdc1 f0, 0(RA) - | b ->fff_res - |. sdc1 f2, 8(RA) - | - |.ffunc_1 pairs - | li AT, LJ_TTAB - | bne CARG3, AT, ->fff_fallback - |. lw PC, FRAME_PC(BASE) -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | lw TAB:TMP2, TAB:CARG1->metatable - | ldc1 f0, CFUNC:RB->upvalue[0] - | bnez TAB:TMP2, ->fff_fallback -#else - | ldc1 f0, CFUNC:RB->upvalue[0] -#endif - |. addiu RA, BASE, -8 - | sw TISNIL, 8+HI(BASE) - | li RD, (3+1)*8 - | b ->fff_res - |. sdc1 f0, 0(RA) - | - |.ffunc ipairs_aux - | sltiu AT, NARGS8:RC, 16 - | lw CARG3, HI(BASE) - | lw TAB:CARG1, LO(BASE) - | lw CARG4, 8+HI(BASE) - | bnez AT, ->fff_fallback - |. ldc1 FARG2, 8(BASE) - | addiu CARG3, CARG3, -LJ_TTAB - | sltiu AT, CARG4, LJ_TISNUM - | li TMP0, 1 - | movn AT, r0, CARG3 - | mtc1 TMP0, FARG1 - | beqz AT, ->fff_fallback - |. lw PC, FRAME_PC(BASE) - | cvt.w.d FRET1, FARG2 - | cvt.d.w FARG1, FARG1 - | lw TMP0, TAB:CARG1->asize - | lw TMP1, TAB:CARG1->array - | mfc1 TMP2, FRET1 - | addiu RA, BASE, -8 - | add.d FARG2, FARG2, FARG1 - | addiu TMP2, TMP2, 1 - | sltu AT, TMP2, TMP0 - | sll TMP3, TMP2, 3 - | addu TMP3, TMP1, TMP3 - | beqz AT, >2 // Not in array part? - |. sdc1 FARG2, 0(RA) - | lw TMP2, HI(TMP3) - | ldc1 f0, 0(TMP3) - |1: - | beq TMP2, TISNIL, ->fff_res // End of iteration, return 0 results. - |. li RD, (0+1)*8 - | li RD, (2+1)*8 - | b ->fff_res - |. sdc1 f0, 8(RA) - |2: // Check for empty hash part first. Otherwise call C function. - | lw TMP0, TAB:CARG1->hmask - | load_got lj_tab_getinth - | beqz TMP0, ->fff_res - |. li RD, (0+1)*8 - | call_intern lj_tab_getinth // (GCtab *t, int32_t key) - |. move CARG2, TMP2 - | // Returns cTValue * or NULL. - | beqz CRET1, ->fff_res - |. li RD, (0+1)*8 - | lw TMP2, HI(CRET1) - | b <1 - |. ldc1 f0, 0(CRET1) - | - |.ffunc_1 ipairs - | li AT, LJ_TTAB - | bne CARG3, AT, ->fff_fallback - |. lw PC, FRAME_PC(BASE) -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | lw TAB:TMP2, TAB:CARG1->metatable - | ldc1 f0, CFUNC:RB->upvalue[0] - | bnez TAB:TMP2, ->fff_fallback -#else - | ldc1 f0, CFUNC:RB->upvalue[0] -#endif - |. addiu RA, BASE, -8 - | sw r0, 8+HI(BASE) - | sw r0, 8+LO(BASE) - | li RD, (3+1)*8 - | b ->fff_res - |. sdc1 f0, 0(RA) - | - |//-- Base library: catch errors ---------------------------------------- - | - |.ffunc pcall - | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | beqz NARGS8:RC, ->fff_fallback - | move TMP2, BASE - | addiu BASE, BASE, 8 - | // Remember active hook before pcall. - | srl TMP3, TMP3, HOOK_ACTIVE_SHIFT - | andi TMP3, TMP3, 1 - | addiu PC, TMP3, 8+FRAME_PCALL - | b ->vm_call_dispatch - |. addiu NARGS8:RC, NARGS8:RC, -8 - | - |.ffunc xpcall - | sltiu AT, NARGS8:RC, 16 - | lw CARG4, 8+HI(BASE) - | bnez AT, ->fff_fallback - |. ldc1 FARG2, 8(BASE) - | ldc1 FARG1, 0(BASE) - | lbu TMP1, DISPATCH_GL(hookmask)(DISPATCH) - | li AT, LJ_TFUNC - | move TMP2, BASE - | bne CARG4, AT, ->fff_fallback // Traceback must be a function. - | addiu BASE, BASE, 16 - | // Remember active hook before pcall. - | srl TMP3, TMP3, HOOK_ACTIVE_SHIFT - | sdc1 FARG2, 0(TMP2) // Swap function and traceback. - | andi TMP3, TMP3, 1 - | sdc1 FARG1, 8(TMP2) - | addiu PC, TMP3, 16+FRAME_PCALL - | b ->vm_call_dispatch - |. addiu NARGS8:RC, NARGS8:RC, -16 - | - |//-- Coroutine library -------------------------------------------------- - | - |.macro coroutine_resume_wrap, resume - |.if resume - |.ffunc_1 coroutine_resume - | li AT, LJ_TTHREAD - | bne CARG3, AT, ->fff_fallback - |.else - |.ffunc coroutine_wrap_aux - | lw L:CARG1, CFUNC:RB->upvalue[0].gcr - |.endif - | lbu TMP0, L:CARG1->status - | lw TMP1, L:CARG1->cframe - | lw CARG2, L:CARG1->top - | lw TMP2, L:CARG1->base - | addiu TMP3, TMP0, -LUA_YIELD - | bgtz TMP3, ->fff_fallback // st > LUA_YIELD? - |. xor TMP2, TMP2, CARG2 - | bnez TMP1, ->fff_fallback // cframe != 0? - |. or AT, TMP2, TMP0 - | lw TMP0, L:CARG1->maxstack - | beqz AT, ->fff_fallback // base == top && st == 0? - |. lw PC, FRAME_PC(BASE) - | addu TMP2, CARG2, NARGS8:RC - | sltu AT, TMP0, TMP2 - | bnez AT, ->fff_fallback // Stack overflow? - |. sw PC, SAVE_PC - | sw BASE, L->base - |1: - |.if resume - | addiu BASE, BASE, 8 // Keep resumed thread in stack for GC. - | addiu NARGS8:RC, NARGS8:RC, -8 - | addiu TMP2, TMP2, -8 - |.endif - | sw TMP2, L:CARG1->top - | addu TMP1, BASE, NARGS8:RC - | move CARG3, CARG2 - | sw BASE, L->top - |2: // Move args to coroutine. - | ldc1 f0, 0(BASE) - | sltu AT, BASE, TMP1 - | beqz AT, >3 - |. addiu BASE, BASE, 8 - | sdc1 f0, 0(CARG3) - | b <2 - |. addiu CARG3, CARG3, 8 - |3: - | bal ->vm_resume // (lua_State *L, TValue *base, 0, 0) - |. move L:RA, L:CARG1 - | // Returns thread status. - |4: - | lw TMP2, L:RA->base - | sltiu AT, CRET1, LUA_YIELD+1 - | lw TMP3, L:RA->top - | li_vmstate INTERP - | lw BASE, L->base - | st_vmstate - | beqz AT, >8 - |. subu RD, TMP3, TMP2 - | lw TMP0, L->maxstack - | beqz RD, >6 // No results? - |. addu TMP1, BASE, RD - | sltu AT, TMP0, TMP1 - | bnez AT, >9 // Need to grow stack? - |. addu TMP3, TMP2, RD - | sw TMP2, L:RA->top // Clear coroutine stack. - | move TMP1, BASE - |5: // Move results from coroutine. - | ldc1 f0, 0(TMP2) - | addiu TMP2, TMP2, 8 - | sltu AT, TMP2, TMP3 - | sdc1 f0, 0(TMP1) - | bnez AT, <5 - |. addiu TMP1, TMP1, 8 - |6: - | andi TMP0, PC, FRAME_TYPE - |.if resume - | li TMP1, LJ_TTRUE - | addiu RA, BASE, -8 - | sw TMP1, -8+HI(BASE) // Prepend true to results. - | addiu RD, RD, 16 - |.else - | move RA, BASE - | addiu RD, RD, 8 - |.endif - |7: - | sw PC, SAVE_PC - | beqz TMP0, ->BC_RET_Z - |. move MULTRES, RD - | b ->vm_return - |. nop - | - |8: // Coroutine returned with error (at co->top-1). - |.if resume - | addiu TMP3, TMP3, -8 - | li TMP1, LJ_TFALSE - | ldc1 f0, 0(TMP3) - | sw TMP3, L:RA->top // Remove error from coroutine stack. - | li RD, (2+1)*8 - | sw TMP1, -8+HI(BASE) // Prepend false to results. - | addiu RA, BASE, -8 - | sdc1 f0, 0(BASE) // Copy error message. - | b <7 - |. andi TMP0, PC, FRAME_TYPE - |.else - | load_got lj_ffh_coroutine_wrap_err - | move CARG2, L:RA - | call_intern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co) - |. move CARG1, L - |.endif - | - |9: // Handle stack expansion on return from yield. - | load_got lj_state_growstack - | srl CARG2, RD, 3 - | call_intern lj_state_growstack // (lua_State *L, int n) - |. move CARG1, L - | b <4 - |. li CRET1, 0 - |.endmacro - | - | coroutine_resume_wrap 1 // coroutine.resume - | coroutine_resume_wrap 0 // coroutine.wrap - | - |.ffunc coroutine_yield - | lw TMP0, L->cframe - | addu TMP1, BASE, NARGS8:RC - | sw BASE, L->base - | andi TMP0, TMP0, CFRAME_RESUME - | sw TMP1, L->top - | beqz TMP0, ->fff_fallback - |. li CRET1, LUA_YIELD - | sw r0, L->cframe - | b ->vm_leave_unw - |. sb CRET1, L->status - | - |//-- Math library ------------------------------------------------------- - | - |.ffunc_n math_abs - |. abs.d FRET1, FARG1 - |->fff_resn: - | lw PC, FRAME_PC(BASE) - | addiu RA, BASE, -8 - | b ->fff_res1 - |. sdc1 FRET1, -8(BASE) - | - |->fff_restv: - | // CARG3/CARG1 = TValue result. - | lw PC, FRAME_PC(BASE) - | sw CARG3, -8+HI(BASE) - | addiu RA, BASE, -8 - | sw CARG1, -8+LO(BASE) - |->fff_res1: - | // RA = results, PC = return. - | li RD, (1+1)*8 - |->fff_res: - | // RA = results, RD = (nresults+1)*8, PC = return. - | andi TMP0, PC, FRAME_TYPE - | bnez TMP0, ->vm_return - |. move MULTRES, RD - | lw INS, -4(PC) - | decode_RB8a RB, INS - | decode_RB8b RB - |5: - | sltu AT, RD, RB - | bnez AT, >6 // More results expected? - |. decode_RA8a TMP0, INS - | decode_RA8b TMP0 - | ins_next1 - | // Adjust BASE. KBASE is assumed to be set for the calling frame. - | subu BASE, RA, TMP0 - | ins_next2 - | - |6: // Fill up results with nil. - | addu TMP1, RA, RD - | addiu RD, RD, 8 - | b <5 - |. sw TISNIL, -8+HI(TMP1) - | - |.macro math_extern, func - |->ff_math_ .. func: - | lw CARG3, HI(BASE) - | beqz NARGS8:RC, ->fff_fallback - |. load_got func - | sltiu AT, CARG3, LJ_TISNUM - | beqz AT, ->fff_fallback - |. nop - | call_extern - |. ldc1 FARG1, 0(BASE) - | b ->fff_resn - |. nop - |.endmacro - | - |.macro math_extern2, func - | .ffunc_nn math_ .. func - |. load_got func - | call_extern - |. nop - | b ->fff_resn - |. nop - |.endmacro - | - |.macro math_round, func - | .ffunc_n math_ .. func - |. nop - | bal ->vm_ .. func - |. nop - | b ->fff_resn - |. nop - |.endmacro - | - | math_round floor - | math_round ceil - | - | math_extern log - | math_extern log10 - | math_extern exp - | math_extern sin - | math_extern cos - | math_extern tan - | math_extern asin - | math_extern acos - | math_extern atan - | math_extern sinh - | math_extern cosh - | math_extern tanh - | math_extern2 pow - | math_extern2 atan2 - | math_extern2 fmod - | - |.ffunc_n math_sqrt - |. sqrt.d FRET1, FARG1 - | b ->fff_resn - |. nop - | - |->ff_math_deg: - |.ffunc_n math_rad - |. ldc1 FARG2, CFUNC:RB->upvalue[0] - | b ->fff_resn - |. mul.d FRET1, FARG1, FARG2 - | - |.ffunc_nn math_ldexp - | cvt.w.d FARG2, FARG2 - | load_got ldexp - | mfc1 CARG3, FARG2 - | call_extern - |. nop - | b ->fff_resn - |. nop - | - |.ffunc_n math_frexp - | load_got frexp - | lw PC, FRAME_PC(BASE) - | call_extern - |. addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) - | lw TMP1, DISPATCH_GL(tmptv)(DISPATCH) - | addiu RA, BASE, -8 - | mtc1 TMP1, FARG2 - | sdc1 FRET1, 0(RA) - | cvt.d.w FARG2, FARG2 - | sdc1 FARG2, 8(RA) - | b ->fff_res - |. li RD, (2+1)*8 - | - |.ffunc_n math_modf - | load_got modf - | lw PC, FRAME_PC(BASE) - | call_extern - |. addiu CARG3, BASE, -8 - | addiu RA, BASE, -8 - | sdc1 FRET1, 0(BASE) - | b ->fff_res - |. li RD, (2+1)*8 - | - |.macro math_minmax, name, ismax - |->ff_ .. name: - | lw CARG3, HI(BASE) - | beqz NARGS8:RC, ->fff_fallback - |. ldc1 FRET1, 0(BASE) - | sltiu AT, CARG3, LJ_TISNUM - | beqz AT, ->fff_fallback - |. addu TMP2, BASE, NARGS8:RC - | addiu TMP1, BASE, 8 - | beq TMP1, TMP2, ->fff_resn - |1: - |. lw CARG3, HI(TMP1) - | ldc1 FARG1, 0(TMP1) - | addiu TMP1, TMP1, 8 - | sltiu AT, CARG3, LJ_TISNUM - | beqz AT, ->fff_fallback - |.if ismax - |. c.olt.d FARG1, FRET1 - |.else - |. c.olt.d FRET1, FARG1 - |.endif - | bne TMP1, TMP2, <1 - |. movf.d FRET1, FARG1 - | b ->fff_resn - |. nop - |.endmacro - | - | math_minmax math_min, 0 - | math_minmax math_max, 1 - | - |//-- String library ----------------------------------------------------- - | - |.ffunc_1 string_len - | li AT, LJ_TSTR - | bne CARG3, AT, ->fff_fallback - |. nop - | b ->fff_resi - |. lw CRET1, STR:CARG1->len - | - |.ffunc string_byte // Only handle the 1-arg case here. - | lw CARG3, HI(BASE) - | lw STR:CARG1, LO(BASE) - | xori AT, NARGS8:RC, 8 - | addiu CARG3, CARG3, -LJ_TSTR - | or AT, AT, CARG3 - | bnez AT, ->fff_fallback // Need exactly 1 string argument. - |. nop - | lw TMP0, STR:CARG1->len - | lbu TMP1, STR:CARG1[1] // Access is always ok (NUL at end). - | addiu RA, BASE, -8 - | sltu RD, r0, TMP0 - | mtc1 TMP1, f0 - | addiu RD, RD, 1 - | cvt.d.w f0, f0 - | lw PC, FRAME_PC(BASE) - | sll RD, RD, 3 // RD = ((str->len != 0)+1)*8 - | b ->fff_res - |. sdc1 f0, 0(RA) - | - |.ffunc string_char // Only handle the 1-arg case here. - | ffgccheck - | lw CARG3, HI(BASE) - | ldc1 FARG1, 0(BASE) - | li AT, 8 - | bne NARGS8:RC, AT, ->fff_fallback // Exactly 1 argument. - |. sltiu AT, CARG3, LJ_TISNUM - | beqz AT, ->fff_fallback - |. li CARG3, 1 - | cvt.w.d FARG1, FARG1 - | addiu CARG2, sp, ARG5_OFS - | sltiu AT, TMP0, 256 - | mfc1 TMP0, FARG1 - | beqz AT, ->fff_fallback - |. sw TMP0, ARG5 - |->fff_newstr: - | load_got lj_str_new - | sw BASE, L->base - | sw PC, SAVE_PC - | call_intern lj_str_new // (lua_State *L, char *str, size_t l) - |. move CARG1, L - | // Returns GCstr *. - | lw BASE, L->base - | move CARG1, CRET1 - | b ->fff_restv - |. li CARG3, LJ_TSTR - | - |.ffunc string_sub - | ffgccheck - | addiu AT, NARGS8:RC, -16 - | lw CARG3, 16+HI(BASE) - | ldc1 f0, 16(BASE) - | lw TMP0, HI(BASE) - | lw STR:CARG1, LO(BASE) - | bltz AT, ->fff_fallback - | lw CARG2, 8+HI(BASE) - | ldc1 f2, 8(BASE) - | beqz AT, >1 - |. li CARG4, -1 - | cvt.w.d f0, f0 - | sltiu AT, CARG3, LJ_TISNUM - | beqz AT, ->fff_fallback - |. mfc1 CARG4, f0 - |1: - | sltiu AT, CARG2, LJ_TISNUM - | beqz AT, ->fff_fallback - |. li AT, LJ_TSTR - | cvt.w.d f2, f2 - | bne TMP0, AT, ->fff_fallback - |. lw CARG2, STR:CARG1->len - | mfc1 CARG3, f2 - | // STR:CARG1 = str, CARG2 = str->len, CARG3 = start, CARG4 = end - | slt AT, CARG4, r0 - | addiu TMP0, CARG2, 1 - | addu TMP1, CARG4, TMP0 - | slt TMP3, CARG3, r0 - | movn CARG4, TMP1, AT // if (end < 0) end += len+1 - | addu TMP1, CARG3, TMP0 - | movn CARG3, TMP1, TMP3 // if (start < 0) start += len+1 - | li TMP2, 1 - | slt AT, CARG4, r0 - | slt TMP3, r0, CARG3 - | movn CARG4, r0, AT // if (end < 0) end = 0 - | movz CARG3, TMP2, TMP3 // if (start < 1) start = 1 - | slt AT, CARG2, CARG4 - | movn CARG4, CARG2, AT // if (end > len) end = len - | addu CARG2, STR:CARG1, CARG3 - | subu CARG3, CARG4, CARG3 // len = end - start - | addiu CARG2, CARG2, sizeof(GCstr)-1 - | bgez CARG3, ->fff_newstr - |. addiu CARG3, CARG3, 1 // len++ - |->fff_emptystr: // Return empty string. - | addiu STR:CARG1, DISPATCH, DISPATCH_GL(strempty) - | b ->fff_restv - |. li CARG3, LJ_TSTR - | - |.ffunc string_rep // Only handle the 1-char case inline. - | ffgccheck - | lw TMP0, HI(BASE) - | sltiu AT, NARGS8:RC, 16 - | lw CARG4, 8+HI(BASE) - | lw STR:CARG1, LO(BASE) - | addiu TMP0, TMP0, -LJ_TSTR - | ldc1 f0, 8(BASE) - | or AT, AT, TMP0 - | bnez AT, ->fff_fallback - |. sltiu AT, CARG4, LJ_TISNUM - | cvt.w.d f0, f0 - | beqz AT, ->fff_fallback - |. lw TMP0, STR:CARG1->len - | mfc1 CARG3, f0 - | lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) - | li AT, 1 - | blez CARG3, ->fff_emptystr // Count <= 0? - |. sltu AT, AT, TMP0 - | beqz TMP0, ->fff_emptystr // Zero length string? - |. sltu TMP0, TMP1, CARG3 - | or AT, AT, TMP0 - | lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) - | bnez AT, ->fff_fallback // Fallback for > 1-char strings. - |. lbu TMP0, STR:CARG1[1] - | addu TMP2, CARG2, CARG3 - |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). - | addiu TMP2, TMP2, -1 - | sltu AT, CARG2, TMP2 - | bnez AT, <1 - |. sb TMP0, 0(TMP2) - | b ->fff_newstr - |. nop - | - |.ffunc string_reverse - | ffgccheck - | lw CARG3, HI(BASE) - | lw STR:CARG1, LO(BASE) - | beqz NARGS8:RC, ->fff_fallback - |. li AT, LJ_TSTR - | bne CARG3, AT, ->fff_fallback - |. lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) - | lw CARG3, STR:CARG1->len - | addiu CARG1, STR:CARG1, #STR - | lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) - | sltu AT, TMP1, CARG3 - | bnez AT, ->fff_fallback - |. addu TMP3, CARG1, CARG3 - | addu CARG4, CARG2, CARG3 - |1: // Reverse string copy. - | lbu TMP1, 0(CARG1) - | sltu AT, CARG1, TMP3 - | beqz AT, ->fff_newstr - |. addiu CARG1, CARG1, 1 - | addiu CARG4, CARG4, -1 - | b <1 - | sb TMP1, 0(CARG4) - | - |.macro ffstring_case, name, lo - | .ffunc name - | ffgccheck - | lw CARG3, HI(BASE) - | lw STR:CARG1, LO(BASE) - | beqz NARGS8:RC, ->fff_fallback - |. li AT, LJ_TSTR - | bne CARG3, AT, ->fff_fallback - |. lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) - | lw CARG3, STR:CARG1->len - | addiu CARG1, STR:CARG1, #STR - | lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) - | sltu AT, TMP1, CARG3 - | bnez AT, ->fff_fallback - |. addu TMP3, CARG1, CARG3 - | move CARG4, CARG2 - |1: // ASCII case conversion. - | lbu TMP1, 0(CARG1) - | sltu AT, CARG1, TMP3 - | beqz AT, ->fff_newstr - |. addiu TMP0, TMP1, -lo - | xori TMP2, TMP1, 0x20 - | sltiu AT, TMP0, 26 - | movn TMP1, TMP2, AT - | addiu CARG1, CARG1, 1 - | sb TMP1, 0(CARG4) - | b <1 - |. addiu CARG4, CARG4, 1 - |.endmacro - | - |ffstring_case string_lower, 65 - |ffstring_case string_upper, 97 - | - |//-- Table library ------------------------------------------------------ - | - |.ffunc_1 table_getn - | li AT, LJ_TTAB - | bne CARG3, AT, ->fff_fallback - |. load_got lj_tab_len - | call_intern lj_tab_len // (GCtab *t) - |. nop - | // Returns uint32_t (but less than 2^31). - | b ->fff_resi - |. nop - | - |//-- Bit library -------------------------------------------------------- - | - |.macro .ffunc_bit, name - | .ffunc_n bit_..name - |. add.d FARG1, FARG1, TOBIT - | mfc1 CRET1, FARG1 - |.endmacro - | - |.macro .ffunc_bit_op, name, ins - | .ffunc_bit name - | addiu TMP1, BASE, 8 - | addu TMP2, BASE, NARGS8:RC - |1: - | lw CARG4, HI(TMP1) - | beq TMP1, TMP2, ->fff_resi - |. ldc1 FARG1, 0(TMP1) - | sltiu AT, CARG4, LJ_TISNUM - | beqz AT, ->fff_fallback - | add.d FARG1, FARG1, TOBIT - | mfc1 CARG2, FARG1 - | ins CRET1, CRET1, CARG2 - | b <1 - |. addiu TMP1, TMP1, 8 - |.endmacro - | - |.ffunc_bit_op band, and - |.ffunc_bit_op bor, or - |.ffunc_bit_op bxor, xor - | - |.ffunc_bit bswap - | srl TMP0, CRET1, 24 - | srl TMP2, CRET1, 8 - | sll TMP1, CRET1, 24 - | andi TMP2, TMP2, 0xff00 - | or TMP0, TMP0, TMP1 - | andi CRET1, CRET1, 0xff00 - | or TMP0, TMP0, TMP2 - | sll CRET1, CRET1, 8 - | b ->fff_resi - |. or CRET1, TMP0, CRET1 - | - |.ffunc_bit bnot - | b ->fff_resi - |. not CRET1, CRET1 - | - |.macro .ffunc_bit_sh, name, ins, shmod - | .ffunc_nn bit_..name - |. add.d FARG1, FARG1, TOBIT - | add.d FARG2, FARG2, TOBIT - | mfc1 CARG1, FARG1 - | mfc1 CARG2, FARG2 - |.if shmod == 1 - | li AT, 32 - | subu TMP0, AT, CARG2 - | sllv CARG2, CARG1, CARG2 - | srlv CARG1, CARG1, TMP0 - |.elif shmod == 2 - | li AT, 32 - | subu TMP0, AT, CARG2 - | srlv CARG2, CARG1, CARG2 - | sllv CARG1, CARG1, TMP0 - |.endif - | b ->fff_resi - |. ins CRET1, CARG1, CARG2 - |.endmacro - | - |.ffunc_bit_sh lshift, sllv, 0 - |.ffunc_bit_sh rshift, srlv, 0 - |.ffunc_bit_sh arshift, srav, 0 - |// Can't use rotrv, since it's only in MIPS32R2. - |.ffunc_bit_sh rol, or, 1 - |.ffunc_bit_sh ror, or, 2 - | - |.ffunc_bit tobit - |->fff_resi: - | mtc1 CRET1, FRET1 - | b ->fff_resn - |. cvt.d.w FRET1, FRET1 - | - |//----------------------------------------------------------------------- - | - |->fff_fallback: // Call fast function fallback handler. - | // BASE = new base, RB = CFUNC, RC = nargs*8 - | lw TMP3, CFUNC:RB->f - | addu TMP1, BASE, NARGS8:RC - | lw PC, FRAME_PC(BASE) // Fallback may overwrite PC. - | addiu TMP0, TMP1, 8*LUA_MINSTACK - | lw TMP2, L->maxstack - | sw PC, SAVE_PC // Redundant (but a defined value). - | sltu AT, TMP2, TMP0 - | sw BASE, L->base - | sw TMP1, L->top - | bnez AT, >5 // Need to grow stack. - |. move CFUNCADDR, TMP3 - | jalr TMP3 // (lua_State *L) - |. move CARG1, L - | // Either throws an error, or recovers and returns -1, 0 or nresults+1. - | lw BASE, L->base - | sll RD, CRET1, 3 - | bgtz CRET1, ->fff_res // Returned nresults+1? - |. addiu RA, BASE, -8 - |1: // Returned 0 or -1: retry fast path. - | lw TMP0, L->top - | lw LFUNC:RB, FRAME_FUNC(BASE) - | bnez CRET1, ->vm_call_tail // Returned -1? - |. subu NARGS8:RC, TMP0, BASE - | ins_callt // Returned 0: retry fast path. - | - |// Reconstruct previous base for vmeta_call during tailcall. - |->vm_call_tail: - | andi TMP0, PC, FRAME_TYPE - | li AT, -4 - | bnez TMP0, >3 - |. and TMP1, PC, AT - | lbu TMP1, OFS_RA(PC) - | sll TMP1, TMP1, 3 - | addiu TMP1, TMP1, 8 - |3: - | b ->vm_call_dispatch // Resolve again for tailcall. - |. subu TMP2, BASE, TMP1 - | - |5: // Grow stack for fallback handler. - | load_got lj_state_growstack - | li CARG2, LUA_MINSTACK - | call_intern lj_state_growstack // (lua_State *L, int n) - |. move CARG1, L - | lw BASE, L->base - | b <1 - |. li CRET1, 0 // Force retry. - | - |->fff_gcstep: // Call GC step function. - | // BASE = new base, RC = nargs*8 - | move MULTRES, ra - | load_got lj_gc_step - | sw BASE, L->base - | addu TMP0, BASE, NARGS8:RC - | sw PC, SAVE_PC // Redundant (but a defined value). - | sw TMP0, L->top - | call_intern lj_gc_step // (lua_State *L) - |. move CARG1, L - | lw BASE, L->base - | move ra, MULTRES - | lw TMP0, L->top - | lw CFUNC:RB, FRAME_FUNC(BASE) - | jr ra - |. subu NARGS8:RC, TMP0, BASE - | - |//----------------------------------------------------------------------- - |//-- Special dispatch targets ------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_record: // Dispatch target for recording phase. -#if LJ_HASJIT - | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | andi AT, TMP3, HOOK_VMEVENT // No recording while in vmevent. - | bnez AT, >5 - | // Decrement the hookcount for consistency, but always do the call. - |. lw TMP2, DISPATCH_GL(hookcount)(DISPATCH) - | andi AT, TMP3, HOOK_ACTIVE - | bnez AT, >1 - |. addiu TMP2, TMP2, -1 - | andi AT, TMP3, LUA_MASKLINE|LUA_MASKCOUNT - | beqz AT, >1 - |. nop - | b >1 - |. sw TMP2, DISPATCH_GL(hookcount)(DISPATCH) -#endif - | - |->vm_rethook: // Dispatch target for return hooks. - | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | andi AT, TMP3, HOOK_ACTIVE // Hook already active? - | beqz AT, >1 - |5: // Re-dispatch to static ins. - |. lw AT, GG_DISP2STATIC(TMP0) // Assumes TMP0 holds DISPATCH+OP*4. - | jr AT - |. nop - | - |->vm_inshook: // Dispatch target for instr/line hooks. - | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | lw TMP2, DISPATCH_GL(hookcount)(DISPATCH) - | andi AT, TMP3, HOOK_ACTIVE // Hook already active? - | bnez AT, <5 - |. andi AT, TMP3, LUA_MASKLINE|LUA_MASKCOUNT - | beqz AT, <5 - |. addiu TMP2, TMP2, -1 - | beqz TMP2, >1 - |. sw TMP2, DISPATCH_GL(hookcount)(DISPATCH) - | andi AT, TMP3, LUA_MASKLINE - | beqz AT, <5 - |1: - |. load_got lj_dispatch_ins - | sw MULTRES, SAVE_MULTRES - | move CARG2, PC - | sw BASE, L->base - | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. - | call_intern lj_dispatch_ins // (lua_State *L, const BCIns *pc) - |. move CARG1, L - |3: - | lw BASE, L->base - |4: // Re-dispatch to static ins. - | lw INS, -4(PC) - | decode_OP4a TMP1, INS - | decode_OP4b TMP1 - | addu TMP0, DISPATCH, TMP1 - | decode_RD8a RD, INS - | lw AT, GG_DISP2STATIC(TMP0) - | decode_RA8a RA, INS - | decode_RD8b RD - | jr AT - | decode_RA8b RA - | - |->cont_hook: // Continue from hook yield. - | addiu PC, PC, 4 - | b <4 - |. lw MULTRES, -24+LO(RB) // Restore MULTRES for *M ins. - | - |->vm_hotloop: // Hot loop counter underflow. -#if LJ_HASJIT - | lw LFUNC:TMP1, FRAME_FUNC(BASE) - | addiu CARG1, DISPATCH, GG_DISP2J - | sw PC, SAVE_PC - | lw TMP1, LFUNC:TMP1->pc - | move CARG2, PC - | sw L, DISPATCH_J(L)(DISPATCH) - | lbu TMP1, PC2PROTO(framesize)(TMP1) - | load_got lj_trace_hot - | sw BASE, L->base - | sll TMP1, TMP1, 3 - | addu TMP1, BASE, TMP1 - | call_intern lj_trace_hot // (jit_State *J, const BCIns *pc) - |. sw TMP1, L->top - | b <3 - |. nop -#endif - | - |->vm_callhook: // Dispatch target for call hooks. -#if LJ_HASJIT - | b >1 -#endif - |. move CARG2, PC - | - |->vm_hotcall: // Hot call counter underflow. -#if LJ_HASJIT - | ori CARG2, PC, 1 - |1: -#endif - | load_got lj_dispatch_call - | addu TMP0, BASE, RC - | sw PC, SAVE_PC - | sw BASE, L->base - | subu RA, RA, BASE - | sw TMP0, L->top - | call_intern lj_dispatch_call // (lua_State *L, const BCIns *pc) - |. move CARG1, L - | // Returns ASMFunction. - | lw BASE, L->base - | lw TMP0, L->top - | sw r0, SAVE_PC // Invalidate for subsequent line hook. - | subu NARGS8:RC, TMP0, BASE - | addu RA, BASE, RA - | lw LFUNC:RB, FRAME_FUNC(BASE) - | jr CRET1 - |. lw INS, -4(PC) - | - |//----------------------------------------------------------------------- - |//-- Trace exit handler ------------------------------------------------- - |//----------------------------------------------------------------------- - | - |.macro savex_, a, b - | sdc1 f..a, 16+a*8(sp) - | sw r..a, 16+32*8+a*4(sp) - | sw r..b, 16+32*8+b*4(sp) - |.endmacro - | - |->vm_exit_handler: -#if LJ_HASJIT - | addiu sp, sp, -(16+32*8+32*4) - | savex_ 0, 1 - | savex_ 2, 3 - | savex_ 4, 5 - | savex_ 6, 7 - | savex_ 8, 9 - | savex_ 10, 11 - | savex_ 12, 13 - | savex_ 14, 15 - | savex_ 16, 17 - | savex_ 18, 19 - | savex_ 20, 21 - | savex_ 22, 23 - | savex_ 24, 25 - | savex_ 26, 27 - | sdc1 f28, 16+28*8(sp) - | sw r28, 16+32*8+28*4(sp) - | sdc1 f30, 16+30*8(sp) - | sw r30, 16+32*8+30*4(sp) - | sw r0, 16+32*8+31*4(sp) // Clear RID_TMP. - | li_vmstate EXIT - | addiu TMP2, sp, 16+32*8+32*4 // Recompute original value of sp. - | addiu DISPATCH, JGL, -GG_DISP2G-32768 - | lw TMP1, 0(TMP2) // Load exit number. - | st_vmstate - | sw TMP2, 16+32*8+29*4(sp) // Store sp in RID_SP. - | lw L, DISPATCH_GL(jit_L)(DISPATCH) - | lw BASE, DISPATCH_GL(jit_base)(DISPATCH) - | load_got lj_trace_exit - | sw L, DISPATCH_J(L)(DISPATCH) - | sw ra, DISPATCH_J(parent)(DISPATCH) // Store trace number. - | sw TMP1, DISPATCH_J(exitno)(DISPATCH) // Store exit number. - | addiu CARG1, DISPATCH, GG_DISP2J - | sw BASE, L->base - | call_intern lj_trace_exit // (jit_State *J, ExitState *ex) - |. addiu CARG2, sp, 16 - | // Returns MULTRES (unscaled) or negated error code. - | lw TMP1, L->cframe - | li AT, -4 - | lw BASE, L->base - | and sp, TMP1, AT - | lw PC, SAVE_PC // Get SAVE_PC. - | b >1 - |. sw L, SAVE_L // Set SAVE_L (on-trace resume/yield). -#endif - |->vm_exit_interp: -#if LJ_HASJIT - | // CRET1 = MULTRES or negated error code, BASE, PC and JGL set. - | lw L, SAVE_L - | addiu DISPATCH, JGL, -GG_DISP2G-32768 - |1: - | bltz CRET1, >3 // Check for error from exit. - |. lw LFUNC:TMP1, FRAME_FUNC(BASE) - | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). - | sll MULTRES, CRET1, 3 - | li TISNIL, LJ_TNIL - | sw MULTRES, SAVE_MULTRES - | mtc1 TMP3, TOBIT - | lw TMP1, LFUNC:TMP1->pc - | sw r0, DISPATCH_GL(jit_L)(DISPATCH) - | lw KBASE, PC2PROTO(k)(TMP1) - | cvt.d.s TOBIT, TOBIT - | // Modified copy of ins_next which handles function header dispatch, too. - | lw INS, 0(PC) - | addiu PC, PC, 4 - | // Assumes TISNIL == ~LJ_VMST_INTERP == -1 - | sw TISNIL, DISPATCH_GL(vmstate)(DISPATCH) - | decode_OP4a TMP1, INS - | decode_OP4b TMP1 - | sltiu TMP2, TMP1, BC_FUNCF*4 // Function header? - | addu TMP0, DISPATCH, TMP1 - | decode_RD8a RD, INS - | lw AT, 0(TMP0) - | decode_RA8a RA, INS - | beqz TMP2, >2 - |. decode_RA8b RA - | jr AT - |. decode_RD8b RD - |2: - | addiu RC, MULTRES, -8 - | jr AT - |. add RA, RA, BASE - | - |3: // Rethrow error from the right C frame. - | load_got lj_err_throw - | negu CARG2, CRET1 - | call_intern lj_err_throw // (lua_State *L, int errcode) - |. move CARG1, L -#endif - | - |//----------------------------------------------------------------------- - |//-- Math helper functions ---------------------------------------------- - |//----------------------------------------------------------------------- - | - |// Modifies AT, TMP0, FRET1, FRET2, f4. Keeps all others incl. FARG1, FARG2. - |.macro vm_round, func - | lui TMP0, 0x4330 // Hiword of 2^52 (double). - | mtc1 r0, f4 - | mtc1 TMP0, f5 - | abs.d FRET2, FARG1 // |x| - | mfc1 AT, f13 - | c.olt.d 0, FRET2, f4 - | add.d FRET1, FRET2, f4 // (|x| + 2^52) - 2^52 - | bc1f 0, >1 // Truncate only if |x| < 2^52. - |. sub.d FRET1, FRET1, f4 - | slt AT, AT, r0 - |.if "func" == "ceil" - | lui TMP0, 0xbff0 // Hiword of -1 (double). Preserves -0. - |.else - | lui TMP0, 0x3ff0 // Hiword of +1 (double). - |.endif - |.if "func" == "trunc" - | mtc1 TMP0, f5 - | c.olt.d 0, FRET2, FRET1 // |x| < result? - | sub.d FRET2, FRET1, f4 - | movt.d FRET1, FRET2, 0 // If yes, subtract +1. - | neg.d FRET2, FRET1 - | jr ra - |. movn.d FRET1, FRET2, AT // Merge sign bit back in. - |.else - | neg.d FRET2, FRET1 - | mtc1 TMP0, f5 - | movn.d FRET1, FRET2, AT // Merge sign bit back in. - |.if "func" == "ceil" - | c.olt.d 0, FRET1, FARG1 // x > result? - |.else - | c.olt.d 0, FARG1, FRET1 // x < result? - |.endif - | sub.d FRET2, FRET1, f4 // If yes, subtract +-1. - | jr ra - |. movt.d FRET1, FRET2, 0 - |.endif - |1: - | jr ra - |. mov.d FRET1, FARG1 - |.endmacro - | - |->vm_floor: - | vm_round floor - |->vm_ceil: - | vm_round ceil - |->vm_trunc: -#if LJ_HASJIT - | vm_round trunc -#endif - | - |//----------------------------------------------------------------------- - |//-- Miscellaneous functions -------------------------------------------- - |//----------------------------------------------------------------------- - | - |//----------------------------------------------------------------------- - |//-- FFI helper functions ----------------------------------------------- - |//----------------------------------------------------------------------- - | - |// Handler for callback functions. Callback slot number in r1, g in r2. - |->vm_ffi_callback: -#if LJ_HASFFI - |.type CTSTATE, CTState, PC - | saveregs - | lw CTSTATE, GL:r2->ctype_state - | addiu DISPATCH, r2, GG_G2DISP - | load_got lj_ccallback_enter - | sw r1, CTSTATE->cb.slot - | sw CARG1, CTSTATE->cb.gpr[0] - | sw CARG2, CTSTATE->cb.gpr[1] - | sdc1 FARG1, CTSTATE->cb.fpr[0] - | sw CARG3, CTSTATE->cb.gpr[2] - | sw CARG4, CTSTATE->cb.gpr[3] - | sdc1 FARG2, CTSTATE->cb.fpr[1] - | addiu TMP0, sp, CFRAME_SPACE+16 - | sw TMP0, CTSTATE->cb.stack - | sw r0, SAVE_PC // Any value outside of bytecode is ok. - | move CARG2, sp - | call_intern lj_ccallback_enter // (CTState *cts, void *cf) - |. move CARG1, CTSTATE - | // Returns lua_State *. - | lw BASE, L:CRET1->base - | lw RC, L:CRET1->top - | move L, CRET1 - | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). - | lw LFUNC:RB, FRAME_FUNC(BASE) - | mtc1 TMP3, TOBIT - | li_vmstate INTERP - | li TISNIL, LJ_TNIL - | subu RC, RC, BASE - | st_vmstate - | cvt.d.s TOBIT, TOBIT - | ins_callt -#endif - | - |->cont_ffi_callback: // Return from FFI callback. -#if LJ_HASFFI - | load_got lj_ccallback_leave - | lw CTSTATE, DISPATCH_GL(ctype_state)(DISPATCH) - | sw BASE, L->base - | sw RB, L->top - | sw L, CTSTATE->L - | move CARG2, RA - | call_intern lj_ccallback_leave // (CTState *cts, TValue *o) - |. move CARG1, CTSTATE - | lw CRET1, CTSTATE->cb.gpr[0] - | ldc1 FRET1, CTSTATE->cb.fpr[0] - | lw CRET2, CTSTATE->cb.gpr[1] - | b ->vm_leave_unw - |. ldc1 FRET2, CTSTATE->cb.fpr[1] -#endif - | - |->vm_ffi_call: // Call C function via FFI. - | // Caveat: needs special frame unwinding, see below. -#if LJ_HASFFI - | .type CCSTATE, CCallState, CARG1 - | lw TMP1, CCSTATE->spadj - | lbu CARG2, CCSTATE->nsp - | move TMP2, sp - | subu sp, sp, TMP1 - | sw ra, -4(TMP2) - | sll CARG2, CARG2, 2 - | sw r16, -8(TMP2) - | sw CCSTATE, -12(TMP2) - | move r16, TMP2 - | addiu TMP1, CCSTATE, offsetof(CCallState, stack) - | addiu TMP2, sp, 16 - | beqz CARG2, >2 - |. addu TMP3, TMP1, CARG2 - |1: - | lw TMP0, 0(TMP1) - | addiu TMP1, TMP1, 4 - | sltu AT, TMP1, TMP3 - | sw TMP0, 0(TMP2) - | bnez AT, <1 - |. addiu TMP2, TMP2, 4 - |2: - | lw CFUNCADDR, CCSTATE->func - | lw CARG2, CCSTATE->gpr[1] - | lw CARG3, CCSTATE->gpr[2] - | lw CARG4, CCSTATE->gpr[3] - | ldc1 FARG1, CCSTATE->fpr[0] - | ldc1 FARG2, CCSTATE->fpr[1] - | jalr CFUNCADDR - |. lw CARG1, CCSTATE->gpr[0] // Do this last, since CCSTATE is CARG1. - | lw CCSTATE:TMP1, -12(r16) - | lw TMP2, -8(r16) - | lw ra, -4(r16) - | sw CRET1, CCSTATE:TMP1->gpr[0] - | sw CRET2, CCSTATE:TMP1->gpr[1] - | sdc1 FRET1, CCSTATE:TMP1->fpr[0] - | sdc1 FRET2, CCSTATE:TMP1->fpr[1] - | move sp, r16 - | jr ra - |. move r16, TMP2 -#endif - |// Note: vm_ffi_call must be the last function in this object file! - | - |//----------------------------------------------------------------------- -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop) -{ - int vk = 0; - |=>defop: - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - | // RA = src1*8, RD = src2*8, JMP with RD = target - | addu CARG2, BASE, RA - | addu CARG3, BASE, RD - | lw TMP0, HI(CARG2) - | lw TMP1, HI(CARG3) - | ldc1 f0, 0(CARG2) - | ldc1 f2, 0(CARG3) - | sltiu TMP0, TMP0, LJ_TISNUM - | sltiu TMP1, TMP1, LJ_TISNUM - | lhu TMP2, OFS_RD(PC) - | and TMP0, TMP0, TMP1 - | addiu PC, PC, 4 - | beqz TMP0, ->vmeta_comp - |. lui TMP1, (-(BCBIAS_J*4 >> 16) & 65535) - | decode_RD4b TMP2 - | addu TMP2, TMP2, TMP1 - if (op == BC_ISLT || op == BC_ISGE) { - | c.olt.d f0, f2 - } else { - | c.ole.d f0, f2 - } - if (op == BC_ISLT || op == BC_ISLE) { - | movf TMP2, r0 - } else { - | movt TMP2, r0 - } - | addu PC, PC, TMP2 - |1: - | ins_next - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - | // RA = src1*8, RD = src2*8, JMP with RD = target - | addu RA, BASE, RA - | addiu PC, PC, 4 - | lw TMP0, HI(RA) - | ldc1 f0, 0(RA) - | addu RD, BASE, RD - | lhu TMP2, -4+OFS_RD(PC) - | lw TMP1, HI(RD) - | ldc1 f2, 0(RD) - | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) - | sltiu AT, TMP0, LJ_TISNUM - | sltiu CARG1, TMP1, LJ_TISNUM - | decode_RD4b TMP2 - | and AT, AT, CARG1 - | beqz AT, >5 - |. addu TMP2, TMP2, TMP3 - | c.eq.d f0, f2 - if (vk) { - | movf TMP2, r0 - } else { - | movt TMP2, r0 - } - |1: - | addu PC, PC, TMP2 - | ins_next - |5: // Either or both types are not numbers. - | lw CARG2, LO(RA) - | lw CARG3, LO(RD) - if (LJ_HASFFI) { - | li TMP3, LJ_TCDATA - | beq TMP0, TMP3, ->vmeta_equal_cd - } - |. sltiu AT, TMP0, LJ_TISPRI // Not a primitive? - if (LJ_HASFFI) { - | beq TMP1, TMP3, ->vmeta_equal_cd - } - |. xor TMP3, CARG2, CARG3 // Same tv? - | xor TMP1, TMP1, TMP0 // Same type? - | sltiu CARG1, TMP0, LJ_TISTABUD+1 // Table or userdata? - | movz TMP3, r0, AT // Ignore tv if primitive. - | movn CARG1, r0, TMP1 // Tab/ud and same type? - | or AT, TMP1, TMP3 // Same type && (pri||same tv). - | movz CARG1, r0, AT - | beqz CARG1, <1 // Done if not tab/ud or not same type or same tv. - if (vk) { - |. movn TMP2, r0, AT - } else { - |. movz TMP2, r0, AT - } - | // Different tables or userdatas. Need to check __eq metamethod. - | // Field metatable must be at same offset for GCtab and GCudata! - | lw TAB:TMP1, TAB:CARG2->metatable - | beqz TAB:TMP1, <1 // No metatable? - |. nop - | lbu TMP1, TAB:TMP1->nomm - | andi TMP1, TMP1, 1<vmeta_equal // Handle __eq metamethod. - |. li CARG4, 1-vk // ne = 0 or 1. - break; - - case BC_ISEQS: case BC_ISNES: - vk = op == BC_ISEQS; - | // RA = src*8, RD = str_const*8 (~), JMP with RD = target - | addu RA, BASE, RA - | addiu PC, PC, 4 - | lw TMP0, HI(RA) - | srl RD, RD, 1 - | lw STR:TMP3, LO(RA) - | subu RD, KBASE, RD - | lhu TMP2, -4+OFS_RD(PC) - if (LJ_HASFFI) { - | li AT, LJ_TCDATA - | beq TMP0, AT, ->vmeta_equal_cd - } - |. lw STR:TMP1, -4(RD) // KBASE-4-str_const*4 - | addiu TMP0, TMP0, -LJ_TSTR - | decode_RD4b TMP2 - | xor TMP1, STR:TMP1, STR:TMP3 - | or TMP0, TMP0, TMP1 - | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) - | addu TMP2, TMP2, TMP3 - if (vk) { - | movn TMP2, r0, TMP0 - } else { - | movz TMP2, r0, TMP0 - } - | addu PC, PC, TMP2 - | ins_next - break; - - case BC_ISEQN: case BC_ISNEN: - vk = op == BC_ISEQN; - | // RA = src*8, RD = num_const*8, JMP with RD = target - | addu RA, BASE, RA - | addiu PC, PC, 4 - | lw TMP0, HI(RA) - | ldc1 f0, 0(RA) - | addu RD, KBASE, RD - | lhu TMP2, -4+OFS_RD(PC) - | ldc1 f2, 0(RD) - | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) - | sltiu AT, TMP0, LJ_TISNUM - | decode_RD4b TMP2 - if (LJ_HASFFI) { - | beqz AT, >5 - } else { - | beqz AT, >1 - } - |. addu TMP2, TMP2, TMP3 - | c.eq.d f0, f2 - if (vk) { - | movf TMP2, r0 - | addu PC, PC, TMP2 - |1: - } else { - | movt TMP2, r0 - |1: - | addu PC, PC, TMP2 - } - | ins_next - if (LJ_HASFFI) { - |5: - | li AT, LJ_TCDATA - | beq TMP0, AT, ->vmeta_equal_cd - |. nop - | b <1 - |. nop - } - break; - - case BC_ISEQP: case BC_ISNEP: - vk = op == BC_ISEQP; - | // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target - | addu RA, BASE, RA - | srl TMP1, RD, 3 - | lw TMP0, HI(RA) - | lhu TMP2, OFS_RD(PC) - | not TMP1, TMP1 - | addiu PC, PC, 4 - if (LJ_HASFFI) { - | li AT, LJ_TCDATA - | beq TMP0, AT, ->vmeta_equal_cd - } - |. xor TMP0, TMP0, TMP1 - | decode_RD4b TMP2 - | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) - | addu TMP2, TMP2, TMP3 - if (vk) { - | movn TMP2, r0, TMP0 - } else { - | movz TMP2, r0, TMP0 - } - | addu PC, PC, TMP2 - | ins_next - break; - - /* -- Unary test and copy ops ------------------------------------------- */ - - case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: - | // RA = dst*8 or unused, RD = src*8, JMP with RD = target - | addu RD, BASE, RD - | lhu TMP2, OFS_RD(PC) - | lw TMP0, HI(RD) - | addiu PC, PC, 4 - if (op == BC_IST || op == BC_ISF) { - | sltiu TMP0, TMP0, LJ_TISTRUECOND - | decode_RD4b TMP2 - | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) - | addu TMP2, TMP2, TMP3 - if (op == BC_IST) { - | movz TMP2, r0, TMP0 - } else { - | movn TMP2, r0, TMP0 - } - | addu PC, PC, TMP2 - } else { - | sltiu TMP0, TMP0, LJ_TISTRUECOND - | ldc1 f0, 0(RD) - if (op == BC_ISTC) { - | beqz TMP0, >1 - } else { - | bnez TMP0, >1 - } - |. addu RA, BASE, RA - | decode_RD4b TMP2 - | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) - | addu TMP2, TMP2, TMP3 - | sdc1 f0, 0(RA) - | addu PC, PC, TMP2 - |1: - } - | ins_next - break; - - /* -- Unary ops --------------------------------------------------------- */ - - case BC_MOV: - | // RA = dst*8, RD = src*8 - | addu RD, BASE, RD - | addu RA, BASE, RA - | ldc1 f0, 0(RD) - | ins_next1 - | sdc1 f0, 0(RA) - | ins_next2 - break; - case BC_NOT: - | // RA = dst*8, RD = src*8 - | addu RD, BASE, RD - | addu RA, BASE, RA - | lw TMP0, HI(RD) - | li TMP1, LJ_TFALSE - | sltiu TMP0, TMP0, LJ_TISTRUECOND - | addiu TMP1, TMP0, LJ_TTRUE - | ins_next1 - | sw TMP1, HI(RA) - | ins_next2 - break; - case BC_UNM: - | // RA = dst*8, RD = src*8 - | addu CARG3, BASE, RD - | addu RA, BASE, RA - | lw TMP0, HI(CARG3) - | ldc1 f0, 0(CARG3) - | sltiu AT, TMP0, LJ_TISNUM - | beqz AT, ->vmeta_unm - |. neg.d f0, f0 - | ins_next1 - | sdc1 f0, 0(RA) - | ins_next2 - break; - case BC_LEN: - | // RA = dst*8, RD = src*8 - | addu CARG2, BASE, RD - | addu RA, BASE, RA - | lw TMP0, HI(CARG2) - | lw CARG1, LO(CARG2) - | li AT, LJ_TSTR - | bne TMP0, AT, >2 - |. li AT, LJ_TTAB - | lw CRET1, STR:CARG1->len - |1: - | mtc1 CRET1, f0 - | cvt.d.w f0, f0 - | ins_next1 - | sdc1 f0, 0(RA) - | ins_next2 - |2: - | bne TMP0, AT, ->vmeta_len - |. nop -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | lw TAB:TMP2, TAB:CARG1->metatable - | bnez TAB:TMP2, >9 - |. nop - |3: -#endif - |->BC_LEN_Z: - | load_got lj_tab_len - | call_intern lj_tab_len // (GCtab *t) - |. nop - | // Returns uint32_t (but less than 2^31). - | b <1 - |. nop -#ifdef LUAJIT_ENABLE_LUA52COMPAT - |9: - | lbu TMP0, TAB:TMP2->nomm - | andi TMP0, TMP0, 1<vmeta_len - |. nop -#endif - break; - - /* -- Binary ops -------------------------------------------------------- */ - - |.macro ins_arithpre - ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); - | decode_RB8a RB, INS - | decode_RB8b RB - | decode_RDtoRC8 RC, RD - | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8 - ||switch (vk) { - ||case 0: - | addu CARG3, BASE, RB - | addu CARG4, KBASE, RC - | lw TMP1, HI(CARG3) - | ldc1 f20, 0(CARG3) - | ldc1 f22, 0(CARG4) - | sltiu AT, TMP1, LJ_TISNUM - || break; - ||case 1: - | addu CARG4, BASE, RB - | addu CARG3, KBASE, RC - | lw TMP1, HI(CARG4) - | ldc1 f22, 0(CARG4) - | ldc1 f20, 0(CARG3) - | sltiu AT, TMP1, LJ_TISNUM - || break; - ||default: - | addu CARG3, BASE, RB - | addu CARG4, BASE, RC - | lw TMP1, HI(CARG3) - | lw TMP2, HI(CARG4) - | ldc1 f20, 0(CARG3) - | ldc1 f22, 0(CARG4) - | sltiu AT, TMP1, LJ_TISNUM - | sltiu TMP0, TMP2, LJ_TISNUM - | and AT, AT, TMP0 - || break; - ||} - | beqz AT, ->vmeta_arith - |. addu RA, BASE, RA - |.endmacro - | - |.macro fpmod, a, b, c - |->BC_MODVN_Z: - | bal ->vm_floor // floor(b/c) - |. div.d FARG1, b, c - | mul.d a, FRET1, c - | sub.d a, b, a // b - floor(b/c)*c - |.endmacro - | - |.macro ins_arith, ins - | ins_arithpre - |.if "ins" == "fpmod_" - | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway. - |. nop - |.else - | ins f0, f20, f22 - | ins_next1 - | sdc1 f0, 0(RA) - | ins_next2 - |.endif - |.endmacro - - case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: - | ins_arith add.d - break; - case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: - | ins_arith sub.d - break; - case BC_MULVN: case BC_MULNV: case BC_MULVV: - | ins_arith mul.d - break; - case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: - | ins_arith div.d - break; - case BC_MODVN: - | ins_arith fpmod - break; - case BC_MODNV: case BC_MODVV: - | ins_arith fpmod_ - break; - case BC_POW: - | decode_RB8a RB, INS - | decode_RB8b RB - | decode_RDtoRC8 RC, RD - | addu CARG3, BASE, RB - | addu CARG4, BASE, RC - | lw TMP1, HI(CARG3) - | lw TMP2, HI(CARG4) - | ldc1 FARG1, 0(CARG3) - | ldc1 FARG2, 0(CARG4) - | sltiu AT, TMP1, LJ_TISNUM - | sltiu TMP0, TMP2, LJ_TISNUM - | and AT, AT, TMP0 - | load_got pow - | beqz AT, ->vmeta_arith - |. addu RA, BASE, RA - | call_extern - |. nop - | ins_next1 - | sdc1 FRET1, 0(RA) - | ins_next2 - break; - - case BC_CAT: - | // RA = dst*8, RB = src_start*8, RC = src_end*8 - | decode_RB8a RB, INS - | decode_RB8b RB - | decode_RDtoRC8 RC, RD - | subu CARG3, RC, RB - | sw BASE, L->base - | addu CARG2, BASE, RC - | move MULTRES, RB - |->BC_CAT_Z: - | load_got lj_meta_cat - | srl CARG3, CARG3, 3 - | sw PC, SAVE_PC - | call_intern lj_meta_cat // (lua_State *L, TValue *top, int left) - |. move CARG1, L - | // Returns NULL (finished) or TValue * (metamethod). - | bnez CRET1, ->vmeta_binop - |. lw BASE, L->base - | addu RB, BASE, MULTRES - | ldc1 f0, 0(RB) - | addu RA, BASE, RA - | ins_next1 - | sdc1 f0, 0(RA) // Copy result from RB to RA. - | ins_next2 - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - | // RA = dst*8, RD = str_const*8 (~) - | srl TMP1, RD, 1 - | subu TMP1, KBASE, TMP1 - | ins_next1 - | lw TMP0, -4(TMP1) // KBASE-4-str_const*4 - | addu RA, BASE, RA - | li TMP2, LJ_TSTR - | sw TMP0, LO(RA) - | sw TMP2, HI(RA) - | ins_next2 - break; - case BC_KCDATA: -#if LJ_HASFFI - | // RA = dst*8, RD = cdata_const*8 (~) - | srl TMP1, RD, 1 - | subu TMP1, KBASE, TMP1 - | ins_next1 - | lw TMP0, -4(TMP1) // KBASE-4-cdata_const*4 - | addu RA, BASE, RA - | li TMP2, LJ_TCDATA - | sw TMP0, LO(RA) - | sw TMP2, HI(RA) - | ins_next2 -#endif - break; - case BC_KSHORT: - | // RA = dst*8, RD = int16_literal*8 - | sra RD, INS, 16 - | mtc1 RD, f0 - | addu RA, BASE, RA - | cvt.d.w f0, f0 - | ins_next1 - | sdc1 f0, 0(RA) - | ins_next2 - break; - case BC_KNUM: - | // RA = dst*8, RD = num_const*8 - | addu RD, KBASE, RD - | addu RA, BASE, RA - | ldc1 f0, 0(RD) - | ins_next1 - | sdc1 f0, 0(RA) - | ins_next2 - break; - case BC_KPRI: - | // RA = dst*8, RD = primitive_type*8 (~) - | srl TMP1, RD, 3 - | addu RA, BASE, RA - | not TMP0, TMP1 - | ins_next1 - | sw TMP0, HI(RA) - | ins_next2 - break; - case BC_KNIL: - | // RA = base*8, RD = end*8 - | addu RA, BASE, RA - | sw TISNIL, HI(RA) - | addiu RA, RA, 8 - | addu RD, BASE, RD - |1: - | sw TISNIL, HI(RA) - | slt AT, RA, RD - | bnez AT, <1 - |. addiu RA, RA, 8 - | ins_next_ - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - | // RA = dst*8, RD = uvnum*8 - | lw LFUNC:RB, FRAME_FUNC(BASE) - | srl RD, RD, 1 - | addu RD, RD, LFUNC:RB - | lw UPVAL:RB, LFUNC:RD->uvptr - | ins_next1 - | lw TMP1, UPVAL:RB->v - | ldc1 f0, 0(TMP1) - | addu RA, BASE, RA - | sdc1 f0, 0(RA) - | ins_next2 - break; - case BC_USETV: - | // RA = uvnum*8, RD = src*8 - | lw LFUNC:RB, FRAME_FUNC(BASE) - | srl RA, RA, 1 - | addu RD, BASE, RD - | addu RA, RA, LFUNC:RB - | ldc1 f0, 0(RD) - | lw UPVAL:RB, LFUNC:RA->uvptr - | lbu TMP3, UPVAL:RB->marked - | lw CARG2, UPVAL:RB->v - | andi TMP3, TMP3, LJ_GC_BLACK // isblack(uv) - | lbu TMP0, UPVAL:RB->closed - | lw TMP2, HI(RD) - | sdc1 f0, 0(CARG2) - | li AT, LJ_GC_BLACK|1 - | or TMP3, TMP3, TMP0 - | beq TMP3, AT, >2 // Upvalue is closed and black? - |. addiu TMP2, TMP2, -(LJ_TISNUM+1) - |1: - | ins_next - | - |2: // Check if new value is collectable. - | sltiu AT, TMP2, LJ_TISGCV - (LJ_TISNUM+1) - | beqz AT, <1 // tvisgcv(v) - |. lw TMP1, LO(RD) - | lbu TMP3, GCOBJ:TMP1->gch.marked - | andi TMP3, TMP3, LJ_GC_WHITES // iswhite(v) - | beqz TMP3, <1 - |. load_got lj_gc_barrieruv - | // Crossed a write barrier. Move the barrier forward. - | call_intern lj_gc_barrieruv // (global_State *g, TValue *tv) - |. addiu CARG1, DISPATCH, GG_DISP2G - | b <1 - |. nop - break; - case BC_USETS: - | // RA = uvnum*8, RD = str_const*8 (~) - | lw LFUNC:RB, FRAME_FUNC(BASE) - | srl RA, RA, 1 - | srl TMP1, RD, 1 - | addu RA, RA, LFUNC:RB - | subu TMP1, KBASE, TMP1 - | lw UPVAL:RB, LFUNC:RA->uvptr - | lw STR:TMP1, -4(TMP1) // KBASE-4-str_const*4 - | lbu TMP2, UPVAL:RB->marked - | lw CARG2, UPVAL:RB->v - | lbu TMP3, STR:TMP1->marked - | andi AT, TMP2, LJ_GC_BLACK // isblack(uv) - | lbu TMP2, UPVAL:RB->closed - | li TMP0, LJ_TSTR - | sw STR:TMP1, LO(CARG2) - | bnez AT, >2 - |. sw TMP0, HI(CARG2) - |1: - | ins_next - | - |2: // Check if string is white and ensure upvalue is closed. - | beqz TMP2, <1 - |. andi AT, TMP3, LJ_GC_WHITES // iswhite(str) - | beqz AT, <1 - |. load_got lj_gc_barrieruv - | // Crossed a write barrier. Move the barrier forward. - | call_intern lj_gc_barrieruv // (global_State *g, TValue *tv) - |. addiu CARG1, DISPATCH, GG_DISP2G - | b <1 - |. nop - break; - case BC_USETN: - | // RA = uvnum*8, RD = num_const*8 - | lw LFUNC:RB, FRAME_FUNC(BASE) - | srl RA, RA, 1 - | addu RD, KBASE, RD - | addu RA, RA, LFUNC:RB - | ldc1 f0, 0(RD) - | lw UPVAL:RB, LFUNC:RA->uvptr - | ins_next1 - | lw TMP1, UPVAL:RB->v - | sdc1 f0, 0(TMP1) - | ins_next2 - break; - case BC_USETP: - | // RA = uvnum*8, RD = primitive_type*8 (~) - | lw LFUNC:RB, FRAME_FUNC(BASE) - | srl RA, RA, 1 - | srl TMP0, RD, 3 - | addu RA, RA, LFUNC:RB - | not TMP0, TMP0 - | lw UPVAL:RB, LFUNC:RA->uvptr - | ins_next1 - | lw TMP1, UPVAL:RB->v - | sw TMP0, HI(TMP1) - | ins_next2 - break; - - case BC_UCLO: - | // RA = level*8, RD = target - | lw TMP2, L->openupval - | branch_RD // Do this first since RD is not saved. - | load_got lj_func_closeuv - | sw BASE, L->base - | beqz TMP2, >1 - |. move CARG1, L - | call_intern lj_func_closeuv // (lua_State *L, TValue *level) - |. addu CARG2, BASE, RA - | lw BASE, L->base - |1: - | ins_next - break; - - case BC_FNEW: - | // RA = dst*8, RD = proto_const*8 (~) (holding function prototype) - | srl TMP1, RD, 1 - | load_got lj_func_newL_gc - | subu TMP1, KBASE, TMP1 - | lw CARG3, FRAME_FUNC(BASE) - | lw CARG2, -4(TMP1) // KBASE-4-tab_const*4 - | sw BASE, L->base - | sw PC, SAVE_PC - | // (lua_State *L, GCproto *pt, GCfuncL *parent) - | call_intern lj_func_newL_gc - |. move CARG1, L - | // Returns GCfuncL *. - | lw BASE, L->base - | li TMP0, LJ_TFUNC - | ins_next1 - | addu RA, BASE, RA - | sw TMP0, HI(RA) - | sw LFUNC:CRET1, LO(RA) - | ins_next2 - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - case BC_TDUP: - | // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~) - | lw TMP0, DISPATCH_GL(gc.total)(DISPATCH) - | lw TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) - | sw BASE, L->base - | sw PC, SAVE_PC - | sltu AT, TMP0, TMP1 - | beqz AT, >5 - |1: - if (op == BC_TNEW) { - | load_got lj_tab_new - | srl CARG2, RD, 3 - | andi CARG2, CARG2, 0x7ff - | li TMP0, 0x801 - | addiu AT, CARG2, -0x7ff - | srl CARG3, RD, 14 - | movz CARG2, TMP0, AT - | // (lua_State *L, int32_t asize, uint32_t hbits) - | call_intern lj_tab_new - |. move CARG1, L - | // Returns Table *. - } else { - | load_got lj_tab_dup - | srl TMP1, RD, 1 - | subu TMP1, KBASE, TMP1 - | move CARG1, L - | call_intern lj_tab_dup // (lua_State *L, Table *kt) - |. lw CARG2, -4(TMP1) // KBASE-4-str_const*4 - | // Returns Table *. - } - | lw BASE, L->base - | ins_next1 - | addu RA, BASE, RA - | li TMP0, LJ_TTAB - | sw TAB:CRET1, LO(RA) - | sw TMP0, HI(RA) - | ins_next2 - |5: - | load_got lj_gc_step_fixtop - | move MULTRES, RD - | call_intern lj_gc_step_fixtop // (lua_State *L) - |. move CARG1, L - | b <1 - |. move RD, MULTRES - break; - - case BC_GGET: - | // RA = dst*8, RD = str_const*8 (~) - case BC_GSET: - | // RA = src*8, RD = str_const*8 (~) - | lw LFUNC:TMP2, FRAME_FUNC(BASE) - | srl TMP1, RD, 1 - | subu TMP1, KBASE, TMP1 - | lw TAB:RB, LFUNC:TMP2->env - | lw STR:RC, -4(TMP1) // KBASE-4-str_const*4 - if (op == BC_GGET) { - | b ->BC_TGETS_Z - } else { - | b ->BC_TSETS_Z - } - |. addu RA, BASE, RA - break; - - case BC_TGETV: - | // RA = dst*8, RB = table*8, RC = key*8 - | decode_RB8a RB, INS - | decode_RB8b RB - | decode_RDtoRC8 RC, RD - | addu CARG2, BASE, RB - | addu CARG3, BASE, RC - | lw TMP1, HI(CARG2) - | lw TMP2, HI(CARG3) - | lw TAB:RB, LO(CARG2) - | li AT, LJ_TTAB - | ldc1 f0, 0(CARG3) - | bne TMP1, AT, ->vmeta_tgetv - |. addu RA, BASE, RA - | sltiu AT, TMP2, LJ_TISNUM - | beqz AT, >5 - |. li AT, LJ_TSTR - | - | // Convert number key to integer, check for integerness and range. - | cvt.w.d f2, f0 - | lw TMP0, TAB:RB->asize - | mfc1 TMP2, f2 - | cvt.d.w f4, f2 - | lw TMP1, TAB:RB->array - | c.eq.d f0, f4 - | sltu AT, TMP2, TMP0 - | movf AT, r0 - | sll TMP2, TMP2, 3 - | beqz AT, ->vmeta_tgetv // Integer key and in array part? - |. addu TMP2, TMP1, TMP2 - | lw TMP0, HI(TMP2) - | beq TMP0, TISNIL, >2 - |. ldc1 f0, 0(TMP2) - |1: - | ins_next1 - | sdc1 f0, 0(RA) - | ins_next2 - | - |2: // Check for __index if table value is nil. - | lw TAB:TMP2, TAB:RB->metatable - | beqz TAB:TMP2, <1 // No metatable: done. - |. nop - | lbu TMP0, TAB:TMP2->nomm - | andi TMP0, TMP0, 1<vmeta_tgetv - |. nop - | - |5: - | bne TMP2, AT, ->vmeta_tgetv - |. lw STR:RC, LO(CARG3) - | b ->BC_TGETS_Z // String key? - |. nop - break; - case BC_TGETS: - | // RA = dst*8, RB = table*8, RC = str_const*4 (~) - | decode_RB8a RB, INS - | decode_RB8b RB - | addu CARG2, BASE, RB - | decode_RC4a RC, INS - | lw TMP0, HI(CARG2) - | decode_RC4b RC - | li AT, LJ_TTAB - | lw TAB:RB, LO(CARG2) - | subu CARG3, KBASE, RC - | lw STR:RC, -4(CARG3) // KBASE-4-str_const*4 - | bne TMP0, AT, ->vmeta_tgets1 - |. addu RA, BASE, RA - |->BC_TGETS_Z: - | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8 - | lw TMP0, TAB:RB->hmask - | lw TMP1, STR:RC->hash - | lw NODE:TMP2, TAB:RB->node - | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask - | sll TMP0, TMP1, 5 - | sll TMP1, TMP1, 3 - | subu TMP1, TMP0, TMP1 - | addu NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) - |1: - | lw CARG1, offsetof(Node, key)+HI(NODE:TMP2) - | lw TMP0, offsetof(Node, key)+LO(NODE:TMP2) - | lw NODE:TMP1, NODE:TMP2->next - | lw CARG2, offsetof(Node, val)+HI(NODE:TMP2) - | addiu CARG1, CARG1, -LJ_TSTR - | xor TMP0, TMP0, STR:RC - | or AT, CARG1, TMP0 - | bnez AT, >4 - |. lw TAB:TMP3, TAB:RB->metatable - | beq CARG2, TISNIL, >5 // Key found, but nil value? - |. lw CARG1, offsetof(Node, val)+LO(NODE:TMP2) - |3: - | ins_next1 - | sw CARG2, HI(RA) - | sw CARG1, LO(RA) - | ins_next2 - | - |4: // Follow hash chain. - | bnez NODE:TMP1, <1 - |. move NODE:TMP2, NODE:TMP1 - | // End of hash chain: key not found, nil result. - | - |5: // Check for __index if table value is nil. - | beqz TAB:TMP3, <3 // No metatable: done. - |. li CARG2, LJ_TNIL - | lbu TMP0, TAB:TMP3->nomm - | andi TMP0, TMP0, 1<vmeta_tgets - |. nop - break; - case BC_TGETB: - | // RA = dst*8, RB = table*8, RC = index*8 - | decode_RB8a RB, INS - | decode_RB8b RB - | addu CARG2, BASE, RB - | decode_RDtoRC8 RC, RD - | lw CARG1, HI(CARG2) - | li AT, LJ_TTAB - | lw TAB:RB, LO(CARG2) - | addu RA, BASE, RA - | bne CARG1, AT, ->vmeta_tgetb - |. srl TMP0, RC, 3 - | lw TMP1, TAB:RB->asize - | lw TMP2, TAB:RB->array - | sltu AT, TMP0, TMP1 - | beqz AT, ->vmeta_tgetb - |. addu RC, TMP2, RC - | lw TMP1, HI(RC) - | beq TMP1, TISNIL, >5 - |. ldc1 f0, 0(RC) - |1: - | ins_next1 - | sdc1 f0, 0(RA) - | ins_next2 - | - |5: // Check for __index if table value is nil. - | lw TAB:TMP2, TAB:RB->metatable - | beqz TAB:TMP2, <1 // No metatable: done. - |. nop - | lbu TMP1, TAB:TMP2->nomm - | andi TMP1, TMP1, 1<vmeta_tgetb // Caveat: preserve TMP0! - |. nop - break; - - case BC_TSETV: - | // RA = src*8, RB = table*8, RC = key*8 - | decode_RB8a RB, INS - | decode_RB8b RB - | decode_RDtoRC8 RC, RD - | addu CARG2, BASE, RB - | addu CARG3, BASE, RC - | lw TMP1, HI(CARG2) - | lw TMP2, HI(CARG3) - | lw TAB:RB, LO(CARG2) - | li AT, LJ_TTAB - | ldc1 f0, 0(CARG3) - | bne TMP1, AT, ->vmeta_tsetv - |. addu RA, BASE, RA - | sltiu AT, TMP2, LJ_TISNUM - | beqz AT, >5 - |. li AT, LJ_TSTR - | - | // Convert number key to integer, check for integerness and range. - | cvt.w.d f2, f0 - | lw TMP0, TAB:RB->asize - | mfc1 TMP2, f2 - | cvt.d.w f4, f2 - | lw TMP1, TAB:RB->array - | c.eq.d f0, f4 - | sltu AT, TMP2, TMP0 - | movf AT, r0 - | sll TMP2, TMP2, 3 - | beqz AT, ->vmeta_tsetv // Integer key and in array part? - |. addu TMP1, TMP1, TMP2 - | lbu TMP3, TAB:RB->marked - | lw TMP0, HI(TMP1) - | beq TMP0, TISNIL, >3 - |. ldc1 f0, 0(RA) - |1: - | andi AT, TMP3, LJ_GC_BLACK // isblack(table) - | bnez AT, >7 - |. sdc1 f0, 0(TMP1) - |2: - | ins_next - | - |3: // Check for __newindex if previous value is nil. - | lw TAB:TMP2, TAB:RB->metatable - | beqz TAB:TMP2, <1 // No metatable: done. - |. nop - | lbu TMP2, TAB:TMP2->nomm - | andi TMP2, TMP2, 1<vmeta_tsetv - |. nop - | - |5: - | bne TMP2, AT, ->vmeta_tsetv - |. lw STR:RC, LO(CARG3) - | b ->BC_TSETS_Z // String key? - |. nop - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, TMP3, TMP0, <2 - break; - case BC_TSETS: - | // RA = src*8, RB = table*8, RC = str_const*8 (~) - | decode_RB8a RB, INS - | decode_RB8b RB - | addu CARG2, BASE, RB - | decode_RC4a RC, INS - | lw TMP0, HI(CARG2) - | decode_RC4b RC - | li AT, LJ_TTAB - | subu CARG3, KBASE, RC - | lw TAB:RB, LO(CARG2) - | lw STR:RC, -4(CARG3) // KBASE-4-str_const*4 - | bne TMP0, AT, ->vmeta_tsets1 - |. addu RA, BASE, RA - |->BC_TSETS_Z: - | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = BASE+src*8 - | lw TMP0, TAB:RB->hmask - | lw TMP1, STR:RC->hash - | lw NODE:TMP2, TAB:RB->node - | sb r0, TAB:RB->nomm // Clear metamethod cache. - | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask - | sll TMP0, TMP1, 5 - | sll TMP1, TMP1, 3 - | subu TMP1, TMP0, TMP1 - | addu NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) - | ldc1 f20, 0(RA) - |1: - | lw CARG1, offsetof(Node, key)+HI(NODE:TMP2) - | lw TMP0, offsetof(Node, key)+LO(NODE:TMP2) - | li AT, LJ_TSTR - | lw NODE:TMP1, NODE:TMP2->next - | bne CARG1, AT, >5 - |. lw CARG2, offsetof(Node, val)+HI(NODE:TMP2) - | bne TMP0, STR:RC, >5 - |. lbu TMP3, TAB:RB->marked - | beq CARG2, TISNIL, >4 // Key found, but nil value? - |. lw TAB:TMP0, TAB:RB->metatable - |2: - | andi AT, TMP3, LJ_GC_BLACK // isblack(table) - | bnez AT, >7 - |. sdc1 f20, NODE:TMP2->val - |3: - | ins_next - | - |4: // Check for __newindex if previous value is nil. - | beqz TAB:TMP0, <2 // No metatable: done. - |. nop - | lbu TMP0, TAB:TMP0->nomm - | andi TMP0, TMP0, 1<vmeta_tsets - |. nop - | - |5: // Follow hash chain. - | bnez NODE:TMP1, <1 - |. move NODE:TMP2, NODE:TMP1 - | // End of hash chain: key not found, add a new one - | - | // But check for __newindex first. - | lw TAB:TMP2, TAB:RB->metatable - | beqz TAB:TMP2, >6 // No metatable: continue. - |. addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) - | lbu TMP0, TAB:TMP2->nomm - | andi TMP0, TMP0, 1<vmeta_tsets // 'no __newindex' flag NOT set: check. - |. li AT, LJ_TSTR - |6: - | load_got lj_tab_newkey - | sw STR:RC, LO(CARG3) - | sw AT, HI(CARG3) - | sw BASE, L->base - | move CARG2, TAB:RB - | sw PC, SAVE_PC - | call_intern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k - |. move CARG1, L - | // Returns TValue *. - | lw BASE, L->base - | b <3 // No 2nd write barrier needed. - |. sdc1 f20, 0(CRET1) - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, TMP3, TMP0, <3 - break; - case BC_TSETB: - | // RA = src*8, RB = table*8, RC = index*8 - | decode_RB8a RB, INS - | decode_RB8b RB - | addu CARG2, BASE, RB - | decode_RDtoRC8 RC, RD - | lw CARG1, HI(CARG2) - | li AT, LJ_TTAB - | lw TAB:RB, LO(CARG2) - | addu RA, BASE, RA - | bne CARG1, AT, ->vmeta_tsetb - |. srl TMP0, RC, 3 - | lw TMP1, TAB:RB->asize - | lw TMP2, TAB:RB->array - | sltu AT, TMP0, TMP1 - | beqz AT, ->vmeta_tsetb - |. addu RC, TMP2, RC - | lw TMP1, HI(RC) - | lbu TMP3, TAB:RB->marked - | beq TMP1, TISNIL, >5 - |. ldc1 f0, 0(RA) - |1: - | andi AT, TMP3, LJ_GC_BLACK // isblack(table) - | bnez AT, >7 - |. sdc1 f0, 0(RC) - |2: - | ins_next - | - |5: // Check for __newindex if previous value is nil. - | lw TAB:TMP2, TAB:RB->metatable - | beqz TAB:TMP2, <1 // No metatable: done. - |. nop - | lbu TMP1, TAB:TMP2->nomm - | andi TMP1, TMP1, 1<vmeta_tsetb // Caveat: preserve TMP0! - |. nop - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, TMP3, TMP0, <2 - break; - - case BC_TSETM: - | // RA = base*8 (table at base-1), RD = num_const*8 (start index) - | addu RA, BASE, RA - |1: - | addu TMP3, KBASE, RD - | lw TAB:CARG2, -8+LO(RA) // Guaranteed to be a table. - | addiu TMP0, MULTRES, -8 - | lw TMP3, LO(TMP3) // Integer constant is in lo-word. - | beqz TMP0, >4 // Nothing to copy? - |. srl CARG3, TMP0, 3 - | addu CARG3, CARG3, TMP3 - | lw TMP2, TAB:CARG2->asize - | sll TMP1, TMP3, 3 - | lbu TMP3, TAB:CARG2->marked - | lw CARG1, TAB:CARG2->array - | sltu AT, TMP2, CARG3 - | bnez AT, >5 - |. addu TMP2, RA, TMP0 - | addu TMP1, TMP1, CARG1 - | andi TMP0, TMP3, LJ_GC_BLACK // isblack(table) - |3: // Copy result slots to table. - | ldc1 f0, 0(RA) - | addiu RA, RA, 8 - | sltu AT, RA, TMP2 - | sdc1 f0, 0(TMP1) - | bnez AT, <3 - |. addiu TMP1, TMP1, 8 - | bnez TMP0, >7 - |. nop - |4: - | ins_next - | - |5: // Need to resize array part. - | load_got lj_tab_reasize - | sw BASE, L->base - | sw PC, SAVE_PC - | move BASE, RD - | call_intern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize) - |. move CARG1, L - | // Must not reallocate the stack. - | move RD, BASE - | b <1 - |. lw BASE, L->base // Reload BASE for lack of a saved register. - | - |7: // Possible table write barrier for any value. Skip valiswhite check. - | barrierback TAB:CARG2, TMP3, TMP0, <4 - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALLM: - | // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8 - | decode_RDtoRC8 NARGS8:RC, RD - | b ->BC_CALL_Z - |. addu NARGS8:RC, NARGS8:RC, MULTRES - break; - case BC_CALL: - | // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8 - | decode_RDtoRC8 NARGS8:RC, RD - |->BC_CALL_Z: - | move TMP2, BASE - | addu BASE, BASE, RA - | li AT, LJ_TFUNC - | lw TMP0, HI(BASE) - | lw LFUNC:RB, LO(BASE) - | addiu BASE, BASE, 8 - | bne TMP0, AT, ->vmeta_call - |. addiu NARGS8:RC, NARGS8:RC, -8 - | ins_call - break; - - case BC_CALLMT: - | // RA = base*8, (RB = 0,) RC = extra_nargs*8 - | addu NARGS8:RD, NARGS8:RD, MULTRES // BC_CALLT gets RC from RD. - | // Fall through. Assumes BC_CALLT follows. - break; - case BC_CALLT: - | // RA = base*8, (RB = 0,) RC = (nargs+1)*8 - | addu RA, BASE, RA - | li AT, LJ_TFUNC - | lw TMP0, HI(RA) - | lw LFUNC:RB, LO(RA) - | move NARGS8:RC, RD - | lw TMP1, FRAME_PC(BASE) - | addiu RA, RA, 8 - | bne TMP0, AT, ->vmeta_callt - |. addiu NARGS8:RC, NARGS8:RC, -8 - |->BC_CALLT_Z: - | andi TMP0, TMP1, FRAME_TYPE // Caveat: preserve TMP0 until the 'or'. - | lbu TMP3, LFUNC:RB->ffid - | bnez TMP0, >7 - |. xori TMP2, TMP1, FRAME_VARG - |1: - | sw LFUNC:RB, FRAME_FUNC(BASE) // Copy function down, but keep PC. - | sltiu AT, TMP3, 2 // (> FF_C) Calling a fast function? - | move TMP2, BASE - | beqz NARGS8:RC, >3 - |. move TMP3, NARGS8:RC - |2: - | ldc1 f0, 0(RA) - | addiu RA, RA, 8 - | addiu TMP3, TMP3, -8 - | sdc1 f0, 0(TMP2) - | bnez TMP3, <2 - |. addiu TMP2, TMP2, 8 - |3: - | or TMP0, TMP0, AT - | beqz TMP0, >5 - |. nop - |4: - | ins_callt - | - |5: // Tailcall to a fast function with a Lua frame below. - | lw INS, -4(TMP1) - | decode_RA8a RA, INS - | decode_RA8b RA - | subu TMP1, BASE, RA - | lw LFUNC:TMP1, -8+FRAME_FUNC(TMP1) - | lw TMP1, LFUNC:TMP1->pc - | b <4 - |. lw KBASE, PC2PROTO(k)(TMP1) // Need to prepare KBASE. - | - |7: // Tailcall from a vararg function. - | andi AT, TMP2, FRAME_TYPEP - | bnez AT, <1 // Vararg frame below? - |. subu TMP2, BASE, TMP2 // Relocate BASE down. - | move BASE, TMP2 - | lw TMP1, FRAME_PC(TMP2) - | b <1 - |. andi TMP0, TMP1, FRAME_TYPE - break; - - case BC_ITERC: - | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8)) - | move TMP2, BASE - | addu BASE, BASE, RA - | li AT, LJ_TFUNC - | lw TMP1, -24+HI(BASE) - | lw LFUNC:RB, -24+LO(BASE) - | ldc1 f2, -8(BASE) - | ldc1 f0, -16(BASE) - | sw TMP1, HI(BASE) // Copy callable. - | sw LFUNC:RB, LO(BASE) - | sdc1 f2, 16(BASE) // Copy control var. - | sdc1 f0, 8(BASE) // Copy state. - | addiu BASE, BASE, 8 - | bne TMP1, AT, ->vmeta_call - |. li NARGS8:RC, 16 // Iterators get 2 arguments. - | ins_call - break; - - case BC_ITERN: - | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) -#if LJ_HASJIT - | // NYI: add hotloop, record BC_ITERN. -#endif - | addu RA, BASE, RA - | lw TAB:RB, -16+LO(RA) - | lw RC, -8+LO(RA) // Get index from control var. - | lw TMP0, TAB:RB->asize - | lw TMP1, TAB:RB->array - | addiu PC, PC, 4 - |1: // Traverse array part. - | sltu AT, RC, TMP0 - | beqz AT, >5 // Index points after array part? - |. sll TMP3, RC, 3 - | addu TMP3, TMP1, TMP3 - | lw TMP2, HI(TMP3) - | ldc1 f0, 0(TMP3) - | mtc1 RC, f2 - | lhu RD, -4+OFS_RD(PC) - | beq TMP2, TISNIL, <1 // Skip holes in array part. - |. addiu RC, RC, 1 - | cvt.d.w f2, f2 - | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) - | sdc1 f0, 8(RA) - | decode_RD4b RD - | addu RD, RD, TMP3 - | sw RC, -8+LO(RA) // Update control var. - | addu PC, PC, RD - | sdc1 f2, 0(RA) - |3: - | ins_next - | - |5: // Traverse hash part. - | lw TMP1, TAB:RB->hmask - | subu RC, RC, TMP0 - | lw TMP2, TAB:RB->node - |6: - | sltu AT, TMP1, RC // End of iteration? Branch to ITERL+1. - | bnez AT, <3 - |. sll TMP3, RC, 5 - | sll RB, RC, 3 - | subu TMP3, TMP3, RB - | addu NODE:TMP3, TMP3, TMP2 - | lw RB, HI(NODE:TMP3) - | ldc1 f0, 0(NODE:TMP3) - | lhu RD, -4+OFS_RD(PC) - | beq RB, TISNIL, <6 // Skip holes in hash part. - |. addiu RC, RC, 1 - | ldc1 f2, NODE:TMP3->key - | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) - | sdc1 f0, 8(RA) - | addu RC, RC, TMP0 - | decode_RD4b RD - | addu RD, RD, TMP3 - | sdc1 f2, 0(RA) - | addu PC, PC, RD - | b <3 - |. sw RC, -8+LO(RA) // Update control var. - break; - - case BC_ISNEXT: - | // RA = base*8, RD = target (points to ITERN) - | addu RA, BASE, RA - | lw TMP0, -24+HI(RA) - | lw CFUNC:TMP1, -24+LO(RA) - | lw TMP2, -16+HI(RA) - | lw TMP3, -8+HI(RA) - | li AT, LJ_TFUNC - | bne TMP0, AT, >5 - |. addiu TMP2, TMP2, -LJ_TTAB - | lbu TMP1, CFUNC:TMP1->ffid - | addiu TMP3, TMP3, -LJ_TNIL - | srl TMP0, RD, 1 - | or TMP2, TMP2, TMP3 - | addiu TMP1, TMP1, -FF_next_N - | addu TMP0, PC, TMP0 - | or TMP1, TMP1, TMP2 - | bnez TMP1, >5 - |. lui TMP2, (-(BCBIAS_J*4 >> 16) & 65535) - | addu PC, TMP0, TMP2 - | sw r0, -8+LO(RA) // Initialize control var. - |1: - | ins_next - |5: // Despecialize bytecode if any of the checks fail. - | li TMP3, BC_JMP - | li TMP1, BC_ITERC - | sb TMP3, -4+OFS_OP(PC) - | addu PC, TMP0, TMP2 - | b <1 - |. sb TMP1, OFS_OP(PC) - break; - - case BC_VARG: - | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8 - | lw TMP0, FRAME_PC(BASE) - | decode_RDtoRC8 RC, RD - | decode_RB8a RB, INS - | addu RC, BASE, RC - | decode_RB8b RB - | addu RA, BASE, RA - | addiu RC, RC, FRAME_VARG - | addu TMP2, RA, RB - | addiu TMP3, BASE, -8 // TMP3 = vtop - | subu RC, RC, TMP0 // RC = vbase - | // Note: RC may now be even _above_ BASE if nargs was < numparams. - | beqz RB, >5 // Copy all varargs? - |. subu TMP1, TMP3, RC - | addiu TMP2, TMP2, -16 - |1: // Copy vararg slots to destination slots. - | lw CARG1, HI(RC) - | sltu AT, RC, TMP3 - | lw CARG2, LO(RC) - | addiu RC, RC, 8 - | movz CARG1, TISNIL, AT - | sw CARG1, HI(RA) - | sw CARG2, LO(RA) - | sltu AT, RA, TMP2 - | bnez AT, <1 - |. addiu RA, RA, 8 - |3: - | ins_next - | - |5: // Copy all varargs. - | lw TMP0, L->maxstack - | blez TMP1, <3 // No vararg slots? - |. li MULTRES, 8 // MULTRES = (0+1)*8 - | addu TMP2, RA, TMP1 - | sltu AT, TMP0, TMP2 - | bnez AT, >7 - |. addiu MULTRES, TMP1, 8 - |6: - | ldc1 f0, 0(RC) - | addiu RC, RC, 8 - | sdc1 f0, 0(RA) - | sltu AT, RC, TMP3 - | bnez AT, <6 // More vararg slots? - |. addiu RA, RA, 8 - | b <3 - |. nop - | - |7: // Grow stack for varargs. - | load_got lj_state_growstack - | sw RA, L->top - | subu RA, RA, BASE - | sw BASE, L->base - | subu BASE, RC, BASE // Need delta, because BASE may change. - | sw PC, SAVE_PC - | srl CARG2, TMP1, 3 - | call_intern lj_state_growstack // (lua_State *L, int n) - |. move CARG1, L - | move RC, BASE - | lw BASE, L->base - | addu RA, BASE, RA - | addu RC, BASE, RC - | b <6 - |. addiu TMP3, BASE, -8 - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - | // RA = results*8, RD = extra_nresults*8 - | addu RD, RD, MULTRES // MULTRES >= 8, so RD >= 8. - | // Fall through. Assumes BC_RET follows. - break; - - case BC_RET: - | // RA = results*8, RD = (nresults+1)*8 - | lw PC, FRAME_PC(BASE) - | addu RA, BASE, RA - | move MULTRES, RD - |1: - | andi TMP0, PC, FRAME_TYPE - | bnez TMP0, ->BC_RETV_Z - |. xori TMP1, PC, FRAME_VARG - | - |->BC_RET_Z: - | // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return - | lw INS, -4(PC) - | addiu TMP2, BASE, -8 - | addiu RC, RD, -8 - | decode_RA8a TMP0, INS - | decode_RB8a RB, INS - | decode_RA8b TMP0 - | decode_RB8b RB - | addu TMP3, TMP2, RB - | beqz RC, >3 - |. subu BASE, TMP2, TMP0 - |2: - | ldc1 f0, 0(RA) - | addiu RA, RA, 8 - | addiu RC, RC, -8 - | sdc1 f0, 0(TMP2) - | bnez RC, <2 - |. addiu TMP2, TMP2, 8 - |3: - | addiu TMP3, TMP3, -8 - |5: - | sltu AT, TMP2, TMP3 - | bnez AT, >6 - |. lw LFUNC:TMP1, FRAME_FUNC(BASE) - | ins_next1 - | lw TMP1, LFUNC:TMP1->pc - | lw KBASE, PC2PROTO(k)(TMP1) - | ins_next2 - | - |6: // Fill up results with nil. - | sw TISNIL, HI(TMP2) - | b <5 - |. addiu TMP2, TMP2, 8 - | - |->BC_RETV_Z: // Non-standard return case. - | andi TMP2, TMP1, FRAME_TYPEP - | bnez TMP2, ->vm_return - |. nop - | // Return from vararg function: relocate BASE down. - | subu BASE, BASE, TMP1 - | b <1 - |. lw PC, FRAME_PC(BASE) - break; - - case BC_RET0: case BC_RET1: - | // RA = results*8, RD = (nresults+1)*8 - | lw PC, FRAME_PC(BASE) - | addu RA, BASE, RA - | move MULTRES, RD - | andi TMP0, PC, FRAME_TYPE - | bnez TMP0, ->BC_RETV_Z - |. xori TMP1, PC, FRAME_VARG - | - | lw INS, -4(PC) - | addiu TMP2, BASE, -8 - if (op == BC_RET1) { - | ldc1 f0, 0(RA) - } - | decode_RB8a RB, INS - | decode_RA8a RA, INS - | decode_RB8b RB - | decode_RA8b RA - if (op == BC_RET1) { - | sdc1 f0, 0(TMP2) - } - | subu BASE, TMP2, RA - |5: - | sltu AT, RD, RB - | bnez AT, >6 - |. lw LFUNC:TMP1, FRAME_FUNC(BASE) - | ins_next1 - | lw TMP1, LFUNC:TMP1->pc - | lw KBASE, PC2PROTO(k)(TMP1) - | ins_next2 - | - |6: // Fill up results with nil. - | addiu TMP2, TMP2, 8 - | addiu RD, RD, 8 - | b <5 - if (op == BC_RET1) { - |. sw TISNIL, HI(TMP2) - } else { - |. sw TISNIL, -8+HI(TMP2) - } - break; - - /* -- Loops and branches ------------------------------------------------ */ - - case BC_FORL: -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_IFORL follows. - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - | // RA = base*8, RD = target (after end of loop or start of loop) - vk = (op == BC_IFORL || op == BC_JFORL); - | addu RA, BASE, RA - if (vk) { - | ldc1 f0, FORL_IDX*8(RA) - | ldc1 f4, FORL_STEP*8(RA) - | ldc1 f2, FORL_STOP*8(RA) - | lw TMP3, FORL_STEP*8+HI(RA) - | add.d f0, f0, f4 - | sdc1 f0, FORL_IDX*8(RA) - } else { - | lw TMP1, FORL_IDX*8+HI(RA) - | lw TMP3, FORL_STEP*8+HI(RA) - | lw TMP2, FORL_STOP*8+HI(RA) - | sltiu TMP1, TMP1, LJ_TISNUM - | sltiu TMP0, TMP3, LJ_TISNUM - | sltiu TMP2, TMP2, LJ_TISNUM - | and TMP1, TMP1, TMP0 - | and TMP1, TMP1, TMP2 - | ldc1 f0, FORL_IDX*8(RA) - | beqz TMP1, ->vmeta_for - |. ldc1 f2, FORL_STOP*8(RA) - } - if (op != BC_JFORL) { - | srl RD, RD, 1 - | lui TMP0, (-(BCBIAS_J*4 >> 16) & 65535) - } - | c.le.d 0, f0, f2 - | c.le.d 1, f2, f0 - | sdc1 f0, FORL_EXT*8(RA) - if (op == BC_JFORI) { - | li TMP1, 1 - | li TMP2, 1 - | addu TMP0, RD, TMP0 - | slt TMP3, TMP3, r0 - | movf TMP1, r0, 0 - | addu PC, PC, TMP0 - | movf TMP2, r0, 1 - | lhu RD, -4+OFS_RD(PC) - | movn TMP1, TMP2, TMP3 - | bnez TMP1, =>BC_JLOOP - |. decode_RD8b RD - } else if (op == BC_JFORL) { - | li TMP1, 1 - | li TMP2, 1 - | slt TMP3, TMP3, r0 - | movf TMP1, r0, 0 - | movf TMP2, r0, 1 - | movn TMP1, TMP2, TMP3 - | bnez TMP1, =>BC_JLOOP - |. nop - } else { - | addu TMP1, RD, TMP0 - | slt TMP3, TMP3, r0 - | move TMP2, TMP1 - if (op == BC_FORI) { - | movt TMP1, r0, 0 - | movt TMP2, r0, 1 - } else { - | movf TMP1, r0, 0 - | movf TMP2, r0, 1 - } - | movn TMP1, TMP2, TMP3 - | addu PC, PC, TMP1 - } - | ins_next - break; - - case BC_ITERL: -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_IITERL follows. - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - | // RA = base*8, RD = target - | addu RA, BASE, RA - | lw TMP1, HI(RA) - | beq TMP1, TISNIL, >1 // Stop if iterator returned nil. - |. lw TMP2, LO(RA) - if (op == BC_JITERL) { - | sw TMP1, -8+HI(RA) - | b =>BC_JLOOP - |. sw TMP2, -8+LO(RA) - } else { - | branch_RD // Otherwise save control var + branch. - | sw TMP1, -8+HI(RA) - | sw TMP2, -8+LO(RA) - } - |1: - | ins_next - break; - - case BC_LOOP: - | // RA = base*8, RD = target (loop extent) - | // Note: RA/RD is only used by trace recorder to determine scope/extent - | // This opcode does NOT jump, it's only purpose is to detect a hot loop. -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_ILOOP follows. - break; - - case BC_ILOOP: - | // RA = base*8, RD = target (loop extent) - | ins_next - break; - - case BC_JLOOP: -#if LJ_HASJIT - | // RA = base*8 (ignored), RD = traceno*8 - | lw TMP1, DISPATCH_J(trace)(DISPATCH) - | srl RD, RD, 1 - | li AT, 0 - | addu TMP1, TMP1, RD - | // Traces on MIPS don't store the trace number, so use 0. - | sw AT, DISPATCH_GL(vmstate)(DISPATCH) - | lw TRACE:TMP2, 0(TMP1) - | sw BASE, DISPATCH_GL(jit_base)(DISPATCH) - | sw L, DISPATCH_GL(jit_L)(DISPATCH) - | lw TMP2, TRACE:TMP2->mcode - | jr TMP2 - |. addiu JGL, DISPATCH, GG_DISP2G+32768 -#endif - break; - - case BC_JMP: - | // RA = base*8 (only used by trace recorder), RD = target - | branch_RD - | ins_next - break; - - /* -- Function headers -------------------------------------------------- */ - - case BC_FUNCF: -#if LJ_HASJIT - | hotcall -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow. - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 - | lw TMP2, L->maxstack - | lbu TMP1, -4+PC2PROTO(numparams)(PC) - | lw KBASE, -4+PC2PROTO(k)(PC) - | sltu AT, TMP2, RA - | bnez AT, ->vm_growstack_l - |. sll TMP1, TMP1, 3 - if (op != BC_JFUNCF) { - | ins_next1 - } - |2: - | sltu AT, NARGS8:RC, TMP1 // Check for missing parameters. - | bnez AT, >3 - |. addu AT, BASE, NARGS8:RC - if (op == BC_JFUNCF) { - | decode_RD8a RD, INS - | b =>BC_JLOOP - |. decode_RD8b RD - } else { - | ins_next2 - } - | - |3: // Clear missing parameters. - | sw TISNIL, HI(AT) - | b <2 - |. addiu NARGS8:RC, NARGS8:RC, 8 - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - | NYI // NYI: compiled vararg functions - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 - | addu TMP1, BASE, RC - | lw TMP2, L->maxstack - | addu TMP0, RA, RC - | sw LFUNC:RB, LO(TMP1) // Store copy of LFUNC. - | addiu TMP3, RC, 8+FRAME_VARG - | sltu AT, TMP0, TMP2 - | lw KBASE, -4+PC2PROTO(k)(PC) - | beqz AT, ->vm_growstack_l - |. sw TMP3, HI(TMP1) // Store delta + FRAME_VARG. - | lbu TMP2, -4+PC2PROTO(numparams)(PC) - | move RA, BASE - | move RC, TMP1 - | ins_next1 - | beqz TMP2, >3 - |. addiu BASE, TMP1, 8 - |1: - | lw TMP0, HI(RA) - | lw TMP3, LO(RA) - | sltu AT, RA, RC // Less args than parameters? - | move CARG1, TMP0 - | movz TMP0, TISNIL, AT // Clear missing parameters. - | movn CARG1, TISNIL, AT // Clear old fixarg slot (help the GC). - | sw TMP3, 8+LO(TMP1) - | addiu TMP2, TMP2, -1 - | sw TMP0, 8+HI(TMP1) - | addiu TMP1, TMP1, 8 - | sw CARG1, HI(RA) - | bnez TMP2, <1 - |. addiu RA, RA, 8 - |3: - | ins_next2 - break; - - case BC_FUNCC: - case BC_FUNCCW: - | // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8 - if (op == BC_FUNCC) { - | lw CFUNCADDR, CFUNC:RB->f - } else { - | lw CFUNCADDR, DISPATCH_GL(wrapf)(DISPATCH) - } - | addu TMP1, RA, NARGS8:RC - | lw TMP2, L->maxstack - | addu RC, BASE, NARGS8:RC - | sw BASE, L->base - | sltu AT, TMP2, TMP1 - | sw RC, L->top - | li_vmstate C - if (op == BC_FUNCCW) { - | lw CARG2, CFUNC:RB->f - } - | bnez AT, ->vm_growstack_c // Need to grow stack. - |. move CARG1, L - | jalr CFUNCADDR // (lua_State *L [, lua_CFunction f]) - |. st_vmstate - | // Returns nresults. - | lw BASE, L->base - | sll RD, CRET1, 3 - | lw TMP1, L->top - | li_vmstate INTERP - | lw PC, FRAME_PC(BASE) // Fetch PC of caller. - | subu RA, TMP1, RD // RA = L->top - nresults*8 - | b ->vm_returnc - |. st_vmstate - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx); - - |.code_op - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); - int i; - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.4byte .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.4byte 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 31\n" - "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.4byte .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.4byte .Lframe0\n" - "\t.4byte .Lbegin\n" - "\t.4byte %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x9f\n\t.sleb128 1\n" - "\t.byte 0x9e\n\t.sleb128 2\n", - fcofs, CFRAME_SIZE); - for (i = 23; i >= 16; i--) - fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 26-i); - for (i = 30; i >= 20; i -= 2) - fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+32+i, 42-i); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE0:\n\n"); -#if LJ_HASFFI - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.4byte .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.4byte .Lframe0\n" - "\t.4byte lj_vm_ffi_call\n" - "\t.4byte %d\n" - "\t.byte 0x9f\n\t.uleb128 1\n" - "\t.byte 0x90\n\t.uleb128 2\n" - "\t.byte 0xd\n\t.uleb128 0x10\n" - "\t.align 2\n" - ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); -#endif - fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n"); - fprintf(ctx->fp, - "\t.globl lj_err_unwind_dwarf\n" - ".Lframe1:\n" - "\t.4byte .LECIE1-.LSCIE1\n" - ".LSCIE1:\n" - "\t.4byte 0\n" - "\t.byte 0x1\n" - "\t.string \"zPR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 31\n" - "\t.uleb128 6\n" /* augmentation length */ - "\t.byte 0\n" - "\t.4byte lj_err_unwind_dwarf\n" - "\t.byte 0\n" - "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE1:\n\n"); - fprintf(ctx->fp, - ".LSFDE2:\n" - "\t.4byte .LEFDE2-.LASFDE2\n" - ".LASFDE2:\n" - "\t.4byte .LASFDE2-.Lframe1\n" - "\t.4byte .Lbegin\n" - "\t.4byte %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x9f\n\t.sleb128 1\n" - "\t.byte 0x9e\n\t.sleb128 2\n", - fcofs, CFRAME_SIZE); - for (i = 23; i >= 16; i--) - fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 26-i); - for (i = 30; i >= 20; i -= 2) - fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+32+i, 42-i); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE2:\n\n"); -#if LJ_HASFFI - fprintf(ctx->fp, - ".Lframe2:\n" - "\t.4byte .LECIE2-.LSCIE2\n" - ".LSCIE2:\n" - "\t.4byte 0\n" - "\t.byte 0x1\n" - "\t.string \"zR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 31\n" - "\t.uleb128 1\n" /* augmentation length */ - "\t.byte 0\n" - "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE2:\n\n"); - fprintf(ctx->fp, - ".LSFDE3:\n" - "\t.4byte .LEFDE3-.LASFDE3\n" - ".LASFDE3:\n" - "\t.4byte .LASFDE3-.Lframe2\n" - "\t.4byte lj_vm_ffi_call\n" - "\t.4byte %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0x9f\n\t.uleb128 1\n" - "\t.byte 0x90\n\t.uleb128 2\n" - "\t.byte 0xd\n\t.uleb128 0x10\n" - "\t.align 2\n" - ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); -#endif - break; - default: - break; - } -} - diff --git a/src/buildvm_mips.h b/src/buildvm_mips.h deleted file mode 100644 index bab93343..00000000 --- a/src/buildvm_mips.h +++ /dev/null @@ -1,7495 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM mips version 1.3.0 -** DO NOT EDIT! The original file is in "buildvm_mips.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -#define DASM_SECTION_CODE_OP 0 -#define DASM_SECTION_CODE_SUB 1 -#define DASM_MAXSECTION 2 -static const unsigned int build_actionlist[6324] = { -0xff010001, -0xff060014, -0x32410000, -0xff090200, -0x10200000, -0xff050815, -0x240d0000, -0xff098200, -0x8dd20000, -0xff098200, -0x01c08021, -0xaeed0000, -0xff098200, -0x26f7fff8, -0xff060016, -0x324c0000, -0xff090200, -0x254a0008, -0x11800000, -0xff050817, -0x0140a821, -0xff060018, -0x240efff8, -0x39810000, -0xff090200, -0x024e7024, -0x14200000, -0xff050814, -0x020e7023, -0x254dfff8, -0xae8e0000, -0xff098200, -0x240c0000, -0xff098200, -0x8fae0078, -0x2610fff8, -0xae6c0000, -0xff098200, -0x11a00000, -0xff050802, -0x000e70c0, -0xff06000b, -0x25adfff8, -0xd6e00000, -0x26f70008, -0xf6000000, -0x15a00000, -0xff05080b, -0x26100008, -0xff06000c, -0x15ca0000, -0xff050806, -0xff06000d, -0xae900000, -0xff098200, -0xff060019, -0xff000000, -0x8fac0074, -0x00001021, -0xae8c0000, -0xff098200, -0xff06001a, -0x8fbf0000, -0xff098200, -0x8fbe0000, -0xff098200, -0xd7be0000, -0xff098200, -0x8fb70000, -0xff098200, -0x8fb60000, -0xff098200, -0xd7bc0000, -0xff098200, -0x8fb50000, -0xff098200, -0x8fb40000, -0xff098200, -0xd7ba0000, -0xff098200, -0x8fb30000, -0xff098200, -0x8fb20000, -0xff098200, -0xd7b80000, -0xff098200, -0x8fb10000, -0xff098200, -0x8fb00000, -0xff098200, -0xd7b60000, -0xff098200, -0xd7b40000, -0xff098200, -0x03e00008, -0x27bd0070, -0xff060010, -0x8e8d0000, -0xff098200, -0x01ca082a, -0x14200000, -0xff050807, -0x020d082a, -0x10200000, -0xff050808, -0x00000000, -0xae1e0000, -0xff098200, -0xff000000, -0x254a0008, -0x10000000, -0xff05080c, -0x26100008, -0xff060011, -0x014e6023, -0x020c6023, -0x10000000, -0xff05080d, -0x018e800b, -0xff060012, -0x8e790000, -0xff098200, -0x0140a821, -0x01c02821, -0x0320f809, -0x02802021, -0x8fae0078, -0x8e900000, -0xff098200, -0x02a05021, -0x10000000, -0xff05080c, -0x000e70c0, -0xff06001b, -0x0080e821, -0x00a01021, -0xff06001c, -0x8fb40070, -0x240c0000, -0xff098200, -0x8e8d0000, -0xff098200, -0x10000000, -0xff05081a, -0xadac0000, -0xff098200, -0xff06001d, -0x2401fffc, -0x0081e824, -0xff06001e, -0x8fb40070, -0x3c0f59c0, -0x241e0000, -0xff098200, -0x8e900000, -0xff098200, -0x8e930000, -0xff098200, -0x448ff000, -0x240d0000, -0xff098200, -0x240c0000, -0xff098200, -0x8e120000, -0xff098200, -0x4600f7a1, -0x2617fff8, -0x26730000, -0xff098200, -0xaeed0000, -0xff098200, -0xff000000, -0xae6c0000, -0xff098200, -0x10000000, -0xff050816, -0x240a0010, -0xff06001f, -0x10000000, -0xff050802, -0x24050000, -0xff098200, -0xff060020, -0x02094821, -0x02f0b823, -0xae900000, -0xff098200, -0x26520004, -0xae890000, -0xff098200, -0x001728c2, -0xff06000c, -0x8e790000, -0xff098200, -0xafb20014, -0x0320f809, -0x02802021, -0x8e900000, -0xff098200, -0x8e890000, -0xff098200, -0x8e080000, -0xff098200, -0x01304823, -0x8d120000, -0xff098200, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000bb942, -0x000d6880, -0x32f707f8, -0x026d6021, -0x8d8c0000, -0x01800008, -0x02f0b821, -0xff060021, -0x27bdff90, -0xafbf0000, -0xff098200, -0xafbe0000, -0xff098200, -0xf7be0000, -0xff098200, -0xafb70000, -0xff098200, -0xafb60000, -0xff098200, -0xf7bc0000, -0xff098200, -0xafb50000, -0xff098200, -0xafb40000, -0xff098200, -0xff000000, -0xf7ba0000, -0xff098200, -0xafb30000, -0xff098200, -0xafb20000, -0xff098200, -0xf7b80000, -0xff098200, -0xafb10000, -0xff098200, -0xafb00000, -0xff098200, -0xf7b60000, -0xff098200, -0xf7b40000, -0xff098200, -0x0080a021, -0x8e930000, -0xff098200, -0x00a08021, -0x928d0000, -0xff098200, -0xafb40070, -0x24120000, -0xff098200, -0x27ac0000, -0xff098200, -0x26730000, -0xff098200, -0xafa00078, -0xafa0007c, -0xae8c0000, -0xff098200, -0xafa00074, -0x11a00000, -0xff050803, -0xafa40014, -0x0200b821, -0x8e900000, -0xff098200, -0x8e8d0000, -0xff098200, -0x8e120000, -0xff098200, -0x3c0f59c0, -0x01b05023, -0x448ff000, -0xa2800000, -0xff098200, -0x4600f7a1, -0x240c0000, -0xff098200, -0x254a0008, -0xae6c0000, -0xff098200, -0x0140a821, -0x324c0000, -0xff090200, -0x11800000, -0xff050817, -0xff000000, -0x241e0000, -0xff098200, -0x10000000, -0xff050818, -0x00000000, -0xff060022, -0x27bdff90, -0xafbf0000, -0xff098200, -0xafbe0000, -0xff098200, -0xf7be0000, -0xff098200, -0xafb70000, -0xff098200, -0xafb60000, -0xff098200, -0xf7bc0000, -0xff098200, -0xafb50000, -0xff098200, -0xafb40000, -0xff098200, -0xf7ba0000, -0xff098200, -0xafb30000, -0xff098200, -0xafb20000, -0xff098200, -0xf7b80000, -0xff098200, -0xafb10000, -0xff098200, -0xafb00000, -0xff098200, -0xf7b60000, -0xff098200, -0xf7b40000, -0xff098200, -0xafa7007c, -0x10000000, -0xff050801, -0x24120000, -0xff098200, -0xff060023, -0x27bdff90, -0xafbf0000, -0xff098200, -0xff000000, -0xafbe0000, -0xff098200, -0xf7be0000, -0xff098200, -0xafb70000, -0xff098200, -0xafb60000, -0xff098200, -0xf7bc0000, -0xff098200, -0xafb50000, -0xff098200, -0xafb40000, -0xff098200, -0xf7ba0000, -0xff098200, -0xafb30000, -0xff098200, -0xafb20000, -0xff098200, -0xf7b80000, -0xff098200, -0xafb10000, -0xff098200, -0xafb00000, -0xff098200, -0xf7b60000, -0xff098200, -0xf7b40000, -0xff098200, -0x24120000, -0xff098200, -0xff06000b, -0x8c8d0000, -0xff098200, -0xafa60078, -0x0080a021, -0xafa40070, -0x00a08021, -0xae9d0000, -0xff098200, -0x8e930000, -0xff098200, -0xafa40014, -0xafad0074, -0x26730000, -0xff098200, -0xff06000d, -0x8e8e0000, -0xff098200, -0xff000000, -0x3c0f59c0, -0x8e8d0000, -0xff098200, -0x448ff000, -0x02509021, -0x01b04823, -0x024e9023, -0x4600f7a1, -0x240c0000, -0xff098200, -0x241e0000, -0xff098200, -0xae6c0000, -0xff098200, -0xff060024, -0x8e0c0000, -0xff098200, -0x24010000, -0xff098200, -0x15810000, -0xff050825, -0x8e080000, -0xff098200, -0xff060026, -0xae120000, -0xff098200, -0x8d120000, -0xff098200, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000bb942, -0x000d6880, -0x32f707f8, -0x026d6021, -0x8d8c0000, -0x01800008, -0x02f0b821, -0xff060027, -0x27bdff90, -0xafbf0000, -0xff098200, -0xafbe0000, -0xff098200, -0xf7be0000, -0xff098200, -0xafb70000, -0xff098200, -0xafb60000, -0xff098200, -0xf7bc0000, -0xff098200, -0xafb50000, -0xff098200, -0xafb40000, -0xff098200, -0xf7ba0000, -0xff098200, -0xafb30000, -0xff098200, -0xff000000, -0xafb20000, -0xff098200, -0xf7b80000, -0xff098200, -0xafb10000, -0xff098200, -0xafb00000, -0xff098200, -0xf7b60000, -0xff098200, -0xf7b40000, -0xff098200, -0x0080a021, -0x8c8c0000, -0xff098200, -0xafa40070, -0x8e8d0000, -0xff098200, -0xafa40014, -0x018d6023, -0x8e8d0000, -0xff098200, -0xae9d0000, -0xff098200, -0xafac0078, -0xafa0007c, -0x00e0c821, -0x00e0f809, -0xafad0074, -0x00408021, -0x8e930000, -0xff098200, -0x24120000, -0xff098200, -0x14400000, -0xff05080d, -0x26730000, -0xff098200, -0x10000000, -0xff050819, -0x00000000, -0xff060015, -0x8e0c0000, -0xff098200, -0x02004021, -0x01c08021, -0x8dcd0000, -0xff098200, -0xff000000, -0x2d810002, -0xff000000, -0x8d120000, -0xff098200, -0x02ea7021, -0x8dad0000, -0xff098200, -0xff000000, -0x14200000, -0xff050801, -0xff000000, -0xadde0000, -0xff098200, -0x01800008, -0x8db10000, -0xff098200, -0xff000000, -0xff06000b, -0x15800000, -0xff050828, -0x250dfff0, -0x10000000, -0xff050829, -0x01b04823, -0xff000000, -0xff06002a, -0x8e4bfffc, -0x2505fff0, -0xd6e00000, -0x000bad42, -0x000bb942, -0x32b507f8, -0x32f707f8, -0x02156821, -0xae900000, -0xff098200, -0x00ad3023, -0x15a50000, -0xff05082b, -0xf4a00000, -0x0217b821, -0x10000000, -0xff05082c, -0xf6e00000, -0xff06002d, -0x26660000, -0xff098200, -0x240c0000, -0xff098200, -0xacc90000, -0xff098200, -0x10000000, -0xff050801, -0xaccc0000, -0xff098200, -0xff06002e, -0x26650000, -0xff098200, -0x240c0000, -0xff098200, -0xaca80000, -0xff098200, -0x26660000, -0xff098200, -0xacac0000, -0xff098200, -0x240d0000, -0xff098200, -0xacc90000, -0xff098200, -0x10000000, -0xff050801, -0xaccd0000, -0xff098200, -0xff06002f, -0x448c0000, -0x46800021, -0x26660000, -0xff098200, -0xf4c00000, -0xff060030, -0xff06000b, -0xff000000, -0x8e790000, -0xff098200, -0xae900000, -0xff098200, -0xafb20014, -0x0320f809, -0x02802021, -0x10400000, -0xff050803, -0x260d0000, -0xff098200, -0xd4400000, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000d, -0x8e900000, -0xff098200, -0xae120000, -0xff098200, -0x020d9023, -0x8e080000, -0xff098200, -0x10000000, -0xff050826, -0x24090010, -0xff060031, -0x26660000, -0xff098200, -0x240c0000, -0xff098200, -0xacc90000, -0xff098200, -0x10000000, -0xff050801, -0xaccc0000, -0xff098200, -0xff060032, -0x26650000, -0xff098200, -0x240c0000, -0xff098200, -0xaca80000, -0xff098200, -0x26660000, -0xff098200, -0xacac0000, -0xff098200, -0x240d0000, -0xff098200, -0xacc90000, -0xff098200, -0xff000000, -0x10000000, -0xff050801, -0xaccd0000, -0xff098200, -0xff060033, -0x448c0000, -0x46800021, -0x26660000, -0xff098200, -0xf4c00000, -0xff060034, -0xff06000b, -0x8e790000, -0xff098200, -0xae900000, -0xff098200, -0xafb20014, -0x0320f809, -0x02802021, -0x10400000, -0xff050803, -0xd6e00000, -0x8e4b0000, -0x26520004, -0xf4400000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000d, -0x260d0000, -0xff098200, -0x8e900000, -0xff098200, -0xae120000, -0xff098200, -0x020d9023, -0x8e080000, -0xff098200, -0xf6000010, -0x10000000, -0xff050826, -0x24090018, -0xff060035, -0x8e790000, -0xff098200, -0x2652fffc, -0xae900000, -0xff098200, -0xafb20014, -0x316700ff, -0x0320f809, -0x02802021, -0xff06000d, -0x2c410002, -0x10200000, -0xff050836, -0x00027023, -0xff06000e, -0x964a0000, -0xff098200, -0x26520004, -0x3c0d0000, -0xff090200, -0xff000000, -0x000a5080, -0x014d5021, -0x014e5024, -0x024a9021, -0xff06002c, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff060037, -0x924d0000, -0xff098200, -0xd6e00000, -0x000d68c0, -0x020d6821, -0x10000000, -0xff05082c, -0xf5a00000, -0xff060038, -0x8eec0000, -0xff098200, -0x2d810000, -0xff098200, -0x10000000, -0xff05080e, -0x00017023, -0xff060039, -0x8eec0000, -0xff098200, -0x2d810000, -0xff098200, -0x10000000, -0xff05080e, -0x242effff, -0xff06003a, -0x8e790000, -0xff098200, -0x2652fffc, -0xae900000, -0xff098200, -0xafb20014, -0x0320f809, -0x02802021, -0x10000000, -0xff05080d, -0x00000000, -0xff06003b, -0xff000000, -0x8e790000, -0xff098200, -0x01602821, -0x2652fffc, -0xae900000, -0xff098200, -0xafb20014, -0x0320f809, -0x02802021, -0x10000000, -0xff05080d, -0x00000000, -0xff000000, -0xff06003c, -0x00c03821, -0xff06003d, -0x8e790000, -0xff098200, -0x316c00ff, -0xae900000, -0xff098200, -0xafb20014, -0x02e02821, -0xafac0010, -0x0320f809, -0x02802021, -0x10400000, -0xff05082c, -0x00000000, -0xff060036, -0x00506823, -0xac520000, -0xff098200, -0x02007021, -0x25b20000, -0xff098200, -0x00408021, -0x10000000, -0xff050824, -0x24090010, -0xff06003e, -0xff000000, -0x0080a821, -0xff000000, -0x8e790000, -0xff098200, -0xae900000, -0xff098200, -0xafb20014, -0x0320f809, -0x02802021, -0xff000000, -0x14400000, -0xff050836, -0x00000000, -0x10000000, -0xff05083f, -0x02a02021, -0xff000000, -0x10000000, -0xff050836, -0x00000000, -0xff000000, -0xff060025, -0x8e790000, -0xff098200, -0xae8e0000, -0xff098200, -0x2605fff8, -0xafb20014, -0x02093021, -0x0120a821, -0x0320f809, -0x02802021, -0x8e080000, -0xff098200, -0x26a90008, -0xae120000, -0xff098200, -0x8d120000, -0xff098200, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000bb942, -0x000d6880, -0x32f707f8, -0x026d6021, -0x8d8c0000, -0x01800008, -0x02f0b821, -0xff060040, -0x8e790000, -0xff098200, -0xae900000, -0xff098200, -0x26e5fff8, -0xafb20014, -0x02e93021, -0x0120a821, -0x0320f809, -0x02802021, -0x8e0d0000, -0xff098200, -0x8ee80000, -0xff098200, -0x10000000, -0xff050841, -0x26a90008, -0xff060042, -0x8e790000, -0xff098200, -0xae900000, -0xff098200, -0x02e02821, -0xafb20014, -0x0160a821, -0x0320f809, -0x02802021, -0xff000000, -0x32ac00ff, -0x24010000, -0xff098200, -0xff000000, -0x0015b942, -0x00155402, -0x32f707f8, -0xff000000, -0x11810000, -0xff070800, -0x000a50c0, -0x10000000, -0xff070800, -0x00000000, -0xff000000, -0x10000000, -0xff070800, -0x000a50c0, -0xff000000, -0xff060043, -0x11200000, -0xff050844, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x2617fff8, -0x8e120000, -0xff098200, -0x252a0008, -0x02e97021, -0xaee60000, -0xff098200, -0x260d0008, -0x120e0000, -0xff050845, -0xaee40000, -0xff098200, -0xff06000b, -0xd5a00000, -0xf5a0fff8, -0x15ae0000, -0xff05080b, -0x25ad0008, -0x10000000, -0xff050845, -0x00000000, -0xff060046, -0x8e060000, -0xff098200, -0x240d0000, -0xff098200, -0x11200000, -0xff050844, -0x2ccc0000, -0xff098200, -0x00cc680a, -0x01a06827, -0x000d68c0, -0x010d6821, -0x10000000, -0xff050847, -0xd5a00000, -0xff098200, -0xff060048, -0x11200000, -0xff050844, -0x8e060000, -0xff098200, -0xff000000, -0x8e040000, -0xff098200, -0x24010000, -0xff098200, -0x14c10000, -0xff050806, -0x24010000, -0xff098200, -0xff06000b, -0x8c840000, -0xff098200, -0xff06000c, -0x8e690000, -0xff098200, -0x10800000, -0xff050849, -0x24060000, -0xff098200, -0x8c8c0000, -0xff098200, -0x24060000, -0xff098200, -0x8d2d0000, -0xff098200, -0x8c8e0000, -0xff098200, -0x01ac6824, -0x000d6140, -0x000d68c0, -0x018d6823, -0x01cd7021, -0x24010000, -0xff098200, -0xff06000d, -0x8dc70000, -0xff098200, -0x8dcc0000, -0xff098200, -0x8dcf0000, -0xff098200, -0x14e10000, -0xff050804, -0x8dc50000, -0xff098200, -0x11890000, -0xff050805, -0x8dcd0000, -0xff098200, -0xff06000e, -0xff000000, -0x11e00000, -0xff050849, -0x01e07021, -0x10000000, -0xff05080d, -0x00000000, -0xff06000f, -0x10be0000, -0xff050849, -0x00000000, -0x00a03021, -0x10000000, -0xff050849, -0x01a02021, -0xff060010, -0x10c10000, -0xff05080b, -0x2ccc0000, -0xff098200, -0x240d0000, -0xff098200, -0x00cc680a, -0x01a06827, -0x000d6880, -0x026d6821, -0x10000000, -0xff05080c, -0x8da40000, -0xff098200, -0xff06004a, -0x2d210010, -0x8e060000, -0xff098200, -0x14200000, -0xff050844, -0x8e070000, -0xff098200, -0x8e040000, -0xff098200, -0x8e050000, -0xff098200, -0x24010000, -0xff098200, -0x14c10000, -0xff050844, -0x24e70000, -0xff098200, -0x8c8d0000, -0xff098200, -0x908f0000, -0xff098200, -0x00ed0825, -0x14200000, -0xff050844, -0xff000000, -0x31e10000, -0xff090200, -0x10200000, -0xff050849, -0xac850000, -0xff098200, -0x8e6c0000, -0xff098200, -0x31ef0000, -0xff090200, -0xae640000, -0xff098200, -0xa08f0000, -0xff098200, -0x10000000, -0xff050849, -0xac8c0000, -0xff098200, -0xff06004b, -0x8e070000, -0xff098200, -0x2d210010, -0x8e050000, -0xff098200, -0x8e790000, -0xff098200, -0x24e70000, -0xff098200, -0x00270825, -0x14200000, -0xff050844, -0x26060008, -0x0320f809, -0x02802021, -0x10000000, -0xff050847, -0xd4400000, -0xff06004c, -0x8e040000, -0xff098200, -0x39210008, -0x2c840000, -0xff098200, -0x0001200b, -0x10800000, -0xff050844, -0xd6000000, -0x10000000, -0xff050847, -0x00000000, -0xff06004d, -0x11200000, -0xff050844, -0xff000000, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x24010000, -0xff098200, -0x10c10000, -0xff050849, -0x8e6d0000, -0xff098200, -0x2ccc0000, -0xff098200, -0x2dad0001, -0x018d6024, -0x11800000, -0xff050844, -0xae900000, -0xff098200, -0x8e6c0000, -0xff098200, -0x8e6d0000, -0xff098200, -0x018d0823, -0x04310000, -0xff05084e, -0xafb20014, -0x8e790000, -0xff098200, -0x02802021, -0x0320f809, -0x02002821, -0x24060000, -0xff098200, -0x10000000, -0xff050849, -0x00402021, -0xff06004f, -0x8e040000, -0xff098200, -0x8e050000, -0xff098200, -0x11200000, -0xff050844, -0x02097021, -0x24010000, -0xff098200, -0xadde0000, -0xff098200, -0x14810000, -0xff050844, -0x8e120000, -0xff098200, -0x8e790000, -0xff098200, -0xff000000, -0xae900000, -0xff098200, -0xae900000, -0xff098200, -0x26060008, -0xafb20014, -0x0320f809, -0x02802021, -0x10400000, -0xff050849, -0x24060000, -0xff098200, -0xd6000008, -0x2617fff8, -0xd6020010, -0x240a0000, -0xff098200, -0xf6e00000, -0x10000000, -0xff050845, -0xf6e20008, -0xff060050, -0x11200000, -0xff050844, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x24010000, -0xff098200, -0x14c10000, -0xff050844, -0x8e120000, -0xff098200, -0xff000000, -0x8c8e0000, -0xff098200, -0xd5000000, -0xff098200, -0x15c00000, -0xff050844, -0xff000000, -0xd5000000, -0xff098200, -0xff000000, -0x2617fff8, -0xae1e0000, -0xff098200, -0x240a0000, -0xff098200, -0x10000000, -0xff050845, -0xf6e00000, -0xff060051, -0x2d210010, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x8e070000, -0xff098200, -0x14200000, -0xff050844, -0xd60e0008, -0x24c60000, -0xff098200, -0x2ce10000, -0xff098200, -0x240c0001, -0x0006080b, -0x448c6000, -0x10200000, -0xff050844, -0x8e120000, -0xff098200, -0x46207024, -0x46806321, -0x8c8c0000, -0xff098200, -0x8c8d0000, -0xff098200, -0x440e0000, -0x2617fff8, -0x462c7380, -0x25ce0001, -0x01cc082b, -0x000e78c0, -0x01af7821, -0x10200000, -0xff050802, -0xf6ee0000, -0x8dee0000, -0xff098200, -0xd5e00000, -0xff06000b, -0x11de0000, -0xff050845, -0x240a0000, -0xff098200, -0x240a0000, -0xff098200, -0x10000000, -0xff050845, -0xf6e00008, -0xff06000c, -0x8c8c0000, -0xff098200, -0xff000000, -0x8e790000, -0xff098200, -0x11800000, -0xff050845, -0x240a0000, -0xff098200, -0x0320f809, -0x01c02821, -0x10400000, -0xff050845, -0x240a0000, -0xff098200, -0x8c4e0000, -0xff098200, -0x10000000, -0xff05080b, -0xd4400000, -0xff060052, -0x11200000, -0xff050844, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x24010000, -0xff098200, -0x14c10000, -0xff050844, -0x8e120000, -0xff098200, -0xff000000, -0x8c8e0000, -0xff098200, -0xd5000000, -0xff098200, -0x15c00000, -0xff050844, -0xff000000, -0xd5000000, -0xff098200, -0xff000000, -0x2617fff8, -0xae000000, -0xff098200, -0xae000000, -0xff098200, -0x240a0000, -0xff098200, -0x10000000, -0xff050845, -0xf6e00000, -0xff060053, -0x926f0000, -0xff098200, -0x11200000, -0xff050844, -0x02007021, -0x26100008, -0x000f7802, -0xff0900a6, -0x31ef0001, -0x25f20000, -0xff098200, -0x10000000, -0xff050824, -0x2529fff8, -0xff060054, -0x2d210010, -0x8e070000, -0xff098200, -0x14200000, -0xff050844, -0xd60e0008, -0xd60c0000, -0x926d0000, -0xff098200, -0x24010000, -0xff098200, -0x02007021, -0x14e10000, -0xff050844, -0x26100010, -0x000f7802, -0xff0900a6, -0xf5ce0000, -0x31ef0001, -0xf5cc0008, -0x25f20000, -0xff098200, -0x10000000, -0xff050824, -0x2529fff0, -0xff060055, -0x11200000, -0xff050844, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0xff000000, -0x24010000, -0xff098200, -0x14c10000, -0xff050844, -0x908c0000, -0xff098200, -0x8c8d0000, -0xff098200, -0x8c850000, -0xff098200, -0x8c8e0000, -0xff098200, -0x258f0000, -0xff098200, -0x1de00000, -0xff050844, -0x01c57026, -0x15a00000, -0xff050844, -0x01cc0825, -0x8c8c0000, -0xff098200, -0x10200000, -0xff050844, -0x8e120000, -0xff098200, -0x00a97021, -0x018e082b, -0x14200000, -0xff050844, -0xafb20014, -0xae900000, -0xff098200, -0xff06000b, -0x26100008, -0x2529fff8, -0x25cefff8, -0xac8e0000, -0xff098200, -0x02096821, -0x00a03021, -0xae900000, -0xff098200, -0xff06000c, -0xd6000000, -0x020d082b, -0x10200000, -0xff050803, -0x26100008, -0xf4c00000, -0x10000000, -0xff05080c, -0x24c60008, -0xff06000d, -0x04110000, -0xff050821, -0x0080b821, -0xff06000e, -0xff000000, -0x8eee0000, -0xff098200, -0x2c410000, -0xff098200, -0x8eef0000, -0xff098200, -0x240c0000, -0xff098200, -0x8e900000, -0xff098200, -0xae6c0000, -0xff098200, -0x10200000, -0xff050808, -0x01ee5023, -0x8e8c0000, -0xff098200, -0x11400000, -0xff050806, -0x020a6821, -0x018d082b, -0x14200000, -0xff050809, -0x01ca7821, -0xaeee0000, -0xff098200, -0x02006821, -0xff06000f, -0xd5c00000, -0x25ce0008, -0x01cf082b, -0xf5a00000, -0x14200000, -0xff05080f, -0x25ad0008, -0xff060010, -0x324c0000, -0xff090200, -0x240d0000, -0xff098200, -0x2617fff8, -0xae0d0000, -0xff098200, -0x254a0010, -0xff060011, -0xafb20014, -0x11800000, -0xff050817, -0x0140a821, -0x10000000, -0xff050818, -0x00000000, -0xff060012, -0x25effff8, -0x240d0000, -0xff098200, -0xd5e00000, -0xaeef0000, -0xff098200, -0xff000000, -0x240a0000, -0xff098200, -0xae0d0000, -0xff098200, -0x2617fff8, -0xf6000000, -0x10000000, -0xff050811, -0x324c0000, -0xff090200, -0xff060013, -0x8e790000, -0xff098200, -0x000a28c2, -0x0320f809, -0x02802021, -0x10000000, -0xff05080e, -0x24020000, -0xff060056, -0x8d040000, -0xff098200, -0x908c0000, -0xff098200, -0x8c8d0000, -0xff098200, -0x8c850000, -0xff098200, -0x8c8e0000, -0xff098200, -0x258f0000, -0xff098200, -0x1de00000, -0xff050844, -0x01c57026, -0x15a00000, -0xff050844, -0x01cc0825, -0x8c8c0000, -0xff098200, -0x10200000, -0xff050844, -0x8e120000, -0xff098200, -0x00a97021, -0x018e082b, -0x14200000, -0xff050844, -0xafb20014, -0xae900000, -0xff098200, -0xff06000b, -0xac8e0000, -0xff098200, -0xff000000, -0x02096821, -0x00a03021, -0xae900000, -0xff098200, -0xff06000c, -0xd6000000, -0x020d082b, -0x10200000, -0xff050803, -0x26100008, -0xf4c00000, -0x10000000, -0xff05080c, -0x24c60008, -0xff06000d, -0x04110000, -0xff050821, -0x0080b821, -0xff06000e, -0x8eee0000, -0xff098200, -0x2c410000, -0xff098200, -0x8eef0000, -0xff098200, -0x240c0000, -0xff098200, -0x8e900000, -0xff098200, -0xae6c0000, -0xff098200, -0x10200000, -0xff050808, -0x01ee5023, -0x8e8c0000, -0xff098200, -0x11400000, -0xff050806, -0x020a6821, -0x018d082b, -0x14200000, -0xff050809, -0x01ca7821, -0xaeee0000, -0xff098200, -0x02006821, -0xff06000f, -0xd5c00000, -0x25ce0008, -0x01cf082b, -0xf5a00000, -0x14200000, -0xff05080f, -0x25ad0008, -0xff060010, -0x324c0000, -0xff090200, -0x0200b821, -0x254a0008, -0xff060011, -0xff000000, -0xafb20014, -0x11800000, -0xff050817, -0x0140a821, -0x10000000, -0xff050818, -0x00000000, -0xff060012, -0x8e790000, -0xff098200, -0x02e02821, -0x0320f809, -0x02802021, -0xff060013, -0x8e790000, -0xff098200, -0x000a28c2, -0x0320f809, -0x02802021, -0x10000000, -0xff05080e, -0x24020000, -0xff060057, -0x8e8c0000, -0xff098200, -0x02096821, -0xae900000, -0xff098200, -0x318c0000, -0xff090200, -0xae8d0000, -0xff098200, -0x11800000, -0xff050844, -0x24020000, -0xff098200, -0xae800000, -0xff098200, -0x10000000, -0xff05081a, -0xa2820000, -0xff098200, -0xff060058, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x46206005, -0xff060047, -0xff000000, -0x8e120000, -0xff098200, -0x2617fff8, -0x10000000, -0xff050859, -0xf600fff8, -0xff060049, -0x8e120000, -0xff098200, -0xae060000, -0xff098200, -0x2617fff8, -0xae040000, -0xff098200, -0xff060059, -0x240a0000, -0xff098200, -0xff060045, -0x324c0000, -0xff090200, -0x15800000, -0xff050818, -0x0140a821, -0x8e4bfffc, -0x000b4542, -0x310807f8, -0xff06000f, -0x0148082b, -0x14200000, -0xff050806, -0x000b6142, -0x318c07f8, -0x8e4b0000, -0x26520004, -0x02ec8023, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff060010, -0x02ea6821, -0x254a0008, -0x10000000, -0xff05080f, -0xadbe0000, -0xff098200, -0xff06005a, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x04110000, -0xff05085b, -0x00000000, -0x10000000, -0xff050847, -0xff000000, -0x00000000, -0xff06005c, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x04110000, -0xff05085d, -0x00000000, -0x10000000, -0xff050847, -0x00000000, -0xff06005e, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff06005f, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff060060, -0x8e060000, -0xff098200, -0xff000000, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff060061, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff060062, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff060063, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0xff000000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff060064, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff060065, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff060066, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0xff000000, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff060067, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff060068, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff060069, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0x8e790000, -0xff098200, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x00000000, -0x0320f809, -0xd60c0000, -0x10000000, -0xff050847, -0x00000000, -0xff06006a, -0xff000000, -0x2d210010, -0x8e060000, -0xff098200, -0x14200000, -0xff050844, -0x8e070000, -0xff098200, -0xd60c0000, -0xd60e0008, -0x2ccc0000, -0xff098200, -0x2ced0000, -0xff098200, -0x018d6024, -0x11800000, -0xff050844, -0x8e790000, -0xff098200, -0x0320f809, -0x00000000, -0x10000000, -0xff050847, -0x00000000, -0xff06006b, -0x2d210010, -0x8e060000, -0xff098200, -0x14200000, -0xff050844, -0x8e070000, -0xff098200, -0xd60c0000, -0xd60e0008, -0x2ccc0000, -0xff098200, -0x2ced0000, -0xff098200, -0x018d6024, -0x11800000, -0xff050844, -0x8e790000, -0xff098200, -0x0320f809, -0x00000000, -0x10000000, -0xff050847, -0x00000000, -0xff06006c, -0x2d210010, -0x8e060000, -0xff098200, -0x14200000, -0xff050844, -0x8e070000, -0xff098200, -0xd60c0000, -0xd60e0008, -0x2ccc0000, -0xff098200, -0x2ced0000, -0xff098200, -0xff000000, -0x018d6024, -0x11800000, -0xff050844, -0x8e790000, -0xff098200, -0x0320f809, -0x00000000, -0x10000000, -0xff050847, -0x00000000, -0xff06006d, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x46206004, -0x10000000, -0xff050847, -0x00000000, -0xff06006e, -0xff06006f, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0xd50e0000, -0xff098200, -0x10000000, -0xff050847, -0x462e6002, -0xff060070, -0x2d210010, -0x8e060000, -0xff098200, -0x14200000, -0xff050844, -0x8e070000, -0xff098200, -0xd60c0000, -0xd60e0008, -0x2ccc0000, -0xff098200, -0x2ced0000, -0xff098200, -0xff000000, -0x018d6024, -0x11800000, -0xff050844, -0x462073a4, -0x8e790000, -0xff098200, -0x44067000, -0x0320f809, -0x00000000, -0x10000000, -0xff050847, -0x00000000, -0xff060071, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x8e790000, -0xff098200, -0x8e120000, -0xff098200, -0x0320f809, -0x26660000, -0xff098200, -0x8e6d0000, -0xff098200, -0x2617fff8, -0x448d7000, -0xf6e00000, -0x468073a1, -0xf6ee0008, -0x10000000, -0xff050845, -0x240a0000, -0xff098200, -0xff060072, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x8e790000, -0xff098200, -0x8e120000, -0xff098200, -0x0320f809, -0x2606fff8, -0x2617fff8, -0xf6000000, -0x10000000, -0xff050845, -0x240a0000, -0xff098200, -0xff060073, -0xff000000, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd6000000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x02097021, -0x260d0008, -0x11ae0000, -0xff050847, -0xff06000b, -0x8da60000, -0xff098200, -0xd5ac0000, -0x25ad0008, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x462c0034, -0x15ae0000, -0xff05080b, -0x46206011, -0x10000000, -0xff050847, -0x00000000, -0xff060074, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd6000000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x02097021, -0x260d0008, -0x11ae0000, -0xff050847, -0xff06000b, -0x8da60000, -0xff098200, -0xd5ac0000, -0x25ad0008, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x46206034, -0x15ae0000, -0xff05080b, -0x46206011, -0x10000000, -0xff050847, -0xff000000, -0x00000000, -0xff060075, -0x11200000, -0xff050844, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x24010000, -0xff098200, -0x14c10000, -0xff050844, -0x00000000, -0x10000000, -0xff050876, -0x8c820000, -0xff098200, -0xff060077, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x39210008, -0x24c60000, -0xff098200, -0x00260825, -0x14200000, -0xff050844, -0x00000000, -0x8c8c0000, -0xff098200, -0x908d0000, -0xff098200, -0x2617fff8, -0x000c502b, -0x448d0000, -0x254a0001, -0x46800021, -0x8e120000, -0xff098200, -0x000a50c0, -0x10000000, -0xff050845, -0xf6e00000, -0xff060078, -0x8e6c0000, -0xff098200, -0x8e6d0000, -0xff098200, -0x018d0823, -0x04310000, -0xff05084e, -0x8e060000, -0xff098200, -0xd60c0000, -0x24010008, -0x15210000, -0xff050844, -0xff000000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x24060001, -0x46206324, -0x27a50010, -0x2d810100, -0x440c6000, -0x10200000, -0xff050844, -0xafac0010, -0xff060079, -0x8e790000, -0xff098200, -0xae900000, -0xff098200, -0xafb20014, -0x0320f809, -0x02802021, -0x8e900000, -0xff098200, -0x00402021, -0x10000000, -0xff050849, -0x24060000, -0xff098200, -0xff06007a, -0x8e6c0000, -0xff098200, -0x8e6d0000, -0xff098200, -0x018d0823, -0x04310000, -0xff05084e, -0x2521fff0, -0x8e060000, -0xff098200, -0xd6000010, -0x8e0c0000, -0xff098200, -0x8e040000, -0xff098200, -0x04200000, -0xff050844, -0x8e050000, -0xff098200, -0xd6020008, -0x10200000, -0xff050801, -0x2407ffff, -0x46200024, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x44070000, -0xff06000b, -0x2ca10000, -0xff098200, -0xff000000, -0x10200000, -0xff050844, -0x24010000, -0xff098200, -0x462010a4, -0x15810000, -0xff050844, -0x8c850000, -0xff098200, -0x44061000, -0x00e0082a, -0x24ac0001, -0x00ec6821, -0x00c0782a, -0x01a1380b, -0x00cc6821, -0x01af300b, -0x240e0001, -0x00e0082a, -0x0006782a, -0x0001380b, -0x01cf300a, -0x00a7082a, -0x00a1380b, -0x00862821, -0x00e63023, -0x24a50000, -0xff098200, -0x04c10000, -0xff050879, -0x24c60001, -0xff06007b, -0x26640000, -0xff098200, -0x10000000, -0xff050849, -0x24060000, -0xff098200, -0xff06007c, -0x8e6c0000, -0xff098200, -0x8e6d0000, -0xff098200, -0x018d0823, -0x04310000, -0xff05084e, -0x8e0c0000, -0xff098200, -0x2d210010, -0x8e070000, -0xff098200, -0x8e040000, -0xff098200, -0x258c0000, -0xff098200, -0xd6000008, -0x002c0825, -0x14200000, -0xff050844, -0x2ce10000, -0xff098200, -0x46200024, -0x10200000, -0xff050844, -0x8c8c0000, -0xff098200, -0x44060000, -0x8e6d0000, -0xff098200, -0xff000000, -0x24010001, -0x18c00000, -0xff05087b, -0x002c082b, -0x11800000, -0xff05087b, -0x01a6602b, -0x002c0825, -0x8e650000, -0xff098200, -0x14200000, -0xff050844, -0x908c0000, -0xff098200, -0x00a67021, -0xff06000b, -0x25ceffff, -0x00ae082b, -0x14200000, -0xff05080b, -0xa1cc0000, -0x10000000, -0xff050879, -0x00000000, -0xff06007d, -0x8e6c0000, -0xff098200, -0x8e6d0000, -0xff098200, -0x018d0823, -0x04310000, -0xff05084e, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x11200000, -0xff050844, -0x24010000, -0xff098200, -0x14c10000, -0xff050844, -0x8e6d0000, -0xff098200, -0x8c860000, -0xff098200, -0x24840000, -0xff098200, -0x8e650000, -0xff098200, -0x01a6082b, -0x14200000, -0xff050844, -0x00867821, -0x00a63821, -0xff06000b, -0xff000000, -0x908d0000, -0x008f082b, -0x10200000, -0xff050879, -0x24840001, -0x24e7ffff, -0x10000000, -0xff05080b, -0xa0ed0000, -0xff06007e, -0x8e6c0000, -0xff098200, -0x8e6d0000, -0xff098200, -0x018d0823, -0x04310000, -0xff05084e, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x11200000, -0xff050844, -0x24010000, -0xff098200, -0x14c10000, -0xff050844, -0x8e6d0000, -0xff098200, -0x8c860000, -0xff098200, -0x24840000, -0xff098200, -0x8e650000, -0xff098200, -0x01a6082b, -0x14200000, -0xff050844, -0x00867821, -0x00a03821, -0xff06000b, -0x908d0000, -0x008f082b, -0x10200000, -0xff050879, -0x25acffbf, -0x39ae0020, -0x2d81001a, -0x01c1680b, -0x24840001, -0xa0ed0000, -0x10000000, -0xff05080b, -0x24e70001, -0xff06007f, -0x8e6c0000, -0xff098200, -0x8e6d0000, -0xff098200, -0x018d0823, -0x04310000, -0xff05084e, -0xff000000, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x11200000, -0xff050844, -0x24010000, -0xff098200, -0x14c10000, -0xff050844, -0x8e6d0000, -0xff098200, -0x8c860000, -0xff098200, -0x24840000, -0xff098200, -0x8e650000, -0xff098200, -0x01a6082b, -0x14200000, -0xff050844, -0x00867821, -0x00a03821, -0xff06000b, -0x908d0000, -0x008f082b, -0x10200000, -0xff050879, -0x25acff9f, -0x39ae0020, -0x2d81001a, -0x01c1680b, -0x24840001, -0xa0ed0000, -0x10000000, -0xff05080b, -0x24e70001, -0xff060080, -0x11200000, -0xff050844, -0x8e060000, -0xff098200, -0x8e040000, -0xff098200, -0x24010000, -0xff098200, -0x14c10000, -0xff050844, -0x8e790000, -0xff098200, -0x0320f809, -0x00000000, -0x10000000, -0xff050876, -0x00000000, -0xff060081, -0x8e060000, -0xff098200, -0xff000000, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x463e6300, -0x44026000, -0x260d0008, -0x02097021, -0xff06000b, -0x8da70000, -0xff098200, -0x11ae0000, -0xff050876, -0xd5ac0000, -0x2ce10000, -0xff098200, -0x10200000, -0xff050844, -0x463e6300, -0x44056000, -0x00451024, -0x10000000, -0xff05080b, -0x25ad0008, -0xff060082, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x463e6300, -0x44026000, -0x260d0008, -0x02097021, -0xff06000b, -0x8da70000, -0xff098200, -0x11ae0000, -0xff050876, -0xd5ac0000, -0x2ce10000, -0xff098200, -0x10200000, -0xff050844, -0x463e6300, -0x44056000, -0x00451025, -0x10000000, -0xff05080b, -0x25ad0008, -0xff060083, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xff000000, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x463e6300, -0x44026000, -0x260d0008, -0x02097021, -0xff06000b, -0x8da70000, -0xff098200, -0x11ae0000, -0xff050876, -0xd5ac0000, -0x2ce10000, -0xff098200, -0x10200000, -0xff050844, -0x463e6300, -0x44056000, -0x00451026, -0x10000000, -0xff05080b, -0x25ad0008, -0xff060084, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x463e6300, -0x44026000, -0x00026602, -0x00027202, -0x00026e00, -0x31ceff00, -0x018d6025, -0x3042ff00, -0x018e6025, -0x00021200, -0x10000000, -0xff050876, -0x01821025, -0xff060085, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x463e6300, -0x44026000, -0x10000000, -0xff050876, -0x00401027, -0xff060086, -0x2d210010, -0x8e060000, -0xff098200, -0x14200000, -0xff050844, -0xff000000, -0x8e070000, -0xff098200, -0xd60c0000, -0xd60e0008, -0x2ccc0000, -0xff098200, -0x2ced0000, -0xff098200, -0x018d6024, -0x11800000, -0xff050844, -0x463e6300, -0x463e7380, -0x44046000, -0x44057000, -0x10000000, -0xff050876, -0x00a41004, -0xff060087, -0x2d210010, -0x8e060000, -0xff098200, -0x14200000, -0xff050844, -0x8e070000, -0xff098200, -0xd60c0000, -0xd60e0008, -0x2ccc0000, -0xff098200, -0x2ced0000, -0xff098200, -0x018d6024, -0x11800000, -0xff050844, -0x463e6300, -0x463e7380, -0x44046000, -0x44057000, -0x10000000, -0xff050876, -0x00a41006, -0xff060088, -0x2d210010, -0x8e060000, -0xff098200, -0x14200000, -0xff050844, -0x8e070000, -0xff098200, -0xd60c0000, -0xd60e0008, -0x2ccc0000, -0xff098200, -0x2ced0000, -0xff098200, -0x018d6024, -0x11800000, -0xff050844, -0x463e6300, -0x463e7380, -0x44046000, -0x44057000, -0x10000000, -0xff050876, -0x00a41007, -0xff060089, -0x2d210010, -0x8e060000, -0xff098200, -0xff000000, -0x14200000, -0xff050844, -0x8e070000, -0xff098200, -0xd60c0000, -0xd60e0008, -0x2ccc0000, -0xff098200, -0x2ced0000, -0xff098200, -0x018d6024, -0x11800000, -0xff050844, -0x463e6300, -0x463e7380, -0x44046000, -0x44057000, -0x24010020, -0x00256023, -0x00a42804, -0x01842006, -0x10000000, -0xff050876, -0x00851025, -0xff06008a, -0x2d210010, -0x8e060000, -0xff098200, -0x14200000, -0xff050844, -0x8e070000, -0xff098200, -0xd60c0000, -0xd60e0008, -0x2ccc0000, -0xff098200, -0x2ced0000, -0xff098200, -0x018d6024, -0x11800000, -0xff050844, -0x463e6300, -0x463e7380, -0x44046000, -0x44057000, -0x24010020, -0x00256023, -0x00a42806, -0x01842004, -0x10000000, -0xff050876, -0x00851025, -0xff06008b, -0x8e060000, -0xff098200, -0x11200000, -0xff050844, -0xd60c0000, -0x2cc10000, -0xff098200, -0x10200000, -0xff050844, -0x463e6300, -0x44026000, -0xff060076, -0x44820000, -0x10000000, -0xff050847, -0x46800021, -0xff060044, -0x8d0f0000, -0xff098200, -0xff000000, -0x02096821, -0x8e120000, -0xff098200, -0x25ac0000, -0xff098200, -0x8e8e0000, -0xff098200, -0xafb20014, -0x01cc082b, -0xae900000, -0xff098200, -0xae8d0000, -0xff098200, -0x14200000, -0xff050805, -0x01e0c821, -0x01e0f809, -0x02802021, -0x8e900000, -0xff098200, -0x000250c0, -0x1c400000, -0xff050845, -0x2617fff8, -0xff06000b, -0x8e8c0000, -0xff098200, -0x8e080000, -0xff098200, -0x14400000, -0xff050829, -0x01904823, -0x8d120000, -0xff098200, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000bb942, -0x000d6880, -0x32f707f8, -0x026d6021, -0x8d8c0000, -0x01800008, -0x02f0b821, -0xff060029, -0x324c0000, -0xff090200, -0x2401fffc, -0x15800000, -0xff050803, -0x02416824, -0x924d0000, -0xff098200, -0x000d68c0, -0x25ad0008, -0xff06000d, -0x10000000, -0xff050824, -0x020d7023, -0xff06000f, -0x8e790000, -0xff098200, -0x24050000, -0xff098200, -0x0320f809, -0x02802021, -0x8e900000, -0xff098200, -0xff000000, -0x10000000, -0xff05080b, -0x24020000, -0xff06004e, -0x03e0a821, -0x8e790000, -0xff098200, -0xae900000, -0xff098200, -0x02096021, -0xafb20014, -0xae8c0000, -0xff098200, -0x0320f809, -0x02802021, -0x8e900000, -0xff098200, -0x02a0f821, -0x8e8c0000, -0xff098200, -0x8e080000, -0xff098200, -0x03e00008, -0x01904823, -0xff06008c, -0xff000000, -0x926f0000, -0xff098200, -0x31e10000, -0xff090200, -0x14200000, -0xff050805, -0x8e6e0000, -0xff098200, -0x31e10000, -0xff090200, -0x14200000, -0xff050801, -0x25ceffff, -0x31e10000, -0xff090200, -0x10200000, -0xff050801, -0x00000000, -0x10000000, -0xff050801, -0xae6e0000, -0xff098200, -0xff000000, -0xff06008d, -0x926f0000, -0xff098200, -0x31e10000, -0xff090200, -0x10200000, -0xff050801, -0xff06000f, -0x8d810000, -0xff098200, -0x00200008, -0x00000000, -0xff06008e, -0x926f0000, -0xff098200, -0x8e6e0000, -0xff098200, -0x31e10000, -0xff090200, -0x14200000, -0xff05080f, -0x31e10000, -0xff090200, -0x10200000, -0xff05080f, -0x25ceffff, -0x11c00000, -0xff050801, -0xae6e0000, -0xff098200, -0x31e10000, -0xff090200, -0x10200000, -0xff05080f, -0xff06000b, -0x8e790000, -0xff098200, -0xafb50010, -0x02402821, -0xae900000, -0xff098200, -0x0320f809, -0x02802021, -0xff06000d, -0x8e900000, -0xff098200, -0xff06000e, -0xff000000, -0x8e4bfffc, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0xff098200, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06008f, -0x26520004, -0x10000000, -0xff05080e, -0x8d150000, -0xff098200, -0xff060090, -0xff000000, -0x8e0d0000, -0xff098200, -0x26640000, -0xff098200, -0xafb20014, -0x8dad0000, -0xff098200, -0x02402821, -0xae740000, -0xff098200, -0x91ad0000, -0xff098200, -0x8e790000, -0xff098200, -0xae900000, -0xff098200, -0x000d68c0, -0x020d6821, -0x0320f809, -0xae8d0000, -0xff098200, -0x10000000, -0xff05080d, -0x00000000, -0xff000000, -0xff060091, -0xff000000, -0x10000000, -0xff050801, -0xff000000, -0x02402821, -0xff060092, -0xff000000, -0x36450001, -0xff06000b, -0xff000000, -0x8e790000, -0xff098200, -0x02096021, -0xafb20014, -0xae900000, -0xff098200, -0x02f0b823, -0xae8c0000, -0xff098200, -0x0320f809, -0x02802021, -0x8e900000, -0xff098200, -0x8e8c0000, -0xff098200, -0xafa00014, -0x01904823, -0x0217b821, -0x8e080000, -0xff098200, -0x00400008, -0x8e4bfffc, -0xff060093, -0xff000000, -0x27bd0000, -0xff098200, -0xf7a00000, -0xff098200, -0xafa00000, -0xff098200, -0xafa10000, -0xff098200, -0xf7a20000, -0xff098200, -0xafa20000, -0xff098200, -0xafa30000, -0xff098200, -0xf7a40000, -0xff098200, -0xafa40000, -0xff098200, -0xafa50000, -0xff098200, -0xf7a60000, -0xff098200, -0xafa60000, -0xff098200, -0xafa70000, -0xff098200, -0xf7a80000, -0xff098200, -0xafa80000, -0xff098200, -0xafa90000, -0xff098200, -0xf7aa0000, -0xff098200, -0xafaa0000, -0xff098200, -0xafab0000, -0xff098200, -0xf7ac0000, -0xff098200, -0xafac0000, -0xff098200, -0xafad0000, -0xff098200, -0xf7ae0000, -0xff098200, -0xff000000, -0xafae0000, -0xff098200, -0xafaf0000, -0xff098200, -0xf7b00000, -0xff098200, -0xafb00000, -0xff098200, -0xafb10000, -0xff098200, -0xf7b20000, -0xff098200, -0xafb20000, -0xff098200, -0xafb30000, -0xff098200, -0xf7b40000, -0xff098200, -0xafb40000, -0xff098200, -0xafb50000, -0xff098200, -0xf7b60000, -0xff098200, -0xafb60000, -0xff098200, -0xafb70000, -0xff098200, -0xf7b80000, -0xff098200, -0xafb80000, -0xff098200, -0xafb90000, -0xff098200, -0xf7ba0000, -0xff098200, -0xafba0000, -0xff098200, -0xafbb0000, -0xff098200, -0xf7bc0000, -0xff098200, -0xafbc0000, -0xff098200, -0xf7be0000, -0xff098200, -0xff000000, -0xafbe0000, -0xff098200, -0xafa00000, -0xff098200, -0x240c0000, -0xff098200, -0x27ae0000, -0xff098200, -0x27d30000, -0xff098200, -0x8dcd0000, -0xae6c0000, -0xff098200, -0xafae0000, -0xff098200, -0x8e740000, -0xff098200, -0x8e700000, -0xff098200, -0x8e790000, -0xff098200, -0xae740000, -0xff098200, -0xae7f0000, -0xff098200, -0xae6d0000, -0xff098200, -0x26640000, -0xff098200, -0xae900000, -0xff098200, -0x0320f809, -0x27a50010, -0x8e8d0000, -0xff098200, -0x2401fffc, -0x8e900000, -0xff098200, -0x01a1e824, -0x8fb20014, -0x10000000, -0xff050801, -0xafb40070, -0xff000000, -0xff060094, -0xff000000, -0x8fb40070, -0x27d30000, -0xff098200, -0xff06000b, -0x04400000, -0xff050803, -0x8e0d0000, -0xff098200, -0x3c0f59c0, -0x0002a8c0, -0x241e0000, -0xff098200, -0xafb50010, -0x448ff000, -0x8dad0000, -0xff098200, -0xae600000, -0xff098200, -0x8db10000, -0xff098200, -0x4600f7a1, -0x8e4b0000, -0x26520004, -0xae7e0000, -0xff098200, -0x316d00ff, -0x000d6880, -0x2dae0000, -0xff098200, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x11c00000, -0xff050802, -0x32f707f8, -0x00200008, -0x000a50c0, -0xff06000c, -0x26a9fff8, -0x00200008, -0x02f0b820, -0xff06000d, -0x8e790000, -0xff098200, -0x00022823, -0x0320f809, -0x02802021, -0xff000000, -0xff06005b, -0x3c0c4330, -0x44802000, -0x448c2800, -0x46206085, -0x44016800, -0x46241034, -0x46241000, -0x45000000, -0xff050801, -0x46240001, -0x0020082a, -0x3c0c3ff0, -0x46200087, -0x448c2800, -0x46211013, -0x46206034, -0x46240081, -0x03e00008, -0x46211011, -0xff06000b, -0x03e00008, -0x46206006, -0xff06005d, -0x3c0c4330, -0x44802000, -0x448c2800, -0x46206085, -0x44016800, -0x46241034, -0x46241000, -0x45000000, -0xff050801, -0x46240001, -0x0020082a, -0x3c0cbff0, -0x46200087, -0x448c2800, -0x46211013, -0x462c0034, -0x46240081, -0x03e00008, -0x46211011, -0xff06000b, -0x03e00008, -0x46206006, -0xff060095, -0xff000000, -0x3c0c4330, -0x44802000, -0x448c2800, -0x46206085, -0x44016800, -0x46241034, -0x46241000, -0x45000000, -0xff050801, -0x46240001, -0x0020082a, -0x3c0c3ff0, -0x448c2800, -0x46201034, -0x46240081, -0x46211011, -0x46200087, -0x03e00008, -0x46211013, -0xff06000b, -0x03e00008, -0x46206006, -0xff000000, -0xff060096, -0xff000000, -0x27bdff90, -0xafbf0000, -0xff098200, -0xafbe0000, -0xff098200, -0xf7be0000, -0xff098200, -0xafb70000, -0xff098200, -0xafb60000, -0xff098200, -0xf7bc0000, -0xff098200, -0xafb50000, -0xff098200, -0xafb40000, -0xff098200, -0xf7ba0000, -0xff098200, -0xafb30000, -0xff098200, -0xafb20000, -0xff098200, -0xf7b80000, -0xff098200, -0xafb10000, -0xff098200, -0xafb00000, -0xff098200, -0xf7b60000, -0xff098200, -0xf7b40000, -0xff098200, -0x8c520000, -0xff098200, -0x24530000, -0xff098200, -0x8e790000, -0xff098200, -0xae410000, -0xff098200, -0xae440000, -0xff098200, -0xae450000, -0xff098200, -0xf64c0000, -0xff098200, -0xff000000, -0xae460000, -0xff098200, -0xae470000, -0xff098200, -0xf64e0000, -0xff098200, -0x27ac0000, -0xff098200, -0xae4c0000, -0xff098200, -0xafa00014, -0x03a02821, -0x0320f809, -0x02402021, -0x8c500000, -0xff098200, -0x8c490000, -0xff098200, -0x0040a021, -0x3c0f59c0, -0x8e080000, -0xff098200, -0x448ff000, -0x240c0000, -0xff098200, -0x241e0000, -0xff098200, -0x01304823, -0xae6c0000, -0xff098200, -0x4600f7a1, -0x8d120000, -0xff098200, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000bb942, -0x000d6880, -0x32f707f8, -0x026d6021, -0x8d8c0000, -0x01800008, -0x02f0b821, -0xff000000, -0xff060028, -0xff000000, -0x8e790000, -0xff098200, -0x8e720000, -0xff098200, -0xae900000, -0xff098200, -0xae880000, -0xff098200, -0xae540000, -0xff098200, -0x02e02821, -0x0320f809, -0x02402021, -0x8e420000, -0xff098200, -0xd6400000, -0xff098200, -0x8e430000, -0xff098200, -0x10000000, -0xff05081a, -0xd6420000, -0xff098200, -0xff000000, -0xff060097, -0xff000000, -0x8c8d0000, -0xff098200, -0x90850000, -0xff098200, -0x03a07021, -0x03ade823, -0xaddffffc, -0x00052880, -0xadd0fff8, -0xadc4fff4, -0x01c08021, -0x248d0000, -0xff098200, -0x27ae0010, -0x10a00000, -0xff050802, -0x01a57821, -0xff06000b, -0x8dac0000, -0x25ad0004, -0x01af082b, -0xadcc0000, -0x14200000, -0xff05080b, -0x25ce0004, -0xff06000c, -0x8c990000, -0xff098200, -0x8c850000, -0xff098200, -0x8c860000, -0xff098200, -0x8c870000, -0xff098200, -0xd48c0000, -0xff098200, -0xd48e0000, -0xff098200, -0x0320f809, -0x8c840000, -0xff098200, -0x8e0dfff4, -0x8e0efff8, -0x8e1ffffc, -0xada20000, -0xff098200, -0xada30000, -0xff098200, -0xf5a00000, -0xff098200, -0xf5a20000, -0xff098200, -0x0200e821, -0x03e00008, -0x01c08021, -0xff000000, -0xff080000, -0xff000000, -0x02172821, -0x020a3021, -0x8cac0000, -0xff098200, -0x8ccd0000, -0xff098200, -0xd4a00000, -0xd4c20000, -0x2d8c0000, -0xff098200, -0x2dad0000, -0xff098200, -0x964e0000, -0xff098200, -0x018d6024, -0x26520004, -0x11800000, -0xff050835, -0x3c0d0000, -0xff090200, -0x000e7080, -0x01cd7021, -0xff000000, -0x46220034, -0xff000000, -0x46220036, -0xff000000, -0x00007001, -0xff000000, -0x00017001, -0xff000000, -0x024e9021, -0xff06000b, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x0217b821, -0x26520004, -0x8eec0000, -0xff098200, -0xd6e00000, -0x020a5021, -0x964e0000, -0xff098200, -0x8d4d0000, -0xff098200, -0xd5420000, -0x3c0f0000, -0xff090200, -0x2d810000, -0xff098200, -0x2da40000, -0xff098200, -0x000e7080, -0x00240824, -0x10200000, -0xff050805, -0x01cf7021, -0x46220032, -0xff000000, -0x00007001, -0xff000000, -0x00017001, -0xff000000, -0xff06000b, -0x024e9021, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000f, -0x8ee50000, -0xff098200, -0x8d460000, -0xff098200, -0xff000000, -0x240f0000, -0xff098200, -0x118f0000, -0xff05083b, -0xff000000, -0x2d810000, -0xff098200, -0xff000000, -0x11af0000, -0xff05083b, -0xff000000, -0x00a67826, -0x01ac6826, -0x2d840000, -0xff098200, -0x0001780a, -0x000d200b, -0x01af0825, -0x0001200a, -0x10800000, -0xff05080b, -0xff000000, -0x0001700b, -0xff000000, -0x0001700a, -0xff000000, -0x8cad0000, -0xff098200, -0x11a00000, -0xff05080b, -0x00000000, -0x91ad0000, -0xff098200, -0x31ad0000, -0xff090200, -0x15a00000, -0xff05080b, -0x00000000, -0x10000000, -0xff05083a, -0x24070000, -0xff098200, -0xff000000, -0x0217b821, -0x26520004, -0x8eec0000, -0xff098200, -0x000a5042, -0x8eef0000, -0xff098200, -0x022a5023, -0x964e0000, -0xff098200, -0xff000000, -0x24010000, -0xff098200, -0x11810000, -0xff05083b, -0xff000000, -0x8d4dfffc, -0x258c0000, -0xff098200, -0x000e7080, -0x01af6826, -0x018d6025, -0x3c0f0000, -0xff090200, -0x01cf7021, -0xff000000, -0x000c700b, -0xff000000, -0x000c700a, -0xff000000, -0x024e9021, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x0217b821, -0x26520004, -0x8eec0000, -0xff098200, -0xd6e00000, -0x022a5021, -0x964e0000, -0xff098200, -0xd5420000, -0x3c0f0000, -0xff090200, -0x2d810000, -0xff098200, -0x000e7080, -0xff000000, -0x10200000, -0xff050805, -0xff000000, -0x10200000, -0xff050801, -0xff000000, -0x01cf7021, -0x46220032, -0xff000000, -0x00007001, -0x024e9021, -0xff06000b, -0xff000000, -0x00017001, -0xff06000b, -0x024e9021, -0xff000000, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0xff06000f, -0x24010000, -0xff098200, -0x11810000, -0xff05083b, -0x00000000, -0x10000000, -0xff05080b, -0x00000000, -0xff000000, -0x0217b821, -0x000a68c2, -0x8eec0000, -0xff098200, -0x964e0000, -0xff098200, -0x01a06827, -0x26520004, -0xff000000, -0x24010000, -0xff098200, -0x11810000, -0xff05083b, -0xff000000, -0x018d6026, -0x000e7080, -0x3c0f0000, -0xff090200, -0x01cf7021, -0xff000000, -0x000c700b, -0xff000000, -0x000c700a, -0xff000000, -0x024e9021, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x020a5021, -0x964e0000, -0xff098200, -0x8d4c0000, -0xff098200, -0x26520004, -0xff000000, -0x2d8c0000, -0xff098200, -0x000e7080, -0x3c0f0000, -0xff090200, -0x01cf7021, -0xff000000, -0x000c700a, -0xff000000, -0x000c700b, -0xff000000, -0x024e9021, -0xff000000, -0x2d8c0000, -0xff098200, -0xd5400000, -0xff000000, -0x11800000, -0xff050801, -0xff000000, -0x15800000, -0xff050801, -0xff000000, -0x0217b821, -0x000e7080, -0x3c0f0000, -0xff090200, -0x01cf7021, -0xf6e00000, -0x024e9021, -0xff06000b, -0xff000000, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x020a5021, -0x0217b821, -0xd5400000, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x020a5021, -0x0217b821, -0x8d4c0000, -0xff098200, -0x240d0000, -0xff098200, -0x2d8c0000, -0xff098200, -0x258d0000, -0xff098200, -0x8e4b0000, -0x26520004, -0xaeed0000, -0xff098200, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x020a3021, -0x0217b821, -0x8ccc0000, -0xff098200, -0xd4c00000, -0x2d810000, -0xff098200, -0x10200000, -0xff05083c, -0x46200007, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x020a2821, -0x0217b821, -0x8cac0000, -0xff098200, -0x8ca40000, -0xff098200, -0x24010000, -0xff098200, -0x15810000, -0xff050802, -0x24010000, -0xff098200, -0x8c820000, -0xff098200, -0xff06000b, -0x44820000, -0x46800021, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000c, -0x15810000, -0xff05083e, -0x00000000, -0xff000000, -0x8c8e0000, -0xff098200, -0x15c00000, -0xff050809, -0x00000000, -0xff06000d, -0xff000000, -0xff06003f, -0x8e790000, -0xff098200, -0x0320f809, -0x00000000, -0x10000000, -0xff05080b, -0x00000000, -0xff000000, -0xff060013, -0x91cc0000, -0xff098200, -0x318c0000, -0xff090200, -0x15800000, -0xff05080d, -0x00000000, -0x10000000, -0xff05083e, -0x00000000, -0xff000000, -0x000b4542, -0x310807f8, -0x314907f8, -0xff000000, -0x02083021, -0x02293821, -0x8ccd0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0xff000000, -0x02083821, -0x02293021, -0x8ced0000, -0xff098200, -0xd4f60000, -0xd4d40000, -0x2da10000, -0xff098200, -0xff000000, -0x02083021, -0x02093821, -0x8ccd0000, -0xff098200, -0x8cee0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0x2dcc0000, -0xff098200, -0x002c0824, -0xff000000, -0x10200000, -0xff05083d, -0x0217b821, -0x4636a000, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000b4542, -0x310807f8, -0x314907f8, -0xff000000, -0x02083021, -0x02293821, -0x8ccd0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0xff000000, -0x02083821, -0x02293021, -0x8ced0000, -0xff098200, -0xd4f60000, -0xd4d40000, -0x2da10000, -0xff098200, -0xff000000, -0x02083021, -0x02093821, -0x8ccd0000, -0xff098200, -0x8cee0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0x2dcc0000, -0xff098200, -0x002c0824, -0xff000000, -0x10200000, -0xff05083d, -0x0217b821, -0x4636a001, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000b4542, -0x310807f8, -0x314907f8, -0xff000000, -0x02083021, -0x02293821, -0x8ccd0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0xff000000, -0x02083821, -0x02293021, -0x8ced0000, -0xff098200, -0xd4f60000, -0xd4d40000, -0x2da10000, -0xff098200, -0xff000000, -0x02083021, -0x02093821, -0x8ccd0000, -0xff098200, -0x8cee0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0x2dcc0000, -0xff098200, -0x002c0824, -0xff000000, -0x10200000, -0xff05083d, -0x0217b821, -0x4636a002, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000b4542, -0x310807f8, -0x314907f8, -0xff000000, -0x02083021, -0x02293821, -0x8ccd0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0xff000000, -0x02083821, -0x02293021, -0x8ced0000, -0xff098200, -0xd4f60000, -0xd4d40000, -0x2da10000, -0xff098200, -0xff000000, -0x02083021, -0x02093821, -0x8ccd0000, -0xff098200, -0x8cee0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0x2dcc0000, -0xff098200, -0x002c0824, -0xff000000, -0x10200000, -0xff05083d, -0x0217b821, -0x4636a003, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000b4542, -0x310807f8, -0x314907f8, -0xff000000, -0x02083021, -0x02293821, -0x8ccd0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0xff000000, -0x02083821, -0x02293021, -0x8ced0000, -0xff098200, -0xd4f60000, -0xd4d40000, -0x2da10000, -0xff098200, -0xff000000, -0x02083021, -0x02093821, -0x8ccd0000, -0xff098200, -0x8cee0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0x2dcc0000, -0xff098200, -0x002c0824, -0xff000000, -0x10200000, -0xff05083d, -0x0217b821, -0xff060098, -0x04110000, -0xff05085b, -0x4636a303, -0x46360002, -0x4620a001, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000b4542, -0x310807f8, -0x314907f8, -0xff000000, -0x02083021, -0x02293821, -0x8ccd0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0xff000000, -0x02083821, -0x02293021, -0x8ced0000, -0xff098200, -0xd4f60000, -0xd4d40000, -0x2da10000, -0xff098200, -0xff000000, -0x02083021, -0x02093821, -0x8ccd0000, -0xff098200, -0x8cee0000, -0xff098200, -0xd4d40000, -0xd4f60000, -0x2da10000, -0xff098200, -0x2dcc0000, -0xff098200, -0x002c0824, -0xff000000, -0x10200000, -0xff05083d, -0x0217b821, -0x10000000, -0xff050898, -0x00000000, -0xff000000, -0x000b4542, -0x310807f8, -0x314907f8, -0x02083021, -0x02093821, -0x8ccd0000, -0xff098200, -0x8cee0000, -0xff098200, -0xd4cc0000, -0xd4ee0000, -0x2da10000, -0xff098200, -0x2dcc0000, -0xff098200, -0x002c0824, -0x8e790000, -0xff098200, -0x10200000, -0xff05083d, -0x0217b821, -0x0320f809, -0x00000000, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000b4542, -0x310807f8, -0x314907f8, -0x01283023, -0xae900000, -0xff098200, -0x02092821, -0x0100a821, -0xff06002b, -0x8e790000, -0xff098200, -0x000630c2, -0xafb20014, -0x0320f809, -0x02802021, -0x14400000, -0xff050836, -0x8e900000, -0xff098200, -0x02154021, -0xd5000000, -0x0217b821, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000a6842, -0x022d6823, -0x8e4b0000, -0x26520004, -0x8dacfffc, -0x0217b821, -0x240e0000, -0xff098200, -0xaeec0000, -0xff098200, -0xaeee0000, -0xff098200, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000a6842, -0x022d6823, -0x8e4b0000, -0x26520004, -0x8dacfffc, -0x0217b821, -0x240e0000, -0xff098200, -0xaeec0000, -0xff098200, -0xaeee0000, -0xff098200, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000b5403, -0x448a0000, -0x0217b821, -0x46800021, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x022a5021, -0x0217b821, -0xd5400000, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000a68c2, -0x0217b821, -0x01a06027, -0x8e4b0000, -0x26520004, -0xaeec0000, -0xff098200, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x0217b821, -0xaefe0000, -0xff098200, -0x26f70008, -0x020a5021, -0xff06000b, -0xaefe0000, -0xff098200, -0x02ea082a, -0x14200000, -0xff05080b, -0x26f70008, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x8e080000, -0xff098200, -0x000a5042, -0x01485021, -0x8d480000, -0xff098200, -0x8e4b0000, -0x26520004, -0x8d0d0000, -0xff098200, -0xd5a00000, -0x0217b821, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x8e080000, -0xff098200, -0x0017b842, -0x020a5021, -0x02e8b821, -0xd5400000, -0x8ee80000, -0xff098200, -0x910f0000, -0xff098200, -0x8d050000, -0xff098200, -0x31ef0000, -0xff090200, -0x910c0000, -0xff098200, -0x8d4e0000, -0xff098200, -0xf4a00000, -0x24010000, -0xff098200, -0x01ec7825, -0x11e10000, -0xff050802, -0x25ce0000, -0xff098200, -0xff06000b, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000c, -0x2dc10000, -0xff098200, -0x10200000, -0xff05080b, -0x8d4d0000, -0xff098200, -0x91af0000, -0xff098200, -0x31ef0000, -0xff090200, -0x11e00000, -0xff05080b, -0x8e790000, -0xff098200, -0x0320f809, -0x26640000, -0xff098200, -0x10000000, -0xff05080b, -0x00000000, -0xff000000, -0x8e080000, -0xff098200, -0x0017b842, -0x000a6842, -0x02e8b821, -0x022d6823, -0x8ee80000, -0xff098200, -0x8dadfffc, -0x910e0000, -0xff098200, -0x8d050000, -0xff098200, -0x91af0000, -0xff098200, -0x31c10000, -0xff090200, -0x910e0000, -0xff098200, -0x240c0000, -0xff098200, -0xacad0000, -0xff098200, -0x14200000, -0xff050802, -0xacac0000, -0xff098200, -0xff06000b, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000c, -0x11c00000, -0xff05080b, -0x31e10000, -0xff090200, -0x10200000, -0xff05080b, -0x8e790000, -0xff098200, -0x0320f809, -0x26640000, -0xff098200, -0x10000000, -0xff05080b, -0x00000000, -0xff000000, -0x8e080000, -0xff098200, -0x0017b842, -0x022a5021, -0x02e8b821, -0xd5400000, -0x8ee80000, -0xff098200, -0x8e4b0000, -0x26520004, -0x8d0d0000, -0xff098200, -0xf5a00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x8e080000, -0xff098200, -0x0017b842, -0x000a60c2, -0x02e8b821, -0x01806027, -0x8ee80000, -0xff098200, -0x8e4b0000, -0x26520004, -0x8d0d0000, -0xff098200, -0xadac0000, -0xff098200, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x8e8e0000, -0xff098200, -0x000a6042, -0x3c010000, -0xff090200, -0x01816021, -0x024c9021, -0x8e790000, -0xff098200, -0xae900000, -0xff098200, -0x11c00000, -0xff050801, -0x02802021, -0x0320f809, -0x02172821, -0x8e900000, -0xff098200, -0xff06000b, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x000a6842, -0x8e790000, -0xff098200, -0x022d6823, -0x8e060000, -0xff098200, -0x8da5fffc, -0xae900000, -0xff098200, -0xafb20014, -0x0320f809, -0x02802021, -0x8e900000, -0xff098200, -0x240c0000, -0xff098200, -0x8e4b0000, -0x26520004, -0x0217b821, -0xaeec0000, -0xff098200, -0xaee20000, -0xff098200, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x8e6c0000, -0xff098200, -0x8e6d0000, -0xff098200, -0xae900000, -0xff098200, -0xafb20014, -0x018d082b, -0x10200000, -0xff050805, -0xff06000b, -0xff000000, -0x8e790000, -0xff098200, -0x000a28c2, -0x30a507ff, -0x240c0801, -0x24a1f801, -0x000a3382, -0x0181280a, -0x0320f809, -0x02802021, -0xff000000, -0x8e790000, -0xff098200, -0x000a6842, -0x022d6823, -0x02802021, -0x0320f809, -0x8da5fffc, -0xff000000, -0x8e900000, -0xff098200, -0x8e4b0000, -0x26520004, -0x0217b821, -0x240c0000, -0xff098200, -0xaee20000, -0xff098200, -0xaeec0000, -0xff098200, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000f, -0x8e790000, -0xff098200, -0x0140a821, -0x0320f809, -0x02802021, -0x10000000, -0xff05080b, -0x02a05021, -0xff000000, -0x8e0e0000, -0xff098200, -0x000a6842, -0x022d6823, -0x8dc80000, -0xff098200, -0x8da9fffc, -0xff000000, -0x10000000, -0xff050899, -0xff000000, -0x10000000, -0xff05089a, -0xff000000, -0x0217b821, -0xff000000, -0x000b4542, -0x310807f8, -0x314907f8, -0x02082821, -0x02093021, -0x8cad0000, -0xff098200, -0x8cce0000, -0xff098200, -0x8ca80000, -0xff098200, -0x24010000, -0xff098200, -0xd4c00000, -0x15a10000, -0xff050830, -0x0217b821, -0x2dc10000, -0xff098200, -0x10200000, -0xff050805, -0x24010000, -0xff098200, -0x462000a4, -0x8d0c0000, -0xff098200, -0x440e1000, -0x46801121, -0x8d0d0000, -0xff098200, -0x46240032, -0x01cc082b, -0x00000801, -0x000e70c0, -0x10200000, -0xff050830, -0x01ae7021, -0x8dcc0000, -0xff098200, -0x119e0000, -0xff050802, -0xd5c00000, -0xff06000b, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000c, -0x8d0e0000, -0xff098200, -0x11c00000, -0xff05080b, -0x00000000, -0x91cc0000, -0xff098200, -0x318c0000, -0xff090200, -0x15800000, -0xff05080b, -0x00000000, -0x10000000, -0xff050830, -0x00000000, -0xff06000f, -0x15c10000, -0xff050830, -0xff000000, -0x8cc90000, -0xff098200, -0x10000000, -0xff050899, -0x00000000, -0xff000000, -0x000b4542, -0x310807f8, -0x02082821, -0x000b4b82, -0x8cac0000, -0xff098200, -0x312903fc, -0x24010000, -0xff098200, -0x8ca80000, -0xff098200, -0x02293023, -0x8cc9fffc, -0x15810000, -0xff05082d, -0x0217b821, -0xff060099, -0x8d0c0000, -0xff098200, -0x8d2d0000, -0xff098200, -0x8d0e0000, -0xff098200, -0x01ac6824, -0x000d6140, -0x000d68c0, -0x018d6823, -0x01cd7021, -0xff06000b, -0x8dc40000, -0xff098200, -0x8dcc0000, -0xff098200, -0x8dcd0000, -0xff098200, -0x8dc50000, -0xff098200, -0x24840000, -0xff098200, -0x01896026, -0x008c0825, -0x14200000, -0xff050804, -0x8d0f0000, -0xff098200, -0x10be0000, -0xff050805, -0x8dc40000, -0xff098200, -0xff06000d, -0x8e4b0000, -0x26520004, -0xaee50000, -0xff098200, -0xaee40000, -0xff098200, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000e, -0x15a00000, -0xff05080b, -0xff000000, -0x01a07021, -0xff06000f, -0x11e00000, -0xff05080d, -0x24050000, -0xff098200, -0x91ec0000, -0xff098200, -0x318c0000, -0xff090200, -0x15800000, -0xff05080d, -0x00000000, -0x10000000, -0xff05082e, -0x00000000, -0xff000000, -0x000b4542, -0x310807f8, -0x02082821, -0x314907f8, -0x8ca40000, -0xff098200, -0x24010000, -0xff098200, -0x8ca80000, -0xff098200, -0x0217b821, -0x14810000, -0xff05082f, -0x000960c2, -0x8d0d0000, -0xff098200, -0x8d0e0000, -0xff098200, -0x018d082b, -0x10200000, -0xff05082f, -0x01c94821, -0x8d2d0000, -0xff098200, -0x11be0000, -0xff050805, -0xd5200000, -0xff06000b, -0x8e4b0000, -0x26520004, -0xf6e00000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000f, -0x8d0e0000, -0xff098200, -0x11c00000, -0xff05080b, -0x00000000, -0x91cd0000, -0xff098200, -0x31ad0000, -0xff090200, -0x15a00000, -0xff05080b, -0x00000000, -0x10000000, -0xff05082f, -0x00000000, -0xff000000, -0x000b4542, -0x310807f8, -0x314907f8, -0x02082821, -0x02093021, -0x8cad0000, -0xff098200, -0x8cce0000, -0xff098200, -0x8ca80000, -0xff098200, -0x24010000, -0xff098200, -0xd4c00000, -0x15a10000, -0xff050834, -0x0217b821, -0x2dc10000, -0xff098200, -0x10200000, -0xff050805, -0x24010000, -0xff098200, -0x462000a4, -0x8d0c0000, -0xff098200, -0x440e1000, -0x46801121, -0x8d0d0000, -0xff098200, -0x46240032, -0x01cc082b, -0x00000801, -0x000e70c0, -0x10200000, -0xff050834, -0x01ae6821, -0x910f0000, -0xff098200, -0x8dac0000, -0xff098200, -0x119e0000, -0xff050803, -0xd6e00000, -0xff06000b, -0x31e10000, -0xff090200, -0x14200000, -0xff050807, -0xf5a00000, -0xff06000c, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000d, -0x8d0e0000, -0xff098200, -0x11c00000, -0xff05080b, -0x00000000, -0x91ce0000, -0xff098200, -0x31ce0000, -0xff090200, -0xff000000, -0x15c00000, -0xff05080b, -0x00000000, -0x10000000, -0xff050834, -0x00000000, -0xff06000f, -0x15c10000, -0xff050834, -0x8cc90000, -0xff098200, -0x10000000, -0xff05089a, -0x00000000, -0xff060011, -0x8e6c0000, -0xff098200, -0x31ef0000, -0xff090200, -0xae680000, -0xff098200, -0xa10f0000, -0xff098200, -0x10000000, -0xff05080c, -0xad0c0000, -0xff098200, -0xff000000, -0x000b4542, -0x310807f8, -0x02082821, -0x000b4b82, -0x8cac0000, -0xff098200, -0x312903fc, -0x24010000, -0xff098200, -0x02293023, -0x8ca80000, -0xff098200, -0x8cc9fffc, -0x15810000, -0xff050831, -0x0217b821, -0xff06009a, -0x8d0c0000, -0xff098200, -0x8d2d0000, -0xff098200, -0x8d0e0000, -0xff098200, -0xa1000000, -0xff098200, -0x01ac6824, -0x000d6140, -0x000d68c0, -0x018d6823, -0x01cd7021, -0xd6f40000, -0xff06000b, -0x8dc40000, -0xff098200, -0x8dcc0000, -0xff098200, -0x24010000, -0xff098200, -0x8dcd0000, -0xff098200, -0x14810000, -0xff050805, -0x8dc50000, -0xff098200, -0x15890000, -0xff050805, -0x910f0000, -0xff098200, -0x10be0000, -0xff050804, -0x8d0c0000, -0xff098200, -0xff06000c, -0x31e10000, -0xff090200, -0x14200000, -0xff050807, -0xff000000, -0xf5d40000, -0xff098200, -0xff06000d, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000e, -0x11800000, -0xff05080c, -0x00000000, -0x918c0000, -0xff098200, -0x318c0000, -0xff090200, -0x15800000, -0xff05080c, -0x00000000, -0x10000000, -0xff050832, -0x00000000, -0xff06000f, -0x15a00000, -0xff05080b, -0x01a07021, -0x8d0e0000, -0xff098200, -0x11c00000, -0xff050806, -0x26660000, -0xff098200, -0x91cc0000, -0xff098200, -0x318c0000, -0xff090200, -0x11800000, -0xff050832, -0x24010000, -0xff098200, -0xff060010, -0x8e790000, -0xff098200, -0xacc90000, -0xff098200, -0xacc10000, -0xff098200, -0xae900000, -0xff098200, -0x01002821, -0xafb20014, -0x0320f809, -0x02802021, -0x8e900000, -0xff098200, -0xff000000, -0x10000000, -0xff05080d, -0xf4540000, -0xff060011, -0x8e6c0000, -0xff098200, -0x31ef0000, -0xff090200, -0xae680000, -0xff098200, -0xa10f0000, -0xff098200, -0x10000000, -0xff05080d, -0xad0c0000, -0xff098200, -0xff000000, -0x000b4542, -0x310807f8, -0x02082821, -0x314907f8, -0x8ca40000, -0xff098200, -0x24010000, -0xff098200, -0x8ca80000, -0xff098200, -0x0217b821, -0x14810000, -0xff050833, -0x000960c2, -0x8d0d0000, -0xff098200, -0x8d0e0000, -0xff098200, -0x018d082b, -0x10200000, -0xff050833, -0x01c94821, -0x8d2d0000, -0xff098200, -0x910f0000, -0xff098200, -0x11be0000, -0xff050805, -0xd6e00000, -0xff06000b, -0x31e10000, -0xff090200, -0x14200000, -0xff050807, -0xf5200000, -0xff06000c, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000f, -0x8d0e0000, -0xff098200, -0x11c00000, -0xff05080b, -0x00000000, -0x91cd0000, -0xff098200, -0x31ad0000, -0xff090200, -0x15a00000, -0xff05080b, -0x00000000, -0x10000000, -0xff050833, -0x00000000, -0xff060011, -0x8e6c0000, -0xff098200, -0xff000000, -0x31ef0000, -0xff090200, -0xae680000, -0xff098200, -0xa10f0000, -0xff098200, -0x10000000, -0xff05080c, -0xad0c0000, -0xff098200, -0xff000000, -0x0217b821, -0xff06000b, -0x022a7821, -0x8ee50000, -0xff098200, -0x26acfff8, -0x8def0000, -0xff098200, -0x11800000, -0xff050804, -0x000c30c2, -0x00cf3021, -0x8cae0000, -0xff098200, -0x000f68c0, -0x90af0000, -0xff098200, -0x8ca40000, -0xff098200, -0x01c6082b, -0x14200000, -0xff050805, -0x02ec7021, -0x01a46821, -0x31ec0000, -0xff090200, -0xff06000d, -0xd6e00000, -0x26f70008, -0x02ee082b, -0xf5a00000, -0x14200000, -0xff05080d, -0x25ad0008, -0x15800000, -0xff050807, -0x00000000, -0xff06000e, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000f, -0x8e790000, -0xff098200, -0xae900000, -0xff098200, -0xafb20014, -0x01408021, -0x0320f809, -0x02802021, -0x02005021, -0x10000000, -0xff05080b, -0x8e900000, -0xff098200, -0xff060011, -0x8e6c0000, -0xff098200, -0x31ef0000, -0xff090200, -0xae650000, -0xff098200, -0xa0af0000, -0xff098200, -0xff000000, -0x10000000, -0xff05080e, -0xacac0000, -0xff098200, -0xff000000, -0x314907f8, -0x10000000, -0xff05089b, -0x01354821, -0xff000000, -0x314907f8, -0xff06009b, -0x02007021, -0x02178021, -0x24010000, -0xff098200, -0x8e0c0000, -0xff098200, -0x8e080000, -0xff098200, -0x26100008, -0x15810000, -0xff050825, -0x2529fff8, -0xae120000, -0xff098200, -0x8d120000, -0xff098200, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000bb942, -0x000d6880, -0x32f707f8, -0x026d6021, -0x8d8c0000, -0x01800008, -0x02f0b821, -0xff000000, -0x01555021, -0xff000000, -0x0217b821, -0x24010000, -0xff098200, -0x8eec0000, -0xff098200, -0x8ee80000, -0xff098200, -0x01404821, -0x8e0d0000, -0xff098200, -0x26f70008, -0x15810000, -0xff050840, -0x2529fff8, -0xff060041, -0x31ac0000, -0xff090200, -0x910f0000, -0xff098200, -0x15800000, -0xff050807, -0x39ae0000, -0xff090200, -0xff06000b, -0xae080000, -0xff098200, -0x2de10002, -0x02007021, -0x11200000, -0xff050803, -0x01207821, -0xff06000c, -0xd6e00000, -0x26f70008, -0x25effff8, -0xf5c00000, -0x15e00000, -0xff05080c, -0x25ce0008, -0xff06000d, -0x01816025, -0x11800000, -0xff050805, -0x00000000, -0xff06000e, -0x8d120000, -0xff098200, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000bb942, -0x000d6880, -0x32f707f8, -0x026d6021, -0x8d8c0000, -0x01800008, -0x02f0b821, -0xff06000f, -0x8dabfffc, -0x000bb942, -0x32f707f8, -0x02176823, -0x8dad0000, -0xff098200, -0x8dad0000, -0xff098200, -0x10000000, -0xff05080e, -0xff000000, -0x8db10000, -0xff098200, -0xff060011, -0x31c10000, -0xff090200, -0x14200000, -0xff05080b, -0x020e7023, -0x01c08021, -0x8dcd0000, -0xff098200, -0x10000000, -0xff05080b, -0x31ac0000, -0xff090200, -0xff000000, -0x02007021, -0x02178021, -0x24010000, -0xff098200, -0x8e0d0000, -0xff098200, -0x8e080000, -0xff098200, -0xd602fff8, -0xd600fff0, -0xae0d0000, -0xff098200, -0xae080000, -0xff098200, -0xf6020010, -0xf6000008, -0x26100008, -0x15a10000, -0xff050825, -0x24090010, -0xae120000, -0xff098200, -0x8d120000, -0xff098200, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000bb942, -0x000d6880, -0x32f707f8, -0x026d6021, -0x8d8c0000, -0x01800008, -0x02f0b821, -0xff000000, -0x0217b821, -0x8ee80000, -0xff098200, -0x8ee90000, -0xff098200, -0x8d0c0000, -0xff098200, -0x8d0d0000, -0xff098200, -0x26520004, -0xff06000b, -0x012c082b, -0x10200000, -0xff050805, -0x000978c0, -0x01af7821, -0x8dee0000, -0xff098200, -0xd5e00000, -0x44891000, -0x964a0000, -0xff098200, -0x11de0000, -0xff05080b, -0x25290001, -0x468010a1, -0x3c0f0000, -0xff090200, -0xf6e00008, -0x000a5080, -0x014f5021, -0xaee90000, -0xff098200, -0x024a9021, -0xf6e20000, -0xff06000d, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000f, -0x8d0d0000, -0xff098200, -0x012c4823, -0x8d0e0000, -0xff098200, -0xff060010, -0x01a9082b, -0x14200000, -0xff05080d, -0x00097940, -0x000940c0, -0x01e87823, -0x01ee7821, -0x8de80000, -0xff098200, -0xd5e00000, -0x964a0000, -0xff098200, -0x111e0000, -0xff050810, -0x25290001, -0xd5e20000, -0xff098200, -0x3c0f0000, -0xff090200, -0xf6e00008, -0x012c4821, -0x000a5080, -0x014f5021, -0xf6e20000, -0x024a9021, -0x10000000, -0xff05080d, -0xff000000, -0xaee90000, -0xff098200, -0xff000000, -0x0217b821, -0x8eec0000, -0xff098200, -0x8eed0000, -0xff098200, -0x8eee0000, -0xff098200, -0x8eef0000, -0xff098200, -0x24010000, -0xff098200, -0x15810000, -0xff050805, -0x25ce0000, -0xff098200, -0x91ad0000, -0xff098200, -0x25ef0000, -0xff098200, -0x000a6042, -0x01cf7025, -0x25ad0000, -0xff098200, -0x024c6021, -0x01ae6825, -0x15a00000, -0xff050805, -0x3c0e0000, -0xff090200, -0x018e9021, -0xaee00000, -0xff098200, -0xff06000b, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000f, -0x240f0000, -0xff098200, -0x240d0000, -0xff098200, -0xa24f0000, -0xff098200, -0x018e9021, -0x10000000, -0xff05080b, -0xa24d0000, -0xff098200, -0xff000000, -0x8e0c0000, -0xff098200, -0x314907f8, -0x000b4542, -0x02094821, -0x310807f8, -0x0217b821, -0x25290000, -0xff098200, -0x02e87021, -0x260ffff8, -0x012c4823, -0x11000000, -0xff050805, -0x01e96823, -0x25cefff0, -0xff06000b, -0x8d240000, -0xff098200, -0x012f082b, -0x8d250000, -0xff098200, -0x25290008, -0x03c1200a, -0xaee40000, -0xff098200, -0xaee50000, -0xff098200, -0x02ee082b, -0x14200000, -0xff05080b, -0x26f70008, -0xff06000d, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff06000f, -0x8e8c0000, -0xff098200, -0x19a00000, -0xff05080d, -0x24150008, -0x02ed7021, -0x018e082b, -0x14200000, -0xff050807, -0x25b50008, -0xff060010, -0xd5200000, -0x25290008, -0xf6e00000, -0x012f082b, -0x14200000, -0xff050810, -0x26f70008, -0x10000000, -0xff05080d, -0x00000000, -0xff060011, -0x8e790000, -0xff098200, -0xae970000, -0xff098200, -0x02f0b823, -0xae900000, -0xff098200, -0x01308023, -0xafb20014, -0x000d28c2, -0x0320f809, -0x02802021, -0x02004821, -0x8e900000, -0xff098200, -0x0217b821, -0x02094821, -0x10000000, -0xff050810, -0xff000000, -0x260ffff8, -0xff000000, -0x01555021, -0xff000000, -0x8e120000, -0xff098200, -0x0217b821, -0x0140a821, -0xff06000b, -0x324c0000, -0xff090200, -0x15800000, -0xff05089c, -0x3a4d0000, -0xff090200, -0xff060017, -0x8e4bfffc, -0x260efff8, -0x2549fff8, -0x000b6142, -0x000b4542, -0x318c07f8, -0x310807f8, -0x01c87821, -0x11200000, -0xff050803, -0x01cc8023, -0xff06000c, -0xd6e00000, -0x26f70008, -0x2529fff8, -0xf5c00000, -0x15200000, -0xff05080c, -0x25ce0008, -0xff06000d, -0x25effff8, -0xff06000f, -0x01cf082b, -0x14200000, -0xff050806, -0x8e0d0000, -0xff098200, -0x8e4b0000, -0x26520004, -0x8dad0000, -0xff098200, -0x8db10000, -0xff098200, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff060010, -0xadde0000, -0xff098200, -0x10000000, -0xff05080f, -0x25ce0008, -0xff06009c, -0x31ae0000, -0xff090200, -0x15c00000, -0xff050818, -0x00000000, -0x020d8023, -0x10000000, -0xff05080b, -0x8e120000, -0xff098200, -0xff000000, -0x8e120000, -0xff098200, -0x0217b821, -0x0140a821, -0x324c0000, -0xff090200, -0x15800000, -0xff05089c, -0x3a4d0000, -0xff090200, -0x8e4bfffc, -0x260efff8, -0xff000000, -0xd6e00000, -0xff000000, -0x000b4542, -0x000bb942, -0x310807f8, -0x32f707f8, -0xff000000, -0xf5c00000, -0xff000000, -0x01d78023, -0xff06000f, -0x0148082b, -0x14200000, -0xff050806, -0x8e0d0000, -0xff098200, -0x8e4b0000, -0x26520004, -0x8dad0000, -0xff098200, -0x8db10000, -0xff098200, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff060010, -0x25ce0008, -0x254a0008, -0x10000000, -0xff05080f, -0xff000000, -0xadde0000, -0xff098200, -0xff000000, -0xadde0000, -0xff098200, -0xff000000, -0x00126842, -0x31ad007e, -0x01b36821, -0x95ae0000, -0xff098200, -0x25ce0000, -0xff098200, -0x05c00000, -0xff050890, -0xa5ae0000, -0xff098200, -0xff000000, -0x0217b821, -0xff000000, -0xd6e00000, -0xff098200, -0xd6e40000, -0xff098200, -0xd6e20000, -0xff098200, -0x8eef0000, -0xff098200, -0x46240000, -0xf6e00000, -0xff098200, -0xff000000, -0x8eed0000, -0xff098200, -0x8eef0000, -0xff098200, -0x8eee0000, -0xff098200, -0x2dad0000, -0xff098200, -0x2dec0000, -0xff098200, -0x2dce0000, -0xff098200, -0x01ac6824, -0x01ae6824, -0xd6e00000, -0xff098200, -0x11a00000, -0xff050842, -0xd6e20000, -0xff098200, -0xff000000, -0x000a5042, -0x3c0c0000, -0xff090200, -0xff000000, -0x4622003e, -0x4620113e, -0xf6e00000, -0xff098200, -0xff000000, -0x240d0001, -0x240e0001, -0x014c6021, -0x01e0782a, -0x00006801, -0x024c9021, -0x00047001, -0x964a0000, -0xff098200, -0x01cf680b, -0x15a00000, -0xff070800, -0x000a50c0, -0xff000000, -0x240d0001, -0x240e0001, -0x01e0782a, -0x00006801, -0x00047001, -0x01cf680b, -0x15a00000, -0xff070800, -0x00000000, -0xff000000, -0x014c6821, -0x01e0782a, -0x01a07021, -0xff000000, -0x00016801, -0x00057001, -0xff000000, -0x00006801, -0x00047001, -0xff000000, -0x01cf680b, -0x024d9021, -0xff000000, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x00126842, -0x31ad007e, -0x01b36821, -0x95ae0000, -0xff098200, -0x25ce0000, -0xff098200, -0x05c00000, -0xff050890, -0xa5ae0000, -0xff098200, -0xff000000, -0x0217b821, -0x8eed0000, -0xff098200, -0x11be0000, -0xff050801, -0x8eee0000, -0xff098200, -0xff000000, -0xaeed0000, -0xff098200, -0x10000000, -0xff070800, -0xaeee0000, -0xff098200, -0xff000000, -0x000a6042, -0x3c010000, -0xff090200, -0x01816021, -0x024c9021, -0xaeed0000, -0xff098200, -0xaeee0000, -0xff098200, -0xff000000, -0xff06000b, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x00126842, -0x31ad007e, -0x01b36821, -0x95ae0000, -0xff098200, -0x25ce0000, -0xff098200, -0x05c00000, -0xff050890, -0xa5ae0000, -0xff098200, -0xff000000, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x8e6d0000, -0xff098200, -0x000a5042, -0x24010000, -0x01aa6821, -0xae610000, -0xff098200, -0x8dae0000, -0xae700000, -0xff098200, -0xae740000, -0xff098200, -0x8dce0000, -0xff098200, -0x01c00008, -0x267e0000, -0xff098200, -0xff000000, -0x000a6042, -0x3c010000, -0xff090200, -0x01816021, -0x024c9021, -0x8e4b0000, -0x26520004, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x00126842, -0x31ad007e, -0x01b36821, -0x95ae0000, -0xff098200, -0x25ce0000, -0xff098200, -0x05c00000, -0xff050892, -0xa5ae0000, -0xff098200, -0xff000000, -0x8e8e0000, -0xff098200, -0x924d0000, -0xff098200, -0x8e510000, -0xff098200, -0x01d7082b, -0x14200000, -0xff050820, -0x000d68c0, -0xff000000, -0x8e4b0000, -0x26520004, -0xff000000, -0xff06000c, -0x012d082b, -0x14200000, -0xff050803, -0x02090821, -0xff000000, -0x000b5402, -0x10000000, -0xff070800, -0x000a50c0, -0xff000000, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0xff06000d, -0xac3e0000, -0xff098200, -0x10000000, -0xff05080c, -0x25290008, -0xff000000, -0xf0f0f0f0, -0xff000000, -0x02096821, -0x8e8e0000, -0xff098200, -0x02e96021, -0xada80000, -0xff098200, -0x252f0000, -0xff098200, -0x018e082b, -0x8e510000, -0xff098200, -0x10200000, -0xff050820, -0xadaf0000, -0xff098200, -0x924e0000, -0xff098200, -0x0200b821, -0x01a04821, -0x8e4b0000, -0x26520004, -0x11c00000, -0xff050803, -0x25b00008, -0xff06000b, -0x8eec0000, -0xff098200, -0x8eef0000, -0xff098200, -0x02e9082b, -0x01802021, -0x03c1600a, -0x03c1200b, -0xadaf0000, -0xff098200, -0x25ceffff, -0xadac0000, -0xff098200, -0x25ad0008, -0xaee40000, -0xff098200, -0x15c00000, -0xff05080b, -0x26f70008, -0xff06000d, -0x316d00ff, -0x000d6880, -0x026d6021, -0x000b5402, -0x8d810000, -0x000bb942, -0x000a50c0, -0x00200008, -0x32f707f8, -0xff000000, -0x8d190000, -0xff098200, -0xff000000, -0x8e790000, -0xff098200, -0xff000000, -0x02e96821, -0x8e8e0000, -0xff098200, -0x02094821, -0xae900000, -0xff098200, -0x01cd082b, -0xae890000, -0xff098200, -0x240c0000, -0xff098200, -0xff000000, -0x8d050000, -0xff098200, -0xff000000, -0x14200000, -0xff05081f, -0x02802021, -0x0320f809, -0xae6c0000, -0xff098200, -0x8e900000, -0xff098200, -0x000250c0, -0x8e8d0000, -0xff098200, -0x240c0000, -0xff098200, -0x8e120000, -0xff098200, -0x01aab823, -0x10000000, -0xff050816, -0xae6c0000, -0xff098200, -0xff000000, -0xff010000 -}; - -enum { - GLOB_vm_returnp, - GLOB_cont_dispatch, - GLOB_vm_returnc, - GLOB_BC_RET_Z, - GLOB_vm_return, - GLOB_vm_leave_cp, - GLOB_vm_leave_unw, - GLOB_vm_unwind_c, - GLOB_vm_unwind_c_eh, - GLOB_vm_unwind_ff, - GLOB_vm_unwind_ff_eh, - GLOB_vm_growstack_c, - GLOB_vm_growstack_l, - GLOB_vm_resume, - GLOB_vm_pcall, - GLOB_vm_call, - GLOB_vm_call_dispatch, - GLOB_vmeta_call, - GLOB_vm_call_dispatch_f, - GLOB_vm_cpcall, - GLOB_cont_ffi_callback, - GLOB_vm_call_tail, - GLOB_cont_cat, - GLOB_BC_CAT_Z, - GLOB_cont_nop, - GLOB_vmeta_tgets1, - GLOB_vmeta_tgets, - GLOB_vmeta_tgetb, - GLOB_vmeta_tgetv, - GLOB_vmeta_tsets1, - GLOB_vmeta_tsets, - GLOB_vmeta_tsetb, - GLOB_vmeta_tsetv, - GLOB_vmeta_comp, - GLOB_vmeta_binop, - GLOB_cont_ra, - GLOB_cont_condt, - GLOB_cont_condf, - GLOB_vmeta_equal, - GLOB_vmeta_equal_cd, - GLOB_vmeta_unm, - GLOB_vmeta_arith, - GLOB_vmeta_len, - GLOB_BC_LEN_Z, - GLOB_vmeta_callt, - GLOB_BC_CALLT_Z, - GLOB_vmeta_for, - GLOB_ff_assert, - GLOB_fff_fallback, - GLOB_fff_res, - GLOB_ff_type, - GLOB_fff_resn, - GLOB_ff_getmetatable, - GLOB_fff_restv, - GLOB_ff_setmetatable, - GLOB_ff_rawget, - GLOB_ff_tonumber, - GLOB_ff_tostring, - GLOB_fff_gcstep, - GLOB_ff_next, - GLOB_ff_pairs, - GLOB_ff_ipairs_aux, - GLOB_ff_ipairs, - GLOB_ff_pcall, - GLOB_ff_xpcall, - GLOB_ff_coroutine_resume, - GLOB_ff_coroutine_wrap_aux, - GLOB_ff_coroutine_yield, - GLOB_ff_math_abs, - GLOB_fff_res1, - GLOB_ff_math_floor, - GLOB_vm_floor, - GLOB_ff_math_ceil, - GLOB_vm_ceil, - GLOB_ff_math_log, - GLOB_ff_math_log10, - GLOB_ff_math_exp, - GLOB_ff_math_sin, - GLOB_ff_math_cos, - GLOB_ff_math_tan, - GLOB_ff_math_asin, - GLOB_ff_math_acos, - GLOB_ff_math_atan, - GLOB_ff_math_sinh, - GLOB_ff_math_cosh, - GLOB_ff_math_tanh, - GLOB_ff_math_pow, - GLOB_ff_math_atan2, - GLOB_ff_math_fmod, - GLOB_ff_math_sqrt, - GLOB_ff_math_deg, - GLOB_ff_math_rad, - GLOB_ff_math_ldexp, - GLOB_ff_math_frexp, - GLOB_ff_math_modf, - GLOB_ff_math_min, - GLOB_ff_math_max, - GLOB_ff_string_len, - GLOB_fff_resi, - GLOB_ff_string_byte, - GLOB_ff_string_char, - GLOB_fff_newstr, - GLOB_ff_string_sub, - GLOB_fff_emptystr, - GLOB_ff_string_rep, - GLOB_ff_string_reverse, - GLOB_ff_string_lower, - GLOB_ff_string_upper, - GLOB_ff_table_getn, - GLOB_ff_bit_band, - GLOB_ff_bit_bor, - GLOB_ff_bit_bxor, - GLOB_ff_bit_bswap, - GLOB_ff_bit_bnot, - GLOB_ff_bit_lshift, - GLOB_ff_bit_rshift, - GLOB_ff_bit_arshift, - GLOB_ff_bit_rol, - GLOB_ff_bit_ror, - GLOB_ff_bit_tobit, - GLOB_vm_record, - GLOB_vm_rethook, - GLOB_vm_inshook, - GLOB_cont_hook, - GLOB_vm_hotloop, - GLOB_vm_callhook, - GLOB_vm_hotcall, - GLOB_vm_exit_handler, - GLOB_vm_exit_interp, - GLOB_vm_trunc, - GLOB_vm_ffi_callback, - GLOB_vm_ffi_call, - GLOB_BC_MODVN_Z, - GLOB_BC_TGETS_Z, - GLOB_BC_TSETS_Z, - GLOB_BC_CALL_Z, - GLOB_BC_RETV_Z, - GLOB__MAX -}; -static const char *const globnames[] = { - "vm_returnp", - "cont_dispatch", - "vm_returnc", - "BC_RET_Z", - "vm_return", - "vm_leave_cp", - "vm_leave_unw", - "vm_unwind_c", - "vm_unwind_c_eh", - "vm_unwind_ff", - "vm_unwind_ff_eh", - "vm_growstack_c", - "vm_growstack_l", - "vm_resume", - "vm_pcall", - "vm_call", - "vm_call_dispatch", - "vmeta_call", - "vm_call_dispatch_f", - "vm_cpcall", - "cont_ffi_callback", - "vm_call_tail", - "cont_cat", - "BC_CAT_Z", - "cont_nop", - "vmeta_tgets1", - "vmeta_tgets", - "vmeta_tgetb", - "vmeta_tgetv", - "vmeta_tsets1", - "vmeta_tsets", - "vmeta_tsetb", - "vmeta_tsetv", - "vmeta_comp", - "vmeta_binop", - "cont_ra", - "cont_condt", - "cont_condf", - "vmeta_equal", - "vmeta_equal_cd", - "vmeta_unm", - "vmeta_arith", - "vmeta_len", - "BC_LEN_Z", - "vmeta_callt", - "BC_CALLT_Z", - "vmeta_for", - "ff_assert", - "fff_fallback", - "fff_res", - "ff_type", - "fff_resn", - "ff_getmetatable", - "fff_restv", - "ff_setmetatable", - "ff_rawget", - "ff_tonumber", - "ff_tostring", - "fff_gcstep", - "ff_next", - "ff_pairs", - "ff_ipairs_aux", - "ff_ipairs", - "ff_pcall", - "ff_xpcall", - "ff_coroutine_resume", - "ff_coroutine_wrap_aux", - "ff_coroutine_yield", - "ff_math_abs", - "fff_res1", - "ff_math_floor", - "vm_floor", - "ff_math_ceil", - "vm_ceil", - "ff_math_log", - "ff_math_log10", - "ff_math_exp", - "ff_math_sin", - "ff_math_cos", - "ff_math_tan", - "ff_math_asin", - "ff_math_acos", - "ff_math_atan", - "ff_math_sinh", - "ff_math_cosh", - "ff_math_tanh", - "ff_math_pow", - "ff_math_atan2", - "ff_math_fmod", - "ff_math_sqrt", - "ff_math_deg", - "ff_math_rad", - "ff_math_ldexp", - "ff_math_frexp", - "ff_math_modf", - "ff_math_min", - "ff_math_max", - "ff_string_len", - "fff_resi", - "ff_string_byte", - "ff_string_char", - "fff_newstr", - "ff_string_sub", - "fff_emptystr", - "ff_string_rep", - "ff_string_reverse", - "ff_string_lower", - "ff_string_upper", - "ff_table_getn", - "ff_bit_band", - "ff_bit_bor", - "ff_bit_bxor", - "ff_bit_bswap", - "ff_bit_bnot", - "ff_bit_lshift", - "ff_bit_rshift", - "ff_bit_arshift", - "ff_bit_rol", - "ff_bit_ror", - "ff_bit_tobit", - "vm_record", - "vm_rethook", - "vm_inshook", - "cont_hook", - "vm_hotloop", - "vm_callhook", - "vm_hotcall", - "vm_exit_handler", - "vm_exit_interp", - "vm_trunc", - "vm_ffi_callback", - "vm_ffi_call", - "BC_MODVN_Z", - "BC_TGETS_Z", - "BC_TSETS_Z", - "BC_CALL_Z", - "BC_RETV_Z", - (const char *)0 -}; -static const char *const extnames[] = { - (const char *)0 -}; -#define Dt1(_V) (int)(ptrdiff_t)&(((lua_State *)0)_V) -#define Dt2(_V) (int)(ptrdiff_t)&(((global_State *)0)_V) -#define Dt3(_V) (int)(ptrdiff_t)&(((TValue *)0)_V) -#define Dt4(_V) (int)(ptrdiff_t)&(((GCobj *)0)_V) -#define Dt5(_V) (int)(ptrdiff_t)&(((GCstr *)0)_V) -#define Dt6(_V) (int)(ptrdiff_t)&(((GCtab *)0)_V) -#define Dt7(_V) (int)(ptrdiff_t)&(((GCfuncL *)0)_V) -#define Dt8(_V) (int)(ptrdiff_t)&(((GCfuncC *)0)_V) -#define Dt9(_V) (int)(ptrdiff_t)&(((GCproto *)0)_V) -#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V) -#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V) -#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V) -#define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V) -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -#define GG_DISP2GOT (GG_OFS(got) - GG_OFS(dispatch)) -#define DISPATCH_GOT(name) (GG_DISP2GOT + 4*LJ_GOT_##name) -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx) -{ - dasm_put(Dst, 0); - dasm_put(Dst, 1, FRAME_P, LJ_TTRUE, LJ_ENDIAN_SELECT(-4,-8), LJ_ENDIAN_SELECT(-4,-8), FRAME_TYPE, FRAME_C, Dt1(->base), ~LJ_VMST_C, DISPATCH_GL(vmstate), Dt1(->top)); - dasm_put(Dst, 57, Dt1(->cframe), 72+9*4, 72+8*4, 24+5*8, 72+7*4, 72+6*4, 24+4*8, 72+5*4, 72+4*4, 24+3*8, 72+3*4, 72+2*4, 24+2*8, 72+1*4, 72+0*4, 24+1*8, 24+0*8, Dt1(->maxstack), LJ_ENDIAN_SELECT(4,0)); - dasm_put(Dst, 109, DISPATCH_GOT(lj_state_growstack), Dt1(->top), ~LJ_VMST_C, Dt1(->glref), Dt2(->vmstate), LJ_TNIL, Dt1(->base), Dt1(->glref), LJ_TFALSE, ~LJ_VMST_INTERP, LJ_ENDIAN_SELECT(-4,-8), GG_G2DISP, LJ_ENDIAN_SELECT(4,0)); - dasm_put(Dst, 172, DISPATCH_GL(vmstate), LUA_MINSTACK, Dt1(->base), Dt1(->top), DISPATCH_GOT(lj_state_growstack), Dt1(->base), Dt1(->top), LJ_ENDIAN_SELECT(-8,-4), Dt7(->pc), 72+9*4, 72+8*4, 24+5*8, 72+7*4, 72+6*4, 24+4*8, 72+5*4, 72+4*4); - dasm_put(Dst, 235, 24+3*8, 72+3*4, 72+2*4, 24+2*8, 72+1*4, 72+0*4, 24+1*8, 24+0*8, Dt1(->glref), Dt1(->status), FRAME_CP, CFRAME_RESUME, GG_G2DISP, Dt1(->cframe), Dt1(->base), Dt1(->top), LJ_ENDIAN_SELECT(-4,-8), Dt1(->status), ~LJ_VMST_INTERP, DISPATCH_GL(vmstate), FRAME_TYPE); - dasm_put(Dst, 296, LJ_TNIL, 72+9*4, 72+8*4, 24+5*8, 72+7*4, 72+6*4, 24+4*8, 72+5*4, 72+4*4, 24+3*8, 72+3*4, 72+2*4, 24+2*8, 72+1*4, 72+0*4, 24+1*8, 24+0*8, FRAME_CP, 72+9*4); - dasm_put(Dst, 345, 72+8*4, 24+5*8, 72+7*4, 72+6*4, 24+4*8, 72+5*4, 72+4*4, 24+3*8, 72+3*4, 72+2*4, 24+2*8, 72+1*4, 72+0*4, 24+1*8, 24+0*8, FRAME_C, Dt1(->cframe), Dt1(->cframe), Dt1(->glref), GG_G2DISP, Dt1(->base)); - dasm_put(Dst, 396, Dt1(->top), ~LJ_VMST_INTERP, LJ_TNIL, DISPATCH_GL(vmstate), LJ_ENDIAN_SELECT(-4,-8), LJ_TFUNC, LJ_ENDIAN_SELECT(-8,-4), LJ_ENDIAN_SELECT(-4,-8), Dt7(->pc), 72+9*4, 72+8*4, 24+5*8, 72+7*4, 72+6*4, 24+4*8, 72+5*4, 72+4*4, 24+3*8, 72+3*4); - dasm_put(Dst, 457, 72+2*4, 24+2*8, 72+1*4, 72+0*4, 24+1*8, 24+0*8, Dt1(->stack), Dt1(->top), Dt1(->cframe), Dt1(->cframe), Dt1(->glref), FRAME_CP, GG_G2DISP, -16+LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(-8,-4)); -#if LJ_HASFFI - dasm_put(Dst, 506); -#endif - dasm_put(Dst, 508, -16+LJ_ENDIAN_SELECT(4,0), Dt7(->pc)); -#if LJ_HASFFI - dasm_put(Dst, 514); -#endif - dasm_put(Dst, 517, -8+LJ_ENDIAN_SELECT(4,0), PC2PROTO(k)); -#if LJ_HASFFI - dasm_put(Dst, 523); -#endif - dasm_put(Dst, 531, Dt1(->base), DISPATCH_GL(tmptv), LJ_TSTR, LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0), DISPATCH_GL(tmptv), LJ_TTAB, LJ_ENDIAN_SELECT(0,4), DISPATCH_GL(tmptv2), LJ_ENDIAN_SELECT(4,0), LJ_TSTR, LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0), DISPATCH_GL(tmptv)); - dasm_put(Dst, 589, DISPATCH_GOT(lj_meta_tget), Dt1(->base), -FRAME_CONT, Dt1(->top), -16+LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(-8,-4), DISPATCH_GL(tmptv), LJ_TSTR, LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0), DISPATCH_GL(tmptv), LJ_TTAB, LJ_ENDIAN_SELECT(0,4), DISPATCH_GL(tmptv2), LJ_ENDIAN_SELECT(4,0), LJ_TSTR, LJ_ENDIAN_SELECT(0,4)); - dasm_put(Dst, 651, LJ_ENDIAN_SELECT(4,0), DISPATCH_GL(tmptv), DISPATCH_GOT(lj_meta_tset), Dt1(->base), -FRAME_CONT, Dt1(->top), -16+LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(-8,-4), DISPATCH_GOT(lj_meta_comp), Dt1(->base), LJ_ENDIAN_SELECT(2,0), (-(BCBIAS_J*4 >> 16) & 65535)); - dasm_put(Dst, 721, -4+LJ_ENDIAN_SELECT(1,2), LJ_ENDIAN_SELECT(4,0), LJ_TISTRUECOND, LJ_ENDIAN_SELECT(4,0), LJ_TISTRUECOND, DISPATCH_GOT(lj_meta_equal), Dt1(->base)); -#if LJ_HASFFI - dasm_put(Dst, 776, DISPATCH_GOT(lj_meta_equal_cd), Dt1(->base)); -#endif - dasm_put(Dst, 789, DISPATCH_GOT(lj_meta_arith), Dt1(->base), -16+LJ_ENDIAN_SELECT(4,0), FRAME_CONT); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 818); -#endif - dasm_put(Dst, 820, DISPATCH_GOT(lj_meta_len), Dt1(->base)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 828); -#else - dasm_put(Dst, 835); -#endif - dasm_put(Dst, 839, DISPATCH_GOT(lj_meta_call), Dt1(->base), LJ_ENDIAN_SELECT(-8,-4), LJ_ENDIAN_SELECT(-4,-8), Dt7(->pc), DISPATCH_GOT(lj_meta_call), Dt1(->base), LJ_ENDIAN_SELECT(-4,-8), LJ_ENDIAN_SELECT(-8,-4), DISPATCH_GOT(lj_meta_for), Dt1(->base)); -#if LJ_HASJIT - dasm_put(Dst, 896, BC_JFORI); -#endif - dasm_put(Dst, 900); -#if LJ_HASJIT - dasm_put(Dst, 904, BC_JFORI, BC_FORI); -#else - dasm_put(Dst, 911, BC_FORI); -#endif - dasm_put(Dst, 915, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TISTRUECOND, LJ_ENDIAN_SELECT(-4,-8), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM, Dt8(->upvalue), LJ_ENDIAN_SELECT(4,0)); - dasm_put(Dst, 970, LJ_ENDIAN_SELECT(0,4), LJ_TTAB, LJ_TUDATA, Dt6(->metatable), DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable]), LJ_TNIL, Dt6(->hmask), LJ_TTAB, Dt5(->hash), Dt6(->node), LJ_TSTR, offsetof(Node, key)+LJ_ENDIAN_SELECT(4,0), offsetof(Node, key)+LJ_ENDIAN_SELECT(0,4), DtB(->next), offsetof(Node, val)+LJ_ENDIAN_SELECT(4,0), offsetof(Node, val)+LJ_ENDIAN_SELECT(0,4)); - dasm_put(Dst, 1020, LJ_TISNUM, LJ_TISNUM, DISPATCH_GL(gcroot[GCROOT_BASEMT]), LJ_ENDIAN_SELECT(4,0), 8+LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), 8+LJ_ENDIAN_SELECT(0,4), LJ_TTAB, -LJ_TTAB, Dt6(->metatable), Dt6(->marked)); - dasm_put(Dst, 1075, LJ_GC_BLACK, Dt6(->metatable), DISPATCH_GL(gc.grayagain), ~LJ_GC_BLACK & 255, DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), DISPATCH_GOT(lj_tab_get), -LJ_TTAB, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM); - dasm_put(Dst, 1129, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TSTR, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM]), LJ_TISNUM, Dt1(->base), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), DISPATCH_GOT(lj_str_fromnum), LJ_TSTR, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TTAB, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(-4,-8), DISPATCH_GOT(lj_tab_next)); - dasm_put(Dst, 1184, Dt1(->base), Dt1(->top), LJ_TNIL, (2+1)*8, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TTAB, LJ_ENDIAN_SELECT(-4,-8)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1219, Dt6(->metatable), Dt8(->upvalue[0])); -#else - dasm_put(Dst, 1226, Dt8(->upvalue[0])); -#endif - dasm_put(Dst, 1229, 8+LJ_ENDIAN_SELECT(4,0), (3+1)*8, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), 8+LJ_ENDIAN_SELECT(4,0), -LJ_TTAB, LJ_TISNUM, LJ_ENDIAN_SELECT(-4,-8), Dt6(->asize), Dt6(->array), LJ_ENDIAN_SELECT(4,0), (0+1)*8, (2+1)*8, Dt6(->hmask)); - dasm_put(Dst, 1292, DISPATCH_GOT(lj_tab_getinth), (0+1)*8, (0+1)*8, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TTAB, LJ_ENDIAN_SELECT(-4,-8)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1323, Dt6(->metatable), Dt8(->upvalue[0])); -#else - dasm_put(Dst, 1330, Dt8(->upvalue[0])); -#endif - dasm_put(Dst, 1333, 8+LJ_ENDIAN_SELECT(4,0), 8+LJ_ENDIAN_SELECT(0,4), (3+1)*8, DISPATCH_GL(hookmask), HOOK_ACTIVE_SHIFT, 8+FRAME_PCALL, 8+LJ_ENDIAN_SELECT(4,0), DISPATCH_GL(hookmask), LJ_TFUNC, HOOK_ACTIVE_SHIFT, 16+FRAME_PCALL, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4)); - dasm_put(Dst, 1392, LJ_TTHREAD, Dt1(->status), Dt1(->cframe), Dt1(->top), Dt1(->base), -LUA_YIELD, Dt1(->maxstack), LJ_ENDIAN_SELECT(-4,-8), Dt1(->base), Dt1(->top), Dt1(->top)); - dasm_put(Dst, 1451, Dt1(->base), LUA_YIELD+1, Dt1(->top), ~LJ_VMST_INTERP, Dt1(->base), DISPATCH_GL(vmstate), Dt1(->maxstack), Dt1(->top), FRAME_TYPE, LJ_TTRUE, -8+LJ_ENDIAN_SELECT(4,0), LJ_TFALSE, Dt1(->top)); - dasm_put(Dst, 1511, (2+1)*8, -8+LJ_ENDIAN_SELECT(4,0), FRAME_TYPE, DISPATCH_GOT(lj_state_growstack), Dt8(->upvalue[0].gcr), Dt1(->status), Dt1(->cframe), Dt1(->top), Dt1(->base), -LUA_YIELD, Dt1(->maxstack), LJ_ENDIAN_SELECT(-4,-8), Dt1(->base), Dt1(->top)); - dasm_put(Dst, 1566, Dt1(->top), Dt1(->base), LUA_YIELD+1, Dt1(->top), ~LJ_VMST_INTERP, Dt1(->base), DISPATCH_GL(vmstate), Dt1(->maxstack), Dt1(->top), FRAME_TYPE); - dasm_put(Dst, 1627, DISPATCH_GOT(lj_ffh_coroutine_wrap_err), DISPATCH_GOT(lj_state_growstack), Dt1(->cframe), Dt1(->base), CFRAME_RESUME, Dt1(->top), LUA_YIELD, Dt1(->cframe), Dt1(->status), LJ_ENDIAN_SELECT(4,0), LJ_TISNUM); - dasm_put(Dst, 1682, LJ_ENDIAN_SELECT(-4,-8), LJ_ENDIAN_SELECT(-4,-8), -8+LJ_ENDIAN_SELECT(4,0), -8+LJ_ENDIAN_SELECT(0,4), (1+1)*8, FRAME_TYPE, -8+LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(4,0), LJ_TISNUM); - dasm_put(Dst, 1750, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(log), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(log10), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0)); - dasm_put(Dst, 1806, DISPATCH_GOT(exp), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(sin), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(cos), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(tan)); - dasm_put(Dst, 1862, LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(asin), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(acos), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(atan), LJ_TISNUM); - dasm_put(Dst, 1918, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(sinh), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(cosh), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(tanh), LJ_TISNUM); - dasm_put(Dst, 1977, LJ_ENDIAN_SELECT(4,0), 8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM, DISPATCH_GOT(pow), LJ_ENDIAN_SELECT(4,0), 8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM, DISPATCH_GOT(atan2), LJ_ENDIAN_SELECT(4,0), 8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM); - dasm_put(Dst, 2039, DISPATCH_GOT(fmod), LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, Dt8(->upvalue[0]), LJ_ENDIAN_SELECT(4,0), 8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM); - dasm_put(Dst, 2094, DISPATCH_GOT(ldexp), LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, DISPATCH_GOT(frexp), LJ_ENDIAN_SELECT(-4,-8), DISPATCH_GL(tmptv), DISPATCH_GL(tmptv), (2+1)*8, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, DISPATCH_GOT(modf), LJ_ENDIAN_SELECT(-4,-8), (2+1)*8); - dasm_put(Dst, 2158, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM); - dasm_put(Dst, 2217, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TSTR, Dt5(->len), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), -LJ_TSTR, Dt5(->len), Dt5([1]), LJ_ENDIAN_SELECT(-4,-8), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_ENDIAN_SELECT(4,0)); - dasm_put(Dst, 2276, LJ_TISNUM, DISPATCH_GOT(lj_str_new), Dt1(->base), Dt1(->base), LJ_TSTR, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), 16+LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), 8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM); - dasm_put(Dst, 2337, LJ_TSTR, Dt5(->len), sizeof(GCstr)-1, DISPATCH_GL(strempty), LJ_TSTR, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_ENDIAN_SELECT(4,0), 8+LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), -LJ_TSTR, LJ_TISNUM, Dt5(->len), DISPATCH_GL(tmpbuf.sz)); - dasm_put(Dst, 2407, DISPATCH_GL(tmpbuf.buf), Dt5([1]), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TSTR, DISPATCH_GL(tmpbuf.sz), Dt5(->len), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf)); - dasm_put(Dst, 2464, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TSTR, DISPATCH_GL(tmpbuf.sz), Dt5(->len), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 2527, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TSTR, DISPATCH_GL(tmpbuf.sz), Dt5(->len), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TTAB, DISPATCH_GOT(lj_tab_len), LJ_ENDIAN_SELECT(4,0)); - dasm_put(Dst, 2586, LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0)); - dasm_put(Dst, 2649, LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_ENDIAN_SELECT(4,0)); - dasm_put(Dst, 2719, 8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), 8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), 8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM, LJ_ENDIAN_SELECT(4,0)); - dasm_put(Dst, 2790, 8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), 8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, Dt8(->f)); - dasm_put(Dst, 2863, LJ_ENDIAN_SELECT(-4,-8), 8*LUA_MINSTACK, Dt1(->maxstack), Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top), LJ_ENDIAN_SELECT(-8,-4), Dt7(->pc), FRAME_TYPE, LJ_ENDIAN_SELECT(1,2), DISPATCH_GOT(lj_state_growstack), LUA_MINSTACK, Dt1(->base)); - dasm_put(Dst, 2932, DISPATCH_GOT(lj_gc_step), Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top), LJ_ENDIAN_SELECT(-8,-4)); -#if LJ_HASJIT - dasm_put(Dst, 2958, DISPATCH_GL(hookmask), HOOK_VMEVENT, DISPATCH_GL(hookcount), HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount)); -#endif - dasm_put(Dst, 2981, DISPATCH_GL(hookmask), HOOK_ACTIVE, GG_DISP2STATIC, DISPATCH_GL(hookmask), DISPATCH_GL(hookcount), HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount), LUA_MASKLINE, DISPATCH_GOT(lj_dispatch_ins), Dt1(->base), Dt1(->base)); - dasm_put(Dst, 3029, GG_DISP2STATIC, -24+LJ_ENDIAN_SELECT(0,4)); -#if LJ_HASJIT - dasm_put(Dst, 3048, LJ_ENDIAN_SELECT(-8,-4), GG_DISP2J, Dt7(->pc), DISPATCH_J(L), PC2PROTO(framesize), DISPATCH_GOT(lj_trace_hot), Dt1(->base), Dt1(->top)); -#endif - dasm_put(Dst, 3073); -#if LJ_HASJIT - dasm_put(Dst, 3075); -#endif - dasm_put(Dst, 3078); -#if LJ_HASJIT - dasm_put(Dst, 3081); -#endif - dasm_put(Dst, 3084, DISPATCH_GOT(lj_dispatch_call), Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top), LJ_ENDIAN_SELECT(-8,-4)); -#if LJ_HASJIT - dasm_put(Dst, 3108, -(16+32*8+32*4), 16+0*8, 16+32*8+0*4, 16+32*8+1*4, 16+2*8, 16+32*8+2*4, 16+32*8+3*4, 16+4*8, 16+32*8+4*4, 16+32*8+5*4, 16+6*8, 16+32*8+6*4, 16+32*8+7*4, 16+8*8, 16+32*8+8*4, 16+32*8+9*4, 16+10*8, 16+32*8+10*4, 16+32*8+11*4, 16+12*8, 16+32*8+12*4, 16+32*8+13*4, 16+14*8); - dasm_put(Dst, 3155, 16+32*8+14*4, 16+32*8+15*4, 16+16*8, 16+32*8+16*4, 16+32*8+17*4, 16+18*8, 16+32*8+18*4, 16+32*8+19*4, 16+20*8, 16+32*8+20*4, 16+32*8+21*4, 16+22*8, 16+32*8+22*4, 16+32*8+23*4, 16+24*8, 16+32*8+24*4, 16+32*8+25*4, 16+26*8, 16+32*8+26*4, 16+32*8+27*4, 16+28*8, 16+32*8+28*4, 16+30*8); - dasm_put(Dst, 3202, 16+32*8+30*4, 16+32*8+31*4, ~LJ_VMST_EXIT, 16+32*8+32*4, -GG_DISP2G-32768, DISPATCH_GL(vmstate), 16+32*8+29*4, DISPATCH_GL(jit_L), DISPATCH_GL(jit_base), DISPATCH_GOT(lj_trace_exit), DISPATCH_J(L), DISPATCH_J(parent), DISPATCH_J(exitno), GG_DISP2J, Dt1(->base), Dt1(->cframe), Dt1(->base)); -#endif - dasm_put(Dst, 3246); -#if LJ_HASJIT - dasm_put(Dst, 3248, -GG_DISP2G-32768, LJ_ENDIAN_SELECT(-8,-4), LJ_TNIL, Dt7(->pc), DISPATCH_GL(jit_L), PC2PROTO(k), DISPATCH_GL(vmstate), BC_FUNCF*4, DISPATCH_GOT(lj_err_throw)); -#endif - dasm_put(Dst, 3297); -#if LJ_HASJIT - dasm_put(Dst, 3345); -#endif - dasm_put(Dst, 3368); -#if LJ_HASFFI -#define DtE(_V) (int)(ptrdiff_t)&(((CTState *)0)_V) - dasm_put(Dst, 3370, 72+9*4, 72+8*4, 24+5*8, 72+7*4, 72+6*4, 24+4*8, 72+5*4, 72+4*4, 24+3*8, 72+3*4, 72+2*4, 24+2*8, 72+1*4, 72+0*4, 24+1*8, 24+0*8, Dt2(->ctype_state), GG_G2DISP, DISPATCH_GOT(lj_ccallback_enter), DtE(->cb.slot), DtE(->cb.gpr[0]), DtE(->cb.gpr[1]), DtE(->cb.fpr[0])); - dasm_put(Dst, 3418, DtE(->cb.gpr[2]), DtE(->cb.gpr[3]), DtE(->cb.fpr[1]), 112+16, DtE(->cb.stack), Dt1(->base), Dt1(->top), LJ_ENDIAN_SELECT(-8,-4), ~LJ_VMST_INTERP, LJ_TNIL, DISPATCH_GL(vmstate), Dt7(->pc)); -#endif - dasm_put(Dst, 3462); -#if LJ_HASFFI - dasm_put(Dst, 3464, DISPATCH_GOT(lj_ccallback_leave), DISPATCH_GL(ctype_state), Dt1(->base), Dt1(->top), DtE(->L), DtE(->cb.gpr[0]), DtE(->cb.fpr[0]), DtE(->cb.gpr[1]), DtE(->cb.fpr[1])); -#endif - dasm_put(Dst, 3488); -#if LJ_HASFFI -#define DtF(_V) (int)(ptrdiff_t)&(((CCallState *)0)_V) - dasm_put(Dst, 3490, DtF(->spadj), DtF(->nsp), offsetof(CCallState, stack), DtF(->func), DtF(->gpr[1]), DtF(->gpr[2]), DtF(->gpr[3]), DtF(->fpr[0]), DtF(->fpr[1]), DtF(->gpr[0]), DtF(->gpr[0]), DtF(->gpr[1]), DtF(->fpr[0]), DtF(->fpr[1])); -#endif -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop) -{ - int vk = 0; - dasm_put(Dst, 3546, defop); - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - dasm_put(Dst, 3548, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM, LJ_ENDIAN_SELECT(2,0), (-(BCBIAS_J*4 >> 16) & 65535)); - if (op == BC_ISLT || op == BC_ISGE) { - dasm_put(Dst, 3571); - } else { - dasm_put(Dst, 3573); - } - if (op == BC_ISLT || op == BC_ISLE) { - dasm_put(Dst, 3575); - } else { - dasm_put(Dst, 3577); - } - dasm_put(Dst, 3579); - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - dasm_put(Dst, 3593, LJ_ENDIAN_SELECT(4,0), -4+LJ_ENDIAN_SELECT(2,0), LJ_ENDIAN_SELECT(4,0), (-(BCBIAS_J*4 >> 16) & 65535), LJ_TISNUM, LJ_TISNUM); - if (vk) { - dasm_put(Dst, 3617); - } else { - dasm_put(Dst, 3619); - } - dasm_put(Dst, 3621, LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(0,4)); - if (LJ_HASFFI) { - dasm_put(Dst, 3640, LJ_TCDATA); - } - dasm_put(Dst, 3645, LJ_TISPRI); - if (LJ_HASFFI) { - dasm_put(Dst, 3648); - } - dasm_put(Dst, 3651, LJ_TISTABUD+1); - if (vk) { - dasm_put(Dst, 3662); - } else { - dasm_put(Dst, 3664); - } - dasm_put(Dst, 3666, Dt6(->metatable), Dt6(->nomm), 1<> 16) & 65535)); - if (vk) { - dasm_put(Dst, 3709); - } else { - dasm_put(Dst, 3711); - } - dasm_put(Dst, 3713); - break; - - case BC_ISEQN: case BC_ISNEN: - vk = op == BC_ISEQN; - dasm_put(Dst, 3726, LJ_ENDIAN_SELECT(4,0), -4+LJ_ENDIAN_SELECT(2,0), (-(BCBIAS_J*4 >> 16) & 65535), LJ_TISNUM); - if (LJ_HASFFI) { - dasm_put(Dst, 3741); - } else { - dasm_put(Dst, 3744); - } - dasm_put(Dst, 3747); - if (vk) { - dasm_put(Dst, 3750); - } else { - dasm_put(Dst, 3754); - } - dasm_put(Dst, 3758); - if (LJ_HASFFI) { - dasm_put(Dst, 3770, LJ_TCDATA); - } - break; - - case BC_ISEQP: case BC_ISNEP: - vk = op == BC_ISEQP; - dasm_put(Dst, 3780, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(2,0)); - if (LJ_HASFFI) { - dasm_put(Dst, 3789, LJ_TCDATA); - } - dasm_put(Dst, 3794, (-(BCBIAS_J*4 >> 16) & 65535)); - if (vk) { - dasm_put(Dst, 3800); - } else { - dasm_put(Dst, 3802); - } - dasm_put(Dst, 3804); - break; - - /* -- Unary test and copy ops ------------------------------------------- */ - - case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: - dasm_put(Dst, 3817, LJ_ENDIAN_SELECT(2,0), LJ_ENDIAN_SELECT(4,0)); - if (op == BC_IST || op == BC_ISF) { - dasm_put(Dst, 3824, LJ_TISTRUECOND, (-(BCBIAS_J*4 >> 16) & 65535)); - if (op == BC_IST) { - dasm_put(Dst, 3831); - } else { - dasm_put(Dst, 3833); - } - dasm_put(Dst, 3835); - } else { - dasm_put(Dst, 3837, LJ_TISTRUECOND); - if (op == BC_ISTC) { - dasm_put(Dst, 3841); - } else { - dasm_put(Dst, 3844); - } - dasm_put(Dst, 3847, (-(BCBIAS_J*4 >> 16) & 65535)); - } - dasm_put(Dst, 3856); - break; - - /* -- Unary ops --------------------------------------------------------- */ - - case BC_MOV: - dasm_put(Dst, 3868); - break; - case BC_NOT: - dasm_put(Dst, 3884, LJ_ENDIAN_SELECT(4,0), LJ_TFALSE, LJ_TISTRUECOND, LJ_TTRUE, LJ_ENDIAN_SELECT(4,0)); - break; - case BC_UNM: - dasm_put(Dst, 3908, LJ_ENDIAN_SELECT(4,0), LJ_TISNUM); - break; - case BC_LEN: - dasm_put(Dst, 3931, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TSTR, LJ_TTAB, Dt5(->len)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 3965, Dt6(->metatable)); -#endif - dasm_put(Dst, 3972, DISPATCH_GOT(lj_tab_len)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 3981, Dt6(->nomm), 1<base), DISPATCH_GOT(lj_meta_cat), Dt1(->base)); - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - dasm_put(Dst, 4377, LJ_TSTR, LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0)); - break; - case BC_KCDATA: -#if LJ_HASFFI - dasm_put(Dst, 4399, LJ_TCDATA, LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0)); -#endif - break; - case BC_KSHORT: - dasm_put(Dst, 4421); - break; - case BC_KNUM: - dasm_put(Dst, 4438); - break; - case BC_KPRI: - dasm_put(Dst, 4454, LJ_ENDIAN_SELECT(4,0)); - break; - case BC_KNIL: - dasm_put(Dst, 4471, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(4,0)); - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - dasm_put(Dst, 4495, LJ_ENDIAN_SELECT(-8,-4), Dt7(->uvptr), DtA(->v)); - break; - case BC_USETV: - dasm_put(Dst, 4518, LJ_ENDIAN_SELECT(-8,-4), Dt7(->uvptr), DtA(->marked), DtA(->v), LJ_GC_BLACK, DtA(->closed), LJ_ENDIAN_SELECT(4,0), LJ_GC_BLACK|1, -(LJ_TISNUM+1), LJ_TISGCV - (LJ_TISNUM+1), LJ_ENDIAN_SELECT(0,4), Dt4(->gch.marked), LJ_GC_WHITES, DISPATCH_GOT(lj_gc_barrieruv), GG_DISP2G); - break; - case BC_USETS: - dasm_put(Dst, 4578, LJ_ENDIAN_SELECT(-8,-4), Dt7(->uvptr), DtA(->marked), DtA(->v), Dt5(->marked), LJ_GC_BLACK, DtA(->closed), LJ_TSTR, LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0), LJ_GC_WHITES, DISPATCH_GOT(lj_gc_barrieruv), GG_DISP2G); - break; - case BC_USETN: - dasm_put(Dst, 4633, LJ_ENDIAN_SELECT(-8,-4), Dt7(->uvptr), DtA(->v)); - break; - case BC_USETP: - dasm_put(Dst, 4656, LJ_ENDIAN_SELECT(-8,-4), Dt7(->uvptr), DtA(->v), LJ_ENDIAN_SELECT(4,0)); - break; - - case BC_UCLO: - dasm_put(Dst, 4680, Dt1(->openupval), (-(BCBIAS_J*4 >> 16) & 65535), DISPATCH_GOT(lj_func_closeuv), Dt1(->base), Dt1(->base)); - break; - - case BC_FNEW: - dasm_put(Dst, 4711, DISPATCH_GOT(lj_func_newL_gc), LJ_ENDIAN_SELECT(-8,-4), Dt1(->base), Dt1(->base), LJ_TFUNC, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4)); - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - case BC_TDUP: - dasm_put(Dst, 4744, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base)); - if (op == BC_TNEW) { - dasm_put(Dst, 4756, DISPATCH_GOT(lj_tab_new)); - } else { - dasm_put(Dst, 4767, DISPATCH_GOT(lj_tab_dup)); - } - dasm_put(Dst, 4775, Dt1(->base), LJ_TTAB, LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0), DISPATCH_GOT(lj_gc_step_fixtop)); - break; - - case BC_GGET: - case BC_GSET: - dasm_put(Dst, 4805, LJ_ENDIAN_SELECT(-8,-4), Dt7(->env)); - if (op == BC_GGET) { - dasm_put(Dst, 4813); - } else { - dasm_put(Dst, 4816); - } - dasm_put(Dst, 4819); - break; - - case BC_TGETV: - dasm_put(Dst, 4821, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_TTAB, LJ_TISNUM, LJ_TSTR, Dt6(->asize), Dt6(->array), LJ_ENDIAN_SELECT(4,0), Dt6(->metatable), Dt6(->nomm), 1<hmask), Dt5(->hash), Dt6(->node), offsetof(Node, key)+LJ_ENDIAN_SELECT(4,0), offsetof(Node, key)+LJ_ENDIAN_SELECT(0,4), DtB(->next), offsetof(Node, val)+LJ_ENDIAN_SELECT(4,0), -LJ_TSTR, Dt6(->metatable), offsetof(Node, val)+LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4)); - dasm_put(Dst, 4971, LJ_TNIL, Dt6(->nomm), 1<asize), Dt6(->array), LJ_ENDIAN_SELECT(4,0), Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), Dt6(->marked), LJ_ENDIAN_SELECT(4,0), LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<marked), Dt6(->gclist)); - break; - case BC_TSETS: - dasm_put(Dst, 5146, LJ_ENDIAN_SELECT(4,0), LJ_TTAB, LJ_ENDIAN_SELECT(0,4), Dt6(->hmask), Dt5(->hash), Dt6(->node), Dt6(->nomm), offsetof(Node, key)+LJ_ENDIAN_SELECT(4,0), offsetof(Node, key)+LJ_ENDIAN_SELECT(0,4), LJ_TSTR, DtB(->next), offsetof(Node, val)+LJ_ENDIAN_SELECT(4,0), Dt6(->marked), Dt6(->metatable), LJ_GC_BLACK); - dasm_put(Dst, 5204, DtB(->val), Dt6(->nomm), 1<metatable), DISPATCH_GL(tmptv), Dt6(->nomm), 1<base), Dt1(->base)); - dasm_put(Dst, 5266, DISPATCH_GL(gc.grayagain), ~LJ_GC_BLACK & 255, DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist)); - break; - case BC_TSETB: - dasm_put(Dst, 5283, LJ_ENDIAN_SELECT(4,0), LJ_TTAB, LJ_ENDIAN_SELECT(0,4), Dt6(->asize), Dt6(->array), LJ_ENDIAN_SELECT(4,0), Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<marked), Dt6(->gclist)); - break; - - case BC_TSETM: - dasm_put(Dst, 5361, -8+LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(0,4), Dt6(->asize), Dt6(->marked), Dt6(->array), LJ_GC_BLACK, DISPATCH_GOT(lj_tab_reasize), Dt1(->base), Dt1(->base), DISPATCH_GL(gc.grayagain), ~LJ_GC_BLACK & 255, DISPATCH_GL(gc.grayagain), Dt6(->marked)); - dasm_put(Dst, 5434, Dt6(->gclist)); - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALLM: - dasm_put(Dst, 5439); - break; - case BC_CALL: - dasm_put(Dst, 5444, LJ_TFUNC, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(-4,-8), Dt7(->pc)); - break; - - case BC_CALLMT: - dasm_put(Dst, 5473); - break; - case BC_CALLT: - dasm_put(Dst, 5475, LJ_TFUNC, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(-4,-8), FRAME_TYPE, Dt7(->ffid), FRAME_VARG, LJ_ENDIAN_SELECT(-8,-4), Dt7(->pc), -8+LJ_ENDIAN_SELECT(-8,-4), Dt7(->pc)); - dasm_put(Dst, 5544, PC2PROTO(k), FRAME_TYPEP, LJ_ENDIAN_SELECT(-4,-8), FRAME_TYPE); - break; - - case BC_ITERC: - dasm_put(Dst, 5560, LJ_TFUNC, -24+LJ_ENDIAN_SELECT(4,0), -24+LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(-4,-8), Dt7(->pc)); - break; - - case BC_ITERN: -#if LJ_HASJIT -#endif - dasm_put(Dst, 5595, -16+LJ_ENDIAN_SELECT(0,4), -8+LJ_ENDIAN_SELECT(0,4), Dt6(->asize), Dt6(->array), LJ_ENDIAN_SELECT(4,0), -4+LJ_ENDIAN_SELECT(2,0), (-(BCBIAS_J*4 >> 16) & 65535), -8+LJ_ENDIAN_SELECT(0,4), Dt6(->hmask), Dt6(->node), LJ_ENDIAN_SELECT(4,0), -4+LJ_ENDIAN_SELECT(2,0), DtB(->key), (-(BCBIAS_J*4 >> 16) & 65535)); - dasm_put(Dst, 5677, -8+LJ_ENDIAN_SELECT(0,4)); - break; - - case BC_ISNEXT: - dasm_put(Dst, 5680, -24+LJ_ENDIAN_SELECT(4,0), -24+LJ_ENDIAN_SELECT(0,4), -16+LJ_ENDIAN_SELECT(4,0), -8+LJ_ENDIAN_SELECT(4,0), LJ_TFUNC, -LJ_TTAB, Dt8(->ffid), -LJ_TNIL, -FF_next_N, (-(BCBIAS_J*4 >> 16) & 65535), -8+LJ_ENDIAN_SELECT(0,4), BC_JMP, BC_ITERC, -4+LJ_ENDIAN_SELECT(0,3), LJ_ENDIAN_SELECT(0,3)); - break; - - case BC_VARG: - dasm_put(Dst, 5737, LJ_ENDIAN_SELECT(-4,-8), FRAME_VARG, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), Dt1(->maxstack), DISPATCH_GOT(lj_state_growstack), Dt1(->top), Dt1(->base), Dt1(->base)); - dasm_put(Dst, 5824); - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - dasm_put(Dst, 5826); - break; - - case BC_RET: - dasm_put(Dst, 5828, LJ_ENDIAN_SELECT(-4,-8), FRAME_TYPE, FRAME_VARG, LJ_ENDIAN_SELECT(-8,-4), Dt7(->pc), PC2PROTO(k), LJ_ENDIAN_SELECT(4,0), FRAME_TYPEP, LJ_ENDIAN_SELECT(-4,-8)); - break; - - case BC_RET0: case BC_RET1: - dasm_put(Dst, 5900, LJ_ENDIAN_SELECT(-4,-8), FRAME_TYPE, FRAME_VARG); - if (op == BC_RET1) { - dasm_put(Dst, 5913); - } - dasm_put(Dst, 5915); - if (op == BC_RET1) { - dasm_put(Dst, 5920); - } - dasm_put(Dst, 5922, LJ_ENDIAN_SELECT(-8,-4), Dt7(->pc), PC2PROTO(k)); - if (op == BC_RET1) { - dasm_put(Dst, 5950, LJ_ENDIAN_SELECT(4,0)); - } else { - dasm_put(Dst, 5953, -8+LJ_ENDIAN_SELECT(4,0)); - } - break; - - /* -- Loops and branches ------------------------------------------------ */ - - case BC_FORL: -#if LJ_HASJIT - dasm_put(Dst, 5956, GG_DISP2HOT, -HOTCOUNT_LOOP, GG_DISP2HOT); -#endif - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - vk = (op == BC_IFORL || op == BC_JFORL); - dasm_put(Dst, 5968); - if (vk) { - dasm_put(Dst, 5970, FORL_IDX*8, FORL_STEP*8, FORL_STOP*8, FORL_STEP*8+LJ_ENDIAN_SELECT(4,0), FORL_IDX*8); - } else { - dasm_put(Dst, 5982, FORL_IDX*8+LJ_ENDIAN_SELECT(4,0), FORL_STEP*8+LJ_ENDIAN_SELECT(4,0), FORL_STOP*8+LJ_ENDIAN_SELECT(4,0), LJ_TISNUM, LJ_TISNUM, LJ_TISNUM, FORL_IDX*8, FORL_STOP*8); - } - if (op != BC_JFORL) { - dasm_put(Dst, 6003, (-(BCBIAS_J*4 >> 16) & 65535)); - } - dasm_put(Dst, 6007, FORL_EXT*8); - if (op == BC_JFORI) { - dasm_put(Dst, 6012, -4+LJ_ENDIAN_SELECT(2,0), BC_JLOOP); - } else if (op == BC_JFORL) { - dasm_put(Dst, 6026, BC_JLOOP); - } else { - dasm_put(Dst, 6036); - if (op == BC_FORI) { - dasm_put(Dst, 6040); - } else { - dasm_put(Dst, 6043); - } - dasm_put(Dst, 6046); - } - dasm_put(Dst, 6049); - break; - - case BC_ITERL: -#if LJ_HASJIT - dasm_put(Dst, 6061, GG_DISP2HOT, -HOTCOUNT_LOOP, GG_DISP2HOT); -#endif - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - dasm_put(Dst, 6073, LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4)); - if (op == BC_JITERL) { - dasm_put(Dst, 6081, -8+LJ_ENDIAN_SELECT(4,0), BC_JLOOP, -8+LJ_ENDIAN_SELECT(0,4)); - } else { - dasm_put(Dst, 6088, (-(BCBIAS_J*4 >> 16) & 65535), -8+LJ_ENDIAN_SELECT(4,0), -8+LJ_ENDIAN_SELECT(0,4)); - } - dasm_put(Dst, 6098); - break; - - case BC_LOOP: -#if LJ_HASJIT - dasm_put(Dst, 6111, GG_DISP2HOT, -HOTCOUNT_LOOP, GG_DISP2HOT); -#endif - break; - - case BC_ILOOP: - dasm_put(Dst, 6123); - break; - - case BC_JLOOP: -#if LJ_HASJIT - dasm_put(Dst, 6135, DISPATCH_J(trace), DISPATCH_GL(vmstate), DISPATCH_GL(jit_base), DISPATCH_GL(jit_L), DtD(->mcode), GG_DISP2G+32768); -#endif - break; - - case BC_JMP: - dasm_put(Dst, 6153, (-(BCBIAS_J*4 >> 16) & 65535)); - break; - - /* -- Function headers -------------------------------------------------- */ - - case BC_FUNCF: -#if LJ_HASJIT - dasm_put(Dst, 6170, GG_DISP2HOT, -HOTCOUNT_CALL, GG_DISP2HOT); -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - dasm_put(Dst, 6182, Dt1(->maxstack), -4+PC2PROTO(numparams), -4+PC2PROTO(k)); - if (op != BC_JFUNCF) { - dasm_put(Dst, 6193); - } - dasm_put(Dst, 6196); - if (op == BC_JFUNCF) { - dasm_put(Dst, 6202, BC_JLOOP); - } else { - dasm_put(Dst, 6207); - } - dasm_put(Dst, 6217, LJ_ENDIAN_SELECT(4,0)); - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - dasm_put(Dst, 6224); - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - dasm_put(Dst, 6226, Dt1(->maxstack), LJ_ENDIAN_SELECT(0,4), 8+FRAME_VARG, -4+PC2PROTO(k), LJ_ENDIAN_SELECT(4,0), -4+PC2PROTO(numparams), LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(0,4), 8+LJ_ENDIAN_SELECT(0,4), 8+LJ_ENDIAN_SELECT(4,0), LJ_ENDIAN_SELECT(4,0)); - break; - - case BC_FUNCC: - case BC_FUNCCW: - if (op == BC_FUNCC) { - dasm_put(Dst, 6281, Dt8(->f)); - } else { - dasm_put(Dst, 6284, DISPATCH_GL(wrapf)); - } - dasm_put(Dst, 6287, Dt1(->maxstack), Dt1(->base), Dt1(->top), ~LJ_VMST_C); - if (op == BC_FUNCCW) { - dasm_put(Dst, 6299, Dt8(->f)); - } - dasm_put(Dst, 6302, DISPATCH_GL(vmstate), Dt1(->base), Dt1(->top), ~LJ_VMST_INTERP, LJ_ENDIAN_SELECT(-4,-8), DISPATCH_GL(vmstate)); - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx); - - dasm_put(Dst, 6323); - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); - int i; - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.4byte .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.4byte 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 31\n" - "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.4byte .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.4byte .Lframe0\n" - "\t.4byte .Lbegin\n" - "\t.4byte %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x9f\n\t.sleb128 1\n" - "\t.byte 0x9e\n\t.sleb128 2\n", - fcofs, CFRAME_SIZE); - for (i = 23; i >= 16; i--) - fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 26-i); - for (i = 30; i >= 20; i -= 2) - fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+32+i, 42-i); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE0:\n\n"); -#if LJ_HASFFI - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.4byte .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.4byte .Lframe0\n" - "\t.4byte lj_vm_ffi_call\n" - "\t.4byte %d\n" - "\t.byte 0x9f\n\t.uleb128 1\n" - "\t.byte 0x90\n\t.uleb128 2\n" - "\t.byte 0xd\n\t.uleb128 0x10\n" - "\t.align 2\n" - ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); -#endif - fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n"); - fprintf(ctx->fp, - "\t.globl lj_err_unwind_dwarf\n" - ".Lframe1:\n" - "\t.4byte .LECIE1-.LSCIE1\n" - ".LSCIE1:\n" - "\t.4byte 0\n" - "\t.byte 0x1\n" - "\t.string \"zPR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 31\n" - "\t.uleb128 6\n" /* augmentation length */ - "\t.byte 0\n" - "\t.4byte lj_err_unwind_dwarf\n" - "\t.byte 0\n" - "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE1:\n\n"); - fprintf(ctx->fp, - ".LSFDE2:\n" - "\t.4byte .LEFDE2-.LASFDE2\n" - ".LASFDE2:\n" - "\t.4byte .LASFDE2-.Lframe1\n" - "\t.4byte .Lbegin\n" - "\t.4byte %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x9f\n\t.sleb128 1\n" - "\t.byte 0x9e\n\t.sleb128 2\n", - fcofs, CFRAME_SIZE); - for (i = 23; i >= 16; i--) - fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 26-i); - for (i = 30; i >= 20; i -= 2) - fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+32+i, 42-i); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE2:\n\n"); -#if LJ_HASFFI - fprintf(ctx->fp, - ".Lframe2:\n" - "\t.4byte .LECIE2-.LSCIE2\n" - ".LSCIE2:\n" - "\t.4byte 0\n" - "\t.byte 0x1\n" - "\t.string \"zR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 31\n" - "\t.uleb128 1\n" /* augmentation length */ - "\t.byte 0\n" - "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE2:\n\n"); - fprintf(ctx->fp, - ".LSFDE3:\n" - "\t.4byte .LEFDE3-.LASFDE3\n" - ".LASFDE3:\n" - "\t.4byte .LASFDE3-.Lframe2\n" - "\t.4byte lj_vm_ffi_call\n" - "\t.4byte %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0x9f\n\t.uleb128 1\n" - "\t.byte 0x90\n\t.uleb128 2\n" - "\t.byte 0xd\n\t.uleb128 0x10\n" - "\t.align 2\n" - ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); -#endif - break; - default: - break; - } -} - diff --git a/src/buildvm_peobj.c b/src/buildvm_peobj.c deleted file mode 100644 index 17b3293a..00000000 --- a/src/buildvm_peobj.c +++ /dev/null @@ -1,352 +0,0 @@ -/* -** LuaJIT VM builder: PE object emitter. -** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -** -** Only used for building on Windows, since we cannot assume the presence -** of a suitable assembler. The host and target byte order must match. -*/ - -#include "buildvm.h" -#include "lj_bc.h" - -#if LJ_TARGET_X86ORX64 - -/* Context for PE object emitter. */ -static char *strtab; -static size_t strtabofs; - -/* -- PE object definitions ----------------------------------------------- */ - -/* PE header. */ -typedef struct PEheader { - uint16_t arch; - uint16_t nsects; - uint32_t time; - uint32_t symtabofs; - uint32_t nsyms; - uint16_t opthdrsz; - uint16_t flags; -} PEheader; - -/* PE section. */ -typedef struct PEsection { - char name[8]; - uint32_t vsize; - uint32_t vaddr; - uint32_t size; - uint32_t ofs; - uint32_t relocofs; - uint32_t lineofs; - uint16_t nreloc; - uint16_t nline; - uint32_t flags; -} PEsection; - -/* PE relocation. */ -typedef struct PEreloc { - uint32_t vaddr; - uint32_t symidx; - uint16_t type; -} PEreloc; - -/* Cannot use sizeof, because it pads up to the max. alignment. */ -#define PEOBJ_RELOC_SIZE (4+4+2) - -/* PE symbol table entry. */ -typedef struct PEsym { - union { - char name[8]; - uint32_t nameref[2]; - } n; - uint32_t value; - int16_t sect; - uint16_t type; - uint8_t scl; - uint8_t naux; -} PEsym; - -/* PE symbol table auxiliary entry for a section. */ -typedef struct PEsymaux { - uint32_t size; - uint16_t nreloc; - uint16_t nline; - uint32_t cksum; - uint16_t assoc; - uint8_t comdatsel; - uint8_t unused[3]; -} PEsymaux; - -/* Cannot use sizeof, because it pads up to the max. alignment. */ -#define PEOBJ_SYM_SIZE (8+4+2+2+1+1) - -/* PE object CPU specific defines. */ -#if LJ_TARGET_X86 -#define PEOBJ_ARCH_TARGET 0x014c -#define PEOBJ_RELOC_REL32 0x14 /* MS: REL32, GNU: DISP32. */ -#define PEOBJ_RELOC_DIR32 0x06 -#elif LJ_TARGET_X64 -#define PEOBJ_ARCH_TARGET 0x8664 -#define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */ -#define PEOBJ_RELOC_DIR32 0x02 -#define PEOBJ_RELOC_ADDR32NB 0x03 -#endif - -/* Section numbers (0-based). */ -enum { - PEOBJ_SECT_ABS = -2, - PEOBJ_SECT_UNDEF = -1, - PEOBJ_SECT_TEXT, -#if LJ_TARGET_X64 - PEOBJ_SECT_PDATA, - PEOBJ_SECT_XDATA, -#endif - PEOBJ_SECT_RDATA_Z, - PEOBJ_NSECTIONS -}; - -/* Symbol types. */ -#define PEOBJ_TYPE_NULL 0 -#define PEOBJ_TYPE_FUNC 0x20 - -/* Symbol storage class. */ -#define PEOBJ_SCL_EXTERN 2 -#define PEOBJ_SCL_STATIC 3 - -/* -- PE object emitter --------------------------------------------------- */ - -/* Emit PE object symbol. */ -static void emit_peobj_sym(BuildCtx *ctx, const char *name, uint32_t value, - int sect, int type, int scl) -{ - PEsym sym; - size_t len = strlen(name); - if (!strtab) { /* Pass 1: only calculate string table length. */ - if (len > 8) strtabofs += len+1; - return; - } - if (len <= 8) { - memcpy(sym.n.name, name, len); - memset(sym.n.name+len, 0, 8-len); - } else { - sym.n.nameref[0] = 0; - sym.n.nameref[1] = (uint32_t)strtabofs; - memcpy(strtab + strtabofs, name, len); - strtab[strtabofs+len] = 0; - strtabofs += len+1; - } - sym.value = value; - sym.sect = (int16_t)(sect+1); /* 1-based section number. */ - sym.type = (uint16_t)type; - sym.scl = (uint8_t)scl; - sym.naux = 0; - owrite(ctx, &sym, PEOBJ_SYM_SIZE); -} - -/* Emit PE object section symbol. */ -static void emit_peobj_sym_sect(BuildCtx *ctx, PEsection *pesect, int sect) -{ - PEsym sym; - PEsymaux aux; - if (!strtab) return; /* Pass 1: no output. */ - memcpy(sym.n.name, pesect[sect].name, 8); - sym.value = 0; - sym.sect = (int16_t)(sect+1); /* 1-based section number. */ - sym.type = PEOBJ_TYPE_NULL; - sym.scl = PEOBJ_SCL_STATIC; - sym.naux = 1; - owrite(ctx, &sym, PEOBJ_SYM_SIZE); - memset(&aux, 0, sizeof(PEsymaux)); - aux.size = pesect[sect].size; - aux.nreloc = pesect[sect].nreloc; - owrite(ctx, &aux, PEOBJ_SYM_SIZE); -} - -/* Emit Windows PE object file. */ -void emit_peobj(BuildCtx *ctx) -{ - PEheader pehdr; - PEsection pesect[PEOBJ_NSECTIONS]; - uint32_t sofs; - int i, nrsym; - union { uint8_t b; uint32_t u; } host_endian; - - host_endian.u = 1; - if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) { - fprintf(stderr, "Error: different byte order for host and target\n"); - exit(1); - } - - sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection); - - /* Fill in PE sections. */ - memset(&pesect, 0, PEOBJ_NSECTIONS*sizeof(PEsection)); - memcpy(pesect[PEOBJ_SECT_TEXT].name, ".text", sizeof(".text")-1); - pesect[PEOBJ_SECT_TEXT].ofs = sofs; - sofs += (pesect[PEOBJ_SECT_TEXT].size = (uint32_t)ctx->codesz); - pesect[PEOBJ_SECT_TEXT].relocofs = sofs; - sofs += (pesect[PEOBJ_SECT_TEXT].nreloc = (uint16_t)ctx->nreloc) * PEOBJ_RELOC_SIZE; - /* Flags: 60 = read+execute, 50 = align16, 20 = code. */ - pesect[PEOBJ_SECT_TEXT].flags = 0x60500020; - -#if LJ_TARGET_X64 - memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1); - pesect[PEOBJ_SECT_PDATA].ofs = sofs; - sofs += (pesect[PEOBJ_SECT_PDATA].size = 6*4); - pesect[PEOBJ_SECT_PDATA].relocofs = sofs; - sofs += (pesect[PEOBJ_SECT_PDATA].nreloc = 6) * PEOBJ_RELOC_SIZE; - /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ - pesect[PEOBJ_SECT_PDATA].flags = 0x40300040; - - memcpy(pesect[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1); - pesect[PEOBJ_SECT_XDATA].ofs = sofs; - sofs += (pesect[PEOBJ_SECT_XDATA].size = 8*2+4+6*2); /* See below. */ - pesect[PEOBJ_SECT_XDATA].relocofs = sofs; - sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; - /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ - pesect[PEOBJ_SECT_XDATA].flags = 0x40300040; -#endif - - memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1); - pesect[PEOBJ_SECT_RDATA_Z].ofs = sofs; - sofs += (pesect[PEOBJ_SECT_RDATA_Z].size = (uint32_t)strlen(ctx->dasm_ident)+1); - /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ - pesect[PEOBJ_SECT_RDATA_Z].flags = 0x40300040; - - /* Fill in PE header. */ - pehdr.arch = PEOBJ_ARCH_TARGET; - pehdr.nsects = PEOBJ_NSECTIONS; - pehdr.time = 0; /* Timestamp is optional. */ - pehdr.symtabofs = sofs; - pehdr.opthdrsz = 0; - pehdr.flags = 0; - - /* Compute the size of the symbol table: - ** @feat.00 + nsections*2 - ** + asm_start + nsym - ** + nrsym - */ - nrsym = ctx->nrelocsym; - pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; -#if LJ_TARGET_X64 - pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */ -#endif - - /* Write PE object header and all sections. */ - owrite(ctx, &pehdr, sizeof(PEheader)); - owrite(ctx, &pesect, sizeof(PEsection)*PEOBJ_NSECTIONS); - - /* Write .text section. */ - owrite(ctx, ctx->code, ctx->codesz); - for (i = 0; i < ctx->nreloc; i++) { - PEreloc reloc; - reloc.vaddr = (uint32_t)ctx->reloc[i].ofs; - reloc.symidx = 1+2+ctx->reloc[i].sym; /* Reloc syms are after .text sym. */ - reloc.type = ctx->reloc[i].type ? PEOBJ_RELOC_REL32 : PEOBJ_RELOC_DIR32; - owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); - } - -#if LJ_TARGET_X64 - { /* Write .pdata section. */ - uint32_t fcofs = (uint32_t)ctx->sym[ctx->nsym-1].ofs; - uint32_t pdata[3]; /* Start of .text, end of .text and .xdata. */ - PEreloc reloc; - pdata[0] = 0; pdata[1] = fcofs; pdata[2] = 0; - owrite(ctx, &pdata, sizeof(pdata)); - pdata[0] = fcofs; pdata[1] = (uint32_t)ctx->codesz; pdata[2] = 20; - owrite(ctx, &pdata, sizeof(pdata)); - reloc.vaddr = 0; reloc.symidx = 1+2+nrsym+2+2+1; - reloc.type = PEOBJ_RELOC_ADDR32NB; - owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); - reloc.vaddr = 4; reloc.symidx = 1+2+nrsym+2+2+1; - reloc.type = PEOBJ_RELOC_ADDR32NB; - owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); - reloc.vaddr = 8; reloc.symidx = 1+2+nrsym+2; - reloc.type = PEOBJ_RELOC_ADDR32NB; - owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); - reloc.vaddr = 12; reloc.symidx = 1+2+nrsym+2+2+1; - reloc.type = PEOBJ_RELOC_ADDR32NB; - owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); - reloc.vaddr = 16; reloc.symidx = 1+2+nrsym+2+2+1; - reloc.type = PEOBJ_RELOC_ADDR32NB; - owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); - reloc.vaddr = 20; reloc.symidx = 1+2+nrsym+2; - reloc.type = PEOBJ_RELOC_ADDR32NB; - owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); - } - { /* Write .xdata section. */ - uint16_t xdata[8+2+6]; - PEreloc reloc; - xdata[0] = 0x01|0x08|0x10; /* Ver. 1, uhandler/ehandler, prolog size 0. */ - xdata[1] = 0x0005; /* Number of unwind codes, no frame pointer. */ - xdata[2] = 0x4200; /* Stack offset 4*8+8 = aword*5. */ - xdata[3] = 0x3000; /* Push rbx. */ - xdata[4] = 0x6000; /* Push rsi. */ - xdata[5] = 0x7000; /* Push rdi. */ - xdata[6] = 0x5000; /* Push rbp. */ - xdata[7] = 0; /* Alignment. */ - xdata[8] = xdata[9] = 0; /* Relocated address of exception handler. */ - xdata[10] = 0x01; /* Ver. 1, no handler, prolog size 0. */ - xdata[11] = 0x1504; /* Number of unwind codes, fp = rbp, fpofs = 16. */ - xdata[12] = 0x0300; /* set_fpreg. */ - xdata[13] = 0x0200; /* stack offset 0*8+8 = aword*1. */ - xdata[14] = 0x3000; /* Push rbx. */ - xdata[15] = 0x5000; /* Push rbp. */ - owrite(ctx, &xdata, sizeof(xdata)); - reloc.vaddr = 2*8; reloc.symidx = 1+2+nrsym+2+2; - reloc.type = PEOBJ_RELOC_ADDR32NB; - owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); - } -#endif - - /* Write .rdata$Z section. */ - owrite(ctx, ctx->dasm_ident, strlen(ctx->dasm_ident)+1); - - /* Write symbol table. */ - strtab = NULL; /* 1st pass: collect string sizes. */ - for (;;) { - strtabofs = 4; - /* Mark as SafeSEH compliant. */ - emit_peobj_sym(ctx, "@feat.00", 1, - PEOBJ_SECT_ABS, PEOBJ_TYPE_NULL, PEOBJ_SCL_STATIC); - - emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_TEXT); - for (i = 0; i < nrsym; i++) - emit_peobj_sym(ctx, ctx->relocsym[i], 0, - PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); - -#if LJ_TARGET_X64 - emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); - emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); - emit_peobj_sym(ctx, "lj_err_unwind_win64", 0, - PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); -#endif - - emit_peobj_sym(ctx, ctx->beginsym, 0, - PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN); - for (i = 0; i < ctx->nsym; i++) - emit_peobj_sym(ctx, ctx->sym[i].name, (uint32_t)ctx->sym[i].ofs, - PEOBJ_SECT_TEXT, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); - - emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_RDATA_Z); - - if (strtab) - break; - /* 2nd pass: alloc strtab, write syms and copy strings. */ - strtab = (char *)malloc(strtabofs); - *(uint32_t *)strtab = (uint32_t)strtabofs; - } - - /* Write string table. */ - owrite(ctx, strtab, strtabofs); -} - -#else - -void emit_peobj(BuildCtx *ctx) -{ - UNUSED(ctx); - fprintf(stderr, "Error: no PE object support for this target\n"); - exit(1); -} - -#endif diff --git a/src/buildvm_ppc.dasc b/src/buildvm_ppc.dasc deleted file mode 100644 index 49f92d0a..00000000 --- a/src/buildvm_ppc.dasc +++ /dev/null @@ -1,4888 +0,0 @@ -|// Low-level VM code for PowerPC CPUs. -|// Bytecode interpreter, fast functions and helper functions. -|// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -| -|.arch ppc -|.section code_op, code_sub -| -|.actionlist build_actionlist -|.globals GLOB_ -|.globalnames globnames -|.externnames extnames -| -|// Note: The ragged indentation of the instructions is intentional. -|// The starting columns indicate data dependencies. -| -|//----------------------------------------------------------------------- -| -|// Fixed register assignments for the interpreter. -|// Don't use: r1 = sp, r2 and r13 = reserved (TOC, TLS or SDATA) -| -|// The following must be C callee-save (but BASE is often refetched). -|.define BASE, r14 // Base of current Lua stack frame. -|.define KBASE, r15 // Constants of current Lua function. -|.define PC, r16 // Next PC. -|.define DISPATCH, r17 // Opcode dispatch table. -|.define LREG, r18 // Register holding lua_State (also in SAVE_L). -|.define MULTRES, r19 // Size of multi-result: (nresults+1)*8. -|.define JGL, r31 // On-trace: global_State + 32768. -| -|// Constants for type-comparisons, stores and conversions. C callee-save. -|.define TISNUM, r22 -|.define TISNIL, r23 -|.define ZERO, r24 -|.define TOBIT, f30 // 2^52 + 2^51. -|.define TONUM, f31 // 2^52 + 2^51 + 2^31. -| -|// The following temporaries are not saved across C calls, except for RA. -|.define RA, r20 // Callee-save. -|.define RB, r10 -|.define RC, r11 -|.define RD, r12 -|.define INS, r7 // Overlaps CARG5. -| -|.define TMP0, r0 -|.define TMP1, r8 -|.define TMP2, r9 -|.define TMP3, r6 // Overlaps CARG4. -| -|// Saved temporaries. -|.define SAVE0, r21 -| -|// Calling conventions. -|.define CARG1, r3 -|.define CARG2, r4 -|.define CARG3, r5 -|.define CARG4, r6 // Overlaps TMP3. -|.define CARG5, r7 // Overlaps INS. -| -|.define FARG1, f1 -|.define FARG2, f2 -| -|.define CRET1, r3 -|.define CRET2, r4 -| -|// Stack layout while in interpreter. Must match with lj_frame.h. -|.define SAVE_LR, 276(sp) -|.define CFRAME_SPACE, 272 // Delta for sp. -|// Back chain for sp: 272(sp) <-- sp entering interpreter -|.define SAVE_FPR_, 128 // .. 128+18*8: 64 bit FPR saves. -|.define SAVE_GPR_, 56 // .. 56+18*4: 32 bit GPR saves. -|.define SAVE_CR, 52(sp) // 32 bit CR save. -|.define SAVE_ERRF, 48(sp) // 32 bit C frame info. -|.define SAVE_NRES, 44(sp) -|.define SAVE_CFRAME, 40(sp) -|.define SAVE_L, 36(sp) -|.define SAVE_PC, 32(sp) -|.define SAVE_MULTRES, 28(sp) -|.define UNUSED1, 24(sp) -|.define TMPD_LO, 20(sp) -|.define TMPD_HI, 16(sp) -|.define TONUM_LO, 12(sp) -|.define TONUM_HI, 8(sp) -|// Next frame lr: 4(sp) -|// Back chain for sp: 0(sp) <-- sp while in interpreter -| -|.define TMPD_BLO, 23(sp) -|.define TMPD, TMPD_HI -|.define TONUM_D, TONUM_HI -| -|.macro save_, reg -| stw r..reg, SAVE_GPR_+(reg-14)*4(sp) -| stfd f..reg, SAVE_FPR_+(reg-14)*8(sp) -|.endmacro -|.macro rest_, reg -| lwz r..reg, SAVE_GPR_+(reg-14)*4(sp) -| lfd f..reg, SAVE_FPR_+(reg-14)*8(sp) -|.endmacro -| -|.macro saveregs -| stwu sp, -CFRAME_SPACE(sp) -| save_ 14; save_ 15; save_ 16 -| mflr r0 -| save_ 17; save_ 18; save_ 19; save_ 20; save_ 21; save_ 22 -| stw r0, SAVE_LR -| save_ 23; save_ 24; save_ 25 -| mfcr r0 -| save_ 26; save_ 27; save_ 28; save_ 29; save_ 30; save_ 31 -| stw r0, SAVE_CR -|.endmacro -| -|.macro restoreregs -| lwz r0, SAVE_LR; lwz r12, SAVE_CR -| rest_ 14; rest_ 15; rest_ 16; rest_ 17; rest_ 18; rest_ 19 -| mtlr r0; mtcrf 0x38, r12 -| rest_ 20; rest_ 21; rest_ 22; rest_ 23; rest_ 24; rest_ 25 -| rest_ 26; rest_ 27; rest_ 28; rest_ 29; rest_ 30; rest_ 31 -| addi sp, sp, CFRAME_SPACE -|.endmacro -| -|// Type definitions. Some of these are only used for documentation. -|.type L, lua_State, LREG -|.type GL, global_State -|.type TVALUE, TValue -|.type GCOBJ, GCobj -|.type STR, GCstr -|.type TAB, GCtab -|.type LFUNC, GCfuncL -|.type CFUNC, GCfuncC -|.type PROTO, GCproto -|.type UPVAL, GCupval -|.type NODE, Node -|.type NARGS8, int -|.type TRACE, GCtrace -| -|//----------------------------------------------------------------------- -| -|// These basic macros should really be part of DynASM. -|.macro srwi, rx, ry, n; rlwinm rx, ry, 32-n, n, 31; .endmacro -|.macro slwi, rx, ry, n; rlwinm rx, ry, n, 0, 31-n; .endmacro -|.macro rotlwi, rx, ry, n; rlwinm rx, ry, n, 0, 31; .endmacro -|.macro rotlw, rx, ry, rn; rlwnm rx, ry, rn, 0, 31; .endmacro -|.macro subi, rx, ry, i; addi rx, ry, -i; .endmacro -| -|// Trap for not-yet-implemented parts. -|.macro NYI; tw 4, sp, sp; .endmacro -| -|// int/FP conversions. -|.macro tonum_i, freg, reg -| xoris reg, reg, 0x8000 -| stw reg, TONUM_LO -| lfd freg, TONUM_D -| fsub freg, freg, TONUM -|.endmacro -| -|.macro tonum_u, freg, reg -| stw reg, TONUM_LO -| lfd freg, TONUM_D -| fsub freg, freg, TOBIT -|.endmacro -| -|.macro toint, reg, freg, tmpfreg -| fctiwz tmpfreg, freg -| stfd tmpfreg, TMPD -| lwz reg, TMPD_LO -|.endmacro -| -|.macro toint, reg, freg -| toint reg, freg, freg -|.endmacro -| -|//----------------------------------------------------------------------- -| -|// Access to frame relative to BASE. -|.define FRAME_PC, -8 -|.define FRAME_FUNC, -4 -| -|// Instruction decode. -|.macro decode_OP4, dst, ins; rlwinm dst, ins, 2, 22, 29; .endmacro -|.macro decode_RA8, dst, ins; rlwinm dst, ins, 27, 21, 28; .endmacro -|.macro decode_RB8, dst, ins; rlwinm dst, ins, 11, 21, 28; .endmacro -|.macro decode_RC8, dst, ins; rlwinm dst, ins, 19, 21, 28; .endmacro -|.macro decode_RD8, dst, ins; rlwinm dst, ins, 19, 13, 28; .endmacro -| -|.macro decode_OP1, dst, ins; rlwinm dst, ins, 0, 24, 31; .endmacro -|.macro decode_RD4, dst, ins; rlwinm dst, ins, 18, 14, 29; .endmacro -| -|// Instruction fetch. -|.macro ins_NEXT1 -| lwz INS, 0(PC) -| addi PC, PC, 4 -|.endmacro -|// Instruction decode+dispatch. Note: optimized for e300! -|.macro ins_NEXT2 -| decode_OP4 TMP1, INS -| lwzx TMP0, DISPATCH, TMP1 -| mtctr TMP0 -| decode_RB8 RB, INS -| decode_RD8 RD, INS -| decode_RA8 RA, INS -| decode_RC8 RC, INS -| bctr -|.endmacro -|.macro ins_NEXT -| ins_NEXT1 -| ins_NEXT2 -|.endmacro -| -|// Instruction footer. -|.if 1 -| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use. -| .define ins_next, ins_NEXT -| .define ins_next_, ins_NEXT -| .define ins_next1, ins_NEXT1 -| .define ins_next2, ins_NEXT2 -|.else -| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch. -| // Affects only certain kinds of benchmarks (and only with -j off). -| .macro ins_next -| b ->ins_next -| .endmacro -| .macro ins_next1 -| .endmacro -| .macro ins_next2 -| b ->ins_next -| .endmacro -| .macro ins_next_ -| ->ins_next: -| ins_NEXT -| .endmacro -|.endif -| -|// Call decode and dispatch. -|.macro ins_callt -| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC -| lwz PC, LFUNC:RB->pc -| lwz INS, 0(PC) -| addi PC, PC, 4 -| decode_OP4 TMP1, INS -| decode_RA8 RA, INS -| lwzx TMP0, DISPATCH, TMP1 -| add RA, RA, BASE -| mtctr TMP0 -| bctr -|.endmacro -| -|.macro ins_call -| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, PC = caller PC -| stw PC, FRAME_PC(BASE) -| ins_callt -|.endmacro -| -|//----------------------------------------------------------------------- -| -|// Macros to test operand types. -|.macro checknum, reg; cmplw reg, TISNUM; .endmacro -|.macro checknum, cr, reg; cmplw cr, reg, TISNUM; .endmacro -|.macro checkstr, reg; cmpwi reg, LJ_TSTR; .endmacro -|.macro checktab, reg; cmpwi reg, LJ_TTAB; .endmacro -|.macro checkfunc, reg; cmpwi reg, LJ_TFUNC; .endmacro -|.macro checknil, reg; cmpwi reg, LJ_TNIL; .endmacro -| -|.macro branch_RD -| srwi TMP0, RD, 1 -| addis PC, PC, -(BCBIAS_J*4 >> 16) -| add PC, PC, TMP0 -|.endmacro -| -|// Assumes DISPATCH is relative to GL. -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -| -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) -| -|.macro hotcheck, delta, target -| rlwinm TMP1, PC, 31, 25, 30 -| addi TMP1, TMP1, GG_DISP2HOT -| lhzx TMP2, DISPATCH, TMP1 -| addic. TMP2, TMP2, -delta -| sthx TMP2, DISPATCH, TMP1 -| blt target -|.endmacro -| -|.macro hotloop -| hotcheck HOTCOUNT_LOOP, ->vm_hotloop -|.endmacro -| -|.macro hotcall -| hotcheck HOTCOUNT_CALL, ->vm_hotcall -|.endmacro -| -|// Set current VM state. Uses TMP0. -|.macro li_vmstate, st; li TMP0, ~LJ_VMST_..st; .endmacro -|.macro st_vmstate; stw TMP0, DISPATCH_GL(vmstate)(DISPATCH); .endmacro -| -|// Move table write barrier back. Overwrites mark and tmp. -|.macro barrierback, tab, mark, tmp -| lwz tmp, DISPATCH_GL(gc.grayagain)(DISPATCH) -| // Assumes LJ_GC_BLACK is 0x04. -| rlwinm mark, mark, 0, 30, 28 // black2gray(tab) -| stw tab, DISPATCH_GL(gc.grayagain)(DISPATCH) -| stb mark, tab->marked -| stw tmp, tab->gclist -|.endmacro -| -|//----------------------------------------------------------------------- - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx) -{ - |.code_sub - | - |//----------------------------------------------------------------------- - |//-- Return handling ---------------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_returnp: - | // See vm_return. Also: TMP2 = previous base. - | andi. TMP0, PC, FRAME_P - | li TMP1, LJ_TTRUE - | beq ->cont_dispatch - | - | // Return from pcall or xpcall fast func. - | lwz PC, FRAME_PC(TMP2) // Fetch PC of previous frame. - | mr BASE, TMP2 // Restore caller base. - | // Prepending may overwrite the pcall frame, so do it at the end. - | stwu TMP1, FRAME_PC(RA) // Prepend true to results. - | - |->vm_returnc: - | andi. TMP0, PC, FRAME_TYPE - | addi RD, RD, 8 // RD = (nresults+1)*8. - | mr MULTRES, RD - | beq ->BC_RET_Z // Handle regular return to Lua. - | - |->vm_return: - | // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return - | // TMP0 = PC & FRAME_TYPE - | cmpwi TMP0, FRAME_C - | rlwinm TMP2, PC, 0, 0, 28 - | li_vmstate C - | sub TMP2, BASE, TMP2 // TMP2 = previous base. - | bney ->vm_returnp - | - | addic. TMP1, RD, -8 - | stw TMP2, L->base - | lwz TMP2, SAVE_NRES - | subi BASE, BASE, 8 - | st_vmstate - | slwi TMP2, TMP2, 3 - | beq >2 - |1: - | addic. TMP1, TMP1, -8 - | lfd f0, 0(RA) - | addi RA, RA, 8 - | stfd f0, 0(BASE) - | addi BASE, BASE, 8 - | bney <1 - | - |2: - | cmpw TMP2, RD // More/less results wanted? - | bne >6 - |3: - | stw BASE, L->top // Store new top. - | - |->vm_leave_cp: - | lwz TMP0, SAVE_CFRAME // Restore previous C frame. - | li CRET1, 0 // Ok return status for vm_pcall. - | stw TMP0, L->cframe - | - |->vm_leave_unw: - | restoreregs - | blr - | - |6: - | ble >7 // Less results wanted? - | // More results wanted. Check stack size and fill up results with nil. - | lwz TMP1, L->maxstack - | cmplw BASE, TMP1 - | bge >8 - | stw TISNIL, 0(BASE) - | addi RD, RD, 8 - | addi BASE, BASE, 8 - | b <2 - | - |7: // Less results wanted. - | subfic TMP3, TMP2, 0 // LUA_MULTRET+1 case? - | sub TMP0, RD, TMP2 - | subfe TMP1, TMP1, TMP1 // TMP1 = TMP2 == 0 ? 0 : -1 - | and TMP0, TMP0, TMP1 - | sub BASE, BASE, TMP0 // Either keep top or shrink it. - | b <3 - | - |8: // Corner case: need to grow stack for filling up results. - | // This can happen if: - | // - A C function grows the stack (a lot). - | // - The GC shrinks the stack in between. - | // - A return back from a lua_call() with (high) nresults adjustment. - | stw BASE, L->top // Save current top held in BASE (yes). - | mr SAVE0, RD - | mr CARG2, TMP2 - | mr CARG1, L - | bl extern lj_state_growstack // (lua_State *L, int n) - | lwz TMP2, SAVE_NRES - | mr RD, SAVE0 - | slwi TMP2, TMP2, 3 - | lwz BASE, L->top // Need the (realloced) L->top in BASE. - | b <2 - | - |->vm_unwind_c: // Unwind C stack, return from vm_pcall. - | // (void *cframe, int errcode) - | mr sp, CARG1 - | mr CRET1, CARG2 - |->vm_unwind_c_eh: // Landing pad for external unwinder. - | lwz L, SAVE_L - | li TMP0, ~LJ_VMST_C - | lwz GL:TMP1, L->glref - | stw TMP0, GL:TMP1->vmstate - | b ->vm_leave_unw - | - |->vm_unwind_ff: // Unwind C stack, return from ff pcall. - | // (void *cframe) - | rlwinm sp, CARG1, 0, 0, 29 - |->vm_unwind_ff_eh: // Landing pad for external unwinder. - | lwz L, SAVE_L - | li TISNUM, LJ_TISNUM // Setup type comparison constants. - | lwz BASE, L->base - | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). - | lwz DISPATCH, L->glref // Setup pointer to dispatch table. - | li ZERO, 0 - | stw TMP3, TMPD - | li TMP1, LJ_TFALSE - | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float). - | li TISNIL, LJ_TNIL - | li_vmstate INTERP - | lfs TOBIT, TMPD - | lwz PC, FRAME_PC(BASE) // Fetch PC of previous frame. - | la RA, -8(BASE) // Results start at BASE-8. - | stw TMP3, TMPD - | addi DISPATCH, DISPATCH, GG_G2DISP - | stw TMP1, 0(RA) // Prepend false to error message. - | li RD, 16 // 2 results: false + error message. - | st_vmstate - | lfs TONUM, TMPD - | b ->vm_returnc - | - |//----------------------------------------------------------------------- - |//-- Grow stack for calls ----------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_growstack_c: // Grow stack for C function. - | li CARG2, LUA_MINSTACK - | b >2 - | - |->vm_growstack_l: // Grow stack for Lua function. - | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC - | add RC, BASE, RC - | sub RA, RA, BASE - | stw BASE, L->base - | addi PC, PC, 4 // Must point after first instruction. - | stw RC, L->top - | srwi CARG2, RA, 3 - |2: - | // L->base = new base, L->top = top - | stw PC, SAVE_PC - | mr CARG1, L - | bl extern lj_state_growstack // (lua_State *L, int n) - | lwz BASE, L->base - | lwz RC, L->top - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | sub RC, RC, BASE - | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC - | ins_callt // Just retry the call. - | - |//----------------------------------------------------------------------- - |//-- Entry points into the assembler VM --------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_resume: // Setup C frame and resume thread. - | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0) - | saveregs - | mr L, CARG1 - | lwz DISPATCH, L->glref // Setup pointer to dispatch table. - | mr BASE, CARG2 - | lbz TMP1, L->status - | stw L, SAVE_L - | li PC, FRAME_CP - | addi TMP0, sp, CFRAME_RESUME - | addi DISPATCH, DISPATCH, GG_G2DISP - | stw CARG3, SAVE_NRES - | cmplwi TMP1, 0 - | stw CARG3, SAVE_ERRF - | stw TMP0, L->cframe - | stw CARG3, SAVE_CFRAME - | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. - | beq >3 - | - | // Resume after yield (like a return). - | mr RA, BASE - | lwz BASE, L->base - | li TISNUM, LJ_TISNUM // Setup type comparison constants. - | lwz TMP1, L->top - | lwz PC, FRAME_PC(BASE) - | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). - | stb CARG3, L->status - | stw TMP3, TMPD - | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float). - | lfs TOBIT, TMPD - | sub RD, TMP1, BASE - | stw TMP3, TMPD - | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double) - | addi RD, RD, 8 - | stw TMP0, TONUM_HI - | li_vmstate INTERP - | li ZERO, 0 - | st_vmstate - | andi. TMP0, PC, FRAME_TYPE - | mr MULTRES, RD - | lfs TONUM, TMPD - | li TISNIL, LJ_TNIL - | beq ->BC_RET_Z - | b ->vm_return - | - |->vm_pcall: // Setup protected C frame and enter VM. - | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef) - | saveregs - | li PC, FRAME_CP - | stw CARG4, SAVE_ERRF - | b >1 - | - |->vm_call: // Setup C frame and enter VM. - | // (lua_State *L, TValue *base, int nres1) - | saveregs - | li PC, FRAME_C - | - |1: // Entry point for vm_pcall above (PC = ftype). - | lwz TMP1, L:CARG1->cframe - | stw CARG3, SAVE_NRES - | mr L, CARG1 - | stw CARG1, SAVE_L - | mr BASE, CARG2 - | stw sp, L->cframe // Add our C frame to cframe chain. - | lwz DISPATCH, L->glref // Setup pointer to dispatch table. - | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. - | stw TMP1, SAVE_CFRAME - | addi DISPATCH, DISPATCH, GG_G2DISP - | - |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype). - | lwz TMP2, L->base // TMP2 = old base (used in vmeta_call). - | li TISNUM, LJ_TISNUM // Setup type comparison constants. - | lwz TMP1, L->top - | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). - | add PC, PC, BASE - | stw TMP3, TMPD - | li ZERO, 0 - | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float). - | lfs TOBIT, TMPD - | sub PC, PC, TMP2 // PC = frame delta + frame type - | stw TMP3, TMPD - | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double) - | sub NARGS8:RC, TMP1, BASE - | stw TMP0, TONUM_HI - | li_vmstate INTERP - | lfs TONUM, TMPD - | li TISNIL, LJ_TNIL - | st_vmstate - | - |->vm_call_dispatch: - | // TMP2 = old base, BASE = new base, RC = nargs*8, PC = caller PC - | lwz TMP0, FRAME_PC(BASE) - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | checkfunc TMP0; bne ->vmeta_call - | - |->vm_call_dispatch_f: - | ins_call - | // BASE = new base, RB = func, RC = nargs*8, PC = caller PC - | - |->vm_cpcall: // Setup protected C frame, call C. - | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp) - | saveregs - | mr L, CARG1 - | lwz TMP0, L:CARG1->stack - | stw CARG1, SAVE_L - | lwz TMP1, L->top - | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. - | sub TMP0, TMP0, TMP1 // Compute -savestack(L, L->top). - | lwz TMP1, L->cframe - | stw sp, L->cframe // Add our C frame to cframe chain. - | li TMP2, 0 - | stw TMP0, SAVE_NRES // Neg. delta means cframe w/o frame. - | stw TMP2, SAVE_ERRF // No error function. - | stw TMP1, SAVE_CFRAME - | mtctr CARG4 - | bctrl // (lua_State *L, lua_CFunction func, void *ud) - | mr. BASE, CRET1 - | lwz DISPATCH, L->glref // Setup pointer to dispatch table. - | li PC, FRAME_CP - | addi DISPATCH, DISPATCH, GG_G2DISP - | bne <3 // Else continue with the call. - | b ->vm_leave_cp // No base? Just remove C frame. - | - |//----------------------------------------------------------------------- - |//-- Metamethod handling ------------------------------------------------ - |//----------------------------------------------------------------------- - | - |// The lj_meta_* functions (except for lj_meta_cat) don't reallocate the - |// stack, so BASE doesn't need to be reloaded across these calls. - | - |//-- Continuation dispatch ---------------------------------------------- - | - |->cont_dispatch: - | // BASE = meta base, RA = resultptr, RD = (nresults+1)*8 - | lwz TMP0, -12(BASE) // Continuation. - | mr RB, BASE - | mr BASE, TMP2 // Restore caller BASE. - | lwz LFUNC:TMP1, FRAME_FUNC(TMP2) -#if LJ_HASFFI - | cmplwi TMP0, 1 -#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 LJ_HASFFI - | ble >1 -#endif - | lwz KBASE, PC2PROTO(k)(TMP1) - | // BASE = base, RA = resultptr, RB = meta base - | mtctr TMP0 - | bctr // Jump to continuation. - | -#if LJ_HASFFI - |1: - | beq ->cont_ffi_callback // cont = 1: return from FFI callback. - | // cont = 0: tailcall from C function. - | subi TMP1, RB, 16 - | sub RC, TMP1, BASE - | b ->vm_call_tail -#endif - | - |->cont_cat: // RA = resultptr, RB = meta base - | lwz INS, -4(PC) - | subi CARG2, RB, 16 - | decode_RB8 SAVE0, INS - | lfd f0, 0(RA) - | add TMP1, BASE, SAVE0 - | stw BASE, L->base - | cmplw TMP1, CARG2 - | sub CARG3, CARG2, TMP1 - | decode_RA8 RA, INS - | stfd f0, 0(CARG2) - | bney ->BC_CAT_Z - | stfdx f0, BASE, RA - | b ->cont_nop - | - |//-- Table indexing metamethods ----------------------------------------- - | - |->vmeta_tgets1: - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | li TMP0, LJ_TSTR - | decode_RB8 RB, INS - | stw STR:RC, 4(CARG3) - | add CARG2, BASE, RB - | stw TMP0, 0(CARG3) - | b >1 - | - |->vmeta_tgets: - | la CARG2, DISPATCH_GL(tmptv)(DISPATCH) - | li TMP0, LJ_TTAB - | stw TAB:RB, 4(CARG2) - | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH) - | stw TMP0, 0(CARG2) - | li TMP1, LJ_TSTR - | stw STR:RC, 4(CARG3) - | stw TMP1, 0(CARG3) - | b >1 - | - |->vmeta_tgetb: // TMP0 = index - if (!LJ_DUALNUM) { - | tonum_u f0, TMP0 - } - | decode_RB8 RB, INS - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | add CARG2, BASE, RB - if (LJ_DUALNUM) { - | stw TISNUM, 0(CARG3) - | stw TMP0, 4(CARG3) - } else { - | stfd f0, 0(CARG3) - } - | b >1 - | - |->vmeta_tgetv: - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | add CARG2, BASE, RB - | add CARG3, BASE, RC - |1: - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | bl extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k) - | // Returns TValue * (finished) or NULL (metamethod). - | cmplwi CRET1, 0 - | beq >3 - | lfd f0, 0(CRET1) - | ins_next1 - | stfdx f0, BASE, RA - | ins_next2 - | - |3: // Call __index metamethod. - | // BASE = base, L->top = new base, stack = cont/func/t/k - | subfic TMP1, BASE, FRAME_CONT - | lwz BASE, L->top - | stw PC, -16(BASE) // [cont|PC] - | add PC, TMP1, BASE - | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. - | li NARGS8:RC, 16 // 2 args for func(t, k). - | b ->vm_call_dispatch_f - | - |//----------------------------------------------------------------------- - | - |->vmeta_tsets1: - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | li TMP0, LJ_TSTR - | decode_RB8 RB, INS - | stw STR:RC, 4(CARG3) - | add CARG2, BASE, RB - | stw TMP0, 0(CARG3) - | b >1 - | - |->vmeta_tsets: - | la CARG2, DISPATCH_GL(tmptv)(DISPATCH) - | li TMP0, LJ_TTAB - | stw TAB:RB, 4(CARG2) - | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH) - | stw TMP0, 0(CARG2) - | li TMP1, LJ_TSTR - | stw STR:RC, 4(CARG3) - | stw TMP1, 0(CARG3) - | b >1 - | - |->vmeta_tsetb: // TMP0 = index - if (!LJ_DUALNUM) { - | tonum_u f0, TMP0 - } - | decode_RB8 RB, INS - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | add CARG2, BASE, RB - if (LJ_DUALNUM) { - | stw TISNUM, 0(CARG3) - | stw TMP0, 4(CARG3) - } else { - | stfd f0, 0(CARG3) - } - | b >1 - | - |->vmeta_tsetv: - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | add CARG2, BASE, RB - | add CARG3, BASE, RC - |1: - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | bl extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k) - | // Returns TValue * (finished) or NULL (metamethod). - | cmplwi CRET1, 0 - | lfdx f0, BASE, RA - | beq >3 - | // NOBARRIER: lj_meta_tset ensures the table is not black. - | ins_next1 - | stfd f0, 0(CRET1) - | ins_next2 - | - |3: // Call __newindex metamethod. - | // BASE = base, L->top = new base, stack = cont/func/t/k/(v) - | subfic TMP1, BASE, FRAME_CONT - | lwz BASE, L->top - | stw PC, -16(BASE) // [cont|PC] - | add PC, TMP1, BASE - | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. - | li NARGS8:RC, 24 // 3 args for func(t, k, v) - | stfd f0, 16(BASE) // Copy value to third argument. - | b ->vm_call_dispatch_f - | - |//-- Comparison metamethods --------------------------------------------- - | - |->vmeta_comp: - | mr CARG1, L - | subi PC, PC, 4 - if (LJ_DUALNUM) { - | mr CARG2, RA - } else { - | add CARG2, BASE, RA - } - | stw PC, SAVE_PC - if (LJ_DUALNUM) { - | mr CARG3, RD - } else { - | add CARG3, BASE, RD - } - | stw BASE, L->base - | decode_OP1 CARG4, INS - | bl extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op) - | // Returns 0/1 or TValue * (metamethod). - |3: - | cmplwi CRET1, 1 - | bgt ->vmeta_binop - | subfic CRET1, CRET1, 0 - |4: - | lwz INS, 0(PC) - | addi PC, PC, 4 - | decode_RD4 TMP2, INS - | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) - | and TMP2, TMP2, CRET1 - | add PC, PC, TMP2 - |->cont_nop: - | ins_next - | - |->cont_ra: // RA = resultptr - | lwz INS, -4(PC) - | lfd f0, 0(RA) - | decode_RA8 TMP1, INS - | stfdx f0, BASE, TMP1 - | b ->cont_nop - | - |->cont_condt: // RA = resultptr - | lwz TMP0, 0(RA) - | subfic TMP0, TMP0, LJ_TTRUE // Branch if result is true. - | subfe CRET1, CRET1, CRET1 - | not CRET1, CRET1 - | b <4 - | - |->cont_condf: // RA = resultptr - | lwz TMP0, 0(RA) - | subfic TMP0, TMP0, LJ_TTRUE // Branch if result is false. - | subfe CRET1, CRET1, CRET1 - | b <4 - | - |->vmeta_equal: - | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV. - | subi PC, PC, 4 - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | bl extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne) - | // Returns 0/1 or TValue * (metamethod). - | b <3 - | - |->vmeta_equal_cd: -#if LJ_HASFFI - | mr CARG2, INS - | subi PC, PC, 4 - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | bl extern lj_meta_equal_cd // (lua_State *L, BCIns op) - | // Returns 0/1 or TValue * (metamethod). - | b <3 -#endif - | - |//-- Arithmetic metamethods --------------------------------------------- - | - |->vmeta_arith_nv: - | add CARG3, KBASE, RC - | add CARG4, BASE, RB - | b >1 - |->vmeta_arith_nv2: - if (LJ_DUALNUM) { - | mr CARG3, RC - | mr CARG4, RB - | b >1 - } - | - |->vmeta_unm: - | mr CARG3, RD - | mr CARG4, RD - | b >1 - | - |->vmeta_arith_vn: - | add CARG3, BASE, RB - | add CARG4, KBASE, RC - | b >1 - | - |->vmeta_arith_vv: - | add CARG3, BASE, RB - | add CARG4, BASE, RC - if (LJ_DUALNUM) { - | b >1 - } - |->vmeta_arith_vn2: - |->vmeta_arith_vv2: - if (LJ_DUALNUM) { - | mr CARG3, RB - | mr CARG4, RC - } - |1: - | add CARG2, BASE, RA - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | decode_OP1 CARG5, INS // Caveat: CARG5 overlaps INS. - | bl extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op) - | // Returns NULL (finished) or TValue * (metamethod). - | cmplwi CRET1, 0 - | beq ->cont_nop - | - | // Call metamethod for binary op. - |->vmeta_binop: - | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2 - | sub TMP1, CRET1, BASE - | stw PC, -16(CRET1) // [cont|PC] - | mr TMP2, BASE - | addi PC, TMP1, FRAME_CONT - | mr BASE, CRET1 - | li NARGS8:RC, 16 // 2 args for func(o1, o2). - | b ->vm_call_dispatch - | - |->vmeta_len: -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | mr SAVE0, CARG1 -#endif - | mr CARG2, RD - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | bl extern lj_meta_len // (lua_State *L, TValue *o) - | // Returns NULL (retry) or TValue * (metamethod base). -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | cmplwi CRET1, 0 - | bne ->vmeta_binop // Binop call for compatibility. - | mr CARG1, SAVE0 - | b ->BC_LEN_Z -#else - | b ->vmeta_binop // Binop call for compatibility. -#endif - | - |//-- Call metamethod ---------------------------------------------------- - | - |->vmeta_call: // Resolve and call __call metamethod. - | // TMP2 = old base, BASE = new base, RC = nargs*8 - | mr CARG1, L - | stw TMP2, L->base // This is the callers base! - | subi CARG2, BASE, 8 - | stw PC, SAVE_PC - | add CARG3, BASE, RC - | mr SAVE0, NARGS8:RC - | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) - | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. - | addi NARGS8:RC, SAVE0, 8 // Got one more argument now. - | ins_call - | - |->vmeta_callt: // Resolve __call for BC_CALLT. - | // BASE = old base, RA = new base, RC = nargs*8 - | mr CARG1, L - | stw BASE, L->base - | subi CARG2, RA, 8 - | stw PC, SAVE_PC - | add CARG3, RA, RC - | mr SAVE0, NARGS8:RC - | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) - | lwz TMP1, FRAME_PC(BASE) - | addi NARGS8:RC, SAVE0, 8 // Got one more argument now. - | lwz LFUNC:RB, FRAME_FUNC(RA) // Guaranteed to be a function here. - | b ->BC_CALLT_Z - | - |//-- Argument coercion for 'for' statement ------------------------------ - | - |->vmeta_for: - | mr CARG1, L - | stw BASE, L->base - | mr CARG2, RA - | stw PC, SAVE_PC - | mr SAVE0, INS - | bl extern lj_meta_for // (lua_State *L, TValue *base) -#if LJ_HASJIT - | decode_OP1 TMP0, SAVE0 -#endif - | decode_RA8 RA, SAVE0 -#if LJ_HASJIT - | cmpwi TMP0, BC_JFORI -#endif - | decode_RD8 RD, SAVE0 -#if LJ_HASJIT - | beqy =>BC_JFORI -#endif - | b =>BC_FORI - | - |//----------------------------------------------------------------------- - |//-- Fast functions ----------------------------------------------------- - |//----------------------------------------------------------------------- - | - |.macro .ffunc, name - |->ff_ .. name: - |.endmacro - | - |.macro .ffunc_1, name - |->ff_ .. name: - | cmplwi NARGS8:RC, 8 - | lwz CARG3, 0(BASE) - | lwz CARG1, 4(BASE) - | blt ->fff_fallback - |.endmacro - | - |.macro .ffunc_2, name - |->ff_ .. name: - | cmplwi NARGS8:RC, 16 - | lwz CARG3, 0(BASE) - | lwz CARG4, 8(BASE) - | lwz CARG1, 4(BASE) - | lwz CARG2, 12(BASE) - | blt ->fff_fallback - |.endmacro - | - |.macro .ffunc_n, name - |->ff_ .. name: - | cmplwi NARGS8:RC, 8 - | lwz CARG3, 0(BASE) - | lfd FARG1, 0(BASE) - | blt ->fff_fallback - | checknum CARG3; bge ->fff_fallback - |.endmacro - | - |.macro .ffunc_nn, name - |->ff_ .. name: - | cmplwi NARGS8:RC, 16 - | lwz CARG3, 0(BASE) - | lfd FARG1, 0(BASE) - | lwz CARG4, 8(BASE) - | lfd FARG2, 8(BASE) - | blt ->fff_fallback - | checknum CARG3; bge ->fff_fallback - | checknum CARG4; bge ->fff_fallback - |.endmacro - | - |// Inlined GC threshold check. Caveat: uses TMP0 and TMP1. - |.macro ffgccheck - | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH) - | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) - | cmplw TMP0, TMP1 - | bgel ->fff_gcstep - |.endmacro - | - |//-- Base library: checks ----------------------------------------------- - | - |.ffunc_1 assert - | li TMP1, LJ_TFALSE - | la RA, -8(BASE) - | cmplw cr1, CARG3, TMP1 - | lwz PC, FRAME_PC(BASE) - | bge cr1, ->fff_fallback - | stw CARG3, 0(RA) - | addi RD, NARGS8:RC, 8 // Compute (nresults+1)*8. - | stw CARG1, 4(RA) - | beq ->fff_res // Done if exactly 1 argument. - | li TMP1, 8 - | subi RC, RC, 8 - |1: - | cmplw TMP1, RC - | lfdx f0, BASE, TMP1 - | stfdx f0, RA, TMP1 - | addi TMP1, TMP1, 8 - | bney <1 - | b ->fff_res - | - |.ffunc type - | cmplwi NARGS8:RC, 8 - | lwz CARG1, 0(BASE) - | blt ->fff_fallback - | subfc TMP0, TISNUM, CARG1 - | subfe TMP2, CARG1, CARG1 - | orc TMP1, TMP2, TMP0 - | addi TMP1, TMP1, ~LJ_TISNUM+1 - | slwi TMP1, TMP1, 3 - | la TMP2, CFUNC:RB->upvalue - | lfdx FARG1, TMP2, TMP1 - | b ->fff_resn - | - |//-- Base library: getters and setters --------------------------------- - | - |.ffunc_1 getmetatable - | checktab CARG3; bne >6 - |1: // Field metatable must be at same offset for GCtab and GCudata! - | lwz TAB:CARG1, TAB:CARG1->metatable - |2: - | li CARG3, LJ_TNIL - | cmplwi TAB:CARG1, 0 - | lwz STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH) - | beq ->fff_restv - | lwz TMP0, TAB:CARG1->hmask - | li CARG3, LJ_TTAB // Use metatable as default result. - | lwz TMP1, STR:RC->hash - | lwz NODE:TMP2, TAB:CARG1->node - | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask - | slwi TMP0, TMP1, 5 - | slwi TMP1, TMP1, 3 - | sub TMP1, TMP0, TMP1 - | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) - |3: // Rearranged logic, because we expect _not_ to find the key. - | lwz CARG4, NODE:TMP2->key - | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2) - | lwz CARG2, NODE:TMP2->val - | lwz TMP1, 4+offsetof(Node, val)(NODE:TMP2) - | checkstr CARG4; bne >4 - | cmpw TMP0, STR:RC; beq >5 - |4: - | lwz NODE:TMP2, NODE:TMP2->next - | cmplwi NODE:TMP2, 0 - | beq ->fff_restv // Not found, keep default result. - | b <3 - |5: - | checknil CARG2 - | beq ->fff_restv // Ditto for nil value. - | mr CARG3, CARG2 // Return value of mt.__metatable. - | mr CARG1, TMP1 - | b ->fff_restv - | - |6: - | cmpwi CARG3, LJ_TUDATA; beq <1 - | subfc TMP0, TISNUM, CARG3 - | subfe TMP2, CARG3, CARG3 - | orc TMP1, TMP2, TMP0 - | addi TMP1, TMP1, ~LJ_TISNUM+1 - | slwi TMP1, TMP1, 2 - | la TMP2, DISPATCH_GL(gcroot[GCROOT_BASEMT])(DISPATCH) - | lwzx TAB:CARG1, TMP2, TMP1 - | b <2 - | - |.ffunc_2 setmetatable - | // Fast path: no mt for table yet and not clearing the mt. - | checktab CARG3; bne ->fff_fallback - | lwz TAB:TMP1, TAB:CARG1->metatable - | checktab CARG4; bne ->fff_fallback - | cmplwi TAB:TMP1, 0 - | lbz TMP3, TAB:CARG1->marked - | bne ->fff_fallback - | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) - | stw TAB:CARG2, TAB:CARG1->metatable - | beq ->fff_restv - | barrierback TAB:CARG1, TMP3, TMP0 - | b ->fff_restv - | - |.ffunc rawget - | cmplwi NARGS8:RC, 16 - | lwz CARG4, 0(BASE) - | lwz TAB:CARG2, 4(BASE) - | blt ->fff_fallback - | checktab CARG4; bne ->fff_fallback - | la CARG3, 8(BASE) - | mr CARG1, L - | bl extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key) - | // Returns cTValue *. - | lfd FARG1, 0(CRET1) - | b ->fff_resn - | - |//-- Base library: conversions ------------------------------------------ - | - |.ffunc tonumber - | // Only handles the number case inline (without a base argument). - | cmplwi NARGS8:RC, 8 - | lwz CARG1, 0(BASE) - | lfd FARG1, 0(BASE) - | bne ->fff_fallback // Exactly one argument. - | checknum CARG1; bgt ->fff_fallback - | b ->fff_resn - | - |.ffunc_1 tostring - | // Only handles the string or number case inline. - | checkstr CARG3 - | // A __tostring method in the string base metatable is ignored. - | beq ->fff_restv // String key? - | // Handle numbers inline, unless a number base metatable is present. - | lwz TMP0, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])(DISPATCH) - | checknum CARG3 - | cmplwi cr1, TMP0, 0 - | stw BASE, L->base // Add frame since C call can throw. - | crorc 4*cr0+eq, 4*cr0+gt, 4*cr1+eq - | stw PC, SAVE_PC // Redundant (but a defined value). - | beq ->fff_fallback - | ffgccheck - | mr CARG1, L - | mr CARG2, BASE - if (LJ_DUALNUM) { - | bl extern lj_str_fromnumber // (lua_State *L, cTValue *o) - } else { - | bl extern lj_str_fromnum // (lua_State *L, lua_Number *np) - } - | // Returns GCstr *. - | li CARG3, LJ_TSTR - | b ->fff_restv - | - |//-- Base library: iterators ------------------------------------------- - | - |.ffunc next - | cmplwi NARGS8:RC, 8 - | lwz CARG1, 0(BASE) - | lwz TAB:CARG2, 4(BASE) - | blt ->fff_fallback - | stwx TISNIL, BASE, NARGS8:RC // Set missing 2nd arg to nil. - | checktab CARG1 - | lwz PC, FRAME_PC(BASE) - | bne ->fff_fallback - | stw BASE, L->base // Add frame since C call can throw. - | mr CARG1, L - | stw 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 - | li CARG3, LJ_TNIL - | beq ->fff_restv // End of traversal: return nil. - | lfd f0, 8(BASE) // Copy key and value to results. - | la RA, -8(BASE) - | lfd f1, 16(BASE) - | stfd f0, 0(RA) - | li RD, (2+1)*8 - | stfd f1, 8(RA) - | b ->fff_res - | - |.ffunc_1 pairs - | checktab CARG3 - | lwz PC, FRAME_PC(BASE) - | bne ->fff_fallback -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | lwz TAB:TMP2, TAB:CARG1->metatable - | lfd f0, CFUNC:RB->upvalue[0] - | cmplwi TAB:TMP2, 0 - | la RA, -8(BASE) - | bne ->fff_fallback -#else - | lfd f0, CFUNC:RB->upvalue[0] - | la RA, -8(BASE) -#endif - | stw TISNIL, 8(BASE) - | li RD, (3+1)*8 - | stfd f0, 0(RA) - | b ->fff_res - | - |.ffunc ipairs_aux - | cmplwi NARGS8:RC, 16 - | lwz CARG3, 0(BASE) - | lwz TAB:CARG1, 4(BASE) - | lwz CARG4, 8(BASE) - if (LJ_DUALNUM) { - | lwz TMP2, 12(BASE) - } else { - | lfd FARG2, 8(BASE) - } - | blt ->fff_fallback - | checktab CARG3 - | checknum cr1, CARG4 - | lwz PC, FRAME_PC(BASE) - if (LJ_DUALNUM) { - | bne ->fff_fallback - | bne cr1, ->fff_fallback - } else { - | lus TMP0, 0x3ff0 - | stw ZERO, TMPD_LO - | bne ->fff_fallback - | stw TMP0, TMPD_HI - | bge cr1, ->fff_fallback - | lfd FARG1, TMPD - | toint TMP2, FARG2, f0 - } - | lwz TMP0, TAB:CARG1->asize - | lwz TMP1, TAB:CARG1->array - if (!LJ_DUALNUM) { - | fadd FARG2, FARG2, FARG1 - } - | addi TMP2, TMP2, 1 - | la RA, -8(BASE) - | cmplw TMP0, TMP2 - if (LJ_DUALNUM) { - | stw TISNUM, 0(RA) - | slwi TMP3, TMP2, 3 - | stw TMP2, 4(RA) - } else { - | slwi TMP3, TMP2, 3 - | stfd FARG2, 0(RA) - } - | ble >2 // Not in array part? - | lwzx TMP2, TMP1, TMP3 - | lfdx f0, TMP1, TMP3 - |1: - | checknil TMP2 - | li RD, (0+1)*8 - | beq ->fff_res // End of iteration, return 0 results. - | li RD, (2+1)*8 - | stfd f0, 8(RA) - | b ->fff_res - |2: // Check for empty hash part first. Otherwise call C function. - | lwz TMP0, TAB:CARG1->hmask - | cmplwi TMP0, 0 - | li RD, (0+1)*8 - | beq ->fff_res - | mr CARG2, TMP2 - | bl extern lj_tab_getinth // (GCtab *t, int32_t key) - | // Returns cTValue * or NULL. - | cmplwi CRET1, 0 - | li RD, (0+1)*8 - | beq ->fff_res - | lwz TMP2, 0(CRET1) - | lfd f0, 0(CRET1) - | b <1 - | - |.ffunc_1 ipairs - | checktab CARG3 - | lwz PC, FRAME_PC(BASE) - | bne ->fff_fallback -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | lwz TAB:TMP2, TAB:CARG1->metatable - | lfd f0, CFUNC:RB->upvalue[0] - | cmplwi TAB:TMP2, 0 - | la RA, -8(BASE) - | bne ->fff_fallback -#else - | lfd f0, CFUNC:RB->upvalue[0] - | la RA, -8(BASE) -#endif - if (LJ_DUALNUM) { - | stw TISNUM, 8(BASE) - } else { - | stw ZERO, 8(BASE) - } - | stw ZERO, 12(BASE) - | li RD, (3+1)*8 - | stfd f0, 0(RA) - | b ->fff_res - | - |//-- Base library: catch errors ---------------------------------------- - | - |.ffunc pcall - | cmplwi NARGS8:RC, 8 - | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | blt ->fff_fallback - | mr TMP2, BASE - | la BASE, 8(BASE) - | // Remember active hook before pcall. - | rlwinm TMP3, TMP3, 32-HOOK_ACTIVE_SHIFT, 31, 31 - | subi NARGS8:RC, NARGS8:RC, 8 - | addi PC, TMP3, 8+FRAME_PCALL - | b ->vm_call_dispatch - | - |.ffunc xpcall - | cmplwi NARGS8:RC, 16 - | lwz CARG4, 8(BASE) - | lfd FARG2, 8(BASE) - | lfd FARG1, 0(BASE) - | blt ->fff_fallback - | lbz TMP1, DISPATCH_GL(hookmask)(DISPATCH) - | mr TMP2, BASE - | checkfunc CARG4; bne ->fff_fallback // Traceback must be a function. - | la BASE, 16(BASE) - | // Remember active hook before pcall. - | rlwinm TMP1, TMP1, 32-HOOK_ACTIVE_SHIFT, 31, 31 - | stfd FARG2, 0(TMP2) // Swap function and traceback. - | subi NARGS8:RC, NARGS8:RC, 16 - | stfd FARG1, 8(TMP2) - | addi PC, TMP1, 16+FRAME_PCALL - | b ->vm_call_dispatch - | - |//-- Coroutine library -------------------------------------------------- - | - |.macro coroutine_resume_wrap, resume - |.if resume - |.ffunc_1 coroutine_resume - | cmpwi CARG3, LJ_TTHREAD; bne ->fff_fallback - |.else - |.ffunc coroutine_wrap_aux - | lwz L:CARG1, CFUNC:RB->upvalue[0].gcr - |.endif - | lbz TMP0, L:CARG1->status - | lwz TMP1, L:CARG1->cframe - | lwz CARG2, L:CARG1->top - | cmplwi cr0, TMP0, LUA_YIELD - | lwz TMP2, L:CARG1->base - | cmplwi cr1, TMP1, 0 - | lwz TMP0, L:CARG1->maxstack - | cmplw cr7, CARG2, TMP2 - | lwz PC, FRAME_PC(BASE) - | crorc 4*cr6+lt, 4*cr0+gt, 4*cr1+eq // st>LUA_YIELD || cframe!=0 - | add TMP2, CARG2, NARGS8:RC - | crandc 4*cr6+gt, 4*cr7+eq, 4*cr0+eq // base==top && st!=LUA_YIELD - | cmplw cr1, TMP2, TMP0 - | cror 4*cr6+lt, 4*cr6+lt, 4*cr6+gt - | stw PC, SAVE_PC - | cror 4*cr6+lt, 4*cr6+lt, 4*cr1+gt // cond1 || cond2 || stackov - | stw BASE, L->base - | blt cr6, ->fff_fallback - |1: - |.if resume - | addi BASE, BASE, 8 // Keep resumed thread in stack for GC. - | subi NARGS8:RC, NARGS8:RC, 8 - | subi TMP2, TMP2, 8 - |.endif - | stw TMP2, L:CARG1->top - | li TMP1, 0 - | stw BASE, L->top - |2: // Move args to coroutine. - | cmpw TMP1, NARGS8:RC - | lfdx f0, BASE, TMP1 - | beq >3 - | stfdx f0, CARG2, TMP1 - | addi TMP1, TMP1, 8 - | b <2 - |3: - | li CARG3, 0 - | mr L:SAVE0, L:CARG1 - | li CARG4, 0 - | bl ->vm_resume // (lua_State *L, TValue *base, 0, 0) - | // Returns thread status. - |4: - | lwz TMP2, L:SAVE0->base - | cmplwi CRET1, LUA_YIELD - | lwz TMP3, L:SAVE0->top - | li_vmstate INTERP - | lwz BASE, L->base - | st_vmstate - | bgt >8 - | sub RD, TMP3, TMP2 - | lwz TMP0, L->maxstack - | cmplwi RD, 0 - | add TMP1, BASE, RD - | beq >6 // No results? - | cmplw TMP1, TMP0 - | li TMP1, 0 - | bgt >9 // Need to grow stack? - | - | subi TMP3, RD, 8 - | stw TMP2, L:SAVE0->top // Clear coroutine stack. - |5: // Move results from coroutine. - | cmplw TMP1, TMP3 - | lfdx f0, TMP2, TMP1 - | stfdx f0, BASE, TMP1 - | addi TMP1, TMP1, 8 - | bne <5 - |6: - | andi. TMP0, PC, FRAME_TYPE - |.if resume - | li TMP1, LJ_TTRUE - | la RA, -8(BASE) - | stw TMP1, -8(BASE) // Prepend true to results. - | addi RD, RD, 16 - |.else - | mr RA, BASE - | addi RD, RD, 8 - |.endif - |7: - | stw PC, SAVE_PC - | mr MULTRES, RD - | beq ->BC_RET_Z - | b ->vm_return - | - |8: // Coroutine returned with error (at co->top-1). - |.if resume - | andi. TMP0, PC, FRAME_TYPE - | la TMP3, -8(TMP3) - | li TMP1, LJ_TFALSE - | lfd f0, 0(TMP3) - | stw TMP3, L:SAVE0->top // Remove error from coroutine stack. - | li RD, (2+1)*8 - | stw TMP1, -8(BASE) // Prepend false to results. - | la RA, -8(BASE) - | stfd f0, 0(BASE) // Copy error message. - | b <7 - |.else - | mr CARG1, L - | mr CARG2, L:SAVE0 - | bl extern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co) - |.endif - | - |9: // Handle stack expansion on return from yield. - | mr CARG1, L - | srwi CARG2, RD, 3 - | bl extern lj_state_growstack // (lua_State *L, int n) - | li CRET1, 0 - | b <4 - |.endmacro - | - | coroutine_resume_wrap 1 // coroutine.resume - | coroutine_resume_wrap 0 // coroutine.wrap - | - |.ffunc coroutine_yield - | lwz TMP0, L->cframe - | add TMP1, BASE, NARGS8:RC - | stw BASE, L->base - | andi. TMP0, TMP0, CFRAME_RESUME - | stw TMP1, L->top - | li CRET1, LUA_YIELD - | beq ->fff_fallback - | stw ZERO, L->cframe - | stb CRET1, L->status - | b ->vm_leave_unw - | - |//-- Math library ------------------------------------------------------- - | - |.ffunc_1 math_abs - | checknum CARG3 - if (LJ_DUALNUM) { - | bne >2 - | srawi TMP1, CARG1, 31 - | xor TMP2, TMP1, CARG1 - | sub. CARG1, TMP2, TMP1 - | blt >1 - |->fff_resi: - | lwz PC, FRAME_PC(BASE) - | la RA, -8(BASE) - | stw TISNUM, -8(BASE) - | stw CRET1, -4(BASE) - | b ->fff_res1 - |1: - | lus CARG3, 0x41e0 // 2^31. - | li CARG1, 0 - | b ->fff_restv - |2: - } - | bge ->fff_fallback - | rlwinm CARG3, CARG3, 0, 1, 31 - | // Fallthrough. - | - |->fff_restv: - | // CARG3/CARG1 = TValue result. - | lwz PC, FRAME_PC(BASE) - | stw CARG3, -8(BASE) - | la RA, -8(BASE) - | stw CARG1, -4(BASE) - |->fff_res1: - | // RA = results, PC = return. - | li RD, (1+1)*8 - |->fff_res: - | // RA = results, RD = (nresults+1)*8, PC = return. - | andi. TMP0, PC, FRAME_TYPE - | mr MULTRES, RD - | bney ->vm_return - | lwz INS, -4(PC) - | decode_RB8 RB, INS - |5: - | cmplw RB, RD // More results expected? - | decode_RA8 TMP0, INS - | bgt >6 - | ins_next1 - | // Adjust BASE. KBASE is assumed to be set for the calling frame. - | sub BASE, RA, TMP0 - | ins_next2 - | - |6: // Fill up results with nil. - | subi TMP1, RD, 8 - | addi RD, RD, 8 - | stwx TISNIL, RA, TMP1 - | b <5 - | - |.macro math_extern, func - | .ffunc_n math_ .. func - | bl extern func - | b ->fff_resn - |.endmacro - | - |.macro math_extern2, func - | .ffunc_nn math_ .. func - | bl extern func - | b ->fff_resn - |.endmacro - | - |.macro math_round, func - | .ffunc_1 math_ .. func - | checknum CARG3; beqy ->fff_restv - | rlwinm TMP2, CARG3, 12, 21, 31 - | bge ->fff_fallback - | addic. TMP2, TMP2, -1023 // exp = exponent(x) - 1023 - | cmplwi cr1, TMP2, 31 // 0 <= exp < 31? - | subfic TMP0, TMP2, 31 - | blt >3 - | slwi TMP1, CARG3, 11 - | srwi TMP3, CARG1, 21 - | oris TMP1, TMP1, 0x8000 - | addi TMP2, TMP2, 1 - | or TMP1, TMP1, TMP3 - | slwi CARG2, CARG1, 11 - | bge cr1, >4 - | slw TMP3, TMP1, TMP2 - | srw CARG1, TMP1, TMP0 - | or TMP3, TMP3, CARG2 - | srawi TMP2, CARG3, 31 - |.if "func" == "floor" - | and TMP1, TMP3, TMP2 - | addic TMP0, TMP1, -1 - | subfe TMP1, TMP0, TMP1 - | add CARG1, CARG1, TMP1 - | xor CARG1, CARG1, TMP2 - | sub CARG1, CARG1, TMP2 - | b ->fff_resi - |.else - | andc TMP1, TMP3, TMP2 - | addic TMP0, TMP1, -1 - | subfe TMP1, TMP0, TMP1 - | addo. CARG1, CARG1, TMP1 - | xor CARG1, CARG1, TMP2 - | sub CARG1, CARG1, TMP2 - | bns ->fff_resi - | // Potential overflow. - | mcrxr cr0; bley ->fff_resi // Ignore unrelated overflow. - | lus CARG3, 0x41e0 // 2^31. - | li CARG1, 0 - | b ->fff_restv - |.endif - |3: // |x| < 1 - | add TMP2, CARG3, CARG3 - | srawi TMP1, CARG3, 31 - | or TMP2, CARG1, TMP2 // ztest = (hi+hi) | lo - |.if "func" == "floor" - | and TMP1, TMP2, TMP1 // (ztest & sign) == 0 ? 0 : -1 - | subfic TMP2, TMP1, 0 - | subfe CARG1, CARG1, CARG1 - |.else - | andc TMP1, TMP2, TMP1 // (ztest & ~sign) == 0 ? 0 : 1 - | addic TMP2, TMP1, -1 - | subfe CARG1, TMP2, TMP1 - |.endif - | b ->fff_resi - |4: // exp >= 31. Check for -(2^31). - | xoris TMP1, TMP1, 0x8000 - | srawi TMP2, CARG3, 31 - |.if "func" == "floor" - | or TMP1, TMP1, CARG2 - |.endif - | orc. TMP1, TMP1, TMP2 - | crand 4*cr0+eq, 4*cr0+eq, 4*cr1+eq - | lus CARG1, 0x8000 // -(2^31). - | beqy ->fff_resi - |5: - | lfd FARG1, 0(BASE) - | bl extern func - | b ->fff_resn - |.endmacro - | - if (LJ_DUALNUM) { - | math_round floor - | math_round ceil - } else { - | // NYI: use internal implementation. - | math_extern floor - | math_extern ceil - } - | - | math_extern sqrt - | math_extern log - | math_extern log10 - | math_extern exp - | math_extern sin - | math_extern cos - | math_extern tan - | math_extern asin - | math_extern acos - | math_extern atan - | math_extern sinh - | math_extern cosh - | math_extern tanh - | math_extern2 pow - | math_extern2 atan2 - | math_extern2 fmod - | - |->ff_math_deg: - |.ffunc_n math_rad - | lfd FARG2, CFUNC:RB->upvalue[0] - | fmul FARG1, FARG1, FARG2 - | b ->fff_resn - | - if (LJ_DUALNUM) { - |.ffunc math_ldexp - | cmplwi NARGS8:RC, 16 - | lwz CARG3, 0(BASE) - | lfd FARG1, 0(BASE) - | lwz CARG4, 8(BASE) - | lwz CARG1, 12(BASE) - | blt ->fff_fallback - | checknum CARG3; bge ->fff_fallback - | checknum CARG4; bne ->fff_fallback - } else { - |.ffunc_nn math_ldexp - | toint CARG1, FARG2 - } - | bl extern ldexp - | b ->fff_resn - | - |.ffunc_n math_frexp - | la CARG1, DISPATCH_GL(tmptv)(DISPATCH) - | lwz PC, FRAME_PC(BASE) - | bl extern frexp - | lwz TMP1, DISPATCH_GL(tmptv)(DISPATCH) - | la RA, -8(BASE) - if (!LJ_DUALNUM) { - | tonum_i FARG2, TMP1 - } - | stfd FARG1, 0(RA) - | li RD, (2+1)*8 - if (LJ_DUALNUM) { - | stw TISNUM, 8(RA) - | stw TMP1, 12(RA) - } else { - | stfd FARG2, 8(RA) - } - | b ->fff_res - | - |.ffunc_n math_modf - | la CARG1, -8(BASE) - | lwz PC, FRAME_PC(BASE) - | bl extern modf - | la RA, -8(BASE) - | stfd FARG1, 0(BASE) - | li RD, (2+1)*8 - | b ->fff_res - | - |.macro math_minmax, name, ismax - ||if (LJ_DUALNUM) { - | .ffunc_1 name - | checknum CARG3 - | addi TMP1, BASE, 8 - | add TMP2, BASE, NARGS8:RC - | bne >4 - |1: // Handle integers. - | lwz CARG4, 0(TMP1) - | cmplw cr1, TMP1, TMP2 - | lwz CARG2, 4(TMP1) - | bge cr1, ->fff_resi - | checknum CARG4 - | xoris TMP0, CARG1, 0x8000 - | xoris TMP3, CARG2, 0x8000 - | bne >3 - | subfc TMP3, TMP3, TMP0 - | subfe TMP0, TMP0, TMP0 - |.if ismax - | andc TMP3, TMP3, TMP0 - |.else - | and TMP3, TMP3, TMP0 - |.endif - | add CARG1, TMP3, CARG2 - | addi TMP1, TMP1, 8 - | b <1 - |3: - | bge ->fff_fallback - | // Convert intermediate result to number and continue below. - | tonum_i FARG1, CARG1 - | lfd FARG2, 0(TMP1) - | b >6 - |4: - | lfd FARG1, 0(BASE) - | bge ->fff_fallback - |5: // Handle numbers. - | lwz CARG4, 0(TMP1) - | cmplw cr1, TMP1, TMP2 - | lfd FARG2, 0(TMP1) - | bge cr1, ->fff_resn - | checknum CARG4; bge >7 - |6: - | fsub f0, FARG1, FARG2 - | addi TMP1, TMP1, 8 - |.if ismax - | fsel FARG1, f0, FARG1, FARG2 - |.else - | fsel FARG1, f0, FARG2, FARG1 - |.endif - | b <5 - |7: // Convert integer to number and continue above. - | lwz CARG2, 4(TMP1) - | bne ->fff_fallback - | tonum_i FARG2, CARG2 - | b <6 - ||} else { - | .ffunc_n name - | li TMP1, 8 - |1: - | lwzx CARG2, BASE, TMP1 - | lfdx FARG2, BASE, TMP1 - | cmplw cr1, TMP1, NARGS8:RC - | checknum CARG2 - | bge cr1, ->fff_resn - | bge ->fff_fallback - | fsub f0, FARG1, FARG2 - | addi TMP1, TMP1, 8 - |.if ismax - | fsel FARG1, f0, FARG1, FARG2 - |.else - | fsel FARG1, f0, FARG2, FARG1 - |.endif - | b <1 - ||} - |.endmacro - | - | math_minmax math_min, 0 - | math_minmax math_max, 1 - | - |//-- String library ----------------------------------------------------- - | - |.ffunc_1 string_len - | checkstr CARG3; bne ->fff_fallback - | lwz CRET1, STR:CARG1->len - | b ->fff_resi - | - |.ffunc string_byte // Only handle the 1-arg case here. - | cmplwi NARGS8:RC, 8 - | lwz CARG3, 0(BASE) - | lwz STR:CARG1, 4(BASE) - | bne ->fff_fallback // Need exactly 1 argument. - | checkstr CARG3 - | bne ->fff_fallback - | lwz TMP0, STR:CARG1->len - if (LJ_DUALNUM) { - | lbz CARG1, STR:CARG1[1] // Access is always ok (NUL at end). - | li RD, (0+1)*8 - | lwz PC, FRAME_PC(BASE) - | cmplwi TMP0, 0 - | la RA, -8(BASE) - | beqy ->fff_res - | b ->fff_resi - } else { - | lbz TMP1, STR:CARG1[1] // Access is always ok (NUL at end). - | addic TMP3, TMP0, -1 // RD = ((str->len != 0)+1)*8 - | subfe RD, TMP3, TMP0 - | stw TMP1, TONUM_LO // Inlined tonum_u f0, TMP1. - | addi RD, RD, 1 - | lfd f0, TONUM_D - | la RA, -8(BASE) - | lwz PC, FRAME_PC(BASE) - | fsub f0, f0, TOBIT - | slwi RD, RD, 3 - | stfd f0, 0(RA) - | b ->fff_res - } - | - |.ffunc string_char // Only handle the 1-arg case here. - | ffgccheck - | cmplwi NARGS8:RC, 8 - | lwz CARG3, 0(BASE) - if (LJ_DUALNUM) { - | lwz TMP0, 4(BASE) - | bne ->fff_fallback // Exactly 1 argument. - | checknum CARG3; bne ->fff_fallback - | la CARG2, 7(BASE) - } else { - | lfd FARG1, 0(BASE) - | bne ->fff_fallback // Exactly 1 argument. - | checknum CARG3; bge ->fff_fallback - | toint TMP0, FARG1 - | la CARG2, TMPD_BLO - } - | li CARG3, 1 - | cmplwi TMP0, 255; bgt ->fff_fallback - |->fff_newstr: - | mr CARG1, L - | stw BASE, L->base - | stw PC, SAVE_PC - | bl extern lj_str_new // (lua_State *L, char *str, size_t l) - | // Returns GCstr *. - | lwz BASE, L->base - | li CARG3, LJ_TSTR - | b ->fff_restv - | - |.ffunc string_sub - | ffgccheck - | cmplwi NARGS8:RC, 16 - | lwz CARG3, 16(BASE) - if (!LJ_DUALNUM) { - | lfd f0, 16(BASE) - } - | lwz TMP0, 0(BASE) - | lwz STR:CARG1, 4(BASE) - | blt ->fff_fallback - | lwz CARG2, 8(BASE) - if (LJ_DUALNUM) { - | lwz TMP1, 12(BASE) - } else { - | lfd f1, 8(BASE) - } - | li TMP2, -1 - | beq >1 - if (LJ_DUALNUM) { - | checknum CARG3 - | lwz TMP2, 20(BASE) - | bne ->fff_fallback - |1: - | checknum CARG2; bne ->fff_fallback - } else { - | checknum CARG3; bge ->fff_fallback - | toint TMP2, f0 - |1: - | checknum CARG2; bge ->fff_fallback - } - | checkstr TMP0; bne ->fff_fallback - if (!LJ_DUALNUM) { - | toint TMP1, f1 - } - | lwz TMP0, STR:CARG1->len - | cmplw TMP0, TMP2 // len < end? (unsigned compare) - | addi TMP3, TMP2, 1 - | blt >5 - |2: - | cmpwi TMP1, 0 // start <= 0? - | add TMP3, TMP1, TMP0 - | ble >7 - |3: - | sub CARG3, TMP2, TMP1 - | addi CARG2, STR:CARG1, #STR-1 - | srawi TMP0, CARG3, 31 - | addi CARG3, CARG3, 1 - | add CARG2, CARG2, TMP1 - | andc CARG3, CARG3, TMP0 - | b ->fff_newstr - | - |5: // Negative end or overflow. - | sub CARG2, TMP0, TMP2 - | srawi CARG2, CARG2, 31 - | andc TMP3, TMP3, CARG2 // end = end > len ? len : end+len+1 - | add TMP2, TMP0, TMP3 - | b <2 - | - |7: // Negative start or underflow. - | addic CARG3, TMP1, -1 - | subfe CARG3, CARG3, CARG3 - | srawi CARG2, TMP3, 31 // Note: modifies carry. - | andc TMP3, TMP3, CARG3 - | andc TMP1, TMP3, CARG2 - | addi TMP1, TMP1, 1 // start = 1 + (start ? start+len : 0) - | b <3 - | - |.ffunc string_rep // Only handle the 1-char case inline. - | ffgccheck - | cmplwi NARGS8:RC, 16 - | lwz TMP0, 0(BASE) - | lwz STR:CARG1, 4(BASE) - | lwz CARG4, 8(BASE) - if (LJ_DUALNUM) { - | lwz CARG3, 12(BASE) - } else { - | lfd FARG2, 8(BASE) - } - | blt ->fff_fallback - | checkstr TMP0; bne ->fff_fallback - if (LJ_DUALNUM) { - | checknum CARG4; bne ->fff_fallback - } else { - | checknum CARG4; bge ->fff_fallback - | toint CARG3, FARG2 - } - | lwz TMP0, STR:CARG1->len - | cmpwi CARG3, 0 - | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) - | ble >2 // Count <= 0? (or non-int) - | cmplwi TMP0, 1 - | subi TMP2, CARG3, 1 - | blt >2 // Zero length string? - | cmplw cr1, TMP1, CARG3 - | bne ->fff_fallback // Fallback for > 1-char strings. - | lbz TMP0, STR:CARG1[1] - | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) - | blt cr1, ->fff_fallback - |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). - | cmplwi TMP2, 0 - | stbx TMP0, CARG2, TMP2 - | subi TMP2, TMP2, 1 - | bne <1 - | b ->fff_newstr - |2: // Return empty string. - | la STR:CARG1, DISPATCH_GL(strempty)(DISPATCH) - | li CARG3, LJ_TSTR - | b ->fff_restv - | - |.ffunc string_reverse - | ffgccheck - | cmplwi NARGS8:RC, 8 - | lwz CARG3, 0(BASE) - | lwz STR:CARG1, 4(BASE) - | blt ->fff_fallback - | checkstr CARG3 - | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) - | bne ->fff_fallback - | lwz CARG3, STR:CARG1->len - | la CARG1, #STR(STR:CARG1) - | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) - | li TMP2, 0 - | cmplw TMP1, CARG3 - | subi TMP3, CARG3, 1 - | blt ->fff_fallback - |1: // Reverse string copy. - | cmpwi TMP3, 0 - | lbzx TMP1, CARG1, TMP2 - | blty ->fff_newstr - | stbx TMP1, CARG2, TMP3 - | subi TMP3, TMP3, 1 - | addi TMP2, TMP2, 1 - | b <1 - | - |.macro ffstring_case, name, lo - | .ffunc name - | ffgccheck - | cmplwi NARGS8:RC, 8 - | lwz CARG3, 0(BASE) - | lwz STR:CARG1, 4(BASE) - | blt ->fff_fallback - | checkstr CARG3 - | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) - | bne ->fff_fallback - | lwz CARG3, STR:CARG1->len - | la CARG1, #STR(STR:CARG1) - | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) - | cmplw TMP1, CARG3 - | li TMP2, 0 - | blt ->fff_fallback - |1: // ASCII case conversion. - | cmplw TMP2, CARG3 - | lbzx TMP1, CARG1, TMP2 - | bgey ->fff_newstr - | subi TMP0, TMP1, lo - | xori TMP3, TMP1, 0x20 - | addic TMP0, TMP0, -26 - | subfe TMP3, TMP3, TMP3 - | andi. TMP3, TMP3, 0x20 - | xor TMP1, TMP1, TMP3 - | stbx TMP1, CARG2, TMP2 - | addi TMP2, TMP2, 1 - | b <1 - |.endmacro - | - |ffstring_case string_lower, 65 - |ffstring_case string_upper, 97 - | - |//-- Table library ------------------------------------------------------ - | - |.ffunc_1 table_getn - | checktab CARG3; bne ->fff_fallback - | bl extern lj_tab_len // (GCtab *t) - | // Returns uint32_t (but less than 2^31). - | b ->fff_resi - | - |//-- Bit library -------------------------------------------------------- - | - |.macro .ffunc_bit, name - ||if (LJ_DUALNUM) { - | .ffunc_1 bit_..name - | checknum CARG3; bnel ->fff_tobit_fb - ||} else { - | .ffunc_n bit_..name - | fadd FARG1, FARG1, TOBIT - | stfd FARG1, TMPD - | lwz CARG1, TMPD_LO - ||} - |.endmacro - | - |.macro .ffunc_bit_op, name, ins - | .ffunc_bit name - | addi TMP1, BASE, 8 - | add TMP2, BASE, NARGS8:RC - |1: - | lwz CARG4, 0(TMP1) - | cmplw cr1, TMP1, TMP2 - ||if (LJ_DUALNUM) { - | lwz CARG2, 4(TMP1) - ||} else { - | lfd FARG1, 0(TMP1) - ||} - | bgey cr1, ->fff_resi - | checknum CARG4 - ||if (LJ_DUALNUM) { - | bnel ->fff_bitop_fb - ||} else { - | fadd FARG1, FARG1, TOBIT - | bge ->fff_fallback - | stfd FARG1, TMPD - | lwz CARG2, TMPD_LO - ||} - | ins CARG1, CARG1, CARG2 - | addi TMP1, TMP1, 8 - | b <1 - |.endmacro - | - |.ffunc_bit_op band, and - |.ffunc_bit_op bor, or - |.ffunc_bit_op bxor, xor - | - |.ffunc_bit bswap - | rotlwi TMP0, CARG1, 8 - | rlwimi TMP0, CARG1, 24, 0, 7 - | rlwimi TMP0, CARG1, 24, 16, 23 - | mr CRET1, TMP0 - | b ->fff_resi - | - |.ffunc_bit bnot - | not CRET1, CARG1 - | b ->fff_resi - | - |.macro .ffunc_bit_sh, name, ins, shmod - ||if (LJ_DUALNUM) { - | .ffunc_2 bit_..name - | checknum CARG3; bnel ->fff_tobit_fb - | // Note: no inline conversion from number for 2nd argument! - | checknum CARG4; bne ->fff_fallback - ||} else { - | .ffunc_nn bit_..name - | fadd FARG1, FARG1, TOBIT - | fadd FARG2, FARG2, TOBIT - | stfd FARG1, TMPD - | lwz CARG1, TMPD_LO - | stfd FARG2, TMPD - | lwz CARG2, TMPD_LO - ||} - |.if shmod == 1 - | rlwinm CARG2, CARG2, 0, 27, 31 - |.elif shmod == 2 - | neg CARG2, CARG2 - |.endif - | ins CRET1, CARG1, CARG2 - | b ->fff_resi - |.endmacro - | - |.ffunc_bit_sh lshift, slw, 1 - |.ffunc_bit_sh rshift, srw, 1 - |.ffunc_bit_sh arshift, sraw, 1 - |.ffunc_bit_sh rol, rotlw, 0 - |.ffunc_bit_sh ror, rotlw, 2 - | - |.ffunc_bit tobit - if (LJ_DUALNUM) { - | b ->fff_resi - } else { - |->fff_resi: - | tonum_i FARG1, CRET1 - } - |->fff_resn: - | lwz PC, FRAME_PC(BASE) - | la RA, -8(BASE) - | stfd FARG1, -8(BASE) - | b ->fff_res1 - | - |// Fallback FP number to bit conversion. - |->fff_tobit_fb: - if (LJ_DUALNUM) { - | lfd FARG1, 0(BASE) - | bgt ->fff_fallback - | fadd FARG1, FARG1, TOBIT - | stfd FARG1, TMPD - | lwz CARG1, TMPD_LO - | blr - } - |->fff_bitop_fb: - if (LJ_DUALNUM) { - | lfd FARG1, 0(TMP1) - | bgt ->fff_fallback - | fadd FARG1, FARG1, TOBIT - | stfd FARG1, TMPD - | lwz CARG2, TMPD_LO - | blr - } - | - |//----------------------------------------------------------------------- - | - |->fff_fallback: // Call fast function fallback handler. - | // BASE = new base, RB = CFUNC, RC = nargs*8 - | lwz TMP3, CFUNC:RB->f - | add TMP1, BASE, NARGS8:RC - | lwz PC, FRAME_PC(BASE) // Fallback may overwrite PC. - | addi TMP0, TMP1, 8*LUA_MINSTACK - | lwz TMP2, L->maxstack - | stw PC, SAVE_PC // Redundant (but a defined value). - | cmplw TMP0, TMP2 - | stw BASE, L->base - | stw TMP1, L->top - | mr CARG1, L - | bgt >5 // Need to grow stack. - | mtctr TMP3 - | bctrl // (lua_State *L) - | // Either throws an error, or recovers and returns -1, 0 or nresults+1. - | lwz BASE, L->base - | cmpwi CRET1, 0 - | slwi RD, CRET1, 3 - | la RA, -8(BASE) - | bgt ->fff_res // Returned nresults+1? - |1: // Returned 0 or -1: retry fast path. - | lwz TMP0, L->top - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | sub NARGS8:RC, TMP0, BASE - | bne ->vm_call_tail // Returned -1? - | ins_callt // Returned 0: retry fast path. - | - |// Reconstruct previous base for vmeta_call during tailcall. - |->vm_call_tail: - | andi. TMP0, PC, FRAME_TYPE - | rlwinm TMP1, PC, 0, 0, 28 - | bne >3 - | lwz INS, -4(PC) - | decode_RA8 TMP1, INS - | addi TMP1, TMP1, 8 - |3: - | sub TMP2, BASE, TMP1 - | b ->vm_call_dispatch // Resolve again for tailcall. - | - |5: // Grow stack for fallback handler. - | li CARG2, LUA_MINSTACK - | bl extern lj_state_growstack // (lua_State *L, int n) - | lwz BASE, L->base - | cmpw TMP0, TMP0 // Set 4*cr0+eq to force retry. - | b <1 - | - |->fff_gcstep: // Call GC step function. - | // BASE = new base, RC = nargs*8 - | mflr SAVE0 - | stw BASE, L->base - | add TMP0, BASE, NARGS8:RC - | stw PC, SAVE_PC // Redundant (but a defined value). - | stw TMP0, L->top - | mr CARG1, L - | bl extern lj_gc_step // (lua_State *L) - | lwz BASE, L->base - | mtlr SAVE0 - | lwz TMP0, L->top - | sub NARGS8:RC, TMP0, BASE - | lwz CFUNC:RB, FRAME_FUNC(BASE) - | blr - | - |//----------------------------------------------------------------------- - |//-- Special dispatch targets ------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_record: // Dispatch target for recording phase. -#if LJ_HASJIT - | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | andi. TMP0, TMP3, HOOK_VMEVENT // No recording while in vmevent. - | bne >5 - | // Decrement the hookcount for consistency, but always do the call. - | lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH) - | andi. TMP0, TMP3, HOOK_ACTIVE - | bne >1 - | subi TMP2, TMP2, 1 - | andi. TMP0, TMP3, LUA_MASKLINE|LUA_MASKCOUNT - | beqy >1 - | stw TMP2, DISPATCH_GL(hookcount)(DISPATCH) - | b >1 -#endif - | - |->vm_rethook: // Dispatch target for return hooks. - | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | andi. TMP0, TMP3, HOOK_ACTIVE // Hook already active? - | beq >1 - |5: // Re-dispatch to static ins. - | addi TMP1, TMP1, GG_DISP2STATIC // Assumes decode_OP4 TMP1, INS. - | lwzx TMP0, DISPATCH, TMP1 - | mtctr TMP0 - | bctr - | - |->vm_inshook: // Dispatch target for instr/line hooks. - | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH) - | andi. TMP0, TMP3, HOOK_ACTIVE // Hook already active? - | rlwinm TMP0, TMP3, 31-LUA_HOOKLINE, 31, 0 - | bne <5 - | - | cmpwi cr1, TMP0, 0 - | addic. TMP2, TMP2, -1 - | beq cr1, <5 - | stw TMP2, DISPATCH_GL(hookcount)(DISPATCH) - | beq >1 - | bge cr1, <5 - |1: - | mr CARG1, L - | stw MULTRES, SAVE_MULTRES - | mr CARG2, PC - | stw BASE, L->base - | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. - | bl extern lj_dispatch_ins // (lua_State *L, const BCIns *pc) - |3: - | lwz BASE, L->base - |4: // Re-dispatch to static ins. - | lwz INS, -4(PC) - | decode_OP4 TMP1, INS - | decode_RB8 RB, INS - | addi TMP1, TMP1, GG_DISP2STATIC - | decode_RD8 RD, INS - | lwzx TMP0, DISPATCH, TMP1 - | decode_RA8 RA, INS - | decode_RC8 RC, INS - | mtctr TMP0 - | bctr - | - |->cont_hook: // Continue from hook yield. - | addi PC, PC, 4 - | lwz MULTRES, -20(RB) // Restore MULTRES for *M ins. - | b <4 - | - |->vm_hotloop: // Hot loop counter underflow. -#if LJ_HASJIT - | lwz LFUNC:TMP1, FRAME_FUNC(BASE) - | addi CARG1, DISPATCH, GG_DISP2J - | stw PC, SAVE_PC - | lwz TMP1, LFUNC:TMP1->pc - | mr CARG2, PC - | stw L, DISPATCH_J(L)(DISPATCH) - | lbz TMP1, PC2PROTO(framesize)(TMP1) - | stw BASE, L->base - | slwi TMP1, TMP1, 3 - | add TMP1, BASE, TMP1 - | stw TMP1, L->top - | bl extern lj_trace_hot // (jit_State *J, const BCIns *pc) - | b <3 -#endif - | - |->vm_callhook: // Dispatch target for call hooks. - | mr CARG2, PC -#if LJ_HASJIT - | b >1 -#endif - | - |->vm_hotcall: // Hot call counter underflow. -#if LJ_HASJIT - | ori CARG2, PC, 1 - |1: -#endif - | add TMP0, BASE, RC - | stw PC, SAVE_PC - | mr CARG1, L - | stw BASE, L->base - | sub RA, RA, BASE - | stw TMP0, L->top - | bl extern lj_dispatch_call // (lua_State *L, const BCIns *pc) - | // Returns ASMFunction. - | lwz BASE, L->base - | lwz TMP0, L->top - | stw ZERO, SAVE_PC // Invalidate for subsequent line hook. - | sub NARGS8:RC, TMP0, BASE - | add RA, BASE, RA - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | lwz INS, -4(PC) - | mtctr CRET1 - | bctr - | - |//----------------------------------------------------------------------- - |//-- Trace exit handler ------------------------------------------------- - |//----------------------------------------------------------------------- - | - |.macro savex_, a, b, c, d - | stfd f..a, 16+a*8(sp) - | stfd f..b, 16+b*8(sp) - | stfd f..c, 16+c*8(sp) - | stfd f..d, 16+d*8(sp) - |.endmacro - | - |->vm_exit_handler: -#if LJ_HASJIT - | addi sp, sp, -(16+32*8+32*4) - | stmw r2, 16+32*8+2*4(sp) - | addi DISPATCH, JGL, -GG_DISP2G-32768 - | li CARG2, ~LJ_VMST_EXIT - | lwz CARG1, 16+32*8+32*4(sp) // Get stack chain. - | stw CARG2, DISPATCH_GL(vmstate)(DISPATCH) - | savex_ 0,1,2,3 - | stw CARG1, 0(sp) // Store extended stack chain. - | mcrxr cr0 // Clear SO flag. - | savex_ 4,5,6,7 - | addi CARG2, sp, 16+32*8+32*4 // Recompute original value of sp. - | savex_ 8,9,10,11 - | stw CARG2, 16+32*8+1*4(sp) // Store sp in RID_SP. - | savex_ 12,13,14,15 - | mflr CARG3 - | li TMP1, 0 - | savex_ 16,17,18,19 - | stw TMP1, 16+32*8+0*4(sp) // Clear RID_TMP. - | savex_ 20,21,22,23 - | lhz CARG4, 2(CARG3) // Load trace number. - | savex_ 24,25,26,27 - | lwz L, DISPATCH_GL(jit_L)(DISPATCH) - | savex_ 28,29,30,31 - | sub CARG3, TMP0, CARG3 // Compute exit number. - | lwz BASE, DISPATCH_GL(jit_base)(DISPATCH) - | srwi CARG3, CARG3, 2 - | stw L, DISPATCH_J(L)(DISPATCH) - | subi CARG3, CARG3, 2 - | stw TMP1, DISPATCH_GL(jit_L)(DISPATCH) - | stw CARG4, DISPATCH_J(parent)(DISPATCH) - | stw BASE, L->base - | addi CARG1, DISPATCH, GG_DISP2J - | stw CARG3, DISPATCH_J(exitno)(DISPATCH) - | addi CARG2, sp, 16 - | bl extern lj_trace_exit // (jit_State *J, ExitState *ex) - | // Returns MULTRES (unscaled) or negated error code. - | lwz TMP1, L->cframe - | lwz TMP2, 0(sp) - | lwz BASE, L->base - | rlwinm sp, TMP1, 0, 0, 29 - | lwz PC, SAVE_PC // Get SAVE_PC. - | stw TMP2, 0(sp) - | stw L, SAVE_L // Set SAVE_L (on-trace resume/yield). - | b >1 -#endif - |->vm_exit_interp: -#if LJ_HASJIT - | // CARG1 = MULTRES or negated error code, BASE, PC and JGL set. - | lwz L, SAVE_L - | addi DISPATCH, JGL, -GG_DISP2G-32768 - |1: - | cmpwi CARG1, 0 - | blt >3 // Check for error from exit. - | lwz LFUNC:TMP1, FRAME_FUNC(BASE) - | slwi MULTRES, CARG1, 3 - | li TMP2, 0 - | stw MULTRES, SAVE_MULTRES - | lwz TMP1, LFUNC:TMP1->pc - | stw TMP2, DISPATCH_GL(jit_L)(DISPATCH) - | lwz KBASE, PC2PROTO(k)(TMP1) - | // Setup type comparison constants. - | li TISNUM, LJ_TISNUM - | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). - | stw TMP3, TMPD - | li ZERO, 0 - | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float). - | lfs TOBIT, TMPD - | stw TMP3, TMPD - | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double) - | li TISNIL, LJ_TNIL - | stw TMP0, TONUM_HI - | lfs TONUM, TMPD - | // Modified copy of ins_next which handles function header dispatch, too. - | lwz INS, 0(PC) - | addi PC, PC, 4 - | // Assumes TISNIL == ~LJ_VMST_INTERP == -1. - | stw TISNIL, DISPATCH_GL(vmstate)(DISPATCH) - | decode_OP4 TMP1, INS - | decode_RA8 RA, INS - | lwzx TMP0, DISPATCH, TMP1 - | mtctr TMP0 - | cmplwi TMP1, BC_FUNCF*4 // Function header? - | bge >2 - | decode_RB8 RB, INS - | decode_RD8 RD, INS - | decode_RC8 RC, INS - | bctr - |2: - | subi RC, MULTRES, 8 - | add RA, RA, BASE - | bctr - | - |3: // Rethrow error from the right C frame. - | neg CARG2, CARG1 - | mr CARG1, L - | bl extern lj_err_throw // (lua_State *L, int errcode) -#endif - | - |//----------------------------------------------------------------------- - |//-- Math helper functions ---------------------------------------------- - |//----------------------------------------------------------------------- - | - | // NYI: Use internal implementation. - |->vm_floor: - | b extern floor - |->vm_ceil: - | b extern ceil - |->vm_trunc: -#if LJ_HASJIT - | b extern trunc -#endif - | - |->vm_modi: - | divwo. TMP0, CARG1, CARG2 - | bso >1 - | xor. CARG3, CARG1, CARG2 - | mullw TMP0, TMP0, CARG2 - | sub CARG1, CARG1, TMP0 - | bgelr - | cmpwi CARG1, 0; beqlr - | add CARG1, CARG1, CARG2 - | blr - |1: - | cmpwi CARG2, 0 - | li CARG1, 0 - | beqlr - | mcrxr cr0 // Clear SO for -2147483648 % -1 and return 0. - | blr - | - |// Callable from C: double lj_vm_foldarith(double x, double y, int op) - |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -) - |// and basic math functions. ORDER ARITH - |->vm_foldarith: - | cmplwi CARG1, 1 - | beq >1; bgt >2 - | fadd FARG1, FARG1, FARG2; blr - |1: - | fsub FARG1, FARG1, FARG2; blr - |2: - | cmplwi CARG1, 3; beq >1; bgt >2 - | fmul FARG1, FARG1, FARG2; blr - |1: - | fdiv FARG1, FARG1, FARG2; blr - |2: - | cmplwi CARG1, 5; beq >1; bgt >2 - | // NYI: Use internal implementation of floor and avoid spills. - | stwu sp, -32(sp); stfd f14, 16(sp); stfd f15, 24(sp) - | mflr r0 - | fmr f14, FARG1 - | fdiv FARG1, FARG1, FARG2 - | stw r0, 36(sp) - | fmr f15, FARG2 - | bl extern floor - | lwz r0, 36(sp) - | fmul FARG1, FARG1, f15 - | mtlr r0 - | fsub FARG1, f14, FARG1 - | lfd f14, 16(sp); lfd f15, 24(sp); addi sp, sp, 32; blr - |1: - | b extern pow - |2: - | cmplwi CARG1, 7; beq >1; bgt >2 - | fneg FARG1, FARG1; blr - |1: - | fabs FARG1, FARG1; blr - |2: -#if LJ_HASJIT - | cmplwi CARG1, 9; beq >9; bgt >2 - | b extern atan2 - | // No support needed for IR_LDEXP. - |2: - | cmplwi CARG1, 11; bgt >9 - | fsub f0, FARG1, FARG2 - | beq >1 - | fsel FARG1, f0, FARG2, FARG1 // IR_MAX - | blr - |1: - | fsel FARG1, f0, FARG1, FARG2 // IR_MIN - | blr - |9: - | NYI // Bad op. -#else - | NYI // Other operations only needed by JIT compiler. -#endif - | - |//----------------------------------------------------------------------- - |//-- Miscellaneous functions -------------------------------------------- - |//----------------------------------------------------------------------- - | - |// void lj_vm_cachesync(void *start, void *end) - |// Flush D-Cache and invalidate I-Cache. Assumes 32 byte cache line size. - |// This is a good lower bound, except for very ancient PPC models. - |->vm_cachesync: - | // Compute start of first cache line and number of cache lines. - | rlwinm CARG1, CARG1, 0, 0, 26 - | sub CARG2, CARG2, CARG1 - | addi CARG2, CARG2, 31 - | rlwinm. CARG2, CARG2, 27, 5, 31 - | beqlr - | mtctr CARG2 - | mr CARG3, CARG1 - |1: // Flush D-Cache. - | dcbst r0, CARG1 - | addi CARG1, CARG1, 32 - | bdnz <1 - | sync - | mtctr CARG2 - |1: // Invalidate I-Cache. - | icbi r0, CARG3 - | addi CARG3, CARG3, 32 - | bdnz <1 - | isync - | blr - | - |//----------------------------------------------------------------------- - |//-- FFI helper functions ----------------------------------------------- - |//----------------------------------------------------------------------- - | - |// Handler for callback functions. Callback slot number in r11, g in r12. - |->vm_ffi_callback: -#if LJ_HASFFI - |.type CTSTATE, CTState, PC - | saveregs - | lwz CTSTATE, GL:r12->ctype_state - | addi DISPATCH, r12, GG_G2DISP - | stw r11, CTSTATE->cb.slot - | stw r3, CTSTATE->cb.gpr[0] - | stfd f1, CTSTATE->cb.fpr[0] - | stw r4, CTSTATE->cb.gpr[1] - | stfd f2, CTSTATE->cb.fpr[1] - | stw r5, CTSTATE->cb.gpr[2] - | stfd f3, CTSTATE->cb.fpr[2] - | stw r6, CTSTATE->cb.gpr[3] - | stfd f4, CTSTATE->cb.fpr[3] - | stw r7, CTSTATE->cb.gpr[4] - | stfd f5, CTSTATE->cb.fpr[4] - | stw r8, CTSTATE->cb.gpr[5] - | stfd f6, CTSTATE->cb.fpr[5] - | stw r9, CTSTATE->cb.gpr[6] - | stfd f7, CTSTATE->cb.fpr[6] - | stw r10, CTSTATE->cb.gpr[7] - | stfd f8, CTSTATE->cb.fpr[7] - | addi TMP0, sp, CFRAME_SPACE+8 - | stw TMP0, CTSTATE->cb.stack - | mr CARG1, CTSTATE - | stw CTSTATE, SAVE_PC // Any value outside of bytecode is ok. - | mr CARG2, sp - | bl extern lj_ccallback_enter // (CTState *cts, void *cf) - | // Returns lua_State *. - | lwz BASE, L:CRET1->base - | li TISNUM, LJ_TISNUM // Setup type comparison constants. - | lwz RC, L:CRET1->top - | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). - | li ZERO, 0 - | mr L, CRET1 - | stw TMP3, TMPD - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float). - | li TISNIL, LJ_TNIL - | li_vmstate INTERP - | lfs TOBIT, TMPD - | stw TMP3, TMPD - | sub RC, RC, BASE - | st_vmstate - | lfs TONUM, TMPD - | ins_callt -#endif - | - |->cont_ffi_callback: // Return from FFI callback. -#if LJ_HASFFI - | lwz CTSTATE, DISPATCH_GL(ctype_state)(DISPATCH) - | stw BASE, L->base - | stw RB, L->top - | stw L, CTSTATE->L - | mr CARG1, CTSTATE - | mr CARG2, RA - | bl extern lj_ccallback_leave // (CTState *cts, TValue *o) - | lwz CRET1, CTSTATE->cb.gpr[0] - | lfd FARG1, CTSTATE->cb.fpr[0] - | lwz CRET2, CTSTATE->cb.gpr[1] - | b ->vm_leave_unw -#endif - | - |->vm_ffi_call: // Call C function via FFI. - | // Caveat: needs special frame unwinding, see below. -#if LJ_HASFFI - | .type CCSTATE, CCallState, CARG1 - | lwz TMP1, CCSTATE->spadj - | mflr TMP0 - | lbz CARG2, CCSTATE->nsp - | lbz CARG3, CCSTATE->nfpr - | neg TMP1, TMP1 - | stw TMP0, 4(sp) - | cmpwi cr1, CARG3, 0 - | mr TMP2, sp - | addic. CARG2, CARG2, -1 - | stwux sp, sp, TMP1 - | crnot 4*cr1+eq, 4*cr1+eq // For vararg calls. - | stw r14, -4(TMP2) - | stw CCSTATE, -8(TMP2) - | mr r14, TMP2 - | la TMP1, CCSTATE->stack - | slwi CARG2, CARG2, 2 - | blty >2 - | la TMP2, 8(sp) - |1: - | lwzx TMP0, TMP1, CARG2 - | stwx TMP0, TMP2, CARG2 - | addic. CARG2, CARG2, -4 - | bge <1 - |2: - | bney cr1, >3 - | lfd f1, CCSTATE->fpr[0] - | lfd f2, CCSTATE->fpr[1] - | lfd f3, CCSTATE->fpr[2] - | lfd f4, CCSTATE->fpr[3] - | lfd f5, CCSTATE->fpr[4] - | lfd f6, CCSTATE->fpr[5] - | lfd f7, CCSTATE->fpr[6] - | lfd f8, CCSTATE->fpr[7] - |3: - | lwz TMP0, CCSTATE->func - | lwz CARG2, CCSTATE->gpr[1] - | lwz CARG3, CCSTATE->gpr[2] - | lwz CARG4, CCSTATE->gpr[3] - | lwz CARG5, CCSTATE->gpr[4] - | mtctr TMP0 - | lwz r8, CCSTATE->gpr[5] - | lwz r9, CCSTATE->gpr[6] - | lwz r10, CCSTATE->gpr[7] - | lwz CARG1, CCSTATE->gpr[0] // Do this last, since CCSTATE is CARG1. - | bctrl - | lwz CCSTATE:TMP1, -8(r14) - | lwz TMP2, -4(r14) - | lwz TMP0, 4(r14) - | stw CARG1, CCSTATE:TMP1->gpr[0] - | stfd FARG1, CCSTATE:TMP1->fpr[0] - | stw CARG2, CCSTATE:TMP1->gpr[1] - | mtlr TMP0 - | stw CARG3, CCSTATE:TMP1->gpr[2] - | mr sp, r14 - | stw CARG4, CCSTATE:TMP1->gpr[3] - | mr r14, TMP2 - | blr -#endif - |// Note: vm_ffi_call must be the last function in this object file! - | - |//----------------------------------------------------------------------- -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop) -{ - int vk = 0; - |=>defop: - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - | // RA = src1*8, RD = src2*8, JMP with RD = target - if (LJ_DUALNUM) { - | lwzux TMP0, RA, BASE - | addi PC, PC, 4 - | lwz CARG2, 4(RA) - | lwzux TMP1, RD, BASE - | lwz TMP2, -4(PC) - | checknum cr0, TMP0 - | lwz CARG3, 4(RD) - | decode_RD4 TMP2, TMP2 - | checknum cr1, TMP1 - | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) - | bne cr0, >7 - | bne cr1, >8 - | cmpw CARG2, CARG3 - if (op == BC_ISLT) { - | bge >2 - } else if (op == BC_ISGE) { - | blt >2 - } else if (op == BC_ISLE) { - | bgt >2 - } else { - | ble >2 - } - |1: - | add PC, PC, TMP2 - |2: - | ins_next - | - |7: // RA is not an integer. - | bgt cr0, ->vmeta_comp - | // RA is a number. - | lfd f0, 0(RA) - | bgt cr1, ->vmeta_comp - | blt cr1, >4 - | // RA is a number, RD is an integer. - | tonum_i f1, CARG3 - | b >5 - | - |8: // RA is an integer, RD is not an integer. - | bgt cr1, ->vmeta_comp - | // RA is an integer, RD is a number. - | tonum_i f0, CARG2 - |4: - | lfd f1, 0(RD) - |5: - | fcmpu cr0, f0, f1 - if (op == BC_ISLT) { - | bge <2 - } else if (op == BC_ISGE) { - | blt <2 - } else if (op == BC_ISLE) { - | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq - | bge <2 - } else { - | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq - | blt <2 - } - | b <1 - } else { - | lwzx TMP0, BASE, RA - | addi PC, PC, 4 - | lfdx f0, BASE, RA - | lwzx TMP1, BASE, RD - | checknum cr0, TMP0 - | lwz TMP2, -4(PC) - | lfdx f1, BASE, RD - | checknum cr1, TMP1 - | decode_RD4 TMP2, TMP2 - | bge cr0, ->vmeta_comp - | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) - | bge cr1, ->vmeta_comp - | fcmpu cr0, f0, f1 - if (op == BC_ISLT) { - | bge >1 - } else if (op == BC_ISGE) { - | blt >1 - } else if (op == BC_ISLE) { - | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq - | bge >1 - } else { - | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq - | blt >1 - } - | add PC, PC, TMP2 - |1: - | ins_next - } - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - | // RA = src1*8, RD = src2*8, JMP with RD = target - if (LJ_DUALNUM) { - | lwzux TMP0, RA, BASE - | addi PC, PC, 4 - | lwz CARG2, 4(RA) - | lwzux TMP1, RD, BASE - | checknum cr0, TMP0 - | lwz TMP2, -4(PC) - | checknum cr1, TMP1 - | decode_RD4 TMP2, TMP2 - | lwz CARG3, 4(RD) - | cror 4*cr7+gt, 4*cr0+gt, 4*cr1+gt - | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) - if (vk) { - | ble cr7, ->BC_ISEQN_Z - } else { - | ble cr7, ->BC_ISNEN_Z - } - } else { - | lwzux TMP0, RA, BASE - | lwz TMP2, 0(PC) - | lfd f0, 0(RA) - | addi PC, PC, 4 - | lwzux TMP1, RD, BASE - | checknum cr0, TMP0 - | decode_RD4 TMP2, TMP2 - | lfd f1, 0(RD) - | checknum cr1, TMP1 - | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) - | bge cr0, >5 - | bge cr1, >5 - | fcmpu cr0, f0, f1 - if (vk) { - | bne >1 - | add PC, PC, TMP2 - } else { - | beq >1 - | add PC, PC, TMP2 - } - |1: - | ins_next - } - |5: // Either or both types are not numbers. - if (!LJ_DUALNUM) { - | lwz CARG2, 4(RA) - | lwz CARG3, 4(RD) - } - if (LJ_HASFFI) { - | cmpwi cr7, TMP0, LJ_TCDATA - | cmpwi cr5, TMP1, LJ_TCDATA - } - | not TMP3, TMP0 - | cmplw TMP0, TMP1 - | cmplwi cr1, TMP3, ~LJ_TISPRI // Primitive? - if (LJ_HASFFI) { - | cror 4*cr7+eq, 4*cr7+eq, 4*cr5+eq - } - | cmplwi cr6, TMP3, ~LJ_TISTABUD // Table or userdata? - if (LJ_HASFFI) { - | beq cr7, ->vmeta_equal_cd - } - | cmplw cr5, CARG2, CARG3 - | crandc 4*cr0+gt, 4*cr0+eq, 4*cr1+gt // 2: Same type and primitive. - | crorc 4*cr0+lt, 4*cr5+eq, 4*cr0+eq // 1: Same tv or different type. - | crand 4*cr0+eq, 4*cr0+eq, 4*cr5+eq // 0: Same type and same tv. - | mr SAVE0, PC - | cror 4*cr0+eq, 4*cr0+eq, 4*cr0+gt // 0 or 2. - | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+gt // 1 or 2. - if (vk) { - | bne cr0, >6 - | add PC, PC, TMP2 - |6: - } else { - | beq cr0, >6 - | add PC, PC, TMP2 - |6: - } - if (LJ_DUALNUM) { - | bge cr0, >2 // Done if 1 or 2. - |1: - | ins_next - |2: - } else { - | blt cr0, <1 // Done if 1 or 2. - } - | blt cr6, <1 // Done if not tab/ud. - | - | // Different tables or userdatas. Need to check __eq metamethod. - | // Field metatable must be at same offset for GCtab and GCudata! - | lwz TAB:TMP2, TAB:CARG2->metatable - | li CARG4, 1-vk // ne = 0 or 1. - | cmplwi TAB:TMP2, 0 - | beq <1 // No metatable? - | lbz TMP2, TAB:TMP2->nomm - | andi. TMP2, TMP2, 1<vmeta_equal // Handle __eq metamethod. - break; - - case BC_ISEQS: case BC_ISNES: - vk = op == BC_ISEQS; - | // RA = src*8, RD = str_const*8 (~), JMP with RD = target - | lwzux TMP0, RA, BASE - | srwi RD, RD, 1 - | lwz STR:TMP3, 4(RA) - | lwz TMP2, 0(PC) - | subfic RD, RD, -4 - | addi PC, PC, 4 - if (LJ_HASFFI) { - | cmpwi TMP0, LJ_TCDATA - } - | lwzx STR:TMP1, KBASE, RD // KBASE-4-str_const*4 - | subfic TMP0, TMP0, LJ_TSTR - if (LJ_HASFFI) { - | beq ->vmeta_equal_cd - } - | sub TMP1, STR:TMP1, STR:TMP3 - | or TMP0, TMP0, TMP1 - | decode_RD4 TMP2, TMP2 - | subfic TMP0, TMP0, 0 - | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) - | subfe TMP1, TMP1, TMP1 - if (vk) { - | andc TMP2, TMP2, TMP1 - } else { - | and TMP2, TMP2, TMP1 - } - | add PC, PC, TMP2 - | ins_next - break; - - case BC_ISEQN: case BC_ISNEN: - vk = op == BC_ISEQN; - | // RA = src*8, RD = num_const*8, JMP with RD = target - if (LJ_DUALNUM) { - | lwzux TMP0, RA, BASE - | addi PC, PC, 4 - | lwz CARG2, 4(RA) - | lwzux TMP1, RD, KBASE - | checknum cr0, TMP0 - | lwz TMP2, -4(PC) - | checknum cr1, TMP1 - | decode_RD4 TMP2, TMP2 - | lwz CARG3, 4(RD) - | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) - if (vk) { - |->BC_ISEQN_Z: - } else { - |->BC_ISNEN_Z: - } - | bne cr0, >7 - | bne cr1, >8 - | cmpw CARG2, CARG3 - |4: - } else { - if (vk) { - |->BC_ISEQN_Z: // Dummy label. - } else { - |->BC_ISNEN_Z: // Dummy label. - } - | lwzx TMP0, BASE, RA - | addi PC, PC, 4 - | lfdx f0, BASE, RA - | lwz TMP2, -4(PC) - | lfdx f1, KBASE, RD - | decode_RD4 TMP2, TMP2 - | checknum TMP0 - | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) - | bge >3 - | fcmpu cr0, f0, f1 - } - if (vk) { - | bne >1 - | add PC, PC, TMP2 - |1: - if (!LJ_HASFFI) { - |3: - } - } else { - | beq >2 - |1: - if (!LJ_HASFFI) { - |3: - } - | add PC, PC, TMP2 - |2: - } - | ins_next - if (LJ_HASFFI) { - |3: - | cmpwi TMP0, LJ_TCDATA - | beq ->vmeta_equal_cd - | b <1 - } - if (LJ_DUALNUM) { - |7: // RA is not an integer. - | bge cr0, <3 - | // RA is a number. - | lfd f0, 0(RA) - | blt cr1, >1 - | // RA is a number, RD is an integer. - | tonum_i f1, CARG3 - | b >2 - | - |8: // RA is an integer, RD is a number. - | tonum_i f0, CARG2 - |1: - | lfd f1, 0(RD) - |2: - | fcmpu cr0, f0, f1 - | b <4 - } - break; - - case BC_ISEQP: case BC_ISNEP: - vk = op == BC_ISEQP; - | // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target - | lwzx TMP0, BASE, RA - | srwi TMP1, RD, 3 - | lwz TMP2, 0(PC) - | not TMP1, TMP1 - | addi PC, PC, 4 - if (LJ_HASFFI) { - | cmpwi TMP0, LJ_TCDATA - } - | sub TMP0, TMP0, TMP1 - if (LJ_HASFFI) { - | beq ->vmeta_equal_cd - } - | decode_RD4 TMP2, TMP2 - | addic TMP0, TMP0, -1 - | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) - | subfe TMP1, TMP1, TMP1 - if (vk) { - | and TMP2, TMP2, TMP1 - } else { - | andc TMP2, TMP2, TMP1 - } - | add PC, PC, TMP2 - | ins_next - break; - - /* -- Unary test and copy ops ------------------------------------------- */ - - case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: - | // RA = dst*8 or unused, RD = src*8, JMP with RD = target - | lwzx TMP0, BASE, RD - | lwz INS, 0(PC) - | addi PC, PC, 4 - if (op == BC_IST || op == BC_ISF) { - | subfic TMP0, TMP0, LJ_TTRUE - | decode_RD4 TMP2, INS - | subfe TMP1, TMP1, TMP1 - | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) - if (op == BC_IST) { - | andc TMP2, TMP2, TMP1 - } else { - | and TMP2, TMP2, TMP1 - } - | add PC, PC, TMP2 - } else { - | li TMP1, LJ_TFALSE - | lfdx f0, BASE, RD - | cmplw TMP0, TMP1 - if (op == BC_ISTC) { - | bge >1 - } else { - | blt >1 - } - | addis PC, PC, -(BCBIAS_J*4 >> 16) - | decode_RD4 TMP2, INS - | stfdx f0, BASE, RA - | add PC, PC, TMP2 - |1: - } - | ins_next - break; - - /* -- Unary ops --------------------------------------------------------- */ - - case BC_MOV: - | // RA = dst*8, RD = src*8 - | ins_next1 - | lfdx f0, BASE, RD - | stfdx f0, BASE, RA - | ins_next2 - break; - case BC_NOT: - | // RA = dst*8, RD = src*8 - | ins_next1 - | lwzx TMP0, BASE, RD - | subfic TMP1, TMP0, LJ_TTRUE - | adde TMP0, TMP0, TMP1 - | stwx TMP0, BASE, RA - | ins_next2 - break; - case BC_UNM: - | // RA = dst*8, RD = src*8 - | lwzux TMP1, RD, BASE - | lwz TMP0, 4(RD) - | checknum TMP1 - if (LJ_DUALNUM) { - | bne >5 - | nego. TMP0, TMP0 - | bso >4 - |1: - | ins_next1 - | stwux TISNUM, RA, BASE - | stw TMP0, 4(RA) - |3: - | ins_next2 - |4: // Potential overflow. - | mcrxr cr0; bley <1 // Ignore unrelated overflow. - | lus TMP1, 0x41e0 // 2^31. - | li TMP0, 0 - | b >7 - } - |5: - | bge ->vmeta_unm - | xoris TMP1, TMP1, 0x8000 - |7: - | ins_next1 - | stwux TMP1, RA, BASE - | stw TMP0, 4(RA) - if (LJ_DUALNUM) { - | b <3 - } else { - | ins_next2 - } - break; - case BC_LEN: - | // RA = dst*8, RD = src*8 - | lwzux TMP0, RD, BASE - | lwz CARG1, 4(RD) - | checkstr TMP0; bne >2 - | lwz CRET1, STR:CARG1->len - |1: - if (LJ_DUALNUM) { - | ins_next1 - | stwux TISNUM, RA, BASE - | stw CRET1, 4(RA) - } else { - | tonum_u f0, CRET1 // Result is a non-negative integer. - | ins_next1 - | stfdx f0, BASE, RA - } - | ins_next2 - |2: - | checktab TMP0; bne ->vmeta_len -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | lwz TAB:TMP2, TAB:CARG1->metatable - | cmplwi TAB:TMP2, 0 - | bne >9 - |3: -#endif - |->BC_LEN_Z: - | bl extern lj_tab_len // (GCtab *t) - | // Returns uint32_t (but less than 2^31). - | b <1 -#ifdef LUAJIT_ENABLE_LUA52COMPAT - |9: - | lbz TMP0, TAB:TMP2->nomm - | andi. TMP0, TMP0, 1<vmeta_len -#endif - break; - - /* -- Binary ops -------------------------------------------------------- */ - - |.macro ins_arithpre - | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8 - ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); - ||switch (vk) { - ||case 0: - | lwzx TMP1, BASE, RB - ||if (LJ_DUALNUM) { - | lwzx TMP2, KBASE, RC - ||} - | lfdx f14, BASE, RB - | lfdx f15, KBASE, RC - ||if (LJ_DUALNUM) { - | checknum cr0, TMP1 - | checknum cr1, TMP2 - | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt - | bge ->vmeta_arith_vn - ||} else { - | checknum TMP1; bge ->vmeta_arith_vn - ||} - || break; - ||case 1: - | lwzx TMP1, BASE, RB - ||if (LJ_DUALNUM) { - | lwzx TMP2, KBASE, RC - ||} - | lfdx f15, BASE, RB - | lfdx f14, KBASE, RC - ||if (LJ_DUALNUM) { - | checknum cr0, TMP1 - | checknum cr1, TMP2 - | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt - | bge ->vmeta_arith_nv - ||} else { - | checknum TMP1; bge ->vmeta_arith_nv - ||} - || break; - ||default: - | lwzx TMP1, BASE, RB - | lwzx TMP2, BASE, RC - | lfdx f14, BASE, RB - | lfdx f15, BASE, RC - | checknum cr0, TMP1 - | checknum cr1, TMP2 - | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt - | bge ->vmeta_arith_vv - || break; - ||} - |.endmacro - | - |.macro ins_arithfallback, ins - ||switch (vk) { - ||case 0: - | ins ->vmeta_arith_vn2 - || break; - ||case 1: - | ins ->vmeta_arith_nv2 - || break; - ||default: - | ins ->vmeta_arith_vv2 - || break; - ||} - |.endmacro - | - |.macro intmod, a, b, c - | bl ->vm_modi - |.endmacro - | - |.macro fpmod, a, b, c - |->BC_MODVN_Z: - | fdiv FARG1, b, c - | // NYI: Use internal implementation of floor. - | bl extern floor // floor(b/c) - | fmul a, FARG1, c - | fsub a, b, a // b - floor(b/c)*c - |.endmacro - | - |.macro ins_arithfp, fpins - | ins_arithpre - |.if "fpins" == "fpmod_" - | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway. - |.else - | fpins f0, f14, f15 - | ins_next1 - | stfdx f0, BASE, RA - | ins_next2 - |.endif - |.endmacro - | - |.macro ins_arithdn, intins, fpins - | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8 - ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); - ||switch (vk) { - ||case 0: - | lwzux TMP1, RB, BASE - | lwzux TMP2, RC, KBASE - | lwz CARG1, 4(RB) - | checknum cr0, TMP1 - | lwz CARG2, 4(RC) - || break; - ||case 1: - | lwzux TMP1, RB, BASE - | lwzux TMP2, RC, KBASE - | lwz CARG2, 4(RB) - | checknum cr0, TMP1 - | lwz CARG1, 4(RC) - || break; - ||default: - | lwzux TMP1, RB, BASE - | lwzux TMP2, RC, BASE - | lwz CARG1, 4(RB) - | checknum cr0, TMP1 - | lwz CARG2, 4(RC) - || break; - ||} - | checknum cr1, TMP2 - | bne >5 - | bne cr1, >5 - | intins CARG1, CARG1, CARG2 - | bso >4 - |1: - | ins_next1 - | stwux TISNUM, RA, BASE - | stw CARG1, 4(RA) - |2: - | ins_next2 - |4: // Overflow. - | mcrxr cr0; bley <1 // Ignore unrelated overflow. - | ins_arithfallback b - |5: // FP variant. - ||if (vk == 1) { - | lfd f15, 0(RB) - | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt - | lfd f14, 0(RC) - ||} else { - | lfd f14, 0(RB) - | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt - | lfd f15, 0(RC) - ||} - | ins_arithfallback bge - |.if "fpins" == "fpmod_" - | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway. - |.else - | fpins f0, f14, f15 - | ins_next1 - | stfdx f0, BASE, RA - | b <2 - |.endif - |.endmacro - | - |.macro ins_arith, intins, fpins - ||if (LJ_DUALNUM) { - | ins_arithdn intins, fpins - ||} else { - | ins_arithfp fpins - ||} - |.endmacro - - case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: - | ins_arith addo., fadd - break; - case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: - | ins_arith subo., fsub - break; - case BC_MULVN: case BC_MULNV: case BC_MULVV: - | ins_arith mullwo., fmul - break; - case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: - | ins_arithfp fdiv - break; - case BC_MODVN: - | ins_arith intmod, fpmod - break; - case BC_MODNV: case BC_MODVV: - | ins_arith intmod, fpmod_ - break; - case BC_POW: - | // NYI: (partial) integer arithmetic. - | lwzx TMP1, BASE, RB - | lfdx FARG1, BASE, RB - | lwzx TMP2, BASE, RC - | lfdx FARG2, BASE, RC - | checknum cr0, TMP1 - | checknum cr1, TMP2 - | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt - | bge ->vmeta_arith_vv - | bl extern pow - | ins_next1 - | stfdx FARG1, BASE, RA - | ins_next2 - break; - - case BC_CAT: - | // RA = dst*8, RB = src_start*8, RC = src_end*8 - | sub CARG3, RC, RB - | stw BASE, L->base - | add CARG2, BASE, RC - | mr SAVE0, RB - |->BC_CAT_Z: - | stw PC, SAVE_PC - | mr CARG1, L - | srwi CARG3, CARG3, 3 - | bl extern lj_meta_cat // (lua_State *L, TValue *top, int left) - | // Returns NULL (finished) or TValue * (metamethod). - | cmplwi CRET1, 0 - | lwz BASE, L->base - | bne ->vmeta_binop - | ins_next1 - | lfdx f0, BASE, SAVE0 // Copy result from RB to RA. - | stfdx f0, BASE, RA - | ins_next2 - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - | // RA = dst*8, RD = str_const*8 (~) - | srwi TMP1, RD, 1 - | subfic TMP1, TMP1, -4 - | ins_next1 - | lwzx TMP0, KBASE, TMP1 // KBASE-4-str_const*4 - | li TMP2, LJ_TSTR - | stwux TMP2, RA, BASE - | stw TMP0, 4(RA) - | ins_next2 - break; - case BC_KCDATA: -#if LJ_HASFFI - | // RA = dst*8, RD = cdata_const*8 (~) - | srwi TMP1, RD, 1 - | subfic TMP1, TMP1, -4 - | ins_next1 - | lwzx TMP0, KBASE, TMP1 // KBASE-4-cdata_const*4 - | li TMP2, LJ_TCDATA - | stwux TMP2, RA, BASE - | stw TMP0, 4(RA) - | ins_next2 -#endif - break; - case BC_KSHORT: - | // RA = dst*8, RD = int16_literal*8 - if (LJ_DUALNUM) { - | slwi RD, RD, 13 - | srawi RD, RD, 16 - | ins_next1 - | stwux TISNUM, RA, BASE - | stw RD, 4(RA) - | ins_next2 - } else { - | // The soft-float approach is faster. - | slwi RD, RD, 13 - | srawi TMP1, RD, 31 - | xor TMP2, TMP1, RD - | sub TMP2, TMP2, TMP1 // TMP2 = abs(x) - | cntlzw TMP3, TMP2 - | subfic TMP1, TMP3, 0x40d // TMP1 = exponent-1 - | slw TMP2, TMP2, TMP3 // TMP2 = left aligned mantissa - | subfic TMP3, RD, 0 - | slwi TMP1, TMP1, 20 - | rlwimi RD, TMP2, 21, 1, 31 // hi = sign(x) | (mantissa>>11) - | subfe TMP0, TMP0, TMP0 - | add RD, RD, TMP1 // hi = hi + exponent-1 - | and RD, RD, TMP0 // hi = x == 0 ? 0 : hi - | ins_next1 - | stwux RD, RA, BASE - | stw ZERO, 4(RA) - | ins_next2 - } - break; - case BC_KNUM: - | // RA = dst*8, RD = num_const*8 - | ins_next1 - | lfdx f0, KBASE, RD - | stfdx f0, BASE, RA - | ins_next2 - break; - case BC_KPRI: - | // RA = dst*8, RD = primitive_type*8 (~) - | srwi TMP1, RD, 3 - | not TMP0, TMP1 - | ins_next1 - | stwx TMP0, BASE, RA - | ins_next2 - break; - case BC_KNIL: - | // RA = base*8, RD = end*8 - | stwx TISNIL, BASE, RA - | addi RA, RA, 8 - |1: - | stwx TISNIL, BASE, RA - | cmpw RA, RD - | addi RA, RA, 8 - | blt <1 - | ins_next_ - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - | // RA = dst*8, RD = uvnum*8 - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | srwi RD, RD, 1 - | addi RD, RD, offsetof(GCfuncL, uvptr) - | lwzx UPVAL:RB, LFUNC:RB, RD - | ins_next1 - | lwz TMP1, UPVAL:RB->v - | lfd f0, 0(TMP1) - | stfdx f0, BASE, RA - | ins_next2 - break; - case BC_USETV: - | // RA = uvnum*8, RD = src*8 - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | srwi RA, RA, 1 - | addi RA, RA, offsetof(GCfuncL, uvptr) - | lfdux f0, RD, BASE - | lwzx UPVAL:RB, LFUNC:RB, RA - | lbz TMP3, UPVAL:RB->marked - | lwz CARG2, UPVAL:RB->v - | andi. TMP3, TMP3, LJ_GC_BLACK // isblack(uv) - | lbz TMP0, UPVAL:RB->closed - | lwz TMP2, 0(RD) - | stfd f0, 0(CARG2) - | cmplwi cr1, TMP0, 0 - | lwz TMP1, 4(RD) - | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq - | subi TMP2, TMP2, (LJ_TISNUM+1) - | bne >2 // Upvalue is closed and black? - |1: - | ins_next - | - |2: // Check if new value is collectable. - | cmplwi TMP2, LJ_TISGCV - (LJ_TISNUM+1) - | bge <1 // tvisgcv(v) - | lbz TMP3, GCOBJ:TMP1->gch.marked - | andi. TMP3, TMP3, LJ_GC_WHITES // iswhite(v) - | la CARG1, GG_DISP2G(DISPATCH) - | // Crossed a write barrier. Move the barrier forward. - | beq <1 - | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) - | b <1 - break; - case BC_USETS: - | // RA = uvnum*8, RD = str_const*8 (~) - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | srwi TMP1, RD, 1 - | srwi RA, RA, 1 - | subfic TMP1, TMP1, -4 - | addi RA, RA, offsetof(GCfuncL, uvptr) - | lwzx STR:TMP1, KBASE, TMP1 // KBASE-4-str_const*4 - | lwzx UPVAL:RB, LFUNC:RB, RA - | lbz TMP3, UPVAL:RB->marked - | lwz CARG2, UPVAL:RB->v - | andi. TMP3, TMP3, LJ_GC_BLACK // isblack(uv) - | lbz TMP3, STR:TMP1->marked - | lbz TMP2, UPVAL:RB->closed - | li TMP0, LJ_TSTR - | stw STR:TMP1, 4(CARG2) - | stw TMP0, 0(CARG2) - | bne >2 - |1: - | ins_next - | - |2: // Check if string is white and ensure upvalue is closed. - | andi. TMP3, TMP3, LJ_GC_WHITES // iswhite(str) - | cmplwi cr1, TMP2, 0 - | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq - | la CARG1, GG_DISP2G(DISPATCH) - | // Crossed a write barrier. Move the barrier forward. - | beq <1 - | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) - | b <1 - break; - case BC_USETN: - | // RA = uvnum*8, RD = num_const*8 - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | srwi RA, RA, 1 - | addi RA, RA, offsetof(GCfuncL, uvptr) - | lfdx f0, KBASE, RD - | lwzx UPVAL:RB, LFUNC:RB, RA - | ins_next1 - | lwz TMP1, UPVAL:RB->v - | stfd f0, 0(TMP1) - | ins_next2 - break; - case BC_USETP: - | // RA = uvnum*8, RD = primitive_type*8 (~) - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | srwi RA, RA, 1 - | srwi TMP0, RD, 3 - | addi RA, RA, offsetof(GCfuncL, uvptr) - | not TMP0, TMP0 - | lwzx UPVAL:RB, LFUNC:RB, RA - | ins_next1 - | lwz TMP1, UPVAL:RB->v - | stw TMP0, 0(TMP1) - | ins_next2 - break; - - case BC_UCLO: - | // RA = level*8, RD = target - | lwz TMP1, L->openupval - | branch_RD // Do this first since RD is not saved. - | stw BASE, L->base - | cmplwi TMP1, 0 - | mr CARG1, L - | beq >1 - | add CARG2, BASE, RA - | bl extern lj_func_closeuv // (lua_State *L, TValue *level) - | lwz BASE, L->base - |1: - | ins_next - break; - - case BC_FNEW: - | // RA = dst*8, RD = proto_const*8 (~) (holding function prototype) - | srwi TMP1, RD, 1 - | stw BASE, L->base - | subfic TMP1, TMP1, -4 - | stw PC, SAVE_PC - | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4 - | mr CARG1, L - | lwz CARG3, FRAME_FUNC(BASE) - | // (lua_State *L, GCproto *pt, GCfuncL *parent) - | bl extern lj_func_newL_gc - | // Returns GCfuncL *. - | lwz BASE, L->base - | li TMP0, LJ_TFUNC - | stwux TMP0, RA, BASE - | stw LFUNC:CRET1, 4(RA) - | ins_next - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - case BC_TDUP: - | // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~) - | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH) - | mr CARG1, L - | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) - | stw BASE, L->base - | cmplw TMP0, TMP1 - | stw PC, SAVE_PC - | bge >5 - |1: - if (op == BC_TNEW) { - | rlwinm CARG2, RD, 29, 21, 31 - | rlwinm CARG3, RD, 18, 27, 31 - | cmpwi CARG2, 0x7ff; beq >3 - |2: - | bl extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits) - | // Returns Table *. - } else { - | srwi TMP1, RD, 1 - | subfic TMP1, TMP1, -4 - | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4 - | bl extern lj_tab_dup // (lua_State *L, Table *kt) - | // Returns Table *. - } - | lwz BASE, L->base - | li TMP0, LJ_TTAB - | stwux TMP0, RA, BASE - | stw TAB:CRET1, 4(RA) - | ins_next - if (op == BC_TNEW) { - |3: - | li CARG2, 0x801 - | b <2 - } - |5: - | mr SAVE0, RD - | bl extern lj_gc_step_fixtop // (lua_State *L) - | mr RD, SAVE0 - | mr CARG1, L - | b <1 - break; - - case BC_GGET: - | // RA = dst*8, RD = str_const*8 (~) - case BC_GSET: - | // RA = src*8, RD = str_const*8 (~) - | lwz LFUNC:TMP2, FRAME_FUNC(BASE) - | srwi TMP1, RD, 1 - | lwz TAB:RB, LFUNC:TMP2->env - | subfic TMP1, TMP1, -4 - | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 - if (op == BC_GGET) { - | b ->BC_TGETS_Z - } else { - | b ->BC_TSETS_Z - } - break; - - case BC_TGETV: - | // RA = dst*8, RB = table*8, RC = key*8 - | lwzux CARG1, RB, BASE - | lwzux CARG2, RC, BASE - | lwz TAB:RB, 4(RB) - if (LJ_DUALNUM) { - | lwz RC, 4(RC) - } else { - | lfd f0, 0(RC) - } - | checktab CARG1 - | checknum cr1, CARG2 - | bne ->vmeta_tgetv - if (LJ_DUALNUM) { - | lwz TMP0, TAB:RB->asize - | bne cr1, >5 - | lwz TMP1, TAB:RB->array - | cmplw TMP0, RC - | slwi TMP2, RC, 3 - } else { - | bge cr1, >5 - | // Convert number key to integer, check for integerness and range. - | fctiwz f1, f0 - | fadd f2, f0, TOBIT - | stfd f1, TMPD - | lwz TMP0, TAB:RB->asize - | fsub f2, f2, TOBIT - | lwz TMP2, TMPD_LO - | lwz TMP1, TAB:RB->array - | fcmpu cr1, f0, f2 - | cmplw cr0, TMP0, TMP2 - | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+eq - | slwi TMP2, TMP2, 3 - } - | ble ->vmeta_tgetv // Integer key and in array part? - | lwzx TMP0, TMP1, TMP2 - | lfdx f14, TMP1, TMP2 - | checknil TMP0; beq >2 - |1: - | ins_next1 - | stfdx f14, BASE, RA - | ins_next2 - | - |2: // Check for __index if table value is nil. - | lwz TAB:TMP2, TAB:RB->metatable - | cmplwi TAB:TMP2, 0 - | beq <1 // No metatable: done. - | lbz TMP0, TAB:TMP2->nomm - | andi. TMP0, TMP0, 1<vmeta_tgetv - | - |5: - | checkstr CARG2; bne ->vmeta_tgetv - if (!LJ_DUALNUM) { - | lwz STR:RC, 4(RC) - } - | b ->BC_TGETS_Z // String key? - break; - case BC_TGETS: - | // RA = dst*8, RB = table*8, RC = str_const*8 (~) - | lwzux CARG1, RB, BASE - | srwi TMP1, RC, 1 - | lwz TAB:RB, 4(RB) - | subfic TMP1, TMP1, -4 - | checktab CARG1 - | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 - | bne ->vmeta_tgets1 - |->BC_TGETS_Z: - | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8 - | lwz TMP0, TAB:RB->hmask - | lwz TMP1, STR:RC->hash - | lwz NODE:TMP2, TAB:RB->node - | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask - | slwi TMP0, TMP1, 5 - | slwi TMP1, TMP1, 3 - | sub TMP1, TMP0, TMP1 - | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) - |1: - | lwz CARG1, NODE:TMP2->key - | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2) - | lwz CARG2, NODE:TMP2->val - | lwz TMP1, 4+offsetof(Node, val)(NODE:TMP2) - | checkstr CARG1; bne >4 - | cmpw TMP0, STR:RC; bne >4 - | checknil CARG2; beq >5 // Key found, but nil value? - |3: - | stwux CARG2, RA, BASE - | stw TMP1, 4(RA) - | ins_next - | - |4: // Follow hash chain. - | lwz NODE:TMP2, NODE:TMP2->next - | cmplwi NODE:TMP2, 0 - | bne <1 - | // End of hash chain: key not found, nil result. - | li CARG2, LJ_TNIL - | - |5: // Check for __index if table value is nil. - | lwz TAB:TMP2, TAB:RB->metatable - | cmplwi TAB:TMP2, 0 - | beq <3 // No metatable: done. - | lbz TMP0, TAB:TMP2->nomm - | andi. TMP0, TMP0, 1<vmeta_tgets - break; - case BC_TGETB: - | // RA = dst*8, RB = table*8, RC = index*8 - | lwzux CARG1, RB, BASE - | srwi TMP0, RC, 3 - | lwz TAB:RB, 4(RB) - | checktab CARG1; bne ->vmeta_tgetb - | lwz TMP1, TAB:RB->asize - | lwz TMP2, TAB:RB->array - | cmplw TMP0, TMP1; bge ->vmeta_tgetb - | lwzx TMP1, TMP2, RC - | lfdx f0, TMP2, RC - | checknil TMP1; beq >5 - |1: - | ins_next1 - | stfdx f0, BASE, RA - | ins_next2 - | - |5: // Check for __index if table value is nil. - | lwz TAB:TMP2, TAB:RB->metatable - | cmplwi TAB:TMP2, 0 - | beq <1 // No metatable: done. - | lbz TMP2, TAB:TMP2->nomm - | andi. TMP2, TMP2, 1<vmeta_tgetb // Caveat: preserve TMP0! - break; - - case BC_TSETV: - | // RA = src*8, RB = table*8, RC = key*8 - | lwzux CARG1, RB, BASE - | lwzux CARG2, RC, BASE - | lwz TAB:RB, 4(RB) - if (LJ_DUALNUM) { - | lwz RC, 4(RC) - } else { - | lfd f0, 0(RC) - } - | checktab CARG1 - | checknum cr1, CARG2 - | bne ->vmeta_tsetv - if (LJ_DUALNUM) { - | lwz TMP0, TAB:RB->asize - | bne cr1, >5 - | lwz TMP1, TAB:RB->array - | cmplw TMP0, RC - | slwi TMP0, RC, 3 - } else { - | bge cr1, >5 - | // Convert number key to integer, check for integerness and range. - | fctiwz f1, f0 - | fadd f2, f0, TOBIT - | stfd f1, TMPD - | lwz TMP0, TAB:RB->asize - | fsub f2, f2, TOBIT - | lwz TMP2, TMPD_LO - | lwz TMP1, TAB:RB->array - | fcmpu cr1, f0, f2 - | cmplw cr0, TMP0, TMP2 - | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+eq - | slwi TMP0, TMP2, 3 - } - | ble ->vmeta_tsetv // Integer key and in array part? - | lwzx TMP2, TMP1, TMP0 - | lbz TMP3, TAB:RB->marked - | lfdx f14, BASE, RA - | checknil TMP2; beq >3 - |1: - | andi. TMP2, TMP3, LJ_GC_BLACK // isblack(table) - | stfdx f14, TMP1, TMP0 - | bne >7 - |2: - | ins_next - | - |3: // Check for __newindex if previous value is nil. - | lwz TAB:TMP2, TAB:RB->metatable - | cmplwi TAB:TMP2, 0 - | beq <1 // No metatable: done. - | lbz TMP2, TAB:TMP2->nomm - | andi. TMP2, TMP2, 1<vmeta_tsetv - | - |5: - | checkstr CARG2; bne ->vmeta_tsetv - if (!LJ_DUALNUM) { - | lwz STR:RC, 4(RC) - } - | b ->BC_TSETS_Z // String key? - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, TMP3, TMP0 - | b <2 - break; - case BC_TSETS: - | // RA = src*8, RB = table*8, RC = str_const*8 (~) - | lwzux CARG1, RB, BASE - | srwi TMP1, RC, 1 - | lwz TAB:RB, 4(RB) - | subfic TMP1, TMP1, -4 - | checktab CARG1 - | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 - | bne ->vmeta_tsets1 - |->BC_TSETS_Z: - | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = src*8 - | lwz TMP0, TAB:RB->hmask - | lwz TMP1, STR:RC->hash - | lwz NODE:TMP2, TAB:RB->node - | stb ZERO, TAB:RB->nomm // Clear metamethod cache. - | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask - | lfdx f14, BASE, RA - | slwi TMP0, TMP1, 5 - | slwi TMP1, TMP1, 3 - | sub TMP1, TMP0, TMP1 - | lbz TMP3, TAB:RB->marked - | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) - |1: - | lwz CARG1, NODE:TMP2->key - | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2) - | lwz CARG2, NODE:TMP2->val - | lwz NODE:TMP1, NODE:TMP2->next - | checkstr CARG1; bne >5 - | cmpw TMP0, STR:RC; bne >5 - | checknil CARG2; beq >4 // Key found, but nil value? - |2: - | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) - | stfd f14, NODE:TMP2->val - | bne >7 - |3: - | ins_next - | - |4: // Check for __newindex if previous value is nil. - | lwz TAB:TMP1, TAB:RB->metatable - | cmplwi TAB:TMP1, 0 - | beq <2 // No metatable: done. - | lbz TMP0, TAB:TMP1->nomm - | andi. TMP0, TMP0, 1<vmeta_tsets - | - |5: // Follow hash chain. - | cmplwi NODE:TMP1, 0 - | mr NODE:TMP2, NODE:TMP1 - | bne <1 - | // End of hash chain: key not found, add a new one. - | - | // But check for __newindex first. - | lwz TAB:TMP1, TAB:RB->metatable - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | stw PC, SAVE_PC - | mr CARG1, L - | cmplwi TAB:TMP1, 0 - | stw BASE, L->base - | beq >6 // No metatable: continue. - | lbz TMP0, TAB:TMP1->nomm - | andi. TMP0, TMP0, 1<vmeta_tsets // 'no __newindex' flag NOT set: check. - |6: - | li TMP0, LJ_TSTR - | stw STR:RC, 4(CARG3) - | mr CARG2, TAB:RB - | stw TMP0, 0(CARG3) - | bl extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k) - | // Returns TValue *. - | lwz BASE, L->base - | stfd f14, 0(CRET1) - | b <3 // No 2nd write barrier needed. - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, TMP3, TMP0 - | b <3 - break; - case BC_TSETB: - | // RA = src*8, RB = table*8, RC = index*8 - | lwzux CARG1, RB, BASE - | srwi TMP0, RC, 3 - | lwz TAB:RB, 4(RB) - | checktab CARG1; bne ->vmeta_tsetb - | lwz TMP1, TAB:RB->asize - | lwz TMP2, TAB:RB->array - | lbz TMP3, TAB:RB->marked - | cmplw TMP0, TMP1 - | lfdx f14, BASE, RA - | bge ->vmeta_tsetb - | lwzx TMP1, TMP2, RC - | checknil TMP1; beq >5 - |1: - | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) - | stfdx f14, TMP2, RC - | bne >7 - |2: - | ins_next - | - |5: // Check for __newindex if previous value is nil. - | lwz TAB:TMP1, TAB:RB->metatable - | cmplwi TAB:TMP1, 0 - | beq <1 // No metatable: done. - | lbz TMP1, TAB:TMP1->nomm - | andi. TMP1, TMP1, 1<vmeta_tsetb // Caveat: preserve TMP0! - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, TMP3, TMP0 - | b <2 - break; - - case BC_TSETM: - | // RA = base*8 (table at base-1), RD = num_const*8 (start index) - | add RA, BASE, RA - |1: - | add TMP3, KBASE, RD - | lwz TAB:CARG2, -4(RA) // Guaranteed to be a table. - | addic. TMP0, MULTRES, -8 - | lwz TMP3, 4(TMP3) // Integer constant is in lo-word. - | srwi CARG3, TMP0, 3 - | beq >4 // Nothing to copy? - | add CARG3, CARG3, TMP3 - | lwz TMP2, TAB:CARG2->asize - | slwi TMP1, TMP3, 3 - | lbz TMP3, TAB:CARG2->marked - | cmplw CARG3, TMP2 - | add TMP2, RA, TMP0 - | lwz TMP0, TAB:CARG2->array - | bgt >5 - | add TMP1, TMP1, TMP0 - | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) - |3: // Copy result slots to table. - | lfd f0, 0(RA) - | addi RA, RA, 8 - | cmpw cr1, RA, TMP2 - | stfd f0, 0(TMP1) - | addi TMP1, TMP1, 8 - | blt cr1, <3 - | bne >7 - |4: - | ins_next - | - |5: // Need to resize array part. - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | mr SAVE0, RD - | bl extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize) - | // Must not reallocate the stack. - | mr RD, SAVE0 - | b <1 - | - |7: // Possible table write barrier for any value. Skip valiswhite check. - | barrierback TAB:CARG2, TMP3, TMP0 - | b <4 - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALLM: - | // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8 - | add NARGS8:RC, NARGS8:RC, MULTRES - | // Fall through. Assumes BC_CALL follows. - break; - case BC_CALL: - | // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8 - | mr TMP2, BASE - | lwzux TMP0, BASE, RA - | lwz LFUNC:RB, 4(BASE) - | subi NARGS8:RC, NARGS8:RC, 8 - | addi BASE, BASE, 8 - | checkfunc TMP0; bne ->vmeta_call - | ins_call - break; - - case BC_CALLMT: - | // RA = base*8, (RB = 0,) RC = extra_nargs*8 - | add NARGS8:RC, NARGS8:RC, MULTRES - | // Fall through. Assumes BC_CALLT follows. - break; - case BC_CALLT: - | // RA = base*8, (RB = 0,) RC = (nargs+1)*8 - | lwzux TMP0, RA, BASE - | lwz LFUNC:RB, 4(RA) - | subi NARGS8:RC, NARGS8:RC, 8 - | lwz TMP1, FRAME_PC(BASE) - | checkfunc TMP0 - | addi RA, RA, 8 - | bne ->vmeta_callt - |->BC_CALLT_Z: - | andi. TMP0, TMP1, FRAME_TYPE // Caveat: preserve cr0 until the crand. - | lbz TMP3, LFUNC:RB->ffid - | xori TMP2, TMP1, FRAME_VARG - | cmplwi cr1, NARGS8:RC, 0 - | bne >7 - |1: - | stw LFUNC:RB, FRAME_FUNC(BASE) // Copy function down, but keep PC. - | li TMP2, 0 - | cmplwi cr7, TMP3, 1 // (> FF_C) Calling a fast function? - | beq cr1, >3 - |2: - | addi TMP3, TMP2, 8 - | lfdx f0, RA, TMP2 - | cmplw cr1, TMP3, NARGS8:RC - | stfdx f0, BASE, TMP2 - | mr TMP2, TMP3 - | bne cr1, <2 - |3: - | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+gt - | beq >5 - |4: - | ins_callt - | - |5: // Tailcall to a fast function with a Lua frame below. - | lwz INS, -4(TMP1) - | decode_RA8 RA, INS - | sub TMP1, BASE, RA - | lwz LFUNC:TMP1, FRAME_FUNC-8(TMP1) - | lwz TMP1, LFUNC:TMP1->pc - | lwz KBASE, PC2PROTO(k)(TMP1) // Need to prepare KBASE. - | b <4 - | - |7: // Tailcall from a vararg function. - | andi. TMP0, TMP2, FRAME_TYPEP - | bne <1 // Vararg frame below? - | sub BASE, BASE, TMP2 // Relocate BASE down. - | lwz TMP1, FRAME_PC(BASE) - | andi. TMP0, TMP1, FRAME_TYPE - | b <1 - break; - - case BC_ITERC: - | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8)) - | mr TMP2, BASE - | add BASE, BASE, RA - | lwz TMP1, -24(BASE) - | lwz LFUNC:RB, -20(BASE) - | lfd f1, -8(BASE) - | lfd f0, -16(BASE) - | stw TMP1, 0(BASE) // Copy callable. - | stw LFUNC:RB, 4(BASE) - | checkfunc TMP1 - | stfd f1, 16(BASE) // Copy control var. - | li NARGS8:RC, 16 // Iterators get 2 arguments. - | stfdu f0, 8(BASE) // Copy state. - | bne ->vmeta_call - | ins_call - break; - - case BC_ITERN: - | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) -#if LJ_HASJIT - | // NYI: add hotloop, record BC_ITERN. -#endif - | add RA, BASE, RA - | lwz TAB:RB, -12(RA) - | lwz RC, -4(RA) // Get index from control var. - | lwz TMP0, TAB:RB->asize - | lwz TMP1, TAB:RB->array - | addi PC, PC, 4 - |1: // Traverse array part. - | cmplw RC, TMP0 - | slwi TMP3, RC, 3 - | bge >5 // Index points after array part? - | lwzx TMP2, TMP1, TMP3 - | lfdx f0, TMP1, TMP3 - | checknil TMP2 - | lwz INS, -4(PC) - | beq >4 - if (LJ_DUALNUM) { - | stw RC, 4(RA) - | stw TISNUM, 0(RA) - } else { - | tonum_u f1, RC - } - | addi RC, RC, 1 - | addis TMP3, PC, -(BCBIAS_J*4 >> 16) - | stfd f0, 8(RA) - | decode_RD4 TMP1, INS - | stw RC, -4(RA) // Update control var. - | add PC, TMP1, TMP3 - if (!LJ_DUALNUM) { - | stfd f1, 0(RA) - } - |3: - | ins_next - | - |4: // Skip holes in array part. - | addi RC, RC, 1 - | b <1 - | - |5: // Traverse hash part. - | lwz TMP1, TAB:RB->hmask - | sub RC, RC, TMP0 - | lwz TMP2, TAB:RB->node - |6: - | cmplw RC, TMP1 // End of iteration? Branch to ITERL+1. - | slwi TMP3, RC, 5 - | bgty <3 - | slwi RB, RC, 3 - | sub TMP3, TMP3, RB - | lwzx RB, TMP2, TMP3 - | lfdx f0, TMP2, TMP3 - | add NODE:TMP3, TMP2, TMP3 - | checknil RB - | lwz INS, -4(PC) - | beq >7 - | lfd f1, NODE:TMP3->key - | addis TMP2, PC, -(BCBIAS_J*4 >> 16) - | stfd f0, 8(RA) - | add RC, RC, TMP0 - | decode_RD4 TMP1, INS - | stfd f1, 0(RA) - | addi RC, RC, 1 - | add PC, TMP1, TMP2 - | stw RC, -4(RA) // Update control var. - | b <3 - | - |7: // Skip holes in hash part. - | addi RC, RC, 1 - | b <6 - break; - - case BC_ISNEXT: - | // RA = base*8, RD = target (points to ITERN) - | add RA, BASE, RA - | lwz TMP0, -24(RA) - | lwz CFUNC:TMP1, -20(RA) - | lwz TMP2, -16(RA) - | lwz TMP3, -8(RA) - | cmpwi cr0, TMP2, LJ_TTAB - | cmpwi cr1, TMP0, LJ_TFUNC - | cmpwi cr6, TMP3, LJ_TNIL - | bne cr1, >5 - | lbz TMP1, CFUNC:TMP1->ffid - | crand 4*cr0+eq, 4*cr0+eq, 4*cr6+eq - | cmpwi cr7, TMP1, FF_next_N - | srwi TMP0, RD, 1 - | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq - | add TMP3, PC, TMP0 - | bne cr0, >5 - | stw ZERO, -4(RA) // Initialize control var. - | addis PC, TMP3, -(BCBIAS_J*4 >> 16) - |1: - | ins_next - |5: // Despecialize bytecode if any of the checks fail. - | li TMP0, BC_JMP - | li TMP1, BC_ITERC - | stb TMP0, -1(PC) - | addis PC, TMP3, -(BCBIAS_J*4 >> 16) - | stb TMP1, 3(PC) - | b <1 - break; - - case BC_VARG: - | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8 - | lwz TMP0, FRAME_PC(BASE) - | add RC, BASE, RC - | add RA, BASE, RA - | addi RC, RC, FRAME_VARG - | add TMP2, RA, RB - | subi TMP3, BASE, 8 // TMP3 = vtop - | sub RC, RC, TMP0 // RC = vbase - | // Note: RC may now be even _above_ BASE if nargs was < numparams. - | cmplwi cr1, RB, 0 - | sub. TMP1, TMP3, RC - | beq cr1, >5 // Copy all varargs? - | subi TMP2, TMP2, 16 - | ble >2 // No vararg slots? - |1: // Copy vararg slots to destination slots. - | lfd f0, 0(RC) - | addi RC, RC, 8 - | stfd f0, 0(RA) - | cmplw RA, TMP2 - | cmplw cr1, RC, TMP3 - | bge >3 // All destination slots filled? - | addi RA, RA, 8 - | blt cr1, <1 // More vararg slots? - |2: // Fill up remainder with nil. - | stw TISNIL, 0(RA) - | cmplw RA, TMP2 - | addi RA, RA, 8 - | blt <2 - |3: - | ins_next - | - |5: // Copy all varargs. - | lwz TMP0, L->maxstack - | li MULTRES, 8 // MULTRES = (0+1)*8 - | bley <3 // No vararg slots? - | add TMP2, RA, TMP1 - | cmplw TMP2, TMP0 - | addi MULTRES, TMP1, 8 - | bgt >7 - |6: - | lfd f0, 0(RC) - | addi RC, RC, 8 - | stfd f0, 0(RA) - | cmplw RC, TMP3 - | addi RA, RA, 8 - | blt <6 // More vararg slots? - | b <3 - | - |7: // Grow stack for varargs. - | mr CARG1, L - | stw RA, L->top - | sub SAVE0, RC, BASE // Need delta, because BASE may change. - | stw BASE, L->base - | sub RA, RA, BASE - | stw PC, SAVE_PC - | srwi CARG2, TMP1, 3 - | bl extern lj_state_growstack // (lua_State *L, int n) - | lwz BASE, L->base - | add RA, BASE, RA - | add RC, BASE, SAVE0 - | subi TMP3, BASE, 8 - | b <6 - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - | // RA = results*8, RD = extra_nresults*8 - | add RD, RD, MULTRES // MULTRES >= 8, so RD >= 8. - | // Fall through. Assumes BC_RET follows. - break; - - case BC_RET: - | // RA = results*8, RD = (nresults+1)*8 - | lwz PC, FRAME_PC(BASE) - | add RA, BASE, RA - | mr MULTRES, RD - |1: - | andi. TMP0, PC, FRAME_TYPE - | xori TMP1, PC, FRAME_VARG - | bne ->BC_RETV_Z - | - |->BC_RET_Z: - | // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return - | lwz INS, -4(PC) - | cmpwi RD, 8 - | subi TMP2, BASE, 8 - | subi RC, RD, 8 - | decode_RB8 RB, INS - | beq >3 - | li TMP1, 0 - |2: - | addi TMP3, TMP1, 8 - | lfdx f0, RA, TMP1 - | cmpw TMP3, RC - | stfdx f0, TMP2, TMP1 - | beq >3 - | addi TMP1, TMP3, 8 - | lfdx f1, RA, TMP3 - | cmpw TMP1, RC - | stfdx f1, TMP2, TMP3 - | bne <2 - |3: - |5: - | cmplw RB, RD - | decode_RA8 RA, INS - | bgt >6 - | sub BASE, TMP2, RA - | lwz LFUNC:TMP1, FRAME_FUNC(BASE) - | ins_next1 - | lwz TMP1, LFUNC:TMP1->pc - | lwz KBASE, PC2PROTO(k)(TMP1) - | ins_next2 - | - |6: // Fill up results with nil. - | subi TMP1, RD, 8 - | addi RD, RD, 8 - | stwx TISNIL, TMP2, TMP1 - | b <5 - | - |->BC_RETV_Z: // Non-standard return case. - | andi. TMP2, TMP1, FRAME_TYPEP - | bne ->vm_return - | // Return from vararg function: relocate BASE down. - | sub BASE, BASE, TMP1 - | lwz PC, FRAME_PC(BASE) - | b <1 - break; - - case BC_RET0: case BC_RET1: - | // RA = results*8, RD = (nresults+1)*8 - | lwz PC, FRAME_PC(BASE) - | add RA, BASE, RA - | mr MULTRES, RD - | andi. TMP0, PC, FRAME_TYPE - | xori TMP1, PC, FRAME_VARG - | bney ->BC_RETV_Z - | - | lwz INS, -4(PC) - | subi TMP2, BASE, 8 - | decode_RB8 RB, INS - if (op == BC_RET1) { - | lfd f0, 0(RA) - | stfd f0, 0(TMP2) - } - |5: - | cmplw RB, RD - | decode_RA8 RA, INS - | bgt >6 - | sub BASE, TMP2, RA - | lwz LFUNC:TMP1, FRAME_FUNC(BASE) - | ins_next1 - | lwz TMP1, LFUNC:TMP1->pc - | lwz KBASE, PC2PROTO(k)(TMP1) - | ins_next2 - | - |6: // Fill up results with nil. - | subi TMP1, RD, 8 - | addi RD, RD, 8 - | stwx TISNIL, TMP2, TMP1 - | b <5 - break; - - /* -- Loops and branches ------------------------------------------------ */ - - case BC_FORL: -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_IFORL follows. - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - | // RA = base*8, RD = target (after end of loop or start of loop) - vk = (op == BC_IFORL || op == BC_JFORL); - if (LJ_DUALNUM) { - | // Integer loop. - | lwzux TMP1, RA, BASE - | lwz CARG1, FORL_IDX*8+4(RA) - | cmplw cr0, TMP1, TISNUM - if (vk) { - | lwz CARG3, FORL_STEP*8+4(RA) - | bne >9 - | addo. CARG1, CARG1, CARG3 - | cmpwi cr6, CARG3, 0 - | lwz CARG2, FORL_STOP*8+4(RA) - | bso >6 - |4: - | stw CARG1, FORL_IDX*8+4(RA) - } else { - | lwz TMP3, FORL_STEP*8(RA) - | lwz CARG3, FORL_STEP*8+4(RA) - | lwz TMP2, FORL_STOP*8(RA) - | lwz CARG2, FORL_STOP*8+4(RA) - | cmplw cr7, TMP3, TISNUM - | cmplw cr1, TMP2, TISNUM - | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq - | crand 4*cr0+eq, 4*cr0+eq, 4*cr1+eq - | cmpwi cr6, CARG3, 0 - | bne >9 - } - | blt cr6, >5 - | cmpw CARG1, CARG2 - |1: - | stw TISNUM, FORL_EXT*8(RA) - if (op != BC_JFORL) { - | srwi RD, RD, 1 - } - | stw CARG1, FORL_EXT*8+4(RA) - if (op != BC_JFORL) { - | add RD, PC, RD - } - if (op == BC_FORI) { - | bgt >3 // See FP loop below. - } else if (op == BC_JFORI) { - | addis PC, RD, -(BCBIAS_J*4 >> 16) - | bley >7 - } else if (op == BC_IFORL) { - | bgt >2 - | addis PC, RD, -(BCBIAS_J*4 >> 16) - } else { - | bley =>BC_JLOOP - } - |2: - | ins_next - |5: // Invert check for negative step. - | cmpw CARG2, CARG1 - | b <1 - if (vk) { - |6: // Potential overflow. - | mcrxr cr0; bley <4 // Ignore unrelated overflow. - | b <2 - } - } - if (vk) { - if (LJ_DUALNUM) { - |9: // FP loop. - | lfd f1, FORL_IDX*8(RA) - } else { - | lfdux f1, RA, BASE - } - | lfd f3, FORL_STEP*8(RA) - | lfd f2, FORL_STOP*8(RA) - | lwz TMP3, FORL_STEP*8(RA) - | fadd f1, f1, f3 - | stfd f1, FORL_IDX*8(RA) - } else { - if (LJ_DUALNUM) { - |9: // FP loop. - } else { - | lwzux TMP1, RA, BASE - | lwz TMP3, FORL_STEP*8(RA) - | lwz TMP2, FORL_STOP*8(RA) - | cmplw cr0, TMP1, TISNUM - | cmplw cr7, TMP3, TISNUM - | cmplw cr1, TMP2, TISNUM - } - | lfd f1, FORL_IDX*8(RA) - | crand 4*cr0+lt, 4*cr0+lt, 4*cr7+lt - | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt - | lfd f2, FORL_STOP*8(RA) - | bge ->vmeta_for - } - | cmpwi cr6, TMP3, 0 - if (op != BC_JFORL) { - | srwi RD, RD, 1 - } - | stfd f1, FORL_EXT*8(RA) - if (op != BC_JFORL) { - | add RD, PC, RD - } - | fcmpu cr0, f1, f2 - if (op == BC_JFORI) { - | addis PC, RD, -(BCBIAS_J*4 >> 16) - } - | blt cr6, >5 - if (op == BC_FORI) { - | bgt >3 - } else if (op == BC_IFORL) { - if (LJ_DUALNUM) { - | bgty <2 - } else { - | bgt >2 - } - |1: - | addis PC, RD, -(BCBIAS_J*4 >> 16) - } else if (op == BC_JFORI) { - | bley >7 - } else { - | bley =>BC_JLOOP - } - if (LJ_DUALNUM) { - | b <2 - } else { - |2: - | ins_next - } - |5: // Negative step. - if (op == BC_FORI) { - | bge <2 - |3: // Used by integer loop, too. - | addis PC, RD, -(BCBIAS_J*4 >> 16) - } else if (op == BC_IFORL) { - | bgey <1 - } else if (op == BC_JFORI) { - | bgey >7 - } else { - | bgey =>BC_JLOOP - } - | b <2 - if (op == BC_JFORI) { - |7: - | lwz INS, -4(PC) - | decode_RD8 RD, INS - | b =>BC_JLOOP - } - break; - - case BC_ITERL: -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_IITERL follows. - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - | // RA = base*8, RD = target - | lwzux TMP1, RA, BASE - | lwz TMP2, 4(RA) - | checknil TMP1; beq >1 // Stop if iterator returned nil. - if (op == BC_JITERL) { - | stw TMP1, -8(RA) - | stw TMP2, -4(RA) - | b =>BC_JLOOP - } else { - | branch_RD // Otherwise save control var + branch. - | stw TMP1, -8(RA) - | stw TMP2, -4(RA) - } - |1: - | ins_next - break; - - case BC_LOOP: - | // RA = base*8, RD = target (loop extent) - | // Note: RA/RD is only used by trace recorder to determine scope/extent - | // This opcode does NOT jump, it's only purpose is to detect a hot loop. -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_ILOOP follows. - break; - - case BC_ILOOP: - | // RA = base*8, RD = target (loop extent) - | ins_next - break; - - case BC_JLOOP: -#if LJ_HASJIT - | // RA = base*8 (ignored), RD = traceno*8 - | lwz TMP1, DISPATCH_J(trace)(DISPATCH) - | srwi RD, RD, 1 - | // Traces on PPC don't store the trace number, so use 0. - | stw ZERO, DISPATCH_GL(vmstate)(DISPATCH) - | lwzx TRACE:TMP2, TMP1, RD - | mcrxr cr0 // Clear SO flag. - | lwz TMP2, TRACE:TMP2->mcode - | stw BASE, DISPATCH_GL(jit_base)(DISPATCH) - | mtctr TMP2 - | stw L, DISPATCH_GL(jit_L)(DISPATCH) - | addi JGL, DISPATCH, GG_DISP2G+32768 - | bctr -#endif - break; - - case BC_JMP: - | // RA = base*8 (only used by trace recorder), RD = target - | branch_RD - | ins_next - break; - - /* -- Function headers -------------------------------------------------- */ - - case BC_FUNCF: -#if LJ_HASJIT - | hotcall -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow. - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 - | lwz TMP2, L->maxstack - | lbz TMP1, -4+PC2PROTO(numparams)(PC) - | lwz KBASE, -4+PC2PROTO(k)(PC) - | cmplw RA, TMP2 - | slwi TMP1, TMP1, 3 - | bgt ->vm_growstack_l - if (op != BC_JFUNCF) { - | ins_next1 - } - |2: - | cmplw NARGS8:RC, TMP1 // Check for missing parameters. - | blt >3 - if (op == BC_JFUNCF) { - | decode_RD8 RD, INS - | b =>BC_JLOOP - } else { - | ins_next2 - } - | - |3: // Clear missing parameters. - | stwx TISNIL, BASE, NARGS8:RC - | addi NARGS8:RC, NARGS8:RC, 8 - | b <2 - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - | NYI // NYI: compiled vararg functions - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 - | lwz TMP2, L->maxstack - | add TMP1, BASE, RC - | add TMP0, RA, RC - | stw LFUNC:RB, 4(TMP1) // Store copy of LFUNC. - | addi TMP3, RC, 8+FRAME_VARG - | lwz KBASE, -4+PC2PROTO(k)(PC) - | cmplw TMP0, TMP2 - | stw TMP3, 0(TMP1) // Store delta + FRAME_VARG. - | bge ->vm_growstack_l - | lbz TMP2, -4+PC2PROTO(numparams)(PC) - | mr RA, BASE - | mr RC, TMP1 - | ins_next1 - | cmpwi TMP2, 0 - | addi BASE, TMP1, 8 - | beq >3 - |1: - | cmplw RA, RC // Less args than parameters? - | lwz TMP0, 0(RA) - | lwz TMP3, 4(RA) - | bge >4 - | stw TISNIL, 0(RA) // Clear old fixarg slot (help the GC). - | addi RA, RA, 8 - |2: - | addic. TMP2, TMP2, -1 - | stw TMP0, 8(TMP1) - | stw TMP3, 12(TMP1) - | addi TMP1, TMP1, 8 - | bne <1 - |3: - | ins_next2 - | - |4: // Clear missing parameters. - | li TMP0, LJ_TNIL - | b <2 - break; - - case BC_FUNCC: - case BC_FUNCCW: - | // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8 - if (op == BC_FUNCC) { - | lwz TMP3, CFUNC:RB->f - } else { - | lwz TMP3, DISPATCH_GL(wrapf)(DISPATCH) - } - | add TMP1, RA, NARGS8:RC - | lwz TMP2, L->maxstack - | add RC, BASE, NARGS8:RC - | stw BASE, L->base - | cmplw TMP1, TMP2 - | stw RC, L->top - | li_vmstate C - | mtctr TMP3 - if (op == BC_FUNCCW) { - | lwz CARG2, CFUNC:RB->f - } - | mr CARG1, L - | bgt ->vm_growstack_c // Need to grow stack. - | st_vmstate - | bctrl // (lua_State *L [, lua_CFunction f]) - | // Returns nresults. - | lwz BASE, L->base - | slwi RD, CRET1, 3 - | lwz TMP1, L->top - | li_vmstate INTERP - | lwz PC, FRAME_PC(BASE) // Fetch PC of caller. - | sub RA, TMP1, RD // RA = L->top - nresults*8 - | st_vmstate - | b ->vm_returnc - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx); - - |.code_op - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); - int i; - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.long .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.long 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 65\n" - "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.long .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.long .Lframe0\n" - "\t.long .Lbegin\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x5\n\t.uleb128 70\n\t.uleb128 55\n", - fcofs, CFRAME_SIZE); - for (i = 14; i <= 31; i++) - fprintf(ctx->fp, - "\t.byte %d\n\t.uleb128 %d\n" - "\t.byte %d\n\t.uleb128 %d\n", - 0x80+i, 37+(31-i), 0x80+32+i, 2+2*(31-i)); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE0:\n\n"); -#if LJ_HASFFI - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.long .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.long .Lframe0\n" - "\t.long lj_vm_ffi_call\n" - "\t.long %d\n" - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x8e\n\t.uleb128 2\n" - "\t.byte 0xd\n\t.uleb128 0xe\n" - "\t.align 2\n" - ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); -#endif - fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe1:\n" - "\t.long .LECIE1-.LSCIE1\n" - ".LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zPR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 65\n" - "\t.uleb128 6\n" /* augmentation length */ - "\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 1\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE1:\n\n"); - fprintf(ctx->fp, - ".LSFDE2:\n" - "\t.long .LEFDE2-.LASFDE2\n" - ".LASFDE2:\n" - "\t.long .LASFDE2-.Lframe1\n" - "\t.long .Lbegin-.\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x5\n\t.uleb128 70\n\t.uleb128 55\n", - fcofs, CFRAME_SIZE); - for (i = 14; i <= 31; i++) - fprintf(ctx->fp, - "\t.byte %d\n\t.uleb128 %d\n" - "\t.byte %d\n\t.uleb128 %d\n", - 0x80+i, 37+(31-i), 0x80+32+i, 2+2*(31-i)); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE2:\n\n"); -#if LJ_HASFFI - fprintf(ctx->fp, - ".Lframe2:\n" - "\t.long .LECIE2-.LSCIE2\n" - ".LSCIE2:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 65\n" - "\t.uleb128 1\n" /* augmentation length */ - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE2:\n\n"); - fprintf(ctx->fp, - ".LSFDE3:\n" - "\t.long .LEFDE3-.LASFDE3\n" - ".LASFDE3:\n" - "\t.long .LASFDE3-.Lframe2\n" - "\t.long lj_vm_ffi_call-.\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x8e\n\t.uleb128 2\n" - "\t.byte 0xd\n\t.uleb128 0xe\n" - "\t.align 2\n" - ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); -#endif - break; - default: - break; - } -} - diff --git a/src/buildvm_ppc.h b/src/buildvm_ppc.h deleted file mode 100644 index ce0941ec..00000000 --- a/src/buildvm_ppc.h +++ /dev/null @@ -1,9797 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM ppc version 1.3.0 -** DO NOT EDIT! The original file is in "buildvm_ppc.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -#define DASM_SECTION_CODE_OP 0 -#define DASM_SECTION_CODE_SUB 1 -#define DASM_MAXSECTION 2 -static const unsigned int build_actionlist[7763] = { -0x00010001, -0x00060014, -0x72000000, -0x00090200, -0x39000000, -0x00098200, -0x41820000, -0x00050815, -0x8209fff8, -0x7d2e4b78, -0x9514fff8, -0x00060016, -0x72000000, -0x00090200, -0x398c0008, -0x7d936378, -0x41820000, -0x00050817, -0x00060018, -0x2c000000, -0x00098200, -0x56090038, -0x38000000, -0x00098200, -0x7d297050, -0x40a20000, -0x00050814, -0x350cfff8, -0x91320000, -0x00098200, -0x8121002c, -0x39cefff8, -0x90110000, -0x00098200, -0x55291800, -0x000900a1, -0x41820000, -0x00050802, -0x0006000b, -0x3508fff8, -0xc8140000, -0x3a940008, -0xd80e0000, -0x39ce0008, -0x40a20000, -0x0005080b, -0x0006000c, -0x7c096000, -0x40820000, -0x00050806, -0x0006000d, -0x91d20000, -0x00098200, -0x00060019, -0x00000000, -0x80010028, -0x38600000, -0x90120000, -0x00098200, -0x0006001a, -0x80010114, -0x81810034, -0x81c10000, -0x00098200, -0xc9c10000, -0x00098200, -0x81e10000, -0x00098200, -0xc9e10000, -0x00098200, -0x82010000, -0x00098200, -0xca010000, -0x00098200, -0x82210000, -0x00098200, -0xca210000, -0x00098200, -0x82410000, -0x00098200, -0xca410000, -0x00098200, -0x82610000, -0x00098200, -0xca610000, -0x00098200, -0x7c0803a6, -0x7d838120, -0x82810000, -0x00098200, -0xca810000, -0x00098200, -0x82a10000, -0x00098200, -0xcaa10000, -0x00098200, -0x82c10000, -0x00098200, -0xcac10000, -0x00098200, -0x82e10000, -0x00098200, -0xcae10000, -0x00098200, -0x00000000, -0x83010000, -0x00098200, -0xcb010000, -0x00098200, -0x83210000, -0x00098200, -0xcb210000, -0x00098200, -0x83410000, -0x00098200, -0xcb410000, -0x00098200, -0x83610000, -0x00098200, -0xcb610000, -0x00098200, -0x83810000, -0x00098200, -0xcb810000, -0x00098200, -0x83a10000, -0x00098200, -0xcba10000, -0x00098200, -0x83c10000, -0x00098200, -0xcbc10000, -0x00098200, -0x83e10000, -0x00098200, -0xcbe10000, -0x00098200, -0x38210110, -0x4e800020, -0x00060010, -0x40810000, -0x00050807, -0x81120000, -0x00098200, -0x7c0e4040, -0x40800000, -0x00050808, -0x92ee0000, -0x398c0008, -0x39ce0008, -0x48000000, -0x0005000c, -0x00060011, -0x00000000, -0x20c90000, -0x7c096050, -0x7d084110, -0x7c004038, -0x7dc07050, -0x48000000, -0x0005000d, -0x00060012, -0x91d20000, -0x00098200, -0x7d956378, -0x7d244b78, -0x7e439378, -0x48000001, -0x00030000, -0x8121002c, -0x7eacab78, -0x55291800, -0x000900a1, -0x81d20000, -0x00098200, -0x48000000, -0x0005000c, -0x0006001b, -0x7c611b78, -0x7c832378, -0x0006001c, -0x82410024, -0x38000000, -0x00098200, -0x81120000, -0x00098200, -0x90080000, -0x00098200, -0x48000000, -0x0005001a, -0x0006001d, -0x5461003a, -0x0006001e, -0x82410024, -0x3ac00000, -0x00098200, -0x81d20000, -0x00098200, -0x3cc059c0, -0x82320000, -0x00098200, -0x3b000000, -0x90c10010, -0x39000000, -0x00098200, -0x60c60004, -0x3ae00000, -0x00098200, -0x38000000, -0x00098200, -0xc3c10010, -0x820efff8, -0x3a8efff8, -0x90c10010, -0x3a310000, -0x00098200, -0x00000000, -0x91140000, -0x39800010, -0x90110000, -0x00098200, -0xc3e10010, -0x48000000, -0x00050016, -0x0006001f, -0x38800000, -0x00098200, -0x48000000, -0x00050002, -0x00060020, -0x7d6e5a14, -0x7e8ea050, -0x91d20000, -0x00098200, -0x3a100004, -0x91720000, -0x00098200, -0x568400fe, -0x000900ab, -0x0006000c, -0x92010020, -0x7e439378, -0x48000001, -0x00030000, -0x81d20000, -0x00098200, -0x81720000, -0x00098200, -0x814efffc, -0x7d6e5850, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00060021, -0x9421fef0, -0x91c10000, -0x00098200, -0xd9c10000, -0x00098200, -0x91e10000, -0x00098200, -0xd9e10000, -0x00098200, -0x92010000, -0x00098200, -0xda010000, -0x00098200, -0x7c0802a6, -0x92210000, -0x00098200, -0x00000000, -0xda210000, -0x00098200, -0x92410000, -0x00098200, -0xda410000, -0x00098200, -0x92610000, -0x00098200, -0xda610000, -0x00098200, -0x92810000, -0x00098200, -0xda810000, -0x00098200, -0x92a10000, -0x00098200, -0xdaa10000, -0x00098200, -0x92c10000, -0x00098200, -0xdac10000, -0x00098200, -0x90010114, -0x92e10000, -0x00098200, -0xdae10000, -0x00098200, -0x93010000, -0x00098200, -0xdb010000, -0x00098200, -0x93210000, -0x00098200, -0xdb210000, -0x00098200, -0x7c000026, -0x93410000, -0x00098200, -0xdb410000, -0x00098200, -0x93610000, -0x00098200, -0xdb610000, -0x00098200, -0x93810000, -0x00098200, -0x00000000, -0xdb810000, -0x00098200, -0x93a10000, -0x00098200, -0xdba10000, -0x00098200, -0x93c10000, -0x00098200, -0xdbc10000, -0x00098200, -0x93e10000, -0x00098200, -0xdbe10000, -0x00098200, -0x90010034, -0x7c721b78, -0x82320000, -0x00098200, -0x7c8e2378, -0x89120000, -0x00098200, -0x92410024, -0x3a000000, -0x00098200, -0x38010000, -0x00098200, -0x3a310000, -0x00098200, -0x90a1002c, -0x28080000, -0x90a10030, -0x90120000, -0x00098200, -0x90a10028, -0x90610020, -0x41820000, -0x00050803, -0x7dd47378, -0x81d20000, -0x00098200, -0x3ac00000, -0x00098200, -0x81120000, -0x00098200, -0x820efff8, -0x3cc059c0, -0x98b20000, -0x00098200, -0x90c10010, -0x60c60004, -0xc3c10010, -0x7d8e4050, -0x90c10010, -0x3c004338, -0x398c0008, -0x90010008, -0x38000000, -0x00098200, -0x3b000000, -0x90110000, -0x00098200, -0x72000000, -0x00090200, -0x7d936378, -0xc3e10010, -0x3ae00000, -0x00098200, -0x00000000, -0x41820000, -0x00050817, -0x48000000, -0x00050018, -0x00060022, -0x9421fef0, -0x91c10000, -0x00098200, -0xd9c10000, -0x00098200, -0x91e10000, -0x00098200, -0xd9e10000, -0x00098200, -0x92010000, -0x00098200, -0xda010000, -0x00098200, -0x7c0802a6, -0x92210000, -0x00098200, -0xda210000, -0x00098200, -0x92410000, -0x00098200, -0xda410000, -0x00098200, -0x92610000, -0x00098200, -0xda610000, -0x00098200, -0x92810000, -0x00098200, -0xda810000, -0x00098200, -0x92a10000, -0x00098200, -0xdaa10000, -0x00098200, -0x92c10000, -0x00098200, -0xdac10000, -0x00098200, -0x90010114, -0x92e10000, -0x00098200, -0x00000000, -0xdae10000, -0x00098200, -0x93010000, -0x00098200, -0xdb010000, -0x00098200, -0x93210000, -0x00098200, -0xdb210000, -0x00098200, -0x7c000026, -0x93410000, -0x00098200, -0xdb410000, -0x00098200, -0x93610000, -0x00098200, -0xdb610000, -0x00098200, -0x93810000, -0x00098200, -0xdb810000, -0x00098200, -0x93a10000, -0x00098200, -0xdba10000, -0x00098200, -0x93c10000, -0x00098200, -0xdbc10000, -0x00098200, -0x93e10000, -0x00098200, -0xdbe10000, -0x00098200, -0x90010034, -0x3a000000, -0x00098200, -0x90c10030, -0x48000000, -0x00050001, -0x00060023, -0x9421fef0, -0x91c10000, -0x00098200, -0xd9c10000, -0x00098200, -0x00000000, -0x91e10000, -0x00098200, -0xd9e10000, -0x00098200, -0x92010000, -0x00098200, -0xda010000, -0x00098200, -0x7c0802a6, -0x92210000, -0x00098200, -0xda210000, -0x00098200, -0x92410000, -0x00098200, -0xda410000, -0x00098200, -0x92610000, -0x00098200, -0xda610000, -0x00098200, -0x92810000, -0x00098200, -0xda810000, -0x00098200, -0x92a10000, -0x00098200, -0xdaa10000, -0x00098200, -0x92c10000, -0x00098200, -0xdac10000, -0x00098200, -0x90010114, -0x92e10000, -0x00098200, -0xdae10000, -0x00098200, -0x93010000, -0x00098200, -0xdb010000, -0x00098200, -0x93210000, -0x00098200, -0xdb210000, -0x00098200, -0x00000000, -0x7c000026, -0x93410000, -0x00098200, -0xdb410000, -0x00098200, -0x93610000, -0x00098200, -0xdb610000, -0x00098200, -0x93810000, -0x00098200, -0xdb810000, -0x00098200, -0x93a10000, -0x00098200, -0xdba10000, -0x00098200, -0x93c10000, -0x00098200, -0xdbc10000, -0x00098200, -0x93e10000, -0x00098200, -0xdbe10000, -0x00098200, -0x90010034, -0x3a000000, -0x00098200, -0x0006000b, -0x81030000, -0x00098200, -0x90a1002c, -0x7c721b78, -0x90610024, -0x7c8e2378, -0x90320000, -0x00098200, -0x82320000, -0x00098200, -0x90610020, -0x91010028, -0x3a310000, -0x00098200, -0x0006000d, -0x81320000, -0x00098200, -0x3ac00000, -0x00098200, -0x81120000, -0x00098200, -0x00000000, -0x3cc059c0, -0x7e107214, -0x90c10010, -0x3b000000, -0x60c60004, -0xc3c10010, -0x7e098050, -0x90c10010, -0x3c004338, -0x7d6e4050, -0x90010008, -0x38000000, -0x00098200, -0xc3e10010, -0x3ae00000, -0x00098200, -0x90110000, -0x00098200, -0x00060024, -0x800efff8, -0x814efffc, -0x2c000000, -0x00098200, -0x40820000, -0x00050825, -0x00060026, -0x920efff8, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00060027, -0x9421fef0, -0x91c10000, -0x00098200, -0xd9c10000, -0x00098200, -0x91e10000, -0x00098200, -0xd9e10000, -0x00098200, -0x92010000, -0x00098200, -0xda010000, -0x00098200, -0x7c0802a6, -0x92210000, -0x00098200, -0xda210000, -0x00098200, -0x92410000, -0x00098200, -0xda410000, -0x00098200, -0x92610000, -0x00098200, -0xda610000, -0x00098200, -0x92810000, -0x00098200, -0x00000000, -0xda810000, -0x00098200, -0x92a10000, -0x00098200, -0xdaa10000, -0x00098200, -0x92c10000, -0x00098200, -0xdac10000, -0x00098200, -0x90010114, -0x92e10000, -0x00098200, -0xdae10000, -0x00098200, -0x93010000, -0x00098200, -0xdb010000, -0x00098200, -0x93210000, -0x00098200, -0xdb210000, -0x00098200, -0x7c000026, -0x93410000, -0x00098200, -0xdb410000, -0x00098200, -0x93610000, -0x00098200, -0xdb610000, -0x00098200, -0x93810000, -0x00098200, -0xdb810000, -0x00098200, -0x93a10000, -0x00098200, -0xdba10000, -0x00098200, -0x93c10000, -0x00098200, -0xdbc10000, -0x00098200, -0x93e10000, -0x00098200, -0x00000000, -0xdbe10000, -0x00098200, -0x90010034, -0x7c721b78, -0x80030000, -0x00098200, -0x90610024, -0x81120000, -0x00098200, -0x90610020, -0x7c080050, -0x81120000, -0x00098200, -0x90320000, -0x00098200, -0x39200000, -0x9001002c, -0x91210030, -0x91010028, -0x7cc903a6, -0x4e800421, -0x7c6e1b79, -0x82320000, -0x00098200, -0x3a000000, -0x00098200, -0x3a310000, -0x00098200, -0x40820000, -0x0005080d, -0x48000000, -0x00050019, -0x00060015, -0x800efff4, -0x7dca7378, -0x7d2e4b78, -0x8109fffc, -0x00000000, -0x28000001, -0x00000000, -0x820afff0, -0x392cfff8, -0x81080000, -0x00098200, -0x7ef4492e, -0x00000000, -0x40810000, -0x00050801, -0x00000000, -0x81e80000, -0x00098200, -0x7c0903a6, -0x4e800420, -0x00000000, -0x0006000b, -0x41820000, -0x00050828, -0x390afff0, -0x7d6e4050, -0x48000000, -0x00050029, -0x00000000, -0x0006002a, -0x80f0fffc, -0x388afff0, -0x54f55d78, -0xc8140000, -0x7d0eaa14, -0x91d20000, -0x00098200, -0x7c082040, -0x7ca82050, -0x54f4dd78, -0xd8040000, -0x40a20000, -0x0005082b, -0x7c0ea5ae, -0x48000000, -0x0005002c, -0x0006002d, -0x38b10000, -0x00098200, -0x38000000, -0x00098200, -0x54ea5d78, -0x91650004, -0x7c8e5214, -0x90050000, -0x48000000, -0x00050001, -0x0006002e, -0x38910000, -0x00098200, -0x38000000, -0x00098200, -0x91440004, -0x38b10000, -0x00098200, -0x90040000, -0x39000000, -0x00098200, -0x91650004, -0x91050000, -0x48000000, -0x00050001, -0x0006002f, -0x00000000, -0x9001000c, -0xc8010008, -0xfc00f028, -0x00000000, -0x54ea5d78, -0x38b10000, -0x00098200, -0x7c8e5214, -0x00000000, -0x92c50000, -0x90050004, -0x00000000, -0xd8050000, -0x00000000, -0x48000000, -0x00050001, -0x00060030, -0x54ea5d78, -0x54eb9d78, -0x7c8e5214, -0x7cae5a14, -0x0006000b, -0x91d20000, -0x00098200, -0x7e439378, -0x92010020, -0x48000001, -0x00030001, -0x28030000, -0x41820000, -0x00050803, -0xc8030000, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000d, -0x210e0000, -0x00098200, -0x81d20000, -0x00098200, -0x920efff0, -0x7e087214, -0x814efffc, -0x39600010, -0x48000000, -0x00050026, -0x00060031, -0x38b10000, -0x00098200, -0x38000000, -0x00098200, -0x54ea5d78, -0x91650004, -0x7c8e5214, -0x90050000, -0x48000000, -0x00050001, -0x00060032, -0x38910000, -0x00098200, -0x38000000, -0x00098200, -0x91440004, -0x38b10000, -0x00098200, -0x90040000, -0x39000000, -0x00098200, -0x91650004, -0x91050000, -0x48000000, -0x00050001, -0x00060033, -0x00000000, -0x9001000c, -0xc8010008, -0xfc00f028, -0x00000000, -0x54ea5d78, -0x38b10000, -0x00098200, -0x7c8e5214, -0x00000000, -0x92c50000, -0x90050004, -0x00000000, -0xd8050000, -0x00000000, -0x48000000, -0x00050001, -0x00060034, -0x54ea5d78, -0x54eb9d78, -0x7c8e5214, -0x7cae5a14, -0x0006000b, -0x91d20000, -0x00098200, -0x7e439378, -0x92010020, -0x48000001, -0x00030002, -0x28030000, -0x7c0ea4ae, -0x41820000, -0x00050803, -0x80f00000, -0x3a100004, -0xd8030000, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000d, -0x210e0000, -0x00098200, -0x81d20000, -0x00098200, -0x920efff0, -0x7e087214, -0x814efffc, -0x39600018, -0xd80e0010, -0x48000000, -0x00050026, -0x00060035, -0x7e439378, -0x3a10fffc, -0x00000000, -0x7e84a378, -0x00000000, -0x7c8ea214, -0x00000000, -0x92010020, -0x00000000, -0x7d856378, -0x00000000, -0x7cae6214, -0x00000000, -0x91d20000, -0x00098200, -0x54e6063e, -0x48000001, -0x00030003, -0x0006000d, -0x28030001, -0x41810000, -0x00050836, -0x20630000, -0x0006000e, -0x80f00000, -0x3a100004, -0x54e993ba, -0x3d290000, -0x00098200, -0x7d291838, -0x7e104a14, -0x0006002c, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00060037, -0x80f0fffc, -0xc8140000, -0x54e8dd78, -0x7c0e45ae, -0x48000000, -0x0005002c, -0x00060038, -0x80140000, -0x20000000, -0x00098200, -0x7c631910, -0x7c6318f8, -0x48000000, -0x0005000e, -0x00060039, -0x80140000, -0x20000000, -0x00098200, -0x7c631910, -0x48000000, -0x0005000e, -0x0006003a, -0x3a10fffc, -0x91d20000, -0x00098200, -0x7e439378, -0x92010020, -0x48000001, -0x00030004, -0x48000000, -0x0005000d, -0x0006003b, -0x00000000, -0x7ce43b78, -0x3a10fffc, -0x91d20000, -0x00098200, -0x7e439378, -0x92010020, -0x48000001, -0x00030005, -0x48000000, -0x0005000d, -0x00000000, -0x0006003c, -0x7caf5a14, -0x7cce5214, -0x48000000, -0x00050001, -0x0006003d, -0x00000000, -0x7d655b78, -0x7d465378, -0x48000000, -0x00050001, -0x00000000, -0x0006003e, -0x7d856378, -0x7d866378, -0x48000000, -0x00050001, -0x0006003f, -0x7cae5214, -0x7ccf5a14, -0x48000000, -0x00050001, -0x00060040, -0x7cae5214, -0x7cce5a14, -0x00000000, -0x48000000, -0x00050001, -0x00000000, -0x00060041, -0x00060042, -0x00000000, -0x7d455378, -0x7d665b78, -0x00000000, -0x0006000b, -0x7c8ea214, -0x91d20000, -0x00098200, -0x7e439378, -0x92010020, -0x54e7063e, -0x48000001, -0x00030006, -0x28030000, -0x41820000, -0x0005082c, -0x00060036, -0x7d0e1850, -0x9203fff0, -0x7dc97378, -0x3a080000, -0x00098200, -0x7c6e1b78, -0x39600010, -0x48000000, -0x00050024, -0x00060043, -0x00000000, -0x7c751b78, -0x00000000, -0x7d846378, -0x91d20000, -0x00098200, -0x7e439378, -0x92010020, -0x48000001, -0x00030007, -0x00000000, -0x28030000, -0x40820000, -0x00050836, -0x7ea3ab78, -0x48000000, -0x00050044, -0x00000000, -0x48000000, -0x00050036, -0x00000000, -0x00060025, -0x7e439378, -0x91320000, -0x00098200, -0x388efff8, -0x92010020, -0x7cae5a14, -0x7d755b78, -0x48000001, -0x00030008, -0x814efffc, -0x39750008, -0x920efff8, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00060045, -0x7e439378, -0x91d20000, -0x00098200, -0x3894fff8, -0x92010020, -0x7cb45a14, -0x7d755b78, -0x48000001, -0x00030008, -0x810efff8, -0x39750008, -0x8154fffc, -0x48000000, -0x00050046, -0x00060047, -0x7e439378, -0x91d20000, -0x00098200, -0x7e84a378, -0x92010020, -0x7cf53b78, -0x48000001, -0x00030009, -0x00000000, -0x56a0063e, -0x00000000, -0x56b4dd78, -0x00000000, -0x2c000000, -0x00098200, -0x00000000, -0x56ac9b78, -0x00000000, -0x41a20000, -0x00070800, -0x00000000, -0x48000000, -0x00070000, -0x00060048, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x39000000, -0x00098200, -0x3a8efff8, -0x7c854040, -0x820efff8, -0x40840000, -0x00050849, -0x90b40000, -0x398b0008, -0x90740004, -0x41820000, -0x0005084a, -0x39000008, -0x396bfff8, -0x0006000b, -0x7c085840, -0x7c0e44ae, -0x7c1445ae, -0x39080008, -0x40a20000, -0x0005080b, -0x48000000, -0x0005004a, -0x0006004b, -0x280b0008, -0x806e0000, -0x41800000, -0x00050849, -0x7c161810, -0x7d231910, -0x7d280338, -0x39080000, -0x00098200, -0x55081800, -0x000900a1, -0x392a0000, -0x00098200, -0x7c2944ae, -0x48000000, -0x0005004c, -0x0006004d, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x40820000, -0x00050806, -0x0006000b, -0x80630000, -0x00098200, -0x0006000c, -0x00000000, -0x38a00000, -0x00098200, -0x28030000, -0x81710000, -0x00098200, -0x41820000, -0x0005084e, -0x80030000, -0x00098200, -0x38a00000, -0x00098200, -0x810b0000, -0x00098200, -0x81230000, -0x00098200, -0x7d080038, -0x55002800, -0x000900a1, -0x55081800, -0x000900a1, -0x7d080050, -0x7d294214, -0x0006000d, -0x80c90000, -0x00098200, -0x80090000, -0x00098200, -0x80890000, -0x00098200, -0x81090000, -0x00098200, -0x2c060000, -0x00098200, -0x40820000, -0x00050804, -0x7c005800, -0x41820000, -0x00050805, -0x0006000e, -0x81290000, -0x00098200, -0x28090000, -0x41820000, -0x0005084e, -0x48000000, -0x0005000d, -0x0006000f, -0x00000000, -0x2c040000, -0x00098200, -0x41820000, -0x0005084e, -0x7c852378, -0x7d034378, -0x48000000, -0x0005004e, -0x00060010, -0x2c050000, -0x00098200, -0x41820000, -0x0005080b, -0x7c162810, -0x7d252910, -0x7d280338, -0x39080000, -0x00098200, -0x55081000, -0x000900a1, -0x39310000, -0x00098200, -0x7c69402e, -0x48000000, -0x0005000c, -0x0006004f, -0x280b0010, -0x80ae0000, -0x80ce0008, -0x806e0004, -0x808e000c, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x40820000, -0x00050849, -0x81030000, -0x00098200, -0x2c060000, -0x00098200, -0x40820000, -0x00050849, -0x28080000, -0x88c30000, -0x00098200, -0x40820000, -0x00050849, -0x70c00000, -0x00090200, -0x90830000, -0x00098200, -0x41820000, -0x0005084e, -0x00000000, -0x80110000, -0x00098200, -0x54c607b8, -0x90710000, -0x00098200, -0x98c30000, -0x00098200, -0x90030000, -0x00098200, -0x48000000, -0x0005004e, -0x00060050, -0x280b0010, -0x80ce0000, -0x808e0004, -0x41800000, -0x00050849, -0x2c060000, -0x00098200, -0x40820000, -0x00050849, -0x38ae0008, -0x7e439378, -0x48000001, -0x0003000a, -0xc8230000, -0x48000000, -0x0005004c, -0x00060051, -0x280b0008, -0x806e0000, -0xc82e0000, -0x40820000, -0x00050849, -0x7c03b040, -0x41810000, -0x00050849, -0x48000000, -0x0005004c, -0x00060052, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x41820000, -0x0005084e, -0x80110000, -0x00098200, -0x7c05b040, -0x28800000, -0x91d20000, -0x00098200, -0x4c413342, -0x92010020, -0x41820000, -0x00050849, -0x00000000, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x00050853, -0x7e439378, -0x7dc47378, -0x00000000, -0x48000001, -0x0003000b, -0x00000000, -0x48000001, -0x0003000c, -0x00000000, -0x38a00000, -0x00098200, -0x48000000, -0x0005004e, -0x00060054, -0x280b0008, -0x806e0000, -0x808e0004, -0x41800000, -0x00050849, -0x7eee592e, -0x2c030000, -0x00098200, -0x820efff8, -0x40820000, -0x00050849, -0x91d20000, -0x00098200, -0x7e439378, -0x91d20000, -0x00098200, -0x38ae0008, -0x92010020, -0x48000001, -0x0003000d, -0x28030000, -0x38a00000, -0x00098200, -0x41820000, -0x0005084e, -0xc80e0008, -0x3a8efff8, -0xc82e0010, -0xd8140000, -0x39800000, -0x00098200, -0xd8340008, -0x48000000, -0x0005004a, -0x00060055, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x820efff8, -0x40820000, -0x00050849, -0x00000000, -0x81230000, -0x00098200, -0xc80a0000, -0x00098200, -0x28090000, -0x3a8efff8, -0x40820000, -0x00050849, -0x00000000, -0xc80a0000, -0x00098200, -0x3a8efff8, -0x00000000, -0x92ee0008, -0x39800000, -0x00098200, -0xd8140000, -0x48000000, -0x0005004a, -0x00060056, -0x280b0010, -0x80ae0000, -0x806e0004, -0x80ce0008, -0x00000000, -0x812e000c, -0x00000000, -0xc84e0008, -0x00000000, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x7c86b040, -0x820efff8, -0x00000000, -0x40820000, -0x00050849, -0x40860000, -0x00050849, -0x00000000, -0x3c003ff0, -0x93010014, -0x40820000, -0x00050849, -0x90010010, -0x40840000, -0x00050849, -0xc8210010, -0xfc00101e, -0xd8010010, -0x81210014, -0x00000000, -0x80030000, -0x00098200, -0x81030000, -0x00098200, -0x00000000, -0xfc42082a, -0x00000000, -0x39290001, -0x3a8efff8, -0x7c004840, -0x00000000, -0x92d40000, -0x55261800, -0x000900a1, -0x91340004, -0x00000000, -0x55261800, -0x000900a1, -0xd8540000, -0x00000000, -0x40810000, -0x00050802, -0x7d28302e, -0x7c0834ae, -0x0006000b, -0x2c090000, -0x00098200, -0x39800000, -0x00098200, -0x41820000, -0x0005084a, -0x39800000, -0x00098200, -0xd8140008, -0x48000000, -0x0005004a, -0x0006000c, -0x80030000, -0x00098200, -0x28000000, -0x39800000, -0x00098200, -0x41820000, -0x0005084a, -0x7d244b78, -0x48000001, -0x0003000e, -0x28030000, -0x39800000, -0x00098200, -0x41820000, -0x0005084a, -0x81230000, -0xc8030000, -0x48000000, -0x0005000b, -0x00060057, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x820efff8, -0x40820000, -0x00050849, -0x00000000, -0x81230000, -0x00098200, -0xc80a0000, -0x00098200, -0x28090000, -0x3a8efff8, -0x40820000, -0x00050849, -0x00000000, -0xc80a0000, -0x00098200, -0x3a8efff8, -0x00000000, -0x92ce0008, -0x00000000, -0x930e0008, -0x00000000, -0x930e000c, -0x39800000, -0x00098200, -0xd8140000, -0x48000000, -0x0005004a, -0x00060058, -0x280b0008, -0x88d10000, -0x00098200, -0x41800000, -0x00050849, -0x7dc97378, -0x39ce0008, -0x54c607fe, -0x000900ab, -0x396bfff8, -0x3a060000, -0x00098200, -0x48000000, -0x00050024, -0x00060059, -0x280b0010, -0x80ce0008, -0xc84e0008, -0xc82e0000, -0x41800000, -0x00050849, -0x89110000, -0x00098200, -0x7dc97378, -0x2c060000, -0x00098200, -0x40820000, -0x00050849, -0x39ce0010, -0x550807fe, -0x000900ab, -0xd8490000, -0x396bfff0, -0xd8290008, -0x3a080000, -0x00098200, -0x48000000, -0x00050024, -0x0006005a, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x40820000, -0x00050849, -0x88030000, -0x00098200, -0x81030000, -0x00098200, -0x00000000, -0x80830000, -0x00098200, -0x28000000, -0x00090200, -0x81230000, -0x00098200, -0x28880000, -0x80030000, -0x00098200, -0x7f844840, -0x820efff8, -0x4f013342, -0x7d245a14, -0x4f3e1102, -0x7c890040, -0x4f18cb82, -0x92010020, -0x4f182b82, -0x91d20000, -0x00098200, -0x41980000, -0x00050849, -0x0006000b, -0x39ce0008, -0x396bfff8, -0x3929fff8, -0x91230000, -0x00098200, -0x39000000, -0x91d20000, -0x00098200, -0x0006000c, -0x7c085800, -0x7c0e44ae, -0x41820000, -0x00050803, -0x7c0445ae, -0x39080008, -0x48000000, -0x0005000c, -0x0006000d, -0x38a00000, -0x7c751b78, -0x38c00000, -0x48000001, -0x00050021, -0x0006000e, -0x81350000, -0x00098200, -0x28030000, -0x00090200, -0x80d50000, -0x00098200, -0x38000000, -0x00098200, -0x81d20000, -0x00098200, -0x90110000, -0x00098200, -0x41810000, -0x00050808, -0x00000000, -0x7d893050, -0x80120000, -0x00098200, -0x280c0000, -0x7d0e6214, -0x41820000, -0x00050806, -0x7c080040, -0x39000000, -0x41810000, -0x00050809, -0x38ccfff8, -0x91350000, -0x00098200, -0x0006000f, -0x7c083040, -0x7c0944ae, -0x7c0e45ae, -0x39080008, -0x40820000, -0x0005080f, -0x00060010, -0x72000000, -0x00090200, -0x39000000, -0x00098200, -0x3a8efff8, -0x910efff8, -0x398c0010, -0x00060011, -0x92010020, -0x7d936378, -0x41820000, -0x00050817, -0x48000000, -0x00050018, -0x00060012, -0x72000000, -0x00090200, -0x38c6fff8, -0x39000000, -0x00098200, -0xc8060000, -0x90d50000, -0x00098200, -0x39800000, -0x00098200, -0x910efff8, -0x3a8efff8, -0xd80e0000, -0x48000000, -0x00050011, -0x00060013, -0x7e439378, -0x558400fe, -0x000900ab, -0x48000001, -0x00030000, -0x38600000, -0x48000000, -0x0005000e, -0x0006005b, -0x00000000, -0x806a0000, -0x00098200, -0x88030000, -0x00098200, -0x81030000, -0x00098200, -0x80830000, -0x00098200, -0x28000000, -0x00090200, -0x81230000, -0x00098200, -0x28880000, -0x80030000, -0x00098200, -0x7f844840, -0x820efff8, -0x4f013342, -0x7d245a14, -0x4f3e1102, -0x7c890040, -0x4f18cb82, -0x92010020, -0x4f182b82, -0x91d20000, -0x00098200, -0x41980000, -0x00050849, -0x0006000b, -0x91230000, -0x00098200, -0x39000000, -0x91d20000, -0x00098200, -0x0006000c, -0x7c085800, -0x7c0e44ae, -0x41820000, -0x00050803, -0x7c0445ae, -0x39080008, -0x48000000, -0x0005000c, -0x0006000d, -0x38a00000, -0x7c751b78, -0x38c00000, -0x48000001, -0x00050021, -0x0006000e, -0x81350000, -0x00098200, -0x28030000, -0x00090200, -0x80d50000, -0x00098200, -0x38000000, -0x00098200, -0x00000000, -0x81d20000, -0x00098200, -0x90110000, -0x00098200, -0x41810000, -0x00050808, -0x7d893050, -0x80120000, -0x00098200, -0x280c0000, -0x7d0e6214, -0x41820000, -0x00050806, -0x7c080040, -0x39000000, -0x41810000, -0x00050809, -0x38ccfff8, -0x91350000, -0x00098200, -0x0006000f, -0x7c083040, -0x7c0944ae, -0x7c0e45ae, -0x39080008, -0x40820000, -0x0005080f, -0x00060010, -0x72000000, -0x00090200, -0x7dd47378, -0x398c0008, -0x00060011, -0x92010020, -0x7d936378, -0x41820000, -0x00050817, -0x48000000, -0x00050018, -0x00060012, -0x7e439378, -0x7ea4ab78, -0x48000001, -0x0003000f, -0x00060013, -0x7e439378, -0x558400fe, -0x000900ab, -0x48000001, -0x00030000, -0x38600000, -0x48000000, -0x0005000e, -0x0006005c, -0x80120000, -0x00098200, -0x00000000, -0x7d0e5a14, -0x91d20000, -0x00098200, -0x70000000, -0x00090200, -0x91120000, -0x00098200, -0x38600000, -0x00098200, -0x41820000, -0x00050849, -0x93120000, -0x00098200, -0x98720000, -0x00098200, -0x48000000, -0x0005001a, -0x0006005d, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x00000000, -0x40820000, -0x00050802, -0x7c68fe70, -0x7d091a78, -0x7c684851, -0x41800000, -0x00050801, -0x0006005e, -0x820efff8, -0x3a8efff8, -0x92cefff8, -0x906efffc, -0x48000000, -0x0005005f, -0x0006000b, -0x3ca041e0, -0x38600000, -0x48000000, -0x0005004e, -0x0006000c, -0x00000000, -0x40800000, -0x00050849, -0x54a5007e, -0x0006004e, -0x820efff8, -0x90aefff8, -0x3a8efff8, -0x906efffc, -0x0006005f, -0x39800000, -0x00098200, -0x0006004a, -0x72000000, -0x00090200, -0x7d936378, -0x40a20000, -0x00050818, -0x80f0fffc, -0x54ea5d78, -0x0006000f, -0x7c0a6040, -0x54e0dd78, -0x41810000, -0x00050806, -0x80f00000, -0x3a100004, -0x7dc0a050, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00060010, -0x390cfff8, -0x398c0008, -0x7ef4412e, -0x48000000, -0x0005000f, -0x00000000, -0x00060060, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x41a20000, -0x0005084e, -0x54a9657e, -0x40800000, -0x00050849, -0x3529fc01, -0x2889001f, -0x2009001f, -0x41800000, -0x00050803, -0x54a85800, -0x000900a1, -0x5466057e, -0x000900ab, -0x65088000, -0x39290001, -0x7d083378, -0x54645800, -0x000900a1, -0x40840000, -0x00050804, -0x7d064830, -0x7d030430, -0x7cc62378, -0x7ca9fe70, -0x7cc84838, -0x3008ffff, -0x7d004110, -0x7c634214, -0x7c634a78, -0x7c691850, -0x48000000, -0x0005005e, -0x0006000d, -0x7d252a14, -0x7ca8fe70, -0x7c694b78, -0x7d284038, -0x21280000, -0x7c631910, -0x48000000, -0x0005005e, -0x0006000e, -0x6d088000, -0x7ca9fe70, -0x7d082378, -0x7d084b39, -0x4c423202, -0x3c608000, -0x41a20000, -0x0005085e, -0x0006000f, -0xc82e0000, -0x48000001, -0x00030010, -0x48000000, -0x0005004c, -0x00060061, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x41a20000, -0x0005084e, -0x54a9657e, -0x40800000, -0x00050849, -0x3529fc01, -0x2889001f, -0x2009001f, -0x41800000, -0x00050803, -0x00000000, -0x54a85800, -0x000900a1, -0x5466057e, -0x000900ab, -0x65088000, -0x39290001, -0x7d083378, -0x54645800, -0x000900a1, -0x40840000, -0x00050804, -0x7d064830, -0x7d030430, -0x7cc62378, -0x7ca9fe70, -0x7cc84878, -0x3008ffff, -0x7d004110, -0x7c634615, -0x7c634a78, -0x7c691850, -0x40830000, -0x0005085e, -0x7c000400, -0x40a10000, -0x0005085e, -0x3ca041e0, -0x38600000, -0x48000000, -0x0005004e, -0x0006000d, -0x7d252a14, -0x7ca8fe70, -0x7c694b78, -0x7d284078, -0x3128ffff, -0x7c694110, -0x48000000, -0x0005005e, -0x0006000e, -0x6d088000, -0x7ca9fe70, -0x7d084b39, -0x4c423202, -0x3c608000, -0x41a20000, -0x0005085e, -0x0006000f, -0xc82e0000, -0x48000001, -0x00030011, -0x48000000, -0x0005004c, -0x00000000, -0x00060060, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x00030010, -0x48000000, -0x0005004c, -0x00060061, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x00030011, -0x48000000, -0x0005004c, -0x00000000, -0x00060062, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x00030012, -0x48000000, -0x0005004c, -0x00060063, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x00030013, -0x48000000, -0x0005004c, -0x00060064, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x00030014, -0x48000000, -0x0005004c, -0x00060065, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x00030015, -0x48000000, -0x0005004c, -0x00060066, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x00000000, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x00030016, -0x48000000, -0x0005004c, -0x00060067, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x00030017, -0x48000000, -0x0005004c, -0x00060068, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x00030018, -0x48000000, -0x0005004c, -0x00060069, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x00030019, -0x48000000, -0x0005004c, -0x0006006a, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x0003001a, -0x00000000, -0x48000000, -0x0005004c, -0x0006006b, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x0003001b, -0x48000000, -0x0005004c, -0x0006006c, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x0003001c, -0x48000000, -0x0005004c, -0x0006006d, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x0003001d, -0x48000000, -0x0005004c, -0x0006006e, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x48000001, -0x0003001e, -0x48000000, -0x0005004c, -0x0006006f, -0x00000000, -0x280b0010, -0x80ae0000, -0xc82e0000, -0x80ce0008, -0xc84e0008, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x7c06b040, -0x40800000, -0x00050849, -0x48000001, -0x0003001f, -0x48000000, -0x0005004c, -0x00060070, -0x280b0010, -0x80ae0000, -0xc82e0000, -0x80ce0008, -0xc84e0008, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x7c06b040, -0x40800000, -0x00050849, -0x48000001, -0x00030020, -0x48000000, -0x0005004c, -0x00060071, -0x280b0010, -0x80ae0000, -0xc82e0000, -0x80ce0008, -0xc84e0008, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x7c06b040, -0x40800000, -0x00050849, -0x48000001, -0x00030021, -0x48000000, -0x0005004c, -0x00060072, -0x00060073, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0xc84a0000, -0x00098200, -0x00000000, -0xfc2100b2, -0x48000000, -0x0005004c, -0x00000000, -0x00060074, -0x280b0010, -0x80ae0000, -0xc82e0000, -0x80ce0008, -0x806e000c, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x7c06b040, -0x40820000, -0x00050849, -0x00000000, -0x00060074, -0x280b0010, -0x80ae0000, -0xc82e0000, -0x80ce0008, -0xc84e0008, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x7c06b040, -0x40800000, -0x00050849, -0xfc40101e, -0xd8410010, -0x80610014, -0x00000000, -0x48000001, -0x00030022, -0x48000000, -0x0005004c, -0x00060075, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x38710000, -0x00098200, -0x820efff8, -0x48000001, -0x00030023, -0x81110000, -0x00098200, -0x3a8efff8, -0x00000000, -0x6d088000, -0x9101000c, -0xc8410008, -0xfc42f828, -0x00000000, -0xd8340000, -0x39800000, -0x00098200, -0x00000000, -0x92d40008, -0x9114000c, -0x00000000, -0xd8540008, -0x00000000, -0x48000000, -0x0005004a, -0x00060076, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x386efff8, -0x820efff8, -0x48000001, -0x00030024, -0x3a8efff8, -0xd82e0000, -0x39800000, -0x00098200, -0x48000000, -0x0005004a, -0x00000000, -0x00060077, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x390e0008, -0x7d2e5a14, -0x40820000, -0x00050804, -0x0006000b, -0x80c80000, -0x7c884840, -0x80880004, -0x40840000, -0x0005085e, -0x7c06b040, -0x6c608000, -0x6c868000, -0x40820000, -0x00050803, -0x7cc60010, -0x7c000110, -0x7cc60038, -0x7c662214, -0x39080008, -0x48000000, -0x0005000b, -0x0006000d, -0x40800000, -0x00050849, -0x6c638000, -0x9061000c, -0xc8210008, -0xfc21f828, -0xc8480000, -0x48000000, -0x00050006, -0x0006000e, -0xc82e0000, -0x40800000, -0x00050849, -0x0006000f, -0x80c80000, -0x7c884840, -0xc8480000, -0x40840000, -0x0005084c, -0x7c06b040, -0x40800000, -0x00050807, -0x00060010, -0xfc011028, -0x39080008, -0xfc2008ae, -0x48000000, -0x0005000f, -0x00060011, -0x80880004, -0x40820000, -0x00050849, -0x6c848000, -0x9081000c, -0xc8410008, -0xfc42f828, -0x48000000, -0x00050010, -0x00000000, -0x00060077, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x39000008, -0x0006000b, -0x7c8e402e, -0x7c4e44ae, -0x7c885840, -0x7c04b040, -0x40840000, -0x0005084c, -0x40800000, -0x00050849, -0xfc011028, -0x39080008, -0xfc2008ae, -0x48000000, -0x0005000b, -0x00000000, -0x00060078, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x390e0008, -0x7d2e5a14, -0x40820000, -0x00050804, -0x0006000b, -0x80c80000, -0x7c884840, -0x80880004, -0x40840000, -0x0005085e, -0x7c06b040, -0x6c608000, -0x6c868000, -0x40820000, -0x00050803, -0x7cc60010, -0x7c000110, -0x7cc60078, -0x7c662214, -0x39080008, -0x48000000, -0x0005000b, -0x0006000d, -0x40800000, -0x00050849, -0x6c638000, -0x9061000c, -0xc8210008, -0xfc21f828, -0xc8480000, -0x48000000, -0x00050006, -0x0006000e, -0xc82e0000, -0x40800000, -0x00050849, -0x0006000f, -0x80c80000, -0x7c884840, -0xc8480000, -0x40840000, -0x0005084c, -0x7c06b040, -0x40800000, -0x00050807, -0x00060010, -0xfc011028, -0x39080008, -0xfc20106e, -0x48000000, -0x0005000f, -0x00060011, -0x80880004, -0x40820000, -0x00050849, -0x6c848000, -0x9081000c, -0xc8410008, -0xfc42f828, -0x48000000, -0x00050010, -0x00000000, -0x00060078, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x39000008, -0x0006000b, -0x7c8e402e, -0x7c4e44ae, -0x7c885840, -0x7c04b040, -0x40840000, -0x0005084c, -0x40800000, -0x00050849, -0xfc011028, -0x39080008, -0xfc20106e, -0x48000000, -0x0005000b, -0x00000000, -0x00060079, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x40820000, -0x00050849, -0x80630000, -0x00098200, -0x48000000, -0x0005005e, -0x0006007a, -0x280b0008, -0x80ae0000, -0x806e0004, -0x40820000, -0x00050849, -0x2c050000, -0x00098200, -0x40820000, -0x00050849, -0x80030000, -0x00098200, -0x00000000, -0x88630000, -0x00098200, -0x39800000, -0x00098200, -0x820efff8, -0x28000000, -0x3a8efff8, -0x41a20000, -0x0005084a, -0x48000000, -0x0005005e, -0x00000000, -0x89030000, -0x00098200, -0x30c0ffff, -0x7d860110, -0x9101000c, -0x398c0001, -0xc8010008, -0x3a8efff8, -0x820efff8, -0xfc00f028, -0x558c1800, -0x000900a1, -0xd8140000, -0x48000000, -0x0005004a, -0x00000000, -0x0006007b, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x00050853, -0x280b0008, -0x80ae0000, -0x00000000, -0x800e0004, -0x40820000, -0x00050849, -0x7c05b040, -0x40820000, -0x00050849, -0x388e0007, -0x00000000, -0xc82e0000, -0x40820000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0xfc20081e, -0xd8210010, -0x80010014, -0x38810017, -0x00000000, -0x38a00001, -0x280000ff, -0x41810000, -0x00050849, -0x0006007c, -0x7e439378, -0x91d20000, -0x00098200, -0x92010020, -0x48000001, -0x00030025, -0x81d20000, -0x00098200, -0x38a00000, -0x00098200, -0x48000000, -0x0005004e, -0x0006007d, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x00050853, -0x280b0010, -0x80ae0010, -0x00000000, -0xc80e0010, -0x00000000, -0x800e0000, -0x806e0004, -0x41800000, -0x00050849, -0x808e0008, -0x00000000, -0x810e000c, -0x00000000, -0xc82e0008, -0x00000000, -0x3920ffff, -0x41820000, -0x00050801, -0x00000000, -0x7c05b040, -0x812e0014, -0x40820000, -0x00050849, -0x0006000b, -0x7c04b040, -0x40820000, -0x00050849, -0x00000000, -0x7c05b040, -0x40800000, -0x00050849, -0xfc00001e, -0xd8010010, -0x81210014, -0x0006000b, -0x7c04b040, -0x40800000, -0x00050849, -0x00000000, -0x2c000000, -0x00098200, -0x40820000, -0x00050849, -0x00000000, -0xfc20081e, -0xd8210010, -0x81010014, -0x00000000, -0x80030000, -0x00098200, -0x7c004840, -0x38c90001, -0x41800000, -0x00050805, -0x0006000c, -0x2c080000, -0x7cc80214, -0x40810000, -0x00050807, -0x0006000d, -0x7ca84850, -0x38830000, -0x00098200, -0x7ca0fe70, -0x38a50001, -0x7c844214, -0x7ca50078, -0x48000000, -0x0005007c, -0x0006000f, -0x7c890050, -0x7c84fe70, -0x7cc62078, -0x7d203214, -0x48000000, -0x0005000c, -0x00060011, -0x30a8ffff, -0x7ca52910, -0x7cc4fe70, -0x7cc62878, -0x7cc82078, -0x39080001, -0x48000000, -0x0005000d, -0x0006007e, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x00050853, -0x280b0010, -0x800e0000, -0x806e0004, -0x80ce0008, -0x00000000, -0x80ae000c, -0x00000000, -0xc84e0008, -0x00000000, -0x41800000, -0x00050849, -0x2c000000, -0x00098200, -0x40820000, -0x00050849, -0x00000000, -0x7c06b040, -0x40820000, -0x00050849, -0x00000000, -0x7c06b040, -0x40800000, -0x00050849, -0xfc40101e, -0xd8410010, -0x80a10014, -0x00000000, -0x80030000, -0x00098200, -0x2c050000, -0x81110000, -0x00098200, -0x40810000, -0x00050802, -0x28000001, -0x3925ffff, -0x41800000, -0x00050802, -0x7c882840, -0x40820000, -0x00050849, -0x88030000, -0x00098200, -0x80910000, -0x00098200, -0x41840000, -0x00050849, -0x0006000b, -0x28090000, -0x7c0449ae, -0x3929ffff, -0x40820000, -0x0005080b, -0x48000000, -0x0005007c, -0x0006000c, -0x38710000, -0x00098200, -0x38a00000, -0x00098200, -0x48000000, -0x0005004e, -0x0006007f, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x00050853, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x81110000, -0x00098200, -0x00000000, -0x40820000, -0x00050849, -0x80a30000, -0x00098200, -0x38630000, -0x00098200, -0x80910000, -0x00098200, -0x39200000, -0x7c082840, -0x38c5ffff, -0x41800000, -0x00050849, -0x0006000b, -0x2c060000, -0x7d0348ae, -0x41a00000, -0x0005087c, -0x7d0431ae, -0x38c6ffff, -0x39290001, -0x48000000, -0x0005000b, -0x00060080, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x00050853, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x81110000, -0x00098200, -0x40820000, -0x00050849, -0x80a30000, -0x00098200, -0x38630000, -0x00098200, -0x80910000, -0x00098200, -0x7c082840, -0x39200000, -0x41800000, -0x00050849, -0x0006000b, -0x7c092840, -0x7d0348ae, -0x40a00000, -0x0005087c, -0x00000000, -0x3808ffbf, -0x69060020, -0x3000ffe6, -0x7cc63110, -0x70c60020, -0x7d083278, -0x7d0449ae, -0x39290001, -0x48000000, -0x0005000b, -0x00060081, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x00050853, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x81110000, -0x00098200, -0x40820000, -0x00050849, -0x80a30000, -0x00098200, -0x38630000, -0x00098200, -0x80910000, -0x00098200, -0x7c082840, -0x39200000, -0x41800000, -0x00050849, -0x0006000b, -0x7c092840, -0x7d0348ae, -0x40a00000, -0x0005087c, -0x3808ff9f, -0x69060020, -0x3000ffe6, -0x7cc63110, -0x70c60020, -0x7d083278, -0x7d0449ae, -0x39290001, -0x48000000, -0x0005000b, -0x00060082, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x2c050000, -0x00098200, -0x40820000, -0x00050849, -0x48000001, -0x00030026, -0x48000000, -0x0005005e, -0x00000000, -0x00060083, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x00000000, -0x00060083, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xd8210010, -0x80610014, -0x00000000, -0x390e0008, -0x7d2e5a14, -0x0006000b, -0x80c80000, -0x7c884840, -0x00000000, -0x80880004, -0x00000000, -0xc8280000, -0x00000000, -0x40a40000, -0x0005085e, -0x7c06b040, -0x00000000, -0x40820001, -0x00050885, -0x00000000, -0xfc21f02a, -0x40800000, -0x00050849, -0xd8210010, -0x80810014, -0x00000000, -0x7c632038, -0x39080008, -0x48000000, -0x0005000b, -0x00000000, -0x00060086, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x00000000, -0x00060086, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xd8210010, -0x80610014, -0x00000000, -0x390e0008, -0x7d2e5a14, -0x0006000b, -0x80c80000, -0x7c884840, -0x00000000, -0x80880004, -0x00000000, -0xc8280000, -0x00000000, -0x40a40000, -0x0005085e, -0x7c06b040, -0x00000000, -0x40820001, -0x00050885, -0x00000000, -0xfc21f02a, -0x40800000, -0x00050849, -0xd8210010, -0x80810014, -0x00000000, -0x7c632378, -0x39080008, -0x48000000, -0x0005000b, -0x00000000, -0x00060087, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x00000000, -0x00060087, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xd8210010, -0x80610014, -0x00000000, -0x390e0008, -0x7d2e5a14, -0x0006000b, -0x80c80000, -0x7c884840, -0x00000000, -0x80880004, -0x00000000, -0xc8280000, -0x00000000, -0x40a40000, -0x0005085e, -0x7c06b040, -0x00000000, -0x40820001, -0x00050885, -0x00000000, -0xfc21f02a, -0x40800000, -0x00050849, -0xd8210010, -0x80810014, -0x00000000, -0x7c632278, -0x39080008, -0x48000000, -0x0005000b, -0x00000000, -0x00060088, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x00000000, -0x00060088, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xd8210010, -0x80610014, -0x00000000, -0x5460403e, -0x5060c00e, -0x5060c42e, -0x7c030378, -0x48000000, -0x0005005e, -0x00000000, -0x00060089, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x00000000, -0x00060089, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xd8210010, -0x80610014, -0x00000000, -0x7c6318f8, -0x48000000, -0x0005005e, -0x00000000, -0x0006008a, -0x280b0010, -0x80ae0000, -0x80ce0008, -0x806e0004, -0x808e000c, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x7c06b040, -0x40820000, -0x00050849, -0x00000000, -0x0006008a, -0x280b0010, -0x80ae0000, -0xc82e0000, -0x80ce0008, -0xc84e0008, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x7c06b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xfc42f02a, -0xd8210010, -0x80610014, -0xd8410010, -0x80810014, -0x00000000, -0x548406fe, -0x7c632030, -0x48000000, -0x0005005e, -0x00000000, -0x0006008b, -0x280b0010, -0x80ae0000, -0x80ce0008, -0x806e0004, -0x808e000c, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x7c06b040, -0x40820000, -0x00050849, -0x00000000, -0x0006008b, -0x280b0010, -0x80ae0000, -0xc82e0000, -0x80ce0008, -0xc84e0008, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x7c06b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xfc42f02a, -0xd8210010, -0x80610014, -0xd8410010, -0x80810014, -0x00000000, -0x548406fe, -0x7c632430, -0x48000000, -0x0005005e, -0x00000000, -0x0006008c, -0x280b0010, -0x80ae0000, -0x80ce0008, -0x806e0004, -0x808e000c, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x7c06b040, -0x40820000, -0x00050849, -0x00000000, -0x0006008c, -0x280b0010, -0x80ae0000, -0xc82e0000, -0x80ce0008, -0xc84e0008, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x7c06b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xfc42f02a, -0xd8210010, -0x80610014, -0xd8410010, -0x80810014, -0x00000000, -0x548406fe, -0x7c632630, -0x48000000, -0x0005005e, -0x00000000, -0x0006008d, -0x280b0010, -0x80ae0000, -0x80ce0008, -0x806e0004, -0x808e000c, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x7c06b040, -0x40820000, -0x00050849, -0x00000000, -0x0006008d, -0x280b0010, -0x80ae0000, -0xc82e0000, -0x80ce0008, -0xc84e0008, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x7c06b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xfc42f02a, -0xd8210010, -0x80610014, -0xd8410010, -0x80810014, -0x00000000, -0x5c63203e, -0x48000000, -0x0005005e, -0x00000000, -0x0006008e, -0x280b0010, -0x80ae0000, -0x80ce0008, -0x806e0004, -0x808e000c, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x7c06b040, -0x40820000, -0x00050849, -0x00000000, -0x0006008e, -0x280b0010, -0x80ae0000, -0xc82e0000, -0x80ce0008, -0xc84e0008, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0x7c06b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xfc42f02a, -0xd8210010, -0x80610014, -0xd8410010, -0x80810014, -0x00000000, -0x7c8400d0, -0x5c63203e, -0x48000000, -0x0005005e, -0x00000000, -0x0006008f, -0x280b0008, -0x80ae0000, -0x806e0004, -0x41800000, -0x00050849, -0x7c05b040, -0x40820001, -0x00050884, -0x00000000, -0x0006008f, -0x280b0008, -0x80ae0000, -0xc82e0000, -0x41800000, -0x00050849, -0x7c05b040, -0x40800000, -0x00050849, -0xfc21f02a, -0xd8210010, -0x80610014, -0x00000000, -0x48000000, -0x0005005e, -0x00000000, -0x0006005e, -0x6c638000, -0x9061000c, -0xc8210008, -0xfc21f828, -0x00000000, -0x0006004c, -0x820efff8, -0x3a8efff8, -0xd82efff8, -0x48000000, -0x0005005f, -0x00060084, -0x00000000, -0xc82e0000, -0x41810000, -0x00050849, -0xfc21f02a, -0xd8210010, -0x80610014, -0x4e800020, -0x00000000, -0x00060085, -0x00000000, -0xc8280000, -0x41810000, -0x00050849, -0xfc21f02a, -0xd8210010, -0x80810014, -0x4e800020, -0x00000000, -0x00060049, -0x80ca0000, -0x00098200, -0x7d0e5a14, -0x820efff8, -0x38080000, -0x00098200, -0x81320000, -0x00098200, -0x92010020, -0x7c004840, -0x91d20000, -0x00098200, -0x91120000, -0x00098200, -0x7e439378, -0x41810000, -0x00050805, -0x7cc903a6, -0x4e800421, -0x81d20000, -0x00098200, -0x2c030000, -0x546c1800, -0x000900a1, -0x3a8efff8, -0x41810000, -0x0005084a, -0x0006000b, -0x80120000, -0x00098200, -0x814efffc, -0x7d6e0050, -0x40820000, -0x00050829, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00060029, -0x72000000, -0x00090200, -0x56080038, -0x40820000, -0x00050803, -0x80f0fffc, -0x54e8dd78, -0x39080008, -0x0006000d, -0x7d287050, -0x48000000, -0x00050024, -0x0006000f, -0x38800000, -0x00098200, -0x48000001, -0x00030000, -0x00000000, -0x81d20000, -0x00098200, -0x7c000000, -0x48000000, -0x0005000b, -0x00060053, -0x7ea802a6, -0x91d20000, -0x00098200, -0x7c0e5a14, -0x92010020, -0x90120000, -0x00098200, -0x7e439378, -0x48000001, -0x00030027, -0x81d20000, -0x00098200, -0x7ea803a6, -0x80120000, -0x00098200, -0x7d6e0050, -0x814efffc, -0x4e800020, -0x00060090, -0x00000000, -0x88d10000, -0x00098200, -0x70c00000, -0x00090200, -0x40820000, -0x00050805, -0x81310000, -0x00098200, -0x70c00000, -0x00090200, -0x40820000, -0x00050801, -0x3929ffff, -0x70c00000, -0x00090200, -0x41a20000, -0x00050801, -0x91310000, -0x00098200, -0x48000000, -0x00050001, -0x00000000, -0x00060091, -0x88d10000, -0x00098200, -0x70c00000, -0x00090200, -0x41820000, -0x00050801, -0x0006000f, -0x39080000, -0x00098200, -0x7c11402e, -0x7c0903a6, -0x4e800420, -0x00060092, -0x88d10000, -0x00098200, -0x81310000, -0x00098200, -0x70c00000, -0x00090200, -0x54c007c0, -0x000900ab, -0x40820000, -0x0005080f, -0x2c800000, -0x3529ffff, -0x41860000, -0x0005080f, -0x91310000, -0x00098200, -0x41820000, -0x00050801, -0x40840000, -0x0005080f, -0x0006000b, -0x7e439378, -0x9261001c, -0x7e048378, -0x91d20000, -0x00098200, -0x48000001, -0x00030028, -0x0006000d, -0x81d20000, -0x00098200, -0x0006000e, -0x00000000, -0x80f0fffc, -0x54e815ba, -0x54ea5d78, -0x39080000, -0x00098200, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00060093, -0x3a100004, -0x826affec, -0x48000000, -0x0005000e, -0x00060094, -0x00000000, -0x810efffc, -0x38710000, -0x00098200, -0x92010020, -0x81080000, -0x00098200, -0x7e048378, -0x92510000, -0x00098200, -0x89080000, -0x00098200, -0x91d20000, -0x00098200, -0x55081800, -0x000900a1, -0x7d0e4214, -0x91120000, -0x00098200, -0x48000001, -0x00030029, -0x48000000, -0x0005000d, -0x00000000, -0x00060095, -0x7e048378, -0x00000000, -0x48000000, -0x00050001, -0x00000000, -0x00060096, -0x00000000, -0x62040001, -0x0006000b, -0x00000000, -0x7c0e5a14, -0x92010020, -0x7e439378, -0x91d20000, -0x00098200, -0x7e8ea050, -0x90120000, -0x00098200, -0x48000001, -0x0003002a, -0x81d20000, -0x00098200, -0x80120000, -0x00098200, -0x93010020, -0x7d6e0050, -0x7e8ea214, -0x814efffc, -0x80f0fffc, -0x7c6903a6, -0x4e800420, -0x00060097, -0x00000000, -0x38210000, -0x00098200, -0xbc410000, -0x00098200, -0x3a3f0000, -0x00098200, -0x38800000, -0x00098200, -0x80610000, -0x00098200, -0x90910000, -0x00098200, -0xd8010000, -0x00098200, -0xd8210000, -0x00098200, -0xd8410000, -0x00098200, -0xd8610000, -0x00098200, -0x90610000, -0x7c000400, -0xd8810000, -0x00098200, -0xd8a10000, -0x00098200, -0xd8c10000, -0x00098200, -0xd8e10000, -0x00098200, -0x38810000, -0x00098200, -0xd9010000, -0x00098200, -0xd9210000, -0x00098200, -0xd9410000, -0x00098200, -0xd9610000, -0x00098200, -0x90810000, -0x00098200, -0xd9810000, -0x00098200, -0xd9a10000, -0x00098200, -0x00000000, -0xd9c10000, -0x00098200, -0xd9e10000, -0x00098200, -0x7ca802a6, -0x39000000, -0xda010000, -0x00098200, -0xda210000, -0x00098200, -0xda410000, -0x00098200, -0xda610000, -0x00098200, -0x91010000, -0x00098200, -0xda810000, -0x00098200, -0xdaa10000, -0x00098200, -0xdac10000, -0x00098200, -0xdae10000, -0x00098200, -0xa0c50002, -0xdb010000, -0x00098200, -0xdb210000, -0x00098200, -0xdb410000, -0x00098200, -0xdb610000, -0x00098200, -0x82510000, -0x00098200, -0xdb810000, -0x00098200, -0xdba10000, -0x00098200, -0xdbc10000, -0x00098200, -0xdbe10000, -0x00098200, -0x7ca50050, -0x81d10000, -0x00098200, -0x54a500be, -0x000900ab, -0x00000000, -0x92510000, -0x00098200, -0x38a5fffe, -0x91110000, -0x00098200, -0x90d10000, -0x00098200, -0x91d20000, -0x00098200, -0x38710000, -0x00098200, -0x90b10000, -0x00098200, -0x38810010, -0x48000001, -0x0003002b, -0x81120000, -0x00098200, -0x81210000, -0x81d20000, -0x00098200, -0x5501003a, -0x82010020, -0x91210000, -0x92410024, -0x48000000, -0x00050001, -0x00000000, -0x00060098, -0x00000000, -0x82410024, -0x3a3f0000, -0x00098200, -0x0006000b, -0x2c030000, -0x41800000, -0x00050803, -0x810efffc, -0x54731800, -0x000900a1, -0x39200000, -0x9261001c, -0x81080000, -0x00098200, -0x91310000, -0x00098200, -0x81e80000, -0x00098200, -0x3ac00000, -0x00098200, -0x3cc059c0, -0x90c10010, -0x3b000000, -0x60c60004, -0xc3c10010, -0x90c10010, -0x3c004338, -0x3ae00000, -0x00098200, -0x90010008, -0xc3e10010, -0x80f00000, -0x3a100004, -0x92f10000, -0x00098200, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7c0903a6, -0x28080000, -0x00090200, -0x40800000, -0x00050802, -0x54ea5d78, -0x54ec9b78, -0x54eb9d78, -0x4e800420, -0x0006000c, -0x3973fff8, -0x7e947214, -0x4e800420, -0x0006000d, -0x7c8300d0, -0x7e439378, -0x48000001, -0x0003002c, -0x00000000, -0x00060099, -0x48000000, -0x00030010, -0x0006009a, -0x48000000, -0x00030011, -0x0006009b, -0x00000000, -0x48000000, -0x0003002d, -0x00000000, -0x0006009c, -0x7c0327d7, -0x41830000, -0x00050801, -0x7c652279, -0x7c0021d6, -0x7c601850, -0x4c800020, -0x2c030000, -0x4d820020, -0x7c632214, -0x4e800020, -0x0006000b, -0x2c040000, -0x38600000, -0x4d820020, -0x7c000400, -0x4e800020, -0x0006009d, -0x28030001, -0x41820000, -0x00050801, -0x41810000, -0x00050802, -0xfc21102a, -0x4e800020, -0x0006000b, -0xfc211028, -0x4e800020, -0x0006000c, -0x28030003, -0x41820000, -0x00050801, -0x41810000, -0x00050802, -0xfc2100b2, -0x4e800020, -0x0006000b, -0xfc211024, -0x4e800020, -0x0006000c, -0x28030005, -0x41820000, -0x00050801, -0x41810000, -0x00050802, -0x9421ffe0, -0xd9c10010, -0xd9e10018, -0x7c0802a6, -0xfdc00890, -0xfc211024, -0x90010024, -0xfde01090, -0x48000001, -0x00030010, -0x80010024, -0xfc2103f2, -0x7c0803a6, -0xfc2e0828, -0xc9c10010, -0xc9e10018, -0x38210020, -0x4e800020, -0x0006000b, -0x48000000, -0x0003001f, -0x0006000c, -0x28030007, -0x41820000, -0x00050801, -0x41810000, -0x00050802, -0xfc200850, -0x4e800020, -0x0006000b, -0xfc200a10, -0x4e800020, -0x0006000c, -0x00000000, -0x28030009, -0x41820000, -0x00050809, -0x41810000, -0x00050802, -0x48000000, -0x00030020, -0x0006000c, -0x2803000b, -0x41810000, -0x00050809, -0xfc011028, -0x41820000, -0x00050801, -0xfc2008ae, -0x4e800020, -0x0006000b, -0xfc20106e, -0x4e800020, -0x00060013, -0x7c810808, -0x00000000, -0x7c810808, -0x00000000, -0x0006009e, -0x54630034, -0x7c832050, -0x3884001f, -0x5484d97f, -0x4d820020, -0x7c8903a6, -0x7c651b78, -0x0006000b, -0x7c00186c, -0x38630020, -0x42000000, -0x0005080b, -0x7c0004ac, -0x7c8903a6, -0x0006000b, -0x7c002fac, -0x38a50020, -0x42000000, -0x0005080b, -0x4c00012c, -0x4e800020, -0x0006009f, -0x00000000, -0x9421fef0, -0x91c10000, -0x00098200, -0xd9c10000, -0x00098200, -0x91e10000, -0x00098200, -0xd9e10000, -0x00098200, -0x92010000, -0x00098200, -0xda010000, -0x00098200, -0x7c0802a6, -0x92210000, -0x00098200, -0xda210000, -0x00098200, -0x92410000, -0x00098200, -0xda410000, -0x00098200, -0x92610000, -0x00098200, -0xda610000, -0x00098200, -0x92810000, -0x00098200, -0xda810000, -0x00098200, -0x92a10000, -0x00098200, -0xdaa10000, -0x00098200, -0x92c10000, -0x00098200, -0xdac10000, -0x00098200, -0x90010114, -0x92e10000, -0x00098200, -0xdae10000, -0x00098200, -0x93010000, -0x00098200, -0xdb010000, -0x00098200, -0x00000000, -0x93210000, -0x00098200, -0xdb210000, -0x00098200, -0x7c000026, -0x93410000, -0x00098200, -0xdb410000, -0x00098200, -0x93610000, -0x00098200, -0xdb610000, -0x00098200, -0x93810000, -0x00098200, -0xdb810000, -0x00098200, -0x93a10000, -0x00098200, -0xdba10000, -0x00098200, -0x93c10000, -0x00098200, -0xdbc10000, -0x00098200, -0x93e10000, -0x00098200, -0xdbe10000, -0x00098200, -0x90010034, -0x820c0000, -0x00098200, -0x3a2c0000, -0x00098200, -0x91700000, -0x00098200, -0x90700000, -0x00098200, -0xd8300000, -0x00098200, -0x90900000, -0x00098200, -0xd8500000, -0x00098200, -0x90b00000, -0x00098200, -0x00000000, -0xd8700000, -0x00098200, -0x90d00000, -0x00098200, -0xd8900000, -0x00098200, -0x90f00000, -0x00098200, -0xd8b00000, -0x00098200, -0x91100000, -0x00098200, -0xd8d00000, -0x00098200, -0x91300000, -0x00098200, -0xd8f00000, -0x00098200, -0x91500000, -0x00098200, -0xd9100000, -0x00098200, -0x38010000, -0x00098200, -0x90100000, -0x00098200, -0x7e038378, -0x92010020, -0x7c240b78, -0x48000001, -0x0003002e, -0x81c30000, -0x00098200, -0x3ac00000, -0x00098200, -0x81630000, -0x00098200, -0x3cc059c0, -0x3b000000, -0x7c721b78, -0x90c10010, -0x814efffc, -0x60c60004, -0x3ae00000, -0x00098200, -0x38000000, -0x00098200, -0xc3c10010, -0x90c10010, -0x7d6e5850, -0x90110000, -0x00098200, -0xc3e10010, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00000000, -0x00060028, -0x00000000, -0x82110000, -0x00098200, -0x91d20000, -0x00098200, -0x91520000, -0x00098200, -0x92500000, -0x00098200, -0x7e038378, -0x7e84a378, -0x48000001, -0x0003002f, -0x80700000, -0x00098200, -0xc8300000, -0x00098200, -0x80900000, -0x00098200, -0x48000000, -0x0005001a, -0x00000000, -0x000600a0, -0x00000000, -0x81030000, -0x00098200, -0x7c0802a6, -0x88830000, -0x00098200, -0x88a30000, -0x00098200, -0x7d0800d0, -0x90010004, -0x2c850000, -0x7c290b78, -0x3484ffff, -0x7c21416e, -0x4cc63042, -0x91c9fffc, -0x9069fff8, -0x7d2e4b78, -0x39030000, -0x00098200, -0x54841000, -0x000900a1, -0x41a00000, -0x00050802, -0x39210008, -0x0006000b, -0x7c08202e, -0x7c09212e, -0x3484fffc, -0x40800000, -0x0005080b, -0x0006000c, -0x40a60000, -0x00050803, -0xc8230000, -0x00098200, -0xc8430000, -0x00098200, -0xc8630000, -0x00098200, -0xc8830000, -0x00098200, -0xc8a30000, -0x00098200, -0xc8c30000, -0x00098200, -0xc8e30000, -0x00098200, -0xc9030000, -0x00098200, -0x0006000d, -0x80030000, -0x00098200, -0x80830000, -0x00098200, -0x80a30000, -0x00098200, -0x00000000, -0x80c30000, -0x00098200, -0x80e30000, -0x00098200, -0x7c0903a6, -0x81030000, -0x00098200, -0x81230000, -0x00098200, -0x81430000, -0x00098200, -0x80630000, -0x00098200, -0x4e800421, -0x810efff8, -0x812efffc, -0x800e0004, -0x90680000, -0x00098200, -0xd8280000, -0x00098200, -0x90880000, -0x00098200, -0x7c0803a6, -0x90a80000, -0x00098200, -0x7dc17378, -0x90c80000, -0x00098200, -0x7d2e4b78, -0x4e800020, -0x00000000, -0x00080000, -0x00000000, -0x7c14706e, -0x3a100004, -0x80940004, -0x7d0c706e, -0x8130fffc, -0x7c00b040, -0x80ac0004, -0x552993ba, -0x7c88b040, -0x3d290000, -0x00098200, -0x40820000, -0x00050807, -0x40860000, -0x00050808, -0x7c042800, -0x00000000, -0x40800000, -0x00050802, -0x00000000, -0x41800000, -0x00050802, -0x00000000, -0x41810000, -0x00050802, -0x00000000, -0x40810000, -0x00050802, -0x00000000, -0x0006000b, -0x7e104a14, -0x0006000c, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00060011, -0x41810000, -0x00050835, -0xc8140000, -0x41850000, -0x00050835, -0x41840000, -0x00050804, -0x6ca58000, -0x90a1000c, -0xc8210008, -0xfc21f828, -0x48000000, -0x00050005, -0x00060012, -0x41850000, -0x00050835, -0x6c848000, -0x9081000c, -0xc8010008, -0xfc00f828, -0x0006000e, -0xc82c0000, -0x0006000f, -0xfc000800, -0x00000000, -0x40800000, -0x0005080c, -0x00000000, -0x41800000, -0x0005080c, -0x00000000, -0x4c001382, -0x40800000, -0x0005080c, -0x00000000, -0x4c001382, -0x41800000, -0x0005080c, -0x00000000, -0x48000000, -0x0005000b, -0x00000000, -0x7c0ea02e, -0x3a100004, -0x7c0ea4ae, -0x7d0e602e, -0x7c00b040, -0x8130fffc, -0x7c2e64ae, -0x7c88b040, -0x552993ba, -0x40800000, -0x00050835, -0x3d290000, -0x00098200, -0x40840000, -0x00050835, -0xfc000800, -0x00000000, -0x40800000, -0x00050801, -0x00000000, -0x41800000, -0x00050801, -0x00000000, -0x4c001382, -0x40800000, -0x00050801, -0x00000000, -0x4c001382, -0x41800000, -0x00050801, -0x00000000, -0x7e104a14, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7c14706e, -0x3a100004, -0x80940004, -0x7d0c706e, -0x7c00b040, -0x8130fffc, -0x7c88b040, -0x552993ba, -0x80ac0004, -0x4fa12b82, -0x3d290000, -0x00098200, -0x00000000, -0x409d0000, -0x000508a1, -0x00000000, -0x409d0000, -0x000508a2, -0x00000000, -0x7c14706e, -0x81300000, -0xc8140000, -0x3a100004, -0x7d0c706e, -0x7c00b040, -0x552993ba, -0xc82c0000, -0x7c88b040, -0x3d290000, -0x00098200, -0x40800000, -0x00050805, -0x40840000, -0x00050805, -0xfc000800, -0x00000000, -0x40820000, -0x00050801, -0x7e104a14, -0x00000000, -0x41820000, -0x00050801, -0x7e104a14, -0x00000000, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x0006000f, -0x00000000, -0x80940004, -0x80ac0004, -0x00000000, -0x2f800000, -0x00098200, -0x2e880000, -0x00098200, -0x00000000, -0x7c0600f8, -0x7c004040, -0x28860000, -0x00090200, -0x00000000, -0x4fdeb382, -0x00000000, -0x2b060000, -0x00090200, -0x00000000, -0x419e0000, -0x0005083b, -0x00000000, -0x7e842840, -0x4c222902, -0x4c161342, -0x4c42b202, -0x7e158378, -0x4c420b82, -0x4c000b82, -0x00000000, -0x40820000, -0x00050806, -0x7e104a14, -0x00060010, -0x00000000, -0x41820000, -0x00050806, -0x7e104a14, -0x00060010, -0x00000000, -0x40800000, -0x00050802, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000c, -0x00000000, -0x41800000, -0x0005080b, -0x00000000, -0x41980000, -0x0005080b, -0x81240000, -0x00098200, -0x38c00000, -0x00098200, -0x28090000, -0x41820000, -0x0005080b, -0x89290000, -0x00098200, -0x71290000, -0x00090200, -0x40820000, -0x0005080b, -0x7eb0ab78, -0x48000000, -0x0005003a, -0x00000000, -0x7c14706e, -0x558c007e, -0x000900ab, -0x80d40004, -0x81300000, -0x218cfffc, -0x3a100004, -0x00000000, -0x2c000000, -0x00098200, -0x00000000, -0x7d0f602e, -0x20000000, -0x00098200, -0x00000000, -0x41820000, -0x0005083b, -0x00000000, -0x7d064050, -0x7c004378, -0x552993ba, -0x20000000, -0x3d290000, -0x00098200, -0x7d084110, -0x00000000, -0x7d294078, -0x00000000, -0x7d294038, -0x00000000, -0x7e104a14, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7c14706e, -0x3a100004, -0x80940004, -0x7d0c786e, -0x7c00b040, -0x8130fffc, -0x7c88b040, -0x552993ba, -0x80ac0004, -0x3d290000, -0x00098200, -0x00000000, -0x000600a1, -0x00000000, -0x000600a2, -0x00000000, -0x40820000, -0x00050807, -0x40860000, -0x00050808, -0x7c042800, -0x0006000e, -0x00000000, -0x000600a1, -0x00000000, -0x000600a2, -0x00000000, -0x7c0ea02e, -0x3a100004, -0x7c0ea4ae, -0x8130fffc, -0x7c2f64ae, -0x552993ba, -0x7c00b040, -0x3d290000, -0x00098200, -0x40800000, -0x00050803, -0xfc000800, -0x00000000, -0x40820000, -0x00050801, -0x7e104a14, -0x0006000b, -0x00000000, -0x0006000d, -0x00000000, -0x41820000, -0x00050802, -0x0006000b, -0x00000000, -0x0006000d, -0x00000000, -0x7e104a14, -0x0006000c, -0x00000000, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x0006000d, -0x2c000000, -0x00098200, -0x41820000, -0x0005083b, -0x48000000, -0x0005000b, -0x00000000, -0x00060011, -0x40800000, -0x0005080d, -0xc8140000, -0x41840000, -0x00050801, -0x6ca58000, -0x90a1000c, -0xc8210008, -0xfc21f828, -0x48000000, -0x00050002, -0x00060012, -0x6c848000, -0x9081000c, -0xc8010008, -0xfc00f828, -0x0006000b, -0xc82c0000, -0x0006000c, -0xfc000800, -0x48000000, -0x0005000e, -0x00000000, -0x7c0ea02e, -0x558800fe, -0x000900ab, -0x81300000, -0x7d0840f8, -0x3a100004, -0x00000000, -0x2c000000, -0x00098200, -0x00000000, -0x7c080050, -0x00000000, -0x41820000, -0x0005083b, -0x00000000, -0x552993ba, -0x3000ffff, -0x3d290000, -0x00098200, -0x7d084110, -0x00000000, -0x7d294038, -0x00000000, -0x7d294078, -0x00000000, -0x7e104a14, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7c0e602e, -0x80f00000, -0x3a100004, -0x00000000, -0x20000000, -0x00098200, -0x54e993ba, -0x7d084110, -0x3d290000, -0x00098200, -0x00000000, -0x7d294078, -0x00000000, -0x7d294038, -0x00000000, -0x7e104a14, -0x00000000, -0x39000000, -0x00098200, -0x7c0e64ae, -0x7c004040, -0x00000000, -0x40800000, -0x00050801, -0x00000000, -0x41800000, -0x00050801, -0x00000000, -0x3e100000, -0x00098200, -0x54e993ba, -0x7c0ea5ae, -0x7e104a14, -0x0006000b, -0x00000000, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x80f00000, -0x3a100004, -0x7c0e64ae, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x80f00000, -0x3a100004, -0x7c0e602e, -0x21000000, -0x00098200, -0x7c004114, -0x7c0ea12e, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7d0c706e, -0x800c0004, -0x7c08b040, -0x00000000, -0x40820000, -0x00050805, -0x7c0004d1, -0x41830000, -0x00050804, -0x0006000b, -0x80f00000, -0x3a100004, -0x7ed4716e, -0x90140004, -0x0006000d, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000e, -0x7c000400, -0x40a10000, -0x0005080b, -0x3d0041e0, -0x38000000, -0x48000000, -0x00050007, -0x00000000, -0x0006000f, -0x40800000, -0x0005083e, -0x6d088000, -0x00060011, -0x80f00000, -0x3a100004, -0x7d14716e, -0x90140004, -0x00000000, -0x48000000, -0x0005000d, -0x00000000, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7c0c706e, -0x806c0004, -0x2c000000, -0x00098200, -0x40820000, -0x00050802, -0x80630000, -0x00098200, -0x0006000b, -0x00000000, -0x80f00000, -0x3a100004, -0x7ed4716e, -0x90740004, -0x00000000, -0x9061000c, -0xc8010008, -0xfc00f028, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x00000000, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000c, -0x2c000000, -0x00098200, -0x40820000, -0x00050843, -0x00000000, -0x81230000, -0x00098200, -0x28090000, -0x40820000, -0x00050809, -0x0006000d, -0x00000000, -0x00060044, -0x48000001, -0x00030026, -0x48000000, -0x0005000b, -0x00000000, -0x00060013, -0x88090000, -0x00098200, -0x70000000, -0x00090200, -0x40820000, -0x0005080d, -0x48000000, -0x00050043, -0x00000000, -0x7d0a706e, -0x7d2b786e, -0x806a0004, -0x7c08b040, -0x808b0004, -0x00000000, -0x7d0a706e, -0x7d2b786e, -0x808a0004, -0x7c08b040, -0x806b0004, -0x00000000, -0x7d0a706e, -0x7d2b706e, -0x806a0004, -0x7c08b040, -0x808b0004, -0x00000000, -0x7c89b040, -0x40820000, -0x00050805, -0x40860000, -0x00050805, -0x7c632615, -0x41830000, -0x00050804, -0x0006000b, -0x80f00000, -0x3a100004, -0x7ed4716e, -0x90740004, -0x0006000c, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000e, -0x7c000400, -0x40a10000, -0x0005080b, -0x00000000, -0x48000000, -0x00050041, -0x00000000, -0x48000000, -0x0005003d, -0x00000000, -0x48000000, -0x00050042, -0x00000000, -0x0006000f, -0x00000000, -0xc9ea0000, -0x4c002202, -0xc9cb0000, -0x00000000, -0xc9ca0000, -0x4c002202, -0xc9eb0000, -0x00000000, -0x40800000, -0x00050841, -0x00000000, -0x40800000, -0x0005083d, -0x00000000, -0x40800000, -0x00050842, -0x00000000, -0xfc0e782a, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x48000000, -0x0005000c, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dce54ae, -0x7def5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083f, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083f, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dee54ae, -0x7dcf5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083c, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083c, -0x00000000, -0x7d0e502e, -0x7d2e582e, -0x7dce54ae, -0x7dee5cae, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x00050840, -0x00000000, -0xfc0e782a, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7d0a706e, -0x7d2b786e, -0x806a0004, -0x7c08b040, -0x808b0004, -0x00000000, -0x7d0a706e, -0x7d2b786e, -0x808a0004, -0x7c08b040, -0x806b0004, -0x00000000, -0x7d0a706e, -0x7d2b706e, -0x806a0004, -0x7c08b040, -0x808b0004, -0x00000000, -0x7c89b040, -0x40820000, -0x00050805, -0x40860000, -0x00050805, -0x7c641c51, -0x41830000, -0x00050804, -0x0006000b, -0x80f00000, -0x3a100004, -0x7ed4716e, -0x90740004, -0x0006000c, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000e, -0x7c000400, -0x40a10000, -0x0005080b, -0x00000000, -0x48000000, -0x00050041, -0x00000000, -0x48000000, -0x0005003d, -0x00000000, -0x48000000, -0x00050042, -0x00000000, -0x0006000f, -0x00000000, -0xc9ea0000, -0x4c002202, -0xc9cb0000, -0x00000000, -0xc9ca0000, -0x4c002202, -0xc9eb0000, -0x00000000, -0x40800000, -0x00050841, -0x00000000, -0x40800000, -0x0005083d, -0x00000000, -0x40800000, -0x00050842, -0x00000000, -0xfc0e7828, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x48000000, -0x0005000c, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dce54ae, -0x7def5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083f, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083f, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dee54ae, -0x7dcf5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083c, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083c, -0x00000000, -0x7d0e502e, -0x7d2e582e, -0x7dce54ae, -0x7dee5cae, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x00050840, -0x00000000, -0xfc0e7828, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7d0a706e, -0x7d2b786e, -0x806a0004, -0x7c08b040, -0x808b0004, -0x00000000, -0x7d0a706e, -0x7d2b786e, -0x808a0004, -0x7c08b040, -0x806b0004, -0x00000000, -0x7d0a706e, -0x7d2b706e, -0x806a0004, -0x7c08b040, -0x808b0004, -0x00000000, -0x7c89b040, -0x40820000, -0x00050805, -0x40860000, -0x00050805, -0x7c6325d7, -0x41830000, -0x00050804, -0x0006000b, -0x80f00000, -0x3a100004, -0x7ed4716e, -0x90740004, -0x0006000c, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000e, -0x7c000400, -0x40a10000, -0x0005080b, -0x00000000, -0x48000000, -0x00050041, -0x00000000, -0x48000000, -0x0005003d, -0x00000000, -0x48000000, -0x00050042, -0x00000000, -0x0006000f, -0x00000000, -0xc9ea0000, -0x4c002202, -0xc9cb0000, -0x00000000, -0xc9ca0000, -0x4c002202, -0xc9eb0000, -0x00000000, -0x40800000, -0x00050841, -0x00000000, -0x40800000, -0x0005083d, -0x00000000, -0x40800000, -0x00050842, -0x00000000, -0xfc0e03f2, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x48000000, -0x0005000c, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dce54ae, -0x7def5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083f, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083f, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dee54ae, -0x7dcf5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083c, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083c, -0x00000000, -0x7d0e502e, -0x7d2e582e, -0x7dce54ae, -0x7dee5cae, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x00050840, -0x00000000, -0xfc0e03f2, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dce54ae, -0x7def5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083f, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083f, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dee54ae, -0x7dcf5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083c, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083c, -0x00000000, -0x7d0e502e, -0x7d2e582e, -0x7dce54ae, -0x7dee5cae, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x00050840, -0x00000000, -0xfc0e7824, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7d0a706e, -0x7d2b786e, -0x806a0004, -0x7c08b040, -0x808b0004, -0x00000000, -0x7d0a706e, -0x7d2b786e, -0x808a0004, -0x7c08b040, -0x806b0004, -0x00000000, -0x7d0a706e, -0x7d2b706e, -0x806a0004, -0x7c08b040, -0x808b0004, -0x00000000, -0x7c89b040, -0x40820000, -0x00050805, -0x40860000, -0x00050805, -0x48000001, -0x0005009c, -0x41830000, -0x00050804, -0x0006000b, -0x80f00000, -0x3a100004, -0x7ed4716e, -0x90740004, -0x0006000c, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000e, -0x7c000400, -0x40a10000, -0x0005080b, -0x00000000, -0x48000000, -0x00050041, -0x00000000, -0x48000000, -0x0005003d, -0x00000000, -0x48000000, -0x00050042, -0x00000000, -0x0006000f, -0x00000000, -0xc9ea0000, -0x4c002202, -0xc9cb0000, -0x00000000, -0xc9ca0000, -0x4c002202, -0xc9eb0000, -0x00000000, -0x40800000, -0x00050841, -0x00000000, -0x40800000, -0x0005083d, -0x00000000, -0x40800000, -0x00050842, -0x00000000, -0x000600a3, -0xfc2e7824, -0x48000001, -0x00030010, -0xfc0103f2, -0xfc0e0028, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x48000000, -0x0005000c, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dce54ae, -0x7def5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083f, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083f, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dee54ae, -0x7dcf5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083c, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083c, -0x00000000, -0x7d0e502e, -0x7d2e582e, -0x7dce54ae, -0x7dee5cae, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x00050840, -0x00000000, -0x000600a3, -0xfc2e7824, -0x48000001, -0x00030010, -0xfc0103f2, -0xfc0e0028, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7d0a706e, -0x7d2b786e, -0x806a0004, -0x7c08b040, -0x808b0004, -0x00000000, -0x7d0a706e, -0x7d2b786e, -0x808a0004, -0x7c08b040, -0x806b0004, -0x00000000, -0x7d0a706e, -0x7d2b706e, -0x806a0004, -0x7c08b040, -0x808b0004, -0x00000000, -0x7c89b040, -0x40820000, -0x00050805, -0x40860000, -0x00050805, -0x48000001, -0x0005009c, -0x41830000, -0x00050804, -0x0006000b, -0x80f00000, -0x3a100004, -0x7ed4716e, -0x90740004, -0x0006000c, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000e, -0x7c000400, -0x40a10000, -0x0005080b, -0x00000000, -0x48000000, -0x00050041, -0x00000000, -0x48000000, -0x0005003d, -0x00000000, -0x48000000, -0x00050042, -0x00000000, -0x0006000f, -0x00000000, -0xc9ea0000, -0x4c002202, -0xc9cb0000, -0x00000000, -0xc9ca0000, -0x4c002202, -0xc9eb0000, -0x00000000, -0x40800000, -0x00050841, -0x00000000, -0x40800000, -0x0005083d, -0x00000000, -0x40800000, -0x00050842, -0x00000000, -0x48000000, -0x000500a3, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dce54ae, -0x7def5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083f, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083f, -0x00000000, -0x7d0e502e, -0x00000000, -0x7d2f582e, -0x00000000, -0x7dee54ae, -0x7dcf5cae, -0x00000000, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x0005083c, -0x00000000, -0x7c08b040, -0x40800000, -0x0005083c, -0x00000000, -0x7d0e502e, -0x7d2e582e, -0x7dce54ae, -0x7dee5cae, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x00050840, -0x00000000, -0x48000000, -0x000500a3, -0x00000000, -0x7d0e502e, -0x7c2e54ae, -0x7d2e582e, -0x7c4e5cae, -0x7c08b040, -0x7c89b040, -0x4c002202, -0x40800000, -0x00050840, -0x48000001, -0x0003001f, -0x80f00000, -0x3a100004, -0x7c2ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7caa5850, -0x91d20000, -0x00098200, -0x7c8e5a14, -0x7d555378, -0x0006002b, -0x92010020, -0x7e439378, -0x54a500fe, -0x000900ab, -0x48000001, -0x00030030, -0x28030000, -0x81d20000, -0x00098200, -0x40820000, -0x00050836, -0x80f00000, -0x3a100004, -0x7c0eacae, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x5588007e, -0x000900ab, -0x2108fffc, -0x80f00000, -0x3a100004, -0x7c0f402e, -0x39200000, -0x00098200, -0x7d34716e, -0x90140004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x5588007e, -0x000900ab, -0x2108fffc, -0x80f00000, -0x3a100004, -0x7c0f402e, -0x39200000, -0x00098200, -0x7d34716e, -0x90140004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x558c6800, -0x000900a1, -0x7d8c8670, -0x80f00000, -0x3a100004, -0x7ed4716e, -0x91940004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x558c6800, -0x000900a1, -0x7d88fe70, -0x7d096278, -0x7d284850, -0x7d260034, -0x2106040d, -0x7d293030, -0x20cc0000, -0x5508a000, -0x000900a1, -0x512ca87e, -0x7c000110, -0x7d8c4214, -0x7d8c0038, -0x80f00000, -0x3a100004, -0x7d94716e, -0x93140004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x80f00000, -0x3a100004, -0x7c0f64ae, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x558800fe, -0x000900ab, -0x7d0040f8, -0x80f00000, -0x3a100004, -0x7c0ea12e, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x7eeea12e, -0x3a940008, -0x0006000b, -0x7eeea12e, -0x7c146000, -0x3a940008, -0x41800000, -0x0005080b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x814efffc, -0x558c007e, -0x000900ab, -0x398c0000, -0x00098200, -0x7d4a602e, -0x80f00000, -0x3a100004, -0x810a0000, -0x00098200, -0xc8080000, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x814efffc, -0x5694007e, -0x000900ab, -0x3a940000, -0x00098200, -0x7c0c74ee, -0x7d4aa02e, -0x88ca0000, -0x00098200, -0x808a0000, -0x00098200, -0x70c60000, -0x00090200, -0x880a0000, -0x00098200, -0x812c0000, -0xd8040000, -0x28800000, -0x810c0004, -0x4c423382, -0x39290000, -0x00098200, -0x40820000, -0x00050802, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000c, -0x28090000, -0x00090200, -0x40800000, -0x0005080b, -0x88c80000, -0x00098200, -0x70c60000, -0x00090200, -0x38710000, -0x00098200, -0x41820000, -0x0005080b, -0x48000001, -0x00030031, -0x48000000, -0x0005000b, -0x00000000, -0x814efffc, -0x5588007e, -0x000900ab, -0x5694007e, -0x000900ab, -0x2108fffc, -0x3a940000, -0x00098200, -0x7d0f402e, -0x7d4aa02e, -0x88ca0000, -0x00098200, -0x808a0000, -0x00098200, -0x70c60000, -0x00090200, -0x88c80000, -0x00098200, -0x892a0000, -0x00098200, -0x38000000, -0x00098200, -0x91040004, -0x90040000, -0x40820000, -0x00050802, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000c, -0x70c60000, -0x00090200, -0x28890000, -0x4c423382, -0x38710000, -0x00098200, -0x41820000, -0x0005080b, -0x48000001, -0x00030031, -0x48000000, -0x0005000b, -0x00000000, -0x814efffc, -0x5694007e, -0x000900ab, -0x3a940000, -0x00098200, -0x7c0f64ae, -0x7d4aa02e, -0x80f00000, -0x3a100004, -0x810a0000, -0x00098200, -0xd8080000, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x814efffc, -0x5694007e, -0x000900ab, -0x558000fe, -0x000900ab, -0x3a940000, -0x00098200, -0x7c0000f8, -0x7d4aa02e, -0x80f00000, -0x3a100004, -0x810a0000, -0x00098200, -0x90080000, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x81120000, -0x00098200, -0x5580007e, -0x000900ab, -0x3e100000, -0x00098200, -0x7e100214, -0x91d20000, -0x00098200, -0x28080000, -0x7e439378, -0x41820000, -0x00050801, -0x7c8ea214, -0x48000001, -0x00030032, -0x81d20000, -0x00098200, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x5588007e, -0x000900ab, -0x91d20000, -0x00098200, -0x2108fffc, -0x92010020, -0x7c8f402e, -0x7e439378, -0x80aefffc, -0x48000001, -0x00030033, -0x81d20000, -0x00098200, -0x38000000, -0x00098200, -0x7c14716e, -0x90740004, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x80110000, -0x00098200, -0x7e439378, -0x81110000, -0x00098200, -0x91d20000, -0x00098200, -0x7c004040, -0x92010020, -0x40800000, -0x00050805, -0x0006000b, -0x00000000, -0x5584ed7e, -0x558596fe, -0x2c0407ff, -0x41820000, -0x00050803, -0x0006000c, -0x48000001, -0x00030034, -0x00000000, -0x5588007e, -0x000900ab, -0x2108fffc, -0x7c8f402e, -0x48000001, -0x00030035, -0x00000000, -0x81d20000, -0x00098200, -0x38000000, -0x00098200, -0x7c14716e, -0x90740004, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x0006000d, -0x38800801, -0x48000000, -0x0005000c, -0x00000000, -0x0006000f, -0x7d956378, -0x48000001, -0x00030036, -0x7eacab78, -0x7e439378, -0x48000000, -0x0005000b, -0x00000000, -0x812efffc, -0x5588007e, -0x000900ab, -0x81490000, -0x00098200, -0x2108fffc, -0x7d6f402e, -0x00000000, -0x48000000, -0x000500a4, -0x00000000, -0x48000000, -0x000500a5, -0x00000000, -0x7c6a706e, -0x7c8b706e, -0x814a0004, -0x00000000, -0x816b0004, -0x00000000, -0xc80b0000, -0x00000000, -0x2c030000, -0x00098200, -0x7c84b040, -0x40820000, -0x00050830, -0x00000000, -0x800a0000, -0x00098200, -0x40860000, -0x00050805, -0x810a0000, -0x00098200, -0x7c005840, -0x55691800, -0x000900a1, -0x00000000, -0x40840000, -0x00050805, -0xfc20001e, -0xfc40f02a, -0xd8210010, -0x800a0000, -0x00098200, -0xfc42f028, -0x81210014, -0x810a0000, -0x00098200, -0xfc801000, -0x7c004840, -0x4c213202, -0x55291800, -0x000900a1, -0x00000000, -0x40810000, -0x00050830, -0x7c08482e, -0x7dc84cae, -0x2c000000, -0x00098200, -0x41820000, -0x00050802, -0x0006000b, -0x80f00000, -0x3a100004, -0x7dcea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000c, -0x812a0000, -0x00098200, -0x28090000, -0x41820000, -0x0005080b, -0x88090000, -0x00098200, -0x70000000, -0x00090200, -0x40820000, -0x0005080b, -0x48000000, -0x00050030, -0x0006000f, -0x2c040000, -0x00098200, -0x40820000, -0x00050830, -0x00000000, -0x816b0004, -0x00000000, -0x48000000, -0x000500a4, -0x00000000, -0x7c6a706e, -0x5568007e, -0x000900ab, -0x814a0004, -0x2108fffc, -0x2c030000, -0x00098200, -0x7d6f402e, -0x40820000, -0x0005082d, -0x000600a4, -0x800a0000, -0x00098200, -0x810b0000, -0x00098200, -0x812a0000, -0x00098200, -0x7d080038, -0x55002800, -0x000900a1, -0x55081800, -0x000900a1, -0x7d080050, -0x7d294214, -0x0006000b, -0x80690000, -0x00098200, -0x80090000, -0x00098200, -0x80890000, -0x00098200, -0x81090000, -0x00098200, -0x2c030000, -0x00098200, -0x40820000, -0x00050804, -0x7c005800, -0x40820000, -0x00050804, -0x2c040000, -0x00098200, -0x41820000, -0x00050805, -0x0006000d, -0x7c94716e, -0x91140004, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000e, -0x81290000, -0x00098200, -0x00000000, -0x28090000, -0x40820000, -0x0005080b, -0x38800000, -0x00098200, -0x0006000f, -0x812a0000, -0x00098200, -0x28090000, -0x41820000, -0x0005080d, -0x88090000, -0x00098200, -0x70000000, -0x00090200, -0x40820000, -0x0005080d, -0x48000000, -0x0005002e, -0x00000000, -0x7c6a706e, -0x556000fe, -0x000900ab, -0x814a0004, -0x2c030000, -0x00098200, -0x40820000, -0x0005082f, -0x810a0000, -0x00098200, -0x812a0000, -0x00098200, -0x7c004040, -0x40800000, -0x0005082f, -0x7d09582e, -0x7c095cae, -0x2c080000, -0x00098200, -0x41820000, -0x00050805, -0x0006000b, -0x80f00000, -0x3a100004, -0x7c0ea5ae, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000f, -0x812a0000, -0x00098200, -0x28090000, -0x41820000, -0x0005080b, -0x89290000, -0x00098200, -0x71290000, -0x00090200, -0x40820000, -0x0005080b, -0x48000000, -0x0005002f, -0x00000000, -0x7c6a706e, -0x7c8b706e, -0x814a0004, -0x00000000, -0x816b0004, -0x00000000, -0xc80b0000, -0x00000000, -0x2c030000, -0x00098200, -0x7c84b040, -0x40820000, -0x00050834, -0x00000000, -0x800a0000, -0x00098200, -0x40860000, -0x00050805, -0x810a0000, -0x00098200, -0x7c005840, -0x55601800, -0x000900a1, -0x00000000, -0x40840000, -0x00050805, -0xfc20001e, -0xfc40f02a, -0xd8210010, -0x800a0000, -0x00098200, -0xfc42f028, -0x81210014, -0x810a0000, -0x00098200, -0xfc801000, -0x7c004840, -0x4c213202, -0x55201800, -0x000900a1, -0x00000000, -0x40810000, -0x00050834, -0x7d28002e, -0x88ca0000, -0x00098200, -0x7dcea4ae, -0x2c090000, -0x00098200, -0x41820000, -0x00050803, -0x0006000b, -0x70c90000, -0x00090200, -0x7dc805ae, -0x40820000, -0x00050807, -0x0006000c, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000d, -0x812a0000, -0x00098200, -0x28090000, -0x41820000, -0x0005080b, -0x89290000, -0x00098200, -0x71290000, -0x00090200, -0x40820000, -0x0005080b, -0x48000000, -0x00050034, -0x0006000f, -0x2c040000, -0x00098200, -0x40820000, -0x00050834, -0x00000000, -0x816b0004, -0x00000000, -0x48000000, -0x000500a5, -0x00060011, -0x80110000, -0x00098200, -0x54c607b8, -0x91510000, -0x00098200, -0x98ca0000, -0x00098200, -0x900a0000, -0x00098200, -0x48000000, -0x0005000c, -0x00000000, -0x7c6a706e, -0x5568007e, -0x000900ab, -0x814a0004, -0x2108fffc, -0x2c030000, -0x00098200, -0x7d6f402e, -0x40820000, -0x00050831, -0x000600a5, -0x800a0000, -0x00098200, -0x810b0000, -0x00098200, -0x812a0000, -0x00098200, -0x9b0a0000, -0x00098200, -0x7d080038, -0x7dcea4ae, -0x55002800, -0x000900a1, -0x55081800, -0x000900a1, -0x7d080050, -0x88ca0000, -0x00098200, -0x7d294214, -0x0006000b, -0x80690000, -0x00098200, -0x80090000, -0x00098200, -0x80890000, -0x00098200, -0x81090000, -0x00098200, -0x2c030000, -0x00098200, -0x40820000, -0x00050805, -0x7c005800, -0x40820000, -0x00050805, -0x2c040000, -0x00098200, -0x41820000, -0x00050804, -0x0006000c, -0x00000000, -0x70c00000, -0x00090200, -0xd9c90000, -0x00098200, -0x40820000, -0x00050807, -0x0006000d, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000e, -0x810a0000, -0x00098200, -0x28080000, -0x41820000, -0x0005080c, -0x88080000, -0x00098200, -0x70000000, -0x00090200, -0x40820000, -0x0005080c, -0x48000000, -0x00050032, -0x0006000f, -0x28080000, -0x7d094378, -0x40820000, -0x0005080b, -0x810a0000, -0x00098200, -0x38b10000, -0x00098200, -0x92010020, -0x7e439378, -0x28080000, -0x91d20000, -0x00098200, -0x41820000, -0x00050806, -0x88080000, -0x00098200, -0x70000000, -0x00090200, -0x41820000, -0x00050832, -0x00060010, -0x38000000, -0x00098200, -0x00000000, -0x91650004, -0x7d445378, -0x90050000, -0x48000001, -0x00030037, -0x81d20000, -0x00098200, -0xd9c30000, -0x48000000, -0x0005000d, -0x00060011, -0x80110000, -0x00098200, -0x54c607b8, -0x91510000, -0x00098200, -0x98ca0000, -0x00098200, -0x900a0000, -0x00098200, -0x48000000, -0x0005000d, -0x00000000, -0x7c6a706e, -0x556000fe, -0x000900ab, -0x814a0004, -0x2c030000, -0x00098200, -0x40820000, -0x00050833, -0x810a0000, -0x00098200, -0x812a0000, -0x00098200, -0x88ca0000, -0x00098200, -0x7c004040, -0x7dcea4ae, -0x40800000, -0x00050833, -0x7d09582e, -0x2c080000, -0x00098200, -0x41820000, -0x00050805, -0x0006000b, -0x70c00000, -0x00090200, -0x7dc95dae, -0x40820000, -0x00050807, -0x0006000c, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000f, -0x810a0000, -0x00098200, -0x28080000, -0x41820000, -0x0005080b, -0x89080000, -0x00098200, -0x71080000, -0x00090200, -0x40820000, -0x0005080b, -0x48000000, -0x00050033, -0x00060011, -0x80110000, -0x00098200, -0x00000000, -0x54c607b8, -0x91510000, -0x00098200, -0x98ca0000, -0x00098200, -0x900a0000, -0x00098200, -0x48000000, -0x0005000c, -0x00000000, -0x7e8ea214, -0x0006000b, -0x7ccf6214, -0x8094fffc, -0x3413fff8, -0x80c60004, -0x540500fe, -0x000900ab, -0x41820000, -0x00050804, -0x7ca53214, -0x81240000, -0x00098200, -0x54c81800, -0x000900a1, -0x88c40000, -0x00098200, -0x7c054840, -0x7d340214, -0x80040000, -0x00098200, -0x41810000, -0x00050805, -0x7d080214, -0x70c00000, -0x00090200, -0x0006000d, -0xc8140000, -0x3a940008, -0x7c944800, -0xd8080000, -0x39080008, -0x41840000, -0x0005080d, -0x40820000, -0x00050807, -0x0006000e, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000f, -0x91d20000, -0x00098200, -0x7e439378, -0x92010020, -0x7d956378, -0x48000001, -0x00030038, -0x7eacab78, -0x48000000, -0x0005000b, -0x00060011, -0x80110000, -0x00098200, -0x54c607b8, -0x90910000, -0x00098200, -0x98c40000, -0x00098200, -0x90040000, -0x00098200, -0x00000000, -0x48000000, -0x0005000e, -0x00000000, -0x7d6b9a14, -0x00000000, -0x7dc97378, -0x7c0ea06e, -0x814e0004, -0x396bfff8, -0x39ce0008, -0x2c000000, -0x00098200, -0x40820000, -0x00050825, -0x920efff8, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00000000, -0x7d6b9a14, -0x00000000, -0x7c14706e, -0x81540004, -0x396bfff8, -0x810efff8, -0x2c000000, -0x00098200, -0x3a940008, -0x40820000, -0x00050845, -0x00060046, -0x71000000, -0x00090200, -0x88ca0000, -0x00098200, -0x69090000, -0x00090200, -0x288b0000, -0x40820000, -0x00050807, -0x0006000b, -0x914efffc, -0x39200000, -0x2b860001, -0x41860000, -0x00050803, -0x0006000c, -0x38c90008, -0x7c144cae, -0x7c865840, -0x7c0e4dae, -0x7cc93378, -0x40860000, -0x0005080c, -0x0006000d, -0x4c42ea02, -0x41820000, -0x00050805, -0x0006000e, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x0006000f, -0x80e8fffc, -0x54f4dd78, -0x7d147050, -0x81080000, -0x00098200, -0x81080000, -0x00098200, -0x81e80000, -0x00098200, -0x48000000, -0x0005000e, -0x00060011, -0x71200000, -0x00090200, -0x00000000, -0x40820000, -0x0005080b, -0x7dc97050, -0x810efff8, -0x71000000, -0x00090200, -0x48000000, -0x0005000b, -0x00000000, -0x7dc97378, -0x7dcea214, -0x810effe8, -0x814effec, -0xc82efff8, -0xc80efff0, -0x910e0000, -0x914e0004, -0x2c080000, -0x00098200, -0xd82e0010, -0x39600010, -0xdc0e0008, -0x40820000, -0x00050825, -0x920efff8, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00000000, -0x7e8ea214, -0x8154fff4, -0x8174fffc, -0x800a0000, -0x00098200, -0x810a0000, -0x00098200, -0x3a100004, -0x0006000b, -0x7c0b0040, -0x55661800, -0x000900a1, -0x40800000, -0x00050805, -0x7d28302e, -0x7c0834ae, -0x2c090000, -0x00098200, -0x80f0fffc, -0x41820000, -0x00050804, -0x00000000, -0x91740004, -0x92d40000, -0x00000000, -0x9161000c, -0xc8210008, -0xfc21f028, -0x00000000, -0x396b0001, -0x3cd00000, -0x00098200, -0xd8140008, -0x54e893ba, -0x9174fffc, -0x7e083214, -0x00000000, -0xd8340000, -0x00000000, -0x0006000d, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000e, -0x396b0001, -0x48000000, -0x0005000b, -0x0006000f, -0x810a0000, -0x00098200, -0x7d605850, -0x812a0000, -0x00098200, -0x00060010, -0x7c0b4040, -0x55662800, -0x000900a1, -0x41a10000, -0x0005080d, -0x556a1800, -0x000900a1, -0x7cca3050, -0x7d49302e, -0x7c0934ae, -0x7cc93214, -0x2c0a0000, -0x00098200, -0x80f0fffc, -0x41820000, -0x00050807, -0xc8260000, -0x00098200, -0x3d300000, -0x00098200, -0xd8140008, -0x7d6b0214, -0x54e893ba, -0xd8340000, -0x396b0001, -0x7e084a14, -0x9174fffc, -0x48000000, -0x0005000d, -0x00060011, -0x396b0001, -0x48000000, -0x00050010, -0x00000000, -0x7e8ea214, -0x8014ffe8, -0x8114ffec, -0x8134fff0, -0x80d4fff8, -0x2c090000, -0x00098200, -0x2c800000, -0x00098200, -0x2f060000, -0x00098200, -0x40860000, -0x00050805, -0x89080000, -0x00098200, -0x4c42d202, -0x2f880000, -0x00098200, -0x5580007e, -0x000900ab, -0x4c42f202, -0x7cd00214, -0x40820000, -0x00050805, -0x9314fffc, -0x3e060000, -0x00098200, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000f, -0x38000000, -0x00098200, -0x39000000, -0x00098200, -0x9810ffff, -0x3e060000, -0x00098200, -0x99100003, -0x48000000, -0x0005000b, -0x00000000, -0x800efff8, -0x7d6e5a14, -0x7e8ea214, -0x396b0000, -0x00098200, -0x7d345214, -0x38cefff8, -0x7d605850, -0x288a0000, -0x7d0b3051, -0x41860000, -0x00050805, -0x3929fff0, -0x40810000, -0x00050802, -0x0006000b, -0xc80b0000, -0x396b0008, -0xd8140000, -0x7c144840, -0x7c8b3040, -0x40800000, -0x00050803, -0x3a940008, -0x41840000, -0x0005080b, -0x0006000c, -0x92f40000, -0x7c144840, -0x3a940008, -0x41800000, -0x0005080c, -0x0006000d, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000f, -0x80120000, -0x00098200, -0x3a600008, -0x40a10000, -0x0005080d, -0x7d344214, -0x7c090040, -0x3a680008, -0x41810000, -0x00050807, -0x00060010, -0xc80b0000, -0x396b0008, -0xd8140000, -0x7c0b3040, -0x3a940008, -0x41800000, -0x00050810, -0x48000000, -0x0005000d, -0x00060011, -0x7e439378, -0x92920000, -0x00098200, -0x7eae5850, -0x91d20000, -0x00098200, -0x7e8ea050, -0x92010020, -0x550400fe, -0x000900ab, -0x48000001, -0x00030000, -0x81d20000, -0x00098200, -0x00000000, -0x7e8ea214, -0x7d6eaa14, -0x38cefff8, -0x48000000, -0x00050010, -0x00000000, -0x7d8c9a14, -0x00000000, -0x820efff8, -0x7e8ea214, -0x7d936378, -0x0006000b, -0x72000000, -0x00090200, -0x6a080000, -0x00090200, -0x40820000, -0x000508a6, -0x00060017, -0x80f0fffc, -0x2c0c0008, -0x392efff8, -0x396cfff8, -0x54ea5d78, -0x41820000, -0x00050803, -0x39000000, -0x0006000c, -0x38c80008, -0x7c1444ae, -0x7c065800, -0x7c0945ae, -0x41820000, -0x00050803, -0x39060008, -0x7c3434ae, -0x7c085800, -0x7c2935ae, -0x40820000, -0x0005080c, -0x0006000d, -0x0006000f, -0x7c0a6040, -0x54f4dd78, -0x41810000, -0x00050806, -0x7dd44850, -0x810efffc, -0x80f00000, -0x3a100004, -0x81080000, -0x00098200, -0x81e80000, -0x00098200, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00060010, -0x390cfff8, -0x398c0008, -0x7ee9412e, -0x48000000, -0x0005000f, -0x000600a6, -0x71090000, -0x00090200, -0x40820000, -0x00050818, -0x7dc87050, -0x820efff8, -0x48000000, -0x0005000b, -0x00000000, -0x820efff8, -0x7e8ea214, -0x7d936378, -0x72000000, -0x00090200, -0x6a080000, -0x00090200, -0x40a20000, -0x000508a6, -0x80f0fffc, -0x392efff8, -0x54ea5d78, -0x00000000, -0xc8140000, -0xd8090000, -0x00000000, -0x0006000f, -0x7c0a6040, -0x54f4dd78, -0x41810000, -0x00050806, -0x7dd44850, -0x810efffc, -0x80f00000, -0x3a100004, -0x81080000, -0x00098200, -0x81e80000, -0x00098200, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00060010, -0x390cfff8, -0x398c0008, -0x7ee9412e, -0x48000000, -0x0005000f, -0x00000000, -0x5608fe7c, -0x39080000, -0x00098200, -0x7d31422e, -0x35290000, -0x00098200, -0x7d31432e, -0x41800000, -0x00050894, -0x00000000, -0x7d14706e, -0x80740000, -0x00098200, -0x7c08b040, -0x00000000, -0x80b40000, -0x00098200, -0x40820000, -0x00050809, -0x7c632e15, -0x2f050000, -0x80940000, -0x00098200, -0x41830000, -0x00050806, -0x0006000e, -0x90740000, -0x00098200, -0x00000000, -0x80d40000, -0x00098200, -0x80b40000, -0x00098200, -0x81340000, -0x00098200, -0x80940000, -0x00098200, -0x7f86b040, -0x7c89b040, -0x4c42f202, -0x4c423202, -0x2f050000, -0x40820000, -0x00050809, -0x00000000, -0x41980000, -0x00050805, -0x7c032000, -0x0006000b, -0x92d40000, -0x00098200, -0x00000000, -0x558c007e, -0x000900ab, -0x00000000, -0x90740000, -0x00098200, -0x00000000, -0x7d906214, -0x00000000, -0x41810000, -0x00050803, -0x00000000, -0x3e0c0000, -0x00098200, -0x40a10000, -0x00050807, -0x00000000, -0x41810000, -0x00050802, -0x3e0c0000, -0x00098200, -0x00000000, -0x40a10000, -0x00070800, -0x00000000, -0x0006000c, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000f, -0x7c041800, -0x48000000, -0x0005000b, -0x00000000, -0x00060010, -0x7c000400, -0x40a10000, -0x0005080e, -0x48000000, -0x0005000c, -0x00000000, -0x00060013, -0xc8340000, -0x00098200, -0x00000000, -0x7c3474ee, -0x00000000, -0xc8740000, -0x00098200, -0xc8540000, -0x00098200, -0x80d40000, -0x00098200, -0xfc21182a, -0xd8340000, -0x00098200, -0x00000000, -0x00060013, -0x00000000, -0x7d14706e, -0x80d40000, -0x00098200, -0x81340000, -0x00098200, -0x7c08b040, -0x7f86b040, -0x7c89b040, -0x00000000, -0xc8340000, -0x00098200, -0x4c00e202, -0x4c002202, -0xc8540000, -0x00098200, -0x40800000, -0x00050847, -0x00000000, -0x2f060000, -0x00000000, -0x558c007e, -0x000900ab, -0x00000000, -0xd8340000, -0x00098200, -0x00000000, -0x7d906214, -0x00000000, -0xfc011000, -0x00000000, -0x3e0c0000, -0x00098200, -0x00000000, -0x41980000, -0x00050805, -0x00000000, -0x41810000, -0x00050803, -0x00000000, -0x41a10000, -0x0005080c, -0x00000000, -0x41810000, -0x00050802, -0x00000000, -0x0006000b, -0x3e0c0000, -0x00098200, -0x00000000, -0x40a10000, -0x00050807, -0x00000000, -0x40a10000, -0x00070800, -0x00000000, -0x48000000, -0x0005000c, -0x00000000, -0x0006000c, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x0006000f, -0x00000000, -0x40800000, -0x0005080c, -0x0006000d, -0x3e0c0000, -0x00098200, -0x00000000, -0x40a00000, -0x0005080b, -0x00000000, -0x40a00000, -0x00050807, -0x00000000, -0x40a00000, -0x00070800, -0x00000000, -0x48000000, -0x0005000c, -0x00000000, -0x00060011, -0x80f0fffc, -0x54ec9b78, -0x48000000, -0x00070000, -0x00000000, -0x5608fe7c, -0x39080000, -0x00098200, -0x7d31422e, -0x35290000, -0x00098200, -0x7d31432e, -0x41800000, -0x00050894, -0x00000000, -0x7d14706e, -0x81340004, -0x2c080000, -0x00098200, -0x41820000, -0x00050801, -0x00000000, -0x9114fff8, -0x9134fffc, -0x48000000, -0x00070000, -0x00000000, -0x5580007e, -0x000900ab, -0x3e100000, -0x00098200, -0x7e100214, -0x9114fff8, -0x9134fffc, -0x00000000, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x5608fe7c, -0x39080000, -0x00098200, -0x7d31422e, -0x35290000, -0x00098200, -0x7d31432e, -0x41800000, -0x00050894, -0x00000000, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x81110000, -0x00098200, -0x558c007e, -0x000900ab, -0x93110000, -0x00098200, -0x7d28602e, -0x7c000400, -0x81290000, -0x00098200, -0x91d10000, -0x00098200, -0x7d2903a6, -0x92510000, -0x00098200, -0x3bf10000, -0x00098200, -0x4e800420, -0x00000000, -0x5580007e, -0x000900ab, -0x3e100000, -0x00098200, -0x7e100214, -0x80f00000, -0x3a100004, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x5608fe7c, -0x39080000, -0x00098200, -0x7d31422e, -0x35290000, -0x00098200, -0x7d31432e, -0x41800000, -0x00050896, -0x00000000, -0x81320000, -0x00098200, -0x89100000, -0x00098200, -0x81f00000, -0x00098200, -0x7c144840, -0x55081800, -0x000900a1, -0x41810000, -0x00050820, -0x00000000, -0x80f00000, -0x3a100004, -0x00000000, -0x0006000c, -0x7c0b4040, -0x41800000, -0x00050803, -0x00000000, -0x54ec9b78, -0x48000000, -0x00070000, -0x00000000, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x00000000, -0x0006000d, -0x7eee592e, -0x396b0008, -0x48000000, -0x0005000c, -0x00000000, -0x7c810808, -0x00000000, -0x81320000, -0x00098200, -0x7d0e5a14, -0x7c145a14, -0x91480004, -0x38cb0000, -0x00098200, -0x81f00000, -0x00098200, -0x7c004840, -0x90c80000, -0x40800000, -0x00050820, -0x89300000, -0x00098200, -0x7dd47378, -0x7d0b4378, -0x80f00000, -0x3a100004, -0x2c090000, -0x39c80008, -0x41820000, -0x00050803, -0x0006000b, -0x7c145840, -0x80140000, -0x80d40004, -0x40800000, -0x00050804, -0x92f40000, -0x3a940008, -0x0006000c, -0x3529ffff, -0x90080008, -0x90c8000c, -0x39080008, -0x40820000, -0x0005080b, -0x0006000d, -0x54e815ba, -0x7c11402e, -0x7c0903a6, -0x54ea5d78, -0x54ec9b78, -0x54f4dd78, -0x54eb9d78, -0x4e800420, -0x0006000e, -0x38000000, -0x00098200, -0x48000000, -0x0005000c, -0x00000000, -0x80ca0000, -0x00098200, -0x00000000, -0x80d10000, -0x00098200, -0x00000000, -0x7d145a14, -0x81320000, -0x00098200, -0x7d6e5a14, -0x91d20000, -0x00098200, -0x7c084840, -0x91720000, -0x00098200, -0x38000000, -0x00098200, -0x7cc903a6, -0x00000000, -0x808a0000, -0x00098200, -0x00000000, -0x7e439378, -0x41810000, -0x0005081f, -0x90110000, -0x00098200, -0x4e800421, -0x81d20000, -0x00098200, -0x546c1800, -0x000900a1, -0x81120000, -0x00098200, -0x38000000, -0x00098200, -0x820efff8, -0x7e8c4050, -0x90110000, -0x00098200, -0x48000000, -0x00050016, -0x00000000, -0x00010000 -}; - -enum { - GLOB_vm_returnp, - GLOB_cont_dispatch, - GLOB_vm_returnc, - GLOB_BC_RET_Z, - GLOB_vm_return, - GLOB_vm_leave_cp, - GLOB_vm_leave_unw, - GLOB_vm_unwind_c, - GLOB_vm_unwind_c_eh, - GLOB_vm_unwind_ff, - GLOB_vm_unwind_ff_eh, - GLOB_vm_growstack_c, - GLOB_vm_growstack_l, - GLOB_vm_resume, - GLOB_vm_pcall, - GLOB_vm_call, - GLOB_vm_call_dispatch, - GLOB_vmeta_call, - GLOB_vm_call_dispatch_f, - GLOB_vm_cpcall, - GLOB_cont_ffi_callback, - GLOB_vm_call_tail, - GLOB_cont_cat, - GLOB_BC_CAT_Z, - GLOB_cont_nop, - GLOB_vmeta_tgets1, - GLOB_vmeta_tgets, - GLOB_vmeta_tgetb, - GLOB_vmeta_tgetv, - GLOB_vmeta_tsets1, - GLOB_vmeta_tsets, - GLOB_vmeta_tsetb, - GLOB_vmeta_tsetv, - GLOB_vmeta_comp, - GLOB_vmeta_binop, - GLOB_cont_ra, - GLOB_cont_condt, - GLOB_cont_condf, - GLOB_vmeta_equal, - GLOB_vmeta_equal_cd, - GLOB_vmeta_arith_nv, - GLOB_vmeta_arith_nv2, - GLOB_vmeta_unm, - GLOB_vmeta_arith_vn, - GLOB_vmeta_arith_vv, - GLOB_vmeta_arith_vn2, - GLOB_vmeta_arith_vv2, - GLOB_vmeta_len, - GLOB_BC_LEN_Z, - GLOB_vmeta_callt, - GLOB_BC_CALLT_Z, - GLOB_vmeta_for, - GLOB_ff_assert, - GLOB_fff_fallback, - GLOB_fff_res, - GLOB_ff_type, - GLOB_fff_resn, - GLOB_ff_getmetatable, - GLOB_fff_restv, - GLOB_ff_setmetatable, - GLOB_ff_rawget, - GLOB_ff_tonumber, - GLOB_ff_tostring, - GLOB_fff_gcstep, - GLOB_ff_next, - GLOB_ff_pairs, - GLOB_ff_ipairs_aux, - GLOB_ff_ipairs, - GLOB_ff_pcall, - GLOB_ff_xpcall, - GLOB_ff_coroutine_resume, - GLOB_ff_coroutine_wrap_aux, - GLOB_ff_coroutine_yield, - GLOB_ff_math_abs, - GLOB_fff_resi, - GLOB_fff_res1, - GLOB_ff_math_floor, - GLOB_ff_math_ceil, - GLOB_ff_math_sqrt, - GLOB_ff_math_log, - GLOB_ff_math_log10, - GLOB_ff_math_exp, - GLOB_ff_math_sin, - GLOB_ff_math_cos, - GLOB_ff_math_tan, - GLOB_ff_math_asin, - GLOB_ff_math_acos, - GLOB_ff_math_atan, - GLOB_ff_math_sinh, - GLOB_ff_math_cosh, - GLOB_ff_math_tanh, - GLOB_ff_math_pow, - GLOB_ff_math_atan2, - GLOB_ff_math_fmod, - GLOB_ff_math_deg, - GLOB_ff_math_rad, - GLOB_ff_math_ldexp, - GLOB_ff_math_frexp, - GLOB_ff_math_modf, - GLOB_ff_math_min, - GLOB_ff_math_max, - GLOB_ff_string_len, - GLOB_ff_string_byte, - GLOB_ff_string_char, - GLOB_fff_newstr, - GLOB_ff_string_sub, - GLOB_ff_string_rep, - GLOB_ff_string_reverse, - GLOB_ff_string_lower, - GLOB_ff_string_upper, - GLOB_ff_table_getn, - GLOB_ff_bit_band, - GLOB_fff_tobit_fb, - GLOB_fff_bitop_fb, - GLOB_ff_bit_bor, - GLOB_ff_bit_bxor, - GLOB_ff_bit_bswap, - GLOB_ff_bit_bnot, - GLOB_ff_bit_lshift, - GLOB_ff_bit_rshift, - GLOB_ff_bit_arshift, - GLOB_ff_bit_rol, - GLOB_ff_bit_ror, - GLOB_ff_bit_tobit, - GLOB_vm_record, - GLOB_vm_rethook, - GLOB_vm_inshook, - GLOB_cont_hook, - GLOB_vm_hotloop, - GLOB_vm_callhook, - GLOB_vm_hotcall, - GLOB_vm_exit_handler, - GLOB_vm_exit_interp, - GLOB_vm_floor, - GLOB_vm_ceil, - GLOB_vm_trunc, - GLOB_vm_modi, - GLOB_vm_foldarith, - GLOB_vm_cachesync, - GLOB_vm_ffi_callback, - GLOB_vm_ffi_call, - GLOB_BC_ISEQN_Z, - GLOB_BC_ISNEN_Z, - GLOB_BC_MODVN_Z, - GLOB_BC_TGETS_Z, - GLOB_BC_TSETS_Z, - GLOB_BC_RETV_Z, - GLOB__MAX -}; -static const char *const globnames[] = { - "vm_returnp", - "cont_dispatch", - "vm_returnc", - "BC_RET_Z", - "vm_return", - "vm_leave_cp", - "vm_leave_unw", - "vm_unwind_c", - "vm_unwind_c_eh", - "vm_unwind_ff", - "vm_unwind_ff_eh", - "vm_growstack_c", - "vm_growstack_l", - "vm_resume", - "vm_pcall", - "vm_call", - "vm_call_dispatch", - "vmeta_call", - "vm_call_dispatch_f", - "vm_cpcall", - "cont_ffi_callback", - "vm_call_tail", - "cont_cat", - "BC_CAT_Z", - "cont_nop", - "vmeta_tgets1", - "vmeta_tgets", - "vmeta_tgetb", - "vmeta_tgetv", - "vmeta_tsets1", - "vmeta_tsets", - "vmeta_tsetb", - "vmeta_tsetv", - "vmeta_comp", - "vmeta_binop", - "cont_ra", - "cont_condt", - "cont_condf", - "vmeta_equal", - "vmeta_equal_cd", - "vmeta_arith_nv", - "vmeta_arith_nv2", - "vmeta_unm", - "vmeta_arith_vn", - "vmeta_arith_vv", - "vmeta_arith_vn2", - "vmeta_arith_vv2", - "vmeta_len", - "BC_LEN_Z", - "vmeta_callt", - "BC_CALLT_Z", - "vmeta_for", - "ff_assert", - "fff_fallback", - "fff_res", - "ff_type", - "fff_resn", - "ff_getmetatable", - "fff_restv", - "ff_setmetatable", - "ff_rawget", - "ff_tonumber", - "ff_tostring", - "fff_gcstep", - "ff_next", - "ff_pairs", - "ff_ipairs_aux", - "ff_ipairs", - "ff_pcall", - "ff_xpcall", - "ff_coroutine_resume", - "ff_coroutine_wrap_aux", - "ff_coroutine_yield", - "ff_math_abs", - "fff_resi", - "fff_res1", - "ff_math_floor", - "ff_math_ceil", - "ff_math_sqrt", - "ff_math_log", - "ff_math_log10", - "ff_math_exp", - "ff_math_sin", - "ff_math_cos", - "ff_math_tan", - "ff_math_asin", - "ff_math_acos", - "ff_math_atan", - "ff_math_sinh", - "ff_math_cosh", - "ff_math_tanh", - "ff_math_pow", - "ff_math_atan2", - "ff_math_fmod", - "ff_math_deg", - "ff_math_rad", - "ff_math_ldexp", - "ff_math_frexp", - "ff_math_modf", - "ff_math_min", - "ff_math_max", - "ff_string_len", - "ff_string_byte", - "ff_string_char", - "fff_newstr", - "ff_string_sub", - "ff_string_rep", - "ff_string_reverse", - "ff_string_lower", - "ff_string_upper", - "ff_table_getn", - "ff_bit_band", - "fff_tobit_fb", - "fff_bitop_fb", - "ff_bit_bor", - "ff_bit_bxor", - "ff_bit_bswap", - "ff_bit_bnot", - "ff_bit_lshift", - "ff_bit_rshift", - "ff_bit_arshift", - "ff_bit_rol", - "ff_bit_ror", - "ff_bit_tobit", - "vm_record", - "vm_rethook", - "vm_inshook", - "cont_hook", - "vm_hotloop", - "vm_callhook", - "vm_hotcall", - "vm_exit_handler", - "vm_exit_interp", - "vm_floor", - "vm_ceil", - "vm_trunc", - "vm_modi", - "vm_foldarith", - "vm_cachesync", - "vm_ffi_callback", - "vm_ffi_call", - "BC_ISEQN_Z", - "BC_ISNEN_Z", - "BC_MODVN_Z", - "BC_TGETS_Z", - "BC_TSETS_Z", - "BC_RETV_Z", - (const char *)0 -}; -static const char *const extnames[] = { - "lj_state_growstack", - "lj_meta_tget", - "lj_meta_tset", - "lj_meta_comp", - "lj_meta_equal", - "lj_meta_equal_cd", - "lj_meta_arith", - "lj_meta_len", - "lj_meta_call", - "lj_meta_for", - "lj_tab_get", - "lj_str_fromnumber", - "lj_str_fromnum", - "lj_tab_next", - "lj_tab_getinth", - "lj_ffh_coroutine_wrap_err", - "floor", - "ceil", - "sqrt", - "log", - "log10", - "exp", - "sin", - "cos", - "tan", - "asin", - "acos", - "atan", - "sinh", - "cosh", - "tanh", - "pow", - "atan2", - "fmod", - "ldexp", - "frexp", - "modf", - "lj_str_new", - "lj_tab_len", - "lj_gc_step", - "lj_dispatch_ins", - "lj_trace_hot", - "lj_dispatch_call", - "lj_trace_exit", - "lj_err_throw", - "trunc", - "lj_ccallback_enter", - "lj_ccallback_leave", - "lj_meta_cat", - "lj_gc_barrieruv", - "lj_func_closeuv", - "lj_func_newL_gc", - "lj_tab_new", - "lj_tab_dup", - "lj_gc_step_fixtop", - "lj_tab_newkey", - "lj_tab_reasize", - (const char *)0 -}; -#define Dt1(_V) (int)(ptrdiff_t)&(((lua_State *)0)_V) -#define Dt2(_V) (int)(ptrdiff_t)&(((global_State *)0)_V) -#define Dt3(_V) (int)(ptrdiff_t)&(((TValue *)0)_V) -#define Dt4(_V) (int)(ptrdiff_t)&(((GCobj *)0)_V) -#define Dt5(_V) (int)(ptrdiff_t)&(((GCstr *)0)_V) -#define Dt6(_V) (int)(ptrdiff_t)&(((GCtab *)0)_V) -#define Dt7(_V) (int)(ptrdiff_t)&(((GCfuncL *)0)_V) -#define Dt8(_V) (int)(ptrdiff_t)&(((GCfuncC *)0)_V) -#define Dt9(_V) (int)(ptrdiff_t)&(((GCproto *)0)_V) -#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V) -#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V) -#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V) -#define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V) -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx) -{ - dasm_put(Dst, 0); - dasm_put(Dst, 1, FRAME_P, LJ_TTRUE, FRAME_TYPE, FRAME_C, ~LJ_VMST_C, Dt1(->base), DISPATCH_GL(vmstate), 31-3, Dt1(->top)); - dasm_put(Dst, 55, Dt1(->cframe), 56+(14-14)*4, 128+(14-14)*8, 56+(15-14)*4, 128+(15-14)*8, 56+(16-14)*4, 128+(16-14)*8, 56+(17-14)*4, 128+(17-14)*8, 56+(18-14)*4, 128+(18-14)*8, 56+(19-14)*4, 128+(19-14)*8, 56+(20-14)*4, 128+(20-14)*8, 56+(21-14)*4, 128+(21-14)*8, 56+(22-14)*4, 128+(22-14)*8, 56+(23-14)*4, 128+(23-14)*8); - dasm_put(Dst, 105, 56+(24-14)*4, 128+(24-14)*8, 56+(25-14)*4, 128+(25-14)*8, 56+(26-14)*4, 128+(26-14)*8, 56+(27-14)*4, 128+(27-14)*8, 56+(28-14)*4, 128+(28-14)*8, 56+(29-14)*4, 128+(29-14)*8, 56+(30-14)*4, 128+(30-14)*8, 56+(31-14)*4, 128+(31-14)*8, Dt1(->maxstack)); - dasm_put(Dst, 154, Dt1(->top), 31-3, Dt1(->top), ~LJ_VMST_C, Dt1(->glref), Dt2(->vmstate), LJ_TISNUM, Dt1(->base), Dt1(->glref), LJ_TFALSE, LJ_TNIL, ~LJ_VMST_INTERP, GG_G2DISP); - dasm_put(Dst, 217, DISPATCH_GL(vmstate), LUA_MINSTACK, Dt1(->base), Dt1(->top), 32-3, Dt1(->base), Dt1(->top), Dt7(->pc), 56+(14-14)*4, 128+(14-14)*8, 56+(15-14)*4, 128+(15-14)*8, 56+(16-14)*4, 128+(16-14)*8, 56+(17-14)*4); - dasm_put(Dst, 278, 128+(17-14)*8, 56+(18-14)*4, 128+(18-14)*8, 56+(19-14)*4, 128+(19-14)*8, 56+(20-14)*4, 128+(20-14)*8, 56+(21-14)*4, 128+(21-14)*8, 56+(22-14)*4, 128+(22-14)*8, 56+(23-14)*4, 128+(23-14)*8, 56+(24-14)*4, 128+(24-14)*8, 56+(25-14)*4, 128+(25-14)*8, 56+(26-14)*4, 128+(26-14)*8, 56+(27-14)*4, 128+(27-14)*8, 56+(28-14)*4); - dasm_put(Dst, 325, 128+(28-14)*8, 56+(29-14)*4, 128+(29-14)*8, 56+(30-14)*4, 128+(30-14)*8, 56+(31-14)*4, 128+(31-14)*8, Dt1(->glref), Dt1(->status), FRAME_CP, CFRAME_RESUME, GG_G2DISP, Dt1(->cframe), Dt1(->base), LJ_TISNUM, Dt1(->top), Dt1(->status), ~LJ_VMST_INTERP, DISPATCH_GL(vmstate), FRAME_TYPE, LJ_TNIL); - dasm_put(Dst, 393, 56+(14-14)*4, 128+(14-14)*8, 56+(15-14)*4, 128+(15-14)*8, 56+(16-14)*4, 128+(16-14)*8, 56+(17-14)*4, 128+(17-14)*8, 56+(18-14)*4, 128+(18-14)*8, 56+(19-14)*4, 128+(19-14)*8, 56+(20-14)*4, 128+(20-14)*8, 56+(21-14)*4, 128+(21-14)*8, 56+(22-14)*4, 128+(22-14)*8, 56+(23-14)*4); - dasm_put(Dst, 440, 128+(23-14)*8, 56+(24-14)*4, 128+(24-14)*8, 56+(25-14)*4, 128+(25-14)*8, 56+(26-14)*4, 128+(26-14)*8, 56+(27-14)*4, 128+(27-14)*8, 56+(28-14)*4, 128+(28-14)*8, 56+(29-14)*4, 128+(29-14)*8, 56+(30-14)*4, 128+(30-14)*8, 56+(31-14)*4, 128+(31-14)*8, FRAME_CP, 56+(14-14)*4, 128+(14-14)*8); - dasm_put(Dst, 488, 56+(15-14)*4, 128+(15-14)*8, 56+(16-14)*4, 128+(16-14)*8, 56+(17-14)*4, 128+(17-14)*8, 56+(18-14)*4, 128+(18-14)*8, 56+(19-14)*4, 128+(19-14)*8, 56+(20-14)*4, 128+(20-14)*8, 56+(21-14)*4, 128+(21-14)*8, 56+(22-14)*4, 128+(22-14)*8, 56+(23-14)*4, 128+(23-14)*8, 56+(24-14)*4, 128+(24-14)*8, 56+(25-14)*4, 128+(25-14)*8); - dasm_put(Dst, 535, 56+(26-14)*4, 128+(26-14)*8, 56+(27-14)*4, 128+(27-14)*8, 56+(28-14)*4, 128+(28-14)*8, 56+(29-14)*4, 128+(29-14)*8, 56+(30-14)*4, 128+(30-14)*8, 56+(31-14)*4, 128+(31-14)*8, FRAME_C, Dt1(->cframe), Dt1(->cframe), Dt1(->glref), GG_G2DISP, Dt1(->base), LJ_TISNUM, Dt1(->top)); - dasm_put(Dst, 586, ~LJ_VMST_INTERP, LJ_TNIL, DISPATCH_GL(vmstate), LJ_TFUNC, Dt7(->pc), 56+(14-14)*4, 128+(14-14)*8, 56+(15-14)*4, 128+(15-14)*8, 56+(16-14)*4, 128+(16-14)*8, 56+(17-14)*4, 128+(17-14)*8, 56+(18-14)*4, 128+(18-14)*8, 56+(19-14)*4, 128+(19-14)*8, 56+(20-14)*4); - dasm_put(Dst, 653, 128+(20-14)*8, 56+(21-14)*4, 128+(21-14)*8, 56+(22-14)*4, 128+(22-14)*8, 56+(23-14)*4, 128+(23-14)*8, 56+(24-14)*4, 128+(24-14)*8, 56+(25-14)*4, 128+(25-14)*8, 56+(26-14)*4, 128+(26-14)*8, 56+(27-14)*4, 128+(27-14)*8, 56+(28-14)*4, 128+(28-14)*8, 56+(29-14)*4, 128+(29-14)*8, 56+(30-14)*4, 128+(30-14)*8, 56+(31-14)*4); - dasm_put(Dst, 700, 128+(31-14)*8, Dt1(->stack), Dt1(->top), Dt1(->cframe), Dt1(->cframe), Dt1(->glref), FRAME_CP, GG_G2DISP); -#if LJ_HASFFI - dasm_put(Dst, 738); -#endif - dasm_put(Dst, 740, Dt7(->pc)); -#if LJ_HASFFI - dasm_put(Dst, 746); -#endif - dasm_put(Dst, 749, PC2PROTO(k)); -#if LJ_HASFFI - dasm_put(Dst, 754); -#endif - dasm_put(Dst, 762, Dt1(->base), DISPATCH_GL(tmptv), LJ_TSTR, DISPATCH_GL(tmptv), LJ_TTAB, DISPATCH_GL(tmptv2), LJ_TSTR); - if (!LJ_DUALNUM) { - dasm_put(Dst, 807); - } - dasm_put(Dst, 811, DISPATCH_GL(tmptv)); - if (LJ_DUALNUM) { - dasm_put(Dst, 816); - } else { - dasm_put(Dst, 819); - } - dasm_put(Dst, 821, Dt1(->base), FRAME_CONT, Dt1(->top), DISPATCH_GL(tmptv), LJ_TSTR, DISPATCH_GL(tmptv), LJ_TTAB, DISPATCH_GL(tmptv2), LJ_TSTR); - if (!LJ_DUALNUM) { - dasm_put(Dst, 889); - } - dasm_put(Dst, 893, DISPATCH_GL(tmptv)); - if (LJ_DUALNUM) { - dasm_put(Dst, 898); - } else { - dasm_put(Dst, 901); - } - dasm_put(Dst, 903, Dt1(->base), FRAME_CONT, Dt1(->top)); - if (LJ_DUALNUM) { - dasm_put(Dst, 948); - } else { - dasm_put(Dst, 950); - } - dasm_put(Dst, 952); - if (LJ_DUALNUM) { - dasm_put(Dst, 954); - } else { - dasm_put(Dst, 956); - } - dasm_put(Dst, 958, Dt1(->base), -(BCBIAS_J*4 >> 16), LJ_TTRUE, LJ_TTRUE, Dt1(->base)); -#if LJ_HASFFI - dasm_put(Dst, 1021, Dt1(->base)); -#endif - dasm_put(Dst, 1032); - if (LJ_DUALNUM) { - dasm_put(Dst, 1039); - } - dasm_put(Dst, 1044); - if (LJ_DUALNUM) { - dasm_put(Dst, 1058); - } - dasm_put(Dst, 1061); - if (LJ_DUALNUM) { - dasm_put(Dst, 1064); - } - dasm_put(Dst, 1067, Dt1(->base), FRAME_CONT); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1091); -#endif - dasm_put(Dst, 1093, Dt1(->base)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1101); -#else - dasm_put(Dst, 1108); -#endif - dasm_put(Dst, 1111, Dt1(->base), Dt7(->pc), Dt1(->base), Dt1(->base)); -#if LJ_HASJIT - dasm_put(Dst, 1159); -#endif - dasm_put(Dst, 1161); -#if LJ_HASJIT - dasm_put(Dst, 1163, BC_JFORI); -#endif - dasm_put(Dst, 1166); -#if LJ_HASJIT - dasm_put(Dst, 1168, BC_JFORI); -#endif - dasm_put(Dst, 1171, BC_FORI, LJ_TFALSE, ~LJ_TISNUM+1, 31-3, Dt8(->upvalue), LJ_TTAB, Dt6(->metatable)); - dasm_put(Dst, 1234, LJ_TNIL, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable]), Dt6(->hmask), LJ_TTAB, Dt5(->hash), Dt6(->node), 31-5, 31-3, DtB(->key), 4+offsetof(Node, key), DtB(->val), 4+offsetof(Node, val), LJ_TSTR, DtB(->next)); - dasm_put(Dst, 1282, LJ_TNIL, LJ_TUDATA, ~LJ_TISNUM+1, 31-2, DISPATCH_GL(gcroot[GCROOT_BASEMT]), LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable)); - dasm_put(Dst, 1337, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist), LJ_TTAB, LJ_TSTR, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM]), Dt1(->base)); - dasm_put(Dst, 1397, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - if (LJ_DUALNUM) { - dasm_put(Dst, 1407); - } else { - dasm_put(Dst, 1410); - } - dasm_put(Dst, 1413, LJ_TSTR, LJ_TTAB, Dt1(->base), Dt1(->top), LJ_TNIL, (2+1)*8, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1464, Dt6(->metatable), Dt8(->upvalue[0])); -#else - dasm_put(Dst, 1473, Dt8(->upvalue[0])); -#endif - dasm_put(Dst, 1477, (3+1)*8); - if (LJ_DUALNUM) { - dasm_put(Dst, 1489); - } else { - dasm_put(Dst, 1491); - } - dasm_put(Dst, 1493, LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 1500); - } else { - dasm_put(Dst, 1505); - } - dasm_put(Dst, 1517, Dt6(->asize), Dt6(->array)); - if (!LJ_DUALNUM) { - dasm_put(Dst, 1522); - } - dasm_put(Dst, 1524); - if (LJ_DUALNUM) { - dasm_put(Dst, 1528, 31-3); - } else { - dasm_put(Dst, 1533, 31-3); - } - dasm_put(Dst, 1537, LJ_TNIL, (0+1)*8, (2+1)*8, Dt6(->hmask), (0+1)*8, (0+1)*8, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1585, Dt6(->metatable), Dt8(->upvalue[0])); -#else - dasm_put(Dst, 1594, Dt8(->upvalue[0])); -#endif - if (LJ_DUALNUM) { - dasm_put(Dst, 1598); - } else { - dasm_put(Dst, 1600); - } - dasm_put(Dst, 1602, (3+1)*8, DISPATCH_GL(hookmask), 32-HOOK_ACTIVE_SHIFT, 8+FRAME_PCALL, DISPATCH_GL(hookmask), LJ_TFUNC, 32-HOOK_ACTIVE_SHIFT, 16+FRAME_PCALL, LJ_TTHREAD, Dt1(->status), Dt1(->cframe)); - dasm_put(Dst, 1662, Dt1(->top), LUA_YIELD, Dt1(->base), Dt1(->maxstack), Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->base), LUA_YIELD, Dt1(->top), ~LJ_VMST_INTERP, Dt1(->base), DISPATCH_GL(vmstate)); - dasm_put(Dst, 1724, Dt1(->maxstack), Dt1(->top), FRAME_TYPE, LJ_TTRUE, FRAME_TYPE, LJ_TFALSE, Dt1(->top), (2+1)*8, 32-3); - dasm_put(Dst, 1787, Dt8(->upvalue[0].gcr), Dt1(->status), Dt1(->cframe), Dt1(->top), LUA_YIELD, Dt1(->base), Dt1(->maxstack), Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->base), LUA_YIELD, Dt1(->top), ~LJ_VMST_INTERP); - dasm_put(Dst, 1846, Dt1(->base), DISPATCH_GL(vmstate), Dt1(->maxstack), Dt1(->top), FRAME_TYPE, 32-3, Dt1(->cframe)); - dasm_put(Dst, 1903, Dt1(->base), CFRAME_RESUME, Dt1(->top), LUA_YIELD, Dt1(->cframe), Dt1(->status)); - if (LJ_DUALNUM) { - dasm_put(Dst, 1928); - } - dasm_put(Dst, 1949, (1+1)*8, FRAME_TYPE); - if (LJ_DUALNUM) { - dasm_put(Dst, 1991, 31-11, 32-21, 31-11); - dasm_put(Dst, 2073, 31-11, 32-21, 31-11); - } else { - dasm_put(Dst, 2127); - } - dasm_put(Dst, 2154); - dasm_put(Dst, 2213); - dasm_put(Dst, 2271); - dasm_put(Dst, 2327, Dt8(->upvalue[0])); - dasm_put(Dst, 2393); - if (LJ_DUALNUM) { - dasm_put(Dst, 2397); - } else { - dasm_put(Dst, 2412); - } - dasm_put(Dst, 2430, DISPATCH_GL(tmptv), DISPATCH_GL(tmptv)); - if (!LJ_DUALNUM) { - dasm_put(Dst, 2452); - } - dasm_put(Dst, 2457, (2+1)*8); - if (LJ_DUALNUM) { - dasm_put(Dst, 2461); - } else { - dasm_put(Dst, 2464); - } - dasm_put(Dst, 2466, (2+1)*8); - if (LJ_DUALNUM) { - dasm_put(Dst, 2488); - } else { - dasm_put(Dst, 2557); - } - if (LJ_DUALNUM) { - dasm_put(Dst, 2582); - } else { - dasm_put(Dst, 2651); - } - dasm_put(Dst, 2676, LJ_TSTR, Dt5(->len), LJ_TSTR, Dt5(->len)); - if (LJ_DUALNUM) { - dasm_put(Dst, 2703, Dt5([1]), (0+1)*8); - } else { - dasm_put(Dst, 2715, Dt5([1]), 31-3); - } - dasm_put(Dst, 2731, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - if (LJ_DUALNUM) { - dasm_put(Dst, 2742); - } else { - dasm_put(Dst, 2750); - } - dasm_put(Dst, 2761, Dt1(->base), Dt1(->base), LJ_TSTR, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - if (!LJ_DUALNUM) { - dasm_put(Dst, 2789); - } - dasm_put(Dst, 2791); - if (LJ_DUALNUM) { - dasm_put(Dst, 2797); - } else { - dasm_put(Dst, 2799); - } - dasm_put(Dst, 2801); - if (LJ_DUALNUM) { - dasm_put(Dst, 2805); - } else { - dasm_put(Dst, 2814); - } - dasm_put(Dst, 2825, LJ_TSTR); - if (!LJ_DUALNUM) { - dasm_put(Dst, 2830); - } - dasm_put(Dst, 2834, Dt5(->len), sizeof(GCstr)-1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - if (LJ_DUALNUM) { - dasm_put(Dst, 2884); - } else { - dasm_put(Dst, 2886); - } - dasm_put(Dst, 2888, LJ_TSTR); - if (LJ_DUALNUM) { - dasm_put(Dst, 2895); - } else { - dasm_put(Dst, 2899); - } - dasm_put(Dst, 2906, Dt5(->len), DISPATCH_GL(tmpbuf.sz), Dt5([1]), DISPATCH_GL(tmpbuf.buf), DISPATCH_GL(strempty), LJ_TSTR, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, DISPATCH_GL(tmpbuf.sz)); - dasm_put(Dst, 2959, Dt5(->len), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, DISPATCH_GL(tmpbuf.sz), Dt5(->len), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf)); - dasm_put(Dst, 3017, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, DISPATCH_GL(tmpbuf.sz), Dt5(->len), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf), LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 3086); - } else { - dasm_put(Dst, 3096); - } - dasm_put(Dst, 3109); - if (LJ_DUALNUM) { - dasm_put(Dst, 3115); - } else { - dasm_put(Dst, 3117); - } - dasm_put(Dst, 3119); - if (LJ_DUALNUM) { - dasm_put(Dst, 3123); - } else { - dasm_put(Dst, 3126); - } - dasm_put(Dst, 3132); - if (LJ_DUALNUM) { - dasm_put(Dst, 3137); - } else { - dasm_put(Dst, 3147); - } - dasm_put(Dst, 3160); - if (LJ_DUALNUM) { - dasm_put(Dst, 3166); - } else { - dasm_put(Dst, 3168); - } - dasm_put(Dst, 3170); - if (LJ_DUALNUM) { - dasm_put(Dst, 3174); - } else { - dasm_put(Dst, 3177); - } - dasm_put(Dst, 3183); - if (LJ_DUALNUM) { - dasm_put(Dst, 3188); - } else { - dasm_put(Dst, 3198); - } - dasm_put(Dst, 3211); - if (LJ_DUALNUM) { - dasm_put(Dst, 3217); - } else { - dasm_put(Dst, 3219); - } - dasm_put(Dst, 3221); - if (LJ_DUALNUM) { - dasm_put(Dst, 3225); - } else { - dasm_put(Dst, 3228); - } - dasm_put(Dst, 3234); - if (LJ_DUALNUM) { - dasm_put(Dst, 3239); - } else { - dasm_put(Dst, 3249); - } - dasm_put(Dst, 3262); - if (LJ_DUALNUM) { - dasm_put(Dst, 3269); - } else { - dasm_put(Dst, 3279); - } - dasm_put(Dst, 3292); - if (LJ_DUALNUM) { - dasm_put(Dst, 3296); - } else { - dasm_put(Dst, 3311); - } - dasm_put(Dst, 3332); - if (LJ_DUALNUM) { - dasm_put(Dst, 3337); - } else { - dasm_put(Dst, 3352); - } - dasm_put(Dst, 3373); - if (LJ_DUALNUM) { - dasm_put(Dst, 3378); - } else { - dasm_put(Dst, 3393); - } - dasm_put(Dst, 3414); - if (LJ_DUALNUM) { - dasm_put(Dst, 3419); - } else { - dasm_put(Dst, 3434); - } - dasm_put(Dst, 3455); - if (LJ_DUALNUM) { - dasm_put(Dst, 3459); - } else { - dasm_put(Dst, 3474); - } - dasm_put(Dst, 3495); - if (LJ_DUALNUM) { - dasm_put(Dst, 3500); - } else { - dasm_put(Dst, 3510); - } - if (LJ_DUALNUM) { - dasm_put(Dst, 3523); - } else { - dasm_put(Dst, 3526); - } - dasm_put(Dst, 3532); - if (LJ_DUALNUM) { - dasm_put(Dst, 3540); - } - dasm_put(Dst, 3548); - if (LJ_DUALNUM) { - dasm_put(Dst, 3550); - } - dasm_put(Dst, 3558, Dt8(->f), 8*LUA_MINSTACK, Dt1(->maxstack), Dt1(->base), Dt1(->top), Dt1(->base), 31-3, Dt1(->top), Dt7(->pc), FRAME_TYPE, LUA_MINSTACK); - dasm_put(Dst, 3622, Dt1(->base), Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 3648, DISPATCH_GL(hookmask), HOOK_VMEVENT, DISPATCH_GL(hookcount), HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount)); -#endif - dasm_put(Dst, 3670, DISPATCH_GL(hookmask), HOOK_ACTIVE, GG_DISP2STATIC, DISPATCH_GL(hookmask), DISPATCH_GL(hookcount), HOOK_ACTIVE, 31-LUA_HOOKLINE, DISPATCH_GL(hookcount), Dt1(->base), Dt1(->base)); - dasm_put(Dst, 3717, GG_DISP2STATIC); -#if LJ_HASJIT - dasm_put(Dst, 3735, GG_DISP2J, Dt7(->pc), DISPATCH_J(L), PC2PROTO(framesize), Dt1(->base), 31-3, Dt1(->top)); -#endif - dasm_put(Dst, 3758); -#if LJ_HASJIT - dasm_put(Dst, 3761); -#endif - dasm_put(Dst, 3764); -#if LJ_HASJIT - dasm_put(Dst, 3766); -#endif - dasm_put(Dst, 3769, Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 3792, -(16+32*8+32*4), 16+32*8+2*4, -GG_DISP2G-32768, ~LJ_VMST_EXIT, 16+32*8+32*4, DISPATCH_GL(vmstate), 16+0*8, 16+1*8, 16+2*8, 16+3*8, 16+4*8, 16+5*8, 16+6*8, 16+7*8, 16+32*8+32*4, 16+8*8, 16+9*8, 16+10*8, 16+11*8, 16+32*8+1*4, 16+12*8, 16+13*8); - dasm_put(Dst, 3839, 16+14*8, 16+15*8, 16+16*8, 16+17*8, 16+18*8, 16+19*8, 16+32*8+0*4, 16+20*8, 16+21*8, 16+22*8, 16+23*8, 16+24*8, 16+25*8, 16+26*8, 16+27*8, DISPATCH_GL(jit_L), 16+28*8, 16+29*8, 16+30*8, 16+31*8, DISPATCH_GL(jit_base), 32-2); - dasm_put(Dst, 3888, DISPATCH_J(L), DISPATCH_GL(jit_L), DISPATCH_J(parent), Dt1(->base), GG_DISP2J, DISPATCH_J(exitno), Dt1(->cframe), Dt1(->base)); -#endif - dasm_put(Dst, 3916); -#if LJ_HASJIT - dasm_put(Dst, 3918, -GG_DISP2G-32768, 31-3, Dt7(->pc), DISPATCH_GL(jit_L), PC2PROTO(k), LJ_TISNUM, LJ_TNIL, DISPATCH_GL(vmstate), BC_FUNCF*4); -#endif - dasm_put(Dst, 3975); -#if LJ_HASJIT - dasm_put(Dst, 3983); -#endif - dasm_put(Dst, 3986); -#if LJ_HASJIT - dasm_put(Dst, 4066); -#else - dasm_put(Dst, 4088); -#endif - dasm_put(Dst, 4090); -#if LJ_HASFFI -#define DtE(_V) (int)(ptrdiff_t)&(((CTState *)0)_V) - dasm_put(Dst, 4114, 56+(14-14)*4, 128+(14-14)*8, 56+(15-14)*4, 128+(15-14)*8, 56+(16-14)*4, 128+(16-14)*8, 56+(17-14)*4, 128+(17-14)*8, 56+(18-14)*4, 128+(18-14)*8, 56+(19-14)*4, 128+(19-14)*8, 56+(20-14)*4, 128+(20-14)*8, 56+(21-14)*4, 128+(21-14)*8, 56+(22-14)*4, 128+(22-14)*8, 56+(23-14)*4, 128+(23-14)*8, 56+(24-14)*4, 128+(24-14)*8); - dasm_put(Dst, 4162, 56+(25-14)*4, 128+(25-14)*8, 56+(26-14)*4, 128+(26-14)*8, 56+(27-14)*4, 128+(27-14)*8, 56+(28-14)*4, 128+(28-14)*8, 56+(29-14)*4, 128+(29-14)*8, 56+(30-14)*4, 128+(30-14)*8, 56+(31-14)*4, 128+(31-14)*8, Dt2(->ctype_state), GG_G2DISP, DtE(->cb.slot), DtE(->cb.gpr[0]), DtE(->cb.fpr[0]), DtE(->cb.gpr[1]), DtE(->cb.fpr[1]), DtE(->cb.gpr[2])); - dasm_put(Dst, 4209, DtE(->cb.fpr[2]), DtE(->cb.gpr[3]), DtE(->cb.fpr[3]), DtE(->cb.gpr[4]), DtE(->cb.fpr[4]), DtE(->cb.gpr[5]), DtE(->cb.fpr[5]), DtE(->cb.gpr[6]), DtE(->cb.fpr[6]), DtE(->cb.gpr[7]), DtE(->cb.fpr[7]), 272+8, DtE(->cb.stack), Dt1(->base), LJ_TISNUM, Dt1(->top), LJ_TNIL, ~LJ_VMST_INTERP, DISPATCH_GL(vmstate), Dt7(->pc)); -#endif - dasm_put(Dst, 4273); -#if LJ_HASFFI - dasm_put(Dst, 4275, DISPATCH_GL(ctype_state), Dt1(->base), Dt1(->top), DtE(->L), DtE(->cb.gpr[0]), DtE(->cb.fpr[0]), DtE(->cb.gpr[1])); -#endif - dasm_put(Dst, 4296); -#if LJ_HASFFI -#define DtF(_V) (int)(ptrdiff_t)&(((CCallState *)0)_V) - dasm_put(Dst, 4298, DtF(->spadj), DtF(->nsp), DtF(->nfpr), DtF(->stack), 31-2, DtF(->fpr[0]), DtF(->fpr[1]), DtF(->fpr[2]), DtF(->fpr[3]), DtF(->fpr[4]), DtF(->fpr[5]), DtF(->fpr[6]), DtF(->fpr[7]), DtF(->func), DtF(->gpr[1]), DtF(->gpr[2])); - dasm_put(Dst, 4355, DtF(->gpr[3]), DtF(->gpr[4]), DtF(->gpr[5]), DtF(->gpr[6]), DtF(->gpr[7]), DtF(->gpr[0]), DtF(->gpr[0]), DtF(->fpr[0]), DtF(->gpr[1]), DtF(->gpr[2]), DtF(->gpr[3])); -#endif -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop) -{ - int vk = 0; - dasm_put(Dst, 4387, defop); - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - if (LJ_DUALNUM) { - dasm_put(Dst, 4389, -(BCBIAS_J*4 >> 16)); - if (op == BC_ISLT) { - dasm_put(Dst, 4406); - } else if (op == BC_ISGE) { - dasm_put(Dst, 4409); - } else if (op == BC_ISLE) { - dasm_put(Dst, 4412); - } else { - dasm_put(Dst, 4415); - } - dasm_put(Dst, 4418); - if (op == BC_ISLT) { - dasm_put(Dst, 4457); - } else if (op == BC_ISGE) { - dasm_put(Dst, 4460); - } else if (op == BC_ISLE) { - dasm_put(Dst, 4463); - } else { - dasm_put(Dst, 4467); - } - dasm_put(Dst, 4471); - } else { - dasm_put(Dst, 4474, -(BCBIAS_J*4 >> 16)); - if (op == BC_ISLT) { - dasm_put(Dst, 4491); - } else if (op == BC_ISGE) { - dasm_put(Dst, 4494); - } else if (op == BC_ISLE) { - dasm_put(Dst, 4497); - } else { - dasm_put(Dst, 4501); - } - dasm_put(Dst, 4505); - } - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - if (LJ_DUALNUM) { - dasm_put(Dst, 4518, -(BCBIAS_J*4 >> 16)); - if (vk) { - dasm_put(Dst, 4531); - } else { - dasm_put(Dst, 4534); - } - } else { - dasm_put(Dst, 4537, -(BCBIAS_J*4 >> 16)); - if (vk) { - dasm_put(Dst, 4554); - } else { - dasm_put(Dst, 4558); - } - dasm_put(Dst, 4562); - } - dasm_put(Dst, 4574); - if (!LJ_DUALNUM) { - dasm_put(Dst, 4576); - } - if (LJ_HASFFI) { - dasm_put(Dst, 4579, LJ_TCDATA, LJ_TCDATA); - } - dasm_put(Dst, 4584, ~LJ_TISPRI); - if (LJ_HASFFI) { - dasm_put(Dst, 4589); - } - dasm_put(Dst, 4591, ~LJ_TISTABUD); - if (LJ_HASFFI) { - dasm_put(Dst, 4594); - } - dasm_put(Dst, 4597); - if (vk) { - dasm_put(Dst, 4605); - } else { - dasm_put(Dst, 4610); - } - if (LJ_DUALNUM) { - dasm_put(Dst, 4615); - } else { - dasm_put(Dst, 4630); - } - dasm_put(Dst, 4633, Dt6(->metatable), 1-vk, Dt6(->nomm), 1<> 16)); - if (vk) { - dasm_put(Dst, 4678); - } else { - dasm_put(Dst, 4680); - } - dasm_put(Dst, 4682); - break; - - case BC_ISEQN: case BC_ISNEN: - vk = op == BC_ISEQN; - if (LJ_DUALNUM) { - dasm_put(Dst, 4694, -(BCBIAS_J*4 >> 16)); - if (vk) { - dasm_put(Dst, 4706); - } else { - dasm_put(Dst, 4708); - } - dasm_put(Dst, 4710); - } else { - if (vk) { - dasm_put(Dst, 4717); - } else { - dasm_put(Dst, 4719); - } - dasm_put(Dst, 4721, -(BCBIAS_J*4 >> 16)); - } - if (vk) { - dasm_put(Dst, 4734); - if (!LJ_HASFFI) { - dasm_put(Dst, 4739); - } - } else { - dasm_put(Dst, 4741); - if (!LJ_HASFFI) { - dasm_put(Dst, 4745); - } - dasm_put(Dst, 4747); - } - dasm_put(Dst, 4750); - if (LJ_HASFFI) { - dasm_put(Dst, 4761, LJ_TCDATA); - } - if (LJ_DUALNUM) { - dasm_put(Dst, 4769); - } - break; - - case BC_ISEQP: case BC_ISNEP: - vk = op == BC_ISEQP; - dasm_put(Dst, 4793, 32-3); - if (LJ_HASFFI) { - dasm_put(Dst, 4800, LJ_TCDATA); - } - dasm_put(Dst, 4803); - if (LJ_HASFFI) { - dasm_put(Dst, 4805); - } - dasm_put(Dst, 4808, -(BCBIAS_J*4 >> 16)); - if (vk) { - dasm_put(Dst, 4814); - } else { - dasm_put(Dst, 4816); - } - dasm_put(Dst, 4818); - break; - - /* -- Unary test and copy ops ------------------------------------------- */ - - case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: - dasm_put(Dst, 4830); - if (op == BC_IST || op == BC_ISF) { - dasm_put(Dst, 4834, LJ_TTRUE, -(BCBIAS_J*4 >> 16)); - if (op == BC_IST) { - dasm_put(Dst, 4841); - } else { - dasm_put(Dst, 4843); - } - dasm_put(Dst, 4845); - } else { - dasm_put(Dst, 4847, LJ_TFALSE); - if (op == BC_ISTC) { - dasm_put(Dst, 4852); - } else { - dasm_put(Dst, 4855); - } - dasm_put(Dst, 4858, -(BCBIAS_J*4 >> 16)); - } - dasm_put(Dst, 4865); - break; - - /* -- Unary ops --------------------------------------------------------- */ - - case BC_MOV: - dasm_put(Dst, 4876); - break; - case BC_NOT: - dasm_put(Dst, 4889, LJ_TTRUE); - break; - case BC_UNM: - dasm_put(Dst, 4905); - if (LJ_DUALNUM) { - dasm_put(Dst, 4909); - } - dasm_put(Dst, 4937); - if (LJ_DUALNUM) { - dasm_put(Dst, 4947); - } else { - dasm_put(Dst, 4950); - } - break; - case BC_LEN: - dasm_put(Dst, 4959, LJ_TSTR, Dt5(->len)); - if (LJ_DUALNUM) { - dasm_put(Dst, 4969); - } else { - dasm_put(Dst, 4974); - } - dasm_put(Dst, 4981, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 4995, Dt6(->metatable)); -#endif - dasm_put(Dst, 5002); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 5008, Dt6(->nomm), 1<base), 32-3, Dt1(->base)); - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - dasm_put(Dst, 5811, 32-1, LJ_TSTR); - break; - case BC_KCDATA: -#if LJ_HASFFI - dasm_put(Dst, 5830, 32-1, LJ_TCDATA); -#endif - break; - case BC_KSHORT: - if (LJ_DUALNUM) { - dasm_put(Dst, 5849, 31-13); - } else { - dasm_put(Dst, 5865, 31-13, 31-20); - } - break; - case BC_KNUM: - dasm_put(Dst, 5893); - break; - case BC_KPRI: - dasm_put(Dst, 5906, 32-3); - break; - case BC_KNIL: - dasm_put(Dst, 5921); - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - dasm_put(Dst, 5940, 32-1, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_USETV: - dasm_put(Dst, 5961, 32-1, offsetof(GCfuncL, uvptr), DtA(->marked), DtA(->v), LJ_GC_BLACK, DtA(->closed), -(LJ_TISNUM+1), LJ_TISGCV - (LJ_TISNUM+1), Dt4(->gch.marked), LJ_GC_WHITES, GG_DISP2G); - break; - case BC_USETS: - dasm_put(Dst, 6014, 32-1, 32-1, offsetof(GCfuncL, uvptr), DtA(->marked), DtA(->v), LJ_GC_BLACK, Dt5(->marked), DtA(->closed), LJ_TSTR, LJ_GC_WHITES, GG_DISP2G); - break; - case BC_USETN: - dasm_put(Dst, 6065, 32-1, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_USETP: - dasm_put(Dst, 6086, 32-1, 32-3, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - - case BC_UCLO: - dasm_put(Dst, 6109, Dt1(->openupval), 32-1, -(BCBIAS_J*4 >> 16), Dt1(->base), Dt1(->base)); - break; - - case BC_FNEW: - dasm_put(Dst, 6139, 32-1, Dt1(->base), Dt1(->base), LJ_TFUNC); - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - case BC_TDUP: - dasm_put(Dst, 6167, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base)); - if (op == BC_TNEW) { - dasm_put(Dst, 6180); - } else { - dasm_put(Dst, 6189, 32-1); - } - dasm_put(Dst, 6196, Dt1(->base), LJ_TTAB); - if (op == BC_TNEW) { - dasm_put(Dst, 6213); - } - dasm_put(Dst, 6218); - break; - - case BC_GGET: - case BC_GSET: - dasm_put(Dst, 6227, 32-1, Dt7(->env)); - if (op == BC_GGET) { - dasm_put(Dst, 6235); - } else { - dasm_put(Dst, 6238); - } - break; - - case BC_TGETV: - dasm_put(Dst, 6241); - if (LJ_DUALNUM) { - dasm_put(Dst, 6245); - } else { - dasm_put(Dst, 6247); - } - dasm_put(Dst, 6249, LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 6255, Dt6(->asize), Dt6(->array), 31-3); - } else { - dasm_put(Dst, 6265, Dt6(->asize), Dt6(->array), 31-3); - } - dasm_put(Dst, 6282, LJ_TNIL, Dt6(->metatable), Dt6(->nomm), 1<hmask), Dt5(->hash), Dt6(->node), 31-5, 31-3, DtB(->key), 4+offsetof(Node, key), DtB(->val), 4+offsetof(Node, val), LJ_TSTR, LJ_TNIL, DtB(->next)); - dasm_put(Dst, 6388, LJ_TNIL, Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), LJ_TNIL, Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), 31-3); - } else { - dasm_put(Dst, 6480, Dt6(->asize), Dt6(->array), 31-3); - } - dasm_put(Dst, 6497, Dt6(->marked), LJ_TNIL, LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<marked), Dt6(->gclist)); - break; - case BC_TSETS: - dasm_put(Dst, 6561, 32-1, LJ_TTAB, Dt6(->hmask), Dt5(->hash), Dt6(->node), Dt6(->nomm), 31-5, 31-3, Dt6(->marked), DtB(->key), 4+offsetof(Node, key), DtB(->val), DtB(->next), LJ_TSTR, LJ_TNIL); - dasm_put(Dst, 6612, LJ_GC_BLACK, DtB(->val), Dt6(->metatable), Dt6(->nomm), 1<metatable), DISPATCH_GL(tmptv), Dt1(->base), Dt6(->nomm), 1<base), DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist)); - break; - case BC_TSETB: - dasm_put(Dst, 6692, 32-3, LJ_TTAB, Dt6(->asize), Dt6(->array), Dt6(->marked), LJ_TNIL, LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<marked), Dt6(->gclist)); - break; - - case BC_TSETM: - dasm_put(Dst, 6760, 32-3, Dt6(->asize), 31-3, Dt6(->marked), Dt6(->array), LJ_GC_BLACK, Dt1(->base), DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist)); - dasm_put(Dst, 6829); - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALLM: - dasm_put(Dst, 6832); - break; - case BC_CALL: - dasm_put(Dst, 6834, LJ_TFUNC, Dt7(->pc)); - break; - - case BC_CALLMT: - dasm_put(Dst, 6855); - break; - case BC_CALLT: - dasm_put(Dst, 6857, LJ_TFUNC, FRAME_TYPE, Dt7(->ffid), FRAME_VARG, Dt7(->pc), -4-8, Dt7(->pc), PC2PROTO(k), FRAME_TYPEP); - dasm_put(Dst, 6921, FRAME_TYPE); - break; - - case BC_ITERC: - dasm_put(Dst, 6930, LJ_TFUNC, Dt7(->pc)); - break; - - case BC_ITERN: -#if LJ_HASJIT -#endif - dasm_put(Dst, 6957, Dt6(->asize), Dt6(->array), 31-3, LJ_TNIL); - if (LJ_DUALNUM) { - dasm_put(Dst, 6979); - } else { - dasm_put(Dst, 6982); - } - dasm_put(Dst, 6986, -(BCBIAS_J*4 >> 16)); - if (!LJ_DUALNUM) { - dasm_put(Dst, 6994); - } - dasm_put(Dst, 6996, Dt6(->hmask), Dt6(->node), 31-5, 31-3, LJ_TNIL, DtB(->key), -(BCBIAS_J*4 >> 16)); - break; - - case BC_ISNEXT: - dasm_put(Dst, 7052, LJ_TTAB, LJ_TFUNC, LJ_TNIL, Dt8(->ffid), FF_next_N, 32-1, -(BCBIAS_J*4 >> 16), BC_JMP, BC_ITERC, -(BCBIAS_J*4 >> 16)); - break; - - case BC_VARG: - dasm_put(Dst, 7102, FRAME_VARG, Dt1(->maxstack), Dt1(->top), Dt1(->base), 32-3, Dt1(->base)); - dasm_put(Dst, 7182); - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - dasm_put(Dst, 7188); - break; - - case BC_RET: - dasm_put(Dst, 7190, FRAME_TYPE, FRAME_VARG, Dt7(->pc), PC2PROTO(k), FRAME_TYPEP); - break; - - case BC_RET0: case BC_RET1: - dasm_put(Dst, 7260, FRAME_TYPE, FRAME_VARG); - if (op == BC_RET1) { - dasm_put(Dst, 7273); - } - dasm_put(Dst, 7276, Dt7(->pc), PC2PROTO(k)); - break; - - /* -- Loops and branches ------------------------------------------------ */ - - case BC_FORL: -#if LJ_HASJIT - dasm_put(Dst, 7304, GG_DISP2HOT, -HOTCOUNT_LOOP); -#endif - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - vk = (op == BC_IFORL || op == BC_JFORL); - if (LJ_DUALNUM) { - dasm_put(Dst, 7314, FORL_IDX*8+4); - if (vk) { - dasm_put(Dst, 7319, FORL_STEP*8+4, FORL_STOP*8+4, FORL_IDX*8+4); - } else { - dasm_put(Dst, 7333, FORL_STEP*8, FORL_STEP*8+4, FORL_STOP*8, FORL_STOP*8+4); - } - dasm_put(Dst, 7349, FORL_EXT*8); - if (op != BC_JFORL) { - dasm_put(Dst, 7356, 32-1); - } - dasm_put(Dst, 7359, FORL_EXT*8+4); - if (op != BC_JFORL) { - dasm_put(Dst, 7362); - } - if (op == BC_FORI) { - dasm_put(Dst, 7364); - } else if (op == BC_JFORI) { - dasm_put(Dst, 7367, -(BCBIAS_J*4 >> 16)); - } else if (op == BC_IFORL) { - dasm_put(Dst, 7372, -(BCBIAS_J*4 >> 16)); - } else { - dasm_put(Dst, 7377, BC_JLOOP); - } - dasm_put(Dst, 7380); - if (vk) { - dasm_put(Dst, 7396); - } - } - if (vk) { - if (LJ_DUALNUM) { - dasm_put(Dst, 7403, FORL_IDX*8); - } else { - dasm_put(Dst, 7407); - } - dasm_put(Dst, 7409, FORL_STEP*8, FORL_STOP*8, FORL_STEP*8, FORL_IDX*8); - } else { - if (LJ_DUALNUM) { - dasm_put(Dst, 7419); - } else { - dasm_put(Dst, 7421, FORL_STEP*8, FORL_STOP*8); - } - dasm_put(Dst, 7430, FORL_IDX*8, FORL_STOP*8); - } - dasm_put(Dst, 7439); - if (op != BC_JFORL) { - dasm_put(Dst, 7441, 32-1); - } - dasm_put(Dst, 7444, FORL_EXT*8); - if (op != BC_JFORL) { - dasm_put(Dst, 7447); - } - dasm_put(Dst, 7449); - if (op == BC_JFORI) { - dasm_put(Dst, 7451, -(BCBIAS_J*4 >> 16)); - } - dasm_put(Dst, 7454); - if (op == BC_FORI) { - dasm_put(Dst, 7457); - } else if (op == BC_IFORL) { - if (LJ_DUALNUM) { - dasm_put(Dst, 7460); - } else { - dasm_put(Dst, 7463); - } - dasm_put(Dst, 7466, -(BCBIAS_J*4 >> 16)); - } else if (op == BC_JFORI) { - dasm_put(Dst, 7470); - } else { - dasm_put(Dst, 7473, BC_JLOOP); - } - if (LJ_DUALNUM) { - dasm_put(Dst, 7476); - } else { - dasm_put(Dst, 7479); - } - dasm_put(Dst, 7491); - if (op == BC_FORI) { - dasm_put(Dst, 7493, -(BCBIAS_J*4 >> 16)); - } else if (op == BC_IFORL) { - dasm_put(Dst, 7499); - } else if (op == BC_JFORI) { - dasm_put(Dst, 7502); - } else { - dasm_put(Dst, 7505, BC_JLOOP); - } - dasm_put(Dst, 7508); - if (op == BC_JFORI) { - dasm_put(Dst, 7511, BC_JLOOP); - } - break; - - case BC_ITERL: -#if LJ_HASJIT - dasm_put(Dst, 7517, GG_DISP2HOT, -HOTCOUNT_LOOP); -#endif - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - dasm_put(Dst, 7527, LJ_TNIL); - if (op == BC_JITERL) { - dasm_put(Dst, 7534, BC_JLOOP); - } else { - dasm_put(Dst, 7539, 32-1, -(BCBIAS_J*4 >> 16)); - } - dasm_put(Dst, 7547); - break; - - case BC_LOOP: -#if LJ_HASJIT - dasm_put(Dst, 7559, GG_DISP2HOT, -HOTCOUNT_LOOP); -#endif - break; - - case BC_ILOOP: - dasm_put(Dst, 7569); - break; - - case BC_JLOOP: -#if LJ_HASJIT - dasm_put(Dst, 7580, DISPATCH_J(trace), 32-1, DISPATCH_GL(vmstate), DtD(->mcode), DISPATCH_GL(jit_base), DISPATCH_GL(jit_L), GG_DISP2G+32768); -#endif - break; - - case BC_JMP: - dasm_put(Dst, 7599, 32-1, -(BCBIAS_J*4 >> 16)); - break; - - /* -- Function headers -------------------------------------------------- */ - - case BC_FUNCF: -#if LJ_HASJIT - dasm_put(Dst, 7615, GG_DISP2HOT, -HOTCOUNT_CALL); -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - dasm_put(Dst, 7625, Dt1(->maxstack), -4+PC2PROTO(numparams), -4+PC2PROTO(k), 31-3); - if (op != BC_JFUNCF) { - dasm_put(Dst, 7637); - } - dasm_put(Dst, 7640); - if (op == BC_JFUNCF) { - dasm_put(Dst, 7645, BC_JLOOP); - } else { - dasm_put(Dst, 7649); - } - dasm_put(Dst, 7658); - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - dasm_put(Dst, 7664); - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - dasm_put(Dst, 7666, Dt1(->maxstack), 8+FRAME_VARG, -4+PC2PROTO(k), -4+PC2PROTO(numparams), LJ_TNIL); - break; - - case BC_FUNCC: - case BC_FUNCCW: - if (op == BC_FUNCC) { - dasm_put(Dst, 7719, Dt8(->f)); - } else { - dasm_put(Dst, 7722, DISPATCH_GL(wrapf)); - } - dasm_put(Dst, 7725, Dt1(->maxstack), Dt1(->base), Dt1(->top), ~LJ_VMST_C); - if (op == BC_FUNCCW) { - dasm_put(Dst, 7738, Dt8(->f)); - } - dasm_put(Dst, 7741, DISPATCH_GL(vmstate), Dt1(->base), 31-3, Dt1(->top), ~LJ_VMST_INTERP, DISPATCH_GL(vmstate)); - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx); - - dasm_put(Dst, 7762); - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); - int i; - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.long .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.long 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 65\n" - "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.long .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.long .Lframe0\n" - "\t.long .Lbegin\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x5\n\t.uleb128 70\n\t.uleb128 55\n", - fcofs, CFRAME_SIZE); - for (i = 14; i <= 31; i++) - fprintf(ctx->fp, - "\t.byte %d\n\t.uleb128 %d\n" - "\t.byte %d\n\t.uleb128 %d\n", - 0x80+i, 37+(31-i), 0x80+32+i, 2+2*(31-i)); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE0:\n\n"); -#if LJ_HASFFI - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.long .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.long .Lframe0\n" - "\t.long lj_vm_ffi_call\n" - "\t.long %d\n" - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x8e\n\t.uleb128 2\n" - "\t.byte 0xd\n\t.uleb128 0xe\n" - "\t.align 2\n" - ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); -#endif - fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe1:\n" - "\t.long .LECIE1-.LSCIE1\n" - ".LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zPR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 65\n" - "\t.uleb128 6\n" /* augmentation length */ - "\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 1\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE1:\n\n"); - fprintf(ctx->fp, - ".LSFDE2:\n" - "\t.long .LEFDE2-.LASFDE2\n" - ".LASFDE2:\n" - "\t.long .LASFDE2-.Lframe1\n" - "\t.long .Lbegin-.\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x5\n\t.uleb128 70\n\t.uleb128 55\n", - fcofs, CFRAME_SIZE); - for (i = 14; i <= 31; i++) - fprintf(ctx->fp, - "\t.byte %d\n\t.uleb128 %d\n" - "\t.byte %d\n\t.uleb128 %d\n", - 0x80+i, 37+(31-i), 0x80+32+i, 2+2*(31-i)); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE2:\n\n"); -#if LJ_HASFFI - fprintf(ctx->fp, - ".Lframe2:\n" - "\t.long .LECIE2-.LSCIE2\n" - ".LSCIE2:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 65\n" - "\t.uleb128 1\n" /* augmentation length */ - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE2:\n\n"); - fprintf(ctx->fp, - ".LSFDE3:\n" - "\t.long .LEFDE3-.LASFDE3\n" - ".LASFDE3:\n" - "\t.long .LASFDE3-.Lframe2\n" - "\t.long lj_vm_ffi_call-.\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x8e\n\t.uleb128 2\n" - "\t.byte 0xd\n\t.uleb128 0xe\n" - "\t.align 2\n" - ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); -#endif - break; - default: - break; - } -} - diff --git a/src/buildvm_ppcspe.dasc b/src/buildvm_ppcspe.dasc deleted file mode 100644 index a7ef3ccd..00000000 --- a/src/buildvm_ppcspe.dasc +++ /dev/null @@ -1,3705 +0,0 @@ -|// Low-level VM code for PowerPC/e500 CPUs. -|// Bytecode interpreter, fast functions and helper functions. -|// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -| -|.arch ppc -|.section code_op, code_sub -| -|.actionlist build_actionlist -|.globals GLOB_ -|.globalnames globnames -|.externnames extnames -| -|// Note: The ragged indentation of the instructions is intentional. -|// The starting columns indicate data dependencies. -| -|//----------------------------------------------------------------------- -| -|// Fixed register assignments for the interpreter. -|// Don't use: r1 = sp, r2 and r13 = reserved and/or small data area ptr -| -|// The following must be C callee-save (but BASE is often refetched). -|.define BASE, r14 // Base of current Lua stack frame. -|.define KBASE, r15 // Constants of current Lua function. -|.define PC, r16 // Next PC. -|.define DISPATCH, r17 // Opcode dispatch table. -|.define LREG, r18 // Register holding lua_State (also in SAVE_L). -|.define MULTRES, r19 // Size of multi-result: (nresults+1)*8. -| -|// Constants for vectorized type-comparisons (hi+low GPR). C callee-save. -|.define TISNUM, r22 -|.define TISSTR, r23 -|.define TISTAB, r24 -|.define TISFUNC, r25 -|.define TISNIL, r26 -|.define TOBIT, r27 -|.define ZERO, TOBIT // Zero in lo word. -| -|// The following temporaries are not saved across C calls, except for RA. -|.define RA, r20 // Callee-save. -|.define RB, r10 -|.define RC, r11 -|.define RD, r12 -|.define INS, r7 // Overlaps CARG5. -| -|.define TMP0, r0 -|.define TMP1, r8 -|.define TMP2, r9 -|.define TMP3, r6 // Overlaps CARG4. -| -|// Saved temporaries. -|.define SAVE0, r21 -| -|// Calling conventions. -|.define CARG1, r3 -|.define CARG2, r4 -|.define CARG3, r5 -|.define CARG4, r6 // Overlaps TMP3. -|.define CARG5, r7 // Overlaps INS. -| -|.define CRET1, r3 -|.define CRET2, r4 -| -|// Stack layout while in interpreter. Must match with lj_frame.h. -|.define SAVE_LR, 188(sp) -|.define CFRAME_SPACE, 184 // Delta for sp. -|// Back chain for sp: 184(sp) <-- sp entering interpreter -|.define SAVE_r31, 176(sp) // 64 bit register saves. -|.define SAVE_r30, 168(sp) -|.define SAVE_r29, 160(sp) -|.define SAVE_r28, 152(sp) -|.define SAVE_r27, 144(sp) -|.define SAVE_r26, 136(sp) -|.define SAVE_r25, 128(sp) -|.define SAVE_r24, 120(sp) -|.define SAVE_r23, 112(sp) -|.define SAVE_r22, 104(sp) -|.define SAVE_r21, 96(sp) -|.define SAVE_r20, 88(sp) -|.define SAVE_r19, 80(sp) -|.define SAVE_r18, 72(sp) -|.define SAVE_r17, 64(sp) -|.define SAVE_r16, 56(sp) -|.define SAVE_r15, 48(sp) -|.define SAVE_r14, 40(sp) -|.define SAVE_CR, 36(sp) -|.define UNUSED1, 32(sp) -|.define SAVE_ERRF, 28(sp) // 32 bit C frame info. -|.define SAVE_NRES, 24(sp) -|.define SAVE_CFRAME, 20(sp) -|.define SAVE_L, 16(sp) -|.define SAVE_PC, 12(sp) -|.define SAVE_MULTRES, 8(sp) -|// Next frame lr: 4(sp) -|// Back chain for sp: 0(sp) <-- sp while in interpreter -| -|.macro save_, reg; evstdd reg, SAVE_..reg; .endmacro -|.macro rest_, reg; evldd reg, SAVE_..reg; .endmacro -| -|.macro saveregs -| stwu sp, -CFRAME_SPACE(sp) -| save_ r14; save_ r15; save_ r16; save_ r17; save_ r18; save_ r19 -| mflr r0; mfcr r12 -| save_ r20; save_ r21; save_ r22; save_ r23; save_ r24; save_ r25 -| stw r0, SAVE_LR; stw r12, SAVE_CR -| save_ r26; save_ r27; save_ r28; save_ r29; save_ r30; save_ r31 -|.endmacro -| -|.macro restoreregs -| lwz r0, SAVE_LR; lwz r12, SAVE_CR -| rest_ r14; rest_ r15; rest_ r16; rest_ r17; rest_ r18; rest_ r19 -| mtlr r0; mtcrf 0x38, r12 -| rest_ r20; rest_ r21; rest_ r22; rest_ r23; rest_ r24; rest_ r25 -| rest_ r26; rest_ r27; rest_ r28; rest_ r29; rest_ r30; rest_ r31 -| addi sp, sp, CFRAME_SPACE -|.endmacro -| -|// Type definitions. Some of these are only used for documentation. -|.type L, lua_State, LREG -|.type GL, global_State -|.type TVALUE, TValue -|.type GCOBJ, GCobj -|.type STR, GCstr -|.type TAB, GCtab -|.type LFUNC, GCfuncL -|.type CFUNC, GCfuncC -|.type PROTO, GCproto -|.type UPVAL, GCupval -|.type NODE, Node -|.type NARGS8, int -|.type TRACE, GCtrace -| -|//----------------------------------------------------------------------- -| -|// These basic macros should really be part of DynASM. -|.macro srwi, rx, ry, n; rlwinm rx, ry, 32-n, n, 31; .endmacro -|.macro slwi, rx, ry, n; rlwinm rx, ry, n, 0, 31-n; .endmacro -|.macro rotlwi, rx, ry, n; rlwinm rx, ry, n, 0, 31; .endmacro -|.macro rotlw, rx, ry, rn; rlwnm rx, ry, rn, 0, 31; .endmacro -|.macro subi, rx, ry, i; addi rx, ry, -i; .endmacro -| -|// Trap for not-yet-implemented parts. -|.macro NYI; tw 4, sp, sp; .endmacro -| -|//----------------------------------------------------------------------- -| -|// Access to frame relative to BASE. -|.define FRAME_PC, -8 -|.define FRAME_FUNC, -4 -| -|// Instruction decode. -|.macro decode_OP4, dst, ins; rlwinm dst, ins, 2, 22, 29; .endmacro -|.macro decode_RA8, dst, ins; rlwinm dst, ins, 27, 21, 28; .endmacro -|.macro decode_RB8, dst, ins; rlwinm dst, ins, 11, 21, 28; .endmacro -|.macro decode_RC8, dst, ins; rlwinm dst, ins, 19, 21, 28; .endmacro -|.macro decode_RD8, dst, ins; rlwinm dst, ins, 19, 13, 28; .endmacro -| -|.macro decode_OP1, dst, ins; rlwinm dst, ins, 0, 24, 31; .endmacro -|.macro decode_RD4, dst, ins; rlwinm dst, ins, 18, 14, 29; .endmacro -| -|// Instruction fetch. -|.macro ins_NEXT1 -| lwz INS, 0(PC) -| addi PC, PC, 4 -|.endmacro -|// Instruction decode+dispatch. -|.macro ins_NEXT2 -| decode_OP4 TMP1, INS -| decode_RB8 RB, INS -| decode_RD8 RD, INS -| lwzx TMP0, DISPATCH, TMP1 -| decode_RA8 RA, INS -| decode_RC8 RC, INS -| mtctr TMP0 -| bctr -|.endmacro -|.macro ins_NEXT -| ins_NEXT1 -| ins_NEXT2 -|.endmacro -| -|// Instruction footer. -|.if 1 -| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use. -| .define ins_next, ins_NEXT -| .define ins_next_, ins_NEXT -| .define ins_next1, ins_NEXT1 -| .define ins_next2, ins_NEXT2 -|.else -| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch. -| // Affects only certain kinds of benchmarks (and only with -j off). -| .macro ins_next -| b ->ins_next -| .endmacro -| .macro ins_next1 -| .endmacro -| .macro ins_next2 -| b ->ins_next -| .endmacro -| .macro ins_next_ -| ->ins_next: -| ins_NEXT -| .endmacro -|.endif -| -|// Call decode and dispatch. -|.macro ins_callt -| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC -| lwz PC, LFUNC:RB->pc -| lwz INS, 0(PC) -| addi PC, PC, 4 -| decode_OP4 TMP1, INS -| decode_RA8 RA, INS -| lwzx TMP0, DISPATCH, TMP1 -| add RA, RA, BASE -| mtctr TMP0 -| bctr -|.endmacro -| -|.macro ins_call -| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, PC = caller PC -| stw PC, FRAME_PC(BASE) -| ins_callt -|.endmacro -| -|//----------------------------------------------------------------------- -| -|// Macros to test operand types. -|.macro checknum, reg; evcmpltu reg, TISNUM; .endmacro -|.macro checkstr, reg; evcmpeq reg, TISSTR; .endmacro -|.macro checktab, reg; evcmpeq reg, TISTAB; .endmacro -|.macro checkfunc, reg; evcmpeq reg, TISFUNC; .endmacro -|.macro checknil, reg; evcmpeq reg, TISNIL; .endmacro -|.macro checkok, label; blt label; .endmacro -|.macro checkfail, label; bge label; .endmacro -|.macro checkanyfail, label; bns label; .endmacro -|.macro checkallok, label; bso label; .endmacro -| -|.macro branch_RD -| srwi TMP0, RD, 1 -| add PC, PC, TMP0 -| addis PC, PC, -(BCBIAS_J*4 >> 16) -|.endmacro -| -|// Assumes DISPATCH is relative to GL. -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -| -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) -| -|.macro hotloop -| NYI -|.endmacro -| -|.macro hotcall -| NYI -|.endmacro -| -|// Set current VM state. Uses TMP0. -|.macro li_vmstate, st; li TMP0, ~LJ_VMST_..st; .endmacro -|.macro st_vmstate; stw TMP0, DISPATCH_GL(vmstate)(DISPATCH); .endmacro -| -|// Move table write barrier back. Overwrites mark and tmp. -|.macro barrierback, tab, mark, tmp -| lwz tmp, DISPATCH_GL(gc.grayagain)(DISPATCH) -| // Assumes LJ_GC_BLACK is 0x04. -| rlwinm mark, mark, 0, 30, 28 // black2gray(tab) -| stw tab, DISPATCH_GL(gc.grayagain)(DISPATCH) -| stb mark, tab->marked -| stw tmp, tab->gclist -|.endmacro -| -|//----------------------------------------------------------------------- - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx) -{ - |.code_sub - | - |//----------------------------------------------------------------------- - |//-- Return handling ---------------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_returnp: - | // See vm_return. Also: TMP2 = previous base. - | andi. TMP0, PC, FRAME_P - | evsplati TMP1, LJ_TTRUE - | beq ->cont_dispatch - | - | // Return from pcall or xpcall fast func. - | lwz PC, FRAME_PC(TMP2) // Fetch PC of previous frame. - | mr BASE, TMP2 // Restore caller base. - | // Prepending may overwrite the pcall frame, so do it at the end. - | stwu TMP1, FRAME_PC(RA) // Prepend true to results. - | - |->vm_returnc: - | andi. TMP0, PC, FRAME_TYPE - | addi RD, RD, 8 // RD = (nresults+1)*8. - | mr MULTRES, RD - | beq ->BC_RET_Z // Handle regular return to Lua. - | - |->vm_return: - | // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return - | // TMP0 = PC & FRAME_TYPE - | cmpwi TMP0, FRAME_C - | rlwinm TMP2, PC, 0, 0, 28 - | li_vmstate C - | sub TMP2, BASE, TMP2 // TMP2 = previous base. - | bne ->vm_returnp - | - | addic. TMP1, RD, -8 - | stw TMP2, L->base - | lwz TMP2, SAVE_NRES - | subi BASE, BASE, 8 - | st_vmstate - | slwi TMP2, TMP2, 3 - | beq >2 - |1: - | addic. TMP1, TMP1, -8 - | evldd TMP0, 0(RA) - | addi RA, RA, 8 - | evstdd TMP0, 0(BASE) - | addi BASE, BASE, 8 - | bne <1 - | - |2: - | cmpw TMP2, RD // More/less results wanted? - | bne >6 - |3: - | stw BASE, L->top // Store new top. - | - |->vm_leave_cp: - | lwz TMP0, SAVE_CFRAME // Restore previous C frame. - | li CRET1, 0 // Ok return status for vm_pcall. - | stw TMP0, L->cframe - | - |->vm_leave_unw: - | restoreregs - | blr - | - |6: - | ble >7 // Less results wanted? - | // More results wanted. Check stack size and fill up results with nil. - | lwz TMP1, L->maxstack - | cmplw BASE, TMP1 - | bge >8 - | evstdd TISNIL, 0(BASE) - | addi RD, RD, 8 - | addi BASE, BASE, 8 - | b <2 - | - |7: // Less results wanted. - | sub TMP0, RD, TMP2 - | cmpwi TMP2, 0 // LUA_MULTRET+1 case? - | sub TMP0, BASE, TMP0 // Subtract the difference. - | iseleq BASE, BASE, TMP0 // Either keep top or shrink it. - | b <3 - | - |8: // Corner case: need to grow stack for filling up results. - | // This can happen if: - | // - A C function grows the stack (a lot). - | // - The GC shrinks the stack in between. - | // - A return back from a lua_call() with (high) nresults adjustment. - | stw BASE, L->top // Save current top held in BASE (yes). - | mr SAVE0, RD - | mr CARG2, TMP2 - | mr CARG1, L - | bl extern lj_state_growstack // (lua_State *L, int n) - | lwz TMP2, SAVE_NRES - | mr RD, SAVE0 - | slwi TMP2, TMP2, 3 - | lwz BASE, L->top // Need the (realloced) L->top in BASE. - | b <2 - | - |->vm_unwind_c: // Unwind C stack, return from vm_pcall. - | // (void *cframe, int errcode) - | mr sp, CARG1 - | mr CRET1, CARG2 - |->vm_unwind_c_eh: // Landing pad for external unwinder. - | lwz L, SAVE_L - | li TMP0, ~LJ_VMST_C - | lwz GL:TMP1, L->glref - | stw TMP0, GL:TMP1->vmstate - | b ->vm_leave_unw - | - |->vm_unwind_ff: // Unwind C stack, return from ff pcall. - | // (void *cframe) - | rlwinm sp, CARG1, 0, 0, 29 - |->vm_unwind_ff_eh: // Landing pad for external unwinder. - | lwz L, SAVE_L - | evsplati TISNUM, LJ_TISNUM+1 // Setup type comparison constants. - | evsplati TISFUNC, LJ_TFUNC - | lus TOBIT, 0x4338 - | evsplati TISTAB, LJ_TTAB - | li TMP0, 0 - | lwz BASE, L->base - | evmergelo TOBIT, TOBIT, TMP0 - | lwz DISPATCH, L->glref // Setup pointer to dispatch table. - | evsplati TISSTR, LJ_TSTR - | li TMP1, LJ_TFALSE - | evsplati TISNIL, LJ_TNIL - | li_vmstate INTERP - | lwz PC, FRAME_PC(BASE) // Fetch PC of previous frame. - | la RA, -8(BASE) // Results start at BASE-8. - | addi DISPATCH, DISPATCH, GG_G2DISP - | stw TMP1, 0(RA) // Prepend false to error message. - | li RD, 16 // 2 results: false + error message. - | st_vmstate - | b ->vm_returnc - | - |//----------------------------------------------------------------------- - |//-- Grow stack for calls ----------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_growstack_c: // Grow stack for C function. - | li CARG2, LUA_MINSTACK - | b >2 - | - |->vm_growstack_l: // Grow stack for Lua function. - | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC - | add RC, BASE, RC - | sub RA, RA, BASE - | stw BASE, L->base - | addi PC, PC, 4 // Must point after first instruction. - | stw RC, L->top - | srwi CARG2, RA, 3 - |2: - | // L->base = new base, L->top = top - | stw PC, SAVE_PC - | mr CARG1, L - | bl extern lj_state_growstack // (lua_State *L, int n) - | lwz BASE, L->base - | lwz RC, L->top - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | sub RC, RC, BASE - | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC - | ins_callt // Just retry the call. - | - |//----------------------------------------------------------------------- - |//-- Entry points into the assembler VM --------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_resume: // Setup C frame and resume thread. - | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0) - | saveregs - | mr L, CARG1 - | lwz DISPATCH, L->glref // Setup pointer to dispatch table. - | mr BASE, CARG2 - | lbz TMP1, L->status - | stw L, SAVE_L - | li PC, FRAME_CP - | addi TMP0, sp, CFRAME_RESUME - | addi DISPATCH, DISPATCH, GG_G2DISP - | stw CARG3, SAVE_NRES - | cmplwi TMP1, 0 - | stw CARG3, SAVE_ERRF - | stw TMP0, L->cframe - | stw CARG3, SAVE_CFRAME - | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. - | beq >3 - | - | // Resume after yield (like a return). - | mr RA, BASE - | lwz BASE, L->base - | evsplati TISNUM, LJ_TISNUM+1 // Setup type comparison constants. - | lwz TMP1, L->top - | evsplati TISFUNC, LJ_TFUNC - | lus TOBIT, 0x4338 - | evsplati TISTAB, LJ_TTAB - | lwz PC, FRAME_PC(BASE) - | li TMP2, 0 - | evsplati TISSTR, LJ_TSTR - | sub RD, TMP1, BASE - | evmergelo TOBIT, TOBIT, TMP2 - | stb CARG3, L->status - | andi. TMP0, PC, FRAME_TYPE - | li_vmstate INTERP - | addi RD, RD, 8 - | evsplati TISNIL, LJ_TNIL - | mr MULTRES, RD - | st_vmstate - | beq ->BC_RET_Z - | b ->vm_return - | - |->vm_pcall: // Setup protected C frame and enter VM. - | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef) - | saveregs - | li PC, FRAME_CP - | stw CARG4, SAVE_ERRF - | b >1 - | - |->vm_call: // Setup C frame and enter VM. - | // (lua_State *L, TValue *base, int nres1) - | saveregs - | li PC, FRAME_C - | - |1: // Entry point for vm_pcall above (PC = ftype). - | lwz TMP1, L:CARG1->cframe - | stw CARG3, SAVE_NRES - | mr L, CARG1 - | stw CARG1, SAVE_L - | mr BASE, CARG2 - | stw sp, L->cframe // Add our C frame to cframe chain. - | lwz DISPATCH, L->glref // Setup pointer to dispatch table. - | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. - | stw TMP1, SAVE_CFRAME - | addi DISPATCH, DISPATCH, GG_G2DISP - | - |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype). - | lwz TMP2, L->base // TMP2 = old base (used in vmeta_call). - | evsplati TISNUM, LJ_TISNUM+1 // Setup type comparison constants. - | lwz TMP1, L->top - | evsplati TISFUNC, LJ_TFUNC - | add PC, PC, BASE - | evsplati TISTAB, LJ_TTAB - | lus TOBIT, 0x4338 - | li TMP0, 0 - | sub PC, PC, TMP2 // PC = frame delta + frame type - | evsplati TISSTR, LJ_TSTR - | sub NARGS8:RC, TMP1, BASE - | evmergelo TOBIT, TOBIT, TMP0 - | li_vmstate INTERP - | evsplati TISNIL, LJ_TNIL - | st_vmstate - | - |->vm_call_dispatch: - | // TMP2 = old base, BASE = new base, RC = nargs*8, PC = caller PC - | li TMP0, -8 - | evlddx LFUNC:RB, BASE, TMP0 - | checkfunc LFUNC:RB - | checkfail ->vmeta_call - | - |->vm_call_dispatch_f: - | ins_call - | // BASE = new base, RB = func, RC = nargs*8, PC = caller PC - | - |->vm_cpcall: // Setup protected C frame, call C. - | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp) - | saveregs - | mr L, CARG1 - | lwz TMP0, L:CARG1->stack - | stw CARG1, SAVE_L - | lwz TMP1, L->top - | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. - | sub TMP0, TMP0, TMP1 // Compute -savestack(L, L->top). - | lwz TMP1, L->cframe - | stw sp, L->cframe // Add our C frame to cframe chain. - | li TMP2, 0 - | stw TMP0, SAVE_NRES // Neg. delta means cframe w/o frame. - | stw TMP2, SAVE_ERRF // No error function. - | stw TMP1, SAVE_CFRAME - | mtctr CARG4 - | bctrl // (lua_State *L, lua_CFunction func, void *ud) - | mr. BASE, CRET1 - | lwz DISPATCH, L->glref // Setup pointer to dispatch table. - | li PC, FRAME_CP - | addi DISPATCH, DISPATCH, GG_G2DISP - | bne <3 // Else continue with the call. - | b ->vm_leave_cp // No base? Just remove C frame. - | - |//----------------------------------------------------------------------- - |//-- Metamethod handling ------------------------------------------------ - |//----------------------------------------------------------------------- - | - |// The lj_meta_* functions (except for lj_meta_cat) don't reallocate the - |// stack, so BASE doesn't need to be reloaded across these calls. - | - |//-- Continuation dispatch ---------------------------------------------- - | - |->cont_dispatch: - | // BASE = meta base, RA = resultptr, RD = (nresults+1)*8 - | lwz TMP0, -12(BASE) // Continuation. - | mr RB, BASE - | mr BASE, TMP2 // Restore caller BASE. - | lwz LFUNC:TMP1, FRAME_FUNC(TMP2) - | cmplwi TMP0, 0 - | lwz PC, -16(RB) // Restore PC from [cont|PC]. - | beq >1 - | subi TMP2, RD, 8 - | lwz TMP1, LFUNC:TMP1->pc - | evstddx TISNIL, RA, TMP2 // Ensure one valid arg. - | lwz KBASE, PC2PROTO(k)(TMP1) - | // BASE = base, RA = resultptr, RB = meta base - | mtctr TMP0 - | bctr // Jump to continuation. - | - |1: // Tail call from C function. - | subi TMP1, RB, 16 - | sub RC, TMP1, BASE - | b ->vm_call_tail - | - |->cont_cat: // RA = resultptr, RB = meta base - | lwz INS, -4(PC) - | subi CARG2, RB, 16 - | decode_RB8 SAVE0, INS - | evldd TMP0, 0(RA) - | add TMP1, BASE, SAVE0 - | stw BASE, L->base - | cmplw TMP1, CARG2 - | sub CARG3, CARG2, TMP1 - | decode_RA8 RA, INS - | evstdd TMP0, 0(CARG2) - | bne ->BC_CAT_Z - | evstddx TMP0, BASE, RA - | b ->cont_nop - | - |//-- Table indexing metamethods ----------------------------------------- - | - |->vmeta_tgets1: - | evmergelo STR:RC, TISSTR, STR:RC - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | decode_RB8 RB, INS - | evstdd STR:RC, 0(CARG3) - | add CARG2, BASE, RB - | b >1 - | - |->vmeta_tgets: - | evmergelo TAB:RB, TISTAB, TAB:RB - | la CARG2, DISPATCH_GL(tmptv)(DISPATCH) - | evmergelo STR:RC, TISSTR, STR:RC - | evstdd TAB:RB, 0(CARG2) - | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH) - | evstdd STR:RC, 0(CARG3) - | b >1 - | - |->vmeta_tgetb: // TMP0 = index - | efdcfsi TMP0, TMP0 - | decode_RB8 RB, INS - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | add CARG2, BASE, RB - | evstdd TMP0, 0(CARG3) - | b >1 - | - |->vmeta_tgetv: - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | add CARG2, BASE, RB - | add CARG3, BASE, RC - |1: - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | bl extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k) - | // Returns TValue * (finished) or NULL (metamethod). - | cmplwi CRET1, 0 - | beq >3 - | evldd TMP0, 0(CRET1) - | evstddx TMP0, BASE, RA - | ins_next - | - |3: // Call __index metamethod. - | // BASE = base, L->top = new base, stack = cont/func/t/k - | subfic TMP1, BASE, FRAME_CONT - | lwz BASE, L->top - | stw PC, -16(BASE) // [cont|PC] - | add PC, TMP1, BASE - | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. - | li NARGS8:RC, 16 // 2 args for func(t, k). - | b ->vm_call_dispatch_f - | - |//----------------------------------------------------------------------- - | - |->vmeta_tsets1: - | evmergelo STR:RC, TISSTR, STR:RC - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | decode_RB8 RB, INS - | evstdd STR:RC, 0(CARG3) - | add CARG2, BASE, RB - | b >1 - | - |->vmeta_tsets: - | evmergelo TAB:RB, TISTAB, TAB:RB - | la CARG2, DISPATCH_GL(tmptv)(DISPATCH) - | evmergelo STR:RC, TISSTR, STR:RC - | evstdd TAB:RB, 0(CARG2) - | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH) - | evstdd STR:RC, 0(CARG3) - | b >1 - | - |->vmeta_tsetb: // TMP0 = index - | efdcfsi TMP0, TMP0 - | decode_RB8 RB, INS - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | add CARG2, BASE, RB - | evstdd TMP0, 0(CARG3) - | b >1 - | - |->vmeta_tsetv: - | decode_RB8 RB, INS - | decode_RC8 RC, INS - | add CARG2, BASE, RB - | add CARG3, BASE, RC - |1: - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | bl extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k) - | // Returns TValue * (finished) or NULL (metamethod). - | cmplwi CRET1, 0 - | evlddx TMP0, BASE, RA - | beq >3 - | // NOBARRIER: lj_meta_tset ensures the table is not black. - | evstdd TMP0, 0(CRET1) - | ins_next - | - |3: // Call __newindex metamethod. - | // BASE = base, L->top = new base, stack = cont/func/t/k/(v) - | subfic TMP1, BASE, FRAME_CONT - | lwz BASE, L->top - | stw PC, -16(BASE) // [cont|PC] - | add PC, TMP1, BASE - | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. - | li NARGS8:RC, 24 // 3 args for func(t, k, v) - | evstdd TMP0, 16(BASE) // Copy value to third argument. - | b ->vm_call_dispatch_f - | - |//-- Comparison metamethods --------------------------------------------- - | - |->vmeta_comp: - | mr CARG1, L - | subi PC, PC, 4 - | add CARG2, BASE, RA - | stw PC, SAVE_PC - | add CARG3, BASE, RD - | stw BASE, L->base - | decode_OP1 CARG4, INS - | bl extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op) - | // Returns 0/1 or TValue * (metamethod). - |3: - | cmplwi CRET1, 1 - | bgt ->vmeta_binop - |4: - | lwz INS, 0(PC) - | addi PC, PC, 4 - | decode_RD4 TMP2, INS - | addis TMP3, PC, -(BCBIAS_J*4 >> 16) - | add TMP2, TMP2, TMP3 - | isellt PC, PC, TMP2 - |->cont_nop: - | ins_next - | - |->cont_ra: // RA = resultptr - | lwz INS, -4(PC) - | evldd TMP0, 0(RA) - | decode_RA8 TMP1, INS - | evstddx TMP0, BASE, TMP1 - | b ->cont_nop - | - |->cont_condt: // RA = resultptr - | lwz TMP0, 0(RA) - | li TMP1, LJ_TTRUE - | cmplw TMP1, TMP0 // Branch if result is true. - | b <4 - | - |->cont_condf: // RA = resultptr - | lwz TMP0, 0(RA) - | li TMP1, LJ_TFALSE - | cmplw TMP0, TMP1 // Branch if result is false. - | b <4 - | - |->vmeta_equal: - | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV. - | subi PC, PC, 4 - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | bl extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne) - | // Returns 0/1 or TValue * (metamethod). - | b <3 - | - |//-- Arithmetic metamethods --------------------------------------------- - | - |->vmeta_arith_vn: - | add CARG3, BASE, RB - | add CARG4, KBASE, RC - | b >1 - | - |->vmeta_arith_nv: - | add CARG3, KBASE, RC - | add CARG4, BASE, RB - | b >1 - | - |->vmeta_unm: - | add CARG3, BASE, RD - | mr CARG4, CARG3 - | b >1 - | - |->vmeta_arith_vv: - | add CARG3, BASE, RB - | add CARG4, BASE, RC - |1: - | add CARG2, BASE, RA - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | decode_OP1 CARG5, INS // Caveat: CARG5 overlaps INS. - | bl extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op) - | // Returns NULL (finished) or TValue * (metamethod). - | cmplwi CRET1, 0 - | beq ->cont_nop - | - | // Call metamethod for binary op. - |->vmeta_binop: - | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2 - | sub TMP1, CRET1, BASE - | stw PC, -16(CRET1) // [cont|PC] - | mr TMP2, BASE - | addi PC, TMP1, FRAME_CONT - | mr BASE, CRET1 - | li NARGS8:RC, 16 // 2 args for func(o1, o2). - | b ->vm_call_dispatch - | - |->vmeta_len: -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | mr SAVE0, CARG1 -#endif - | add CARG2, BASE, RD - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | bl extern lj_meta_len // (lua_State *L, TValue *o) - | // Returns NULL (retry) or TValue * (metamethod base). -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | cmplwi CRET1, 0 - | bne ->vmeta_binop // Binop call for compatibility. - | mr CARG1, SAVE0 - | b ->BC_LEN_Z -#else - | b ->vmeta_binop // Binop call for compatibility. -#endif - | - |//-- Call metamethod ---------------------------------------------------- - | - |->vmeta_call: // Resolve and call __call metamethod. - | // TMP2 = old base, BASE = new base, RC = nargs*8 - | mr CARG1, L - | stw TMP2, L->base // This is the callers base! - | subi CARG2, BASE, 8 - | stw PC, SAVE_PC - | add CARG3, BASE, RC - | mr SAVE0, NARGS8:RC - | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) - | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. - | addi NARGS8:RC, SAVE0, 8 // Got one more argument now. - | ins_call - | - |->vmeta_callt: // Resolve __call for BC_CALLT. - | // BASE = old base, RA = new base, RC = nargs*8 - | mr CARG1, L - | stw BASE, L->base - | subi CARG2, RA, 8 - | stw PC, SAVE_PC - | add CARG3, RA, RC - | mr SAVE0, NARGS8:RC - | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) - | lwz TMP1, FRAME_PC(BASE) - | addi NARGS8:RC, SAVE0, 8 // Got one more argument now. - | lwz LFUNC:RB, FRAME_FUNC(RA) // Guaranteed to be a function here. - | b ->BC_CALLT_Z - | - |//-- Argument coercion for 'for' statement ------------------------------ - | - |->vmeta_for: - | mr CARG1, L - | stw BASE, L->base - | mr CARG2, RA - | stw PC, SAVE_PC - | mr SAVE0, INS - | bl extern lj_meta_for // (lua_State *L, TValue *base) -#if LJ_HASJIT - | decode_OP1 TMP0, SAVE0 -#endif - | decode_RA8 RA, SAVE0 -#if LJ_HASJIT - | cmpwi TMP0, BC_JFORI -#endif - | decode_RD8 RD, SAVE0 -#if LJ_HASJIT - | beq =>BC_JFORI -#endif - | b =>BC_FORI - | - |//----------------------------------------------------------------------- - |//-- Fast functions ----------------------------------------------------- - |//----------------------------------------------------------------------- - | - |.macro .ffunc, name - |->ff_ .. name: - |.endmacro - | - |.macro .ffunc_1, name - |->ff_ .. name: - | cmplwi NARGS8:RC, 8 - | evldd CARG1, 0(BASE) - | blt ->fff_fallback - |.endmacro - | - |.macro .ffunc_2, name - |->ff_ .. name: - | cmplwi NARGS8:RC, 16 - | evldd CARG1, 0(BASE) - | evldd CARG2, 8(BASE) - | blt ->fff_fallback - |.endmacro - | - |.macro .ffunc_n, name - | .ffunc_1 name - | checknum CARG1 - | checkfail ->fff_fallback - |.endmacro - | - |.macro .ffunc_nn, name - | .ffunc_2 name - | evmergehi TMP0, CARG1, CARG2 - | checknum TMP0 - | checkanyfail ->fff_fallback - |.endmacro - | - |// Inlined GC threshold check. Caveat: uses TMP0 and TMP1. - |.macro ffgccheck - | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH) - | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) - | cmplw TMP0, TMP1 - | bgel ->fff_gcstep - |.endmacro - | - |//-- Base library: checks ----------------------------------------------- - | - |.ffunc assert - | cmplwi NARGS8:RC, 8 - | evldd TMP0, 0(BASE) - | blt ->fff_fallback - | evaddw TMP1, TISNIL, TISNIL // Synthesize LJ_TFALSE. - | la RA, -8(BASE) - | evcmpltu cr1, TMP0, TMP1 - | lwz PC, FRAME_PC(BASE) - | bge cr1, ->fff_fallback - | evstdd TMP0, 0(RA) - | addi RD, NARGS8:RC, 8 // Compute (nresults+1)*8. - | beq ->fff_res // Done if exactly 1 argument. - | li TMP1, 8 - | subi RC, RC, 8 - |1: - | cmplw TMP1, RC - | evlddx TMP0, BASE, TMP1 - | evstddx TMP0, RA, TMP1 - | addi TMP1, TMP1, 8 - | bne <1 - | b ->fff_res - | - |.ffunc type - | cmplwi NARGS8:RC, 8 - | lwz CARG1, 0(BASE) - | blt ->fff_fallback - | li TMP2, ~LJ_TNUMX - | cmplw CARG1, TISNUM - | not TMP1, CARG1 - | isellt TMP1, TMP2, TMP1 - | slwi TMP1, TMP1, 3 - | la TMP2, CFUNC:RB->upvalue - | evlddx STR:CRET1, TMP2, TMP1 - | b ->fff_restv - | - |//-- Base library: getters and setters --------------------------------- - | - |.ffunc_1 getmetatable - | checktab CARG1 - | evmergehi TMP1, CARG1, CARG1 - | checkfail >6 - |1: // Field metatable must be at same offset for GCtab and GCudata! - | lwz TAB:RB, TAB:CARG1->metatable - |2: - | evmr CRET1, TISNIL - | cmplwi TAB:RB, 0 - | lwz STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH) - | beq ->fff_restv - | lwz TMP0, TAB:RB->hmask - | evmergelo CRET1, TISTAB, TAB:RB // Use metatable as default result. - | lwz TMP1, STR:RC->hash - | lwz NODE:TMP2, TAB:RB->node - | evmergelo STR:RC, TISSTR, STR:RC - | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask - | slwi TMP0, TMP1, 5 - | slwi TMP1, TMP1, 3 - | sub TMP1, TMP0, TMP1 - | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) - |3: // Rearranged logic, because we expect _not_ to find the key. - | evldd TMP0, NODE:TMP2->key - | evldd TMP1, NODE:TMP2->val - | evcmpeq TMP0, STR:RC - | lwz NODE:TMP2, NODE:TMP2->next - | checkallok >5 - | cmplwi NODE:TMP2, 0 - | beq ->fff_restv // Not found, keep default result. - | b <3 - |5: - | checknil TMP1 - | checkok ->fff_restv // Ditto for nil value. - | evmr CRET1, TMP1 // Return value of mt.__metatable. - | b ->fff_restv - | - |6: - | cmpwi TMP1, LJ_TUDATA - | not TMP1, TMP1 - | beq <1 - | checknum CARG1 - | slwi TMP1, TMP1, 2 - | li TMP2, 4*~LJ_TNUMX - | isellt TMP1, TMP2, TMP1 - | la TMP2, DISPATCH_GL(gcroot[GCROOT_BASEMT])(DISPATCH) - | lwzx TAB:RB, TMP2, TMP1 - | b <2 - | - |.ffunc_2 setmetatable - | // Fast path: no mt for table yet and not clearing the mt. - | evmergehi TMP0, TAB:CARG1, TAB:CARG2 - | checktab TMP0 - | checkanyfail ->fff_fallback - | lwz TAB:TMP1, TAB:CARG1->metatable - | cmplwi TAB:TMP1, 0 - | lbz TMP3, TAB:CARG1->marked - | bne ->fff_fallback - | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) - | stw TAB:CARG2, TAB:CARG1->metatable - | beq ->fff_restv - | barrierback TAB:CARG1, TMP3, TMP0 - | b ->fff_restv - | - |.ffunc rawget - | cmplwi NARGS8:RC, 16 - | evldd CARG2, 0(BASE) - | blt ->fff_fallback - | checktab CARG2 - | la CARG3, 8(BASE) - | checkfail ->fff_fallback - | mr CARG1, L - | bl extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key) - | // Returns cTValue *. - | evldd CRET1, 0(CRET1) - | b ->fff_restv - | - |//-- Base library: conversions ------------------------------------------ - | - |.ffunc tonumber - | // Only handles the number case inline (without a base argument). - | cmplwi NARGS8:RC, 8 - | evldd CARG1, 0(BASE) - | bne ->fff_fallback // Exactly one argument. - | checknum CARG1 - | checkok ->fff_restv - | b ->fff_fallback - | - |.ffunc_1 tostring - | // Only handles the string or number case inline. - | checkstr CARG1 - | // A __tostring method in the string base metatable is ignored. - | checkok ->fff_restv // String key? - | // Handle numbers inline, unless a number base metatable is present. - | lwz TMP0, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])(DISPATCH) - | checknum CARG1 - | cmplwi cr1, TMP0, 0 - | stw BASE, L->base // Add frame since C call can throw. - | crand 4*cr0+eq, 4*cr0+lt, 4*cr1+eq - | stw PC, SAVE_PC // Redundant (but a defined value). - | bne ->fff_fallback - | ffgccheck - | mr CARG1, L - | mr CARG2, BASE - | bl extern lj_str_fromnum // (lua_State *L, lua_Number *np) - | // Returns GCstr *. - | evmergelo STR:CRET1, TISSTR, STR:CRET1 - | b ->fff_restv - | - |//-- Base library: iterators ------------------------------------------- - | - |.ffunc next - | cmplwi NARGS8:RC, 8 - | evldd CARG2, 0(BASE) - | blt ->fff_fallback - | evstddx TISNIL, BASE, NARGS8:RC // Set missing 2nd arg to nil. - | checktab TAB:CARG2 - | lwz PC, FRAME_PC(BASE) - | checkfail ->fff_fallback - | stw BASE, L->base // Add frame since C call can throw. - | mr CARG1, L - | stw 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 - | evmr CRET1, TISNIL - | beq ->fff_restv // End of traversal: return nil. - | evldd TMP0, 8(BASE) // Copy key and value to results. - | la RA, -8(BASE) - | evldd TMP1, 16(BASE) - | evstdd TMP0, 0(RA) - | li RD, (2+1)*8 - | evstdd TMP1, 8(RA) - | b ->fff_res - | - |.ffunc_1 pairs - | checktab TAB:CARG1 - | lwz PC, FRAME_PC(BASE) - | checkfail ->fff_fallback -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | lwz TAB:TMP2, TAB:CARG1->metatable - | evldd CFUNC:TMP0, CFUNC:RB->upvalue[0] - | cmplwi TAB:TMP2, 0 - | la RA, -8(BASE) - | bne ->fff_fallback -#else - | evldd CFUNC:TMP0, CFUNC:RB->upvalue[0] - | la RA, -8(BASE) -#endif - | evstdd TISNIL, 8(BASE) - | li RD, (3+1)*8 - | evstdd CFUNC:TMP0, 0(RA) - | b ->fff_res - | - |.ffunc_2 ipairs_aux - | checktab TAB:CARG1 - | lwz PC, FRAME_PC(BASE) - | checkfail ->fff_fallback - | checknum CARG2 - | lus TMP3, 0x3ff0 - | checkfail ->fff_fallback - | efdctsi TMP2, CARG2 - | lwz TMP0, TAB:CARG1->asize - | evmergelo TMP3, TMP3, ZERO - | lwz TMP1, TAB:CARG1->array - | efdadd CARG2, CARG2, TMP3 - | addi TMP2, TMP2, 1 - | la RA, -8(BASE) - | cmplw TMP0, TMP2 - | slwi TMP3, TMP2, 3 - | evstdd CARG2, 0(RA) - | ble >2 // Not in array part? - | evlddx TMP1, TMP1, TMP3 - |1: - | checknil TMP1 - | li RD, (0+1)*8 - | checkok ->fff_res // End of iteration, return 0 results. - | li RD, (2+1)*8 - | evstdd TMP1, 8(RA) - | b ->fff_res - |2: // Check for empty hash part first. Otherwise call C function. - | lwz TMP0, TAB:CARG1->hmask - | cmplwi TMP0, 0 - | li RD, (0+1)*8 - | beq ->fff_res - | mr CARG2, TMP2 - | bl extern lj_tab_getinth // (GCtab *t, int32_t key) - | // Returns cTValue * or NULL. - | cmplwi CRET1, 0 - | li RD, (0+1)*8 - | beq ->fff_res - | evldd TMP1, 0(CRET1) - | b <1 - | - |.ffunc_1 ipairs - | checktab TAB:CARG1 - | lwz PC, FRAME_PC(BASE) - | checkfail ->fff_fallback -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | lwz TAB:TMP2, TAB:CARG1->metatable - | evldd CFUNC:TMP0, CFUNC:RB->upvalue[0] - | cmplwi TAB:TMP2, 0 - | la RA, -8(BASE) - | bne ->fff_fallback -#else - | evldd CFUNC:TMP0, CFUNC:RB->upvalue[0] - | la RA, -8(BASE) -#endif - | evsplati TMP1, 0 - | li RD, (3+1)*8 - | evstdd TMP1, 8(BASE) - | evstdd CFUNC:TMP0, 0(RA) - | b ->fff_res - | - |//-- Base library: catch errors ---------------------------------------- - | - |.ffunc pcall - | cmplwi NARGS8:RC, 8 - | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | blt ->fff_fallback - | mr TMP2, BASE - | la BASE, 8(BASE) - | // Remember active hook before pcall. - | rlwinm TMP3, TMP3, 32-HOOK_ACTIVE_SHIFT, 31, 31 - | subi NARGS8:RC, NARGS8:RC, 8 - | addi PC, TMP3, 8+FRAME_PCALL - | b ->vm_call_dispatch - | - |.ffunc_2 xpcall - | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | mr TMP2, BASE - | checkfunc CARG2 // Traceback must be a function. - | checkfail ->fff_fallback - | la BASE, 16(BASE) - | // Remember active hook before pcall. - | rlwinm TMP3, TMP3, 32-HOOK_ACTIVE_SHIFT, 31, 31 - | evstdd CARG2, 0(TMP2) // Swap function and traceback. - | subi NARGS8:RC, NARGS8:RC, 16 - | evstdd CARG1, 8(TMP2) - | addi PC, TMP3, 16+FRAME_PCALL - | b ->vm_call_dispatch - | - |//-- Coroutine library -------------------------------------------------- - | - |.macro coroutine_resume_wrap, resume - |.if resume - |.ffunc_1 coroutine_resume - | evmergehi TMP0, L:CARG1, L:CARG1 - |.else - |.ffunc coroutine_wrap_aux - | lwz L:CARG1, CFUNC:RB->upvalue[0].gcr - |.endif - |.if resume - | cmpwi TMP0, LJ_TTHREAD - | bne ->fff_fallback - |.endif - | lbz TMP0, L:CARG1->status - | lwz TMP1, L:CARG1->cframe - | lwz CARG2, L:CARG1->top - | cmplwi cr0, TMP0, LUA_YIELD - | lwz TMP2, L:CARG1->base - | cmplwi cr1, TMP1, 0 - | lwz TMP0, L:CARG1->maxstack - | cmplw cr7, CARG2, TMP2 - | lwz PC, FRAME_PC(BASE) - | crorc 4*cr6+lt, 4*cr0+gt, 4*cr1+eq // st>LUA_YIELD || cframe!=0 - | add TMP2, CARG2, NARGS8:RC - | crandc 4*cr6+gt, 4*cr7+eq, 4*cr0+eq // base==top && st!=LUA_YIELD - | cmplw cr1, TMP2, TMP0 - | cror 4*cr6+lt, 4*cr6+lt, 4*cr6+gt - | stw PC, SAVE_PC - | cror 4*cr6+lt, 4*cr6+lt, 4*cr1+gt // cond1 || cond2 || stackov - | stw BASE, L->base - | blt cr6, ->fff_fallback - |1: - |.if resume - | addi BASE, BASE, 8 // Keep resumed thread in stack for GC. - | subi NARGS8:RC, NARGS8:RC, 8 - | subi TMP2, TMP2, 8 - |.endif - | stw TMP2, L:CARG1->top - | li TMP1, 0 - | stw BASE, L->top - |2: // Move args to coroutine. - | cmpw TMP1, NARGS8:RC - | evlddx TMP0, BASE, TMP1 - | beq >3 - | evstddx TMP0, CARG2, TMP1 - | addi TMP1, TMP1, 8 - | b <2 - |3: - | li CARG3, 0 - | mr L:SAVE0, L:CARG1 - | li CARG4, 0 - | bl ->vm_resume // (lua_State *L, TValue *base, 0, 0) - | // Returns thread status. - |4: - | lwz TMP2, L:SAVE0->base - | cmplwi CRET1, LUA_YIELD - | lwz TMP3, L:SAVE0->top - | li_vmstate INTERP - | lwz BASE, L->base - | st_vmstate - | bgt >8 - | sub RD, TMP3, TMP2 - | lwz TMP0, L->maxstack - | cmplwi RD, 0 - | add TMP1, BASE, RD - | beq >6 // No results? - | cmplw TMP1, TMP0 - | li TMP1, 0 - | bgt >9 // Need to grow stack? - | - | subi TMP3, RD, 8 - | stw TMP2, L:SAVE0->top // Clear coroutine stack. - |5: // Move results from coroutine. - | cmplw TMP1, TMP3 - | evlddx TMP0, TMP2, TMP1 - | evstddx TMP0, BASE, TMP1 - | addi TMP1, TMP1, 8 - | bne <5 - |6: - | andi. TMP0, PC, FRAME_TYPE - |.if resume - | li TMP1, LJ_TTRUE - | la RA, -8(BASE) - | stw TMP1, -8(BASE) // Prepend true to results. - | addi RD, RD, 16 - |.else - | mr RA, BASE - | addi RD, RD, 8 - |.endif - |7: - | stw PC, SAVE_PC - | mr MULTRES, RD - | beq ->BC_RET_Z - | b ->vm_return - | - |8: // Coroutine returned with error (at co->top-1). - |.if resume - | andi. TMP0, PC, FRAME_TYPE - | la TMP3, -8(TMP3) - | li TMP1, LJ_TFALSE - | evldd TMP0, 0(TMP3) - | stw TMP3, L:SAVE0->top // Remove error from coroutine stack. - | li RD, (2+1)*8 - | stw TMP1, -8(BASE) // Prepend false to results. - | la RA, -8(BASE) - | evstdd TMP0, 0(BASE) // Copy error message. - | b <7 - |.else - | mr CARG1, L - | mr CARG2, L:SAVE0 - | bl extern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co) - |.endif - | - |9: // Handle stack expansion on return from yield. - | mr CARG1, L - | srwi CARG2, RD, 3 - | bl extern lj_state_growstack // (lua_State *L, int n) - | li CRET1, 0 - | b <4 - |.endmacro - | - | coroutine_resume_wrap 1 // coroutine.resume - | coroutine_resume_wrap 0 // coroutine.wrap - | - |.ffunc coroutine_yield - | lwz TMP0, L->cframe - | add TMP1, BASE, NARGS8:RC - | stw BASE, L->base - | andi. TMP0, TMP0, CFRAME_RESUME - | stw TMP1, L->top - | li CRET1, LUA_YIELD - | beq ->fff_fallback - | stw ZERO, L->cframe - | stb CRET1, L->status - | b ->vm_leave_unw - | - |//-- Math library ------------------------------------------------------- - | - |.ffunc_n math_abs - | efdabs CRET1, CARG1 - | // Fallthrough. - | - |->fff_restv: - | // CRET1 = TValue result. - | lwz PC, FRAME_PC(BASE) - | la RA, -8(BASE) - | evstdd CRET1, 0(RA) - |->fff_res1: - | // RA = results, PC = return. - | li RD, (1+1)*8 - |->fff_res: - | // RA = results, RD = (nresults+1)*8, PC = return. - | andi. TMP0, PC, FRAME_TYPE - | mr MULTRES, RD - | bne ->vm_return - | lwz INS, -4(PC) - | decode_RB8 RB, INS - |5: - | cmplw RB, RD // More results expected? - | decode_RA8 TMP0, INS - | bgt >6 - | ins_next1 - | // Adjust BASE. KBASE is assumed to be set for the calling frame. - | sub BASE, RA, TMP0 - | ins_next2 - | - |6: // Fill up results with nil. - | subi TMP1, RD, 8 - | addi RD, RD, 8 - | evstddx TISNIL, RA, TMP1 - | b <5 - | - |.macro math_extern, func - | .ffunc math_ .. func - | cmplwi NARGS8:RC, 8 - | evldd CARG2, 0(BASE) - | blt ->fff_fallback - | checknum CARG2 - | evmergehi CARG1, CARG2, CARG2 - | checkfail ->fff_fallback - | bl extern func - | evmergelo CRET1, CRET1, CRET2 - | b ->fff_restv - |.endmacro - | - |.macro math_extern2, func - | .ffunc math_ .. func - | cmplwi NARGS8:RC, 16 - | evldd CARG2, 0(BASE) - | evldd CARG4, 8(BASE) - | blt ->fff_fallback - | evmergehi CARG1, CARG4, CARG2 - | checknum CARG1 - | evmergehi CARG3, CARG4, CARG4 - | checkanyfail ->fff_fallback - | bl extern func - | evmergelo CRET1, CRET1, CRET2 - | b ->fff_restv - |.endmacro - | - |.macro math_round, func - | .ffunc math_ .. func - | cmplwi NARGS8:RC, 8 - | evldd CARG2, 0(BASE) - | blt ->fff_fallback - | checknum CARG2 - | evmergehi CARG1, CARG2, CARG2 - | checkfail ->fff_fallback - | lwz PC, FRAME_PC(BASE) - | bl ->vm_..func.._hilo; - | la RA, -8(BASE) - | evstdd CRET2, 0(RA) - | b ->fff_res1 - |.endmacro - | - | math_round floor - | math_round ceil - | - | math_extern sqrt - | math_extern log - | math_extern log10 - | math_extern exp - | math_extern sin - | math_extern cos - | math_extern tan - | math_extern asin - | math_extern acos - | math_extern atan - | math_extern sinh - | math_extern cosh - | math_extern tanh - | math_extern2 pow - | math_extern2 atan2 - | math_extern2 fmod - | - |->ff_math_deg: - |.ffunc_n math_rad - | evldd CARG2, CFUNC:RB->upvalue[0] - | efdmul CRET1, CARG1, CARG2 - | b ->fff_restv - | - |.ffunc math_ldexp - | cmplwi NARGS8:RC, 16 - | evldd CARG2, 0(BASE) - | evldd CARG4, 8(BASE) - | blt ->fff_fallback - | evmergehi CARG1, CARG4, CARG2 - | checknum CARG1 - | checkanyfail ->fff_fallback - | efdctsi CARG3, CARG4 - | bl extern ldexp - | evmergelo CRET1, CRET1, CRET2 - | b ->fff_restv - | - |.ffunc math_frexp - | cmplwi NARGS8:RC, 8 - | evldd CARG2, 0(BASE) - | blt ->fff_fallback - | checknum CARG2 - | evmergehi CARG1, CARG2, CARG2 - | checkfail ->fff_fallback - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | lwz PC, FRAME_PC(BASE) - | bl extern frexp - | lwz TMP1, DISPATCH_GL(tmptv)(DISPATCH) - | evmergelo CRET1, CRET1, CRET2 - | efdcfsi CRET2, TMP1 - | la RA, -8(BASE) - | evstdd CRET1, 0(RA) - | li RD, (2+1)*8 - | evstdd CRET2, 8(RA) - | b ->fff_res - | - |.ffunc math_modf - | cmplwi NARGS8:RC, 8 - | evldd CARG2, 0(BASE) - | blt ->fff_fallback - | checknum CARG2 - | evmergehi CARG1, CARG2, CARG2 - | checkfail ->fff_fallback - | la CARG3, -8(BASE) - | lwz PC, FRAME_PC(BASE) - | bl extern modf - | evmergelo CRET1, CRET1, CRET2 - | la RA, -8(BASE) - | evstdd CRET1, 0(BASE) - | li RD, (2+1)*8 - | b ->fff_res - | - |.macro math_minmax, name, cmpop - | .ffunc_1 name - | checknum CARG1 - | li TMP1, 8 - | checkfail ->fff_fallback - |1: - | evlddx CARG2, BASE, TMP1 - | cmplw cr1, TMP1, NARGS8:RC - | checknum CARG2 - | bge cr1, ->fff_restv // Ok, since CRET1 = CARG1. - | checkfail ->fff_fallback - | cmpop CARG2, CARG1 - | addi TMP1, TMP1, 8 - | crmove 4*cr0+lt, 4*cr0+gt - | evsel CARG1, CARG2, CARG1 - | b <1 - |.endmacro - | - | math_minmax math_min, efdtstlt - | math_minmax math_max, efdtstgt - | - |//-- String library ----------------------------------------------------- - | - |.ffunc_1 string_len - | checkstr STR:CARG1 - | checkfail ->fff_fallback - | lwz TMP0, STR:CARG1->len - | efdcfsi CRET1, TMP0 - | b ->fff_restv - | - |.ffunc string_byte // Only handle the 1-arg case here. - | cmplwi NARGS8:RC, 8 - | evldd STR:CARG1, 0(BASE) - | bne ->fff_fallback // Need exactly 1 argument. - | checkstr STR:CARG1 - | la RA, -8(BASE) - | checkfail ->fff_fallback - | lwz TMP0, STR:CARG1->len - | li RD, (0+1)*8 - | lbz TMP1, STR:CARG1[1] // Access is always ok (NUL at end). - | li TMP2, (1+1)*8 - | cmplwi TMP0, 0 - | lwz PC, FRAME_PC(BASE) - | efdcfsi CRET1, TMP1 - | iseleq RD, RD, TMP2 - | evstdd CRET1, 0(RA) - | b ->fff_res - | - |.ffunc string_char // Only handle the 1-arg case here. - | ffgccheck - | cmplwi NARGS8:RC, 8 - | evldd CARG1, 0(BASE) - | bne ->fff_fallback // Exactly 1 argument. - | checknum CARG1 - | la CARG2, DISPATCH_GL(tmptv)(DISPATCH) - | checkfail ->fff_fallback - | efdctsiz TMP0, CARG1 - | li CARG3, 1 - | cmplwi TMP0, 255 - | stb TMP0, 0(CARG2) - | bgt ->fff_fallback - |->fff_newstr: - | mr CARG1, L - | stw BASE, L->base - | stw PC, SAVE_PC - | bl extern lj_str_new // (lua_State *L, char *str, size_t l) - | // Returns GCstr *. - | lwz BASE, L->base - | evmergelo STR:CRET1, TISSTR, STR:CRET1 - | b ->fff_restv - | - |.ffunc string_sub - | ffgccheck - | cmplwi NARGS8:RC, 16 - | evldd CARG3, 16(BASE) - | evldd STR:CARG1, 0(BASE) - | blt ->fff_fallback - | evldd CARG2, 8(BASE) - | li TMP2, -1 - | beq >1 - | checknum CARG3 - | checkfail ->fff_fallback - | efdctsiz TMP2, CARG3 - |1: - | checknum CARG2 - | checkfail ->fff_fallback - | checkstr STR:CARG1 - | efdctsiz TMP1, CARG2 - | checkfail ->fff_fallback - | lwz TMP0, STR:CARG1->len - | cmplw TMP0, TMP2 // len < end? (unsigned compare) - | add TMP3, TMP2, TMP0 - | blt >5 - |2: - | cmpwi TMP1, 0 // start <= 0? - | add TMP3, TMP1, TMP0 - | ble >7 - |3: - | sub. CARG3, TMP2, TMP1 - | addi CARG2, STR:CARG1, #STR-1 - | addi CARG3, CARG3, 1 - | add CARG2, CARG2, TMP1 - | isellt CARG3, r0, CARG3 - | b ->fff_newstr - | - |5: // Negative end or overflow. - | cmpw TMP0, TMP2 - | addi TMP3, TMP3, 1 - | iselgt TMP2, TMP3, TMP0 // end = end > len ? len : end+len+1 - | b <2 - | - |7: // Negative start or underflow. - | cmpwi cr1, TMP3, 0 - | iseleq TMP1, r0, TMP3 - | isel TMP1, r0, TMP1, 4*cr1+lt - | addi TMP1, TMP1, 1 // start = 1 + (start ? start+len : 0) - | b <3 - | - |.ffunc string_rep // Only handle the 1-char case inline. - | ffgccheck - | cmplwi NARGS8:RC, 16 - | evldd CARG1, 0(BASE) - | evldd CARG2, 8(BASE) - | blt ->fff_fallback - | checknum CARG2 - | checkfail ->fff_fallback - | checkstr STR:CARG1 - | efdctsiz CARG3, CARG2 - | checkfail ->fff_fallback - | lwz TMP0, STR:CARG1->len - | cmpwi CARG3, 0 - | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) - | ble >2 // Count <= 0? (or non-int) - | cmplwi TMP0, 1 - | subi TMP2, CARG3, 1 - | blt >2 // Zero length string? - | cmplw cr1, TMP1, CARG3 - | bne ->fff_fallback // Fallback for > 1-char strings. - | lbz TMP0, STR:CARG1[1] - | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) - | blt cr1, ->fff_fallback - |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). - | cmplwi TMP2, 0 - | stbx TMP0, CARG2, TMP2 - | subi TMP2, TMP2, 1 - | bne <1 - | b ->fff_newstr - |2: // Return empty string. - | la STR:CRET1, DISPATCH_GL(strempty)(DISPATCH) - | evmergelo CRET1, TISSTR, STR:CRET1 - | b ->fff_restv - | - |.ffunc string_reverse - | ffgccheck - | cmplwi NARGS8:RC, 8 - | evldd CARG1, 0(BASE) - | blt ->fff_fallback - | checkstr STR:CARG1 - | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) - | checkfail ->fff_fallback - | lwz CARG3, STR:CARG1->len - | la CARG1, #STR(STR:CARG1) - | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) - | li TMP2, 0 - | cmplw TMP1, CARG3 - | subi TMP3, CARG3, 1 - | blt ->fff_fallback - |1: // Reverse string copy. - | cmpwi TMP3, 0 - | lbzx TMP1, CARG1, TMP2 - | blt ->fff_newstr - | stbx TMP1, CARG2, TMP3 - | subi TMP3, TMP3, 1 - | addi TMP2, TMP2, 1 - | b <1 - | - |.macro ffstring_case, name, lo - | .ffunc name - | ffgccheck - | cmplwi NARGS8:RC, 8 - | evldd CARG1, 0(BASE) - | blt ->fff_fallback - | checkstr STR:CARG1 - | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) - | checkfail ->fff_fallback - | lwz CARG3, STR:CARG1->len - | la CARG1, #STR(STR:CARG1) - | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) - | cmplw TMP1, CARG3 - | li TMP2, 0 - | blt ->fff_fallback - |1: // ASCII case conversion. - | cmplw TMP2, CARG3 - | lbzx TMP1, CARG1, TMP2 - | bge ->fff_newstr - | subi TMP0, TMP1, lo - | xori TMP3, TMP1, 0x20 - | cmplwi TMP0, 26 - | isellt TMP1, TMP3, TMP1 - | stbx TMP1, CARG2, TMP2 - | addi TMP2, TMP2, 1 - | b <1 - |.endmacro - | - |ffstring_case string_lower, 65 - |ffstring_case string_upper, 97 - | - |//-- Table library ------------------------------------------------------ - | - |.ffunc_1 table_getn - | checktab CARG1 - | checkfail ->fff_fallback - | bl extern lj_tab_len // (GCtab *t) - | // Returns uint32_t (but less than 2^31). - | efdcfsi CRET1, CRET1 - | b ->fff_restv - | - |//-- Bit library -------------------------------------------------------- - | - |.macro .ffunc_bit, name - | .ffunc_n bit_..name - | efdadd CARG1, CARG1, TOBIT - |.endmacro - | - |.ffunc_bit tobit - |->fff_resbit: - | efdcfsi CRET1, CARG1 - | b ->fff_restv - | - |.macro .ffunc_bit_op, name, ins - | .ffunc_bit name - | li TMP1, 8 - |1: - | evlddx CARG2, BASE, TMP1 - | cmplw cr1, TMP1, NARGS8:RC - | checknum CARG2 - | bge cr1, ->fff_resbit - | checkfail ->fff_fallback - | efdadd CARG2, CARG2, TOBIT - | ins CARG1, CARG1, CARG2 - | addi TMP1, TMP1, 8 - | b <1 - |.endmacro - | - |.ffunc_bit_op band, and - |.ffunc_bit_op bor, or - |.ffunc_bit_op bxor, xor - | - |.ffunc_bit bswap - | rotlwi TMP0, CARG1, 8 - | rlwimi TMP0, CARG1, 24, 0, 7 - | rlwimi TMP0, CARG1, 24, 16, 23 - | efdcfsi CRET1, TMP0 - | b ->fff_restv - | - |.ffunc_bit bnot - | not TMP0, CARG1 - | efdcfsi CRET1, TMP0 - | b ->fff_restv - | - |.macro .ffunc_bit_sh, name, ins, shmod - | .ffunc_nn bit_..name - | efdadd CARG2, CARG2, TOBIT - | efdadd CARG1, CARG1, TOBIT - |.if shmod == 1 - | rlwinm CARG2, CARG2, 0, 27, 31 - |.elif shmod == 2 - | neg CARG2, CARG2 - |.endif - | ins TMP0, CARG1, CARG2 - | efdcfsi CRET1, TMP0 - | b ->fff_restv - |.endmacro - | - |.ffunc_bit_sh lshift, slw, 1 - |.ffunc_bit_sh rshift, srw, 1 - |.ffunc_bit_sh arshift, sraw, 1 - |.ffunc_bit_sh rol, rotlw, 0 - |.ffunc_bit_sh ror, rotlw, 2 - | - |//----------------------------------------------------------------------- - | - |->fff_fallback: // Call fast function fallback handler. - | // BASE = new base, RB = CFUNC, RC = nargs*8 - | lwz TMP3, CFUNC:RB->f - | add TMP1, BASE, NARGS8:RC - | lwz PC, FRAME_PC(BASE) // Fallback may overwrite PC. - | addi TMP0, TMP1, 8*LUA_MINSTACK - | lwz TMP2, L->maxstack - | stw PC, SAVE_PC // Redundant (but a defined value). - | cmplw TMP0, TMP2 - | stw BASE, L->base - | stw TMP1, L->top - | mr CARG1, L - | bgt >5 // Need to grow stack. - | mtctr TMP3 - | bctrl // (lua_State *L) - | // Either throws an error, or recovers and returns -1, 0 or nresults+1. - | lwz BASE, L->base - | cmpwi CRET1, 0 - | slwi RD, CRET1, 3 - | la RA, -8(BASE) - | bgt ->fff_res // Returned nresults+1? - |1: // Returned 0 or -1: retry fast path. - | lwz TMP0, L->top - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | sub NARGS8:RC, TMP0, BASE - | bne ->vm_call_tail // Returned -1? - | ins_callt // Returned 0: retry fast path. - | - |// Reconstruct previous base for vmeta_call during tailcall. - |->vm_call_tail: - | andi. TMP0, PC, FRAME_TYPE - | rlwinm TMP1, PC, 0, 0, 28 - | bne >3 - | lwz INS, -4(PC) - | decode_RA8 TMP1, INS - | addi TMP1, TMP1, 8 - |3: - | sub TMP2, BASE, TMP1 - | b ->vm_call_dispatch // Resolve again for tailcall. - | - |5: // Grow stack for fallback handler. - | li CARG2, LUA_MINSTACK - | bl extern lj_state_growstack // (lua_State *L, int n) - | lwz BASE, L->base - | cmpw TMP0, TMP0 // Set 4*cr0+eq to force retry. - | b <1 - | - |->fff_gcstep: // Call GC step function. - | // BASE = new base, RC = nargs*8 - | mflr SAVE0 - | stw BASE, L->base - | add TMP0, BASE, NARGS8:RC - | stw PC, SAVE_PC // Redundant (but a defined value). - | stw TMP0, L->top - | mr CARG1, L - | bl extern lj_gc_step // (lua_State *L) - | lwz BASE, L->base - | mtlr SAVE0 - | lwz TMP0, L->top - | sub NARGS8:RC, TMP0, BASE - | lwz CFUNC:RB, FRAME_FUNC(BASE) - | blr - | - |//----------------------------------------------------------------------- - |//-- Special dispatch targets ------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_record: // Dispatch target for recording phase. -#if LJ_HASJIT - | NYI -#endif - | - |->vm_rethook: // Dispatch target for return hooks. - | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | andi. TMP0, TMP3, HOOK_ACTIVE // Hook already active? - | beq >1 - |5: // Re-dispatch to static ins. - | addi TMP1, TMP1, GG_DISP2STATIC // Assumes decode_OP4 TMP1, INS. - | lwzx TMP0, DISPATCH, TMP1 - | mtctr TMP0 - | bctr - | - |->vm_inshook: // Dispatch target for instr/line hooks. - | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) - | lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH) - | andi. TMP0, TMP3, HOOK_ACTIVE // Hook already active? - | rlwinm TMP0, TMP3, 31-LUA_HOOKLINE, 31, 0 - | bne <5 - | - | cmpwi cr1, TMP0, 0 - | addic. TMP2, TMP2, -1 - | beq cr1, <5 - | stw TMP2, DISPATCH_GL(hookcount)(DISPATCH) - | beq >1 - | bge cr1, <5 - |1: - | mr CARG1, L - | stw MULTRES, SAVE_MULTRES - | mr CARG2, PC - | stw BASE, L->base - | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. - | bl extern lj_dispatch_ins // (lua_State *L, const BCIns *pc) - |3: - | lwz BASE, L->base - |4: // Re-dispatch to static ins. - | lwz INS, -4(PC) - | decode_OP4 TMP1, INS - | decode_RB8 RB, INS - | addi TMP1, TMP1, GG_DISP2STATIC - | decode_RD8 RD, INS - | lwzx TMP0, DISPATCH, TMP1 - | decode_RA8 RA, INS - | decode_RC8 RC, INS - | mtctr TMP0 - | bctr - | - |->cont_hook: // Continue from hook yield. - | addi PC, PC, 4 - | lwz MULTRES, -20(RB) // Restore MULTRES for *M ins. - | b <4 - | - |->vm_hotloop: // Hot loop counter underflow. -#if LJ_HASJIT - | NYI -#endif - | - |->vm_callhook: // Dispatch target for call hooks. - | mr CARG2, PC -#if LJ_HASJIT - | b >1 -#endif - | - |->vm_hotcall: // Hot call counter underflow. -#if LJ_HASJIT - | ori CARG2, PC, 1 - |1: -#endif - | add TMP0, BASE, RC - | stw PC, SAVE_PC - | mr CARG1, L - | stw BASE, L->base - | sub RA, RA, BASE - | stw TMP0, L->top - | bl extern lj_dispatch_call // (lua_State *L, const BCIns *pc) - | // Returns ASMFunction. - | lwz BASE, L->base - | lwz TMP0, L->top - | stw ZERO, SAVE_PC // Invalidate for subsequent line hook. - | sub NARGS8:RC, TMP0, BASE - | add RA, BASE, RA - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | mtctr CRET1 - | bctr - | - |//----------------------------------------------------------------------- - |//-- Trace exit handler ------------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_exit_handler: -#if LJ_HASJIT - | NYI -#endif - |->vm_exit_interp: -#if LJ_HASJIT - | NYI -#endif - | - |//----------------------------------------------------------------------- - |//-- Math helper functions ---------------------------------------------- - |//----------------------------------------------------------------------- - | - |// FP value rounding. Called by math.floor/math.ceil fast functions - |// and from JIT code. - |// - |// This can be inlined if the CPU has the frin/friz/frip/frim instructions. - |// The alternative hard-float approaches have a deep dependency chain. - |// The resulting latency is at least 3x-7x the double-precision FP latency - |// (e500v2: 6cy, e600: 5cy, Cell: 10cy) or around 20-70 cycles. - |// - |// The soft-float approach is tedious, but much faster (e500v2: ~11cy/~6cy). - |// However it relies on a fast way to transfer the FP value to GPRs - |// (e500v2: 0cy for lo-word, 1cy for hi-word). - |// - |.macro vm_round, name, mode - | // Used temporaries: TMP0, TMP1, TMP2, TMP3. - |->name.._efd: // Input: CARG2, output: CRET2 - | evmergehi CARG1, CARG2, CARG2 - |->name.._hilo: - | // Input: CARG1 (hi), CARG2 (hi, lo), output: CRET2 - | rlwinm TMP2, CARG1, 12, 21, 31 - | addic. TMP2, TMP2, -1023 // exp = exponent(x) - 1023 - | li TMP1, -1 - | cmplwi cr1, TMP2, 51 // 0 <= exp <= 51? - | subfic TMP0, TMP2, 52 - | bgt cr1, >1 - | lus TMP3, 0xfff0 - | slw TMP0, TMP1, TMP0 // lomask = -1 << (52-exp) - | sraw TMP1, TMP3, TMP2 // himask = (int32_t)0xfff00000 >> exp - |.if mode == 2 // trunc(x): - | evmergelo TMP0, TMP1, TMP0 - | evand CRET2, CARG2, TMP0 // hi &= himask, lo &= lomask - |.else - | andc TMP2, CARG2, TMP0 - | andc TMP3, CARG1, TMP1 - | or TMP2, TMP2, TMP3 // ztest = (hi&~himask) | (lo&~lomask) - | srawi TMP3, CARG1, 31 // signmask = (int32_t)hi >> 31 - |.if mode == 0 // floor(x): - | and. TMP2, TMP2, TMP3 // iszero = ((ztest & signmask) == 0) - |.else // ceil(x): - | andc. TMP2, TMP2, TMP3 // iszero = ((ztest & ~signmask) == 0) - |.endif - | and CARG2, CARG2, TMP0 // lo &= lomask - | and CARG1, CARG1, TMP1 // hi &= himask - | subc TMP0, CARG2, TMP0 - | iseleq TMP0, CARG2, TMP0 // lo = iszero ? lo : lo-lomask - | sube TMP1, CARG1, TMP1 - | iseleq TMP1, CARG1, TMP1 // hi = iszero ? hi : hi-himask+carry - | evmergelo CRET2, TMP1, TMP0 - |.endif - | blr - |1: - | bgtlr // Already done if >=2^52, +-inf or nan. - |.if mode == 2 // trunc(x): - | rlwinm TMP1, CARG1, 0, 0, 0 // hi = sign(x) - | li TMP0, 0 - | evmergelo CRET2, TMP1, TMP0 - |.else - | rlwinm TMP2, CARG1, 0, 1, 31 - | srawi TMP0, CARG1, 31 // signmask = (int32_t)hi >> 31 - | or TMP2, TMP2, CARG2 // ztest = abs(hi) | lo - | lus TMP1, 0x3ff0 - |.if mode == 0 // floor(x): - | and. TMP2, TMP2, TMP0 // iszero = ((ztest & signmask) == 0) - |.else // ceil(x): - | andc. TMP2, TMP2, TMP0 // iszero = ((ztest & ~signmask) == 0) - |.endif - | li TMP0, 0 - | iseleq TMP1, r0, TMP1 - | rlwimi CARG1, TMP1, 0, 1, 31 // hi = sign(x) | (iszero ? 0.0 : 1.0) - | evmergelo CRET2, CARG1, TMP0 - |.endif - | blr - |.endmacro - | - |->vm_floor: - | mflr CARG3 - | bl ->vm_floor_hilo - | mtlr CARG3 - | evmergehi CRET1, CRET2, CRET2 - | blr - | - | vm_round vm_floor, 0 - | vm_round vm_ceil, 1 -#if LJ_HASJIT - | vm_round vm_trunc, 2 -#else - |->vm_trunc_efd: - |->vm_trunc_hilo: -#endif - | - |// Callable from C: double lj_vm_foldarith(double x, double y, int op) - |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -) - |// and basic math functions. ORDER ARITH - |->vm_foldarith: - | evmergelo CARG2, CARG1, CARG2 - | cmplwi CARG5, 1 - | evmergelo CARG4, CARG3, CARG4 - | beq >1; bgt >2 - | efdadd CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr - |1: - | efdsub CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr - |2: - | cmplwi CARG5, 3; beq >1; bgt >2 - | efdmul CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr - |1: - | efddiv CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr - |2: - | cmplwi CARG5, 5; beq >1; bgt >2 - | evmr CARG3, CARG2; efddiv CRET2, CARG2, CARG4; evmr RB, CARG4 - | mflr RC; bl ->vm_floor_efd; mtlr RC - | efdmul CRET2, CRET2, RB; efdsub CRET2, CARG3, CRET2 - | evmergehi CRET1, CRET2, CRET2; blr - |1: - | b extern pow - |2: - | cmplwi CARG5, 7; beq >1; bgt >2 - | xoris CARG1, CARG1, 0x8000; blr - |1: - | rlwinm CARG1, CARG1, 0, 1, 31; blr - |2: - | NYI // Other operations only needed by JIT compiler. - | - |//----------------------------------------------------------------------- - |//-- Miscellaneous functions -------------------------------------------- - |//----------------------------------------------------------------------- - | - |//----------------------------------------------------------------------- - |//-- FFI helper functions ----------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_ffi_call: -#if LJ_HASFFI - | NYI -#endif - | - |//----------------------------------------------------------------------- -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop) -{ - int vk = 0; - |=>defop: - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - | // RA = src1*8, RD = src2*8, JMP with RD = target - | evlddx TMP0, BASE, RA - | addi PC, PC, 4 - | evlddx TMP1, BASE, RD - | addis TMP3, PC, -(BCBIAS_J*4 >> 16) - | lwz TMP2, -4(PC) - | evmergehi RB, TMP0, TMP1 - | decode_RD4 TMP2, TMP2 - | checknum RB - | add TMP2, TMP2, TMP3 - | checkanyfail ->vmeta_comp - | efdcmplt TMP0, TMP1 - if (op == BC_ISLE || op == BC_ISGT) { - | efdcmpeq cr1, TMP0, TMP1 - | cror 4*cr0+gt, 4*cr0+gt, 4*cr1+gt - } - if (op == BC_ISLT || op == BC_ISLE) { - | iselgt PC, TMP2, PC - } else { - | iselgt PC, PC, TMP2 - } - | ins_next - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - | // RA = src1*8, RD = src2*8, JMP with RD = target - | evlddx CARG2, BASE, RA - | addi PC, PC, 4 - | evlddx CARG3, BASE, RD - | addis TMP3, PC, -(BCBIAS_J*4 >> 16) - | lwz TMP2, -4(PC) - | evmergehi RB, CARG2, CARG3 - | decode_RD4 TMP2, TMP2 - | checknum RB - | add TMP2, TMP2, TMP3 - | checkanyfail >5 - | efdcmpeq CARG2, CARG3 - if (vk) { - | iselgt PC, TMP2, PC - } else { - | iselgt PC, PC, TMP2 - } - |1: - | ins_next - | - |5: // Either or both types are not numbers. - | evcmpeq CARG2, CARG3 - | not TMP3, RB - | cmplwi cr1, TMP3, ~LJ_TISPRI // Primitive? - | crorc 4*cr7+lt, 4*cr0+so, 4*cr0+lt // 1: Same tv or different type. - | cmplwi cr6, TMP3, ~LJ_TISTABUD // Table or userdata? - | crandc 4*cr7+gt, 4*cr0+lt, 4*cr1+gt // 2: Same type and primitive. - | mr SAVE0, PC - if (vk) { - | isel PC, TMP2, PC, 4*cr7+gt - } else { - | isel TMP2, PC, TMP2, 4*cr7+gt - } - | cror 4*cr7+lt, 4*cr7+lt, 4*cr7+gt // 1 or 2. - if (vk) { - | isel PC, TMP2, PC, 4*cr0+so - } else { - | isel PC, PC, TMP2, 4*cr0+so - } - | blt cr7, <1 // Done if 1 or 2. - | blt cr6, <1 // Done if not tab/ud. - | - | // Different tables or userdatas. Need to check __eq metamethod. - | // Field metatable must be at same offset for GCtab and GCudata! - | lwz TAB:TMP2, TAB:CARG2->metatable - | li CARG4, 1-vk // ne = 0 or 1. - | cmplwi TAB:TMP2, 0 - | beq <1 // No metatable? - | lbz TMP2, TAB:TMP2->nomm - | andi. TMP2, TMP2, 1<vmeta_equal // Handle __eq metamethod. - break; - - case BC_ISEQS: case BC_ISNES: - vk = op == BC_ISEQS; - | // RA = src*8, RD = str_const*8 (~), JMP with RD = target - | evlddx TMP0, BASE, RA - | srwi RD, RD, 1 - | lwz INS, 0(PC) - | subfic RD, RD, -4 - | addi PC, PC, 4 - | lwzx STR:TMP1, KBASE, RD // KBASE-4-str_const*4 - | addis TMP3, PC, -(BCBIAS_J*4 >> 16) - | decode_RD4 TMP2, INS - | evmergelo STR:TMP1, TISSTR, STR:TMP1 - | add TMP2, TMP2, TMP3 - | evcmpeq TMP0, STR:TMP1 - if (vk) { - | isel PC, TMP2, PC, 4*cr0+so - } else { - | isel PC, PC, TMP2, 4*cr0+so - } - | ins_next - break; - - case BC_ISEQN: case BC_ISNEN: - vk = op == BC_ISEQN; - | // RA = src*8, RD = num_const*8, JMP with RD = target - | evlddx TMP0, BASE, RA - | addi PC, PC, 4 - | evlddx TMP1, KBASE, RD - | addis TMP3, PC, -(BCBIAS_J*4 >> 16) - | lwz INS, -4(PC) - | checknum TMP0 - | checkfail >5 - | efdcmpeq TMP0, TMP1 - |1: - | decode_RD4 TMP2, INS - | add TMP2, TMP2, TMP3 - if (vk) { - | iselgt PC, TMP2, PC - |5: - } else { - | iselgt PC, PC, TMP2 - } - |3: - | ins_next - if (!vk) { - |5: - | decode_RD4 TMP2, INS - | add PC, TMP2, TMP3 - | b <3 - } - break; - - case BC_ISEQP: case BC_ISNEP: - vk = op == BC_ISEQP; - | // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target - | lwzx TMP0, BASE, RA - | srwi TMP1, RD, 3 - | lwz INS, 0(PC) - | addi PC, PC, 4 - | not TMP1, TMP1 - | addis TMP3, PC, -(BCBIAS_J*4 >> 16) - | cmplw TMP0, TMP1 - | decode_RD4 TMP2, INS - | add TMP2, TMP2, TMP3 - if (vk) { - | iseleq PC, TMP2, PC - } else { - | iseleq PC, PC, TMP2 - } - | ins_next - break; - - /* -- Unary test and copy ops ------------------------------------------- */ - - case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: - | // RA = dst*8 or unused, RD = src*8, JMP with RD = target - | evlddx TMP0, BASE, RD - | evaddw TMP1, TISNIL, TISNIL // Synthesize LJ_TFALSE. - | lwz INS, 0(PC) - | evcmpltu TMP0, TMP1 - | addi PC, PC, 4 - if (op == BC_IST || op == BC_ISF) { - | addis TMP3, PC, -(BCBIAS_J*4 >> 16) - | decode_RD4 TMP2, INS - | add TMP2, TMP2, TMP3 - if (op == BC_IST) { - | isellt PC, TMP2, PC - } else { - | isellt PC, PC, TMP2 - } - } else { - if (op == BC_ISTC) { - | checkfail >1 - } else { - | checkok >1 - } - | addis PC, PC, -(BCBIAS_J*4 >> 16) - | decode_RD4 TMP2, INS - | evstddx TMP0, BASE, RA - | add PC, PC, TMP2 - |1: - } - | ins_next - break; - - /* -- Unary ops --------------------------------------------------------- */ - - case BC_MOV: - | // RA = dst*8, RD = src*8 - | ins_next1 - | evlddx TMP0, BASE, RD - | evstddx TMP0, BASE, RA - | ins_next2 - break; - case BC_NOT: - | // RA = dst*8, RD = src*8 - | ins_next1 - | lwzx TMP0, BASE, RD - | subfic TMP1, TMP0, LJ_TTRUE - | adde TMP0, TMP0, TMP1 - | stwx TMP0, BASE, RA - | ins_next2 - break; - case BC_UNM: - | // RA = dst*8, RD = src*8 - | evlddx TMP0, BASE, RD - | checknum TMP0 - | checkfail ->vmeta_unm - | efdneg TMP0, TMP0 - | ins_next1 - | evstddx TMP0, BASE, RA - | ins_next2 - break; - case BC_LEN: - | // RA = dst*8, RD = src*8 - | evlddx CARG1, BASE, RD - | checkstr CARG1 - | checkfail >2 - | lwz CRET1, STR:CARG1->len - |1: - | ins_next1 - | efdcfsi TMP0, CRET1 - | evstddx TMP0, BASE, RA - | ins_next2 - |2: - | checktab CARG1 - | checkfail ->vmeta_len -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | lwz TAB:TMP2, TAB:CARG1->metatable - | cmplwi TAB:TMP2, 0 - | bne >9 - |3: -#endif - |->BC_LEN_Z: - | bl extern lj_tab_len // (GCtab *t) - | // Returns uint32_t (but less than 2^31). - | b <1 -#ifdef LUAJIT_ENABLE_LUA52COMPAT - |9: - | lbz TMP0, TAB:TMP2->nomm - | andi. TMP0, TMP0, 1<vmeta_len -#endif - break; - - /* -- Binary ops -------------------------------------------------------- */ - - |.macro ins_arithpre, t0, t1 - | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8 - ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); - ||switch (vk) { - ||case 0: - | evlddx t0, BASE, RB - | checknum t0 - | evlddx t1, KBASE, RC - | checkfail ->vmeta_arith_vn - || break; - ||case 1: - | evlddx t1, BASE, RB - | checknum t1 - | evlddx t0, KBASE, RC - | checkfail ->vmeta_arith_nv - || break; - ||default: - | evlddx t0, BASE, RB - | evlddx t1, BASE, RC - | evmergehi TMP2, t0, t1 - | checknum TMP2 - | checkanyfail ->vmeta_arith_vv - || break; - ||} - |.endmacro - | - |.macro ins_arith, ins - | ins_arithpre TMP0, TMP1 - | ins_next1 - | ins TMP0, TMP0, TMP1 - | evstddx TMP0, BASE, RA - | ins_next2 - |.endmacro - - case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: - | ins_arith efdadd - break; - case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: - | ins_arith efdsub - break; - case BC_MULVN: case BC_MULNV: case BC_MULVV: - | ins_arith efdmul - break; - case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: - | ins_arith efddiv - break; - case BC_MODVN: - | ins_arithpre RD, SAVE0 - |->BC_MODVN_Z: - | efddiv CARG2, RD, SAVE0 - | bl ->vm_floor_efd // floor(b/c) - | efdmul TMP0, CRET2, SAVE0 - | ins_next1 - | efdsub TMP0, RD, TMP0 // b - floor(b/c)*c - | evstddx TMP0, BASE, RA - | ins_next2 - break; - case BC_MODNV: case BC_MODVV: - | ins_arithpre RD, SAVE0 - | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway. - break; - case BC_POW: - | evlddx CARG2, BASE, RB - | evlddx CARG4, BASE, RC - | evmergehi CARG1, CARG4, CARG2 - | checknum CARG1 - | evmergehi CARG3, CARG4, CARG4 - | checkanyfail ->vmeta_arith_vv - | bl extern pow - | evmergelo CRET2, CRET1, CRET2 - | evstddx CRET2, BASE, RA - | ins_next - break; - - case BC_CAT: - | // RA = dst*8, RB = src_start*8, RC = src_end*8 - | sub CARG3, RC, RB - | stw BASE, L->base - | add CARG2, BASE, RC - | mr SAVE0, RB - |->BC_CAT_Z: - | stw PC, SAVE_PC - | mr CARG1, L - | srwi CARG3, CARG3, 3 - | bl extern lj_meta_cat // (lua_State *L, TValue *top, int left) - | // Returns NULL (finished) or TValue * (metamethod). - | cmplwi CRET1, 0 - | lwz BASE, L->base - | bne ->vmeta_binop - | evlddx TMP0, BASE, SAVE0 // Copy result from RB to RA. - | evstddx TMP0, BASE, RA - | ins_next - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - | // RA = dst*8, RD = str_const*8 (~) - | ins_next1 - | srwi TMP1, RD, 1 - | subfic TMP1, TMP1, -4 - | lwzx TMP0, KBASE, TMP1 // KBASE-4-str_const*4 - | evmergelo TMP0, TISSTR, TMP0 - | evstddx TMP0, BASE, RA - | ins_next2 - break; - case BC_KCDATA: -#if LJ_HASFFI - | // RA = dst*8, RD = cdata_const*8 (~) - | ins_next1 - | srwi TMP1, RD, 1 - | subfic TMP1, TMP1, -4 - | lwzx TMP0, KBASE, TMP1 // KBASE-4-cdata_const*4 - | li TMP2, LJ_TCDATA - | evmergelo TMP0, TMP2, TMP0 - | evstddx TMP0, BASE, RA - | ins_next2 -#endif - break; - case BC_KSHORT: - | // RA = dst*8, RD = int16_literal*8 - | srwi TMP1, RD, 3 - | extsh TMP1, TMP1 - | ins_next1 - | efdcfsi TMP0, TMP1 - | evstddx TMP0, BASE, RA - | ins_next2 - break; - case BC_KNUM: - | // RA = dst*8, RD = num_const*8 - | evlddx TMP0, KBASE, RD - | ins_next1 - | evstddx TMP0, BASE, RA - | ins_next2 - break; - case BC_KPRI: - | // RA = dst*8, RD = primitive_type*8 (~) - | srwi TMP1, RD, 3 - | not TMP0, TMP1 - | ins_next1 - | stwx TMP0, BASE, RA - | ins_next2 - break; - case BC_KNIL: - | // RA = base*8, RD = end*8 - | evstddx TISNIL, BASE, RA - | addi RA, RA, 8 - |1: - | evstddx TISNIL, BASE, RA - | cmpw RA, RD - | addi RA, RA, 8 - | blt <1 - | ins_next_ - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - | // RA = dst*8, RD = uvnum*8 - | ins_next1 - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | srwi RD, RD, 1 - | addi RD, RD, offsetof(GCfuncL, uvptr) - | lwzx UPVAL:RB, LFUNC:RB, RD - | lwz TMP1, UPVAL:RB->v - | evldd TMP0, 0(TMP1) - | evstddx TMP0, BASE, RA - | ins_next2 - break; - case BC_USETV: - | // RA = uvnum*8, RD = src*8 - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | srwi RA, RA, 1 - | addi RA, RA, offsetof(GCfuncL, uvptr) - | evlddx TMP1, BASE, RD - | lwzx UPVAL:RB, LFUNC:RB, RA - | lbz TMP3, UPVAL:RB->marked - | lwz CARG2, UPVAL:RB->v - | andi. TMP3, TMP3, LJ_GC_BLACK // isblack(uv) - | lbz TMP0, UPVAL:RB->closed - | evmergehi TMP2, TMP1, TMP1 - | evstdd TMP1, 0(CARG2) - | cmplwi cr1, TMP0, 0 - | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq - | subi TMP2, TMP2, (LJ_TISNUM+1) - | bne >2 // Upvalue is closed and black? - |1: - | ins_next - | - |2: // Check if new value is collectable. - | cmplwi TMP2, LJ_TISGCV - (LJ_TISNUM+1) - | bge <1 // tvisgcv(v) - | lbz TMP3, GCOBJ:TMP1->gch.marked - | andi. TMP3, TMP3, LJ_GC_WHITES // iswhite(v) - | la CARG1, GG_DISP2G(DISPATCH) - | // Crossed a write barrier. Move the barrier forward. - | beq <1 - | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) - | b <1 - break; - case BC_USETS: - | // RA = uvnum*8, RD = str_const*8 (~) - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | srwi TMP1, RD, 1 - | srwi RA, RA, 1 - | subfic TMP1, TMP1, -4 - | addi RA, RA, offsetof(GCfuncL, uvptr) - | lwzx STR:TMP1, KBASE, TMP1 // KBASE-4-str_const*4 - | lwzx UPVAL:RB, LFUNC:RB, RA - | evmergelo STR:TMP1, TISSTR, STR:TMP1 - | lbz TMP3, UPVAL:RB->marked - | lwz CARG2, UPVAL:RB->v - | andi. TMP3, TMP3, LJ_GC_BLACK // isblack(uv) - | lbz TMP3, STR:TMP1->marked - | lbz TMP2, UPVAL:RB->closed - | evstdd STR:TMP1, 0(CARG2) - | bne >2 - |1: - | ins_next - | - |2: // Check if string is white and ensure upvalue is closed. - | andi. TMP3, TMP3, LJ_GC_WHITES // iswhite(str) - | cmplwi cr1, TMP2, 0 - | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq - | la CARG1, GG_DISP2G(DISPATCH) - | // Crossed a write barrier. Move the barrier forward. - | beq <1 - | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) - | b <1 - break; - case BC_USETN: - | // RA = uvnum*8, RD = num_const*8 - | ins_next1 - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | srwi RA, RA, 1 - | addi RA, RA, offsetof(GCfuncL, uvptr) - | evlddx TMP0, KBASE, RD - | lwzx UPVAL:RB, LFUNC:RB, RA - | lwz TMP1, UPVAL:RB->v - | evstdd TMP0, 0(TMP1) - | ins_next2 - break; - case BC_USETP: - | // RA = uvnum*8, RD = primitive_type*8 (~) - | ins_next1 - | lwz LFUNC:RB, FRAME_FUNC(BASE) - | srwi RA, RA, 1 - | addi RA, RA, offsetof(GCfuncL, uvptr) - | srwi TMP0, RD, 3 - | lwzx UPVAL:RB, LFUNC:RB, RA - | not TMP0, TMP0 - | lwz TMP1, UPVAL:RB->v - | stw TMP0, 0(TMP1) - | ins_next2 - break; - - case BC_UCLO: - | // RA = level*8, RD = target - | lwz TMP1, L->openupval - | branch_RD // Do this first since RD is not saved. - | stw BASE, L->base - | cmplwi TMP1, 0 - | mr CARG1, L - | beq >1 - | add CARG2, BASE, RA - | bl extern lj_func_closeuv // (lua_State *L, TValue *level) - | lwz BASE, L->base - |1: - | ins_next - break; - - case BC_FNEW: - | // RA = dst*8, RD = proto_const*8 (~) (holding function prototype) - | srwi TMP1, RD, 1 - | stw BASE, L->base - | subfic TMP1, TMP1, -4 - | stw PC, SAVE_PC - | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4 - | mr CARG1, L - | lwz CARG3, FRAME_FUNC(BASE) - | // (lua_State *L, GCproto *pt, GCfuncL *parent) - | bl extern lj_func_newL_gc - | // Returns GCfuncL *. - | lwz BASE, L->base - | evmergelo LFUNC:CRET1, TISFUNC, LFUNC:CRET1 - | evstddx LFUNC:CRET1, BASE, RA - | ins_next - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - case BC_TDUP: - | // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~) - | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH) - | mr CARG1, L - | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) - | stw BASE, L->base - | cmplw TMP0, TMP1 - | stw PC, SAVE_PC - | bge >5 - |1: - if (op == BC_TNEW) { - | rlwinm CARG2, RD, 29, 21, 31 - | rlwinm CARG3, RD, 18, 27, 31 - | cmpwi CARG2, 0x7ff - | li TMP1, 0x801 - | iseleq CARG2, TMP1, CARG2 - | bl extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits) - | // Returns Table *. - } else { - | srwi TMP1, RD, 1 - | subfic TMP1, TMP1, -4 - | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4 - | bl extern lj_tab_dup // (lua_State *L, Table *kt) - | // Returns Table *. - } - | lwz BASE, L->base - | evmergelo TAB:CRET1, TISTAB, TAB:CRET1 - | evstddx TAB:CRET1, BASE, RA - | ins_next - |5: - | mr SAVE0, RD - | bl extern lj_gc_step_fixtop // (lua_State *L) - | mr RD, SAVE0 - | mr CARG1, L - | b <1 - break; - - case BC_GGET: - | // RA = dst*8, RD = str_const*8 (~) - case BC_GSET: - | // RA = src*8, RD = str_const*8 (~) - | lwz LFUNC:TMP2, FRAME_FUNC(BASE) - | srwi TMP1, RD, 1 - | lwz TAB:RB, LFUNC:TMP2->env - | subfic TMP1, TMP1, -4 - | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 - if (op == BC_GGET) { - | b ->BC_TGETS_Z - } else { - | b ->BC_TSETS_Z - } - break; - - case BC_TGETV: - | // RA = dst*8, RB = table*8, RC = key*8 - | evlddx TAB:RB, BASE, RB - | evlddx RC, BASE, RC - | checktab TAB:RB - | checkfail ->vmeta_tgetv - | checknum RC - | checkfail >5 - | // Convert number key to integer - | efdctsi TMP2, RC - | lwz TMP0, TAB:RB->asize - | efdcfsi TMP1, TMP2 - | cmplw cr0, TMP0, TMP2 - | efdcmpeq cr1, RC, TMP1 - | lwz TMP1, TAB:RB->array - | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+gt - | slwi TMP2, TMP2, 3 - | ble ->vmeta_tgetv // Integer key and in array part? - | evlddx TMP1, TMP1, TMP2 - | checknil TMP1 - | checkok >2 - |1: - | evstddx TMP1, BASE, RA - | ins_next - | - |2: // Check for __index if table value is nil. - | lwz TAB:TMP2, TAB:RB->metatable - | cmplwi TAB:TMP2, 0 - | beq <1 // No metatable: done. - | lbz TMP0, TAB:TMP2->nomm - | andi. TMP0, TMP0, 1<vmeta_tgetv - | - |5: - | checkstr STR:RC // String key? - | checkok ->BC_TGETS_Z - | b ->vmeta_tgetv - break; - case BC_TGETS: - | // RA = dst*8, RB = table*8, RC = str_const*8 (~) - | evlddx TAB:RB, BASE, RB - | srwi TMP1, RC, 1 - | checktab TAB:RB - | subfic TMP1, TMP1, -4 - | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 - | checkfail ->vmeta_tgets1 - |->BC_TGETS_Z: - | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8 - | lwz TMP0, TAB:RB->hmask - | lwz TMP1, STR:RC->hash - | lwz NODE:TMP2, TAB:RB->node - | evmergelo STR:RC, TISSTR, STR:RC - | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask - | slwi TMP0, TMP1, 5 - | slwi TMP1, TMP1, 3 - | sub TMP1, TMP0, TMP1 - | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) - |1: - | evldd TMP0, NODE:TMP2->key - | evldd TMP1, NODE:TMP2->val - | evcmpeq TMP0, STR:RC - | checkanyfail >4 - | checknil TMP1 - | checkok >5 // Key found, but nil value? - |3: - | evstddx TMP1, BASE, RA - | ins_next - | - |4: // Follow hash chain. - | lwz NODE:TMP2, NODE:TMP2->next - | cmplwi NODE:TMP2, 0 - | bne <1 - | // End of hash chain: key not found, nil result. - | evmr TMP1, TISNIL - | - |5: // Check for __index if table value is nil. - | lwz TAB:TMP2, TAB:RB->metatable - | cmplwi TAB:TMP2, 0 - | beq <3 // No metatable: done. - | lbz TMP0, TAB:TMP2->nomm - | andi. TMP0, TMP0, 1<vmeta_tgets - break; - case BC_TGETB: - | // RA = dst*8, RB = table*8, RC = index*8 - | evlddx TAB:RB, BASE, RB - | srwi TMP0, RC, 3 - | checktab TAB:RB - | checkfail ->vmeta_tgetb - | lwz TMP1, TAB:RB->asize - | lwz TMP2, TAB:RB->array - | cmplw TMP0, TMP1 - | bge ->vmeta_tgetb - | evlddx TMP1, TMP2, RC - | checknil TMP1 - | checkok >5 - |1: - | ins_next1 - | evstddx TMP1, BASE, RA - | ins_next2 - | - |5: // Check for __index if table value is nil. - | lwz TAB:TMP2, TAB:RB->metatable - | cmplwi TAB:TMP2, 0 - | beq <1 // No metatable: done. - | lbz TMP2, TAB:TMP2->nomm - | andi. TMP2, TMP2, 1<vmeta_tgetb // Caveat: preserve TMP0! - break; - - case BC_TSETV: - | // RA = src*8, RB = table*8, RC = key*8 - | evlddx TAB:RB, BASE, RB - | evlddx RC, BASE, RC - | checktab TAB:RB - | checkfail ->vmeta_tsetv - | checknum RC - | checkfail >5 - | // Convert number key to integer - | efdctsi TMP2, RC - | evlddx SAVE0, BASE, RA - | lwz TMP0, TAB:RB->asize - | efdcfsi TMP1, TMP2 - | cmplw cr0, TMP0, TMP2 - | efdcmpeq cr1, RC, TMP1 - | lwz TMP1, TAB:RB->array - | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+gt - | slwi TMP0, TMP2, 3 - | ble ->vmeta_tsetv // Integer key and in array part? - | lbz TMP3, TAB:RB->marked - | evlddx TMP2, TMP1, TMP0 - | checknil TMP2 - | checkok >3 - |1: - | andi. TMP2, TMP3, LJ_GC_BLACK // isblack(table) - | evstddx SAVE0, TMP1, TMP0 - | bne >7 - |2: - | ins_next - | - |3: // Check for __newindex if previous value is nil. - | lwz TAB:TMP2, TAB:RB->metatable - | cmplwi TAB:TMP2, 0 - | beq <1 // No metatable: done. - | lbz TMP2, TAB:TMP2->nomm - | andi. TMP2, TMP2, 1<vmeta_tsetv - | - |5: - | checkstr STR:RC // String key? - | checkok ->BC_TSETS_Z - | b ->vmeta_tsetv - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, TMP3, TMP0 - | b <2 - break; - case BC_TSETS: - | // RA = src*8, RB = table*8, RC = str_const*8 (~) - | evlddx TAB:RB, BASE, RB - | srwi TMP1, RC, 1 - | checktab TAB:RB - | subfic TMP1, TMP1, -4 - | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 - | checkfail ->vmeta_tsets1 - |->BC_TSETS_Z: - | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = src*8 - | lwz TMP0, TAB:RB->hmask - | lwz TMP1, STR:RC->hash - | lwz NODE:TMP2, TAB:RB->node - | evmergelo STR:RC, TISSTR, STR:RC - | stb ZERO, TAB:RB->nomm // Clear metamethod cache. - | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask - | evlddx SAVE0, BASE, RA - | slwi TMP0, TMP1, 5 - | slwi TMP1, TMP1, 3 - | sub TMP1, TMP0, TMP1 - | lbz TMP3, TAB:RB->marked - | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) - |1: - | evldd TMP0, NODE:TMP2->key - | evldd TMP1, NODE:TMP2->val - | evcmpeq TMP0, STR:RC - | checkanyfail >5 - | checknil TMP1 - | checkok >4 // Key found, but nil value? - |2: - | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) - | evstdd SAVE0, NODE:TMP2->val - | bne >7 - |3: - | ins_next - | - |4: // Check for __newindex if previous value is nil. - | lwz TAB:TMP1, TAB:RB->metatable - | cmplwi TAB:TMP1, 0 - | beq <2 // No metatable: done. - | lbz TMP0, TAB:TMP1->nomm - | andi. TMP0, TMP0, 1<vmeta_tsets - | - |5: // Follow hash chain. - | lwz NODE:TMP2, NODE:TMP2->next - | cmplwi NODE:TMP2, 0 - | bne <1 - | // End of hash chain: key not found, add a new one. - | - | // But check for __newindex first. - | lwz TAB:TMP1, TAB:RB->metatable - | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) - | stw PC, SAVE_PC - | mr CARG1, L - | cmplwi TAB:TMP1, 0 - | stw BASE, L->base - | beq >6 // No metatable: continue. - | lbz TMP0, TAB:TMP1->nomm - | andi. TMP0, TMP0, 1<vmeta_tsets // 'no __newindex' flag NOT set: check. - |6: - | mr CARG2, TAB:RB - | evstdd STR:RC, 0(CARG3) - | bl extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k) - | // Returns TValue *. - | lwz BASE, L->base - | evstdd SAVE0, 0(CRET1) - | b <3 // No 2nd write barrier needed. - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, TMP3, TMP0 - | b <3 - break; - case BC_TSETB: - | // RA = src*8, RB = table*8, RC = index*8 - | evlddx TAB:RB, BASE, RB - | srwi TMP0, RC, 3 - | checktab TAB:RB - | checkfail ->vmeta_tsetb - | lwz TMP1, TAB:RB->asize - | lwz TMP2, TAB:RB->array - | lbz TMP3, TAB:RB->marked - | cmplw TMP0, TMP1 - | evlddx SAVE0, BASE, RA - | bge ->vmeta_tsetb - | evlddx TMP1, TMP2, RC - | checknil TMP1 - | checkok >5 - |1: - | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) - | evstddx SAVE0, TMP2, RC - | bne >7 - |2: - | ins_next - | - |5: // Check for __newindex if previous value is nil. - | lwz TAB:TMP1, TAB:RB->metatable - | cmplwi TAB:TMP1, 0 - | beq <1 // No metatable: done. - | lbz TMP1, TAB:TMP1->nomm - | andi. TMP1, TMP1, 1<vmeta_tsetb // Caveat: preserve TMP0! - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, TMP3, TMP0 - | b <2 - break; - - case BC_TSETM: - | // RA = base*8 (table at base-1), RD = num_const*8 (start index) - | add RA, BASE, RA - |1: - | add TMP3, KBASE, RD - | lwz TAB:CARG2, -4(RA) // Guaranteed to be a table. - | addic. TMP0, MULTRES, -8 - | lwz TMP3, 4(TMP3) // Integer constant is in lo-word. - | srwi CARG3, TMP0, 3 - | beq >4 // Nothing to copy? - | add CARG3, CARG3, TMP3 - | lwz TMP2, TAB:CARG2->asize - | slwi TMP1, TMP3, 3 - | lbz TMP3, TAB:CARG2->marked - | cmplw CARG3, TMP2 - | add TMP2, RA, TMP0 - | lwz TMP0, TAB:CARG2->array - | bgt >5 - | add TMP1, TMP1, TMP0 - | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) - |3: // Copy result slots to table. - | evldd TMP0, 0(RA) - | addi RA, RA, 8 - | cmpw cr1, RA, TMP2 - | evstdd TMP0, 0(TMP1) - | addi TMP1, TMP1, 8 - | blt cr1, <3 - | bne >7 - |4: - | ins_next - | - |5: // Need to resize array part. - | stw BASE, L->base - | mr CARG1, L - | stw PC, SAVE_PC - | mr SAVE0, RD - | bl extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize) - | // Must not reallocate the stack. - | mr RD, SAVE0 - | b <1 - | - |7: // Possible table write barrier for any value. Skip valiswhite check. - | barrierback TAB:CARG2, TMP3, TMP0 - | b <4 - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALLM: - | // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8 - | add NARGS8:RC, NARGS8:RC, MULTRES - | // Fall through. Assumes BC_CALL follows. - break; - case BC_CALL: - | // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8 - | evlddx LFUNC:RB, BASE, RA - | mr TMP2, BASE - | add BASE, BASE, RA - | subi NARGS8:RC, NARGS8:RC, 8 - | checkfunc LFUNC:RB - | addi BASE, BASE, 8 - | checkfail ->vmeta_call - | ins_call - break; - - case BC_CALLMT: - | // RA = base*8, (RB = 0,) RC = extra_nargs*8 - | add NARGS8:RC, NARGS8:RC, MULTRES - | // Fall through. Assumes BC_CALLT follows. - break; - case BC_CALLT: - | // RA = base*8, (RB = 0,) RC = (nargs+1)*8 - | evlddx LFUNC:RB, BASE, RA - | add RA, BASE, RA - | lwz TMP1, FRAME_PC(BASE) - | subi NARGS8:RC, NARGS8:RC, 8 - | checkfunc LFUNC:RB - | addi RA, RA, 8 - | checkfail ->vmeta_callt - |->BC_CALLT_Z: - | andi. TMP0, TMP1, FRAME_TYPE // Caveat: preserve cr0 until the crand. - | lbz TMP3, LFUNC:RB->ffid - | xori TMP2, TMP1, FRAME_VARG - | cmplwi cr1, NARGS8:RC, 0 - | bne >7 - |1: - | stw LFUNC:RB, FRAME_FUNC(BASE) // Copy function down, but keep PC. - | li TMP2, 0 - | cmplwi cr7, TMP3, 1 // (> FF_C) Calling a fast function? - | beq cr1, >3 - |2: - | addi TMP3, TMP2, 8 - | evlddx TMP0, RA, TMP2 - | cmplw cr1, TMP3, NARGS8:RC - | evstddx TMP0, BASE, TMP2 - | mr TMP2, TMP3 - | bne cr1, <2 - |3: - | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+gt - | beq >5 - |4: - | ins_callt - | - |5: // Tailcall to a fast function with a Lua frame below. - | lwz INS, -4(TMP1) - | decode_RA8 RA, INS - | sub TMP1, BASE, RA - | lwz LFUNC:TMP1, FRAME_FUNC-8(TMP1) - | lwz TMP1, LFUNC:TMP1->pc - | lwz KBASE, PC2PROTO(k)(TMP1) // Need to prepare KBASE. - | b <4 - | - |7: // Tailcall from a vararg function. - | andi. TMP0, TMP2, FRAME_TYPEP - | bne <1 // Vararg frame below? - | sub BASE, BASE, TMP2 // Relocate BASE down. - | lwz TMP1, FRAME_PC(BASE) - | andi. TMP0, TMP1, FRAME_TYPE - | b <1 - break; - - case BC_ITERC: - | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8)) - | subi RA, RA, 24 // evldd doesn't support neg. offsets. - | mr TMP2, BASE - | evlddx LFUNC:RB, BASE, RA - | add BASE, BASE, RA - | evldd TMP0, 8(BASE) - | evldd TMP1, 16(BASE) - | evstdd LFUNC:RB, 24(BASE) // Copy callable. - | checkfunc LFUNC:RB - | evstdd TMP0, 32(BASE) // Copy state. - | li NARGS8:RC, 16 // Iterators get 2 arguments. - | evstdd TMP1, 40(BASE) // Copy control var. - | addi BASE, BASE, 32 - | checkfail ->vmeta_call - | ins_call - break; - - case BC_ITERN: - | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) -#if LJ_HASJIT - | // NYI: add hotloop, record BC_ITERN. -#endif - | add RA, BASE, RA - | lwz TAB:RB, -12(RA) - | lwz RC, -4(RA) // Get index from control var. - | lwz TMP0, TAB:RB->asize - | lwz TMP1, TAB:RB->array - | addi PC, PC, 4 - |1: // Traverse array part. - | cmplw RC, TMP0 - | slwi TMP3, RC, 3 - | bge >5 // Index points after array part? - | evlddx TMP2, TMP1, TMP3 - | checknil TMP2 - | lwz INS, -4(PC) - | checkok >4 - | efdcfsi TMP0, RC - | addi RC, RC, 1 - | addis TMP3, PC, -(BCBIAS_J*4 >> 16) - | evstdd TMP2, 8(RA) - | decode_RD4 TMP1, INS - | stw RC, -4(RA) // Update control var. - | add PC, TMP1, TMP3 - | evstdd TMP0, 0(RA) - |3: - | ins_next - | - |4: // Skip holes in array part. - | addi RC, RC, 1 - | b <1 - | - |5: // Traverse hash part. - | lwz TMP1, TAB:RB->hmask - | sub RC, RC, TMP0 - | lwz TMP2, TAB:RB->node - |6: - | cmplw RC, TMP1 // End of iteration? Branch to ITERL+1. - | slwi TMP3, RC, 5 - | bgt <3 - | slwi RB, RC, 3 - | sub TMP3, TMP3, RB - | evlddx RB, TMP2, TMP3 - | add NODE:TMP3, TMP2, TMP3 - | checknil RB - | lwz INS, -4(PC) - | checkok >7 - | evldd TMP3, NODE:TMP3->key - | addis TMP2, PC, -(BCBIAS_J*4 >> 16) - | evstdd RB, 8(RA) - | add RC, RC, TMP0 - | decode_RD4 TMP1, INS - | evstdd TMP3, 0(RA) - | addi RC, RC, 1 - | add PC, TMP1, TMP2 - | stw RC, -4(RA) // Update control var. - | b <3 - | - |7: // Skip holes in hash part. - | addi RC, RC, 1 - | b <6 - break; - - case BC_ISNEXT: - | // RA = base*8, RD = target (points to ITERN) - | add RA, BASE, RA - | li TMP2, -24 - | evlddx CFUNC:TMP1, RA, TMP2 - | lwz TMP2, -16(RA) - | lwz TMP3, -8(RA) - | evmergehi TMP0, CFUNC:TMP1, CFUNC:TMP1 - | cmpwi cr0, TMP2, LJ_TTAB - | cmpwi cr1, TMP0, LJ_TFUNC - | cmpwi cr6, TMP3, LJ_TNIL - | bne cr1, >5 - | lbz TMP1, CFUNC:TMP1->ffid - | crand 4*cr0+eq, 4*cr0+eq, 4*cr6+eq - | cmpwi cr7, TMP1, FF_next_N - | srwi TMP0, RD, 1 - | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq - | add TMP3, PC, TMP0 - | bne cr0, >5 - | stw ZERO, -4(RA) // Initialize control var. - | addis PC, TMP3, -(BCBIAS_J*4 >> 16) - |1: - | ins_next - |5: // Despecialize bytecode if any of the checks fail. - | li TMP0, BC_JMP - | li TMP1, BC_ITERC - | stb TMP0, -1(PC) - | addis PC, TMP3, -(BCBIAS_J*4 >> 16) - | stb TMP1, 3(PC) - | b <1 - break; - - case BC_VARG: - | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8 - | lwz TMP0, FRAME_PC(BASE) - | add RC, BASE, RC - | add RA, BASE, RA - | addi RC, RC, FRAME_VARG - | add TMP2, RA, RB - | subi TMP3, BASE, 8 // TMP3 = vtop - | sub RC, RC, TMP0 // RC = vbase - | // Note: RC may now be even _above_ BASE if nargs was < numparams. - | cmplwi cr1, RB, 0 - | sub. TMP1, TMP3, RC - | beq cr1, >5 // Copy all varargs? - | subi TMP2, TMP2, 16 - | ble >2 // No vararg slots? - |1: // Copy vararg slots to destination slots. - | evldd TMP0, 0(RC) - | addi RC, RC, 8 - | evstdd TMP0, 0(RA) - | cmplw RA, TMP2 - | cmplw cr1, RC, TMP3 - | bge >3 // All destination slots filled? - | addi RA, RA, 8 - | blt cr1, <1 // More vararg slots? - |2: // Fill up remainder with nil. - | evstdd TISNIL, 0(RA) - | cmplw RA, TMP2 - | addi RA, RA, 8 - | blt <2 - |3: - | ins_next - | - |5: // Copy all varargs. - | lwz TMP0, L->maxstack - | li MULTRES, 8 // MULTRES = (0+1)*8 - | ble <3 // No vararg slots? - | add TMP2, RA, TMP1 - | cmplw TMP2, TMP0 - | addi MULTRES, TMP1, 8 - | bgt >7 - |6: - | evldd TMP0, 0(RC) - | addi RC, RC, 8 - | evstdd TMP0, 0(RA) - | cmplw RC, TMP3 - | addi RA, RA, 8 - | blt <6 // More vararg slots? - | b <3 - | - |7: // Grow stack for varargs. - | mr CARG1, L - | stw RA, L->top - | sub SAVE0, RC, BASE // Need delta, because BASE may change. - | stw BASE, L->base - | sub RA, RA, BASE - | stw PC, SAVE_PC - | srwi CARG2, TMP1, 3 - | bl extern lj_state_growstack // (lua_State *L, int n) - | lwz BASE, L->base - | add RA, BASE, RA - | add RC, BASE, SAVE0 - | subi TMP3, BASE, 8 - | b <6 - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - | // RA = results*8, RD = extra_nresults*8 - | add RD, RD, MULTRES // MULTRES >= 8, so RD >= 8. - | // Fall through. Assumes BC_RET follows. - break; - - case BC_RET: - | // RA = results*8, RD = (nresults+1)*8 - | lwz PC, FRAME_PC(BASE) - | add RA, BASE, RA - | mr MULTRES, RD - |1: - | andi. TMP0, PC, FRAME_TYPE - | xori TMP1, PC, FRAME_VARG - | bne ->BC_RETV_Z - | - |->BC_RET_Z: - | // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return - | lwz INS, -4(PC) - | cmpwi RD, 8 - | subi TMP2, BASE, 8 - | subi RC, RD, 8 - | decode_RB8 RB, INS - | beq >3 - | li TMP1, 0 - |2: - | addi TMP3, TMP1, 8 - | evlddx TMP0, RA, TMP1 - | cmpw TMP3, RC - | evstddx TMP0, TMP2, TMP1 - | beq >3 - | addi TMP1, TMP3, 8 - | evlddx TMP0, RA, TMP3 - | cmpw TMP1, RC - | evstddx TMP0, TMP2, TMP3 - | bne <2 - |3: - |5: - | cmplw RB, RD - | decode_RA8 RA, INS - | bgt >6 - | sub BASE, TMP2, RA - | lwz LFUNC:TMP1, FRAME_FUNC(BASE) - | ins_next1 - | lwz TMP1, LFUNC:TMP1->pc - | lwz KBASE, PC2PROTO(k)(TMP1) - | ins_next2 - | - |6: // Fill up results with nil. - | subi TMP1, RD, 8 - | addi RD, RD, 8 - | evstddx TISNIL, TMP2, TMP1 - | b <5 - | - |->BC_RETV_Z: // Non-standard return case. - | andi. TMP2, TMP1, FRAME_TYPEP - | bne ->vm_return - | // Return from vararg function: relocate BASE down. - | sub BASE, BASE, TMP1 - | lwz PC, FRAME_PC(BASE) - | b <1 - break; - - case BC_RET0: case BC_RET1: - | // RA = results*8, RD = (nresults+1)*8 - | lwz PC, FRAME_PC(BASE) - | add RA, BASE, RA - | mr MULTRES, RD - | andi. TMP0, PC, FRAME_TYPE - | xori TMP1, PC, FRAME_VARG - | bne ->BC_RETV_Z - | - | lwz INS, -4(PC) - | subi TMP2, BASE, 8 - | decode_RB8 RB, INS - if (op == BC_RET1) { - | evldd TMP0, 0(RA) - | evstdd TMP0, 0(TMP2) - } - |5: - | cmplw RB, RD - | decode_RA8 RA, INS - | bgt >6 - | sub BASE, TMP2, RA - | lwz LFUNC:TMP1, FRAME_FUNC(BASE) - | ins_next1 - | lwz TMP1, LFUNC:TMP1->pc - | lwz KBASE, PC2PROTO(k)(TMP1) - | ins_next2 - | - |6: // Fill up results with nil. - | subi TMP1, RD, 8 - | addi RD, RD, 8 - | evstddx TISNIL, TMP2, TMP1 - | b <5 - break; - - /* -- Loops and branches ------------------------------------------------ */ - - case BC_FORL: -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_IFORL follows. - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - | // RA = base*8, RD = target (after end of loop or start of loop) - vk = (op == BC_IFORL || op == BC_JFORL); - | add RA, BASE, RA - | evldd TMP1, FORL_IDX*8(RA) - | evldd TMP3, FORL_STEP*8(RA) - | evldd TMP2, FORL_STOP*8(RA) - if (!vk) { - | evcmpgtu cr0, TMP1, TISNUM - | evcmpgtu cr7, TMP3, TISNUM - | evcmpgtu cr1, TMP2, TISNUM - | cror 4*cr0+lt, 4*cr0+lt, 4*cr7+lt - | cror 4*cr0+lt, 4*cr0+lt, 4*cr1+lt - | blt ->vmeta_for - } - if (vk) { - | efdadd TMP1, TMP1, TMP3 - | evstdd TMP1, FORL_IDX*8(RA) - } - | evcmpgts TMP3, TISNIL - | evstdd TMP1, FORL_EXT*8(RA) - | bge >2 - | efdcmpgt TMP1, TMP2 - |1: - if (op != BC_JFORL) { - | srwi RD, RD, 1 - | add RD, PC, RD - if (op == BC_JFORI) { - | addis PC, RD, -(BCBIAS_J*4 >> 16) - } else { - | addis RD, RD, -(BCBIAS_J*4 >> 16) - } - } - if (op == BC_FORI) { - | iselgt PC, RD, PC - } else if (op == BC_IFORL) { - | iselgt PC, PC, RD - } else { - | ble =>BC_JLOOP - } - | ins_next - |2: - | efdcmpgt TMP2, TMP1 - | b <1 - break; - - case BC_ITERL: -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_IITERL follows. - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - | // RA = base*8, RD = target - | evlddx TMP1, BASE, RA - | subi RA, RA, 8 - | checknil TMP1 - | checkok >1 // Stop if iterator returned nil. - if (op == BC_JITERL) { - | NYI - } else { - | branch_RD // Otherwise save control var + branch. - | evstddx TMP1, BASE, RA - } - |1: - | ins_next - break; - - case BC_LOOP: - | // RA = base*8, RD = target (loop extent) - | // Note: RA/RD is only used by trace recorder to determine scope/extent - | // This opcode does NOT jump, it's only purpose is to detect a hot loop. -#if LJ_HASJIT - | hotloop -#endif - | // Fall through. Assumes BC_ILOOP follows. - break; - - case BC_ILOOP: - | // RA = base*8, RD = target (loop extent) - | ins_next - break; - - case BC_JLOOP: -#if LJ_HASJIT - | NYI -#endif - break; - - case BC_JMP: - | // RA = base*8 (only used by trace recorder), RD = target - | branch_RD - | ins_next - break; - - /* -- Function headers -------------------------------------------------- */ - - case BC_FUNCF: -#if LJ_HASJIT - | hotcall -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow. - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 - | lwz TMP2, L->maxstack - | lbz TMP1, -4+PC2PROTO(numparams)(PC) - | lwz KBASE, -4+PC2PROTO(k)(PC) - | cmplw RA, TMP2 - | slwi TMP1, TMP1, 3 - | bgt ->vm_growstack_l - | ins_next1 - |2: - | cmplw NARGS8:RC, TMP1 // Check for missing parameters. - | ble >3 - if (op == BC_JFUNCF) { - | NYI - } else { - | ins_next2 - } - | - |3: // Clear missing parameters. - | evstddx TISNIL, BASE, NARGS8:RC - | addi NARGS8:RC, NARGS8:RC, 8 - | b <2 - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - | NYI // NYI: compiled vararg functions - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 - | lwz TMP2, L->maxstack - | add TMP1, BASE, RC - | add TMP0, RA, RC - | stw LFUNC:RB, 4(TMP1) // Store copy of LFUNC. - | addi TMP3, RC, 8+FRAME_VARG - | lwz KBASE, -4+PC2PROTO(k)(PC) - | cmplw TMP0, TMP2 - | stw TMP3, 0(TMP1) // Store delta + FRAME_VARG. - | bge ->vm_growstack_l - | lbz TMP2, -4+PC2PROTO(numparams)(PC) - | mr RA, BASE - | mr RC, TMP1 - | ins_next1 - | cmpwi TMP2, 0 - | addi BASE, TMP1, 8 - | beq >3 - |1: - | cmplw RA, RC // Less args than parameters? - | evldd TMP0, 0(RA) - | bge >4 - | evstdd TISNIL, 0(RA) // Clear old fixarg slot (help the GC). - | addi RA, RA, 8 - |2: - | addic. TMP2, TMP2, -1 - | evstdd TMP0, 8(TMP1) - | addi TMP1, TMP1, 8 - | bne <1 - |3: - | ins_next2 - | - |4: // Clear missing parameters. - | evmr TMP0, TISNIL - | b <2 - break; - - case BC_FUNCC: - case BC_FUNCCW: - | // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8 - if (op == BC_FUNCC) { - | lwz TMP3, CFUNC:RB->f - } else { - | lwz TMP3, DISPATCH_GL(wrapf)(DISPATCH) - } - | add TMP1, RA, NARGS8:RC - | lwz TMP2, L->maxstack - | add RC, BASE, NARGS8:RC - | stw BASE, L->base - | cmplw TMP1, TMP2 - | stw RC, L->top - | li_vmstate C - | mtctr TMP3 - if (op == BC_FUNCCW) { - | lwz CARG2, CFUNC:RB->f - } - | mr CARG1, L - | bgt ->vm_growstack_c // Need to grow stack. - | st_vmstate - | bctrl // (lua_State *L [, lua_CFunction f]) - | // Returns nresults. - | lwz TMP1, L->top - | slwi RD, CRET1, 3 - | lwz BASE, L->base - | li_vmstate INTERP - | lwz PC, FRAME_PC(BASE) // Fetch PC of caller. - | sub RA, TMP1, RD // RA = L->top - nresults*8 - | st_vmstate - | b ->vm_returnc - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx); - - |.code_op - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int i; - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.long .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.long 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 65\n" - "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.long .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.long .Lframe0\n" - "\t.long .Lbegin\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x5\n\t.uleb128 70\n\t.sleb128 37\n", - (int)ctx->codesz, CFRAME_SIZE); - for (i = 14; i <= 31; i++) - fprintf(ctx->fp, - "\t.byte %d\n\t.uleb128 %d\n" - "\t.byte 5\n\t.uleb128 %d\n\t.uleb128 %d\n", - 0x80+i, 1+2*(31-i), 1200+i, 2+2*(31-i)); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE0:\n\n"); - fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe1:\n" - "\t.long .LECIE1-.LSCIE1\n" - ".LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zPR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 65\n" - "\t.uleb128 6\n" /* augmentation length */ - "\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 1\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE1:\n\n"); - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.long .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.long .LASFDE1-.Lframe1\n" - "\t.long .Lbegin-.\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x5\n\t.uleb128 70\n\t.sleb128 37\n", - (int)ctx->codesz, CFRAME_SIZE); - for (i = 14; i <= 31; i++) - fprintf(ctx->fp, - "\t.byte %d\n\t.uleb128 %d\n" - "\t.byte 5\n\t.uleb128 %d\n\t.uleb128 %d\n", - 0x80+i, 1+2*(31-i), 1200+i, 2+2*(31-i)); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE1:\n\n"); - break; - default: - break; - } -} - diff --git a/src/buildvm_ppcspe.h b/src/buildvm_ppcspe.h deleted file mode 100644 index 44fed683..00000000 --- a/src/buildvm_ppcspe.h +++ /dev/null @@ -1,6094 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM ppc version 1.3.0 -** DO NOT EDIT! The original file is in "buildvm_ppcspe.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -#define DASM_SECTION_CODE_OP 0 -#define DASM_SECTION_CODE_SUB 1 -#define DASM_MAXSECTION 2 -static const unsigned int build_actionlist[4996] = { -0x00010001, -0x00060014, -0x72000000, -0x00090200, -0x11000229, -0x000980b0, -0x41820000, -0x00050815, -0x8209fff8, -0x7d2e4b78, -0x9514fff8, -0x00060016, -0x72000000, -0x00090200, -0x398c0008, -0x7d936378, -0x41820000, -0x00050817, -0x00060018, -0x2c000000, -0x00098200, -0x56090038, -0x38000000, -0x00098200, -0x7d297050, -0x40820000, -0x00050814, -0x350cfff8, -0x91320000, -0x00098200, -0x81210018, -0x39cefff8, -0x90110000, -0x00098200, -0x55291800, -0x000900a1, -0x41820000, -0x00050802, -0x0006000b, -0x3508fff8, -0x10140301, -0x3a940008, -0x100e0321, -0x39ce0008, -0x40820000, -0x0005080b, -0x0006000c, -0x7c096000, -0x40820000, -0x00050806, -0x0006000d, -0x91d20000, -0x00098200, -0x00060019, -0x00000000, -0x80010014, -0x38600000, -0x90120000, -0x00098200, -0x0006001a, -0x800100bc, -0x81810024, -0x11c12b01, -0x11e13301, -0x12013b01, -0x12214301, -0x12414b01, -0x12615301, -0x7c0803a6, -0x7d838120, -0x12815b01, -0x12a16301, -0x12c16b01, -0x12e17301, -0x13017b01, -0x13218301, -0x13418b01, -0x13619301, -0x13819b01, -0x13a1a301, -0x13c1ab01, -0x13e1b301, -0x382100b8, -0x4e800020, -0x00060010, -0x40810000, -0x00050807, -0x81120000, -0x00098200, -0x7c0e4040, -0x40800000, -0x00050808, -0x134e0321, -0x398c0008, -0x39ce0008, -0x48000000, -0x0005000c, -0x00060011, -0x7c096050, -0x2c090000, -0x7c007050, -0x7dce009e, -0x48000000, -0x0005000d, -0x00060012, -0x91d20000, -0x00098200, -0x7d956378, -0x7d244b78, -0x7e439378, -0x48000001, -0x00030000, -0x81210018, -0x7eacab78, -0x55291800, -0x000900a1, -0x81d20000, -0x00098200, -0x48000000, -0x0005000c, -0x0006001b, -0x7c611b78, -0x7c832378, -0x0006001c, -0x82410010, -0x38000000, -0x00098200, -0x81120000, -0x00098200, -0x90080000, -0x00098200, -0x48000000, -0x0005001a, -0x0006001d, -0x00000000, -0x5461003a, -0x0006001e, -0x82410010, -0x12c00229, -0x000980b0, -0x13200229, -0x000980b0, -0x3f604338, -0x13000229, -0x000980b0, -0x38000000, -0x81d20000, -0x00098200, -0x137b022d, -0x82320000, -0x00098200, -0x12e00229, -0x000980b0, -0x39000000, -0x00098200, -0x13400229, -0x000980b0, -0x38000000, -0x00098200, -0x820efff8, -0x3a8efff8, -0x3a310000, -0x00098200, -0x91140000, -0x39800010, -0x90110000, -0x00098200, -0x48000000, -0x00050016, -0x0006001f, -0x38800000, -0x00098200, -0x48000000, -0x00050002, -0x00060020, -0x7d6e5a14, -0x7e8ea050, -0x91d20000, -0x00098200, -0x3a100004, -0x91720000, -0x00098200, -0x568400fe, -0x000900ab, -0x0006000c, -0x9201000c, -0x7e439378, -0x48000001, -0x00030000, -0x00000000, -0x81d20000, -0x00098200, -0x81720000, -0x00098200, -0x814efffc, -0x7d6e5850, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00060021, -0x9421ff48, -0x11c12b21, -0x11e13321, -0x12013b21, -0x12214321, -0x12414b21, -0x12615321, -0x7c0802a6, -0x7d800026, -0x12815b21, -0x12a16321, -0x12c16b21, -0x12e17321, -0x13017b21, -0x13218321, -0x900100bc, -0x91810024, -0x13418b21, -0x13619321, -0x13819b21, -0x13a1a321, -0x13c1ab21, -0x13e1b321, -0x7c721b78, -0x82320000, -0x00098200, -0x7c8e2378, -0x89120000, -0x00098200, -0x92410010, -0x3a000000, -0x00098200, -0x38010000, -0x00098200, -0x3a310000, -0x00098200, -0x90a10018, -0x28080000, -0x90a1001c, -0x90120000, -0x00098200, -0x90a10014, -0x9061000c, -0x41820000, -0x00050803, -0x7dd47378, -0x81d20000, -0x00098200, -0x12c00229, -0x000980b0, -0x81120000, -0x00098200, -0x13200229, -0x000980b0, -0x3f604338, -0x13000229, -0x000980b0, -0x820efff8, -0x39200000, -0x12e00229, -0x000980b0, -0x7d8e4050, -0x137b4a2d, -0x98b20000, -0x00098200, -0x72000000, -0x00090200, -0x38000000, -0x00098200, -0x398c0008, -0x13400229, -0x000980b0, -0x7d936378, -0x90110000, -0x00098200, -0x00000000, -0x41820000, -0x00050817, -0x48000000, -0x00050018, -0x00060022, -0x9421ff48, -0x11c12b21, -0x11e13321, -0x12013b21, -0x12214321, -0x12414b21, -0x12615321, -0x7c0802a6, -0x7d800026, -0x12815b21, -0x12a16321, -0x12c16b21, -0x12e17321, -0x13017b21, -0x13218321, -0x900100bc, -0x91810024, -0x13418b21, -0x13619321, -0x13819b21, -0x13a1a321, -0x13c1ab21, -0x13e1b321, -0x3a000000, -0x00098200, -0x90c1001c, -0x48000000, -0x00050001, -0x00060023, -0x9421ff48, -0x11c12b21, -0x11e13321, -0x12013b21, -0x12214321, -0x12414b21, -0x12615321, -0x7c0802a6, -0x7d800026, -0x12815b21, -0x12a16321, -0x12c16b21, -0x12e17321, -0x13017b21, -0x13218321, -0x900100bc, -0x91810024, -0x13418b21, -0x13619321, -0x13819b21, -0x13a1a321, -0x13c1ab21, -0x13e1b321, -0x3a000000, -0x00098200, -0x0006000b, -0x81030000, -0x00098200, -0x90a10018, -0x7c721b78, -0x90610010, -0x7c8e2378, -0x90320000, -0x00098200, -0x82320000, -0x00098200, -0x9061000c, -0x91010014, -0x3a310000, -0x00098200, -0x0006000d, -0x81320000, -0x00098200, -0x12c00229, -0x000980b0, -0x81120000, -0x00098200, -0x13200229, -0x000980b0, -0x7e107214, -0x13000229, -0x000980b0, -0x3f604338, -0x38000000, -0x7e098050, -0x12e00229, -0x000980b0, -0x7d6e4050, -0x137b022d, -0x38000000, -0x00098200, -0x13400229, -0x000980b0, -0x90110000, -0x00098200, -0x00060024, -0x00000000, -0x3800fff8, -0x114e0300, -0x100aca34, -0x40800000, -0x00050825, -0x00060026, -0x920efff8, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00060027, -0x9421ff48, -0x11c12b21, -0x11e13321, -0x12013b21, -0x12214321, -0x12414b21, -0x12615321, -0x7c0802a6, -0x7d800026, -0x12815b21, -0x12a16321, -0x12c16b21, -0x12e17321, -0x13017b21, -0x13218321, -0x900100bc, -0x91810024, -0x13418b21, -0x13619321, -0x13819b21, -0x13a1a321, -0x13c1ab21, -0x13e1b321, -0x7c721b78, -0x80030000, -0x00098200, -0x90610010, -0x81120000, -0x00098200, -0x9061000c, -0x7c080050, -0x81120000, -0x00098200, -0x90320000, -0x00098200, -0x39200000, -0x90010018, -0x9121001c, -0x91010014, -0x7cc903a6, -0x4e800421, -0x7c6e1b79, -0x82320000, -0x00098200, -0x3a000000, -0x00098200, -0x3a310000, -0x00098200, -0x40820000, -0x0005080d, -0x48000000, -0x00050019, -0x00060015, -0x800efff4, -0x7dca7378, -0x7d2e4b78, -0x8109fffc, -0x28000000, -0x820afff0, -0x41820000, -0x00050801, -0x392cfff8, -0x81080000, -0x00098200, -0x13544b20, -0x81e80000, -0x00098200, -0x7c0903a6, -0x4e800420, -0x0006000b, -0x390afff0, -0x7d6e4050, -0x48000000, -0x00050028, -0x00060029, -0x80f0fffc, -0x388afff0, -0x54f55d78, -0x10140301, -0x7d0eaa14, -0x91d20000, -0x00098200, -0x7c082040, -0x7ca82050, -0x54f4dd78, -0x10040321, -0x40820000, -0x0005082a, -0x00000000, -0x100ea320, -0x48000000, -0x0005002b, -0x0006002c, -0x11775a2d, -0x38b10000, -0x00098200, -0x54ea5d78, -0x11650321, -0x7c8e5214, -0x48000000, -0x00050001, -0x0006002d, -0x1158522d, -0x38910000, -0x00098200, -0x11775a2d, -0x11440321, -0x38b10000, -0x00098200, -0x11650321, -0x48000000, -0x00050001, -0x0006002e, -0x100002f1, -0x54ea5d78, -0x38b10000, -0x00098200, -0x7c8e5214, -0x10050321, -0x48000000, -0x00050001, -0x0006002f, -0x54ea5d78, -0x54eb9d78, -0x7c8e5214, -0x7cae5a14, -0x0006000b, -0x91d20000, -0x00098200, -0x7e439378, -0x9201000c, -0x48000001, -0x00030001, -0x28030000, -0x41820000, -0x00050803, -0x10030301, -0x100ea320, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000d, -0x210e0000, -0x00098200, -0x81d20000, -0x00098200, -0x920efff0, -0x7e087214, -0x814efffc, -0x39600010, -0x48000000, -0x00050026, -0x00060030, -0x11775a2d, -0x38b10000, -0x00098200, -0x00000000, -0x54ea5d78, -0x11650321, -0x7c8e5214, -0x48000000, -0x00050001, -0x00060031, -0x1158522d, -0x38910000, -0x00098200, -0x11775a2d, -0x11440321, -0x38b10000, -0x00098200, -0x11650321, -0x48000000, -0x00050001, -0x00060032, -0x100002f1, -0x54ea5d78, -0x38b10000, -0x00098200, -0x7c8e5214, -0x10050321, -0x48000000, -0x00050001, -0x00060033, -0x54ea5d78, -0x54eb9d78, -0x7c8e5214, -0x7cae5a14, -0x0006000b, -0x91d20000, -0x00098200, -0x7e439378, -0x9201000c, -0x48000001, -0x00030002, -0x28030000, -0x100ea300, -0x41820000, -0x00050803, -0x10030321, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000d, -0x210e0000, -0x00098200, -0x81d20000, -0x00098200, -0x920efff0, -0x7e087214, -0x814efffc, -0x39600018, -0x100e1321, -0x48000000, -0x00050026, -0x00060034, -0x7e439378, -0x3a10fffc, -0x7c8ea214, -0x9201000c, -0x7cae6214, -0x91d20000, -0x00098200, -0x54e6063e, -0x48000001, -0x00030003, -0x0006000d, -0x28030001, -0x41810000, -0x00050835, -0x0006000e, -0x00000000, -0x80f00000, -0x3a100004, -0x54e993ba, -0x3cd00000, -0x00098200, -0x7d293214, -0x7e10481e, -0x0006002b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00060036, -0x80f0fffc, -0x10140301, -0x54e8dd78, -0x100e4320, -0x48000000, -0x0005002b, -0x00060037, -0x80140000, -0x39000000, -0x00098200, -0x7c080040, -0x48000000, -0x0005000e, -0x00060038, -0x80140000, -0x39000000, -0x00098200, -0x7c004040, -0x48000000, -0x0005000e, -0x00060039, -0x3a10fffc, -0x91d20000, -0x00098200, -0x7e439378, -0x9201000c, -0x48000001, -0x00030004, -0x48000000, -0x0005000d, -0x0006003a, -0x7cae5214, -0x7ccf5a14, -0x48000000, -0x00050001, -0x0006003b, -0x7caf5a14, -0x7cce5214, -0x48000000, -0x00050001, -0x0006003c, -0x7cae6214, -0x7ca62b78, -0x48000000, -0x00050001, -0x0006003d, -0x7cae5214, -0x7cce5a14, -0x0006000b, -0x00000000, -0x7c8ea214, -0x91d20000, -0x00098200, -0x7e439378, -0x9201000c, -0x54e7063e, -0x48000001, -0x00030005, -0x28030000, -0x41820000, -0x0005082b, -0x00060035, -0x7d0e1850, -0x9203fff0, -0x7dc97378, -0x3a080000, -0x00098200, -0x7c6e1b78, -0x39600010, -0x48000000, -0x00050024, -0x0006003e, -0x00000000, -0x7c751b78, -0x00000000, -0x7c8e6214, -0x91d20000, -0x00098200, -0x7e439378, -0x9201000c, -0x48000001, -0x00030006, -0x00000000, -0x28030000, -0x40820000, -0x00050835, -0x7ea3ab78, -0x48000000, -0x0005003f, -0x00000000, -0x48000000, -0x00050035, -0x00000000, -0x00060025, -0x7e439378, -0x91320000, -0x00098200, -0x388efff8, -0x9201000c, -0x7cae5a14, -0x7d755b78, -0x48000001, -0x00030007, -0x814efffc, -0x39750008, -0x920efff8, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00060040, -0x7e439378, -0x91d20000, -0x00098200, -0x3894fff8, -0x9201000c, -0x7cb45a14, -0x7d755b78, -0x48000001, -0x00030007, -0x810efff8, -0x39750008, -0x8154fffc, -0x48000000, -0x00050041, -0x00060042, -0x7e439378, -0x91d20000, -0x00098200, -0x7e84a378, -0x9201000c, -0x7cf53b78, -0x48000001, -0x00030008, -0x00000000, -0x56a0063e, -0x00000000, -0x56b4dd78, -0x00000000, -0x2c000000, -0x00098200, -0x00000000, -0x56ac9b78, -0x00000000, -0x41820000, -0x00070800, -0x00000000, -0x48000000, -0x00070000, -0x00060043, -0x280b0008, -0x100e0301, -0x41800000, -0x00050844, -0x111ad200, -0x3a8efff8, -0x10804232, -0x820efff8, -0x40840000, -0x00050844, -0x10140321, -0x398b0008, -0x41820000, -0x00050845, -0x39000008, -0x396bfff8, -0x0006000b, -0x7c085840, -0x100e4300, -0x10144320, -0x39080008, -0x40820000, -0x0005080b, -0x48000000, -0x00050045, -0x00060046, -0x280b0008, -0x806e0000, -0x41800000, -0x00050844, -0x39200000, -0x00098200, -0x7c03b040, -0x7c6818f8, -0x7d09401e, -0x55081800, -0x000900a1, -0x392a0000, -0x00098200, -0x10694300, -0x48000000, -0x00050047, -0x00060048, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003c234, -0x11031a2c, -0x40800000, -0x00050806, -0x0006000b, -0x81430000, -0x00098200, -0x0006000c, -0x107ad217, -0x280a0000, -0x81710000, -0x00098200, -0x41820000, -0x00050847, -0x00000000, -0x800a0000, -0x00098200, -0x1078522d, -0x810b0000, -0x00098200, -0x812a0000, -0x00098200, -0x11775a2d, -0x7d080038, -0x55002800, -0x000900a1, -0x55081800, -0x000900a1, -0x7d080050, -0x7d294214, -0x0006000d, -0x10090301, -0x00090cab, -0x11090301, -0x00090cab, -0x10005a34, -0x81290000, -0x00098200, -0x41830000, -0x00050805, -0x28090000, -0x41820000, -0x00050847, -0x48000000, -0x0005000d, -0x0006000f, -0x1008d234, -0x41800000, -0x00050847, -0x10684217, -0x48000000, -0x00050047, -0x00060010, -0x2c080000, -0x00098200, -0x7d0840f8, -0x41820000, -0x0005080b, -0x1003b232, -0x55081000, -0x000900a1, -0x39200000, -0x00098200, -0x7d09401e, -0x39310000, -0x00098200, -0x7d49402e, -0x48000000, -0x0005000c, -0x00060049, -0x00000000, -0x280b0010, -0x106e0301, -0x108e0b01, -0x41800000, -0x00050844, -0x1003222c, -0x1000c234, -0x40830000, -0x00050844, -0x81030000, -0x00098200, -0x28080000, -0x88c30000, -0x00098200, -0x40820000, -0x00050844, -0x70c00000, -0x00090200, -0x90830000, -0x00098200, -0x41820000, -0x00050847, -0x80110000, -0x00098200, -0x54c607b8, -0x90710000, -0x00098200, -0x98c30000, -0x00098200, -0x90030000, -0x00098200, -0x48000000, -0x00050047, -0x0006004a, -0x280b0010, -0x108e0301, -0x41800000, -0x00050844, -0x1004c234, -0x38ae0008, -0x40800000, -0x00050844, -0x7e439378, -0x48000001, -0x00030009, -0x10630301, -0x48000000, -0x00050047, -0x0006004b, -0x280b0008, -0x106e0301, -0x40820000, -0x00050844, -0x1003b232, -0x41800000, -0x00050847, -0x48000000, -0x00050044, -0x0006004c, -0x00000000, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003ba34, -0x41800000, -0x00050847, -0x80110000, -0x00098200, -0x1003b232, -0x28800000, -0x91d20000, -0x00098200, -0x4c403202, -0x9201000c, -0x40820000, -0x00050844, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x0005084d, -0x7e439378, -0x7dc47378, -0x48000001, -0x0003000a, -0x10771a2d, -0x48000000, -0x00050047, -0x0006004e, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x134e5b20, -0x1004c234, -0x820efff8, -0x40800000, -0x00050844, -0x91d20000, -0x00098200, -0x7e439378, -0x91d20000, -0x00098200, -0x38ae0008, -0x9201000c, -0x48000001, -0x0003000b, -0x28030000, -0x107ad217, -0x41820000, -0x00050847, -0x100e0b01, -0x3a8efff8, -0x110e1301, -0x10140321, -0x39800000, -0x00098200, -0x11140b21, -0x48000000, -0x00050045, -0x0006004f, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003c234, -0x820efff8, -0x40800000, -0x00050844, -0x00000000, -0x81230000, -0x00098200, -0x100a0301, -0x00090cab, -0x28090000, -0x3a8efff8, -0x40820000, -0x00050844, -0x00000000, -0x100a0301, -0x00090cab, -0x3a8efff8, -0x00000000, -0x134e0b21, -0x39800000, -0x00098200, -0x10140321, -0x48000000, -0x00050045, -0x00060050, -0x280b0010, -0x106e0301, -0x108e0b01, -0x41800000, -0x00050844, -0x1003c234, -0x820efff8, -0x40800000, -0x00050844, -0x1004b232, -0x3cc03ff0, -0x40800000, -0x00050844, -0x112022f5, -0x80030000, -0x00098200, -0x10c6da2d, -0x81030000, -0x00098200, -0x108432e0, -0x39290001, -0x3a8efff8, -0x7c004840, -0x55261800, -0x000900a1, -0x10940321, -0x40810000, -0x00050802, -0x11083300, -0x0006000b, -0x1008d234, -0x39800000, -0x00098200, -0x41800000, -0x00050845, -0x39800000, -0x00098200, -0x11140b21, -0x48000000, -0x00050045, -0x0006000c, -0x80030000, -0x00098200, -0x28000000, -0x39800000, -0x00098200, -0x41820000, -0x00050845, -0x7d244b78, -0x48000001, -0x0003000c, -0x28030000, -0x39800000, -0x00098200, -0x41820000, -0x00050845, -0x00000000, -0x11030301, -0x48000000, -0x0005000b, -0x00060051, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003c234, -0x820efff8, -0x40800000, -0x00050844, -0x00000000, -0x81230000, -0x00098200, -0x100a0301, -0x00090cab, -0x28090000, -0x3a8efff8, -0x40820000, -0x00050844, -0x00000000, -0x100a0301, -0x00090cab, -0x3a8efff8, -0x00000000, -0x11000229, -0x39800000, -0x00098200, -0x110e0b21, -0x10140321, -0x48000000, -0x00050045, -0x00060052, -0x280b0008, -0x88d10000, -0x00098200, -0x41800000, -0x00050844, -0x7dc97378, -0x39ce0008, -0x54c607fe, -0x000900ab, -0x396bfff8, -0x3a060000, -0x00098200, -0x48000000, -0x00050024, -0x00060053, -0x280b0010, -0x106e0301, -0x108e0b01, -0x41800000, -0x00050844, -0x88d10000, -0x00098200, -0x7dc97378, -0x1004ca34, -0x40800000, -0x00050844, -0x39ce0010, -0x54c607fe, -0x000900ab, -0x10890321, -0x396bfff0, -0x10690b21, -0x3a060000, -0x00098200, -0x48000000, -0x00050024, -0x00060054, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x10031a2c, -0x2c000000, -0x00098200, -0x40820000, -0x00050844, -0x88030000, -0x00098200, -0x81030000, -0x00098200, -0x80830000, -0x00098200, -0x00000000, -0x28000000, -0x00090200, -0x81230000, -0x00098200, -0x28880000, -0x80030000, -0x00098200, -0x7f844840, -0x820efff8, -0x4f013342, -0x7d245a14, -0x4f3e1102, -0x7c890040, -0x4f18cb82, -0x9201000c, -0x4f182b82, -0x91d20000, -0x00098200, -0x41980000, -0x00050844, -0x0006000b, -0x39ce0008, -0x396bfff8, -0x3929fff8, -0x91230000, -0x00098200, -0x39000000, -0x91d20000, -0x00098200, -0x0006000c, -0x7c085800, -0x100e4300, -0x41820000, -0x00050803, -0x10044320, -0x39080008, -0x48000000, -0x0005000c, -0x0006000d, -0x38a00000, -0x7c751b78, -0x38c00000, -0x48000001, -0x00050021, -0x0006000e, -0x81350000, -0x00098200, -0x28030000, -0x00090200, -0x80d50000, -0x00098200, -0x38000000, -0x00098200, -0x81d20000, -0x00098200, -0x90110000, -0x00098200, -0x41810000, -0x00050808, -0x7d893050, -0x80120000, -0x00098200, -0x00000000, -0x280c0000, -0x7d0e6214, -0x41820000, -0x00050806, -0x7c080040, -0x39000000, -0x41810000, -0x00050809, -0x38ccfff8, -0x91350000, -0x00098200, -0x0006000f, -0x7c083040, -0x10094300, -0x100e4320, -0x39080008, -0x40820000, -0x0005080f, -0x00060010, -0x72000000, -0x00090200, -0x39000000, -0x00098200, -0x3a8efff8, -0x910efff8, -0x398c0010, -0x00060011, -0x9201000c, -0x7d936378, -0x41820000, -0x00050817, -0x48000000, -0x00050018, -0x00060012, -0x72000000, -0x00090200, -0x38c6fff8, -0x39000000, -0x00098200, -0x10060301, -0x90d50000, -0x00098200, -0x39800000, -0x00098200, -0x910efff8, -0x3a8efff8, -0x100e0321, -0x48000000, -0x00050011, -0x00060013, -0x7e439378, -0x558400fe, -0x000900ab, -0x48000001, -0x00030000, -0x38600000, -0x48000000, -0x0005000e, -0x00060055, -0x00000000, -0x806a0000, -0x00098200, -0x88030000, -0x00098200, -0x81030000, -0x00098200, -0x80830000, -0x00098200, -0x28000000, -0x00090200, -0x81230000, -0x00098200, -0x28880000, -0x80030000, -0x00098200, -0x7f844840, -0x820efff8, -0x4f013342, -0x7d245a14, -0x4f3e1102, -0x7c890040, -0x4f18cb82, -0x9201000c, -0x4f182b82, -0x91d20000, -0x00098200, -0x41980000, -0x00050844, -0x0006000b, -0x91230000, -0x00098200, -0x39000000, -0x91d20000, -0x00098200, -0x0006000c, -0x7c085800, -0x100e4300, -0x41820000, -0x00050803, -0x10044320, -0x39080008, -0x48000000, -0x0005000c, -0x0006000d, -0x38a00000, -0x7c751b78, -0x38c00000, -0x48000001, -0x00050021, -0x0006000e, -0x81350000, -0x00098200, -0x28030000, -0x00090200, -0x80d50000, -0x00098200, -0x38000000, -0x00098200, -0x00000000, -0x81d20000, -0x00098200, -0x90110000, -0x00098200, -0x41810000, -0x00050808, -0x7d893050, -0x80120000, -0x00098200, -0x280c0000, -0x7d0e6214, -0x41820000, -0x00050806, -0x7c080040, -0x39000000, -0x41810000, -0x00050809, -0x38ccfff8, -0x91350000, -0x00098200, -0x0006000f, -0x7c083040, -0x10094300, -0x100e4320, -0x39080008, -0x40820000, -0x0005080f, -0x00060010, -0x72000000, -0x00090200, -0x7dd47378, -0x398c0008, -0x00060011, -0x9201000c, -0x7d936378, -0x41820000, -0x00050817, -0x48000000, -0x00050018, -0x00060012, -0x7e439378, -0x7ea4ab78, -0x48000001, -0x0003000d, -0x00060013, -0x7e439378, -0x558400fe, -0x000900ab, -0x48000001, -0x00030000, -0x38600000, -0x48000000, -0x0005000e, -0x00060056, -0x80120000, -0x00098200, -0x00000000, -0x7d0e5a14, -0x91d20000, -0x00098200, -0x70000000, -0x00090200, -0x91120000, -0x00098200, -0x38600000, -0x00098200, -0x41820000, -0x00050844, -0x93720000, -0x00098200, -0x98720000, -0x00098200, -0x48000000, -0x0005001a, -0x00060057, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003b232, -0x40800000, -0x00050844, -0x106302e4, -0x00060047, -0x820efff8, -0x3a8efff8, -0x10740321, -0x00060058, -0x39800000, -0x00098200, -0x00060045, -0x72000000, -0x00090200, -0x7d936378, -0x40820000, -0x00050818, -0x80f0fffc, -0x54ea5d78, -0x0006000f, -0x7c0a6040, -0x54e0dd78, -0x41810000, -0x00050806, -0x80f00000, -0x3a100004, -0x7dc0a050, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00060010, -0x390cfff8, -0x398c0008, -0x13544320, -0x48000000, -0x0005000f, -0x00060059, -0x00000000, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x820efff8, -0x48000001, -0x0005005a, -0x3a8efff8, -0x10940321, -0x48000000, -0x00050058, -0x0006005b, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x820efff8, -0x48000001, -0x0005005c, -0x3a8efff8, -0x10940321, -0x48000000, -0x00050058, -0x0006005d, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x0003000e, -0x1063222d, -0x48000000, -0x00050047, -0x0006005e, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x0003000f, -0x1063222d, -0x48000000, -0x00050047, -0x0006005f, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x00000000, -0x48000001, -0x00030010, -0x1063222d, -0x48000000, -0x00050047, -0x00060060, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x00030011, -0x1063222d, -0x48000000, -0x00050047, -0x00060061, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x00030012, -0x1063222d, -0x48000000, -0x00050047, -0x00060062, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x00030013, -0x1063222d, -0x48000000, -0x00050047, -0x00060063, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x00030014, -0x1063222d, -0x48000000, -0x00050047, -0x00060064, -0x00000000, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x00030015, -0x1063222d, -0x48000000, -0x00050047, -0x00060065, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x00030016, -0x1063222d, -0x48000000, -0x00050047, -0x00060066, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x00030017, -0x1063222d, -0x48000000, -0x00050047, -0x00060067, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x00030018, -0x1063222d, -0x48000000, -0x00050047, -0x00060068, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x00000000, -0x48000001, -0x00030019, -0x1063222d, -0x48000000, -0x00050047, -0x00060069, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x48000001, -0x0003001a, -0x1063222d, -0x48000000, -0x00050047, -0x0006006a, -0x280b0010, -0x108e0301, -0x10ce0b01, -0x41800000, -0x00050844, -0x1066222c, -0x1003b232, -0x10a6322c, -0x40830000, -0x00050844, -0x48000001, -0x0003001b, -0x1063222d, -0x48000000, -0x00050047, -0x0006006b, -0x280b0010, -0x108e0301, -0x10ce0b01, -0x41800000, -0x00050844, -0x1066222c, -0x1003b232, -0x10a6322c, -0x40830000, -0x00050844, -0x48000001, -0x0003001c, -0x1063222d, -0x48000000, -0x00050047, -0x0006006c, -0x280b0010, -0x108e0301, -0x10ce0b01, -0x41800000, -0x00050844, -0x1066222c, -0x1003b232, -0x10a6322c, -0x40830000, -0x00050844, -0x48000001, -0x0003001d, -0x1063222d, -0x48000000, -0x00050047, -0x0006006d, -0x0006006e, -0x00000000, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003b232, -0x40800000, -0x00050844, -0x108a0301, -0x00090cab, -0x106322e8, -0x48000000, -0x00050047, -0x0006006f, -0x280b0010, -0x108e0301, -0x10ce0b01, -0x41800000, -0x00050844, -0x1066222c, -0x1003b232, -0x40830000, -0x00050844, -0x10a032f5, -0x48000001, -0x0003001e, -0x1063222d, -0x48000000, -0x00050047, -0x00060070, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x38b10000, -0x00098200, -0x820efff8, -0x48000001, -0x0003001f, -0x81110000, -0x00098200, -0x1063222d, -0x108042f1, -0x3a8efff8, -0x10740321, -0x39800000, -0x00098200, -0x10940b21, -0x48000000, -0x00050045, -0x00060071, -0x280b0008, -0x108e0301, -0x41800000, -0x00050844, -0x1004b232, -0x1064222c, -0x40800000, -0x00050844, -0x38aefff8, -0x820efff8, -0x48000001, -0x00030020, -0x1063222d, -0x3a8efff8, -0x106e0321, -0x39800000, -0x00098200, -0x00000000, -0x48000000, -0x00050045, -0x00060072, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003b232, -0x39000008, -0x40800000, -0x00050844, -0x0006000b, -0x108e4300, -0x7c885840, -0x1004b232, -0x40840000, -0x00050847, -0x40800000, -0x00050844, -0x10041afd, -0x39080008, -0x4c010b82, -0x10641a78, -0x48000000, -0x0005000b, -0x00060073, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003b232, -0x39000008, -0x40800000, -0x00050844, -0x0006000b, -0x108e4300, -0x7c885840, -0x1004b232, -0x40840000, -0x00050847, -0x40800000, -0x00050844, -0x10041afc, -0x39080008, -0x4c010b82, -0x10641a78, -0x48000000, -0x0005000b, -0x00060074, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003ba34, -0x40800000, -0x00050844, -0x80030000, -0x00098200, -0x106002f1, -0x48000000, -0x00050047, -0x00060075, -0x280b0008, -0x106e0301, -0x40820000, -0x00050844, -0x00000000, -0x1003ba34, -0x3a8efff8, -0x40800000, -0x00050844, -0x80030000, -0x00098200, -0x39800000, -0x00098200, -0x89030000, -0x00098200, -0x39200000, -0x00098200, -0x28000000, -0x820efff8, -0x106042f1, -0x7d8c489e, -0x10740321, -0x48000000, -0x00050045, -0x00060076, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x0005084d, -0x280b0008, -0x106e0301, -0x40820000, -0x00050844, -0x1003b232, -0x38910000, -0x00098200, -0x40800000, -0x00050844, -0x10001afa, -0x38a00001, -0x280000ff, -0x98040000, -0x41810000, -0x00050844, -0x00060077, -0x7e439378, -0x91d20000, -0x00098200, -0x9201000c, -0x48000001, -0x00030021, -0x81d20000, -0x00098200, -0x10771a2d, -0x48000000, -0x00050047, -0x00060078, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x00000000, -0x7c004040, -0x40800001, -0x0005084d, -0x280b0010, -0x10ae1301, -0x106e0301, -0x41800000, -0x00050844, -0x108e0b01, -0x3920ffff, -0x41820000, -0x00050801, -0x1005b232, -0x40800000, -0x00050844, -0x11202afa, -0x0006000b, -0x1004b232, -0x40800000, -0x00050844, -0x1003ba34, -0x110022fa, -0x40800000, -0x00050844, -0x80030000, -0x00098200, -0x7c004840, -0x7cc90214, -0x41800000, -0x00050805, -0x0006000c, -0x2c080000, -0x7cc80214, -0x40810000, -0x00050807, -0x0006000d, -0x7ca84851, -0x38830000, -0x00098200, -0x38a50001, -0x7c844214, -0x7ca0281e, -0x48000000, -0x00050077, -0x0006000f, -0x7c004800, -0x38c60001, -0x7d26005e, -0x48000000, -0x0005000c, -0x00060011, -0x2c860000, -0x7d00309e, -0x7d00411e, -0x39080001, -0x48000000, -0x0005000d, -0x00060079, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x0005084d, -0x00000000, -0x280b0010, -0x106e0301, -0x108e0b01, -0x41800000, -0x00050844, -0x1004b232, -0x40800000, -0x00050844, -0x1003ba34, -0x10a022fa, -0x40800000, -0x00050844, -0x80030000, -0x00098200, -0x2c050000, -0x81110000, -0x00098200, -0x40810000, -0x00050802, -0x28000001, -0x3925ffff, -0x41800000, -0x00050802, -0x7c882840, -0x40820000, -0x00050844, -0x88030000, -0x00098200, -0x80910000, -0x00098200, -0x41840000, -0x00050844, -0x0006000b, -0x28090000, -0x7c0449ae, -0x3929ffff, -0x40820000, -0x0005080b, -0x48000000, -0x00050077, -0x0006000c, -0x38710000, -0x00098200, -0x10771a2d, -0x48000000, -0x00050047, -0x0006007a, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x0005084d, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x00000000, -0x1003ba34, -0x81110000, -0x00098200, -0x40800000, -0x00050844, -0x80a30000, -0x00098200, -0x38630000, -0x00098200, -0x80910000, -0x00098200, -0x39200000, -0x7c082840, -0x38c5ffff, -0x41800000, -0x00050844, -0x0006000b, -0x2c060000, -0x7d0348ae, -0x41800000, -0x00050877, -0x7d0431ae, -0x38c6ffff, -0x39290001, -0x48000000, -0x0005000b, -0x0006007b, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x0005084d, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003ba34, -0x81110000, -0x00098200, -0x40800000, -0x00050844, -0x80a30000, -0x00098200, -0x38630000, -0x00098200, -0x80910000, -0x00098200, -0x7c082840, -0x39200000, -0x41800000, -0x00050844, -0x0006000b, -0x7c092840, -0x7d0348ae, -0x40800000, -0x00050877, -0x00000000, -0x3808ffbf, -0x69060020, -0x2800001a, -0x7d06401e, -0x7d0449ae, -0x39290001, -0x48000000, -0x0005000b, -0x0006007c, -0x80110000, -0x00098200, -0x81110000, -0x00098200, -0x7c004040, -0x40800001, -0x0005084d, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003ba34, -0x81110000, -0x00098200, -0x40800000, -0x00050844, -0x80a30000, -0x00098200, -0x38630000, -0x00098200, -0x80910000, -0x00098200, -0x7c082840, -0x39200000, -0x41800000, -0x00050844, -0x0006000b, -0x7c092840, -0x7d0348ae, -0x40800000, -0x00050877, -0x3808ff9f, -0x69060020, -0x2800001a, -0x7d06401e, -0x7d0449ae, -0x39290001, -0x48000000, -0x0005000b, -0x0006007d, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003c234, -0x40800000, -0x00050844, -0x48000001, -0x00030022, -0x10601af1, -0x48000000, -0x00050047, -0x0006007e, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x00000000, -0x1003b232, -0x40800000, -0x00050844, -0x1063dae0, -0x0006007f, -0x10601af1, -0x48000000, -0x00050047, -0x00060080, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003b232, -0x40800000, -0x00050844, -0x1063dae0, -0x39000008, -0x0006000b, -0x108e4300, -0x7c885840, -0x1004b232, -0x40840000, -0x0005087f, -0x40800000, -0x00050844, -0x1084dae0, -0x7c632038, -0x39080008, -0x48000000, -0x0005000b, -0x00060081, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003b232, -0x40800000, -0x00050844, -0x1063dae0, -0x39000008, -0x0006000b, -0x108e4300, -0x7c885840, -0x1004b232, -0x40840000, -0x0005087f, -0x40800000, -0x00050844, -0x1084dae0, -0x7c632378, -0x39080008, -0x48000000, -0x0005000b, -0x00060082, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003b232, -0x40800000, -0x00050844, -0x1063dae0, -0x39000008, -0x0006000b, -0x108e4300, -0x7c885840, -0x1004b232, -0x40840000, -0x0005087f, -0x00000000, -0x40800000, -0x00050844, -0x1084dae0, -0x7c632278, -0x39080008, -0x48000000, -0x0005000b, -0x00060083, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003b232, -0x40800000, -0x00050844, -0x1063dae0, -0x5460403e, -0x5060c00e, -0x5060c42e, -0x106002f1, -0x48000000, -0x00050047, -0x00060084, -0x280b0008, -0x106e0301, -0x41800000, -0x00050844, -0x1003b232, -0x40800000, -0x00050844, -0x1063dae0, -0x7c6018f8, -0x106002f1, -0x48000000, -0x00050047, -0x00060085, -0x280b0010, -0x106e0301, -0x108e0b01, -0x41800000, -0x00050844, -0x1003222c, -0x1000b232, -0x40830000, -0x00050844, -0x1084dae0, -0x1063dae0, -0x548406fe, -0x7c602030, -0x106002f1, -0x48000000, -0x00050047, -0x00060086, -0x280b0010, -0x106e0301, -0x108e0b01, -0x41800000, -0x00050844, -0x1003222c, -0x1000b232, -0x40830000, -0x00050844, -0x1084dae0, -0x1063dae0, -0x548406fe, -0x7c602430, -0x106002f1, -0x48000000, -0x00050047, -0x00060087, -0x280b0010, -0x106e0301, -0x108e0b01, -0x41800000, -0x00050844, -0x1003222c, -0x1000b232, -0x40830000, -0x00050844, -0x1084dae0, -0x1063dae0, -0x548406fe, -0x7c602630, -0x106002f1, -0x48000000, -0x00050047, -0x00060088, -0x00000000, -0x280b0010, -0x106e0301, -0x108e0b01, -0x41800000, -0x00050844, -0x1003222c, -0x1000b232, -0x40830000, -0x00050844, -0x1084dae0, -0x1063dae0, -0x5c60203e, -0x106002f1, -0x48000000, -0x00050047, -0x00060089, -0x280b0010, -0x106e0301, -0x108e0b01, -0x41800000, -0x00050844, -0x1003222c, -0x1000b232, -0x40830000, -0x00050844, -0x1084dae0, -0x1063dae0, -0x7c8400d0, -0x5c60203e, -0x106002f1, -0x48000000, -0x00050047, -0x00060044, -0x80ca0000, -0x00098200, -0x7d0e5a14, -0x820efff8, -0x38080000, -0x00098200, -0x81320000, -0x00098200, -0x9201000c, -0x7c004840, -0x91d20000, -0x00098200, -0x91120000, -0x00098200, -0x7e439378, -0x41810000, -0x00050805, -0x7cc903a6, -0x4e800421, -0x81d20000, -0x00098200, -0x2c030000, -0x546c1800, -0x000900a1, -0x3a8efff8, -0x41810000, -0x00050845, -0x0006000b, -0x80120000, -0x00098200, -0x814efffc, -0x7d6e0050, -0x40820000, -0x00050828, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00060028, -0x00000000, -0x72000000, -0x00090200, -0x56080038, -0x40820000, -0x00050803, -0x80f0fffc, -0x54e8dd78, -0x39080008, -0x0006000d, -0x7d287050, -0x48000000, -0x00050024, -0x0006000f, -0x38800000, -0x00098200, -0x48000001, -0x00030000, -0x81d20000, -0x00098200, -0x7c000000, -0x48000000, -0x0005000b, -0x0006004d, -0x7ea802a6, -0x91d20000, -0x00098200, -0x7c0e5a14, -0x9201000c, -0x90120000, -0x00098200, -0x7e439378, -0x48000001, -0x00030023, -0x81d20000, -0x00098200, -0x7ea803a6, -0x80120000, -0x00098200, -0x7d6e0050, -0x814efffc, -0x4e800020, -0x0006008a, -0x00000000, -0x7c810808, -0x00000000, -0x0006008b, -0x88d10000, -0x00098200, -0x70c00000, -0x00090200, -0x41820000, -0x00050801, -0x0006000f, -0x39080000, -0x00098200, -0x7c11402e, -0x7c0903a6, -0x4e800420, -0x0006008c, -0x88d10000, -0x00098200, -0x81310000, -0x00098200, -0x70c00000, -0x00090200, -0x54c007c0, -0x000900ab, -0x40820000, -0x0005080f, -0x2c800000, -0x3529ffff, -0x41860000, -0x0005080f, -0x91310000, -0x00098200, -0x41820000, -0x00050801, -0x40840000, -0x0005080f, -0x0006000b, -0x7e439378, -0x92610008, -0x7e048378, -0x91d20000, -0x00098200, -0x48000001, -0x00030024, -0x0006000d, -0x81d20000, -0x00098200, -0x0006000e, -0x00000000, -0x80f0fffc, -0x54e815ba, -0x54ea5d78, -0x39080000, -0x00098200, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006008d, -0x3a100004, -0x826affec, -0x48000000, -0x0005000e, -0x0006008e, -0x00000000, -0x7c810808, -0x00000000, -0x0006008f, -0x7e048378, -0x00000000, -0x48000000, -0x00050001, -0x00000000, -0x00060090, -0x00000000, -0x62040001, -0x0006000b, -0x00000000, -0x7c0e5a14, -0x9201000c, -0x7e439378, -0x91d20000, -0x00098200, -0x7e8ea050, -0x90120000, -0x00098200, -0x48000001, -0x00030025, -0x81d20000, -0x00098200, -0x80120000, -0x00098200, -0x9361000c, -0x7d6e0050, -0x7e8ea214, -0x814efffc, -0x7c6903a6, -0x4e800420, -0x00060091, -0x00000000, -0x7c810808, -0x00000000, -0x00060092, -0x00000000, -0x7c810808, -0x00000000, -0x00060093, -0x7ca802a6, -0x48000001, -0x0005005a, -0x7ca803a6, -0x1064222c, -0x4e800020, -0x00060094, -0x1064222c, -0x0006005a, -0x5469657e, -0x3529fc01, -0x3900ffff, -0x28890033, -0x20090034, -0x41850000, -0x00050801, -0x3cc0fff0, -0x7d000030, -0x7cc84e30, -0x7c890078, -0x7c664078, -0x7d293378, -0x7c66fe70, -0x7d293039, -0x7c840038, -0x7c634038, -0x7c002010, -0x7c04009e, -0x7d081910, -0x7d03409e, -0x1088022d, -0x4e800020, -0x0006000b, -0x4d810020, -0x5469007e, -0x7c60fe70, -0x7d292378, -0x3d003ff0, -0x7d290039, -0x38000000, -0x7d00409e, -0x5103007e, -0x1083022d, -0x4e800020, -0x00060095, -0x1064222c, -0x0006005c, -0x5469657e, -0x3529fc01, -0x3900ffff, -0x28890033, -0x20090034, -0x41850000, -0x00050801, -0x3cc0fff0, -0x7d000030, -0x7cc84e30, -0x7c890078, -0x7c664078, -0x7d293378, -0x7c66fe70, -0x7d293079, -0x7c840038, -0x7c634038, -0x7c002010, -0x7c04009e, -0x7d081910, -0x7d03409e, -0x1088022d, -0x4e800020, -0x0006000b, -0x4d810020, -0x5469007e, -0x7c60fe70, -0x7d292378, -0x3d003ff0, -0x7d290079, -0x38000000, -0x7d00409e, -0x5103007e, -0x1083022d, -0x4e800020, -0x00000000, -0x00060096, -0x1064222c, -0x00060097, -0x5469657e, -0x3529fc01, -0x3900ffff, -0x28890033, -0x20090034, -0x41850000, -0x00050801, -0x3cc0fff0, -0x7d000030, -0x7cc84e30, -0x1008022d, -0x10840211, -0x4e800020, -0x0006000b, -0x4d810020, -0x54680000, -0x38000000, -0x1088022d, -0x4e800020, -0x00000000, -0x00060096, -0x00060097, -0x00000000, -0x00060098, -0x1083222d, -0x28070001, -0x10c5322d, -0x41820000, -0x00050801, -0x41810000, -0x00050802, -0x108432e0, -0x1064222c, -0x4e800020, -0x0006000b, -0x108432e1, -0x1064222c, -0x4e800020, -0x0006000c, -0x28070003, -0x41820000, -0x00050801, -0x41810000, -0x00050802, -0x108432e8, -0x1064222c, -0x4e800020, -0x0006000b, -0x108432e9, -0x1064222c, -0x4e800020, -0x0006000c, -0x28070005, -0x41820000, -0x00050801, -0x41810000, -0x00050802, -0x10a42217, -0x108432e9, -0x11463217, -0x7d6802a6, -0x48000001, -0x00050094, -0x7d6803a6, -0x108452e8, -0x108522e1, -0x1064222c, -0x4e800020, -0x0006000b, -0x48000000, -0x0003001b, -0x0006000c, -0x28070007, -0x41820000, -0x00050801, -0x41810000, -0x00050802, -0x6c638000, -0x4e800020, -0x0006000b, -0x5463007e, -0x4e800020, -0x0006000c, -0x7c810808, -0x00060099, -0x00000000, -0x7c810808, -0x00000000, -0x00080000, -0x00000000, -0x100ea300, -0x3a100004, -0x110e6300, -0x3cd00000, -0x00098200, -0x8130fffc, -0x1140422c, -0x552993ba, -0x100ab232, -0x7d293214, -0x40830000, -0x00050834, -0x100042ed, -0x00000000, -0x108042ee, -0x4c212b82, -0x00000000, -0x7e09805e, -0x00000000, -0x7e10485e, -0x00000000, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x108ea300, -0x3a100004, -0x10ae6300, -0x3cd00000, -0x00098200, -0x8130fffc, -0x11442a2c, -0x552993ba, -0x100ab232, -0x7d293214, -0x40830000, -0x00050805, -0x10042aee, -0x00000000, -0x7e09805e, -0x00000000, -0x7e10485e, -0x00000000, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000f, -0x10042a34, -0x7d4650f8, -0x28860000, -0x00090200, -0x4f830342, -0x2b060000, -0x00090200, -0x4fa02902, -0x7e158378, -0x00000000, -0x7e09875e, -0x00000000, -0x7d304f5e, -0x00000000, -0x4f9ceb82, -0x00000000, -0x7e0980de, -0x00000000, -0x7e1048de, -0x00000000, -0x419c0000, -0x0005080b, -0x41980000, -0x0005080b, -0x81240000, -0x00098200, -0x38c00000, -0x00098200, -0x28090000, -0x41820000, -0x0005080b, -0x89290000, -0x00098200, -0x71290000, -0x00090200, -0x40820000, -0x0005080b, -0x7eb0ab78, -0x48000000, -0x00050039, -0x00000000, -0x100ea300, -0x558c007e, -0x000900ab, -0x80f00000, -0x218cfffc, -0x3a100004, -0x7d0f602e, -0x3cd00000, -0x00098200, -0x54e993ba, -0x1117422d, -0x7d293214, -0x10004234, -0x00000000, -0x7e0980de, -0x00000000, -0x7e1048de, -0x00000000, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x100ea300, -0x3a100004, -0x110f6300, -0x3cd00000, -0x00098200, -0x80f0fffc, -0x1000b232, -0x40800000, -0x00050805, -0x100042ee, -0x0006000b, -0x54e993ba, -0x7d293214, -0x00000000, -0x7e09805e, -0x0006000f, -0x00000000, -0x7e10485e, -0x00000000, -0x0006000d, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x0006000f, -0x54e993ba, -0x7e093214, -0x48000000, -0x0005000d, -0x00000000, -0x7c0ea02e, -0x558800fe, -0x000900ab, -0x80f00000, -0x3a100004, -0x7d0840f8, -0x3cd00000, -0x00098200, -0x7c004040, -0x54e993ba, -0x7d293214, -0x00000000, -0x7e09809e, -0x00000000, -0x7e10489e, -0x00000000, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x100e6300, -0x111ad200, -0x80f00000, -0x10004232, -0x3a100004, -0x00000000, -0x3cd00000, -0x00098200, -0x54e993ba, -0x7d293214, -0x00000000, -0x7e09801e, -0x00000000, -0x7e10481e, -0x00000000, -0x40800000, -0x00050801, -0x00000000, -0x41800000, -0x00050801, -0x00000000, -0x3e100000, -0x00098200, -0x54e993ba, -0x100ea320, -0x7e104a14, -0x0006000b, -0x00000000, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x80f00000, -0x3a100004, -0x100e6300, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x80f00000, -0x3a100004, -0x7c0e602e, -0x21000000, -0x00098200, -0x7c004114, -0x7c0ea12e, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x100e6300, -0x1000b232, -0x40800000, -0x0005083c, -0x100002e6, -0x80f00000, -0x3a100004, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x106e6300, -0x1003ba34, -0x40800000, -0x00050802, -0x80630000, -0x00098200, -0x0006000b, -0x80f00000, -0x3a100004, -0x10001af1, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000c, -0x1003c234, -0x40800000, -0x0005083e, -0x00000000, -0x81230000, -0x00098200, -0x28090000, -0x40820000, -0x00050809, -0x0006000d, -0x00000000, -0x0006003f, -0x48000001, -0x00030022, -0x48000000, -0x0005000b, -0x00000000, -0x00060013, -0x88090000, -0x00098200, -0x70000000, -0x00090200, -0x40820000, -0x0005080d, -0x48000000, -0x0005003e, -0x00000000, -0x100e5300, -0x1000b232, -0x110f5b00, -0x40800000, -0x0005083a, -0x00000000, -0x110e5300, -0x1008b232, -0x100f5b00, -0x40800000, -0x0005083b, -0x00000000, -0x100e5300, -0x110e5b00, -0x1120422c, -0x1009b232, -0x40830000, -0x0005083d, -0x00000000, -0x80f00000, -0x3a100004, -0x100042e0, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x100e5300, -0x1000b232, -0x110f5b00, -0x40800000, -0x0005083a, -0x00000000, -0x110e5300, -0x1008b232, -0x100f5b00, -0x40800000, -0x0005083b, -0x00000000, -0x100e5300, -0x110e5b00, -0x1120422c, -0x1009b232, -0x40830000, -0x0005083d, -0x00000000, -0x80f00000, -0x3a100004, -0x100042e1, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x100e5300, -0x1000b232, -0x110f5b00, -0x40800000, -0x0005083a, -0x00000000, -0x110e5300, -0x1008b232, -0x100f5b00, -0x40800000, -0x0005083b, -0x00000000, -0x100e5300, -0x110e5b00, -0x1120422c, -0x1009b232, -0x40830000, -0x0005083d, -0x00000000, -0x80f00000, -0x3a100004, -0x100042e8, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x100e5300, -0x1000b232, -0x110f5b00, -0x40800000, -0x0005083a, -0x00000000, -0x110e5300, -0x1008b232, -0x100f5b00, -0x40800000, -0x0005083b, -0x00000000, -0x100e5300, -0x110e5b00, -0x1120422c, -0x1009b232, -0x40830000, -0x0005083d, -0x00000000, -0x80f00000, -0x3a100004, -0x100042e9, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x118e5300, -0x100cb232, -0x12af5b00, -0x40800000, -0x0005083a, -0x00000000, -0x12ae5300, -0x1015b232, -0x118f5b00, -0x40800000, -0x0005083b, -0x00000000, -0x118e5300, -0x12ae5b00, -0x112caa2c, -0x1009b232, -0x40830000, -0x0005083d, -0x00000000, -0x0006009a, -0x108caae9, -0x48000001, -0x00050094, -0x1004aae8, -0x80f00000, -0x3a100004, -0x100c02e1, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x118e5300, -0x100cb232, -0x12af5b00, -0x40800000, -0x0005083a, -0x00000000, -0x12ae5300, -0x1015b232, -0x118f5b00, -0x40800000, -0x0005083b, -0x00000000, -0x118e5300, -0x12ae5b00, -0x112caa2c, -0x1009b232, -0x40830000, -0x0005083d, -0x00000000, -0x48000000, -0x0005009a, -0x00000000, -0x108e5300, -0x10ce5b00, -0x1066222c, -0x1003b232, -0x10a6322c, -0x40830000, -0x0005083d, -0x48000001, -0x0003001b, -0x1083222d, -0x108ea320, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x7caa5850, -0x91d20000, -0x00098200, -0x7c8e5a14, -0x7d555378, -0x0006002a, -0x9201000c, -0x7e439378, -0x54a500fe, -0x000900ab, -0x48000001, -0x00030026, -0x28030000, -0x81d20000, -0x00098200, -0x40820000, -0x00050835, -0x100eab00, -0x100ea320, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x80f00000, -0x3a100004, -0x5588007e, -0x000900ab, -0x2108fffc, -0x7c0f402e, -0x1017022d, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x80f00000, -0x3a100004, -0x5588007e, -0x000900ab, -0x2108fffc, -0x7c0f402e, -0x39200000, -0x00098200, -0x1009022d, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x558800fe, -0x000900ab, -0x7d080734, -0x80f00000, -0x3a100004, -0x100042f1, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x100f6300, -0x80f00000, -0x3a100004, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x558800fe, -0x000900ab, -0x7d0040f8, -0x80f00000, -0x3a100004, -0x7c0ea12e, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x134ea320, -0x3a940008, -0x0006000b, -0x134ea320, -0x7c146000, -0x3a940008, -0x41800000, -0x0005080b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x80f00000, -0x3a100004, -0x814efffc, -0x558c007e, -0x000900ab, -0x398c0000, -0x00098200, -0x7d4a602e, -0x810a0000, -0x00098200, -0x10080301, -0x100ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x814efffc, -0x5694007e, -0x000900ab, -0x3a940000, -0x00098200, -0x110e6300, -0x7d4aa02e, -0x88ca0000, -0x00098200, -0x808a0000, -0x00098200, -0x70c60000, -0x00090200, -0x880a0000, -0x00098200, -0x1128422c, -0x11040321, -0x28800000, -0x4c423382, -0x39290000, -0x00098200, -0x40820000, -0x00050802, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000c, -0x28090000, -0x00090200, -0x40800000, -0x0005080b, -0x88c80000, -0x00098200, -0x70c60000, -0x00090200, -0x38710000, -0x00098200, -0x41820000, -0x0005080b, -0x48000001, -0x00030027, -0x48000000, -0x0005000b, -0x00000000, -0x814efffc, -0x5588007e, -0x000900ab, -0x5694007e, -0x000900ab, -0x2108fffc, -0x3a940000, -0x00098200, -0x7d0f402e, -0x7d4aa02e, -0x1117422d, -0x88ca0000, -0x00098200, -0x808a0000, -0x00098200, -0x70c60000, -0x00090200, -0x88c80000, -0x00098200, -0x892a0000, -0x00098200, -0x11040321, -0x40820000, -0x00050802, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000c, -0x70c60000, -0x00090200, -0x28890000, -0x4c423382, -0x38710000, -0x00098200, -0x41820000, -0x0005080b, -0x48000001, -0x00030027, -0x48000000, -0x0005000b, -0x00000000, -0x80f00000, -0x3a100004, -0x814efffc, -0x5694007e, -0x000900ab, -0x3a940000, -0x00098200, -0x100f6300, -0x7d4aa02e, -0x810a0000, -0x00098200, -0x10080321, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x80f00000, -0x3a100004, -0x814efffc, -0x5694007e, -0x000900ab, -0x3a940000, -0x00098200, -0x558000fe, -0x000900ab, -0x7d4aa02e, -0x7c0000f8, -0x810a0000, -0x00098200, -0x90080000, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x81120000, -0x00098200, -0x5580007e, -0x000900ab, -0x7e100214, -0x3e100000, -0x00098200, -0x91d20000, -0x00098200, -0x28080000, -0x7e439378, -0x41820000, -0x00050801, -0x7c8ea214, -0x48000001, -0x00030028, -0x81d20000, -0x00098200, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x5588007e, -0x000900ab, -0x91d20000, -0x00098200, -0x2108fffc, -0x9201000c, -0x7c8f402e, -0x7e439378, -0x80aefffc, -0x48000001, -0x00030029, -0x81d20000, -0x00098200, -0x10791a2d, -0x106ea320, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x80110000, -0x00098200, -0x7e439378, -0x81110000, -0x00098200, -0x91d20000, -0x00098200, -0x7c004040, -0x9201000c, -0x40800000, -0x00050805, -0x0006000b, -0x00000000, -0x5584ed7e, -0x558596fe, -0x2c0407ff, -0x39000801, -0x7c88209e, -0x48000001, -0x0003002a, -0x00000000, -0x5588007e, -0x000900ab, -0x2108fffc, -0x7c8f402e, -0x48000001, -0x0003002b, -0x00000000, -0x81d20000, -0x00098200, -0x10781a2d, -0x106ea320, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000f, -0x7d956378, -0x48000001, -0x0003002c, -0x7eacab78, -0x7e439378, -0x48000000, -0x0005000b, -0x00000000, -0x812efffc, -0x5588007e, -0x000900ab, -0x81490000, -0x00098200, -0x2108fffc, -0x7d6f402e, -0x00000000, -0x48000000, -0x0005009b, -0x00000000, -0x48000000, -0x0005009c, -0x00000000, -0x114e5300, -0x116e5b00, -0x100ac234, -0x40800000, -0x0005082f, -0x100bb232, -0x40800000, -0x00050805, -0x11205af5, -0x800a0000, -0x00098200, -0x11004af1, -0x7c004840, -0x108b42ee, -0x810a0000, -0x00098200, -0x4c212a02, -0x55291800, -0x000900a1, -0x40810000, -0x0005082f, -0x11084b00, -0x1008d234, -0x41800000, -0x00050802, -0x0006000b, -0x110ea320, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000c, -0x812a0000, -0x00098200, -0x28090000, -0x41820000, -0x0005080b, -0x88090000, -0x00098200, -0x70000000, -0x00090200, -0x40820000, -0x0005080b, -0x48000000, -0x0005002f, -0x0006000f, -0x100bba34, -0x41800000, -0x0005089b, -0x48000000, -0x0005002f, -0x00000000, -0x114e5300, -0x5568007e, -0x000900ab, -0x100ac234, -0x2108fffc, -0x7d6f402e, -0x40800000, -0x0005082c, -0x0006009b, -0x800a0000, -0x00098200, -0x810b0000, -0x00098200, -0x812a0000, -0x00098200, -0x11775a2d, -0x7d080038, -0x55002800, -0x000900a1, -0x55081800, -0x000900a1, -0x7d080050, -0x7d294214, -0x0006000b, -0x10090301, -0x00090cab, -0x11090301, -0x00090cab, -0x10005a34, -0x40830000, -0x00050804, -0x1008d234, -0x41800000, -0x00050805, -0x0006000d, -0x110ea320, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000e, -0x81290000, -0x00098200, -0x28090000, -0x40820000, -0x0005080b, -0x111ad217, -0x0006000f, -0x812a0000, -0x00098200, -0x28090000, -0x41820000, -0x0005080d, -0x88090000, -0x00098200, -0x70000000, -0x00090200, -0x00000000, -0x40820000, -0x0005080d, -0x48000000, -0x0005002d, -0x00000000, -0x114e5300, -0x556000fe, -0x000900ab, -0x100ac234, -0x40800000, -0x0005082e, -0x810a0000, -0x00098200, -0x812a0000, -0x00098200, -0x7c004040, -0x40800000, -0x0005082e, -0x11095b00, -0x1008d234, -0x41800000, -0x00050805, -0x0006000b, -0x80f00000, -0x3a100004, -0x110ea320, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000f, -0x812a0000, -0x00098200, -0x28090000, -0x41820000, -0x0005080b, -0x89290000, -0x00098200, -0x71290000, -0x00090200, -0x40820000, -0x0005080b, -0x48000000, -0x0005002e, -0x00000000, -0x114e5300, -0x116e5b00, -0x100ac234, -0x40800000, -0x00050833, -0x100bb232, -0x40800000, -0x00050805, -0x11205af5, -0x12aea300, -0x800a0000, -0x00098200, -0x11004af1, -0x7c004840, -0x108b42ee, -0x810a0000, -0x00098200, -0x4c212a02, -0x55201800, -0x000900a1, -0x40810000, -0x00050833, -0x88ca0000, -0x00098200, -0x11280300, -0x1009d234, -0x41800000, -0x00050803, -0x0006000b, -0x70c90000, -0x00090200, -0x12a80320, -0x40820000, -0x00050807, -0x0006000c, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000d, -0x812a0000, -0x00098200, -0x28090000, -0x41820000, -0x0005080b, -0x89290000, -0x00098200, -0x71290000, -0x00090200, -0x40820000, -0x0005080b, -0x48000000, -0x00050033, -0x0006000f, -0x100bba34, -0x41800000, -0x0005089c, -0x48000000, -0x00050033, -0x00060011, -0x00000000, -0x80110000, -0x00098200, -0x54c607b8, -0x91510000, -0x00098200, -0x98ca0000, -0x00098200, -0x900a0000, -0x00098200, -0x48000000, -0x0005000c, -0x00000000, -0x114e5300, -0x5568007e, -0x000900ab, -0x100ac234, -0x2108fffc, -0x7d6f402e, -0x40800000, -0x00050830, -0x0006009c, -0x800a0000, -0x00098200, -0x810b0000, -0x00098200, -0x812a0000, -0x00098200, -0x11775a2d, -0x9b6a0000, -0x00098200, -0x7d080038, -0x12aea300, -0x55002800, -0x000900a1, -0x55081800, -0x000900a1, -0x7d080050, -0x88ca0000, -0x00098200, -0x7d294214, -0x0006000b, -0x10090301, -0x00090cab, -0x11090301, -0x00090cab, -0x10005a34, -0x40830000, -0x00050805, -0x1008d234, -0x41800000, -0x00050804, -0x0006000c, -0x70c00000, -0x00090200, -0x12a90321, -0x00090cab, -0x40820000, -0x00050807, -0x0006000d, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000e, -0x810a0000, -0x00098200, -0x00000000, -0x28080000, -0x41820000, -0x0005080c, -0x88080000, -0x00098200, -0x70000000, -0x00090200, -0x40820000, -0x0005080c, -0x48000000, -0x00050031, -0x0006000f, -0x81290000, -0x00098200, -0x28090000, -0x40820000, -0x0005080b, -0x810a0000, -0x00098200, -0x38b10000, -0x00098200, -0x9201000c, -0x7e439378, -0x28080000, -0x91d20000, -0x00098200, -0x41820000, -0x00050806, -0x88080000, -0x00098200, -0x70000000, -0x00090200, -0x41820000, -0x00050831, -0x00060010, -0x7d445378, -0x11650321, -0x48000001, -0x0003002d, -0x81d20000, -0x00098200, -0x12a30321, -0x48000000, -0x0005000d, -0x00060011, -0x80110000, -0x00098200, -0x54c607b8, -0x91510000, -0x00098200, -0x00000000, -0x98ca0000, -0x00098200, -0x900a0000, -0x00098200, -0x48000000, -0x0005000d, -0x00000000, -0x114e5300, -0x556000fe, -0x000900ab, -0x100ac234, -0x40800000, -0x00050832, -0x810a0000, -0x00098200, -0x812a0000, -0x00098200, -0x88ca0000, -0x00098200, -0x7c004040, -0x12aea300, -0x40800000, -0x00050832, -0x11095b00, -0x1008d234, -0x41800000, -0x00050805, -0x0006000b, -0x70c00000, -0x00090200, -0x12a95b20, -0x40820000, -0x00050807, -0x0006000c, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000f, -0x810a0000, -0x00098200, -0x28080000, -0x41820000, -0x0005080b, -0x89080000, -0x00098200, -0x71080000, -0x00090200, -0x40820000, -0x0005080b, -0x48000000, -0x00050032, -0x00060011, -0x80110000, -0x00098200, -0x54c607b8, -0x91510000, -0x00098200, -0x98ca0000, -0x00098200, -0x00000000, -0x900a0000, -0x00098200, -0x48000000, -0x0005000c, -0x00000000, -0x7e8ea214, -0x0006000b, -0x7ccf6214, -0x8094fffc, -0x3413fff8, -0x80c60004, -0x540500fe, -0x000900ab, -0x41820000, -0x00050804, -0x7ca53214, -0x81240000, -0x00098200, -0x54c81800, -0x000900a1, -0x88c40000, -0x00098200, -0x7c054840, -0x7d340214, -0x80040000, -0x00098200, -0x41810000, -0x00050805, -0x7d080214, -0x70c00000, -0x00090200, -0x0006000d, -0x10140301, -0x3a940008, -0x7c944800, -0x10080321, -0x39080008, -0x41840000, -0x0005080d, -0x40820000, -0x00050807, -0x0006000e, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000f, -0x91d20000, -0x00098200, -0x7e439378, -0x9201000c, -0x7d956378, -0x48000001, -0x0003002e, -0x7eacab78, -0x48000000, -0x0005000b, -0x00060011, -0x80110000, -0x00098200, -0x54c607b8, -0x90910000, -0x00098200, -0x98c40000, -0x00098200, -0x90040000, -0x00098200, -0x00000000, -0x48000000, -0x0005000e, -0x00000000, -0x7d6b9a14, -0x00000000, -0x114ea300, -0x7dc97378, -0x7dcea214, -0x396bfff8, -0x100aca34, -0x39ce0008, -0x40800000, -0x00050825, -0x920efff8, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00000000, -0x7d6b9a14, -0x00000000, -0x114ea300, -0x7e8ea214, -0x810efff8, -0x396bfff8, -0x100aca34, -0x3a940008, -0x40800000, -0x00050840, -0x00060041, -0x71000000, -0x00090200, -0x88ca0000, -0x00098200, -0x69090000, -0x00090200, -0x288b0000, -0x40820000, -0x00050807, -0x0006000b, -0x914efffc, -0x39200000, -0x2b860001, -0x41860000, -0x00050803, -0x0006000c, -0x38c90008, -0x10144b00, -0x7c865840, -0x100e4b20, -0x7cc93378, -0x40860000, -0x0005080c, -0x0006000d, -0x4c42ea02, -0x41820000, -0x00050805, -0x0006000e, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x0006000f, -0x80e8fffc, -0x54f4dd78, -0x7d147050, -0x81080000, -0x00098200, -0x81080000, -0x00098200, -0x81e80000, -0x00098200, -0x48000000, -0x0005000e, -0x00060011, -0x71200000, -0x00090200, -0x40820000, -0x0005080b, -0x00000000, -0x7dc97050, -0x810efff8, -0x71000000, -0x00090200, -0x48000000, -0x0005000b, -0x00000000, -0x3a94ffe8, -0x7dc97378, -0x114ea300, -0x7dcea214, -0x100e0b01, -0x110e1301, -0x114e1b21, -0x100aca34, -0x100e2321, -0x39600010, -0x110e2b21, -0x39ce0020, -0x40800000, -0x00050825, -0x920efff8, -0x820a0000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54f4dd78, -0x7c11402e, -0x7e947214, -0x7c0903a6, -0x4e800420, -0x00000000, -0x7e8ea214, -0x8154fff4, -0x8174fffc, -0x800a0000, -0x00098200, -0x810a0000, -0x00098200, -0x3a100004, -0x0006000b, -0x7c0b0040, -0x55661800, -0x000900a1, -0x40800000, -0x00050805, -0x11283300, -0x1009d234, -0x80f0fffc, -0x41800000, -0x00050804, -0x10005af1, -0x396b0001, -0x3cd00000, -0x00098200, -0x11340b21, -0x54e893ba, -0x9174fffc, -0x7e083214, -0x10140321, -0x0006000d, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000e, -0x396b0001, -0x48000000, -0x0005000b, -0x0006000f, -0x810a0000, -0x00098200, -0x7d605850, -0x812a0000, -0x00098200, -0x00060010, -0x7c0b4040, -0x55662800, -0x000900a1, -0x41810000, -0x0005080d, -0x556a1800, -0x000900a1, -0x7cca3050, -0x11493300, -0x7cc93214, -0x100ad234, -0x80f0fffc, -0x41800000, -0x00050807, -0x10c60301, -0x00090cab, -0x3d300000, -0x00098200, -0x11540b21, -0x7d6b0214, -0x54e893ba, -0x10d40321, -0x396b0001, -0x7e084a14, -0x9174fffc, -0x48000000, -0x0005000d, -0x00060011, -0x00000000, -0x396b0001, -0x48000000, -0x00050010, -0x00000000, -0x7e8ea214, -0x3920ffe8, -0x11144b00, -0x8134fff0, -0x80d4fff8, -0x1008422c, -0x2c090000, -0x00098200, -0x2c800000, -0x00098200, -0x2f060000, -0x00098200, -0x40860000, -0x00050805, -0x89080000, -0x00098200, -0x4c42d202, -0x2f880000, -0x00098200, -0x5580007e, -0x000900ab, -0x4c42f202, -0x7cd00214, -0x40820000, -0x00050805, -0x9374fffc, -0x3e060000, -0x00098200, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000f, -0x38000000, -0x00098200, -0x39000000, -0x00098200, -0x9810ffff, -0x3e060000, -0x00098200, -0x99100003, -0x48000000, -0x0005000b, -0x00000000, -0x800efff8, -0x7d6e5a14, -0x7e8ea214, -0x396b0000, -0x00098200, -0x7d345214, -0x38cefff8, -0x7d605850, -0x288a0000, -0x7d0b3051, -0x41860000, -0x00050805, -0x3929fff0, -0x40810000, -0x00050802, -0x0006000b, -0x100b0301, -0x396b0008, -0x10140321, -0x7c144840, -0x7c8b3040, -0x40800000, -0x00050803, -0x3a940008, -0x41840000, -0x0005080b, -0x0006000c, -0x13540321, -0x7c144840, -0x3a940008, -0x41800000, -0x0005080c, -0x0006000d, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000f, -0x80120000, -0x00098200, -0x3a600008, -0x40810000, -0x0005080d, -0x7d344214, -0x7c090040, -0x3a680008, -0x41810000, -0x00050807, -0x00060010, -0x100b0301, -0x396b0008, -0x10140321, -0x7c0b3040, -0x3a940008, -0x41800000, -0x00050810, -0x48000000, -0x0005000d, -0x00060011, -0x7e439378, -0x92920000, -0x00098200, -0x7eae5850, -0x91d20000, -0x00098200, -0x7e8ea050, -0x9201000c, -0x550400fe, -0x000900ab, -0x48000001, -0x00030000, -0x81d20000, -0x00098200, -0x00000000, -0x7e8ea214, -0x7d6eaa14, -0x38cefff8, -0x48000000, -0x00050010, -0x00000000, -0x7d8c9a14, -0x00000000, -0x820efff8, -0x7e8ea214, -0x7d936378, -0x0006000b, -0x72000000, -0x00090200, -0x6a080000, -0x00090200, -0x40820000, -0x0005089d, -0x00060017, -0x80f0fffc, -0x2c0c0008, -0x392efff8, -0x396cfff8, -0x54ea5d78, -0x41820000, -0x00050803, -0x39000000, -0x0006000c, -0x38c80008, -0x10144300, -0x7c065800, -0x10094320, -0x41820000, -0x00050803, -0x39060008, -0x10143300, -0x7c085800, -0x10093320, -0x40820000, -0x0005080c, -0x0006000d, -0x0006000f, -0x7c0a6040, -0x54f4dd78, -0x41810000, -0x00050806, -0x7dd44850, -0x810efffc, -0x80f00000, -0x3a100004, -0x81080000, -0x00098200, -0x81e80000, -0x00098200, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00060010, -0x390cfff8, -0x398c0008, -0x13494320, -0x48000000, -0x0005000f, -0x0006009d, -0x71090000, -0x00090200, -0x40820000, -0x00050818, -0x7dc87050, -0x820efff8, -0x48000000, -0x0005000b, -0x00000000, -0x820efff8, -0x7e8ea214, -0x7d936378, -0x72000000, -0x00090200, -0x6a080000, -0x00090200, -0x40820000, -0x0005089d, -0x80f0fffc, -0x392efff8, -0x54ea5d78, -0x00000000, -0x10140301, -0x10090321, -0x00000000, -0x0006000f, -0x7c0a6040, -0x54f4dd78, -0x41810000, -0x00050806, -0x7dd44850, -0x810efffc, -0x80f00000, -0x3a100004, -0x81080000, -0x00098200, -0x81e80000, -0x00098200, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00060010, -0x390cfff8, -0x398c0008, -0x13494320, -0x48000000, -0x0005000f, -0x00000000, -0x7c810808, -0x00000000, -0x7e8ea214, -0x11140301, -0x00090cab, -0x10d40301, -0x00090cab, -0x11340301, -0x00090cab, -0x00000000, -0x1008b230, -0x1386b230, -0x1089b230, -0x4c00e382, -0x4c002382, -0x41800000, -0x00050842, -0x00000000, -0x110832e0, -0x11140321, -0x00090cab, -0x00000000, -0x1006d231, -0x11140321, -0x00090cab, -0x40800000, -0x00050802, -0x10084aec, -0x0006000b, -0x00000000, -0x558c007e, -0x000900ab, -0x7d906214, -0x00000000, -0x3e0c0000, -0x00098200, -0x00000000, -0x3d8c0000, -0x00098200, -0x00000000, -0x7e0c805e, -0x00000000, -0x7e10605e, -0x00000000, -0x40810000, -0x00070800, -0x00000000, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000c, -0x100942ec, -0x48000000, -0x0005000b, -0x00000000, -0x7c810808, -0x00000000, -0x110ea300, -0x3a94fff8, -0x1008d234, -0x41800000, -0x00050801, -0x00000000, -0x7c810808, -0x00000000, -0x5580007e, -0x000900ab, -0x7e100214, -0x3e100000, -0x00098200, -0x110ea320, -0x00000000, -0x0006000b, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x7c810808, -0x00000000, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x7c810808, -0x00000000, -0x5580007e, -0x000900ab, -0x7e100214, -0x3e100000, -0x00098200, -0x80f00000, -0x3a100004, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x7c810808, -0x00000000, -0x81320000, -0x00098200, -0x89100000, -0x00098200, -0x81f00000, -0x00098200, -0x7c144840, -0x55081800, -0x000900a1, -0x41810000, -0x00050820, -0x80f00000, -0x3a100004, -0x0006000c, -0x7c0b4040, -0x40810000, -0x00050803, -0x00000000, -0x7c810808, -0x00000000, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x00000000, -0x0006000d, -0x134e5b20, -0x396b0008, -0x48000000, -0x0005000c, -0x00000000, -0x7c810808, -0x00000000, -0x81320000, -0x00098200, -0x7d0e5a14, -0x7c145a14, -0x91480004, -0x38cb0000, -0x00098200, -0x81f00000, -0x00098200, -0x7c004840, -0x90c80000, -0x40800000, -0x00050820, -0x89300000, -0x00098200, -0x7dd47378, -0x7d0b4378, -0x80f00000, -0x3a100004, -0x2c090000, -0x39c80008, -0x41820000, -0x00050803, -0x0006000b, -0x7c145840, -0x10140301, -0x40800000, -0x00050804, -0x13540321, -0x3a940008, -0x0006000c, -0x3529ffff, -0x10080b21, -0x39080008, -0x40820000, -0x0005080b, -0x0006000d, -0x54e815ba, -0x54ea5d78, -0x54ec9b78, -0x7c11402e, -0x54f4dd78, -0x54eb9d78, -0x7c0903a6, -0x4e800420, -0x0006000e, -0x101ad217, -0x48000000, -0x0005000c, -0x00000000, -0x80ca0000, -0x00098200, -0x00000000, -0x80d10000, -0x00098200, -0x00000000, -0x7d145a14, -0x81320000, -0x00098200, -0x7d6e5a14, -0x91d20000, -0x00098200, -0x7c084840, -0x91720000, -0x00098200, -0x38000000, -0x00098200, -0x7cc903a6, -0x00000000, -0x808a0000, -0x00098200, -0x00000000, -0x7e439378, -0x41810000, -0x0005081f, -0x90110000, -0x00098200, -0x4e800421, -0x81120000, -0x00098200, -0x546c1800, -0x000900a1, -0x81d20000, -0x00098200, -0x38000000, -0x00098200, -0x820efff8, -0x7e8c4050, -0x90110000, -0x00098200, -0x48000000, -0x00050016, -0x00000000, -0x00010000 -}; - -enum { - GLOB_vm_returnp, - GLOB_cont_dispatch, - GLOB_vm_returnc, - GLOB_BC_RET_Z, - GLOB_vm_return, - GLOB_vm_leave_cp, - GLOB_vm_leave_unw, - GLOB_vm_unwind_c, - GLOB_vm_unwind_c_eh, - GLOB_vm_unwind_ff, - GLOB_vm_unwind_ff_eh, - GLOB_vm_growstack_c, - GLOB_vm_growstack_l, - GLOB_vm_resume, - GLOB_vm_pcall, - GLOB_vm_call, - GLOB_vm_call_dispatch, - GLOB_vmeta_call, - GLOB_vm_call_dispatch_f, - GLOB_vm_cpcall, - GLOB_vm_call_tail, - GLOB_cont_cat, - GLOB_BC_CAT_Z, - GLOB_cont_nop, - GLOB_vmeta_tgets1, - GLOB_vmeta_tgets, - GLOB_vmeta_tgetb, - GLOB_vmeta_tgetv, - GLOB_vmeta_tsets1, - GLOB_vmeta_tsets, - GLOB_vmeta_tsetb, - GLOB_vmeta_tsetv, - GLOB_vmeta_comp, - GLOB_vmeta_binop, - GLOB_cont_ra, - GLOB_cont_condt, - GLOB_cont_condf, - GLOB_vmeta_equal, - GLOB_vmeta_arith_vn, - GLOB_vmeta_arith_nv, - GLOB_vmeta_unm, - GLOB_vmeta_arith_vv, - GLOB_vmeta_len, - GLOB_BC_LEN_Z, - GLOB_vmeta_callt, - GLOB_BC_CALLT_Z, - GLOB_vmeta_for, - GLOB_ff_assert, - GLOB_fff_fallback, - GLOB_fff_res, - GLOB_ff_type, - GLOB_fff_restv, - GLOB_ff_getmetatable, - GLOB_ff_setmetatable, - GLOB_ff_rawget, - GLOB_ff_tonumber, - GLOB_ff_tostring, - GLOB_fff_gcstep, - GLOB_ff_next, - GLOB_ff_pairs, - GLOB_ff_ipairs_aux, - GLOB_ff_ipairs, - GLOB_ff_pcall, - GLOB_ff_xpcall, - GLOB_ff_coroutine_resume, - GLOB_ff_coroutine_wrap_aux, - GLOB_ff_coroutine_yield, - GLOB_ff_math_abs, - GLOB_fff_res1, - GLOB_ff_math_floor, - GLOB_vm_floor_hilo, - GLOB_ff_math_ceil, - GLOB_vm_ceil_hilo, - GLOB_ff_math_sqrt, - GLOB_ff_math_log, - GLOB_ff_math_log10, - GLOB_ff_math_exp, - GLOB_ff_math_sin, - GLOB_ff_math_cos, - GLOB_ff_math_tan, - GLOB_ff_math_asin, - GLOB_ff_math_acos, - GLOB_ff_math_atan, - GLOB_ff_math_sinh, - GLOB_ff_math_cosh, - GLOB_ff_math_tanh, - GLOB_ff_math_pow, - GLOB_ff_math_atan2, - GLOB_ff_math_fmod, - GLOB_ff_math_deg, - GLOB_ff_math_rad, - GLOB_ff_math_ldexp, - GLOB_ff_math_frexp, - GLOB_ff_math_modf, - GLOB_ff_math_min, - GLOB_ff_math_max, - GLOB_ff_string_len, - GLOB_ff_string_byte, - GLOB_ff_string_char, - GLOB_fff_newstr, - GLOB_ff_string_sub, - GLOB_ff_string_rep, - GLOB_ff_string_reverse, - GLOB_ff_string_lower, - GLOB_ff_string_upper, - GLOB_ff_table_getn, - GLOB_ff_bit_tobit, - GLOB_fff_resbit, - GLOB_ff_bit_band, - GLOB_ff_bit_bor, - GLOB_ff_bit_bxor, - GLOB_ff_bit_bswap, - GLOB_ff_bit_bnot, - GLOB_ff_bit_lshift, - GLOB_ff_bit_rshift, - GLOB_ff_bit_arshift, - GLOB_ff_bit_rol, - GLOB_ff_bit_ror, - GLOB_vm_record, - GLOB_vm_rethook, - GLOB_vm_inshook, - GLOB_cont_hook, - GLOB_vm_hotloop, - GLOB_vm_callhook, - GLOB_vm_hotcall, - GLOB_vm_exit_handler, - GLOB_vm_exit_interp, - GLOB_vm_floor, - GLOB_vm_floor_efd, - GLOB_vm_ceil_efd, - GLOB_vm_trunc_efd, - GLOB_vm_trunc_hilo, - GLOB_vm_foldarith, - GLOB_vm_ffi_call, - GLOB_BC_MODVN_Z, - GLOB_BC_TGETS_Z, - GLOB_BC_TSETS_Z, - GLOB_BC_RETV_Z, - GLOB__MAX -}; -static const char *const globnames[] = { - "vm_returnp", - "cont_dispatch", - "vm_returnc", - "BC_RET_Z", - "vm_return", - "vm_leave_cp", - "vm_leave_unw", - "vm_unwind_c", - "vm_unwind_c_eh", - "vm_unwind_ff", - "vm_unwind_ff_eh", - "vm_growstack_c", - "vm_growstack_l", - "vm_resume", - "vm_pcall", - "vm_call", - "vm_call_dispatch", - "vmeta_call", - "vm_call_dispatch_f", - "vm_cpcall", - "vm_call_tail", - "cont_cat", - "BC_CAT_Z", - "cont_nop", - "vmeta_tgets1", - "vmeta_tgets", - "vmeta_tgetb", - "vmeta_tgetv", - "vmeta_tsets1", - "vmeta_tsets", - "vmeta_tsetb", - "vmeta_tsetv", - "vmeta_comp", - "vmeta_binop", - "cont_ra", - "cont_condt", - "cont_condf", - "vmeta_equal", - "vmeta_arith_vn", - "vmeta_arith_nv", - "vmeta_unm", - "vmeta_arith_vv", - "vmeta_len", - "BC_LEN_Z", - "vmeta_callt", - "BC_CALLT_Z", - "vmeta_for", - "ff_assert", - "fff_fallback", - "fff_res", - "ff_type", - "fff_restv", - "ff_getmetatable", - "ff_setmetatable", - "ff_rawget", - "ff_tonumber", - "ff_tostring", - "fff_gcstep", - "ff_next", - "ff_pairs", - "ff_ipairs_aux", - "ff_ipairs", - "ff_pcall", - "ff_xpcall", - "ff_coroutine_resume", - "ff_coroutine_wrap_aux", - "ff_coroutine_yield", - "ff_math_abs", - "fff_res1", - "ff_math_floor", - "vm_floor_hilo", - "ff_math_ceil", - "vm_ceil_hilo", - "ff_math_sqrt", - "ff_math_log", - "ff_math_log10", - "ff_math_exp", - "ff_math_sin", - "ff_math_cos", - "ff_math_tan", - "ff_math_asin", - "ff_math_acos", - "ff_math_atan", - "ff_math_sinh", - "ff_math_cosh", - "ff_math_tanh", - "ff_math_pow", - "ff_math_atan2", - "ff_math_fmod", - "ff_math_deg", - "ff_math_rad", - "ff_math_ldexp", - "ff_math_frexp", - "ff_math_modf", - "ff_math_min", - "ff_math_max", - "ff_string_len", - "ff_string_byte", - "ff_string_char", - "fff_newstr", - "ff_string_sub", - "ff_string_rep", - "ff_string_reverse", - "ff_string_lower", - "ff_string_upper", - "ff_table_getn", - "ff_bit_tobit", - "fff_resbit", - "ff_bit_band", - "ff_bit_bor", - "ff_bit_bxor", - "ff_bit_bswap", - "ff_bit_bnot", - "ff_bit_lshift", - "ff_bit_rshift", - "ff_bit_arshift", - "ff_bit_rol", - "ff_bit_ror", - "vm_record", - "vm_rethook", - "vm_inshook", - "cont_hook", - "vm_hotloop", - "vm_callhook", - "vm_hotcall", - "vm_exit_handler", - "vm_exit_interp", - "vm_floor", - "vm_floor_efd", - "vm_ceil_efd", - "vm_trunc_efd", - "vm_trunc_hilo", - "vm_foldarith", - "vm_ffi_call", - "BC_MODVN_Z", - "BC_TGETS_Z", - "BC_TSETS_Z", - "BC_RETV_Z", - (const char *)0 -}; -static const char *const extnames[] = { - "lj_state_growstack", - "lj_meta_tget", - "lj_meta_tset", - "lj_meta_comp", - "lj_meta_equal", - "lj_meta_arith", - "lj_meta_len", - "lj_meta_call", - "lj_meta_for", - "lj_tab_get", - "lj_str_fromnum", - "lj_tab_next", - "lj_tab_getinth", - "lj_ffh_coroutine_wrap_err", - "sqrt", - "log", - "log10", - "exp", - "sin", - "cos", - "tan", - "asin", - "acos", - "atan", - "sinh", - "cosh", - "tanh", - "pow", - "atan2", - "fmod", - "ldexp", - "frexp", - "modf", - "lj_str_new", - "lj_tab_len", - "lj_gc_step", - "lj_dispatch_ins", - "lj_dispatch_call", - "lj_meta_cat", - "lj_gc_barrieruv", - "lj_func_closeuv", - "lj_func_newL_gc", - "lj_tab_new", - "lj_tab_dup", - "lj_gc_step_fixtop", - "lj_tab_newkey", - "lj_tab_reasize", - (const char *)0 -}; -#define Dt1(_V) (int)(ptrdiff_t)&(((lua_State *)0)_V) -#define Dt2(_V) (int)(ptrdiff_t)&(((global_State *)0)_V) -#define Dt3(_V) (int)(ptrdiff_t)&(((TValue *)0)_V) -#define Dt4(_V) (int)(ptrdiff_t)&(((GCobj *)0)_V) -#define Dt5(_V) (int)(ptrdiff_t)&(((GCstr *)0)_V) -#define Dt6(_V) (int)(ptrdiff_t)&(((GCtab *)0)_V) -#define Dt7(_V) (int)(ptrdiff_t)&(((GCfuncL *)0)_V) -#define Dt8(_V) (int)(ptrdiff_t)&(((GCfuncC *)0)_V) -#define Dt9(_V) (int)(ptrdiff_t)&(((GCproto *)0)_V) -#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V) -#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V) -#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V) -#define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V) -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx) -{ - dasm_put(Dst, 0); - dasm_put(Dst, 1, FRAME_P, LJ_TTRUE, FRAME_TYPE, FRAME_C, ~LJ_VMST_C, Dt1(->base), DISPATCH_GL(vmstate), 31-3, Dt1(->top)); - dasm_put(Dst, 55, Dt1(->cframe), Dt1(->maxstack), Dt1(->top), 31-3, Dt1(->top), ~LJ_VMST_C, Dt1(->glref), Dt2(->vmstate)); - dasm_put(Dst, 135, LJ_TISNUM+1, LJ_TFUNC, LJ_TTAB, Dt1(->base), Dt1(->glref), LJ_TSTR, LJ_TFALSE, LJ_TNIL, ~LJ_VMST_INTERP, GG_G2DISP, DISPATCH_GL(vmstate), LUA_MINSTACK, Dt1(->base), Dt1(->top), 32-3); - dasm_put(Dst, 190, Dt1(->base), Dt1(->top), Dt7(->pc), Dt1(->glref), Dt1(->status), FRAME_CP, CFRAME_RESUME, GG_G2DISP, Dt1(->cframe), Dt1(->base), LJ_TISNUM+1, Dt1(->top), LJ_TFUNC, LJ_TTAB, LJ_TSTR, Dt1(->status), FRAME_TYPE, ~LJ_VMST_INTERP, LJ_TNIL, DISPATCH_GL(vmstate)); - dasm_put(Dst, 283, FRAME_CP, FRAME_C, Dt1(->cframe), Dt1(->cframe), Dt1(->glref), GG_G2DISP, Dt1(->base), LJ_TISNUM+1, Dt1(->top), LJ_TFUNC, LJ_TTAB, LJ_TSTR, ~LJ_VMST_INTERP, LJ_TNIL, DISPATCH_GL(vmstate)); - dasm_put(Dst, 384, Dt7(->pc), Dt1(->stack), Dt1(->top), Dt1(->cframe), Dt1(->cframe), Dt1(->glref), FRAME_CP, GG_G2DISP, Dt7(->pc), PC2PROTO(k), Dt1(->base)); - dasm_put(Dst, 491, DISPATCH_GL(tmptv), DISPATCH_GL(tmptv), DISPATCH_GL(tmptv2), DISPATCH_GL(tmptv), Dt1(->base), FRAME_CONT, Dt1(->top), DISPATCH_GL(tmptv)); - dasm_put(Dst, 566, DISPATCH_GL(tmptv), DISPATCH_GL(tmptv2), DISPATCH_GL(tmptv), Dt1(->base), FRAME_CONT, Dt1(->top), Dt1(->base)); - dasm_put(Dst, 647, -(BCBIAS_J*4 >> 16), LJ_TTRUE, LJ_TFALSE, Dt1(->base)); - dasm_put(Dst, 716, Dt1(->base), FRAME_CONT); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 739); -#endif - dasm_put(Dst, 741, Dt1(->base)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 749); -#else - dasm_put(Dst, 756); -#endif - dasm_put(Dst, 759, Dt1(->base), Dt7(->pc), Dt1(->base), Dt1(->base)); -#if LJ_HASJIT - dasm_put(Dst, 807); -#endif - dasm_put(Dst, 809); -#if LJ_HASJIT - dasm_put(Dst, 811, BC_JFORI); -#endif - dasm_put(Dst, 814); -#if LJ_HASJIT - dasm_put(Dst, 816, BC_JFORI); -#endif - dasm_put(Dst, 819, BC_FORI, ~LJ_TNUMX, 31-3, Dt8(->upvalue), Dt6(->metatable), DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])); - dasm_put(Dst, 884, Dt6(->hmask), Dt5(->hash), Dt6(->node), 31-5, 31-3, DtB(->key), DtB(->val), DtB(->next), LJ_TUDATA, 31-2, 4*~LJ_TNUMX, DISPATCH_GL(gcroot[GCROOT_BASEMT])); - dasm_put(Dst, 940, Dt6(->metatable), Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist)); - dasm_put(Dst, 1000, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM]), Dt1(->base), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), Dt1(->top), (2+1)*8); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1073, Dt6(->metatable), Dt8(->upvalue[0])); -#else - dasm_put(Dst, 1082, Dt8(->upvalue[0])); -#endif - dasm_put(Dst, 1086, (3+1)*8, Dt6(->asize), Dt6(->array), 31-3, (0+1)*8, (2+1)*8, Dt6(->hmask), (0+1)*8, (0+1)*8); - dasm_put(Dst, 1150); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1163, Dt6(->metatable), Dt8(->upvalue[0])); -#else - dasm_put(Dst, 1172, Dt8(->upvalue[0])); -#endif - dasm_put(Dst, 1176, (3+1)*8, DISPATCH_GL(hookmask), 32-HOOK_ACTIVE_SHIFT, 8+FRAME_PCALL, DISPATCH_GL(hookmask), 32-HOOK_ACTIVE_SHIFT, 16+FRAME_PCALL, LJ_TTHREAD, Dt1(->status), Dt1(->cframe), Dt1(->top)); - dasm_put(Dst, 1237, LUA_YIELD, Dt1(->base), Dt1(->maxstack), Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->base), LUA_YIELD, Dt1(->top), ~LJ_VMST_INTERP, Dt1(->base), DISPATCH_GL(vmstate), Dt1(->maxstack)); - dasm_put(Dst, 1300, Dt1(->top), FRAME_TYPE, LJ_TTRUE, FRAME_TYPE, LJ_TFALSE, Dt1(->top), (2+1)*8, 32-3); - dasm_put(Dst, 1360, Dt8(->upvalue[0].gcr), Dt1(->status), Dt1(->cframe), Dt1(->top), LUA_YIELD, Dt1(->base), Dt1(->maxstack), Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->base), LUA_YIELD, Dt1(->top), ~LJ_VMST_INTERP); - dasm_put(Dst, 1419, Dt1(->base), DISPATCH_GL(vmstate), Dt1(->maxstack), Dt1(->top), FRAME_TYPE, 32-3, Dt1(->cframe)); - dasm_put(Dst, 1476, Dt1(->base), CFRAME_RESUME, Dt1(->top), LUA_YIELD, Dt1(->cframe), Dt1(->status), (1+1)*8, FRAME_TYPE); - dasm_put(Dst, 1541); - dasm_put(Dst, 1610); - dasm_put(Dst, 1673); - dasm_put(Dst, 1738); - dasm_put(Dst, 1808, Dt8(->upvalue[0]), DISPATCH_GL(tmptv), DISPATCH_GL(tmptv), (2+1)*8, (2+1)*8); - dasm_put(Dst, 1880, Dt5(->len)); - dasm_put(Dst, 1947, Dt5(->len), (0+1)*8, Dt5([1]), (1+1)*8, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), DISPATCH_GL(tmptv), Dt1(->base), Dt1(->base), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 2007, Dt5(->len), sizeof(GCstr)-1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 2073, Dt5(->len), DISPATCH_GL(tmpbuf.sz), Dt5([1]), DISPATCH_GL(tmpbuf.buf), DISPATCH_GL(strempty), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 2132, DISPATCH_GL(tmpbuf.sz), Dt5(->len), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), DISPATCH_GL(tmpbuf.sz), Dt5(->len), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf)); - dasm_put(Dst, 2191, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), DISPATCH_GL(tmpbuf.sz), Dt5(->len), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf)); - dasm_put(Dst, 2258); - dasm_put(Dst, 2329); - dasm_put(Dst, 2417, Dt8(->f), 8*LUA_MINSTACK, Dt1(->maxstack), Dt1(->base), Dt1(->top), Dt1(->base), 31-3, Dt1(->top), Dt7(->pc)); - dasm_put(Dst, 2496, FRAME_TYPE, LUA_MINSTACK, Dt1(->base), Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 2539); -#endif - dasm_put(Dst, 2541, DISPATCH_GL(hookmask), HOOK_ACTIVE, GG_DISP2STATIC, DISPATCH_GL(hookmask), DISPATCH_GL(hookcount), HOOK_ACTIVE, 31-LUA_HOOKLINE, DISPATCH_GL(hookcount), Dt1(->base), Dt1(->base)); - dasm_put(Dst, 2588, GG_DISP2STATIC); -#if LJ_HASJIT - dasm_put(Dst, 2606); -#endif - dasm_put(Dst, 2608); -#if LJ_HASJIT - dasm_put(Dst, 2611); -#endif - dasm_put(Dst, 2614); -#if LJ_HASJIT - dasm_put(Dst, 2616); -#endif - dasm_put(Dst, 2619, Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 2641); -#endif - dasm_put(Dst, 2643); -#if LJ_HASJIT - dasm_put(Dst, 2645); -#endif - dasm_put(Dst, 2647); -#if LJ_HASJIT - dasm_put(Dst, 2731); -#else - dasm_put(Dst, 2754); -#endif - dasm_put(Dst, 2757); -#if LJ_HASFFI - dasm_put(Dst, 2820); -#endif -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop) -{ - int vk = 0; - dasm_put(Dst, 2822, defop); - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - dasm_put(Dst, 2824, -(BCBIAS_J*4 >> 16)); - if (op == BC_ISLE || op == BC_ISGT) { - dasm_put(Dst, 2838); - } - if (op == BC_ISLT || op == BC_ISLE) { - dasm_put(Dst, 2841); - } else { - dasm_put(Dst, 2843); - } - dasm_put(Dst, 2845); - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - dasm_put(Dst, 2856, -(BCBIAS_J*4 >> 16)); - if (vk) { - dasm_put(Dst, 2870); - } else { - dasm_put(Dst, 2872); - } - dasm_put(Dst, 2874, ~LJ_TISPRI, ~LJ_TISTABUD); - if (vk) { - dasm_put(Dst, 2896); - } else { - dasm_put(Dst, 2898); - } - dasm_put(Dst, 2900); - if (vk) { - dasm_put(Dst, 2902); - } else { - dasm_put(Dst, 2904); - } - dasm_put(Dst, 2906, Dt6(->metatable), 1-vk, Dt6(->nomm), 1<> 16)); - if (vk) { - dasm_put(Dst, 2941); - } else { - dasm_put(Dst, 2943); - } - dasm_put(Dst, 2945); - break; - - case BC_ISEQN: case BC_ISNEN: - vk = op == BC_ISEQN; - dasm_put(Dst, 2956, -(BCBIAS_J*4 >> 16)); - if (vk) { - dasm_put(Dst, 2970); - } else { - dasm_put(Dst, 2973); - } - dasm_put(Dst, 2975); - if (!vk) { - dasm_put(Dst, 2987); - } - break; - - case BC_ISEQP: case BC_ISNEP: - vk = op == BC_ISEQP; - dasm_put(Dst, 2993, 32-3, -(BCBIAS_J*4 >> 16)); - if (vk) { - dasm_put(Dst, 3005); - } else { - dasm_put(Dst, 3007); - } - dasm_put(Dst, 3009); - break; - - /* -- Unary test and copy ops ------------------------------------------- */ - - case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: - dasm_put(Dst, 3020); - if (op == BC_IST || op == BC_ISF) { - dasm_put(Dst, 3026, -(BCBIAS_J*4 >> 16)); - if (op == BC_IST) { - dasm_put(Dst, 3031); - } else { - dasm_put(Dst, 3033); - } - } else { - if (op == BC_ISTC) { - dasm_put(Dst, 3035); - } else { - dasm_put(Dst, 3038); - } - dasm_put(Dst, 3041, -(BCBIAS_J*4 >> 16)); - } - dasm_put(Dst, 3048); - break; - - /* -- Unary ops --------------------------------------------------------- */ - - case BC_MOV: - dasm_put(Dst, 3059); - break; - case BC_NOT: - dasm_put(Dst, 3072, LJ_TTRUE); - break; - case BC_UNM: - dasm_put(Dst, 3088); - break; - case BC_LEN: - dasm_put(Dst, 3105, Dt5(->len)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 3129, Dt6(->metatable)); -#endif - dasm_put(Dst, 3136); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 3142, Dt6(->nomm), 1<base), 32-3, Dt1(->base)); - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - dasm_put(Dst, 3391, 32-1); - break; - case BC_KCDATA: -#if LJ_HASFFI - dasm_put(Dst, 3408, 32-1, LJ_TCDATA); -#endif - break; - case BC_KSHORT: - dasm_put(Dst, 3427, 32-3); - break; - case BC_KNUM: - dasm_put(Dst, 3443); - break; - case BC_KPRI: - dasm_put(Dst, 3456, 32-3); - break; - case BC_KNIL: - dasm_put(Dst, 3471); - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - dasm_put(Dst, 3490, 32-1, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_USETV: - dasm_put(Dst, 3511, 32-1, offsetof(GCfuncL, uvptr), DtA(->marked), DtA(->v), LJ_GC_BLACK, DtA(->closed), -(LJ_TISNUM+1), LJ_TISGCV - (LJ_TISNUM+1), Dt4(->gch.marked), LJ_GC_WHITES, GG_DISP2G); - break; - case BC_USETS: - dasm_put(Dst, 3563, 32-1, 32-1, offsetof(GCfuncL, uvptr), DtA(->marked), DtA(->v), LJ_GC_BLACK, Dt5(->marked), DtA(->closed), LJ_GC_WHITES, GG_DISP2G); - break; - case BC_USETN: - dasm_put(Dst, 3612, 32-1, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_USETP: - dasm_put(Dst, 3633, 32-1, offsetof(GCfuncL, uvptr), 32-3, DtA(->v)); - break; - - case BC_UCLO: - dasm_put(Dst, 3656, Dt1(->openupval), 32-1, -(BCBIAS_J*4 >> 16), Dt1(->base), Dt1(->base)); - break; - - case BC_FNEW: - dasm_put(Dst, 3686, 32-1, Dt1(->base), Dt1(->base)); - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - case BC_TDUP: - dasm_put(Dst, 3712, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base)); - if (op == BC_TNEW) { - dasm_put(Dst, 3725); - } else { - dasm_put(Dst, 3733, 32-1); - } - dasm_put(Dst, 3740, Dt1(->base)); - break; - - case BC_GGET: - case BC_GSET: - dasm_put(Dst, 3763, 32-1, Dt7(->env)); - if (op == BC_GGET) { - dasm_put(Dst, 3771); - } else { - dasm_put(Dst, 3774); - } - break; - - case BC_TGETV: - dasm_put(Dst, 3777, Dt6(->asize), Dt6(->array), 31-3, Dt6(->metatable), Dt6(->nomm), 1<hmask), Dt5(->hash), Dt6(->node), 31-5, 31-3, DtB(->key), DtB(->val), DtB(->next), Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), 31-3, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<marked), Dt6(->gclist)); - break; - case BC_TSETS: - dasm_put(Dst, 4027, 32-1, Dt6(->hmask), Dt5(->hash), Dt6(->node), Dt6(->nomm), 31-5, 31-3, Dt6(->marked), DtB(->key), DtB(->val), LJ_GC_BLACK, DtB(->val), Dt6(->metatable)); - dasm_put(Dst, 4088, Dt6(->nomm), 1<next), Dt6(->metatable), DISPATCH_GL(tmptv), Dt1(->base), Dt6(->nomm), 1<base), DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain)); - dasm_put(Dst, 4139, Dt6(->marked), Dt6(->gclist)); - break; - case BC_TSETB: - dasm_put(Dst, 4146, 32-3, Dt6(->asize), Dt6(->array), Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<marked)); - dasm_put(Dst, 4206, Dt6(->gclist)); - break; - - case BC_TSETM: - dasm_put(Dst, 4211, 32-3, Dt6(->asize), 31-3, Dt6(->marked), Dt6(->array), LJ_GC_BLACK, Dt1(->base), DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist)); - dasm_put(Dst, 4280); - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALLM: - dasm_put(Dst, 4283); - break; - case BC_CALL: - dasm_put(Dst, 4285, Dt7(->pc)); - break; - - case BC_CALLMT: - dasm_put(Dst, 4305); - break; - case BC_CALLT: - dasm_put(Dst, 4307, FRAME_TYPE, Dt7(->ffid), FRAME_VARG, Dt7(->pc), -4-8, Dt7(->pc), PC2PROTO(k), FRAME_TYPEP); - dasm_put(Dst, 4372, FRAME_TYPE); - break; - - case BC_ITERC: - dasm_put(Dst, 4379, Dt7(->pc)); - break; - - case BC_ITERN: -#if LJ_HASJIT -#endif - dasm_put(Dst, 4405, Dt6(->asize), Dt6(->array), 31-3, -(BCBIAS_J*4 >> 16), Dt6(->hmask), Dt6(->node), 31-5, 31-3, DtB(->key), -(BCBIAS_J*4 >> 16)); - dasm_put(Dst, 4484); - break; - - case BC_ISNEXT: - dasm_put(Dst, 4488, LJ_TTAB, LJ_TFUNC, LJ_TNIL, Dt8(->ffid), FF_next_N, 32-1, -(BCBIAS_J*4 >> 16), BC_JMP, BC_ITERC, -(BCBIAS_J*4 >> 16)); - break; - - case BC_VARG: - dasm_put(Dst, 4539, FRAME_VARG, Dt1(->maxstack), Dt1(->top), Dt1(->base), 32-3, Dt1(->base)); - dasm_put(Dst, 4619); - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - dasm_put(Dst, 4625); - break; - - case BC_RET: - dasm_put(Dst, 4627, FRAME_TYPE, FRAME_VARG, Dt7(->pc), PC2PROTO(k), FRAME_TYPEP); - break; - - case BC_RET0: case BC_RET1: - dasm_put(Dst, 4697, FRAME_TYPE, FRAME_VARG); - if (op == BC_RET1) { - dasm_put(Dst, 4710); - } - dasm_put(Dst, 4713, Dt7(->pc), PC2PROTO(k)); - break; - - /* -- Loops and branches ------------------------------------------------ */ - - case BC_FORL: -#if LJ_HASJIT - dasm_put(Dst, 4741); -#endif - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - vk = (op == BC_IFORL || op == BC_JFORL); - dasm_put(Dst, 4743, FORL_IDX*8, FORL_STEP*8, FORL_STOP*8); - if (!vk) { - dasm_put(Dst, 4751); - } - if (vk) { - dasm_put(Dst, 4759, FORL_IDX*8); - } - dasm_put(Dst, 4763, FORL_EXT*8); - if (op != BC_JFORL) { - dasm_put(Dst, 4771, 32-1); - if (op == BC_JFORI) { - dasm_put(Dst, 4775, -(BCBIAS_J*4 >> 16)); - } else { - dasm_put(Dst, 4778, -(BCBIAS_J*4 >> 16)); - } - } - if (op == BC_FORI) { - dasm_put(Dst, 4781); - } else if (op == BC_IFORL) { - dasm_put(Dst, 4783); - } else { - dasm_put(Dst, 4785, BC_JLOOP); - } - dasm_put(Dst, 4788); - break; - - case BC_ITERL: -#if LJ_HASJIT - dasm_put(Dst, 4803); -#endif - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - dasm_put(Dst, 4805); - if (op == BC_JITERL) { - dasm_put(Dst, 4811); - } else { - dasm_put(Dst, 4813, 32-1, -(BCBIAS_J*4 >> 16)); - } - dasm_put(Dst, 4820); - break; - - case BC_LOOP: -#if LJ_HASJIT - dasm_put(Dst, 4832); -#endif - break; - - case BC_ILOOP: - dasm_put(Dst, 4834); - break; - - case BC_JLOOP: -#if LJ_HASJIT - dasm_put(Dst, 4845); -#endif - break; - - case BC_JMP: - dasm_put(Dst, 4847, 32-1, -(BCBIAS_J*4 >> 16)); - break; - - /* -- Function headers -------------------------------------------------- */ - - case BC_FUNCF: -#if LJ_HASJIT - dasm_put(Dst, 4863); -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - dasm_put(Dst, 4865, Dt1(->maxstack), -4+PC2PROTO(numparams), -4+PC2PROTO(k), 31-3); - if (op == BC_JFUNCF) { - dasm_put(Dst, 4883); - } else { - dasm_put(Dst, 4885); - } - dasm_put(Dst, 4894); - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - dasm_put(Dst, 4900); - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - dasm_put(Dst, 4902, Dt1(->maxstack), 8+FRAME_VARG, -4+PC2PROTO(k), -4+PC2PROTO(numparams)); - break; - - case BC_FUNCC: - case BC_FUNCCW: - if (op == BC_FUNCC) { - dasm_put(Dst, 4952, Dt8(->f)); - } else { - dasm_put(Dst, 4955, DISPATCH_GL(wrapf)); - } - dasm_put(Dst, 4958, Dt1(->maxstack), Dt1(->base), Dt1(->top), ~LJ_VMST_C); - if (op == BC_FUNCCW) { - dasm_put(Dst, 4971, Dt8(->f)); - } - dasm_put(Dst, 4974, DISPATCH_GL(vmstate), Dt1(->top), 31-3, Dt1(->base), ~LJ_VMST_INTERP, DISPATCH_GL(vmstate)); - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx); - - dasm_put(Dst, 4995); - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int i; - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.long .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.long 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 65\n" - "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.long .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.long .Lframe0\n" - "\t.long .Lbegin\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x5\n\t.uleb128 70\n\t.sleb128 37\n", - (int)ctx->codesz, CFRAME_SIZE); - for (i = 14; i <= 31; i++) - fprintf(ctx->fp, - "\t.byte %d\n\t.uleb128 %d\n" - "\t.byte 5\n\t.uleb128 %d\n\t.uleb128 %d\n", - 0x80+i, 1+2*(31-i), 1200+i, 2+2*(31-i)); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE0:\n\n"); - fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe1:\n" - "\t.long .LECIE1-.LSCIE1\n" - ".LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zPR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -4\n" - "\t.byte 65\n" - "\t.uleb128 6\n" /* augmentation length */ - "\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 1\n\t.uleb128 0\n" - "\t.align 2\n" - ".LECIE1:\n\n"); - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.long .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.long .LASFDE1-.Lframe1\n" - "\t.long .Lbegin-.\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" - "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" - "\t.byte 0x5\n\t.uleb128 70\n\t.sleb128 37\n", - (int)ctx->codesz, CFRAME_SIZE); - for (i = 14; i <= 31; i++) - fprintf(ctx->fp, - "\t.byte %d\n\t.uleb128 %d\n" - "\t.byte 5\n\t.uleb128 %d\n\t.uleb128 %d\n", - 0x80+i, 1+2*(31-i), 1200+i, 2+2*(31-i)); - fprintf(ctx->fp, - "\t.align 2\n" - ".LEFDE1:\n\n"); - break; - default: - break; - } -} - diff --git a/src/buildvm_x64.h b/src/buildvm_x64.h deleted file mode 100644 index 55b22b2e..00000000 --- a/src/buildvm_x64.h +++ /dev/null @@ -1,3406 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM x64 version 1.3.0 -** DO NOT EDIT! The original file is in "buildvm_x86.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -#define DASM_SECTION_CODE_OP 0 -#define DASM_SECTION_CODE_SUB 1 -#define DASM_MAXSECTION 2 -static const unsigned char build_actionlist[16378] = { - 254,1,248,10,252,247,195,237,15,132,244,11,131,227,252,248,41,218,72,141, - 76,25,252,248,139,90,252,252,199,68,10,4,237,248,12,131,192,1,137,68,36,4, - 252,247,195,237,15,132,244,13,248,14,129,252,243,239,252,247,195,237,15,133, - 244,10,65,199,134,233,237,131,227,252,248,41,211,252,247,219,131,232,1,15, - 132,244,248,248,1,72,139,44,10,72,137,106,252,248,131,194,8,131,232,1,15, - 133,244,1,248,2,255,139,108,36,24,137,157,233,248,3,139,68,36,4,139,76,36, - 16,248,4,57,193,15,133,244,252,248,5,131,252,234,8,137,149,233,248,15,72, - 139,76,36,32,72,137,141,233,49,192,248,16,72,131,196,40,65,94,65,95,91,93, - 195,248,6,15,130,244,253,59,149,233,15,135,244,254,199,66,252,252,237,131, - 194,8,131,192,1,252,233,244,4,248,7,255,133,201,15,132,244,5,41,193,141,20, - 202,252,233,244,5,248,8,137,149,233,137,68,36,4,137,206,137,252,239,232,251, - 1,0,139,149,233,252,233,244,3,248,17,137,252,240,72,137,252,252,248,18,139, - 108,36,24,139,173,233,199,133,233,237,252,233,244,16,248,19,139,124,36,24, - 137,198,72,131,196,40,65,94,65,95,91,93,252,233,251,1,1,248,20,72,129,231, - 239,72,137,252,252,248,21,255,139,108,36,24,72,199,193,252,248,252,255,252, - 255,252,255,184,237,139,149,233,68,139,181,233,65,129,198,239,139,90,252, - 252,199,66,252,252,237,65,199,134,233,237,252,233,244,12,248,22,190,237,252, - 233,244,248,248,23,131,232,8,252,233,244,247,248,24,141,68,194,252,248,248, - 1,15,182,139,233,131,195,4,137,149,233,255,137,133,233,137,92,36,28,137,206, - 248,2,137,252,239,232,251,1,0,139,149,233,139,133,233,139,106,252,248,41, - 208,193,232,3,131,192,1,139,157,233,139,11,15,182,252,233,15,182,205,131, - 195,4,65,252,255,36,252,238,248,25,85,83,65,87,65,86,72,131,252,236,40,137, - 252,253,137,124,36,24,137,252,241,187,237,49,192,76,141,188,253,36,233,68, - 139,181,233,65,129,198,239,76,137,189,233,137,68,36,28,72,137,68,36,32,137, - 68,36,16,137,68,36,20,56,133,233,15,132,244,249,65,199,134,233,237,136,133, - 233,139,149,233,139,133,233,41,200,193,232,3,131,192,1,41,209,139,90,252, - 252,137,68,36,4,252,247,195,237,255,15,132,244,13,252,233,244,14,248,26,85, - 83,65,87,65,86,72,131,252,236,40,187,237,137,76,36,20,252,233,244,247,248, - 27,85,83,65,87,65,86,72,131,252,236,40,187,237,248,1,137,84,36,16,137,252, - 253,137,124,36,24,137,252,241,76,139,189,233,76,137,124,36,32,137,108,36, - 28,72,137,165,233,248,2,68,139,181,233,65,129,198,239,248,3,65,199,134,233, - 237,139,149,233,255,1,203,41,211,139,133,233,41,200,193,232,3,131,192,1,248, - 28,139,105,252,248,129,121,253,252,252,239,15,133,244,29,248,30,137,202,137, - 90,252,252,139,157,233,139,11,15,182,252,233,15,182,205,131,195,4,65,252, - 255,36,252,238,248,31,85,83,65,87,65,86,72,131,252,236,40,137,252,253,137, - 124,36,24,137,108,36,28,68,139,189,233,68,43,189,233,199,68,36,20,0,0,0,0, - 68,137,124,36,16,76,139,189,233,76,137,124,36,32,72,137,165,233,252,255,209, - 133,192,15,132,244,15,137,193,187,237,252,233,244,2,248,11,1,209,131,227, - 252,248,137,213,41,218,199,68,193,252,252,237,137,200,139,93,252,244,72,99, - 77,252,240,255,131,252,249,1,15,134,244,247,255,76,141,61,245,76,1,252,249, - 255,68,139,122,252,248,69,139,191,233,69,139,191,233,252,255,225,255,248, - 1,15,132,244,32,41,213,193,252,237,3,141,69,252,255,252,233,244,33,255,248, - 34,15,182,75,252,255,131,252,237,16,141,12,202,41,252,233,15,132,244,35,252, - 247,217,193,252,233,3,139,124,36,24,137,151,233,137,202,72,139,8,72,137,77, - 0,137,252,238,252,233,244,36,248,37,137,4,36,199,68,36,4,237,72,141,4,36, - 128,123,252,252,235,15,133,244,247,65,141,142,233,137,41,199,65,4,237,137, - 205,252,233,244,248,248,38,15,182,67,252,254,255,199,68,36,4,237,137,4,36, - 255,252,242,15,42,192,252,242,15,17,4,36,255,72,141,4,36,252,233,244,247, - 248,39,15,182,67,252,254,141,4,194,248,1,15,182,107,252,255,141,44,252,234, - 248,2,139,124,36,24,137,151,233,137,252,238,72,137,194,137,252,253,137,92, - 36,28,232,251,1,2,139,149,233,133,192,15,132,244,249,248,35,15,182,75,252, - 253,72,139,40,72,137,44,202,139,3,15,182,204,15,182,232,131,195,4,193,232, - 16,65,252,255,36,252,238,248,3,139,141,233,137,89,252,244,141,153,233,41, - 211,139,105,252,248,184,237,252,233,244,30,248,40,137,4,36,199,68,36,4,237, - 72,141,4,36,128,123,252,252,235,15,133,244,247,255,65,141,142,233,137,41, - 199,65,4,237,137,205,252,233,244,248,248,41,15,182,67,252,254,255,72,141, - 4,36,252,233,244,247,248,42,15,182,67,252,254,141,4,194,248,1,15,182,107, - 252,255,141,44,252,234,248,2,139,124,36,24,137,151,233,137,252,238,72,137, - 194,137,252,253,137,92,36,28,232,251,1,3,139,149,233,133,192,15,132,244,249, - 15,182,75,252,253,72,139,44,202,72,137,40,248,43,139,3,15,182,204,15,182, - 232,131,195,4,193,232,16,65,252,255,36,252,238,248,3,139,141,233,137,89,252, - 244,15,182,67,252,253,72,139,44,194,72,137,105,16,141,153,233,41,211,139, - 105,252,248,184,237,252,233,244,30,248,44,139,108,36,24,137,149,233,141,52, - 202,141,20,194,137,252,239,15,182,75,252,252,137,92,36,28,232,251,1,4,248, - 3,139,149,233,255,131,252,248,1,15,135,244,45,248,4,141,91,4,15,130,244,252, - 248,5,15,183,67,252,254,141,156,253,131,233,248,6,139,3,15,182,204,15,182, - 232,131,195,4,193,232,16,65,252,255,36,252,238,248,46,131,195,4,129,120,253, - 4,239,15,130,244,5,252,233,244,6,248,47,129,120,253,4,239,252,233,244,4,248, - 48,131,252,235,4,137,206,137,252,233,139,108,36,24,137,149,233,255,137,194, - 137,252,239,137,92,36,28,232,251,1,5,252,233,244,3,248,49,255,131,252,235, - 4,139,108,36,24,137,149,233,137,252,239,139,115,252,252,137,92,36,28,232, - 251,1,6,252,233,244,3,255,248,50,255,15,182,107,252,255,255,248,51,65,141, - 4,199,252,233,244,247,248,52,255,248,53,65,141,4,199,141,44,252,234,149,252, - 233,244,248,248,54,141,4,194,137,197,252,233,244,248,248,55,255,248,56,141, - 4,194,248,1,141,44,252,234,248,2,141,12,202,68,15,182,67,252,252,137,206, - 137,193,139,124,36,24,137,151,233,137,252,234,137,252,253,137,92,36,28,232, - 251,1,7,139,149,233,133,192,15,132,244,43,248,45,137,193,41,208,137,89,252, - 244,141,152,233,184,237,252,233,244,28,248,57,139,108,36,24,137,149,233,141, - 52,194,137,252,239,137,92,36,28,232,251,1,8,139,149,233,255,133,192,15,133, - 244,45,15,183,67,252,254,139,60,194,252,233,244,58,255,252,233,244,45,255, - 248,59,141,76,202,8,248,29,137,76,36,4,137,4,36,131,252,233,8,139,108,36, - 24,137,149,233,137,206,141,20,193,137,252,239,137,92,36,28,232,251,1,9,139, - 149,233,139,76,36,4,139,4,36,139,105,252,248,131,192,1,65,57,215,15,132,244, - 60,137,202,137,90,252,252,139,157,233,139,11,15,182,252,233,15,182,205,131, - 195,4,65,252,255,36,252,238,248,61,139,108,36,24,137,149,233,137,206,137, - 252,239,137,92,36,28,232,251,1,10,139,149,233,139,67,252,252,15,182,204,15, - 182,232,193,232,16,65,252,255,164,253,252,238,233,248,62,129,252,248,239, - 15,130,244,63,139,106,4,129,252,253,239,15,131,244,63,139,90,252,252,137, - 68,36,4,137,106,252,252,139,42,137,106,252,248,131,232,2,15,132,244,248,255, - 137,209,248,1,131,193,8,72,139,41,72,137,105,252,248,131,232,1,15,133,244, - 1,248,2,139,68,36,4,252,233,244,64,248,65,129,252,248,239,15,130,244,63,139, - 106,4,137,252,233,193,252,249,15,131,252,249,252,254,15,132,244,249,184,237, - 252,247,213,57,232,255,15,71,197,255,15,134,244,247,137,232,248,1,255,248, - 2,139,106,252,248,139,132,253,197,233,139,90,252,252,199,66,252,252,237,137, - 66,252,248,252,233,244,66,248,3,184,237,252,233,244,2,248,67,129,252,248, - 239,15,130,244,63,139,106,4,139,90,252,252,129,252,253,239,15,133,244,252, - 248,1,139,42,139,173,233,248,2,133,252,237,199,66,252,252,237,255,15,132, - 244,66,65,139,134,233,199,66,252,252,237,137,106,252,248,139,141,233,35,136, - 233,105,201,239,3,141,233,248,3,129,185,233,239,15,133,244,250,57,129,233, - 15,132,244,251,248,4,139,137,233,133,201,15,133,244,3,255,252,233,244,66, - 248,5,139,105,4,129,252,253,239,15,132,244,66,139,1,137,106,252,252,137,66, - 252,248,252,233,244,66,248,6,129,252,253,239,15,132,244,1,129,252,253,239, - 15,135,244,254,129,252,253,239,15,134,244,253,189,237,252,233,244,254,248, - 7,255,189,237,248,8,252,247,213,65,139,172,253,174,233,252,233,244,2,248, - 68,129,252,248,239,15,130,244,63,129,122,253,4,239,15,133,244,63,139,42,131, - 189,233,0,15,133,244,63,129,122,253,12,239,15,133,244,63,139,66,8,137,133, - 233,139,90,252,252,199,66,252,252,237,255,137,106,252,248,252,246,133,233, - 235,15,132,244,247,128,165,233,235,65,139,134,233,65,137,174,233,137,133, - 233,248,1,252,233,244,66,248,69,129,252,248,239,15,130,244,63,129,122,253, - 4,239,15,133,244,63,137,213,139,50,141,82,8,139,124,36,24,232,251,1,11,137, - 252,234,72,139,40,139,90,252,252,72,137,106,252,248,252,233,244,66,248,70, - 255,129,252,248,239,15,133,244,63,129,122,253,4,239,255,15,133,244,247,139, - 42,252,233,244,71,248,1,15,135,244,63,255,15,131,244,63,255,252,242,15,16, - 2,252,233,244,72,255,221,2,252,233,244,73,255,248,74,129,252,248,239,15,130, - 244,63,139,90,252,252,129,122,253,4,239,15,133,244,249,139,2,248,2,199,66, - 252,252,237,137,66,252,248,252,233,244,66,248,3,129,122,253,4,239,15,135, - 244,63,65,131,190,233,0,15,133,244,63,65,139,174,233,65,59,174,233,255,15, - 130,244,247,232,244,75,248,1,139,108,36,24,137,149,233,137,92,36,28,137,214, - 137,252,239,255,232,251,1,12,255,232,251,1,13,255,139,149,233,252,233,244, - 2,248,76,129,252,248,239,15,130,244,63,15,132,244,248,248,1,129,122,253,4, - 239,15,133,244,63,139,108,36,24,137,149,233,137,149,233,139,90,252,252,139, - 50,141,82,8,137,252,239,137,92,36,28,232,251,1,14,139,149,233,133,192,15, - 132,244,249,72,139,106,8,72,139,66,16,72,137,106,252,248,72,137,2,248,77, - 184,237,255,252,233,244,78,248,2,199,66,12,237,252,233,244,1,248,3,199,66, - 252,252,237,252,233,244,66,248,79,129,252,248,239,15,130,244,63,139,42,129, - 122,253,4,239,15,133,244,63,255,131,189,233,0,15,133,244,63,255,139,106,252, - 248,139,133,233,139,90,252,252,199,66,252,252,237,137,66,252,248,199,66,12, - 237,184,237,252,233,244,78,248,80,129,252,248,239,15,130,244,63,129,122,253, - 4,239,15,133,244,63,129,122,253,12,239,255,139,90,252,252,255,139,66,8,131, - 192,1,199,66,252,252,237,137,66,252,248,255,252,242,15,16,66,8,72,189,237, - 237,102,72,15,110,205,252,242,15,88,193,252,242,15,45,192,252,242,15,17,66, - 252,248,255,139,42,59,133,233,15,131,244,248,193,224,3,3,133,233,248,1,129, - 120,253,4,239,15,132,244,81,72,139,40,72,137,42,252,233,244,77,248,2,131, - 189,233,0,15,132,244,81,137,252,239,137,213,137,198,232,251,1,15,137,252, - 234,133,192,15,133,244,1,248,81,184,237,252,233,244,78,248,82,255,139,106, - 252,248,139,133,233,139,90,252,252,199,66,252,252,237,137,66,252,248,255, - 199,66,12,237,199,66,8,0,0,0,0,255,15,87,192,252,242,15,17,66,8,255,217,252, - 238,221,90,8,255,184,237,252,233,244,78,248,83,129,252,248,239,15,130,244, - 63,141,74,8,131,232,1,187,237,248,1,65,15,182,174,233,193,252,237,235,131, - 229,1,1,252,235,252,233,244,28,248,84,129,252,248,239,15,130,244,63,129,122, - 253,12,239,15,133,244,63,255,139,106,4,137,106,12,199,66,4,237,139,42,139, - 90,8,137,106,8,137,26,141,74,16,131,232,2,187,237,252,233,244,1,248,85,129, - 252,248,239,15,130,244,63,139,42,139,90,252,252,137,92,36,28,137,44,36,129, - 122,253,4,239,15,133,244,63,72,131,189,233,0,15,133,244,63,128,189,233,235, - 15,135,244,63,139,141,233,15,132,244,247,255,59,141,233,15,132,244,63,248, - 1,141,92,193,252,240,59,157,233,15,135,244,63,137,157,233,139,108,36,24,137, - 149,233,131,194,8,137,149,233,141,108,194,232,72,41,221,57,203,15,132,244, - 249,248,2,72,139,4,43,72,137,67,252,248,131,252,235,8,57,203,15,133,244,2, - 248,3,137,206,139,60,36,232,244,25,65,199,134,233,237,255,139,108,36,24,139, - 28,36,139,149,233,129,252,248,239,15,135,244,254,248,4,139,139,233,68,139, - 187,233,137,139,233,68,137,252,251,41,203,15,132,244,252,141,4,26,193,252, - 235,3,59,133,233,15,135,244,255,137,213,72,41,205,248,5,72,139,1,72,137,4, - 41,131,193,8,68,57,252,249,15,133,244,5,248,6,141,67,2,199,66,252,252,237, - 248,7,139,92,36,28,137,68,36,4,72,199,193,252,248,252,255,252,255,252,255, - 252,247,195,237,255,15,132,244,13,252,233,244,14,248,8,199,66,252,252,237, - 139,139,233,131,252,233,8,137,139,233,72,139,1,72,137,2,184,237,252,233,244, - 7,248,9,139,12,36,68,137,185,233,137,222,137,252,239,232,251,1,0,139,28,36, - 139,149,233,252,233,244,4,248,86,139,106,252,248,139,173,233,139,90,252,252, - 137,92,36,28,137,44,36,72,131,189,233,0,15,133,244,63,255,128,189,233,235, - 15,135,244,63,139,141,233,15,132,244,247,59,141,233,15,132,244,63,248,1,141, - 92,193,252,248,59,157,233,15,135,244,63,137,157,233,139,108,36,24,137,149, - 233,137,149,233,141,108,194,252,240,72,41,221,57,203,15,132,244,249,248,2, - 255,72,139,4,43,72,137,67,252,248,131,252,235,8,57,203,15,133,244,2,248,3, - 137,206,139,60,36,232,244,25,65,199,134,233,237,139,108,36,24,139,28,36,139, - 149,233,129,252,248,239,15,135,244,254,248,4,139,139,233,68,139,187,233,137, - 139,233,68,137,252,251,41,203,15,132,244,252,141,4,26,193,252,235,3,59,133, - 233,15,135,244,255,255,137,213,72,41,205,248,5,72,139,1,72,137,4,41,131,193, - 8,68,57,252,249,15,133,244,5,248,6,141,67,1,248,7,139,92,36,28,137,68,36, - 4,49,201,252,247,195,237,15,132,244,13,252,233,244,14,248,8,137,222,137,252, - 239,232,251,1,16,248,9,139,12,36,68,137,185,233,137,222,137,252,239,232,251, - 1,0,139,28,36,139,149,233,252,233,244,4,248,87,139,108,36,24,72,252,247,133, - 233,237,15,132,244,63,255,137,149,233,141,68,194,252,248,137,133,233,49,192, - 72,137,133,233,176,235,136,133,233,252,233,244,16,255,248,71,255,248,73,139, - 90,252,252,221,90,252,248,252,233,244,66,255,248,88,129,252,248,239,15,130, - 244,63,255,129,122,253,4,239,15,133,244,248,139,42,131,252,253,0,15,137,244, - 71,252,247,221,15,136,244,247,248,89,248,71,139,90,252,252,199,66,252,252, - 237,137,106,252,248,252,233,244,66,248,1,139,90,252,252,199,66,252,252,0, - 0,224,65,199,66,252,248,0,0,0,0,252,233,244,66,248,2,15,135,244,63,255,129, - 122,253,4,239,15,131,244,63,255,252,242,15,16,2,72,184,237,237,102,72,15, - 110,200,15,84,193,248,72,139,90,252,252,252,242,15,17,66,252,248,255,221, - 2,217,225,248,72,248,73,139,90,252,252,221,90,252,248,255,248,66,184,237, - 248,78,137,68,36,4,248,64,252,247,195,237,15,133,244,253,248,5,56,67,252, - 255,15,135,244,252,15,182,75,252,253,72,252,247,209,141,20,202,139,3,15,182, - 204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,6,199,68,194, - 252,244,237,131,192,1,252,233,244,5,248,7,72,199,193,252,248,252,255,252, - 255,252,255,252,233,244,14,248,90,255,129,122,253,4,239,15,133,244,247,139, - 42,252,233,244,71,248,1,15,135,244,63,255,252,242,15,16,2,232,244,91,255, - 252,242,15,45,232,129,252,253,0,0,0,128,15,133,244,71,252,242,15,42,205,102, - 15,46,193,15,138,244,72,15,132,244,71,255,221,2,232,244,91,255,248,92,255, - 252,242,15,16,2,232,244,93,255,221,2,232,244,93,255,248,94,129,252,248,239, - 15,130,244,63,129,122,253,4,239,15,131,244,63,252,242,15,81,2,252,233,244, - 72,255,248,94,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244, - 63,221,2,217,252,250,252,233,244,73,255,248,95,129,252,248,239,15,130,244, - 63,129,122,253,4,239,15,131,244,63,217,252,237,221,2,217,252,241,252,233, - 244,73,248,96,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244, - 63,217,252,236,221,2,217,252,241,252,233,244,73,248,97,129,252,248,239,255, - 15,130,244,63,129,122,253,4,239,15,131,244,63,221,2,232,244,98,252,233,244, - 73,248,99,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,221, - 2,217,252,254,252,233,244,73,248,100,129,252,248,239,255,15,130,244,63,129, - 122,253,4,239,15,131,244,63,221,2,217,252,255,252,233,244,73,248,101,129, - 252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,221,2,217,252,242, - 221,216,252,233,244,73,248,102,129,252,248,239,15,130,244,63,255,129,122, - 253,4,239,15,131,244,63,221,2,217,192,216,200,217,232,222,225,217,252,250, - 217,252,243,252,233,244,73,248,103,129,252,248,239,15,130,244,63,129,122, - 253,4,239,15,131,244,63,221,2,217,192,216,200,217,232,222,225,217,252,250, - 217,201,217,252,243,252,233,244,73,248,104,129,252,248,239,15,130,244,63, - 129,122,253,4,239,15,131,244,63,255,221,2,217,232,217,252,243,252,233,244, - 73,255,248,105,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244, - 63,252,242,15,16,2,255,137,213,232,251,1,17,137,252,234,252,233,244,72,255, - 248,106,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,252, - 242,15,16,2,255,137,213,232,251,1,18,137,252,234,252,233,244,72,255,248,107, - 129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,252,242,15, - 16,2,255,137,213,232,251,1,19,137,252,234,252,233,244,72,248,108,255,248, - 109,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,252,242, - 15,16,2,139,106,252,248,252,242,15,89,133,233,252,233,244,72,255,248,109, - 129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,221,2,139,106, - 252,248,220,141,233,252,233,244,73,255,248,110,129,252,248,239,15,130,244, - 63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244,63,221,2, - 221,66,8,217,252,243,252,233,244,73,248,111,129,252,248,239,15,130,244,63, - 129,122,253,4,239,15,131,244,63,129,122,253,12,239,255,15,131,244,63,221, - 66,8,221,2,217,252,253,221,217,252,233,244,73,248,112,129,252,248,239,15, - 130,244,63,139,106,4,129,252,253,239,15,131,244,63,139,90,252,252,139,2,137, - 106,252,252,137,66,252,248,209,229,129,252,253,0,0,224,252,255,15,131,244, - 249,9,232,15,132,244,249,184,252,254,3,0,0,129,252,253,0,0,32,0,15,130,244, - 250,248,1,193,252,237,21,41,197,255,252,242,15,42,197,255,137,44,36,219,4, - 36,255,139,106,252,252,129,229,252,255,252,255,15,128,129,205,0,0,224,63, - 137,106,252,252,248,2,255,252,242,15,17,2,255,221,26,255,184,237,252,233, - 244,78,248,3,255,15,87,192,252,233,244,2,255,217,252,238,252,233,244,2,255, - 248,4,255,252,242,15,16,2,72,189,237,237,102,72,15,110,205,252,242,15,89, - 193,252,242,15,17,66,252,248,255,221,2,199,4,36,0,0,128,90,216,12,36,221, - 90,252,248,255,139,106,252,252,184,52,4,0,0,209,229,252,233,244,1,255,248, - 113,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,252,242, - 15,16,2,255,248,113,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131, - 244,63,221,2,255,139,106,4,139,90,252,252,209,229,129,252,253,0,0,224,252, - 255,15,132,244,250,255,15,40,224,232,244,114,252,242,15,92,224,248,1,252, - 242,15,17,66,252,248,252,242,15,17,34,255,217,192,232,244,114,220,252,233, - 248,1,221,90,252,248,221,26,255,139,66,252,252,139,106,4,49,232,15,136,244, - 249,248,2,184,237,252,233,244,78,248,3,129,252,245,0,0,0,128,137,106,4,252, - 233,244,2,248,4,255,15,87,228,252,233,244,1,255,217,252,238,217,201,252,233, - 244,1,255,248,115,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131, - 244,63,129,122,253,12,239,15,131,244,63,221,66,8,221,2,248,1,217,252,248, - 223,224,158,15,138,244,1,221,217,252,233,244,73,255,248,116,129,252,248,239, - 15,130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244, - 63,252,242,15,16,2,252,242,15,16,74,8,232,244,117,252,233,244,72,255,248, - 116,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,129,122, - 253,12,239,15,131,244,63,221,2,221,66,8,232,244,117,252,233,244,73,255,248, - 118,185,2,0,0,0,129,122,253,4,239,255,15,133,244,250,139,42,248,1,57,193, - 15,131,244,71,129,124,253,202,252,252,239,15,133,244,249,59,108,202,252,248, - 15,79,108,202,252,248,131,193,1,252,233,244,1,248,3,15,135,244,63,255,252, - 233,244,252,248,4,15,135,244,63,255,252,242,15,16,2,248,5,57,193,15,131,244, - 72,129,124,253,202,252,252,239,255,15,130,244,252,15,135,244,63,252,242,15, - 42,76,202,252,248,252,233,244,253,255,248,6,252,242,15,16,76,202,252,248, - 248,7,252,242,15,93,193,131,193,1,252,233,244,5,255,248,119,185,2,0,0,0,129, - 122,253,4,239,255,15,133,244,250,139,42,248,1,57,193,15,131,244,71,129,124, - 253,202,252,252,239,15,133,244,249,59,108,202,252,248,15,76,108,202,252,248, - 131,193,1,252,233,244,1,248,3,15,135,244,63,255,248,6,252,242,15,16,76,202, - 252,248,248,7,252,242,15,95,193,131,193,1,252,233,244,5,255,248,9,221,216, - 252,233,244,63,255,248,120,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,133,244,63,139,42,255,139,173,233,252,233,244,71,255,252,242,15,42,133, - 233,252,233,244,72,255,219,133,233,252,233,244,73,255,248,121,129,252,248, - 239,15,133,244,63,129,122,253,4,239,15,133,244,63,139,42,139,90,252,252,131, - 189,233,1,15,130,244,81,15,182,173,233,255,252,242,15,42,197,252,233,244, - 72,255,137,44,36,219,4,36,252,233,244,73,255,248,122,65,139,174,233,65,59, - 174,233,15,130,244,247,232,244,75,248,1,129,252,248,239,15,133,244,63,129, - 122,253,4,239,255,15,133,244,63,139,42,129,252,253,252,255,0,0,0,15,135,244, - 63,137,108,36,4,255,15,131,244,63,252,242,15,44,42,129,252,253,252,255,0, - 0,0,15,135,244,63,137,108,36,4,255,15,131,244,63,221,2,219,92,36,4,129,124, - 36,4,252,255,0,0,0,15,135,244,63,255,199,68,36,8,1,0,0,0,72,141,68,36,4,248, - 123,139,108,36,24,137,149,233,139,84,36,8,72,137,198,137,252,239,137,92,36, - 28,232,251,1,20,139,149,233,139,90,252,252,199,66,252,252,237,137,66,252, - 248,252,233,244,66,248,124,65,139,174,233,65,59,174,233,15,130,244,247,232, - 244,75,248,1,199,68,36,4,252,255,252,255,252,255,252,255,129,252,248,239, - 15,130,244,63,15,134,244,247,129,122,253,20,239,255,15,133,244,63,139,106, - 16,137,108,36,4,255,15,131,244,63,252,242,15,44,106,16,137,108,36,4,255,15, - 131,244,63,221,66,16,219,92,36,4,255,248,1,129,122,253,4,239,15,133,244,63, - 129,122,253,12,239,255,139,42,137,108,36,8,139,173,233,255,139,74,8,255,252, - 242,15,44,74,8,255,139,68,36,4,57,197,15,130,244,251,248,2,133,201,15,142, - 244,253,248,3,139,108,36,8,41,200,15,140,244,125,141,172,253,13,233,131,192, - 1,248,4,137,68,36,8,137,232,252,233,244,123,248,5,15,140,244,252,141,68,40, - 1,252,233,244,2,248,6,137,232,252,233,244,2,248,7,255,15,132,244,254,1,252, - 233,131,193,1,15,143,244,3,248,8,185,1,0,0,0,252,233,244,3,248,125,49,192, - 252,233,244,4,248,126,129,252,248,239,15,130,244,63,65,139,174,233,65,59, - 174,233,15,130,244,247,232,244,75,248,1,255,129,122,253,4,239,15,133,244, - 63,129,122,253,12,239,139,42,255,15,133,244,63,139,66,8,255,15,131,244,63, - 252,242,15,44,66,8,255,15,131,244,63,221,66,8,219,92,36,4,139,68,36,4,255, - 133,192,15,142,244,125,131,189,233,1,15,130,244,125,15,133,244,127,65,57, - 134,233,15,130,244,127,15,182,141,233,65,139,174,233,137,68,36,8,248,1,136, - 77,0,131,197,1,131,232,1,15,133,244,1,65,139,134,233,252,233,244,123,248, - 128,129,252,248,239,255,15,130,244,63,65,139,174,233,65,59,174,233,15,130, - 244,247,232,244,75,248,1,129,122,253,4,239,15,133,244,63,139,42,139,133,233, - 133,192,15,132,244,125,65,57,134,233,15,130,244,129,129,197,239,137,92,36, - 4,137,68,36,8,65,139,158,233,248,1,255,15,182,77,0,131,197,1,131,232,1,136, - 12,3,15,133,244,1,137,216,139,92,36,4,252,233,244,123,248,130,129,252,248, - 239,15,130,244,63,65,139,174,233,65,59,174,233,15,130,244,247,232,244,75, - 248,1,129,122,253,4,239,15,133,244,63,139,42,139,133,233,65,57,134,233,255, - 15,130,244,129,129,197,239,137,92,36,4,137,68,36,8,65,139,158,233,252,233, - 244,249,248,1,15,182,76,5,0,131,252,249,65,15,130,244,248,131,252,249,90, - 15,135,244,248,131,252,241,32,248,2,136,12,3,248,3,131,232,1,15,137,244,1, - 137,216,139,92,36,4,252,233,244,123,248,131,129,252,248,239,15,130,244,63, - 255,65,139,174,233,65,59,174,233,15,130,244,247,232,244,75,248,1,129,122, - 253,4,239,15,133,244,63,139,42,139,133,233,65,57,134,233,15,130,244,129,129, - 197,239,137,92,36,4,137,68,36,8,65,139,158,233,252,233,244,249,248,1,15,182, - 76,5,0,131,252,249,97,15,130,244,248,255,131,252,249,122,15,135,244,248,131, - 252,241,32,248,2,136,12,3,248,3,131,232,1,15,137,244,1,137,216,139,92,36, - 4,252,233,244,123,248,132,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,133,244,63,137,213,139,58,232,251,1,21,137,252,234,255,137,197,252,233, - 244,71,255,252,242,15,42,192,252,233,244,72,255,248,133,129,252,248,239,15, - 130,244,63,129,122,253,4,239,255,15,133,244,247,139,42,252,233,244,89,248, - 1,15,135,244,63,255,252,242,15,16,2,72,189,237,237,102,72,15,110,205,252, - 242,15,88,193,102,15,126,197,255,252,233,244,89,255,248,134,129,252,248,239, - 15,130,244,63,255,72,189,237,237,102,72,15,110,205,255,199,4,36,0,0,192,89, - 255,15,133,244,247,139,42,252,233,244,248,248,1,15,135,244,63,255,252,242, - 15,16,2,252,242,15,88,193,102,15,126,197,255,248,2,137,68,36,4,141,68,194, - 252,240,248,1,57,208,15,134,244,89,129,120,253,4,239,255,15,133,244,248,35, - 40,131,232,8,252,233,244,1,248,2,15,135,244,135,255,15,131,244,135,255,252, - 242,15,16,0,252,242,15,88,193,102,15,126,193,33,205,255,131,232,8,252,233, - 244,1,248,136,129,252,248,239,15,130,244,63,255,15,133,244,248,11,40,131, - 232,8,252,233,244,1,248,2,15,135,244,135,255,252,242,15,16,0,252,242,15,88, - 193,102,15,126,193,9,205,255,131,232,8,252,233,244,1,248,137,129,252,248, - 239,15,130,244,63,255,15,133,244,248,51,40,131,232,8,252,233,244,1,248,2, - 15,135,244,135,255,252,242,15,16,0,252,242,15,88,193,102,15,126,193,49,205, - 255,131,232,8,252,233,244,1,248,138,129,252,248,239,15,130,244,63,129,122, - 253,4,239,255,248,2,15,205,252,233,244,89,248,139,129,252,248,239,15,130, - 244,63,129,122,253,4,239,255,248,2,252,247,213,255,248,89,252,242,15,42,197, - 252,233,244,72,255,248,135,139,68,36,4,252,233,244,63,255,248,140,129,252, - 248,239,15,130,244,63,129,122,253,4,239,255,248,2,129,122,253,12,239,15,133, - 244,63,139,74,8,255,248,140,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,131,244,63,129,122,253,12,239,15,131,244,63,252,242,15,16,2,252,242,15, - 16,74,8,72,189,237,237,102,72,15,110,213,252,242,15,88,194,252,242,15,88, - 202,102,15,126,197,102,15,126,201,255,211,229,252,233,244,89,255,248,141, - 129,252,248,239,15,130,244,63,129,122,253,4,239,255,248,141,129,252,248,239, - 15,130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244, - 63,252,242,15,16,2,252,242,15,16,74,8,72,189,237,237,102,72,15,110,213,252, - 242,15,88,194,252,242,15,88,202,102,15,126,197,102,15,126,201,255,211,252, - 237,252,233,244,89,255,248,142,129,252,248,239,15,130,244,63,129,122,253, - 4,239,255,248,142,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131, - 244,63,129,122,253,12,239,15,131,244,63,252,242,15,16,2,252,242,15,16,74, - 8,72,189,237,237,102,72,15,110,213,252,242,15,88,194,252,242,15,88,202,102, - 15,126,197,102,15,126,201,255,211,252,253,252,233,244,89,255,248,143,129, - 252,248,239,15,130,244,63,129,122,253,4,239,255,248,143,129,252,248,239,15, - 130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244, - 63,252,242,15,16,2,252,242,15,16,74,8,72,189,237,237,102,72,15,110,213,252, - 242,15,88,194,252,242,15,88,202,102,15,126,197,102,15,126,201,255,211,197, - 252,233,244,89,255,248,144,129,252,248,239,15,130,244,63,129,122,253,4,239, - 255,248,144,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63, - 129,122,253,12,239,15,131,244,63,252,242,15,16,2,252,242,15,16,74,8,72,189, - 237,237,102,72,15,110,213,252,242,15,88,194,252,242,15,88,202,102,15,126, - 197,102,15,126,201,255,211,205,252,233,244,89,248,127,184,237,252,233,244, - 63,248,129,184,237,248,63,139,108,36,24,139,90,252,252,137,92,36,28,137,149, - 233,141,68,194,252,248,141,136,233,137,133,233,139,66,252,248,59,141,233, - 15,135,244,251,137,252,239,252,255,144,233,139,149,233,133,192,15,143,244, - 78,248,1,255,139,141,233,41,209,193,252,233,3,133,192,141,65,1,139,106,252, - 248,15,133,244,33,139,157,233,139,11,15,182,252,233,15,182,205,131,195,4, - 65,252,255,36,252,238,248,33,137,209,252,247,195,237,15,133,244,249,15,182, - 107,252,253,72,252,247,213,141,20,252,234,252,233,244,28,248,3,137,221,131, - 229,252,248,41,252,234,252,233,244,28,248,5,190,237,137,252,239,232,251,1, - 0,139,149,233,49,192,252,233,244,1,248,75,93,72,137,108,36,8,139,108,36,24, - 137,92,36,28,137,149,233,255,141,68,194,252,248,137,252,239,137,133,233,232, - 251,1,22,139,149,233,139,133,233,41,208,193,232,3,131,192,1,72,139,108,36, - 8,85,195,248,145,255,65,15,182,134,233,168,235,15,133,244,251,168,235,15, - 133,244,247,168,235,15,132,244,247,65,252,255,142,233,252,233,244,247,255, - 248,146,65,15,182,134,233,168,235,15,133,244,251,252,233,244,247,248,147, - 65,15,182,134,233,168,235,15,133,244,251,168,235,15,132,244,251,65,252,255, - 142,233,15,132,244,247,168,235,15,132,244,251,248,1,255,139,108,36,24,137, - 149,233,137,222,137,252,239,232,251,1,23,248,3,139,149,233,248,4,15,182,75, - 252,253,248,5,15,182,107,252,252,15,183,67,252,254,65,252,255,164,253,252, - 238,233,248,148,131,195,4,139,77,232,137,76,36,4,252,233,244,4,248,149,255, - 139,106,252,248,139,173,233,15,182,133,233,141,4,194,139,108,36,24,137,149, - 233,137,133,233,137,222,65,141,190,233,73,137,174,233,137,92,36,28,232,251, - 1,24,252,233,244,3,255,248,150,137,92,36,28,255,248,151,255,137,92,36,28, - 131,203,1,248,1,255,141,68,194,252,248,139,108,36,24,137,149,233,137,133, - 233,137,222,137,252,239,232,251,1,25,199,68,36,28,0,0,0,0,255,131,227,252, - 254,255,139,149,233,72,137,193,139,133,233,41,208,72,137,205,15,182,75,252, - 253,193,232,3,131,192,1,252,255,229,248,152,255,65,85,65,84,65,83,65,82,65, - 81,65,80,87,86,85,72,141,108,36,88,85,83,82,81,80,15,182,69,252,248,138,101, - 252,240,76,137,125,252,248,76,137,117,252,240,68,139,117,0,65,139,142,233, - 65,199,134,233,237,65,137,134,233,65,137,142,233,72,129,252,236,239,72,131, - 197,128,252,242,68,15,17,125,252,248,252,242,68,15,17,117,252,240,252,242, - 68,15,17,109,232,252,242,68,15,17,101,224,252,242,68,15,17,93,216,252,242, - 68,15,17,85,208,252,242,68,15,17,77,200,252,242,68,15,17,69,192,252,242,15, - 17,125,184,252,242,15,17,117,176,252,242,15,17,109,168,252,242,15,17,101, - 160,252,242,15,17,93,152,252,242,15,17,85,144,252,242,15,17,77,136,252,242, - 15,17,69,128,65,139,174,233,65,139,150,233,73,137,174,233,65,199,134,233, - 0,0,0,0,137,149,233,72,137,230,65,141,190,233,232,251,1,26,72,139,141,233, - 72,129,225,239,72,137,204,137,169,233,139,149,233,139,153,233,252,233,244, - 247,255,248,153,255,72,131,196,16,248,1,76,139,108,36,8,76,139,36,36,133, - 192,15,136,244,249,137,68,36,4,68,139,122,252,248,69,139,191,233,69,139,191, - 233,65,199,134,233,0,0,0,0,65,199,134,233,237,139,3,15,182,204,15,182,232, - 131,195,4,193,232,16,129,252,253,239,15,130,244,248,139,68,36,4,248,2,65, - 252,255,36,252,238,248,3,252,247,216,137,252,239,137,198,232,251,1,1,255, - 248,91,255,217,124,36,4,137,68,36,8,102,184,0,4,102,11,68,36,4,102,37,252, - 255,252,247,102,137,68,36,6,217,108,36,6,217,252,252,217,108,36,4,139,68, - 36,8,195,255,248,154,72,184,237,237,102,72,15,110,208,72,184,237,237,102, - 72,15,110,216,15,40,200,102,15,84,202,102,15,46,217,15,134,244,247,102,15, - 85,208,252,242,15,88,203,252,242,15,92,203,102,15,86,202,72,184,237,237,102, - 72,15,110,208,252,242,15,194,193,1,102,15,84,194,252,242,15,92,200,15,40, - 193,248,1,195,248,93,255,217,124,36,4,137,68,36,8,102,184,0,8,102,11,68,36, - 4,102,37,252,255,252,251,102,137,68,36,6,217,108,36,6,217,252,252,217,108, - 36,4,139,68,36,8,195,255,248,155,72,184,237,237,102,72,15,110,208,72,184, - 237,237,102,72,15,110,216,15,40,200,102,15,84,202,102,15,46,217,15,134,244, - 247,102,15,85,208,252,242,15,88,203,252,242,15,92,203,102,15,86,202,72,184, - 237,237,102,72,15,110,208,252,242,15,194,193,6,102,15,84,194,252,242,15,92, - 200,15,40,193,248,1,195,248,114,255,217,124,36,4,137,68,36,8,102,184,0,12, - 102,11,68,36,4,102,137,68,36,6,217,108,36,6,217,252,252,217,108,36,4,139, - 68,36,8,195,255,248,156,72,184,237,237,102,72,15,110,208,72,184,237,237,102, - 72,15,110,216,15,40,200,102,15,84,202,102,15,46,217,15,134,244,247,102,15, - 85,208,15,40,193,252,242,15,88,203,252,242,15,92,203,72,184,237,237,102,72, - 15,110,216,252,242,15,194,193,1,102,15,84,195,252,242,15,92,200,102,15,86, - 202,15,40,193,248,1,195,248,157,255,15,40,232,252,242,15,94,193,72,184,237, - 237,102,72,15,110,208,72,184,237,237,102,72,15,110,216,15,40,224,102,15,84, - 226,102,15,46,220,15,134,244,247,102,15,85,208,252,242,15,88,227,252,242, - 15,92,227,102,15,86,226,72,184,237,237,102,72,15,110,208,252,242,15,194,196, - 1,102,15,84,194,252,242,15,92,224,15,40,197,252,242,15,89,204,252,242,15, - 92,193,195,248,1,252,242,15,89,200,15,40,197,252,242,15,92,193,195,255,217, - 193,216,252,241,217,124,36,4,102,184,0,4,102,11,68,36,4,102,37,252,255,252, - 247,102,137,68,36,6,217,108,36,6,217,252,252,217,108,36,4,222,201,222,252, - 233,195,255,248,98,217,252,234,222,201,248,158,217,84,36,252,248,129,124, - 36,252,248,0,0,128,127,15,132,244,247,129,124,36,252,248,0,0,128,252,255, - 15,132,244,248,248,159,217,192,217,252,252,220,252,233,217,201,217,252,240, - 217,232,222,193,217,252,253,221,217,248,1,195,248,2,221,216,217,252,238,195, - 255,248,117,255,248,160,252,242,15,45,193,252,242,15,42,208,102,15,46,202, - 15,133,244,254,15,138,244,255,248,161,131,252,248,1,15,142,244,252,248,1, - 169,1,0,0,0,15,133,244,248,252,242,15,89,192,209,232,252,233,244,1,248,2, - 209,232,15,132,244,251,15,40,200,248,3,252,242,15,89,192,209,232,15,132,244, - 250,15,131,244,3,255,252,242,15,89,200,252,233,244,3,248,4,252,242,15,89, - 193,248,5,195,248,6,15,132,244,5,15,130,244,253,252,247,216,232,244,1,72, - 184,237,237,102,72,15,110,200,252,242,15,94,200,15,40,193,195,248,7,72,184, - 237,237,102,72,15,110,192,195,248,8,102,72,15,126,200,72,209,224,72,193,192, - 12,72,61,252,254,15,0,0,15,132,244,248,102,72,15,126,192,72,209,224,15,132, - 244,250,255,72,193,192,12,72,61,252,254,15,0,0,15,132,244,251,252,242,15, - 17,76,36,252,240,252,242,15,17,68,36,252,248,221,68,36,252,240,221,68,36, - 252,248,217,252,241,217,192,217,252,252,220,252,233,217,201,217,252,240,217, - 232,222,193,217,252,253,221,217,221,92,36,252,248,252,242,15,16,68,36,252, - 248,195,248,9,72,184,237,237,102,72,15,110,208,102,15,46,194,15,132,244,247, - 15,40,193,248,1,195,248,2,72,184,237,237,102,72,15,110,208,102,15,84,194, - 72,184,237,237,102,72,15,110,208,102,15,46,194,15,132,244,1,102,15,80,193, - 15,87,192,136,196,15,146,208,48,224,15,133,244,1,248,3,72,184,237,237,255, - 102,72,15,110,192,195,248,4,102,15,80,193,133,192,15,133,244,3,15,87,192, - 195,248,5,102,15,80,193,133,192,15,132,244,3,15,87,192,195,248,162,255,131, - 252,255,1,15,130,244,91,15,132,244,93,131,252,255,3,15,130,244,114,15,135, - 244,248,252,242,15,81,192,195,248,2,252,242,15,17,68,36,252,248,221,68,36, - 252,248,131,252,255,5,15,135,244,248,15,132,244,247,232,244,98,252,233,244, - 253,248,1,232,244,158,255,252,233,244,253,248,2,131,252,255,7,15,132,244, - 247,15,135,244,248,217,252,237,217,201,217,252,241,252,233,244,253,248,1, - 217,232,217,201,217,252,241,252,233,244,253,248,2,131,252,255,9,15,132,244, - 247,15,135,244,248,217,252,236,217,201,217,252,241,252,233,244,253,248,1, - 255,217,252,254,252,233,244,253,248,2,131,252,255,11,15,132,244,247,15,135, - 244,255,217,252,255,252,233,244,253,248,1,217,252,242,221,216,248,7,221,92, - 36,252,248,252,242,15,16,68,36,252,248,195,255,139,124,36,12,221,68,36,4, - 131,252,255,1,15,130,244,91,15,132,244,93,131,252,255,3,15,130,244,114,15, - 135,244,248,217,252,250,195,248,2,131,252,255,5,15,130,244,98,15,132,244, - 158,131,252,255,7,15,132,244,247,15,135,244,248,217,252,237,217,201,217,252, - 241,195,248,1,217,232,217,201,217,252,241,195,248,2,131,252,255,9,15,132, - 244,247,255,15,135,244,248,217,252,236,217,201,217,252,241,195,248,1,217, - 252,254,195,248,2,131,252,255,11,15,132,244,247,15,135,244,255,217,252,255, - 195,248,1,217,252,242,221,216,195,255,248,9,204,255,248,163,255,131,252,255, - 1,15,132,244,247,15,135,244,248,252,242,15,88,193,195,248,1,252,242,15,92, - 193,195,248,2,131,252,255,3,15,132,244,247,15,135,244,248,252,242,15,89,193, - 195,248,1,252,242,15,94,193,195,248,2,131,252,255,5,15,130,244,157,15,132, - 244,117,131,252,255,7,15,132,244,247,15,135,244,248,72,184,237,237,255,102, - 72,15,110,200,15,87,193,195,248,1,72,184,237,237,102,72,15,110,200,15,84, - 193,195,248,2,131,252,255,9,15,135,244,248,252,242,15,17,68,36,252,248,252, - 242,15,17,76,36,252,240,221,68,36,252,248,221,68,36,252,240,15,132,244,247, - 217,252,243,248,7,221,92,36,252,248,252,242,15,16,68,36,252,248,195,248,1, - 217,201,217,252,253,221,217,252,233,244,7,248,2,131,252,255,11,15,132,244, - 247,15,135,244,255,252,242,15,93,193,195,248,1,252,242,15,95,193,195,248, - 9,204,255,139,68,36,20,221,68,36,4,221,68,36,12,131,252,248,1,15,132,244, - 247,15,135,244,248,222,193,195,248,1,222,252,233,195,248,2,131,252,248,3, - 15,132,244,247,15,135,244,248,222,201,195,248,1,222,252,249,195,248,2,131, - 252,248,5,15,130,244,157,15,132,244,117,131,252,248,7,15,132,244,247,15,135, - 244,248,255,221,216,217,224,195,248,1,221,216,217,225,195,248,2,131,252,248, - 9,15,132,244,247,15,135,244,248,217,252,243,195,248,1,217,201,217,252,253, - 221,217,195,248,2,131,252,248,11,15,132,244,247,15,135,244,255,255,219,252, - 233,219,209,221,217,195,248,1,219,252,233,218,209,221,217,195,255,221,225, - 223,224,252,246,196,1,15,132,244,248,217,201,248,2,221,216,195,248,1,221, - 225,223,224,252,246,196,1,15,133,244,248,217,201,248,2,221,216,195,255,248, - 164,137,252,248,83,15,162,137,6,137,94,4,137,78,8,137,86,12,91,195,248,165, - 255,204,248,166,255,83,65,87,65,86,72,131,252,236,40,68,141,181,233,139,157, - 233,15,183,192,137,131,233,72,137,187,233,72,137,179,233,72,137,147,233,72, - 137,139,233,252,242,15,17,131,233,252,242,15,17,139,233,252,242,15,17,147, - 233,252,242,15,17,155,233,72,141,132,253,36,233,76,137,131,233,76,137,139, - 233,252,242,15,17,163,233,252,242,15,17,171,233,252,242,15,17,179,233,252, - 242,15,17,187,233,72,137,131,233,72,137,230,137,92,36,28,137,223,232,251, - 1,27,65,199,134,233,237,255,139,144,233,139,128,233,41,208,139,106,252,248, - 193,232,3,131,192,1,139,157,233,139,11,15,182,252,233,15,182,205,131,195, - 4,65,252,255,36,252,238,255,248,32,255,139,76,36,24,65,139,158,233,72,137, - 139,233,137,145,233,137,169,233,137,223,137,198,232,251,1,28,72,139,131,233, - 252,242,15,16,131,233,252,233,244,16,255,248,167,255,85,72,137,229,83,72, - 137,252,251,139,131,233,72,41,196,255,15,182,139,233,131,252,233,1,15,136, - 244,248,248,1,72,139,132,253,203,233,72,137,132,253,204,233,131,252,233,1, - 15,137,244,1,248,2,15,182,131,233,72,139,187,233,72,139,179,233,72,139,147, - 233,72,139,139,233,76,139,131,233,76,139,139,233,133,192,15,132,244,251,15, - 40,131,233,15,40,139,233,255,15,40,147,233,15,40,155,233,131,252,248,4,15, - 134,244,251,15,40,163,233,15,40,171,233,15,40,179,233,15,40,187,233,248,5, - 252,255,147,233,72,137,131,233,15,41,131,233,72,137,147,233,15,41,139,233, - 255,72,139,93,252,248,201,195,255,129,124,253,202,4,239,15,133,244,253,129, - 124,253,194,4,239,15,133,244,254,139,44,202,131,195,4,59,44,194,255,15,141, - 244,255,255,15,140,244,255,255,15,143,244,255,255,15,142,244,255,255,248, - 6,15,183,67,252,254,141,156,253,131,233,248,9,139,3,15,182,204,15,182,232, - 131,195,4,193,232,16,65,252,255,36,252,238,248,7,15,135,244,44,129,124,253, - 194,4,239,15,130,244,247,15,133,244,44,255,252,242,15,42,4,194,252,233,244, - 248,255,221,4,202,219,4,194,252,233,244,249,255,248,8,15,135,244,44,255,252, - 242,15,42,12,202,252,242,15,16,4,194,131,195,4,102,15,46,193,255,15,134,244, - 9,255,15,135,244,9,255,15,130,244,9,255,15,131,244,9,255,252,233,244,6,255, - 219,4,202,252,233,244,248,255,129,124,253,202,4,239,15,131,244,44,129,124, - 253,194,4,239,15,131,244,44,255,248,1,252,242,15,16,4,194,248,2,131,195,4, - 102,15,46,4,202,248,3,255,248,1,221,4,202,248,2,221,4,194,248,3,131,195,4, - 255,223,252,233,221,216,255,218,252,233,223,224,158,255,15,135,244,247,255, - 15,130,244,247,255,15,131,244,247,255,15,183,67,252,254,141,156,253,131,233, - 248,1,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252, - 238,255,139,108,194,4,131,195,4,255,129,252,253,239,15,133,244,253,129,124, - 253,202,4,239,15,133,244,254,139,44,194,59,44,202,255,15,133,244,255,255, - 15,132,244,255,255,15,183,67,252,254,141,156,253,131,233,248,9,139,3,15,182, - 204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,7,15,135,244, - 251,129,124,253,202,4,239,15,130,244,247,15,133,244,251,255,252,242,15,42, - 4,202,255,219,4,202,255,252,233,244,248,248,8,15,135,244,251,255,252,242, - 15,42,4,194,102,15,46,4,202,255,219,4,194,221,4,202,255,252,233,244,250,255, - 129,252,253,239,15,131,244,251,129,124,253,202,4,239,15,131,244,251,255,248, - 1,252,242,15,16,4,202,248,2,102,15,46,4,194,248,4,255,248,1,221,4,202,248, - 2,221,4,194,248,4,255,15,138,244,248,15,133,244,248,255,15,138,244,248,15, - 132,244,247,255,248,1,15,183,67,252,254,141,156,253,131,233,248,2,255,248, - 2,15,183,67,252,254,141,156,253,131,233,248,1,255,252,233,244,9,255,248,5, - 255,129,252,253,239,15,132,244,49,129,124,253,202,4,239,15,132,244,49,255, - 57,108,202,4,15,133,244,2,129,252,253,239,15,131,244,1,139,12,202,139,4,194, - 57,193,15,132,244,1,129,252,253,239,15,135,244,2,129,252,253,239,15,130,244, - 2,139,169,233,133,252,237,15,132,244,2,252,246,133,233,235,15,133,244,2,255, - 49,252,237,255,189,1,0,0,0,255,252,233,244,48,255,248,3,129,252,253,239,255, - 15,133,244,9,255,252,233,244,49,255,72,252,247,208,139,108,202,4,131,195, - 4,129,252,253,239,15,133,244,249,139,12,202,65,59,12,135,255,139,108,202, - 4,131,195,4,255,129,252,253,239,15,133,244,253,65,129,124,253,199,4,239,15, - 133,244,254,65,139,44,199,59,44,202,255,15,183,67,252,254,141,156,253,131, - 233,248,9,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36, - 252,238,248,7,15,135,244,249,65,129,124,253,199,4,239,15,130,244,247,255, - 252,242,65,15,42,4,199,255,65,219,4,199,255,252,233,244,248,248,8,255,252, - 242,15,42,4,202,102,65,15,46,4,199,255,219,4,202,65,221,4,199,255,129,252, - 253,239,15,131,244,249,255,248,1,252,242,65,15,16,4,199,248,2,102,15,46,4, - 202,248,4,255,248,1,65,221,4,199,248,2,221,4,202,248,4,255,72,252,247,208, - 139,108,202,4,131,195,4,57,197,255,15,133,244,249,15,183,67,252,254,141,156, - 253,131,233,248,2,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252, - 255,36,252,238,248,3,129,252,253,239,15,133,244,2,252,233,244,49,255,15,132, - 244,248,129,252,253,239,15,132,244,49,15,183,67,252,254,141,156,253,131,233, - 248,2,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252, - 238,255,139,108,194,4,131,195,4,129,252,253,239,255,137,108,202,4,139,44, - 194,137,44,202,255,72,139,44,194,72,137,44,202,139,3,15,182,204,15,182,232, - 131,195,4,193,232,16,65,252,255,36,252,238,255,49,252,237,129,124,253,194, - 4,239,129,213,239,137,108,202,4,139,3,15,182,204,15,182,232,131,195,4,193, - 232,16,65,252,255,36,252,238,255,129,124,253,194,4,239,15,133,244,251,139, - 44,194,252,247,221,15,128,244,250,199,68,202,4,237,137,44,202,248,9,139,3, - 15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,4,199, - 68,202,4,0,0,224,65,199,4,202,0,0,0,0,252,233,244,9,248,5,15,135,244,54,255, - 129,124,253,194,4,239,15,131,244,54,255,252,242,15,16,4,194,72,184,237,237, - 102,72,15,110,200,15,87,193,252,242,15,17,4,202,255,221,4,194,217,224,221, - 28,202,255,129,124,253,194,4,239,15,133,244,248,139,4,194,255,139,128,233, - 248,1,199,68,202,4,237,137,4,202,255,15,87,192,252,242,15,42,128,233,248, - 1,252,242,15,17,4,202,255,219,128,233,248,1,221,28,202,255,139,3,15,182,204, - 15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,2,129,124,253,194, - 4,239,15,133,244,57,139,60,194,255,139,175,233,131,252,253,0,15,133,244,255, - 248,3,255,248,58,137,213,232,251,1,21,255,252,242,15,42,192,255,137,252,234, - 15,182,75,252,253,252,233,244,1,255,248,9,252,246,133,233,235,15,133,244, - 3,252,233,244,57,255,15,182,252,236,15,182,192,255,129,124,253,252,234,4, - 239,15,133,244,51,65,129,124,253,199,4,239,15,133,244,51,139,44,252,234,65, - 3,44,199,15,128,244,50,255,129,124,253,252,234,4,239,15,133,244,53,65,129, - 124,253,199,4,239,15,133,244,53,65,139,4,199,3,4,252,234,15,128,244,52,255, - 129,124,253,252,234,4,239,15,133,244,56,129,124,253,194,4,239,15,133,244, - 56,139,44,252,234,3,44,194,15,128,244,55,255,199,68,202,4,237,255,129,124, - 253,252,234,4,239,15,131,244,51,255,65,129,124,253,199,4,239,15,131,244,51, - 255,252,242,15,16,4,252,234,252,242,65,15,88,4,199,255,221,4,252,234,65,220, - 4,199,255,129,124,253,252,234,4,239,15,131,244,53,255,65,129,124,253,199, - 4,239,15,131,244,53,255,252,242,65,15,16,4,199,252,242,15,88,4,252,234,255, - 65,221,4,199,220,4,252,234,255,129,124,253,252,234,4,239,15,131,244,56,129, - 124,253,194,4,239,15,131,244,56,255,252,242,15,16,4,252,234,252,242,15,88, - 4,194,255,221,4,252,234,220,4,194,255,129,124,253,252,234,4,239,15,133,244, - 51,65,129,124,253,199,4,239,15,133,244,51,139,44,252,234,65,43,44,199,15, - 128,244,50,255,129,124,253,252,234,4,239,15,133,244,53,65,129,124,253,199, - 4,239,15,133,244,53,65,139,4,199,43,4,252,234,15,128,244,52,255,129,124,253, - 252,234,4,239,15,133,244,56,129,124,253,194,4,239,15,133,244,56,139,44,252, - 234,43,44,194,15,128,244,55,255,252,242,15,16,4,252,234,252,242,65,15,92, - 4,199,255,221,4,252,234,65,220,36,199,255,252,242,65,15,16,4,199,252,242, - 15,92,4,252,234,255,65,221,4,199,220,36,252,234,255,252,242,15,16,4,252,234, - 252,242,15,92,4,194,255,221,4,252,234,220,36,194,255,129,124,253,252,234, - 4,239,15,133,244,51,65,129,124,253,199,4,239,15,133,244,51,139,44,252,234, - 65,15,175,44,199,15,128,244,50,255,129,124,253,252,234,4,239,15,133,244,53, - 65,129,124,253,199,4,239,15,133,244,53,65,139,4,199,15,175,4,252,234,15,128, - 244,52,255,129,124,253,252,234,4,239,15,133,244,56,129,124,253,194,4,239, - 15,133,244,56,139,44,252,234,15,175,44,194,15,128,244,55,255,252,242,15,16, - 4,252,234,252,242,65,15,89,4,199,255,221,4,252,234,65,220,12,199,255,252, - 242,65,15,16,4,199,252,242,15,89,4,252,234,255,65,221,4,199,220,12,252,234, - 255,252,242,15,16,4,252,234,252,242,15,89,4,194,255,221,4,252,234,220,12, - 194,255,252,242,15,16,4,252,234,252,242,65,15,94,4,199,255,221,4,252,234, - 65,220,52,199,255,252,242,65,15,16,4,199,252,242,15,94,4,252,234,255,65,221, - 4,199,220,52,252,234,255,252,242,15,16,4,252,234,252,242,15,94,4,194,255, - 221,4,252,234,220,52,194,255,252,242,15,16,4,252,234,252,242,65,15,16,12, - 199,255,221,4,252,234,65,221,4,199,255,252,242,65,15,16,4,199,252,242,15, - 16,12,252,234,255,65,221,4,199,221,4,252,234,255,252,242,15,16,4,252,234, - 252,242,15,16,12,194,255,221,4,252,234,221,4,194,255,248,168,232,244,157, - 255,252,233,244,168,255,232,244,117,255,15,182,252,236,15,182,192,139,124, - 36,24,137,151,233,141,52,194,137,194,41,252,234,248,36,137,252,253,137,92, - 36,28,232,251,1,29,139,149,233,133,192,15,133,244,45,15,182,107,252,255,15, - 182,75,252,253,72,139,4,252,234,72,137,4,202,139,3,15,182,204,15,182,232, - 131,195,4,193,232,16,65,252,255,36,252,238,255,72,252,247,208,65,139,4,135, - 199,68,202,4,237,137,4,202,139,3,15,182,204,15,182,232,131,195,4,193,232, - 16,65,252,255,36,252,238,255,15,191,192,199,68,202,4,237,137,4,202,255,15, - 191,192,252,242,15,42,192,252,242,15,17,4,202,255,223,67,252,254,221,28,202, - 255,252,242,65,15,16,4,199,252,242,15,17,4,202,255,65,221,4,199,221,28,202, - 255,72,252,247,208,137,68,202,4,139,3,15,182,204,15,182,232,131,195,4,193, - 232,16,65,252,255,36,252,238,255,141,76,202,12,141,68,194,4,189,237,137,105, - 252,248,248,1,137,41,131,193,8,57,193,15,134,244,1,139,3,15,182,204,15,182, - 232,131,195,4,193,232,16,65,252,255,36,252,238,255,139,106,252,248,139,172, - 253,133,233,139,173,233,72,139,69,0,72,137,4,202,139,3,15,182,204,15,182, - 232,131,195,4,193,232,16,65,252,255,36,252,238,255,139,106,252,248,139,172, - 253,141,233,128,189,233,0,139,173,233,139,12,194,139,68,194,4,137,77,0,137, - 69,4,15,132,244,247,252,246,133,233,235,15,133,244,248,248,1,139,3,15,182, - 204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,2,129,232,239, - 129,252,248,239,15,134,244,1,252,246,129,233,235,15,132,244,1,137,252,238, - 137,213,65,141,190,233,255,232,251,1,30,137,252,234,252,233,244,1,255,72, - 252,247,208,139,106,252,248,139,172,253,141,233,65,139,12,135,139,133,233, - 137,8,199,64,4,237,252,246,133,233,235,15,133,244,248,248,1,139,3,15,182, - 204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,2,252,246,129, - 233,235,15,132,244,1,128,189,233,0,15,132,244,1,137,213,137,198,65,141,190, - 233,232,251,1,30,137,252,234,252,233,244,1,255,139,106,252,248,255,252,242, - 65,15,16,4,199,255,139,172,253,141,233,139,141,233,255,252,242,15,17,1,255, - 221,25,255,72,252,247,208,139,106,252,248,139,172,253,141,233,139,141,233, - 137,65,4,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252, - 238,255,141,156,253,131,233,139,108,36,24,131,189,233,0,15,132,244,247,137, - 149,233,141,52,202,137,252,239,232,251,1,31,139,149,233,248,1,139,3,15,182, - 204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,255,72,252,247, - 208,139,108,36,24,137,149,233,139,82,252,248,65,139,52,135,137,252,239,137, - 92,36,28,232,251,1,32,139,149,233,15,182,75,252,253,137,4,202,199,68,202, - 4,237,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252, - 238,255,139,108,36,24,137,149,233,65,139,142,233,65,59,142,233,137,92,36, - 28,15,131,244,251,248,1,137,194,37,252,255,7,0,0,193,252,234,11,61,252,255, - 7,0,0,15,132,244,249,248,2,137,252,239,137,198,232,251,1,33,139,149,233,15, - 182,75,252,253,137,4,202,199,68,202,4,237,139,3,15,182,204,15,182,232,131, - 195,4,193,232,16,65,252,255,36,252,238,248,3,184,1,8,0,0,252,233,244,2,248, - 5,137,252,239,232,251,1,34,15,183,67,252,254,252,233,244,1,255,72,252,247, - 208,139,108,36,24,65,139,142,233,137,92,36,28,65,59,142,233,137,149,233,15, - 131,244,249,248,2,65,139,52,135,137,252,239,232,251,1,35,139,149,233,15,182, - 75,252,253,137,4,202,199,68,202,4,237,139,3,15,182,204,15,182,232,131,195, - 4,193,232,16,65,252,255,36,252,238,248,3,137,252,239,232,251,1,34,15,183, - 67,252,254,72,252,247,208,252,233,244,2,255,72,252,247,208,139,106,252,248, - 139,173,233,65,139,4,135,252,233,244,169,255,72,252,247,208,139,106,252,248, - 139,173,233,65,139,4,135,252,233,244,170,255,15,182,252,236,15,182,192,129, - 124,253,252,234,4,239,15,133,244,39,139,44,252,234,255,129,124,253,194,4, - 239,15,133,244,251,139,4,194,255,129,124,253,194,4,239,15,131,244,251,255, - 252,242,15,16,4,194,252,242,15,45,192,252,242,15,42,200,102,15,46,193,255, - 15,133,244,39,255,59,133,233,15,131,244,39,193,224,3,3,133,233,129,120,253, - 4,239,15,132,244,248,72,139,40,72,137,44,202,248,1,139,3,15,182,204,15,182, - 232,131,195,4,193,232,16,65,252,255,36,252,238,248,2,131,189,233,0,15,132, - 244,249,139,141,233,252,246,129,233,235,15,132,244,39,15,182,75,252,253,248, - 3,199,68,202,4,237,252,233,244,1,248,5,255,129,124,253,194,4,239,15,133,244, - 39,139,4,194,252,233,244,169,255,15,182,252,236,15,182,192,72,252,247,208, - 65,139,4,135,129,124,253,252,234,4,239,15,133,244,37,139,44,252,234,248,169, - 139,141,233,35,136,233,105,201,239,3,141,233,248,1,129,185,233,239,15,133, - 244,250,57,129,233,15,133,244,250,129,121,253,4,239,15,132,244,251,15,182, - 67,252,253,72,139,41,72,137,44,194,248,2,255,139,3,15,182,204,15,182,232, - 131,195,4,193,232,16,65,252,255,36,252,238,248,3,15,182,67,252,253,199,68, - 194,4,237,252,233,244,2,248,4,139,137,233,133,201,15,133,244,1,248,5,139, - 141,233,133,201,15,132,244,3,252,246,129,233,235,15,133,244,3,252,233,244, - 37,255,15,182,252,236,15,182,192,129,124,253,252,234,4,239,15,133,244,38, - 139,44,252,234,59,133,233,15,131,244,38,193,224,3,3,133,233,129,120,253,4, - 239,15,132,244,248,72,139,40,72,137,44,202,248,1,139,3,15,182,204,15,182, - 232,131,195,4,193,232,16,65,252,255,36,252,238,248,2,131,189,233,0,15,132, - 244,249,139,141,233,252,246,129,233,235,15,132,244,38,255,15,182,75,252,253, - 248,3,199,68,202,4,237,252,233,244,1,255,15,182,252,236,15,182,192,129,124, - 253,252,234,4,239,15,133,244,42,139,44,252,234,255,15,133,244,42,255,59,133, - 233,15,131,244,42,193,224,3,3,133,233,129,120,253,4,239,15,132,244,249,248, - 1,252,246,133,233,235,15,133,244,253,248,2,72,139,44,202,72,137,40,139,3, - 15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,3,131, - 189,233,0,15,132,244,1,139,141,233,252,246,129,233,235,255,15,132,244,42, - 15,182,75,252,253,252,233,244,1,248,5,129,124,253,194,4,239,15,133,244,42, - 139,4,194,252,233,244,170,248,7,128,165,233,235,65,139,142,233,65,137,174, - 233,137,141,233,15,182,75,252,253,252,233,244,2,255,15,182,252,236,15,182, - 192,72,252,247,208,65,139,4,135,129,124,253,252,234,4,239,15,133,244,40,139, - 44,252,234,248,170,139,141,233,35,136,233,105,201,239,198,133,233,0,3,141, - 233,248,1,129,185,233,239,15,133,244,251,57,129,233,15,133,244,251,129,121, - 253,4,239,15,132,244,250,248,2,255,252,246,133,233,235,15,133,244,253,248, - 3,15,182,67,252,253,72,139,44,194,72,137,41,139,3,15,182,204,15,182,232,131, - 195,4,193,232,16,65,252,255,36,252,238,248,4,131,189,233,0,15,132,244,2,137, - 12,36,139,141,233,252,246,129,233,235,15,132,244,40,139,12,36,252,233,244, - 2,248,5,139,137,233,133,201,15,133,244,1,255,139,141,233,133,201,15,132,244, - 252,252,246,129,233,235,15,132,244,40,248,6,137,4,36,199,68,36,4,237,137, - 108,36,8,139,124,36,24,137,151,233,72,141,20,36,137,252,238,137,252,253,137, - 92,36,28,232,251,1,36,139,149,233,139,108,36,8,137,193,252,233,244,2,248, - 7,128,165,233,235,65,139,134,233,65,137,174,233,137,133,233,252,233,244,3, - 255,15,182,252,236,15,182,192,129,124,253,252,234,4,239,15,133,244,41,139, - 44,252,234,59,133,233,15,131,244,41,193,224,3,3,133,233,129,120,253,4,239, - 15,132,244,249,248,1,252,246,133,233,235,15,133,244,253,248,2,72,139,12,202, - 72,137,8,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252, - 238,248,3,131,189,233,0,15,132,244,1,255,139,141,233,252,246,129,233,235, - 15,132,244,41,15,182,75,252,253,252,233,244,1,248,7,128,165,233,235,65,139, - 142,233,65,137,174,233,137,141,233,15,182,75,252,253,252,233,244,2,255,68, - 137,60,36,69,139,60,199,248,1,141,12,202,139,105,252,248,252,246,133,233, - 235,15,133,244,253,248,2,139,68,36,4,131,232,1,15,132,244,250,68,1,252,248, - 59,133,233,15,135,244,251,68,41,252,248,65,193,231,3,68,3,189,233,248,3,72, - 139,41,131,193,8,73,137,47,65,131,199,8,131,232,1,15,133,244,3,248,4,68,139, - 60,36,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252, - 238,248,5,139,124,36,24,137,151,233,137,252,238,137,194,137,252,253,137,92, - 36,28,232,251,1,37,139,149,233,15,182,75,252,253,252,233,244,1,248,7,255, - 128,165,233,235,65,139,134,233,65,137,174,233,137,133,233,252,233,244,2,255, - 3,68,36,4,255,129,124,253,202,4,239,139,44,202,15,133,244,59,141,84,202,8, - 137,90,252,252,139,157,233,139,11,15,182,252,233,15,182,205,131,195,4,65, - 252,255,36,252,238,255,141,76,202,8,65,137,215,139,105,252,248,129,121,253, - 252,252,239,15,133,244,29,248,60,139,90,252,252,252,247,195,237,15,133,244, - 253,248,1,137,106,252,248,137,68,36,4,131,232,1,15,132,244,249,248,2,72,139, - 41,131,193,8,73,137,47,65,131,199,8,131,232,1,15,133,244,2,139,106,252,248, - 248,3,139,68,36,4,128,189,233,1,15,135,244,251,248,4,139,157,233,139,11,15, - 182,252,233,15,182,205,131,195,4,65,252,255,36,252,238,248,5,255,252,247, - 195,237,15,133,244,4,15,182,75,252,253,72,252,247,209,141,12,202,68,139,121, - 252,248,69,139,191,233,69,139,191,233,252,233,244,4,248,7,129,252,235,239, - 252,247,195,237,15,133,244,254,41,218,65,137,215,139,90,252,252,252,233,244, - 1,248,8,129,195,239,252,233,244,1,255,141,76,202,8,72,139,105,232,72,139, - 65,252,240,72,137,41,72,137,65,8,139,105,224,139,65,228,137,105,252,248,137, - 65,252,252,129,252,248,239,184,237,15,133,244,29,137,202,137,90,252,252,139, - 157,233,139,11,15,182,252,233,15,182,205,131,195,4,65,252,255,36,252,238, - 255,68,137,60,36,68,137,116,36,4,139,108,202,252,240,139,68,202,252,248,68, - 139,181,233,131,195,4,68,139,189,233,248,1,68,57,252,240,15,131,244,251,65, - 129,124,253,199,4,239,15,132,244,250,255,219,68,202,252,248,255,73,139,44, - 199,72,137,108,202,8,131,192,1,255,137,68,202,252,248,248,2,15,183,67,252, - 254,141,156,253,131,233,248,3,68,139,116,36,4,68,139,60,36,139,3,15,182,204, - 15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,4,131,192,1,255, - 137,68,202,252,248,255,252,233,244,1,248,5,68,41,252,240,248,6,59,133,233, - 15,135,244,3,68,105,252,248,239,68,3,189,233,65,129,191,233,239,15,132,244, - 253,70,141,116,48,1,73,139,175,233,73,139,135,233,72,137,44,202,72,137,68, - 202,8,68,137,116,202,252,248,252,233,244,2,248,7,131,192,1,252,233,244,6, - 255,129,124,253,202,252,236,239,15,133,244,251,139,108,202,232,129,124,253, - 202,252,244,239,15,133,244,251,129,124,253,202,252,252,239,15,133,244,251, - 128,189,233,235,15,133,244,251,141,156,253,131,233,199,68,202,252,248,0,0, - 0,0,248,1,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36, - 252,238,248,5,198,67,252,252,235,141,156,253,131,233,198,3,235,252,233,244, - 1,255,15,182,252,236,15,182,192,68,137,60,36,68,141,188,253,194,233,141,12, - 202,68,43,122,252,252,133,252,237,15,132,244,251,141,108,252,233,252,248, - 65,57,215,15,131,244,248,248,1,73,139,71,252,248,65,131,199,8,72,137,1,131, - 193,8,57,252,233,15,131,244,249,65,57,215,15,130,244,1,248,2,199,65,4,237, - 131,193,8,57,252,233,15,130,244,2,248,3,68,139,60,36,139,3,15,182,204,15, - 182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,5,199,68,36,4,1,0, - 0,0,137,208,68,41,252,248,15,134,244,3,137,197,193,252,237,3,131,197,1,137, - 108,36,4,139,108,36,24,1,200,59,133,233,15,135,244,253,248,6,255,73,139,71, - 252,248,65,131,199,8,72,137,1,131,193,8,65,57,215,15,130,244,6,252,233,244, - 3,248,7,137,149,233,137,141,233,137,92,36,28,65,41,215,139,116,36,4,131,252, - 238,1,137,252,239,232,251,1,0,139,149,233,139,141,233,65,1,215,252,233,244, - 6,255,193,225,3,255,248,1,139,90,252,252,137,68,36,4,252,247,195,237,15,133, - 244,253,255,248,13,65,137,215,131,232,1,15,132,244,249,248,2,73,139,44,15, - 73,137,111,252,248,65,131,199,8,131,232,1,15,133,244,2,248,3,139,68,36,4, - 15,182,107,252,255,248,5,57,197,15,135,244,252,255,72,139,44,10,72,137,106, - 252,248,255,248,5,56,67,252,255,15,135,244,252,255,15,182,75,252,253,72,252, - 247,209,141,20,202,68,139,122,252,248,69,139,191,233,69,139,191,233,139,3, - 15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,6,255, - 65,199,71,252,252,237,65,131,199,8,255,199,68,194,252,244,237,255,131,192, - 1,252,233,244,5,248,7,141,171,233,252,247,197,237,15,133,244,14,41,252,234, - 255,1,252,233,255,137,221,209,252,237,129,229,239,102,65,129,172,253,46,233, - 238,15,130,244,149,255,141,12,202,255,129,121,253,4,239,15,133,244,255,255, - 129,121,253,12,239,15,133,244,61,129,121,253,20,239,15,133,244,61,139,41, - 131,121,16,0,15,140,244,251,255,129,121,253,12,239,15,133,244,165,129,121, - 253,20,239,15,133,244,165,255,139,105,16,133,252,237,15,136,244,251,3,41, - 15,128,244,247,137,41,255,59,105,8,199,65,28,237,137,105,24,255,15,142,244, - 253,248,1,248,6,141,156,253,131,233,255,141,156,253,131,233,15,183,67,252, - 254,15,142,245,248,1,248,6,255,15,143,244,253,248,6,141,156,253,131,233,248, - 1,255,248,7,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36, - 252,238,248,5,255,3,41,15,128,244,1,137,41,255,15,141,244,7,255,141,156,253, - 131,233,15,183,67,252,254,15,141,245,255,15,140,244,7,255,252,233,244,6,248, - 9,255,129,121,253,4,239,255,15,131,244,61,129,121,253,12,239,15,131,244,61, - 255,129,121,253,12,239,15,131,244,165,129,121,253,20,239,15,131,244,165,255, - 139,105,20,255,129,252,253,239,15,131,244,61,255,252,242,15,16,1,252,242, - 15,16,73,8,255,252,242,15,88,65,16,252,242,15,17,1,133,252,237,15,136,244, - 249,255,15,140,244,249,255,102,15,46,200,248,1,252,242,15,17,65,24,255,221, - 65,8,221,1,255,220,65,16,221,17,221,81,24,133,252,237,15,136,244,247,255, - 221,81,24,15,140,244,247,255,217,201,248,1,255,15,183,67,252,254,255,15,131, - 244,7,255,15,131,244,248,141,156,253,131,233,255,141,156,253,131,233,15,183, - 67,252,254,15,131,245,255,15,130,244,7,255,15,130,244,248,141,156,253,131, - 233,255,248,3,102,15,46,193,252,233,244,1,255,141,12,202,139,105,4,129,252, - 253,239,15,132,244,247,255,137,105,252,252,139,41,137,105,252,248,252,233, - 245,255,141,156,253,131,233,139,1,137,105,252,252,137,65,252,248,255,65,139, - 142,233,139,4,129,72,139,128,233,139,108,36,24,65,137,150,233,65,137,174, - 233,76,137,36,36,76,137,108,36,8,72,131,252,236,16,252,255,224,255,141,156, - 253,131,233,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36, - 252,238,255,137,221,209,252,237,129,229,239,102,65,129,172,253,46,233,238, - 15,130,244,151,255,68,139,187,233,139,108,36,24,141,12,202,59,141,233,15, - 135,244,24,15,182,139,233,57,200,15,134,244,249,248,2,255,15,183,67,252,254, - 252,233,245,255,248,3,199,68,194,252,252,237,131,192,1,57,200,15,134,244, - 3,252,233,244,2,255,141,44,197,237,141,4,194,68,139,122,252,248,137,104,252, - 252,68,137,120,252,248,139,108,36,24,141,12,200,59,141,233,15,135,244,23, - 137,209,137,194,15,182,171,233,133,252,237,15,132,244,248,248,1,131,193,8, - 57,209,15,131,244,249,68,139,121,252,248,68,137,56,68,139,121,252,252,68, - 137,120,4,131,192,8,199,65,252,252,237,131,252,237,1,15,133,244,1,248,2,255, - 68,139,187,233,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255, - 36,252,238,255,248,3,199,64,4,237,131,192,8,131,252,237,1,15,133,244,3,252, - 233,244,2,255,139,106,252,248,76,139,189,233,139,108,36,24,141,68,194,252, - 248,137,149,233,141,136,233,59,141,233,137,133,233,255,76,137,252,254,137, - 252,239,255,15,135,244,22,65,199,134,233,237,255,65,252,255,215,255,65,252, - 255,150,233,255,65,199,134,233,237,139,149,233,141,12,194,252,247,217,3,141, - 233,139,90,252,252,252,233,244,12,255,254,0 -}; - -enum { - GLOB_vm_returnp, - GLOB_cont_dispatch, - GLOB_vm_returnc, - GLOB_BC_RET_Z, - GLOB_vm_return, - GLOB_vm_leave_cp, - GLOB_vm_leave_unw, - GLOB_vm_unwind_c, - GLOB_vm_unwind_c_eh, - GLOB_vm_unwind_rethrow, - GLOB_vm_unwind_ff, - GLOB_vm_unwind_ff_eh, - GLOB_vm_growstack_c, - GLOB_vm_growstack_v, - GLOB_vm_growstack_f, - GLOB_vm_resume, - GLOB_vm_pcall, - GLOB_vm_call, - GLOB_vm_call_dispatch, - GLOB_vmeta_call, - GLOB_vm_call_dispatch_f, - GLOB_vm_cpcall, - GLOB_cont_ffi_callback, - GLOB_vm_call_tail, - GLOB_cont_cat, - GLOB_cont_ra, - GLOB_BC_CAT_Z, - GLOB_vmeta_tgets, - GLOB_vmeta_tgetb, - GLOB_vmeta_tgetv, - GLOB_vmeta_tsets, - GLOB_vmeta_tsetb, - GLOB_vmeta_tsetv, - GLOB_cont_nop, - GLOB_vmeta_comp, - GLOB_vmeta_binop, - GLOB_cont_condt, - GLOB_cont_condf, - GLOB_vmeta_equal, - GLOB_vmeta_equal_cd, - GLOB_vmeta_arith_vno, - GLOB_vmeta_arith_vn, - GLOB_vmeta_arith_nvo, - GLOB_vmeta_arith_nv, - GLOB_vmeta_unm, - GLOB_vmeta_arith_vvo, - GLOB_vmeta_arith_vv, - GLOB_vmeta_len, - GLOB_BC_LEN_Z, - GLOB_vmeta_call_ra, - GLOB_BC_CALLT_Z, - GLOB_vmeta_for, - GLOB_ff_assert, - GLOB_fff_fallback, - GLOB_fff_res_, - GLOB_ff_type, - GLOB_fff_res1, - GLOB_ff_getmetatable, - GLOB_ff_setmetatable, - GLOB_ff_rawget, - GLOB_ff_tonumber, - GLOB_fff_resi, - GLOB_fff_resxmm0, - GLOB_fff_resn, - GLOB_ff_tostring, - GLOB_fff_gcstep, - GLOB_ff_next, - GLOB_fff_res2, - GLOB_fff_res, - GLOB_ff_pairs, - GLOB_ff_ipairs_aux, - GLOB_fff_res0, - GLOB_ff_ipairs, - GLOB_ff_pcall, - GLOB_ff_xpcall, - GLOB_ff_coroutine_resume, - GLOB_ff_coroutine_wrap_aux, - GLOB_ff_coroutine_yield, - GLOB_ff_math_abs, - GLOB_fff_resbit, - GLOB_ff_math_floor, - GLOB_vm_floor, - GLOB_ff_math_ceil, - GLOB_vm_ceil, - GLOB_ff_math_sqrt, - GLOB_ff_math_log, - GLOB_ff_math_log10, - GLOB_ff_math_exp, - GLOB_vm_exp_x87, - GLOB_ff_math_sin, - GLOB_ff_math_cos, - GLOB_ff_math_tan, - GLOB_ff_math_asin, - GLOB_ff_math_acos, - GLOB_ff_math_atan, - GLOB_ff_math_sinh, - GLOB_ff_math_cosh, - GLOB_ff_math_tanh, - GLOB_ff_math_deg, - GLOB_ff_math_rad, - GLOB_ff_math_atan2, - GLOB_ff_math_ldexp, - GLOB_ff_math_frexp, - GLOB_ff_math_modf, - GLOB_vm_trunc, - GLOB_ff_math_fmod, - GLOB_ff_math_pow, - GLOB_vm_pow, - GLOB_ff_math_min, - GLOB_ff_math_max, - GLOB_ff_string_len, - GLOB_ff_string_byte, - GLOB_ff_string_char, - GLOB_fff_newstr, - GLOB_ff_string_sub, - GLOB_fff_emptystr, - GLOB_ff_string_rep, - GLOB_fff_fallback_2, - GLOB_ff_string_reverse, - GLOB_fff_fallback_1, - GLOB_ff_string_lower, - GLOB_ff_string_upper, - GLOB_ff_table_getn, - GLOB_ff_bit_tobit, - GLOB_ff_bit_band, - GLOB_fff_fallback_bit_op, - GLOB_ff_bit_bor, - GLOB_ff_bit_bxor, - GLOB_ff_bit_bswap, - GLOB_ff_bit_bnot, - GLOB_ff_bit_lshift, - GLOB_ff_bit_rshift, - GLOB_ff_bit_arshift, - GLOB_ff_bit_rol, - GLOB_ff_bit_ror, - GLOB_vm_record, - GLOB_vm_rethook, - GLOB_vm_inshook, - GLOB_cont_hook, - GLOB_vm_hotloop, - GLOB_vm_callhook, - GLOB_vm_hotcall, - GLOB_vm_exit_handler, - GLOB_vm_exit_interp, - GLOB_vm_floor_sse, - GLOB_vm_ceil_sse, - GLOB_vm_trunc_sse, - GLOB_vm_mod, - GLOB_vm_exp2_x87, - GLOB_vm_exp2raw, - GLOB_vm_pow_sse, - GLOB_vm_powi_sse, - GLOB_vm_foldfpm, - GLOB_vm_foldarith, - GLOB_vm_cpuid, - GLOB_assert_bad_for_arg_type, - GLOB_vm_ffi_callback, - GLOB_vm_ffi_call, - GLOB_BC_MODVN_Z, - GLOB_BC_TGETS_Z, - GLOB_BC_TSETS_Z, - GLOB__MAX -}; -static const char *const globnames[] = { - "vm_returnp", - "cont_dispatch", - "vm_returnc", - "BC_RET_Z", - "vm_return", - "vm_leave_cp", - "vm_leave_unw", - "vm_unwind_c@8", - "vm_unwind_c_eh", - "vm_unwind_rethrow", - "vm_unwind_ff@4", - "vm_unwind_ff_eh", - "vm_growstack_c", - "vm_growstack_v", - "vm_growstack_f", - "vm_resume", - "vm_pcall", - "vm_call", - "vm_call_dispatch", - "vmeta_call", - "vm_call_dispatch_f", - "vm_cpcall", - "cont_ffi_callback", - "vm_call_tail", - "cont_cat", - "cont_ra", - "BC_CAT_Z", - "vmeta_tgets", - "vmeta_tgetb", - "vmeta_tgetv", - "vmeta_tsets", - "vmeta_tsetb", - "vmeta_tsetv", - "cont_nop", - "vmeta_comp", - "vmeta_binop", - "cont_condt", - "cont_condf", - "vmeta_equal", - "vmeta_equal_cd", - "vmeta_arith_vno", - "vmeta_arith_vn", - "vmeta_arith_nvo", - "vmeta_arith_nv", - "vmeta_unm", - "vmeta_arith_vvo", - "vmeta_arith_vv", - "vmeta_len", - "BC_LEN_Z", - "vmeta_call_ra", - "BC_CALLT_Z", - "vmeta_for", - "ff_assert", - "fff_fallback", - "fff_res_", - "ff_type", - "fff_res1", - "ff_getmetatable", - "ff_setmetatable", - "ff_rawget", - "ff_tonumber", - "fff_resi", - "fff_resxmm0", - "fff_resn", - "ff_tostring", - "fff_gcstep", - "ff_next", - "fff_res2", - "fff_res", - "ff_pairs", - "ff_ipairs_aux", - "fff_res0", - "ff_ipairs", - "ff_pcall", - "ff_xpcall", - "ff_coroutine_resume", - "ff_coroutine_wrap_aux", - "ff_coroutine_yield", - "ff_math_abs", - "fff_resbit", - "ff_math_floor", - "vm_floor", - "ff_math_ceil", - "vm_ceil", - "ff_math_sqrt", - "ff_math_log", - "ff_math_log10", - "ff_math_exp", - "vm_exp_x87", - "ff_math_sin", - "ff_math_cos", - "ff_math_tan", - "ff_math_asin", - "ff_math_acos", - "ff_math_atan", - "ff_math_sinh", - "ff_math_cosh", - "ff_math_tanh", - "ff_math_deg", - "ff_math_rad", - "ff_math_atan2", - "ff_math_ldexp", - "ff_math_frexp", - "ff_math_modf", - "vm_trunc", - "ff_math_fmod", - "ff_math_pow", - "vm_pow", - "ff_math_min", - "ff_math_max", - "ff_string_len", - "ff_string_byte", - "ff_string_char", - "fff_newstr", - "ff_string_sub", - "fff_emptystr", - "ff_string_rep", - "fff_fallback_2", - "ff_string_reverse", - "fff_fallback_1", - "ff_string_lower", - "ff_string_upper", - "ff_table_getn", - "ff_bit_tobit", - "ff_bit_band", - "fff_fallback_bit_op", - "ff_bit_bor", - "ff_bit_bxor", - "ff_bit_bswap", - "ff_bit_bnot", - "ff_bit_lshift", - "ff_bit_rshift", - "ff_bit_arshift", - "ff_bit_rol", - "ff_bit_ror", - "vm_record", - "vm_rethook", - "vm_inshook", - "cont_hook", - "vm_hotloop", - "vm_callhook", - "vm_hotcall", - "vm_exit_handler", - "vm_exit_interp", - "vm_floor_sse", - "vm_ceil_sse", - "vm_trunc_sse", - "vm_mod", - "vm_exp2_x87", - "vm_exp2raw", - "vm_pow_sse", - "vm_powi_sse", - "vm_foldfpm", - "vm_foldarith", - "vm_cpuid", - "assert_bad_for_arg_type", - "vm_ffi_callback", - "vm_ffi_call@4", - "BC_MODVN_Z", - "BC_TGETS_Z", - "BC_TSETS_Z", - (const char *)0 -}; -static const char *const extnames[] = { - "lj_state_growstack@8", - "lj_err_throw@8", - "lj_meta_tget", - "lj_meta_tset", - "lj_meta_comp", - "lj_meta_equal", - "lj_meta_equal_cd@8", - "lj_meta_arith", - "lj_meta_len@8", - "lj_meta_call", - "lj_meta_for@8", - "lj_tab_get", - "lj_str_fromnumber@8", - "lj_str_fromnum@8", - "lj_tab_next", - "lj_tab_getinth@8", - "lj_ffh_coroutine_wrap_err@8", - "lj_vm_sinh", - "lj_vm_cosh", - "lj_vm_tanh", - "lj_str_new", - "lj_tab_len@4", - "lj_gc_step@4", - "lj_dispatch_ins@8", - "lj_trace_hot@8", - "lj_dispatch_call@8", - "lj_trace_exit@8", - "lj_ccallback_enter@8", - "lj_ccallback_leave@8", - "lj_meta_cat", - "lj_gc_barrieruv@8", - "lj_func_closeuv@8", - "lj_func_newL_gc", - "lj_tab_new", - "lj_gc_step_fixtop@4", - "lj_tab_dup@8", - "lj_tab_newkey", - "lj_tab_reasize", - (const char *)0 -}; -#define Dt1(_V) (int)(ptrdiff_t)&(((lua_State *)0)_V) -#define Dt2(_V) (int)(ptrdiff_t)&(((global_State *)0)_V) -#define Dt3(_V) (int)(ptrdiff_t)&(((TValue *)0)_V) -#define Dt4(_V) (int)(ptrdiff_t)&(((GCobj *)0)_V) -#define Dt5(_V) (int)(ptrdiff_t)&(((GCstr *)0)_V) -#define Dt6(_V) (int)(ptrdiff_t)&(((GCtab *)0)_V) -#define Dt7(_V) (int)(ptrdiff_t)&(((GCfuncL *)0)_V) -#define Dt8(_V) (int)(ptrdiff_t)&(((GCfuncC *)0)_V) -#define Dt9(_V) (int)(ptrdiff_t)&(((GCproto *)0)_V) -#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V) -#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V) -#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V) -#define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V) -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx, int cmov, int sse) -{ - dasm_put(Dst, 0); - dasm_put(Dst, 2, FRAME_P, LJ_TTRUE, FRAME_TYPE, FRAME_C, FRAME_TYPE, DISPATCH_GL(vmstate), ~LJ_VMST_C); - dasm_put(Dst, 109, Dt1(->base), Dt1(->top), Dt1(->cframe), Dt1(->maxstack), LJ_TNIL); - dasm_put(Dst, 200, Dt1(->top), Dt1(->top), Dt1(->glref), Dt2(->vmstate), ~LJ_VMST_C, CFRAME_RAWMASK); - dasm_put(Dst, 302, 1+1, Dt1(->base), Dt1(->glref), GG_G2DISP, LJ_TFALSE, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, LUA_MINSTACK, -4+PC2PROTO(framesize), Dt1(->base)); - dasm_put(Dst, 385, Dt1(->top), Dt1(->base), Dt1(->top), Dt7(->pc), FRAME_CP, CFRAME_RESUME, Dt1(->glref), GG_G2DISP, Dt1(->cframe), Dt1(->status), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->status), Dt1(->base), Dt1(->top), FRAME_TYPE); - dasm_put(Dst, 548, FRAME_CP, FRAME_C, Dt1(->cframe), Dt1(->cframe), Dt1(->glref), GG_G2DISP, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base)); - dasm_put(Dst, 648, Dt1(->top), LJ_TFUNC, Dt7(->pc), Dt1(->stack), Dt1(->top), Dt1(->cframe), Dt1(->cframe), FRAME_CP, LJ_TNIL); -#if LJ_HASFFI - dasm_put(Dst, 813); -#endif - dasm_put(Dst, 822, 0); -#if LJ_HASFFI -#endif - dasm_put(Dst, 831, Dt7(->pc), PC2PROTO(k)); -#if LJ_HASFFI - dasm_put(Dst, 848); -#endif - dasm_put(Dst, 869, Dt1(->base), LJ_TSTR, BC_GGET, DISPATCH_GL(tmptv), LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 967, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 976); - } else { - } - dasm_put(Dst, 988, Dt1(->base), Dt1(->base), Dt1(->top), FRAME_CONT, 2+1, LJ_TSTR, BC_GSET); - dasm_put(Dst, 1134, DISPATCH_GL(tmptv), LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 967, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 976); - } else { - } - dasm_put(Dst, 1158, Dt1(->base), Dt1(->base), Dt1(->top), FRAME_CONT, 3+1, Dt1(->base), Dt1(->base)); - dasm_put(Dst, 1330, -BCBIAS_J*4, LJ_TISTRUECOND, LJ_TISTRUECOND, Dt1(->base)); - dasm_put(Dst, 1429); -#if LJ_HASFFI - dasm_put(Dst, 1449, Dt1(->base)); -#endif - dasm_put(Dst, 1480); -#if LJ_DUALNUM - dasm_put(Dst, 1483); -#endif - dasm_put(Dst, 1489); -#if LJ_DUALNUM - dasm_put(Dst, 961); -#endif - dasm_put(Dst, 1502); -#if LJ_DUALNUM - dasm_put(Dst, 1483); -#endif - dasm_put(Dst, 1531, Dt1(->base), Dt1(->base), FRAME_CONT, 2+1, Dt1(->base), Dt1(->base)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1633); -#else - dasm_put(Dst, 1652); -#endif - dasm_put(Dst, 1657, Dt1(->base), Dt1(->base), Dt7(->pc), Dt1(->base), Dt1(->base), GG_DISP2STATIC, 1+1, LJ_TISTRUECOND); - dasm_put(Dst, 1843, 1+1, ~LJ_TNUMX); - if (cmov) { - dasm_put(Dst, 1912); - } else { - dasm_put(Dst, 1916); - } - dasm_put(Dst, 1925, ((char *)(&((GCfuncC *)0)->upvalue)), LJ_TSTR, ~LJ_TLIGHTUD, 1+1, LJ_TTAB, Dt6(->metatable), LJ_TNIL); - dasm_put(Dst, 2004, DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable), LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), DtB(->next)); - dasm_put(Dst, 2062, LJ_TNIL, LJ_TUDATA, LJ_TNUMX, LJ_TISNUM, LJ_TLIGHTUD); - dasm_put(Dst, 2128, LJ_TNUMX, DISPATCH_GL(gcroot[GCROOT_BASEMT]), 2+1, LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->metatable), LJ_TTAB); - dasm_put(Dst, 2199, Dt6(->marked), LJ_GC_BLACK, Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist), 2+1, LJ_TTAB); - dasm_put(Dst, 2289, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 2303); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 2325); - } else { - dasm_put(Dst, 2335); - } - dasm_put(Dst, 2342, 1+1, LJ_TSTR, LJ_TSTR, LJ_TISNUM, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM]), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 2411, Dt1(->base)); - if (LJ_DUALNUM) { - dasm_put(Dst, 2437); - } else { - dasm_put(Dst, 2442); - } - dasm_put(Dst, 2447, Dt1(->base), 1+1, LJ_TTAB, Dt1(->base), Dt1(->top), Dt1(->base), 1+2); - dasm_put(Dst, 2539, LJ_TNIL, LJ_TNIL, 1+1, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 2586, Dt6(->metatable)); -#endif - dasm_put(Dst, 2595, Dt8(->upvalue[0]), LJ_TFUNC, LJ_TNIL, 1+3, 1+1, LJ_TTAB, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 2581); - } else { - dasm_put(Dst, 2320); - } - dasm_put(Dst, 2650); - if (LJ_DUALNUM) { - dasm_put(Dst, 2655, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 2671, (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32)); - } else { - } - dasm_put(Dst, 2704, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->hmask), 1+0); - dasm_put(Dst, 2566, 1+1, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 2586, Dt6(->metatable)); -#endif - dasm_put(Dst, 2781, Dt8(->upvalue[0]), LJ_TFUNC); - if (LJ_DUALNUM) { - dasm_put(Dst, 2802, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 2814); - } else { - dasm_put(Dst, 2824); - } - dasm_put(Dst, 2831, 1+3, 1+1, 8+FRAME_PCALL, DISPATCH_GL(hookmask), HOOK_ACTIVE_SHIFT, 2+1, LJ_TFUNC); - dasm_put(Dst, 2896, LJ_TFUNC, 16+FRAME_PCALL, 1+1, LJ_TTHREAD, Dt1(->cframe), Dt1(->status), LUA_YIELD, Dt1(->top)); - dasm_put(Dst, 2985, Dt1(->base), Dt1(->maxstack), Dt1(->top), Dt1(->base), Dt1(->top), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP); - dasm_put(Dst, 3072, Dt1(->base), LUA_YIELD, Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->maxstack), LJ_TTRUE, FRAME_TYPE); - dasm_put(Dst, 3187, LJ_TFALSE, Dt1(->top), Dt1(->top), 1+2, Dt1(->top), Dt1(->base), Dt8(->upvalue[0].gcr), Dt1(->cframe)); - dasm_put(Dst, 3282, Dt1(->status), LUA_YIELD, Dt1(->top), Dt1(->base), Dt1(->maxstack), Dt1(->top), Dt1(->base), Dt1(->top)); - dasm_put(Dst, 3348, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base), LUA_YIELD, Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->maxstack)); - dasm_put(Dst, 3437, FRAME_TYPE, Dt1(->top), Dt1(->base), Dt1(->cframe), CFRAME_RESUME); - dasm_put(Dst, 3547, Dt1(->base), Dt1(->top), Dt1(->cframe), LUA_YIELD, Dt1(->status)); - if (!LJ_DUALNUM) { - dasm_put(Dst, 3574); - } - if (sse) { - dasm_put(Dst, 3577); - } - dasm_put(Dst, 3592, 1+1); - if (LJ_DUALNUM) { - dasm_put(Dst, 3603, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 3683, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 3693, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32)); - } else { - dasm_put(Dst, 3724); - } - dasm_put(Dst, 3741, 1+1, FRAME_TYPE, LJ_TNIL); - if (LJ_DUALNUM) { - dasm_put(Dst, 3838, LJ_TISNUM); - } else { - dasm_put(Dst, 3683, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 3860); - if (LJ_DUALNUM) { - dasm_put(Dst, 3869); - } - dasm_put(Dst, 2330); - } else { - dasm_put(Dst, 3903); - if (LJ_DUALNUM) { - } else { - dasm_put(Dst, 2337); - } - } - dasm_put(Dst, 3909); - if (LJ_DUALNUM) { - dasm_put(Dst, 3838, LJ_TISNUM); - } else { - dasm_put(Dst, 3683, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 3912); - if (LJ_DUALNUM) { - dasm_put(Dst, 3869); - } - dasm_put(Dst, 2330); - } else { - dasm_put(Dst, 3921); - if (LJ_DUALNUM) { - } else { - dasm_put(Dst, 2337); - } - } - if (sse) { - dasm_put(Dst, 3927, 1+1, LJ_TISNUM); - } else { - dasm_put(Dst, 3956, 1+1, LJ_TISNUM); - } - dasm_put(Dst, 3985, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1); - dasm_put(Dst, 4054, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1); - dasm_put(Dst, 4111, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1); - dasm_put(Dst, 4174, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM); - dasm_put(Dst, 4264); - if (sse) { - dasm_put(Dst, 4276, 1+1, LJ_TISNUM); - } else { - } - dasm_put(Dst, 4301); - if (sse) { - dasm_put(Dst, 4315, 1+1, LJ_TISNUM); - } else { - } - dasm_put(Dst, 4340); - if (sse) { - dasm_put(Dst, 4354, 1+1, LJ_TISNUM); - } else { - } - dasm_put(Dst, 4379); - if (sse) { - dasm_put(Dst, 4395, 1+1, LJ_TISNUM, Dt8(->upvalue[0])); - } else { - dasm_put(Dst, 4434, 1+1, LJ_TISNUM, Dt8(->upvalue[0])); - } - dasm_put(Dst, 4467, 2+1, LJ_TISNUM, LJ_TISNUM, 2+1, LJ_TISNUM, LJ_TISNUM); - dasm_put(Dst, 4532, 1+1, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4631); - } else { - dasm_put(Dst, 4637); - } - dasm_put(Dst, 4644); - if (sse) { - dasm_put(Dst, 4669); - } else { - dasm_put(Dst, 4675); - } - dasm_put(Dst, 4678, 1+2); - if (sse) { - dasm_put(Dst, 4687); - } else { - dasm_put(Dst, 4695); - } - dasm_put(Dst, 4703); - if (sse) { - dasm_put(Dst, 4706, (unsigned int)(U64x(43500000,00000000)), (unsigned int)((U64x(43500000,00000000))>>32)); - } else { - dasm_put(Dst, 4733); - } - dasm_put(Dst, 4750); - if (sse) { - dasm_put(Dst, 4766, 1+1, LJ_TISNUM); - } else { - dasm_put(Dst, 4791, 1+1, LJ_TISNUM); - } - dasm_put(Dst, 4813); - if (sse) { - dasm_put(Dst, 4835); - } else { - dasm_put(Dst, 4861); - } - dasm_put(Dst, 4878, 1+2); - if (sse) { - dasm_put(Dst, 4918); - } else { - dasm_put(Dst, 4926); - } - dasm_put(Dst, 4936, 2+1, LJ_TISNUM, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4988, 2+1, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 5035, 2+1, LJ_TISNUM, LJ_TISNUM); - } - dasm_put(Dst, 5076, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5089, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4631); - } else { - } - dasm_put(Dst, 5139); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 5150, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5171); - } else { - dasm_put(Dst, 2320); - } - dasm_put(Dst, 5192); - } else { - } - dasm_put(Dst, 5217, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5230, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4631); - } else { - } - dasm_put(Dst, 5139); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 5150, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5171); - } else { - dasm_put(Dst, 2320); - } - dasm_put(Dst, 5280); - } else { - } - if (!sse) { - dasm_put(Dst, 5305); - } - dasm_put(Dst, 5314, 1+1, LJ_TSTR); - if (LJ_DUALNUM) { - dasm_put(Dst, 5336, Dt5(->len)); - } else if (sse) { - dasm_put(Dst, 5344, Dt5(->len)); - } else { - dasm_put(Dst, 5355, Dt5(->len)); - } - dasm_put(Dst, 5363, 1+1, LJ_TSTR, Dt5(->len), Dt5([1])); - if (LJ_DUALNUM) { - dasm_put(Dst, 5339); - } else if (sse) { - dasm_put(Dst, 5401); - } else { - dasm_put(Dst, 5411); - } - dasm_put(Dst, 5422, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5455); - } else if (sse) { - dasm_put(Dst, 5478); - } else { - dasm_put(Dst, 5504); - } - dasm_put(Dst, 5528, Dt1(->base), Dt1(->base), LJ_TSTR, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), 1+2, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5637); - } else if (sse) { - dasm_put(Dst, 5649); - } else { - dasm_put(Dst, 5664); - } - dasm_put(Dst, 5676, LJ_TSTR, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 2581); - } else { - dasm_put(Dst, 2320); - } - dasm_put(Dst, 5693, Dt5(->len)); - if (LJ_DUALNUM) { - dasm_put(Dst, 5703); - } else if (sse) { - dasm_put(Dst, 5707); - } else { - } - dasm_put(Dst, 5714, sizeof(GCstr)-1); - dasm_put(Dst, 5789, 2+1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 5850, LJ_TSTR, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5867); - } else if (sse) { - dasm_put(Dst, 5875); - } else { - dasm_put(Dst, 5886); - } - dasm_put(Dst, 5902, Dt5(->len), DISPATCH_GL(tmpbuf.sz), Dt5([1]), DISPATCH_GL(tmpbuf.buf), DISPATCH_GL(tmpbuf.buf), 1+1); - dasm_put(Dst, 5970, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf)); - dasm_put(Dst, 6037, 1+1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz)); - dasm_put(Dst, 6110, sizeof(GCstr), DISPATCH_GL(tmpbuf.buf), 1+1); - dasm_put(Dst, 6195, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf)); - dasm_put(Dst, 6269, 1+1, LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 6336); - } else if (sse) { - dasm_put(Dst, 6343); - } else { - } - dasm_put(Dst, 6353, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6369); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6386, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 106); - if (LJ_DUALNUM || sse) { - if (!sse) { - } - dasm_put(Dst, 6410); - } else { - } - dasm_put(Dst, 6415, 1+1); - if (sse) { - dasm_put(Dst, 6426, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - dasm_put(Dst, 6436); - } - dasm_put(Dst, 2297, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6444); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6461); - } else { - } - dasm_put(Dst, 6476, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6501); - } else { - dasm_put(Dst, 6521); - } - if (sse) { - dasm_put(Dst, 6526); - } else { - } - dasm_put(Dst, 6543, 1+1); - if (sse) { - dasm_put(Dst, 6426, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - dasm_put(Dst, 6436); - } - dasm_put(Dst, 2297, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6444); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6461); - } else { - } - dasm_put(Dst, 6476, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6561); - } else { - dasm_put(Dst, 6521); - } - if (sse) { - dasm_put(Dst, 6581); - } else { - } - dasm_put(Dst, 6598, 1+1); - if (sse) { - dasm_put(Dst, 6426, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - dasm_put(Dst, 6436); - } - dasm_put(Dst, 2297, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6444); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6461); - } else { - } - dasm_put(Dst, 6476, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6616); - } else { - dasm_put(Dst, 6521); - } - if (sse) { - dasm_put(Dst, 6636); - } else { - } - dasm_put(Dst, 6653, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6444); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6386, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6676, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6444); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6386, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6700); - if (LJ_DUALNUM) { - dasm_put(Dst, 6410); - } else if (sse) { - dasm_put(Dst, 6706); - } else { - } - dasm_put(Dst, 6718); - if (LJ_DUALNUM) { - dasm_put(Dst, 6729, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6444); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6386, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6745, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 6760, 2+1, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6827); - if (LJ_DUALNUM) { - dasm_put(Dst, 6834, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6444); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6386, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6745, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 6850, 2+1, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6917); - if (LJ_DUALNUM) { - dasm_put(Dst, 6925, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6444); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6386, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6745, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 6941, 2+1, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 7008); - if (LJ_DUALNUM) { - dasm_put(Dst, 7016, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6444); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6386, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6745, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 7032, 2+1, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 7099); - if (LJ_DUALNUM) { - dasm_put(Dst, 7106, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6444); - } else { - dasm_put(Dst, 2320); - } - if (sse) { - dasm_put(Dst, 6386, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6745, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 7122, 2+1, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 7189, 1+2, 1+1, Dt1(->base), 8*LUA_MINSTACK, Dt1(->top), Dt1(->maxstack), Dt8(->f), Dt1(->base)); - dasm_put(Dst, 7265, Dt1(->top), Dt7(->pc), FRAME_TYPE, LUA_MINSTACK, Dt1(->base), Dt1(->base)); - dasm_put(Dst, 7392, Dt1(->top), Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 7431, DISPATCH_GL(hookmask), HOOK_VMEVENT, HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount)); -#endif - dasm_put(Dst, 7464, DISPATCH_GL(hookmask), HOOK_ACTIVE, DISPATCH_GL(hookmask), HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount), LUA_MASKLINE); - dasm_put(Dst, 7518, Dt1(->base), Dt1(->base), GG_DISP2STATIC); -#if LJ_HASJIT - dasm_put(Dst, 7585, Dt7(->pc), PC2PROTO(framesize), Dt1(->base), Dt1(->top), GG_DISP2J, DISPATCH_J(L)); -#endif - dasm_put(Dst, 7632); -#if LJ_HASJIT - dasm_put(Dst, 7459); -#endif - dasm_put(Dst, 7639); -#if LJ_HASJIT - dasm_put(Dst, 7642); -#endif - dasm_put(Dst, 7652, Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 7685); -#endif - dasm_put(Dst, 7690, Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 7721, DISPATCH_GL(vmstate), DISPATCH_GL(vmstate), ~LJ_VMST_EXIT, DISPATCH_J(exitno), DISPATCH_J(parent), 16*8, DISPATCH_GL(jit_L), DISPATCH_GL(jit_base), DISPATCH_J(L), DISPATCH_GL(jit_L), Dt1(->base), GG_DISP2J, Dt1(->cframe), CFRAME_RAWMASK, CFRAME_OFS_L, Dt1(->base), CFRAME_OFS_PC); -#endif - dasm_put(Dst, 7960); -#if LJ_HASJIT - dasm_put(Dst, 7963, Dt7(->pc), PC2PROTO(k), DISPATCH_GL(jit_L), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, BC_FUNCF); -#endif - dasm_put(Dst, 8063); - if (!sse) { - dasm_put(Dst, 8066); - } - dasm_put(Dst, 8111, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32)); - if (!sse) { - dasm_put(Dst, 8197); - } - dasm_put(Dst, 8242, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(bff00000,00000000)), (unsigned int)((U64x(bff00000,00000000))>>32)); - if (!sse) { - dasm_put(Dst, 8328); - } - dasm_put(Dst, 8367, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32)); - if (sse) { - dasm_put(Dst, 8456, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32)); - } else { - dasm_put(Dst, 8570); - } - dasm_put(Dst, 8617); - if (!sse) { - } else { - dasm_put(Dst, 8694); - } - dasm_put(Dst, 8697); - dasm_put(Dst, 8782, (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32)); - dasm_put(Dst, 8885, (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32), (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32), (unsigned int)(U64x(7ff00000,00000000)), (unsigned int)((U64x(7ff00000,00000000))>>32)); - dasm_put(Dst, 9047); -#if LJ_HASJIT - if (sse) { - dasm_put(Dst, 9088); - dasm_put(Dst, 9158); - dasm_put(Dst, 9230); - } else { - dasm_put(Dst, 9282); - dasm_put(Dst, 9374); - } - dasm_put(Dst, 9420); -#endif - dasm_put(Dst, 9424); - if (sse) { - dasm_put(Dst, 9427, (unsigned int)(U64x(80000000,00000000)), (unsigned int)((U64x(80000000,00000000))>>32)); - dasm_put(Dst, 9512, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32)); - } else { - dasm_put(Dst, 9640); - dasm_put(Dst, 9723); - if (cmov) { - dasm_put(Dst, 9778); - } else { - dasm_put(Dst, 9797); - } - dasm_put(Dst, 9420); - } - dasm_put(Dst, 9838); -#ifdef LUA_USE_ASSERT - dasm_put(Dst, 9422); -#endif - dasm_put(Dst, 9862); -#if LJ_HASFFI -#define DtE(_V) (int)(ptrdiff_t)&(((CTState *)0)_V) - dasm_put(Dst, 9866, GG_G2DISP, Dt2(->ctype_state), DtE(->cb.slot), DtE(->cb.gpr[0]), DtE(->cb.gpr[1]), DtE(->cb.gpr[2]), DtE(->cb.gpr[3]), DtE(->cb.fpr[0]), DtE(->cb.fpr[1]), DtE(->cb.fpr[2]), DtE(->cb.fpr[3]), CFRAME_SIZE, DtE(->cb.gpr[4]), DtE(->cb.gpr[5]), DtE(->cb.fpr[4]), DtE(->cb.fpr[5]), DtE(->cb.fpr[6]), DtE(->cb.fpr[7]), DtE(->cb.stack), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP); - dasm_put(Dst, 9990, Dt1(->base), Dt1(->top), Dt7(->pc)); -#endif - dasm_put(Dst, 10030); -#if LJ_HASFFI - dasm_put(Dst, 10033, DISPATCH_GL(ctype_state), DtE(->L), Dt1(->base), Dt1(->top), DtE(->cb.gpr[0]), DtE(->cb.fpr[0])); -#endif - dasm_put(Dst, 10074); -#if LJ_HASFFI -#define DtF(_V) (int)(ptrdiff_t)&(((CCallState *)0)_V) - dasm_put(Dst, 10077, DtF(->spadj)); -#if LJ_TARGET_WINDOWS -#endif - dasm_put(Dst, 10093, DtF(->nsp), offsetof(CCallState, stack), CCALL_SPS_EXTRA*8, DtF(->nfpr), DtF(->gpr[0]), DtF(->gpr[1]), DtF(->gpr[2]), DtF(->gpr[3]), DtF(->gpr[4]), DtF(->gpr[5]), DtF(->fpr[0]), DtF(->fpr[1])); - dasm_put(Dst, 10172, DtF(->fpr[2]), DtF(->fpr[3]), DtF(->fpr[4]), DtF(->fpr[5]), DtF(->fpr[6]), DtF(->fpr[7]), DtF(->func), DtF(->gpr[0]), DtF(->fpr[0]), DtF(->gpr[1]), DtF(->fpr[1])); -#if LJ_TARGET_WINDOWS -#endif - dasm_put(Dst, 10227); -#endif -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse) -{ - int vk = 0; - dasm_put(Dst, 829, defop); - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - if (LJ_DUALNUM) { - dasm_put(Dst, 10235, LJ_TISNUM, LJ_TISNUM); - switch (op) { - case BC_ISLT: - dasm_put(Dst, 10265); - break; - case BC_ISGE: - dasm_put(Dst, 10270); - break; - case BC_ISLE: - dasm_put(Dst, 10275); - break; - case BC_ISGT: - dasm_put(Dst, 10280); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 10285, -BCBIAS_J*4, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 10340); - } else { - dasm_put(Dst, 10351); - } - dasm_put(Dst, 10362); - if (sse) { - dasm_put(Dst, 10369); - switch (op) { - case BC_ISLT: - dasm_put(Dst, 10389); - break; - case BC_ISGE: - dasm_put(Dst, 10394); - break; - case BC_ISLE: - dasm_put(Dst, 10399); - break; - case BC_ISGT: - dasm_put(Dst, 10404); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 10409); - } else { - dasm_put(Dst, 10414); - } - } else { - dasm_put(Dst, 10422, LJ_TISNUM, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 10443); - } else { - dasm_put(Dst, 10464); - if (cmov) { - dasm_put(Dst, 10480); - } else { - dasm_put(Dst, 10486); - } - } - if (LJ_DUALNUM) { - switch (op) { - case BC_ISLT: - dasm_put(Dst, 10389); - break; - case BC_ISGE: - dasm_put(Dst, 10394); - break; - case BC_ISLE: - dasm_put(Dst, 10399); - break; - case BC_ISGT: - dasm_put(Dst, 10404); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 10409); - } else { - switch (op) { - case BC_ISLT: - dasm_put(Dst, 817); - break; - case BC_ISGE: - dasm_put(Dst, 10493); - break; - case BC_ISLE: - dasm_put(Dst, 10498); - break; - case BC_ISGT: - dasm_put(Dst, 10503); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 10508, -BCBIAS_J*4); - } - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - dasm_put(Dst, 10541); - if (LJ_DUALNUM) { - dasm_put(Dst, 10549, LJ_TISNUM, LJ_TISNUM); - if (vk) { - dasm_put(Dst, 10574); - } else { - dasm_put(Dst, 10579); - } - dasm_put(Dst, 10584, -BCBIAS_J*4, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 10637); - } else { - dasm_put(Dst, 10644); - } - dasm_put(Dst, 10648); - if (sse) { - dasm_put(Dst, 10659); - } else { - dasm_put(Dst, 10671); - } - dasm_put(Dst, 10678); - } else { - dasm_put(Dst, 10683, LJ_TISNUM, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 10702); - } else { - dasm_put(Dst, 10720); - if (cmov) { - dasm_put(Dst, 10480); - } else { - dasm_put(Dst, 10486); - } - } - iseqne_fp: - if (vk) { - dasm_put(Dst, 10733); - } else { - dasm_put(Dst, 10742); - } - iseqne_end: - if (vk) { - dasm_put(Dst, 10751, -BCBIAS_J*4); - if (!LJ_HASFFI) { - dasm_put(Dst, 4684); - } - } else { - if (!LJ_HASFFI) { - dasm_put(Dst, 4684); - } - dasm_put(Dst, 10766, -BCBIAS_J*4); - } - if (LJ_DUALNUM && (op == BC_ISEQV || op == BC_ISNEV || - op == BC_ISEQN || op == BC_ISNEN)) { - dasm_put(Dst, 10781); - } else { - dasm_put(Dst, 10520); - } - if (op == BC_ISEQV || op == BC_ISNEV) { - dasm_put(Dst, 10786); - if (LJ_HASFFI) { - dasm_put(Dst, 10789, LJ_TCDATA, LJ_TCDATA); - } - dasm_put(Dst, 10808, LJ_TISPRI, LJ_TISTABUD, LJ_TUDATA, Dt6(->metatable), Dt6(->nomm), 1<>32)); - } else { - dasm_put(Dst, 11412); - } - if (LJ_DUALNUM) { - dasm_put(Dst, 10781); - } else { - dasm_put(Dst, 10520); - } - break; - case BC_LEN: - dasm_put(Dst, 11421, LJ_TSTR); - if (LJ_DUALNUM) { - dasm_put(Dst, 11435, Dt5(->len), LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 11449, Dt5(->len)); - } else { - dasm_put(Dst, 11467, Dt5(->len)); - } - dasm_put(Dst, 11476, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 11512, Dt6(->metatable)); -#endif - dasm_put(Dst, 11526); - if (LJ_DUALNUM) { - } else if (sse) { - dasm_put(Dst, 11535); - } else { - } - dasm_put(Dst, 11541); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 11554, Dt6(->nomm), 1<base), Dt1(->base)); - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - dasm_put(Dst, 12415, LJ_TSTR); - break; - case BC_KCDATA: -#if LJ_HASFFI - dasm_put(Dst, 12415, LJ_TCDATA); -#endif - break; - case BC_KSHORT: - if (LJ_DUALNUM) { - dasm_put(Dst, 12452, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 12464); - } else { - dasm_put(Dst, 12479); - } - dasm_put(Dst, 10520); - break; - case BC_KNUM: - if (sse) { - dasm_put(Dst, 12487); - } else { - dasm_put(Dst, 12501); - } - dasm_put(Dst, 10520); - break; - case BC_KPRI: - dasm_put(Dst, 12509); - break; - case BC_KNIL: - dasm_put(Dst, 12538, LJ_TNIL); - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - dasm_put(Dst, 12586, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_USETV: -#define TV2MARKOFS \ - ((int32_t)offsetof(GCupval, marked)-(int32_t)offsetof(GCupval, tv)) - dasm_put(Dst, 12627, offsetof(GCfuncL, uvptr), DtA(->closed), DtA(->v), TV2MARKOFS, LJ_GC_BLACK, LJ_TISGCV, LJ_TISNUM - LJ_TISGCV, Dt4(->gch.marked), LJ_GC_WHITES, GG_DISP2G); - dasm_put(Dst, 12723); - break; -#undef TV2MARKOFS - case BC_USETS: - dasm_put(Dst, 12735, offsetof(GCfuncL, uvptr), DtA(->v), LJ_TSTR, DtA(->marked), LJ_GC_BLACK, Dt4(->gch.marked), LJ_GC_WHITES, DtA(->closed), GG_DISP2G); - break; - case BC_USETN: - dasm_put(Dst, 12831); - if (sse) { - dasm_put(Dst, 12836); - } else { - dasm_put(Dst, 11052); - } - dasm_put(Dst, 12844, offsetof(GCfuncL, uvptr), DtA(->v)); - if (sse) { - dasm_put(Dst, 12853); - } else { - dasm_put(Dst, 12859); - } - dasm_put(Dst, 10520); - break; - case BC_USETP: - dasm_put(Dst, 12862, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_UCLO: - dasm_put(Dst, 12902, -BCBIAS_J*4, Dt1(->openupval), Dt1(->base), Dt1(->base)); - break; - - case BC_FNEW: - dasm_put(Dst, 12958, Dt1(->base), Dt1(->base), LJ_TFUNC); - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - dasm_put(Dst, 13025, Dt1(->base), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), LJ_TTAB); - break; - case BC_TDUP: - dasm_put(Dst, 13149, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), Dt1(->base), LJ_TTAB); - break; - - case BC_GGET: - dasm_put(Dst, 13248, Dt7(->env)); - break; - case BC_GSET: - dasm_put(Dst, 13268, Dt7(->env)); - break; - - case BC_TGETV: - dasm_put(Dst, 13288, LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 13311, LJ_TISNUM); - } else { - dasm_put(Dst, 13325, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 13336); - } else { - } - dasm_put(Dst, 13357); - } - dasm_put(Dst, 13362, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), LJ_TNIL); - dasm_put(Dst, 13557, LJ_TNIL, DtB(->next), Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), LJ_TNIL, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), LJ_TNIL, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - case BC_TSETS: - dasm_put(Dst, 13910, LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->nomm), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), LJ_TNIL); - dasm_put(Dst, 13987, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<next)); - dasm_put(Dst, 14074, Dt6(->metatable), Dt6(->nomm), 1<base), Dt1(->base), Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - case BC_TSETB: - dasm_put(Dst, 14166, LJ_TTAB, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable)); - dasm_put(Dst, 14261, Dt6(->metatable), Dt6(->nomm), 1<marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - - case BC_TSETM: - dasm_put(Dst, 14309, Dt6(->marked), LJ_GC_BLACK, Dt6(->asize), Dt6(->array), Dt1(->base), Dt1(->base)); - dasm_put(Dst, 14459, Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALL: case BC_CALLM: - dasm_put(Dst, 11574); - if (op == BC_CALLM) { - dasm_put(Dst, 14479); - } - dasm_put(Dst, 14484, LJ_TFUNC, Dt7(->pc)); - break; - - case BC_CALLMT: - dasm_put(Dst, 14479); - break; - case BC_CALLT: - dasm_put(Dst, 14527, LJ_TFUNC, FRAME_TYPE, Dt7(->ffid), Dt7(->pc)); - dasm_put(Dst, 14645, FRAME_TYPE, Dt7(->pc), PC2PROTO(k), FRAME_VARG, FRAME_TYPEP, FRAME_VARG); - break; - - case BC_ITERC: - dasm_put(Dst, 14719, LJ_TFUNC, 2+1, Dt7(->pc)); - break; - - case BC_ITERN: -#if LJ_HASJIT -#endif - dasm_put(Dst, 14791, Dt6(->asize), Dt6(->array), LJ_TNIL); - if (LJ_DUALNUM) { - dasm_put(Dst, 11440, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 11535); - } else { - dasm_put(Dst, 14843); - } - dasm_put(Dst, 14849); - if (LJ_DUALNUM) { - } else if (sse) { - dasm_put(Dst, 11405); - } else { - dasm_put(Dst, 11417); - } - dasm_put(Dst, 14862, -BCBIAS_J*4); - if (!LJ_DUALNUM && !sse) { - dasm_put(Dst, 14916); - } - dasm_put(Dst, 14922, Dt6(->hmask), sizeof(Node), Dt6(->node), DtB(->val.it), LJ_TNIL, DtB(->key), DtB(->val)); - break; - - case BC_ISNEXT: - dasm_put(Dst, 15001, LJ_TFUNC, LJ_TTAB, LJ_TNIL, Dt8(->ffid), FF_next_N, -BCBIAS_J*4, BC_JMP, -BCBIAS_J*4, BC_ITERC); - break; - - case BC_VARG: - dasm_put(Dst, 15102, (8+FRAME_VARG), LJ_TNIL, Dt1(->maxstack)); - dasm_put(Dst, 15269, Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top)); - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - dasm_put(Dst, 14479); - break; - - case BC_RET: case BC_RET0: case BC_RET1: - if (op != BC_RET0) { - dasm_put(Dst, 15339); - } - dasm_put(Dst, 15343, FRAME_TYPE); - switch (op) { - case BC_RET: - dasm_put(Dst, 15362); - break; - case BC_RET1: - dasm_put(Dst, 15416); - /* fallthrough */ - case BC_RET0: - dasm_put(Dst, 15426); - default: - break; - } - dasm_put(Dst, 15437, Dt7(->pc), PC2PROTO(k)); - if (op == BC_RET) { - dasm_put(Dst, 15485, LJ_TNIL); - } else { - dasm_put(Dst, 15496, LJ_TNIL); - } - dasm_put(Dst, 15503, -FRAME_VARG, FRAME_TYPEP); - if (op != BC_RET0) { - dasm_put(Dst, 15527); - } - dasm_put(Dst, 4761); - break; - - /* -- Loops and branches ------------------------------------------------ */ - - - case BC_FORL: -#if LJ_HASJIT - dasm_put(Dst, 15531, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - vk = (op == BC_IFORL || op == BC_JFORL); - dasm_put(Dst, 15552); - if (LJ_DUALNUM) { - dasm_put(Dst, 15556, LJ_TISNUM); - if (!vk) { - dasm_put(Dst, 15566, LJ_TISNUM, LJ_TISNUM); - } else { -#ifdef LUA_USE_ASSERT - dasm_put(Dst, 15595, LJ_TISNUM, LJ_TISNUM); -#endif - dasm_put(Dst, 15614); - } - dasm_put(Dst, 15633, LJ_TISNUM); - if (op == BC_FORI) { - dasm_put(Dst, 15644, -BCBIAS_J*4); - } else if (op == BC_JFORI) { - dasm_put(Dst, 15658, -BCBIAS_J*4, BC_JLOOP); - } else if (op == BC_IFORL) { - dasm_put(Dst, 15676, -BCBIAS_J*4); - } else { - dasm_put(Dst, 15668, BC_JLOOP); - } - dasm_put(Dst, 15690); - if (vk) { - dasm_put(Dst, 15715); - } - dasm_put(Dst, 15633, LJ_TISNUM); - if (op == BC_FORI) { - dasm_put(Dst, 15724); - } else if (op == BC_JFORI) { - dasm_put(Dst, 15729, -BCBIAS_J*4, BC_JLOOP); - } else if (op == BC_IFORL) { - dasm_put(Dst, 15743); - } else { - dasm_put(Dst, 15739, BC_JLOOP); - } - dasm_put(Dst, 15748); - } else if (!vk) { - dasm_put(Dst, 15755, LJ_TISNUM); - } - if (!vk) { - dasm_put(Dst, 15761, LJ_TISNUM); - } else { -#ifdef LUA_USE_ASSERT - dasm_put(Dst, 15775, LJ_TISNUM, LJ_TISNUM); -#endif - } - dasm_put(Dst, 15794); - if (!vk) { - dasm_put(Dst, 15798, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 15807); - if (vk) { - dasm_put(Dst, 15819); - } else { - dasm_put(Dst, 15838); - } - dasm_put(Dst, 15843); - } else { - dasm_put(Dst, 15856); - if (vk) { - dasm_put(Dst, 15862); - } else { - dasm_put(Dst, 15878); - } - dasm_put(Dst, 15886); - if (cmov) { - dasm_put(Dst, 10480); - } else { - dasm_put(Dst, 10486); - } - if (!cmov) { - dasm_put(Dst, 15891); - } - } - if (op == BC_FORI) { - if (LJ_DUALNUM) { - dasm_put(Dst, 15897); - } else { - dasm_put(Dst, 15902, -BCBIAS_J*4); - } - } else if (op == BC_JFORI) { - dasm_put(Dst, 15912, -BCBIAS_J*4, BC_JLOOP); - } else if (op == BC_IFORL) { - if (LJ_DUALNUM) { - dasm_put(Dst, 15926); - } else { - dasm_put(Dst, 15931, -BCBIAS_J*4); - } - } else { - dasm_put(Dst, 15922, BC_JLOOP); - } - if (LJ_DUALNUM) { - dasm_put(Dst, 10409); - } else { - dasm_put(Dst, 11186); - } - if (sse) { - dasm_put(Dst, 15941); - } - break; - - case BC_ITERL: -#if LJ_HASJIT - dasm_put(Dst, 15531, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - dasm_put(Dst, 15952, LJ_TNIL); - if (op == BC_JITERL) { - dasm_put(Dst, 15967, BC_JLOOP); - } else { - dasm_put(Dst, 15981, -BCBIAS_J*4); - } - dasm_put(Dst, 10518); - break; - - case BC_LOOP: -#if LJ_HASJIT - dasm_put(Dst, 15531, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_ILOOP: - dasm_put(Dst, 10520); - break; - - case BC_JLOOP: -#if LJ_HASJIT - dasm_put(Dst, 15997, DISPATCH_J(trace), DtD(->mcode), DISPATCH_GL(jit_base), DISPATCH_GL(jit_L)); -#endif - break; - - case BC_JMP: - dasm_put(Dst, 16038, -BCBIAS_J*4); - break; - - /* -- Function headers -------------------------------------------------- */ - - /* - ** Reminder: A function may be called with func/args above L->maxstack, - ** i.e. occupying EXTRA_STACK slots. And vmeta_call may add one extra slot, - ** too. This means all FUNC* ops (including fast functions) must check - ** for stack overflow _before_ adding more slots! - */ - - case BC_FUNCF: -#if LJ_HASJIT - dasm_put(Dst, 16064, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_CALL); -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - dasm_put(Dst, 16085, -4+PC2PROTO(k), Dt1(->maxstack), -4+PC2PROTO(numparams)); - if (op == BC_JFUNCF) { - dasm_put(Dst, 16116, BC_JLOOP); - } else { - dasm_put(Dst, 10520); - } - dasm_put(Dst, 16125, LJ_TNIL); - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - dasm_put(Dst, 9422); - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - dasm_put(Dst, 16147, FRAME_VARG, Dt1(->maxstack), -4+PC2PROTO(numparams), LJ_TNIL); - if (op == BC_JFUNCV) { - dasm_put(Dst, 16116, BC_JLOOP); - } else { - dasm_put(Dst, 16244, -4+PC2PROTO(k)); - } - dasm_put(Dst, 16269, LJ_TNIL); - break; - - case BC_FUNCC: - case BC_FUNCCW: - dasm_put(Dst, 16291, Dt8(->f), Dt1(->base), 8*LUA_MINSTACK, Dt1(->maxstack), Dt1(->top)); - if (op == BC_FUNCC) { - dasm_put(Dst, 2433); - } else { - dasm_put(Dst, 16321); - } - dasm_put(Dst, 16329, DISPATCH_GL(vmstate), ~LJ_VMST_C); - if (op == BC_FUNCC) { - dasm_put(Dst, 16339); - } else { - dasm_put(Dst, 16344, DISPATCH_GL(wrapf)); - } - dasm_put(Dst, 16350, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base), Dt1(->top)); - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - int cmov = 1; - int sse = 0; -#ifdef LUAJIT_CPU_NOCMOV - cmov = 0; -#endif -#if defined(LUAJIT_CPU_SSE2) || defined(LJ_TARGET_X64) - sse = 1; -#endif - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx, cmov, sse); - - dasm_put(Dst, 16376); - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op, cmov, sse); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); -#if LJ_64 -#define SZPTR "8" -#define BSZPTR "3" -#define REG_SP "0x7" -#define REG_RA "0x10" -#else -#define SZPTR "4" -#define BSZPTR "2" -#define REG_SP "0x4" -#define REG_RA "0x8" -#endif - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.long .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.long 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.long .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.long .Lframe0\n" -#if LJ_64 - "\t.quad .Lbegin\n" - "\t.quad %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.long .Lbegin\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE0:\n\n", fcofs, CFRAME_SIZE); -#if LJ_HASFFI - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.long .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.long .Lframe0\n" -#if LJ_64 - "\t.quad lj_vm_ffi_call\n" - "\t.quad %d\n" - "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ -#else - "\t.long lj_vm_ffi_call\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); -#endif -#if (defined(__sun__) && defined(__svr4__)) || defined(__solaris_) - fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n"); -#else - fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); -#endif - fprintf(ctx->fp, - ".Lframe1:\n" - "\t.long .LECIE1-.LSCIE1\n" - ".LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zPR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 6\n" /* augmentation length */ - "\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 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE1:\n\n"); - fprintf(ctx->fp, - ".LSFDE2:\n" - "\t.long .LEFDE2-.LASFDE2\n" - ".LASFDE2:\n" - "\t.long .LASFDE2-.Lframe1\n" - "\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 */ -#if LJ_64 - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE2:\n\n", fcofs, CFRAME_SIZE); -#if LJ_HASFFI - fprintf(ctx->fp, - ".Lframe2:\n" - "\t.long .LECIE2-.LSCIE2\n" - ".LSCIE2:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 1\n" /* augmentation length */ - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE2:\n\n"); - fprintf(ctx->fp, - ".LSFDE3:\n" - "\t.long .LEFDE3-.LASFDE3\n" - ".LASFDE3:\n" - "\t.long .LASFDE3-.Lframe2\n" - "\t.long lj_vm_ffi_call-.\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ -#else - "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); -#endif - break; - case BUILD_coffasm: - fprintf(ctx->fp, "\t.section .eh_frame,\"dr\"\n"); - fprintf(ctx->fp, - "\t.def %slj_err_unwind_dwarf; .scl 2; .type 32; .endef\n", - LJ_32 ? "_" : ""); - fprintf(ctx->fp, - "Lframe1:\n" - "\t.long LECIE1-LSCIE1\n" - "LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zP\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 5\n" /* augmentation length */ - "\t.byte 0x00\n" /* absptr */ - "\t.long %slj_err_unwind_dwarf\n" - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - "LECIE1:\n\n", LJ_32 ? "_" : ""); - fprintf(ctx->fp, - "LSFDE1:\n" - "\t.long LEFDE1-LASFDE1\n" - "LASFDE1:\n" - "\t.long LASFDE1-Lframe1\n" - "\t.long %slj_vm_asm_begin\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ -#if LJ_64 - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - "LEFDE1:\n\n", LJ_32 ? "_" : "", (int)ctx->codesz, CFRAME_SIZE); - break; - /* Mental note: never let Apple design an assembler. - ** Or a linker. Or a plastic case. But I digress. - */ - case BUILD_machasm: { -#if LJ_HASFFI - int fcsize = 0; -#endif - int i; - 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.byte 0x1\n" - "\t.byte 128-" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 6\n" /* augmentation length */ - "\t.byte 0x9b\n" /* indirect|pcrel|sdata4 */ -#if LJ_64 - "\t.long _lj_err_unwind_dwarf+4@GOTPCREL\n" - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n" -#else - "\t.long L_lj_err_unwind_dwarf$non_lazy_ptr-.\n" - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH-O. */ -#endif - "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n" - "\t.align " BSZPTR "\n" - "LECIEX:\n\n"); - for (i = 0; i < ctx->nsym; i++) { - const char *name = ctx->sym[i].name; - int32_t size = ctx->sym[i+1].ofs - ctx->sym[i].ofs; - if (size == 0) continue; -#if LJ_HASFFI - if (!strcmp(name, "_lj_vm_ffi_call")) { fcsize = size; continue; } -#endif - fprintf(ctx->fp, - "%s.eh:\n" - "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.byte 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.byte %d\n" /* def_cfa_offset */ -#if LJ_64 - "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.byte 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.byte 0x5\n" /* offset r14 */ -#else - "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/ - "\t.byte 0x87\n\t.byte 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.byte 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.byte 0x5\n" /* offset ebx */ -#endif - "\t.align " BSZPTR "\n" - "LEFDE%d:\n\n", - name, i, i, i, i, i, i, i, name, size, CFRAME_SIZE, i); - } -#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.byte 0x1\n" - "\t.byte 128-" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 1\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n" -#else - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH. */ -#endif - "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n" - "\t.align " BSZPTR "\n" - "LECIEY:\n\n"); - fprintf(ctx->fp, - "_lj_vm_ffi_call.eh:\n" - "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.byte 0\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0xe\n\t.byte 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */ -#else - "\t.byte 0xe\n\t.byte 8\n" /* def_cfa_offset */ - "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/ - "\t.byte 0xd\n\t.uleb128 0x4\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset ebx */ -#endif - "\t.align " BSZPTR "\n" - "LEFDEY:\n\n", fcsize); - } -#endif -#if LJ_64 - fprintf(ctx->fp, "\t.subsections_via_symbols\n"); -#else - fprintf(ctx->fp, - "\t.non_lazy_symbol_pointer\n" - "L_lj_err_unwind_dwarf$non_lazy_ptr:\n" - ".indirect_symbol _lj_err_unwind_dwarf\n" - ".long 0\n"); -#endif - } - break; - default: /* Difficult for other modes. */ - break; - } -} - diff --git a/src/buildvm_x64win.h b/src/buildvm_x64win.h deleted file mode 100644 index 533d5b00..00000000 --- a/src/buildvm_x64win.h +++ /dev/null @@ -1,3401 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM x64 version 1.3.0 -** DO NOT EDIT! The original file is in "buildvm_x86.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -#define DASM_SECTION_CODE_OP 0 -#define DASM_SECTION_CODE_SUB 1 -#define DASM_MAXSECTION 2 -static const unsigned char build_actionlist[16196] = { - 254,1,248,10,252,247,198,237,15,132,244,11,131,230,252,248,41,252,242,72, - 141,76,49,252,248,139,114,252,252,199,68,10,4,237,248,12,131,192,1,137,68, - 36,84,252,247,198,237,15,132,244,13,248,14,129,252,246,239,252,247,198,237, - 15,133,244,10,199,131,233,237,131,230,252,248,41,214,252,247,222,131,232, - 1,15,132,244,248,248,1,72,139,44,10,72,137,106,252,248,131,194,8,131,232, - 1,15,133,244,1,248,2,255,139,108,36,96,137,181,233,248,3,139,68,36,84,139, - 76,36,88,248,4,57,193,15,133,244,252,248,5,131,252,234,8,137,149,233,248, - 15,72,139,76,36,104,72,137,141,233,49,192,248,16,72,131,196,40,91,94,95,93, - 195,248,6,15,130,244,253,59,149,233,15,135,244,254,199,66,252,252,237,131, - 194,8,131,192,1,252,233,244,4,248,7,255,133,201,15,132,244,5,41,193,141,20, - 202,252,233,244,5,248,8,137,149,233,137,68,36,84,137,202,137,252,233,232, - 251,1,0,139,149,233,252,233,244,3,248,17,137,208,72,137,204,248,18,139,108, - 36,96,139,173,233,199,133,233,237,252,233,244,16,248,19,248,20,72,129,225, - 239,72,137,204,248,21,255,139,108,36,96,72,199,193,252,248,252,255,252,255, - 252,255,184,237,139,149,233,139,157,233,129,195,239,139,114,252,252,199,66, - 252,252,237,199,131,233,237,252,233,244,12,248,22,186,237,252,233,244,248, - 248,23,131,232,8,252,233,244,247,248,24,141,68,194,252,248,248,1,15,182,142, - 233,131,198,4,137,149,233,255,137,133,233,137,116,36,100,137,202,248,2,137, - 252,233,232,251,1,0,139,149,233,139,133,233,139,106,252,248,41,208,193,232, - 3,131,192,1,139,181,233,139,14,15,182,252,233,15,182,205,131,198,4,252,255, - 36,252,235,248,25,85,87,86,83,72,131,252,236,40,137,205,137,76,36,96,137, - 209,190,237,49,192,72,141,188,253,36,233,139,157,233,129,195,239,72,137,189, - 233,137,68,36,100,72,137,68,36,104,137,68,36,88,137,68,36,92,56,133,233,15, - 132,244,249,199,131,233,237,136,133,233,139,149,233,139,133,233,41,200,193, - 232,3,131,192,1,41,209,139,114,252,252,137,68,36,84,252,247,198,237,255,15, - 132,244,13,252,233,244,14,248,26,85,87,86,83,72,131,252,236,40,190,237,68, - 137,76,36,92,252,233,244,247,248,27,85,87,86,83,72,131,252,236,40,190,237, - 248,1,68,137,68,36,88,137,205,137,76,36,96,137,209,72,139,189,233,72,137, - 124,36,104,137,108,36,100,72,137,165,233,248,2,139,157,233,129,195,239,248, - 3,199,131,233,237,139,149,233,255,1,206,41,214,139,133,233,41,200,193,232, - 3,131,192,1,248,28,139,105,252,248,129,121,253,252,252,239,15,133,244,29, - 248,30,137,202,137,114,252,252,139,181,233,139,14,15,182,252,233,15,182,205, - 131,198,4,252,255,36,252,235,248,31,85,87,86,83,72,131,252,236,40,137,205, - 137,76,36,96,137,108,36,100,139,189,233,43,189,233,199,68,36,92,0,0,0,0,137, - 124,36,88,72,139,189,233,72,137,124,36,104,72,137,165,233,65,252,255,209, - 133,192,15,132,244,15,137,193,190,237,252,233,244,2,248,11,1,209,131,230, - 252,248,137,213,41,252,242,199,68,193,252,252,237,137,200,139,117,252,244, - 72,99,77,252,240,255,131,252,249,1,15,134,244,247,255,72,141,61,245,72,1, - 252,249,255,139,122,252,248,139,191,233,139,191,233,252,255,225,255,248,1, - 15,132,244,32,41,213,193,252,237,3,141,69,252,255,252,233,244,33,255,248, - 34,15,182,78,252,255,131,252,237,16,141,12,202,41,252,233,15,132,244,35,252, - 247,217,193,252,233,3,65,137,200,139,76,36,96,137,145,233,72,139,0,72,137, - 69,0,137,252,234,252,233,244,36,248,37,137,68,36,80,199,68,36,84,237,72,141, - 68,36,80,128,126,252,252,235,15,133,244,247,141,139,233,137,41,199,65,4,237, - 137,205,252,233,244,248,248,38,15,182,70,252,254,255,199,68,36,84,237,137, - 68,36,80,255,252,242,15,42,192,252,242,15,17,68,36,80,255,72,141,68,36,80, - 252,233,244,247,248,39,15,182,70,252,254,141,4,194,248,1,15,182,110,252,255, - 141,44,252,234,248,2,139,76,36,96,137,145,233,137,252,234,73,137,192,137, - 205,137,116,36,100,232,251,1,1,139,149,233,133,192,15,132,244,249,248,35, - 15,182,78,252,253,72,139,40,72,137,44,202,139,6,15,182,204,15,182,232,131, - 198,4,193,232,16,252,255,36,252,235,248,3,139,141,233,137,113,252,244,141, - 177,233,41,214,139,105,252,248,184,237,252,233,244,30,248,40,137,68,36,80, - 199,68,36,84,237,72,141,68,36,80,128,126,252,252,235,15,133,244,247,255,141, - 139,233,137,41,199,65,4,237,137,205,252,233,244,248,248,41,15,182,70,252, - 254,255,72,141,68,36,80,252,233,244,247,248,42,15,182,70,252,254,141,4,194, - 248,1,15,182,110,252,255,141,44,252,234,248,2,139,76,36,96,137,145,233,137, - 252,234,73,137,192,137,205,137,116,36,100,232,251,1,2,139,149,233,133,192, - 15,132,244,249,15,182,78,252,253,72,139,44,202,72,137,40,248,43,139,6,15, - 182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235,248,3,139,141, - 233,137,113,252,244,15,182,70,252,253,72,139,44,194,72,137,105,16,141,177, - 233,41,214,139,105,252,248,184,237,252,233,244,30,248,44,139,108,36,96,137, - 149,233,68,141,4,194,141,20,202,137,252,233,68,15,182,78,252,252,137,116, - 36,100,232,251,1,3,248,3,139,149,233,255,131,252,248,1,15,135,244,45,248, - 4,141,118,4,15,130,244,252,248,5,15,183,70,252,254,141,180,253,134,233,248, - 6,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235,248, - 46,131,198,4,129,120,253,4,239,15,130,244,5,252,233,244,6,248,47,129,120, - 253,4,239,252,233,244,4,248,48,131,252,238,4,65,137,192,65,137,252,233,139, - 108,36,96,137,149,233,255,137,202,137,252,233,137,116,36,100,232,251,1,4, - 252,233,244,3,248,49,255,131,252,238,4,139,108,36,96,137,149,233,137,252, - 233,139,86,252,252,137,116,36,100,232,251,1,5,252,233,244,3,255,248,50,255, - 15,182,110,252,255,255,248,51,141,4,199,252,233,244,247,248,52,255,248,53, - 141,4,199,141,44,252,234,149,252,233,244,248,248,54,141,4,194,137,197,252, - 233,244,248,248,55,255,248,56,141,4,194,248,1,141,44,252,234,248,2,141,12, - 202,65,137,232,65,137,193,15,182,70,252,252,137,68,36,32,139,108,36,96,137, - 149,233,137,202,137,252,233,137,116,36,100,232,251,1,6,139,149,233,133,192, - 15,132,244,43,248,45,137,193,41,208,137,113,252,244,141,176,233,184,237,252, - 233,244,28,248,57,139,108,36,96,137,149,233,141,20,194,137,252,233,137,116, - 36,100,232,251,1,7,139,149,233,255,133,192,15,133,244,45,15,183,70,252,254, - 139,12,194,252,233,244,58,255,252,233,244,45,255,248,59,141,76,202,8,248, - 29,137,76,36,84,137,68,36,80,131,252,233,8,139,108,36,96,137,149,233,137, - 202,68,141,4,193,137,252,233,137,116,36,100,232,251,1,8,139,149,233,139,76, - 36,84,139,68,36,80,139,105,252,248,131,192,1,57,215,15,132,244,60,137,202, - 137,114,252,252,139,181,233,139,14,15,182,252,233,15,182,205,131,198,4,252, - 255,36,252,235,248,61,139,108,36,96,137,149,233,137,202,137,252,233,137,116, - 36,100,232,251,1,9,139,149,233,139,70,252,252,15,182,204,15,182,232,193,232, - 16,252,255,164,253,252,235,233,248,62,129,252,248,239,15,130,244,63,139,106, - 4,129,252,253,239,15,131,244,63,139,114,252,252,137,68,36,84,137,106,252, - 252,139,42,137,106,252,248,131,232,2,15,132,244,248,255,137,209,248,1,131, - 193,8,72,139,41,72,137,105,252,248,131,232,1,15,133,244,1,248,2,139,68,36, - 84,252,233,244,64,248,65,129,252,248,239,15,130,244,63,139,106,4,137,252, - 233,193,252,249,15,131,252,249,252,254,15,132,244,249,184,237,252,247,213, - 57,232,255,15,71,197,255,15,134,244,247,137,232,248,1,255,248,2,139,106,252, - 248,139,132,253,197,233,139,114,252,252,199,66,252,252,237,137,66,252,248, - 252,233,244,66,248,3,184,237,252,233,244,2,248,67,129,252,248,239,15,130, - 244,63,139,106,4,139,114,252,252,129,252,253,239,15,133,244,252,248,1,139, - 42,139,173,233,248,2,133,252,237,199,66,252,252,237,255,15,132,244,66,139, - 131,233,199,66,252,252,237,137,106,252,248,139,141,233,35,136,233,105,201, - 239,3,141,233,248,3,129,185,233,239,15,133,244,250,57,129,233,15,132,244, - 251,248,4,139,137,233,133,201,15,133,244,3,255,252,233,244,66,248,5,139,105, - 4,129,252,253,239,15,132,244,66,139,1,137,106,252,252,137,66,252,248,252, - 233,244,66,248,6,129,252,253,239,15,132,244,1,129,252,253,239,15,135,244, - 254,129,252,253,239,15,134,244,253,189,237,252,233,244,254,248,7,255,189, - 237,248,8,252,247,213,139,172,253,171,233,252,233,244,2,248,68,129,252,248, - 239,15,130,244,63,129,122,253,4,239,15,133,244,63,139,42,131,189,233,0,15, - 133,244,63,129,122,253,12,239,15,133,244,63,139,66,8,137,133,233,139,114, - 252,252,199,66,252,252,237,255,137,106,252,248,252,246,133,233,235,15,132, - 244,247,128,165,233,235,139,131,233,137,171,233,137,133,233,248,1,252,233, - 244,66,248,69,129,252,248,239,15,130,244,63,129,122,253,4,239,15,133,244, - 63,137,213,68,141,66,8,139,18,139,76,36,96,232,251,1,10,137,252,234,72,139, - 40,139,114,252,252,72,137,106,252,248,252,233,244,66,248,70,255,129,252,248, - 239,15,133,244,63,129,122,253,4,239,255,15,133,244,247,139,42,252,233,244, - 71,248,1,15,135,244,63,255,15,131,244,63,255,252,242,15,16,2,252,233,244, - 72,255,221,2,252,233,244,73,255,248,74,129,252,248,239,15,130,244,63,139, - 114,252,252,129,122,253,4,239,15,133,244,249,139,2,248,2,199,66,252,252,237, - 137,66,252,248,252,233,244,66,248,3,129,122,253,4,239,15,135,244,63,131,187, - 233,0,15,133,244,63,139,171,233,59,171,233,255,15,130,244,247,232,244,75, - 248,1,139,108,36,96,137,149,233,137,116,36,100,137,252,233,255,232,251,1, - 11,255,232,251,1,12,255,139,149,233,252,233,244,2,248,76,129,252,248,239, - 15,130,244,63,15,132,244,248,248,1,129,122,253,4,239,15,133,244,63,139,108, - 36,96,137,149,233,137,149,233,139,114,252,252,68,141,66,8,139,18,137,252, - 233,137,116,36,100,232,251,1,13,139,149,233,133,192,15,132,244,249,72,139, - 106,8,72,139,66,16,72,137,106,252,248,72,137,2,248,77,184,237,255,252,233, - 244,78,248,2,199,66,12,237,252,233,244,1,248,3,199,66,252,252,237,252,233, - 244,66,248,79,129,252,248,239,15,130,244,63,139,42,129,122,253,4,239,15,133, - 244,63,255,131,189,233,0,15,133,244,63,255,139,106,252,248,139,133,233,139, - 114,252,252,199,66,252,252,237,137,66,252,248,199,66,12,237,184,237,252,233, - 244,78,248,80,129,252,248,239,15,130,244,63,129,122,253,4,239,15,133,244, - 63,129,122,253,12,239,255,139,114,252,252,255,139,66,8,131,192,1,199,66,252, - 252,237,137,66,252,248,255,252,242,15,16,66,8,72,189,237,237,102,72,15,110, - 205,252,242,15,88,193,252,242,15,45,192,252,242,15,17,66,252,248,255,139, - 42,59,133,233,15,131,244,248,193,224,3,3,133,233,248,1,129,120,253,4,239, - 15,132,244,81,72,139,40,72,137,42,252,233,244,77,248,2,131,189,233,0,15,132, - 244,81,137,252,233,137,213,137,194,232,251,1,14,137,252,234,133,192,15,133, - 244,1,248,81,184,237,252,233,244,78,248,82,255,139,106,252,248,139,133,233, - 139,114,252,252,199,66,252,252,237,137,66,252,248,255,199,66,12,237,199,66, - 8,0,0,0,0,255,15,87,192,252,242,15,17,66,8,255,217,252,238,221,90,8,255,184, - 237,252,233,244,78,248,83,129,252,248,239,15,130,244,63,141,74,8,131,232, - 1,190,237,248,1,15,182,171,233,193,252,237,235,131,229,1,1,252,238,252,233, - 244,28,248,84,129,252,248,239,15,130,244,63,129,122,253,12,239,15,133,244, - 63,255,139,106,4,137,106,12,199,66,4,237,139,42,139,114,8,137,106,8,137,50, - 141,74,16,131,232,2,190,237,252,233,244,1,248,85,129,252,248,239,15,130,244, - 63,139,42,139,114,252,252,137,116,36,100,137,108,36,80,129,122,253,4,239, - 15,133,244,63,72,131,189,233,0,15,133,244,63,128,189,233,235,15,135,244,63, - 139,141,233,15,132,244,247,255,59,141,233,15,132,244,63,248,1,141,116,193, - 252,240,59,181,233,15,135,244,63,137,181,233,139,108,36,96,137,149,233,131, - 194,8,137,149,233,141,108,194,232,72,41,252,245,57,206,15,132,244,249,248, - 2,72,139,4,46,72,137,70,252,248,131,252,238,8,57,206,15,133,244,2,248,3,137, - 202,139,76,36,80,232,244,25,199,131,233,237,255,139,108,36,96,139,116,36, - 80,139,149,233,129,252,248,239,15,135,244,254,248,4,139,142,233,139,190,233, - 137,142,233,137,252,254,41,206,15,132,244,252,141,4,50,193,252,238,3,59,133, - 233,15,135,244,255,137,213,72,41,205,248,5,72,139,1,72,137,4,41,131,193,8, - 57,252,249,15,133,244,5,248,6,141,70,2,199,66,252,252,237,248,7,139,116,36, - 100,137,68,36,84,72,199,193,252,248,252,255,252,255,252,255,252,247,198,237, - 255,15,132,244,13,252,233,244,14,248,8,199,66,252,252,237,139,142,233,131, - 252,233,8,137,142,233,72,139,1,72,137,2,184,237,252,233,244,7,248,9,139,76, - 36,80,137,185,233,137,252,242,137,252,233,232,251,1,0,139,116,36,80,139,149, - 233,252,233,244,4,248,86,139,106,252,248,139,173,233,139,114,252,252,137, - 116,36,100,137,108,36,80,72,131,189,233,0,15,133,244,63,255,128,189,233,235, - 15,135,244,63,139,141,233,15,132,244,247,59,141,233,15,132,244,63,248,1,141, - 116,193,252,248,59,181,233,15,135,244,63,137,181,233,139,108,36,96,137,149, - 233,137,149,233,141,108,194,252,240,72,41,252,245,57,206,15,132,244,249,248, - 2,255,72,139,4,46,72,137,70,252,248,131,252,238,8,57,206,15,133,244,2,248, - 3,137,202,139,76,36,80,232,244,25,199,131,233,237,139,108,36,96,139,116,36, - 80,139,149,233,129,252,248,239,15,135,244,254,248,4,139,142,233,139,190,233, - 137,142,233,137,252,254,41,206,15,132,244,252,141,4,50,193,252,238,3,59,133, - 233,15,135,244,255,255,137,213,72,41,205,248,5,72,139,1,72,137,4,41,131,193, - 8,57,252,249,15,133,244,5,248,6,141,70,1,248,7,139,116,36,100,137,68,36,84, - 49,201,252,247,198,237,15,132,244,13,252,233,244,14,248,8,137,252,242,137, - 252,233,232,251,1,15,248,9,139,76,36,80,137,185,233,137,252,242,137,252,233, - 232,251,1,0,139,116,36,80,139,149,233,252,233,244,4,248,87,139,108,36,96, - 72,252,247,133,233,237,15,132,244,63,255,137,149,233,141,68,194,252,248,137, - 133,233,49,192,72,137,133,233,176,235,136,133,233,252,233,244,16,255,248, - 71,255,248,73,139,114,252,252,221,90,252,248,252,233,244,66,255,248,88,129, - 252,248,239,15,130,244,63,255,129,122,253,4,239,15,133,244,248,139,42,131, - 252,253,0,15,137,244,71,252,247,221,15,136,244,247,248,89,248,71,139,114, - 252,252,199,66,252,252,237,137,106,252,248,252,233,244,66,248,1,139,114,252, - 252,199,66,252,252,0,0,224,65,199,66,252,248,0,0,0,0,252,233,244,66,248,2, - 15,135,244,63,255,129,122,253,4,239,15,131,244,63,255,252,242,15,16,2,72, - 184,237,237,102,72,15,110,200,15,84,193,248,72,139,114,252,252,252,242,15, - 17,66,252,248,255,221,2,217,225,248,72,248,73,139,114,252,252,221,90,252, - 248,255,248,66,184,237,248,78,137,68,36,84,248,64,252,247,198,237,15,133, - 244,253,248,5,56,70,252,255,15,135,244,252,15,182,78,252,253,72,252,247,209, - 141,20,202,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,252, - 235,248,6,199,68,194,252,244,237,131,192,1,252,233,244,5,248,7,72,199,193, - 252,248,252,255,252,255,252,255,252,233,244,14,248,90,255,129,122,253,4,239, - 15,133,244,247,139,42,252,233,244,71,248,1,15,135,244,63,255,252,242,15,16, - 2,232,244,91,255,252,242,15,45,232,129,252,253,0,0,0,128,15,133,244,71,252, - 242,15,42,205,102,15,46,193,15,138,244,72,15,132,244,71,255,221,2,232,244, - 91,255,248,92,255,252,242,15,16,2,232,244,93,255,221,2,232,244,93,255,248, - 94,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,252,242, - 15,81,2,252,233,244,72,255,248,94,129,252,248,239,15,130,244,63,129,122,253, - 4,239,15,131,244,63,221,2,217,252,250,252,233,244,73,255,248,95,129,252,248, - 239,15,130,244,63,129,122,253,4,239,15,131,244,63,217,252,237,221,2,217,252, - 241,252,233,244,73,248,96,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,131,244,63,217,252,236,221,2,217,252,241,252,233,244,73,248,97,129,252, - 248,239,255,15,130,244,63,129,122,253,4,239,15,131,244,63,221,2,232,244,98, - 252,233,244,73,248,99,129,252,248,239,15,130,244,63,129,122,253,4,239,15, - 131,244,63,221,2,217,252,254,252,233,244,73,248,100,129,252,248,239,255,15, - 130,244,63,129,122,253,4,239,15,131,244,63,221,2,217,252,255,252,233,244, - 73,248,101,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63, - 221,2,217,252,242,221,216,252,233,244,73,248,102,129,252,248,239,15,130,244, - 63,255,129,122,253,4,239,15,131,244,63,221,2,217,192,216,200,217,232,222, - 225,217,252,250,217,252,243,252,233,244,73,248,103,129,252,248,239,15,130, - 244,63,129,122,253,4,239,15,131,244,63,221,2,217,192,216,200,217,232,222, - 225,217,252,250,217,201,217,252,243,252,233,244,73,248,104,129,252,248,239, - 15,130,244,63,129,122,253,4,239,15,131,244,63,255,221,2,217,232,217,252,243, - 252,233,244,73,255,248,105,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,131,244,63,252,242,15,16,2,255,137,213,232,251,1,16,137,252,234,252,233, - 244,72,255,248,106,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131, - 244,63,252,242,15,16,2,255,137,213,232,251,1,17,137,252,234,252,233,244,72, - 255,248,107,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63, - 252,242,15,16,2,255,137,213,232,251,1,18,137,252,234,252,233,244,72,248,108, - 255,248,109,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63, - 252,242,15,16,2,139,106,252,248,252,242,15,89,133,233,252,233,244,72,255, - 248,109,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,221, - 2,139,106,252,248,220,141,233,252,233,244,73,255,248,110,129,252,248,239, - 15,130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244, - 63,221,2,221,66,8,217,252,243,252,233,244,73,248,111,129,252,248,239,15,130, - 244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,255,15,131,244, - 63,221,66,8,221,2,217,252,253,221,217,252,233,244,73,248,112,129,252,248, - 239,15,130,244,63,139,106,4,129,252,253,239,15,131,244,63,139,114,252,252, - 139,2,137,106,252,252,137,66,252,248,209,229,129,252,253,0,0,224,252,255, - 15,131,244,249,9,232,15,132,244,249,184,252,254,3,0,0,129,252,253,0,0,32, - 0,15,130,244,250,248,1,193,252,237,21,41,197,255,252,242,15,42,197,255,137, - 108,36,80,219,68,36,80,255,139,106,252,252,129,229,252,255,252,255,15,128, - 129,205,0,0,224,63,137,106,252,252,248,2,255,252,242,15,17,2,255,221,26,255, - 184,237,252,233,244,78,248,3,255,15,87,192,252,233,244,2,255,217,252,238, - 252,233,244,2,255,248,4,255,252,242,15,16,2,72,189,237,237,102,72,15,110, - 205,252,242,15,89,193,252,242,15,17,66,252,248,255,221,2,199,68,36,80,0,0, - 128,90,216,76,36,80,221,90,252,248,255,139,106,252,252,184,52,4,0,0,209,229, - 252,233,244,1,255,248,113,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,131,244,63,252,242,15,16,2,255,248,113,129,252,248,239,15,130,244,63,129, - 122,253,4,239,15,131,244,63,221,2,255,139,106,4,139,114,252,252,209,229,129, - 252,253,0,0,224,252,255,15,132,244,250,255,15,40,224,232,244,114,252,242, - 15,92,224,248,1,252,242,15,17,66,252,248,252,242,15,17,34,255,217,192,232, - 244,114,220,252,233,248,1,221,90,252,248,221,26,255,139,66,252,252,139,106, - 4,49,232,15,136,244,249,248,2,184,237,252,233,244,78,248,3,129,252,245,0, - 0,0,128,137,106,4,252,233,244,2,248,4,255,15,87,228,252,233,244,1,255,217, - 252,238,217,201,252,233,244,1,255,248,115,129,252,248,239,15,130,244,63,129, - 122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244,63,221,66,8,221, - 2,248,1,217,252,248,223,224,158,15,138,244,1,221,217,252,233,244,73,255,248, - 116,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,129,122, - 253,12,239,15,131,244,63,252,242,15,16,2,252,242,15,16,74,8,232,244,117,252, - 233,244,72,255,248,116,129,252,248,239,15,130,244,63,129,122,253,4,239,15, - 131,244,63,129,122,253,12,239,15,131,244,63,221,2,221,66,8,232,244,117,252, - 233,244,73,255,248,118,185,2,0,0,0,129,122,253,4,239,255,15,133,244,250,139, - 42,248,1,57,193,15,131,244,71,129,124,253,202,252,252,239,15,133,244,249, - 59,108,202,252,248,15,79,108,202,252,248,131,193,1,252,233,244,1,248,3,15, - 135,244,63,255,252,233,244,252,248,4,15,135,244,63,255,252,242,15,16,2,248, - 5,57,193,15,131,244,72,129,124,253,202,252,252,239,255,15,130,244,252,15, - 135,244,63,252,242,15,42,76,202,252,248,252,233,244,253,255,248,6,252,242, - 15,16,76,202,252,248,248,7,252,242,15,93,193,131,193,1,252,233,244,5,255, - 248,119,185,2,0,0,0,129,122,253,4,239,255,15,133,244,250,139,42,248,1,57, - 193,15,131,244,71,129,124,253,202,252,252,239,15,133,244,249,59,108,202,252, - 248,15,76,108,202,252,248,131,193,1,252,233,244,1,248,3,15,135,244,63,255, - 248,6,252,242,15,16,76,202,252,248,248,7,252,242,15,95,193,131,193,1,252, - 233,244,5,255,248,9,221,216,252,233,244,63,255,248,120,129,252,248,239,15, - 130,244,63,129,122,253,4,239,15,133,244,63,139,42,255,139,173,233,252,233, - 244,71,255,252,242,15,42,133,233,252,233,244,72,255,219,133,233,252,233,244, - 73,255,248,121,129,252,248,239,15,133,244,63,129,122,253,4,239,15,133,244, - 63,139,42,139,114,252,252,131,189,233,1,15,130,244,81,15,182,173,233,255, - 252,242,15,42,197,252,233,244,72,255,137,108,36,80,219,68,36,80,252,233,244, - 73,255,248,122,139,171,233,59,171,233,15,130,244,247,232,244,75,248,1,129, - 252,248,239,15,133,244,63,129,122,253,4,239,255,15,133,244,63,139,42,129, - 252,253,252,255,0,0,0,15,135,244,63,137,108,36,84,255,15,131,244,63,252,242, - 15,44,42,129,252,253,252,255,0,0,0,15,135,244,63,137,108,36,84,255,15,131, - 244,63,221,2,219,92,36,84,129,124,36,84,252,255,0,0,0,15,135,244,63,255,199, - 68,36,32,1,0,0,0,72,141,68,36,84,248,123,139,108,36,96,137,149,233,68,139, - 68,36,32,72,137,194,137,252,233,137,116,36,100,232,251,1,19,139,149,233,139, - 114,252,252,199,66,252,252,237,137,66,252,248,252,233,244,66,248,124,139, - 171,233,59,171,233,15,130,244,247,232,244,75,248,1,199,68,36,84,252,255,252, - 255,252,255,252,255,129,252,248,239,15,130,244,63,15,134,244,247,129,122, - 253,20,239,255,15,133,244,63,139,106,16,137,108,36,84,255,15,131,244,63,252, - 242,15,44,106,16,137,108,36,84,255,15,131,244,63,221,66,16,219,92,36,84,255, - 248,1,129,122,253,4,239,15,133,244,63,129,122,253,12,239,255,139,42,137,108, - 36,32,139,173,233,255,139,74,8,255,252,242,15,44,74,8,255,139,68,36,84,57, - 197,15,130,244,251,248,2,133,201,15,142,244,253,248,3,139,108,36,32,41,200, - 15,140,244,125,141,172,253,13,233,131,192,1,248,4,137,68,36,32,137,232,252, - 233,244,123,248,5,15,140,244,252,141,68,40,1,252,233,244,2,248,6,137,232, - 252,233,244,2,248,7,255,15,132,244,254,1,252,233,131,193,1,15,143,244,3,248, - 8,185,1,0,0,0,252,233,244,3,248,125,49,192,252,233,244,4,248,126,129,252, - 248,239,15,130,244,63,139,171,233,59,171,233,15,130,244,247,232,244,75,248, - 1,255,129,122,253,4,239,15,133,244,63,129,122,253,12,239,139,42,255,15,133, - 244,63,139,66,8,255,15,131,244,63,252,242,15,44,66,8,255,15,131,244,63,221, - 66,8,219,92,36,84,139,68,36,84,255,133,192,15,142,244,125,131,189,233,1,15, - 130,244,125,15,133,244,127,57,131,233,15,130,244,127,15,182,141,233,139,171, - 233,137,68,36,32,248,1,136,77,0,131,197,1,131,232,1,15,133,244,1,139,131, - 233,252,233,244,123,248,128,129,252,248,239,255,15,130,244,63,139,171,233, - 59,171,233,15,130,244,247,232,244,75,248,1,129,122,253,4,239,15,133,244,63, - 139,42,139,133,233,133,192,15,132,244,125,57,131,233,15,130,244,129,129,197, - 239,137,116,36,84,137,68,36,32,139,179,233,248,1,255,15,182,77,0,131,197, - 1,131,232,1,136,12,6,15,133,244,1,137,252,240,139,116,36,84,252,233,244,123, - 248,130,129,252,248,239,15,130,244,63,139,171,233,59,171,233,15,130,244,247, - 232,244,75,248,1,129,122,253,4,239,15,133,244,63,139,42,139,133,233,57,131, - 233,255,15,130,244,129,129,197,239,137,116,36,84,137,68,36,32,139,179,233, - 252,233,244,249,248,1,15,182,76,5,0,131,252,249,65,15,130,244,248,131,252, - 249,90,15,135,244,248,131,252,241,32,248,2,136,12,6,248,3,131,232,1,15,137, - 244,1,137,252,240,139,116,36,84,252,233,244,123,248,131,129,252,248,239,15, - 130,244,63,255,139,171,233,59,171,233,15,130,244,247,232,244,75,248,1,129, - 122,253,4,239,15,133,244,63,139,42,139,133,233,57,131,233,15,130,244,129, - 129,197,239,137,116,36,84,137,68,36,32,139,179,233,252,233,244,249,248,1, - 15,182,76,5,0,131,252,249,97,15,130,244,248,255,131,252,249,122,15,135,244, - 248,131,252,241,32,248,2,136,12,6,248,3,131,232,1,15,137,244,1,137,252,240, - 139,116,36,84,252,233,244,123,248,132,129,252,248,239,15,130,244,63,129,122, - 253,4,239,15,133,244,63,137,213,139,10,232,251,1,20,137,252,234,255,137,197, - 252,233,244,71,255,252,242,15,42,192,252,233,244,72,255,248,133,129,252,248, - 239,15,130,244,63,129,122,253,4,239,255,15,133,244,247,139,42,252,233,244, - 89,248,1,15,135,244,63,255,252,242,15,16,2,72,189,237,237,102,72,15,110,205, - 252,242,15,88,193,102,15,126,197,255,252,233,244,89,255,248,134,129,252,248, - 239,15,130,244,63,255,72,189,237,237,102,72,15,110,205,255,199,68,36,80,0, - 0,192,89,255,15,133,244,247,139,42,252,233,244,248,248,1,15,135,244,63,255, - 252,242,15,16,2,252,242,15,88,193,102,15,126,197,255,248,2,137,68,36,84,141, - 68,194,252,240,248,1,57,208,15,134,244,89,129,120,253,4,239,255,15,133,244, - 248,35,40,131,232,8,252,233,244,1,248,2,15,135,244,135,255,15,131,244,135, - 255,252,242,15,16,0,252,242,15,88,193,102,15,126,193,33,205,255,131,232,8, - 252,233,244,1,248,136,129,252,248,239,15,130,244,63,255,15,133,244,248,11, - 40,131,232,8,252,233,244,1,248,2,15,135,244,135,255,252,242,15,16,0,252,242, - 15,88,193,102,15,126,193,9,205,255,131,232,8,252,233,244,1,248,137,129,252, - 248,239,15,130,244,63,255,15,133,244,248,51,40,131,232,8,252,233,244,1,248, - 2,15,135,244,135,255,252,242,15,16,0,252,242,15,88,193,102,15,126,193,49, - 205,255,131,232,8,252,233,244,1,248,138,129,252,248,239,15,130,244,63,129, - 122,253,4,239,255,248,2,15,205,252,233,244,89,248,139,129,252,248,239,15, - 130,244,63,129,122,253,4,239,255,248,2,252,247,213,255,248,89,252,242,15, - 42,197,252,233,244,72,255,248,135,139,68,36,84,252,233,244,63,255,248,140, - 129,252,248,239,15,130,244,63,129,122,253,4,239,255,248,2,129,122,253,12, - 239,15,133,244,63,139,74,8,255,248,140,129,252,248,239,15,130,244,63,129, - 122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244,63,252,242,15,16, - 2,252,242,15,16,74,8,72,189,237,237,102,72,15,110,213,252,242,15,88,194,252, - 242,15,88,202,102,15,126,197,102,15,126,201,255,211,229,252,233,244,89,255, - 248,141,129,252,248,239,15,130,244,63,129,122,253,4,239,255,248,141,129,252, - 248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239, - 15,131,244,63,252,242,15,16,2,252,242,15,16,74,8,72,189,237,237,102,72,15, - 110,213,252,242,15,88,194,252,242,15,88,202,102,15,126,197,102,15,126,201, - 255,211,252,237,252,233,244,89,255,248,142,129,252,248,239,15,130,244,63, - 129,122,253,4,239,255,248,142,129,252,248,239,15,130,244,63,129,122,253,4, - 239,15,131,244,63,129,122,253,12,239,15,131,244,63,252,242,15,16,2,252,242, - 15,16,74,8,72,189,237,237,102,72,15,110,213,252,242,15,88,194,252,242,15, - 88,202,102,15,126,197,102,15,126,201,255,211,252,253,252,233,244,89,255,248, - 143,129,252,248,239,15,130,244,63,129,122,253,4,239,255,248,143,129,252,248, - 239,15,130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131, - 244,63,252,242,15,16,2,252,242,15,16,74,8,72,189,237,237,102,72,15,110,213, - 252,242,15,88,194,252,242,15,88,202,102,15,126,197,102,15,126,201,255,211, - 197,252,233,244,89,255,248,144,129,252,248,239,15,130,244,63,129,122,253, - 4,239,255,248,144,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131, - 244,63,129,122,253,12,239,15,131,244,63,252,242,15,16,2,252,242,15,16,74, - 8,72,189,237,237,102,72,15,110,213,252,242,15,88,194,252,242,15,88,202,102, - 15,126,197,102,15,126,201,255,211,205,252,233,244,89,248,127,184,237,252, - 233,244,63,248,129,184,237,248,63,139,108,36,96,139,114,252,252,137,116,36, - 100,137,149,233,141,68,194,252,248,141,136,233,137,133,233,139,66,252,248, - 59,141,233,15,135,244,251,137,252,233,252,255,144,233,139,149,233,133,192, - 15,143,244,78,248,1,255,139,141,233,41,209,193,252,233,3,133,192,141,65,1, - 139,106,252,248,15,133,244,33,139,181,233,139,14,15,182,252,233,15,182,205, - 131,198,4,252,255,36,252,235,248,33,137,209,252,247,198,237,15,133,244,249, - 15,182,110,252,253,72,252,247,213,141,20,252,234,252,233,244,28,248,3,137, - 252,245,131,229,252,248,41,252,234,252,233,244,28,248,5,186,237,137,252,233, - 232,251,1,0,139,149,233,49,192,252,233,244,1,248,75,93,72,137,108,36,32,139, - 108,36,96,137,116,36,100,137,149,233,255,141,68,194,252,248,137,252,233,137, - 133,233,232,251,1,21,139,149,233,139,133,233,41,208,193,232,3,131,192,1,72, - 139,108,36,32,85,195,248,145,255,15,182,131,233,168,235,15,133,244,251,168, - 235,15,133,244,247,168,235,15,132,244,247,252,255,139,233,252,233,244,247, - 255,248,146,15,182,131,233,168,235,15,133,244,251,252,233,244,247,248,147, - 15,182,131,233,168,235,15,133,244,251,168,235,15,132,244,251,252,255,139, - 233,15,132,244,247,168,235,15,132,244,251,248,1,255,139,108,36,96,137,149, - 233,137,252,242,137,252,233,232,251,1,22,248,3,139,149,233,248,4,15,182,78, - 252,253,248,5,15,182,110,252,252,15,183,70,252,254,252,255,164,253,252,235, - 233,248,148,131,198,4,139,77,232,137,76,36,84,252,233,244,4,248,149,255,139, - 106,252,248,139,173,233,15,182,133,233,141,4,194,139,108,36,96,137,149,233, - 137,133,233,137,252,242,141,139,233,72,137,171,233,137,116,36,100,232,251, - 1,23,252,233,244,3,255,248,150,137,116,36,100,255,248,151,255,137,116,36, - 100,131,206,1,248,1,255,141,68,194,252,248,139,108,36,96,137,149,233,137, - 133,233,137,252,242,137,252,233,232,251,1,24,199,68,36,100,0,0,0,0,255,131, - 230,252,254,255,139,149,233,72,137,193,139,133,233,41,208,72,137,205,15,182, - 78,252,253,193,232,3,131,192,1,252,255,229,248,152,255,65,85,65,84,65,83, - 65,82,65,81,65,80,87,86,85,72,141,108,36,88,85,83,82,81,80,15,182,69,252, - 248,138,101,252,240,76,137,125,252,248,76,137,117,252,240,139,93,0,139,139, - 233,199,131,233,237,137,131,233,137,139,233,72,129,252,236,239,72,131,197, - 128,252,242,68,15,17,125,252,248,252,242,68,15,17,117,252,240,252,242,68, - 15,17,109,232,252,242,68,15,17,101,224,252,242,68,15,17,93,216,252,242,68, - 15,17,85,208,252,242,68,15,17,77,200,252,242,68,15,17,69,192,252,242,15,17, - 125,184,252,242,15,17,117,176,252,242,15,17,109,168,252,242,15,17,101,160, - 252,242,15,17,93,152,252,242,15,17,85,144,252,242,15,17,77,136,252,242,15, - 17,69,128,139,171,233,139,147,233,72,137,171,233,199,131,233,0,0,0,0,137, - 149,233,72,141,148,253,36,233,141,139,233,232,251,1,25,72,139,141,233,72, - 129,225,239,137,169,233,139,149,233,139,177,233,252,233,244,247,255,248,153, - 255,72,141,140,253,36,233,248,1,102,68,15,111,185,233,102,68,15,111,177,233, - 102,68,15,111,169,233,102,68,15,111,161,233,102,68,15,111,153,233,102,68, - 15,111,145,233,102,68,15,111,137,233,102,68,15,111,129,233,102,15,111,185, - 233,72,137,204,102,15,111,49,76,139,124,36,16,76,139,116,36,24,76,139,108, - 36,32,76,139,100,36,80,133,192,15,136,244,249,137,68,36,84,139,122,252,248, - 139,191,233,139,191,233,199,131,233,0,0,0,0,199,131,233,237,139,6,15,182, - 204,15,182,232,131,198,4,193,232,16,129,252,253,239,15,130,244,248,255,139, - 68,36,84,248,2,252,255,36,252,235,248,3,252,247,216,137,252,233,137,194,232, - 251,1,26,255,248,91,255,217,124,36,4,137,68,36,8,102,184,0,4,102,11,68,36, - 4,102,37,252,255,252,247,102,137,68,36,6,217,108,36,6,217,252,252,217,108, - 36,4,139,68,36,8,195,255,248,154,72,184,237,237,102,72,15,110,208,72,184, - 237,237,102,72,15,110,216,15,40,200,102,15,84,202,102,15,46,217,15,134,244, - 247,102,15,85,208,252,242,15,88,203,252,242,15,92,203,102,15,86,202,72,184, - 237,237,102,72,15,110,208,252,242,15,194,193,1,102,15,84,194,252,242,15,92, - 200,15,40,193,248,1,195,248,93,255,217,124,36,4,137,68,36,8,102,184,0,8,102, - 11,68,36,4,102,37,252,255,252,251,102,137,68,36,6,217,108,36,6,217,252,252, - 217,108,36,4,139,68,36,8,195,255,248,155,72,184,237,237,102,72,15,110,208, - 72,184,237,237,102,72,15,110,216,15,40,200,102,15,84,202,102,15,46,217,15, - 134,244,247,102,15,85,208,252,242,15,88,203,252,242,15,92,203,102,15,86,202, - 72,184,237,237,102,72,15,110,208,252,242,15,194,193,6,102,15,84,194,252,242, - 15,92,200,15,40,193,248,1,195,248,114,255,217,124,36,4,137,68,36,8,102,184, - 0,12,102,11,68,36,4,102,137,68,36,6,217,108,36,6,217,252,252,217,108,36,4, - 139,68,36,8,195,255,248,156,72,184,237,237,102,72,15,110,208,72,184,237,237, - 102,72,15,110,216,15,40,200,102,15,84,202,102,15,46,217,15,134,244,247,102, - 15,85,208,15,40,193,252,242,15,88,203,252,242,15,92,203,72,184,237,237,102, - 72,15,110,216,252,242,15,194,193,1,102,15,84,195,252,242,15,92,200,102,15, - 86,202,15,40,193,248,1,195,248,157,255,15,40,232,252,242,15,94,193,72,184, - 237,237,102,72,15,110,208,72,184,237,237,102,72,15,110,216,15,40,224,102, - 15,84,226,102,15,46,220,15,134,244,247,102,15,85,208,252,242,15,88,227,252, - 242,15,92,227,102,15,86,226,72,184,237,237,102,72,15,110,208,252,242,15,194, - 196,1,102,15,84,194,252,242,15,92,224,15,40,197,252,242,15,89,204,252,242, - 15,92,193,195,248,1,252,242,15,89,200,15,40,197,252,242,15,92,193,195,255, - 217,193,216,252,241,217,124,36,4,102,184,0,4,102,11,68,36,4,102,37,252,255, - 252,247,102,137,68,36,6,217,108,36,6,217,252,252,217,108,36,4,222,201,222, - 252,233,195,255,248,98,217,252,234,222,201,248,158,217,84,36,8,129,124,36, - 8,0,0,128,127,15,132,244,247,129,124,36,8,0,0,128,252,255,15,132,244,248, - 248,159,217,192,217,252,252,220,252,233,217,201,217,252,240,217,232,222,193, - 217,252,253,221,217,248,1,195,248,2,221,216,217,252,238,195,255,248,117,255, - 248,160,252,242,15,45,193,252,242,15,42,208,102,15,46,202,15,133,244,254, - 15,138,244,255,248,161,131,252,248,1,15,142,244,252,248,1,169,1,0,0,0,15, - 133,244,248,252,242,15,89,192,209,232,252,233,244,1,248,2,209,232,15,132, - 244,251,15,40,200,248,3,252,242,15,89,192,209,232,15,132,244,250,15,131,244, - 3,255,252,242,15,89,200,252,233,244,3,248,4,252,242,15,89,193,248,5,195,248, - 6,15,132,244,5,15,130,244,253,252,247,216,232,244,1,72,184,237,237,102,72, - 15,110,200,252,242,15,94,200,15,40,193,195,248,7,72,184,237,237,102,72,15, - 110,192,195,248,8,102,72,15,126,200,72,209,224,72,193,192,12,72,61,252,254, - 15,0,0,15,132,244,248,102,72,15,126,192,72,209,224,15,132,244,250,255,72, - 193,192,12,72,61,252,254,15,0,0,15,132,244,251,252,242,15,17,76,36,16,252, - 242,15,17,68,36,8,221,68,36,16,221,68,36,8,217,252,241,217,192,217,252,252, - 220,252,233,217,201,217,252,240,217,232,222,193,217,252,253,221,217,221,92, - 36,8,252,242,15,16,68,36,8,195,248,9,72,184,237,237,102,72,15,110,208,102, - 15,46,194,15,132,244,247,15,40,193,248,1,195,248,2,72,184,237,237,102,72, - 15,110,208,102,15,84,194,72,184,237,237,102,72,15,110,208,102,15,46,194,15, - 132,244,1,102,15,80,193,15,87,192,136,196,15,146,208,48,224,15,133,244,1, - 248,3,72,184,237,237,255,102,72,15,110,192,195,248,4,102,15,80,193,133,192, - 15,133,244,3,15,87,192,195,248,5,102,15,80,193,133,192,15,132,244,3,15,87, - 192,195,248,162,255,131,252,250,1,15,130,244,91,15,132,244,93,131,252,250, - 3,15,130,244,114,15,135,244,248,252,242,15,81,192,195,248,2,252,242,15,17, - 68,36,8,221,68,36,8,131,252,250,5,15,135,244,248,88,15,132,244,247,232,244, - 98,80,252,233,244,253,248,1,232,244,158,255,80,252,233,244,253,248,2,131, - 252,250,7,15,132,244,247,15,135,244,248,217,252,237,217,201,217,252,241,252, - 233,244,253,248,1,217,232,217,201,217,252,241,252,233,244,253,248,2,131,252, - 250,9,15,132,244,247,15,135,244,248,217,252,236,217,201,217,252,241,252,233, - 244,253,248,1,255,217,252,254,252,233,244,253,248,2,131,252,250,11,15,132, - 244,247,15,135,244,255,217,252,255,252,233,244,253,248,1,217,252,242,221, - 216,248,7,221,92,36,8,252,242,15,16,68,36,8,195,255,139,84,36,12,221,68,36, - 4,131,252,250,1,15,130,244,91,15,132,244,93,131,252,250,3,15,130,244,114, - 15,135,244,248,217,252,250,195,248,2,131,252,250,5,15,130,244,98,15,132,244, - 158,131,252,250,7,15,132,244,247,15,135,244,248,217,252,237,217,201,217,252, - 241,195,248,1,217,232,217,201,217,252,241,195,248,2,131,252,250,9,15,132, - 244,247,255,15,135,244,248,217,252,236,217,201,217,252,241,195,248,1,217, - 252,254,195,248,2,131,252,250,11,15,132,244,247,15,135,244,255,217,252,255, - 195,248,1,217,252,242,221,216,195,255,248,9,204,255,248,163,255,65,131,252, - 248,1,15,132,244,247,15,135,244,248,252,242,15,88,193,195,248,1,252,242,15, - 92,193,195,248,2,65,131,252,248,3,15,132,244,247,15,135,244,248,252,242,15, - 89,193,195,248,1,252,242,15,94,193,195,248,2,65,131,252,248,5,15,130,244, - 157,15,132,244,117,65,131,252,248,7,15,132,244,247,15,135,244,248,72,184, - 237,237,255,102,72,15,110,200,15,87,193,195,248,1,72,184,237,237,102,72,15, - 110,200,15,84,193,195,248,2,65,131,252,248,9,15,135,244,248,252,242,15,17, - 68,36,8,252,242,15,17,76,36,16,221,68,36,8,221,68,36,16,15,132,244,247,217, - 252,243,248,7,221,92,36,8,252,242,15,16,68,36,8,195,248,1,217,201,217,252, - 253,221,217,252,233,244,7,248,2,65,131,252,248,11,15,132,244,247,15,135,244, - 255,252,242,15,93,193,195,248,1,252,242,15,95,193,195,248,9,204,255,139,68, - 36,20,221,68,36,4,221,68,36,12,131,252,248,1,15,132,244,247,15,135,244,248, - 222,193,195,248,1,222,252,233,195,248,2,131,252,248,3,15,132,244,247,15,135, - 244,248,222,201,195,248,1,222,252,249,195,248,2,131,252,248,5,15,130,244, - 157,15,132,244,117,131,252,248,7,15,132,244,247,15,135,244,248,255,221,216, - 217,224,195,248,1,221,216,217,225,195,248,2,131,252,248,9,15,132,244,247, - 15,135,244,248,217,252,243,195,248,1,217,201,217,252,253,221,217,195,248, - 2,131,252,248,11,15,132,244,247,15,135,244,255,255,219,252,233,219,209,221, - 217,195,248,1,219,252,233,218,209,221,217,195,255,221,225,223,224,252,246, - 196,1,15,132,244,248,217,201,248,2,221,216,195,248,1,221,225,223,224,252, - 246,196,1,15,133,244,248,217,201,248,2,221,216,195,255,248,164,137,200,86, - 72,137,214,83,15,162,137,6,137,94,4,137,78,8,137,86,12,91,94,195,248,165, - 255,204,248,166,255,87,86,83,72,131,252,236,40,141,157,233,139,181,233,15, - 183,192,137,134,233,72,137,142,233,72,137,150,233,76,137,134,233,76,137,142, - 233,252,242,15,17,134,233,252,242,15,17,142,233,252,242,15,17,150,233,252, - 242,15,17,158,233,72,141,132,253,36,233,72,137,134,233,72,137,226,137,116, - 36,100,137,252,241,232,251,1,27,199,131,233,237,139,144,233,139,128,233,41, - 208,139,106,252,248,193,232,3,131,192,1,139,181,233,139,14,15,182,252,233, - 15,182,205,131,198,4,252,255,36,252,235,255,248,32,255,139,76,36,96,139,179, - 233,72,137,142,233,137,145,233,137,169,233,137,252,241,137,194,232,251,1, - 28,72,139,134,233,252,242,15,16,134,233,252,233,244,16,255,248,167,255,85, - 72,137,229,83,72,137,203,139,131,233,72,41,196,255,15,182,139,233,131,252, - 233,1,15,136,244,248,248,1,72,139,132,253,203,233,72,137,132,253,204,233, - 131,252,233,1,15,137,244,1,248,2,15,182,131,233,72,139,139,233,72,139,147, - 233,76,139,131,233,76,139,139,233,133,192,15,132,244,251,15,40,131,233,15, - 40,139,233,15,40,147,233,15,40,155,233,248,5,255,252,255,147,233,72,137,131, - 233,15,41,131,233,255,72,139,93,252,248,201,195,255,129,124,253,202,4,239, - 15,133,244,253,129,124,253,194,4,239,15,133,244,254,139,44,202,131,198,4, - 59,44,194,255,15,141,244,255,255,15,140,244,255,255,15,143,244,255,255,15, - 142,244,255,255,248,6,15,183,70,252,254,141,180,253,134,233,248,9,139,6,15, - 182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235,248,7,15,135,244, - 44,129,124,253,194,4,239,15,130,244,247,15,133,244,44,255,252,242,15,42,4, - 194,252,233,244,248,255,221,4,202,219,4,194,252,233,244,249,255,248,8,15, - 135,244,44,255,252,242,15,42,12,202,252,242,15,16,4,194,131,198,4,102,15, - 46,193,255,15,134,244,9,255,15,135,244,9,255,15,130,244,9,255,15,131,244, - 9,255,252,233,244,6,255,219,4,202,252,233,244,248,255,129,124,253,202,4,239, - 15,131,244,44,129,124,253,194,4,239,15,131,244,44,255,248,1,252,242,15,16, - 4,194,248,2,131,198,4,102,15,46,4,202,248,3,255,248,1,221,4,202,248,2,221, - 4,194,248,3,131,198,4,255,223,252,233,221,216,255,218,252,233,223,224,158, - 255,15,135,244,247,255,15,130,244,247,255,15,131,244,247,255,15,183,70,252, - 254,141,180,253,134,233,248,1,139,6,15,182,204,15,182,232,131,198,4,193,232, - 16,252,255,36,252,235,255,139,108,194,4,131,198,4,255,129,252,253,239,15, - 133,244,253,129,124,253,202,4,239,15,133,244,254,139,44,194,59,44,202,255, - 15,133,244,255,255,15,132,244,255,255,15,183,70,252,254,141,180,253,134,233, - 248,9,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235, - 248,7,15,135,244,251,129,124,253,202,4,239,15,130,244,247,15,133,244,251, - 255,252,242,15,42,4,202,255,219,4,202,255,252,233,244,248,248,8,15,135,244, - 251,255,252,242,15,42,4,194,102,15,46,4,202,255,219,4,194,221,4,202,255,252, - 233,244,250,255,129,252,253,239,15,131,244,251,129,124,253,202,4,239,15,131, - 244,251,255,248,1,252,242,15,16,4,202,248,2,102,15,46,4,194,248,4,255,248, - 1,221,4,202,248,2,221,4,194,248,4,255,15,138,244,248,15,133,244,248,255,15, - 138,244,248,15,132,244,247,255,248,1,15,183,70,252,254,141,180,253,134,233, - 248,2,255,248,2,15,183,70,252,254,141,180,253,134,233,248,1,255,252,233,244, - 9,255,129,252,253,239,15,132,244,49,129,124,253,202,4,239,15,132,244,49,255, - 57,108,202,4,15,133,244,2,129,252,253,239,15,131,244,1,139,12,202,139,4,194, - 57,193,15,132,244,1,129,252,253,239,15,135,244,2,129,252,253,239,15,130,244, - 2,139,169,233,133,252,237,15,132,244,2,252,246,133,233,235,15,133,244,2,255, - 49,252,237,255,189,1,0,0,0,255,252,233,244,48,255,248,3,129,252,253,239,255, - 15,133,244,9,255,252,233,244,49,255,72,252,247,208,139,108,202,4,131,198, - 4,129,252,253,239,15,133,244,249,139,12,202,59,12,135,255,139,108,202,4,131, - 198,4,255,129,252,253,239,15,133,244,253,129,124,253,199,4,239,15,133,244, - 254,139,44,199,59,44,202,255,15,183,70,252,254,141,180,253,134,233,248,9, - 139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235,248,7, - 15,135,244,249,129,124,253,199,4,239,15,130,244,247,255,252,242,15,42,4,199, - 255,219,4,199,255,252,233,244,248,248,8,255,252,242,15,42,4,202,102,15,46, - 4,199,255,219,4,202,221,4,199,255,129,252,253,239,15,131,244,249,255,248, - 1,252,242,15,16,4,199,248,2,102,15,46,4,202,248,4,255,248,1,221,4,199,248, - 2,221,4,202,248,4,255,72,252,247,208,139,108,202,4,131,198,4,57,197,255,15, - 133,244,249,15,183,70,252,254,141,180,253,134,233,248,2,139,6,15,182,204, - 15,182,232,131,198,4,193,232,16,252,255,36,252,235,248,3,129,252,253,239, - 15,133,244,2,252,233,244,49,255,15,132,244,248,129,252,253,239,15,132,244, - 49,15,183,70,252,254,141,180,253,134,233,248,2,139,6,15,182,204,15,182,232, - 131,198,4,193,232,16,252,255,36,252,235,255,139,108,194,4,131,198,4,129,252, - 253,239,255,137,108,202,4,139,44,194,137,44,202,255,72,139,44,194,72,137, - 44,202,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235, - 255,49,252,237,129,124,253,194,4,239,129,213,239,137,108,202,4,139,6,15,182, - 204,15,182,232,131,198,4,193,232,16,252,255,36,252,235,255,129,124,253,194, - 4,239,15,133,244,251,139,44,194,252,247,221,15,128,244,250,199,68,202,4,237, - 137,44,202,248,9,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255, - 36,252,235,248,4,199,68,202,4,0,0,224,65,199,4,202,0,0,0,0,252,233,244,9, - 248,5,15,135,244,54,255,129,124,253,194,4,239,15,131,244,54,255,252,242,15, - 16,4,194,72,184,237,237,102,72,15,110,200,15,87,193,252,242,15,17,4,202,255, - 221,4,194,217,224,221,28,202,255,129,124,253,194,4,239,15,133,244,248,139, - 4,194,255,139,128,233,248,1,199,68,202,4,237,137,4,202,255,15,87,192,252, - 242,15,42,128,233,248,1,252,242,15,17,4,202,255,219,128,233,248,1,221,28, - 202,255,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235, - 248,2,129,124,253,194,4,239,15,133,244,57,139,12,194,255,139,169,233,131, - 252,253,0,15,133,244,255,248,3,255,248,58,137,213,232,251,1,20,255,252,242, - 15,42,192,255,137,252,234,15,182,78,252,253,252,233,244,1,255,248,9,252,246, - 133,233,235,15,133,244,3,252,233,244,57,255,15,182,252,236,15,182,192,255, - 129,124,253,252,234,4,239,15,133,244,51,129,124,253,199,4,239,15,133,244, - 51,139,44,252,234,3,44,199,15,128,244,50,255,129,124,253,252,234,4,239,15, - 133,244,53,129,124,253,199,4,239,15,133,244,53,139,4,199,3,4,252,234,15,128, - 244,52,255,129,124,253,252,234,4,239,15,133,244,56,129,124,253,194,4,239, - 15,133,244,56,139,44,252,234,3,44,194,15,128,244,55,255,199,68,202,4,237, - 255,129,124,253,252,234,4,239,15,131,244,51,255,129,124,253,199,4,239,15, - 131,244,51,255,252,242,15,16,4,252,234,252,242,15,88,4,199,255,221,4,252, - 234,220,4,199,255,129,124,253,252,234,4,239,15,131,244,53,255,129,124,253, - 199,4,239,15,131,244,53,255,252,242,15,16,4,199,252,242,15,88,4,252,234,255, - 221,4,199,220,4,252,234,255,129,124,253,252,234,4,239,15,131,244,56,129,124, - 253,194,4,239,15,131,244,56,255,252,242,15,16,4,252,234,252,242,15,88,4,194, - 255,221,4,252,234,220,4,194,255,129,124,253,252,234,4,239,15,133,244,51,129, - 124,253,199,4,239,15,133,244,51,139,44,252,234,43,44,199,15,128,244,50,255, - 129,124,253,252,234,4,239,15,133,244,53,129,124,253,199,4,239,15,133,244, - 53,139,4,199,43,4,252,234,15,128,244,52,255,129,124,253,252,234,4,239,15, - 133,244,56,129,124,253,194,4,239,15,133,244,56,139,44,252,234,43,44,194,15, - 128,244,55,255,252,242,15,16,4,252,234,252,242,15,92,4,199,255,221,4,252, - 234,220,36,199,255,252,242,15,16,4,199,252,242,15,92,4,252,234,255,221,4, - 199,220,36,252,234,255,252,242,15,16,4,252,234,252,242,15,92,4,194,255,221, - 4,252,234,220,36,194,255,129,124,253,252,234,4,239,15,133,244,51,129,124, - 253,199,4,239,15,133,244,51,139,44,252,234,15,175,44,199,15,128,244,50,255, - 129,124,253,252,234,4,239,15,133,244,53,129,124,253,199,4,239,15,133,244, - 53,139,4,199,15,175,4,252,234,15,128,244,52,255,129,124,253,252,234,4,239, - 15,133,244,56,129,124,253,194,4,239,15,133,244,56,139,44,252,234,15,175,44, - 194,15,128,244,55,255,252,242,15,16,4,252,234,252,242,15,89,4,199,255,221, - 4,252,234,220,12,199,255,252,242,15,16,4,199,252,242,15,89,4,252,234,255, - 221,4,199,220,12,252,234,255,252,242,15,16,4,252,234,252,242,15,89,4,194, - 255,221,4,252,234,220,12,194,255,252,242,15,16,4,252,234,252,242,15,94,4, - 199,255,221,4,252,234,220,52,199,255,252,242,15,16,4,199,252,242,15,94,4, - 252,234,255,221,4,199,220,52,252,234,255,252,242,15,16,4,252,234,252,242, - 15,94,4,194,255,221,4,252,234,220,52,194,255,252,242,15,16,4,252,234,252, - 242,15,16,12,199,255,221,4,252,234,221,4,199,255,252,242,15,16,4,199,252, - 242,15,16,12,252,234,255,221,4,199,221,4,252,234,255,252,242,15,16,4,252, - 234,252,242,15,16,12,194,255,221,4,252,234,221,4,194,255,248,168,232,244, - 157,255,252,233,244,168,255,232,244,117,255,15,182,252,236,15,182,192,139, - 76,36,96,137,145,233,141,20,194,65,137,192,65,41,232,248,36,137,205,137,116, - 36,100,232,251,1,29,139,149,233,133,192,15,133,244,45,15,182,110,252,255, - 15,182,78,252,253,72,139,4,252,234,72,137,4,202,139,6,15,182,204,15,182,232, - 131,198,4,193,232,16,252,255,36,252,235,255,72,252,247,208,139,4,135,199, - 68,202,4,237,137,4,202,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252, - 255,36,252,235,255,15,191,192,199,68,202,4,237,137,4,202,255,15,191,192,252, - 242,15,42,192,252,242,15,17,4,202,255,223,70,252,254,221,28,202,255,252,242, - 15,16,4,199,252,242,15,17,4,202,255,221,4,199,221,28,202,255,72,252,247,208, - 137,68,202,4,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36, - 252,235,255,141,76,202,12,141,68,194,4,189,237,137,105,252,248,248,1,137, - 41,131,193,8,57,193,15,134,244,1,139,6,15,182,204,15,182,232,131,198,4,193, - 232,16,252,255,36,252,235,255,139,106,252,248,139,172,253,133,233,139,173, - 233,72,139,69,0,72,137,4,202,139,6,15,182,204,15,182,232,131,198,4,193,232, - 16,252,255,36,252,235,255,139,106,252,248,139,172,253,141,233,128,189,233, - 0,139,173,233,139,12,194,139,68,194,4,137,77,0,137,69,4,15,132,244,247,252, - 246,133,233,235,15,133,244,248,248,1,139,6,15,182,204,15,182,232,131,198, - 4,193,232,16,252,255,36,252,235,248,2,129,232,239,129,252,248,239,15,134, - 244,1,252,246,129,233,235,15,132,244,1,135,213,141,139,233,255,232,251,1, - 30,137,252,234,252,233,244,1,255,72,252,247,208,139,106,252,248,139,172,253, - 141,233,139,12,135,139,133,233,137,8,199,64,4,237,252,246,133,233,235,15, - 133,244,248,248,1,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255, - 36,252,235,248,2,252,246,129,233,235,15,132,244,1,128,189,233,0,15,132,244, - 1,137,213,137,194,141,139,233,232,251,1,30,137,252,234,252,233,244,1,255, - 139,106,252,248,255,252,242,15,16,4,199,255,139,172,253,141,233,139,141,233, - 255,252,242,15,17,1,255,221,25,255,72,252,247,208,139,106,252,248,139,172, - 253,141,233,139,141,233,137,65,4,139,6,15,182,204,15,182,232,131,198,4,193, - 232,16,252,255,36,252,235,255,141,180,253,134,233,139,108,36,96,131,189,233, - 0,15,132,244,247,137,149,233,141,20,202,137,252,233,232,251,1,31,139,149, - 233,248,1,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,252, - 235,255,72,252,247,208,139,108,36,96,137,149,233,68,139,66,252,248,139,20, - 135,137,252,233,137,116,36,100,232,251,1,32,139,149,233,15,182,78,252,253, - 137,4,202,199,68,202,4,237,139,6,15,182,204,15,182,232,131,198,4,193,232, - 16,252,255,36,252,235,255,139,108,36,96,137,149,233,139,139,233,59,139,233, - 137,116,36,100,15,131,244,251,248,1,65,137,192,37,252,255,7,0,0,65,193,232, - 11,61,252,255,7,0,0,15,132,244,249,248,2,137,252,233,137,194,232,251,1,33, - 139,149,233,15,182,78,252,253,137,4,202,199,68,202,4,237,139,6,15,182,204, - 15,182,232,131,198,4,193,232,16,252,255,36,252,235,248,3,184,1,8,0,0,252, - 233,244,2,248,5,137,252,233,232,251,1,34,15,183,70,252,254,252,233,244,1, - 255,72,252,247,208,139,108,36,96,139,139,233,137,116,36,100,59,139,233,137, - 149,233,15,131,244,249,248,2,139,20,135,137,252,233,232,251,1,35,139,149, - 233,15,182,78,252,253,137,4,202,199,68,202,4,237,139,6,15,182,204,15,182, - 232,131,198,4,193,232,16,252,255,36,252,235,248,3,137,252,233,232,251,1,34, - 15,183,70,252,254,72,252,247,208,252,233,244,2,255,72,252,247,208,139,106, - 252,248,139,173,233,139,4,135,252,233,244,169,255,72,252,247,208,139,106, - 252,248,139,173,233,139,4,135,252,233,244,170,255,15,182,252,236,15,182,192, - 129,124,253,252,234,4,239,15,133,244,39,139,44,252,234,255,129,124,253,194, - 4,239,15,133,244,251,139,4,194,255,129,124,253,194,4,239,15,131,244,251,255, - 252,242,15,16,4,194,252,242,15,45,192,252,242,15,42,200,102,15,46,193,255, - 15,133,244,39,255,59,133,233,15,131,244,39,193,224,3,3,133,233,129,120,253, - 4,239,15,132,244,248,72,139,40,72,137,44,202,248,1,139,6,15,182,204,15,182, - 232,131,198,4,193,232,16,252,255,36,252,235,248,2,131,189,233,0,15,132,244, - 249,139,141,233,252,246,129,233,235,15,132,244,39,15,182,78,252,253,248,3, - 199,68,202,4,237,252,233,244,1,248,5,255,129,124,253,194,4,239,15,133,244, - 39,139,4,194,252,233,244,169,255,15,182,252,236,15,182,192,72,252,247,208, - 139,4,135,129,124,253,252,234,4,239,15,133,244,37,139,44,252,234,248,169, - 139,141,233,35,136,233,105,201,239,3,141,233,248,1,129,185,233,239,15,133, - 244,250,57,129,233,15,133,244,250,129,121,253,4,239,15,132,244,251,15,182, - 70,252,253,72,139,41,72,137,44,194,248,2,255,139,6,15,182,204,15,182,232, - 131,198,4,193,232,16,252,255,36,252,235,248,3,15,182,70,252,253,199,68,194, - 4,237,252,233,244,2,248,4,139,137,233,133,201,15,133,244,1,248,5,139,141, - 233,133,201,15,132,244,3,252,246,129,233,235,15,133,244,3,252,233,244,37, - 255,15,182,252,236,15,182,192,129,124,253,252,234,4,239,15,133,244,38,139, - 44,252,234,59,133,233,15,131,244,38,193,224,3,3,133,233,129,120,253,4,239, - 15,132,244,248,72,139,40,72,137,44,202,248,1,139,6,15,182,204,15,182,232, - 131,198,4,193,232,16,252,255,36,252,235,248,2,131,189,233,0,15,132,244,249, - 139,141,233,252,246,129,233,235,15,132,244,38,255,15,182,78,252,253,248,3, - 199,68,202,4,237,252,233,244,1,255,15,182,252,236,15,182,192,129,124,253, - 252,234,4,239,15,133,244,42,139,44,252,234,255,15,133,244,42,255,59,133,233, - 15,131,244,42,193,224,3,3,133,233,129,120,253,4,239,15,132,244,249,248,1, - 252,246,133,233,235,15,133,244,253,248,2,72,139,44,202,72,137,40,139,6,15, - 182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235,248,3,131,189, - 233,0,15,132,244,1,139,141,233,252,246,129,233,235,255,15,132,244,42,15,182, - 78,252,253,252,233,244,1,248,5,129,124,253,194,4,239,15,133,244,42,139,4, - 194,252,233,244,170,248,7,128,165,233,235,139,139,233,137,171,233,137,141, - 233,15,182,78,252,253,252,233,244,2,255,15,182,252,236,15,182,192,72,252, - 247,208,139,4,135,129,124,253,252,234,4,239,15,133,244,40,139,44,252,234, - 248,170,139,141,233,35,136,233,105,201,239,198,133,233,0,3,141,233,248,1, - 129,185,233,239,15,133,244,251,57,129,233,15,133,244,251,129,121,253,4,239, - 15,132,244,250,248,2,255,252,246,133,233,235,15,133,244,253,248,3,15,182, - 70,252,253,72,139,44,194,72,137,41,139,6,15,182,204,15,182,232,131,198,4, - 193,232,16,252,255,36,252,235,248,4,131,189,233,0,15,132,244,2,137,76,36, - 80,139,141,233,252,246,129,233,235,15,132,244,40,139,76,36,80,252,233,244, - 2,248,5,139,137,233,133,201,15,133,244,1,255,139,141,233,133,201,15,132,244, - 252,252,246,129,233,235,15,132,244,40,248,6,137,68,36,80,199,68,36,84,237, - 137,108,36,32,139,76,36,96,137,145,233,76,141,68,36,80,137,252,234,137,205, - 137,116,36,100,232,251,1,36,139,149,233,139,108,36,32,137,193,252,233,244, - 2,248,7,128,165,233,235,139,131,233,137,171,233,137,133,233,252,233,244,3, - 255,15,182,252,236,15,182,192,129,124,253,252,234,4,239,15,133,244,41,139, - 44,252,234,59,133,233,15,131,244,41,193,224,3,3,133,233,129,120,253,4,239, - 15,132,244,249,248,1,252,246,133,233,235,15,133,244,253,248,2,72,139,12,202, - 72,137,8,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,252, - 235,248,3,131,189,233,0,15,132,244,1,255,139,141,233,252,246,129,233,235, - 15,132,244,41,15,182,78,252,253,252,233,244,1,248,7,128,165,233,235,139,139, - 233,137,171,233,137,141,233,15,182,78,252,253,252,233,244,2,255,137,124,36, - 80,139,60,199,248,1,141,12,202,139,105,252,248,252,246,133,233,235,15,133, - 244,253,248,2,139,68,36,84,131,232,1,15,132,244,250,1,252,248,59,133,233, - 15,135,244,251,41,252,248,193,231,3,3,189,233,248,3,72,139,41,131,193,8,72, - 137,47,131,199,8,131,232,1,15,133,244,3,248,4,139,124,36,80,139,6,15,182, - 204,15,182,232,131,198,4,193,232,16,252,255,36,252,235,248,5,139,76,36,96, - 137,145,233,137,252,234,65,137,192,137,205,137,116,36,100,232,251,1,37,139, - 149,233,15,182,78,252,253,252,233,244,1,248,7,255,128,165,233,235,139,131, - 233,137,171,233,137,133,233,252,233,244,2,255,3,68,36,84,255,129,124,253, - 202,4,239,139,44,202,15,133,244,59,141,84,202,8,137,114,252,252,139,181,233, - 139,14,15,182,252,233,15,182,205,131,198,4,252,255,36,252,235,255,141,76, - 202,8,137,215,139,105,252,248,129,121,253,252,252,239,15,133,244,29,248,60, - 139,114,252,252,252,247,198,237,15,133,244,253,248,1,137,106,252,248,137, - 68,36,84,131,232,1,15,132,244,249,248,2,72,139,41,131,193,8,72,137,47,131, - 199,8,131,232,1,15,133,244,2,139,106,252,248,248,3,139,68,36,84,128,189,233, - 1,15,135,244,251,248,4,139,181,233,139,14,15,182,252,233,15,182,205,131,198, - 4,252,255,36,252,235,248,5,255,252,247,198,237,15,133,244,4,15,182,78,252, - 253,72,252,247,209,141,12,202,139,121,252,248,139,191,233,139,191,233,252, - 233,244,4,248,7,129,252,238,239,252,247,198,237,15,133,244,254,41,252,242, - 137,215,139,114,252,252,252,233,244,1,248,8,129,198,239,252,233,244,1,255, - 141,76,202,8,72,139,105,232,72,139,65,252,240,72,137,41,72,137,65,8,139,105, - 224,139,65,228,137,105,252,248,137,65,252,252,129,252,248,239,184,237,15, - 133,244,29,137,202,137,114,252,252,139,181,233,139,14,15,182,252,233,15,182, - 205,131,198,4,252,255,36,252,235,255,137,124,36,80,137,92,36,84,139,108,202, - 252,240,139,68,202,252,248,139,157,233,131,198,4,139,189,233,248,1,57,216, - 15,131,244,251,129,124,253,199,4,239,15,132,244,250,255,219,68,202,252,248, - 255,72,139,44,199,72,137,108,202,8,131,192,1,255,137,68,202,252,248,248,2, - 15,183,70,252,254,141,180,253,134,233,248,3,139,92,36,84,139,124,36,80,139, - 6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235,248,4,131, - 192,1,255,137,68,202,252,248,255,252,233,244,1,248,5,41,216,248,6,59,133, - 233,15,135,244,3,105,252,248,239,3,189,233,129,191,233,239,15,132,244,253, - 141,92,24,1,72,139,175,233,72,139,135,233,72,137,44,202,72,137,68,202,8,137, - 92,202,252,248,252,233,244,2,248,7,131,192,1,252,233,244,6,255,129,124,253, - 202,252,236,239,15,133,244,251,139,108,202,232,129,124,253,202,252,244,239, - 15,133,244,251,129,124,253,202,252,252,239,15,133,244,251,128,189,233,235, - 15,133,244,251,141,180,253,134,233,199,68,202,252,248,0,0,0,0,248,1,139,6, - 15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235,248,5,198,70, - 252,252,235,141,180,253,134,233,198,6,235,252,233,244,1,255,15,182,252,236, - 15,182,192,137,124,36,80,141,188,253,194,233,141,12,202,43,122,252,252,133, - 252,237,15,132,244,251,141,108,252,233,252,248,57,215,15,131,244,248,248, - 1,72,139,71,252,248,131,199,8,72,137,1,131,193,8,57,252,233,15,131,244,249, - 57,215,15,130,244,1,248,2,199,65,4,237,131,193,8,57,252,233,15,130,244,2, - 248,3,139,124,36,80,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252, - 255,36,252,235,248,5,199,68,36,84,1,0,0,0,137,208,41,252,248,15,134,244,3, - 137,197,193,252,237,3,131,197,1,137,108,36,84,139,108,36,96,1,200,59,133, - 233,15,135,244,253,248,6,255,72,139,71,252,248,131,199,8,72,137,1,131,193, - 8,57,215,15,130,244,6,252,233,244,3,248,7,137,149,233,137,141,233,137,116, - 36,100,41,215,139,84,36,84,131,252,234,1,137,252,233,232,251,1,0,139,149, - 233,139,141,233,1,215,252,233,244,6,255,193,225,3,255,248,1,139,114,252,252, - 137,68,36,84,252,247,198,237,15,133,244,253,255,248,13,137,215,131,232,1, - 15,132,244,249,248,2,72,139,44,15,72,137,111,252,248,131,199,8,131,232,1, - 15,133,244,2,248,3,139,68,36,84,15,182,110,252,255,248,5,57,197,15,135,244, - 252,255,72,139,44,10,72,137,106,252,248,255,248,5,56,70,252,255,15,135,244, - 252,255,15,182,78,252,253,72,252,247,209,141,20,202,139,122,252,248,139,191, - 233,139,191,233,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255, - 36,252,235,248,6,255,199,71,252,252,237,131,199,8,255,199,68,194,252,244, - 237,255,131,192,1,252,233,244,5,248,7,141,174,233,252,247,197,237,15,133, - 244,14,41,252,234,255,1,252,233,255,137,252,245,209,252,237,129,229,239,102, - 129,172,253,43,233,238,15,130,244,149,255,141,12,202,255,129,121,253,4,239, - 15,133,244,255,255,129,121,253,12,239,15,133,244,61,129,121,253,20,239,15, - 133,244,61,139,41,131,121,16,0,15,140,244,251,255,129,121,253,12,239,15,133, - 244,165,129,121,253,20,239,15,133,244,165,255,139,105,16,133,252,237,15,136, - 244,251,3,41,15,128,244,247,137,41,255,59,105,8,199,65,28,237,137,105,24, - 255,15,142,244,253,248,1,248,6,141,180,253,134,233,255,141,180,253,134,233, - 15,183,70,252,254,15,142,245,248,1,248,6,255,15,143,244,253,248,6,141,180, - 253,134,233,248,1,255,248,7,139,6,15,182,204,15,182,232,131,198,4,193,232, - 16,252,255,36,252,235,248,5,255,3,41,15,128,244,1,137,41,255,15,141,244,7, - 255,141,180,253,134,233,15,183,70,252,254,15,141,245,255,15,140,244,7,255, - 252,233,244,6,248,9,255,129,121,253,4,239,255,15,131,244,61,129,121,253,12, - 239,15,131,244,61,255,129,121,253,12,239,15,131,244,165,129,121,253,20,239, - 15,131,244,165,255,139,105,20,255,129,252,253,239,15,131,244,61,255,252,242, - 15,16,1,252,242,15,16,73,8,255,252,242,15,88,65,16,252,242,15,17,1,133,252, - 237,15,136,244,249,255,15,140,244,249,255,102,15,46,200,248,1,252,242,15, - 17,65,24,255,221,65,8,221,1,255,220,65,16,221,17,221,81,24,133,252,237,15, - 136,244,247,255,221,81,24,15,140,244,247,255,217,201,248,1,255,15,183,70, - 252,254,255,15,131,244,7,255,15,131,244,248,141,180,253,134,233,255,141,180, - 253,134,233,15,183,70,252,254,15,131,245,255,15,130,244,7,255,15,130,244, - 248,141,180,253,134,233,255,248,3,102,15,46,193,252,233,244,1,255,141,12, - 202,139,105,4,129,252,253,239,15,132,244,247,255,137,105,252,252,139,41,137, - 105,252,248,252,233,245,255,141,180,253,134,233,139,1,137,105,252,252,137, - 65,252,248,255,139,139,233,139,4,129,72,139,128,233,139,108,36,96,137,147, - 233,137,171,233,76,137,100,36,80,76,137,108,36,32,76,137,116,36,24,76,137, - 124,36,16,72,137,225,72,129,252,236,239,102,15,127,49,102,15,127,185,233, - 102,68,15,127,129,233,102,68,15,127,137,233,102,68,15,127,145,233,102,68, - 15,127,153,233,102,68,15,127,161,233,102,68,15,127,169,233,102,68,15,127, - 177,233,102,68,15,127,185,233,252,255,224,255,141,180,253,134,233,139,6,15, - 182,204,15,182,232,131,198,4,193,232,16,252,255,36,252,235,255,137,252,245, - 209,252,237,129,229,239,102,129,172,253,43,233,238,15,130,244,151,255,139, - 190,233,139,108,36,96,141,12,202,59,141,233,15,135,244,24,15,182,142,233, - 57,200,15,134,244,249,248,2,255,15,183,70,252,254,252,233,245,255,248,3,199, - 68,194,252,252,237,131,192,1,57,200,15,134,244,3,252,233,244,2,255,141,44, - 197,237,141,4,194,139,122,252,248,137,104,252,252,137,120,252,248,139,108, - 36,96,141,12,200,59,141,233,15,135,244,23,137,209,137,194,15,182,174,233, - 133,252,237,15,132,244,248,248,1,131,193,8,57,209,15,131,244,249,139,121, - 252,248,137,56,139,121,252,252,137,120,4,131,192,8,199,65,252,252,237,131, - 252,237,1,15,133,244,1,248,2,255,139,190,233,139,6,15,182,204,15,182,232, - 131,198,4,193,232,16,252,255,36,252,235,255,248,3,199,64,4,237,131,192,8, - 131,252,237,1,15,133,244,3,252,233,244,2,255,139,106,252,248,72,139,189,233, - 139,108,36,96,141,68,194,252,248,137,149,233,141,136,233,59,141,233,137,133, - 233,255,72,137,252,250,137,252,233,255,15,135,244,22,199,131,233,237,255, - 252,255,215,255,252,255,147,233,255,199,131,233,237,139,149,233,141,12,194, - 252,247,217,3,141,233,139,114,252,252,252,233,244,12,255,254,0 -}; - -enum { - GLOB_vm_returnp, - GLOB_cont_dispatch, - GLOB_vm_returnc, - GLOB_BC_RET_Z, - GLOB_vm_return, - GLOB_vm_leave_cp, - GLOB_vm_leave_unw, - GLOB_vm_unwind_c, - GLOB_vm_unwind_c_eh, - GLOB_vm_unwind_rethrow, - GLOB_vm_unwind_ff, - GLOB_vm_unwind_ff_eh, - GLOB_vm_growstack_c, - GLOB_vm_growstack_v, - GLOB_vm_growstack_f, - GLOB_vm_resume, - GLOB_vm_pcall, - GLOB_vm_call, - GLOB_vm_call_dispatch, - GLOB_vmeta_call, - GLOB_vm_call_dispatch_f, - GLOB_vm_cpcall, - GLOB_cont_ffi_callback, - GLOB_vm_call_tail, - GLOB_cont_cat, - GLOB_cont_ra, - GLOB_BC_CAT_Z, - GLOB_vmeta_tgets, - GLOB_vmeta_tgetb, - GLOB_vmeta_tgetv, - GLOB_vmeta_tsets, - GLOB_vmeta_tsetb, - GLOB_vmeta_tsetv, - GLOB_cont_nop, - GLOB_vmeta_comp, - GLOB_vmeta_binop, - GLOB_cont_condt, - GLOB_cont_condf, - GLOB_vmeta_equal, - GLOB_vmeta_equal_cd, - GLOB_vmeta_arith_vno, - GLOB_vmeta_arith_vn, - GLOB_vmeta_arith_nvo, - GLOB_vmeta_arith_nv, - GLOB_vmeta_unm, - GLOB_vmeta_arith_vvo, - GLOB_vmeta_arith_vv, - GLOB_vmeta_len, - GLOB_BC_LEN_Z, - GLOB_vmeta_call_ra, - GLOB_BC_CALLT_Z, - GLOB_vmeta_for, - GLOB_ff_assert, - GLOB_fff_fallback, - GLOB_fff_res_, - GLOB_ff_type, - GLOB_fff_res1, - GLOB_ff_getmetatable, - GLOB_ff_setmetatable, - GLOB_ff_rawget, - GLOB_ff_tonumber, - GLOB_fff_resi, - GLOB_fff_resxmm0, - GLOB_fff_resn, - GLOB_ff_tostring, - GLOB_fff_gcstep, - GLOB_ff_next, - GLOB_fff_res2, - GLOB_fff_res, - GLOB_ff_pairs, - GLOB_ff_ipairs_aux, - GLOB_fff_res0, - GLOB_ff_ipairs, - GLOB_ff_pcall, - GLOB_ff_xpcall, - GLOB_ff_coroutine_resume, - GLOB_ff_coroutine_wrap_aux, - GLOB_ff_coroutine_yield, - GLOB_ff_math_abs, - GLOB_fff_resbit, - GLOB_ff_math_floor, - GLOB_vm_floor, - GLOB_ff_math_ceil, - GLOB_vm_ceil, - GLOB_ff_math_sqrt, - GLOB_ff_math_log, - GLOB_ff_math_log10, - GLOB_ff_math_exp, - GLOB_vm_exp_x87, - GLOB_ff_math_sin, - GLOB_ff_math_cos, - GLOB_ff_math_tan, - GLOB_ff_math_asin, - GLOB_ff_math_acos, - GLOB_ff_math_atan, - GLOB_ff_math_sinh, - GLOB_ff_math_cosh, - GLOB_ff_math_tanh, - GLOB_ff_math_deg, - GLOB_ff_math_rad, - GLOB_ff_math_atan2, - GLOB_ff_math_ldexp, - GLOB_ff_math_frexp, - GLOB_ff_math_modf, - GLOB_vm_trunc, - GLOB_ff_math_fmod, - GLOB_ff_math_pow, - GLOB_vm_pow, - GLOB_ff_math_min, - GLOB_ff_math_max, - GLOB_ff_string_len, - GLOB_ff_string_byte, - GLOB_ff_string_char, - GLOB_fff_newstr, - GLOB_ff_string_sub, - GLOB_fff_emptystr, - GLOB_ff_string_rep, - GLOB_fff_fallback_2, - GLOB_ff_string_reverse, - GLOB_fff_fallback_1, - GLOB_ff_string_lower, - GLOB_ff_string_upper, - GLOB_ff_table_getn, - GLOB_ff_bit_tobit, - GLOB_ff_bit_band, - GLOB_fff_fallback_bit_op, - GLOB_ff_bit_bor, - GLOB_ff_bit_bxor, - GLOB_ff_bit_bswap, - GLOB_ff_bit_bnot, - GLOB_ff_bit_lshift, - GLOB_ff_bit_rshift, - GLOB_ff_bit_arshift, - GLOB_ff_bit_rol, - GLOB_ff_bit_ror, - GLOB_vm_record, - GLOB_vm_rethook, - GLOB_vm_inshook, - GLOB_cont_hook, - GLOB_vm_hotloop, - GLOB_vm_callhook, - GLOB_vm_hotcall, - GLOB_vm_exit_handler, - GLOB_vm_exit_interp, - GLOB_vm_floor_sse, - GLOB_vm_ceil_sse, - GLOB_vm_trunc_sse, - GLOB_vm_mod, - GLOB_vm_exp2_x87, - GLOB_vm_exp2raw, - GLOB_vm_pow_sse, - GLOB_vm_powi_sse, - GLOB_vm_foldfpm, - GLOB_vm_foldarith, - GLOB_vm_cpuid, - GLOB_assert_bad_for_arg_type, - GLOB_vm_ffi_callback, - GLOB_vm_ffi_call, - GLOB_BC_MODVN_Z, - GLOB_BC_TGETS_Z, - GLOB_BC_TSETS_Z, - GLOB__MAX -}; -static const char *const globnames[] = { - "vm_returnp", - "cont_dispatch", - "vm_returnc", - "BC_RET_Z", - "vm_return", - "vm_leave_cp", - "vm_leave_unw", - "vm_unwind_c@8", - "vm_unwind_c_eh", - "vm_unwind_rethrow", - "vm_unwind_ff@4", - "vm_unwind_ff_eh", - "vm_growstack_c", - "vm_growstack_v", - "vm_growstack_f", - "vm_resume", - "vm_pcall", - "vm_call", - "vm_call_dispatch", - "vmeta_call", - "vm_call_dispatch_f", - "vm_cpcall", - "cont_ffi_callback", - "vm_call_tail", - "cont_cat", - "cont_ra", - "BC_CAT_Z", - "vmeta_tgets", - "vmeta_tgetb", - "vmeta_tgetv", - "vmeta_tsets", - "vmeta_tsetb", - "vmeta_tsetv", - "cont_nop", - "vmeta_comp", - "vmeta_binop", - "cont_condt", - "cont_condf", - "vmeta_equal", - "vmeta_equal_cd", - "vmeta_arith_vno", - "vmeta_arith_vn", - "vmeta_arith_nvo", - "vmeta_arith_nv", - "vmeta_unm", - "vmeta_arith_vvo", - "vmeta_arith_vv", - "vmeta_len", - "BC_LEN_Z", - "vmeta_call_ra", - "BC_CALLT_Z", - "vmeta_for", - "ff_assert", - "fff_fallback", - "fff_res_", - "ff_type", - "fff_res1", - "ff_getmetatable", - "ff_setmetatable", - "ff_rawget", - "ff_tonumber", - "fff_resi", - "fff_resxmm0", - "fff_resn", - "ff_tostring", - "fff_gcstep", - "ff_next", - "fff_res2", - "fff_res", - "ff_pairs", - "ff_ipairs_aux", - "fff_res0", - "ff_ipairs", - "ff_pcall", - "ff_xpcall", - "ff_coroutine_resume", - "ff_coroutine_wrap_aux", - "ff_coroutine_yield", - "ff_math_abs", - "fff_resbit", - "ff_math_floor", - "vm_floor", - "ff_math_ceil", - "vm_ceil", - "ff_math_sqrt", - "ff_math_log", - "ff_math_log10", - "ff_math_exp", - "vm_exp_x87", - "ff_math_sin", - "ff_math_cos", - "ff_math_tan", - "ff_math_asin", - "ff_math_acos", - "ff_math_atan", - "ff_math_sinh", - "ff_math_cosh", - "ff_math_tanh", - "ff_math_deg", - "ff_math_rad", - "ff_math_atan2", - "ff_math_ldexp", - "ff_math_frexp", - "ff_math_modf", - "vm_trunc", - "ff_math_fmod", - "ff_math_pow", - "vm_pow", - "ff_math_min", - "ff_math_max", - "ff_string_len", - "ff_string_byte", - "ff_string_char", - "fff_newstr", - "ff_string_sub", - "fff_emptystr", - "ff_string_rep", - "fff_fallback_2", - "ff_string_reverse", - "fff_fallback_1", - "ff_string_lower", - "ff_string_upper", - "ff_table_getn", - "ff_bit_tobit", - "ff_bit_band", - "fff_fallback_bit_op", - "ff_bit_bor", - "ff_bit_bxor", - "ff_bit_bswap", - "ff_bit_bnot", - "ff_bit_lshift", - "ff_bit_rshift", - "ff_bit_arshift", - "ff_bit_rol", - "ff_bit_ror", - "vm_record", - "vm_rethook", - "vm_inshook", - "cont_hook", - "vm_hotloop", - "vm_callhook", - "vm_hotcall", - "vm_exit_handler", - "vm_exit_interp", - "vm_floor_sse", - "vm_ceil_sse", - "vm_trunc_sse", - "vm_mod", - "vm_exp2_x87", - "vm_exp2raw", - "vm_pow_sse", - "vm_powi_sse", - "vm_foldfpm", - "vm_foldarith", - "vm_cpuid", - "assert_bad_for_arg_type", - "vm_ffi_callback", - "vm_ffi_call@4", - "BC_MODVN_Z", - "BC_TGETS_Z", - "BC_TSETS_Z", - (const char *)0 -}; -static const char *const extnames[] = { - "lj_state_growstack@8", - "lj_meta_tget", - "lj_meta_tset", - "lj_meta_comp", - "lj_meta_equal", - "lj_meta_equal_cd@8", - "lj_meta_arith", - "lj_meta_len@8", - "lj_meta_call", - "lj_meta_for@8", - "lj_tab_get", - "lj_str_fromnumber@8", - "lj_str_fromnum@8", - "lj_tab_next", - "lj_tab_getinth@8", - "lj_ffh_coroutine_wrap_err@8", - "lj_vm_sinh", - "lj_vm_cosh", - "lj_vm_tanh", - "lj_str_new", - "lj_tab_len@4", - "lj_gc_step@4", - "lj_dispatch_ins@8", - "lj_trace_hot@8", - "lj_dispatch_call@8", - "lj_trace_exit@8", - "lj_err_throw@8", - "lj_ccallback_enter@8", - "lj_ccallback_leave@8", - "lj_meta_cat", - "lj_gc_barrieruv@8", - "lj_func_closeuv@8", - "lj_func_newL_gc", - "lj_tab_new", - "lj_gc_step_fixtop@4", - "lj_tab_dup@8", - "lj_tab_newkey", - "lj_tab_reasize", - (const char *)0 -}; -#define Dt1(_V) (int)(ptrdiff_t)&(((lua_State *)0)_V) -#define Dt2(_V) (int)(ptrdiff_t)&(((global_State *)0)_V) -#define Dt3(_V) (int)(ptrdiff_t)&(((TValue *)0)_V) -#define Dt4(_V) (int)(ptrdiff_t)&(((GCobj *)0)_V) -#define Dt5(_V) (int)(ptrdiff_t)&(((GCstr *)0)_V) -#define Dt6(_V) (int)(ptrdiff_t)&(((GCtab *)0)_V) -#define Dt7(_V) (int)(ptrdiff_t)&(((GCfuncL *)0)_V) -#define Dt8(_V) (int)(ptrdiff_t)&(((GCfuncC *)0)_V) -#define Dt9(_V) (int)(ptrdiff_t)&(((GCproto *)0)_V) -#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V) -#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V) -#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V) -#define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V) -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx, int cmov, int sse) -{ - dasm_put(Dst, 0); - dasm_put(Dst, 2, FRAME_P, LJ_TTRUE, FRAME_TYPE, FRAME_C, FRAME_TYPE, DISPATCH_GL(vmstate), ~LJ_VMST_C); - dasm_put(Dst, 109, Dt1(->base), Dt1(->top), Dt1(->cframe), Dt1(->maxstack), LJ_TNIL); - dasm_put(Dst, 198, Dt1(->top), Dt1(->top), Dt1(->glref), Dt2(->vmstate), ~LJ_VMST_C, CFRAME_RAWMASK); - dasm_put(Dst, 276, 1+1, Dt1(->base), Dt1(->glref), GG_G2DISP, LJ_TFALSE, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, LUA_MINSTACK, -4+PC2PROTO(framesize), Dt1(->base)); - dasm_put(Dst, 356, Dt1(->top), Dt1(->base), Dt1(->top), Dt7(->pc), FRAME_CP, CFRAME_RESUME, Dt1(->glref), GG_G2DISP, Dt1(->cframe), Dt1(->status), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->status), Dt1(->base), Dt1(->top), FRAME_TYPE); - dasm_put(Dst, 511, FRAME_CP, FRAME_C, Dt1(->cframe), Dt1(->cframe), Dt1(->glref), GG_G2DISP, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base)); - dasm_put(Dst, 604, Dt1(->top), LJ_TFUNC, Dt7(->pc), Dt1(->stack), Dt1(->top), Dt1(->cframe), Dt1(->cframe), FRAME_CP, LJ_TNIL); -#if LJ_HASFFI - dasm_put(Dst, 764); -#endif - dasm_put(Dst, 773, 0); -#if LJ_HASFFI -#endif - dasm_put(Dst, 782, Dt7(->pc), PC2PROTO(k)); -#if LJ_HASFFI - dasm_put(Dst, 796); -#endif - dasm_put(Dst, 817, Dt1(->base), LJ_TSTR, BC_GGET, DISPATCH_GL(tmptv), LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 917, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 927); - } else { - } - dasm_put(Dst, 940, Dt1(->base), Dt1(->base), Dt1(->top), FRAME_CONT, 2+1, LJ_TSTR, BC_GSET); - dasm_put(Dst, 1087, DISPATCH_GL(tmptv), LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 917, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 927); - } else { - } - dasm_put(Dst, 1110, Dt1(->base), Dt1(->base), Dt1(->top), FRAME_CONT, 3+1, Dt1(->base), Dt1(->base)); - dasm_put(Dst, 1283, -BCBIAS_J*4, LJ_TISTRUECOND, LJ_TISTRUECOND, Dt1(->base)); - dasm_put(Dst, 1383); -#if LJ_HASFFI - dasm_put(Dst, 1403, Dt1(->base)); -#endif - dasm_put(Dst, 1434); -#if LJ_DUALNUM - dasm_put(Dst, 1437); -#endif - dasm_put(Dst, 1443); -#if LJ_DUALNUM - dasm_put(Dst, 911); -#endif - dasm_put(Dst, 1455); -#if LJ_DUALNUM - dasm_put(Dst, 1437); -#endif - dasm_put(Dst, 1483, Dt1(->base), Dt1(->base), FRAME_CONT, 2+1, Dt1(->base), Dt1(->base)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1589); -#else - dasm_put(Dst, 1608); -#endif - dasm_put(Dst, 1613, Dt1(->base), Dt1(->base), Dt7(->pc), Dt1(->base), Dt1(->base), GG_DISP2STATIC, 1+1, LJ_TISTRUECOND); - dasm_put(Dst, 1799, 1+1, ~LJ_TNUMX); - if (cmov) { - dasm_put(Dst, 1868); - } else { - dasm_put(Dst, 1872); - } - dasm_put(Dst, 1881, ((char *)(&((GCfuncC *)0)->upvalue)), LJ_TSTR, ~LJ_TLIGHTUD, 1+1, LJ_TTAB, Dt6(->metatable), LJ_TNIL); - dasm_put(Dst, 1960, DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable), LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), DtB(->next)); - dasm_put(Dst, 2017, LJ_TNIL, LJ_TUDATA, LJ_TNUMX, LJ_TISNUM, LJ_TLIGHTUD); - dasm_put(Dst, 2083, LJ_TNUMX, DISPATCH_GL(gcroot[GCROOT_BASEMT]), 2+1, LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->metatable), LJ_TTAB); - dasm_put(Dst, 2153, Dt6(->marked), LJ_GC_BLACK, Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist), 2+1, LJ_TTAB); - dasm_put(Dst, 2242, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 2256); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 2278); - } else { - dasm_put(Dst, 2288); - } - dasm_put(Dst, 2295, 1+1, LJ_TSTR, LJ_TSTR, LJ_TISNUM, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM]), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 2361, Dt1(->base)); - if (LJ_DUALNUM) { - dasm_put(Dst, 2385); - } else { - dasm_put(Dst, 2390); - } - dasm_put(Dst, 2395, Dt1(->base), 1+1, LJ_TTAB, Dt1(->base), Dt1(->top), Dt1(->base), 1+2); - dasm_put(Dst, 2488, LJ_TNIL, LJ_TNIL, 1+1, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 2535, Dt6(->metatable)); -#endif - dasm_put(Dst, 2544, Dt8(->upvalue[0]), LJ_TFUNC, LJ_TNIL, 1+3, 1+1, LJ_TTAB, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 2530); - } else { - dasm_put(Dst, 2273); - } - dasm_put(Dst, 2599); - if (LJ_DUALNUM) { - dasm_put(Dst, 2604, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 2620, (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32)); - } else { - } - dasm_put(Dst, 2653, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->hmask), 1+0); - dasm_put(Dst, 2515, 1+1, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 2535, Dt6(->metatable)); -#endif - dasm_put(Dst, 2730, Dt8(->upvalue[0]), LJ_TFUNC); - if (LJ_DUALNUM) { - dasm_put(Dst, 2751, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 2763); - } else { - dasm_put(Dst, 2773); - } - dasm_put(Dst, 2780, 1+3, 1+1, 8+FRAME_PCALL, DISPATCH_GL(hookmask), HOOK_ACTIVE_SHIFT, 2+1, LJ_TFUNC); - dasm_put(Dst, 2844, LJ_TFUNC, 16+FRAME_PCALL, 1+1, LJ_TTHREAD, Dt1(->cframe), Dt1(->status), LUA_YIELD, Dt1(->top)); - dasm_put(Dst, 2934, Dt1(->base), Dt1(->maxstack), Dt1(->top), Dt1(->base), Dt1(->top), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP); - dasm_put(Dst, 3022, Dt1(->base), LUA_YIELD, Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->maxstack), LJ_TTRUE, FRAME_TYPE); - dasm_put(Dst, 3135, LJ_TFALSE, Dt1(->top), Dt1(->top), 1+2, Dt1(->top), Dt1(->base), Dt8(->upvalue[0].gcr), Dt1(->cframe)); - dasm_put(Dst, 3233, Dt1(->status), LUA_YIELD, Dt1(->top), Dt1(->base), Dt1(->maxstack), Dt1(->top), Dt1(->base), Dt1(->top)); - dasm_put(Dst, 3300, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base), LUA_YIELD, Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->maxstack)); - dasm_put(Dst, 3388, FRAME_TYPE, Dt1(->top), Dt1(->base), Dt1(->cframe), CFRAME_RESUME); - dasm_put(Dst, 3500, Dt1(->base), Dt1(->top), Dt1(->cframe), LUA_YIELD, Dt1(->status)); - if (!LJ_DUALNUM) { - dasm_put(Dst, 3527); - } - if (sse) { - dasm_put(Dst, 3530); - } - dasm_put(Dst, 3545, 1+1); - if (LJ_DUALNUM) { - dasm_put(Dst, 3556, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 3636, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 3646, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32)); - } else { - dasm_put(Dst, 3677); - } - dasm_put(Dst, 3694, 1+1, FRAME_TYPE, LJ_TNIL); - if (LJ_DUALNUM) { - dasm_put(Dst, 3790, LJ_TISNUM); - } else { - dasm_put(Dst, 3636, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 3812); - if (LJ_DUALNUM) { - dasm_put(Dst, 3821); - } - dasm_put(Dst, 2283); - } else { - dasm_put(Dst, 3855); - if (LJ_DUALNUM) { - } else { - dasm_put(Dst, 2290); - } - } - dasm_put(Dst, 3861); - if (LJ_DUALNUM) { - dasm_put(Dst, 3790, LJ_TISNUM); - } else { - dasm_put(Dst, 3636, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 3864); - if (LJ_DUALNUM) { - dasm_put(Dst, 3821); - } - dasm_put(Dst, 2283); - } else { - dasm_put(Dst, 3873); - if (LJ_DUALNUM) { - } else { - dasm_put(Dst, 2290); - } - } - if (sse) { - dasm_put(Dst, 3879, 1+1, LJ_TISNUM); - } else { - dasm_put(Dst, 3908, 1+1, LJ_TISNUM); - } - dasm_put(Dst, 3937, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1); - dasm_put(Dst, 4006, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1); - dasm_put(Dst, 4063, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1); - dasm_put(Dst, 4126, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM); - dasm_put(Dst, 4216); - if (sse) { - dasm_put(Dst, 4228, 1+1, LJ_TISNUM); - } else { - } - dasm_put(Dst, 4253); - if (sse) { - dasm_put(Dst, 4267, 1+1, LJ_TISNUM); - } else { - } - dasm_put(Dst, 4292); - if (sse) { - dasm_put(Dst, 4306, 1+1, LJ_TISNUM); - } else { - } - dasm_put(Dst, 4331); - if (sse) { - dasm_put(Dst, 4347, 1+1, LJ_TISNUM, Dt8(->upvalue[0])); - } else { - dasm_put(Dst, 4386, 1+1, LJ_TISNUM, Dt8(->upvalue[0])); - } - dasm_put(Dst, 4419, 2+1, LJ_TISNUM, LJ_TISNUM, 2+1, LJ_TISNUM, LJ_TISNUM); - dasm_put(Dst, 4484, 1+1, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4583); - } else { - dasm_put(Dst, 4589); - } - dasm_put(Dst, 4598); - if (sse) { - dasm_put(Dst, 4623); - } else { - dasm_put(Dst, 4629); - } - dasm_put(Dst, 4632, 1+2); - if (sse) { - dasm_put(Dst, 4641); - } else { - dasm_put(Dst, 4649); - } - dasm_put(Dst, 4657); - if (sse) { - dasm_put(Dst, 4660, (unsigned int)(U64x(43500000,00000000)), (unsigned int)((U64x(43500000,00000000))>>32)); - } else { - dasm_put(Dst, 4687); - } - dasm_put(Dst, 4706); - if (sse) { - dasm_put(Dst, 4722, 1+1, LJ_TISNUM); - } else { - dasm_put(Dst, 4747, 1+1, LJ_TISNUM); - } - dasm_put(Dst, 4769); - if (sse) { - dasm_put(Dst, 4791); - } else { - dasm_put(Dst, 4817); - } - dasm_put(Dst, 4834, 1+2); - if (sse) { - dasm_put(Dst, 4874); - } else { - dasm_put(Dst, 4882); - } - dasm_put(Dst, 4892, 2+1, LJ_TISNUM, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4944, 2+1, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 4991, 2+1, LJ_TISNUM, LJ_TISNUM); - } - dasm_put(Dst, 5032, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5045, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4583); - } else { - } - dasm_put(Dst, 5095); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 5106, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5127); - } else { - dasm_put(Dst, 2273); - } - dasm_put(Dst, 5148); - } else { - } - dasm_put(Dst, 5173, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5186, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4583); - } else { - } - dasm_put(Dst, 5095); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 5106, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5127); - } else { - dasm_put(Dst, 2273); - } - dasm_put(Dst, 5236); - } else { - } - if (!sse) { - dasm_put(Dst, 5261); - } - dasm_put(Dst, 5270, 1+1, LJ_TSTR); - if (LJ_DUALNUM) { - dasm_put(Dst, 5292, Dt5(->len)); - } else if (sse) { - dasm_put(Dst, 5300, Dt5(->len)); - } else { - dasm_put(Dst, 5311, Dt5(->len)); - } - dasm_put(Dst, 5319, 1+1, LJ_TSTR, Dt5(->len), Dt5([1])); - if (LJ_DUALNUM) { - dasm_put(Dst, 5295); - } else if (sse) { - dasm_put(Dst, 5357); - } else { - dasm_put(Dst, 5367); - } - dasm_put(Dst, 5380, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5411); - } else if (sse) { - dasm_put(Dst, 5434); - } else { - dasm_put(Dst, 5460); - } - dasm_put(Dst, 5484, Dt1(->base), Dt1(->base), LJ_TSTR, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), 1+2, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5592); - } else if (sse) { - dasm_put(Dst, 5604); - } else { - dasm_put(Dst, 5619); - } - dasm_put(Dst, 5631, LJ_TSTR, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 2530); - } else { - dasm_put(Dst, 2273); - } - dasm_put(Dst, 5648, Dt5(->len)); - if (LJ_DUALNUM) { - dasm_put(Dst, 5658); - } else if (sse) { - dasm_put(Dst, 5662); - } else { - } - dasm_put(Dst, 5669, sizeof(GCstr)-1); - dasm_put(Dst, 5744, 2+1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 5803, LJ_TSTR, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5820); - } else if (sse) { - dasm_put(Dst, 5828); - } else { - dasm_put(Dst, 5839); - } - dasm_put(Dst, 5855, Dt5(->len), DISPATCH_GL(tmpbuf.sz), Dt5([1]), DISPATCH_GL(tmpbuf.buf), DISPATCH_GL(tmpbuf.buf), 1+1); - dasm_put(Dst, 5920, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf)); - dasm_put(Dst, 5983, 1+1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz)); - dasm_put(Dst, 6054, sizeof(GCstr), DISPATCH_GL(tmpbuf.buf), 1+1); - dasm_put(Dst, 6139, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf)); - dasm_put(Dst, 6209, 1+1, LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 6277); - } else if (sse) { - dasm_put(Dst, 6284); - } else { - } - dasm_put(Dst, 6294, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6310); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6327, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 106); - if (LJ_DUALNUM || sse) { - if (!sse) { - } - dasm_put(Dst, 6351); - } else { - } - dasm_put(Dst, 6356, 1+1); - if (sse) { - dasm_put(Dst, 6367, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - dasm_put(Dst, 6377); - } - dasm_put(Dst, 2250, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6386); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6403); - } else { - } - dasm_put(Dst, 6418, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6443); - } else { - dasm_put(Dst, 6463); - } - if (sse) { - dasm_put(Dst, 6468); - } else { - } - dasm_put(Dst, 6485, 1+1); - if (sse) { - dasm_put(Dst, 6367, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - dasm_put(Dst, 6377); - } - dasm_put(Dst, 2250, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6386); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6403); - } else { - } - dasm_put(Dst, 6418, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6503); - } else { - dasm_put(Dst, 6463); - } - if (sse) { - dasm_put(Dst, 6523); - } else { - } - dasm_put(Dst, 6540, 1+1); - if (sse) { - dasm_put(Dst, 6367, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - dasm_put(Dst, 6377); - } - dasm_put(Dst, 2250, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6386); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6403); - } else { - } - dasm_put(Dst, 6418, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6558); - } else { - dasm_put(Dst, 6463); - } - if (sse) { - dasm_put(Dst, 6578); - } else { - } - dasm_put(Dst, 6595, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6386); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6327, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6618, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6386); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6327, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6642); - if (LJ_DUALNUM) { - dasm_put(Dst, 6351); - } else if (sse) { - dasm_put(Dst, 6648); - } else { - } - dasm_put(Dst, 6660); - if (LJ_DUALNUM) { - dasm_put(Dst, 6671, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6386); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6327, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6687, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 6702, 2+1, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6769); - if (LJ_DUALNUM) { - dasm_put(Dst, 6776, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6386); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6327, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6687, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 6792, 2+1, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6859); - if (LJ_DUALNUM) { - dasm_put(Dst, 6867, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6386); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6327, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6687, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 6883, 2+1, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6950); - if (LJ_DUALNUM) { - dasm_put(Dst, 6958, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6386); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6327, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6687, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 6974, 2+1, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 7041); - if (LJ_DUALNUM) { - dasm_put(Dst, 7048, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6386); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6327, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 6687, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 7064, 2+1, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32)); - } else { - } - dasm_put(Dst, 7131, 1+2, 1+1, Dt1(->base), 8*LUA_MINSTACK, Dt1(->top), Dt1(->maxstack), Dt8(->f), Dt1(->base)); - dasm_put(Dst, 7207, Dt1(->top), Dt7(->pc), FRAME_TYPE, LUA_MINSTACK, Dt1(->base), Dt1(->base)); - dasm_put(Dst, 7334, Dt1(->top), Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 7373, DISPATCH_GL(hookmask), HOOK_VMEVENT, HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount)); -#endif - dasm_put(Dst, 7404, DISPATCH_GL(hookmask), HOOK_ACTIVE, DISPATCH_GL(hookmask), HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount), LUA_MASKLINE); - dasm_put(Dst, 7455, Dt1(->base), Dt1(->base), GG_DISP2STATIC); -#if LJ_HASJIT - dasm_put(Dst, 7522, Dt7(->pc), PC2PROTO(framesize), Dt1(->base), Dt1(->top), GG_DISP2J, DISPATCH_J(L)); -#endif - dasm_put(Dst, 7569); -#if LJ_HASJIT - dasm_put(Dst, 7399); -#endif - dasm_put(Dst, 7576); -#if LJ_HASJIT - dasm_put(Dst, 7579); -#endif - dasm_put(Dst, 7589, Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 7623); -#endif - dasm_put(Dst, 7628, Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 7659, DISPATCH_GL(vmstate), DISPATCH_GL(vmstate), ~LJ_VMST_EXIT, DISPATCH_J(exitno), DISPATCH_J(parent), 16*8+4*8, DISPATCH_GL(jit_L), DISPATCH_GL(jit_base), DISPATCH_J(L), DISPATCH_GL(jit_L), Dt1(->base), 4*8, GG_DISP2J, Dt1(->cframe), CFRAME_RAWMASK, CFRAME_OFS_L, Dt1(->base), CFRAME_OFS_PC); -#endif - dasm_put(Dst, 7889); -#if LJ_HASJIT - dasm_put(Dst, 7892, 9*16+4*8, -9*16, -8*16, -7*16, -6*16, -5*16, -4*16, -3*16, -2*16, -1*16, Dt7(->pc), PC2PROTO(k), DISPATCH_GL(jit_L), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, BC_FUNCF); - dasm_put(Dst, 8034); -#endif - dasm_put(Dst, 8060); - if (!sse) { - dasm_put(Dst, 8063); - } - dasm_put(Dst, 8108, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32)); - if (!sse) { - dasm_put(Dst, 8194); - } - dasm_put(Dst, 8239, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(bff00000,00000000)), (unsigned int)((U64x(bff00000,00000000))>>32)); - if (!sse) { - dasm_put(Dst, 8325); - } - dasm_put(Dst, 8364, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32)); - if (sse) { - dasm_put(Dst, 8453, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32)); - } else { - dasm_put(Dst, 8567); - } - dasm_put(Dst, 8614); - if (!sse) { - } else { - dasm_put(Dst, 8688); - } - dasm_put(Dst, 8691); - dasm_put(Dst, 8776, (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32)); - dasm_put(Dst, 8879, (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32), (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32), (unsigned int)(U64x(7ff00000,00000000)), (unsigned int)((U64x(7ff00000,00000000))>>32)); - dasm_put(Dst, 9035); -#if LJ_HASJIT - if (sse) { - dasm_put(Dst, 9076); - dasm_put(Dst, 9146); - dasm_put(Dst, 9219); - } else { - dasm_put(Dst, 9269); - dasm_put(Dst, 9361); - } - dasm_put(Dst, 9407); -#endif - dasm_put(Dst, 9411); - if (sse) { - dasm_put(Dst, 9414, (unsigned int)(U64x(80000000,00000000)), (unsigned int)((U64x(80000000,00000000))>>32)); - dasm_put(Dst, 9503, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32)); - } else { - dasm_put(Dst, 9627); - dasm_put(Dst, 9710); - if (cmov) { - dasm_put(Dst, 9765); - } else { - dasm_put(Dst, 9784); - } - dasm_put(Dst, 9407); - } - dasm_put(Dst, 9825); -#ifdef LUA_USE_ASSERT - dasm_put(Dst, 9409); -#endif - dasm_put(Dst, 9853); -#if LJ_HASFFI -#define DtE(_V) (int)(ptrdiff_t)&(((CTState *)0)_V) - dasm_put(Dst, 9857, GG_G2DISP, Dt2(->ctype_state), DtE(->cb.slot), DtE(->cb.gpr[0]), DtE(->cb.gpr[1]), DtE(->cb.gpr[2]), DtE(->cb.gpr[3]), DtE(->cb.fpr[0]), DtE(->cb.fpr[1]), DtE(->cb.fpr[2]), DtE(->cb.fpr[3]), CFRAME_SIZE+4*8, DtE(->cb.stack), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base), Dt1(->top), Dt7(->pc)); -#endif - dasm_put(Dst, 9984); -#if LJ_HASFFI - dasm_put(Dst, 9987, DISPATCH_GL(ctype_state), DtE(->L), Dt1(->base), Dt1(->top), DtE(->cb.gpr[0]), DtE(->cb.fpr[0])); -#endif - dasm_put(Dst, 10028); -#if LJ_HASFFI -#define DtF(_V) (int)(ptrdiff_t)&(((CCallState *)0)_V) - dasm_put(Dst, 10031, DtF(->spadj)); -#if LJ_TARGET_WINDOWS -#endif - dasm_put(Dst, 10046, DtF(->nsp), offsetof(CCallState, stack), CCALL_SPS_EXTRA*8, DtF(->nfpr), DtF(->gpr[0]), DtF(->gpr[1]), DtF(->gpr[2]), DtF(->gpr[3]), DtF(->fpr[0]), DtF(->fpr[1]), DtF(->fpr[2]), DtF(->fpr[3])); - dasm_put(Dst, 10127, DtF(->func), DtF(->gpr[0]), DtF(->fpr[0])); -#if LJ_TARGET_WINDOWS -#endif - dasm_put(Dst, 10140); -#endif -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse) -{ - int vk = 0; - dasm_put(Dst, 780, defop); - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - if (LJ_DUALNUM) { - dasm_put(Dst, 10148, LJ_TISNUM, LJ_TISNUM); - switch (op) { - case BC_ISLT: - dasm_put(Dst, 10178); - break; - case BC_ISGE: - dasm_put(Dst, 10183); - break; - case BC_ISLE: - dasm_put(Dst, 10188); - break; - case BC_ISGT: - dasm_put(Dst, 10193); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 10198, -BCBIAS_J*4, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 10252); - } else { - dasm_put(Dst, 10263); - } - dasm_put(Dst, 10274); - if (sse) { - dasm_put(Dst, 10281); - switch (op) { - case BC_ISLT: - dasm_put(Dst, 10301); - break; - case BC_ISGE: - dasm_put(Dst, 10306); - break; - case BC_ISLE: - dasm_put(Dst, 10311); - break; - case BC_ISGT: - dasm_put(Dst, 10316); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 10321); - } else { - dasm_put(Dst, 10326); - } - } else { - dasm_put(Dst, 10334, LJ_TISNUM, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 10355); - } else { - dasm_put(Dst, 10376); - if (cmov) { - dasm_put(Dst, 10392); - } else { - dasm_put(Dst, 10398); - } - } - if (LJ_DUALNUM) { - switch (op) { - case BC_ISLT: - dasm_put(Dst, 10301); - break; - case BC_ISGE: - dasm_put(Dst, 10306); - break; - case BC_ISLE: - dasm_put(Dst, 10311); - break; - case BC_ISGT: - dasm_put(Dst, 10316); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 10321); - } else { - switch (op) { - case BC_ISLT: - dasm_put(Dst, 768); - break; - case BC_ISGE: - dasm_put(Dst, 10405); - break; - case BC_ISLE: - dasm_put(Dst, 10410); - break; - case BC_ISGT: - dasm_put(Dst, 10415); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 10420, -BCBIAS_J*4); - } - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - dasm_put(Dst, 10452); - if (LJ_DUALNUM) { - dasm_put(Dst, 10460, LJ_TISNUM, LJ_TISNUM); - if (vk) { - dasm_put(Dst, 10485); - } else { - dasm_put(Dst, 10490); - } - dasm_put(Dst, 10495, -BCBIAS_J*4, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 10547); - } else { - dasm_put(Dst, 10554); - } - dasm_put(Dst, 10558); - if (sse) { - dasm_put(Dst, 10569); - } else { - dasm_put(Dst, 10581); - } - dasm_put(Dst, 10588); - } else { - dasm_put(Dst, 10593, LJ_TISNUM, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 10612); - } else { - dasm_put(Dst, 10630); - if (cmov) { - dasm_put(Dst, 10392); - } else { - dasm_put(Dst, 10398); - } - } - iseqne_fp: - if (vk) { - dasm_put(Dst, 10643); - } else { - dasm_put(Dst, 10652); - } - iseqne_end: - if (vk) { - dasm_put(Dst, 10661, -BCBIAS_J*4); - if (!LJ_HASFFI) { - dasm_put(Dst, 4638); - } - } else { - if (!LJ_HASFFI) { - dasm_put(Dst, 4638); - } - dasm_put(Dst, 10676, -BCBIAS_J*4); - } - if (LJ_DUALNUM && (op == BC_ISEQV || op == BC_ISNEV || - op == BC_ISEQN || op == BC_ISNEN)) { - dasm_put(Dst, 10691); - } else { - dasm_put(Dst, 10432); - } - if (op == BC_ISEQV || op == BC_ISNEV) { - dasm_put(Dst, 10124); - if (LJ_HASFFI) { - dasm_put(Dst, 10696, LJ_TCDATA, LJ_TCDATA); - } - dasm_put(Dst, 10715, LJ_TISPRI, LJ_TISTABUD, LJ_TUDATA, Dt6(->metatable), Dt6(->nomm), 1<>32)); - } else { - dasm_put(Dst, 11303); - } - if (LJ_DUALNUM) { - dasm_put(Dst, 10691); - } else { - dasm_put(Dst, 10432); - } - break; - case BC_LEN: - dasm_put(Dst, 11312, LJ_TSTR); - if (LJ_DUALNUM) { - dasm_put(Dst, 11326, Dt5(->len), LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 11340, Dt5(->len)); - } else { - dasm_put(Dst, 11358, Dt5(->len)); - } - dasm_put(Dst, 11367, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 11402, Dt6(->metatable)); -#endif - dasm_put(Dst, 11416); - if (LJ_DUALNUM) { - } else if (sse) { - dasm_put(Dst, 11425); - } else { - } - dasm_put(Dst, 11431); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 11444, Dt6(->nomm), 1<base), Dt1(->base)); - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - dasm_put(Dst, 12270, LJ_TSTR); - break; - case BC_KCDATA: -#if LJ_HASFFI - dasm_put(Dst, 12270, LJ_TCDATA); -#endif - break; - case BC_KSHORT: - if (LJ_DUALNUM) { - dasm_put(Dst, 12305, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 12317); - } else { - dasm_put(Dst, 12332); - } - dasm_put(Dst, 10432); - break; - case BC_KNUM: - if (sse) { - dasm_put(Dst, 12340); - } else { - dasm_put(Dst, 12353); - } - dasm_put(Dst, 10432); - break; - case BC_KPRI: - dasm_put(Dst, 12360); - break; - case BC_KNIL: - dasm_put(Dst, 12388, LJ_TNIL); - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - dasm_put(Dst, 12435, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_USETV: -#define TV2MARKOFS \ - ((int32_t)offsetof(GCupval, marked)-(int32_t)offsetof(GCupval, tv)) - dasm_put(Dst, 12475, offsetof(GCfuncL, uvptr), DtA(->closed), DtA(->v), TV2MARKOFS, LJ_GC_BLACK, LJ_TISGCV, LJ_TISNUM - LJ_TISGCV, Dt4(->gch.marked), LJ_GC_WHITES, GG_DISP2G); - dasm_put(Dst, 12566); - break; -#undef TV2MARKOFS - case BC_USETS: - dasm_put(Dst, 12578, offsetof(GCfuncL, uvptr), DtA(->v), LJ_TSTR, DtA(->marked), LJ_GC_BLACK, Dt4(->gch.marked), LJ_GC_WHITES, DtA(->closed), GG_DISP2G); - break; - case BC_USETN: - dasm_put(Dst, 12671); - if (sse) { - dasm_put(Dst, 12676); - } else { - dasm_put(Dst, 10951); - } - dasm_put(Dst, 12683, offsetof(GCfuncL, uvptr), DtA(->v)); - if (sse) { - dasm_put(Dst, 12692); - } else { - dasm_put(Dst, 12698); - } - dasm_put(Dst, 10432); - break; - case BC_USETP: - dasm_put(Dst, 12701, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_UCLO: - dasm_put(Dst, 12740, -BCBIAS_J*4, Dt1(->openupval), Dt1(->base), Dt1(->base)); - break; - - case BC_FNEW: - dasm_put(Dst, 12795, Dt1(->base), Dt1(->base), LJ_TFUNC); - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - dasm_put(Dst, 12861, Dt1(->base), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), LJ_TTAB); - break; - case BC_TDUP: - dasm_put(Dst, 12983, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), Dt1(->base), LJ_TTAB); - break; - - case BC_GGET: - dasm_put(Dst, 13078, Dt7(->env)); - break; - case BC_GSET: - dasm_put(Dst, 13097, Dt7(->env)); - break; - - case BC_TGETV: - dasm_put(Dst, 13116, LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 13139, LJ_TISNUM); - } else { - dasm_put(Dst, 13153, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 13164); - } else { - } - dasm_put(Dst, 13185); - } - dasm_put(Dst, 13190, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), LJ_TNIL); - dasm_put(Dst, 13383, LJ_TNIL, DtB(->next), Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), LJ_TNIL, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), LJ_TNIL, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - case BC_TSETS: - dasm_put(Dst, 13731, LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->nomm), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), LJ_TNIL); - dasm_put(Dst, 13807, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<next)); - dasm_put(Dst, 13895, Dt6(->metatable), Dt6(->nomm), 1<base), Dt1(->base), Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - case BC_TSETB: - dasm_put(Dst, 13986, LJ_TTAB, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable)); - dasm_put(Dst, 14080, Dt6(->metatable), Dt6(->nomm), 1<marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - - case BC_TSETM: - dasm_put(Dst, 14126, Dt6(->marked), LJ_GC_BLACK, Dt6(->asize), Dt6(->array), Dt1(->base), Dt1(->base)); - dasm_put(Dst, 14269, Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALL: case BC_CALLM: - dasm_put(Dst, 11464); - if (op == BC_CALLM) { - dasm_put(Dst, 14287); - } - dasm_put(Dst, 14292, LJ_TFUNC, Dt7(->pc)); - break; - - case BC_CALLMT: - dasm_put(Dst, 14287); - break; - case BC_CALLT: - dasm_put(Dst, 14334, LJ_TFUNC, FRAME_TYPE, Dt7(->ffid), Dt7(->pc)); - dasm_put(Dst, 14449, FRAME_TYPE, Dt7(->pc), PC2PROTO(k), FRAME_VARG, FRAME_TYPEP, FRAME_VARG); - break; - - case BC_ITERC: - dasm_put(Dst, 14520, LJ_TFUNC, 2+1, Dt7(->pc)); - break; - - case BC_ITERN: -#if LJ_HASJIT -#endif - dasm_put(Dst, 14591, Dt6(->asize), Dt6(->array), LJ_TNIL); - if (LJ_DUALNUM) { - dasm_put(Dst, 11331, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 11425); - } else { - dasm_put(Dst, 14637); - } - dasm_put(Dst, 14643); - if (LJ_DUALNUM) { - } else if (sse) { - dasm_put(Dst, 11296); - } else { - dasm_put(Dst, 11308); - } - dasm_put(Dst, 14656, -BCBIAS_J*4); - if (!LJ_DUALNUM && !sse) { - dasm_put(Dst, 14708); - } - dasm_put(Dst, 14714, Dt6(->hmask), sizeof(Node), Dt6(->node), DtB(->val.it), LJ_TNIL, DtB(->key), DtB(->val)); - break; - - case BC_ISNEXT: - dasm_put(Dst, 14786, LJ_TFUNC, LJ_TTAB, LJ_TNIL, Dt8(->ffid), FF_next_N, -BCBIAS_J*4, BC_JMP, -BCBIAS_J*4, BC_ITERC); - break; - - case BC_VARG: - dasm_put(Dst, 14886, (8+FRAME_VARG), LJ_TNIL, Dt1(->maxstack)); - dasm_put(Dst, 15046, Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top)); - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - dasm_put(Dst, 14287); - break; - - case BC_RET: case BC_RET0: case BC_RET1: - if (op != BC_RET0) { - dasm_put(Dst, 15112); - } - dasm_put(Dst, 15116, FRAME_TYPE); - switch (op) { - case BC_RET: - dasm_put(Dst, 15135); - break; - case BC_RET1: - dasm_put(Dst, 15187); - /* fallthrough */ - case BC_RET0: - dasm_put(Dst, 15197); - default: - break; - } - dasm_put(Dst, 15208, Dt7(->pc), PC2PROTO(k)); - if (op == BC_RET) { - dasm_put(Dst, 15252, LJ_TNIL); - } else { - dasm_put(Dst, 15261, LJ_TNIL); - } - dasm_put(Dst, 15268, -FRAME_VARG, FRAME_TYPEP); - if (op != BC_RET0) { - dasm_put(Dst, 15292); - } - dasm_put(Dst, 4717); - break; - - /* -- Loops and branches ------------------------------------------------ */ - - - case BC_FORL: -#if LJ_HASJIT - dasm_put(Dst, 15296, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - vk = (op == BC_IFORL || op == BC_JFORL); - dasm_put(Dst, 15317); - if (LJ_DUALNUM) { - dasm_put(Dst, 15321, LJ_TISNUM); - if (!vk) { - dasm_put(Dst, 15331, LJ_TISNUM, LJ_TISNUM); - } else { -#ifdef LUA_USE_ASSERT - dasm_put(Dst, 15360, LJ_TISNUM, LJ_TISNUM); -#endif - dasm_put(Dst, 15379); - } - dasm_put(Dst, 15398, LJ_TISNUM); - if (op == BC_FORI) { - dasm_put(Dst, 15409, -BCBIAS_J*4); - } else if (op == BC_JFORI) { - dasm_put(Dst, 15423, -BCBIAS_J*4, BC_JLOOP); - } else if (op == BC_IFORL) { - dasm_put(Dst, 15441, -BCBIAS_J*4); - } else { - dasm_put(Dst, 15433, BC_JLOOP); - } - dasm_put(Dst, 15455); - if (vk) { - dasm_put(Dst, 15479); - } - dasm_put(Dst, 15398, LJ_TISNUM); - if (op == BC_FORI) { - dasm_put(Dst, 15488); - } else if (op == BC_JFORI) { - dasm_put(Dst, 15493, -BCBIAS_J*4, BC_JLOOP); - } else if (op == BC_IFORL) { - dasm_put(Dst, 15507); - } else { - dasm_put(Dst, 15503, BC_JLOOP); - } - dasm_put(Dst, 15512); - } else if (!vk) { - dasm_put(Dst, 15519, LJ_TISNUM); - } - if (!vk) { - dasm_put(Dst, 15525, LJ_TISNUM); - } else { -#ifdef LUA_USE_ASSERT - dasm_put(Dst, 15539, LJ_TISNUM, LJ_TISNUM); -#endif - } - dasm_put(Dst, 15558); - if (!vk) { - dasm_put(Dst, 15562, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 15571); - if (vk) { - dasm_put(Dst, 15583); - } else { - dasm_put(Dst, 15602); - } - dasm_put(Dst, 15607); - } else { - dasm_put(Dst, 15620); - if (vk) { - dasm_put(Dst, 15626); - } else { - dasm_put(Dst, 15642); - } - dasm_put(Dst, 15650); - if (cmov) { - dasm_put(Dst, 10392); - } else { - dasm_put(Dst, 10398); - } - if (!cmov) { - dasm_put(Dst, 15655); - } - } - if (op == BC_FORI) { - if (LJ_DUALNUM) { - dasm_put(Dst, 15661); - } else { - dasm_put(Dst, 15666, -BCBIAS_J*4); - } - } else if (op == BC_JFORI) { - dasm_put(Dst, 15676, -BCBIAS_J*4, BC_JLOOP); - } else if (op == BC_IFORL) { - if (LJ_DUALNUM) { - dasm_put(Dst, 15690); - } else { - dasm_put(Dst, 15695, -BCBIAS_J*4); - } - } else { - dasm_put(Dst, 15686, BC_JLOOP); - } - if (LJ_DUALNUM) { - dasm_put(Dst, 10321); - } else { - dasm_put(Dst, 11081); - } - if (sse) { - dasm_put(Dst, 15705); - } - break; - - case BC_ITERL: -#if LJ_HASJIT - dasm_put(Dst, 15296, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - dasm_put(Dst, 15716, LJ_TNIL); - if (op == BC_JITERL) { - dasm_put(Dst, 15731, BC_JLOOP); - } else { - dasm_put(Dst, 15745, -BCBIAS_J*4); - } - dasm_put(Dst, 10430); - break; - - case BC_LOOP: -#if LJ_HASJIT - dasm_put(Dst, 15296, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_ILOOP: - dasm_put(Dst, 10432); - break; - - case BC_JLOOP: -#if LJ_HASJIT - dasm_put(Dst, 15761, DISPATCH_J(trace), DtD(->mcode), DISPATCH_GL(jit_base), DISPATCH_GL(jit_L), 9*16+4*8, -1*16, -2*16, -3*16, -4*16, -5*16, -6*16, -7*16, -8*16, -9*16); -#endif - break; - - case BC_JMP: - dasm_put(Dst, 15870, -BCBIAS_J*4); - break; - - /* -- Function headers -------------------------------------------------- */ - - /* - ** Reminder: A function may be called with func/args above L->maxstack, - ** i.e. occupying EXTRA_STACK slots. And vmeta_call may add one extra slot, - ** too. This means all FUNC* ops (including fast functions) must check - ** for stack overflow _before_ adding more slots! - */ - - case BC_FUNCF: -#if LJ_HASJIT - dasm_put(Dst, 15895, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_CALL); -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - dasm_put(Dst, 15916, -4+PC2PROTO(k), Dt1(->maxstack), -4+PC2PROTO(numparams)); - if (op == BC_JFUNCF) { - dasm_put(Dst, 15946, BC_JLOOP); - } else { - dasm_put(Dst, 10432); - } - dasm_put(Dst, 15955, LJ_TNIL); - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - dasm_put(Dst, 9409); - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - dasm_put(Dst, 15977, FRAME_VARG, Dt1(->maxstack), -4+PC2PROTO(numparams), LJ_TNIL); - if (op == BC_JFUNCV) { - dasm_put(Dst, 15946, BC_JLOOP); - } else { - dasm_put(Dst, 16068, -4+PC2PROTO(k)); - } - dasm_put(Dst, 16091, LJ_TNIL); - break; - - case BC_FUNCC: - case BC_FUNCCW: - dasm_put(Dst, 16113, Dt8(->f), Dt1(->base), 8*LUA_MINSTACK, Dt1(->maxstack), Dt1(->top)); - if (op == BC_FUNCC) { - dasm_put(Dst, 2381); - } else { - dasm_put(Dst, 16143); - } - dasm_put(Dst, 16151, DISPATCH_GL(vmstate), ~LJ_VMST_C); - if (op == BC_FUNCC) { - dasm_put(Dst, 16160); - } else { - dasm_put(Dst, 16164, DISPATCH_GL(wrapf)); - } - dasm_put(Dst, 16169, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base), Dt1(->top)); - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - int cmov = 1; - int sse = 0; -#ifdef LUAJIT_CPU_NOCMOV - cmov = 0; -#endif -#if defined(LUAJIT_CPU_SSE2) || defined(LJ_TARGET_X64) - sse = 1; -#endif - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx, cmov, sse); - - dasm_put(Dst, 16194); - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op, cmov, sse); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); -#if LJ_64 -#define SZPTR "8" -#define BSZPTR "3" -#define REG_SP "0x7" -#define REG_RA "0x10" -#else -#define SZPTR "4" -#define BSZPTR "2" -#define REG_SP "0x4" -#define REG_RA "0x8" -#endif - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.long .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.long 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.long .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.long .Lframe0\n" -#if LJ_64 - "\t.quad .Lbegin\n" - "\t.quad %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.long .Lbegin\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE0:\n\n", fcofs, CFRAME_SIZE); -#if LJ_HASFFI - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.long .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.long .Lframe0\n" -#if LJ_64 - "\t.quad lj_vm_ffi_call\n" - "\t.quad %d\n" - "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ -#else - "\t.long lj_vm_ffi_call\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); -#endif -#if (defined(__sun__) && defined(__svr4__)) || defined(__solaris_) - fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n"); -#else - fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); -#endif - fprintf(ctx->fp, - ".Lframe1:\n" - "\t.long .LECIE1-.LSCIE1\n" - ".LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zPR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 6\n" /* augmentation length */ - "\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 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE1:\n\n"); - fprintf(ctx->fp, - ".LSFDE2:\n" - "\t.long .LEFDE2-.LASFDE2\n" - ".LASFDE2:\n" - "\t.long .LASFDE2-.Lframe1\n" - "\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 */ -#if LJ_64 - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE2:\n\n", fcofs, CFRAME_SIZE); -#if LJ_HASFFI - fprintf(ctx->fp, - ".Lframe2:\n" - "\t.long .LECIE2-.LSCIE2\n" - ".LSCIE2:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 1\n" /* augmentation length */ - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE2:\n\n"); - fprintf(ctx->fp, - ".LSFDE3:\n" - "\t.long .LEFDE3-.LASFDE3\n" - ".LASFDE3:\n" - "\t.long .LASFDE3-.Lframe2\n" - "\t.long lj_vm_ffi_call-.\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ -#else - "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); -#endif - break; - case BUILD_coffasm: - fprintf(ctx->fp, "\t.section .eh_frame,\"dr\"\n"); - fprintf(ctx->fp, - "\t.def %slj_err_unwind_dwarf; .scl 2; .type 32; .endef\n", - LJ_32 ? "_" : ""); - fprintf(ctx->fp, - "Lframe1:\n" - "\t.long LECIE1-LSCIE1\n" - "LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zP\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 5\n" /* augmentation length */ - "\t.byte 0x00\n" /* absptr */ - "\t.long %slj_err_unwind_dwarf\n" - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - "LECIE1:\n\n", LJ_32 ? "_" : ""); - fprintf(ctx->fp, - "LSFDE1:\n" - "\t.long LEFDE1-LASFDE1\n" - "LASFDE1:\n" - "\t.long LASFDE1-Lframe1\n" - "\t.long %slj_vm_asm_begin\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ -#if LJ_64 - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - "LEFDE1:\n\n", LJ_32 ? "_" : "", (int)ctx->codesz, CFRAME_SIZE); - break; - /* Mental note: never let Apple design an assembler. - ** Or a linker. Or a plastic case. But I digress. - */ - case BUILD_machasm: { -#if LJ_HASFFI - int fcsize = 0; -#endif - int i; - 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.byte 0x1\n" - "\t.byte 128-" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 6\n" /* augmentation length */ - "\t.byte 0x9b\n" /* indirect|pcrel|sdata4 */ -#if LJ_64 - "\t.long _lj_err_unwind_dwarf+4@GOTPCREL\n" - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n" -#else - "\t.long L_lj_err_unwind_dwarf$non_lazy_ptr-.\n" - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH-O. */ -#endif - "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n" - "\t.align " BSZPTR "\n" - "LECIEX:\n\n"); - for (i = 0; i < ctx->nsym; i++) { - const char *name = ctx->sym[i].name; - int32_t size = ctx->sym[i+1].ofs - ctx->sym[i].ofs; - if (size == 0) continue; -#if LJ_HASFFI - if (!strcmp(name, "_lj_vm_ffi_call")) { fcsize = size; continue; } -#endif - fprintf(ctx->fp, - "%s.eh:\n" - "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.byte 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.byte %d\n" /* def_cfa_offset */ -#if LJ_64 - "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.byte 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.byte 0x5\n" /* offset r14 */ -#else - "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/ - "\t.byte 0x87\n\t.byte 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.byte 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.byte 0x5\n" /* offset ebx */ -#endif - "\t.align " BSZPTR "\n" - "LEFDE%d:\n\n", - name, i, i, i, i, i, i, i, name, size, CFRAME_SIZE, i); - } -#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.byte 0x1\n" - "\t.byte 128-" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 1\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n" -#else - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH. */ -#endif - "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n" - "\t.align " BSZPTR "\n" - "LECIEY:\n\n"); - fprintf(ctx->fp, - "_lj_vm_ffi_call.eh:\n" - "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.byte 0\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0xe\n\t.byte 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */ -#else - "\t.byte 0xe\n\t.byte 8\n" /* def_cfa_offset */ - "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/ - "\t.byte 0xd\n\t.uleb128 0x4\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset ebx */ -#endif - "\t.align " BSZPTR "\n" - "LEFDEY:\n\n", fcsize); - } -#endif -#if LJ_64 - fprintf(ctx->fp, "\t.subsections_via_symbols\n"); -#else - fprintf(ctx->fp, - "\t.non_lazy_symbol_pointer\n" - "L_lj_err_unwind_dwarf$non_lazy_ptr:\n" - ".indirect_symbol _lj_err_unwind_dwarf\n" - ".long 0\n"); -#endif - } - break; - default: /* Difficult for other modes. */ - break; - } -} - diff --git a/src/buildvm_x86.dasc b/src/buildvm_x86.dasc deleted file mode 100644 index 30ee5b67..00000000 --- a/src/buildvm_x86.dasc +++ /dev/null @@ -1,6458 +0,0 @@ -|// Low-level VM code for x86 CPUs. -|// Bytecode interpreter, fast functions and helper functions. -|// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -| -|.if X64 -|.arch x64 -|.else -|.arch x86 -|.endif -|.section code_op, code_sub -| -|.actionlist build_actionlist -|.globals GLOB_ -|.globalnames globnames -|.externnames extnames -| -|//----------------------------------------------------------------------- -| -|// Fixed register assignments for the interpreter. -|// This is very fragile and has many dependencies. Caveat emptor. -|.define BASE, edx // Not C callee-save, refetched anyway. -|.if not X64 -|.define KBASE, edi // Must be C callee-save. -|.define KBASEa, KBASE -|.define PC, esi // Must be C callee-save. -|.define PCa, PC -|.define DISPATCH, ebx // Must be C callee-save. -|.elif X64WIN -|.define KBASE, edi // Must be C callee-save. -|.define KBASEa, rdi -|.define PC, esi // Must be C callee-save. -|.define PCa, rsi -|.define DISPATCH, ebx // Must be C callee-save. -|.else -|.define KBASE, r15d // Must be C callee-save. -|.define KBASEa, r15 -|.define PC, ebx // Must be C callee-save. -|.define PCa, rbx -|.define DISPATCH, r14d // Must be C callee-save. -|.endif -| -|.define RA, ecx -|.define RAH, ch -|.define RAL, cl -|.define RB, ebp // Must be ebp (C callee-save). -|.define RC, eax // Must be eax (fcomparepp and others). -|.define RCW, ax -|.define RCH, ah -|.define RCL, al -|.define OP, RB -|.define RD, RC -|.define RDW, RCW -|.define RDL, RCL -|.if X64 -|.define RAa, rcx -|.define RBa, rbp -|.define RCa, rax -|.define RDa, rax -|.else -|.define RAa, RA -|.define RBa, RB -|.define RCa, RC -|.define RDa, RD -|.endif -| -|.if not X64 -|.define FCARG1, ecx // x86 fastcall arguments. -|.define FCARG2, edx -|.elif X64WIN -|.define CARG1, rcx // x64/WIN64 C call arguments. -|.define CARG2, rdx -|.define CARG3, r8 -|.define CARG4, r9 -|.define CARG1d, ecx -|.define CARG2d, edx -|.define CARG3d, r8d -|.define CARG4d, r9d -|.define FCARG1, CARG1d // Upwards compatible to x86 fastcall. -|.define FCARG2, CARG2d -|.else -|.define CARG1, rdi // x64/POSIX C call arguments. -|.define CARG2, rsi -|.define CARG3, rdx -|.define CARG4, rcx -|.define CARG5, r8 -|.define CARG6, r9 -|.define CARG1d, edi -|.define CARG2d, esi -|.define CARG3d, edx -|.define CARG4d, ecx -|.define CARG5d, r8d -|.define CARG6d, r9d -|.define FCARG1, CARG1d // Simulate x86 fastcall. -|.define FCARG2, CARG2d -|.endif -| -|// Type definitions. Some of these are only used for documentation. -|.type L, lua_State -|.type GL, global_State -|.type TVALUE, TValue -|.type GCOBJ, GCobj -|.type STR, GCstr -|.type TAB, GCtab -|.type LFUNC, GCfuncL -|.type CFUNC, GCfuncC -|.type PROTO, GCproto -|.type UPVAL, GCupval -|.type NODE, Node -|.type NARGS, int -|.type TRACE, GCtrace -| -|// Stack layout while in interpreter. Must match with lj_frame.h. -|//----------------------------------------------------------------------- -|.if not X64 // x86 stack layout. -| -|.define CFRAME_SPACE, aword*7 // Delta for esp (see <--). -|.macro saveregs_ -| push edi; push esi; push ebx -| sub esp, CFRAME_SPACE -|.endmacro -|.macro saveregs -| push ebp; saveregs_ -|.endmacro -|.macro restoreregs -| add esp, CFRAME_SPACE -| pop ebx; pop esi; pop edi; pop ebp -|.endmacro -| -|.define SAVE_ERRF, aword [esp+aword*15] // vm_pcall/vm_cpcall only. -|.define SAVE_NRES, aword [esp+aword*14] -|.define SAVE_CFRAME, aword [esp+aword*13] -|.define SAVE_L, aword [esp+aword*12] -|//----- 16 byte aligned, ^^^ arguments from C caller -|.define SAVE_RET, aword [esp+aword*11] //<-- esp entering interpreter. -|.define SAVE_R4, aword [esp+aword*10] -|.define SAVE_R3, aword [esp+aword*9] -|.define SAVE_R2, aword [esp+aword*8] -|//----- 16 byte aligned -|.define SAVE_R1, aword [esp+aword*7] //<-- esp after register saves. -|.define SAVE_PC, aword [esp+aword*6] -|.define TMP2, aword [esp+aword*5] -|.define TMP1, aword [esp+aword*4] -|//----- 16 byte aligned -|.define ARG4, aword [esp+aword*3] -|.define ARG3, aword [esp+aword*2] -|.define ARG2, aword [esp+aword*1] -|.define ARG1, aword [esp] //<-- esp while in interpreter. -|//----- 16 byte aligned, ^^^ arguments for C callee -| -|// FPARGx overlaps ARGx and ARG(x+1) on x86. -|.define FPARG3, qword [esp+qword*1] -|.define FPARG1, qword [esp] -|// TMPQ overlaps TMP1/TMP2. ARG5/MULTRES overlap TMP1/TMP2 (and TMPQ). -|.define TMPQ, qword [esp+aword*4] -|.define TMP3, ARG4 -|.define ARG5, TMP1 -|.define TMPa, TMP1 -|.define MULTRES, TMP2 -| -|// Arguments for vm_call and vm_pcall. -|.define INARG_BASE, SAVE_CFRAME // Overwritten by SAVE_CFRAME! -| -|// Arguments for vm_cpcall. -|.define INARG_CP_CALL, SAVE_ERRF -|.define INARG_CP_UD, SAVE_NRES -|.define INARG_CP_FUNC, SAVE_CFRAME -| -|//----------------------------------------------------------------------- -|.elif X64WIN // x64/Windows stack layout -| -|.define CFRAME_SPACE, aword*5 // Delta for rsp (see <--). -|.macro saveregs_ -| push rdi; push rsi; push rbx -| sub rsp, CFRAME_SPACE -|.endmacro -|.macro saveregs -| push rbp; saveregs_ -|.endmacro -|.macro restoreregs -| add rsp, CFRAME_SPACE -| pop rbx; pop rsi; pop rdi; pop rbp -|.endmacro -| -|.define SAVE_CFRAME, aword [rsp+aword*13] -|.define SAVE_PC, dword [rsp+dword*25] -|.define SAVE_L, dword [rsp+dword*24] -|.define SAVE_ERRF, dword [rsp+dword*23] -|.define SAVE_NRES, dword [rsp+dword*22] -|.define TMP2, dword [rsp+dword*21] -|.define TMP1, dword [rsp+dword*20] -|//----- 16 byte aligned, ^^^ 32 byte register save area, owned by interpreter -|.define SAVE_RET, aword [rsp+aword*9] //<-- rsp entering interpreter. -|.define SAVE_R4, aword [rsp+aword*8] -|.define SAVE_R3, aword [rsp+aword*7] -|.define SAVE_R2, aword [rsp+aword*6] -|.define SAVE_R1, aword [rsp+aword*5] //<-- rsp after register saves. -|.define ARG5, aword [rsp+aword*4] -|.define CSAVE_4, aword [rsp+aword*3] -|.define CSAVE_3, aword [rsp+aword*2] -|.define CSAVE_2, aword [rsp+aword*1] -|.define CSAVE_1, aword [rsp] //<-- rsp while in interpreter. -|//----- 16 byte aligned, ^^^ 32 byte register save area, owned by callee -| -|// TMPQ overlaps TMP1/TMP2. MULTRES overlaps TMP2 (and TMPQ). -|.define TMPQ, qword [rsp+aword*10] -|.define MULTRES, TMP2 -|.define TMPa, ARG5 -|.define ARG5d, dword [rsp+aword*4] -|.define TMP3, ARG5d -| -|//----------------------------------------------------------------------- -|.else // x64/POSIX stack layout -| -|.define CFRAME_SPACE, aword*5 // Delta for rsp (see <--). -|.macro saveregs_ -| push rbx; push r15; push r14 -| sub rsp, CFRAME_SPACE -|.endmacro -|.macro saveregs -| push rbp; saveregs_ -|.endmacro -|.macro restoreregs -| add rsp, CFRAME_SPACE -| pop r14; pop r15; pop rbx; pop rbp -|.endmacro -| -|//----- 16 byte aligned, -|.define SAVE_RET, aword [rsp+aword*9] //<-- rsp entering interpreter. -|.define SAVE_R4, aword [rsp+aword*8] -|.define SAVE_R3, aword [rsp+aword*7] -|.define SAVE_R2, aword [rsp+aword*6] -|.define SAVE_R1, aword [rsp+aword*5] //<-- rsp after register saves. -|.define SAVE_CFRAME, aword [rsp+aword*4] -|.define SAVE_PC, dword [rsp+dword*7] -|.define SAVE_L, dword [rsp+dword*6] -|.define SAVE_ERRF, dword [rsp+dword*5] -|.define SAVE_NRES, dword [rsp+dword*4] -|.define TMPa, aword [rsp+aword*1] -|.define TMP2, dword [rsp+dword*1] -|.define TMP1, dword [rsp] //<-- rsp while in interpreter. -|//----- 16 byte aligned -| -|// TMPQ overlaps TMP1/TMP2. MULTRES overlaps TMP2 (and TMPQ). -|.define TMPQ, qword [rsp] -|.define TMP3, dword [rsp+aword*1] -|.define MULTRES, TMP2 -| -|.endif -| -|//----------------------------------------------------------------------- -| -|// Instruction headers. -|.macro ins_A; .endmacro -|.macro ins_AD; .endmacro -|.macro ins_AJ; .endmacro -|.macro ins_ABC; movzx RB, RCH; movzx RC, RCL; .endmacro -|.macro ins_AB_; movzx RB, RCH; .endmacro -|.macro ins_A_C; movzx RC, RCL; .endmacro -|.macro ins_AND; not RDa; .endmacro -| -|// Instruction decode+dispatch. Carefully tuned (nope, lodsd is not faster). -|.macro ins_NEXT -| mov RC, [PC] -| movzx RA, RCH -| movzx OP, RCL -| add PC, 4 -| shr RC, 16 -|.if X64 -| jmp aword [DISPATCH+OP*8] -|.else -| jmp aword [DISPATCH+OP*4] -|.endif -|.endmacro -| -|// Instruction footer. -|.if 1 -| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use. -| .define ins_next, ins_NEXT -| .define ins_next_, ins_NEXT -|.else -| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch. -| // Affects only certain kinds of benchmarks (and only with -j off). -| // Around 10%-30% slower on Core2, a lot more slower on P4. -| .macro ins_next -| jmp ->ins_next -| .endmacro -| .macro ins_next_ -| ->ins_next: -| ins_NEXT -| .endmacro -|.endif -| -|// Call decode and dispatch. -|.macro ins_callt -| // BASE = new base, RB = LFUNC, RD = nargs+1, [BASE-4] = PC -| mov PC, LFUNC:RB->pc -| mov RA, [PC] -| movzx OP, RAL -| movzx RA, RAH -| add PC, 4 -|.if X64 -| jmp aword [DISPATCH+OP*8] -|.else -| jmp aword [DISPATCH+OP*4] -|.endif -|.endmacro -| -|.macro ins_call -| // BASE = new base, RB = LFUNC, RD = nargs+1 -| mov [BASE-4], PC -| ins_callt -|.endmacro -| -|//----------------------------------------------------------------------- -| -|// Macros to test operand types. -|.macro checktp, reg, tp; cmp dword [BASE+reg*8+4], tp; .endmacro -|.macro checknum, reg, target; checktp reg, LJ_TISNUM; jae target; .endmacro -|.macro checkint, reg, target; checktp reg, LJ_TISNUM; jne target; .endmacro -|.macro checkstr, reg, target; checktp reg, LJ_TSTR; jne target; .endmacro -|.macro checktab, reg, target; checktp reg, LJ_TTAB; jne target; .endmacro -| -|// These operands must be used with movzx. -|.define PC_OP, byte [PC-4] -|.define PC_RA, byte [PC-3] -|.define PC_RB, byte [PC-1] -|.define PC_RC, byte [PC-2] -|.define PC_RD, word [PC-2] -| -|.macro branchPC, reg -| lea PC, [PC+reg*4-BCBIAS_J*4] -|.endmacro -| -|// Assumes DISPATCH is relative to GL. -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -| -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) -| -|// Decrement hashed hotcount and trigger trace recorder if zero. -|.macro hotloop, reg -| mov reg, PC -| shr reg, 1 -| and reg, HOTCOUNT_PCMASK -| sub word [DISPATCH+reg+GG_DISP2HOT], HOTCOUNT_LOOP -| jb ->vm_hotloop -|.endmacro -| -|.macro hotcall, reg -| mov reg, PC -| shr reg, 1 -| and reg, HOTCOUNT_PCMASK -| sub word [DISPATCH+reg+GG_DISP2HOT], HOTCOUNT_CALL -| jb ->vm_hotcall -|.endmacro -| -|// Set current VM state. -|.macro set_vmstate, st -| mov dword [DISPATCH+DISPATCH_GL(vmstate)], ~LJ_VMST_..st -|.endmacro -| -|// Annoying x87 stuff: support for two compare variants. -|.macro fcomparepp // Compare and pop st0 >< st1. -||if (cmov) { -| fucomip st1 -| fpop -||} else { -| fucompp -| fnstsw ax // eax modified! -| sahf -||} -|.endmacro -| -|.macro fdup; fld st0; .endmacro -|.macro fpop1; fstp st1; .endmacro -| -|// Synthesize SSE FP constants. -|.macro sseconst_abs, reg, tmp // Synthesize abs mask. -|.if X64 -| mov64 tmp, U64x(7fffffff,ffffffff); movd reg, tmp -|.else -| pxor reg, reg; pcmpeqd reg, reg; psrlq reg, 1 -|.endif -|.endmacro -| -|.macro sseconst_hi, reg, tmp, val // Synthesize hi-32 bit const. -|.if X64 -| mov64 tmp, U64x(val,00000000); movd reg, tmp -|.else -| mov tmp, 0x .. val; movd reg, tmp; pshufd reg, reg, 0x51 -|.endif -|.endmacro -| -|.macro sseconst_sign, reg, tmp // Synthesize sign mask. -| sseconst_hi reg, tmp, 80000000 -|.endmacro -|.macro sseconst_1, reg, tmp // Synthesize 1.0. -| sseconst_hi reg, tmp, 3ff00000 -|.endmacro -|.macro sseconst_m1, reg, tmp // Synthesize -1.0. -| sseconst_hi reg, tmp, bff00000 -|.endmacro -|.macro sseconst_2p52, reg, tmp // Synthesize 2^52. -| sseconst_hi reg, tmp, 43300000 -|.endmacro -|.macro sseconst_tobit, reg, tmp // Synthesize 2^52 + 2^51. -| sseconst_hi reg, tmp, 43380000 -|.endmacro -| -|// Move table write barrier back. Overwrites reg. -|.macro barrierback, tab, reg -| and byte tab->marked, (uint8_t)~LJ_GC_BLACK // black2gray(tab) -| mov reg, [DISPATCH+DISPATCH_GL(gc.grayagain)] -| mov [DISPATCH+DISPATCH_GL(gc.grayagain)], tab -| mov tab->gclist, reg -|.endmacro -| -|//----------------------------------------------------------------------- - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx, int cmov, int sse) -{ - |.code_sub - | - |//----------------------------------------------------------------------- - |//-- Return handling ---------------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_returnp: - | test PC, FRAME_P - | jz ->cont_dispatch - | - | // Return from pcall or xpcall fast func. - | and PC, -8 - | sub BASE, PC // Restore caller base. - | lea RAa, [RA+PC-8] // Rebase RA and prepend one result. - | mov PC, [BASE-4] // Fetch PC of previous frame. - | // Prepending may overwrite the pcall frame, so do it at the end. - | mov dword [BASE+RA+4], LJ_TTRUE // Prepend true to results. - | - |->vm_returnc: - | add RD, 1 // RD = nresults+1 - | mov MULTRES, RD - | test PC, FRAME_TYPE - | jz ->BC_RET_Z // Handle regular return to Lua. - | - |->vm_return: - | // BASE = base, RA = resultofs, RD = nresults+1 (= MULTRES), PC = return - | xor PC, FRAME_C - | test PC, FRAME_TYPE - | jnz ->vm_returnp - | - | // Return to C. - | set_vmstate C - | and PC, -8 - | sub PC, BASE - | neg PC // Previous base = BASE - delta. - | - | sub RD, 1 - | jz >2 - |1: // Move results down. - |.if X64 - | mov RBa, [BASE+RA] - | mov [BASE-8], RBa - |.else - | mov RB, [BASE+RA] - | mov [BASE-8], RB - | mov RB, [BASE+RA+4] - | mov [BASE-4], RB - |.endif - | add BASE, 8 - | sub RD, 1 - | jnz <1 - |2: - | mov L:RB, SAVE_L - | mov L:RB->base, PC - |3: - | mov RD, MULTRES - | mov RA, SAVE_NRES // RA = wanted nresults+1 - |4: - | cmp RA, RD - | jne >6 // More/less results wanted? - |5: - | sub BASE, 8 - | mov L:RB->top, BASE - | - |->vm_leave_cp: - | mov RAa, SAVE_CFRAME // Restore previous C frame. - | mov L:RB->cframe, RAa - | xor eax, eax // Ok return status for vm_pcall. - | - |->vm_leave_unw: - | restoreregs - | ret - | - |6: - | jb >7 // Less results wanted? - | // More results wanted. Check stack size and fill up results with nil. - | cmp BASE, L:RB->maxstack - | ja >8 - | mov dword [BASE-4], LJ_TNIL - | add BASE, 8 - | add RD, 1 - | jmp <4 - | - |7: // Less results wanted. - | test RA, RA - | jz <5 // But check for LUA_MULTRET+1. - | sub RA, RD // Negative result! - | lea BASE, [BASE+RA*8] // Correct top. - | jmp <5 - | - |8: // Corner case: need to grow stack for filling up results. - | // This can happen if: - | // - A C function grows the stack (a lot). - | // - The GC shrinks the stack in between. - | // - A return back from a lua_call() with (high) nresults adjustment. - | mov L:RB->top, BASE // Save current top held in BASE (yes). - | mov MULTRES, RD // Need to fill only remainder with nil. - | mov FCARG2, RA - | mov FCARG1, L:RB - | call extern lj_state_growstack@8 // (lua_State *L, int n) - | mov BASE, L:RB->top // Need the (realloced) L->top in BASE. - | jmp <3 - | - |->vm_unwind_c@8: // Unwind C stack, return from vm_pcall. - | // (void *cframe, int errcode) - |.if X64 - | mov eax, CARG2d // Error return status for vm_pcall. - | mov rsp, CARG1 - |.else - | mov eax, FCARG2 // Error return status for vm_pcall. - | mov esp, FCARG1 - |.endif - |->vm_unwind_c_eh: // Landing pad for external unwinder. - | mov L:RB, SAVE_L - | mov GL:RB, L:RB->glref - | mov dword GL:RB->vmstate, ~LJ_VMST_C - | jmp ->vm_leave_unw - | - |->vm_unwind_rethrow: - |.if X64 and not X64WIN - | mov FCARG1, SAVE_L - | mov FCARG2, eax - | restoreregs - | jmp extern lj_err_throw@8 // (lua_State *L, int errcode) - |.endif - | - |->vm_unwind_ff@4: // Unwind C stack, return from ff pcall. - | // (void *cframe) - |.if X64 - | and CARG1, CFRAME_RAWMASK - | mov rsp, CARG1 - |.else - | and FCARG1, CFRAME_RAWMASK - | mov esp, FCARG1 - |.endif - |->vm_unwind_ff_eh: // Landing pad for external unwinder. - | mov L:RB, SAVE_L - | mov RAa, -8 // Results start at BASE+RA = BASE-8. - | mov RD, 1+1 // Really 1+2 results, incr. later. - | mov BASE, L:RB->base - | mov DISPATCH, L:RB->glref // Setup pointer to dispatch table. - | add DISPATCH, GG_G2DISP - | mov PC, [BASE-4] // Fetch PC of previous frame. - | mov dword [BASE-4], LJ_TFALSE // Prepend false to error message. - | set_vmstate INTERP - | jmp ->vm_returnc // Increments RD/MULTRES and returns. - | - |//----------------------------------------------------------------------- - |//-- Grow stack for calls ----------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_growstack_c: // Grow stack for C function. - | mov FCARG2, LUA_MINSTACK - | jmp >2 - | - |->vm_growstack_v: // Grow stack for vararg Lua function. - | sub RD, 8 - | jmp >1 - | - |->vm_growstack_f: // Grow stack for fixarg Lua function. - | // BASE = new base, RD = nargs+1, RB = L, PC = first PC - | lea RD, [BASE+NARGS:RD*8-8] - |1: - | movzx RA, byte [PC-4+PC2PROTO(framesize)] - | add PC, 4 // Must point after first instruction. - | mov L:RB->base, BASE - | mov L:RB->top, RD - | mov SAVE_PC, PC - | mov FCARG2, RA - |2: - | // RB = L, L->base = new base, L->top = top - | mov FCARG1, L:RB - | call extern lj_state_growstack@8 // (lua_State *L, int n) - | mov BASE, L:RB->base - | mov RD, L:RB->top - | mov LFUNC:RB, [BASE-8] - | sub RD, BASE - | shr RD, 3 - | add NARGS:RD, 1 - | // BASE = new base, RB = LFUNC, RD = nargs+1 - | ins_callt // Just retry the call. - | - |//----------------------------------------------------------------------- - |//-- Entry points into the assembler VM --------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_resume: // Setup C frame and resume thread. - | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0) - | saveregs - |.if X64 - | mov L:RB, CARG1d // Caveat: CARG1d may be RA. - | mov SAVE_L, CARG1d - | mov RA, CARG2d - |.else - | mov L:RB, SAVE_L - | mov RA, INARG_BASE // Caveat: overlaps SAVE_CFRAME! - |.endif - | mov PC, FRAME_CP - | xor RD, RD - | lea KBASEa, [esp+CFRAME_RESUME] - | mov DISPATCH, L:RB->glref // Setup pointer to dispatch table. - | add DISPATCH, GG_G2DISP - | mov L:RB->cframe, KBASEa - | mov SAVE_PC, RD // Any value outside of bytecode is ok. - | mov SAVE_CFRAME, RDa - |.if X64 - | mov SAVE_NRES, RD - | mov SAVE_ERRF, RD - |.endif - | cmp byte L:RB->status, RDL - | je >3 // Initial resume (like a call). - | - | // Resume after yield (like a return). - | set_vmstate INTERP - | mov byte L:RB->status, RDL - | mov BASE, L:RB->base - | mov RD, L:RB->top - | sub RD, RA - | shr RD, 3 - | add RD, 1 // RD = nresults+1 - | sub RA, BASE // RA = resultofs - | mov PC, [BASE-4] - | mov MULTRES, RD - | test PC, FRAME_TYPE - | jz ->BC_RET_Z - | jmp ->vm_return - | - |->vm_pcall: // Setup protected C frame and enter VM. - | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef) - | saveregs - | mov PC, FRAME_CP - |.if X64 - | mov SAVE_ERRF, CARG4d - |.endif - | jmp >1 - | - |->vm_call: // Setup C frame and enter VM. - | // (lua_State *L, TValue *base, int nres1) - | saveregs - | mov PC, FRAME_C - | - |1: // Entry point for vm_pcall above (PC = ftype). - |.if X64 - | mov SAVE_NRES, CARG3d - | mov L:RB, CARG1d // Caveat: CARG1d may be RA. - | mov SAVE_L, CARG1d - | mov RA, CARG2d - |.else - | mov L:RB, SAVE_L - | mov RA, INARG_BASE // Caveat: overlaps SAVE_CFRAME! - |.endif - | - | mov KBASEa, L:RB->cframe // Add our C frame to cframe chain. - | mov SAVE_CFRAME, KBASEa - | mov SAVE_PC, L:RB // Any value outside of bytecode is ok. - |.if X64 - | mov L:RB->cframe, rsp - |.else - | mov L:RB->cframe, esp - |.endif - | - |2: // Entry point for vm_cpcall below (RA = base, RB = L, PC = ftype). - | mov DISPATCH, L:RB->glref // Setup pointer to dispatch table. - | add DISPATCH, GG_G2DISP - | - |3: // Entry point for vm_resume above (RA = base, RB = L, PC = ftype). - | set_vmstate INTERP - | mov BASE, L:RB->base // BASE = old base (used in vmeta_call). - | add PC, RA - | sub PC, BASE // PC = frame delta + frame type - | - | mov RD, L:RB->top - | sub RD, RA - | shr NARGS:RD, 3 - | add NARGS:RD, 1 // RD = nargs+1 - | - |->vm_call_dispatch: - | mov LFUNC:RB, [RA-8] - | cmp dword [RA-4], LJ_TFUNC - | jne ->vmeta_call // Ensure KBASE defined and != BASE. - | - |->vm_call_dispatch_f: - | mov BASE, RA - | ins_call - | // BASE = new base, RB = func, RD = nargs+1, PC = caller PC - | - |->vm_cpcall: // Setup protected C frame, call C. - | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp) - | saveregs - |.if X64 - | mov L:RB, CARG1d // Caveat: CARG1d may be RA. - | mov SAVE_L, CARG1d - |.else - | mov L:RB, SAVE_L - | // Caveat: INARG_CP_* and SAVE_CFRAME/SAVE_NRES/SAVE_ERRF overlap! - | mov RC, INARG_CP_UD // Get args before they are overwritten. - | mov RA, INARG_CP_FUNC - | mov BASE, INARG_CP_CALL - |.endif - | mov SAVE_PC, L:RB // Any value outside of bytecode is ok. - | - | mov KBASE, L:RB->stack // Compute -savestack(L, L->top). - | sub KBASE, L:RB->top - | mov SAVE_ERRF, 0 // No error function. - | mov SAVE_NRES, KBASE // Neg. delta means cframe w/o frame. - | // Handler may change cframe_nres(L->cframe) or cframe_errfunc(L->cframe). - | - |.if X64 - | mov KBASEa, L:RB->cframe // Add our C frame to cframe chain. - | mov SAVE_CFRAME, KBASEa - | mov L:RB->cframe, rsp - | - | call CARG4 // (lua_State *L, lua_CFunction func, void *ud) - |.else - | mov ARG3, RC // Have to copy args downwards. - | mov ARG2, RA - | mov ARG1, L:RB - | - | mov KBASE, L:RB->cframe // Add our C frame to cframe chain. - | mov SAVE_CFRAME, KBASE - | mov L:RB->cframe, esp - | - | call BASE // (lua_State *L, lua_CFunction func, void *ud) - |.endif - | // TValue * (new base) or NULL returned in eax (RC). - | test RC, RC - | jz ->vm_leave_cp // No base? Just remove C frame. - | mov RA, RC - | mov PC, FRAME_CP - | jmp <2 // Else continue with the call. - | - |//----------------------------------------------------------------------- - |//-- Metamethod handling ------------------------------------------------ - |//----------------------------------------------------------------------- - | - |//-- Continuation dispatch ---------------------------------------------- - | - |->cont_dispatch: - | // BASE = meta base, RA = resultofs, RD = nresults+1 (also in MULTRES) - | add RA, BASE - | and PC, -8 - | mov RB, BASE - | sub BASE, PC // Restore caller BASE. - | mov dword [RA+RD*8-4], LJ_TNIL // Ensure one valid arg. - | mov RC, RA // ... in [RC] - | mov PC, [RB-12] // Restore PC from [cont|PC]. - |.if X64 - | movsxd RAa, dword [RB-16] // May be negative on WIN64 with debug. -#if LJ_HASFFI - | cmp RA, 1 - | jbe >1 -#endif - | lea KBASEa, qword [=>0] - | add RAa, KBASEa - |.else - | mov RA, dword [RB-16] -#if LJ_HASFFI - | cmp RA, 1 - | jbe >1 -#endif - |.endif - | mov LFUNC:KBASE, [BASE-8] - | mov KBASE, LFUNC:KBASE->pc - | mov KBASE, [KBASE+PC2PROTO(k)] - | // BASE = base, RC = result, RB = meta base - | jmp RAa // Jump to continuation. - | -#if LJ_HASFFI - |1: - | je ->cont_ffi_callback // cont = 1: return from FFI callback. - | // cont = 0: Tail call from C function. - | sub RB, BASE - | shr RB, 3 - | lea RD, [RB-1] - | jmp ->vm_call_tail -#endif - | - |->cont_cat: // BASE = base, RC = result, RB = mbase - | movzx RA, PC_RB - | sub RB, 16 - | lea RA, [BASE+RA*8] - | sub RA, RB - | je ->cont_ra - | neg RA - | shr RA, 3 - |.if X64WIN - | mov CARG3d, RA - | mov L:CARG1d, SAVE_L - | mov L:CARG1d->base, BASE - | mov RCa, [RC] - | mov [RB], RCa - | mov CARG2d, RB - |.elif X64 - | mov L:CARG1d, SAVE_L - | mov L:CARG1d->base, BASE - | mov CARG3d, RA - | mov RAa, [RC] - | mov [RB], RAa - | mov CARG2d, RB - |.else - | mov ARG3, RA - | mov RA, [RC+4] - | mov RC, [RC] - | mov [RB+4], RA - | mov [RB], RC - | mov ARG2, RB - |.endif - | jmp ->BC_CAT_Z - | - |//-- Table indexing metamethods ----------------------------------------- - | - |->vmeta_tgets: - | mov TMP1, RC // RC = GCstr * - | mov TMP2, LJ_TSTR - | lea RCa, TMP1 // Store temp. TValue in TMP1/TMP2. - | cmp PC_OP, BC_GGET - | jne >1 - | lea RA, [DISPATCH+DISPATCH_GL(tmptv)] // Store fn->l.env in g->tmptv. - | mov [RA], TAB:RB // RB = GCtab * - | mov dword [RA+4], LJ_TTAB - | mov RB, RA - | jmp >2 - | - |->vmeta_tgetb: - | movzx RC, PC_RC - if (LJ_DUALNUM) { - | mov TMP2, LJ_TISNUM - | mov TMP1, RC - } else if (sse) { - | cvtsi2sd xmm0, RC - | movsd TMPQ, xmm0 - } else { - |.if not X64 - | mov ARG4, RC - | fild ARG4 - | fstp TMPQ - |.endif - } - | lea RCa, TMPQ // Store temp. TValue in TMPQ. - | jmp >1 - | - |->vmeta_tgetv: - | movzx RC, PC_RC // Reload TValue *k from RC. - | lea RC, [BASE+RC*8] - |1: - | movzx RB, PC_RB // Reload TValue *t from RB. - | lea RB, [BASE+RB*8] - |2: - |.if X64 - | mov L:CARG1d, SAVE_L - | mov L:CARG1d->base, BASE // Caveat: CARG2d/CARG3d may be BASE. - | mov CARG2d, RB - | mov CARG3, RCa // May be 64 bit ptr to stack. - | mov L:RB, L:CARG1d - |.else - | mov ARG2, RB - | mov L:RB, SAVE_L - | mov ARG3, RC - | mov ARG1, L:RB - | mov L:RB->base, BASE - |.endif - | mov SAVE_PC, PC - | call extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k) - | // TValue * (finished) or NULL (metamethod) returned in eax (RC). - | mov BASE, L:RB->base - | test RC, RC - | jz >3 - |->cont_ra: // BASE = base, RC = result - | movzx RA, PC_RA - |.if X64 - | mov RBa, [RC] - | mov [BASE+RA*8], RBa - |.else - | mov RB, [RC+4] - | mov RC, [RC] - | mov [BASE+RA*8+4], RB - | mov [BASE+RA*8], RC - |.endif - | ins_next - | - |3: // Call __index metamethod. - | // BASE = base, L->top = new base, stack = cont/func/t/k - | mov RA, L:RB->top - | mov [RA-12], PC // [cont|PC] - | lea PC, [RA+FRAME_CONT] - | sub PC, BASE - | mov LFUNC:RB, [RA-8] // Guaranteed to be a function here. - | mov NARGS:RD, 2+1 // 2 args for func(t, k). - | jmp ->vm_call_dispatch_f - | - |//----------------------------------------------------------------------- - | - |->vmeta_tsets: - | mov TMP1, RC // RC = GCstr * - | mov TMP2, LJ_TSTR - | lea RCa, TMP1 // Store temp. TValue in TMP1/TMP2. - | cmp PC_OP, BC_GSET - | jne >1 - | lea RA, [DISPATCH+DISPATCH_GL(tmptv)] // Store fn->l.env in g->tmptv. - | mov [RA], TAB:RB // RB = GCtab * - | mov dword [RA+4], LJ_TTAB - | mov RB, RA - | jmp >2 - | - |->vmeta_tsetb: - | movzx RC, PC_RC - if (LJ_DUALNUM) { - | mov TMP2, LJ_TISNUM - | mov TMP1, RC - } else if (sse) { - | cvtsi2sd xmm0, RC - | movsd TMPQ, xmm0 - } else { - |.if not X64 - | mov ARG4, RC - | fild ARG4 - | fstp TMPQ - |.endif - } - | lea RCa, TMPQ // Store temp. TValue in TMPQ. - | jmp >1 - | - |->vmeta_tsetv: - | movzx RC, PC_RC // Reload TValue *k from RC. - | lea RC, [BASE+RC*8] - |1: - | movzx RB, PC_RB // Reload TValue *t from RB. - | lea RB, [BASE+RB*8] - |2: - |.if X64 - | mov L:CARG1d, SAVE_L - | mov L:CARG1d->base, BASE // Caveat: CARG2d/CARG3d may be BASE. - | mov CARG2d, RB - | mov CARG3, RCa // May be 64 bit ptr to stack. - | mov L:RB, L:CARG1d - |.else - | mov ARG2, RB - | mov L:RB, SAVE_L - | mov ARG3, RC - | mov ARG1, L:RB - | mov L:RB->base, BASE - |.endif - | mov SAVE_PC, PC - | call extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k) - | // TValue * (finished) or NULL (metamethod) returned in eax (RC). - | mov BASE, L:RB->base - | test RC, RC - | jz >3 - | // NOBARRIER: lj_meta_tset ensures the table is not black. - | movzx RA, PC_RA - |.if X64 - | mov RBa, [BASE+RA*8] - | mov [RC], RBa - |.else - | mov RB, [BASE+RA*8+4] - | mov RA, [BASE+RA*8] - | mov [RC+4], RB - | mov [RC], RA - |.endif - |->cont_nop: // BASE = base, (RC = result) - | ins_next - | - |3: // Call __newindex metamethod. - | // BASE = base, L->top = new base, stack = cont/func/t/k/(v) - | mov RA, L:RB->top - | mov [RA-12], PC // [cont|PC] - | movzx RC, PC_RA - | // Copy value to third argument. - |.if X64 - | mov RBa, [BASE+RC*8] - | mov [RA+16], RBa - |.else - | mov RB, [BASE+RC*8+4] - | mov RC, [BASE+RC*8] - | mov [RA+20], RB - | mov [RA+16], RC - |.endif - | lea PC, [RA+FRAME_CONT] - | sub PC, BASE - | mov LFUNC:RB, [RA-8] // Guaranteed to be a function here. - | mov NARGS:RD, 3+1 // 3 args for func(t, k, v). - | jmp ->vm_call_dispatch_f - | - |//-- Comparison metamethods --------------------------------------------- - | - |->vmeta_comp: - |.if X64 - | mov L:RB, SAVE_L - | mov L:RB->base, BASE // Caveat: CARG2d/CARG3d == BASE. - |.if X64WIN - | lea CARG3d, [BASE+RD*8] - | lea CARG2d, [BASE+RA*8] - |.else - | lea CARG2d, [BASE+RA*8] - | lea CARG3d, [BASE+RD*8] - |.endif - | mov CARG1d, L:RB // Caveat: CARG1d/CARG4d == RA. - | movzx CARG4d, PC_OP - |.else - | movzx RB, PC_OP - | lea RD, [BASE+RD*8] - | lea RA, [BASE+RA*8] - | mov ARG4, RB - | mov L:RB, SAVE_L - | mov ARG3, RD - | mov ARG2, RA - | mov ARG1, L:RB - | mov L:RB->base, BASE - |.endif - | mov SAVE_PC, PC - | call extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op) - | // 0/1 or TValue * (metamethod) returned in eax (RC). - |3: - | mov BASE, L:RB->base - | cmp RC, 1 - | ja ->vmeta_binop - |4: - | lea PC, [PC+4] - | jb >6 - |5: - | movzx RD, PC_RD - | branchPC RD - |6: - | ins_next - | - |->cont_condt: // BASE = base, RC = result - | add PC, 4 - | cmp dword [RC+4], LJ_TISTRUECOND // Branch if result is true. - | jb <5 - | jmp <6 - | - |->cont_condf: // BASE = base, RC = result - | cmp dword [RC+4], LJ_TISTRUECOND // Branch if result is false. - | jmp <4 - | - |->vmeta_equal: - | sub PC, 4 - |.if X64WIN - | mov CARG3d, RD - | mov CARG4d, RB - | mov L:RB, SAVE_L - | mov L:RB->base, BASE // Caveat: CARG2d == BASE. - | mov CARG2d, RA - | mov CARG1d, L:RB // Caveat: CARG1d == RA. - |.elif X64 - | mov CARG2d, RA - | mov CARG4d, RB // Caveat: CARG4d == RA. - | mov L:RB, SAVE_L - | mov L:RB->base, BASE // Caveat: CARG3d == BASE. - | mov CARG3d, RD - | mov CARG1d, L:RB - |.else - | mov ARG4, RB - | mov L:RB, SAVE_L - | mov ARG3, RD - | mov ARG2, RA - | mov ARG1, L:RB - | mov L:RB->base, BASE - |.endif - | mov SAVE_PC, PC - | call extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne) - | // 0/1 or TValue * (metamethod) returned in eax (RC). - | jmp <3 - | - |->vmeta_equal_cd: -#if LJ_HASFFI - | sub PC, 4 - | mov L:RB, SAVE_L - | mov L:RB->base, BASE - | mov FCARG1, L:RB - | mov FCARG2, dword [PC-4] - | mov SAVE_PC, PC - | call extern lj_meta_equal_cd@8 // (lua_State *L, BCIns ins) - | // 0/1 or TValue * (metamethod) returned in eax (RC). - | jmp <3 -#endif - | - |//-- Arithmetic metamethods --------------------------------------------- - | - |->vmeta_arith_vno: -#if LJ_DUALNUM - | movzx RB, PC_RB -#endif - |->vmeta_arith_vn: - | lea RC, [KBASE+RC*8] - | jmp >1 - | - |->vmeta_arith_nvo: -#if LJ_DUALNUM - | movzx RC, PC_RC -#endif - |->vmeta_arith_nv: - | lea RC, [KBASE+RC*8] - | lea RB, [BASE+RB*8] - | xchg RB, RC - | jmp >2 - | - |->vmeta_unm: - | lea RC, [BASE+RD*8] - | mov RB, RC - | jmp >2 - | - |->vmeta_arith_vvo: -#if LJ_DUALNUM - | movzx RB, PC_RB -#endif - |->vmeta_arith_vv: - | lea RC, [BASE+RC*8] - |1: - | lea RB, [BASE+RB*8] - |2: - | lea RA, [BASE+RA*8] - |.if X64WIN - | mov CARG3d, RB - | mov CARG4d, RC - | movzx RC, PC_OP - | mov ARG5d, RC - | mov L:RB, SAVE_L - | mov L:RB->base, BASE // Caveat: CARG2d == BASE. - | mov CARG2d, RA - | mov CARG1d, L:RB // Caveat: CARG1d == RA. - |.elif X64 - | movzx CARG5d, PC_OP - | mov CARG2d, RA - | mov CARG4d, RC // Caveat: CARG4d == RA. - | mov L:CARG1d, SAVE_L - | mov L:CARG1d->base, BASE // Caveat: CARG3d == BASE. - | mov CARG3d, RB - | mov L:RB, L:CARG1d - |.else - | mov ARG3, RB - | mov L:RB, SAVE_L - | mov ARG4, RC - | movzx RC, PC_OP - | mov ARG2, RA - | mov ARG5, RC - | mov ARG1, L:RB - | mov L:RB->base, BASE - |.endif - | mov SAVE_PC, PC - | call extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op) - | // NULL (finished) or TValue * (metamethod) returned in eax (RC). - | mov BASE, L:RB->base - | test RC, RC - | jz ->cont_nop - | - | // Call metamethod for binary op. - |->vmeta_binop: - | // BASE = base, RC = new base, stack = cont/func/o1/o2 - | mov RA, RC - | sub RC, BASE - | mov [RA-12], PC // [cont|PC] - | lea PC, [RC+FRAME_CONT] - | mov NARGS:RD, 2+1 // 2 args for func(o1, o2). - | jmp ->vm_call_dispatch - | - |->vmeta_len: - | mov L:RB, SAVE_L - | mov L:RB->base, BASE - | lea FCARG2, [BASE+RD*8] // Caveat: FCARG2 == BASE - | mov L:FCARG1, L:RB - | mov SAVE_PC, PC - | call extern lj_meta_len@8 // (lua_State *L, TValue *o) - | // NULL (retry) or TValue * (metamethod) returned in eax (RC). - | mov BASE, L:RB->base -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | test RC, RC - | jne ->vmeta_binop // Binop call for compatibility. - | movzx RD, PC_RD - | mov TAB:FCARG1, [BASE+RD*8] - | jmp ->BC_LEN_Z -#else - | jmp ->vmeta_binop // Binop call for compatibility. -#endif - | - |//-- Call metamethod ---------------------------------------------------- - | - |->vmeta_call_ra: - | lea RA, [BASE+RA*8+8] - |->vmeta_call: // Resolve and call __call metamethod. - | // BASE = old base, RA = new base, RC = nargs+1, PC = return - | mov TMP2, RA // Save RA, RC for us. - | mov TMP1, NARGS:RD - | sub RA, 8 - |.if X64 - | mov L:RB, SAVE_L - | mov L:RB->base, BASE // Caveat: CARG2d/CARG3d may be BASE. - | mov CARG2d, RA - | lea CARG3d, [RA+NARGS:RD*8] - | mov CARG1d, L:RB // Caveat: CARG1d may be RA. - |.else - | lea RC, [RA+NARGS:RD*8] - | mov L:RB, SAVE_L - | mov ARG2, RA - | mov ARG3, RC - | mov ARG1, L:RB - | mov L:RB->base, BASE // This is the callers base! - |.endif - | mov SAVE_PC, PC - | call extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) - | mov BASE, L:RB->base - | mov RA, TMP2 - | mov NARGS:RD, TMP1 - | mov LFUNC:RB, [RA-8] - | add NARGS:RD, 1 - | // This is fragile. L->base must not move, KBASE must always be defined. - | cmp KBASE, BASE // Continue with CALLT if flag set. - | je ->BC_CALLT_Z - | mov BASE, RA - | ins_call // Otherwise call resolved metamethod. - | - |//-- Argument coercion for 'for' statement ------------------------------ - | - |->vmeta_for: - | mov L:RB, SAVE_L - | mov L:RB->base, BASE - | mov FCARG2, RA // Caveat: FCARG2 == BASE - | mov L:FCARG1, L:RB // Caveat: FCARG1 == RA - | mov SAVE_PC, PC - | call extern lj_meta_for@8 // (lua_State *L, TValue *base) - | mov BASE, L:RB->base - | mov RC, [PC-4] - | movzx RA, RCH - | movzx OP, RCL - | shr RC, 16 - |.if X64 - | jmp aword [DISPATCH+OP*8+GG_DISP2STATIC] // Retry FORI or JFORI. - |.else - | jmp aword [DISPATCH+OP*4+GG_DISP2STATIC] // Retry FORI or JFORI. - |.endif - | - |//----------------------------------------------------------------------- - |//-- Fast functions ----------------------------------------------------- - |//----------------------------------------------------------------------- - | - |.macro .ffunc, name - |->ff_ .. name: - |.endmacro - | - |.macro .ffunc_1, name - |->ff_ .. name: - | cmp NARGS:RD, 1+1; jb ->fff_fallback - |.endmacro - | - |.macro .ffunc_2, name - |->ff_ .. name: - | cmp NARGS:RD, 2+1; jb ->fff_fallback - |.endmacro - | - |.macro .ffunc_n, name - | .ffunc_1 name - | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback - | fld qword [BASE] - |.endmacro - | - |.macro .ffunc_n, name, op - | .ffunc_1 name - | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback - | op - | fld qword [BASE] - |.endmacro - | - |.macro .ffunc_nsse, name, op - | .ffunc_1 name - | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback - | op xmm0, qword [BASE] - |.endmacro - | - |.macro .ffunc_nsse, name - | .ffunc_nsse name, movsd - |.endmacro - | - |.macro .ffunc_nn, name - | .ffunc_2 name - | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback - | cmp dword [BASE+12], LJ_TISNUM; jae ->fff_fallback - | fld qword [BASE] - | fld qword [BASE+8] - |.endmacro - | - |.macro .ffunc_nnsse, name - | .ffunc_2 name - | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback - | cmp dword [BASE+12], LJ_TISNUM; jae ->fff_fallback - | movsd xmm0, qword [BASE] - | movsd xmm1, qword [BASE+8] - |.endmacro - | - |.macro .ffunc_nnr, name - | .ffunc_2 name - | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback - | cmp dword [BASE+12], LJ_TISNUM; jae ->fff_fallback - | fld qword [BASE+8] - | fld qword [BASE] - |.endmacro - | - |// Inlined GC threshold check. Caveat: uses label 1. - |.macro ffgccheck - | mov RB, [DISPATCH+DISPATCH_GL(gc.total)] - | cmp RB, [DISPATCH+DISPATCH_GL(gc.threshold)] - | jb >1 - | call ->fff_gcstep - |1: - |.endmacro - | - |//-- Base library: checks ----------------------------------------------- - | - |.ffunc_1 assert - | mov RB, [BASE+4] - | cmp RB, LJ_TISTRUECOND; jae ->fff_fallback - | mov PC, [BASE-4] - | mov MULTRES, RD - | mov [BASE-4], RB - | mov RB, [BASE] - | mov [BASE-8], RB - | sub RD, 2 - | jz >2 - | mov RA, BASE - |1: - | add RA, 8 - |.if X64 - | mov RBa, [RA] - | mov [RA-8], RBa - |.else - | mov RB, [RA+4] - | mov [RA-4], RB - | mov RB, [RA] - | mov [RA-8], RB - |.endif - | sub RD, 1 - | jnz <1 - |2: - | mov RD, MULTRES - | jmp ->fff_res_ - | - |.ffunc_1 type - | mov RB, [BASE+4] - |.if X64 - | mov RA, RB - | sar RA, 15 - | cmp RA, -2 - | je >3 - |.endif - | mov RC, ~LJ_TNUMX - | not RB - | cmp RC, RB - ||if (cmov) { - | cmova RC, RB - ||} else { - | jbe >1; mov RC, RB; 1: - ||} - |2: - | mov CFUNC:RB, [BASE-8] - | mov STR:RC, [CFUNC:RB+RC*8+((char *)(&((GCfuncC *)0)->upvalue))] - | mov PC, [BASE-4] - | mov dword [BASE-4], LJ_TSTR - | mov [BASE-8], STR:RC - | jmp ->fff_res1 - |.if X64 - |3: - | mov RC, ~LJ_TLIGHTUD - | jmp <2 - |.endif - | - |//-- Base library: getters and setters --------------------------------- - | - |.ffunc_1 getmetatable - | mov RB, [BASE+4] - | mov PC, [BASE-4] - | cmp RB, LJ_TTAB; jne >6 - |1: // Field metatable must be at same offset for GCtab and GCudata! - | mov TAB:RB, [BASE] - | mov TAB:RB, TAB:RB->metatable - |2: - | test TAB:RB, TAB:RB - | mov dword [BASE-4], LJ_TNIL - | jz ->fff_res1 - | mov STR:RC, [DISPATCH+DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable)] - | mov dword [BASE-4], LJ_TTAB // Store metatable as default result. - | mov [BASE-8], TAB:RB - | mov RA, TAB:RB->hmask - | and RA, STR:RC->hash - | imul RA, #NODE - | add NODE:RA, TAB:RB->node - |3: // Rearranged logic, because we expect _not_ to find the key. - | cmp dword NODE:RA->key.it, LJ_TSTR - | jne >4 - | cmp dword NODE:RA->key.gcr, STR:RC - | je >5 - |4: - | mov NODE:RA, NODE:RA->next - | test NODE:RA, NODE:RA - | jnz <3 - | jmp ->fff_res1 // Not found, keep default result. - |5: - | mov RB, [RA+4] - | cmp RB, LJ_TNIL; je ->fff_res1 // Ditto for nil value. - | mov RC, [RA] - | mov [BASE-4], RB // Return value of mt.__metatable. - | mov [BASE-8], RC - | jmp ->fff_res1 - | - |6: - | cmp RB, LJ_TUDATA; je <1 - |.if X64 - | cmp RB, LJ_TNUMX; ja >8 - | cmp RB, LJ_TISNUM; jbe >7 - | mov RB, LJ_TLIGHTUD - | jmp >8 - |7: - |.else - | cmp RB, LJ_TISNUM; ja >8 - |.endif - | mov RB, LJ_TNUMX - |8: - | not RB - | mov TAB:RB, [DISPATCH+RB*4+DISPATCH_GL(gcroot[GCROOT_BASEMT])] - | jmp <2 - | - |.ffunc_2 setmetatable - | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback - | // Fast path: no mt for table yet and not clearing the mt. - | mov TAB:RB, [BASE] - | cmp dword TAB:RB->metatable, 0; jne ->fff_fallback - | cmp dword [BASE+12], LJ_TTAB; jne ->fff_fallback - | mov TAB:RC, [BASE+8] - | mov TAB:RB->metatable, TAB:RC - | mov PC, [BASE-4] - | mov dword [BASE-4], LJ_TTAB // Return original table. - | mov [BASE-8], TAB:RB - | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) - | jz >1 - | // Possible write barrier. Table is black, but skip iswhite(mt) check. - | barrierback TAB:RB, RC - |1: - | jmp ->fff_res1 - | - |.ffunc_2 rawget - | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback - |.if X64WIN - | mov RB, BASE // Save BASE. - | lea CARG3d, [BASE+8] - | mov CARG2d, [BASE] // Caveat: CARG2d == BASE. - | mov CARG1d, SAVE_L - |.elif X64 - | mov RB, BASE // Save BASE. - | mov CARG2d, [BASE] - | lea CARG3d, [BASE+8] // Caveat: CARG3d == BASE. - | mov CARG1d, SAVE_L - |.else - | mov TAB:RD, [BASE] - | mov L:RB, SAVE_L - | mov ARG2, TAB:RD - | mov ARG1, L:RB - | mov RB, BASE // Save BASE. - | add BASE, 8 - | mov ARG3, BASE - |.endif - | call extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key) - | // cTValue * returned in eax (RD). - | mov BASE, RB // Restore BASE. - | // Copy table slot. - |.if X64 - | mov RBa, [RD] - | mov PC, [BASE-4] - | mov [BASE-8], RBa - |.else - | mov RB, [RD] - | mov RD, [RD+4] - | mov PC, [BASE-4] - | mov [BASE-8], RB - | mov [BASE-4], RD - |.endif - | jmp ->fff_res1 - | - |//-- Base library: conversions ------------------------------------------ - | - |.ffunc tonumber - | // Only handles the number case inline (without a base argument). - | cmp NARGS:RD, 1+1; jne ->fff_fallback // Exactly one argument. - | cmp dword [BASE+4], LJ_TISNUM - if (LJ_DUALNUM) { - | jne >1 - | mov RB, dword [BASE]; jmp ->fff_resi - |1: - | ja ->fff_fallback - } else { - | jae ->fff_fallback - } - if (sse) { - | movsd xmm0, qword [BASE]; jmp ->fff_resxmm0 - } else { - | fld qword [BASE]; jmp ->fff_resn - } - | - |.ffunc_1 tostring - | // Only handles the string or number case inline. - | mov PC, [BASE-4] - | cmp dword [BASE+4], LJ_TSTR; jne >3 - | // A __tostring method in the string base metatable is ignored. - | mov STR:RD, [BASE] - |2: - | mov dword [BASE-4], LJ_TSTR - | mov [BASE-8], STR:RD - | jmp ->fff_res1 - |3: // Handle numbers inline, unless a number base metatable is present. - | cmp dword [BASE+4], LJ_TISNUM; ja ->fff_fallback - | cmp dword [DISPATCH+DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])], 0 - | jne ->fff_fallback - | ffgccheck // Caveat: uses label 1. - | mov L:RB, SAVE_L - | mov L:RB->base, BASE // Add frame since C call can throw. - | mov SAVE_PC, PC // Redundant (but a defined value). - |.if X64 and not X64WIN - | mov FCARG2, BASE // Otherwise: FCARG2 == BASE - |.endif - | mov L:FCARG1, L:RB - if (LJ_DUALNUM) { - | call extern lj_str_fromnumber@8 // (lua_State *L, cTValue *o) - } else { - | call extern lj_str_fromnum@8 // (lua_State *L, lua_Number *np) - } - | // GCstr returned in eax (RD). - | mov BASE, L:RB->base - | jmp <2 - | - |//-- Base library: iterators ------------------------------------------- - | - |.ffunc_1 next - | 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] - |.if X64WIN - | lea CARG3d, [BASE+8] - | mov CARG2d, [BASE] // Caveat: CARG2d == BASE. - | mov CARG1d, L:RB - |.elif X64 - | mov CARG2d, [BASE] - | lea CARG3d, [BASE+8] // Caveat: CARG3d == BASE. - | mov CARG1d, L:RB - |.else - | mov TAB:RD, [BASE] - | mov ARG2, TAB:RD - | mov ARG1, L:RB - | add BASE, 8 - | mov ARG3, BASE - |.endif - | mov SAVE_PC, PC // Redundant (but a defined value). - | 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 - |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] - | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | cmp dword TAB:RB->metatable, 0; jne ->fff_fallback -#endif - | mov CFUNC:RB, [BASE-8] - | mov CFUNC:RD, CFUNC:RB->upvalue[0] - | mov PC, [BASE-4] - | mov dword [BASE-4], LJ_TFUNC - | mov [BASE-8], CFUNC:RD - | mov dword [BASE+12], LJ_TNIL - | mov RD, 1+3 - | jmp ->fff_res - | - |.ffunc_1 ipairs_aux - | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback - | cmp dword [BASE+12], LJ_TISNUM - if (LJ_DUALNUM) { - | jne ->fff_fallback - } else { - | jae ->fff_fallback - } - | mov PC, [BASE-4] - if (LJ_DUALNUM) { - | mov RD, dword [BASE+8] - | add RD, 1 - | mov dword [BASE-4], LJ_TISNUM - | mov dword [BASE-8], RD - } else if (sse) { - | movsd xmm0, qword [BASE+8] - | sseconst_1 xmm1, RBa - | addsd xmm0, xmm1 - | cvtsd2si RD, xmm0 - | movsd qword [BASE-8], xmm0 - } else { - |.if not X64 - | fld qword [BASE+8] - | fld1 - | faddp st1 - | fist ARG1 - | fstp qword [BASE-8] - | mov RD, ARG1 - |.endif - } - | mov TAB:RB, [BASE] - | cmp RD, TAB:RB->asize; jae >2 // Not in array part? - | shl RD, 3 - | add RD, TAB:RB->array - |1: - | cmp dword [RD+4], LJ_TNIL; je ->fff_res0 - | // Copy array slot. - |.if X64 - | mov RBa, [RD] - | mov [BASE], RBa - |.else - | mov RB, [RD] - | mov RD, [RD+4] - | mov [BASE], RB - | mov [BASE+4], RD - |.endif - | jmp ->fff_res2 - |2: // Check for empty hash part first. Otherwise call C function. - | cmp dword TAB:RB->hmask, 0; je ->fff_res0 - | mov FCARG1, TAB:RB - | mov RB, BASE // Save BASE. - | mov FCARG2, RD // Caveat: FCARG2 == BASE - | call extern lj_tab_getinth@8 // (GCtab *t, int32_t key) - | // cTValue * or NULL returned in eax (RD). - | mov BASE, RB - | test RD, RD - | jnz <1 - |->fff_res0: - | mov RD, 1+0 - | jmp ->fff_res - | - |.ffunc_1 ipairs - | mov TAB:RB, [BASE] - | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | cmp dword TAB:RB->metatable, 0; jne ->fff_fallback -#endif - | mov CFUNC:RB, [BASE-8] - | mov CFUNC:RD, CFUNC:RB->upvalue[0] - | mov PC, [BASE-4] - | mov dword [BASE-4], LJ_TFUNC - | mov [BASE-8], CFUNC:RD - if (LJ_DUALNUM) { - | mov dword [BASE+12], LJ_TISNUM - | mov dword [BASE+8], 0 - } else if (sse) { - | xorps xmm0, xmm0 - | movsd qword [BASE+8], xmm0 - } else { - | fldz - | fstp qword [BASE+8] - } - | mov RD, 1+3 - | jmp ->fff_res - | - |//-- Base library: catch errors ---------------------------------------- - | - |.ffunc_1 pcall - | lea RA, [BASE+8] - | sub NARGS:RD, 1 - | mov PC, 8+FRAME_PCALL - |1: - | movzx RB, byte [DISPATCH+DISPATCH_GL(hookmask)] - | shr RB, HOOK_ACTIVE_SHIFT - | and RB, 1 - | add PC, RB // Remember active hook before pcall. - | jmp ->vm_call_dispatch - | - |.ffunc_2 xpcall - | cmp dword [BASE+12], LJ_TFUNC; jne ->fff_fallback - | mov RB, [BASE+4] // Swap function and traceback. - | mov [BASE+12], RB - | mov dword [BASE+4], LJ_TFUNC - | mov LFUNC:RB, [BASE] - | mov PC, [BASE+8] - | mov [BASE+8], LFUNC:RB - | mov [BASE], PC - | lea RA, [BASE+16] - | sub NARGS:RD, 2 - | mov PC, 16+FRAME_PCALL - | jmp <1 - | - |//-- Coroutine library -------------------------------------------------- - | - |.macro coroutine_resume_wrap, resume - |.if resume - |.ffunc_1 coroutine_resume - | mov L:RB, [BASE] - |.else - |.ffunc coroutine_wrap_aux - | mov CFUNC:RB, [BASE-8] - | mov L:RB, CFUNC:RB->upvalue[0].gcr - |.endif - | mov PC, [BASE-4] - | mov SAVE_PC, PC - |.if X64 - | mov TMP1, L:RB - |.else - | mov ARG1, L:RB - |.endif - |.if resume - | cmp dword [BASE+4], LJ_TTHREAD; jne ->fff_fallback - |.endif - | cmp aword L:RB->cframe, 0; jne ->fff_fallback - | cmp byte L:RB->status, LUA_YIELD; ja ->fff_fallback - | mov RA, L:RB->top - | je >1 // Status != LUA_YIELD (i.e. 0)? - | cmp RA, L:RB->base // Check for presence of initial func. - | je ->fff_fallback - |1: - |.if resume - | lea PC, [RA+NARGS:RD*8-16] // Check stack space (-1-thread). - |.else - | lea PC, [RA+NARGS:RD*8-8] // Check stack space (-1). - |.endif - | cmp PC, L:RB->maxstack; ja ->fff_fallback - | mov L:RB->top, PC - | - | mov L:RB, SAVE_L - | mov L:RB->base, BASE - |.if resume - | add BASE, 8 // Keep resumed thread in stack for GC. - |.endif - | mov L:RB->top, BASE - |.if resume - | lea RB, [BASE+NARGS:RD*8-24] // RB = end of source for stack move. - |.else - | lea RB, [BASE+NARGS:RD*8-16] // RB = end of source for stack move. - |.endif - | sub RBa, PCa // Relative to PC. - | - | cmp PC, RA - | je >3 - |2: // Move args to coroutine. - |.if X64 - | mov RCa, [PC+RB] - | mov [PC-8], RCa - |.else - | mov RC, [PC+RB+4] - | mov [PC-4], RC - | mov RC, [PC+RB] - | mov [PC-8], RC - |.endif - | sub PC, 8 - | cmp PC, RA - | jne <2 - |3: - |.if X64 - | mov CARG2d, RA - | mov CARG1d, TMP1 - |.else - | mov ARG2, RA - | xor RA, RA - | mov ARG4, RA - | mov ARG3, RA - |.endif - | call ->vm_resume // (lua_State *L, TValue *base, 0, 0) - | set_vmstate INTERP - | - | mov L:RB, SAVE_L - |.if X64 - | mov L:PC, TMP1 - |.else - | mov L:PC, ARG1 // The callee doesn't modify SAVE_L. - |.endif - | mov BASE, L:RB->base - | cmp eax, LUA_YIELD - | ja >8 - |4: - | mov RA, L:PC->base - | mov KBASE, L:PC->top - | mov L:PC->top, RA // Clear coroutine stack. - | mov PC, KBASE - | sub PC, RA - | je >6 // No results? - | lea RD, [BASE+PC] - | shr PC, 3 - | cmp RD, L:RB->maxstack - | ja >9 // Need to grow stack? - | - | mov RB, BASE - | sub RBa, RAa - |5: // Move results from coroutine. - |.if X64 - | mov RDa, [RA] - | mov [RA+RB], RDa - |.else - | mov RD, [RA] - | mov [RA+RB], RD - | mov RD, [RA+4] - | mov [RA+RB+4], RD - |.endif - | add RA, 8 - | cmp RA, KBASE - | jne <5 - |6: - |.if resume - | lea RD, [PC+2] // nresults+1 = 1 + true + results. - | mov dword [BASE-4], LJ_TTRUE // Prepend true to results. - |.else - | lea RD, [PC+1] // nresults+1 = 1 + results. - |.endif - |7: - | mov PC, SAVE_PC - | mov MULTRES, RD - |.if resume - | mov RAa, -8 - |.else - | xor RA, RA - |.endif - | test PC, FRAME_TYPE - | jz ->BC_RET_Z - | jmp ->vm_return - | - |8: // Coroutine returned with error (at co->top-1). - |.if resume - | mov dword [BASE-4], LJ_TFALSE // Prepend false to results. - | mov RA, L:PC->top - | sub RA, 8 - | mov L:PC->top, RA // Clear error from coroutine stack. - | // Copy error message. - |.if X64 - | mov RDa, [RA] - | mov [BASE], RDa - |.else - | mov RD, [RA] - | mov [BASE], RD - | mov RD, [RA+4] - | mov [BASE+4], RD - |.endif - | mov RD, 1+2 // nresults+1 = 1 + false + error. - | jmp <7 - |.else - | mov FCARG2, L:PC - | mov FCARG1, L:RB - | call extern lj_ffh_coroutine_wrap_err@8 // (lua_State *L, lua_State *co) - | // Error function does not return. - |.endif - | - |9: // Handle stack expansion on return from yield. - |.if X64 - | mov L:RA, TMP1 - |.else - | mov L:RA, ARG1 // The callee doesn't modify SAVE_L. - |.endif - | mov L:RA->top, KBASE // Undo coroutine stack clearing. - | mov FCARG2, PC - | mov FCARG1, L:RB - | call extern lj_state_growstack@8 // (lua_State *L, int n) - |.if X64 - | mov L:PC, TMP1 - |.else - | mov L:PC, ARG1 - |.endif - | mov BASE, L:RB->base - | jmp <4 // Retry the stack move. - |.endmacro - | - | coroutine_resume_wrap 1 // coroutine.resume - | coroutine_resume_wrap 0 // coroutine.wrap - | - |.ffunc coroutine_yield - | mov L:RB, SAVE_L - | test aword L:RB->cframe, CFRAME_RESUME - | jz ->fff_fallback - | mov L:RB->base, BASE - | lea RD, [BASE+NARGS:RD*8-8] - | mov L:RB->top, RD - | xor RD, RD - | mov aword L:RB->cframe, RDa - | mov al, LUA_YIELD - | mov byte L:RB->status, al - | jmp ->vm_leave_unw - | - |//-- Math library ------------------------------------------------------- - | - if (!LJ_DUALNUM) { - |->fff_resi: // Dummy. - } - if (sse) { - |->fff_resn: - | mov PC, [BASE-4] - | fstp qword [BASE-8] - | jmp ->fff_res1 - } - | .ffunc_1 math_abs - if (LJ_DUALNUM) { - | cmp dword [BASE+4], LJ_TISNUM; jne >2 - | mov RB, dword [BASE] - | cmp RB, 0; jns ->fff_resi - | neg RB; js >1 - |->fff_resbit: - |->fff_resi: - | mov PC, [BASE-4] - | mov dword [BASE-4], LJ_TISNUM - | mov dword [BASE-8], RB - | jmp ->fff_res1 - |1: - | mov PC, [BASE-4] - | mov dword [BASE-4], 0x41e00000 // 2^31. - | mov dword [BASE-8], 0 - | jmp ->fff_res1 - |2: - | ja ->fff_fallback - } else { - | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback - } - if (sse) { - | movsd xmm0, qword [BASE] - | sseconst_abs xmm1, RDa - | andps xmm0, xmm1 - |->fff_resxmm0: - | mov PC, [BASE-4] - | movsd qword [BASE-8], xmm0 - | // fallthrough - } else { - | fld qword [BASE] - | fabs - | // fallthrough - |->fff_resxmm0: // Dummy. - |->fff_resn: - | mov PC, [BASE-4] - | fstp qword [BASE-8] - } - |->fff_res1: - | mov RD, 1+1 - |->fff_res: - | mov MULTRES, RD - |->fff_res_: - | test PC, FRAME_TYPE - | jnz >7 - |5: - | cmp PC_RB, RDL // More results expected? - | ja >6 - | // Adjust BASE. KBASE is assumed to be set for the calling frame. - | movzx RA, PC_RA - | not RAa // Note: ~RA = -(RA+1) - | lea BASE, [BASE+RA*8] // base = base - (RA+1)*8 - | ins_next - | - |6: // Fill up results with nil. - | mov dword [BASE+RD*8-12], LJ_TNIL - | add RD, 1 - | jmp <5 - | - |7: // Non-standard return case. - | mov RAa, -8 // Results start at BASE+RA = BASE-8. - | jmp ->vm_return - | - |.macro math_round, func - | .ffunc math_ .. func - ||if (LJ_DUALNUM) { - | cmp dword [BASE+4], LJ_TISNUM; jne >1 - | mov RB, dword [BASE]; jmp ->fff_resi - |1: - | ja ->fff_fallback - ||} else { - | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback - ||} - ||if (sse) { - | movsd xmm0, qword [BASE] - | call ->vm_ .. func - || if (LJ_DUALNUM) { - | cvtsd2si RB, xmm0 - | cmp RB, 0x80000000 - | jne ->fff_resi - | cvtsi2sd xmm1, RB - | ucomisd xmm0, xmm1 - | jp ->fff_resxmm0 - | je ->fff_resi - || } - | jmp ->fff_resxmm0 - ||} else { - | fld qword [BASE] - | call ->vm_ .. func - || if (LJ_DUALNUM) { - |.if not X64 - | fist ARG1 - | mov RB, ARG1 - | cmp RB, 0x80000000; jne >2 - | fdup - | fild ARG1 - | fcomparepp - | jp ->fff_resn - | jne ->fff_resn - |2: - | fpop - | jmp ->fff_resi - |.endif - || } else { - | jmp ->fff_resn - || } - ||} - |.endmacro - | - | math_round floor - | math_round ceil - | - if (sse) { - |.ffunc_nsse math_sqrt, sqrtsd; jmp ->fff_resxmm0 - } else { - |.ffunc_n math_sqrt; fsqrt; jmp ->fff_resn - } - |.ffunc_n math_log, fldln2; fyl2x; jmp ->fff_resn - |.ffunc_n math_log10, fldlg2; fyl2x; jmp ->fff_resn - |.ffunc_n math_exp; call ->vm_exp_x87; jmp ->fff_resn - | - |.ffunc_n math_sin; fsin; jmp ->fff_resn - |.ffunc_n math_cos; fcos; jmp ->fff_resn - |.ffunc_n math_tan; fptan; fpop; jmp ->fff_resn - | - |.ffunc_n math_asin - | fdup; fmul st0; fld1; fsubrp st1; fsqrt; fpatan - | jmp ->fff_resn - |.ffunc_n math_acos - | fdup; fmul st0; fld1; fsubrp st1; fsqrt; fxch; fpatan - | jmp ->fff_resn - |.ffunc_n math_atan; fld1; fpatan; jmp ->fff_resn - | - |.macro math_extern, func - ||if (sse) { - | .ffunc_nsse math_ .. func - | .if not X64 - | movsd FPARG1, xmm0 - | .endif - ||} else { - | .if not X64 - | .ffunc_n math_ .. func - | fstp FPARG1 - | .endif - ||} - | mov RB, BASE - | call extern lj_vm_ .. func - | mov BASE, RB - | .if X64 - | jmp ->fff_resxmm0 - | .else - | jmp ->fff_resn - | .endif - |.endmacro - | - | math_extern sinh - | math_extern cosh - | math_extern tanh - | - |->ff_math_deg: - if (sse) { - |.ffunc_nsse math_rad - | mov CFUNC:RB, [BASE-8] - | mulsd xmm0, qword CFUNC:RB->upvalue[0] - | jmp ->fff_resxmm0 - } else { - |.ffunc_n math_rad - | mov CFUNC:RB, [BASE-8] - | fmul qword CFUNC:RB->upvalue[0] - | jmp ->fff_resn - } - | - |.ffunc_nn math_atan2; fpatan; jmp ->fff_resn - |.ffunc_nnr math_ldexp; fscale; fpop1; jmp ->fff_resn - | - |.ffunc_1 math_frexp - | mov RB, [BASE+4] - | cmp RB, LJ_TISNUM; jae ->fff_fallback - | mov PC, [BASE-4] - | mov RC, [BASE] - | mov [BASE-4], RB; mov [BASE-8], RC - | shl RB, 1; cmp RB, 0xffe00000; jae >3 - | or RC, RB; jz >3 - | mov RC, 1022 - | cmp RB, 0x00200000; jb >4 - |1: - | shr RB, 21; sub RB, RC // Extract and unbias exponent. - if (sse) { - | cvtsi2sd xmm0, RB - } else { - | mov TMP1, RB; fild TMP1 - } - | mov RB, [BASE-4] - | and RB, 0x800fffff // Mask off exponent. - | or RB, 0x3fe00000 // Put mantissa in range [0.5,1) or 0. - | mov [BASE-4], RB - |2: - if (sse) { - | movsd qword [BASE], xmm0 - } else { - | fstp qword [BASE] - } - | mov RD, 1+2 - | jmp ->fff_res - |3: // Return +-0, +-Inf, NaN unmodified and an exponent of 0. - if (sse) { - | xorps xmm0, xmm0; jmp <2 - } else { - | fldz; jmp <2 - } - |4: // Handle denormals by multiplying with 2^54 and adjusting the bias. - if (sse) { - | movsd xmm0, qword [BASE] - | sseconst_hi xmm1, RBa, 43500000 // 2^54. - | mulsd xmm0, xmm1 - | movsd qword [BASE-8], xmm0 - } else { - | fld qword [BASE] - | mov TMP1, 0x5a800000; fmul TMP1 // x = x*2^54 - | fstp qword [BASE-8] - } - | mov RB, [BASE-4]; mov RC, 1076; shl RB, 1; jmp <1 - | - if (sse) { - |.ffunc_nsse math_modf - } else { - |.ffunc_n math_modf - } - | mov RB, [BASE+4] - | mov PC, [BASE-4] - | shl RB, 1; cmp RB, 0xffe00000; je >4 // +-Inf? - if (sse) { - | movaps xmm4, xmm0 - | call ->vm_trunc - | subsd xmm4, xmm0 - |1: - | movsd qword [BASE-8], xmm0 - | movsd qword [BASE], xmm4 - } else { - | fdup - | call ->vm_trunc - | fsub st1, st0 - |1: - | fstp qword [BASE-8] - | fstp qword [BASE] - } - | mov RC, [BASE-4]; mov RB, [BASE+4] - | xor RC, RB; js >3 // Need to adjust sign? - |2: - | mov RD, 1+2 - | jmp ->fff_res - |3: - | xor RB, 0x80000000; mov [BASE+4], RB // Flip sign of fraction. - | jmp <2 - |4: - if (sse) { - | xorps xmm4, xmm4; jmp <1 // Return +-Inf and +-0. - } else { - | fldz; fxch; jmp <1 // Return +-Inf and +-0. - } - | - |.ffunc_nnr math_fmod - |1: ; fprem; fnstsw ax; sahf; jp <1 - | fpop1 - | jmp ->fff_resn - | - if (sse) { - |.ffunc_nnsse math_pow; call ->vm_pow; jmp ->fff_resxmm0 - } else { - |.ffunc_nn math_pow; call ->vm_pow; jmp ->fff_resn - } - | - |.macro math_minmax, name, cmovop, fcmovop, nofcmovop, sseop - | .ffunc name - | mov RA, 2 - | cmp dword [BASE+4], LJ_TISNUM - ||if (LJ_DUALNUM) { - | jne >4 - | mov RB, dword [BASE] - |1: // Handle integers. - | cmp RA, RD; jae ->fff_resi - | cmp dword [BASE+RA*8-4], LJ_TISNUM; jne >3 - | cmp RB, dword [BASE+RA*8-8] - | cmovop RB, dword [BASE+RA*8-8] - | add RA, 1 - | jmp <1 - |3: - | ja ->fff_fallback - | // Convert intermediate result to number and continue below. - ||if (sse) { - | cvtsi2sd xmm0, RB - ||} else { - |.if not X64 - | mov TMP1, RB - | fild TMP1 - |.endif - ||} - | jmp >6 - |4: - | ja ->fff_fallback - ||} else { - | jae ->fff_fallback - ||} - | - ||if (sse) { - | movsd xmm0, qword [BASE] - |5: // Handle numbers or integers. - | cmp RA, RD; jae ->fff_resxmm0 - | cmp dword [BASE+RA*8-4], LJ_TISNUM - ||if (LJ_DUALNUM) { - | jb >6 - | ja ->fff_fallback - | cvtsi2sd xmm1, dword [BASE+RA*8-8] - | jmp >7 - ||} else { - | jae ->fff_fallback - ||} - |6: - | movsd xmm1, qword [BASE+RA*8-8] - |7: - | sseop xmm0, xmm1 - | add RA, 1 - | jmp <5 - ||} else { - |.if not X64 - | fld qword [BASE] - |5: // Handle numbers or integers. - | cmp RA, RD; jae ->fff_resn - | cmp dword [BASE+RA*8-4], LJ_TISNUM - ||if (LJ_DUALNUM) { - | jb >6 - | ja >9 - | fild dword [BASE+RA*8-8] - | jmp >7 - ||} else { - | jae >9 - ||} - |6: - | fld qword [BASE+RA*8-8] - |7: - ||if (cmov) { - | fucomi st1; fcmovop st1; fpop1 - ||} else { - | push eax - | fucom st1; fnstsw ax; test ah, 1; nofcmovop >2; fxch; 2: ; fpop - | pop eax - ||} - | add RA, 1 - | jmp <5 - |.endif - ||} - |.endmacro - | - | math_minmax math_min, cmovg, fcmovnbe, jz, minsd - | math_minmax math_max, cmovl, fcmovbe, jnz, maxsd - if (!sse) { - |9: - | fpop; jmp ->fff_fallback - } - | - |//-- String library ----------------------------------------------------- - | - |.ffunc_1 string_len - | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback - | mov STR:RB, [BASE] - if (LJ_DUALNUM) { - | mov RB, dword STR:RB->len; jmp ->fff_resi - } else if (sse) { - | cvtsi2sd xmm0, dword STR:RB->len; jmp ->fff_resxmm0 - } else { - | fild dword STR:RB->len; jmp ->fff_resn - } - | - |.ffunc string_byte // Only handle the 1-arg case here. - | cmp NARGS:RD, 1+1; jne ->fff_fallback - | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback - | mov STR:RB, [BASE] - | mov PC, [BASE-4] - | cmp dword STR:RB->len, 1 - | jb ->fff_res0 // Return no results for empty string. - | movzx RB, byte STR:RB[1] - if (LJ_DUALNUM) { - | jmp ->fff_resi - } else if (sse) { - | cvtsi2sd xmm0, RB; jmp ->fff_resxmm0 - } else { - | mov TMP1, RB; fild TMP1; jmp ->fff_resn - } - | - |.ffunc string_char // Only handle the 1-arg case here. - | ffgccheck - | cmp NARGS:RD, 1+1; jne ->fff_fallback // *Exactly* 1 arg. - | cmp dword [BASE+4], LJ_TISNUM - if (LJ_DUALNUM) { - | jne ->fff_fallback - | mov RB, dword [BASE] - | cmp RB, 255; ja ->fff_fallback - | mov TMP2, RB - } else if (sse) { - | jae ->fff_fallback - | cvttsd2si RB, qword [BASE] - | cmp RB, 255; ja ->fff_fallback - | mov TMP2, RB - } else { - | jae ->fff_fallback - | fld qword [BASE] - | fistp TMP2 - | cmp TMP2, 255; ja ->fff_fallback - } - |.if X64 - | mov TMP3, 1 - |.else - | mov ARG3, 1 - |.endif - | lea RDa, TMP2 // Points to stack. Little-endian. - |->fff_newstr: - | mov L:RB, SAVE_L - | mov L:RB->base, BASE - |.if X64 - | mov CARG3d, TMP3 // Zero-extended to size_t. - | mov CARG2, RDa // May be 64 bit ptr to stack. - | mov CARG1d, L:RB - |.else - | mov ARG2, RD - | mov ARG1, L:RB - |.endif - | mov SAVE_PC, PC - | call extern lj_str_new // (lua_State *L, char *str, size_t l) - | // GCstr * returned in eax (RD). - | mov BASE, L:RB->base - | mov PC, [BASE-4] - | mov dword [BASE-4], LJ_TSTR - | mov [BASE-8], STR:RD - | jmp ->fff_res1 - | - |.ffunc string_sub - | ffgccheck - | mov TMP2, -1 - | cmp NARGS:RD, 1+2; jb ->fff_fallback - | jna >1 - | cmp dword [BASE+20], LJ_TISNUM - if (LJ_DUALNUM) { - | jne ->fff_fallback - | mov RB, dword [BASE+16] - | mov TMP2, RB - } else if (sse) { - | jae ->fff_fallback - | cvttsd2si RB, qword [BASE+16] - | mov TMP2, RB - } else { - | jae ->fff_fallback - | fld qword [BASE+16] - | fistp TMP2 - } - |1: - | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback - | cmp dword [BASE+12], LJ_TISNUM - if (LJ_DUALNUM) { - | jne ->fff_fallback - } else { - | jae ->fff_fallback - } - | mov STR:RB, [BASE] - | mov TMP3, STR:RB - | mov RB, STR:RB->len - if (LJ_DUALNUM) { - | mov RA, dword [BASE+8] - } else if (sse) { - | cvttsd2si RA, qword [BASE+8] - } else { - |.if not X64 - | fld qword [BASE+8] - | fistp ARG3 - | mov RA, ARG3 - |.endif - } - | mov RC, TMP2 - | cmp RB, RC // len < end? (unsigned compare) - | jb >5 - |2: - | test RA, RA // start <= 0? - | jle >7 - |3: - | mov STR:RB, TMP3 - | sub RC, RA // start > end? - | jl ->fff_emptystr - | lea RB, [STR:RB+RA+#STR-1] - | add RC, 1 - |4: - |.if X64 - | mov TMP3, RC - |.else - | mov ARG3, RC - |.endif - | mov RD, RB - | jmp ->fff_newstr - | - |5: // Negative end or overflow. - | jl >6 - | lea RC, [RC+RB+1] // end = end+(len+1) - | jmp <2 - |6: // Overflow. - | mov RC, RB // end = len - | jmp <2 - | - |7: // Negative start or underflow. - | je >8 - | add RA, RB // start = start+(len+1) - | add RA, 1 - | jg <3 // start > 0? - |8: // Underflow. - | mov RA, 1 // start = 1 - | jmp <3 - | - |->fff_emptystr: // Range underflow. - | xor RC, RC // Zero length. Any ptr in RB is ok. - | jmp <4 - | - |.ffunc_2 string_rep // Only handle the 1-char case inline. - | ffgccheck - | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback - | cmp dword [BASE+12], LJ_TISNUM - | mov STR:RB, [BASE] - if (LJ_DUALNUM) { - | jne ->fff_fallback - | mov RC, dword [BASE+8] - } else if (sse) { - | jae ->fff_fallback - | cvttsd2si RC, qword [BASE+8] - } else { - | jae ->fff_fallback - | fld qword [BASE+8] - | fistp TMP2 - | mov RC, TMP2 - } - | test RC, RC - | jle ->fff_emptystr // Count <= 0? (or non-int) - | cmp dword STR:RB->len, 1 - | jb ->fff_emptystr // Zero length string? - | jne ->fff_fallback_2 // Fallback for > 1-char strings. - | cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC; jb ->fff_fallback_2 - | movzx RA, byte STR:RB[1] - | mov RB, [DISPATCH+DISPATCH_GL(tmpbuf.buf)] - |.if X64 - | mov TMP3, RC - |.else - | mov ARG3, RC - |.endif - |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). - | mov [RB], RAL - | add RB, 1 - | sub RC, 1 - | jnz <1 - | mov RD, [DISPATCH+DISPATCH_GL(tmpbuf.buf)] - | jmp ->fff_newstr - | - |.ffunc_1 string_reverse - | ffgccheck - | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback - | mov STR:RB, [BASE] - | mov RC, STR:RB->len - | test RC, RC - | jz ->fff_emptystr // Zero length string? - | cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC; jb ->fff_fallback_1 - | add RB, #STR - | mov TMP2, PC // Need another temp register. - |.if X64 - | mov TMP3, RC - |.else - | mov ARG3, RC - |.endif - | mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.buf)] - |1: - | movzx RA, byte [RB] - | add RB, 1 - | sub RC, 1 - | mov [PC+RC], RAL - | jnz <1 - | mov RD, PC - | mov PC, TMP2 - | jmp ->fff_newstr - | - |.macro ffstring_case, name, lo, hi - | .ffunc_1 name - | ffgccheck - | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback - | mov STR:RB, [BASE] - | mov RC, STR:RB->len - | cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC; jb ->fff_fallback_1 - | add RB, #STR - | mov TMP2, PC // Need another temp register. - |.if X64 - | mov TMP3, RC - |.else - | mov ARG3, RC - |.endif - | mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.buf)] - | jmp >3 - |1: // ASCII case conversion. Yes, this is suboptimal code (do you care?). - | movzx RA, byte [RB+RC] - | cmp RA, lo - | jb >2 - | cmp RA, hi - | ja >2 - | xor RA, 0x20 - |2: - | mov [PC+RC], RAL - |3: - | sub RC, 1 - | jns <1 - | mov RD, PC - | mov PC, TMP2 - | jmp ->fff_newstr - |.endmacro - | - |ffstring_case string_lower, 0x41, 0x5a - |ffstring_case string_upper, 0x61, 0x7a - | - |//-- Table library ------------------------------------------------------ - | - |.ffunc_1 table_getn - | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback - | mov RB, BASE // Save BASE. - | mov TAB:FCARG1, [BASE] - | call extern lj_tab_len@4 // LJ_FASTCALL (GCtab *t) - | // Length of table returned in eax (RD). - | mov BASE, RB // Restore BASE. - if (LJ_DUALNUM) { - | mov RB, RD; jmp ->fff_resi - } else if (sse) { - | cvtsi2sd xmm0, RD; jmp ->fff_resxmm0 - } else { - |.if not X64 - | mov ARG1, RD; fild ARG1; jmp ->fff_resn - |.endif - } - | - |//-- Bit library -------------------------------------------------------- - | - |.define TOBIT_BIAS, 0x59c00000 // 2^52 + 2^51 (float, not double!). - | - |.macro .ffunc_bit, name, kind - | .ffunc_1 name - |.if kind == 2 - ||if (sse) { - | sseconst_tobit xmm1, RBa - ||} else { - | mov TMP1, TOBIT_BIAS - ||} - |.endif - | cmp dword [BASE+4], LJ_TISNUM - ||if (LJ_DUALNUM) { - | jne >1 - | mov RB, dword [BASE] - |.if kind > 0 - | jmp >2 - |.else - | jmp ->fff_resbit - |.endif - |1: - | ja ->fff_fallback - ||} else { - | jae ->fff_fallback - ||} - ||if (sse) { - | movsd xmm0, qword [BASE] - |.if kind < 2 - | sseconst_tobit xmm1, RBa - |.endif - | addsd xmm0, xmm1 - | movd RB, xmm0 - ||} else { - |.if not X64 - | fld qword [BASE] - |.if kind < 2 - | mov TMP1, TOBIT_BIAS - |.endif - | fadd TMP1 - | fstp FPARG1 - |.if kind > 0 - | mov RB, ARG1 - |.endif - |.endif - ||} - |2: - |.endmacro - | - |.ffunc_bit bit_tobit, 0 - if (LJ_DUALNUM || sse) { - if (!sse) { - |.if not X64 - | mov RB, ARG1 - |.endif - } - | jmp ->fff_resbit - } else { - |.if not X64 - | fild ARG1 - | jmp ->fff_resn - |.endif - } - | - |.macro .ffunc_bit_op, name, ins - | .ffunc_bit name, 2 - | mov TMP2, NARGS:RD // Save for fallback. - | lea RD, [BASE+NARGS:RD*8-16] - |1: - | cmp RD, BASE - | jbe ->fff_resbit - | cmp dword [RD+4], LJ_TISNUM - ||if (LJ_DUALNUM) { - | jne >2 - | ins RB, dword [RD] - | sub RD, 8 - | jmp <1 - |2: - | ja ->fff_fallback_bit_op - ||} else { - | jae ->fff_fallback_bit_op - ||} - ||if (sse) { - | movsd xmm0, qword [RD] - | addsd xmm0, xmm1 - | movd RA, xmm0 - | ins RB, RA - ||} else { - |.if not X64 - | fld qword [RD] - | fadd TMP1 - | fstp FPARG1 - | ins RB, ARG1 - |.endif - ||} - | sub RD, 8 - | jmp <1 - |.endmacro - | - |.ffunc_bit_op bit_band, and - |.ffunc_bit_op bit_bor, or - |.ffunc_bit_op bit_bxor, xor - | - |.ffunc_bit bit_bswap, 1 - | bswap RB - | jmp ->fff_resbit - | - |.ffunc_bit bit_bnot, 1 - | not RB - if (LJ_DUALNUM) { - | jmp ->fff_resbit - } else if (sse) { - |->fff_resbit: - | cvtsi2sd xmm0, RB - | jmp ->fff_resxmm0 - } else { - |.if not X64 - |->fff_resbit: - | mov ARG1, RB - | fild ARG1 - | jmp ->fff_resn - |.endif - } - | - |->fff_fallback_bit_op: - | mov NARGS:RD, TMP2 // Restore for fallback - | jmp ->fff_fallback - | - |.macro .ffunc_bit_sh, name, ins - ||if (LJ_DUALNUM) { - | .ffunc_bit name, 1 - | // Note: no inline conversion from number for 2nd argument! - | cmp dword [BASE+12], LJ_TISNUM; jne ->fff_fallback - | mov RA, dword [BASE+8] - ||} else if (sse) { - | .ffunc_nnsse name - | sseconst_tobit xmm2, RBa - | addsd xmm0, xmm2 - | addsd xmm1, xmm2 - | movd RB, xmm0 - | movd RA, xmm1 - ||} else { - |.if not X64 - | .ffunc_nn name - | mov TMP1, TOBIT_BIAS - | fadd TMP1 - | fstp FPARG3 - | fadd TMP1 - | fstp FPARG1 - | mov RA, ARG3 - | mov RB, ARG1 - |.endif - ||} - | ins RB, cl // Assumes RA is ecx. - | jmp ->fff_resbit - |.endmacro - | - |.ffunc_bit_sh bit_lshift, shl - |.ffunc_bit_sh bit_rshift, shr - |.ffunc_bit_sh bit_arshift, sar - |.ffunc_bit_sh bit_rol, rol - |.ffunc_bit_sh bit_ror, ror - | - |//----------------------------------------------------------------------- - | - |->fff_fallback_2: - | mov NARGS:RD, 1+2 // Other args are ignored, anyway. - | jmp ->fff_fallback - |->fff_fallback_1: - | mov NARGS:RD, 1+1 // Other args are ignored, anyway. - |->fff_fallback: // Call fast function fallback handler. - | // BASE = new base, RD = nargs+1 - | mov L:RB, SAVE_L - | mov PC, [BASE-4] // Fallback may overwrite PC. - | mov SAVE_PC, PC // Redundant (but a defined value). - | mov L:RB->base, BASE - | lea RD, [BASE+NARGS:RD*8-8] - | lea RA, [RD+8*LUA_MINSTACK] // Ensure enough space for handler. - | mov L:RB->top, RD - | mov CFUNC:RD, [BASE-8] - | cmp RA, L:RB->maxstack - | ja >5 // Need to grow stack. - |.if X64 - | mov CARG1d, L:RB - |.else - | mov ARG1, L:RB - |.endif - | call aword CFUNC:RD->f // (lua_State *L) - | mov BASE, L:RB->base - | // Either throws an error, or recovers and returns -1, 0 or nresults+1. - | test RD, RD; jg ->fff_res // Returned nresults+1? - |1: - | mov RA, L:RB->top - | sub RA, BASE - | shr RA, 3 - | test RD, RD - | lea NARGS:RD, [RA+1] - | mov LFUNC:RB, [BASE-8] - | jne ->vm_call_tail // Returned -1? - | ins_callt // Returned 0: retry fast path. - | - |// Reconstruct previous base for vmeta_call during tailcall. - |->vm_call_tail: - | mov RA, BASE - | test PC, FRAME_TYPE - | jnz >3 - | movzx RB, PC_RA - | not RBa // Note: ~RB = -(RB+1) - | lea BASE, [BASE+RB*8] // base = base - (RB+1)*8 - | jmp ->vm_call_dispatch // Resolve again for tailcall. - |3: - | mov RB, PC - | and RB, -8 - | sub BASE, RB - | jmp ->vm_call_dispatch // Resolve again for tailcall. - | - |5: // Grow stack for fallback handler. - | mov FCARG2, LUA_MINSTACK - | mov FCARG1, L:RB - | call extern lj_state_growstack@8 // (lua_State *L, int n) - | mov BASE, L:RB->base - | xor RD, RD // Simulate a return 0. - | jmp <1 // Dumb retry (goes through ff first). - | - |->fff_gcstep: // Call GC step function. - | // BASE = new base, RD = nargs+1 - | pop RBa // Must keep stack at same level. - | mov TMPa, RBa // Save return address - | mov L:RB, SAVE_L - | mov SAVE_PC, PC // Redundant (but a defined value). - | mov L:RB->base, BASE - | lea RD, [BASE+NARGS:RD*8-8] - | mov FCARG1, L:RB - | mov L:RB->top, RD - | call extern lj_gc_step@4 // (lua_State *L) - | mov BASE, L:RB->base - | mov RD, L:RB->top - | sub RD, BASE - | shr RD, 3 - | add NARGS:RD, 1 - | mov RBa, TMPa - | push RBa // Restore return address. - | ret - | - |//----------------------------------------------------------------------- - |//-- Special dispatch targets ------------------------------------------- - |//----------------------------------------------------------------------- - | - |->vm_record: // Dispatch target for recording phase. -#if LJ_HASJIT - | movzx RD, byte [DISPATCH+DISPATCH_GL(hookmask)] - | test RDL, HOOK_VMEVENT // No recording while in vmevent. - | jnz >5 - | // Decrement the hookcount for consistency, but always do the call. - | test RDL, HOOK_ACTIVE - | jnz >1 - | test RDL, LUA_MASKLINE|LUA_MASKCOUNT - | jz >1 - | dec dword [DISPATCH+DISPATCH_GL(hookcount)] - | jmp >1 -#endif - | - |->vm_rethook: // Dispatch target for return hooks. - | movzx RD, byte [DISPATCH+DISPATCH_GL(hookmask)] - | test RDL, HOOK_ACTIVE // Hook already active? - | jnz >5 - | jmp >1 - | - |->vm_inshook: // Dispatch target for instr/line hooks. - | movzx RD, byte [DISPATCH+DISPATCH_GL(hookmask)] - | test RDL, HOOK_ACTIVE // Hook already active? - | jnz >5 - | - | test RDL, LUA_MASKLINE|LUA_MASKCOUNT - | jz >5 - | dec dword [DISPATCH+DISPATCH_GL(hookcount)] - | jz >1 - | test RDL, LUA_MASKLINE - | jz >5 - |1: - | mov L:RB, SAVE_L - | mov L:RB->base, BASE - | mov FCARG2, PC // Caveat: FCARG2 == BASE - | mov FCARG1, L:RB - | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. - | call extern lj_dispatch_ins@8 // (lua_State *L, BCIns *pc) - |3: - | mov BASE, L:RB->base - |4: - | movzx RA, PC_RA - |5: - | movzx OP, PC_OP - | movzx RD, PC_RD - |.if X64 - | jmp aword [DISPATCH+OP*8+GG_DISP2STATIC] // Re-dispatch to static ins. - |.else - | jmp aword [DISPATCH+OP*4+GG_DISP2STATIC] // Re-dispatch to static ins. - |.endif - | - |->cont_hook: // Continue from hook yield. - | add PC, 4 - | mov RA, [RB-24] - | mov MULTRES, RA // Restore MULTRES for *M ins. - | jmp <4 - | - |->vm_hotloop: // Hot loop counter underflow. -#if LJ_HASJIT - | mov LFUNC:RB, [BASE-8] // Same as curr_topL(L). - | mov RB, LFUNC:RB->pc - | movzx RD, byte [RB+PC2PROTO(framesize)] - | lea RD, [BASE+RD*8] - | mov L:RB, SAVE_L - | mov L:RB->base, BASE - | mov L:RB->top, RD - | mov FCARG2, PC - | lea FCARG1, [DISPATCH+GG_DISP2J] - | mov aword [DISPATCH+DISPATCH_J(L)], L:RBa - | mov SAVE_PC, PC - | call extern lj_trace_hot@8 // (jit_State *J, const BCIns *pc) - | jmp <3 -#endif - | - |->vm_callhook: // Dispatch target for call hooks. - | mov SAVE_PC, PC -#if LJ_HASJIT - | jmp >1 -#endif - | - |->vm_hotcall: // Hot call counter underflow. -#if LJ_HASJIT - | mov SAVE_PC, PC - | or PC, 1 // Marker for hot call. - |1: -#endif - | lea RD, [BASE+NARGS:RD*8-8] - | mov L:RB, SAVE_L - | mov L:RB->base, BASE - | mov L:RB->top, RD - | mov FCARG2, PC - | mov FCARG1, L:RB - | call extern lj_dispatch_call@8 // (lua_State *L, const BCIns *pc) - | // ASMFunction returned in eax/rax (RDa). - | mov SAVE_PC, 0 // Invalidate for subsequent line hook. -#if LJ_HASJIT - | and PC, -2 -#endif - | mov BASE, L:RB->base - | mov RAa, RDa - | mov RD, L:RB->top - | sub RD, BASE - | mov RBa, RAa - | movzx RA, PC_RA - | shr RD, 3 - | add NARGS:RD, 1 - | jmp RBa - | - |//----------------------------------------------------------------------- - |//-- Trace exit handler ------------------------------------------------- - |//----------------------------------------------------------------------- - | - |// Called from an exit stub with the exit number on the stack. - |// The 16 bit exit number is stored with two (sign-extended) push imm8. - |->vm_exit_handler: -#if LJ_HASJIT - |.if X64 - | push r13; push r12 - | push r11; push r10; push r9; push r8 - | push rdi; push rsi; push rbp; lea rbp, [rsp+88]; push rbp - | push rbx; push rdx; push rcx; push rax - | movzx RC, byte [rbp-8] // Reconstruct exit number. - | mov RCH, byte [rbp-16] - | mov [rbp-8], r15; mov [rbp-16], r14 - |.else - | push ebp; lea ebp, [esp+12]; push ebp - | push ebx; push edx; push ecx; push eax - | movzx RC, byte [ebp-4] // Reconstruct exit number. - | mov RCH, byte [ebp-8] - | mov [ebp-4], edi; mov [ebp-8], esi - |.endif - | // Caveat: DISPATCH is ebx. - | mov DISPATCH, [ebp] - | mov RA, [DISPATCH+DISPATCH_GL(vmstate)] // Get trace number. - | set_vmstate EXIT - | mov [DISPATCH+DISPATCH_J(exitno)], RC - | mov [DISPATCH+DISPATCH_J(parent)], RA - |.if X64 - |.if X64WIN - | sub rsp, 16*8+4*8 // Room for SSE regs + save area. - |.else - | sub rsp, 16*8 // Room for SSE regs. - |.endif - | add rbp, -128 - | movsd qword [rbp-8], xmm15; movsd qword [rbp-16], xmm14 - | movsd qword [rbp-24], xmm13; movsd qword [rbp-32], xmm12 - | movsd qword [rbp-40], xmm11; movsd qword [rbp-48], xmm10 - | movsd qword [rbp-56], xmm9; movsd qword [rbp-64], xmm8 - | movsd qword [rbp-72], xmm7; movsd qword [rbp-80], xmm6 - | movsd qword [rbp-88], xmm5; movsd qword [rbp-96], xmm4 - | movsd qword [rbp-104], xmm3; movsd qword [rbp-112], xmm2 - | movsd qword [rbp-120], xmm1; movsd qword [rbp-128], xmm0 - |.else - | sub esp, 8*8+16 // Room for SSE regs + args. - | movsd qword [ebp-40], xmm7; movsd qword [ebp-48], xmm6 - | movsd qword [ebp-56], xmm5; movsd qword [ebp-64], xmm4 - | movsd qword [ebp-72], xmm3; movsd qword [ebp-80], xmm2 - | movsd qword [ebp-88], xmm1; movsd qword [ebp-96], xmm0 - |.endif - | // Caveat: RB is ebp. - | mov L:RB, [DISPATCH+DISPATCH_GL(jit_L)] - | mov BASE, [DISPATCH+DISPATCH_GL(jit_base)] - | mov aword [DISPATCH+DISPATCH_J(L)], L:RBa - | mov dword [DISPATCH+DISPATCH_GL(jit_L)], 0 - | mov L:RB->base, BASE - |.if X64WIN - | lea CARG2, [rsp+4*8] - |.elif X64 - | mov CARG2, rsp - |.else - | lea FCARG2, [esp+16] - |.endif - | lea FCARG1, [DISPATCH+GG_DISP2J] - | call extern lj_trace_exit@8 // (jit_State *J, ExitState *ex) - | // MULTRES or negated error code returned in eax (RD). - | mov RAa, L:RB->cframe - | and RAa, CFRAME_RAWMASK - |.if X64WIN - | // Reposition stack later. - |.elif X64 - | mov rsp, RAa // Reposition stack to C frame. - |.else - | mov esp, RAa // Reposition stack to C frame. - |.endif - | mov [RAa+CFRAME_OFS_L], L:RB // Set SAVE_L (on-trace resume/yield). - | mov BASE, L:RB->base - | mov PC, [RAa+CFRAME_OFS_PC] // Get SAVE_PC. - |.if X64 - | jmp >1 - |.endif -#endif - |->vm_exit_interp: - | // RD = MULTRES or negated error code, BASE, PC and DISPATCH set. -#if LJ_HASJIT - |.if X64 - | // Restore additional callee-save registers only used in compiled code. - |.if X64WIN - | lea RAa, [rsp+9*16+4*8] - |1: - | movdqa xmm15, [RAa-9*16] - | movdqa xmm14, [RAa-8*16] - | movdqa xmm13, [RAa-7*16] - | movdqa xmm12, [RAa-6*16] - | movdqa xmm11, [RAa-5*16] - | movdqa xmm10, [RAa-4*16] - | movdqa xmm9, [RAa-3*16] - | movdqa xmm8, [RAa-2*16] - | movdqa xmm7, [RAa-1*16] - | mov rsp, RAa // Reposition stack to C frame. - | movdqa xmm6, [RAa] - | mov r15, CSAVE_3 - | mov r14, CSAVE_4 - |.else - | add rsp, 16 // Reposition stack to C frame. - |1: - |.endif - | mov r13, TMPa - | mov r12, TMPQ - |.endif - | test RD, RD; js >3 // Check for error from exit. - | mov MULTRES, RD - | mov LFUNC:KBASE, [BASE-8] - | mov KBASE, LFUNC:KBASE->pc - | mov KBASE, [KBASE+PC2PROTO(k)] - | mov dword [DISPATCH+DISPATCH_GL(jit_L)], 0 - | set_vmstate INTERP - | // Modified copy of ins_next which handles function header dispatch, too. - | mov RC, [PC] - | movzx RA, RCH - | movzx OP, RCL - | add PC, 4 - | shr RC, 16 - | cmp OP, BC_FUNCF // Function header? - | jb >2 - | mov RC, MULTRES // RC/RD holds nres+1. - |2: - |.if X64 - | jmp aword [DISPATCH+OP*8] - |.else - | jmp aword [DISPATCH+OP*4] - |.endif - | - |3: // Rethrow error from the right C frame. - | neg RD - | mov FCARG1, L:RB - | mov FCARG2, RD - | call extern lj_err_throw@8 // (lua_State *L, int errcode) -#endif - | - |//----------------------------------------------------------------------- - |//-- Math helper functions ---------------------------------------------- - |//----------------------------------------------------------------------- - | - |// FP value rounding. Called by math.floor/math.ceil fast functions - |// and from JIT code. - | - |// x87 variant: Arg/ret on x87 stack. No int/xmm registers modified. - |.macro vm_round_x87, mode1, mode2 - | fnstcw word [esp+4] // Caveat: overwrites ARG1 and ARG2. - | mov [esp+8], eax - | mov ax, mode1 - | or ax, [esp+4] - |.if mode2 ~= 0xffff - | and ax, mode2 - |.endif - | mov [esp+6], ax - | fldcw word [esp+6] - | frndint - | fldcw word [esp+4] - | mov eax, [esp+8] - | ret - |.endmacro - | - |// SSE variant: arg/ret is xmm0. xmm0-xmm3 and RD (eax) modified. - |.macro vm_round_sse, mode - | sseconst_abs xmm2, RDa - | sseconst_2p52 xmm3, RDa - | movaps xmm1, xmm0 - | andpd xmm1, xmm2 // |x| - | ucomisd xmm3, xmm1 // No truncation if 2^52 <= |x|. - | jbe >1 - | andnpd xmm2, xmm0 // Isolate sign bit. - |.if mode == 2 // trunc(x)? - | movaps xmm0, xmm1 - | addsd xmm1, xmm3 // (|x| + 2^52) - 2^52 - | subsd xmm1, xmm3 - | sseconst_1 xmm3, RDa - | cmpsd xmm0, xmm1, 1 // |x| < result? - | andpd xmm0, xmm3 - | subsd xmm1, xmm0 // If yes, subtract -1. - | orpd xmm1, xmm2 // Merge sign bit back in. - |.else - | addsd xmm1, xmm3 // (|x| + 2^52) - 2^52 - | subsd xmm1, xmm3 - | orpd xmm1, xmm2 // Merge sign bit back in. - | .if mode == 1 // ceil(x)? - | sseconst_m1 xmm2, RDa // Must subtract -1 to preserve -0. - | cmpsd xmm0, xmm1, 6 // x > result? - | .else // floor(x)? - | sseconst_1 xmm2, RDa - | cmpsd xmm0, xmm1, 1 // x < result? - | .endif - | andpd xmm0, xmm2 - | subsd xmm1, xmm0 // If yes, subtract +-1. - |.endif - | movaps xmm0, xmm1 - |1: - | ret - |.endmacro - | - |.macro vm_round, name, ssemode, mode1, mode2 - |->name: - ||if (!sse) { - | vm_round_x87 mode1, mode2 - ||} - |->name .. _sse: - | vm_round_sse ssemode - |.endmacro - | - | vm_round vm_floor, 0, 0x0400, 0xf7ff - | vm_round vm_ceil, 1, 0x0800, 0xfbff - | vm_round vm_trunc, 2, 0x0c00, 0xffff - | - |// FP modulo x%y. Called by BC_MOD* and vm_arith. - |->vm_mod: - if (sse) { - |// Args in xmm0/xmm1, return value in xmm0. - |// Caveat: xmm0-xmm5 and RC (eax) modified! - | movaps xmm5, xmm0 - | divsd xmm0, xmm1 - | sseconst_abs xmm2, RDa - | sseconst_2p52 xmm3, RDa - | movaps xmm4, xmm0 - | andpd xmm4, xmm2 // |x/y| - | ucomisd xmm3, xmm4 // No truncation if 2^52 <= |x/y|. - | jbe >1 - | andnpd xmm2, xmm0 // Isolate sign bit. - | addsd xmm4, xmm3 // (|x/y| + 2^52) - 2^52 - | subsd xmm4, xmm3 - | orpd xmm4, xmm2 // Merge sign bit back in. - | sseconst_1 xmm2, RDa - | cmpsd xmm0, xmm4, 1 // x/y < result? - | andpd xmm0, xmm2 - | subsd xmm4, xmm0 // If yes, subtract 1.0. - | movaps xmm0, xmm5 - | mulsd xmm1, xmm4 - | subsd xmm0, xmm1 - | ret - |1: - | mulsd xmm1, xmm0 - | movaps xmm0, xmm5 - | subsd xmm0, xmm1 - | ret - } else { - |// Args/ret on x87 stack (y on top). No xmm registers modified. - |// Caveat: needs 3 slots on x87 stack! RC (eax) modified! - | fld st1 - | fdiv st1 - | fnstcw word [esp+4] - | mov ax, 0x0400 - | or ax, [esp+4] - | and ax, 0xf7ff - | mov [esp+6], ax - | fldcw word [esp+6] - | frndint - | fldcw word [esp+4] - | fmulp st1 - | fsubp st1 - | ret - } - | - |// FP exponentiation e^x and 2^x. Called by math.exp fast function and - |// from JIT code. Arg/ret on x87 stack. No int/xmm regs modified. - |// Caveat: needs 3 slots on x87 stack! - |->vm_exp_x87: - | fldl2e; fmulp st1 // e^x ==> 2^(x*log2(e)) - |->vm_exp2_x87: - | .if X64WIN - | .define expscratch, dword [rsp+8] // Use scratch area. - | .elif X64 - | .define expscratch, dword [rsp-8] // Use red zone. - | .else - | .define expscratch, dword [esp+4] // Needs 4 byte scratch area. - | .endif - | fst expscratch // Caveat: overwrites ARG1. - | cmp expscratch, 0x7f800000; je >1 // Special case: e^+Inf = +Inf - | cmp expscratch, 0xff800000; je >2 // Special case: e^-Inf = 0 - |->vm_exp2raw: // Entry point for vm_pow. Without +-Inf check. - | fdup; frndint; fsub st1, st0; fxch // Split into frac/int part. - | f2xm1; fld1; faddp st1; fscale; fpop1 // ==> (2^frac-1 +1) << int - |1: - | ret - |2: - | fpop; fldz; ret - | - |// Generic power function x^y. Called by BC_POW, math.pow fast function, - |// and vm_arith. - if (!sse) { - |.if not X64 - |// Args/ret on x87 stack (y on top). RC (eax) modified. - |// Caveat: needs 3 slots on x87 stack! - |->vm_pow: - | fist dword [esp+4] // Store/reload int before comparison. - | fild dword [esp+4] // Integral exponent used in vm_powi. - ||if (cmov) { - | fucomip st1 - ||} else { - | fucomp st1; fnstsw ax; sahf - ||} - | jnz >8 // Branch for FP exponents. - | jp >9 // Branch for NaN exponent. - | fpop // Pop y and fallthrough to vm_powi. - | - |// FP/int power function x^i. Arg1/ret on x87 stack. - |// Arg2 (int) on C stack. RC (eax) modified. - |// Caveat: needs 2 slots on x87 stack! - | mov eax, [esp+4] - | cmp eax, 1; jle >6 // i<=1? - | // Now 1 < (unsigned)i <= 0x80000000. - |1: // Handle leading zeros. - | test eax, 1; jnz >2 - | fmul st0 - | shr eax, 1 - | jmp <1 - |2: - | shr eax, 1; jz >5 - | fdup - |3: // Handle trailing bits. - | fmul st0 - | shr eax, 1; jz >4 - | jnc <3 - | fmul st1, st0 - | jmp <3 - |4: - | fmulp st1 - |5: - | ret - |6: - | je <5 // x^1 ==> x - | jb >7 - | fld1; fdivrp st1 - | neg eax - | cmp eax, 1; je <5 // x^-1 ==> 1/x - | jmp <1 // x^-i ==> (1/x)^i - |7: - | fpop; fld1 // x^0 ==> 1 - | ret - | - |8: // FP/FP power function x^y. - | fst dword [esp+4] - | fxch - | fst dword [esp+8] - | mov eax, [esp+4]; shl eax, 1 - | cmp eax, 0xff000000; je >2 // x^+-Inf? - | mov eax, [esp+8]; shl eax, 1; je >4 // +-0^y? - | cmp eax, 0xff000000; je >4 // +-Inf^y? - | fyl2x - | jmp ->vm_exp2raw - | - |9: // Handle x^NaN. - | fld1 - ||if (cmov) { - | fucomip st2 - ||} else { - | fucomp st2; fnstsw ax; sahf - ||} - | je >1 // 1^NaN ==> 1 - | fxch // x^NaN ==> NaN - |1: - | fpop - | ret - | - |2: // Handle x^+-Inf. - | fabs - | fld1 - ||if (cmov) { - | fucomip st1 - ||} else { - | fucomp st1; fnstsw ax; sahf - ||} - | je >3 // +-1^+-Inf ==> 1 - | fpop; fabs; fldz; mov eax, 0; setc al - | ror eax, 1; xor eax, [esp+4]; jns >3 // |x|<>1, x^+-Inf ==> +Inf/0 - | fxch - |3: - | fpop1; fabs - | ret - | - |4: // Handle +-0^y or +-Inf^y. - | cmp dword [esp+4], 0; jge <3 // y >= 0, x^y ==> |x| - | fpop; fpop - | test eax, eax; jz >5 // y < 0, +-0^y ==> +Inf - | fldz // y < 0, +-Inf^y ==> 0 - | ret - |5: - | mov dword [esp+4], 0x7f800000 // Return +Inf. - | fld dword [esp+4] - | ret - |.endif - } else { - |->vm_pow: - } - | - |// Args in xmm0/xmm1. Ret in xmm0. xmm0-xmm2 and RC (eax) modified. - |// Needs 16 byte scratch area for x86. Also called from JIT code. - |->vm_pow_sse: - | cvtsd2si eax, xmm1 - | cvtsi2sd xmm2, eax - | ucomisd xmm1, xmm2 - | jnz >8 // Branch for FP exponents. - | jp >9 // Branch for NaN exponent. - | // Fallthrough to vm_powi_sse. - | - |// Args in xmm0/eax. Ret in xmm0. xmm0-xmm1 and eax modified. - |->vm_powi_sse: - | cmp eax, 1; jle >6 // i<=1? - | // Now 1 < (unsigned)i <= 0x80000000. - |1: // Handle leading zeros. - | test eax, 1; jnz >2 - | mulsd xmm0, xmm0 - | shr eax, 1 - | jmp <1 - |2: - | shr eax, 1; jz >5 - | movaps xmm1, xmm0 - |3: // Handle trailing bits. - | mulsd xmm0, xmm0 - | shr eax, 1; jz >4 - | jnc <3 - | mulsd xmm1, xmm0 - | jmp <3 - |4: - | mulsd xmm0, xmm1 - |5: - | ret - |6: - | je <5 // x^1 ==> x - | jb >7 // x^0 ==> 1 - | neg eax - | call <1 - | sseconst_1 xmm1, RDa - | divsd xmm1, xmm0 - | movaps xmm0, xmm1 - | ret - |7: - | sseconst_1 xmm0, RDa - | ret - | - |8: // FP/FP power function x^y. - |.if X64 - | movd rax, xmm1; shl rax, 1 - | rol rax, 12; cmp rax, 0xffe; je >2 // x^+-Inf? - | movd rax, xmm0; shl rax, 1; je >4 // +-0^y? - | rol rax, 12; cmp rax, 0xffe; je >5 // +-Inf^y? - | .if X64WIN - | movsd qword [rsp+16], xmm1 // Use scratch area. - | movsd qword [rsp+8], xmm0 - | fld qword [rsp+16] - | fld qword [rsp+8] - | .else - | movsd qword [rsp-16], xmm1 // Use red zone. - | movsd qword [rsp-8], xmm0 - | fld qword [rsp-16] - | fld qword [rsp-8] - | .endif - |.else - | movsd qword [esp+12], xmm1 // Needs 16 byte scratch area. - | movsd qword [esp+4], xmm0 - | cmp dword [esp+12], 0; jne >1 - | mov eax, [esp+16]; shl eax, 1 - | cmp eax, 0xffe00000; je >2 // x^+-Inf? - |1: - | cmp dword [esp+4], 0; jne >1 - | mov eax, [esp+8]; shl eax, 1; je >4 // +-0^y? - | cmp eax, 0xffe00000; je >5 // +-Inf^y? - |1: - | fld qword [esp+12] - | fld qword [esp+4] - |.endif - | fyl2x // y*log2(x) - | fdup; frndint; fsub st1, st0; fxch // Split into frac/int part. - | f2xm1; fld1; faddp st1; fscale; fpop1 // ==> (2^frac-1 +1) << int - |.if X64WIN - | fstp qword [rsp+8] // Use scratch area. - | movsd xmm0, qword [rsp+8] - |.elif X64 - | fstp qword [rsp-8] // Use red zone. - | movsd xmm0, qword [rsp-8] - |.else - | fstp qword [esp+4] // Needs 8 byte scratch area. - | movsd xmm0, qword [esp+4] - |.endif - | ret - | - |9: // Handle x^NaN. - | sseconst_1 xmm2, RDa - | ucomisd xmm0, xmm2; je >1 // 1^NaN ==> 1 - | movaps xmm0, xmm1 // x^NaN ==> NaN - |1: - | ret - | - |2: // Handle x^+-Inf. - | sseconst_abs xmm2, RDa - | andpd xmm0, xmm2 // |x| - | sseconst_1 xmm2, RDa - | ucomisd xmm0, xmm2; je <1 // +-1^+-Inf ==> 1 - | movmskpd eax, xmm1 - | xorps xmm0, xmm0 - | mov ah, al; setc al; xor al, ah; jne <1 // |x|<>1, x^+-Inf ==> +Inf/0 - |3: - | sseconst_hi xmm0, RDa, 7ff00000 // +Inf - | ret - | - |4: // Handle +-0^y. - | movmskpd eax, xmm1; test eax, eax; jnz <3 // y < 0, +-0^y ==> +Inf - | xorps xmm0, xmm0 // y >= 0, +-0^y ==> 0 - | ret - | - |5: // Handle +-Inf^y. - | movmskpd eax, xmm1; test eax, eax; jz <3 // y >= 0, +-Inf^y ==> +Inf - | xorps xmm0, xmm0 // y < 0, +-Inf^y ==> 0 - | ret - | - |// Callable from C: double lj_vm_foldfpm(double x, int fpm) - |// Computes fpm(x) for extended math functions. ORDER FPM. - |->vm_foldfpm: -#if LJ_HASJIT - if (sse) { - |.if X64 - | - | .if X64WIN - | .define fpmop, CARG2d - | .else - | .define fpmop, CARG1d - | .endif - | cmp fpmop, 1; jb ->vm_floor; je ->vm_ceil - | cmp fpmop, 3; jb ->vm_trunc; ja >2 - | sqrtsd xmm0, xmm0; ret - |2: - | .if X64WIN - | movsd qword [rsp+8], xmm0 // Use scratch area. - | fld qword [rsp+8] - | .else - | movsd qword [rsp-8], xmm0 // Use red zone. - | fld qword [rsp-8] - | .endif - | cmp fpmop, 5; ja >2 - | .if X64WIN; pop rax; .endif - | je >1 - | call ->vm_exp_x87 - | .if X64WIN; push rax; .endif - | jmp >7 - |1: - | call ->vm_exp2_x87 - | .if X64WIN; push rax; .endif - | jmp >7 - |2: ; cmp fpmop, 7; je >1; ja >2 - | fldln2; fxch; fyl2x; jmp >7 - |1: ; fld1; fxch; fyl2x; jmp >7 - |2: ; cmp fpmop, 9; je >1; ja >2 - | fldlg2; fxch; fyl2x; jmp >7 - |1: ; fsin; jmp >7 - |2: ; cmp fpmop, 11; je >1; ja >9 - | fcos; jmp >7 - |1: ; fptan; fpop - |7: - | .if X64WIN - | fstp qword [rsp+8] // Use scratch area. - | movsd xmm0, qword [rsp+8] - | .else - | fstp qword [rsp-8] // Use red zone. - | movsd xmm0, qword [rsp-8] - | .endif - | ret - | - |.else // x86 calling convention. - | - | .define fpmop, eax - | mov fpmop, [esp+12] - | movsd xmm0, qword [esp+4] - | cmp fpmop, 1; je >1; ja >2 - | call ->vm_floor; jmp >7 - |1: ; call ->vm_ceil; jmp >7 - |2: ; cmp fpmop, 3; je >1; ja >2 - | call ->vm_trunc; jmp >7 - |1: - | sqrtsd xmm0, xmm0 - |7: - | movsd qword [esp+4], xmm0 // Overwrite callee-owned args. - | fld qword [esp+4] - | ret - |2: ; fld qword [esp+4] - | cmp fpmop, 5; jb ->vm_exp_x87; je ->vm_exp2_x87 - |2: ; cmp fpmop, 7; je >1; ja >2 - | fldln2; fxch; fyl2x; ret - |1: ; fld1; fxch; fyl2x; ret - |2: ; cmp fpmop, 9; je >1; ja >2 - | fldlg2; fxch; fyl2x; ret - |1: ; fsin; ret - |2: ; cmp fpmop, 11; je >1; ja >9 - | fcos; ret - |1: ; fptan; fpop; ret - | - |.endif - } else { - | mov fpmop, [esp+12] - | fld qword [esp+4] - | cmp fpmop, 1; jb ->vm_floor; je ->vm_ceil - | cmp fpmop, 3; jb ->vm_trunc; ja >2 - | fsqrt; ret - |2: ; cmp fpmop, 5; jb ->vm_exp_x87; je ->vm_exp2_x87 - | cmp fpmop, 7; je >1; ja >2 - | fldln2; fxch; fyl2x; ret - |1: ; fld1; fxch; fyl2x; ret - |2: ; cmp fpmop, 9; je >1; ja >2 - | fldlg2; fxch; fyl2x; ret - |1: ; fsin; ret - |2: ; cmp fpmop, 11; je >1; ja >9 - | fcos; ret - |1: ; fptan; fpop; ret - } - |9: ; int3 // Bad fpm. -#endif - | - |// Callable from C: double lj_vm_foldarith(double x, double y, int op) - |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -) - |// and basic math functions. ORDER ARITH - |->vm_foldarith: - if (sse) { - |.if X64 - | - | .if X64WIN - | .define foldop, CARG3d - | .else - | .define foldop, CARG1d - | .endif - | cmp foldop, 1; je >1; ja >2 - | addsd xmm0, xmm1; ret - |1: ; subsd xmm0, xmm1; ret - |2: ; cmp foldop, 3; je >1; ja >2 - | mulsd xmm0, xmm1; ret - |1: ; divsd xmm0, xmm1; ret - |2: ; cmp foldop, 5; jb ->vm_mod; je ->vm_pow - | cmp foldop, 7; je >1; ja >2 - | sseconst_sign xmm1, RDa; xorps xmm0, xmm1; ret - |1: ; sseconst_abs xmm1, RDa; andps xmm0, xmm1; ret - |2: ; cmp foldop, 9; ja >2 - |.if X64WIN - | movsd qword [rsp+8], xmm0 // Use scratch area. - | movsd qword [rsp+16], xmm1 - | fld qword [rsp+8] - | fld qword [rsp+16] - |.else - | movsd qword [rsp-8], xmm0 // Use red zone. - | movsd qword [rsp-16], xmm1 - | fld qword [rsp-8] - | fld qword [rsp-16] - |.endif - | je >1 - | fpatan - |7: - |.if X64WIN - | fstp qword [rsp+8] // Use scratch area. - | movsd xmm0, qword [rsp+8] - |.else - | fstp qword [rsp-8] // Use red zone. - | movsd xmm0, qword [rsp-8] - |.endif - | ret - |1: ; fxch; fscale; fpop1; jmp <7 - |2: ; cmp foldop, 11; je >1; ja >9 - | minsd xmm0, xmm1; ret - |1: ; maxsd xmm0, xmm1; ret - |9: ; int3 // Bad op. - | - |.else // x86 calling convention. - | - | .define foldop, eax - | mov foldop, [esp+20] - | movsd xmm0, qword [esp+4] - | movsd xmm1, qword [esp+12] - | cmp foldop, 1; je >1; ja >2 - | addsd xmm0, xmm1 - |7: - | movsd qword [esp+4], xmm0 // Overwrite callee-owned args. - | fld qword [esp+4] - | ret - |1: ; subsd xmm0, xmm1; jmp <7 - |2: ; cmp foldop, 3; je >1; ja >2 - | mulsd xmm0, xmm1; jmp <7 - |1: ; divsd xmm0, xmm1; jmp <7 - |2: ; cmp foldop, 5 - | je >1; ja >2 - | call ->vm_mod; jmp <7 - |1: ; pop edx; call ->vm_pow; push edx; jmp <7 // Writes to scratch area. - |2: ; cmp foldop, 7; je >1; ja >2 - | sseconst_sign xmm1, RDa; xorps xmm0, xmm1; jmp <7 - |1: ; sseconst_abs xmm1, RDa; andps xmm0, xmm1; jmp <7 - |2: ; cmp foldop, 9; ja >2 - | fld qword [esp+4] // Reload from stack - | fld qword [esp+12] - | je >1 - | fpatan; ret - |1: ; fxch; fscale; fpop1; ret - |2: ; cmp foldop, 11; je >1; ja >9 - | minsd xmm0, xmm1; jmp <7 - |1: ; maxsd xmm0, xmm1; jmp <7 - |9: ; int3 // Bad op. - | - |.endif - } else { - | mov eax, [esp+20] - | fld qword [esp+4] - | fld qword [esp+12] - | cmp eax, 1; je >1; ja >2 - | faddp st1; ret - |1: ; fsubp st1; ret - |2: ; cmp eax, 3; je >1; ja >2 - | fmulp st1; ret - |1: ; fdivp st1; ret - |2: ; cmp eax, 5; jb ->vm_mod; je ->vm_pow - | cmp eax, 7; je >1; ja >2 - | fpop; fchs; ret - |1: ; fpop; fabs; ret - |2: ; cmp eax, 9; je >1; ja >2 - | fpatan; ret - |1: ; fxch; fscale; fpop1; ret - |2: ; cmp eax, 11; je >1; ja >9 - ||if (cmov) { - | fucomi st1; fcmovnbe st1; fpop1; ret - |1: ; fucomi st1; fcmovbe st1; fpop1; ret - ||} else { - | fucom st1; fnstsw ax; test ah, 1; jz >2; fxch; 2: ; fpop; ret - |1: ; fucom st1; fnstsw ax; test ah, 1; jnz >2; fxch; 2: ; fpop; ret - ||} - |9: ; int3 // Bad op. - } - | - |//----------------------------------------------------------------------- - |//-- Miscellaneous functions -------------------------------------------- - |//----------------------------------------------------------------------- - | - |// int lj_vm_cpuid(uint32_t f, uint32_t res[4]) - |->vm_cpuid: - |.if X64 - | mov eax, CARG1d - | .if X64WIN; push rsi; mov rsi, CARG2; .endif - | push rbx - | cpuid - | mov [rsi], eax - | mov [rsi+4], ebx - | mov [rsi+8], ecx - | mov [rsi+12], edx - | pop rbx - | .if X64WIN; pop rsi; .endif - | ret - |.else - | pushfd - | pop edx - | mov ecx, edx - | xor edx, 0x00200000 // Toggle ID bit in flags. - | push edx - | popfd - | pushfd - | pop edx - | xor eax, eax // Zero means no features supported. - | cmp ecx, edx - | jz >1 // No ID toggle means no CPUID support. - | mov eax, [esp+4] // Argument 1 is function number. - | push edi - | push ebx - | cpuid - | mov edi, [esp+16] // Argument 2 is result area. - | mov [edi], eax - | mov [edi+4], ebx - | mov [edi+8], ecx - | mov [edi+12], edx - | pop ebx - | pop edi - |1: - | ret - |.endif - | - |//----------------------------------------------------------------------- - |//-- Assertions --------------------------------------------------------- - |//----------------------------------------------------------------------- - | - |->assert_bad_for_arg_type: -#ifdef LUA_USE_ASSERT - | int3 -#endif - | int3 - | - |//----------------------------------------------------------------------- - |//-- FFI helper functions ----------------------------------------------- - |//----------------------------------------------------------------------- - | - |// Handler for callback functions. Callback slot number in ah/al. - |->vm_ffi_callback: -#if LJ_HASFFI - |.type CTSTATE, CTState, PC - |.if not X64 - | sub esp, 16 // Leave room for SAVE_ERRF etc. - |.endif - | saveregs_ // ebp/rbp already saved. ebp now holds global_State *. - | lea DISPATCH, [ebp+GG_G2DISP] - | mov CTSTATE, GL:ebp->ctype_state - | movzx eax, ax - | mov CTSTATE->cb.slot, eax - |.if X64 - | mov CTSTATE->cb.gpr[0], CARG1 - | mov CTSTATE->cb.gpr[1], CARG2 - | mov CTSTATE->cb.gpr[2], CARG3 - | mov CTSTATE->cb.gpr[3], CARG4 - | movsd qword CTSTATE->cb.fpr[0], xmm0 - | movsd qword CTSTATE->cb.fpr[1], xmm1 - | movsd qword CTSTATE->cb.fpr[2], xmm2 - | movsd qword CTSTATE->cb.fpr[3], xmm3 - |.if X64WIN - | lea rax, [rsp+CFRAME_SIZE+4*8] - |.else - | lea rax, [rsp+CFRAME_SIZE] - | mov CTSTATE->cb.gpr[4], CARG5 - | mov CTSTATE->cb.gpr[5], CARG6 - | movsd qword CTSTATE->cb.fpr[4], xmm4 - | movsd qword CTSTATE->cb.fpr[5], xmm5 - | movsd qword CTSTATE->cb.fpr[6], xmm6 - | movsd qword CTSTATE->cb.fpr[7], xmm7 - |.endif - | mov CTSTATE->cb.stack, rax - | mov CARG2, rsp - |.else - | lea eax, [esp+CFRAME_SIZE+16] - | mov CTSTATE->cb.gpr[0], FCARG1 - | mov CTSTATE->cb.gpr[1], FCARG2 - | mov CTSTATE->cb.stack, eax - | mov FCARG1, [esp+CFRAME_SIZE+12] // Move around misplaced retaddr/ebp. - | mov FCARG2, [esp+CFRAME_SIZE+8] - | mov SAVE_RET, FCARG1 - | mov SAVE_R4, FCARG2 - | mov FCARG2, esp - |.endif - | mov SAVE_PC, CTSTATE // Any value outside of bytecode is ok. - | mov FCARG1, CTSTATE - | call extern lj_ccallback_enter@8 // (CTState *cts, void *cf) - | // lua_State * returned in eax (RD). - | set_vmstate INTERP - | mov BASE, L:RD->base - | mov RD, L:RD->top - | sub RD, BASE - | mov LFUNC:RB, [BASE-8] - | shr RD, 3 - | add RD, 1 - | ins_callt -#endif - | - |->cont_ffi_callback: // Return from FFI callback. -#if LJ_HASFFI - | mov L:RA, SAVE_L - | mov CTSTATE, [DISPATCH+DISPATCH_GL(ctype_state)] - | mov aword CTSTATE->L, L:RAa - | mov L:RA->base, BASE - | mov L:RA->top, RB - | mov FCARG1, CTSTATE - | mov FCARG2, RC - | call extern lj_ccallback_leave@8 // (CTState *cts, TValue *o) - |.if X64 - | mov rax, CTSTATE->cb.gpr[0] - | movsd xmm0, qword CTSTATE->cb.fpr[0] - | jmp ->vm_leave_unw - |.else - | mov L:RB, SAVE_L - | mov eax, CTSTATE->cb.gpr[0] - | mov edx, CTSTATE->cb.gpr[1] - | cmp dword CTSTATE->cb.gpr[2], 1 - | jb >7 - | je >6 - | fld qword CTSTATE->cb.fpr[0].d - | jmp >7 - |6: - | fld dword CTSTATE->cb.fpr[0].f - |7: - | mov ecx, L:RB->top - | movzx ecx, word [ecx+6] // Get stack adjustment and copy up. - | mov SAVE_L, ecx // Must be one slot above SAVE_RET - | restoreregs - | pop ecx // Move return addr from SAVE_RET. - | add esp, [esp] // Adjust stack. - | add esp, 16 - | push ecx - | ret - |.endif -#endif - | - |->vm_ffi_call@4: // Call C function via FFI. - | // Caveat: needs special frame unwinding, see below. -#if LJ_HASFFI - |.if X64 - | .type CCSTATE, CCallState, rbx - | push rbp; mov rbp, rsp; push rbx; mov CCSTATE, CARG1 - |.else - | .type CCSTATE, CCallState, ebx - | push ebp; mov ebp, esp; push ebx; mov CCSTATE, FCARG1 - |.endif - | - | // Readjust stack. - |.if X64 - | mov eax, CCSTATE->spadj - | sub rsp, rax - |.else - | sub esp, CCSTATE->spadj -#if LJ_TARGET_WINDOWS - | mov CCSTATE->spadj, esp -#endif - |.endif - | - | // Copy stack slots. - | movzx ecx, byte CCSTATE->nsp - | sub ecx, 1 - | js >2 - |1: - |.if X64 - | mov rax, [CCSTATE+rcx*8+offsetof(CCallState, stack)] - | mov [rsp+rcx*8+CCALL_SPS_EXTRA*8], rax - |.else - | mov eax, [CCSTATE+ecx*4+offsetof(CCallState, stack)] - | mov [esp+ecx*4], eax - |.endif - | sub ecx, 1 - | jns <1 - |2: - | - |.if X64 - | movzx eax, byte CCSTATE->nfpr - | mov CARG1, CCSTATE->gpr[0] - | mov CARG2, CCSTATE->gpr[1] - | mov CARG3, CCSTATE->gpr[2] - | mov CARG4, CCSTATE->gpr[3] - |.if not X64WIN - | mov CARG5, CCSTATE->gpr[4] - | mov CARG6, CCSTATE->gpr[5] - |.endif - | test eax, eax; jz >5 - | movaps xmm0, CCSTATE->fpr[0] - | movaps xmm1, CCSTATE->fpr[1] - | movaps xmm2, CCSTATE->fpr[2] - | movaps xmm3, CCSTATE->fpr[3] - |.if not X64WIN - | cmp eax, 4; jbe >5 - | movaps xmm4, CCSTATE->fpr[4] - | movaps xmm5, CCSTATE->fpr[5] - | movaps xmm6, CCSTATE->fpr[6] - | movaps xmm7, CCSTATE->fpr[7] - |.endif - |5: - |.else - | mov FCARG1, CCSTATE->gpr[0] - | mov FCARG2, CCSTATE->gpr[1] - |.endif - | - | call aword CCSTATE->func - | - |.if X64 - | mov CCSTATE->gpr[0], rax - | movaps CCSTATE->fpr[0], xmm0 - |.if not X64WIN - | mov CCSTATE->gpr[1], rdx - | movaps CCSTATE->fpr[1], xmm1 - |.endif - |.else - | mov CCSTATE->gpr[0], eax - | mov CCSTATE->gpr[1], edx - | cmp byte CCSTATE->resx87, 1 - | jb >7 - | je >6 - | fstp qword CCSTATE->fpr[0].d[0] - | jmp >7 - |6: - | fstp dword CCSTATE->fpr[0].f[0] - |7: -#if LJ_TARGET_WINDOWS - | sub CCSTATE->spadj, esp -#endif - |.endif - | - |.if X64 - | mov rbx, [rbp-8]; leave; ret - |.else - | mov ebx, [ebp-4]; leave; ret - |.endif -#endif - |// Note: vm_ffi_call must be the last function in this object file! - | - |//----------------------------------------------------------------------- -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse) -{ - int vk = 0; - |// Note: aligning all instructions does not pay off. - |=>defop: - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - |.macro jmp_comp, lt, ge, le, gt, target - ||switch (op) { - ||case BC_ISLT: - | lt target - ||break; - ||case BC_ISGE: - | ge target - ||break; - ||case BC_ISLE: - | le target - ||break; - ||case BC_ISGT: - | gt target - ||break; - ||default: break; /* Shut up GCC. */ - ||} - |.endmacro - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - | // RA = src1, RD = src2, JMP with RD = target - | ins_AD - if (LJ_DUALNUM) { - | checkint RA, >7 - | checkint RD, >8 - | mov RB, dword [BASE+RA*8] - | add PC, 4 - | cmp RB, dword [BASE+RD*8] - | jmp_comp jge, jl, jg, jle, >9 - |6: - | movzx RD, PC_RD - | branchPC RD - |9: - | ins_next - | - |7: // RA is not an integer. - | ja ->vmeta_comp - | // RA is a number. - | cmp dword [BASE+RD*8+4], LJ_TISNUM; jb >1; jne ->vmeta_comp - | // RA is a number, RD is an integer. - if (sse) { - | cvtsi2sd xmm0, dword [BASE+RD*8] - | jmp >2 - } else { - | fld qword [BASE+RA*8] - | fild dword [BASE+RD*8] - | jmp >3 - } - | - |8: // RA is an integer, RD is not an integer. - | ja ->vmeta_comp - | // RA is an integer, RD is a number. - if (sse) { - | cvtsi2sd xmm1, dword [BASE+RA*8] - | movsd xmm0, qword [BASE+RD*8] - | add PC, 4 - | ucomisd xmm0, xmm1 - | jmp_comp jbe, ja, jb, jae, <9 - | jmp <6 - } else { - | fild dword [BASE+RA*8] - | jmp >2 - } - } else { - | checknum RA, ->vmeta_comp - | checknum RD, ->vmeta_comp - } - if (sse) { - |1: - | movsd xmm0, qword [BASE+RD*8] - |2: - | add PC, 4 - | ucomisd xmm0, qword [BASE+RA*8] - |3: - } else { - |1: - | fld qword [BASE+RA*8] // Reverse order, i.e like cmp D, A. - |2: - | fld qword [BASE+RD*8] - |3: - | add PC, 4 - | fcomparepp // eax (RD) modified! - } - | // Unordered: all of ZF CF PF set, ordered: PF clear. - | // To preserve NaN semantics GE/GT branch on unordered, but LT/LE don't. - if (LJ_DUALNUM) { - | jmp_comp jbe, ja, jb, jae, <9 - | jmp <6 - } else { - | jmp_comp jbe, ja, jb, jae, >1 - | movzx RD, PC_RD - | branchPC RD - |1: - | ins_next - } - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - | ins_AD // RA = src1, RD = src2, JMP with RD = target - | mov RB, [BASE+RD*8+4] - | add PC, 4 - if (LJ_DUALNUM) { - | cmp RB, LJ_TISNUM; jne >7 - | checkint RA, >8 - | mov RB, dword [BASE+RD*8] - | cmp RB, dword [BASE+RA*8] - if (vk) { - | jne >9 - } else { - | je >9 - } - | movzx RD, PC_RD - | branchPC RD - |9: - | ins_next - | - |7: // RD is not an integer. - | ja >5 - | // RD is a number. - | cmp dword [BASE+RA*8+4], LJ_TISNUM; jb >1; jne >5 - | // RD is a number, RA is an integer. - if (sse) { - | cvtsi2sd xmm0, dword [BASE+RA*8] - } else { - | fild dword [BASE+RA*8] - } - | jmp >2 - | - |8: // RD is an integer, RA is not an integer. - | ja >5 - | // RD is an integer, RA is a number. - if (sse) { - | cvtsi2sd xmm0, dword [BASE+RD*8] - | ucomisd xmm0, qword [BASE+RA*8] - } else { - | fild dword [BASE+RD*8] - | fld qword [BASE+RA*8] - } - | jmp >4 - | - } else { - | cmp RB, LJ_TISNUM; jae >5 - | checknum RA, >5 - } - if (sse) { - |1: - | movsd xmm0, qword [BASE+RA*8] - |2: - | ucomisd xmm0, qword [BASE+RD*8] - |4: - } else { - |1: - | fld qword [BASE+RA*8] - |2: - | fld qword [BASE+RD*8] - |4: - | fcomparepp // eax (RD) modified! - } - iseqne_fp: - if (vk) { - | jp >2 // Unordered means not equal. - | jne >2 - } else { - | jp >2 // Unordered means not equal. - | je >1 - } - iseqne_end: - if (vk) { - |1: // EQ: Branch to the target. - | movzx RD, PC_RD - | branchPC RD - |2: // NE: Fallthrough to next instruction. - if (!LJ_HASFFI) { - |3: - } - } else { - if (!LJ_HASFFI) { - |3: - } - |2: // NE: Branch to the target. - | movzx RD, PC_RD - | branchPC RD - |1: // EQ: Fallthrough to next instruction. - } - if (LJ_DUALNUM && (op == BC_ISEQV || op == BC_ISNEV || - op == BC_ISEQN || op == BC_ISNEN)) { - | jmp <9 - } else { - | ins_next - } - | - if (op == BC_ISEQV || op == BC_ISNEV) { - |5: // Either or both types are not numbers. - if (LJ_HASFFI) { - | cmp RB, LJ_TCDATA; je ->vmeta_equal_cd - | checktp RA, LJ_TCDATA; je ->vmeta_equal_cd - } - | checktp RA, RB // Compare types. - | jne <2 // Not the same type? - | cmp RB, LJ_TISPRI - | jae <1 // Same type and primitive type? - | - | // Same types and not a primitive type. Compare GCobj or pvalue. - | mov RA, [BASE+RA*8] - | mov RD, [BASE+RD*8] - | cmp RA, RD - | je <1 // Same GCobjs or pvalues? - | cmp RB, LJ_TISTABUD - | ja <2 // Different objects and not table/ud? - |.if X64 - | cmp RB, LJ_TUDATA // And not 64 bit lightuserdata. - | jb <2 - |.endif - | - | // Different tables or userdatas. Need to check __eq metamethod. - | // Field metatable must be at same offset for GCtab and GCudata! - | mov TAB:RB, TAB:RA->metatable - | test TAB:RB, TAB:RB - | jz <2 // No metatable? - | test byte TAB:RB->nomm, 1<vmeta_equal // Handle __eq metamethod. - } else if (LJ_HASFFI) { - |3: - | cmp RB, LJ_TCDATA - if (LJ_DUALNUM && vk) { - | jne <9 - } else { - | jne <2 - } - | jmp ->vmeta_equal_cd - } - break; - case BC_ISEQS: case BC_ISNES: - vk = op == BC_ISEQS; - | ins_AND // RA = src, RD = str const, JMP with RD = target - | mov RB, [BASE+RA*8+4] - | add PC, 4 - | cmp RB, LJ_TSTR; jne >3 - | mov RA, [BASE+RA*8] - | cmp RA, [KBASE+RD*4] - iseqne_test: - if (vk) { - | jne >2 - } else { - | je >1 - } - goto iseqne_end; - case BC_ISEQN: case BC_ISNEN: - vk = op == BC_ISEQN; - | ins_AD // RA = src, RD = num const, JMP with RD = target - | mov RB, [BASE+RA*8+4] - | add PC, 4 - if (LJ_DUALNUM) { - | cmp RB, LJ_TISNUM; jne >7 - | cmp dword [KBASE+RD*8+4], LJ_TISNUM; jne >8 - | mov RB, dword [KBASE+RD*8] - | cmp RB, dword [BASE+RA*8] - if (vk) { - | jne >9 - } else { - | je >9 - } - | movzx RD, PC_RD - | branchPC RD - |9: - | ins_next - | - |7: // RA is not an integer. - | ja >3 - | // RA is a number. - | cmp dword [KBASE+RD*8+4], LJ_TISNUM; jb >1 - | // RA is a number, RD is an integer. - if (sse) { - | cvtsi2sd xmm0, dword [KBASE+RD*8] - } else { - | fild dword [KBASE+RD*8] - } - | jmp >2 - | - |8: // RA is an integer, RD is a number. - if (sse) { - | cvtsi2sd xmm0, dword [BASE+RA*8] - | ucomisd xmm0, qword [KBASE+RD*8] - } else { - | fild dword [BASE+RA*8] - | fld qword [KBASE+RD*8] - } - | jmp >4 - } else { - | cmp RB, LJ_TISNUM; jae >3 - } - if (sse) { - |1: - | movsd xmm0, qword [KBASE+RD*8] - |2: - | ucomisd xmm0, qword [BASE+RA*8] - |4: - } else { - |1: - | fld qword [KBASE+RD*8] - |2: - | fld qword [BASE+RA*8] - |4: - | fcomparepp // eax (RD) modified! - } - goto iseqne_fp; - case BC_ISEQP: case BC_ISNEP: - vk = op == BC_ISEQP; - | ins_AND // RA = src, RD = primitive type (~), JMP with RD = target - | mov RB, [BASE+RA*8+4] - | add PC, 4 - | cmp RB, RD - if (!LJ_HASFFI) goto iseqne_test; - if (vk) { - | jne >3 - | movzx RD, PC_RD - | branchPC RD - |2: - | ins_next - |3: - | cmp RB, LJ_TCDATA; jne <2 - | jmp ->vmeta_equal_cd - } else { - | je >2 - | cmp RB, LJ_TCDATA; je ->vmeta_equal_cd - | movzx RD, PC_RD - | branchPC RD - |2: - | ins_next - } - break; - - /* -- Unary test and copy ops ------------------------------------------- */ - - case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: - | ins_AD // RA = dst or unused, RD = src, JMP with RD = target - | mov RB, [BASE+RD*8+4] - | add PC, 4 - | cmp RB, LJ_TISTRUECOND - if (op == BC_IST || op == BC_ISTC) { - | jae >1 - } else { - | jb >1 - } - if (op == BC_ISTC || op == BC_ISFC) { - | mov [BASE+RA*8+4], RB - | mov RB, [BASE+RD*8] - | mov [BASE+RA*8], RB - } - | movzx RD, PC_RD - | branchPC RD - |1: // Fallthrough to the next instruction. - | ins_next - break; - - /* -- Unary ops --------------------------------------------------------- */ - - case BC_MOV: - | ins_AD // RA = dst, RD = src - |.if X64 - | mov RBa, [BASE+RD*8] - | mov [BASE+RA*8], RBa - |.else - | mov RB, [BASE+RD*8+4] - | mov RD, [BASE+RD*8] - | mov [BASE+RA*8+4], RB - | mov [BASE+RA*8], RD - |.endif - | ins_next_ - break; - case BC_NOT: - | ins_AD // RA = dst, RD = src - | xor RB, RB - | checktp RD, LJ_TISTRUECOND - | adc RB, LJ_TTRUE - | mov [BASE+RA*8+4], RB - | ins_next - break; - case BC_UNM: - | ins_AD // RA = dst, RD = src - if (LJ_DUALNUM) { - | checkint RD, >5 - | mov RB, [BASE+RD*8] - | neg RB - | jo >4 - | mov dword [BASE+RA*8+4], LJ_TISNUM - | mov dword [BASE+RA*8], RB - |9: - | ins_next - |4: - | mov dword [BASE+RA*8+4], 0x41e00000 // 2^31. - | mov dword [BASE+RA*8], 0 - | jmp <9 - |5: - | ja ->vmeta_unm - } else { - | checknum RD, ->vmeta_unm - } - if (sse) { - | movsd xmm0, qword [BASE+RD*8] - | sseconst_sign xmm1, RDa - | xorps xmm0, xmm1 - | movsd qword [BASE+RA*8], xmm0 - } else { - | fld qword [BASE+RD*8] - | fchs - | fstp qword [BASE+RA*8] - } - if (LJ_DUALNUM) { - | jmp <9 - } else { - | ins_next - } - break; - case BC_LEN: - | ins_AD // RA = dst, RD = src - | checkstr RD, >2 - | mov STR:RD, [BASE+RD*8] - if (LJ_DUALNUM) { - | mov RD, dword STR:RD->len - |1: - | mov dword [BASE+RA*8+4], LJ_TISNUM - | mov dword [BASE+RA*8], RD - } else if (sse) { - | xorps xmm0, xmm0 - | cvtsi2sd xmm0, dword STR:RD->len - |1: - | movsd qword [BASE+RA*8], xmm0 - } else { - | fild dword STR:RD->len - |1: - | fstp qword [BASE+RA*8] - } - | ins_next - |2: - | checktab RD, ->vmeta_len - | mov TAB:FCARG1, [BASE+RD*8] -#ifdef LUAJIT_ENABLE_LUA52COMPAT - | mov TAB:RB, TAB:FCARG1->metatable - | cmp TAB:RB, 0 - | jnz >9 - |3: -#endif - |->BC_LEN_Z: - | mov RB, BASE // Save BASE. - | call extern lj_tab_len@4 // (GCtab *t) - | // Length of table returned in eax (RD). - if (LJ_DUALNUM) { - | // Nothing to do. - } else if (sse) { - | cvtsi2sd xmm0, RD - } else { - |.if not X64 - | mov ARG1, RD - | fild ARG1 - |.endif - } - | mov BASE, RB // Restore BASE. - | movzx RA, PC_RA - | jmp <1 -#ifdef LUAJIT_ENABLE_LUA52COMPAT - |9: // Check for __len. - | test byte TAB:RB->nomm, 1<vmeta_len // 'no __len' flag NOT set: check. -#endif - break; - - /* -- Binary ops -------------------------------------------------------- */ - - |.macro ins_arithpre, x87ins, sseins, ssereg - | ins_ABC - ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); - ||switch (vk) { - ||case 0: - | checknum RB, ->vmeta_arith_vn - ||if (LJ_DUALNUM) { - | cmp dword [KBASE+RC*8+4], LJ_TISNUM; jae ->vmeta_arith_vn - ||} - ||if (sse) { - | movsd xmm0, qword [BASE+RB*8] - | sseins ssereg, qword [KBASE+RC*8] - ||} else { - | fld qword [BASE+RB*8] - | x87ins qword [KBASE+RC*8] - ||} - || break; - ||case 1: - | checknum RB, ->vmeta_arith_nv - ||if (LJ_DUALNUM) { - | cmp dword [KBASE+RC*8+4], LJ_TISNUM; jae ->vmeta_arith_nv - ||} - ||if (sse) { - | movsd xmm0, qword [KBASE+RC*8] - | sseins ssereg, qword [BASE+RB*8] - ||} else { - | fld qword [KBASE+RC*8] - | x87ins qword [BASE+RB*8] - ||} - || break; - ||default: - | checknum RB, ->vmeta_arith_vv - | checknum RC, ->vmeta_arith_vv - ||if (sse) { - | movsd xmm0, qword [BASE+RB*8] - | sseins ssereg, qword [BASE+RC*8] - ||} else { - | fld qword [BASE+RB*8] - | x87ins qword [BASE+RC*8] - ||} - || break; - ||} - |.endmacro - | - |.macro ins_arithdn, intins - | ins_ABC - ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); - ||switch (vk) { - ||case 0: - | checkint RB, ->vmeta_arith_vn - | cmp dword [KBASE+RC*8+4], LJ_TISNUM; jne ->vmeta_arith_vn - | mov RB, [BASE+RB*8] - | intins RB, [KBASE+RC*8]; jo ->vmeta_arith_vno - || break; - ||case 1: - | checkint RB, ->vmeta_arith_nv - | cmp dword [KBASE+RC*8+4], LJ_TISNUM; jne ->vmeta_arith_nv - | mov RC, [KBASE+RC*8] - | intins RC, [BASE+RB*8]; jo ->vmeta_arith_nvo - || break; - ||default: - | checkint RB, ->vmeta_arith_vv - | checkint RC, ->vmeta_arith_vv - | mov RB, [BASE+RB*8] - | intins RB, [BASE+RC*8]; jo ->vmeta_arith_vvo - || break; - ||} - | mov dword [BASE+RA*8+4], LJ_TISNUM - ||if (vk == 1) { - | mov dword [BASE+RA*8], RC - ||} else { - | mov dword [BASE+RA*8], RB - ||} - | ins_next - |.endmacro - | - |.macro ins_arithpost - ||if (sse) { - | movsd qword [BASE+RA*8], xmm0 - ||} else { - | fstp qword [BASE+RA*8] - ||} - |.endmacro - | - |.macro ins_arith, x87ins, sseins - | ins_arithpre x87ins, sseins, xmm0 - | ins_arithpost - | ins_next - |.endmacro - | - |.macro ins_arith, intins, x87ins, sseins - ||if (LJ_DUALNUM) { - | ins_arithdn intins - ||} else { - | ins_arith, x87ins, sseins - ||} - |.endmacro - - | // RA = dst, RB = src1 or num const, RC = src2 or num const - case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: - | ins_arith add, fadd, addsd - break; - case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: - | ins_arith sub, fsub, subsd - break; - case BC_MULVN: case BC_MULNV: case BC_MULVV: - | ins_arith imul, fmul, mulsd - break; - case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: - | ins_arith fdiv, divsd - break; - case BC_MODVN: - | ins_arithpre fld, movsd, xmm1 - |->BC_MODVN_Z: - | call ->vm_mod - | ins_arithpost - | ins_next - break; - case BC_MODNV: case BC_MODVV: - | ins_arithpre fld, movsd, xmm1 - | jmp ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway. - break; - case BC_POW: - | ins_arithpre fld, movsd, xmm1 - | call ->vm_pow - | ins_arithpost - | ins_next - break; - - case BC_CAT: - | ins_ABC // RA = dst, RB = src_start, RC = src_end - |.if X64 - | mov L:CARG1d, SAVE_L - | mov L:CARG1d->base, BASE - | lea CARG2d, [BASE+RC*8] - | mov CARG3d, RC - | sub CARG3d, RB - |->BC_CAT_Z: - | mov L:RB, L:CARG1d - |.else - | lea RA, [BASE+RC*8] - | sub RC, RB - | mov ARG2, RA - | mov ARG3, RC - |->BC_CAT_Z: - | mov L:RB, SAVE_L - | mov ARG1, L:RB - | mov L:RB->base, BASE - |.endif - | mov SAVE_PC, PC - | call extern lj_meta_cat // (lua_State *L, TValue *top, int left) - | // NULL (finished) or TValue * (metamethod) returned in eax (RC). - | mov BASE, L:RB->base - | test RC, RC - | jnz ->vmeta_binop - | movzx RB, PC_RB // Copy result to Stk[RA] from Stk[RB]. - | movzx RA, PC_RA - |.if X64 - | mov RCa, [BASE+RB*8] - | mov [BASE+RA*8], RCa - |.else - | mov RC, [BASE+RB*8+4] - | mov RB, [BASE+RB*8] - | mov [BASE+RA*8+4], RC - | mov [BASE+RA*8], RB - |.endif - | ins_next - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - | ins_AND // RA = dst, RD = str const (~) - | mov RD, [KBASE+RD*4] - | mov dword [BASE+RA*8+4], LJ_TSTR - | mov [BASE+RA*8], RD - | ins_next - break; - case BC_KCDATA: -#if LJ_HASFFI - | ins_AND // RA = dst, RD = cdata const (~) - | mov RD, [KBASE+RD*4] - | mov dword [BASE+RA*8+4], LJ_TCDATA - | mov [BASE+RA*8], RD - | ins_next -#endif - break; - case BC_KSHORT: - | ins_AD // RA = dst, RD = signed int16 literal - if (LJ_DUALNUM) { - | movsx RD, RDW - | mov dword [BASE+RA*8+4], LJ_TISNUM - | mov dword [BASE+RA*8], RD - } else if (sse) { - | movsx RD, RDW // Sign-extend literal. - | cvtsi2sd xmm0, RD - | movsd qword [BASE+RA*8], xmm0 - } else { - | fild PC_RD // Refetch signed RD from instruction. - | fstp qword [BASE+RA*8] - } - | ins_next - break; - case BC_KNUM: - | ins_AD // RA = dst, RD = num const - if (sse) { - | movsd xmm0, qword [KBASE+RD*8] - | movsd qword [BASE+RA*8], xmm0 - } else { - | fld qword [KBASE+RD*8] - | fstp qword [BASE+RA*8] - } - | ins_next - break; - case BC_KPRI: - | ins_AND // RA = dst, RD = primitive type (~) - | mov [BASE+RA*8+4], RD - | ins_next - break; - case BC_KNIL: - | ins_AD // RA = dst_start, RD = dst_end - | lea RA, [BASE+RA*8+12] - | lea RD, [BASE+RD*8+4] - | mov RB, LJ_TNIL - | mov [RA-8], RB // Sets minimum 2 slots. - |1: - | mov [RA], RB - | add RA, 8 - | cmp RA, RD - | jbe <1 - | ins_next - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - | ins_AD // RA = dst, RD = upvalue # - | mov LFUNC:RB, [BASE-8] - | mov UPVAL:RB, [LFUNC:RB+RD*4+offsetof(GCfuncL, uvptr)] - | mov RB, UPVAL:RB->v - |.if X64 - | mov RDa, [RB] - | mov [BASE+RA*8], RDa - |.else - | mov RD, [RB+4] - | mov RB, [RB] - | mov [BASE+RA*8+4], RD - | mov [BASE+RA*8], RB - |.endif - | ins_next - break; - case BC_USETV: -#define TV2MARKOFS \ - ((int32_t)offsetof(GCupval, marked)-(int32_t)offsetof(GCupval, tv)) - | ins_AD // RA = upvalue #, RD = src - | mov LFUNC:RB, [BASE-8] - | mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)] - | cmp byte UPVAL:RB->closed, 0 - | mov RB, UPVAL:RB->v - | mov RA, [BASE+RD*8] - | mov RD, [BASE+RD*8+4] - | mov [RB], RA - | mov [RB+4], RD - | jz >1 - | // Check barrier for closed upvalue. - | test byte [RB+TV2MARKOFS], LJ_GC_BLACK // isblack(uv) - | jnz >2 - |1: - | ins_next - | - |2: // Upvalue is black. Check if new value is collectable and white. - | sub RD, LJ_TISGCV - | cmp RD, LJ_TISNUM - LJ_TISGCV // tvisgcv(v) - | jbe <1 - | test byte GCOBJ:RA->gch.marked, LJ_GC_WHITES // iswhite(v) - | jz <1 - | // Crossed a write barrier. Move the barrier forward. - |.if X64 and not X64WIN - | mov FCARG2, RB - | mov RB, BASE // Save BASE. - |.else - | xchg FCARG2, RB // Save BASE (FCARG2 == BASE). - |.endif - | lea GL:FCARG1, [DISPATCH+GG_DISP2G] - | call extern lj_gc_barrieruv@8 // (global_State *g, TValue *tv) - | mov BASE, RB // Restore BASE. - | jmp <1 - break; -#undef TV2MARKOFS - case BC_USETS: - | ins_AND // RA = upvalue #, RD = str const (~) - | mov LFUNC:RB, [BASE-8] - | mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)] - | mov GCOBJ:RA, [KBASE+RD*4] - | mov RD, UPVAL:RB->v - | mov [RD], GCOBJ:RA - | mov dword [RD+4], LJ_TSTR - | test byte UPVAL:RB->marked, LJ_GC_BLACK // isblack(uv) - | jnz >2 - |1: - | ins_next - | - |2: // Check if string is white and ensure upvalue is closed. - | test byte GCOBJ:RA->gch.marked, LJ_GC_WHITES // iswhite(str) - | jz <1 - | cmp byte UPVAL:RB->closed, 0 - | jz <1 - | // Crossed a write barrier. Move the barrier forward. - | mov RB, BASE // Save BASE (FCARG2 == BASE). - | mov FCARG2, RD - | lea GL:FCARG1, [DISPATCH+GG_DISP2G] - | call extern lj_gc_barrieruv@8 // (global_State *g, TValue *tv) - | mov BASE, RB // Restore BASE. - | jmp <1 - break; - case BC_USETN: - | ins_AD // RA = upvalue #, RD = num const - | mov LFUNC:RB, [BASE-8] - if (sse) { - | movsd xmm0, qword [KBASE+RD*8] - } else { - | fld qword [KBASE+RD*8] - } - | mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)] - | mov RA, UPVAL:RB->v - if (sse) { - | movsd qword [RA], xmm0 - } else { - | fstp qword [RA] - } - | ins_next - break; - case BC_USETP: - | ins_AND // RA = upvalue #, RD = primitive type (~) - | mov LFUNC:RB, [BASE-8] - | mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)] - | mov RA, UPVAL:RB->v - | mov [RA+4], RD - | ins_next - break; - case BC_UCLO: - | ins_AD // RA = level, RD = target - | branchPC RD // Do this first to free RD. - | mov L:RB, SAVE_L - | cmp dword L:RB->openupval, 0 - | je >1 - | mov L:RB->base, BASE - | lea FCARG2, [BASE+RA*8] // Caveat: FCARG2 == BASE - | mov L:FCARG1, L:RB // Caveat: FCARG1 == RA - | call extern lj_func_closeuv@8 // (lua_State *L, TValue *level) - | mov BASE, L:RB->base - |1: - | ins_next - break; - - case BC_FNEW: - | ins_AND // RA = dst, RD = proto const (~) (holding function prototype) - |.if X64 - | mov L:RB, SAVE_L - | mov L:RB->base, BASE // Caveat: CARG2d/CARG3d may be BASE. - | mov CARG3d, [BASE-8] - | mov CARG2d, [KBASE+RD*4] // Fetch GCproto *. - | mov CARG1d, L:RB - |.else - | mov LFUNC:RA, [BASE-8] - | mov PROTO:RD, [KBASE+RD*4] // Fetch GCproto *. - | mov L:RB, SAVE_L - | mov ARG3, LFUNC:RA - | mov ARG2, PROTO:RD - | mov ARG1, L:RB - | mov L:RB->base, BASE - |.endif - | mov SAVE_PC, PC - | // (lua_State *L, GCproto *pt, GCfuncL *parent) - | call extern lj_func_newL_gc - | // GCfuncL * returned in eax (RC). - | mov BASE, L:RB->base - | movzx RA, PC_RA - | mov [BASE+RA*8], LFUNC:RC - | mov dword [BASE+RA*8+4], LJ_TFUNC - | ins_next - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - | ins_AD // RA = dst, RD = hbits|asize - | mov L:RB, SAVE_L - | mov L:RB->base, BASE - | mov RA, [DISPATCH+DISPATCH_GL(gc.total)] - | cmp RA, [DISPATCH+DISPATCH_GL(gc.threshold)] - | mov SAVE_PC, PC - | jae >5 - |1: - |.if X64 - | mov CARG3d, RD - | and RD, 0x7ff - | shr CARG3d, 11 - |.else - | mov RA, RD - | and RD, 0x7ff - | shr RA, 11 - | mov ARG3, RA - |.endif - | cmp RD, 0x7ff - | je >3 - |2: - |.if X64 - | mov L:CARG1d, L:RB - | mov CARG2d, RD - |.else - | mov ARG1, L:RB - | mov ARG2, RD - |.endif - | call extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits) - | // Table * returned in eax (RC). - | mov BASE, L:RB->base - | movzx RA, PC_RA - | mov [BASE+RA*8], TAB:RC - | mov dword [BASE+RA*8+4], LJ_TTAB - | ins_next - |3: // Turn 0x7ff into 0x801. - | mov RD, 0x801 - | jmp <2 - |5: - | mov L:FCARG1, L:RB - | call extern lj_gc_step_fixtop@4 // (lua_State *L) - | movzx RD, PC_RD - | jmp <1 - break; - case BC_TDUP: - | ins_AND // RA = dst, RD = table const (~) (holding template table) - | mov L:RB, SAVE_L - | mov RA, [DISPATCH+DISPATCH_GL(gc.total)] - | mov SAVE_PC, PC - | cmp RA, [DISPATCH+DISPATCH_GL(gc.threshold)] - | mov L:RB->base, BASE - | jae >3 - |2: - | mov TAB:FCARG2, [KBASE+RD*4] // Caveat: FCARG2 == BASE - | mov L:FCARG1, L:RB // Caveat: FCARG1 == RA - | call extern lj_tab_dup@8 // (lua_State *L, Table *kt) - | // Table * returned in eax (RC). - | mov BASE, L:RB->base - | movzx RA, PC_RA - | mov [BASE+RA*8], TAB:RC - | mov dword [BASE+RA*8+4], LJ_TTAB - | ins_next - |3: - | mov L:FCARG1, L:RB - | call extern lj_gc_step_fixtop@4 // (lua_State *L) - | movzx RD, PC_RD // Need to reload RD. - | not RDa - | jmp <2 - break; - - case BC_GGET: - | ins_AND // RA = dst, RD = str const (~) - | mov LFUNC:RB, [BASE-8] - | mov TAB:RB, LFUNC:RB->env - | mov STR:RC, [KBASE+RD*4] - | jmp ->BC_TGETS_Z - break; - case BC_GSET: - | ins_AND // RA = src, RD = str const (~) - | mov LFUNC:RB, [BASE-8] - | mov TAB:RB, LFUNC:RB->env - | mov STR:RC, [KBASE+RD*4] - | jmp ->BC_TSETS_Z - break; - - case BC_TGETV: - | ins_ABC // RA = dst, RB = table, RC = key - | checktab RB, ->vmeta_tgetv - | mov TAB:RB, [BASE+RB*8] - | - | // Integer key? - if (LJ_DUALNUM) { - | checkint RC, >5 - | mov RC, dword [BASE+RC*8] - } else { - | // Convert number to int and back and compare. - | checknum RC, >5 - if (sse) { - | movsd xmm0, qword [BASE+RC*8] - | cvtsd2si RC, xmm0 - | cvtsi2sd xmm1, RC - | ucomisd xmm0, xmm1 - } else { - |.if not X64 - | fld qword [BASE+RC*8] - | fist ARG1 - | fild ARG1 - | fcomparepp // eax (RC) modified! - | mov RC, ARG1 - |.endif - } - | jne ->vmeta_tgetv // Generic numeric key? Use fallback. - } - | cmp RC, TAB:RB->asize // Takes care of unordered, too. - | jae ->vmeta_tgetv // Not in array part? Use fallback. - | shl RC, 3 - | add RC, TAB:RB->array - | cmp dword [RC+4], LJ_TNIL // Avoid overwriting RB in fastpath. - | je >2 - | // Get array slot. - |.if X64 - | mov RBa, [RC] - | mov [BASE+RA*8], RBa - |.else - | mov RB, [RC] - | mov RC, [RC+4] - | mov [BASE+RA*8], RB - | mov [BASE+RA*8+4], RC - |.endif - |1: - | ins_next - | - |2: // Check for __index if table value is nil. - | cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath. - | jz >3 - | mov TAB:RA, TAB:RB->metatable - | test byte TAB:RA->nomm, 1<vmeta_tgetv // 'no __index' flag NOT set: check. - | movzx RA, PC_RA // Restore RA. - |3: - | mov dword [BASE+RA*8+4], LJ_TNIL - | jmp <1 - | - |5: // String key? - | checkstr RC, ->vmeta_tgetv - | mov STR:RC, [BASE+RC*8] - | jmp ->BC_TGETS_Z - break; - case BC_TGETS: - | ins_ABC // RA = dst, RB = table, RC = str const (~) - | not RCa - | mov STR:RC, [KBASE+RC*4] - | checktab RB, ->vmeta_tgets - | mov TAB:RB, [BASE+RB*8] - |->BC_TGETS_Z: // RB = GCtab *, RC = GCstr *, refetches PC_RA. - | mov RA, TAB:RB->hmask - | and RA, STR:RC->hash - | imul RA, #NODE - | add NODE:RA, TAB:RB->node - |1: - | cmp dword NODE:RA->key.it, LJ_TSTR - | jne >4 - | cmp dword NODE:RA->key.gcr, STR:RC - | jne >4 - | // Ok, key found. Assumes: offsetof(Node, val) == 0 - | cmp dword [RA+4], LJ_TNIL // Avoid overwriting RB in fastpath. - | je >5 // Key found, but nil value? - | movzx RC, PC_RA - | // Get node value. - |.if X64 - | mov RBa, [RA] - | mov [BASE+RC*8], RBa - |.else - | mov RB, [RA] - | mov RA, [RA+4] - | mov [BASE+RC*8], RB - | mov [BASE+RC*8+4], RA - |.endif - |2: - | ins_next - | - |3: - | movzx RC, PC_RA - | mov dword [BASE+RC*8+4], LJ_TNIL - | jmp <2 - | - |4: // Follow hash chain. - | mov NODE:RA, NODE:RA->next - | test NODE:RA, NODE:RA - | jnz <1 - | // End of hash chain: key not found, nil result. - | - |5: // Check for __index if table value is nil. - | mov TAB:RA, TAB:RB->metatable - | test TAB:RA, TAB:RA - | jz <3 // No metatable: done. - | test byte TAB:RA->nomm, 1<vmeta_tgets // Caveat: preserve STR:RC. - break; - case BC_TGETB: - | ins_ABC // RA = dst, RB = table, RC = byte literal - | checktab RB, ->vmeta_tgetb - | mov TAB:RB, [BASE+RB*8] - | cmp RC, TAB:RB->asize - | jae ->vmeta_tgetb - | shl RC, 3 - | add RC, TAB:RB->array - | cmp dword [RC+4], LJ_TNIL // Avoid overwriting RB in fastpath. - | je >2 - | // Get array slot. - |.if X64 - | mov RBa, [RC] - | mov [BASE+RA*8], RBa - |.else - | mov RB, [RC] - | mov RC, [RC+4] - | mov [BASE+RA*8], RB - | mov [BASE+RA*8+4], RC - |.endif - |1: - | ins_next - | - |2: // Check for __index if table value is nil. - | cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath. - | jz >3 - | mov TAB:RA, TAB:RB->metatable - | test byte TAB:RA->nomm, 1<vmeta_tgetb // 'no __index' flag NOT set: check. - | movzx RA, PC_RA // Restore RA. - |3: - | mov dword [BASE+RA*8+4], LJ_TNIL - | jmp <1 - break; - - case BC_TSETV: - | ins_ABC // RA = src, RB = table, RC = key - | checktab RB, ->vmeta_tsetv - | mov TAB:RB, [BASE+RB*8] - | - | // Integer key? - if (LJ_DUALNUM) { - | checkint RC, >5 - | mov RC, dword [BASE+RC*8] - } else { - | // Convert number to int and back and compare. - | checknum RC, >5 - if (sse) { - | movsd xmm0, qword [BASE+RC*8] - | cvtsd2si RC, xmm0 - | cvtsi2sd xmm1, RC - | ucomisd xmm0, xmm1 - } else { - |.if not X64 - | fld qword [BASE+RC*8] - | fist ARG1 - | fild ARG1 - | fcomparepp // eax (RC) modified! - | mov RC, ARG1 - |.endif - } - | jne ->vmeta_tsetv // Generic numeric key? Use fallback. - } - | cmp RC, TAB:RB->asize // Takes care of unordered, too. - | jae ->vmeta_tsetv - | shl RC, 3 - | add RC, TAB:RB->array - | cmp dword [RC+4], LJ_TNIL - | je >3 // Previous value is nil? - |1: - | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) - | jnz >7 - |2: // Set array slot. - |.if X64 - | mov RBa, [BASE+RA*8] - | mov [RC], RBa - |.else - | mov RB, [BASE+RA*8+4] - | mov RA, [BASE+RA*8] - | mov [RC+4], RB - | mov [RC], RA - |.endif - | ins_next - | - |3: // Check for __newindex if previous value is nil. - | cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath. - | jz <1 - | mov TAB:RA, TAB:RB->metatable - | test byte TAB:RA->nomm, 1<vmeta_tsetv // 'no __newindex' flag NOT set: check. - | movzx RA, PC_RA // Restore RA. - | jmp <1 - | - |5: // String key? - | checkstr RC, ->vmeta_tsetv - | mov STR:RC, [BASE+RC*8] - | jmp ->BC_TSETS_Z - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, RA - | movzx RA, PC_RA // Restore RA. - | jmp <2 - break; - case BC_TSETS: - | ins_ABC // RA = src, RB = table, RC = str const (~) - | not RCa - | mov STR:RC, [KBASE+RC*4] - | checktab RB, ->vmeta_tsets - | mov TAB:RB, [BASE+RB*8] - |->BC_TSETS_Z: // RB = GCtab *, RC = GCstr *, refetches PC_RA. - | mov RA, TAB:RB->hmask - | and RA, STR:RC->hash - | imul RA, #NODE - | mov byte TAB:RB->nomm, 0 // Clear metamethod cache. - | add NODE:RA, TAB:RB->node - |1: - | cmp dword NODE:RA->key.it, LJ_TSTR - | jne >5 - | cmp dword NODE:RA->key.gcr, STR:RC - | jne >5 - | // Ok, key found. Assumes: offsetof(Node, val) == 0 - | cmp dword [RA+4], LJ_TNIL - | je >4 // Previous value is nil? - |2: - | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) - | jnz >7 - |3: // Set node value. - | movzx RC, PC_RA - |.if X64 - | mov RBa, [BASE+RC*8] - | mov [RA], RBa - |.else - | mov RB, [BASE+RC*8+4] - | mov RC, [BASE+RC*8] - | mov [RA+4], RB - | mov [RA], RC - |.endif - | ins_next - | - |4: // Check for __newindex if previous value is nil. - | cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath. - | jz <2 - | mov TMP1, RA // Save RA. - | mov TAB:RA, TAB:RB->metatable - | test byte TAB:RA->nomm, 1<vmeta_tsets // 'no __newindex' flag NOT set: check. - | mov RA, TMP1 // Restore RA. - | jmp <2 - | - |5: // Follow hash chain. - | mov NODE:RA, NODE:RA->next - | test NODE:RA, NODE:RA - | jnz <1 - | // End of hash chain: key not found, add a new one. - | - | // But check for __newindex first. - | mov TAB:RA, TAB:RB->metatable - | test TAB:RA, TAB:RA - | jz >6 // No metatable: continue. - | test byte TAB:RA->nomm, 1<vmeta_tsets // 'no __newindex' flag NOT set: check. - |6: - | mov TMP1, STR:RC - | mov TMP2, LJ_TSTR - | mov TMP3, TAB:RB // Save TAB:RB for us. - |.if X64 - | mov L:CARG1d, SAVE_L - | mov L:CARG1d->base, BASE - | lea CARG3, TMP1 - | mov CARG2d, TAB:RB - | mov L:RB, L:CARG1d - |.else - | lea RC, TMP1 // Store temp. TValue in TMP1/TMP2. - | mov ARG2, TAB:RB - | mov L:RB, SAVE_L - | mov ARG3, RC - | mov ARG1, L:RB - | mov L:RB->base, BASE - |.endif - | mov SAVE_PC, PC - | call extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k) - | // Handles write barrier for the new key. TValue * returned in eax (RC). - | mov BASE, L:RB->base - | mov TAB:RB, TMP3 // Need TAB:RB for barrier. - | mov RA, eax - | jmp <2 // Must check write barrier for value. - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, RC // Destroys STR:RC. - | jmp <3 - break; - case BC_TSETB: - | ins_ABC // RA = src, RB = table, RC = byte literal - | checktab RB, ->vmeta_tsetb - | mov TAB:RB, [BASE+RB*8] - | cmp RC, TAB:RB->asize - | jae ->vmeta_tsetb - | shl RC, 3 - | add RC, TAB:RB->array - | cmp dword [RC+4], LJ_TNIL - | je >3 // Previous value is nil? - |1: - | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) - | jnz >7 - |2: // Set array slot. - |.if X64 - | mov RAa, [BASE+RA*8] - | mov [RC], RAa - |.else - | mov RB, [BASE+RA*8+4] - | mov RA, [BASE+RA*8] - | mov [RC+4], RB - | mov [RC], RA - |.endif - | ins_next - | - |3: // Check for __newindex if previous value is nil. - | cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath. - | jz <1 - | mov TAB:RA, TAB:RB->metatable - | test byte TAB:RA->nomm, 1<vmeta_tsetb // 'no __newindex' flag NOT set: check. - | movzx RA, PC_RA // Restore RA. - | jmp <1 - | - |7: // Possible table write barrier for the value. Skip valiswhite check. - | barrierback TAB:RB, RA - | movzx RA, PC_RA // Restore RA. - | jmp <2 - break; - - case BC_TSETM: - | ins_AD // RA = base (table at base-1), RD = num const (start index) - | mov TMP1, KBASE // Need one more free register. - | mov KBASE, dword [KBASE+RD*8] // Integer constant is in lo-word. - |1: - | lea RA, [BASE+RA*8] - | mov TAB:RB, [RA-8] // Guaranteed to be a table. - | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) - | jnz >7 - |2: - | mov RD, MULTRES - | sub RD, 1 - | jz >4 // Nothing to copy? - | add RD, KBASE // Compute needed size. - | cmp RD, TAB:RB->asize - | ja >5 // Doesn't fit into array part? - | sub RD, KBASE - | shl KBASE, 3 - | add KBASE, TAB:RB->array - |3: // Copy result slots to table. - |.if X64 - | mov RBa, [RA] - | add RA, 8 - | mov [KBASE], RBa - |.else - | mov RB, [RA] - | mov [KBASE], RB - | mov RB, [RA+4] - | add RA, 8 - | mov [KBASE+4], RB - |.endif - | add KBASE, 8 - | sub RD, 1 - | jnz <3 - |4: - | mov KBASE, TMP1 - | ins_next - | - |5: // Need to resize array part. - |.if X64 - | mov L:CARG1d, SAVE_L - | mov L:CARG1d->base, BASE // Caveat: CARG2d/CARG3d may be BASE. - | mov CARG2d, TAB:RB - | mov CARG3d, RD - | mov L:RB, L:CARG1d - |.else - | mov ARG2, TAB:RB - | mov L:RB, SAVE_L - | mov L:RB->base, BASE - | mov ARG3, RD - | mov ARG1, L:RB - |.endif - | mov SAVE_PC, PC - | call extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize) - | mov BASE, L:RB->base - | movzx RA, PC_RA // Restore RA. - | jmp <1 // Retry. - | - |7: // Possible table write barrier for any value. Skip valiswhite check. - | barrierback TAB:RB, RD - | jmp <2 - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALL: case BC_CALLM: - | ins_A_C // RA = base, (RB = nresults+1,) RC = nargs+1 | extra_nargs - if (op == BC_CALLM) { - | add NARGS:RD, MULTRES - } - | cmp dword [BASE+RA*8+4], LJ_TFUNC - | mov LFUNC:RB, [BASE+RA*8] - | jne ->vmeta_call_ra - | lea BASE, [BASE+RA*8+8] - | ins_call - break; - - case BC_CALLMT: - | ins_AD // RA = base, RD = extra_nargs - | add NARGS:RD, MULTRES - | // Fall through. Assumes BC_CALLT follows and ins_AD is a no-op. - break; - case BC_CALLT: - | ins_AD // RA = base, RD = nargs+1 - | lea RA, [BASE+RA*8+8] - | mov KBASE, BASE // Use KBASE for move + vmeta_call hint. - | mov LFUNC:RB, [RA-8] - | cmp dword [RA-4], LJ_TFUNC - | jne ->vmeta_call - |->BC_CALLT_Z: - | mov PC, [BASE-4] - | test PC, FRAME_TYPE - | jnz >7 - |1: - | mov [BASE-8], LFUNC:RB // Copy function down, reloaded below. - | mov MULTRES, NARGS:RD - | sub NARGS:RD, 1 - | jz >3 - |2: // Move args down. - |.if X64 - | mov RBa, [RA] - | add RA, 8 - | mov [KBASE], RBa - |.else - | mov RB, [RA] - | mov [KBASE], RB - | mov RB, [RA+4] - | add RA, 8 - | mov [KBASE+4], RB - |.endif - | add KBASE, 8 - | sub NARGS:RD, 1 - | jnz <2 - | - | mov LFUNC:RB, [BASE-8] - |3: - | mov NARGS:RD, MULTRES - | cmp byte LFUNC:RB->ffid, 1 // (> FF_C) Calling a fast function? - | ja >5 - |4: - | ins_callt - | - |5: // Tailcall to a fast function. - | test PC, FRAME_TYPE // Lua frame below? - | jnz <4 - | movzx RA, PC_RA - | not RAa - | lea RA, [BASE+RA*8] - | mov LFUNC:KBASE, [RA-8] // Need to prepare KBASE. - | mov KBASE, LFUNC:KBASE->pc - | mov KBASE, [KBASE+PC2PROTO(k)] - | jmp <4 - | - |7: // Tailcall from a vararg function. - | sub PC, FRAME_VARG - | test PC, FRAME_TYPEP - | jnz >8 // Vararg frame below? - | sub BASE, PC // Need to relocate BASE/KBASE down. - | mov KBASE, BASE - | mov PC, [BASE-4] - | jmp <1 - |8: - | add PC, FRAME_VARG - | jmp <1 - break; - - case BC_ITERC: - | ins_A // RA = base, (RB = nresults+1,) RC = nargs+1 (2+1) - | lea RA, [BASE+RA*8+8] // fb = base+1 - |.if X64 - | mov RBa, [RA-24] // Copy state. fb[0] = fb[-3]. - | mov RCa, [RA-16] // Copy control var. fb[1] = fb[-2]. - | mov [RA], RBa - | mov [RA+8], RCa - |.else - | mov RB, [RA-24] // Copy state. fb[0] = fb[-3]. - | mov RC, [RA-20] - | mov [RA], RB - | mov [RA+4], RC - | mov RB, [RA-16] // Copy control var. fb[1] = fb[-2]. - | mov RC, [RA-12] - | mov [RA+8], RB - | mov [RA+12], RC - |.endif - | mov LFUNC:RB, [RA-32] // Copy callable. fb[-1] = fb[-4] - | mov RC, [RA-28] - | mov [RA-8], LFUNC:RB - | mov [RA-4], RC - | cmp RC, LJ_TFUNC // Handle like a regular 2-arg call. - | mov NARGS:RD, 2+1 - | jne ->vmeta_call - | mov BASE, RA - | ins_call - break; - - case BC_ITERN: - | ins_A // RA = base, (RB = nresults+1, RC = nargs+1 (2+1)) -#if LJ_HASJIT - | // NYI: add hotloop, record BC_ITERN. -#endif - | mov TMP1, KBASE // Need two more free registers. - | mov TMP2, DISPATCH - | mov TAB:RB, [BASE+RA*8-16] - | mov RC, [BASE+RA*8-8] // Get index from control var. - | mov DISPATCH, TAB:RB->asize - | add PC, 4 - | mov KBASE, TAB:RB->array - |1: // Traverse array part. - | cmp RC, DISPATCH; jae >5 // Index points after array part? - | cmp dword [KBASE+RC*8+4], LJ_TNIL; je >4 - if (LJ_DUALNUM) { - | mov dword [BASE+RA*8+4], LJ_TISNUM - | mov dword [BASE+RA*8], RC - } else if (sse) { - | cvtsi2sd xmm0, RC - } else { - | fild dword [BASE+RA*8-8] - } - | // Copy array slot to returned value. - |.if X64 - | mov RBa, [KBASE+RC*8] - | mov [BASE+RA*8+8], RBa - |.else - | mov RB, [KBASE+RC*8+4] - | mov [BASE+RA*8+12], RB - | mov RB, [KBASE+RC*8] - | mov [BASE+RA*8+8], RB - |.endif - | add RC, 1 - | // Return array index as a numeric key. - if (LJ_DUALNUM) { - | // See above. - } else if (sse) { - | movsd qword [BASE+RA*8], xmm0 - } else { - | fstp qword [BASE+RA*8] - } - | mov [BASE+RA*8-8], RC // Update control var. - |2: - | movzx RD, PC_RD // Get target from ITERL. - | branchPC RD - |3: - | mov DISPATCH, TMP2 - | mov KBASE, TMP1 - | ins_next - | - |4: // Skip holes in array part. - | add RC, 1 - if (!LJ_DUALNUM && !sse) { - | mov [BASE+RA*8-8], RC - } - | jmp <1 - | - |5: // Traverse hash part. - | sub RC, DISPATCH - |6: - | cmp RC, TAB:RB->hmask; ja <3 // End of iteration? Branch to ITERL+1. - | imul KBASE, RC, #NODE - | add NODE:KBASE, TAB:RB->node - | cmp dword NODE:KBASE->val.it, LJ_TNIL; je >7 - | lea DISPATCH, [RC+DISPATCH+1] - | // Copy key and value from hash slot. - |.if X64 - | mov RBa, NODE:KBASE->key - | mov RCa, NODE:KBASE->val - | mov [BASE+RA*8], RBa - | mov [BASE+RA*8+8], RCa - |.else - | mov RB, NODE:KBASE->key.gcr - | mov RC, NODE:KBASE->key.it - | mov [BASE+RA*8], RB - | mov [BASE+RA*8+4], RC - | mov RB, NODE:KBASE->val.gcr - | mov RC, NODE:KBASE->val.it - | mov [BASE+RA*8+8], RB - | mov [BASE+RA*8+12], RC - |.endif - | mov [BASE+RA*8-8], DISPATCH - | jmp <2 - | - |7: // Skip holes in hash part. - | add RC, 1 - | jmp <6 - break; - - case BC_ISNEXT: - | ins_AD // RA = base, RD = target (points to ITERN) - | cmp dword [BASE+RA*8-20], LJ_TFUNC; jne >5 - | mov CFUNC:RB, [BASE+RA*8-24] - | cmp dword [BASE+RA*8-12], LJ_TTAB; jne >5 - | cmp dword [BASE+RA*8-4], LJ_TNIL; jne >5 - | cmp byte CFUNC:RB->ffid, FF_next_N; jne >5 - | branchPC RD - | mov dword [BASE+RA*8-8], 0 // Initialize control var. - |1: - | ins_next - |5: // Despecialize bytecode if any of the checks fail. - | mov PC_OP, BC_JMP - | branchPC RD - | mov byte [PC], BC_ITERC - | jmp <1 - break; - - case BC_VARG: - | ins_ABC // RA = base, RB = nresults+1, RC = numparams - | mov TMP1, KBASE // Need one more free register. - | lea KBASE, [BASE+RC*8+(8+FRAME_VARG)] - | lea RA, [BASE+RA*8] - | sub KBASE, [BASE-4] - | // Note: KBASE may now be even _above_ BASE if nargs was < numparams. - | test RB, RB - | jz >5 // Copy all varargs? - | lea RB, [RA+RB*8-8] - | cmp KBASE, BASE // No vararg slots? - | jnb >2 - |1: // Copy vararg slots to destination slots. - |.if X64 - | mov RCa, [KBASE-8] - | add KBASE, 8 - | mov [RA], RCa - |.else - | mov RC, [KBASE-8] - | mov [RA], RC - | mov RC, [KBASE-4] - | add KBASE, 8 - | mov [RA+4], RC - |.endif - | add RA, 8 - | cmp RA, RB // All destination slots filled? - | jnb >3 - | cmp KBASE, BASE // No more vararg slots? - | jb <1 - |2: // Fill up remainder with nil. - | mov dword [RA+4], LJ_TNIL - | add RA, 8 - | cmp RA, RB - | jb <2 - |3: - | mov KBASE, TMP1 - | ins_next - | - |5: // Copy all varargs. - | mov MULTRES, 1 // MULTRES = 0+1 - | mov RC, BASE - | sub RC, KBASE - | jbe <3 // No vararg slots? - | mov RB, RC - | shr RB, 3 - | add RB, 1 - | mov MULTRES, RB // MULTRES = #varargs+1 - | mov L:RB, SAVE_L - | add RC, RA - | cmp RC, L:RB->maxstack - | ja >7 // Need to grow stack? - |6: // Copy all vararg slots. - |.if X64 - | mov RCa, [KBASE-8] - | add KBASE, 8 - | mov [RA], RCa - |.else - | mov RC, [KBASE-8] - | mov [RA], RC - | mov RC, [KBASE-4] - | add KBASE, 8 - | mov [RA+4], RC - |.endif - | add RA, 8 - | cmp KBASE, BASE // No more vararg slots? - | jb <6 - | jmp <3 - | - |7: // Grow stack for varargs. - | mov L:RB->base, BASE - | mov L:RB->top, RA - | mov SAVE_PC, PC - | sub KBASE, BASE // Need delta, because BASE may change. - | mov FCARG2, MULTRES - | sub FCARG2, 1 - | mov FCARG1, L:RB - | call extern lj_state_growstack@8 // (lua_State *L, int n) - | mov BASE, L:RB->base - | mov RA, L:RB->top - | add KBASE, BASE - | jmp <6 - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - | ins_AD // RA = results, RD = extra_nresults - | add RD, MULTRES // MULTRES >=1, so RD >=1. - | // Fall through. Assumes BC_RET follows and ins_AD is a no-op. - break; - - case BC_RET: case BC_RET0: case BC_RET1: - | ins_AD // RA = results, RD = nresults+1 - if (op != BC_RET0) { - | shl RA, 3 - } - |1: - | mov PC, [BASE-4] - | mov MULTRES, RD // Save nresults+1. - | test PC, FRAME_TYPE // Check frame type marker. - | jnz >7 // Not returning to a fixarg Lua func? - switch (op) { - case BC_RET: - |->BC_RET_Z: - | mov KBASE, BASE // Use KBASE for result move. - | sub RD, 1 - | jz >3 - |2: // Move results down. - |.if X64 - | mov RBa, [KBASE+RA] - | mov [KBASE-8], RBa - |.else - | mov RB, [KBASE+RA] - | mov [KBASE-8], RB - | mov RB, [KBASE+RA+4] - | mov [KBASE-4], RB - |.endif - | add KBASE, 8 - | sub RD, 1 - | jnz <2 - |3: - | mov RD, MULTRES // Note: MULTRES may be >255. - | movzx RB, PC_RB // So cannot compare with RDL! - |5: - | cmp RB, RD // More results expected? - | ja >6 - break; - case BC_RET1: - |.if X64 - | mov RBa, [BASE+RA] - | mov [BASE-8], RBa - |.else - | mov RB, [BASE+RA+4] - | mov [BASE-4], RB - | mov RB, [BASE+RA] - | mov [BASE-8], RB - |.endif - /* fallthrough */ - case BC_RET0: - |5: - | cmp PC_RB, RDL // More results expected? - | ja >6 - default: - break; - } - | movzx RA, PC_RA - | not RAa // Note: ~RA = -(RA+1) - | lea BASE, [BASE+RA*8] // base = base - (RA+1)*8 - | mov LFUNC:KBASE, [BASE-8] - | mov KBASE, LFUNC:KBASE->pc - | mov KBASE, [KBASE+PC2PROTO(k)] - | ins_next - | - |6: // Fill up results with nil. - if (op == BC_RET) { - | mov dword [KBASE-4], LJ_TNIL // Note: relies on shifted base. - | add KBASE, 8 - } else { - | mov dword [BASE+RD*8-12], LJ_TNIL - } - | add RD, 1 - | jmp <5 - | - |7: // Non-standard return case. - | lea RB, [PC-FRAME_VARG] - | test RB, FRAME_TYPEP - | jnz ->vm_return - | // Return from vararg function: relocate BASE down and RA up. - | sub BASE, RB - if (op != BC_RET0) { - | add RA, RB - } - | jmp <1 - break; - - /* -- Loops and branches ------------------------------------------------ */ - - |.define FOR_IDX, [RA]; .define FOR_TIDX, dword [RA+4] - |.define FOR_STOP, [RA+8]; .define FOR_TSTOP, dword [RA+12] - |.define FOR_STEP, [RA+16]; .define FOR_TSTEP, dword [RA+20] - |.define FOR_EXT, [RA+24]; .define FOR_TEXT, dword [RA+28] - - case BC_FORL: -#if LJ_HASJIT - | hotloop RB -#endif - | // Fall through. Assumes BC_IFORL follows and ins_AJ is a no-op. - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - vk = (op == BC_IFORL || op == BC_JFORL); - | ins_AJ // RA = base, RD = target (after end of loop or start of loop) - | lea RA, [BASE+RA*8] - if (LJ_DUALNUM) { - | cmp FOR_TIDX, LJ_TISNUM; jne >9 - if (!vk) { - | cmp FOR_TSTOP, LJ_TISNUM; jne ->vmeta_for - | cmp FOR_TSTEP, LJ_TISNUM; jne ->vmeta_for - | mov RB, dword FOR_IDX - | cmp dword FOR_STEP, 0; jl >5 - } else { -#ifdef LUA_USE_ASSERT - | cmp FOR_TSTOP, LJ_TISNUM; jne ->assert_bad_for_arg_type - | cmp FOR_TSTEP, LJ_TISNUM; jne ->assert_bad_for_arg_type -#endif - | mov RB, dword FOR_STEP - | test RB, RB; js >5 - | add RB, dword FOR_IDX; jo >1 - | mov dword FOR_IDX, RB - } - | cmp RB, dword FOR_STOP - | mov FOR_TEXT, LJ_TISNUM - | mov dword FOR_EXT, RB - if (op == BC_FORI) { - | jle >7 - |1: - |6: - | branchPC RD - } else if (op == BC_JFORI) { - | branchPC RD - | movzx RD, PC_RD - | jle =>BC_JLOOP - |1: - |6: - } else if (op == BC_IFORL) { - | jg >7 - |6: - | branchPC RD - |1: - } else { - | jle =>BC_JLOOP - |1: - |6: - } - |7: - | ins_next - | - |5: // Invert check for negative step. - if (vk) { - | add RB, dword FOR_IDX; jo <1 - | mov dword FOR_IDX, RB - } - | cmp RB, dword FOR_STOP - | mov FOR_TEXT, LJ_TISNUM - | mov dword FOR_EXT, RB - if (op == BC_FORI) { - | jge <7 - } else if (op == BC_JFORI) { - | branchPC RD - | movzx RD, PC_RD - | jge =>BC_JLOOP - } else if (op == BC_IFORL) { - | jl <7 - } else { - | jge =>BC_JLOOP - } - | jmp <6 - |9: // Fallback to FP variant. - } else if (!vk) { - | cmp FOR_TIDX, LJ_TISNUM - } - if (!vk) { - | jae ->vmeta_for - | cmp FOR_TSTOP, LJ_TISNUM; jae ->vmeta_for - } else { -#ifdef LUA_USE_ASSERT - | cmp FOR_TSTOP, LJ_TISNUM; jae ->assert_bad_for_arg_type - | cmp FOR_TSTEP, LJ_TISNUM; jae ->assert_bad_for_arg_type -#endif - } - | mov RB, FOR_TSTEP // Load type/hiword of for step. - if (!vk) { - | cmp RB, LJ_TISNUM; jae ->vmeta_for - } - if (sse) { - | movsd xmm0, qword FOR_IDX - | movsd xmm1, qword FOR_STOP - if (vk) { - | addsd xmm0, qword FOR_STEP - | movsd qword FOR_IDX, xmm0 - | test RB, RB; js >3 - } else { - | jl >3 - } - | ucomisd xmm1, xmm0 - |1: - | movsd qword FOR_EXT, xmm0 - } else { - | fld qword FOR_STOP - | fld qword FOR_IDX - if (vk) { - | fadd qword FOR_STEP // nidx = idx + step - | fst qword FOR_IDX - | fst qword FOR_EXT - | test RB, RB; js >1 - } else { - | fst qword FOR_EXT - | jl >1 - } - | fxch // Swap lim/(n)idx if step non-negative. - |1: - | fcomparepp // eax (RD) modified if !cmov. - if (!cmov) { - | movzx RD, PC_RD // Need to reload RD. - } - } - if (op == BC_FORI) { - if (LJ_DUALNUM) { - | jnb <7 - } else { - | jnb >2 - | branchPC RD - } - } else if (op == BC_JFORI) { - | branchPC RD - | movzx RD, PC_RD - | jnb =>BC_JLOOP - } else if (op == BC_IFORL) { - if (LJ_DUALNUM) { - | jb <7 - } else { - | jb >2 - | branchPC RD - } - } else { - | jnb =>BC_JLOOP - } - if (LJ_DUALNUM) { - | jmp <6 - } else { - |2: - | ins_next - } - if (sse) { - |3: // Invert comparison if step is negative. - | ucomisd xmm0, xmm1 - | jmp <1 - } - break; - - case BC_ITERL: -#if LJ_HASJIT - | hotloop RB -#endif - | // Fall through. Assumes BC_IITERL follows and ins_AJ is a no-op. - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - | ins_AJ // RA = base, RD = target - | lea RA, [BASE+RA*8] - | mov RB, [RA+4] - | cmp RB, LJ_TNIL; je >1 // Stop if iterator returned nil. - if (op == BC_JITERL) { - | mov [RA-4], RB - | mov RB, [RA] - | mov [RA-8], RB - | jmp =>BC_JLOOP - } else { - | branchPC RD // Otherwise save control var + branch. - | mov RD, [RA] - | mov [RA-4], RB - | mov [RA-8], RD - } - |1: - | ins_next - break; - - case BC_LOOP: - | ins_A // RA = base, RD = target (loop extent) - | // Note: RA/RD is only used by trace recorder to determine scope/extent - | // This opcode does NOT jump, it's only purpose is to detect a hot loop. -#if LJ_HASJIT - | hotloop RB -#endif - | // Fall through. Assumes BC_ILOOP follows and ins_A is a no-op. - break; - - case BC_ILOOP: - | ins_A // RA = base, RD = target (loop extent) - | ins_next - break; - - case BC_JLOOP: -#if LJ_HASJIT - | ins_AD // RA = base (ignored), RD = traceno - | mov RA, [DISPATCH+DISPATCH_J(trace)] - | mov TRACE:RD, [RA+RD*4] - | mov RDa, TRACE:RD->mcode - | mov L:RB, SAVE_L - | mov [DISPATCH+DISPATCH_GL(jit_base)], BASE - | mov [DISPATCH+DISPATCH_GL(jit_L)], L:RB - | // Save additional callee-save registers only used in compiled code. - |.if X64WIN - | mov TMPQ, r12 - | mov TMPa, r13 - | mov CSAVE_4, r14 - | mov CSAVE_3, r15 - | mov RAa, rsp - | sub rsp, 9*16+4*8 - | movdqa [RAa], xmm6 - | movdqa [RAa-1*16], xmm7 - | movdqa [RAa-2*16], xmm8 - | movdqa [RAa-3*16], xmm9 - | movdqa [RAa-4*16], xmm10 - | movdqa [RAa-5*16], xmm11 - | movdqa [RAa-6*16], xmm12 - | movdqa [RAa-7*16], xmm13 - | movdqa [RAa-8*16], xmm14 - | movdqa [RAa-9*16], xmm15 - |.elif X64 - | mov TMPQ, r12 - | mov TMPa, r13 - | sub rsp, 16 - |.endif - | jmp RDa -#endif - break; - - case BC_JMP: - | ins_AJ // RA = unused, RD = target - | branchPC RD - | ins_next - break; - - /* -- Function headers -------------------------------------------------- */ - - /* - ** Reminder: A function may be called with func/args above L->maxstack, - ** i.e. occupying EXTRA_STACK slots. And vmeta_call may add one extra slot, - ** too. This means all FUNC* ops (including fast functions) must check - ** for stack overflow _before_ adding more slots! - */ - - case BC_FUNCF: -#if LJ_HASJIT - | hotcall RB -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow and ins_AD is a no-op. - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - | ins_AD // BASE = new base, RA = framesize, RD = nargs+1 - | mov KBASE, [PC-4+PC2PROTO(k)] - | mov L:RB, SAVE_L - | lea RA, [BASE+RA*8] // Top of frame. - | cmp RA, L:RB->maxstack - | ja ->vm_growstack_f - | movzx RA, byte [PC-4+PC2PROTO(numparams)] - | cmp NARGS:RD, RA // Check for missing parameters. - | jbe >3 - |2: - if (op == BC_JFUNCF) { - | movzx RD, PC_RD - | jmp =>BC_JLOOP - } else { - | ins_next - } - | - |3: // Clear missing parameters. - | mov dword [BASE+NARGS:RD*8-4], LJ_TNIL - | add NARGS:RD, 1 - | cmp NARGS:RD, RA - | jbe <3 - | jmp <2 - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - | int3 // NYI: compiled vararg functions - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - | ins_AD // BASE = new base, RA = framesize, RD = nargs+1 - | lea RB, [NARGS:RD*8+FRAME_VARG] - | lea RD, [BASE+NARGS:RD*8] - | mov LFUNC:KBASE, [BASE-8] - | mov [RD-4], RB // Store delta + FRAME_VARG. - | mov [RD-8], LFUNC:KBASE // Store copy of LFUNC. - | mov L:RB, SAVE_L - | lea RA, [RD+RA*8] - | cmp RA, L:RB->maxstack - | ja ->vm_growstack_v // Need to grow stack. - | mov RA, BASE - | mov BASE, RD - | movzx RB, byte [PC-4+PC2PROTO(numparams)] - | test RB, RB - | jz >2 - |1: // Copy fixarg slots up to new frame. - | add RA, 8 - | cmp RA, BASE - | jnb >3 // Less args than parameters? - | mov KBASE, [RA-8] - | mov [RD], KBASE - | mov KBASE, [RA-4] - | mov [RD+4], KBASE - | add RD, 8 - | mov dword [RA-4], LJ_TNIL // Clear old fixarg slot (help the GC). - | sub RB, 1 - | jnz <1 - |2: - if (op == BC_JFUNCV) { - | movzx RD, PC_RD - | jmp =>BC_JLOOP - } else { - | mov KBASE, [PC-4+PC2PROTO(k)] - | ins_next - } - | - |3: // Clear missing parameters. - | mov dword [RD+4], LJ_TNIL - | add RD, 8 - | sub RB, 1 - | jnz <3 - | jmp <2 - break; - - case BC_FUNCC: - case BC_FUNCCW: - | ins_AD // BASE = new base, RA = ins RA|RD (unused), RD = nargs+1 - | mov CFUNC:RB, [BASE-8] - | mov KBASEa, CFUNC:RB->f - | mov L:RB, SAVE_L - | lea RD, [BASE+NARGS:RD*8-8] - | mov L:RB->base, BASE - | lea RA, [RD+8*LUA_MINSTACK] - | cmp RA, L:RB->maxstack - | mov L:RB->top, RD - if (op == BC_FUNCC) { - |.if X64 - | mov CARG1d, L:RB // Caveat: CARG1d may be RA. - |.else - | mov ARG1, L:RB - |.endif - } else { - |.if X64 - | mov CARG2, KBASEa - | mov CARG1d, L:RB // Caveat: CARG1d may be RA. - |.else - | mov ARG2, KBASEa - | mov ARG1, L:RB - |.endif - } - | ja ->vm_growstack_c // Need to grow stack. - | set_vmstate C - if (op == BC_FUNCC) { - | call KBASEa // (lua_State *L) - } else { - | // (lua_State *L, lua_CFunction f) - | call aword [DISPATCH+DISPATCH_GL(wrapf)] - } - | set_vmstate INTERP - | // nresults returned in eax (RD). - | mov BASE, L:RB->base - | lea RA, [BASE+RD*8] - | neg RA - | add RA, L:RB->top // RA = (L->top-(L->base+nresults))*8 - | mov PC, [BASE-4] // Fetch PC of caller. - | jmp ->vm_returnc - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - int cmov = 1; - int sse = 0; -#ifdef LUAJIT_CPU_NOCMOV - cmov = 0; -#endif -#if defined(LUAJIT_CPU_SSE2) || defined(LJ_TARGET_X64) - sse = 1; -#endif - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx, cmov, sse); - - |.code_op - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op, cmov, sse); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); -#if LJ_64 -#define SZPTR "8" -#define BSZPTR "3" -#define REG_SP "0x7" -#define REG_RA "0x10" -#else -#define SZPTR "4" -#define BSZPTR "2" -#define REG_SP "0x4" -#define REG_RA "0x8" -#endif - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.long .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.long 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.long .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.long .Lframe0\n" -#if LJ_64 - "\t.quad .Lbegin\n" - "\t.quad %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.long .Lbegin\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE0:\n\n", fcofs, CFRAME_SIZE); -#if LJ_HASFFI - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.long .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.long .Lframe0\n" -#if LJ_64 - "\t.quad lj_vm_ffi_call\n" - "\t.quad %d\n" - "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ -#else - "\t.long lj_vm_ffi_call\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); -#endif -#if (defined(__sun__) && defined(__svr4__)) || defined(__solaris_) - fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n"); -#else - fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); -#endif - fprintf(ctx->fp, - ".Lframe1:\n" - "\t.long .LECIE1-.LSCIE1\n" - ".LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zPR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 6\n" /* augmentation length */ - "\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 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE1:\n\n"); - fprintf(ctx->fp, - ".LSFDE2:\n" - "\t.long .LEFDE2-.LASFDE2\n" - ".LASFDE2:\n" - "\t.long .LASFDE2-.Lframe1\n" - "\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 */ -#if LJ_64 - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE2:\n\n", fcofs, CFRAME_SIZE); -#if LJ_HASFFI - fprintf(ctx->fp, - ".Lframe2:\n" - "\t.long .LECIE2-.LSCIE2\n" - ".LSCIE2:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 1\n" /* augmentation length */ - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE2:\n\n"); - fprintf(ctx->fp, - ".LSFDE3:\n" - "\t.long .LEFDE3-.LASFDE3\n" - ".LASFDE3:\n" - "\t.long .LASFDE3-.Lframe2\n" - "\t.long lj_vm_ffi_call-.\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ -#else - "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); -#endif - break; - case BUILD_coffasm: - fprintf(ctx->fp, "\t.section .eh_frame,\"dr\"\n"); - fprintf(ctx->fp, - "\t.def %slj_err_unwind_dwarf; .scl 2; .type 32; .endef\n", - LJ_32 ? "_" : ""); - fprintf(ctx->fp, - "Lframe1:\n" - "\t.long LECIE1-LSCIE1\n" - "LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zP\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 5\n" /* augmentation length */ - "\t.byte 0x00\n" /* absptr */ - "\t.long %slj_err_unwind_dwarf\n" - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - "LECIE1:\n\n", LJ_32 ? "_" : ""); - fprintf(ctx->fp, - "LSFDE1:\n" - "\t.long LEFDE1-LASFDE1\n" - "LASFDE1:\n" - "\t.long LASFDE1-Lframe1\n" - "\t.long %slj_vm_asm_begin\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ -#if LJ_64 - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - "LEFDE1:\n\n", LJ_32 ? "_" : "", (int)ctx->codesz, CFRAME_SIZE); - break; - /* Mental note: never let Apple design an assembler. - ** Or a linker. Or a plastic case. But I digress. - */ - case BUILD_machasm: { -#if LJ_HASFFI - int fcsize = 0; -#endif - int i; - 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.byte 0x1\n" - "\t.byte 128-" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 6\n" /* augmentation length */ - "\t.byte 0x9b\n" /* indirect|pcrel|sdata4 */ -#if LJ_64 - "\t.long _lj_err_unwind_dwarf+4@GOTPCREL\n" - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n" -#else - "\t.long L_lj_err_unwind_dwarf$non_lazy_ptr-.\n" - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH-O. */ -#endif - "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n" - "\t.align " BSZPTR "\n" - "LECIEX:\n\n"); - for (i = 0; i < ctx->nsym; i++) { - const char *name = ctx->sym[i].name; - int32_t size = ctx->sym[i+1].ofs - ctx->sym[i].ofs; - if (size == 0) continue; -#if LJ_HASFFI - if (!strcmp(name, "_lj_vm_ffi_call")) { fcsize = size; continue; } -#endif - fprintf(ctx->fp, - "%s.eh:\n" - "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.byte 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.byte %d\n" /* def_cfa_offset */ -#if LJ_64 - "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.byte 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.byte 0x5\n" /* offset r14 */ -#else - "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/ - "\t.byte 0x87\n\t.byte 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.byte 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.byte 0x5\n" /* offset ebx */ -#endif - "\t.align " BSZPTR "\n" - "LEFDE%d:\n\n", - name, i, i, i, i, i, i, i, name, size, CFRAME_SIZE, i); - } -#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.byte 0x1\n" - "\t.byte 128-" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 1\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n" -#else - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH. */ -#endif - "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n" - "\t.align " BSZPTR "\n" - "LECIEY:\n\n"); - fprintf(ctx->fp, - "_lj_vm_ffi_call.eh:\n" - "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.byte 0\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0xe\n\t.byte 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */ -#else - "\t.byte 0xe\n\t.byte 8\n" /* def_cfa_offset */ - "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/ - "\t.byte 0xd\n\t.uleb128 0x4\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset ebx */ -#endif - "\t.align " BSZPTR "\n" - "LEFDEY:\n\n", fcsize); - } -#endif -#if LJ_64 - fprintf(ctx->fp, "\t.subsections_via_symbols\n"); -#else - fprintf(ctx->fp, - "\t.non_lazy_symbol_pointer\n" - "L_lj_err_unwind_dwarf$non_lazy_ptr:\n" - ".indirect_symbol _lj_err_unwind_dwarf\n" - ".long 0\n"); -#endif - } - break; - default: /* Difficult for other modes. */ - break; - } -} - diff --git a/src/buildvm_x86.h b/src/buildvm_x86.h deleted file mode 100644 index cd33cf87..00000000 --- a/src/buildvm_x86.h +++ /dev/null @@ -1,3561 +0,0 @@ -/* -** This file has been pre-processed with DynASM. -** http://luajit.org/dynasm.html -** DynASM version 1.3.0, DynASM x86 version 1.3.0 -** DO NOT EDIT! The original file is in "buildvm_x86.dasc". -*/ - -#if DASM_VERSION != 10300 -#error "Version mismatch between DynASM and included encoding engine" -#endif - -#define DASM_SECTION_CODE_OP 0 -#define DASM_SECTION_CODE_SUB 1 -#define DASM_MAXSECTION 2 -static const unsigned char build_actionlist[17321] = { - 254,1,248,10,252,247,198,237,15,132,244,11,131,230,252,248,41,252,242,141, - 76,49,252,248,139,114,252,252,199,68,10,4,237,248,12,131,192,1,137,68,36, - 20,252,247,198,237,15,132,244,13,248,14,129,252,246,239,252,247,198,237,15, - 133,244,10,199,131,233,237,131,230,252,248,41,214,252,247,222,131,232,1,15, - 132,244,248,248,1,139,44,10,137,106,252,248,139,108,10,4,137,106,252,252, - 131,194,8,131,232,1,15,133,244,1,248,2,255,139,108,36,48,137,181,233,248, - 3,139,68,36,20,139,76,36,56,248,4,57,193,15,133,244,252,248,5,131,252,234, - 8,137,149,233,248,15,139,76,36,52,137,141,233,49,192,248,16,131,196,28,91, - 94,95,93,195,248,6,15,130,244,253,59,149,233,15,135,244,254,199,66,252,252, - 237,131,194,8,131,192,1,252,233,244,4,248,7,255,133,201,15,132,244,5,41,193, - 141,20,202,252,233,244,5,248,8,137,149,233,137,68,36,20,137,202,137,252,233, - 232,251,1,0,139,149,233,252,233,244,3,248,17,137,208,137,204,248,18,139,108, - 36,48,139,173,233,199,133,233,237,252,233,244,16,248,19,248,20,129,225,239, - 137,204,248,21,255,139,108,36,48,185,252,248,252,255,252,255,252,255,184, - 237,139,149,233,139,157,233,129,195,239,139,114,252,252,199,66,252,252,237, - 199,131,233,237,252,233,244,12,248,22,186,237,252,233,244,248,248,23,131, - 232,8,252,233,244,247,248,24,141,68,194,252,248,248,1,15,182,142,233,131, - 198,4,137,149,233,255,137,133,233,137,116,36,24,137,202,248,2,137,252,233, - 232,251,1,0,139,149,233,139,133,233,139,106,252,248,41,208,193,232,3,131, - 192,1,139,181,233,139,14,15,182,252,233,15,182,205,131,198,4,252,255,36,171, - 248,25,85,87,86,83,131,252,236,28,139,108,36,48,139,76,36,52,190,237,49,192, - 141,188,253,36,233,139,157,233,129,195,239,137,189,233,137,68,36,24,137,68, - 36,52,56,133,233,15,132,244,249,199,131,233,237,136,133,233,139,149,233,139, - 133,233,41,200,193,232,3,131,192,1,41,209,139,114,252,252,137,68,36,20,252, - 247,198,237,255,15,132,244,13,252,233,244,14,248,26,85,87,86,83,131,252,236, - 28,190,237,252,233,244,247,248,27,85,87,86,83,131,252,236,28,190,237,248, - 1,139,108,36,48,139,76,36,52,139,189,233,137,124,36,52,137,108,36,24,137, - 165,233,248,2,139,157,233,129,195,239,248,3,199,131,233,237,139,149,233,255, - 1,206,41,214,139,133,233,41,200,193,232,3,131,192,1,248,28,139,105,252,248, - 129,121,253,252,252,239,15,133,244,29,248,30,137,202,137,114,252,252,139, - 181,233,139,14,15,182,252,233,15,182,205,131,198,4,252,255,36,171,248,31, - 85,87,86,83,131,252,236,28,139,108,36,48,139,68,36,56,139,76,36,52,139,84, - 36,60,137,108,36,24,139,189,233,43,189,233,199,68,36,60,0,0,0,0,137,124,36, - 56,137,68,36,8,137,76,36,4,137,44,36,139,189,233,137,124,36,52,137,165,233, - 252,255,210,133,192,15,132,244,15,137,193,190,237,252,233,244,2,248,11,1, - 209,131,230,252,248,137,213,41,252,242,199,68,193,252,252,237,137,200,139, - 117,252,244,255,139,77,252,240,255,131,252,249,1,15,134,244,247,255,139,122, - 252,248,139,191,233,139,191,233,252,255,225,255,248,1,15,132,244,32,41,213, - 193,252,237,3,141,69,252,255,252,233,244,33,255,248,34,15,182,78,252,255, - 131,252,237,16,141,12,202,41,252,233,15,132,244,35,252,247,217,193,252,233, - 3,137,76,36,8,139,72,4,139,0,137,77,4,137,69,0,137,108,36,4,252,233,244,36, - 248,37,137,68,36,16,199,68,36,20,237,141,68,36,16,128,126,252,252,235,15, - 133,244,247,141,139,233,137,41,199,65,4,237,137,205,252,233,244,248,248,38, - 15,182,70,252,254,255,199,68,36,20,237,137,68,36,16,255,252,242,15,42,192, - 252,242,15,17,68,36,16,255,137,68,36,12,219,68,36,12,221,92,36,16,255,141, - 68,36,16,252,233,244,247,248,39,15,182,70,252,254,141,4,194,248,1,15,182, - 110,252,255,141,44,252,234,248,2,137,108,36,4,139,108,36,48,137,68,36,8,137, - 44,36,137,149,233,137,116,36,24,232,251,1,1,139,149,233,133,192,15,132,244, - 249,248,35,15,182,78,252,253,139,104,4,139,0,137,108,202,4,137,4,202,139, - 6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,248,3,139,141, - 233,137,113,252,244,141,177,233,41,214,139,105,252,248,184,237,252,233,244, - 30,248,40,137,68,36,16,199,68,36,20,237,141,68,36,16,128,126,252,252,235, - 15,133,244,247,255,141,139,233,137,41,199,65,4,237,137,205,252,233,244,248, - 248,41,15,182,70,252,254,255,141,68,36,16,252,233,244,247,248,42,15,182,70, - 252,254,141,4,194,248,1,15,182,110,252,255,141,44,252,234,248,2,137,108,36, - 4,139,108,36,48,137,68,36,8,137,44,36,137,149,233,137,116,36,24,232,251,1, - 2,139,149,233,133,192,15,132,244,249,15,182,78,252,253,139,108,202,4,139, - 12,202,137,104,4,137,8,248,43,139,6,15,182,204,15,182,232,131,198,4,193,232, - 16,252,255,36,171,248,3,139,141,233,137,113,252,244,15,182,70,252,253,139, - 108,194,4,139,4,194,137,105,20,137,65,16,141,177,233,41,214,139,105,252,248, - 184,237,252,233,244,30,248,44,15,182,110,252,252,141,4,194,141,12,202,137, - 108,36,12,139,108,36,48,137,68,36,8,137,76,36,4,137,44,36,137,149,233,137, - 116,36,24,232,251,1,3,248,3,139,149,233,255,131,252,248,1,15,135,244,45,248, - 4,141,118,4,15,130,244,252,248,5,15,183,70,252,254,141,180,253,134,233,248, - 6,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,248,46, - 131,198,4,129,120,253,4,239,15,130,244,5,252,233,244,6,248,47,129,120,253, - 4,239,252,233,244,4,248,48,131,252,238,4,137,108,36,12,139,108,36,48,137, - 68,36,8,137,76,36,4,137,44,36,137,149,233,255,137,116,36,24,232,251,1,4,252, - 233,244,3,248,49,255,131,252,238,4,139,108,36,48,137,149,233,137,252,233, - 139,86,252,252,137,116,36,24,232,251,1,5,252,233,244,3,255,248,50,255,15, - 182,110,252,255,255,248,51,141,4,199,252,233,244,247,248,52,255,248,53,141, - 4,199,141,44,252,234,149,252,233,244,248,248,54,141,4,194,137,197,252,233, - 244,248,248,55,255,248,56,141,4,194,248,1,141,44,252,234,248,2,141,12,202, - 137,108,36,8,139,108,36,48,137,68,36,12,15,182,70,252,252,137,76,36,4,137, - 68,36,16,137,44,36,137,149,233,137,116,36,24,232,251,1,6,139,149,233,133, - 192,15,132,244,43,248,45,137,193,41,208,137,113,252,244,141,176,233,184,237, - 252,233,244,28,248,57,139,108,36,48,137,149,233,141,20,194,137,252,233,137, - 116,36,24,232,251,1,7,139,149,233,255,133,192,15,133,244,45,15,183,70,252, - 254,139,12,194,252,233,244,58,255,252,233,244,45,255,248,59,141,76,202,8, - 248,29,137,76,36,20,137,68,36,16,131,252,233,8,141,4,193,139,108,36,48,137, - 76,36,4,137,68,36,8,137,44,36,137,149,233,137,116,36,24,232,251,1,8,139,149, - 233,139,76,36,20,139,68,36,16,139,105,252,248,131,192,1,57,215,15,132,244, - 60,137,202,137,114,252,252,139,181,233,139,14,15,182,252,233,15,182,205,131, - 198,4,252,255,36,171,248,61,139,108,36,48,137,149,233,137,202,137,252,233, - 137,116,36,24,232,251,1,9,139,149,233,139,70,252,252,15,182,204,15,182,232, - 193,232,16,252,255,164,253,171,233,248,62,129,252,248,239,15,130,244,63,139, - 106,4,129,252,253,239,15,131,244,63,139,114,252,252,137,68,36,20,137,106, - 252,252,139,42,137,106,252,248,131,232,2,15,132,244,248,255,137,209,248,1, - 131,193,8,139,105,4,137,105,252,252,139,41,137,105,252,248,131,232,1,15,133, - 244,1,248,2,139,68,36,20,252,233,244,64,248,65,129,252,248,239,15,130,244, - 63,139,106,4,184,237,252,247,213,57,232,255,15,71,197,255,15,134,244,247, - 137,232,248,1,255,248,2,139,106,252,248,139,132,253,197,233,139,114,252,252, - 199,66,252,252,237,137,66,252,248,252,233,244,66,248,67,129,252,248,239,15, - 130,244,63,139,106,4,139,114,252,252,129,252,253,239,15,133,244,252,248,1, - 139,42,139,173,233,248,2,133,252,237,199,66,252,252,237,15,132,244,66,139, - 131,233,199,66,252,252,237,255,137,106,252,248,139,141,233,35,136,233,105, - 201,239,3,141,233,248,3,129,185,233,239,15,133,244,250,57,129,233,15,132, - 244,251,248,4,139,137,233,133,201,15,133,244,3,252,233,244,66,248,5,139,105, - 4,129,252,253,239,255,15,132,244,66,139,1,137,106,252,252,137,66,252,248, - 252,233,244,66,248,6,129,252,253,239,15,132,244,1,129,252,253,239,15,135, - 244,254,189,237,248,8,252,247,213,139,172,253,171,233,252,233,244,2,248,68, - 129,252,248,239,15,130,244,63,255,129,122,253,4,239,15,133,244,63,139,42, - 131,189,233,0,15,133,244,63,129,122,253,12,239,15,133,244,63,139,66,8,137, - 133,233,139,114,252,252,199,66,252,252,237,137,106,252,248,252,246,133,233, - 235,15,132,244,247,128,165,233,235,139,131,233,137,171,233,137,133,233,248, - 1,255,252,233,244,66,248,69,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,133,244,63,139,2,139,108,36,48,137,68,36,4,137,44,36,137,213,131,194,8, - 137,84,36,8,232,251,1,10,137,252,234,139,40,139,64,4,139,114,252,252,137, - 106,252,248,137,66,252,252,252,233,244,66,248,70,129,252,248,239,15,133,244, - 63,129,122,253,4,239,255,15,133,244,247,139,42,252,233,244,71,248,1,15,135, - 244,63,255,15,131,244,63,255,252,242,15,16,2,252,233,244,72,255,221,2,252, - 233,244,73,255,248,74,129,252,248,239,15,130,244,63,139,114,252,252,129,122, - 253,4,239,15,133,244,249,139,2,248,2,199,66,252,252,237,137,66,252,248,252, - 233,244,66,248,3,129,122,253,4,239,15,135,244,63,131,187,233,0,15,133,244, - 63,139,171,233,59,171,233,255,15,130,244,247,232,244,75,248,1,139,108,36, - 48,137,149,233,137,116,36,24,137,252,233,255,232,251,1,11,255,232,251,1,12, - 255,139,149,233,252,233,244,2,248,76,129,252,248,239,15,130,244,63,15,132, - 244,248,248,1,129,122,253,4,239,15,133,244,63,139,108,36,48,137,149,233,137, - 149,233,139,114,252,252,139,2,137,68,36,4,137,44,36,131,194,8,137,84,36,8, - 137,116,36,24,232,251,1,13,139,149,233,133,192,15,132,244,249,139,106,8,139, - 66,12,137,106,252,248,137,66,252,252,139,106,16,139,66,20,137,42,137,66,4, - 248,77,184,237,255,252,233,244,78,248,2,199,66,12,237,252,233,244,1,248,3, - 199,66,252,252,237,252,233,244,66,248,79,129,252,248,239,15,130,244,63,139, - 42,129,122,253,4,239,15,133,244,63,255,131,189,233,0,15,133,244,63,255,139, - 106,252,248,139,133,233,139,114,252,252,199,66,252,252,237,137,66,252,248, - 199,66,12,237,184,237,252,233,244,78,248,80,129,252,248,239,15,130,244,63, - 129,122,253,4,239,15,133,244,63,129,122,253,12,239,255,139,114,252,252,255, - 139,66,8,131,192,1,199,66,252,252,237,137,66,252,248,255,252,242,15,16,66, - 8,189,0,0,252,240,63,102,15,110,205,102,15,112,201,81,252,242,15,88,193,252, - 242,15,45,192,252,242,15,17,66,252,248,255,221,66,8,217,232,222,193,219,20, - 36,221,90,252,248,139,4,36,255,139,42,59,133,233,15,131,244,248,193,224,3, - 3,133,233,248,1,129,120,253,4,239,15,132,244,81,139,40,139,64,4,137,42,137, - 66,4,252,233,244,77,248,2,131,189,233,0,15,132,244,81,137,252,233,137,213, - 137,194,232,251,1,14,137,252,234,133,192,15,133,244,1,248,81,184,237,252, - 233,244,78,248,82,255,139,106,252,248,139,133,233,139,114,252,252,199,66, - 252,252,237,137,66,252,248,255,199,66,12,237,199,66,8,0,0,0,0,255,15,87,192, - 252,242,15,17,66,8,255,217,252,238,221,90,8,255,184,237,252,233,244,78,248, - 83,129,252,248,239,15,130,244,63,141,74,8,131,232,1,190,237,248,1,15,182, - 171,233,193,252,237,235,131,229,1,1,252,238,252,233,244,28,248,84,129,252, - 248,239,15,130,244,63,129,122,253,12,239,15,133,244,63,255,139,106,4,137, - 106,12,199,66,4,237,139,42,139,114,8,137,106,8,137,50,141,74,16,131,232,2, - 190,237,252,233,244,1,248,85,129,252,248,239,15,130,244,63,139,42,139,114, - 252,252,137,116,36,24,137,44,36,129,122,253,4,239,15,133,244,63,131,189,233, - 0,15,133,244,63,128,189,233,235,15,135,244,63,139,141,233,15,132,244,247, - 255,59,141,233,15,132,244,63,248,1,141,116,193,252,240,59,181,233,15,135, - 244,63,137,181,233,139,108,36,48,137,149,233,131,194,8,137,149,233,141,108, - 194,232,41,252,245,57,206,15,132,244,249,248,2,139,68,46,4,137,70,252,252, - 139,4,46,137,70,252,248,131,252,238,8,57,206,15,133,244,2,248,3,137,76,36, - 4,49,201,137,76,36,12,137,76,36,8,232,244,25,199,131,233,237,255,139,108, - 36,48,139,52,36,139,149,233,129,252,248,239,15,135,244,254,248,4,139,142, - 233,139,190,233,137,142,233,137,252,254,41,206,15,132,244,252,141,4,50,193, - 252,238,3,59,133,233,15,135,244,255,137,213,41,205,248,5,139,1,137,4,41,139, - 65,4,137,68,41,4,131,193,8,57,252,249,15,133,244,5,248,6,141,70,2,199,66, - 252,252,237,248,7,139,116,36,24,137,68,36,20,185,252,248,252,255,252,255, - 252,255,252,247,198,237,255,15,132,244,13,252,233,244,14,248,8,199,66,252, - 252,237,139,142,233,131,252,233,8,137,142,233,139,1,137,2,139,65,4,137,66, - 4,184,237,252,233,244,7,248,9,139,12,36,137,185,233,137,252,242,137,252,233, - 232,251,1,0,139,52,36,139,149,233,252,233,244,4,248,86,139,106,252,248,139, - 173,233,139,114,252,252,137,116,36,24,137,44,36,131,189,233,0,15,133,244, - 63,255,128,189,233,235,15,135,244,63,139,141,233,15,132,244,247,59,141,233, - 15,132,244,63,248,1,141,116,193,252,248,59,181,233,15,135,244,63,137,181, - 233,139,108,36,48,137,149,233,137,149,233,141,108,194,252,240,41,252,245, - 57,206,15,132,244,249,248,2,255,139,68,46,4,137,70,252,252,139,4,46,137,70, - 252,248,131,252,238,8,57,206,15,133,244,2,248,3,137,76,36,4,49,201,137,76, - 36,12,137,76,36,8,232,244,25,199,131,233,237,139,108,36,48,139,52,36,139, - 149,233,129,252,248,239,15,135,244,254,248,4,139,142,233,139,190,233,137, - 142,233,137,252,254,41,206,15,132,244,252,141,4,50,193,252,238,3,59,133,233, - 15,135,244,255,255,137,213,41,205,248,5,139,1,137,4,41,139,65,4,137,68,41, - 4,131,193,8,57,252,249,15,133,244,5,248,6,141,70,1,248,7,139,116,36,24,137, - 68,36,20,49,201,252,247,198,237,15,132,244,13,252,233,244,14,248,8,137,252, - 242,137,252,233,232,251,1,15,248,9,139,12,36,137,185,233,137,252,242,137, - 252,233,232,251,1,0,139,52,36,139,149,233,252,233,244,4,248,87,139,108,36, - 48,252,247,133,233,237,15,132,244,63,255,137,149,233,141,68,194,252,248,137, - 133,233,49,192,137,133,233,176,235,136,133,233,252,233,244,16,255,248,71, - 255,248,73,139,114,252,252,221,90,252,248,252,233,244,66,255,248,88,129,252, - 248,239,15,130,244,63,255,129,122,253,4,239,15,133,244,248,139,42,131,252, - 253,0,15,137,244,71,252,247,221,15,136,244,247,248,89,248,71,139,114,252, - 252,199,66,252,252,237,137,106,252,248,252,233,244,66,248,1,139,114,252,252, - 199,66,252,252,0,0,224,65,199,66,252,248,0,0,0,0,252,233,244,66,248,2,15, - 135,244,63,255,129,122,253,4,239,15,131,244,63,255,252,242,15,16,2,102,15, - 252,239,201,102,15,118,201,102,15,115,209,1,15,84,193,248,72,139,114,252, - 252,252,242,15,17,66,252,248,255,221,2,217,225,248,72,248,73,139,114,252, - 252,221,90,252,248,255,248,66,184,237,248,78,137,68,36,20,248,64,252,247, - 198,237,15,133,244,253,248,5,56,70,252,255,15,135,244,252,15,182,78,252,253, - 252,247,209,141,20,202,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252, - 255,36,171,248,6,199,68,194,252,244,237,131,192,1,252,233,244,5,248,7,185, - 252,248,252,255,252,255,252,255,252,233,244,14,248,90,255,129,122,253,4,239, - 15,133,244,247,139,42,252,233,244,71,248,1,15,135,244,63,255,252,242,15,16, - 2,232,244,91,255,252,242,15,45,232,129,252,253,0,0,0,128,15,133,244,71,252, - 242,15,42,205,102,15,46,193,15,138,244,72,15,132,244,71,255,221,2,232,244, - 91,255,219,20,36,139,44,36,129,252,253,0,0,0,128,15,133,244,248,217,192,219, - 4,36,255,223,252,233,221,216,255,218,252,233,223,224,158,255,15,138,244,73, - 15,133,244,73,248,2,221,216,252,233,244,71,255,248,92,255,252,242,15,16,2, - 232,244,93,255,221,2,232,244,93,255,248,94,129,252,248,239,15,130,244,63, - 129,122,253,4,239,15,131,244,63,252,242,15,81,2,252,233,244,72,255,248,94, - 129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,221,2,217,252, - 250,252,233,244,73,255,248,95,129,252,248,239,15,130,244,63,129,122,253,4, - 239,15,131,244,63,217,252,237,221,2,217,252,241,252,233,244,73,248,96,129, - 252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,217,252,236,221, - 2,217,252,241,252,233,244,73,248,97,129,252,248,239,255,15,130,244,63,129, - 122,253,4,239,15,131,244,63,221,2,232,244,98,252,233,244,73,248,99,129,252, - 248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,221,2,217,252,254,252, - 233,244,73,248,100,129,252,248,239,255,15,130,244,63,129,122,253,4,239,15, - 131,244,63,221,2,217,252,255,252,233,244,73,248,101,129,252,248,239,15,130, - 244,63,129,122,253,4,239,15,131,244,63,221,2,217,252,242,221,216,252,233, - 244,73,248,102,129,252,248,239,15,130,244,63,255,129,122,253,4,239,15,131, - 244,63,221,2,217,192,216,200,217,232,222,225,217,252,250,217,252,243,252, - 233,244,73,248,103,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131, - 244,63,221,2,217,192,216,200,217,232,222,225,217,252,250,217,201,217,252, - 243,252,233,244,73,248,104,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,131,244,63,255,221,2,217,232,217,252,243,252,233,244,73,255,248,105,129, - 252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,252,242,15,16,2, - 252,242,15,17,4,36,255,248,105,129,252,248,239,15,130,244,63,129,122,253, - 4,239,15,131,244,63,221,2,221,28,36,255,137,213,232,251,1,16,137,252,234, - 252,233,244,73,255,248,106,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,131,244,63,252,242,15,16,2,252,242,15,17,4,36,255,248,106,129,252,248, - 239,15,130,244,63,129,122,253,4,239,15,131,244,63,221,2,221,28,36,255,137, - 213,232,251,1,17,137,252,234,252,233,244,73,255,248,107,129,252,248,239,15, - 130,244,63,129,122,253,4,239,15,131,244,63,252,242,15,16,2,252,242,15,17, - 4,36,255,248,107,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244, - 63,221,2,221,28,36,255,137,213,232,251,1,18,137,252,234,252,233,244,73,248, - 108,255,248,109,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244, - 63,252,242,15,16,2,139,106,252,248,252,242,15,89,133,233,252,233,244,72,255, - 248,109,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,221, - 2,139,106,252,248,220,141,233,252,233,244,73,255,248,110,129,252,248,239, - 15,130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244, - 63,221,2,221,66,8,217,252,243,252,233,244,73,248,111,129,252,248,239,15,130, - 244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,255,15,131,244, - 63,221,66,8,221,2,217,252,253,221,217,252,233,244,73,248,112,129,252,248, - 239,15,130,244,63,139,106,4,129,252,253,239,15,131,244,63,139,114,252,252, - 139,2,137,106,252,252,137,66,252,248,209,229,129,252,253,0,0,224,252,255, - 15,131,244,249,9,232,15,132,244,249,184,252,254,3,0,0,129,252,253,0,0,32, - 0,15,130,244,250,248,1,193,252,237,21,41,197,255,252,242,15,42,197,255,137, - 108,36,16,219,68,36,16,255,139,106,252,252,129,229,252,255,252,255,15,128, - 129,205,0,0,224,63,137,106,252,252,248,2,255,252,242,15,17,2,255,221,26,255, - 184,237,252,233,244,78,248,3,255,15,87,192,252,233,244,2,255,217,252,238, - 252,233,244,2,255,248,4,255,252,242,15,16,2,189,0,0,80,67,102,15,110,205, - 102,15,112,201,81,252,242,15,89,193,252,242,15,17,66,252,248,255,221,2,199, - 68,36,16,0,0,128,90,216,76,36,16,221,90,252,248,255,139,106,252,252,184,52, - 4,0,0,209,229,252,233,244,1,255,248,113,129,252,248,239,15,130,244,63,129, - 122,253,4,239,15,131,244,63,252,242,15,16,2,255,248,113,129,252,248,239,15, - 130,244,63,129,122,253,4,239,15,131,244,63,221,2,255,139,106,4,139,114,252, - 252,209,229,129,252,253,0,0,224,252,255,15,132,244,250,255,15,40,224,232, - 244,114,252,242,15,92,224,248,1,252,242,15,17,66,252,248,252,242,15,17,34, - 255,217,192,232,244,114,220,252,233,248,1,221,90,252,248,221,26,255,139,66, - 252,252,139,106,4,49,232,15,136,244,249,248,2,184,237,252,233,244,78,248, - 3,129,252,245,0,0,0,128,137,106,4,252,233,244,2,248,4,255,15,87,228,252,233, - 244,1,255,217,252,238,217,201,252,233,244,1,255,248,115,129,252,248,239,15, - 130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244, - 63,221,66,8,221,2,248,1,217,252,248,223,224,158,15,138,244,1,221,217,252, - 233,244,73,255,248,116,129,252,248,239,15,130,244,63,129,122,253,4,239,15, - 131,244,63,129,122,253,12,239,15,131,244,63,252,242,15,16,2,252,242,15,16, - 74,8,232,244,117,252,233,244,72,255,248,116,129,252,248,239,15,130,244,63, - 129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244,63,221,2,221, - 66,8,232,244,117,252,233,244,73,255,248,118,185,2,0,0,0,129,122,253,4,239, - 255,15,133,244,250,139,42,248,1,57,193,15,131,244,71,129,124,253,202,252, - 252,239,15,133,244,249,59,108,202,252,248,15,79,108,202,252,248,131,193,1, - 252,233,244,1,248,3,15,135,244,63,255,252,233,244,252,248,4,15,135,244,63, - 255,252,242,15,16,2,248,5,57,193,15,131,244,72,129,124,253,202,252,252,239, - 255,15,130,244,252,15,135,244,63,252,242,15,42,76,202,252,248,252,233,244, - 253,255,248,6,252,242,15,16,76,202,252,248,248,7,252,242,15,93,193,131,193, - 1,252,233,244,5,255,221,2,248,5,57,193,15,131,244,73,129,124,253,202,252, - 252,239,255,15,130,244,252,15,135,244,255,219,68,202,252,248,252,233,244, - 253,255,15,131,244,255,255,248,6,221,68,202,252,248,248,7,255,219,252,233, - 219,209,221,217,255,80,221,225,223,224,252,246,196,1,15,132,244,248,217,201, - 248,2,221,216,88,255,248,119,185,2,0,0,0,129,122,253,4,239,255,15,133,244, - 250,139,42,248,1,57,193,15,131,244,71,129,124,253,202,252,252,239,15,133, - 244,249,59,108,202,252,248,15,76,108,202,252,248,131,193,1,252,233,244,1, - 248,3,15,135,244,63,255,248,6,252,242,15,16,76,202,252,248,248,7,252,242, - 15,95,193,131,193,1,252,233,244,5,255,219,252,233,218,209,221,217,255,80, - 221,225,223,224,252,246,196,1,15,133,244,248,217,201,248,2,221,216,88,255, - 248,9,221,216,252,233,244,63,255,248,120,129,252,248,239,15,130,244,63,129, - 122,253,4,239,15,133,244,63,139,42,255,139,173,233,252,233,244,71,255,252, - 242,15,42,133,233,252,233,244,72,255,219,133,233,252,233,244,73,255,248,121, - 129,252,248,239,15,133,244,63,129,122,253,4,239,15,133,244,63,139,42,139, - 114,252,252,131,189,233,1,15,130,244,81,15,182,173,233,255,252,242,15,42, - 197,252,233,244,72,255,137,108,36,16,219,68,36,16,252,233,244,73,255,248, - 122,139,171,233,59,171,233,15,130,244,247,232,244,75,248,1,129,252,248,239, - 15,133,244,63,129,122,253,4,239,255,15,133,244,63,139,42,129,252,253,252, - 255,0,0,0,15,135,244,63,137,108,36,20,255,15,131,244,63,252,242,15,44,42, - 129,252,253,252,255,0,0,0,15,135,244,63,137,108,36,20,255,15,131,244,63,221, - 2,219,92,36,20,129,124,36,20,252,255,0,0,0,15,135,244,63,255,199,68,36,8, - 1,0,0,0,141,68,36,20,248,123,139,108,36,48,137,149,233,137,68,36,4,137,44, - 36,137,116,36,24,232,251,1,19,139,149,233,139,114,252,252,199,66,252,252, - 237,137,66,252,248,252,233,244,66,248,124,139,171,233,59,171,233,15,130,244, - 247,232,244,75,248,1,199,68,36,20,252,255,252,255,252,255,252,255,129,252, - 248,239,15,130,244,63,15,134,244,247,129,122,253,20,239,255,15,133,244,63, - 139,106,16,137,108,36,20,255,15,131,244,63,252,242,15,44,106,16,137,108,36, - 20,255,15,131,244,63,221,66,16,219,92,36,20,255,248,1,129,122,253,4,239,15, - 133,244,63,129,122,253,12,239,255,139,42,137,108,36,12,139,173,233,255,139, - 74,8,255,252,242,15,44,74,8,255,221,66,8,219,92,36,8,139,76,36,8,255,139, - 68,36,20,57,197,15,130,244,251,248,2,133,201,15,142,244,253,248,3,139,108, - 36,12,41,200,15,140,244,125,141,172,253,13,233,131,192,1,248,4,137,68,36, - 8,137,232,252,233,244,123,248,5,15,140,244,252,141,68,40,1,252,233,244,2, - 248,6,137,232,252,233,244,2,248,7,255,15,132,244,254,1,252,233,131,193,1, - 15,143,244,3,248,8,185,1,0,0,0,252,233,244,3,248,125,49,192,252,233,244,4, - 248,126,129,252,248,239,15,130,244,63,139,171,233,59,171,233,15,130,244,247, - 232,244,75,248,1,255,129,122,253,4,239,15,133,244,63,129,122,253,12,239,139, - 42,255,15,133,244,63,139,66,8,255,15,131,244,63,252,242,15,44,66,8,255,15, - 131,244,63,221,66,8,219,92,36,20,139,68,36,20,255,133,192,15,142,244,125, - 131,189,233,1,15,130,244,125,15,133,244,127,57,131,233,15,130,244,127,15, - 182,141,233,139,171,233,137,68,36,8,248,1,136,77,0,131,197,1,131,232,1,15, - 133,244,1,139,131,233,252,233,244,123,248,128,129,252,248,239,255,15,130, - 244,63,139,171,233,59,171,233,15,130,244,247,232,244,75,248,1,129,122,253, - 4,239,15,133,244,63,139,42,139,133,233,133,192,15,132,244,125,57,131,233, - 15,130,244,129,129,197,239,137,116,36,20,137,68,36,8,139,179,233,248,1,255, - 15,182,77,0,131,197,1,131,232,1,136,12,6,15,133,244,1,137,252,240,139,116, - 36,20,252,233,244,123,248,130,129,252,248,239,15,130,244,63,139,171,233,59, - 171,233,15,130,244,247,232,244,75,248,1,129,122,253,4,239,15,133,244,63,139, - 42,139,133,233,57,131,233,255,15,130,244,129,129,197,239,137,116,36,20,137, - 68,36,8,139,179,233,252,233,244,249,248,1,15,182,76,5,0,131,252,249,65,15, - 130,244,248,131,252,249,90,15,135,244,248,131,252,241,32,248,2,136,12,6,248, - 3,131,232,1,15,137,244,1,137,252,240,139,116,36,20,252,233,244,123,248,131, - 129,252,248,239,15,130,244,63,255,139,171,233,59,171,233,15,130,244,247,232, - 244,75,248,1,129,122,253,4,239,15,133,244,63,139,42,139,133,233,57,131,233, - 15,130,244,129,129,197,239,137,116,36,20,137,68,36,8,139,179,233,252,233, - 244,249,248,1,15,182,76,5,0,131,252,249,97,15,130,244,248,255,131,252,249, - 122,15,135,244,248,131,252,241,32,248,2,136,12,6,248,3,131,232,1,15,137,244, - 1,137,252,240,139,116,36,20,252,233,244,123,248,132,129,252,248,239,15,130, - 244,63,129,122,253,4,239,15,133,244,63,137,213,139,10,232,251,1,20,137,252, - 234,255,137,197,252,233,244,71,255,252,242,15,42,192,252,233,244,72,255,137, - 4,36,219,4,36,252,233,244,73,255,248,133,129,252,248,239,15,130,244,63,129, - 122,253,4,239,255,15,133,244,247,139,42,252,233,244,89,248,1,15,135,244,63, - 255,252,242,15,16,2,189,0,0,56,67,102,15,110,205,102,15,112,201,81,252,242, - 15,88,193,102,15,126,197,255,221,2,199,68,36,16,0,0,192,89,216,68,36,16,221, - 28,36,255,139,44,36,255,252,233,244,89,255,248,134,129,252,248,239,15,130, - 244,63,255,189,0,0,56,67,102,15,110,205,102,15,112,201,81,255,199,68,36,16, - 0,0,192,89,255,15,133,244,247,139,42,252,233,244,248,248,1,15,135,244,63, - 255,252,242,15,16,2,252,242,15,88,193,102,15,126,197,255,221,2,216,68,36, - 16,221,28,36,139,44,36,255,248,2,137,68,36,20,141,68,194,252,240,248,1,57, - 208,15,134,244,89,129,120,253,4,239,255,15,133,244,248,35,40,131,232,8,252, - 233,244,1,248,2,15,135,244,135,255,15,131,244,135,255,252,242,15,16,0,252, - 242,15,88,193,102,15,126,193,33,205,255,221,0,216,68,36,16,221,28,36,35,44, - 36,255,131,232,8,252,233,244,1,248,136,129,252,248,239,15,130,244,63,255, - 15,133,244,248,11,40,131,232,8,252,233,244,1,248,2,15,135,244,135,255,252, - 242,15,16,0,252,242,15,88,193,102,15,126,193,9,205,255,221,0,216,68,36,16, - 221,28,36,11,44,36,255,131,232,8,252,233,244,1,248,137,129,252,248,239,15, - 130,244,63,255,15,133,244,248,51,40,131,232,8,252,233,244,1,248,2,15,135, - 244,135,255,252,242,15,16,0,252,242,15,88,193,102,15,126,193,49,205,255,221, - 0,216,68,36,16,221,28,36,51,44,36,255,131,232,8,252,233,244,1,248,138,129, - 252,248,239,15,130,244,63,129,122,253,4,239,255,221,2,199,68,36,16,0,0,192, - 89,216,68,36,16,221,28,36,139,44,36,255,248,2,15,205,252,233,244,89,248,139, - 129,252,248,239,15,130,244,63,129,122,253,4,239,255,248,2,252,247,213,255, - 248,89,252,242,15,42,197,252,233,244,72,255,248,89,137,44,36,219,4,36,252, - 233,244,73,255,248,135,139,68,36,20,252,233,244,63,255,248,140,129,252,248, - 239,15,130,244,63,129,122,253,4,239,255,248,2,129,122,253,12,239,15,133,244, - 63,139,74,8,255,248,140,129,252,248,239,15,130,244,63,129,122,253,4,239,15, - 131,244,63,129,122,253,12,239,15,131,244,63,252,242,15,16,2,252,242,15,16, - 74,8,189,0,0,56,67,102,15,110,213,102,15,112,210,81,252,242,15,88,194,252, - 242,15,88,202,102,15,126,197,102,15,126,201,255,248,140,129,252,248,239,15, - 130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244, - 63,221,2,221,66,8,199,68,36,16,0,0,192,89,216,68,36,16,221,92,36,8,216,68, - 36,16,221,28,36,139,76,36,8,139,44,36,255,211,229,252,233,244,89,255,248, - 141,129,252,248,239,15,130,244,63,129,122,253,4,239,255,248,141,129,252,248, - 239,15,130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131, - 244,63,252,242,15,16,2,252,242,15,16,74,8,189,0,0,56,67,102,15,110,213,102, - 15,112,210,81,252,242,15,88,194,252,242,15,88,202,102,15,126,197,102,15,126, - 201,255,248,141,129,252,248,239,15,130,244,63,129,122,253,4,239,15,131,244, - 63,129,122,253,12,239,15,131,244,63,221,2,221,66,8,199,68,36,16,0,0,192,89, - 216,68,36,16,221,92,36,8,216,68,36,16,221,28,36,139,76,36,8,139,44,36,255, - 211,252,237,252,233,244,89,255,248,142,129,252,248,239,15,130,244,63,129, - 122,253,4,239,255,248,142,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,131,244,63,129,122,253,12,239,15,131,244,63,252,242,15,16,2,252,242,15, - 16,74,8,189,0,0,56,67,102,15,110,213,102,15,112,210,81,252,242,15,88,194, - 252,242,15,88,202,102,15,126,197,102,15,126,201,255,248,142,129,252,248,239, - 15,130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244, - 63,221,2,221,66,8,199,68,36,16,0,0,192,89,216,68,36,16,221,92,36,8,216,68, - 36,16,221,28,36,139,76,36,8,139,44,36,255,211,252,253,252,233,244,89,255, - 248,143,129,252,248,239,15,130,244,63,129,122,253,4,239,255,248,143,129,252, - 248,239,15,130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239, - 15,131,244,63,252,242,15,16,2,252,242,15,16,74,8,189,0,0,56,67,102,15,110, - 213,102,15,112,210,81,252,242,15,88,194,252,242,15,88,202,102,15,126,197, - 102,15,126,201,255,248,143,129,252,248,239,15,130,244,63,129,122,253,4,239, - 15,131,244,63,129,122,253,12,239,15,131,244,63,221,2,221,66,8,199,68,36,16, - 0,0,192,89,216,68,36,16,221,92,36,8,216,68,36,16,221,28,36,139,76,36,8,139, - 44,36,255,211,197,252,233,244,89,255,248,144,129,252,248,239,15,130,244,63, - 129,122,253,4,239,255,248,144,129,252,248,239,15,130,244,63,129,122,253,4, - 239,15,131,244,63,129,122,253,12,239,15,131,244,63,252,242,15,16,2,252,242, - 15,16,74,8,189,0,0,56,67,102,15,110,213,102,15,112,210,81,252,242,15,88,194, - 252,242,15,88,202,102,15,126,197,102,15,126,201,255,248,144,129,252,248,239, - 15,130,244,63,129,122,253,4,239,15,131,244,63,129,122,253,12,239,15,131,244, - 63,221,2,221,66,8,199,68,36,16,0,0,192,89,216,68,36,16,221,92,36,8,216,68, - 36,16,221,28,36,139,76,36,8,139,44,36,255,211,205,252,233,244,89,248,127, - 184,237,252,233,244,63,248,129,184,237,248,63,139,108,36,48,139,114,252,252, - 137,116,36,24,137,149,233,141,68,194,252,248,141,136,233,137,133,233,139, - 66,252,248,59,141,233,15,135,244,251,137,44,36,252,255,144,233,139,149,233, - 133,192,15,143,244,78,248,1,255,139,141,233,41,209,193,252,233,3,133,192, - 141,65,1,139,106,252,248,15,133,244,33,139,181,233,139,14,15,182,252,233, - 15,182,205,131,198,4,252,255,36,171,248,33,137,209,252,247,198,237,15,133, - 244,249,15,182,110,252,253,252,247,213,141,20,252,234,252,233,244,28,248, - 3,137,252,245,131,229,252,248,41,252,234,252,233,244,28,248,5,186,237,137, - 252,233,232,251,1,0,139,149,233,49,192,252,233,244,1,248,75,93,137,108,36, - 16,139,108,36,48,137,116,36,24,137,149,233,255,141,68,194,252,248,137,252, - 233,137,133,233,232,251,1,21,139,149,233,139,133,233,41,208,193,232,3,131, - 192,1,139,108,36,16,85,195,248,145,255,15,182,131,233,168,235,15,133,244, - 251,168,235,15,133,244,247,168,235,15,132,244,247,252,255,139,233,252,233, - 244,247,255,248,146,15,182,131,233,168,235,15,133,244,251,252,233,244,247, - 248,147,15,182,131,233,168,235,15,133,244,251,168,235,15,132,244,251,252, - 255,139,233,15,132,244,247,168,235,15,132,244,251,248,1,255,139,108,36,48, - 137,149,233,137,252,242,137,252,233,232,251,1,22,248,3,139,149,233,248,4, - 15,182,78,252,253,248,5,15,182,110,252,252,15,183,70,252,254,252,255,164, - 253,171,233,248,148,131,198,4,139,77,232,137,76,36,20,252,233,244,4,248,149, - 255,139,106,252,248,139,173,233,15,182,133,233,141,4,194,139,108,36,48,137, - 149,233,137,133,233,137,252,242,141,139,233,137,171,233,137,116,36,24,232, - 251,1,23,252,233,244,3,255,248,150,137,116,36,24,255,248,151,255,137,116, - 36,24,131,206,1,248,1,255,141,68,194,252,248,139,108,36,48,137,149,233,137, - 133,233,137,252,242,137,252,233,232,251,1,24,199,68,36,24,0,0,0,0,255,131, - 230,252,254,255,139,149,233,137,193,139,133,233,41,208,137,205,15,182,78, - 252,253,193,232,3,131,192,1,252,255,229,248,152,255,85,141,108,36,12,85,83, - 82,81,80,15,182,69,252,252,138,101,252,248,137,125,252,252,137,117,252,248, - 139,93,0,139,139,233,199,131,233,237,137,131,233,137,139,233,129,252,236, - 239,252,242,15,17,125,216,252,242,15,17,117,208,252,242,15,17,109,200,252, - 242,15,17,101,192,252,242,15,17,93,184,252,242,15,17,85,176,252,242,15,17, - 77,168,252,242,15,17,69,160,139,171,233,139,147,233,137,171,233,199,131,233, - 0,0,0,0,137,149,233,141,84,36,16,141,139,233,232,251,1,25,139,141,233,129, - 225,239,137,204,137,169,233,139,149,233,139,177,233,255,248,153,255,133,192, - 15,136,244,249,137,68,36,20,139,122,252,248,139,191,233,139,191,233,199,131, - 233,0,0,0,0,199,131,233,237,139,6,15,182,204,15,182,232,131,198,4,193,232, - 16,129,252,253,239,15,130,244,248,139,68,36,20,248,2,252,255,36,171,248,3, - 252,247,216,137,252,233,137,194,232,251,1,26,255,248,91,255,217,124,36,4, - 137,68,36,8,102,184,0,4,102,11,68,36,4,102,37,252,255,252,247,102,137,68, - 36,6,217,108,36,6,217,252,252,217,108,36,4,139,68,36,8,195,255,248,154,102, - 15,252,239,210,102,15,118,210,102,15,115,210,1,184,0,0,48,67,102,15,110,216, - 102,15,112,219,81,15,40,200,102,15,84,202,102,15,46,217,15,134,244,247,102, - 15,85,208,252,242,15,88,203,252,242,15,92,203,102,15,86,202,184,0,0,252,240, - 63,102,15,110,208,102,15,112,210,81,252,242,15,194,193,1,102,15,84,194,252, - 242,15,92,200,15,40,193,248,1,195,248,93,255,217,124,36,4,137,68,36,8,102, - 184,0,8,102,11,68,36,4,102,37,252,255,252,251,102,137,68,36,6,217,108,36, - 6,217,252,252,217,108,36,4,139,68,36,8,195,255,248,155,102,15,252,239,210, - 102,15,118,210,102,15,115,210,1,184,0,0,48,67,102,15,110,216,102,15,112,219, - 81,15,40,200,102,15,84,202,102,15,46,217,15,134,244,247,102,15,85,208,252, - 242,15,88,203,252,242,15,92,203,102,15,86,202,184,0,0,252,240,191,102,15, - 110,208,102,15,112,210,81,252,242,15,194,193,6,102,15,84,194,252,242,15,92, - 200,15,40,193,248,1,195,248,114,255,217,124,36,4,137,68,36,8,102,184,0,12, - 102,11,68,36,4,102,137,68,36,6,217,108,36,6,217,252,252,217,108,36,4,139, - 68,36,8,195,255,248,156,102,15,252,239,210,102,15,118,210,102,15,115,210, - 1,184,0,0,48,67,102,15,110,216,102,15,112,219,81,15,40,200,102,15,84,202, - 102,15,46,217,15,134,244,247,102,15,85,208,15,40,193,252,242,15,88,203,252, - 242,15,92,203,184,0,0,252,240,63,102,15,110,216,102,15,112,219,81,252,242, - 15,194,193,1,102,15,84,195,252,242,15,92,200,102,15,86,202,15,40,193,248, - 1,195,248,157,255,15,40,232,252,242,15,94,193,102,15,252,239,210,102,15,118, - 210,102,15,115,210,1,184,0,0,48,67,102,15,110,216,102,15,112,219,81,15,40, - 224,102,15,84,226,102,15,46,220,15,134,244,247,102,15,85,208,252,242,15,88, - 227,252,242,15,92,227,102,15,86,226,184,0,0,252,240,63,102,15,110,208,102, - 15,112,210,81,252,242,15,194,196,1,102,15,84,194,252,242,15,92,224,15,40, - 197,252,242,15,89,204,252,242,15,92,193,195,248,1,252,242,15,89,200,15,40, - 197,252,242,15,92,193,195,255,217,193,216,252,241,217,124,36,4,102,184,0, - 4,102,11,68,36,4,102,37,252,255,252,247,102,137,68,36,6,217,108,36,6,217, - 252,252,217,108,36,4,222,201,222,252,233,195,255,248,98,217,252,234,222,201, - 248,158,217,84,36,4,129,124,36,4,0,0,128,127,15,132,244,247,129,124,36,4, - 0,0,128,252,255,15,132,244,248,248,159,217,192,217,252,252,220,252,233,217, - 201,217,252,240,217,232,222,193,217,252,253,221,217,248,1,195,248,2,221,216, - 217,252,238,195,255,248,117,219,84,36,4,219,68,36,4,255,223,252,233,255,221, - 252,233,223,224,158,255,15,133,244,254,15,138,244,255,221,216,139,68,36,4, - 131,252,248,1,15,142,244,252,248,1,169,1,0,0,0,15,133,244,248,216,200,209, - 232,252,233,244,1,248,2,209,232,15,132,244,251,217,192,248,3,216,200,209, - 232,15,132,244,250,15,131,244,3,220,201,252,233,244,3,248,4,255,222,201,248, - 5,195,248,6,15,132,244,5,15,130,244,253,217,232,222,252,241,252,247,216,131, - 252,248,1,15,132,244,5,252,233,244,1,248,7,221,216,217,232,195,248,8,217, - 84,36,4,217,201,217,84,36,8,139,68,36,4,209,224,61,0,0,0,252,255,15,132,244, - 248,139,68,36,8,209,224,15,132,244,250,61,0,0,0,252,255,15,132,244,250,217, - 252,241,252,233,244,159,248,9,255,217,232,255,223,252,234,255,221,252,234, - 223,224,158,255,15,132,244,247,217,201,248,1,221,216,195,248,2,217,225,217, - 232,255,15,132,244,249,221,216,217,225,217,252,238,184,0,0,0,0,15,146,208, - 209,200,51,68,36,4,15,137,244,249,217,201,248,3,221,217,217,225,195,248,4, - 131,124,36,4,0,15,141,244,3,221,216,221,216,133,192,15,132,244,251,217,252, - 238,195,248,5,199,68,36,4,0,0,128,127,217,68,36,4,195,255,248,117,255,248, - 160,252,242,15,45,193,252,242,15,42,208,102,15,46,202,15,133,244,254,15,138, - 244,255,248,161,131,252,248,1,15,142,244,252,248,1,169,1,0,0,0,15,133,244, - 248,252,242,15,89,192,209,232,252,233,244,1,248,2,209,232,15,132,244,251, - 15,40,200,248,3,252,242,15,89,192,209,232,15,132,244,250,15,131,244,3,255, - 252,242,15,89,200,252,233,244,3,248,4,252,242,15,89,193,248,5,195,248,6,15, - 132,244,5,15,130,244,253,252,247,216,232,244,1,184,0,0,252,240,63,102,15, - 110,200,102,15,112,201,81,252,242,15,94,200,15,40,193,195,248,7,184,0,0,252, - 240,63,102,15,110,192,102,15,112,192,81,195,248,8,252,242,15,17,76,36,12, - 252,242,15,17,68,36,4,131,124,36,12,0,15,133,244,247,139,68,36,16,209,224, - 61,0,0,224,252,255,15,132,244,248,248,1,131,124,36,4,0,15,133,244,247,255, - 139,68,36,8,209,224,15,132,244,250,61,0,0,224,252,255,15,132,244,251,248, - 1,221,68,36,12,221,68,36,4,217,252,241,217,192,217,252,252,220,252,233,217, - 201,217,252,240,217,232,222,193,217,252,253,221,217,221,92,36,4,252,242,15, - 16,68,36,4,195,248,9,184,0,0,252,240,63,102,15,110,208,102,15,112,210,81, - 102,15,46,194,15,132,244,247,15,40,193,248,1,195,248,2,102,15,252,239,210, - 102,15,118,210,102,15,115,210,1,102,15,84,194,184,0,0,252,240,63,102,15,110, - 208,102,15,112,210,81,102,15,46,194,15,132,244,1,102,15,80,193,15,87,192, - 136,196,15,146,208,48,224,15,133,244,1,248,3,184,0,0,252,240,127,102,15,110, - 192,102,15,112,192,81,195,248,4,102,15,80,193,133,192,15,133,244,3,15,87, - 192,195,248,5,102,15,80,193,133,192,15,132,244,3,255,15,87,192,195,248,162, - 255,139,68,36,12,252,242,15,16,68,36,4,131,252,248,1,15,132,244,247,15,135, - 244,248,232,244,91,252,233,244,253,248,1,232,244,93,252,233,244,253,248,2, - 131,252,248,3,15,132,244,247,15,135,244,248,232,244,114,255,252,233,244,253, - 248,1,252,242,15,81,192,248,7,252,242,15,17,68,36,4,221,68,36,4,195,248,2, - 221,68,36,4,131,252,248,5,15,130,244,98,15,132,244,158,248,2,131,252,248, - 7,15,132,244,247,15,135,244,248,217,252,237,217,201,217,252,241,195,248,1, - 217,232,217,201,217,252,241,195,248,2,131,252,248,9,15,132,244,247,15,135, - 244,248,255,217,252,236,217,201,217,252,241,195,248,1,217,252,254,195,248, - 2,131,252,248,11,15,132,244,247,15,135,244,255,217,252,255,195,248,1,217, - 252,242,221,216,195,255,139,68,36,12,221,68,36,4,131,252,248,1,15,130,244, - 91,15,132,244,93,131,252,248,3,15,130,244,114,15,135,244,248,217,252,250, - 195,248,2,131,252,248,5,15,130,244,98,15,132,244,158,131,252,248,7,15,132, - 244,247,15,135,244,248,217,252,237,217,201,217,252,241,195,248,1,217,232, - 217,201,217,252,241,195,248,2,131,252,248,9,15,132,244,247,255,15,135,244, - 248,217,252,236,217,201,217,252,241,195,248,1,217,252,254,195,248,2,131,252, - 248,11,15,132,244,247,15,135,244,255,217,252,255,195,248,1,217,252,242,221, - 216,195,255,248,9,204,255,248,163,255,139,68,36,20,252,242,15,16,68,36,4, - 252,242,15,16,76,36,12,131,252,248,1,15,132,244,247,15,135,244,248,252,242, - 15,88,193,248,7,252,242,15,17,68,36,4,221,68,36,4,195,248,1,252,242,15,92, - 193,252,233,244,7,248,2,131,252,248,3,15,132,244,247,15,135,244,248,252,242, - 15,89,193,252,233,244,7,248,1,252,242,15,94,193,252,233,244,7,248,2,131,252, - 248,5,15,132,244,247,255,15,135,244,248,232,244,157,252,233,244,7,248,1,90, - 232,244,117,82,252,233,244,7,248,2,131,252,248,7,15,132,244,247,15,135,244, - 248,184,0,0,0,128,102,15,110,200,102,15,112,201,81,15,87,193,252,233,244, - 7,248,1,102,15,252,239,201,102,15,118,201,102,15,115,209,1,15,84,193,252, - 233,244,7,248,2,255,131,252,248,9,15,135,244,248,221,68,36,4,221,68,36,12, - 15,132,244,247,217,252,243,195,248,1,217,201,217,252,253,221,217,195,248, - 2,131,252,248,11,15,132,244,247,15,135,244,255,252,242,15,93,193,252,233, - 244,7,248,1,252,242,15,95,193,252,233,244,7,248,9,204,255,139,68,36,20,221, - 68,36,4,221,68,36,12,131,252,248,1,15,132,244,247,15,135,244,248,222,193, - 195,248,1,222,252,233,195,248,2,131,252,248,3,15,132,244,247,15,135,244,248, - 222,201,195,248,1,222,252,249,195,248,2,131,252,248,5,15,130,244,157,15,132, - 244,117,131,252,248,7,15,132,244,247,15,135,244,248,255,221,216,217,224,195, - 248,1,221,216,217,225,195,248,2,131,252,248,9,15,132,244,247,15,135,244,248, - 217,252,243,195,248,1,217,201,217,252,253,221,217,195,248,2,131,252,248,11, - 15,132,244,247,15,135,244,255,255,219,252,233,219,209,221,217,195,248,1,219, - 252,233,218,209,221,217,195,255,221,225,223,224,252,246,196,1,15,132,244, - 248,217,201,248,2,221,216,195,248,1,221,225,223,224,252,246,196,1,15,133, - 244,248,217,201,248,2,221,216,195,255,248,164,156,90,137,209,129,252,242, - 0,0,32,0,82,157,156,90,49,192,57,209,15,132,244,247,139,68,36,4,87,83,15, - 162,139,124,36,16,137,7,137,95,4,137,79,8,137,87,12,91,95,248,1,195,248,165, - 255,204,248,166,255,131,252,236,16,87,86,83,131,252,236,28,141,157,233,139, - 181,233,15,183,192,137,134,233,141,132,253,36,233,137,142,233,137,150,233, - 137,134,233,139,140,253,36,233,139,148,253,36,233,137,76,36,44,137,84,36, - 40,137,226,137,116,36,24,137,252,241,232,251,1,27,199,131,233,237,139,144, - 233,139,128,233,41,208,139,106,252,248,193,232,3,131,192,1,139,181,233,139, - 14,15,182,252,233,15,182,205,131,198,4,252,255,36,171,255,248,32,255,139, - 76,36,48,139,179,233,137,142,233,137,145,233,137,169,233,137,252,241,137, - 194,232,251,1,28,139,108,36,48,139,134,233,139,150,233,131,190,233,1,15,130, - 244,253,15,132,244,252,221,134,233,252,233,244,253,248,6,217,134,233,248, - 7,139,141,233,15,183,73,6,137,76,36,48,131,196,28,91,94,95,93,89,3,36,36, - 131,196,16,81,195,255,248,167,255,85,137,229,83,137,203,43,163,233,255,137, - 163,233,255,15,182,139,233,131,252,233,1,15,136,244,248,248,1,139,132,253, - 139,233,137,4,140,131,252,233,1,15,137,244,1,248,2,139,139,233,139,147,233, - 252,255,147,233,137,131,233,137,147,233,128,187,233,1,15,130,244,253,15,132, - 244,252,221,155,233,252,233,244,253,248,6,255,217,155,233,248,7,255,41,163, - 233,255,139,93,252,252,201,195,255,249,255,129,124,253,202,4,239,15,133,244, - 253,129,124,253,194,4,239,15,133,244,254,139,44,202,131,198,4,59,44,194,255, - 15,141,244,255,255,15,140,244,255,255,15,143,244,255,255,15,142,244,255,255, - 248,6,15,183,70,252,254,141,180,253,134,233,248,9,139,6,15,182,204,15,182, - 232,131,198,4,193,232,16,252,255,36,171,248,7,15,135,244,44,129,124,253,194, - 4,239,15,130,244,247,15,133,244,44,255,252,242,15,42,4,194,252,233,244,248, - 255,221,4,202,219,4,194,252,233,244,249,255,248,8,15,135,244,44,255,252,242, - 15,42,12,202,252,242,15,16,4,194,131,198,4,102,15,46,193,255,15,134,244,9, - 255,15,135,244,9,255,15,130,244,9,255,15,131,244,9,255,252,233,244,6,255, - 219,4,202,252,233,244,248,255,129,124,253,202,4,239,15,131,244,44,129,124, - 253,194,4,239,15,131,244,44,255,248,1,252,242,15,16,4,194,248,2,131,198,4, - 102,15,46,4,202,248,3,255,248,1,221,4,202,248,2,221,4,194,248,3,131,198,4, - 255,15,135,244,247,255,15,130,244,247,255,15,131,244,247,255,15,183,70,252, - 254,141,180,253,134,233,248,1,139,6,15,182,204,15,182,232,131,198,4,193,232, - 16,252,255,36,171,255,139,108,194,4,131,198,4,255,129,252,253,239,15,133, - 244,253,129,124,253,202,4,239,15,133,244,254,139,44,194,59,44,202,255,15, - 133,244,255,255,15,132,244,255,255,15,183,70,252,254,141,180,253,134,233, - 248,9,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,248, - 7,15,135,244,251,129,124,253,202,4,239,15,130,244,247,15,133,244,251,255, - 252,242,15,42,4,202,255,219,4,202,255,252,233,244,248,248,8,15,135,244,251, - 255,252,242,15,42,4,194,102,15,46,4,202,255,219,4,194,221,4,202,255,252,233, - 244,250,255,129,252,253,239,15,131,244,251,129,124,253,202,4,239,15,131,244, - 251,255,248,1,252,242,15,16,4,202,248,2,102,15,46,4,194,248,4,255,248,1,221, - 4,202,248,2,221,4,194,248,4,255,15,138,244,248,15,133,244,248,255,15,138, - 244,248,15,132,244,247,255,248,1,15,183,70,252,254,141,180,253,134,233,248, - 2,255,248,2,15,183,70,252,254,141,180,253,134,233,248,1,255,252,233,244,9, - 255,248,5,255,129,252,253,239,15,132,244,49,129,124,253,202,4,239,15,132, - 244,49,255,57,108,202,4,15,133,244,2,129,252,253,239,15,131,244,1,139,12, - 202,139,4,194,57,193,15,132,244,1,129,252,253,239,15,135,244,2,139,169,233, - 133,252,237,15,132,244,2,252,246,133,233,235,15,133,244,2,255,49,252,237, - 255,189,1,0,0,0,255,252,233,244,48,255,248,3,129,252,253,239,255,15,133,244, - 9,255,252,233,244,49,255,252,247,208,139,108,202,4,131,198,4,129,252,253, - 239,15,133,244,249,139,12,202,59,12,135,255,139,108,202,4,131,198,4,255,129, - 252,253,239,15,133,244,253,129,124,253,199,4,239,15,133,244,254,139,44,199, - 59,44,202,255,15,183,70,252,254,141,180,253,134,233,248,9,139,6,15,182,204, - 15,182,232,131,198,4,193,232,16,252,255,36,171,248,7,15,135,244,249,129,124, - 253,199,4,239,15,130,244,247,255,252,242,15,42,4,199,255,219,4,199,255,252, - 233,244,248,248,8,255,252,242,15,42,4,202,102,15,46,4,199,255,219,4,202,221, - 4,199,255,129,252,253,239,15,131,244,249,255,248,1,252,242,15,16,4,199,248, - 2,102,15,46,4,202,248,4,255,248,1,221,4,199,248,2,221,4,202,248,4,255,252, - 247,208,139,108,202,4,131,198,4,57,197,255,15,133,244,249,15,183,70,252,254, - 141,180,253,134,233,248,2,139,6,15,182,204,15,182,232,131,198,4,193,232,16, - 252,255,36,171,248,3,129,252,253,239,15,133,244,2,252,233,244,49,255,15,132, - 244,248,129,252,253,239,15,132,244,49,15,183,70,252,254,141,180,253,134,233, - 248,2,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,255, - 139,108,194,4,131,198,4,129,252,253,239,255,137,108,202,4,139,44,194,137, - 44,202,255,139,108,194,4,139,4,194,137,108,202,4,137,4,202,139,6,15,182,204, - 15,182,232,131,198,4,193,232,16,252,255,36,171,255,49,252,237,129,124,253, - 194,4,239,129,213,239,137,108,202,4,139,6,15,182,204,15,182,232,131,198,4, - 193,232,16,252,255,36,171,255,129,124,253,194,4,239,15,133,244,251,139,44, - 194,252,247,221,15,128,244,250,199,68,202,4,237,137,44,202,248,9,139,6,15, - 182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,248,4,199,68,202,4, - 0,0,224,65,199,4,202,0,0,0,0,252,233,244,9,248,5,15,135,244,54,255,129,124, - 253,194,4,239,15,131,244,54,255,252,242,15,16,4,194,184,0,0,0,128,102,15, - 110,200,102,15,112,201,81,15,87,193,252,242,15,17,4,202,255,221,4,194,217, - 224,221,28,202,255,129,124,253,194,4,239,15,133,244,248,139,4,194,255,139, - 128,233,248,1,199,68,202,4,237,137,4,202,255,15,87,192,252,242,15,42,128, - 233,248,1,252,242,15,17,4,202,255,219,128,233,248,1,221,28,202,255,139,6, - 15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,248,2,129,124,253, - 194,4,239,15,133,244,57,139,12,194,255,139,169,233,131,252,253,0,15,133,244, - 255,248,3,255,248,58,137,213,232,251,1,20,255,252,242,15,42,192,255,137,4, - 36,219,4,36,255,137,252,234,15,182,78,252,253,252,233,244,1,255,248,9,252, - 246,133,233,235,15,133,244,3,252,233,244,57,255,15,182,252,236,15,182,192, - 255,129,124,253,252,234,4,239,15,133,244,51,129,124,253,199,4,239,15,133, - 244,51,139,44,252,234,3,44,199,15,128,244,50,255,129,124,253,252,234,4,239, - 15,133,244,53,129,124,253,199,4,239,15,133,244,53,139,4,199,3,4,252,234,15, - 128,244,52,255,129,124,253,252,234,4,239,15,133,244,56,129,124,253,194,4, - 239,15,133,244,56,139,44,252,234,3,44,194,15,128,244,55,255,199,68,202,4, - 237,255,129,124,253,252,234,4,239,15,131,244,51,255,129,124,253,199,4,239, - 15,131,244,51,255,252,242,15,16,4,252,234,252,242,15,88,4,199,255,221,4,252, - 234,220,4,199,255,129,124,253,252,234,4,239,15,131,244,53,255,129,124,253, - 199,4,239,15,131,244,53,255,252,242,15,16,4,199,252,242,15,88,4,252,234,255, - 221,4,199,220,4,252,234,255,129,124,253,252,234,4,239,15,131,244,56,129,124, - 253,194,4,239,15,131,244,56,255,252,242,15,16,4,252,234,252,242,15,88,4,194, - 255,221,4,252,234,220,4,194,255,129,124,253,252,234,4,239,15,133,244,51,129, - 124,253,199,4,239,15,133,244,51,139,44,252,234,43,44,199,15,128,244,50,255, - 129,124,253,252,234,4,239,15,133,244,53,129,124,253,199,4,239,15,133,244, - 53,139,4,199,43,4,252,234,15,128,244,52,255,129,124,253,252,234,4,239,15, - 133,244,56,129,124,253,194,4,239,15,133,244,56,139,44,252,234,43,44,194,15, - 128,244,55,255,252,242,15,16,4,252,234,252,242,15,92,4,199,255,221,4,252, - 234,220,36,199,255,252,242,15,16,4,199,252,242,15,92,4,252,234,255,221,4, - 199,220,36,252,234,255,252,242,15,16,4,252,234,252,242,15,92,4,194,255,221, - 4,252,234,220,36,194,255,129,124,253,252,234,4,239,15,133,244,51,129,124, - 253,199,4,239,15,133,244,51,139,44,252,234,15,175,44,199,15,128,244,50,255, - 129,124,253,252,234,4,239,15,133,244,53,129,124,253,199,4,239,15,133,244, - 53,139,4,199,15,175,4,252,234,15,128,244,52,255,129,124,253,252,234,4,239, - 15,133,244,56,129,124,253,194,4,239,15,133,244,56,139,44,252,234,15,175,44, - 194,15,128,244,55,255,252,242,15,16,4,252,234,252,242,15,89,4,199,255,221, - 4,252,234,220,12,199,255,252,242,15,16,4,199,252,242,15,89,4,252,234,255, - 221,4,199,220,12,252,234,255,252,242,15,16,4,252,234,252,242,15,89,4,194, - 255,221,4,252,234,220,12,194,255,252,242,15,16,4,252,234,252,242,15,94,4, - 199,255,221,4,252,234,220,52,199,255,252,242,15,16,4,199,252,242,15,94,4, - 252,234,255,221,4,199,220,52,252,234,255,252,242,15,16,4,252,234,252,242, - 15,94,4,194,255,221,4,252,234,220,52,194,255,252,242,15,16,4,252,234,252, - 242,15,16,12,199,255,221,4,252,234,221,4,199,255,252,242,15,16,4,199,252, - 242,15,16,12,252,234,255,221,4,199,221,4,252,234,255,252,242,15,16,4,252, - 234,252,242,15,16,12,194,255,221,4,252,234,221,4,194,255,248,168,232,244, - 157,255,252,233,244,168,255,232,244,117,255,15,182,252,236,15,182,192,141, - 12,194,41,232,137,76,36,4,137,68,36,8,248,36,139,108,36,48,137,44,36,137, - 149,233,137,116,36,24,232,251,1,29,139,149,233,133,192,15,133,244,45,15,182, - 110,252,255,15,182,78,252,253,139,68,252,234,4,139,44,252,234,137,68,202, - 4,137,44,202,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36, - 171,255,252,247,208,139,4,135,199,68,202,4,237,137,4,202,139,6,15,182,204, - 15,182,232,131,198,4,193,232,16,252,255,36,171,255,15,191,192,199,68,202, - 4,237,137,4,202,255,15,191,192,252,242,15,42,192,252,242,15,17,4,202,255, - 223,70,252,254,221,28,202,255,252,242,15,16,4,199,252,242,15,17,4,202,255, - 221,4,199,221,28,202,255,252,247,208,137,68,202,4,139,6,15,182,204,15,182, - 232,131,198,4,193,232,16,252,255,36,171,255,141,76,202,12,141,68,194,4,189, - 237,137,105,252,248,248,1,137,41,131,193,8,57,193,15,134,244,1,139,6,15,182, - 204,15,182,232,131,198,4,193,232,16,252,255,36,171,255,139,106,252,248,139, - 172,253,133,233,139,173,233,139,69,4,139,109,0,137,68,202,4,137,44,202,139, - 6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,255,139,106,252, - 248,139,172,253,141,233,128,189,233,0,139,173,233,139,12,194,139,68,194,4, - 137,77,0,137,69,4,15,132,244,247,252,246,133,233,235,15,133,244,248,248,1, - 139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,248,2,129, - 232,239,129,252,248,239,15,134,244,1,252,246,129,233,235,15,132,244,1,135, - 213,141,139,233,255,232,251,1,30,137,252,234,252,233,244,1,255,252,247,208, - 139,106,252,248,139,172,253,141,233,139,12,135,139,133,233,137,8,199,64,4, - 237,252,246,133,233,235,15,133,244,248,248,1,139,6,15,182,204,15,182,232, - 131,198,4,193,232,16,252,255,36,171,248,2,252,246,129,233,235,15,132,244, - 1,128,189,233,0,15,132,244,1,137,213,137,194,141,139,233,232,251,1,30,137, - 252,234,252,233,244,1,255,139,106,252,248,255,252,242,15,16,4,199,255,139, - 172,253,141,233,139,141,233,255,252,242,15,17,1,255,221,25,255,252,247,208, - 139,106,252,248,139,172,253,141,233,139,141,233,137,65,4,139,6,15,182,204, - 15,182,232,131,198,4,193,232,16,252,255,36,171,255,141,180,253,134,233,139, - 108,36,48,131,189,233,0,15,132,244,247,137,149,233,141,20,202,137,252,233, - 232,251,1,31,139,149,233,248,1,139,6,15,182,204,15,182,232,131,198,4,193, - 232,16,252,255,36,171,255,252,247,208,139,74,252,248,139,4,135,139,108,36, - 48,137,76,36,8,137,68,36,4,137,44,36,137,149,233,137,116,36,24,232,251,1, - 32,139,149,233,15,182,78,252,253,137,4,202,199,68,202,4,237,139,6,15,182, - 204,15,182,232,131,198,4,193,232,16,252,255,36,171,255,139,108,36,48,137, - 149,233,139,139,233,59,139,233,137,116,36,24,15,131,244,251,248,1,137,193, - 37,252,255,7,0,0,193,252,233,11,137,76,36,8,61,252,255,7,0,0,15,132,244,249, - 248,2,137,44,36,137,68,36,4,232,251,1,33,139,149,233,15,182,78,252,253,137, - 4,202,199,68,202,4,237,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252, - 255,36,171,248,3,184,1,8,0,0,252,233,244,2,248,5,137,252,233,232,251,1,34, - 15,183,70,252,254,252,233,244,1,255,252,247,208,139,108,36,48,139,139,233, - 137,116,36,24,59,139,233,137,149,233,15,131,244,249,248,2,139,20,135,137, - 252,233,232,251,1,35,139,149,233,15,182,78,252,253,137,4,202,199,68,202,4, - 237,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,248,3, - 137,252,233,232,251,1,34,15,183,70,252,254,252,247,208,252,233,244,2,255, - 252,247,208,139,106,252,248,139,173,233,139,4,135,252,233,244,169,255,252, - 247,208,139,106,252,248,139,173,233,139,4,135,252,233,244,170,255,15,182, - 252,236,15,182,192,129,124,253,252,234,4,239,15,133,244,39,139,44,252,234, - 255,129,124,253,194,4,239,15,133,244,251,139,4,194,255,129,124,253,194,4, - 239,15,131,244,251,255,252,242,15,16,4,194,252,242,15,45,192,252,242,15,42, - 200,102,15,46,193,255,221,4,194,219,20,36,219,4,36,255,15,133,244,39,255, - 59,133,233,15,131,244,39,193,224,3,3,133,233,129,120,253,4,239,15,132,244, - 248,139,40,139,64,4,137,44,202,137,68,202,4,248,1,139,6,15,182,204,15,182, - 232,131,198,4,193,232,16,252,255,36,171,248,2,131,189,233,0,15,132,244,249, - 139,141,233,252,246,129,233,235,15,132,244,39,15,182,78,252,253,248,3,199, - 68,202,4,237,252,233,244,1,248,5,255,129,124,253,194,4,239,15,133,244,39, - 139,4,194,252,233,244,169,255,15,182,252,236,15,182,192,252,247,208,139,4, - 135,129,124,253,252,234,4,239,15,133,244,37,139,44,252,234,248,169,139,141, - 233,35,136,233,105,201,239,3,141,233,248,1,129,185,233,239,15,133,244,250, - 57,129,233,15,133,244,250,129,121,253,4,239,15,132,244,251,15,182,70,252, - 253,139,41,139,73,4,137,44,194,137,76,194,4,248,2,255,139,6,15,182,204,15, - 182,232,131,198,4,193,232,16,252,255,36,171,248,3,15,182,70,252,253,199,68, - 194,4,237,252,233,244,2,248,4,139,137,233,133,201,15,133,244,1,248,5,139, - 141,233,133,201,15,132,244,3,252,246,129,233,235,15,133,244,3,252,233,244, - 37,255,15,182,252,236,15,182,192,129,124,253,252,234,4,239,15,133,244,38, - 139,44,252,234,59,133,233,15,131,244,38,193,224,3,3,133,233,129,120,253,4, - 239,15,132,244,248,139,40,139,64,4,137,44,202,137,68,202,4,248,1,139,6,15, - 182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,248,2,131,189,233, - 0,15,132,244,249,139,141,233,252,246,129,233,235,15,132,244,38,255,15,182, - 78,252,253,248,3,199,68,202,4,237,252,233,244,1,255,15,182,252,236,15,182, - 192,129,124,253,252,234,4,239,15,133,244,42,139,44,252,234,255,15,133,244, - 42,255,59,133,233,15,131,244,42,193,224,3,3,133,233,129,120,253,4,239,15, - 132,244,249,248,1,252,246,133,233,235,15,133,244,253,248,2,139,108,202,4, - 139,12,202,137,104,4,137,8,139,6,15,182,204,15,182,232,131,198,4,193,232, - 16,252,255,36,171,248,3,131,189,233,0,15,132,244,1,139,141,233,252,246,129, - 233,235,255,15,132,244,42,15,182,78,252,253,252,233,244,1,248,5,129,124,253, - 194,4,239,15,133,244,42,139,4,194,252,233,244,170,248,7,128,165,233,235,139, - 139,233,137,171,233,137,141,233,15,182,78,252,253,252,233,244,2,255,15,182, - 252,236,15,182,192,252,247,208,139,4,135,129,124,253,252,234,4,239,15,133, - 244,40,139,44,252,234,248,170,139,141,233,35,136,233,105,201,239,198,133, - 233,0,3,141,233,248,1,129,185,233,239,15,133,244,251,57,129,233,15,133,244, - 251,129,121,253,4,239,15,132,244,250,248,2,255,252,246,133,233,235,15,133, - 244,253,248,3,15,182,70,252,253,139,108,194,4,139,4,194,137,105,4,137,1,139, - 6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,248,4,131,189, - 233,0,15,132,244,2,137,76,36,16,139,141,233,252,246,129,233,235,15,132,244, - 40,139,76,36,16,252,233,244,2,248,5,139,137,233,133,201,15,133,244,1,255, - 139,141,233,133,201,15,132,244,252,252,246,129,233,235,15,132,244,40,248, - 6,137,68,36,16,199,68,36,20,237,137,108,36,12,141,68,36,16,137,108,36,4,139, - 108,36,48,137,68,36,8,137,44,36,137,149,233,137,116,36,24,232,251,1,36,139, - 149,233,139,108,36,12,137,193,252,233,244,2,248,7,128,165,233,235,139,131, - 233,137,171,233,137,133,233,252,233,244,3,255,15,182,252,236,15,182,192,129, - 124,253,252,234,4,239,15,133,244,41,139,44,252,234,59,133,233,15,131,244, - 41,193,224,3,3,133,233,129,120,253,4,239,15,132,244,249,248,1,252,246,133, - 233,235,15,133,244,253,248,2,139,108,202,4,139,12,202,137,104,4,137,8,139, - 6,15,182,204,15,182,232,131,198,4,193,232,16,252,255,36,171,248,3,131,189, - 233,0,15,132,244,1,255,139,141,233,252,246,129,233,235,15,132,244,41,15,182, - 78,252,253,252,233,244,1,248,7,128,165,233,235,139,139,233,137,171,233,137, - 141,233,15,182,78,252,253,252,233,244,2,255,137,124,36,16,139,60,199,248, - 1,141,12,202,139,105,252,248,252,246,133,233,235,15,133,244,253,248,2,139, - 68,36,20,131,232,1,15,132,244,250,1,252,248,59,133,233,15,135,244,251,41, - 252,248,193,231,3,3,189,233,248,3,139,41,137,47,139,105,4,131,193,8,137,111, - 4,131,199,8,131,232,1,15,133,244,3,248,4,139,124,36,16,139,6,15,182,204,15, - 182,232,131,198,4,193,232,16,252,255,36,171,248,5,137,108,36,4,139,108,36, - 48,137,149,233,137,68,36,8,137,44,36,137,116,36,24,232,251,1,37,139,149,233, - 15,182,78,252,253,252,233,244,1,248,7,255,128,165,233,235,139,131,233,137, - 171,233,137,133,233,252,233,244,2,255,3,68,36,20,255,129,124,253,202,4,239, - 139,44,202,15,133,244,59,141,84,202,8,137,114,252,252,139,181,233,139,14, - 15,182,252,233,15,182,205,131,198,4,252,255,36,171,255,141,76,202,8,137,215, - 139,105,252,248,129,121,253,252,252,239,15,133,244,29,248,60,139,114,252, - 252,252,247,198,237,15,133,244,253,248,1,137,106,252,248,137,68,36,20,131, - 232,1,15,132,244,249,248,2,139,41,137,47,139,105,4,131,193,8,137,111,4,131, - 199,8,131,232,1,15,133,244,2,139,106,252,248,248,3,139,68,36,20,128,189,233, - 1,15,135,244,251,248,4,139,181,233,139,14,15,182,252,233,15,182,205,131,198, - 4,252,255,36,171,248,5,255,252,247,198,237,15,133,244,4,15,182,78,252,253, - 252,247,209,141,12,202,139,121,252,248,139,191,233,139,191,233,252,233,244, - 4,248,7,129,252,238,239,252,247,198,237,15,133,244,254,41,252,242,137,215, - 139,114,252,252,252,233,244,1,248,8,129,198,239,252,233,244,1,255,141,76, - 202,8,139,105,232,139,65,252,236,137,41,137,65,4,139,105,252,240,139,65,252, - 244,137,105,8,137,65,12,139,105,224,139,65,228,137,105,252,248,137,65,252, - 252,129,252,248,239,184,237,15,133,244,29,137,202,137,114,252,252,139,181, - 233,139,14,15,182,252,233,15,182,205,131,198,4,252,255,36,171,255,137,124, - 36,16,137,92,36,20,139,108,202,252,240,139,68,202,252,248,139,157,233,131, - 198,4,139,189,233,248,1,57,216,15,131,244,251,129,124,253,199,4,239,15,132, - 244,250,255,219,68,202,252,248,255,139,108,199,4,137,108,202,12,139,44,199, - 137,108,202,8,131,192,1,255,137,68,202,252,248,248,2,15,183,70,252,254,141, - 180,253,134,233,248,3,139,92,36,20,139,124,36,16,139,6,15,182,204,15,182, - 232,131,198,4,193,232,16,252,255,36,171,248,4,131,192,1,255,137,68,202,252, - 248,255,252,233,244,1,248,5,41,216,248,6,59,133,233,15,135,244,3,105,252, - 248,239,3,189,233,129,191,233,239,15,132,244,253,141,92,24,1,139,175,233, - 139,135,233,137,44,202,137,68,202,4,139,175,233,139,135,233,137,108,202,8, - 137,68,202,12,137,92,202,252,248,252,233,244,2,248,7,255,131,192,1,252,233, - 244,6,255,129,124,253,202,252,236,239,15,133,244,251,139,108,202,232,129, - 124,253,202,252,244,239,15,133,244,251,129,124,253,202,252,252,239,15,133, - 244,251,128,189,233,235,15,133,244,251,141,180,253,134,233,199,68,202,252, - 248,0,0,0,0,248,1,139,6,15,182,204,15,182,232,131,198,4,193,232,16,252,255, - 36,171,248,5,198,70,252,252,235,141,180,253,134,233,198,6,235,252,233,244, - 1,255,15,182,252,236,15,182,192,137,124,36,16,141,188,253,194,233,141,12, - 202,43,122,252,252,133,252,237,15,132,244,251,141,108,252,233,252,248,57, - 215,15,131,244,248,248,1,139,71,252,248,137,1,139,71,252,252,131,199,8,137, - 65,4,131,193,8,57,252,233,15,131,244,249,57,215,15,130,244,1,248,2,199,65, - 4,237,131,193,8,57,252,233,15,130,244,2,248,3,139,124,36,16,139,6,15,182, - 204,15,182,232,131,198,4,193,232,16,252,255,36,171,248,5,199,68,36,20,1,0, - 0,0,137,208,41,252,248,15,134,244,3,137,197,193,252,237,3,131,197,1,137,108, - 36,20,139,108,36,48,1,200,59,133,233,15,135,244,253,248,6,255,139,71,252, - 248,137,1,139,71,252,252,131,199,8,137,65,4,131,193,8,57,215,15,130,244,6, - 252,233,244,3,248,7,137,149,233,137,141,233,137,116,36,24,41,215,139,84,36, - 20,131,252,234,1,137,252,233,232,251,1,0,139,149,233,139,141,233,1,215,252, - 233,244,6,255,193,225,3,255,248,1,139,114,252,252,137,68,36,20,252,247,198, - 237,15,133,244,253,255,248,13,137,215,131,232,1,15,132,244,249,248,2,139, - 44,15,137,111,252,248,139,108,15,4,137,111,252,252,131,199,8,131,232,1,15, - 133,244,2,248,3,139,68,36,20,15,182,110,252,255,248,5,57,197,15,135,244,252, - 255,139,108,10,4,137,106,252,252,139,44,10,137,106,252,248,255,248,5,56,70, - 252,255,15,135,244,252,255,15,182,78,252,253,252,247,209,141,20,202,139,122, - 252,248,139,191,233,139,191,233,139,6,15,182,204,15,182,232,131,198,4,193, - 232,16,252,255,36,171,248,6,255,199,71,252,252,237,131,199,8,255,199,68,194, - 252,244,237,255,131,192,1,252,233,244,5,248,7,141,174,233,252,247,197,237, - 15,133,244,14,41,252,234,255,1,252,233,255,137,252,245,209,252,237,129,229, - 239,102,129,172,253,43,233,238,15,130,244,149,255,141,12,202,255,129,121, - 253,4,239,15,133,244,255,255,129,121,253,12,239,15,133,244,61,129,121,253, - 20,239,15,133,244,61,139,41,131,121,16,0,15,140,244,251,255,129,121,253,12, - 239,15,133,244,165,129,121,253,20,239,15,133,244,165,255,139,105,16,133,252, - 237,15,136,244,251,3,41,15,128,244,247,137,41,255,59,105,8,199,65,28,237, - 137,105,24,255,15,142,244,253,248,1,248,6,141,180,253,134,233,255,141,180, - 253,134,233,15,183,70,252,254,15,142,245,248,1,248,6,255,15,143,244,253,248, - 6,141,180,253,134,233,248,1,255,248,7,139,6,15,182,204,15,182,232,131,198, - 4,193,232,16,252,255,36,171,248,5,255,3,41,15,128,244,1,137,41,255,15,141, - 244,7,255,141,180,253,134,233,15,183,70,252,254,15,141,245,255,15,140,244, - 7,255,252,233,244,6,248,9,255,129,121,253,4,239,255,15,131,244,61,129,121, - 253,12,239,15,131,244,61,255,129,121,253,12,239,15,131,244,165,129,121,253, - 20,239,15,131,244,165,255,139,105,20,255,129,252,253,239,15,131,244,61,255, - 252,242,15,16,1,252,242,15,16,73,8,255,252,242,15,88,65,16,252,242,15,17, - 1,133,252,237,15,136,244,249,255,15,140,244,249,255,102,15,46,200,248,1,252, - 242,15,17,65,24,255,221,65,8,221,1,255,220,65,16,221,17,221,81,24,133,252, - 237,15,136,244,247,255,221,81,24,15,140,244,247,255,217,201,248,1,255,15, - 183,70,252,254,255,15,131,244,7,255,15,131,244,248,141,180,253,134,233,255, - 141,180,253,134,233,15,183,70,252,254,15,131,245,255,15,130,244,7,255,15, - 130,244,248,141,180,253,134,233,255,248,3,102,15,46,193,252,233,244,1,255, - 141,12,202,139,105,4,129,252,253,239,15,132,244,247,255,137,105,252,252,139, - 41,137,105,252,248,252,233,245,255,141,180,253,134,233,139,1,137,105,252, - 252,137,65,252,248,255,139,139,233,139,4,129,139,128,233,139,108,36,48,137, - 147,233,137,171,233,252,255,224,255,141,180,253,134,233,139,6,15,182,204, - 15,182,232,131,198,4,193,232,16,252,255,36,171,255,137,252,245,209,252,237, - 129,229,239,102,129,172,253,43,233,238,15,130,244,151,255,139,190,233,139, - 108,36,48,141,12,202,59,141,233,15,135,244,24,15,182,142,233,57,200,15,134, - 244,249,248,2,255,15,183,70,252,254,252,233,245,255,248,3,199,68,194,252, - 252,237,131,192,1,57,200,15,134,244,3,252,233,244,2,255,141,44,197,237,141, - 4,194,139,122,252,248,137,104,252,252,137,120,252,248,139,108,36,48,141,12, - 200,59,141,233,15,135,244,23,137,209,137,194,15,182,174,233,133,252,237,15, - 132,244,248,248,1,131,193,8,57,209,15,131,244,249,139,121,252,248,137,56, - 139,121,252,252,137,120,4,131,192,8,199,65,252,252,237,131,252,237,1,15,133, - 244,1,248,2,255,139,190,233,139,6,15,182,204,15,182,232,131,198,4,193,232, - 16,252,255,36,171,255,248,3,199,64,4,237,131,192,8,131,252,237,1,15,133,244, - 3,252,233,244,2,255,139,106,252,248,139,189,233,139,108,36,48,141,68,194, - 252,248,137,149,233,141,136,233,59,141,233,137,133,233,255,137,44,36,255, - 137,124,36,4,137,44,36,255,15,135,244,22,199,131,233,237,255,252,255,215, - 255,252,255,147,233,255,199,131,233,237,139,149,233,141,12,194,252,247,217, - 3,141,233,139,114,252,252,252,233,244,12,255,254,0 -}; - -enum { - GLOB_vm_returnp, - GLOB_cont_dispatch, - GLOB_vm_returnc, - GLOB_BC_RET_Z, - GLOB_vm_return, - GLOB_vm_leave_cp, - GLOB_vm_leave_unw, - GLOB_vm_unwind_c, - GLOB_vm_unwind_c_eh, - GLOB_vm_unwind_rethrow, - GLOB_vm_unwind_ff, - GLOB_vm_unwind_ff_eh, - GLOB_vm_growstack_c, - GLOB_vm_growstack_v, - GLOB_vm_growstack_f, - GLOB_vm_resume, - GLOB_vm_pcall, - GLOB_vm_call, - GLOB_vm_call_dispatch, - GLOB_vmeta_call, - GLOB_vm_call_dispatch_f, - GLOB_vm_cpcall, - GLOB_cont_ffi_callback, - GLOB_vm_call_tail, - GLOB_cont_cat, - GLOB_cont_ra, - GLOB_BC_CAT_Z, - GLOB_vmeta_tgets, - GLOB_vmeta_tgetb, - GLOB_vmeta_tgetv, - GLOB_vmeta_tsets, - GLOB_vmeta_tsetb, - GLOB_vmeta_tsetv, - GLOB_cont_nop, - GLOB_vmeta_comp, - GLOB_vmeta_binop, - GLOB_cont_condt, - GLOB_cont_condf, - GLOB_vmeta_equal, - GLOB_vmeta_equal_cd, - GLOB_vmeta_arith_vno, - GLOB_vmeta_arith_vn, - GLOB_vmeta_arith_nvo, - GLOB_vmeta_arith_nv, - GLOB_vmeta_unm, - GLOB_vmeta_arith_vvo, - GLOB_vmeta_arith_vv, - GLOB_vmeta_len, - GLOB_BC_LEN_Z, - GLOB_vmeta_call_ra, - GLOB_BC_CALLT_Z, - GLOB_vmeta_for, - GLOB_ff_assert, - GLOB_fff_fallback, - GLOB_fff_res_, - GLOB_ff_type, - GLOB_fff_res1, - GLOB_ff_getmetatable, - GLOB_ff_setmetatable, - GLOB_ff_rawget, - GLOB_ff_tonumber, - GLOB_fff_resi, - GLOB_fff_resxmm0, - GLOB_fff_resn, - GLOB_ff_tostring, - GLOB_fff_gcstep, - GLOB_ff_next, - GLOB_fff_res2, - GLOB_fff_res, - GLOB_ff_pairs, - GLOB_ff_ipairs_aux, - GLOB_fff_res0, - GLOB_ff_ipairs, - GLOB_ff_pcall, - GLOB_ff_xpcall, - GLOB_ff_coroutine_resume, - GLOB_ff_coroutine_wrap_aux, - GLOB_ff_coroutine_yield, - GLOB_ff_math_abs, - GLOB_fff_resbit, - GLOB_ff_math_floor, - GLOB_vm_floor, - GLOB_ff_math_ceil, - GLOB_vm_ceil, - GLOB_ff_math_sqrt, - GLOB_ff_math_log, - GLOB_ff_math_log10, - GLOB_ff_math_exp, - GLOB_vm_exp_x87, - GLOB_ff_math_sin, - GLOB_ff_math_cos, - GLOB_ff_math_tan, - GLOB_ff_math_asin, - GLOB_ff_math_acos, - GLOB_ff_math_atan, - GLOB_ff_math_sinh, - GLOB_ff_math_cosh, - GLOB_ff_math_tanh, - GLOB_ff_math_deg, - GLOB_ff_math_rad, - GLOB_ff_math_atan2, - GLOB_ff_math_ldexp, - GLOB_ff_math_frexp, - GLOB_ff_math_modf, - GLOB_vm_trunc, - GLOB_ff_math_fmod, - GLOB_ff_math_pow, - GLOB_vm_pow, - GLOB_ff_math_min, - GLOB_ff_math_max, - GLOB_ff_string_len, - GLOB_ff_string_byte, - GLOB_ff_string_char, - GLOB_fff_newstr, - GLOB_ff_string_sub, - GLOB_fff_emptystr, - GLOB_ff_string_rep, - GLOB_fff_fallback_2, - GLOB_ff_string_reverse, - GLOB_fff_fallback_1, - GLOB_ff_string_lower, - GLOB_ff_string_upper, - GLOB_ff_table_getn, - GLOB_ff_bit_tobit, - GLOB_ff_bit_band, - GLOB_fff_fallback_bit_op, - GLOB_ff_bit_bor, - GLOB_ff_bit_bxor, - GLOB_ff_bit_bswap, - GLOB_ff_bit_bnot, - GLOB_ff_bit_lshift, - GLOB_ff_bit_rshift, - GLOB_ff_bit_arshift, - GLOB_ff_bit_rol, - GLOB_ff_bit_ror, - GLOB_vm_record, - GLOB_vm_rethook, - GLOB_vm_inshook, - GLOB_cont_hook, - GLOB_vm_hotloop, - GLOB_vm_callhook, - GLOB_vm_hotcall, - GLOB_vm_exit_handler, - GLOB_vm_exit_interp, - GLOB_vm_floor_sse, - GLOB_vm_ceil_sse, - GLOB_vm_trunc_sse, - GLOB_vm_mod, - GLOB_vm_exp2_x87, - GLOB_vm_exp2raw, - GLOB_vm_pow_sse, - GLOB_vm_powi_sse, - GLOB_vm_foldfpm, - GLOB_vm_foldarith, - GLOB_vm_cpuid, - GLOB_assert_bad_for_arg_type, - GLOB_vm_ffi_callback, - GLOB_vm_ffi_call, - GLOB_BC_MODVN_Z, - GLOB_BC_TGETS_Z, - GLOB_BC_TSETS_Z, - GLOB__MAX -}; -static const char *const globnames[] = { - "vm_returnp", - "cont_dispatch", - "vm_returnc", - "BC_RET_Z", - "vm_return", - "vm_leave_cp", - "vm_leave_unw", - "vm_unwind_c@8", - "vm_unwind_c_eh", - "vm_unwind_rethrow", - "vm_unwind_ff@4", - "vm_unwind_ff_eh", - "vm_growstack_c", - "vm_growstack_v", - "vm_growstack_f", - "vm_resume", - "vm_pcall", - "vm_call", - "vm_call_dispatch", - "vmeta_call", - "vm_call_dispatch_f", - "vm_cpcall", - "cont_ffi_callback", - "vm_call_tail", - "cont_cat", - "cont_ra", - "BC_CAT_Z", - "vmeta_tgets", - "vmeta_tgetb", - "vmeta_tgetv", - "vmeta_tsets", - "vmeta_tsetb", - "vmeta_tsetv", - "cont_nop", - "vmeta_comp", - "vmeta_binop", - "cont_condt", - "cont_condf", - "vmeta_equal", - "vmeta_equal_cd", - "vmeta_arith_vno", - "vmeta_arith_vn", - "vmeta_arith_nvo", - "vmeta_arith_nv", - "vmeta_unm", - "vmeta_arith_vvo", - "vmeta_arith_vv", - "vmeta_len", - "BC_LEN_Z", - "vmeta_call_ra", - "BC_CALLT_Z", - "vmeta_for", - "ff_assert", - "fff_fallback", - "fff_res_", - "ff_type", - "fff_res1", - "ff_getmetatable", - "ff_setmetatable", - "ff_rawget", - "ff_tonumber", - "fff_resi", - "fff_resxmm0", - "fff_resn", - "ff_tostring", - "fff_gcstep", - "ff_next", - "fff_res2", - "fff_res", - "ff_pairs", - "ff_ipairs_aux", - "fff_res0", - "ff_ipairs", - "ff_pcall", - "ff_xpcall", - "ff_coroutine_resume", - "ff_coroutine_wrap_aux", - "ff_coroutine_yield", - "ff_math_abs", - "fff_resbit", - "ff_math_floor", - "vm_floor", - "ff_math_ceil", - "vm_ceil", - "ff_math_sqrt", - "ff_math_log", - "ff_math_log10", - "ff_math_exp", - "vm_exp_x87", - "ff_math_sin", - "ff_math_cos", - "ff_math_tan", - "ff_math_asin", - "ff_math_acos", - "ff_math_atan", - "ff_math_sinh", - "ff_math_cosh", - "ff_math_tanh", - "ff_math_deg", - "ff_math_rad", - "ff_math_atan2", - "ff_math_ldexp", - "ff_math_frexp", - "ff_math_modf", - "vm_trunc", - "ff_math_fmod", - "ff_math_pow", - "vm_pow", - "ff_math_min", - "ff_math_max", - "ff_string_len", - "ff_string_byte", - "ff_string_char", - "fff_newstr", - "ff_string_sub", - "fff_emptystr", - "ff_string_rep", - "fff_fallback_2", - "ff_string_reverse", - "fff_fallback_1", - "ff_string_lower", - "ff_string_upper", - "ff_table_getn", - "ff_bit_tobit", - "ff_bit_band", - "fff_fallback_bit_op", - "ff_bit_bor", - "ff_bit_bxor", - "ff_bit_bswap", - "ff_bit_bnot", - "ff_bit_lshift", - "ff_bit_rshift", - "ff_bit_arshift", - "ff_bit_rol", - "ff_bit_ror", - "vm_record", - "vm_rethook", - "vm_inshook", - "cont_hook", - "vm_hotloop", - "vm_callhook", - "vm_hotcall", - "vm_exit_handler", - "vm_exit_interp", - "vm_floor_sse", - "vm_ceil_sse", - "vm_trunc_sse", - "vm_mod", - "vm_exp2_x87", - "vm_exp2raw", - "vm_pow_sse", - "vm_powi_sse", - "vm_foldfpm", - "vm_foldarith", - "vm_cpuid", - "assert_bad_for_arg_type", - "vm_ffi_callback", - "vm_ffi_call@4", - "BC_MODVN_Z", - "BC_TGETS_Z", - "BC_TSETS_Z", - (const char *)0 -}; -static const char *const extnames[] = { - "lj_state_growstack@8", - "lj_meta_tget", - "lj_meta_tset", - "lj_meta_comp", - "lj_meta_equal", - "lj_meta_equal_cd@8", - "lj_meta_arith", - "lj_meta_len@8", - "lj_meta_call", - "lj_meta_for@8", - "lj_tab_get", - "lj_str_fromnumber@8", - "lj_str_fromnum@8", - "lj_tab_next", - "lj_tab_getinth@8", - "lj_ffh_coroutine_wrap_err@8", - "lj_vm_sinh", - "lj_vm_cosh", - "lj_vm_tanh", - "lj_str_new", - "lj_tab_len@4", - "lj_gc_step@4", - "lj_dispatch_ins@8", - "lj_trace_hot@8", - "lj_dispatch_call@8", - "lj_trace_exit@8", - "lj_err_throw@8", - "lj_ccallback_enter@8", - "lj_ccallback_leave@8", - "lj_meta_cat", - "lj_gc_barrieruv@8", - "lj_func_closeuv@8", - "lj_func_newL_gc", - "lj_tab_new", - "lj_gc_step_fixtop@4", - "lj_tab_dup@8", - "lj_tab_newkey", - "lj_tab_reasize", - (const char *)0 -}; -#define Dt1(_V) (int)(ptrdiff_t)&(((lua_State *)0)_V) -#define Dt2(_V) (int)(ptrdiff_t)&(((global_State *)0)_V) -#define Dt3(_V) (int)(ptrdiff_t)&(((TValue *)0)_V) -#define Dt4(_V) (int)(ptrdiff_t)&(((GCobj *)0)_V) -#define Dt5(_V) (int)(ptrdiff_t)&(((GCstr *)0)_V) -#define Dt6(_V) (int)(ptrdiff_t)&(((GCtab *)0)_V) -#define Dt7(_V) (int)(ptrdiff_t)&(((GCfuncL *)0)_V) -#define Dt8(_V) (int)(ptrdiff_t)&(((GCfuncC *)0)_V) -#define Dt9(_V) (int)(ptrdiff_t)&(((GCproto *)0)_V) -#define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V) -#define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V) -#define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V) -#define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V) -#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) -#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) -#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) - -/* Generate subroutines used by opcodes and other parts of the VM. */ -/* The .code_sub section should be last to help static branch prediction. */ -static void build_subroutines(BuildCtx *ctx, int cmov, int sse) -{ - dasm_put(Dst, 0); - dasm_put(Dst, 2, FRAME_P, LJ_TTRUE, FRAME_TYPE, FRAME_C, FRAME_TYPE, DISPATCH_GL(vmstate), ~LJ_VMST_C); - dasm_put(Dst, 114, Dt1(->base), Dt1(->top), Dt1(->cframe), Dt1(->maxstack), LJ_TNIL); - dasm_put(Dst, 200, Dt1(->top), Dt1(->top), Dt1(->glref), Dt2(->vmstate), ~LJ_VMST_C, CFRAME_RAWMASK); - dasm_put(Dst, 275, 1+1, Dt1(->base), Dt1(->glref), GG_G2DISP, LJ_TFALSE, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, LUA_MINSTACK, -4+PC2PROTO(framesize), Dt1(->base)); - dasm_put(Dst, 353, Dt1(->top), Dt1(->base), Dt1(->top), Dt7(->pc), FRAME_CP, CFRAME_RESUME, Dt1(->glref), GG_G2DISP, Dt1(->cframe), Dt1(->status), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->status), Dt1(->base), Dt1(->top), FRAME_TYPE); - dasm_put(Dst, 495, FRAME_CP, FRAME_C, Dt1(->cframe), Dt1(->cframe), Dt1(->glref), GG_G2DISP, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base)); - dasm_put(Dst, 573, Dt1(->top), LJ_TFUNC, Dt7(->pc), Dt1(->stack), Dt1(->top), Dt1(->cframe), Dt1(->cframe), FRAME_CP, LJ_TNIL); -#if LJ_HASFFI -#endif - dasm_put(Dst, 743); -#if LJ_HASFFI - dasm_put(Dst, 748); -#endif - dasm_put(Dst, 757, Dt7(->pc), PC2PROTO(k)); -#if LJ_HASFFI - dasm_put(Dst, 771); -#endif - dasm_put(Dst, 792, LJ_TSTR, BC_GGET, DISPATCH_GL(tmptv), LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 890, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 900); - } else { - dasm_put(Dst, 913); - } - dasm_put(Dst, 926, Dt1(->base), Dt1(->base), Dt1(->top), FRAME_CONT, 2+1, LJ_TSTR, BC_GSET); - dasm_put(Dst, 1078, DISPATCH_GL(tmptv), LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 890, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 900); - } else { - dasm_put(Dst, 913); - } - dasm_put(Dst, 1101, Dt1(->base), Dt1(->base), Dt1(->top), FRAME_CONT, 3+1, Dt1(->base), Dt1(->base)); - dasm_put(Dst, 1295, -BCBIAS_J*4, LJ_TISTRUECOND, LJ_TISTRUECOND, Dt1(->base)); - dasm_put(Dst, 1402); -#if LJ_HASFFI - dasm_put(Dst, 1417, Dt1(->base)); -#endif - dasm_put(Dst, 1448); -#if LJ_DUALNUM - dasm_put(Dst, 1451); -#endif - dasm_put(Dst, 1457); -#if LJ_DUALNUM - dasm_put(Dst, 884); -#endif - dasm_put(Dst, 1469); -#if LJ_DUALNUM - dasm_put(Dst, 1451); -#endif - dasm_put(Dst, 1497, Dt1(->base), Dt1(->base), FRAME_CONT, 2+1, Dt1(->base), Dt1(->base)); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 1607); -#else - dasm_put(Dst, 1626); -#endif - dasm_put(Dst, 1631, Dt1(->base), Dt1(->base), Dt7(->pc), Dt1(->base), Dt1(->base), GG_DISP2STATIC, 1+1, LJ_TISTRUECOND); - dasm_put(Dst, 1820, 1+1, ~LJ_TNUMX); - if (cmov) { - dasm_put(Dst, 1878); - } else { - dasm_put(Dst, 1882); - } - dasm_put(Dst, 1891, ((char *)(&((GCfuncC *)0)->upvalue)), LJ_TSTR, 1+1, LJ_TTAB, Dt6(->metatable), LJ_TNIL, DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable), LJ_TTAB); - dasm_put(Dst, 1974, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), DtB(->next), LJ_TNIL); - dasm_put(Dst, 2032, LJ_TUDATA, LJ_TISNUM, LJ_TNUMX, DISPATCH_GL(gcroot[GCROOT_BASEMT]), 2+1); - dasm_put(Dst, 2095, LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->marked), LJ_GC_BLACK, Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - dasm_put(Dst, 2167, 2+1, LJ_TTAB, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 2256); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 2278); - } else { - dasm_put(Dst, 2288); - } - dasm_put(Dst, 2295, 1+1, LJ_TSTR, LJ_TSTR, LJ_TISNUM, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM]), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 2361, Dt1(->base)); - if (LJ_DUALNUM) { - dasm_put(Dst, 2385); - } else { - dasm_put(Dst, 2390); - } - dasm_put(Dst, 2395, Dt1(->base), 1+1, LJ_TTAB, Dt1(->base), Dt1(->top), Dt1(->base), 1+2); - dasm_put(Dst, 2504, LJ_TNIL, LJ_TNIL, 1+1, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 2551, Dt6(->metatable)); -#endif - dasm_put(Dst, 2560, Dt8(->upvalue[0]), LJ_TFUNC, LJ_TNIL, 1+3, 1+1, LJ_TTAB, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 2546); - } else { - dasm_put(Dst, 2273); - } - dasm_put(Dst, 2615); - if (LJ_DUALNUM) { - dasm_put(Dst, 2620, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 2636); - } else { - dasm_put(Dst, 2675); - } - dasm_put(Dst, 2693, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->hmask), 1+0); - dasm_put(Dst, 2531, 1+1, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 2551, Dt6(->metatable)); -#endif - dasm_put(Dst, 2774, Dt8(->upvalue[0]), LJ_TFUNC); - if (LJ_DUALNUM) { - dasm_put(Dst, 2795, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 2807); - } else { - dasm_put(Dst, 2817); - } - dasm_put(Dst, 2824, 1+3, 1+1, 8+FRAME_PCALL, DISPATCH_GL(hookmask), HOOK_ACTIVE_SHIFT, 2+1, LJ_TFUNC); - dasm_put(Dst, 2888, LJ_TFUNC, 16+FRAME_PCALL, 1+1, LJ_TTHREAD, Dt1(->cframe), Dt1(->status), LUA_YIELD, Dt1(->top)); - dasm_put(Dst, 2976, Dt1(->base), Dt1(->maxstack), Dt1(->top), Dt1(->base), Dt1(->top), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP); - dasm_put(Dst, 3077, Dt1(->base), LUA_YIELD, Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->maxstack), LJ_TTRUE, FRAME_TYPE); - dasm_put(Dst, 3191, LJ_TFALSE, Dt1(->top), Dt1(->top), 1+2, Dt1(->top), Dt1(->base), Dt8(->upvalue[0].gcr), Dt1(->cframe)); - dasm_put(Dst, 3289, Dt1(->status), LUA_YIELD, Dt1(->top), Dt1(->base), Dt1(->maxstack), Dt1(->top), Dt1(->base), Dt1(->top)); - dasm_put(Dst, 3355, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base), LUA_YIELD, Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->maxstack)); - dasm_put(Dst, 3456, FRAME_TYPE, Dt1(->top), Dt1(->base), Dt1(->cframe), CFRAME_RESUME); - dasm_put(Dst, 3569, Dt1(->base), Dt1(->top), Dt1(->cframe), LUA_YIELD, Dt1(->status)); - if (!LJ_DUALNUM) { - dasm_put(Dst, 3595); - } - if (sse) { - dasm_put(Dst, 3598); - } - dasm_put(Dst, 3613, 1+1); - if (LJ_DUALNUM) { - dasm_put(Dst, 3624, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 3704, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 3714); - } else { - dasm_put(Dst, 3750); - } - dasm_put(Dst, 3767, 1+1, FRAME_TYPE, LJ_TNIL); - if (LJ_DUALNUM) { - dasm_put(Dst, 3859, LJ_TISNUM); - } else { - dasm_put(Dst, 3704, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 3881); - if (LJ_DUALNUM) { - dasm_put(Dst, 3890); - } - dasm_put(Dst, 2283); - } else { - dasm_put(Dst, 3924); - if (LJ_DUALNUM) { - dasm_put(Dst, 3930); - if (cmov) { - dasm_put(Dst, 3953); - } else { - dasm_put(Dst, 3959); - } - dasm_put(Dst, 3966); - } else { - dasm_put(Dst, 2290); - } - } - dasm_put(Dst, 3983); - if (LJ_DUALNUM) { - dasm_put(Dst, 3859, LJ_TISNUM); - } else { - dasm_put(Dst, 3704, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 3986); - if (LJ_DUALNUM) { - dasm_put(Dst, 3890); - } - dasm_put(Dst, 2283); - } else { - dasm_put(Dst, 3995); - if (LJ_DUALNUM) { - dasm_put(Dst, 3930); - if (cmov) { - dasm_put(Dst, 3953); - } else { - dasm_put(Dst, 3959); - } - dasm_put(Dst, 3966); - } else { - dasm_put(Dst, 2290); - } - } - if (sse) { - dasm_put(Dst, 4001, 1+1, LJ_TISNUM); - } else { - dasm_put(Dst, 4030, 1+1, LJ_TISNUM); - } - dasm_put(Dst, 4059, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1); - dasm_put(Dst, 4128, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1); - dasm_put(Dst, 4185, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1); - dasm_put(Dst, 4248, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM); - dasm_put(Dst, 4338); - if (sse) { - dasm_put(Dst, 4350, 1+1, LJ_TISNUM); - } else { - dasm_put(Dst, 4381, 1+1, LJ_TISNUM); - } - dasm_put(Dst, 4406); - if (sse) { - dasm_put(Dst, 4420, 1+1, LJ_TISNUM); - } else { - dasm_put(Dst, 4451, 1+1, LJ_TISNUM); - } - dasm_put(Dst, 4476); - if (sse) { - dasm_put(Dst, 4490, 1+1, LJ_TISNUM); - } else { - dasm_put(Dst, 4521, 1+1, LJ_TISNUM); - } - dasm_put(Dst, 4546); - if (sse) { - dasm_put(Dst, 4562, 1+1, LJ_TISNUM, Dt8(->upvalue[0])); - } else { - dasm_put(Dst, 4601, 1+1, LJ_TISNUM, Dt8(->upvalue[0])); - } - dasm_put(Dst, 4634, 2+1, LJ_TISNUM, LJ_TISNUM, 2+1, LJ_TISNUM, LJ_TISNUM); - dasm_put(Dst, 4699, 1+1, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4798); - } else { - dasm_put(Dst, 4804); - } - dasm_put(Dst, 4813); - if (sse) { - dasm_put(Dst, 4838); - } else { - dasm_put(Dst, 4844); - } - dasm_put(Dst, 4847, 1+2); - if (sse) { - dasm_put(Dst, 4856); - } else { - dasm_put(Dst, 4864); - } - dasm_put(Dst, 4872); - if (sse) { - dasm_put(Dst, 4875); - } else { - dasm_put(Dst, 4907); - } - dasm_put(Dst, 4926); - if (sse) { - dasm_put(Dst, 4942, 1+1, LJ_TISNUM); - } else { - dasm_put(Dst, 4967, 1+1, LJ_TISNUM); - } - dasm_put(Dst, 4989); - if (sse) { - dasm_put(Dst, 5011); - } else { - dasm_put(Dst, 5037); - } - dasm_put(Dst, 5054, 1+2); - if (sse) { - dasm_put(Dst, 5094); - } else { - dasm_put(Dst, 5102); - } - dasm_put(Dst, 5112, 2+1, LJ_TISNUM, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 5164, 2+1, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 5211, 2+1, LJ_TISNUM, LJ_TISNUM); - } - dasm_put(Dst, 5252, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5265, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4798); - } else { - dasm_put(Dst, 4804); - } - dasm_put(Dst, 5315); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 5326, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5347); - } else { - dasm_put(Dst, 2273); - } - dasm_put(Dst, 5368); - } else { - dasm_put(Dst, 5393, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5411); - } else { - dasm_put(Dst, 5429); - } - dasm_put(Dst, 5434); - if (cmov) { - dasm_put(Dst, 5444); - } else { - dasm_put(Dst, 5452); - } - dasm_put(Dst, 5385); - } - dasm_put(Dst, 5473, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5486, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 4798); - } else { - dasm_put(Dst, 4804); - } - dasm_put(Dst, 5315); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 5326, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5347); - } else { - dasm_put(Dst, 2273); - } - dasm_put(Dst, 5536); - } else { - dasm_put(Dst, 5393, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5411); - } else { - dasm_put(Dst, 5429); - } - dasm_put(Dst, 5434); - if (cmov) { - dasm_put(Dst, 5561); - } else { - dasm_put(Dst, 5569); - } - dasm_put(Dst, 5385); - } - if (!sse) { - dasm_put(Dst, 5590); - } - dasm_put(Dst, 5599, 1+1, LJ_TSTR); - if (LJ_DUALNUM) { - dasm_put(Dst, 5621, Dt5(->len)); - } else if (sse) { - dasm_put(Dst, 5629, Dt5(->len)); - } else { - dasm_put(Dst, 5640, Dt5(->len)); - } - dasm_put(Dst, 5648, 1+1, LJ_TSTR, Dt5(->len), Dt5([1])); - if (LJ_DUALNUM) { - dasm_put(Dst, 3978); - } else if (sse) { - dasm_put(Dst, 5686); - } else { - dasm_put(Dst, 5696); - } - dasm_put(Dst, 5709, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5740); - } else if (sse) { - dasm_put(Dst, 5763); - } else { - dasm_put(Dst, 5789); - } - dasm_put(Dst, 5813, Dt1(->base), Dt1(->base), LJ_TSTR, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), 1+2, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 5916); - } else if (sse) { - dasm_put(Dst, 5928); - } else { - dasm_put(Dst, 5943); - } - dasm_put(Dst, 5955, LJ_TSTR, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 2546); - } else { - dasm_put(Dst, 2273); - } - dasm_put(Dst, 5972, Dt5(->len)); - if (LJ_DUALNUM) { - dasm_put(Dst, 5982); - } else if (sse) { - dasm_put(Dst, 5986); - } else { - dasm_put(Dst, 5993); - } - dasm_put(Dst, 6005, sizeof(GCstr)-1); - dasm_put(Dst, 6080, 2+1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold)); - dasm_put(Dst, 6139, LJ_TSTR, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6156); - } else if (sse) { - dasm_put(Dst, 6164); - } else { - dasm_put(Dst, 6175); - } - dasm_put(Dst, 6191, Dt5(->len), DISPATCH_GL(tmpbuf.sz), Dt5([1]), DISPATCH_GL(tmpbuf.buf), DISPATCH_GL(tmpbuf.buf), 1+1); - dasm_put(Dst, 6256, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf)); - dasm_put(Dst, 6319, 1+1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz)); - dasm_put(Dst, 6390, sizeof(GCstr), DISPATCH_GL(tmpbuf.buf), 1+1); - dasm_put(Dst, 6475, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR, Dt5(->len), DISPATCH_GL(tmpbuf.sz), sizeof(GCstr), DISPATCH_GL(tmpbuf.buf)); - dasm_put(Dst, 6545, 1+1, LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 6613); - } else if (sse) { - dasm_put(Dst, 6620); - } else { - dasm_put(Dst, 6630); - } - dasm_put(Dst, 6641, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6657); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6674); - } else { - dasm_put(Dst, 6703); - } - dasm_put(Dst, 111); - if (LJ_DUALNUM || sse) { - if (!sse) { - dasm_put(Dst, 6721); - } - dasm_put(Dst, 6725); - } else { - dasm_put(Dst, 6633); - } - dasm_put(Dst, 6730, 1+1); - if (sse) { - dasm_put(Dst, 6741); - } else { - dasm_put(Dst, 6756); - } - dasm_put(Dst, 2250, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6765); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6782); - } else { - dasm_put(Dst, 6797); - } - dasm_put(Dst, 6810, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6835); - } else { - dasm_put(Dst, 6855); - } - if (sse) { - dasm_put(Dst, 6860); - } else { - dasm_put(Dst, 6877); - } - dasm_put(Dst, 6890, 1+1); - if (sse) { - dasm_put(Dst, 6741); - } else { - dasm_put(Dst, 6756); - } - dasm_put(Dst, 2250, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6765); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6782); - } else { - dasm_put(Dst, 6797); - } - dasm_put(Dst, 6810, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6908); - } else { - dasm_put(Dst, 6855); - } - if (sse) { - dasm_put(Dst, 6928); - } else { - dasm_put(Dst, 6945); - } - dasm_put(Dst, 6958, 1+1); - if (sse) { - dasm_put(Dst, 6741); - } else { - dasm_put(Dst, 6756); - } - dasm_put(Dst, 2250, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6765); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6782); - } else { - dasm_put(Dst, 6797); - } - dasm_put(Dst, 6810, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6976); - } else { - dasm_put(Dst, 6855); - } - if (sse) { - dasm_put(Dst, 6996); - } else { - dasm_put(Dst, 7013); - } - dasm_put(Dst, 7026, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6765); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6674); - } else { - dasm_put(Dst, 7049); - } - dasm_put(Dst, 7070, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6765); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6674); - } else { - dasm_put(Dst, 7049); - } - dasm_put(Dst, 7094); - if (LJ_DUALNUM) { - dasm_put(Dst, 6725); - } else if (sse) { - dasm_put(Dst, 7100); - } else { - dasm_put(Dst, 7112); - } - dasm_put(Dst, 7125); - if (LJ_DUALNUM) { - dasm_put(Dst, 7136, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6765); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6674); - } else { - dasm_put(Dst, 7049); - } - dasm_put(Dst, 7152, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 7167, 2+1, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 7239, 2+1, LJ_TISNUM, LJ_TISNUM); - } - dasm_put(Dst, 7303); - if (LJ_DUALNUM) { - dasm_put(Dst, 7310, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6765); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6674); - } else { - dasm_put(Dst, 7049); - } - dasm_put(Dst, 7152, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 7326, 2+1, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 7398, 2+1, LJ_TISNUM, LJ_TISNUM); - } - dasm_put(Dst, 7462); - if (LJ_DUALNUM) { - dasm_put(Dst, 7470, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6765); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6674); - } else { - dasm_put(Dst, 7049); - } - dasm_put(Dst, 7152, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 7486, 2+1, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 7558, 2+1, LJ_TISNUM, LJ_TISNUM); - } - dasm_put(Dst, 7622); - if (LJ_DUALNUM) { - dasm_put(Dst, 7630, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6765); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6674); - } else { - dasm_put(Dst, 7049); - } - dasm_put(Dst, 7152, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 7646, 2+1, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 7718, 2+1, LJ_TISNUM, LJ_TISNUM); - } - dasm_put(Dst, 7782); - if (LJ_DUALNUM) { - dasm_put(Dst, 7789, 1+1, LJ_TISNUM); - if (LJ_DUALNUM) { - dasm_put(Dst, 6765); - } else { - dasm_put(Dst, 2273); - } - if (sse) { - dasm_put(Dst, 6674); - } else { - dasm_put(Dst, 7049); - } - dasm_put(Dst, 7152, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 7805, 2+1, LJ_TISNUM, LJ_TISNUM); - } else { - dasm_put(Dst, 7877, 2+1, LJ_TISNUM, LJ_TISNUM); - } - dasm_put(Dst, 7941, 1+2, 1+1, Dt1(->base), 8*LUA_MINSTACK, Dt1(->top), Dt1(->maxstack), Dt8(->f), Dt1(->base)); - dasm_put(Dst, 8017, Dt1(->top), Dt7(->pc), FRAME_TYPE, LUA_MINSTACK, Dt1(->base), Dt1(->base)); - dasm_put(Dst, 8141, Dt1(->top), Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 8179, DISPATCH_GL(hookmask), HOOK_VMEVENT, HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount)); -#endif - dasm_put(Dst, 8210, DISPATCH_GL(hookmask), HOOK_ACTIVE, DISPATCH_GL(hookmask), HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount), LUA_MASKLINE); - dasm_put(Dst, 8261, Dt1(->base), Dt1(->base), GG_DISP2STATIC); -#if LJ_HASJIT - dasm_put(Dst, 8327, Dt7(->pc), PC2PROTO(framesize), Dt1(->base), Dt1(->top), GG_DISP2J, DISPATCH_J(L)); -#endif - dasm_put(Dst, 8373); -#if LJ_HASJIT - dasm_put(Dst, 8205); -#endif - dasm_put(Dst, 8380); -#if LJ_HASJIT - dasm_put(Dst, 8383); -#endif - dasm_put(Dst, 8393, Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 8427); -#endif - dasm_put(Dst, 8432, Dt1(->base), Dt1(->top)); -#if LJ_HASJIT - dasm_put(Dst, 8461, DISPATCH_GL(vmstate), DISPATCH_GL(vmstate), ~LJ_VMST_EXIT, DISPATCH_J(exitno), DISPATCH_J(parent), 8*8+16, DISPATCH_GL(jit_L), DISPATCH_GL(jit_base), DISPATCH_J(L), DISPATCH_GL(jit_L), Dt1(->base), GG_DISP2J, Dt1(->cframe), CFRAME_RAWMASK, CFRAME_OFS_L, Dt1(->base), CFRAME_OFS_PC); -#endif - dasm_put(Dst, 8604); -#if LJ_HASJIT - dasm_put(Dst, 8607, Dt7(->pc), PC2PROTO(k), DISPATCH_GL(jit_L), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, BC_FUNCF); -#endif - dasm_put(Dst, 8685); - if (!sse) { - dasm_put(Dst, 8688); - } - dasm_put(Dst, 8733); - if (!sse) { - dasm_put(Dst, 8835); - } - dasm_put(Dst, 8880); - if (!sse) { - dasm_put(Dst, 8982); - } - dasm_put(Dst, 9021); - if (sse) { - dasm_put(Dst, 9126); - } else { - dasm_put(Dst, 9256); - } - dasm_put(Dst, 9303); - if (!sse) { - dasm_put(Dst, 9377); - if (cmov) { - dasm_put(Dst, 9388); - } else { - dasm_put(Dst, 9392); - } - dasm_put(Dst, 9399); - dasm_put(Dst, 9473); - dasm_put(Dst, 9573); - if (cmov) { - dasm_put(Dst, 9576); - } else { - dasm_put(Dst, 9580); - } - dasm_put(Dst, 9587); - if (cmov) { - dasm_put(Dst, 9388); - } else { - dasm_put(Dst, 9392); - } - dasm_put(Dst, 9605); - } else { - dasm_put(Dst, 9684); - } - dasm_put(Dst, 9687); - dasm_put(Dst, 9772); - dasm_put(Dst, 9902); - dasm_put(Dst, 10108); -#if LJ_HASJIT - if (sse) { - dasm_put(Dst, 10115); - dasm_put(Dst, 10172); - dasm_put(Dst, 10263); - } else { - dasm_put(Dst, 10305); - dasm_put(Dst, 10397); - } - dasm_put(Dst, 10443); -#endif - dasm_put(Dst, 10447); - if (sse) { - dasm_put(Dst, 10450); - dasm_put(Dst, 10555); - dasm_put(Dst, 10638); - } else { - dasm_put(Dst, 10710); - dasm_put(Dst, 10793); - if (cmov) { - dasm_put(Dst, 10848); - } else { - dasm_put(Dst, 10867); - } - dasm_put(Dst, 10443); - } - dasm_put(Dst, 10908); -#ifdef LUA_USE_ASSERT - dasm_put(Dst, 10445); -#endif - dasm_put(Dst, 10964); -#if LJ_HASFFI -#define DtE(_V) (int)(ptrdiff_t)&(((CTState *)0)_V) - dasm_put(Dst, 10968, GG_G2DISP, Dt2(->ctype_state), DtE(->cb.slot), CFRAME_SIZE+16, DtE(->cb.gpr[0]), DtE(->cb.gpr[1]), DtE(->cb.stack), CFRAME_SIZE+12, CFRAME_SIZE+8, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base), Dt1(->top), Dt7(->pc)); -#endif - dasm_put(Dst, 11078); -#if LJ_HASFFI - dasm_put(Dst, 11081, DISPATCH_GL(ctype_state), DtE(->L), Dt1(->base), Dt1(->top), DtE(->cb.gpr[0]), DtE(->cb.gpr[1]), DtE(->cb.gpr[2]), DtE(->cb.fpr[0].d), DtE(->cb.fpr[0].f), Dt1(->top)); -#endif - dasm_put(Dst, 11170); -#if LJ_HASFFI -#define DtF(_V) (int)(ptrdiff_t)&(((CCallState *)0)_V) - dasm_put(Dst, 11173, DtF(->spadj)); -#if LJ_TARGET_WINDOWS - dasm_put(Dst, 11183, DtF(->spadj)); -#endif - dasm_put(Dst, 11187, DtF(->nsp), offsetof(CCallState, stack), DtF(->gpr[0]), DtF(->gpr[1]), DtF(->func), DtF(->gpr[0]), DtF(->gpr[1]), DtF(->resx87), DtF(->fpr[0].d[0])); - dasm_put(Dst, 11257, DtF(->fpr[0].f[0])); -#if LJ_TARGET_WINDOWS - dasm_put(Dst, 11263, DtF(->spadj)); -#endif - dasm_put(Dst, 11267); -#endif -} - -/* Generate the code for a single instruction. */ -static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse) -{ - int vk = 0; - dasm_put(Dst, 11274, defop); - - switch (op) { - - /* -- Comparison ops ---------------------------------------------------- */ - - /* Remember: all ops branch for a true comparison, fall through otherwise. */ - - - case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: - if (LJ_DUALNUM) { - dasm_put(Dst, 11276, LJ_TISNUM, LJ_TISNUM); - switch (op) { - case BC_ISLT: - dasm_put(Dst, 11306); - break; - case BC_ISGE: - dasm_put(Dst, 11311); - break; - case BC_ISLE: - dasm_put(Dst, 11316); - break; - case BC_ISGT: - dasm_put(Dst, 11321); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 11326, -BCBIAS_J*4, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 11379); - } else { - dasm_put(Dst, 11390); - } - dasm_put(Dst, 11401); - if (sse) { - dasm_put(Dst, 11408); - switch (op) { - case BC_ISLT: - dasm_put(Dst, 11428); - break; - case BC_ISGE: - dasm_put(Dst, 11433); - break; - case BC_ISLE: - dasm_put(Dst, 11438); - break; - case BC_ISGT: - dasm_put(Dst, 11443); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 11448); - } else { - dasm_put(Dst, 11453); - } - } else { - dasm_put(Dst, 11461, LJ_TISNUM, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 11482); - } else { - dasm_put(Dst, 11503); - if (cmov) { - dasm_put(Dst, 3953); - } else { - dasm_put(Dst, 3959); - } - } - if (LJ_DUALNUM) { - switch (op) { - case BC_ISLT: - dasm_put(Dst, 11428); - break; - case BC_ISGE: - dasm_put(Dst, 11433); - break; - case BC_ISLE: - dasm_put(Dst, 11438); - break; - case BC_ISGT: - dasm_put(Dst, 11443); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 11448); - } else { - switch (op) { - case BC_ISLT: - dasm_put(Dst, 752); - break; - case BC_ISGE: - dasm_put(Dst, 11519); - break; - case BC_ISLE: - dasm_put(Dst, 11524); - break; - case BC_ISGT: - dasm_put(Dst, 11529); - break; - default: break; /* Shut up GCC. */ - } - dasm_put(Dst, 11534, -BCBIAS_J*4); - } - break; - - case BC_ISEQV: case BC_ISNEV: - vk = op == BC_ISEQV; - dasm_put(Dst, 11565); - if (LJ_DUALNUM) { - dasm_put(Dst, 11573, LJ_TISNUM, LJ_TISNUM); - if (vk) { - dasm_put(Dst, 11598); - } else { - dasm_put(Dst, 11603); - } - dasm_put(Dst, 11608, -BCBIAS_J*4, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 11659); - } else { - dasm_put(Dst, 11666); - } - dasm_put(Dst, 11670); - if (sse) { - dasm_put(Dst, 11681); - } else { - dasm_put(Dst, 11693); - } - dasm_put(Dst, 11700); - } else { - dasm_put(Dst, 11705, LJ_TISNUM, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 11724); - } else { - dasm_put(Dst, 11742); - if (cmov) { - dasm_put(Dst, 3953); - } else { - dasm_put(Dst, 3959); - } - } - iseqne_fp: - if (vk) { - dasm_put(Dst, 11755); - } else { - dasm_put(Dst, 11764); - } - iseqne_end: - if (vk) { - dasm_put(Dst, 11773, -BCBIAS_J*4); - if (!LJ_HASFFI) { - dasm_put(Dst, 4853); - } - } else { - if (!LJ_HASFFI) { - dasm_put(Dst, 4853); - } - dasm_put(Dst, 11788, -BCBIAS_J*4); - } - if (LJ_DUALNUM && (op == BC_ISEQV || op == BC_ISNEV || - op == BC_ISEQN || op == BC_ISNEN)) { - dasm_put(Dst, 11803); - } else { - dasm_put(Dst, 11546); - } - if (op == BC_ISEQV || op == BC_ISNEV) { - dasm_put(Dst, 11808); - if (LJ_HASFFI) { - dasm_put(Dst, 11811, LJ_TCDATA, LJ_TCDATA); - } - dasm_put(Dst, 11830, LJ_TISPRI, LJ_TISTABUD, Dt6(->metatable), Dt6(->nomm), 1<len), LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 12450, Dt5(->len)); - } else { - dasm_put(Dst, 12468, Dt5(->len)); - } - dasm_put(Dst, 12477, LJ_TTAB); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 12511, Dt6(->metatable)); -#endif - dasm_put(Dst, 12525); - if (LJ_DUALNUM) { - } else if (sse) { - dasm_put(Dst, 12534); - } else { - dasm_put(Dst, 12540); - } - dasm_put(Dst, 12547); -#ifdef LUAJIT_ENABLE_LUA52COMPAT - dasm_put(Dst, 12560, Dt6(->nomm), 1<base), Dt1(->base)); - break; - - /* -- Constant ops ------------------------------------------------------ */ - - case BC_KSTR: - dasm_put(Dst, 13397, LJ_TSTR); - break; - case BC_KCDATA: -#if LJ_HASFFI - dasm_put(Dst, 13397, LJ_TCDATA); -#endif - break; - case BC_KSHORT: - if (LJ_DUALNUM) { - dasm_put(Dst, 13430, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 13442); - } else { - dasm_put(Dst, 13457); - } - dasm_put(Dst, 11546); - break; - case BC_KNUM: - if (sse) { - dasm_put(Dst, 13465); - } else { - dasm_put(Dst, 13478); - } - dasm_put(Dst, 11546); - break; - case BC_KPRI: - dasm_put(Dst, 13485); - break; - case BC_KNIL: - dasm_put(Dst, 13511, LJ_TNIL); - break; - - /* -- Upvalue and function ops ------------------------------------------ */ - - case BC_UGET: - dasm_put(Dst, 13557, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_USETV: -#define TV2MARKOFS \ - ((int32_t)offsetof(GCupval, marked)-(int32_t)offsetof(GCupval, tv)) - dasm_put(Dst, 13601, offsetof(GCfuncL, uvptr), DtA(->closed), DtA(->v), TV2MARKOFS, LJ_GC_BLACK, LJ_TISGCV, LJ_TISNUM - LJ_TISGCV, Dt4(->gch.marked), LJ_GC_WHITES, GG_DISP2G); - dasm_put(Dst, 13691); - break; -#undef TV2MARKOFS - case BC_USETS: - dasm_put(Dst, 13703, offsetof(GCfuncL, uvptr), DtA(->v), LJ_TSTR, DtA(->marked), LJ_GC_BLACK, Dt4(->gch.marked), LJ_GC_WHITES, DtA(->closed), GG_DISP2G); - break; - case BC_USETN: - dasm_put(Dst, 13794); - if (sse) { - dasm_put(Dst, 13799); - } else { - dasm_put(Dst, 12056); - } - dasm_put(Dst, 13806, offsetof(GCfuncL, uvptr), DtA(->v)); - if (sse) { - dasm_put(Dst, 13815); - } else { - dasm_put(Dst, 13821); - } - dasm_put(Dst, 11546); - break; - case BC_USETP: - dasm_put(Dst, 13824, offsetof(GCfuncL, uvptr), DtA(->v)); - break; - case BC_UCLO: - dasm_put(Dst, 13861, -BCBIAS_J*4, Dt1(->openupval), Dt1(->base), Dt1(->base)); - break; - - case BC_FNEW: - dasm_put(Dst, 13915, Dt1(->base), Dt1(->base), LJ_TFUNC); - break; - - /* -- Table ops --------------------------------------------------------- */ - - case BC_TNEW: - dasm_put(Dst, 13986, Dt1(->base), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), LJ_TTAB); - break; - case BC_TDUP: - dasm_put(Dst, 14112, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), Dt1(->base), LJ_TTAB); - break; - - case BC_GGET: - dasm_put(Dst, 14204, Dt7(->env)); - break; - case BC_GSET: - dasm_put(Dst, 14222, Dt7(->env)); - break; - - case BC_TGETV: - dasm_put(Dst, 14240, LJ_TTAB); - if (LJ_DUALNUM) { - dasm_put(Dst, 14263, LJ_TISNUM); - } else { - dasm_put(Dst, 14277, LJ_TISNUM); - if (sse) { - dasm_put(Dst, 14288); - } else { - dasm_put(Dst, 14309); - if (cmov) { - dasm_put(Dst, 3953); - } else { - dasm_put(Dst, 3959); - } - dasm_put(Dst, 2689); - } - dasm_put(Dst, 14319); - } - dasm_put(Dst, 14324, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), LJ_TNIL); - dasm_put(Dst, 14525, LJ_TNIL, DtB(->next), Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), LJ_TNIL, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<asize), Dt6(->array), LJ_TNIL, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - case BC_TSETS: - dasm_put(Dst, 14880, LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->nomm), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), LJ_TNIL); - dasm_put(Dst, 14955, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<next)); - dasm_put(Dst, 15047, Dt6(->metatable), Dt6(->nomm), 1<base), Dt1(->base), Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - case BC_TSETB: - dasm_put(Dst, 15143, LJ_TTAB, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable)); - dasm_put(Dst, 15241, Dt6(->metatable), Dt6(->nomm), 1<marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - - case BC_TSETM: - dasm_put(Dst, 15287, Dt6(->marked), LJ_GC_BLACK, Dt6(->asize), Dt6(->array), Dt1(->base), Dt1(->base)); - dasm_put(Dst, 15436, Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist)); - break; - - /* -- Calls and vararg handling ----------------------------------------- */ - - case BC_CALL: case BC_CALLM: - dasm_put(Dst, 12580); - if (op == BC_CALLM) { - dasm_put(Dst, 15454); - } - dasm_put(Dst, 15459, LJ_TFUNC, Dt7(->pc)); - break; - - case BC_CALLMT: - dasm_put(Dst, 15454); - break; - case BC_CALLT: - dasm_put(Dst, 15500, LJ_TFUNC, FRAME_TYPE, Dt7(->ffid), Dt7(->pc)); - dasm_put(Dst, 15618, FRAME_TYPE, Dt7(->pc), PC2PROTO(k), FRAME_VARG, FRAME_TYPEP, FRAME_VARG); - break; - - case BC_ITERC: - dasm_put(Dst, 15688, LJ_TFUNC, 2+1, Dt7(->pc)); - break; - - case BC_ITERN: -#if LJ_HASJIT -#endif - dasm_put(Dst, 15768, Dt6(->asize), Dt6(->array), LJ_TNIL); - if (LJ_DUALNUM) { - dasm_put(Dst, 12441, LJ_TISNUM); - } else if (sse) { - dasm_put(Dst, 12534); - } else { - dasm_put(Dst, 15814); - } - dasm_put(Dst, 15820); - if (LJ_DUALNUM) { - } else if (sse) { - dasm_put(Dst, 12406); - } else { - dasm_put(Dst, 12418); - } - dasm_put(Dst, 15839, -BCBIAS_J*4); - if (!LJ_DUALNUM && !sse) { - dasm_put(Dst, 15890); - } - dasm_put(Dst, 15896, Dt6(->hmask), sizeof(Node), Dt6(->node), DtB(->val.it), LJ_TNIL, DtB(->key.gcr), DtB(->key.it), DtB(->val.gcr), DtB(->val.it)); - dasm_put(Dst, 15971); - break; - - case BC_ISNEXT: - dasm_put(Dst, 15979, LJ_TFUNC, LJ_TTAB, LJ_TNIL, Dt8(->ffid), FF_next_N, -BCBIAS_J*4, BC_JMP, -BCBIAS_J*4, BC_ITERC); - break; - - case BC_VARG: - dasm_put(Dst, 16078, (8+FRAME_VARG), LJ_TNIL, Dt1(->maxstack)); - dasm_put(Dst, 16242, Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top)); - break; - - /* -- Returns ----------------------------------------------------------- */ - - case BC_RETM: - dasm_put(Dst, 15454); - break; - - case BC_RET: case BC_RET0: case BC_RET1: - if (op != BC_RET0) { - dasm_put(Dst, 16313); - } - dasm_put(Dst, 16317, FRAME_TYPE); - switch (op) { - case BC_RET: - dasm_put(Dst, 16336); - break; - case BC_RET1: - dasm_put(Dst, 16394); - /* fallthrough */ - case BC_RET0: - dasm_put(Dst, 16410); - default: - break; - } - dasm_put(Dst, 16421, Dt7(->pc), PC2PROTO(k)); - if (op == BC_RET) { - dasm_put(Dst, 16463, LJ_TNIL); - } else { - dasm_put(Dst, 16472, LJ_TNIL); - } - dasm_put(Dst, 16479, -FRAME_VARG, FRAME_TYPEP); - if (op != BC_RET0) { - dasm_put(Dst, 16503); - } - dasm_put(Dst, 4937); - break; - - /* -- Loops and branches ------------------------------------------------ */ - - - case BC_FORL: -#if LJ_HASJIT - dasm_put(Dst, 16507, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_JFORI: - case BC_JFORL: -#if !LJ_HASJIT - break; -#endif - case BC_FORI: - case BC_IFORL: - vk = (op == BC_IFORL || op == BC_JFORL); - dasm_put(Dst, 16528); - if (LJ_DUALNUM) { - dasm_put(Dst, 16532, LJ_TISNUM); - if (!vk) { - dasm_put(Dst, 16542, LJ_TISNUM, LJ_TISNUM); - } else { -#ifdef LUA_USE_ASSERT - dasm_put(Dst, 16571, LJ_TISNUM, LJ_TISNUM); -#endif - dasm_put(Dst, 16590); - } - dasm_put(Dst, 16609, LJ_TISNUM); - if (op == BC_FORI) { - dasm_put(Dst, 16620, -BCBIAS_J*4); - } else if (op == BC_JFORI) { - dasm_put(Dst, 16634, -BCBIAS_J*4, BC_JLOOP); - } else if (op == BC_IFORL) { - dasm_put(Dst, 16652, -BCBIAS_J*4); - } else { - dasm_put(Dst, 16644, BC_JLOOP); - } - dasm_put(Dst, 16666); - if (vk) { - dasm_put(Dst, 16689); - } - dasm_put(Dst, 16609, LJ_TISNUM); - if (op == BC_FORI) { - dasm_put(Dst, 16698); - } else if (op == BC_JFORI) { - dasm_put(Dst, 16703, -BCBIAS_J*4, BC_JLOOP); - } else if (op == BC_IFORL) { - dasm_put(Dst, 16717); - } else { - dasm_put(Dst, 16713, BC_JLOOP); - } - dasm_put(Dst, 16722); - } else if (!vk) { - dasm_put(Dst, 16729, LJ_TISNUM); - } - if (!vk) { - dasm_put(Dst, 16735, LJ_TISNUM); - } else { -#ifdef LUA_USE_ASSERT - dasm_put(Dst, 16749, LJ_TISNUM, LJ_TISNUM); -#endif - } - dasm_put(Dst, 16768); - if (!vk) { - dasm_put(Dst, 16772, LJ_TISNUM); - } - if (sse) { - dasm_put(Dst, 16781); - if (vk) { - dasm_put(Dst, 16793); - } else { - dasm_put(Dst, 16812); - } - dasm_put(Dst, 16817); - } else { - dasm_put(Dst, 16830); - if (vk) { - dasm_put(Dst, 16836); - } else { - dasm_put(Dst, 16852); - } - dasm_put(Dst, 16860); - if (cmov) { - dasm_put(Dst, 3953); - } else { - dasm_put(Dst, 3959); - } - if (!cmov) { - dasm_put(Dst, 16865); - } - } - if (op == BC_FORI) { - if (LJ_DUALNUM) { - dasm_put(Dst, 16871); - } else { - dasm_put(Dst, 16876, -BCBIAS_J*4); - } - } else if (op == BC_JFORI) { - dasm_put(Dst, 16886, -BCBIAS_J*4, BC_JLOOP); - } else if (op == BC_IFORL) { - if (LJ_DUALNUM) { - dasm_put(Dst, 16900); - } else { - dasm_put(Dst, 16905, -BCBIAS_J*4); - } - } else { - dasm_put(Dst, 16896, BC_JLOOP); - } - if (LJ_DUALNUM) { - dasm_put(Dst, 11448); - } else { - dasm_put(Dst, 12184); - } - if (sse) { - dasm_put(Dst, 16915); - } - break; - - case BC_ITERL: -#if LJ_HASJIT - dasm_put(Dst, 16507, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_JITERL: -#if !LJ_HASJIT - break; -#endif - case BC_IITERL: - dasm_put(Dst, 16926, LJ_TNIL); - if (op == BC_JITERL) { - dasm_put(Dst, 16941, BC_JLOOP); - } else { - dasm_put(Dst, 16955, -BCBIAS_J*4); - } - dasm_put(Dst, 11544); - break; - - case BC_LOOP: -#if LJ_HASJIT - dasm_put(Dst, 16507, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP); -#endif - break; - - case BC_ILOOP: - dasm_put(Dst, 11546); - break; - - case BC_JLOOP: -#if LJ_HASJIT - dasm_put(Dst, 16971, DISPATCH_J(trace), DtD(->mcode), DISPATCH_GL(jit_base), DISPATCH_GL(jit_L)); -#endif - break; - - case BC_JMP: - dasm_put(Dst, 16994, -BCBIAS_J*4); - break; - - /* -- Function headers -------------------------------------------------- */ - - /* - ** Reminder: A function may be called with func/args above L->maxstack, - ** i.e. occupying EXTRA_STACK slots. And vmeta_call may add one extra slot, - ** too. This means all FUNC* ops (including fast functions) must check - ** for stack overflow _before_ adding more slots! - */ - - case BC_FUNCF: -#if LJ_HASJIT - dasm_put(Dst, 17018, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_CALL); -#endif - case BC_FUNCV: /* NYI: compiled vararg functions. */ - break; - - case BC_JFUNCF: -#if !LJ_HASJIT - break; -#endif - case BC_IFUNCF: - dasm_put(Dst, 17039, -4+PC2PROTO(k), Dt1(->maxstack), -4+PC2PROTO(numparams)); - if (op == BC_JFUNCF) { - dasm_put(Dst, 17069, BC_JLOOP); - } else { - dasm_put(Dst, 11546); - } - dasm_put(Dst, 17078, LJ_TNIL); - break; - - case BC_JFUNCV: -#if !LJ_HASJIT - break; -#endif - dasm_put(Dst, 10445); - break; /* NYI: compiled vararg functions. */ - - case BC_IFUNCV: - dasm_put(Dst, 17100, FRAME_VARG, Dt1(->maxstack), -4+PC2PROTO(numparams), LJ_TNIL); - if (op == BC_JFUNCV) { - dasm_put(Dst, 17069, BC_JLOOP); - } else { - dasm_put(Dst, 17191, -4+PC2PROTO(k)); - } - dasm_put(Dst, 17213, LJ_TNIL); - break; - - case BC_FUNCC: - case BC_FUNCCW: - dasm_put(Dst, 17235, Dt8(->f), Dt1(->base), 8*LUA_MINSTACK, Dt1(->maxstack), Dt1(->top)); - if (op == BC_FUNCC) { - dasm_put(Dst, 17264); - } else { - dasm_put(Dst, 17268); - } - dasm_put(Dst, 17276, DISPATCH_GL(vmstate), ~LJ_VMST_C); - if (op == BC_FUNCC) { - dasm_put(Dst, 17285); - } else { - dasm_put(Dst, 17289, DISPATCH_GL(wrapf)); - } - dasm_put(Dst, 17294, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base), Dt1(->top)); - break; - - /* ---------------------------------------------------------------------- */ - - default: - fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); - exit(2); - break; - } -} - -static int build_backend(BuildCtx *ctx) -{ - int op; - int cmov = 1; - int sse = 0; -#ifdef LUAJIT_CPU_NOCMOV - cmov = 0; -#endif -#if defined(LUAJIT_CPU_SSE2) || defined(LJ_TARGET_X64) - sse = 1; -#endif - - dasm_growpc(Dst, BC__MAX); - - build_subroutines(ctx, cmov, sse); - - dasm_put(Dst, 17319); - for (op = 0; op < BC__MAX; op++) - build_ins(ctx, (BCOp)op, op, cmov, sse); - - return BC__MAX; -} - -/* Emit pseudo frame-info for all assembler functions. */ -static void emit_asm_debug(BuildCtx *ctx) -{ - int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); -#if LJ_64 -#define SZPTR "8" -#define BSZPTR "3" -#define REG_SP "0x7" -#define REG_RA "0x10" -#else -#define SZPTR "4" -#define BSZPTR "2" -#define REG_SP "0x4" -#define REG_RA "0x8" -#endif - switch (ctx->mode) { - case BUILD_elfasm: - fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); - fprintf(ctx->fp, - ".Lframe0:\n" - "\t.long .LECIE0-.LSCIE0\n" - ".LSCIE0:\n" - "\t.long 0xffffffff\n" - "\t.byte 0x1\n" - "\t.string \"\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE0:\n\n"); - fprintf(ctx->fp, - ".LSFDE0:\n" - "\t.long .LEFDE0-.LASFDE0\n" - ".LASFDE0:\n" - "\t.long .Lframe0\n" -#if LJ_64 - "\t.quad .Lbegin\n" - "\t.quad %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.long .Lbegin\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE0:\n\n", fcofs, CFRAME_SIZE); -#if LJ_HASFFI - fprintf(ctx->fp, - ".LSFDE1:\n" - "\t.long .LEFDE1-.LASFDE1\n" - ".LASFDE1:\n" - "\t.long .Lframe0\n" -#if LJ_64 - "\t.quad lj_vm_ffi_call\n" - "\t.quad %d\n" - "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ -#else - "\t.long lj_vm_ffi_call\n" - "\t.long %d\n" - "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); -#endif -#if (defined(__sun__) && defined(__svr4__)) || defined(__solaris_) - fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n"); -#else - fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); -#endif - fprintf(ctx->fp, - ".Lframe1:\n" - "\t.long .LECIE1-.LSCIE1\n" - ".LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zPR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 6\n" /* augmentation length */ - "\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 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE1:\n\n"); - fprintf(ctx->fp, - ".LSFDE2:\n" - "\t.long .LEFDE2-.LASFDE2\n" - ".LASFDE2:\n" - "\t.long .LASFDE2-.Lframe1\n" - "\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 */ -#if LJ_64 - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE2:\n\n", fcofs, CFRAME_SIZE); -#if LJ_HASFFI - fprintf(ctx->fp, - ".Lframe2:\n" - "\t.long .LECIE2-.LSCIE2\n" - ".LSCIE2:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zR\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 1\n" /* augmentation length */ - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - ".LECIE2:\n\n"); - fprintf(ctx->fp, - ".LSFDE3:\n" - "\t.long .LEFDE3-.LASFDE3\n" - ".LASFDE3:\n" - "\t.long .LASFDE3-.Lframe2\n" - "\t.long lj_vm_ffi_call-.\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ -#else - "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */ - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); -#endif - break; - case BUILD_coffasm: - fprintf(ctx->fp, "\t.section .eh_frame,\"dr\"\n"); - fprintf(ctx->fp, - "\t.def %slj_err_unwind_dwarf; .scl 2; .type 32; .endef\n", - LJ_32 ? "_" : ""); - fprintf(ctx->fp, - "Lframe1:\n" - "\t.long LECIE1-LSCIE1\n" - "LSCIE1:\n" - "\t.long 0\n" - "\t.byte 0x1\n" - "\t.string \"zP\"\n" - "\t.uleb128 0x1\n" - "\t.sleb128 -" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.uleb128 5\n" /* augmentation length */ - "\t.byte 0x00\n" /* absptr */ - "\t.long %slj_err_unwind_dwarf\n" - "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" - "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" - "\t.align " SZPTR "\n" - "LECIE1:\n\n", LJ_32 ? "_" : ""); - fprintf(ctx->fp, - "LSFDE1:\n" - "\t.long LEFDE1-LASFDE1\n" - "LASFDE1:\n" - "\t.long LASFDE1-Lframe1\n" - "\t.long %slj_vm_asm_begin\n" - "\t.long %d\n" - "\t.uleb128 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ -#if LJ_64 - "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ -#else - "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ - "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ -#endif - "\t.align " SZPTR "\n" - "LEFDE1:\n\n", LJ_32 ? "_" : "", (int)ctx->codesz, CFRAME_SIZE); - break; - /* Mental note: never let Apple design an assembler. - ** Or a linker. Or a plastic case. But I digress. - */ - case BUILD_machasm: { -#if LJ_HASFFI - int fcsize = 0; -#endif - int i; - 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.byte 0x1\n" - "\t.byte 128-" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 6\n" /* augmentation length */ - "\t.byte 0x9b\n" /* indirect|pcrel|sdata4 */ -#if LJ_64 - "\t.long _lj_err_unwind_dwarf+4@GOTPCREL\n" - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n" -#else - "\t.long L_lj_err_unwind_dwarf$non_lazy_ptr-.\n" - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH-O. */ -#endif - "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n" - "\t.align " BSZPTR "\n" - "LECIEX:\n\n"); - for (i = 0; i < ctx->nsym; i++) { - const char *name = ctx->sym[i].name; - int32_t size = ctx->sym[i+1].ofs - ctx->sym[i].ofs; - if (size == 0) continue; -#if LJ_HASFFI - if (!strcmp(name, "_lj_vm_ffi_call")) { fcsize = size; continue; } -#endif - fprintf(ctx->fp, - "%s.eh:\n" - "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.byte 0\n" /* augmentation length */ - "\t.byte 0xe\n\t.byte %d\n" /* def_cfa_offset */ -#if LJ_64 - "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */ - "\t.byte 0x8f\n\t.byte 0x4\n" /* offset r15 */ - "\t.byte 0x8e\n\t.byte 0x5\n" /* offset r14 */ -#else - "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/ - "\t.byte 0x87\n\t.byte 0x3\n" /* offset edi */ - "\t.byte 0x86\n\t.byte 0x4\n" /* offset esi */ - "\t.byte 0x83\n\t.byte 0x5\n" /* offset ebx */ -#endif - "\t.align " BSZPTR "\n" - "LEFDE%d:\n\n", - name, i, i, i, i, i, i, i, name, size, CFRAME_SIZE, i); - } -#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.byte 0x1\n" - "\t.byte 128-" SZPTR "\n" - "\t.byte " REG_RA "\n" - "\t.byte 1\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n" -#else - "\t.byte 0x1b\n" /* pcrel|sdata4 */ - "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH. */ -#endif - "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n" - "\t.align " BSZPTR "\n" - "LECIEY:\n\n"); - fprintf(ctx->fp, - "_lj_vm_ffi_call.eh:\n" - "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.byte 0\n" /* augmentation length */ -#if LJ_64 - "\t.byte 0xe\n\t.byte 16\n" /* def_cfa_offset */ - "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */ - "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */ -#else - "\t.byte 0xe\n\t.byte 8\n" /* def_cfa_offset */ - "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/ - "\t.byte 0xd\n\t.uleb128 0x4\n" /* def_cfa_register ebp */ - "\t.byte 0x83\n\t.byte 0x3\n" /* offset ebx */ -#endif - "\t.align " BSZPTR "\n" - "LEFDEY:\n\n", fcsize); - } -#endif -#if LJ_64 - fprintf(ctx->fp, "\t.subsections_via_symbols\n"); -#else - fprintf(ctx->fp, - "\t.non_lazy_symbol_pointer\n" - "L_lj_err_unwind_dwarf$non_lazy_ptr:\n" - ".indirect_symbol _lj_err_unwind_dwarf\n" - ".long 0\n"); -#endif - } - break; - default: /* Difficult for other modes. */ - break; - } -} - diff --git a/src/host/.gitignore b/src/host/.gitignore new file mode 100644 index 00000000..762ac2a0 --- /dev/null +++ b/src/host/.gitignore @@ -0,0 +1,3 @@ +minilua +buildvm +buildvm_arch.h diff --git a/src/host/buildvm.c b/src/host/buildvm.c new file mode 100644 index 00000000..7dbf2cae --- /dev/null +++ b/src/host/buildvm.c @@ -0,0 +1,504 @@ +/* +** LuaJIT VM builder. +** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +** +** This is a tool to build the hand-tuned assembler code required for +** LuaJIT's bytecode interpreter. It supports a variety of output formats +** to feed different toolchains (see usage() below). +** +** This tool is not particularly optimized because it's only used while +** _building_ LuaJIT. There's no point in distributing or installing it. +** Only the object code generated by this tool is linked into LuaJIT. +** +** Caveat: some memory is not free'd, error handling is lazy. +** It's a one-shot tool -- any effort fixing this would be wasted. +*/ + +#include "buildvm.h" +#include "lj_obj.h" +#include "lj_gc.h" +#include "lj_bc.h" +#include "lj_ir.h" +#include "lj_ircall.h" +#include "lj_frame.h" +#include "lj_dispatch.h" +#if LJ_HASFFI +#include "lj_ctype.h" +#include "lj_ccall.h" +#endif +#include "luajit.h" + +#if defined(_WIN32) +#include +#include +#endif + +/* ------------------------------------------------------------------------ */ + +/* DynASM glue definitions. */ +#define Dst ctx +#define Dst_DECL BuildCtx *ctx +#define Dst_REF (ctx->D) +#define DASM_CHECKS 1 + +#include "../dynasm/dasm_proto.h" + +/* Glue macros for DynASM. */ +static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type); + +#define DASM_EXTERN(ctx, addr, idx, type) \ + collect_reloc(ctx, addr, idx, type) + +/* ------------------------------------------------------------------------ */ + +/* Avoid trouble if cross-compiling for an x86 target. Speed doesn't matter. */ +#define DASM_ALIGNED_WRITES 1 + +/* Embed architecture-specific DynASM encoder. */ +#if LJ_TARGET_X86ORX64 +#include "../dynasm/dasm_x86.h" +#elif LJ_TARGET_ARM +#include "../dynasm/dasm_arm.h" +#elif LJ_TARGET_PPC +#include "../dynasm/dasm_ppc.h" +#elif LJ_TARGET_PPCSPE +#include "../dynasm/dasm_ppc.h" +#elif LJ_TARGET_MIPS +#include "../dynasm/dasm_mips.h" +#else +#error "No support for this architecture (yet)" +#endif + +/* Embed generated architecture-specific backend. */ +#include "buildvm_arch.h" + +/* ------------------------------------------------------------------------ */ + +void owrite(BuildCtx *ctx, const void *ptr, size_t sz) +{ + if (fwrite(ptr, 1, sz, ctx->fp) != sz) { + fprintf(stderr, "Error: cannot write to output file: %s\n", + strerror(errno)); + exit(1); + } +} + +/* ------------------------------------------------------------------------ */ + +/* Emit code as raw bytes. Only used for DynASM debugging. */ +static void emit_raw(BuildCtx *ctx) +{ + owrite(ctx, ctx->code, ctx->codesz); +} + +/* -- Build machine code -------------------------------------------------- */ + +static const char *sym_decorate(BuildCtx *ctx, + const char *prefix, const char *suffix) +{ + char name[256]; + char *p; +#if LJ_64 + const char *symprefix = ctx->mode == BUILD_machasm ? "_" : ""; +#else + const char *symprefix = ctx->mode != BUILD_elfasm ? "_" : ""; +#endif + sprintf(name, "%s%s%s", symprefix, prefix, suffix); + p = strchr(name, '@'); + if (p) { + if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj)) + name[0] = '@'; + else + *p = '\0'; + } + p = (char *)malloc(strlen(name)+1); /* MSVC doesn't like strdup. */ + strcpy(p, name); + return p; +} + +#define NRELOCSYM (sizeof(extnames)/sizeof(extnames[0])-1) + +static int relocmap[NRELOCSYM]; + +/* Collect external relocations. */ +static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type) +{ + if (ctx->nreloc >= BUILD_MAX_RELOC) { + fprintf(stderr, "Error: too many relocations, increase BUILD_MAX_RELOC.\n"); + exit(1); + } + if (relocmap[idx] < 0) { + relocmap[idx] = ctx->nrelocsym; + ctx->relocsym[ctx->nrelocsym] = sym_decorate(ctx, "", extnames[idx]); + ctx->nrelocsym++; + } + ctx->reloc[ctx->nreloc].ofs = (int32_t)(addr - ctx->code); + ctx->reloc[ctx->nreloc].sym = relocmap[idx]; + ctx->reloc[ctx->nreloc].type = type; + ctx->nreloc++; + return 0; /* Encode symbol offset of 0. */ +} + +/* Naive insertion sort. Performance doesn't matter here. */ +static void sym_insert(BuildCtx *ctx, int32_t ofs, + const char *prefix, const char *suffix) +{ + ptrdiff_t i = ctx->nsym++; + while (i > 0) { + if (ctx->sym[i-1].ofs <= ofs) + break; + ctx->sym[i] = ctx->sym[i-1]; + i--; + } + ctx->sym[i].ofs = ofs; + ctx->sym[i].name = sym_decorate(ctx, prefix, suffix); +} + +/* Build the machine code. */ +static int build_code(BuildCtx *ctx) +{ + int status; + int i; + + /* Initialize DynASM structures. */ + ctx->nglob = GLOB__MAX; + ctx->glob = (void **)malloc(ctx->nglob*sizeof(void *)); + memset(ctx->glob, 0, ctx->nglob*sizeof(void *)); + ctx->nreloc = 0; + + ctx->globnames = globnames; + ctx->relocsym = (const char **)malloc(NRELOCSYM*sizeof(const char *)); + ctx->nrelocsym = 0; + for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1; + + ctx->dasm_ident = DASM_IDENT; + ctx->dasm_arch = DASM_ARCH; + + dasm_init(Dst, DASM_MAXSECTION); + dasm_setupglobal(Dst, ctx->glob, ctx->nglob); + dasm_setup(Dst, build_actionlist); + + /* Call arch-specific backend to emit the code. */ + ctx->npc = build_backend(ctx); + + /* Finalize the code. */ + (void)dasm_checkstep(Dst, -1); + if ((status = dasm_link(Dst, &ctx->codesz))) return status; + ctx->code = (uint8_t *)malloc(ctx->codesz); + if ((status = dasm_encode(Dst, (void *)ctx->code))) return status; + + /* Allocate symbol table and bytecode offsets. */ + ctx->beginsym = sym_decorate(ctx, "", LABEL_PREFIX "vm_asm_begin"); + ctx->sym = (BuildSym *)malloc((ctx->npc+ctx->nglob+1)*sizeof(BuildSym)); + ctx->nsym = 0; + ctx->bc_ofs = (int32_t *)malloc(ctx->npc*sizeof(int32_t)); + + /* Collect the opcodes (PC labels). */ + for (i = 0; i < ctx->npc; i++) { + int32_t ofs = dasm_getpclabel(Dst, i); + if (ofs < 0) return 0x22000000|i; + ctx->bc_ofs[i] = ofs; + if ((LJ_HASJIT || + !(i == BC_JFORI || i == BC_JFORL || i == BC_JITERL || i == BC_JLOOP || + i == BC_IFORL || i == BC_IITERL || i == BC_ILOOP)) && + (LJ_HASFFI || i != BC_KCDATA)) + sym_insert(ctx, ofs, LABEL_PREFIX_BC, bc_names[i]); + } + + /* Collect the globals (named labels). */ + for (i = 0; i < ctx->nglob; i++) { + const char *gl = globnames[i]; + int len = (int)strlen(gl); + if (!ctx->glob[i]) { + fprintf(stderr, "Error: undefined global %s\n", gl); + exit(2); + } + /* Skip the _Z symbols. */ + if (!(len >= 2 && gl[len-2] == '_' && gl[len-1] == 'Z')) + sym_insert(ctx, (int32_t)((uint8_t *)(ctx->glob[i]) - ctx->code), + LABEL_PREFIX, globnames[i]); + } + + /* Close the address range. */ + sym_insert(ctx, (int32_t)ctx->codesz, "", ""); + ctx->nsym--; + + dasm_free(Dst); + + return 0; +} + +/* -- Generate VM enums --------------------------------------------------- */ + +const char *const bc_names[] = { +#define BCNAME(name, ma, mb, mc, mt) #name, +BCDEF(BCNAME) +#undef BCNAME + NULL +}; + +const char *const ir_names[] = { +#define IRNAME(name, m, m1, m2) #name, +IRDEF(IRNAME) +#undef IRNAME + NULL +}; + +const char *const irt_names[] = { +#define IRTNAME(name) #name, +IRTDEF(IRTNAME) +#undef IRTNAME + NULL +}; + +const char *const irfpm_names[] = { +#define FPMNAME(name) #name, +IRFPMDEF(FPMNAME) +#undef FPMNAME + NULL +}; + +const char *const irfield_names[] = { +#define FLNAME(name, ofs) #name, +IRFLDEF(FLNAME) +#undef FLNAME + NULL +}; + +const char *const ircall_names[] = { +#define IRCALLNAME(cond, name, nargs, kind, type, flags) #name, +IRCALLDEF(IRCALLNAME) +#undef IRCALLNAME + NULL +}; + +static const char *const trace_errors[] = { +#define TREDEF(name, msg) msg, +#include "lj_traceerr.h" + NULL +}; + +static const char *lower(char *buf, const char *s) +{ + char *p = buf; + while (*s) { + *p++ = (*s >= 'A' && *s <= 'Z') ? *s+0x20 : *s; + s++; + } + *p = '\0'; + return buf; +} + +/* Emit C source code for bytecode-related definitions. */ +static void emit_bcdef(BuildCtx *ctx) +{ + int i; + fprintf(ctx->fp, "/* This is a generated file. DO NOT EDIT! */\n\n"); + fprintf(ctx->fp, "LJ_DATADEF const uint16_t lj_bc_ofs[] = {\n"); + for (i = 0; i < ctx->npc; i++) { + if (i != 0) + fprintf(ctx->fp, ",\n"); + fprintf(ctx->fp, "%d", ctx->bc_ofs[i]); + } +} + +/* Emit VM definitions as Lua code for debug modules. */ +static void emit_vmdef(BuildCtx *ctx) +{ + char buf[80]; + int i; + fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\n\n"); + fprintf(ctx->fp, "module(...)\n\n"); + + fprintf(ctx->fp, "bcnames = \""); + for (i = 0; bc_names[i]; i++) fprintf(ctx->fp, "%-6s", bc_names[i]); + fprintf(ctx->fp, "\"\n\n"); + + fprintf(ctx->fp, "irnames = \""); + for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]); + fprintf(ctx->fp, "\"\n\n"); + + fprintf(ctx->fp, "irfpm = { [0]="); + for (i = 0; irfpm_names[i]; i++) + fprintf(ctx->fp, "\"%s\", ", lower(buf, irfpm_names[i])); + fprintf(ctx->fp, "}\n\n"); + + fprintf(ctx->fp, "irfield = { [0]="); + for (i = 0; irfield_names[i]; i++) { + char *p; + lower(buf, irfield_names[i]); + p = strchr(buf, '_'); + if (p) *p = '.'; + fprintf(ctx->fp, "\"%s\", ", buf); + } + fprintf(ctx->fp, "}\n\n"); + + fprintf(ctx->fp, "ircall = {\n[0]="); + for (i = 0; ircall_names[i]; i++) + fprintf(ctx->fp, "\"%s\",\n", ircall_names[i]); + fprintf(ctx->fp, "}\n\n"); + + fprintf(ctx->fp, "traceerr = {\n[0]="); + for (i = 0; trace_errors[i]; i++) + fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]); + fprintf(ctx->fp, "}\n\n"); +} + +/* -- Argument parsing ---------------------------------------------------- */ + +/* Build mode names. */ +static const char *const modenames[] = { +#define BUILDNAME(name) #name, +BUILDDEF(BUILDNAME) +#undef BUILDNAME + NULL +}; + +/* Print usage information and exit. */ +static void usage(void) +{ + int i; + fprintf(stderr, LUAJIT_VERSION " VM builder.\n"); + fprintf(stderr, LUAJIT_COPYRIGHT ", " LUAJIT_URL "\n"); + fprintf(stderr, "Target architecture: " LJ_ARCH_NAME "\n\n"); + fprintf(stderr, "Usage: buildvm -m mode [-o outfile] [infiles...]\n\n"); + fprintf(stderr, "Available modes:\n"); + for (i = 0; i < BUILD__MAX; i++) + fprintf(stderr, " %s\n", modenames[i]); + exit(1); +} + +/* Parse the output mode name. */ +static BuildMode parsemode(const char *mode) +{ + int i; + for (i = 0; modenames[i]; i++) + if (!strcmp(mode, modenames[i])) + return (BuildMode)i; + usage(); + return (BuildMode)-1; +} + +/* Parse arguments. */ +static void parseargs(BuildCtx *ctx, char **argv) +{ + const char *a; + int i; + ctx->mode = (BuildMode)-1; + ctx->outname = "-"; + for (i = 1; (a = argv[i]) != NULL; i++) { + if (a[0] != '-') + break; + switch (a[1]) { + case '-': + if (a[2]) goto err; + i++; + goto ok; + case '\0': + goto ok; + case 'm': + i++; + if (a[2] || argv[i] == NULL) goto err; + ctx->mode = parsemode(argv[i]); + break; + case 'o': + i++; + if (a[2] || argv[i] == NULL) goto err; + ctx->outname = argv[i]; + break; + default: err: + usage(); + break; + } + } +ok: + ctx->args = argv+i; + if (ctx->mode == (BuildMode)-1) goto err; +} + +int main(int argc, char **argv) +{ + BuildCtx ctx_; + BuildCtx *ctx = &ctx_; + int status, binmode; + + if (sizeof(void *) != 4*LJ_32+8*LJ_64) { + fprintf(stderr,"Error: pointer size mismatch in cross-build.\n"); + fprintf(stderr,"Try: make HOST_CC=\"gcc -m32\" CROSS=... TARGET=...\n\n"); + return 1; + } + + UNUSED(argc); + parseargs(ctx, argv); + + if ((status = build_code(ctx))) { + fprintf(stderr,"Error: DASM error %08x\n", status); + return 1; + } + + switch (ctx->mode) { + case BUILD_peobj: + case BUILD_raw: + binmode = 1; + break; + default: + binmode = 0; + break; + } + + if (ctx->outname[0] == '-' && ctx->outname[1] == '\0') { + ctx->fp = stdout; +#if defined(_WIN32) + if (binmode) + _setmode(_fileno(stdout), _O_BINARY); /* Yuck. */ +#endif + } else if (!(ctx->fp = fopen(ctx->outname, binmode ? "wb" : "w"))) { + fprintf(stderr, "Error: cannot open output file '%s': %s\n", + ctx->outname, strerror(errno)); + exit(1); + } + + switch (ctx->mode) { + case BUILD_elfasm: + case BUILD_coffasm: + case BUILD_machasm: + emit_asm(ctx); + emit_asm_debug(ctx); + break; + case BUILD_peobj: + emit_peobj(ctx); + break; + case BUILD_raw: + emit_raw(ctx); + break; + case BUILD_bcdef: + emit_bcdef(ctx); + emit_lib(ctx); + break; + case BUILD_vmdef: + emit_vmdef(ctx); + emit_lib(ctx); + break; + case BUILD_ffdef: + case BUILD_libdef: + case BUILD_recdef: + emit_lib(ctx); + break; + case BUILD_folddef: + emit_fold(ctx); + break; + default: + break; + } + + fflush(ctx->fp); + if (ferror(ctx->fp)) { + fprintf(stderr, "Error: cannot write to output file: %s\n", + strerror(errno)); + exit(1); + } + fclose(ctx->fp); + + return 0; +} + diff --git a/src/host/buildvm.h b/src/host/buildvm.h new file mode 100644 index 00000000..2b7168ed --- /dev/null +++ b/src/host/buildvm.h @@ -0,0 +1,104 @@ +/* +** LuaJIT VM builder. +** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +*/ + +#ifndef _BUILDVM_H +#define _BUILDVM_H + +#include +#include +#include +#include +#include + +#include "lj_def.h" +#include "lj_arch.h" + +/* Hardcoded limits. Increase as needed. */ +#define BUILD_MAX_RELOC 200 /* Max. number of relocations. */ +#define BUILD_MAX_FOLD 4096 /* Max. number of fold rules. */ + +/* Prefix for scanned library definitions. */ +#define LIBDEF_PREFIX "LJLIB_" + +/* Prefix for scanned fold definitions. */ +#define FOLDDEF_PREFIX "LJFOLD" + +/* Prefixes for generated labels. */ +#define LABEL_PREFIX "lj_" +#define LABEL_PREFIX_BC LABEL_PREFIX "BC_" +#define LABEL_PREFIX_FF LABEL_PREFIX "ff_" +#define LABEL_PREFIX_CF LABEL_PREFIX "cf_" +#define LABEL_PREFIX_FFH LABEL_PREFIX "ffh_" +#define LABEL_PREFIX_LIBCF LABEL_PREFIX "lib_cf_" +#define LABEL_PREFIX_LIBINIT LABEL_PREFIX "lib_init_" + +/* Forward declaration. */ +struct dasm_State; + +/* Build modes. */ +#define BUILDDEF(_) \ + _(elfasm) _(coffasm) _(machasm) _(peobj) _(raw) \ + _(bcdef) _(ffdef) _(libdef) _(recdef) _(vmdef) \ + _(folddef) + +typedef enum { +#define BUILDENUM(name) BUILD_##name, +BUILDDEF(BUILDENUM) +#undef BUILDENUM + BUILD__MAX +} BuildMode; + +/* Code relocation. */ +typedef struct BuildReloc { + int32_t ofs; + int sym; + int type; +} BuildReloc; + +typedef struct BuildSym { + const char *name; + int32_t ofs; +} BuildSym; + +/* Build context structure. */ +typedef struct BuildCtx { + /* DynASM state pointer. Should be first member. */ + struct dasm_State *D; + /* Parsed command line. */ + BuildMode mode; + FILE *fp; + const char *outname; + char **args; + /* Code and symbols generated by DynASM. */ + uint8_t *code; + size_t codesz; + int npc, nglob, nsym, nreloc, nrelocsym; + void **glob; + BuildSym *sym; + const char **relocsym; + int32_t *bc_ofs; + const char *beginsym; + /* Strings generated by DynASM. */ + const char *const *globnames; + const char *dasm_ident; + const char *dasm_arch; + /* Relocations. */ + BuildReloc reloc[BUILD_MAX_RELOC]; +} BuildCtx; + +extern void owrite(BuildCtx *ctx, const void *ptr, size_t sz); +extern void emit_asm(BuildCtx *ctx); +extern void emit_peobj(BuildCtx *ctx); +extern void emit_lib(BuildCtx *ctx); +extern void emit_fold(BuildCtx *ctx); + +extern const char *const bc_names[]; +extern const char *const ir_names[]; +extern const char *const irt_names[]; +extern const char *const irfpm_names[]; +extern const char *const irfield_names[]; +extern const char *const ircall_names[]; + +#endif diff --git a/src/host/buildvm_asm.c b/src/host/buildvm_asm.c new file mode 100644 index 00000000..f975eadc --- /dev/null +++ b/src/host/buildvm_asm.c @@ -0,0 +1,283 @@ +/* +** LuaJIT VM builder: Assembler source code emitter. +** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +*/ + +#include "buildvm.h" +#include "lj_bc.h" + +/* ------------------------------------------------------------------------ */ + +#if LJ_TARGET_X86ORX64 +/* Emit bytes piecewise as assembler text. */ +static void emit_asm_bytes(BuildCtx *ctx, uint8_t *p, int n) +{ + int i; + for (i = 0; i < n; i++) { + if ((i & 15) == 0) + fprintf(ctx->fp, "\t.byte %d", p[i]); + else + fprintf(ctx->fp, ",%d", p[i]); + if ((i & 15) == 15) putc('\n', ctx->fp); + } + if ((n & 15) != 0) putc('\n', ctx->fp); +} + +/* Emit relocation */ +static void emit_asm_reloc(BuildCtx *ctx, int type, const char *sym) +{ + switch (ctx->mode) { + case BUILD_elfasm: + if (type) + fprintf(ctx->fp, "\t.long %s-.-4\n", sym); + else + fprintf(ctx->fp, "\t.long %s\n", sym); + break; + case BUILD_coffasm: + fprintf(ctx->fp, "\t.def %s; .scl 3; .type 32; .endef\n", sym); + if (type) + fprintf(ctx->fp, "\t.long %s-.-4\n", sym); + else + fprintf(ctx->fp, "\t.long %s\n", sym); + break; + default: /* BUILD_machasm for relative relocations handled below. */ + fprintf(ctx->fp, "\t.long %s\n", sym); + break; + } +} + +static const char *const jccnames[] = { + "jo", "jno", "jb", "jnb", "jz", "jnz", "jbe", "ja", + "js", "jns", "jpe", "jpo", "jl", "jge", "jle", "jg" +}; + +/* Emit relocation for the incredibly stupid OSX assembler. */ +static void emit_asm_reloc_mach(BuildCtx *ctx, uint8_t *cp, int n, + const char *sym) +{ + const char *opname = NULL; + if (--n < 0) goto err; + if (cp[n] == 0xe8) { + opname = "call"; + } else if (cp[n] == 0xe9) { + opname = "jmp"; + } else if (cp[n] >= 0x80 && cp[n] <= 0x8f && n > 0 && cp[n-1] == 0x0f) { + opname = jccnames[cp[n]-0x80]; + n--; + } else { +err: + fprintf(stderr, "Error: unsupported opcode for %s symbol relocation.\n", + sym); + exit(1); + } + emit_asm_bytes(ctx, cp, n); + fprintf(ctx->fp, "\t%s %s\n", opname, sym); +} +#else +/* Emit words piecewise as assembler text. */ +static void emit_asm_words(BuildCtx *ctx, uint8_t *p, int n) +{ + int i; + for (i = 0; i < n; i += 4) { + if ((i & 15) == 0) + fprintf(ctx->fp, "\t.long 0x%08x", *(uint32_t *)(p+i)); + else + fprintf(ctx->fp, ",0x%08x", *(uint32_t *)(p+i)); + if ((i & 15) == 12) putc('\n', ctx->fp); + } + if ((n & 15) != 0) putc('\n', ctx->fp); +} + +/* Emit relocation as part of an instruction. */ +static void emit_asm_wordreloc(BuildCtx *ctx, uint8_t *p, int n, + const char *sym) +{ + uint32_t ins; + emit_asm_words(ctx, p, n-4); + ins = *(uint32_t *)(p+n-4); +#if LJ_TARGET_ARM + if ((ins & 0xff000000u) == 0xfa000000u) { + fprintf(ctx->fp, "\tblx %s\n", sym); + } else if ((ins & 0x0e000000u) == 0x0a000000u) { + fprintf(ctx->fp, "\t%s%.2s %s\n", (ins & 0x01000000u) ? "bl" : "b", + "eqnecsccmiplvsvchilsgeltgtle" + 2*(ins >> 28), sym); + } else { + fprintf(stderr, + "Error: unsupported opcode %08x for %s symbol relocation.\n", + ins, sym); + exit(1); + } +#elif LJ_TARGET_PPC || LJ_TARGET_PPCSPE + if ((ins >> 26) == 16) { + fprintf(ctx->fp, "\t%s %d, %d, %s\n", + (ins & 1) ? "bcl" : "bc", (ins >> 21) & 31, (ins >> 16) & 31, sym); + } else if ((ins >> 26) == 18) { + fprintf(ctx->fp, "\t%s %s\n", (ins & 1) ? "bl" : "b", sym); + } else { + fprintf(stderr, + "Error: unsupported opcode %08x for %s symbol relocation.\n", + ins, sym); + exit(1); + } +#elif LJ_TARGET_MIPS + fprintf(stderr, + "Error: unsupported opcode %08x for %s symbol relocation.\n", + ins, sym); + exit(1); +#else +#error "missing relocation support for this architecture" +#endif +} +#endif + +#if LJ_TARGET_ARM +#define ELFASM_PX "%%" +#else +#define ELFASM_PX "@" +#endif + +/* Emit an assembler label. */ +static void emit_asm_label(BuildCtx *ctx, const char *name, int size, int isfunc) +{ + switch (ctx->mode) { + case BUILD_elfasm: + fprintf(ctx->fp, + "\n\t.globl %s\n" + "\t.hidden %s\n" + "\t.type %s, " ELFASM_PX "%s\n" + "\t.size %s, %d\n" + "%s:\n", + name, name, name, isfunc ? "function" : "object", name, size, name); + break; + case BUILD_coffasm: + fprintf(ctx->fp, "\n\t.globl %s\n", name); + if (isfunc) + fprintf(ctx->fp, "\t.def %s; .scl 3; .type 32; .endef\n", name); + fprintf(ctx->fp, "%s:\n", name); + break; + case BUILD_machasm: + fprintf(ctx->fp, + "\n\t.private_extern %s\n" + "%s:\n", name, name); + break; + default: + break; + } +} + +/* Emit alignment. */ +static void emit_asm_align(BuildCtx *ctx, int bits) +{ + switch (ctx->mode) { + case BUILD_elfasm: + case BUILD_coffasm: + fprintf(ctx->fp, "\t.p2align %d\n", bits); + break; + case BUILD_machasm: + fprintf(ctx->fp, "\t.align %d\n", bits); + break; + default: + break; + } +} + +/* ------------------------------------------------------------------------ */ + +/* Emit assembler source code. */ +void emit_asm(BuildCtx *ctx) +{ + int i, rel; + + fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch); + fprintf(ctx->fp, "\t.text\n"); + emit_asm_align(ctx, 4); + + emit_asm_label(ctx, ctx->beginsym, 0, 0); + if (ctx->mode != BUILD_machasm) + fprintf(ctx->fp, ".Lbegin:\n"); + +#if LJ_TARGET_ARM && defined(__GNUC__) && !defined(LUAJIT_NO_UNWIND) + /* This should really be moved into buildvm_arm.dasc. */ + fprintf(ctx->fp, + ".fnstart\n" + ".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" + ".pad #28\n"); +#endif +#if LJ_TARGET_MIPS + fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n"); +#endif + + for (i = rel = 0; i < ctx->nsym; i++) { + int32_t ofs = ctx->sym[i].ofs; + int32_t next = ctx->sym[i+1].ofs; +#if LJ_TARGET_ARM && defined(__GNUC__) && !defined(LUAJIT_NO_UNWIND) && \ + LJ_HASFFI + if (!strcmp(ctx->sym[i].name, "lj_vm_ffi_call")) + fprintf(ctx->fp, + ".globl lj_err_unwind_arm\n" + ".personality lj_err_unwind_arm\n" + ".fnend\n" + ".fnstart\n" + ".save {r4, r5, r11, lr}\n" + ".setfp r11, sp\n"); +#endif + emit_asm_label(ctx, ctx->sym[i].name, next - ofs, 1); + while (rel < ctx->nreloc && ctx->reloc[rel].ofs <= next) { + BuildReloc *r = &ctx->reloc[rel]; + int n = r->ofs - ofs; +#if LJ_TARGET_X86ORX64 + if (ctx->mode == BUILD_machasm && r->type != 0) { + emit_asm_reloc_mach(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]); + } else { + emit_asm_bytes(ctx, ctx->code+ofs, n); + emit_asm_reloc(ctx, r->type, ctx->relocsym[r->sym]); + } + ofs += n+4; +#else + emit_asm_wordreloc(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]); + ofs += n; +#endif + rel++; + } +#if LJ_TARGET_X86ORX64 + emit_asm_bytes(ctx, ctx->code+ofs, next-ofs); +#else + emit_asm_words(ctx, ctx->code+ofs, next-ofs); +#endif + } + +#if LJ_TARGET_ARM && defined(__GNUC__) && !defined(LUAJIT_NO_UNWIND) + fprintf(ctx->fp, +#if !LJ_HASFFI + ".globl lj_err_unwind_arm\n" + ".personality lj_err_unwind_arm\n" +#endif + ".fnend\n"); +#endif + + fprintf(ctx->fp, "\n"); + switch (ctx->mode) { + case BUILD_elfasm: + fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n"); +#if LJ_TARGET_PPCSPE + /* Soft-float ABI + SPE. */ + fprintf(ctx->fp, "\t.gnu_attribute 4, 2\n\t.gnu_attribute 8, 3\n"); +#elif LJ_TARGET_PPC + /* Hard-float ABI. */ + fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n"); +#endif + /* fallthrough */ + case BUILD_coffasm: + fprintf(ctx->fp, "\t.ident \"%s\"\n", ctx->dasm_ident); + break; + case BUILD_machasm: + fprintf(ctx->fp, + "\t.cstring\n" + "\t.ascii \"%s\\0\"\n", ctx->dasm_ident); + break; + default: + break; + } + fprintf(ctx->fp, "\n"); +} + diff --git a/src/host/buildvm_fold.c b/src/host/buildvm_fold.c new file mode 100644 index 00000000..73f4f80a --- /dev/null +++ b/src/host/buildvm_fold.c @@ -0,0 +1,229 @@ +/* +** LuaJIT VM builder: IR folding hash table generator. +** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +*/ + +#include "buildvm.h" +#include "lj_obj.h" +#include "lj_ir.h" + +/* Context for the folding hash table generator. */ +static int lineno; +static int funcidx; +static uint32_t foldkeys[BUILD_MAX_FOLD]; +static uint32_t nkeys; + +/* Try to fill the hash table with keys using the hash parameters. */ +static int tryhash(uint32_t *htab, uint32_t sz, uint32_t r, int dorol) +{ + uint32_t i; + if (dorol && ((r & 31) == 0 || (r>>5) == 0)) + return 0; /* Avoid zero rotates. */ + memset(htab, 0xff, (sz+1)*sizeof(uint32_t)); + for (i = 0; i < nkeys; i++) { + uint32_t key = foldkeys[i]; + uint32_t k = key & 0xffffff; + uint32_t h = (dorol ? lj_rol(lj_rol(k, r>>5) - k, r&31) : + (((k << (r>>5)) - k) << (r&31))) % sz; + if (htab[h] != 0xffffffff) { /* Collision on primary slot. */ + if (htab[h+1] != 0xffffffff) { /* Collision on secondary slot. */ + /* Try to move the colliding key, if possible. */ + if (h < sz-1 && htab[h+2] == 0xffffffff) { + uint32_t k2 = htab[h+1] & 0xffffff; + uint32_t h2 = (dorol ? lj_rol(lj_rol(k2, r>>5) - k2, r&31) : + (((k2 << (r>>5)) - k2) << (r&31))) % sz; + if (h2 != h+1) return 0; /* Cannot resolve collision. */ + htab[h+2] = htab[h+1]; /* Move colliding key to secondary slot. */ + } else { + return 0; /* Collision. */ + } + } + htab[h+1] = key; + } else { + htab[h] = key; + } + } + return 1; /* Success, all keys could be stored. */ +} + +/* Print the generated hash table. */ +static void printhash(BuildCtx *ctx, uint32_t *htab, uint32_t sz) +{ + uint32_t i; + fprintf(ctx->fp, "static const uint32_t fold_hash[%d] = {\n0x%08x", + sz+1, htab[0]); + for (i = 1; i < sz+1; i++) + fprintf(ctx->fp, ",\n0x%08x", htab[i]); + fprintf(ctx->fp, "\n};\n\n"); +} + +/* Exhaustive search for the shortest semi-perfect hash table. */ +static void makehash(BuildCtx *ctx) +{ + uint32_t htab[BUILD_MAX_FOLD*2+1]; + uint32_t sz, r; + /* Search for the smallest hash table with an odd size. */ + for (sz = (nkeys|1); sz < BUILD_MAX_FOLD*2; sz += 2) { + /* First try all shift hash combinations. */ + for (r = 0; r < 32*32; r++) { + if (tryhash(htab, sz, r, 0)) { + printhash(ctx, htab, sz); + fprintf(ctx->fp, + "#define fold_hashkey(k)\t(((((k)<<%u)-(k))<<%u)%%%u)\n\n", + r>>5, r&31, sz); + return; + } + } + /* Then try all rotate hash combinations. */ + for (r = 0; r < 32*32; r++) { + if (tryhash(htab, sz, r, 1)) { + printhash(ctx, htab, sz); + fprintf(ctx->fp, + "#define fold_hashkey(k)\t(lj_rol(lj_rol((k),%u)-(k),%u)%%%u)\n\n", + r>>5, r&31, sz); + return; + } + } + } + fprintf(stderr, "Error: search for perfect hash failed\n"); + exit(1); +} + +/* Parse one token of a fold rule. */ +static uint32_t nexttoken(char **pp, int allowlit, int allowany) +{ + char *p = *pp; + if (p) { + uint32_t i; + char *q = strchr(p, ' '); + if (q) *q++ = '\0'; + *pp = q; + if (allowlit && !strncmp(p, "IRFPM_", 6)) { + for (i = 0; irfpm_names[i]; i++) + if (!strcmp(irfpm_names[i], p+6)) + return i; + } else if (allowlit && !strncmp(p, "IRFL_", 5)) { + for (i = 0; irfield_names[i]; i++) + if (!strcmp(irfield_names[i], p+5)) + return i; + } else if (allowlit && !strncmp(p, "IRCALL_", 7)) { + for (i = 0; ircall_names[i]; i++) + if (!strcmp(ircall_names[i], p+7)) + return i; + } else if (allowlit && !strncmp(p, "IRCONV_", 7)) { + for (i = 0; irt_names[i]; i++) { + const char *r = strchr(p+7, '_'); + if (r && !strncmp(irt_names[i], p+7, r-(p+7))) { + uint32_t j; + for (j = 0; irt_names[j]; j++) + if (!strcmp(irt_names[j], r+1)) + return (i << 5) + j; + } + } + } else if (allowlit && *p >= '0' && *p <= '9') { + for (i = 0; *p >= '0' && *p <= '9'; p++) + i = i*10 + (*p - '0'); + if (*p == '\0') + return i; + } else if (allowany && !strcmp("any", p)) { + return allowany; + } else { + for (i = 0; ir_names[i]; i++) + if (!strcmp(ir_names[i], p)) + return i; + } + fprintf(stderr, "Error: bad fold definition token \"%s\" at line %d\n", p, lineno); + exit(1); + } + return 0; +} + +/* Parse a fold rule. */ +static void foldrule(char *p) +{ + uint32_t op = nexttoken(&p, 0, 0); + uint32_t left = nexttoken(&p, 0, 0x7f); + uint32_t right = nexttoken(&p, 1, 0x3ff); + uint32_t key = (funcidx << 24) | (op << 17) | (left << 10) | right; + uint32_t i; + if (nkeys >= BUILD_MAX_FOLD) { + fprintf(stderr, "Error: too many fold rules, increase BUILD_MAX_FOLD.\n"); + exit(1); + } + /* Simple insertion sort to detect duplicates. */ + for (i = nkeys; i > 0; i--) { + if ((foldkeys[i-1]&0xffffff) < (key & 0xffffff)) + break; + if ((foldkeys[i-1]&0xffffff) == (key & 0xffffff)) { + fprintf(stderr, "Error: duplicate fold definition at line %d\n", lineno); + exit(1); + } + foldkeys[i] = foldkeys[i-1]; + } + foldkeys[i] = key; + nkeys++; +} + +/* Emit C source code for IR folding hash table. */ +void emit_fold(BuildCtx *ctx) +{ + char buf[256]; /* We don't care about analyzing lines longer than that. */ + const char *fname = ctx->args[0]; + FILE *fp; + + if (fname == NULL) { + fprintf(stderr, "Error: missing input filename\n"); + exit(1); + } + + if (fname[0] == '-' && fname[1] == '\0') { + fp = stdin; + } else { + fp = fopen(fname, "r"); + if (!fp) { + fprintf(stderr, "Error: cannot open input file '%s': %s\n", + fname, strerror(errno)); + exit(1); + } + } + + fprintf(ctx->fp, "/* This is a generated file. DO NOT EDIT! */\n\n"); + fprintf(ctx->fp, "static const FoldFunc fold_func[] = {\n"); + + lineno = 0; + funcidx = 0; + nkeys = 0; + while (fgets(buf, sizeof(buf), fp) != NULL) { + lineno++; + /* The prefix must be at the start of a line, otherwise it's ignored. */ + if (!strncmp(buf, FOLDDEF_PREFIX, sizeof(FOLDDEF_PREFIX)-1)) { + char *p = buf+sizeof(FOLDDEF_PREFIX)-1; + char *q = strchr(p, ')'); + if (p[0] == '(' && q) { + p++; + *q = '\0'; + foldrule(p); + } else if ((p[0] == 'F' || p[0] == 'X') && p[1] == '(' && q) { + p += 2; + *q = '\0'; + if (funcidx) + fprintf(ctx->fp, ",\n"); + if (p[-2] == 'X') + fprintf(ctx->fp, " %s", p); + else + fprintf(ctx->fp, " fold_%s", p); + funcidx++; + } else { + buf[strlen(buf)-1] = '\0'; + fprintf(stderr, "Error: unknown fold definition tag %s%s at line %d\n", + FOLDDEF_PREFIX, p, lineno); + exit(1); + } + } + } + fclose(fp); + fprintf(ctx->fp, "\n};\n\n"); + + makehash(ctx); +} + diff --git a/src/host/buildvm_lib.c b/src/host/buildvm_lib.c new file mode 100644 index 00000000..3231d3ad --- /dev/null +++ b/src/host/buildvm_lib.c @@ -0,0 +1,377 @@ +/* +** LuaJIT VM builder: library definition compiler. +** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +*/ + +#include "buildvm.h" +#include "lj_obj.h" +#include "lj_lib.h" + +/* Context for library definitions. */ +static uint8_t obuf[8192]; +static uint8_t *optr; +static char modname[80]; +static size_t modnamelen; +static char funcname[80]; +static int modstate, regfunc; +static int ffid, recffid, ffasmfunc; + +enum { + REGFUNC_OK, + REGFUNC_NOREG, + REGFUNC_NOREGUV +}; + +static void libdef_name(const char *p, int kind) +{ + size_t n = strlen(p); + if (kind != LIBINIT_STRING) { + if (n > modnamelen && p[modnamelen] == '_' && + !strncmp(p, modname, modnamelen)) { + p += modnamelen+1; + n -= modnamelen+1; + } + } + if (n > LIBINIT_MAXSTR) { + fprintf(stderr, "Error: string too long: '%s'\n", p); + exit(1); + } + if (optr+1+n+2 > obuf+sizeof(obuf)) { /* +2 for caller. */ + fprintf(stderr, "Error: output buffer overflow\n"); + exit(1); + } + *optr++ = (uint8_t)(n | kind); + memcpy(optr, p, n); + optr += n; +} + +static void libdef_endmodule(BuildCtx *ctx) +{ + if (modstate != 0) { + char line[80]; + const uint8_t *p; + int n; + if (modstate == 1) + fprintf(ctx->fp, " (lua_CFunction)0"); + fprintf(ctx->fp, "\n};\n"); + fprintf(ctx->fp, "static const uint8_t %s%s[] = {\n", + LABEL_PREFIX_LIBINIT, modname); + line[0] = '\0'; + for (n = 0, p = obuf; p < optr; p++) { + n += sprintf(line+n, "%d,", *p); + if (n >= 75) { + fprintf(ctx->fp, "%s\n", line); + n = 0; + line[0] = '\0'; + } + } + fprintf(ctx->fp, "%s%d\n};\n#endif\n\n", line, LIBINIT_END); + } +} + +static void libdef_module(BuildCtx *ctx, char *p, int arg) +{ + UNUSED(arg); + if (ctx->mode == BUILD_libdef) { + libdef_endmodule(ctx); + optr = obuf; + *optr++ = (uint8_t)ffid; + *optr++ = (uint8_t)ffasmfunc; + *optr++ = 0; /* Hash table size. */ + modstate = 1; + fprintf(ctx->fp, "#ifdef %sMODULE_%s\n", LIBDEF_PREFIX, p); + fprintf(ctx->fp, "#undef %sMODULE_%s\n", LIBDEF_PREFIX, p); + fprintf(ctx->fp, "static const lua_CFunction %s%s[] = {\n", + LABEL_PREFIX_LIBCF, p); + } + modnamelen = strlen(p); + if (modnamelen > sizeof(modname)-1) { + fprintf(stderr, "Error: module name too long: '%s'\n", p); + exit(1); + } + strcpy(modname, p); +} + +static int find_ffofs(BuildCtx *ctx, const char *name) +{ + int i; + for (i = 0; i < ctx->nglob; i++) { + const char *gl = ctx->globnames[i]; + if (gl[0] == 'f' && gl[1] == 'f' && gl[2] == '_' && !strcmp(gl+3, name)) { + return (int)((uint8_t *)ctx->glob[i] - ctx->code); + } + } + fprintf(stderr, "Error: undefined fast function %s%s\n", + LABEL_PREFIX_FF, name); + exit(1); +} + +static void libdef_func(BuildCtx *ctx, char *p, int arg) +{ + if (arg != LIBINIT_CF) + ffasmfunc++; + if (ctx->mode == BUILD_libdef) { + if (modstate == 0) { + fprintf(stderr, "Error: no module for function definition %s\n", p); + exit(1); + } + if (regfunc == REGFUNC_NOREG) { + if (optr+1 > obuf+sizeof(obuf)) { + fprintf(stderr, "Error: output buffer overflow\n"); + exit(1); + } + *optr++ = LIBINIT_FFID; + } else { + if (arg != LIBINIT_ASM_) { + if (modstate != 1) fprintf(ctx->fp, ",\n"); + modstate = 2; + fprintf(ctx->fp, " %s%s", arg ? LABEL_PREFIX_FFH : LABEL_PREFIX_CF, p); + } + if (regfunc != REGFUNC_NOREGUV) obuf[2]++; /* Bump hash table size. */ + libdef_name(regfunc == REGFUNC_NOREGUV ? "" : p, arg); + } + } else if (ctx->mode == BUILD_ffdef) { + fprintf(ctx->fp, "FFDEF(%s)\n", p); + } else if (ctx->mode == BUILD_recdef) { + if (strlen(p) > sizeof(funcname)-1) { + fprintf(stderr, "Error: function name too long: '%s'\n", p); + exit(1); + } + strcpy(funcname, p); + } else if (ctx->mode == BUILD_vmdef) { + int i; + for (i = 1; p[i] && modname[i-1]; i++) + if (p[i] == '_') p[i] = '.'; + fprintf(ctx->fp, "\"%s\",\n", p); + } else if (ctx->mode == BUILD_bcdef) { + if (arg != LIBINIT_CF) + fprintf(ctx->fp, ",\n%d", find_ffofs(ctx, p)); + } + ffid++; + regfunc = REGFUNC_OK; +} + +static uint32_t find_rec(char *name) +{ + char *p = (char *)obuf; + uint32_t n; + for (n = 2; *p; n++) { + if (strcmp(p, name) == 0) + return n; + p += strlen(p)+1; + } + if (p+strlen(name)+1 >= (char *)obuf+sizeof(obuf)) { + fprintf(stderr, "Error: output buffer overflow\n"); + exit(1); + } + strcpy(p, name); + return n; +} + +static void libdef_rec(BuildCtx *ctx, char *p, int arg) +{ + UNUSED(arg); + if (ctx->mode == BUILD_recdef) { + char *q; + uint32_t n; + for (; recffid+1 < ffid; recffid++) + fprintf(ctx->fp, ",\n0"); + recffid = ffid; + if (*p == '.') p = funcname; + q = strchr(p, ' '); + if (q) *q++ = '\0'; + n = find_rec(p); + if (q) + fprintf(ctx->fp, ",\n0x%02x00+(%s)", n, q); + else + fprintf(ctx->fp, ",\n0x%02x00", n); + } +} + +static void memcpy_endian(void *dst, void *src, size_t n) +{ + union { uint8_t b; uint32_t u; } host_endian; + host_endian.u = 1; + if (host_endian.b == LJ_ENDIAN_SELECT(1, 0)) { + memcpy(dst, src, n); + } else { + size_t i; + for (i = 0; i < n; i++) + ((uint8_t *)dst)[i] = ((uint8_t *)src)[n-i-1]; + } +} + +static void libdef_push(BuildCtx *ctx, char *p, int arg) +{ + UNUSED(arg); + if (ctx->mode == BUILD_libdef) { + int len = (int)strlen(p); + if (*p == '"') { + if (len > 1 && p[len-1] == '"') { + p[len-1] = '\0'; + libdef_name(p+1, LIBINIT_STRING); + return; + } + } else if (*p >= '0' && *p <= '9') { + char *ep; + double d = strtod(p, &ep); + if (*ep == '\0') { + if (optr+1+sizeof(double) > obuf+sizeof(obuf)) { + fprintf(stderr, "Error: output buffer overflow\n"); + exit(1); + } + *optr++ = LIBINIT_NUMBER; + memcpy_endian(optr, &d, sizeof(double)); + optr += sizeof(double); + return; + } + } else if (!strcmp(p, "lastcl")) { + if (optr+1 > obuf+sizeof(obuf)) { + fprintf(stderr, "Error: output buffer overflow\n"); + exit(1); + } + *optr++ = LIBINIT_LASTCL; + return; + } else if (len > 4 && !strncmp(p, "top-", 4)) { + if (optr+2 > obuf+sizeof(obuf)) { + fprintf(stderr, "Error: output buffer overflow\n"); + exit(1); + } + *optr++ = LIBINIT_COPY; + *optr++ = (uint8_t)atoi(p+4); + return; + } + fprintf(stderr, "Error: bad value for %sPUSH(%s)\n", LIBDEF_PREFIX, p); + exit(1); + } +} + +static void libdef_set(BuildCtx *ctx, char *p, int arg) +{ + UNUSED(arg); + if (ctx->mode == BUILD_libdef) { + if (p[0] == '!' && p[1] == '\0') p[0] = '\0'; /* Set env. */ + libdef_name(p, LIBINIT_STRING); + *optr++ = LIBINIT_SET; + obuf[2]++; /* Bump hash table size. */ + } +} + +static void libdef_regfunc(BuildCtx *ctx, char *p, int arg) +{ + UNUSED(ctx); UNUSED(p); + regfunc = arg; +} + +typedef void (*LibDefFunc)(BuildCtx *ctx, char *p, int arg); + +typedef struct LibDefHandler { + const char *suffix; + const char *stop; + const LibDefFunc func; + const int arg; +} LibDefHandler; + +static const LibDefHandler libdef_handlers[] = { + { "MODULE_", " \t\r\n", libdef_module, 0 }, + { "CF(", ")", libdef_func, LIBINIT_CF }, + { "ASM(", ")", libdef_func, LIBINIT_ASM }, + { "ASM_(", ")", libdef_func, LIBINIT_ASM_ }, + { "REC(", ")", libdef_rec, 0 }, + { "PUSH(", ")", libdef_push, 0 }, + { "SET(", ")", libdef_set, 0 }, + { "NOREGUV", NULL, libdef_regfunc, REGFUNC_NOREGUV }, + { "NOREG", NULL, libdef_regfunc, REGFUNC_NOREG }, + { NULL, NULL, (LibDefFunc)0, 0 } +}; + +/* Emit C source code for library function definitions. */ +void emit_lib(BuildCtx *ctx) +{ + const char *fname; + + if (ctx->mode == BUILD_ffdef || ctx->mode == BUILD_libdef || + ctx->mode == BUILD_recdef) + fprintf(ctx->fp, "/* This is a generated file. DO NOT EDIT! */\n\n"); + else if (ctx->mode == BUILD_vmdef) + fprintf(ctx->fp, "ffnames = {\n[0]=\"Lua\",\n\"C\",\n"); + if (ctx->mode == BUILD_recdef) + fprintf(ctx->fp, "static const uint16_t recff_idmap[] = {\n0,\n0x0100"); + recffid = ffid = FF_C+1; + ffasmfunc = 0; + + while ((fname = *ctx->args++)) { + char buf[256]; /* We don't care about analyzing lines longer than that. */ + FILE *fp; + if (fname[0] == '-' && fname[1] == '\0') { + fp = stdin; + } else { + fp = fopen(fname, "r"); + if (!fp) { + fprintf(stderr, "Error: cannot open input file '%s': %s\n", + fname, strerror(errno)); + exit(1); + } + } + modstate = 0; + regfunc = REGFUNC_OK; + while (fgets(buf, sizeof(buf), fp) != NULL) { + char *p; + for (p = buf; (p = strstr(p, LIBDEF_PREFIX)) != NULL; ) { + const LibDefHandler *ldh; + p += sizeof(LIBDEF_PREFIX)-1; + for (ldh = libdef_handlers; ldh->suffix != NULL; ldh++) { + size_t n, len = strlen(ldh->suffix); + if (!strncmp(p, ldh->suffix, len)) { + p += len; + n = ldh->stop ? strcspn(p, ldh->stop) : 0; + if (!p[n]) break; + p[n] = '\0'; + ldh->func(ctx, p, ldh->arg); + p += n+1; + break; + } + } + if (ldh->suffix == NULL) { + buf[strlen(buf)-1] = '\0'; + fprintf(stderr, "Error: unknown library definition tag %s%s\n", + LIBDEF_PREFIX, p); + exit(1); + } + } + } + fclose(fp); + if (ctx->mode == BUILD_libdef) { + libdef_endmodule(ctx); + } + } + + if (ctx->mode == BUILD_ffdef) { + fprintf(ctx->fp, "\n#undef FFDEF\n\n"); + fprintf(ctx->fp, + "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n", + ffasmfunc); + } else if (ctx->mode == BUILD_vmdef) { + fprintf(ctx->fp, "}\n\n"); + } else if (ctx->mode == BUILD_bcdef) { + int i; + fprintf(ctx->fp, "\n};\n\n"); + fprintf(ctx->fp, "LJ_DATADEF const uint16_t lj_bc_mode[] = {\n"); + fprintf(ctx->fp, "BCDEF(BCMODE)\n"); + for (i = ffasmfunc-1; i > 0; i--) + fprintf(ctx->fp, "BCMODE_FF,\n"); + fprintf(ctx->fp, "BCMODE_FF\n};\n\n"); + } else if (ctx->mode == BUILD_recdef) { + char *p = (char *)obuf; + fprintf(ctx->fp, "\n};\n\n"); + fprintf(ctx->fp, "static const RecordFunc recff_func[] = {\n" + "recff_nyi,\n" + "recff_c"); + while (*p) { + fprintf(ctx->fp, ",\nrecff_%s", p); + p += strlen(p)+1; + } + fprintf(ctx->fp, "\n};\n\n"); + } +} + diff --git a/src/host/buildvm_peobj.c b/src/host/buildvm_peobj.c new file mode 100644 index 00000000..17b3293a --- /dev/null +++ b/src/host/buildvm_peobj.c @@ -0,0 +1,352 @@ +/* +** LuaJIT VM builder: PE object emitter. +** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +** +** Only used for building on Windows, since we cannot assume the presence +** of a suitable assembler. The host and target byte order must match. +*/ + +#include "buildvm.h" +#include "lj_bc.h" + +#if LJ_TARGET_X86ORX64 + +/* Context for PE object emitter. */ +static char *strtab; +static size_t strtabofs; + +/* -- PE object definitions ----------------------------------------------- */ + +/* PE header. */ +typedef struct PEheader { + uint16_t arch; + uint16_t nsects; + uint32_t time; + uint32_t symtabofs; + uint32_t nsyms; + uint16_t opthdrsz; + uint16_t flags; +} PEheader; + +/* PE section. */ +typedef struct PEsection { + char name[8]; + uint32_t vsize; + uint32_t vaddr; + uint32_t size; + uint32_t ofs; + uint32_t relocofs; + uint32_t lineofs; + uint16_t nreloc; + uint16_t nline; + uint32_t flags; +} PEsection; + +/* PE relocation. */ +typedef struct PEreloc { + uint32_t vaddr; + uint32_t symidx; + uint16_t type; +} PEreloc; + +/* Cannot use sizeof, because it pads up to the max. alignment. */ +#define PEOBJ_RELOC_SIZE (4+4+2) + +/* PE symbol table entry. */ +typedef struct PEsym { + union { + char name[8]; + uint32_t nameref[2]; + } n; + uint32_t value; + int16_t sect; + uint16_t type; + uint8_t scl; + uint8_t naux; +} PEsym; + +/* PE symbol table auxiliary entry for a section. */ +typedef struct PEsymaux { + uint32_t size; + uint16_t nreloc; + uint16_t nline; + uint32_t cksum; + uint16_t assoc; + uint8_t comdatsel; + uint8_t unused[3]; +} PEsymaux; + +/* Cannot use sizeof, because it pads up to the max. alignment. */ +#define PEOBJ_SYM_SIZE (8+4+2+2+1+1) + +/* PE object CPU specific defines. */ +#if LJ_TARGET_X86 +#define PEOBJ_ARCH_TARGET 0x014c +#define PEOBJ_RELOC_REL32 0x14 /* MS: REL32, GNU: DISP32. */ +#define PEOBJ_RELOC_DIR32 0x06 +#elif LJ_TARGET_X64 +#define PEOBJ_ARCH_TARGET 0x8664 +#define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */ +#define PEOBJ_RELOC_DIR32 0x02 +#define PEOBJ_RELOC_ADDR32NB 0x03 +#endif + +/* Section numbers (0-based). */ +enum { + PEOBJ_SECT_ABS = -2, + PEOBJ_SECT_UNDEF = -1, + PEOBJ_SECT_TEXT, +#if LJ_TARGET_X64 + PEOBJ_SECT_PDATA, + PEOBJ_SECT_XDATA, +#endif + PEOBJ_SECT_RDATA_Z, + PEOBJ_NSECTIONS +}; + +/* Symbol types. */ +#define PEOBJ_TYPE_NULL 0 +#define PEOBJ_TYPE_FUNC 0x20 + +/* Symbol storage class. */ +#define PEOBJ_SCL_EXTERN 2 +#define PEOBJ_SCL_STATIC 3 + +/* -- PE object emitter --------------------------------------------------- */ + +/* Emit PE object symbol. */ +static void emit_peobj_sym(BuildCtx *ctx, const char *name, uint32_t value, + int sect, int type, int scl) +{ + PEsym sym; + size_t len = strlen(name); + if (!strtab) { /* Pass 1: only calculate string table length. */ + if (len > 8) strtabofs += len+1; + return; + } + if (len <= 8) { + memcpy(sym.n.name, name, len); + memset(sym.n.name+len, 0, 8-len); + } else { + sym.n.nameref[0] = 0; + sym.n.nameref[1] = (uint32_t)strtabofs; + memcpy(strtab + strtabofs, name, len); + strtab[strtabofs+len] = 0; + strtabofs += len+1; + } + sym.value = value; + sym.sect = (int16_t)(sect+1); /* 1-based section number. */ + sym.type = (uint16_t)type; + sym.scl = (uint8_t)scl; + sym.naux = 0; + owrite(ctx, &sym, PEOBJ_SYM_SIZE); +} + +/* Emit PE object section symbol. */ +static void emit_peobj_sym_sect(BuildCtx *ctx, PEsection *pesect, int sect) +{ + PEsym sym; + PEsymaux aux; + if (!strtab) return; /* Pass 1: no output. */ + memcpy(sym.n.name, pesect[sect].name, 8); + sym.value = 0; + sym.sect = (int16_t)(sect+1); /* 1-based section number. */ + sym.type = PEOBJ_TYPE_NULL; + sym.scl = PEOBJ_SCL_STATIC; + sym.naux = 1; + owrite(ctx, &sym, PEOBJ_SYM_SIZE); + memset(&aux, 0, sizeof(PEsymaux)); + aux.size = pesect[sect].size; + aux.nreloc = pesect[sect].nreloc; + owrite(ctx, &aux, PEOBJ_SYM_SIZE); +} + +/* Emit Windows PE object file. */ +void emit_peobj(BuildCtx *ctx) +{ + PEheader pehdr; + PEsection pesect[PEOBJ_NSECTIONS]; + uint32_t sofs; + int i, nrsym; + union { uint8_t b; uint32_t u; } host_endian; + + host_endian.u = 1; + if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) { + fprintf(stderr, "Error: different byte order for host and target\n"); + exit(1); + } + + sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection); + + /* Fill in PE sections. */ + memset(&pesect, 0, PEOBJ_NSECTIONS*sizeof(PEsection)); + memcpy(pesect[PEOBJ_SECT_TEXT].name, ".text", sizeof(".text")-1); + pesect[PEOBJ_SECT_TEXT].ofs = sofs; + sofs += (pesect[PEOBJ_SECT_TEXT].size = (uint32_t)ctx->codesz); + pesect[PEOBJ_SECT_TEXT].relocofs = sofs; + sofs += (pesect[PEOBJ_SECT_TEXT].nreloc = (uint16_t)ctx->nreloc) * PEOBJ_RELOC_SIZE; + /* Flags: 60 = read+execute, 50 = align16, 20 = code. */ + pesect[PEOBJ_SECT_TEXT].flags = 0x60500020; + +#if LJ_TARGET_X64 + memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1); + pesect[PEOBJ_SECT_PDATA].ofs = sofs; + sofs += (pesect[PEOBJ_SECT_PDATA].size = 6*4); + pesect[PEOBJ_SECT_PDATA].relocofs = sofs; + sofs += (pesect[PEOBJ_SECT_PDATA].nreloc = 6) * PEOBJ_RELOC_SIZE; + /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ + pesect[PEOBJ_SECT_PDATA].flags = 0x40300040; + + memcpy(pesect[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1); + pesect[PEOBJ_SECT_XDATA].ofs = sofs; + sofs += (pesect[PEOBJ_SECT_XDATA].size = 8*2+4+6*2); /* See below. */ + pesect[PEOBJ_SECT_XDATA].relocofs = sofs; + sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; + /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ + pesect[PEOBJ_SECT_XDATA].flags = 0x40300040; +#endif + + memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1); + pesect[PEOBJ_SECT_RDATA_Z].ofs = sofs; + sofs += (pesect[PEOBJ_SECT_RDATA_Z].size = (uint32_t)strlen(ctx->dasm_ident)+1); + /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ + pesect[PEOBJ_SECT_RDATA_Z].flags = 0x40300040; + + /* Fill in PE header. */ + pehdr.arch = PEOBJ_ARCH_TARGET; + pehdr.nsects = PEOBJ_NSECTIONS; + pehdr.time = 0; /* Timestamp is optional. */ + pehdr.symtabofs = sofs; + pehdr.opthdrsz = 0; + pehdr.flags = 0; + + /* Compute the size of the symbol table: + ** @feat.00 + nsections*2 + ** + asm_start + nsym + ** + nrsym + */ + nrsym = ctx->nrelocsym; + pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; +#if LJ_TARGET_X64 + pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */ +#endif + + /* Write PE object header and all sections. */ + owrite(ctx, &pehdr, sizeof(PEheader)); + owrite(ctx, &pesect, sizeof(PEsection)*PEOBJ_NSECTIONS); + + /* Write .text section. */ + owrite(ctx, ctx->code, ctx->codesz); + for (i = 0; i < ctx->nreloc; i++) { + PEreloc reloc; + reloc.vaddr = (uint32_t)ctx->reloc[i].ofs; + reloc.symidx = 1+2+ctx->reloc[i].sym; /* Reloc syms are after .text sym. */ + reloc.type = ctx->reloc[i].type ? PEOBJ_RELOC_REL32 : PEOBJ_RELOC_DIR32; + owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); + } + +#if LJ_TARGET_X64 + { /* Write .pdata section. */ + uint32_t fcofs = (uint32_t)ctx->sym[ctx->nsym-1].ofs; + uint32_t pdata[3]; /* Start of .text, end of .text and .xdata. */ + PEreloc reloc; + pdata[0] = 0; pdata[1] = fcofs; pdata[2] = 0; + owrite(ctx, &pdata, sizeof(pdata)); + pdata[0] = fcofs; pdata[1] = (uint32_t)ctx->codesz; pdata[2] = 20; + owrite(ctx, &pdata, sizeof(pdata)); + reloc.vaddr = 0; reloc.symidx = 1+2+nrsym+2+2+1; + reloc.type = PEOBJ_RELOC_ADDR32NB; + owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); + reloc.vaddr = 4; reloc.symidx = 1+2+nrsym+2+2+1; + reloc.type = PEOBJ_RELOC_ADDR32NB; + owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); + reloc.vaddr = 8; reloc.symidx = 1+2+nrsym+2; + reloc.type = PEOBJ_RELOC_ADDR32NB; + owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); + reloc.vaddr = 12; reloc.symidx = 1+2+nrsym+2+2+1; + reloc.type = PEOBJ_RELOC_ADDR32NB; + owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); + reloc.vaddr = 16; reloc.symidx = 1+2+nrsym+2+2+1; + reloc.type = PEOBJ_RELOC_ADDR32NB; + owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); + reloc.vaddr = 20; reloc.symidx = 1+2+nrsym+2; + reloc.type = PEOBJ_RELOC_ADDR32NB; + owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); + } + { /* Write .xdata section. */ + uint16_t xdata[8+2+6]; + PEreloc reloc; + xdata[0] = 0x01|0x08|0x10; /* Ver. 1, uhandler/ehandler, prolog size 0. */ + xdata[1] = 0x0005; /* Number of unwind codes, no frame pointer. */ + xdata[2] = 0x4200; /* Stack offset 4*8+8 = aword*5. */ + xdata[3] = 0x3000; /* Push rbx. */ + xdata[4] = 0x6000; /* Push rsi. */ + xdata[5] = 0x7000; /* Push rdi. */ + xdata[6] = 0x5000; /* Push rbp. */ + xdata[7] = 0; /* Alignment. */ + xdata[8] = xdata[9] = 0; /* Relocated address of exception handler. */ + xdata[10] = 0x01; /* Ver. 1, no handler, prolog size 0. */ + xdata[11] = 0x1504; /* Number of unwind codes, fp = rbp, fpofs = 16. */ + xdata[12] = 0x0300; /* set_fpreg. */ + xdata[13] = 0x0200; /* stack offset 0*8+8 = aword*1. */ + xdata[14] = 0x3000; /* Push rbx. */ + xdata[15] = 0x5000; /* Push rbp. */ + owrite(ctx, &xdata, sizeof(xdata)); + reloc.vaddr = 2*8; reloc.symidx = 1+2+nrsym+2+2; + reloc.type = PEOBJ_RELOC_ADDR32NB; + owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); + } +#endif + + /* Write .rdata$Z section. */ + owrite(ctx, ctx->dasm_ident, strlen(ctx->dasm_ident)+1); + + /* Write symbol table. */ + strtab = NULL; /* 1st pass: collect string sizes. */ + for (;;) { + strtabofs = 4; + /* Mark as SafeSEH compliant. */ + emit_peobj_sym(ctx, "@feat.00", 1, + PEOBJ_SECT_ABS, PEOBJ_TYPE_NULL, PEOBJ_SCL_STATIC); + + emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_TEXT); + for (i = 0; i < nrsym; i++) + emit_peobj_sym(ctx, ctx->relocsym[i], 0, + PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); + +#if LJ_TARGET_X64 + emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); + emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); + emit_peobj_sym(ctx, "lj_err_unwind_win64", 0, + PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); +#endif + + emit_peobj_sym(ctx, ctx->beginsym, 0, + PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN); + for (i = 0; i < ctx->nsym; i++) + emit_peobj_sym(ctx, ctx->sym[i].name, (uint32_t)ctx->sym[i].ofs, + PEOBJ_SECT_TEXT, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); + + emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_RDATA_Z); + + if (strtab) + break; + /* 2nd pass: alloc strtab, write syms and copy strings. */ + strtab = (char *)malloc(strtabofs); + *(uint32_t *)strtab = (uint32_t)strtabofs; + } + + /* Write string table. */ + owrite(ctx, strtab, strtabofs); +} + +#else + +void emit_peobj(BuildCtx *ctx) +{ + UNUSED(ctx); + fprintf(stderr, "Error: no PE object support for this target\n"); + exit(1); +} + +#endif diff --git a/src/msvcbuild.bat b/src/msvcbuild.bat index 63467308..cb973fe4 100644 --- a/src/msvcbuild.bat +++ b/src/msvcbuild.bat @@ -19,17 +19,28 @@ @set LJMT=mt /nologo @set LJLIB=lib /nologo @set DASMDIR=..\dynasm -@set DASM=lua %DASMDIR%\dynasm.lua +@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 -if not exist buildvm_x86.h^ - %DASM% -LN -o buildvm_x86.h buildvm_x86.dasc +%LJCOMPILE% host\minilua.c @if errorlevel 1 goto :BAD -if not exist buildvm_x64win.h^ - %DASM% -LN -D X64 -D X64WIN -o buildvm_x64win.h buildvm_x86.dasc +%LJLINK% /out:minilua.exe minilua.obj @if errorlevel 1 goto :BAD +if exist minilua.exe.manifest^ + %LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe -%LJCOMPILE% /I "." /I %DASMDIR% buildvm*.c +@set DASMFLAGS=-D X64 -D X64WIN +@if defined CPU goto :XCPU +@set CPU=%PROCESSOR_ARCHITECTURE% +:XCPU +@if "%CPU%"=="AMD64" goto :X64 +@if "%CPU%"=="X64" goto :X64 +@set DASMFLAGS= +:X64 +minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h vm_x86.dasc +@if errorlevel 1 goto :BAD + +%LJCOMPILE% /I "." /I %DASMDIR% host\buildvm*.c @if errorlevel 1 goto :BAD %LJLINK% /out:buildvm.exe buildvm*.obj @if errorlevel 1 goto :BAD @@ -85,7 +96,7 @@ if exist lua51.dll.manifest^ if exist luajit.exe.manifest^ %LJMT% -manifest luajit.exe.manifest -outputresource:luajit.exe -@del *.obj *.manifest buildvm.exe +@del *.obj *.manifest minilua.exe buildvm.exe @echo. @echo === Successfully built LuaJIT === diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc new file mode 100644 index 00000000..3a039402 --- /dev/null +++ b/src/vm_arm.dasc @@ -0,0 +1,4121 @@ +|// Low-level VM code for ARM CPUs. +|// Bytecode interpreter, fast functions and helper functions. +|// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +| +|.arch arm +|.section code_op, code_sub +| +|.actionlist build_actionlist +|.globals GLOB_ +|.globalnames globnames +|.externnames extnames +| +|// Note: The ragged indentation of the instructions is intentional. +|// The starting columns indicate data dependencies. +| +|//----------------------------------------------------------------------- +| +|// Fixed register assignments for the interpreter. +| +|// The following must be C callee-save. +|.define MASKR8, r4 // 255*8 constant for fast bytecode decoding. +|.define KBASE, r5 // Constants of current Lua function. +|.define PC, r6 // Next PC. +|.define DISPATCH, r7 // Opcode dispatch table. +|.define LREG, r8 // Register holding lua_State (also in SAVE_L). +| +|// C callee-save in EABI, but often refetched. Temporary in iOS 3.0+. +|.define BASE, r9 // Base of current Lua stack frame. +| +|// The following temporaries are not saved across C calls, except for RA/RC. +|.define RA, r10 // Callee-save. +|.define RC, r11 // Callee-save. +|.define RB, r12 +|.define OP, r12 // Overlaps RB, must not be lr. +|.define INS, lr +| +|// Calling conventions. Also used as temporaries. +|.define CARG1, r0 +|.define CARG2, r1 +|.define CARG3, r2 +|.define CARG4, r3 +|.define CARG12, r0 // For 1st soft-fp double. +|.define CARG34, r2 // For 2nd soft-fp double. +| +|.define CRET1, r0 +|.define CRET2, r1 +| +|// Stack layout while in interpreter. Must match with lj_frame.h. +|.define CFRAME_SPACE, #28 +|.define SAVE_ERRF, [sp, #24] +|.define SAVE_NRES, [sp, #20] +|.define SAVE_CFRAME, [sp, #16] +|.define SAVE_L, [sp, #12] +|.define SAVE_PC, [sp, #8] +|.define SAVE_MULTRES, [sp, #4] +|.define ARG5, [sp] +| +|.define TMPDhi, [sp, #4] +|.define TMPDlo, [sp] +|.define TMPD, [sp] +|.define TMPDp, sp +| +|.macro saveregs +| push {r4, r5, r6, r7, r8, r9, r10, r11, lr} +| sub sp, sp, CFRAME_SPACE +|.endmacro +|.macro restoreregs_ret +| add sp, sp, CFRAME_SPACE +| pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} +|.endmacro +| +|// Type definitions. Some of these are only used for documentation. +|.type L, lua_State, LREG +|.type GL, global_State +|.type TVALUE, TValue +|.type GCOBJ, GCobj +|.type STR, GCstr +|.type TAB, GCtab +|.type LFUNC, GCfuncL +|.type CFUNC, GCfuncC +|.type PROTO, GCproto +|.type UPVAL, GCupval +|.type NODE, Node +|.type NARGS8, int +|.type TRACE, GCtrace +| +|//----------------------------------------------------------------------- +| +|// Trap for not-yet-implemented parts. +|.macro NYI; ud; .endmacro +| +|//----------------------------------------------------------------------- +| +|// Access to frame relative to BASE. +|.define FRAME_FUNC, #-8 +|.define FRAME_PC, #-4 +| +|.macro decode_RA8, dst, ins; and dst, MASKR8, ins, lsr #5; .endmacro +|.macro decode_RB8, dst, ins; and dst, MASKR8, ins, lsr #21; .endmacro +|.macro decode_RC8, dst, ins; and dst, MASKR8, ins, lsr #13; .endmacro +|.macro decode_RD, dst, ins; lsr dst, ins, #16; .endmacro +|.macro decode_OP, dst, ins; and dst, ins, #255; .endmacro +| +|// Instruction fetch. +|.macro ins_NEXT1 +| ldrb OP, [PC] +|.endmacro +|.macro ins_NEXT2 +| ldr INS, [PC], #4 +|.endmacro +|// Instruction decode+dispatch. +|.macro ins_NEXT3 +| ldr OP, [DISPATCH, OP, lsl #2] +| decode_RA8 RA, INS +| decode_RD RC, INS +| bx OP +|.endmacro +|.macro ins_NEXT +| ins_NEXT1 +| ins_NEXT2 +| ins_NEXT3 +|.endmacro +| +|// Instruction footer. +|.if 1 +| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use. +| .define ins_next, ins_NEXT +| .define ins_next_, ins_NEXT +| .define ins_next1, ins_NEXT1 +| .define ins_next2, ins_NEXT2 +| .define ins_next3, ins_NEXT3 +|.else +| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch. +| // Affects only certain kinds of benchmarks (and only with -j off). +| .macro ins_next +| b ->ins_next +| .endmacro +| .macro ins_next1 +| .endmacro +| .macro ins_next2 +| .endmacro +| .macro ins_next3 +| b ->ins_next +| .endmacro +| .macro ins_next_ +| ->ins_next: +| ins_NEXT +| .endmacro +|.endif +| +|// Avoid register name substitution for field name. +#define field_pc pc +| +|// Call decode and dispatch. +|.macro ins_callt +| // BASE = new base, CARG3 = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC +| ldr PC, LFUNC:CARG3->field_pc +| ldrb OP, [PC] // STALL: load PC. early PC. +| ldr INS, [PC], #4 +| ldr OP, [DISPATCH, OP, lsl #2] // STALL: load OP. early OP. +| decode_RA8 RA, INS +| add RA, RA, BASE +| bx OP +|.endmacro +| +|.macro ins_call +| // BASE = new base, CARG3 = LFUNC/CFUNC, RC = nargs*8, PC = caller PC +| str PC, [BASE, FRAME_PC] +| ins_callt // STALL: locked PC. +|.endmacro +| +|//----------------------------------------------------------------------- +| +|// Macros to test operand types. +|.macro checktp, reg, tp; cmn reg, #-tp; .endmacro +|.macro checktpeq, reg, tp; cmneq reg, #-tp; .endmacro +|.macro checktpne, reg, tp; cmnne reg, #-tp; .endmacro +|.macro checkstr, reg, target; checktp reg, LJ_TSTR; bne target; .endmacro +|.macro checktab, reg, target; checktp reg, LJ_TTAB; bne target; .endmacro +|.macro checkfunc, reg, target; checktp reg, LJ_TFUNC; bne target; .endmacro +| +|// Assumes DISPATCH is relative to GL. +#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) +#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) +| +#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) +| +|.macro hotcheck, delta +| lsr CARG1, PC, #1 +| and CARG1, CARG1, #126 +| sub CARG1, CARG1, #-GG_DISP2HOT +| ldrh CARG2, [DISPATCH, CARG1] +| subs CARG2, CARG2, #delta +| strh CARG2, [DISPATCH, CARG1] +|.endmacro +| +|.macro hotloop +| hotcheck HOTCOUNT_LOOP +| blo ->vm_hotloop +|.endmacro +| +|.macro hotcall +| hotcheck HOTCOUNT_CALL +| blo ->vm_hotcall +|.endmacro +| +|// Set current VM state. +|.macro mv_vmstate, reg, st; mvn reg, #LJ_VMST_..st; .endmacro +|.macro st_vmstate, reg; str reg, [DISPATCH, #DISPATCH_GL(vmstate)]; .endmacro +| +|// Move table write barrier back. Overwrites mark and tmp. +|.macro barrierback, tab, mark, tmp +| ldr tmp, [DISPATCH, #DISPATCH_GL(gc.grayagain)] +| bic mark, mark, #LJ_GC_BLACK // black2gray(tab) +| str tab, [DISPATCH, #DISPATCH_GL(gc.grayagain)] +| strb mark, tab->marked +| str tmp, tab->gclist +|.endmacro +| +|.macro IOS, a, b +||if (LJ_TARGET_IOS) { +| a, b +||} +|.endmacro +| +|//----------------------------------------------------------------------- + +#if !LJ_DUALNUM +#error "Only dual-number mode supported for ARM target" +#endif + +/* Generate subroutines used by opcodes and other parts of the VM. */ +/* The .code_sub section should be last to help static branch prediction. */ +static void build_subroutines(BuildCtx *ctx) +{ + |.code_sub + | + |//----------------------------------------------------------------------- + |//-- Return handling ---------------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_returnp: + | // See vm_return. Also: RB = previous base. + | tst PC, #FRAME_P + | beq ->cont_dispatch + | + | // Return from pcall or xpcall fast func. + | ldr PC, [RB, FRAME_PC] // Fetch PC of previous frame. + | mvn CARG2, #~LJ_TTRUE + | mov BASE, RB + | // Prepending may overwrite the pcall frame, so do it at the end. + | str CARG2, [RA, FRAME_PC] // Prepend true to results. + | sub RA, RA, #8 + | + |->vm_returnc: + | add RC, RC, #8 // RC = (nresults+1)*8. + | ands CARG1, PC, #FRAME_TYPE + | str RC, SAVE_MULTRES + | beq ->BC_RET_Z // Handle regular return to Lua. + | + |->vm_return: + | // BASE = base, RA = resultptr, RC/MULTRES = (nresults+1)*8, PC = return + | // CARG1 = PC & FRAME_TYPE + | bic RB, PC, #FRAME_TYPEP + | cmp CARG1, #FRAME_C + | sub RB, BASE, RB // RB = previous base. + | bne ->vm_returnp + | + | str RB, L->base + | ldr KBASE, SAVE_NRES + | mv_vmstate CARG4, C + | sub BASE, BASE, #8 + | subs CARG3, RC, #8 + | lsl KBASE, KBASE, #3 // KBASE = (nresults_wanted+1)*8 + | st_vmstate CARG4 + | beq >2 + |1: + | subs CARG3, CARG3, #8 + | ldrd CARG12, [RA], #8 + | strd CARG12, [BASE], #8 + | bne <1 + |2: + | cmp KBASE, RC // More/less results wanted? + | bne >6 + |3: + | str BASE, L->top // Store new top. + | + |->vm_leave_cp: + | ldr RC, SAVE_CFRAME // Restore previous C frame. + | mov CRET1, #0 // Ok return status for vm_pcall. + | str RC, L->cframe + | + |->vm_leave_unw: + | restoreregs_ret + | + |6: + | blt >7 // Less results wanted? + | // More results wanted. Check stack size and fill up results with nil. + | ldr CARG3, L->maxstack + | mvn CARG2, #~LJ_TNIL + | cmp BASE, CARG3 + | bhs >8 + | str CARG2, [BASE, #4] + | add RC, RC, #8 + | add BASE, BASE, #8 + | b <2 + | + |7: // Less results wanted. + | sub CARG1, RC, KBASE + | cmp KBASE, #0 // LUA_MULTRET+1 case? + | subne BASE, BASE, CARG1 // Either keep top or shrink it. + | b <3 + | + |8: // Corner case: need to grow stack for filling up results. + | // This can happen if: + | // - A C function grows the stack (a lot). + | // - The GC shrinks the stack in between. + | // - A return back from a lua_call() with (high) nresults adjustment. + | str BASE, L->top // Save current top held in BASE (yes). + | mov CARG2, KBASE + | mov CARG1, L + | bl extern lj_state_growstack // (lua_State *L, int n) + | ldr BASE, L->top // Need the (realloced) L->top in BASE. + | b <2 + | + |->vm_unwind_c: // Unwind C stack, return from vm_pcall. + | // (void *cframe, int errcode) + | mov sp, CARG1 + | mov CRET1, CARG2 + |->vm_unwind_c_eh: // Landing pad for external unwinder. + | ldr L, SAVE_L + | mv_vmstate CARG4, C + | ldr GL:CARG3, L->glref + | str CARG4, GL:CARG3->vmstate + | b ->vm_leave_unw + | + |->vm_unwind_ff: // Unwind C stack, return from ff pcall. + | // (void *cframe) + | bic CARG1, CARG1, #~CFRAME_RAWMASK // Use two steps: bic sp is deprecated. + | mov sp, CARG1 + |->vm_unwind_ff_eh: // Landing pad for external unwinder. + | ldr L, SAVE_L + | mov MASKR8, #255 + | mov RC, #16 // 2 results: false + error message. + | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. + | ldr BASE, L->base + | ldr DISPATCH, L->glref // Setup pointer to dispatch table. + | mvn CARG1, #~LJ_TFALSE + | sub RA, BASE, #8 // Results start at BASE-8. + | ldr PC, [BASE, FRAME_PC] // Fetch PC of previous frame. + | add DISPATCH, DISPATCH, #GG_G2DISP + | mv_vmstate CARG2, INTERP + | str CARG1, [BASE, #-4] // Prepend false to error message. + | st_vmstate CARG2 + | b ->vm_returnc + | + |//----------------------------------------------------------------------- + |//-- Grow stack for calls ----------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_growstack_c: // Grow stack for C function. + | // CARG1 = L + | mov CARG2, #LUA_MINSTACK + | b >2 + | + |->vm_growstack_l: // Grow stack for Lua function. + | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC + | add RC, BASE, RC + | sub RA, RA, BASE + | mov CARG1, L + | str BASE, L->base + | add PC, PC, #4 // Must point after first instruction. + | str RC, L->top + | lsr CARG3, RA, #3 + |2: + | // L->base = new base, L->top = top + | str PC, SAVE_PC + | bl extern lj_state_growstack // (lua_State *L, int n) + | ldr BASE, L->base + | ldr RC, L->top + | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] + | sub NARGS8:RC, RC, BASE + | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC + | ins_callt // Just retry the call. + | + |//----------------------------------------------------------------------- + |//-- Entry points into the assembler VM --------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_resume: // Setup C frame and resume thread. + | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0) + | saveregs + | mov L, CARG1 + | ldr DISPATCH, L:CARG1->glref // Setup pointer to dispatch table. + | mov BASE, CARG2 + | add DISPATCH, DISPATCH, #GG_G2DISP + | str L, SAVE_L + | mov PC, #FRAME_CP + | str CARG3, SAVE_NRES + | add CARG2, sp, #CFRAME_RESUME + | ldrb CARG1, L->status + | str CARG3, SAVE_ERRF + | str CARG2, L->cframe + | str CARG3, SAVE_CFRAME + | cmp CARG1, #0 + | str L, SAVE_PC // Any value outside of bytecode is ok. + | beq >3 + | + | // Resume after yield (like a return). + | mov RA, BASE + | ldr BASE, L->base + | ldr CARG1, L->top + | mov MASKR8, #255 + | strb CARG3, L->status + | sub RC, CARG1, BASE + | ldr PC, [BASE, FRAME_PC] + | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. + | mv_vmstate CARG2, INTERP + | add RC, RC, #8 + | ands CARG1, PC, #FRAME_TYPE + | st_vmstate CARG2 + | str RC, SAVE_MULTRES + | beq ->BC_RET_Z + | b ->vm_return + | + |->vm_pcall: // Setup protected C frame and enter VM. + | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef) + | saveregs + | mov PC, #FRAME_CP + | str CARG4, SAVE_ERRF + | b >1 + | + |->vm_call: // Setup C frame and enter VM. + | // (lua_State *L, TValue *base, int nres1) + | saveregs + | mov PC, #FRAME_C + | + |1: // Entry point for vm_pcall above (PC = ftype). + | ldr RC, L:CARG1->cframe + | str CARG3, SAVE_NRES + | mov L, CARG1 + | str CARG1, SAVE_L + | mov BASE, CARG2 + | str sp, L->cframe // Add our C frame to cframe chain. + | ldr DISPATCH, L->glref // Setup pointer to dispatch table. + | str CARG1, SAVE_PC // Any value outside of bytecode is ok. + | str RC, SAVE_CFRAME + | add DISPATCH, DISPATCH, #GG_G2DISP + | + |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype). + | ldr RB, L->base // RB = old base (for vmeta_call). + | ldr CARG1, L->top + | mov MASKR8, #255 + | add PC, PC, BASE + | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. + | sub PC, PC, RB // PC = frame delta + frame type + | mv_vmstate CARG2, INTERP + | sub NARGS8:RC, CARG1, BASE + | st_vmstate CARG2 + | + |->vm_call_dispatch: + | // RB = old base, BASE = new base, RC = nargs*8, PC = caller PC + | ldrd CARG34, [BASE, FRAME_FUNC] + | checkfunc CARG4, ->vmeta_call + | + |->vm_call_dispatch_f: + | ins_call + | // BASE = new base, CARG3 = func, RC = nargs*8, PC = caller PC + | + |->vm_cpcall: // Setup protected C frame, call C. + | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp) + | saveregs + | mov L, CARG1 + | ldr RA, L:CARG1->stack + | str CARG1, SAVE_L + | ldr RB, L->top + | str CARG1, SAVE_PC // Any value outside of bytecode is ok. + | ldr RC, L->cframe + | sub RA, RA, RB // Compute -savestack(L, L->top). + | str sp, L->cframe // Add our C frame to cframe chain. + | mov RB, #0 + | str RA, SAVE_NRES // Neg. delta means cframe w/o frame. + | str RB, SAVE_ERRF // No error function. + | str RC, SAVE_CFRAME + | blx CARG4 // (lua_State *L, lua_CFunction func, void *ud) + | ldr DISPATCH, L->glref // Setup pointer to dispatch table. + | movs BASE, CRET1 + | mov PC, #FRAME_CP + | add DISPATCH, DISPATCH, #GG_G2DISP + | bne <3 // Else continue with the call. + | b ->vm_leave_cp // No base? Just remove C frame. + | + |//----------------------------------------------------------------------- + |//-- Metamethod handling ------------------------------------------------ + |//----------------------------------------------------------------------- + | + |//-- Continuation dispatch ---------------------------------------------- + | + |->cont_dispatch: + | // BASE = meta base, RA = resultptr, RC = (nresults+1)*8 + | ldr LFUNC:CARG3, [RB, FRAME_FUNC] + | ldr CARG1, [BASE, #-16] // Get continuation. + | mov CARG4, BASE + | mov BASE, RB // Restore caller BASE. +#if LJ_HASFFI + | 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 LJ_HASFFI + | bls >1 +#endif + | ldr KBASE, [CARG3, #PC2PROTO(k)] + | // BASE = base, RA = resultptr, CARG4 = meta base + | bx CARG1 + | +#if LJ_HASFFI + |1: + | beq ->cont_ffi_callback // cont = 1: return from FFI callback. + | // cont = 0: tailcall from C function. + | ldr CARG3, [BASE, FRAME_FUNC] + | sub CARG4, CARG4, #16 + | sub RC, CARG4, BASE + | b ->vm_call_tail +#endif + | + |->cont_cat: // RA = resultptr, CARG4 = meta base + | ldr INS, [PC, #-4] + | sub CARG2, CARG4, #16 + | ldrd CARG34, [RA] + | str BASE, L->base + | decode_RB8 RC, INS + | decode_RA8 RA, INS + | add CARG1, BASE, RC + | subs CARG1, CARG2, CARG1 + | strdne CARG34, [CARG2] + | movne CARG3, CARG1 + | bne ->BC_CAT_Z + | strd CARG34, [BASE, RA] + | b ->cont_nop + | + |//-- Table indexing metamethods ----------------------------------------- + | + |->vmeta_tgets1: + | add CARG2, BASE, RB + | b >2 + | + |->vmeta_tgets: + | sub CARG2, DISPATCH, #-DISPATCH_GL(tmptv) + | mvn CARG4, #~LJ_TTAB + | str TAB:RB, [CARG2] + | str CARG4, [CARG2, #4] + |2: + | mvn CARG4, #~LJ_TSTR + | str STR:RC, TMPDlo + | str CARG4, TMPDhi + | mov CARG3, TMPDp + | b >1 + | + |->vmeta_tgetb: // RC = index + | decode_RB8 RB, INS + | str RC, TMPDlo + | mvn CARG4, #~LJ_TISNUM + | add CARG2, BASE, RB + | str CARG4, TMPDhi + | mov CARG3, TMPDp + | b >1 + | + |->vmeta_tgetv: + | add CARG2, BASE, RB + | add CARG3, BASE, RC + |1: + | str BASE, L->base + | mov CARG1, L + | str PC, SAVE_PC + | bl extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k) + | // Returns TValue * (finished) or NULL (metamethod). + | IOS ldr BASE, L->base + | cmp CRET1, #0 + | beq >3 + | ldrd CARG34, [CRET1] + | ins_next1 + | ins_next2 + | strd CARG34, [BASE, RA] + | ins_next3 + | + |3: // Call __index metamethod. + | // BASE = base, L->top = new base, stack = cont/func/t/k + | rsb CARG1, BASE, #FRAME_CONT + | ldr BASE, L->top + | mov NARGS8:RC, #16 // 2 args for func(t, k). + | str PC, [BASE, #-12] // [cont|PC] + | add PC, CARG1, BASE + | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. + | b ->vm_call_dispatch_f + | + |//----------------------------------------------------------------------- + | + |->vmeta_tsets1: + | add CARG2, BASE, RB + | b >2 + | + |->vmeta_tsets: + | sub CARG2, DISPATCH, #-DISPATCH_GL(tmptv) + | mvn CARG4, #~LJ_TTAB + | str TAB:RB, [CARG2] + | str CARG4, [CARG2, #4] + |2: + | mvn CARG4, #~LJ_TSTR + | str STR:RC, TMPDlo + | str CARG4, TMPDhi + | mov CARG3, TMPDp + | b >1 + | + |->vmeta_tsetb: // RC = index + | decode_RB8 RB, INS + | str RC, TMPDlo + | mvn CARG4, #~LJ_TISNUM + | add CARG2, BASE, RB + | str CARG4, TMPDhi + | mov CARG3, TMPDp + | b >1 + | + |->vmeta_tsetv: + | add CARG2, BASE, RB + | add CARG3, BASE, RC + |1: + | str BASE, L->base + | mov CARG1, L + | str PC, SAVE_PC + | bl extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k) + | // Returns TValue * (finished) or NULL (metamethod). + | IOS ldr BASE, L->base + | cmp CRET1, #0 + | ldrd CARG34, [BASE, RA] + | beq >3 + | ins_next1 + | // NOBARRIER: lj_meta_tset ensures the table is not black. + | strd CARG34, [CRET1] + | ins_next2 + | ins_next3 + | + |3: // Call __newindex metamethod. + | // BASE = base, L->top = new base, stack = cont/func/t/k/(v) + | rsb CARG1, BASE, #FRAME_CONT + | ldr BASE, L->top + | mov NARGS8:RC, #24 // 3 args for func(t, k, v). + | strd CARG34, [BASE, #16] // Copy value to third argument. + | str PC, [BASE, #-12] // [cont|PC] + | add PC, CARG1, BASE + | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. + | b ->vm_call_dispatch_f + | + |//-- Comparison metamethods --------------------------------------------- + | + |->vmeta_comp: + | mov CARG1, L + | sub PC, PC, #4 + | mov CARG2, RA + | str BASE, L->base + | mov CARG3, RC + | str PC, SAVE_PC + | decode_OP CARG4, INS + | bl extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op) + | // Returns 0/1 or TValue * (metamethod). + |3: + | IOS ldr BASE, L->base + | cmp CRET1, #1 + | bhi ->vmeta_binop + |4: + | ldrh RB, [PC, #2] + | add PC, PC, #4 + | add RB, PC, RB, lsl #2 + | subhs PC, RB, #0x20000 + |->cont_nop: + | ins_next + | + |->cont_ra: // RA = resultptr + | ldr INS, [PC, #-4] + | ldrd CARG12, [RA] + | decode_RA8 CARG3, INS + | strd CARG12, [BASE, CARG3] + | b ->cont_nop + | + |->cont_condt: // RA = resultptr + | ldr CARG2, [RA, #4] + | mvn CARG1, #~LJ_TTRUE + | cmp CARG1, CARG2 // Branch if result is true. + | b <4 + | + |->cont_condf: // RA = resultptr + | ldr CARG2, [RA, #4] + | checktp CARG2, LJ_TFALSE // Branch if result is false. + | b <4 + | + |->vmeta_equal: + | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV. + | sub PC, PC, #4 + | str BASE, L->base + | mov CARG1, L + | str PC, SAVE_PC + | bl extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne) + | // Returns 0/1 or TValue * (metamethod). + | b <3 + | + |->vmeta_equal_cd: +#if LJ_HASFFI + | sub PC, PC, #4 + | str BASE, L->base + | mov CARG1, L + | mov CARG2, INS + | str PC, SAVE_PC + | bl extern lj_meta_equal_cd // (lua_State *L, BCIns op) + | // Returns 0/1 or TValue * (metamethod). + | b <3 +#endif + | + |//-- Arithmetic metamethods --------------------------------------------- + | + |->vmeta_arith_vn: + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | add CARG3, BASE, RB + | add CARG4, KBASE, RC + | b >1 + | + |->vmeta_arith_nv: + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | add CARG4, BASE, RB + | add CARG3, KBASE, RC + | b >1 + | + |->vmeta_unm: + | ldr INS, [PC, #-8] + | sub PC, PC, #4 + | add CARG3, BASE, RC + | add CARG4, BASE, RC + | b >1 + | + |->vmeta_arith_vv: + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | add CARG3, BASE, RB + | add CARG4, BASE, RC + |1: + | decode_OP OP, INS + | add CARG2, BASE, RA + | str BASE, L->base + | mov CARG1, L + | str PC, SAVE_PC + | str OP, ARG5 + | bl extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op) + | // Returns NULL (finished) or TValue * (metamethod). + | IOS ldr BASE, L->base + | cmp CRET1, #0 + | beq ->cont_nop + | + | // Call metamethod for binary op. + |->vmeta_binop: + | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2 + | sub CARG2, CRET1, BASE + | str PC, [CRET1, #-12] // [cont|PC] + | add PC, CARG2, #FRAME_CONT + | mov BASE, CRET1 + | mov NARGS8:RC, #16 // 2 args for func(o1, o2). + | b ->vm_call_dispatch + | + |->vmeta_len: + | add CARG2, BASE, RC + | str BASE, L->base + | mov CARG1, L + | str PC, SAVE_PC + | bl extern lj_meta_len // (lua_State *L, TValue *o) + | // Returns NULL (retry) or TValue * (metamethod base). + | IOS ldr BASE, L->base +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | cmp CRET1, #0 + | bne ->vmeta_binop // Binop call for compatibility. + | ldr TAB:CARG1, [BASE, RC] + | b ->BC_LEN_Z +#else + | b ->vmeta_binop // Binop call for compatibility. +#endif + | + |//-- Call metamethod ---------------------------------------------------- + | + |->vmeta_call: // Resolve and call __call metamethod. + | // RB = old base, BASE = new base, RC = nargs*8 + | mov CARG1, L + | str RB, L->base // This is the callers base! + | sub CARG2, BASE, #8 + | str PC, SAVE_PC + | add CARG3, BASE, NARGS8:RC + | IOS mov RA, BASE + | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) + | IOS mov BASE, RA + | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. + | add NARGS8:RC, NARGS8:RC, #8 // Got one more argument now. + | ins_call + | + |->vmeta_callt: // Resolve __call for BC_CALLT. + | // BASE = old base, RA = new base, RC = nargs*8 + | mov CARG1, L + | str BASE, L->base + | sub CARG2, RA, #8 + | str PC, SAVE_PC + | add CARG3, RA, NARGS8:RC + | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) + | IOS ldr BASE, L->base + | ldr LFUNC:CARG3, [RA, FRAME_FUNC] // Guaranteed to be a function here. + | ldr PC, [BASE, FRAME_PC] + | add NARGS8:RC, NARGS8:RC, #8 // Got one more argument now. + | b ->BC_CALLT2_Z + | + |//-- Argument coercion for 'for' statement ------------------------------ + | + |->vmeta_for: + | mov CARG1, L + | str BASE, L->base + | mov CARG2, RA + | str PC, SAVE_PC + | bl extern lj_meta_for // (lua_State *L, TValue *base) + | IOS ldr BASE, L->base +#if LJ_HASJIT + | ldrb OP, [PC, #-4] +#endif + | ldr INS, [PC, #-4] +#if LJ_HASJIT + | cmp OP, #BC_JFORI +#endif + | decode_RA8 RA, INS + | decode_RD RC, INS +#if LJ_HASJIT + | beq =>BC_JFORI +#endif + | b =>BC_FORI + | + |//----------------------------------------------------------------------- + |//-- Fast functions ----------------------------------------------------- + |//----------------------------------------------------------------------- + | + |.macro .ffunc, name + |->ff_ .. name: + |.endmacro + | + |.macro .ffunc_1, name + |->ff_ .. name: + | ldrd CARG12, [BASE] + | cmp NARGS8:RC, #8 + | blo ->fff_fallback + |.endmacro + | + |.macro .ffunc_2, name + |->ff_ .. name: + | ldrd CARG12, [BASE] + | ldrd CARG34, [BASE, #8] + | cmp NARGS8:RC, #16 + | blo ->fff_fallback + |.endmacro + | + |.macro .ffunc_n, name + | .ffunc_1 name + | checktp CARG2, LJ_TISNUM + | bhs ->fff_fallback + |.endmacro + | + |.macro .ffunc_nn, name + | .ffunc_2 name + | checktp CARG2, LJ_TISNUM + | cmnlo CARG4, #-LJ_TISNUM + | bhs ->fff_fallback + |.endmacro + | + |// Inlined GC threshold check. Caveat: uses CARG1 and CARG2. + |.macro ffgccheck + | ldr CARG1, [DISPATCH, #DISPATCH_GL(gc.total)] + | ldr CARG2, [DISPATCH, #DISPATCH_GL(gc.threshold)] + | cmp CARG1, CARG2 + | blge ->fff_gcstep + |.endmacro + | + |//-- Base library: checks ----------------------------------------------- + | + |.ffunc_1 assert + | checktp CARG2, LJ_TTRUE + | bhi ->fff_fallback + | ldr PC, [BASE, FRAME_PC] + | strd CARG12, [BASE, #-8] + | mov RB, BASE + | subs RA, NARGS8:RC, #8 + | add RC, NARGS8:RC, #8 // Compute (nresults+1)*8. + | beq ->fff_res // Done if exactly 1 argument. + |1: + | ldrd CARG12, [RB, #8] + | subs RA, RA, #8 + | strd CARG12, [RB], #8 + | bne <1 + | b ->fff_res + | + |.ffunc type + | ldr CARG2, [BASE, #4] + | cmp NARGS8:RC, #8 + | blo ->fff_fallback + | checktp CARG2, LJ_TISNUM + | mvnlo CARG2, #~LJ_TISNUM + | rsb CARG4, CARG2, #(int)(offsetof(GCfuncC, upvalue)>>3)-1 + | lsl CARG4, CARG4, #3 + | ldrd CARG12, [CFUNC:CARG3, CARG4] + | b ->fff_restv + | + |//-- Base library: getters and setters --------------------------------- + | + |.ffunc_1 getmetatable + | checktp CARG2, LJ_TTAB + | cmnne CARG2, #-LJ_TUDATA + | bne >6 + |1: // Field metatable must be at same offset for GCtab and GCudata! + | ldr TAB:RB, TAB:CARG1->metatable + |2: + | mvn CARG2, #~LJ_TNIL + | ldr STR:RC, [DISPATCH, #DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])] + | cmp TAB:RB, #0 + | beq ->fff_restv + | ldr CARG3, TAB:RB->hmask + | ldr CARG4, STR:RC->hash + | ldr NODE:INS, TAB:RB->node + | and CARG3, CARG3, CARG4 // idx = str->hash & tab->hmask + | add CARG3, CARG3, CARG3, lsl #1 + | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8 + |3: // Rearranged logic, because we expect _not_ to find the key. + | ldrd CARG34, NODE:INS->key // STALL: early NODE:INS. + | ldrd CARG12, NODE:INS->val + | ldr NODE:INS, NODE:INS->next + | checktp CARG4, LJ_TSTR + | cmpeq CARG3, STR:RC + | beq >5 + | cmp NODE:INS, #0 + | bne <3 + |4: + | mov CARG1, RB // Use metatable as default result. + | mvn CARG2, #~LJ_TTAB + | b ->fff_restv + |5: + | checktp CARG2, LJ_TNIL + | bne ->fff_restv + | b <4 + | + |6: + | checktp CARG2, LJ_TISNUM + | mvnhs CARG2, CARG2 + | movlo CARG2, #~LJ_TISNUM + | add CARG4, DISPATCH, CARG2, lsl #2 + | ldr TAB:RB, [CARG4, #DISPATCH_GL(gcroot[GCROOT_BASEMT])] + | b <2 + | + |.ffunc_2 setmetatable + | // Fast path: no mt for table yet and not clearing the mt. + | checktp CARG2, LJ_TTAB + | ldreq TAB:RB, TAB:CARG1->metatable + | checktpeq CARG4, LJ_TTAB + | ldrbeq CARG4, TAB:CARG1->marked + | cmpeq TAB:RB, #0 + | bne ->fff_fallback + | tst CARG4, #LJ_GC_BLACK // isblack(table) + | str TAB:CARG3, TAB:CARG1->metatable + | beq ->fff_restv + | barrierback TAB:CARG1, CARG4, CARG3 + | b ->fff_restv + | + |.ffunc rawget + | ldrd CARG34, [BASE] + | cmp NARGS8:RC, #16 + | blo ->fff_fallback + | mov CARG2, CARG3 + | checktab CARG4, ->fff_fallback + | mov CARG1, L + | add CARG3, BASE, #8 + | IOS mov RA, BASE + | bl extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key) + | // Returns cTValue *. + | IOS mov BASE, RA + | ldrd CARG12, [CRET1] + | b ->fff_restv + | + |//-- Base library: conversions ------------------------------------------ + | + |.ffunc tonumber + | // Only handles the number case inline (without a base argument). + | ldrd CARG12, [BASE] + | cmp NARGS8:RC, #8 + | bne ->fff_fallback + | checktp CARG2, LJ_TISNUM + | bls ->fff_restv + | b ->fff_fallback + | + |.ffunc_1 tostring + | // Only handles the string or number case inline. + | checktp CARG2, LJ_TSTR + | // A __tostring method in the string base metatable is ignored. + | beq ->fff_restv + | // Handle numbers inline, unless a number base metatable is present. + | ldr CARG4, [DISPATCH, #DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])] + | str BASE, L->base + | checktp CARG2, LJ_TISNUM + | cmpls CARG4, #0 + | str PC, SAVE_PC // Redundant (but a defined value). + | bhi ->fff_fallback + | ffgccheck + | mov CARG1, L + | mov CARG2, BASE + | bl extern lj_str_fromnumber // (lua_State *L, cTValue *o) + | // Returns GCstr *. + | ldr BASE, L->base + | mvn CARG2, #~LJ_TSTR + | b ->fff_restv + | + |//-- Base library: iterators ------------------------------------------- + | + |.ffunc_1 next + | mvn CARG4, #~LJ_TNIL + | 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. + | 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 + | + |.ffunc_1 pairs + | checktab CARG2, ->fff_fallback +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | ldr TAB:RB, TAB:CARG1->metatable +#endif + | ldrd CFUNC:CARG34, CFUNC:CARG3->upvalue[0] + | ldr PC, [BASE, FRAME_PC] +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | cmp TAB:RB, #0 + | bne ->fff_fallback +#endif + | mvn CARG2, #~LJ_TNIL + | mov RC, #(3+1)*8 + | strd CFUNC:CARG34, [BASE, #-8] + | str CARG2, [BASE, #12] + | b ->fff_res + | + |.ffunc_2 ipairs_aux + | checktp CARG2, LJ_TTAB + | checktpeq CARG4, LJ_TISNUM + | bne ->fff_fallback + | ldr RB, TAB:CARG1->asize + | ldr RC, TAB:CARG1->array + | add CARG3, CARG3, #1 + | ldr PC, [BASE, FRAME_PC] + | cmp CARG3, RB + | add RC, RC, CARG3, lsl #3 + | strd CARG34, [BASE, #-8] + | ldrdlo CARG12, [RC] + | mov RC, #(0+1)*8 + | bhs >2 // Not in array part? + |1: + | checktp CARG2, LJ_TNIL + | movne RC, #(2+1)*8 + | strdne CARG12, [BASE] + | b ->fff_res + |2: // Check for empty hash part first. Otherwise call C function. + | ldr RB, TAB:CARG1->hmask + | mov CARG2, CARG3 + | cmp RB, #0 + | beq ->fff_res + | IOS mov RA, BASE + | bl extern lj_tab_getinth // (GCtab *t, int32_t key) + | // Returns cTValue * or NULL. + | IOS mov BASE, RA + | cmp CRET1, #0 + | beq ->fff_res + | ldrd CARG12, [CRET1] + | b <1 + | + |.ffunc_1 ipairs + | checktab CARG2, ->fff_fallback +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | ldr TAB:RB, TAB:CARG1->metatable +#endif + | ldrd CFUNC:CARG34, CFUNC:CARG3->upvalue[0] + | ldr PC, [BASE, FRAME_PC] +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | cmp TAB:RB, #0 + | bne ->fff_fallback +#endif + | mov CARG1, #0 + | mvn CARG2, #~LJ_TISNUM + | mov RC, #(3+1)*8 + | strd CFUNC:CARG34, [BASE, #-8] + | strd CARG12, [BASE, #8] + | b ->fff_res + | + |//-- Base library: catch errors ---------------------------------------- + | + |.ffunc pcall + | ldrb RA, [DISPATCH, #DISPATCH_GL(hookmask)] + | cmp NARGS8:RC, #8 + | blo ->fff_fallback + | tst RA, #HOOK_ACTIVE // Remember active hook before pcall. + | mov RB, BASE + | add BASE, BASE, #8 + | moveq PC, #8+FRAME_PCALL + | movne PC, #8+FRAME_PCALLH + | sub NARGS8:RC, NARGS8:RC, #8 + | b ->vm_call_dispatch + | + |.ffunc_2 xpcall + | ldrb RA, [DISPATCH, #DISPATCH_GL(hookmask)] + | checkfunc CARG4, ->fff_fallback // Traceback must be a function. + | mov RB, BASE + | strd CARG12, [BASE, #8] // Swap function and traceback. + | strd CARG34, [BASE] + | tst RA, #HOOK_ACTIVE // Remember active hook before pcall. + | add BASE, BASE, #16 + | moveq PC, #16+FRAME_PCALL + | movne PC, #16+FRAME_PCALLH + | sub NARGS8:RC, NARGS8:RC, #16 + | b ->vm_call_dispatch + | + |//-- Coroutine library -------------------------------------------------- + | + |.macro coroutine_resume_wrap, resume + |.if resume + |.ffunc_1 coroutine_resume + | checktp CARG2, LJ_TTHREAD + | bne ->fff_fallback + |.else + |.ffunc coroutine_wrap_aux + | ldr L:CARG1, CFUNC:CARG3->upvalue[0].gcr + |.endif + | ldr PC, [BASE, FRAME_PC] + | str BASE, L->base + | ldr CARG2, L:CARG1->top + | ldrb RA, L:CARG1->status + | ldr RB, L:CARG1->base + | add CARG3, CARG2, NARGS8:RC + | add CARG4, CARG2, RA + | str PC, SAVE_PC + | cmp CARG4, RB + | beq ->fff_fallback + | ldr CARG4, L:CARG1->maxstack + | ldr RB, L:CARG1->cframe + | cmp RA, #LUA_YIELD + | cmpls CARG3, CARG4 + | cmpls RB, #0 + | bhi ->fff_fallback + |1: + |.if resume + | sub CARG3, CARG3, #8 // Keep resumed thread in stack for GC. + | add BASE, BASE, #8 + | sub NARGS8:RC, NARGS8:RC, #8 + |.endif + | str CARG3, L:CARG1->top + | str BASE, L->top + |2: // Move args to coroutine. + | ldrd CARG34, [BASE, RB] + | cmp RB, NARGS8:RC + | strdne CARG34, [CARG2, RB] + | add RB, RB, #8 + | bne <2 + | + | mov CARG3, #0 + | mov L:RA, L:CARG1 + | mov CARG4, #0 + | bl ->vm_resume // (lua_State *L, TValue *base, 0, 0) + | // Returns thread status. + |4: + | ldr CARG3, L:RA->base + | mv_vmstate CARG2, INTERP + | ldr CARG4, L:RA->top + | st_vmstate CARG2 + | cmp CRET1, #LUA_YIELD + | ldr BASE, L->base + | bhi >8 + | subs RC, CARG4, CARG3 + | ldr CARG1, L->maxstack + | add CARG2, BASE, RC + | beq >6 // No results? + | cmp CARG2, CARG1 + | mov RB, #0 + | bhi >9 // Need to grow stack? + | + | sub CARG4, RC, #8 + | str CARG3, L:RA->top // Clear coroutine stack. + |5: // Move results from coroutine. + | ldrd CARG12, [CARG3, RB] + | cmp RB, CARG4 + | strd CARG12, [BASE, RB] + | add RB, RB, #8 + | bne <5 + |6: + |.if resume + | mvn CARG3, #~LJ_TTRUE + | add RC, RC, #16 + |7: + | str CARG3, [BASE, #-4] // Prepend true/false to results. + | sub RA, BASE, #8 + |.else + | mov RA, BASE + | add RC, RC, #8 + |.endif + | ands CARG1, PC, #FRAME_TYPE + | str PC, SAVE_PC + | str RC, SAVE_MULTRES + | beq ->BC_RET_Z + | b ->vm_return + | + |8: // Coroutine returned with error (at co->top-1). + |.if resume + | ldrd CARG12, [CARG4, #-8]! + | mvn CARG3, #~LJ_TFALSE + | mov RC, #(2+1)*8 + | str CARG4, L:RA->top // Remove error from coroutine stack. + | strd CARG12, [BASE] // Copy error message. + | b <7 + |.else + | mov CARG1, L + | mov CARG2, L:RA + | bl extern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co) + | // Never returns. + |.endif + | + |9: // Handle stack expansion on return from yield. + | mov CARG1, L + | lsr CARG2, RC, #3 + | bl extern lj_state_growstack // (lua_State *L, int n) + | mov CRET1, #0 + | b <4 + |.endmacro + | + | coroutine_resume_wrap 1 // coroutine.resume + | coroutine_resume_wrap 0 // coroutine.wrap + | + |.ffunc coroutine_yield + | ldr CARG1, L->cframe + | add CARG2, BASE, NARGS8:RC + | str BASE, L->base + | tst CARG1, #CFRAME_RESUME + | str CARG2, L->top + | mov CRET1, #LUA_YIELD + | mov CARG3, #0 + | beq ->fff_fallback + | str CARG3, L->cframe + | strb CRET1, L->status + | b ->vm_leave_unw + | + |//-- Math library ------------------------------------------------------- + | + |.macro math_round, func + | .ffunc_1 math_ .. func + | checktp CARG2, LJ_TISNUM + | beq ->fff_restv + | bhi ->fff_fallback + | // Round FP value and normalize result. + | lsl CARG3, CARG2, #1 + | adds RB, CARG3, #0x00200000 + | bpl >2 // |x| < 1? + | mvn CARG4, #0x3e0 + | subs RB, CARG4, RB, asr #21 + | lsl CARG4, CARG2, #11 + | lsl CARG3, CARG1, #11 + | orr CARG4, CARG4, #0x80000000 + | rsb INS, RB, #32 + | orr CARG4, CARG4, CARG1, lsr #21 + | bls >3 // |x| >= 2^31? + | orr CARG3, CARG3, CARG4, lsl INS + | lsr CARG1, CARG4, RB + |.if "func" == "floor" + | tst CARG3, CARG2, asr #31 + | addne CARG1, CARG1, #1 + |.else + | bics CARG3, CARG3, CARG2, asr #31 + | addsne CARG1, CARG1, #1 + | ldrdvs CARG12, >9 + | bvs ->fff_restv + |.endif + | cmp CARG2, #0 + | rsblt CARG1, CARG1, #0 + |1: + | mvn CARG2, #~LJ_TISNUM + | b ->fff_restv + | + |2: // |x| < 1 + | bcs ->fff_restv // |x| is not finite. + | orr CARG3, CARG3, CARG1 // ztest = abs(hi) | lo + |.if "func" == "floor" + | tst CARG3, CARG2, asr #31 // return (ztest & sign) == 0 ? 0 : -1 + | moveq CARG1, #0 + | mvnne CARG1, #0 + |.else + | bics CARG3, CARG3, CARG2, asr #31 // return (ztest & ~sign) == 0 ? 0 : 1 + | moveq CARG1, #0 + | movne CARG1, #1 + |.endif + | mvn CARG2, #~LJ_TISNUM + | b ->fff_restv + | + |3: // |x| >= 2^31. Check for x == -(2^31). + | cmpeq CARG4, #0x80000000 + |.if "func" == "floor" + | cmpeq CARG3, #0 + |.endif + | bne >4 + | cmp CARG2, #0 + | movmi CARG1, #0x80000000 + | bmi <1 + |4: + | bl ->vm_..func + | b ->fff_restv + |.endmacro + | + | math_round floor + | math_round ceil + | + |.align 8 + |9: + | .long 0x00000000, 0x41e00000 // 2^31. + | + |.ffunc_1 math_abs + | checktp CARG2, LJ_TISNUM + | bhi ->fff_fallback + | bicne CARG2, CARG2, #0x80000000 + | bne ->fff_restv + | cmp CARG1, #0 + | rsbslt CARG1, CARG1, #0 + | ldrdvs CARG12, <9 + | // Fallthrough. + | + |->fff_restv: + | // CARG12 = TValue result. + | ldr PC, [BASE, FRAME_PC] + | strd CARG12, [BASE, #-8] + |->fff_res1: + | // PC = return. + | mov RC, #(1+1)*8 + |->fff_res: + | // RC = (nresults+1)*8, PC = return. + | ands CARG1, PC, #FRAME_TYPE + | ldreq INS, [PC, #-4] + | str RC, SAVE_MULTRES + | sub RA, BASE, #8 + | bne ->vm_return + | decode_RB8 RB, INS + |5: + | cmp RB, RC // More results expected? + | bhi >6 + | decode_RA8 CARG1, INS + | ins_next1 + | ins_next2 + | // Adjust BASE. KBASE is assumed to be set for the calling frame. + | sub BASE, RA, CARG1 + | ins_next3 + | + |6: // Fill up results with nil. + | add CARG2, RA, RC + | mvn CARG1, #~LJ_TNIL + | add RC, RC, #8 + | str CARG1, [CARG2, #-4] + | b <5 + | + |.macro math_extern, func + | .ffunc_n math_ .. func + | IOS mov RA, BASE + | bl extern func + | IOS mov BASE, RA + | b ->fff_restv + |.endmacro + | + |.macro math_extern2, func + | .ffunc_nn math_ .. func + | IOS mov RA, BASE + | bl extern func + | IOS mov BASE, RA + | b ->fff_restv + |.endmacro + | + | math_extern sqrt + | math_extern log + | math_extern log10 + | math_extern exp + | math_extern sin + | math_extern cos + | math_extern tan + | math_extern asin + | math_extern acos + | math_extern atan + | math_extern sinh + | math_extern cosh + | math_extern tanh + | math_extern2 pow + | math_extern2 atan2 + | math_extern2 fmod + | + |->ff_math_deg: + |.ffunc_n math_rad + | ldrd CARG34, CFUNC:CARG3->upvalue[0] + | bl extern __aeabi_dmul + | b ->fff_restv + | + |.ffunc_2 math_ldexp + | checktp CARG2, LJ_TISNUM + | bhs ->fff_fallback + | checktp CARG4, LJ_TISNUM + | bne ->fff_fallback + | IOS mov RA, BASE + | bl extern ldexp // (double x, int exp) + | IOS mov BASE, RA + | b ->fff_restv + | + |.ffunc_n math_frexp + | mov CARG3, sp + | IOS mov RA, BASE + | bl extern frexp + | IOS mov BASE, RA + | ldr CARG3, [sp] + | mvn CARG4, #~LJ_TISNUM + | ldr PC, [BASE, FRAME_PC] + | strd CARG12, [BASE, #-8] + | mov RC, #(2+1)*8 + | strd CARG34, [BASE] + | b ->fff_res + | + |.ffunc_n math_modf + | sub CARG3, BASE, #8 + | ldr PC, [BASE, FRAME_PC] + | IOS mov RA, BASE + | bl extern modf + | IOS mov BASE, RA + | mov RC, #(2+1)*8 + | strd CARG12, [BASE] + | b ->fff_res + | + |.macro math_minmax, name, cond, fcond + | .ffunc_1 name + | checktp CARG2, LJ_TISNUM + | mov RA, #8 + | bne >4 + |1: // Handle integers. + | ldrd CARG34, [BASE, RA] + | cmp RA, RC + | bhs ->fff_restv + | checktp CARG4, LJ_TISNUM + | bne >3 + | cmp CARG1, CARG3 + | add RA, RA, #8 + | mov..cond CARG1, CARG3 + | b <1 + |3: + | bhi ->fff_fallback + | // Convert intermediate result to number and continue below. + | bl extern __aeabi_i2d + | ldrd CARG34, [BASE, RA] + | b >6 + | + |4: + | bhi ->fff_fallback + |5: // Handle numbers. + | ldrd CARG34, [BASE, RA] + | cmp RA, RC + | bhs ->fff_restv + | checktp CARG4, LJ_TISNUM + | bhs >7 + |6: + | bl extern __aeabi_cdcmple + | add RA, RA, #8 + | mov..fcond CARG1, CARG3 + | mov..fcond CARG2, CARG4 + | b <5 + |7: // Convert integer to number and continue above. + | bhi ->fff_fallback + | strd CARG12, TMPD + | mov CARG1, CARG3 + | bl extern __aeabi_i2d + | ldrd CARG34, TMPD + | b <6 + |.endmacro + | + | math_minmax math_min, gt, hi + | math_minmax math_max, lt, lo + | + |//-- String library ----------------------------------------------------- + | + |.ffunc_1 string_len + | checkstr CARG2, ->fff_fallback + | ldr CARG1, STR:CARG1->len + | mvn CARG2, #~LJ_TISNUM + | b ->fff_restv + | + |.ffunc string_byte // Only handle the 1-arg case here. + | ldrd CARG12, [BASE] + | ldr PC, [BASE, FRAME_PC] + | cmp NARGS8:RC, #8 + | checktpeq CARG2, LJ_TSTR // Need exactly 1 argument. + | bne ->fff_fallback + | ldr CARG3, STR:CARG1->len + | ldrb CARG1, STR:CARG1[1] // Access is always ok (NUL at end). + | mvn CARG2, #~LJ_TISNUM + | cmp CARG3, #0 + | moveq RC, #(0+1)*8 + | movne RC, #(1+1)*8 + | strd CARG12, [BASE, #-8] + | b ->fff_res + | + |.ffunc string_char // Only handle the 1-arg case here. + | ffgccheck + | ldrd CARG12, [BASE] + | ldr PC, [BASE, FRAME_PC] + | cmp NARGS8:RC, #8 // Need exactly 1 argument. + | checktpeq CARG2, LJ_TISNUM + | bicseq CARG4, CARG1, #255 + | mov CARG3, #1 + | bne ->fff_fallback + | str CARG1, TMPD + | mov CARG2, TMPDp // Points to stack. Little-endian. + |->fff_newstr: + | // CARG2 = str, CARG3 = len. + | str BASE, L->base + | mov CARG1, L + | str PC, SAVE_PC + | bl extern lj_str_new // (lua_State *L, char *str, size_t l) + | // Returns GCstr *. + | ldr BASE, L->base + | mvn CARG2, #~LJ_TSTR + | b ->fff_restv + | + |.ffunc string_sub + | ffgccheck + | ldrd CARG12, [BASE] + | ldrd CARG34, [BASE, #16] + | cmp NARGS8:RC, #16 + | mvn RB, #0 + | beq >1 + | blo ->fff_fallback + | checktp CARG4, LJ_TISNUM + | mov RB, CARG3 + | bne ->fff_fallback + |1: + | ldrd CARG34, [BASE, #8] + | checktp CARG2, LJ_TSTR + | ldreq CARG2, STR:CARG1->len + | checktpeq CARG4, LJ_TISNUM + | bne ->fff_fallback + | // CARG1 = str, CARG2 = str->len, CARG3 = start, RB = end + | add CARG4, CARG2, #1 + | cmp CARG3, #0 // if (start < 0) start += len+1 + | addlt CARG3, CARG3, CARG4 + | cmp CARG3, #1 // if (start < 1) start = 1 + | movlt CARG3, #1 + | cmp RB, #0 // if (end < 0) end += len+1 + | addlt RB, RB, CARG4 + | bic RB, RB, RB, asr #31 // if (end < 0) end = 0 + | cmp RB, CARG2 // if (end > len) end = len + | add CARG1, STR:CARG1, #sizeof(GCstr)-1 + | movgt RB, CARG2 + | add CARG2, CARG1, CARG3 + | subs CARG3, RB, CARG3 // len = end - start + | add CARG3, CARG3, #1 // len += 1 + | bge ->fff_newstr + |->fff_emptystr: + | sub STR:CARG1, DISPATCH, #-DISPATCH_GL(strempty) + | mvn CARG2, #~LJ_TSTR + | b ->fff_restv + | + |.ffunc string_rep // Only handle the 1-char case inline. + | ffgccheck + | ldrd CARG12, [BASE] + | ldrd CARG34, [BASE, #8] + | cmp NARGS8:RC, #16 + | blo ->fff_fallback + | checktp CARG2, LJ_TSTR + | checktpeq CARG4, LJ_TISNUM + | bne ->fff_fallback + | subs CARG4, CARG3, #1 + | ldr CARG2, STR:CARG1->len + | blt ->fff_emptystr // Count <= 0? + | cmp CARG2, #1 + | blo ->fff_emptystr // Zero-length string? + | bne ->fff_fallback // Fallback for > 1-char strings. + | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)] + | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)] + | ldr CARG1, STR:CARG1[1] + | cmp RB, CARG3 + | blo ->fff_fallback + |1: // Fill buffer with char. + | strb CARG1, [CARG2, CARG4] + | subs CARG4, CARG4, #1 + | bge <1 + | b ->fff_newstr + | + |.ffunc string_reverse + | ffgccheck + | ldrd CARG12, [BASE] + | cmp NARGS8:RC, #8 + | blo ->fff_fallback + | checkstr CARG2, ->fff_fallback + | ldr CARG3, STR:CARG1->len + | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)] + | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)] + | mov CARG4, CARG3 + | add CARG1, STR:CARG1, #sizeof(GCstr) + | cmp RB, CARG3 + | blo ->fff_fallback + |1: // Reverse string copy. + | ldrb RB, [CARG1], #1 + | subs CARG4, CARG4, #1 + | blt ->fff_newstr + | strb RB, [CARG2, CARG4] + | b <1 + | + |.macro ffstring_case, name, lo + | .ffunc name + | ffgccheck + | ldrd CARG12, [BASE] + | cmp NARGS8:RC, #8 + | blo ->fff_fallback + | checkstr CARG2, ->fff_fallback + | ldr CARG3, STR:CARG1->len + | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)] + | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)] + | mov CARG4, #0 + | add CARG1, STR:CARG1, #sizeof(GCstr) + | cmp RB, CARG3 + | blo ->fff_fallback + |1: // ASCII case conversion. + | ldrb RB, [CARG1, CARG4] + | cmp CARG4, CARG3 + | bhs ->fff_newstr + | sub RC, RB, #lo + | cmp RC, #26 + | eorlo RB, RB, #0x20 + | strb RB, [CARG2, CARG4] + | add CARG4, CARG4, #1 + | b <1 + |.endmacro + | + |ffstring_case string_lower, 65 + |ffstring_case string_upper, 97 + | + |//-- Table library ------------------------------------------------------ + | + |.ffunc_1 table_getn + | checktab CARG2, ->fff_fallback + | IOS mov RA, BASE + | bl extern lj_tab_len // (GCtab *t) + | // Returns uint32_t (but less than 2^31). + | IOS mov BASE, RA + | mvn CARG2, #~LJ_TISNUM + | b ->fff_restv + | + |//-- Bit library -------------------------------------------------------- + | + |// FP number to bit conversion for soft-float. Clobbers r0-r3. + |->vm_tobit_fb: + | bhi ->fff_fallback + |->vm_tobit: + | lsl RB, CARG2, #1 + | adds RB, RB, #0x00200000 + | movpl CARG1, #0 // |x| < 1? + | bxpl lr + | mvn CARG4, #0x3e0 + | subs RB, CARG4, RB, asr #21 + | bmi >1 // |x| >= 2^32? + | lsl CARG4, CARG2, #11 + | orr CARG4, CARG4, #0x80000000 + | orr CARG4, CARG4, CARG1, lsr #21 + | cmp CARG2, #0 + | lsr CARG1, CARG4, RB + | rsblt CARG1, CARG1, #0 + | bx lr + |1: + | add RB, RB, #21 + | lsr CARG4, CARG1, RB + | rsb RB, RB, #20 + | lsl CARG1, CARG2, #12 + | cmp CARG2, #0 + | orr CARG1, CARG4, CARG1, lsl RB + | rsblt CARG1, CARG1, #0 + | bx lr + | + |.macro .ffunc_bit, name + | .ffunc_1 bit_..name + | checktp CARG2, LJ_TISNUM + | blne ->vm_tobit_fb + |.endmacro + | + |.ffunc_bit tobit + | mvn CARG2, #~LJ_TISNUM + | b ->fff_restv + | + |.macro .ffunc_bit_op, name, ins + | .ffunc_bit name + | mov CARG3, CARG1 + | mov RA, #8 + |1: + | ldrd CARG12, [BASE, RA] + | cmp RA, NARGS8:RC + | add RA, RA, #8 + | bge >2 + | checktp CARG2, LJ_TISNUM + | blne ->vm_tobit_fb + | ins CARG3, CARG3, CARG1 + | b <1 + |.endmacro + | + |.ffunc_bit_op band, and + |.ffunc_bit_op bor, orr + |.ffunc_bit_op bxor, eor + | + |2: + | mvn CARG4, #~LJ_TISNUM + | ldr PC, [BASE, FRAME_PC] + | strd CARG34, [BASE, #-8] + | b ->fff_res1 + | + |.ffunc_bit bswap + | eor CARG3, CARG1, CARG1, ror #16 + | bic CARG3, CARG3, #0x00ff0000 + | ror CARG1, CARG1, #8 + | mvn CARG2, #~LJ_TISNUM + | eor CARG1, CARG1, CARG3, lsr #8 + | b ->fff_restv + | + |.ffunc_bit bnot + | mvn CARG1, CARG1 + | mvn CARG2, #~LJ_TISNUM + | b ->fff_restv + | + |.macro .ffunc_bit_sh, name, ins, shmod + | .ffunc bit_..name + | ldrd CARG12, [BASE, #8] + | cmp NARGS8:RC, #16 + | blo ->fff_fallback + | checktp CARG2, LJ_TISNUM + | blne ->vm_tobit_fb + |.if shmod == 0 + | and RA, CARG1, #31 + |.else + | rsb RA, CARG1, #0 + |.endif + | ldrd CARG12, [BASE] + | checktp CARG2, LJ_TISNUM + | blne ->vm_tobit_fb + | ins CARG1, CARG1, RA + | mvn CARG2, #~LJ_TISNUM + | b ->fff_restv + |.endmacro + | + |.ffunc_bit_sh lshift, lsl, 0 + |.ffunc_bit_sh rshift, lsr, 0 + |.ffunc_bit_sh arshift, asr, 0 + |.ffunc_bit_sh rol, ror, 1 + |.ffunc_bit_sh ror, ror, 0 + | + |//----------------------------------------------------------------------- + | + |->fff_fallback: // Call fast function fallback handler. + | // BASE = new base, RC = nargs*8 + | ldr CARG3, [BASE, FRAME_FUNC] + | ldr CARG2, L->maxstack + | add CARG1, BASE, NARGS8:RC + | ldr PC, [BASE, FRAME_PC] // Fallback may overwrite PC. + | str CARG1, L->top + | ldr CARG3, CFUNC:CARG3->f + | str BASE, L->base + | add CARG1, CARG1, #8*LUA_MINSTACK + | str PC, SAVE_PC // Redundant (but a defined value). + | cmp CARG1, CARG2 + | mov CARG1, L + | bhi >5 // Need to grow stack. + | blx CARG3 // (lua_State *L) + | // Either throws an error, or recovers and returns -1, 0 or nresults+1. + | ldr BASE, L->base + | cmp CRET1, #0 + | lsl RC, CRET1, #3 + | sub RA, BASE, #8 + | bgt ->fff_res // Returned nresults+1? + |1: // Returned 0 or -1: retry fast path. + | ldr CARG1, L->top + | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] + | sub NARGS8:RC, CARG1, BASE + | bne ->vm_call_tail // Returned -1? + | ins_callt // Returned 0: retry fast path. + | + |// Reconstruct previous base for vmeta_call during tailcall. + |->vm_call_tail: + | ands CARG1, PC, #FRAME_TYPE + | bic CARG2, PC, #FRAME_TYPEP + | ldreq INS, [PC, #-4] + | andeq CARG2, MASKR8, INS, lsr #5 // Conditional decode_RA8. + | addeq CARG2, CARG2, #8 + | sub RB, BASE, CARG2 + | b ->vm_call_dispatch // Resolve again for tailcall. + | + |5: // Grow stack for fallback handler. + | mov CARG2, #LUA_MINSTACK + | bl extern lj_state_growstack // (lua_State *L, int n) + | ldr BASE, L->base + | cmp CARG1, CARG1 // Set zero-flag to force retry. + | b <1 + | + |->fff_gcstep: // Call GC step function. + | // BASE = new base, RC = nargs*8 + | mov RA, lr + | str BASE, L->base + | add CARG2, BASE, NARGS8:RC + | str PC, SAVE_PC // Redundant (but a defined value). + | str CARG2, L->top + | mov CARG1, L + | bl extern lj_gc_step // (lua_State *L) + | ldr BASE, L->base + | mov lr, RA // Help return address predictor. + | ldr CFUNC:CARG3, [BASE, FRAME_FUNC] + | bx lr + | + |//----------------------------------------------------------------------- + |//-- Special dispatch targets ------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_record: // Dispatch target for recording phase. +#if LJ_HASJIT + | ldrb CARG1, [DISPATCH, #DISPATCH_GL(hookmask)] + | tst CARG1, #HOOK_VMEVENT // No recording while in vmevent. + | bne >5 + | // Decrement the hookcount for consistency, but always do the call. + | ldr CARG2, [DISPATCH, #DISPATCH_GL(hookcount)] + | tst CARG1, #HOOK_ACTIVE + | bne >1 + | sub CARG2, CARG2, #1 + | tst CARG1, #LUA_MASKLINE|LUA_MASKCOUNT + | strne CARG2, [DISPATCH, #DISPATCH_GL(hookcount)] + | b >1 +#endif + | + |->vm_rethook: // Dispatch target for return hooks. + | ldrb CARG1, [DISPATCH, #DISPATCH_GL(hookmask)] + | tst CARG1, #HOOK_ACTIVE // Hook already active? + | beq >1 + |5: // Re-dispatch to static ins. + | decode_OP OP, INS + | add OP, DISPATCH, OP, lsl #2 + | ldr pc, [OP, #GG_DISP2STATIC] + | + |->vm_inshook: // Dispatch target for instr/line hooks. + | ldrb CARG1, [DISPATCH, #DISPATCH_GL(hookmask)] + | ldr CARG2, [DISPATCH, #DISPATCH_GL(hookcount)] + | tst CARG1, #HOOK_ACTIVE // Hook already active? + | bne <5 + | tst CARG1, #LUA_MASKLINE|LUA_MASKCOUNT + | beq <5 + | subs CARG2, CARG2, #1 + | str CARG2, [DISPATCH, #DISPATCH_GL(hookcount)] + | beq >1 + | tst CARG1, #LUA_MASKLINE + | beq <5 + |1: + | mov CARG1, L + | str BASE, L->base + | mov CARG2, PC + | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. + | bl extern lj_dispatch_ins // (lua_State *L, const BCIns *pc) + |3: + | ldr BASE, L->base + |4: // Re-dispatch to static ins. + | ldrb OP, [PC, #-4] + | ldr INS, [PC, #-4] + | add OP, DISPATCH, OP, lsl #2 + | ldr OP, [OP, #GG_DISP2STATIC] + | decode_RA8 RA, INS + | decode_RD RC, INS + | bx OP + | + |->cont_hook: // Continue from hook yield. + | ldr CARG1, [CARG4, #-24] + | add PC, PC, #4 + | str CARG1, SAVE_MULTRES // Restore MULTRES for *M ins. + | b <4 + | + |->vm_hotloop: // Hot loop counter underflow. +#if LJ_HASJIT + | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Same as curr_topL(L). + | sub CARG1, DISPATCH, #-GG_DISP2J + | str PC, SAVE_PC + | ldr CARG3, LFUNC:CARG3->field_pc + | mov CARG2, PC + | str L, [DISPATCH, #DISPATCH_J(L)] + | ldrb CARG3, [CARG3, #PC2PROTO(framesize)] + | str BASE, L->base + | add CARG3, BASE, CARG3, lsl #3 + | str CARG3, L->top + | bl extern lj_trace_hot // (jit_State *J, const BCIns *pc) + | b <3 +#endif + | + |->vm_callhook: // Dispatch target for call hooks. + | mov CARG2, PC +#if LJ_HASJIT + | b >1 +#endif + | + |->vm_hotcall: // Hot call counter underflow. +#if LJ_HASJIT + | orr CARG2, PC, #1 + |1: +#endif + | add CARG4, BASE, RC + | str PC, SAVE_PC + | mov CARG1, L + | str BASE, L->base + | sub RA, RA, BASE + | str CARG4, L->top + | bl extern lj_dispatch_call // (lua_State *L, const BCIns *pc) + | // Returns ASMFunction. + | ldr BASE, L->base + | ldr CARG4, L->top + | mov CARG2, #0 + | add RA, BASE, RA + | sub NARGS8:RC, CARG4, BASE + | str CARG2, SAVE_PC // Invalidate for subsequent line hook. + | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] + | ldr INS, [PC, #-4] + | bx CRET1 + | + |//----------------------------------------------------------------------- + |//-- Trace exit handler ------------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_exit_handler: +#if LJ_HASJIT + | sub sp, sp, #12 + | push {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12} + | ldr CARG1, [sp, #64] // Load original value of lr. + | ldr DISPATCH, [lr] // Load DISPATCH. + | add CARG3, sp, #64 // Recompute original value of sp. + | mv_vmstate CARG4, EXIT + | str CARG3, [sp, #52] // Store sp in RID_SP + | st_vmstate CARG4 + | ldr CARG2, [CARG1, #-4]! // Get exit instruction. + | str CARG1, [sp, #56] // Store exit pc in RID_LR and RID_PC. + | str CARG1, [sp, #60] + | lsl CARG2, CARG2, #8 + | add CARG1, CARG1, CARG2, asr #6 + | ldr CARG2, [lr, #4] // Load exit stub group offset. + | sub CARG1, CARG1, lr + | ldr L, [DISPATCH, #DISPATCH_GL(jit_L)] + | add CARG1, CARG2, CARG1, lsr #2 // Compute exit number. + | ldr BASE, [DISPATCH, #DISPATCH_GL(jit_base)] + | str CARG1, [DISPATCH, #DISPATCH_J(exitno)] + | mov CARG4, #0 + | str L, [DISPATCH, #DISPATCH_J(L)] + | str BASE, L->base + | str CARG4, [DISPATCH, #DISPATCH_GL(jit_L)] + | sub CARG1, DISPATCH, #-GG_DISP2J + | mov CARG2, sp + | bl extern lj_trace_exit // (jit_State *J, ExitState *ex) + | // Returns MULTRES (unscaled) or negated error code. + | ldr CARG2, L->cframe + | ldr BASE, L->base + | bic CARG2, CARG2, #~CFRAME_RAWMASK // Use two steps: bic sp is deprecated. + | mov sp, CARG2 + | ldr PC, SAVE_PC // Get SAVE_PC. + | str L, SAVE_L // Set SAVE_L (on-trace resume/yield). + | b >1 +#endif + |->vm_exit_interp: + | // CARG1 = MULTRES or negated error code, BASE, PC and DISPATCH set. +#if LJ_HASJIT + | ldr L, SAVE_L + |1: + | cmp CARG1, #0 + | blt >3 // Check for error from exit. + | lsl RC, CARG1, #3 + | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] + | str RC, SAVE_MULTRES + | mov CARG3, #0 + | ldr CARG2, LFUNC:CARG2->field_pc + | str CARG3, [DISPATCH, #DISPATCH_GL(jit_L)] + | mv_vmstate CARG4, INTERP + | ldr KBASE, [CARG2, #PC2PROTO(k)] + | // Modified copy of ins_next which handles function header dispatch, too. + | ldrb OP, [PC] + | mov MASKR8, #255 + | ldr INS, [PC], #4 + | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. + | st_vmstate CARG4 + | cmp OP, #BC_FUNCF // Function header? + | ldr OP, [DISPATCH, OP, lsl #2] + | decode_RA8 RA, INS + | lsrlo RC, INS, #16 // No: Decode operands A*8 and D. + | subhs RC, RC, #8 + | addhs RA, RA, BASE // Yes: RA = BASE+framesize*8, RC = nargs*8 + | bx OP + | + |3: // Rethrow error from the right C frame. + | rsb CARG2, CARG1, #0 + | mov CARG1, L + | bl extern lj_err_throw // (lua_State *L, int errcode) +#endif + | + |//----------------------------------------------------------------------- + |//-- Math helper functions ---------------------------------------------- + |//----------------------------------------------------------------------- + | + |// FP value rounding. Called from JIT code. + |// + |// double lj_vm_floor/ceil/trunc(double x); + |.macro vm_round, func + |->vm_ .. func: + | lsl CARG3, CARG2, #1 + | adds RB, CARG3, #0x00200000 + | bpl >2 // |x| < 1? + | mvn CARG4, #0x3cc + | subs RB, CARG4, RB, asr #21 // 2^0: RB = 51, 2^51: RB = 0. + | bxlo lr // |x| >= 2^52: done. + | mvn CARG4, #1 + | bic CARG3, CARG1, CARG4, lsl RB // ztest = lo & ~lomask + | and CARG1, CARG1, CARG4, lsl RB // lo &= lomask + | subs RB, RB, #32 + | bicpl CARG4, CARG2, CARG4, lsl RB // |x| <= 2^20: ztest |= hi & ~himask + | orrpl CARG3, CARG3, CARG4 + | mvnpl CARG4, #1 + | andpl CARG2, CARG2, CARG4, lsl RB // |x| <= 2^20: hi &= himask + |.if "func" == "floor" + | tst CARG3, CARG2, asr #31 // iszero = ((ztest & signmask) == 0) + |.else + | bics CARG3, CARG3, CARG2, asr #31 // iszero = ((ztest & ~signmask) == 0) + |.endif + | bxeq lr // iszero: done. + | mvn CARG4, #1 + | cmp RB, #0 + | lslpl CARG3, CARG4, RB + | mvnmi CARG3, #0 + | add RB, RB, #32 + | subs CARG1, CARG1, CARG4, lsl RB // lo = lo-lomask + | sbc CARG2, CARG2, CARG3 // hi = hi-himask+carry + | bx lr + | + |2: // |x| < 1: + | bxcs lr // |x| is not finite. + | orr CARG3, CARG3, CARG1 // ztest = (2*hi) | lo + |.if "func" == "floor" + | tst CARG3, CARG2, asr #31 // iszero = ((ztest & signmask) == 0) + |.else + | bics CARG3, CARG3, CARG2, asr #31 // iszero = ((ztest & ~signmask) == 0) + |.endif + | mov CARG1, #0 // lo = 0 + | and CARG2, CARG2, #0x80000000 + | ldrne CARG4, <9 // hi = sign(x) | (iszero ? 0.0 : 1.0) + | orrne CARG2, CARG2, CARG4 + | bx lr + |.endmacro + | + |9: + | .long 0x3ff00000 // hiword(1.0) + | vm_round floor + | vm_round ceil + | + |->vm_trunc: +#if LJ_HASJIT + | lsl CARG3, CARG2, #1 + | adds RB, CARG3, #0x00200000 + | andpl CARG2, CARG2, #0x80000000 // |x| < 1? hi = sign(x), lo = 0. + | movpl CARG1, #0 + | bxpl lr + | mvn CARG4, #0x3cc + | subs RB, CARG4, RB, asr #21 // 2^0: RB = 51, 2^51: RB = 0. + | bxlo lr // |x| >= 2^52: already done. + | mvn CARG4, #1 + | and CARG1, CARG1, CARG4, lsl RB // lo &= lomask + | subs RB, RB, #32 + | andpl CARG2, CARG2, CARG4, lsl RB // |x| <= 2^20: hi &= himask + | bx lr +#endif + | + | // double lj_vm_mod(double dividend, double divisor); + |->vm_mod: + | push {r0, r1, r2, r3, r4, lr} + | bl extern __aeabi_ddiv + | bl ->vm_floor + | ldrd CARG34, [sp, #8] + | bl extern __aeabi_dmul + | ldrd CARG34, [sp] + | eor CARG2, CARG2, #0x80000000 + | bl extern __aeabi_dadd + | add sp, sp, #20 + | pop {pc} + | + | // int lj_vm_modi(int dividend, int divisor); + |->vm_modi: + | ands RB, CARG1, #0x80000000 + | rsbmi CARG1, CARG1, #0 // a = |dividend| + | eor RB, RB, CARG2, asr #1 // Keep signdiff and sign(divisor). + | cmp CARG2, #0 + | rsbmi CARG2, CARG2, #0 // b = |divisor| + | subs CARG4, CARG2, #1 + | cmpne CARG1, CARG2 + | moveq CARG1, #0 // if (b == 1 || a == b) a = 0 + | tsthi CARG2, CARG4 + | andeq CARG1, CARG1, CARG4 // else if ((b & (b-1)) == 0) a &= b-1 + | bls >1 + | // Use repeated subtraction to get the remainder. + | clz CARG3, CARG1 + | clz CARG4, CARG2 + | sub CARG4, CARG4, CARG3 + | rsbs CARG3, CARG4, #31 // entry = (31-(clz(b)-clz(a)))*8 + | addne pc, pc, CARG3, lsl #3 // Duff's device. + | nop + { + int i; + for (i = 31; i >= 0; i--) { + | cmp CARG1, CARG2, lsl #i + | subhs CARG1, CARG1, CARG2, lsl #i + } + } + |1: + | cmp CARG1, #0 + | cmpne RB, #0 + | submi CARG1, CARG1, CARG2 // if (y != 0 && signdiff) y = y - b + | eors CARG2, CARG1, RB, lsl #1 + | rsbmi CARG1, CARG1, #0 // if (sign(divisor) != sign(y)) y = -y + | bx lr + | + |// Callable from C: double lj_vm_foldarith(double x, double y, int op) + |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -) + |// and basic math functions. ORDER ARITH + |->vm_foldarith: + | ldr OP, [sp] + | cmp OP, #1 + | blo extern __aeabi_dadd + | beq extern __aeabi_dsub + | cmp OP, #3 + | blo extern __aeabi_dmul + | beq extern __aeabi_ddiv + | cmp OP, #5 + | blo ->vm_mod + | beq extern pow + | cmp OP, #7 + | eorlo CARG2, CARG2, #0x80000000 + | biceq CARG2, CARG2, #0x80000000 + | bxls lr +#if LJ_HASJIT + | cmp OP, #9 + | blo extern atan2 + | beq >9 // No support needed for IR_LDEXP. + | cmp OP, #11 + | bhi >9 + | push {r4, lr} + | beq >1 + | // IR_MIN + | bl extern __aeabi_cdcmple + | movhi CARG1, CARG3 + | movhi CARG2, CARG4 + | pop {r4, pc} + |9: + | NYI // Bad op. + | + |1: // IR_MAX + | bl extern __aeabi_cdcmple + | movlo CARG1, CARG3 + | movlo CARG2, CARG4 + | pop {r4, pc} +#else + | NYI // Other operations only needed by JIT compiler. +#endif + | + |//----------------------------------------------------------------------- + |//-- Miscellaneous functions -------------------------------------------- + |//----------------------------------------------------------------------- + | + |//----------------------------------------------------------------------- + |//-- FFI helper functions ----------------------------------------------- + |//----------------------------------------------------------------------- + | + |// Handler for callback functions. + |// Saveregs already performed. Callback slot number in [sp], g in r12. + |->vm_ffi_callback: +#if LJ_HASFFI + |.type CTSTATE, CTState, PC + | ldr CTSTATE, GL:r12->ctype_state + | add DISPATCH, r12, #GG_G2DISP + | strd CARG12, CTSTATE->cb.gpr[0] + | strd CARG34, CTSTATE->cb.gpr[2] + | ldr CARG4, [sp] + | add CARG3, sp, #CFRAME_SIZE + | mov CARG1, CTSTATE + | lsr CARG4, CARG4, #3 + | str CARG3, CTSTATE->cb.stack + | mov CARG2, sp + | str CARG4, CTSTATE->cb.slot + | str CTSTATE, SAVE_PC // Any value outside of bytecode is ok. + | bl extern lj_ccallback_enter // (CTState *cts, void *cf) + | // Returns lua_State *. + | ldr BASE, L:CRET1->base + | mv_vmstate CARG2, INTERP + | ldr RC, L:CRET1->top + | mov MASKR8, #255 + | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] + | mov L, CRET1 + | sub RC, RC, BASE + | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. + | st_vmstate CARG2 + | ins_callt +#endif + | + |->cont_ffi_callback: // Return from FFI callback. +#if LJ_HASFFI + | ldr CTSTATE, [DISPATCH, #DISPATCH_GL(ctype_state)] + | str BASE, L->base + | str CARG4, L->top + | str L, CTSTATE->L + | mov CARG1, CTSTATE + | mov CARG2, RA + | bl extern lj_ccallback_leave // (CTState *cts, TValue *o) + | ldrd CARG12, CTSTATE->cb.gpr[0] + | b ->vm_leave_unw +#endif + | + |->vm_ffi_call: // Call C function via FFI. + | // Caveat: needs special frame unwinding, see below. +#if LJ_HASFFI + | .type CCSTATE, CCallState, r4 + | push {CCSTATE, r5, r11, lr} + | mov CCSTATE, CARG1 + | ldr CARG1, CCSTATE:CARG1->spadj + | ldrb CARG2, CCSTATE->nsp + | add CARG3, CCSTATE, #offsetof(CCallState, stack) + | mov r11, sp + | sub sp, sp, CARG1 // Readjust stack. + | subs CARG2, CARG2, #1 + | ldr RB, CCSTATE->func + | bmi >2 + |1: // Copy stack slots. + | ldr CARG4, [CARG3, CARG2, lsl #2] + | str CARG4, [sp, CARG2, lsl #2] + | subs CARG2, CARG2, #1 + | bpl <1 + |2: + | ldr CARG1, CCSTATE->gpr[0] + | ldr CARG2, CCSTATE->gpr[1] + | ldr CARG3, CCSTATE->gpr[2] + | ldr CARG4, CCSTATE->gpr[3] + | blx RB + | mov sp, r11 + | str CRET1, CCSTATE->gpr[0] + | str CRET2, CCSTATE->gpr[1] + | pop {CCSTATE, r5, r11, pc} +#endif + |// Note: vm_ffi_call must be the last function in this object file! + | + |//----------------------------------------------------------------------- +} + +/* Generate the code for a single instruction. */ +static void build_ins(BuildCtx *ctx, BCOp op, int defop) +{ + int vk = 0; + |=>defop: + + switch (op) { + + /* -- Comparison ops ---------------------------------------------------- */ + + /* Remember: all ops branch for a true comparison, fall through otherwise. */ + + case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: + | // RA = src1*8, RC = src2, JMP with RC = target + | lsl RC, RC, #3 + | ldrd CARG12, [RA, BASE]! + | ldrh RB, [PC, #2] + | ldrd CARG34, [RC, BASE]! + | add PC, PC, #4 + | add RB, PC, RB, lsl #2 + | checktp CARG2, LJ_TISNUM + | bne >3 + | checktp CARG4, LJ_TISNUM + | bne >4 + | cmp CARG1, CARG3 + if (op == BC_ISLT) { + | sublt PC, RB, #0x20000 + } else if (op == BC_ISGE) { + | subge PC, RB, #0x20000 + } else if (op == BC_ISLE) { + | suble PC, RB, #0x20000 + } else { + | subgt PC, RB, #0x20000 + } + |1: + | ins_next + | + |3: // CARG12 is not an integer. + | bhi ->vmeta_comp + | // CARG12 is a number. + | checktp CARG4, LJ_TISNUM + | movlo RA, RB // Save RB. + | blo >5 + | // CARG12 is a number, CARG3 is an integer. + | mov CARG1, CARG3 + | mov RC, RA + | mov RA, RB // Save RB. + | bl extern __aeabi_i2d + | mov CARG3, CARG1 + | mov CARG4, CARG2 + | ldrd CARG12, [RC] // Restore first operand. + | b >5 + |4: // CARG1 is an integer, CARG34 is not an integer. + | bhi ->vmeta_comp + | // CARG1 is an integer, CARG34 is a number + | mov RA, RB // Save RB. + | bl extern __aeabi_i2d + | ldrd CARG34, [RC] // Restore second operand. + |5: // CARG12 and CARG34 are numbers. + | bl extern __aeabi_cdcmple + | // To preserve NaN semantics GE/GT branch on unordered, but LT/LE don't. + if (op == BC_ISLT) { + | sublo PC, RA, #0x20000 + } else if (op == BC_ISGE) { + | subhs PC, RA, #0x20000 + } else if (op == BC_ISLE) { + | subls PC, RA, #0x20000 + } else { + | subhi PC, RA, #0x20000 + } + | b <1 + break; + + case BC_ISEQV: case BC_ISNEV: + vk = op == BC_ISEQV; + | // RA = src1*8, RC = src2, JMP with RC = target + | lsl RC, RC, #3 + | ldrd CARG12, [RA, BASE]! + | ldrh RB, [PC, #2] + | ldrd CARG34, [RC, BASE]! + | add PC, PC, #4 + | add RB, PC, RB, lsl #2 + | checktp CARG2, LJ_TISNUM + | cmnls CARG4, #-LJ_TISNUM + if (vk) { + | bls ->BC_ISEQN_Z + } else { + | bls ->BC_ISNEN_Z + } + | // Either or both types are not numbers. + if (LJ_HASFFI) { + | checktp CARG2, LJ_TCDATA + | checktpne CARG4, LJ_TCDATA + | beq ->vmeta_equal_cd + } + | cmp CARG2, CARG4 // Compare types. + | bne >2 // Not the same type? + | checktp CARG2, LJ_TISPRI + | bhs >1 // Same type and primitive type? + | + | // Same types and not a primitive type. Compare GCobj or pvalue. + | cmp CARG1, CARG3 + if (vk) { + | bne >3 // Different GCobjs or pvalues? + |1: // Branch if same. + | sub PC, RB, #0x20000 + |2: // Different. + | ins_next + |3: + | checktp CARG2, LJ_TISTABUD + | bhi <2 // Different objects and not table/ud? + } else { + | beq >1 // Same GCobjs or pvalues? + | checktp CARG2, LJ_TISTABUD + | bhi >2 // Different objects and not table/ud? + } + | // Different tables or userdatas. Need to check __eq metamethod. + | // Field metatable must be at same offset for GCtab and GCudata! + | ldr TAB:RA, TAB:CARG1->metatable + | cmp TAB:RA, #0 + if (vk) { + | beq <2 // No metatable? + } else { + | beq >2 // No metatable? + } + | ldrb RA, TAB:RA->nomm + | mov CARG4, #1-vk // ne = 0 or 1. + | mov CARG2, CARG1 + | tst RA, #1<vmeta_equal // 'no __eq' flag not set? + if (vk) { + | b <2 + } else { + |2: // Branch if different. + | sub PC, RB, #0x20000 + |1: // Same. + | ins_next + } + break; + + case BC_ISEQS: case BC_ISNES: + vk = op == BC_ISEQS; + | // RA = src*8, RC = str_const (~), JMP with RC = target + | mvn RC, RC + | ldrd CARG12, [BASE, RA] + | ldrh RB, [PC, #2] + | ldr STR:CARG3, [KBASE, RC, lsl #2] + | add PC, PC, #4 + | add RB, PC, RB, lsl #2 + | checktp CARG2, LJ_TSTR + if (LJ_HASFFI) { + | bne >7 + | cmp CARG1, CARG3 + } else { + | cmpeq CARG1, CARG3 + } + if (vk) { + | subeq PC, RB, #0x20000 + |1: + } else { + |1: + | subne PC, RB, #0x20000 + } + | ins_next + | + if (LJ_HASFFI) { + |7: + | checktp CARG2, LJ_TCDATA + | bne <1 + | b ->vmeta_equal_cd + } + break; + + case BC_ISEQN: case BC_ISNEN: + vk = op == BC_ISEQN; + | // RA = src*8, RC = num_const (~), JMP with RC = target + | lsl RC, RC, #3 + | ldrd CARG12, [RA, BASE]! + | ldrh RB, [PC, #2] + | ldrd CARG34, [RC, KBASE]! + | add PC, PC, #4 + | add RB, PC, RB, lsl #2 + if (vk) { + |->BC_ISEQN_Z: + } else { + |->BC_ISNEN_Z: + } + | checktp CARG2, LJ_TISNUM + | bne >3 + | checktp CARG4, LJ_TISNUM + | bne >4 + | cmp CARG1, CARG3 + if (vk) { + | subeq PC, RB, #0x20000 + |1: + } else { + |1: + | subne PC, RB, #0x20000 + } + |2: + | ins_next + | + |3: // CARG12 is not an integer. + if (LJ_HASFFI) { + | bhi >7 + } else { + if (!vk) { + | subhi PC, RB, #0x20000 + } + | bhi <2 + } + | // CARG12 is a number. + | checktp CARG4, LJ_TISNUM + | movlo RA, RB // Save RB. + | blo >5 + | // CARG12 is a number, CARG3 is an integer. + | mov CARG1, CARG3 + | mov RC, RA + |4: // CARG1 is an integer, CARG34 is a number. + | mov RA, RB // Save RB. + | bl extern __aeabi_i2d + | ldrd CARG34, [RC] // Restore other operand. + |5: // CARG12 and CARG34 are numbers. + | bl extern __aeabi_cdcmpeq + if (vk) { + | subeq PC, RA, #0x20000 + } else { + | subne PC, RA, #0x20000 + } + | b <2 + | + if (LJ_HASFFI) { + |7: + | checktp CARG2, LJ_TCDATA + | bne <1 + | b ->vmeta_equal_cd + } + break; + + case BC_ISEQP: case BC_ISNEP: + vk = op == BC_ISEQP; + | // RA = src*8, RC = primitive_type (~), JMP with RC = target + | ldrd CARG12, [BASE, RA] + | ldrh RB, [PC, #2] + | add PC, PC, #4 + | mvn RC, RC + | add RB, PC, RB, lsl #2 + if (LJ_HASFFI) { + | checktp CARG2, LJ_TCDATA + | beq ->vmeta_equal_cd + } + | cmp CARG2, RC + if (vk) { + | subeq PC, RB, #0x20000 + } else { + | subne PC, RB, #0x20000 + } + | ins_next + break; + + /* -- Unary test and copy ops ------------------------------------------- */ + + case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: + | // RA = dst*8 or unused, RC = src, JMP with RC = target + | add RC, BASE, RC, lsl #3 + | ldrh RB, [PC, #2] + | ldrd CARG12, [RC] + | add PC, PC, #4 + | add RB, PC, RB, lsl #2 + | checktp CARG2, LJ_TTRUE + if (op == BC_ISTC || op == BC_IST) { + | subls PC, RB, #0x20000 + if (op == BC_ISTC) { + | strdls CARG12, [BASE, RA] + } + } else { + | subhi PC, RB, #0x20000 + if (op == BC_ISFC) { + | strdhi CARG12, [BASE, RA] + } + } + | ins_next + break; + + /* -- Unary ops --------------------------------------------------------- */ + + case BC_MOV: + | // RA = dst*8, RC = src + | lsl RC, RC, #3 + | ins_next1 + | ldrd CARG12, [BASE, RC] + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 + break; + case BC_NOT: + | // RA = dst*8, RC = src + | add RC, BASE, RC, lsl #3 + | ins_next1 + | ldr CARG1, [RC, #4] + | add RA, BASE, RA + | ins_next2 + | checktp CARG1, LJ_TTRUE + | mvnls CARG2, #~LJ_TFALSE + | mvnhi CARG2, #~LJ_TTRUE + | str CARG2, [RA, #4] + | ins_next3 + break; + case BC_UNM: + | // RA = dst*8, RC = src + | lsl RC, RC, #3 + | ldrd CARG12, [BASE, RC] + | ins_next1 + | ins_next2 + | checktp CARG2, LJ_TISNUM + | bhi ->vmeta_unm + | eorne CARG2, CARG2, #0x80000000 + | bne >5 + | rsbseq CARG1, CARG1, #0 + | ldrdvs CARG12, >9 + |5: + | strd CARG12, [BASE, RA] + | ins_next3 + | + |.align 8 + |9: + | .long 0x00000000, 0x41e00000 // 2^31. + break; + case BC_LEN: + | // RA = dst*8, RC = src + | lsl RC, RC, #3 + | ldrd CARG12, [BASE, RC] + | checkstr CARG2, >2 + | ldr CARG1, STR:CARG1->len + |1: + | mvn CARG2, #~LJ_TISNUM + | ins_next1 + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 + |2: + | checktab CARG2, ->vmeta_len +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | ldr TAB:CARG3, TAB:CARG1->metatable + | cmp TAB:CARG3, #0 + | bne >9 + |3: +#endif + |->BC_LEN_Z: + | IOS mov RC, BASE + | bl extern lj_tab_len // (GCtab *t) + | // Returns uint32_t (but less than 2^31). + | IOS mov BASE, RC + | b <1 +#ifdef LUAJIT_ENABLE_LUA52COMPAT + |9: + | ldrb CARG4, TAB:CARG3->nomm + | tst CARG4, #1<vmeta_len +#endif + break; + + /* -- Binary ops -------------------------------------------------------- */ + + |.macro ins_arithcheck, cond, ncond, target + ||if (vk == 1) { + | cmn CARG4, #-LJ_TISNUM + | cmn..cond CARG2, #-LJ_TISNUM + ||} else { + | cmn CARG2, #-LJ_TISNUM + | cmn..cond CARG4, #-LJ_TISNUM + ||} + | b..ncond target + |.endmacro + |.macro ins_arithcheck_int, target + | ins_arithcheck eq, ne, target + |.endmacro + |.macro ins_arithcheck_num, target + | ins_arithcheck lo, hs, target + |.endmacro + | + |.macro ins_arithpre + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8 + ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); + ||switch (vk) { + ||case 0: + | ldrd CARG12, [BASE, RB] + | ldrd CARG34, [KBASE, RC] + || break; + ||case 1: + | ldrd CARG34, [BASE, RB] + | ldrd CARG12, [KBASE, RC] + || break; + ||default: + | ldrd CARG12, [BASE, RB] + | ldrd CARG34, [BASE, RC] + || break; + ||} + |.endmacro + | + |.macro ins_arithfallback, ins + ||switch (vk) { + ||case 0: + | ins ->vmeta_arith_vn + || break; + ||case 1: + | ins ->vmeta_arith_nv + || break; + ||default: + | ins ->vmeta_arith_vv + || break; + ||} + |.endmacro + | + |.macro ins_arithdn, intins, fpcall + | ins_arithpre + |.if "intins" ~= "vm_modi" + | ins_next1 + |.endif + | ins_arithcheck_int >5 + |.if "intins" == "smull" + | smull CARG1, RC, CARG3, CARG1 + | cmp RC, CARG1, asr #31 + | ins_arithfallback bne + |.elif "intins" == "vm_modi" + | movs CARG2, CARG3 + | ins_arithfallback beq + | bl ->vm_modi + | mvn CARG2, #~LJ_TISNUM + |.else + | intins CARG1, CARG1, CARG3 + | ins_arithfallback bvs + |.endif + |4: + |.if "intins" == "vm_modi" + | ins_next1 + |.endif + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 + |5: // FP variant. + | ins_arithfallback ins_arithcheck_num + |.if "intins" == "vm_modi" + | bl fpcall + |.else + | bl fpcall + | ins_next1 + |.endif + | b <4 + |.endmacro + | + |.macro ins_arithfp, fpcall + | ins_arithpre + | ins_arithfallback ins_arithcheck_num + |.if "fpcall" == "extern pow" + | IOS mov RC, BASE + | bl fpcall + | IOS mov BASE, RC + |.else + | bl fpcall + |.endif + | ins_next1 + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 + |.endmacro + + case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: + | ins_arithdn adds, extern __aeabi_dadd + break; + case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: + | ins_arithdn subs, extern __aeabi_dsub + break; + case BC_MULVN: case BC_MULNV: case BC_MULVV: + | ins_arithdn smull, extern __aeabi_dmul + break; + case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: + | ins_arithfp extern __aeabi_ddiv + break; + case BC_MODVN: case BC_MODNV: case BC_MODVV: + | ins_arithdn vm_modi, ->vm_mod + break; + case BC_POW: + | // NYI: (partial) integer arithmetic. + | ins_arithfp extern pow + break; + + case BC_CAT: + | decode_RB8 RC, INS + | decode_RC8 RB, INS + | // RA = dst*8, RC = src_start*8, RB = src_end*8 (note: RB/RC swapped!) + | sub CARG3, RB, RC + | str BASE, L->base + | add CARG2, BASE, RB + |->BC_CAT_Z: + | // RA = dst*8, RC = src_start*8, CARG2 = top-1 + | mov CARG1, L + | str PC, SAVE_PC + | lsr CARG3, CARG3, #3 + | bl extern lj_meta_cat // (lua_State *L, TValue *top, int left) + | // Returns NULL (finished) or TValue * (metamethod). + | ldr BASE, L->base + | cmp CRET1, #0 + | bne ->vmeta_binop + | ldrd CARG34, [BASE, RC] + | ins_next1 + | ins_next2 + | strd CARG34, [BASE, RA] // Copy result to RA. + | ins_next3 + break; + + /* -- Constant ops ------------------------------------------------------ */ + + case BC_KSTR: + | // RA = dst*8, RC = str_const (~) + | mvn RC, RC + | ins_next1 + | ldr CARG1, [KBASE, RC, lsl #2] + | mvn CARG2, #~LJ_TSTR + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 + break; + case BC_KCDATA: +#if LJ_HASFFI + | // RA = dst*8, RC = cdata_const (~) + | mvn RC, RC + | ins_next1 + | ldr CARG1, [KBASE, RC, lsl #2] + | mvn CARG2, #~LJ_TCDATA + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 +#endif + break; + case BC_KSHORT: + | // RA = dst*8, (RC = int16_literal) + | mov CARG1, INS, asr #16 // Refetch sign-extended reg. + | mvn CARG2, #~LJ_TISNUM + | ins_next1 + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 + break; + case BC_KNUM: + | // RA = dst*8, RC = num_const + | lsl RC, RC, #3 + | ins_next1 + | ldrd CARG12, [KBASE, RC] + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 + break; + case BC_KPRI: + | // RA = dst*8, RC = primitive_type (~) + | add RA, BASE, RA + | mvn RC, RC + | ins_next1 + | ins_next2 + | str RC, [RA, #4] + | ins_next3 + break; + case BC_KNIL: + | // RA = base*8, RC = end + | add RA, BASE, RA + | add RC, BASE, RC, lsl #3 + | mvn CARG1, #~LJ_TNIL + | str CARG1, [RA, #4] + | add RA, RA, #8 + |1: + | str CARG1, [RA, #4] + | cmp RA, RC + | add RA, RA, #8 + | blt <1 + | ins_next_ + break; + + /* -- Upvalue and function ops ------------------------------------------ */ + + case BC_UGET: + | // RA = dst*8, RC = uvnum + | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] + | lsl RC, RC, #2 + | add RC, RC, #offsetof(GCfuncL, uvptr) + | ldr UPVAL:CARG2, [LFUNC:CARG2, RC] + | ldr CARG2, UPVAL:CARG2->v + | ldrd CARG34, [CARG2] + | ins_next1 + | ins_next2 + | strd CARG34, [BASE, RA] + | ins_next3 + break; + case BC_USETV: + | // RA = uvnum*8, RC = src + | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] + | lsr RA, RA, #1 + | add RA, RA, #offsetof(GCfuncL, uvptr) + | lsl RC, RC, #3 + | ldr UPVAL:CARG2, [LFUNC:CARG2, RA] + | ldrd CARG34, [BASE, RC] + | ldrb RB, UPVAL:CARG2->marked + | ldrb RC, UPVAL:CARG2->closed + | ldr CARG2, UPVAL:CARG2->v + | tst RB, #LJ_GC_BLACK // isblack(uv) + | add RB, CARG4, #-LJ_TISGCV + | cmpne RC, #0 + | strd CARG34, [CARG2] + | bne >2 // Upvalue is closed and black? + |1: + | ins_next + | + |2: // Check if new value is collectable. + | cmn RB, #-(LJ_TISNUM - LJ_TISGCV) + | ldrbhi RC, GCOBJ:CARG3->gch.marked + | bls <1 // tvisgcv(v) + | sub CARG1, DISPATCH, #-GG_DISP2G + | tst RC, #LJ_GC_WHITES + | // Crossed a write barrier. Move the barrier forward. + if (LJ_TARGET_IOS) { + | beq <1 + | mov RC, BASE + | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) + | mov BASE, RC + } else { + | blne extern lj_gc_barrieruv // (global_State *g, TValue *tv) + } + | b <1 + break; + case BC_USETS: + | // RA = uvnum*8, RC = str_const (~) + | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] + | lsr RA, RA, #1 + | add RA, RA, #offsetof(GCfuncL, uvptr) + | mvn RC, RC + | ldr UPVAL:CARG2, [LFUNC:CARG2, RA] + | ldr STR:CARG3, [KBASE, RC, lsl #2] + | mvn CARG4, #~LJ_TSTR + | ldrb RB, UPVAL:CARG2->marked + | ldr CARG2, UPVAL:CARG2->v + | ldrb RC, UPVAL:CARG2->closed + | tst RB, #LJ_GC_BLACK // isblack(uv) + | ldrb RB, STR:CARG3->marked + | strd CARG34, [CARG2] + | bne >2 + |1: + | ins_next + | + |2: // Check if string is white and ensure upvalue is closed. + | tst RB, #LJ_GC_WHITES // iswhite(str) + | cmpne RC, #0 + | sub CARG1, DISPATCH, #-GG_DISP2G + | // Crossed a write barrier. Move the barrier forward. + if (LJ_TARGET_IOS) { + | beq <1 + | mov RC, BASE + | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) + | mov BASE, RC + } else { + | blne extern lj_gc_barrieruv // (global_State *g, TValue *tv) + } + | b <1 + break; + case BC_USETN: + | // RA = uvnum*8, RC = num_const + | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] + | lsr RA, RA, #1 + | add RA, RA, #offsetof(GCfuncL, uvptr) + | lsl RC, RC, #3 + | ldr UPVAL:CARG2, [LFUNC:CARG2, RA] + | ldrd CARG34, [KBASE, RC] + | ldr CARG2, UPVAL:CARG2->v + | ins_next1 + | ins_next2 + | strd CARG34, [CARG2] + | ins_next3 + break; + case BC_USETP: + | // RA = uvnum*8, RC = primitive_type (~) + | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] + | lsr RA, RA, #1 + | add RA, RA, #offsetof(GCfuncL, uvptr) + | ldr UPVAL:CARG2, [LFUNC:CARG2, RA] + | mvn RC, RC + | ldr CARG2, UPVAL:CARG2->v + | ins_next1 + | ins_next2 + | str RC, [CARG2, #4] + | ins_next3 + break; + + case BC_UCLO: + | // RA = level*8, RC = target + | ldr CARG3, L->openupval + | add RC, PC, RC, lsl #2 + | str BASE, L->base + | cmp CARG3, #0 + | sub PC, RC, #0x20000 + | beq >1 + | mov CARG1, L + | add CARG2, BASE, RA + | bl extern lj_func_closeuv // (lua_State *L, TValue *level) + | ldr BASE, L->base + |1: + | ins_next + break; + + case BC_FNEW: + | // RA = dst*8, RC = proto_const (~) (holding function prototype) + | mvn RC, RC + | str BASE, L->base + | ldr CARG2, [KBASE, RC, lsl #2] + | str PC, SAVE_PC + | ldr CARG3, [BASE, FRAME_FUNC] + | mov CARG1, L + | // (lua_State *L, GCproto *pt, GCfuncL *parent) + | bl extern lj_func_newL_gc + | // Returns GCfuncL *. + | ldr BASE, L->base + | mvn CARG2, #~LJ_TFUNC + | ins_next1 + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 + break; + + /* -- Table ops --------------------------------------------------------- */ + + case BC_TNEW: + case BC_TDUP: + | // RA = dst*8, RC = (hbits|asize) | tab_const (~) + if (op == BC_TDUP) { + | mvn RC, RC + } + | ldr CARG3, [DISPATCH, #DISPATCH_GL(gc.total)] + | ldr CARG4, [DISPATCH, #DISPATCH_GL(gc.threshold)] + | str BASE, L->base + | str PC, SAVE_PC + | cmp CARG3, CARG4 + | mov CARG1, L + | bhs >5 + |1: + if (op == BC_TNEW) { + | lsl CARG2, RC, #21 + | lsr CARG3, RC, #11 + | asr RC, CARG2, #21 + | lsr CARG2, CARG2, #21 + | cmn RC, #1 + | addeq CARG2, CARG2, #2 + | bl extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits) + | // Returns GCtab *. + } else { + | ldr CARG2, [KBASE, RC, lsl #2] + | bl extern lj_tab_dup // (lua_State *L, Table *kt) + | // Returns GCtab *. + } + | ldr BASE, L->base + | mvn CARG2, #~LJ_TTAB + | ins_next1 + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 + |5: + | bl extern lj_gc_step_fixtop // (lua_State *L) + | mov CARG1, L + | b <1 + break; + + case BC_GGET: + | // RA = dst*8, RC = str_const (~) + case BC_GSET: + | // RA = dst*8, RC = str_const (~) + | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] + | mvn RC, RC + | ldr TAB:CARG1, LFUNC:CARG2->env + | ldr STR:RC, [KBASE, RC, lsl #2] + if (op == BC_GGET) { + | b ->BC_TGETS_Z + } else { + | b ->BC_TSETS_Z + } + break; + + case BC_TGETV: + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | // RA = dst*8, RB = table*8, RC = key*8 + | ldrd TAB:CARG12, [BASE, RB] + | ldrd CARG34, [BASE, RC] + | checktab CARG2, ->vmeta_tgetv // STALL: load CARG12. + | checktp CARG4, LJ_TISNUM // Integer key? + | ldreq CARG4, TAB:CARG1->array + | ldreq CARG2, TAB:CARG1->asize + | bne >9 + | + | add CARG4, CARG4, CARG3, lsl #3 + | cmp CARG3, CARG2 // In array part? + | ldrdlo CARG34, [CARG4] + | bhs ->vmeta_tgetv + | ins_next1 // Overwrites RB! + | checktp CARG4, LJ_TNIL + | beq >5 + |1: + | ins_next2 + | strd CARG34, [BASE, RA] + | ins_next3 + | + |5: // Check for __index if table value is nil. + | ldr TAB:CARG2, TAB:CARG1->metatable + | cmp TAB:CARG2, #0 + | beq <1 // No metatable: done. + | ldrb CARG2, TAB:CARG2->nomm + | tst CARG2, #1<vmeta_tgetv + | + |9: + | checktp CARG4, LJ_TSTR // String key? + | moveq STR:RC, CARG3 + | beq ->BC_TGETS_Z + | b ->vmeta_tgetv + break; + case BC_TGETS: + | decode_RB8 RB, INS + | and RC, RC, #255 + | // RA = dst*8, RB = table*8, RC = str_const (~) + | ldrd CARG12, [BASE, RB] + | mvn RC, RC + | ldr STR:RC, [KBASE, RC, lsl #2] // STALL: early RC. + | checktab CARG2, ->vmeta_tgets1 + |->BC_TGETS_Z: + | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8 + | ldr CARG3, TAB:CARG1->hmask + | ldr CARG4, STR:RC->hash + | ldr NODE:INS, TAB:CARG1->node + | mov TAB:RB, TAB:CARG1 + | and CARG3, CARG3, CARG4 // idx = str->hash & tab->hmask + | add CARG3, CARG3, CARG3, lsl #1 + | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8 + |1: + | ldrd CARG12, NODE:INS->key // STALL: early NODE:INS. + | ldrd CARG34, NODE:INS->val + | ldr NODE:INS, NODE:INS->next + | checktp CARG2, LJ_TSTR + | cmpeq CARG1, STR:RC + | bne >4 + | checktp CARG4, LJ_TNIL + | beq >5 + |3: + | ins_next1 + | ins_next2 + | strd CARG34, [BASE, RA] + | ins_next3 + | + |4: // Follow hash chain. + | cmp NODE:INS, #0 + | bne <1 + | // End of hash chain: key not found, nil result. + | + |5: // Check for __index if table value is nil. + | ldr TAB:CARG1, TAB:RB->metatable + | mov CARG3, #0 // Optional clear of undef. value (during load stall). + | mvn CARG4, #~LJ_TNIL + | cmp TAB:CARG1, #0 + | beq <3 // No metatable: done. + | ldrb CARG2, TAB:CARG1->nomm + | tst CARG2, #1<vmeta_tgets + break; + case BC_TGETB: + | decode_RB8 RB, INS + | and RC, RC, #255 + | // RA = dst*8, RB = table*8, RC = index + | ldrd CARG12, [BASE, RB] + | checktab CARG2, ->vmeta_tgetb // STALL: load CARG12. + | ldr CARG3, TAB:CARG1->asize + | ldr CARG4, TAB:CARG1->array + | lsl CARG2, RC, #3 + | cmp RC, CARG3 + | ldrdlo CARG34, [CARG4, CARG2] + | bhs ->vmeta_tgetb + | ins_next1 // Overwrites RB! + | checktp CARG4, LJ_TNIL + | beq >5 + |1: + | ins_next2 + | strd CARG34, [BASE, RA] + | ins_next3 + | + |5: // Check for __index if table value is nil. + | ldr TAB:CARG2, TAB:CARG1->metatable + | cmp TAB:CARG2, #0 + | beq <1 // No metatable: done. + | ldrb CARG2, TAB:CARG2->nomm + | tst CARG2, #1<vmeta_tgetb + break; + + case BC_TSETV: + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | // RA = src*8, RB = table*8, RC = key*8 + | ldrd TAB:CARG12, [BASE, RB] + | ldrd CARG34, [BASE, RC] + | checktab CARG2, ->vmeta_tsetv // STALL: load CARG12. + | checktp CARG4, LJ_TISNUM // Integer key? + | ldreq CARG2, TAB:CARG1->array + | ldreq CARG4, TAB:CARG1->asize + | bne >9 + | + | add CARG2, CARG2, CARG3, lsl #3 + | cmp CARG3, CARG4 // In array part? + | ldrlo INS, [CARG2, #4] + | bhs ->vmeta_tsetv + | ins_next1 // Overwrites RB! + | checktp INS, LJ_TNIL + | ldrb INS, TAB:CARG1->marked + | ldrd CARG34, [BASE, RA] + | beq >5 + |1: + | tst INS, #LJ_GC_BLACK // isblack(table) + | strd CARG34, [CARG2] + | bne >7 + |2: + | ins_next2 + | ins_next3 + | + |5: // Check for __newindex if previous value is nil. + | ldr TAB:RA, TAB:CARG1->metatable + | cmp TAB:RA, #0 + | beq <1 // No metatable: done. + | ldrb RA, TAB:RA->nomm + | tst RA, #1<vmeta_tsetv + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:CARG1, INS, CARG3 + | b <2 + | + |9: + | checktp CARG4, LJ_TSTR // String key? + | moveq STR:RC, CARG3 + | beq ->BC_TSETS_Z + | b ->vmeta_tsetv + break; + case BC_TSETS: + | decode_RB8 RB, INS + | and RC, RC, #255 + | // RA = src*8, RB = table*8, RC = str_const (~) + | ldrd CARG12, [BASE, RB] + | mvn RC, RC + | ldr STR:RC, [KBASE, RC, lsl #2] // STALL: early RC. + | checktab CARG2, ->vmeta_tsets1 + |->BC_TSETS_Z: + | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8 + | ldr CARG3, TAB:CARG1->hmask + | ldr CARG4, STR:RC->hash + | ldr NODE:INS, TAB:CARG1->node + | mov TAB:RB, TAB:CARG1 + | and CARG3, CARG3, CARG4 // idx = str->hash & tab->hmask + | add CARG3, CARG3, CARG3, lsl #1 + | mov CARG4, #0 + | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8 + | strb CARG4, TAB:RB->nomm // Clear metamethod cache. + |1: + | ldrd CARG12, NODE:INS->key + | ldr CARG4, NODE:INS->val.it + | ldr NODE:CARG3, NODE:INS->next + | checktp CARG2, LJ_TSTR + | cmpeq CARG1, STR:RC + | bne >5 + | ldrb CARG2, TAB:RB->marked + | checktp CARG4, LJ_TNIL // Key found, but nil value? + | ldrd CARG34, [BASE, RA] + | beq >4 + |2: + | tst CARG2, #LJ_GC_BLACK // isblack(table) + | strd CARG34, NODE:INS->val + | bne >7 + |3: + | ins_next + | + |4: // Check for __newindex if previous value is nil. + | ldr TAB:CARG1, TAB:RB->metatable + | cmp TAB:CARG1, #0 + | beq <2 // No metatable: done. + | ldrb CARG1, TAB:CARG1->nomm + | tst CARG1, #1<vmeta_tsets + | + |5: // Follow hash chain. + | movs NODE:INS, NODE:CARG3 + | bne <1 + | // End of hash chain: key not found, add a new one. + | + | // But check for __newindex first. + | ldr TAB:CARG1, TAB:RB->metatable + | mov CARG3, TMPDp + | str PC, SAVE_PC + | cmp TAB:CARG1, #0 // No metatable: continue. + | str BASE, L->base + | ldrbne CARG2, TAB:CARG1->nomm + | mov CARG1, L + | beq >6 + | tst CARG2, #1<vmeta_tsets // 'no __newindex' flag NOT set: check. + |6: + | mvn CARG4, #~LJ_TSTR + | str STR:RC, TMPDlo + | mov CARG2, TAB:RB + | str CARG4, TMPDhi + | bl extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k) + | // Returns TValue *. + | ldr BASE, L->base + | ldrd CARG34, [BASE, RA] + | strd CARG34, [CRET1] + | b <3 // No 2nd write barrier needed. + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, CARG2, CARG3 + | b <3 + break; + case BC_TSETB: + | decode_RB8 RB, INS + | and RC, RC, #255 + | // RA = src*8, RB = table*8, RC = index + | ldrd CARG12, [BASE, RB] + | checktab CARG2, ->vmeta_tsetb // STALL: load CARG12. + | ldr CARG3, TAB:CARG1->asize + | ldr RB, TAB:CARG1->array + | lsl CARG2, RC, #3 + | cmp RC, CARG3 + | ldrdlo CARG34, [CARG2, RB]! + | bhs ->vmeta_tsetb + | ins_next1 // Overwrites RB! + | checktp CARG4, LJ_TNIL + | ldrb INS, TAB:CARG1->marked + | ldrd CARG34, [BASE, RA] + | beq >5 + |1: + | tst INS, #LJ_GC_BLACK // isblack(table) + | strd CARG34, [CARG2] + | bne >7 + |2: + | ins_next2 + | ins_next3 + | + |5: // Check for __newindex if previous value is nil. + | ldr TAB:RA, TAB:CARG1->metatable + | cmp TAB:RA, #0 + | beq <1 // No metatable: done. + | ldrb RA, TAB:RA->nomm + | tst RA, #1<vmeta_tsetb + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:CARG1, INS, CARG3 + | b <2 + break; + + case BC_TSETM: + | // RA = base*8 (table at base-1), RC = num_const (start index) + | add RA, BASE, RA + |1: + | ldr RB, SAVE_MULTRES + | ldr TAB:CARG2, [RA, #-8] // Guaranteed to be a table. + | ldr CARG1, [KBASE, RC, lsl #3] // Integer constant is in lo-word. + | subs RB, RB, #8 + | ldr CARG4, TAB:CARG2->asize + | beq >4 // Nothing to copy? + | add CARG3, CARG1, RB, lsr #3 + | cmp CARG3, CARG4 + | ldr CARG4, TAB:CARG2->array + | add RB, RA, RB + | bhi >5 + | add INS, CARG4, CARG1, lsl #3 + | ldrb CARG1, TAB:CARG2->marked + |3: // Copy result slots to table. + | ldrd CARG34, [RA], #8 + | strd CARG34, [INS], #8 + | cmp RA, RB + | blo <3 + | tst CARG1, #LJ_GC_BLACK // isblack(table) + | bne >7 + |4: + | ins_next + | + |5: // Need to resize array part. + | str BASE, L->base + | mov CARG1, L + | str PC, SAVE_PC + | bl extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize) + | // Must not reallocate the stack. + | IOS ldr BASE, L->base + | b <1 + | + |7: // Possible table write barrier for any value. Skip valiswhite check. + | barrierback TAB:CARG2, CARG1, CARG3 + | b <4 + break; + + /* -- Calls and vararg handling ----------------------------------------- */ + + case BC_CALLM: + | // RA = base*8, (RB = nresults+1,) RC = extra_nargs + | ldr CARG1, SAVE_MULTRES + | decode_RC8 NARGS8:RC, INS + | add NARGS8:RC, NARGS8:RC, CARG1 + | b ->BC_CALL_Z + break; + case BC_CALL: + | decode_RC8 NARGS8:RC, INS + | // RA = base*8, (RB = nresults+1,) RC = (nargs+1)*8 + |->BC_CALL_Z: + | mov RB, BASE // Save old BASE for vmeta_call. + | ldrd CARG34, [BASE, RA]! + | sub NARGS8:RC, NARGS8:RC, #8 + | add BASE, BASE, #8 + | checkfunc CARG4, ->vmeta_call + | ins_call + break; + + case BC_CALLMT: + | // RA = base*8, (RB = 0,) RC = extra_nargs + | ldr CARG1, SAVE_MULTRES + | add NARGS8:RC, CARG1, RC, lsl #3 + | b ->BC_CALLT1_Z + break; + case BC_CALLT: + | lsl NARGS8:RC, RC, #3 + | // RA = base*8, (RB = 0,) RC = (nargs+1)*8 + |->BC_CALLT1_Z: + | ldrd LFUNC:CARG34, [RA, BASE]! + | sub NARGS8:RC, NARGS8:RC, #8 + | add RA, RA, #8 + | checkfunc CARG4, ->vmeta_callt + | ldr PC, [BASE, FRAME_PC] + |->BC_CALLT2_Z: + | mov RB, #0 + | ldrb CARG4, LFUNC:CARG3->ffid + | tst PC, #FRAME_TYPE + | bne >7 + |1: + | str LFUNC:CARG3, [BASE, FRAME_FUNC] // Copy function down, but keep PC. + | cmp NARGS8:RC, #0 + | beq >3 + |2: + | ldrd CARG12, [RA, RB] + | add INS, RB, #8 + | cmp INS, NARGS8:RC + | strd CARG12, [BASE, RB] + | mov RB, INS + | bne <2 + |3: + | cmp CARG4, #1 // (> FF_C) Calling a fast function? + | bhi >5 + |4: + | ins_callt + | + |5: // Tailcall to a fast function with a Lua frame below. + | ldr INS, [PC, #-4] + | decode_RA8 RA, INS + | sub CARG1, BASE, RA + | ldr LFUNC:CARG1, [CARG1, #-16] + | ldr CARG1, LFUNC:CARG1->field_pc + | ldr KBASE, [CARG1, #PC2PROTO(k)] + | b <4 + | + |7: // Tailcall from a vararg function. + | eor PC, PC, #FRAME_VARG + | tst PC, #FRAME_TYPEP // Vararg frame below? + | movne CARG4, #0 // Clear ffid if no Lua function below. + | bne <1 + | sub BASE, BASE, PC + | ldr PC, [BASE, FRAME_PC] + | tst PC, #FRAME_TYPE + | movne CARG4, #0 // Clear ffid if no Lua function below. + | b <1 + break; + + case BC_ITERC: + | // RA = base*8, (RB = nresults+1, RC = nargs+1 (2+1)) + | add RA, BASE, RA + | mov RB, BASE // Save old BASE for vmeta_call. + | ldrd CARG34, [RA, #-16] + | ldrd CARG12, [RA, #-8] + | add BASE, RA, #8 + | strd CARG34, [RA, #8] // Copy state. + | strd CARG12, [RA, #16] // Copy control var. + | // STALL: locked CARG34. + | ldrd LFUNC:CARG34, [RA, #-24] + | mov NARGS8:RC, #16 // Iterators get 2 arguments. + | // STALL: load CARG34. + | strd LFUNC:CARG34, [RA] // Copy callable. + | checkfunc CARG4, ->vmeta_call + | ins_call + break; + + case BC_ITERN: + | // RA = base*8, (RB = nresults+1, RC = nargs+1 (2+1)) +#if LJ_HASJIT + | // NYI: add hotloop, record BC_ITERN. +#endif + | add RA, BASE, RA + | ldr TAB:RB, [RA, #-16] + | ldr CARG1, [RA, #-8] // Get index from control var. + | ldr INS, TAB:RB->asize + | ldr CARG2, TAB:RB->array + | add PC, PC, #4 + |1: // Traverse array part. + | subs RC, CARG1, INS + | add CARG3, CARG2, CARG1, lsl #3 + | bhs >5 // Index points after array part? + | ldrd CARG34, [CARG3] + | checktp CARG4, LJ_TNIL + | addeq CARG1, CARG1, #1 // Skip holes in array part. + | beq <1 + | ldrh RC, [PC, #-2] + | mvn CARG2, #~LJ_TISNUM + | strd CARG34, [RA, #8] + | add RC, PC, RC, lsl #2 + | add RB, CARG1, #1 + | strd CARG12, [RA] + | sub PC, RC, #0x20000 + | str RB, [RA, #-8] // Update control var. + |3: + | ins_next + | + |5: // Traverse hash part. + | ldr CARG4, TAB:RB->hmask + | ldr NODE:RB, TAB:RB->node + |6: + | add CARG1, RC, RC, lsl #1 + | cmp RC, CARG4 // End of iteration? Branch to ITERL+1. + | add NODE:CARG3, NODE:RB, CARG1, lsl #3 // node = tab->node + idx*3*8 + | bhi <3 + | ldrd CARG12, NODE:CARG3->val + | checktp CARG2, LJ_TNIL + | add RC, RC, #1 + | beq <6 // Skip holes in hash part. + | ldrh RB, [PC, #-2] + | add RC, RC, INS + | ldrd CARG34, NODE:CARG3->key + | str RC, [RA, #-8] // Update control var. + | strd CARG12, [RA, #8] + | add RC, PC, RB, lsl #2 + | sub PC, RC, #0x20000 + | strd CARG34, [RA] + | b <3 + break; + + case BC_ISNEXT: + | // RA = base*8, RC = target (points to ITERN) + | add RA, BASE, RA + | add RC, PC, RC, lsl #2 + | ldrd CFUNC:CARG12, [RA, #-24] + | ldr CARG3, [RA, #-12] + | ldr CARG4, [RA, #-4] + | checktp CARG2, LJ_TFUNC + | ldrbeq CARG1, CFUNC:CARG1->ffid + | checktpeq CARG3, LJ_TTAB + | checktpeq CARG4, LJ_TNIL + | cmpeq CARG1, #FF_next_N + | subeq PC, RC, #0x20000 + | bne >5 + | ins_next1 + | ins_next2 + | mov CARG1, #0 + | str CARG1, [RA, #-8] // Initialize control var. + |1: + | ins_next3 + |5: // Despecialize bytecode if any of the checks fail. + | mov CARG1, #BC_JMP + | mov OP, #BC_ITERC + | strb CARG1, [PC, #-4] + | sub PC, RC, #0x20000 + | strb OP, [PC] // Subsumes ins_next1. + | ins_next2 + | b <1 + break; + + case BC_VARG: + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8 + | ldr CARG1, [BASE, FRAME_PC] + | add RC, BASE, RC + | add RA, BASE, RA + | add RC, RC, #FRAME_VARG + | add CARG4, RA, RB + | sub CARG3, BASE, #8 // CARG3 = vtop + | sub RC, RC, CARG1 // RC = vbase + | // Note: RC may now be even _above_ BASE if nargs was < numparams. + | cmp RB, #0 + | sub CARG1, CARG3, RC + | beq >5 // Copy all varargs? + | sub CARG4, CARG4, #16 + |1: // Copy vararg slots to destination slots. + | cmp RC, CARG3 + | ldrdlo CARG12, [RC], #8 + | mvnhs CARG2, #~LJ_TNIL + | cmp RA, CARG4 + | strd CARG12, [RA], #8 + | blo <1 + |2: + | ins_next + | + |5: // Copy all varargs. + | ldr CARG4, L->maxstack + | cmp CARG1, #0 + | movle RB, #8 // MULTRES = (0+1)*8 + | addgt RB, CARG1, #8 + | add CARG2, RA, CARG1 + | str RB, SAVE_MULTRES + | ble <2 + | cmp CARG2, CARG4 + | bhi >7 + |6: + | ldrd CARG12, [RC], #8 + | strd CARG12, [RA], #8 + | cmp RC, CARG3 + | blo <6 + | b <2 + | + |7: // Grow stack for varargs. + | lsr CARG2, CARG1, #3 + | str RA, L->top + | mov CARG1, L + | str BASE, L->base + | sub RC, RC, BASE // Need delta, because BASE may change. + | str PC, SAVE_PC + | sub RA, RA, BASE + | bl extern lj_state_growstack // (lua_State *L, int n) + | ldr BASE, L->base + | add RA, BASE, RA + | add RC, BASE, RC + | sub CARG3, BASE, #8 + | b <6 + break; + + /* -- Returns ----------------------------------------------------------- */ + + case BC_RETM: + | // RA = results*8, RC = extra results + | ldr CARG1, SAVE_MULTRES + | ldr PC, [BASE, FRAME_PC] + | add RA, BASE, RA + | add RC, CARG1, RC, lsl #3 + | b ->BC_RETM_Z + break; + + case BC_RET: + | // RA = results*8, RC = nresults+1 + | ldr PC, [BASE, FRAME_PC] + | lsl RC, RC, #3 + | add RA, BASE, RA + |->BC_RETM_Z: + | str RC, SAVE_MULTRES + |1: + | ands CARG1, PC, #FRAME_TYPE + | eor CARG2, PC, #FRAME_VARG + | bne ->BC_RETV2_Z + | + |->BC_RET_Z: + | // BASE = base, RA = resultptr, RC = (nresults+1)*8, PC = return + | ldr INS, [PC, #-4] + | subs CARG4, RC, #8 + | sub CARG3, BASE, #8 + | beq >3 + |2: + | ldrd CARG12, [RA], #8 + | add BASE, BASE, #8 + | subs CARG4, CARG4, #8 + | strd CARG12, [BASE, #-16] + | bne <2 + |3: + | decode_RA8 RA, INS + | sub CARG4, CARG3, RA + | decode_RB8 RB, INS + | ldr LFUNC:CARG1, [CARG4, FRAME_FUNC] + |5: + | cmp RB, RC // More results expected? + | bhi >6 + | mov BASE, CARG4 + | ldr CARG2, LFUNC:CARG1->field_pc + | ins_next1 + | ins_next2 + | ldr KBASE, [CARG2, #PC2PROTO(k)] + | ins_next3 + | + |6: // Fill up results with nil. + | mvn CARG2, #~LJ_TNIL + | add BASE, BASE, #8 + | add RC, RC, #8 + | str CARG2, [BASE, #-12] + | b <5 + | + |->BC_RETV1_Z: // Non-standard return case. + | add RA, BASE, RA + |->BC_RETV2_Z: + | tst CARG2, #FRAME_TYPEP + | bne ->vm_return + | // Return from vararg function: relocate BASE down. + | sub BASE, BASE, CARG2 + | ldr PC, [BASE, FRAME_PC] + | b <1 + break; + + case BC_RET0: case BC_RET1: + | // RA = results*8, RC = nresults+1 + | ldr PC, [BASE, FRAME_PC] + | lsl RC, RC, #3 + | str RC, SAVE_MULTRES + | ands CARG1, PC, #FRAME_TYPE + | eor CARG2, PC, #FRAME_VARG + | ldreq INS, [PC, #-4] + | bne ->BC_RETV1_Z + if (op == BC_RET1) { + | ldrd CARG12, [BASE, RA] + } + | sub CARG4, BASE, #8 + | decode_RA8 RA, INS + if (op == BC_RET1) { + | strd CARG12, [CARG4] + } + | sub BASE, CARG4, RA + | decode_RB8 RB, INS + | ldr LFUNC:CARG1, [BASE, FRAME_FUNC] + |5: + | cmp RB, RC + | bhi >6 + | ldr CARG2, LFUNC:CARG1->field_pc + | ins_next1 + | ins_next2 + | ldr KBASE, [CARG2, #PC2PROTO(k)] + | ins_next3 + | + |6: // Fill up results with nil. + | sub CARG2, CARG4, #4 + | mvn CARG3, #~LJ_TNIL + | str CARG3, [CARG2, RC] + | add RC, RC, #8 + | b <5 + break; + + /* -- Loops and branches ------------------------------------------------ */ + + |.define FOR_IDX, [RA]; .define FOR_TIDX, [RA, #4] + |.define FOR_STOP, [RA, #8]; .define FOR_TSTOP, [RA, #12] + |.define FOR_STEP, [RA, #16]; .define FOR_TSTEP, [RA, #20] + |.define FOR_EXT, [RA, #24]; .define FOR_TEXT, [RA, #28] + + case BC_FORL: +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_IFORL follows. + break; + + case BC_JFORI: + case BC_JFORL: +#if !LJ_HASJIT + break; +#endif + case BC_FORI: + case BC_IFORL: + | // RA = base*8, RC = target (after end of loop or start of loop) + vk = (op == BC_IFORL || op == BC_JFORL); + | ldrd CARG12, [RA, BASE]! + if (op != BC_JFORL) { + | add RC, PC, RC, lsl #2 + } + if (!vk) { + | ldrd CARG34, FOR_STOP + | checktp CARG2, LJ_TISNUM + | ldr RB, FOR_TSTEP + | bne >5 + | checktp CARG4, LJ_TISNUM + | ldr CARG4, FOR_STEP + | checktpeq RB, LJ_TISNUM + | bne ->vmeta_for + | cmp CARG4, #0 + | blt >4 + | cmp CARG1, CARG3 + } else { + | ldrd CARG34, FOR_STEP + | checktp CARG2, LJ_TISNUM + | bne >5 + | adds CARG1, CARG1, CARG3 + | ldr CARG4, FOR_STOP + if (op == BC_IFORL) { + | addvs RC, PC, #0x20000 // Overflow: prevent branch. + } else { + | bvs >2 // Overflow: do not enter mcode. + } + | cmp CARG3, #0 + | blt >4 + | cmp CARG1, CARG4 + } + |1: + if (op == BC_FORI) { + | subgt PC, RC, #0x20000 + } else if (op == BC_JFORI) { + | sub PC, RC, #0x20000 + | ldrhle RC, [PC, #-2] + } else if (op == BC_IFORL) { + | suble PC, RC, #0x20000 + } + if (vk) { + | strd CARG12, FOR_IDX + } + |2: + | ins_next1 + | ins_next2 + | strd CARG12, FOR_EXT + if (op == BC_JFORI || op == BC_JFORL) { + | ble =>BC_JLOOP + } + |3: + | ins_next3 + | + |4: // Invert check for negative step. + if (!vk) { + | cmp CARG3, CARG1 + } else { + | cmp CARG4, CARG1 + } + | b <1 + | + |5: // FP loop. + if (!vk) { + | cmnlo CARG4, #-LJ_TISNUM + | cmnlo RB, #-LJ_TISNUM + | bhs ->vmeta_for + | cmp RB, #0 + | strd CARG12, FOR_IDX + | strd CARG12, FOR_EXT + | blt >8 + } else { + | cmp CARG4, #0 + | blt >8 + | bl extern __aeabi_dadd + | strd CARG12, FOR_IDX + | ldrd CARG34, FOR_STOP + | strd CARG12, FOR_EXT + } + |6: + | bl extern __aeabi_cdcmple + if (op == BC_FORI) { + | subhi PC, RC, #0x20000 + } else if (op == BC_JFORI) { + | sub PC, RC, #0x20000 + | ldrhls RC, [PC, #-2] + | bls =>BC_JLOOP + } else if (op == BC_IFORL) { + | subls PC, RC, #0x20000 + } else { + | bls =>BC_JLOOP + } + | ins_next1 + | ins_next2 + | b <3 + | + |8: // Invert check for negative step. + if (vk) { + | bl extern __aeabi_dadd + | strd CARG12, FOR_IDX + | strd CARG12, FOR_EXT + } + | mov CARG3, CARG1 + | mov CARG4, CARG2 + | ldrd CARG12, FOR_STOP + | b <6 + break; + + case BC_ITERL: +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_IITERL follows. + break; + + case BC_JITERL: +#if !LJ_HASJIT + break; +#endif + case BC_IITERL: + | // RA = base*8, RC = target + | ldrd CARG12, [RA, BASE]! + if (op == BC_JITERL) { + | cmn CARG2, #-LJ_TNIL // Stop if iterator returned nil. + | strdne CARG12, [RA, #-8] + | bne =>BC_JLOOP + } else { + | add RC, PC, RC, lsl #2 + | // STALL: load CARG12. + | cmn CARG2, #-LJ_TNIL // Stop if iterator returned nil. + | subne PC, RC, #0x20000 // Otherwise save control var + branch. + | strdne CARG12, [RA, #-8] + } + | ins_next + break; + + case BC_LOOP: + | // RA = base*8, RC = target (loop extent) + | // Note: RA/RC is only used by trace recorder to determine scope/extent + | // This opcode does NOT jump, it's only purpose is to detect a hot loop. +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_ILOOP follows. + break; + + case BC_ILOOP: + | // RA = base*8, RC = target (loop extent) + | ins_next + break; + + case BC_JLOOP: +#if LJ_HASJIT + | // RA = base (ignored), RC = traceno + | ldr CARG1, [DISPATCH, #DISPATCH_J(trace)] + | mov CARG2, #0 // Traces on ARM don't store the trace number, so use 0. + | ldr TRACE:RC, [CARG1, RC, lsl #2] + | st_vmstate CARG2 + | ldr RA, TRACE:RC->mcode + | str BASE, [DISPATCH, #DISPATCH_GL(jit_base)] + | str L, [DISPATCH, #DISPATCH_GL(jit_L)] + | bx RA +#endif + break; + + case BC_JMP: + | // RA = base*8 (only used by trace recorder), RC = target + | add RC, PC, RC, lsl #2 + | sub PC, RC, #0x20000 + | ins_next + break; + + /* -- Function headers -------------------------------------------------- */ + + case BC_FUNCF: +#if LJ_HASJIT + | hotcall +#endif + case BC_FUNCV: /* NYI: compiled vararg functions. */ + | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow. + break; + + case BC_JFUNCF: +#if !LJ_HASJIT + break; +#endif + case BC_IFUNCF: + | // BASE = new base, RA = BASE+framesize*8, CARG3 = LFUNC, RC = nargs*8 + | ldr CARG1, L->maxstack + | ldrb CARG2, [PC, #-4+PC2PROTO(numparams)] + | ldr KBASE, [PC, #-4+PC2PROTO(k)] + | cmp RA, CARG1 + | bhi ->vm_growstack_l + if (op != BC_JFUNCF) { + | ins_next1 + | ins_next2 + } + |2: + | cmp NARGS8:RC, CARG2, lsl #3 // Check for missing parameters. + | mvn CARG4, #~LJ_TNIL + | blo >3 + if (op == BC_JFUNCF) { + | decode_RD RC, INS + | b =>BC_JLOOP + } else { + | ins_next3 + } + | + |3: // Clear missing parameters. + | strd CARG34, [BASE, NARGS8:RC] + | add NARGS8:RC, NARGS8:RC, #8 + | b <2 + break; + + case BC_JFUNCV: +#if !LJ_HASJIT + break; +#endif + | NYI // NYI: compiled vararg functions + break; /* NYI: compiled vararg functions. */ + + case BC_IFUNCV: + | // BASE = new base, RA = BASE+framesize*8, CARG3 = LFUNC, RC = nargs*8 + | ldr CARG1, L->maxstack + | add CARG4, BASE, RC + | add RA, RA, RC + | str LFUNC:CARG3, [CARG4] // Store copy of LFUNC. + | add CARG2, RC, #8+FRAME_VARG + | ldr KBASE, [PC, #-4+PC2PROTO(k)] + | cmp RA, CARG1 + | str CARG2, [CARG4, #4] // Store delta + FRAME_VARG. + | bhs ->vm_growstack_l + | ldrb RB, [PC, #-4+PC2PROTO(numparams)] + | mov RA, BASE + | mov RC, CARG4 + | cmp RB, #0 + | add BASE, CARG4, #8 + | beq >3 + | mvn CARG3, #~LJ_TNIL + |1: + | cmp RA, RC // Less args than parameters? + | ldrdlo CARG12, [RA], #8 + | movhs CARG2, CARG3 + | strlo CARG3, [RA, #-4] // Clear old fixarg slot (help the GC). + |2: + | subs RB, RB, #1 + | strd CARG12, [CARG4, #8]! + | bne <1 + |3: + | ins_next + break; + + case BC_FUNCC: + case BC_FUNCCW: + | // BASE = new base, RA = BASE+framesize*8, CARG3 = CFUNC, RC = nargs*8 + if (op == BC_FUNCC) { + | ldr CARG4, CFUNC:CARG3->f + } else { + | ldr CARG4, [DISPATCH, #DISPATCH_GL(wrapf)] + } + | add CARG2, RA, NARGS8:RC + | ldr CARG1, L->maxstack + | add RC, BASE, NARGS8:RC + | str BASE, L->base + | cmp CARG2, CARG1 + | str RC, L->top + if (op == BC_FUNCCW) { + | ldr CARG2, CFUNC:CARG3->f + } + | mv_vmstate CARG3, C + | mov CARG1, L + | bhi ->vm_growstack_c // Need to grow stack. + | st_vmstate CARG3 + | blx CARG4 // (lua_State *L [, lua_CFunction f]) + | // Returns nresults. + | ldr BASE, L->base + | mv_vmstate CARG3, INTERP + | ldr CRET2, L->top + | lsl RC, CRET1, #3 + | st_vmstate CARG3 + | ldr PC, [BASE, FRAME_PC] + | sub RA, CRET2, RC // RA = L->top - nresults*8 + | b ->vm_returnc + break; + + /* ---------------------------------------------------------------------- */ + + default: + fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); + exit(2); + break; + } +} + +static int build_backend(BuildCtx *ctx) +{ + int op; + + dasm_growpc(Dst, BC__MAX); + + build_subroutines(ctx); + + |.code_op + for (op = 0; op < BC__MAX; op++) + build_ins(ctx, (BCOp)op, op); + + return BC__MAX; +} + +/* Emit pseudo frame-info for all assembler functions. */ +static void emit_asm_debug(BuildCtx *ctx) +{ + int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); + int i; + switch (ctx->mode) { + case BUILD_elfasm: + fprintf(ctx->fp, "\t.section .debug_frame,\"\",%%progbits\n"); + fprintf(ctx->fp, + ".Lframe0:\n" + "\t.long .LECIE0-.LSCIE0\n" + ".LSCIE0:\n" + "\t.long 0xffffffff\n" + "\t.byte 0x1\n" + "\t.string \"\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -4\n" + "\t.byte 0xe\n" /* Return address is in lr. */ + "\t.byte 0xc\n\t.uleb128 0xd\n\t.uleb128 0\n" /* def_cfa sp */ + "\t.align 2\n" + ".LECIE0:\n\n"); + fprintf(ctx->fp, + ".LSFDE0:\n" + "\t.long .LEFDE0-.LASFDE0\n" + ".LASFDE0:\n" + "\t.long .Lframe0\n" + "\t.long .Lbegin\n" + "\t.long %d\n" + "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ + "\t.byte 0x8e\n\t.uleb128 1\n", /* offset lr */ + fcofs, CFRAME_SIZE); + for (i = 11; i >= 4; i--) /* offset r4-r11 */ + fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 2+(11-i)); + fprintf(ctx->fp, + "\t.align 2\n" + ".LEFDE0:\n\n"); +#if LJ_HASFFI + fprintf(ctx->fp, + ".LSFDE1:\n" + "\t.long .LEFDE1-.LASFDE1\n" + ".LASFDE1:\n" + "\t.long .Lframe0\n" + "\t.long lj_vm_ffi_call\n" + "\t.long %d\n" + "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ + "\t.byte 0x8e\n\t.uleb128 1\n" /* offset lr */ + "\t.byte 0x8b\n\t.uleb128 2\n" /* offset r11 */ + "\t.byte 0x85\n\t.uleb128 3\n" /* offset r5 */ + "\t.byte 0x84\n\t.uleb128 4\n" /* offset r4 */ + "\t.byte 0xd\n\t.uleb128 0xb\n" /* def_cfa_register r11 */ + "\t.align 2\n" + ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); +#endif + break; + default: + break; + } +} + diff --git a/src/vm_mips.dasc b/src/vm_mips.dasc new file mode 100644 index 00000000..a7c3b4ae --- /dev/null +++ b/src/vm_mips.dasc @@ -0,0 +1,4224 @@ +|// Low-level VM code for MIPS CPUs. +|// Bytecode interpreter, fast functions and helper functions. +|// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +| +|.arch mips +|.section code_op, code_sub +| +|.actionlist build_actionlist +|.globals GLOB_ +|.globalnames globnames +|.externnames extnames +| +|// Note: The ragged indentation of the instructions is intentional. +|// The starting columns indicate data dependencies. +| +|//----------------------------------------------------------------------- +| +|// Fixed register assignments for the interpreter. +|// Don't use: r0 = 0, r26/r27 = reserved, r28 = gp, r29 = sp, r31 = ra +| +|// The following must be C callee-save (but BASE is often refetched). +|.define BASE, r16 // Base of current Lua stack frame. +|.define KBASE, r17 // Constants of current Lua function. +|.define PC, r18 // Next PC. +|.define DISPATCH, r19 // Opcode dispatch table. +|.define LREG, r20 // Register holding lua_State (also in SAVE_L). +|.define MULTRES, r21 // Size of multi-result: (nresults+1)*8. +|// NYI: r22 currently unused. +| +|.define JGL, r30 // On-trace: global_State + 32768. +| +|// Constants for type-comparisons, stores and conversions. C callee-save. +|.define TISNIL, r30 +|.define TOBIT, f30 // 2^52 + 2^51. +| +|// The following temporaries are not saved across C calls, except for RA. +|.define RA, r23 // Callee-save. +|.define RB, r8 +|.define RC, r9 +|.define RD, r10 +|.define INS, r11 +| +|.define AT, r1 // Assembler temporary. +|.define TMP0, r12 +|.define TMP1, r13 +|.define TMP2, r14 +|.define TMP3, r15 +| +|// Calling conventions. +|.define CFUNCADDR, r25 +|.define CARG1, r4 +|.define CARG2, r5 +|.define CARG3, r6 +|.define CARG4, r7 +| +|.define CRET1, r2 +|.define CRET2, r3 +| +|.define FARG1, f12 +|.define FARG2, f14 +| +|.define FRET1, f0 +|.define FRET2, f2 +| +|// Stack layout while in interpreter. Must match with lj_frame.h. +|.define CFRAME_SPACE, 112 // Delta for sp. +| +|.define SAVE_ERRF, 124(sp) // 32 bit C frame info. +|.define SAVE_NRES, 120(sp) +|.define SAVE_CFRAME, 116(sp) +|.define SAVE_L, 112(sp) +|//----- 8 byte aligned, ^^^^ 16 byte register save area, owned by interpreter. +|.define SAVE_GPR_, 72 // .. 72+10*4: 32 bit GPR saves. +|.define SAVE_FPR_, 24 // .. 24+6*8: 64 bit FPR saves. +|.define SAVE_PC, 20(sp) +|.define ARG5, 16(sp) +|.define CSAVE_4, 12(sp) +|.define CSAVE_3, 8(sp) +|.define CSAVE_2, 4(sp) +|.define CSAVE_1, 0(sp) +|//----- 8 byte aligned, ^^^^ 16 byte register save area, owned by callee. +| +|.define ARG5_OFS, 16 +|.define SAVE_MULTRES, ARG5 +| +|.macro saveregs +| addiu sp, sp, -CFRAME_SPACE +| sw ra, SAVE_GPR_+9*4(sp) +| sw r30, SAVE_GPR_+8*4(sp) +| sdc1 f30, SAVE_FPR_+5*8(sp) +| sw r23, SAVE_GPR_+7*4(sp) +| sw r22, SAVE_GPR_+6*4(sp) +| sdc1 f28, SAVE_FPR_+4*8(sp) +| sw r21, SAVE_GPR_+5*4(sp) +| sw r20, SAVE_GPR_+4*4(sp) +| sdc1 f26, SAVE_FPR_+3*8(sp) +| sw r19, SAVE_GPR_+3*4(sp) +| sw r18, SAVE_GPR_+2*4(sp) +| sdc1 f24, SAVE_FPR_+2*8(sp) +| sw r17, SAVE_GPR_+1*4(sp) +| sw r16, SAVE_GPR_+0*4(sp) +| sdc1 f22, SAVE_FPR_+1*8(sp) +| sdc1 f20, SAVE_FPR_+0*8(sp) +|.endmacro +| +|.macro restoreregs_ret +| lw ra, SAVE_GPR_+9*4(sp) +| lw r30, SAVE_GPR_+8*4(sp) +| ldc1 f30, SAVE_FPR_+5*8(sp) +| lw r23, SAVE_GPR_+7*4(sp) +| lw r22, SAVE_GPR_+6*4(sp) +| ldc1 f28, SAVE_FPR_+4*8(sp) +| lw r21, SAVE_GPR_+5*4(sp) +| lw r20, SAVE_GPR_+4*4(sp) +| ldc1 f26, SAVE_FPR_+3*8(sp) +| lw r19, SAVE_GPR_+3*4(sp) +| lw r18, SAVE_GPR_+2*4(sp) +| ldc1 f24, SAVE_FPR_+2*8(sp) +| lw r17, SAVE_GPR_+1*4(sp) +| lw r16, SAVE_GPR_+0*4(sp) +| ldc1 f22, SAVE_FPR_+1*8(sp) +| ldc1 f20, SAVE_FPR_+0*8(sp) +| jr ra +| addiu sp, sp, CFRAME_SPACE +|.endmacro +| +|// Type definitions. Some of these are only used for documentation. +|.type L, lua_State, LREG +|.type GL, global_State +|.type TVALUE, TValue +|.type GCOBJ, GCobj +|.type STR, GCstr +|.type TAB, GCtab +|.type LFUNC, GCfuncL +|.type CFUNC, GCfuncC +|.type PROTO, GCproto +|.type UPVAL, GCupval +|.type NODE, Node +|.type NARGS8, int +|.type TRACE, GCtrace +| +|//----------------------------------------------------------------------- +| +|// Trap for not-yet-implemented parts. +|.macro NYI; .long 0xf0f0f0f0; .endmacro +| +|// Macros to mark delay slots. +|.macro ., a; a; .endmacro +|.macro ., a,b; a,b; .endmacro +|.macro ., a,b,c; a,b,c; .endmacro +| +|//----------------------------------------------------------------------- +| +|// Endian-specific defines. +|.define FRAME_PC, LJ_ENDIAN_SELECT(-4,-8) +|.define FRAME_FUNC, LJ_ENDIAN_SELECT(-8,-4) +|.define HI, LJ_ENDIAN_SELECT(4,0) +|.define LO, LJ_ENDIAN_SELECT(0,4) +|.define OFS_RD, LJ_ENDIAN_SELECT(2,0) +|.define OFS_RA, LJ_ENDIAN_SELECT(1,2) +|.define OFS_OP, LJ_ENDIAN_SELECT(0,3) +| +|// Instruction decode. +|.macro decode_OP1, dst, ins; andi dst, ins, 0xff; .endmacro +|.macro decode_OP4a, dst, ins; andi dst, ins, 0xff; .endmacro +|.macro decode_OP4b, dst; sll dst, dst, 2; .endmacro +|.macro decode_RC4a, dst, ins; srl dst, ins, 14; .endmacro +|.macro decode_RC4b, dst; andi dst, dst, 0x3fc; .endmacro +|.macro decode_RD4b, dst; sll dst, dst, 2; .endmacro +|.macro decode_RA8a, dst, ins; srl dst, ins, 5; .endmacro +|.macro decode_RA8b, dst; andi dst, dst, 0x7f8; .endmacro +|.macro decode_RB8a, dst, ins; srl dst, ins, 21; .endmacro +|.macro decode_RB8b, dst; andi dst, dst, 0x7f8; .endmacro +|.macro decode_RD8a, dst, ins; srl dst, ins, 16; .endmacro +|.macro decode_RD8b, dst; sll dst, dst, 3; .endmacro +|.macro decode_RDtoRC8, dst, src; andi dst, src, 0x7f8; .endmacro +| +|// Instruction fetch. +|.macro ins_NEXT1 +| lw INS, 0(PC) +| addiu PC, PC, 4 +|.endmacro +|// Instruction decode+dispatch. +|.macro ins_NEXT2 +| decode_OP4a TMP1, INS +| decode_OP4b TMP1 +| addu TMP0, DISPATCH, TMP1 +| decode_RD8a RD, INS +| lw AT, 0(TMP0) +| decode_RA8a RA, INS +| decode_RD8b RD +| jr AT +| decode_RA8b RA +|.endmacro +|.macro ins_NEXT +| ins_NEXT1 +| ins_NEXT2 +|.endmacro +| +|// Instruction footer. +|.if 1 +| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use. +| .define ins_next, ins_NEXT +| .define ins_next_, ins_NEXT +| .define ins_next1, ins_NEXT1 +| .define ins_next2, ins_NEXT2 +|.else +| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch. +| // Affects only certain kinds of benchmarks (and only with -j off). +| .macro ins_next +| b ->ins_next +| .endmacro +| .macro ins_next1 +| .endmacro +| .macro ins_next2 +| b ->ins_next +| .endmacro +| .macro ins_next_ +| ->ins_next: +| ins_NEXT +| .endmacro +|.endif +| +|// Call decode and dispatch. +|.macro ins_callt +| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC +| lw PC, LFUNC:RB->pc +| lw INS, 0(PC) +| addiu PC, PC, 4 +| decode_OP4a TMP1, INS +| decode_RA8a RA, INS +| decode_OP4b TMP1 +| decode_RA8b RA +| addu TMP0, DISPATCH, TMP1 +| lw TMP0, 0(TMP0) +| jr TMP0 +| addu RA, RA, BASE +|.endmacro +| +|.macro ins_call +| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, PC = caller PC +| sw PC, FRAME_PC(BASE) +| ins_callt +|.endmacro +| +|//----------------------------------------------------------------------- +| +|.macro branch_RD +| srl TMP0, RD, 1 +| lui AT, (-(BCBIAS_J*4 >> 16) & 65535) +| addu TMP0, TMP0, AT +| addu PC, PC, TMP0 +|.endmacro +| +|// Assumes DISPATCH is relative to GL. +#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) +#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) +#define GG_DISP2GOT (GG_OFS(got) - GG_OFS(dispatch)) +#define DISPATCH_GOT(name) (GG_DISP2GOT + 4*LJ_GOT_##name) +| +#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) +| +|.macro load_got, func +| lw CFUNCADDR, DISPATCH_GOT(func)(DISPATCH) +|.endmacro +|// Much faster. Sadly, there's no easy way to force the required code layout. +|// .macro call_intern, func; bal extern func; .endmacro +|.macro call_intern, func; jalr CFUNCADDR; .endmacro +|.macro call_extern; jalr CFUNCADDR; .endmacro +|.macro jmp_extern; jr CFUNCADDR; .endmacro +| +|.macro hotcheck, delta, target +| srl TMP1, PC, 1 +| andi TMP1, TMP1, 126 +| addu TMP1, TMP1, DISPATCH +| lhu TMP2, GG_DISP2HOT(TMP1) +| addiu TMP2, TMP2, -delta +| bltz TMP2, target +|. sh TMP2, GG_DISP2HOT(TMP1) +|.endmacro +| +|.macro hotloop +| hotcheck HOTCOUNT_LOOP, ->vm_hotloop +|.endmacro +| +|.macro hotcall +| hotcheck HOTCOUNT_CALL, ->vm_hotcall +|.endmacro +| +|// Set current VM state. Uses TMP0. +|.macro li_vmstate, st; li TMP0, ~LJ_VMST_..st; .endmacro +|.macro st_vmstate; sw TMP0, DISPATCH_GL(vmstate)(DISPATCH); .endmacro +| +|// Move table write barrier back. Overwrites mark and tmp. +|.macro barrierback, tab, mark, tmp, target +| lw tmp, DISPATCH_GL(gc.grayagain)(DISPATCH) +| andi mark, mark, ~LJ_GC_BLACK & 255 // black2gray(tab) +| sw tab, DISPATCH_GL(gc.grayagain)(DISPATCH) +| sb mark, tab->marked +| b target +|. sw tmp, tab->gclist +|.endmacro +| +|//----------------------------------------------------------------------- + +/* Generate subroutines used by opcodes and other parts of the VM. */ +/* The .code_sub section should be last to help static branch prediction. */ +static void build_subroutines(BuildCtx *ctx) +{ + |.code_sub + | + |//----------------------------------------------------------------------- + |//-- Return handling ---------------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_returnp: + | // See vm_return. Also: TMP2 = previous base. + | andi AT, PC, FRAME_P + | beqz AT, ->cont_dispatch + |. li TMP1, LJ_TTRUE + | + | // Return from pcall or xpcall fast func. + | lw PC, FRAME_PC(TMP2) // Fetch PC of previous frame. + | move BASE, TMP2 // Restore caller base. + | // Prepending may overwrite the pcall frame, so do it at the end. + | sw TMP1, FRAME_PC(RA) // Prepend true to results. + | addiu RA, RA, -8 + | + |->vm_returnc: + | andi TMP0, PC, FRAME_TYPE + | addiu RD, RD, 8 // RD = (nresults+1)*8. + | beqz TMP0, ->BC_RET_Z // Handle regular return to Lua. + |. move MULTRES, RD + | + |->vm_return: + | // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return + | // TMP0 = PC & FRAME_TYPE + | li TMP2, -8 + | xori AT, TMP0, FRAME_C + | and TMP2, PC, TMP2 + | bnez AT, ->vm_returnp + | subu TMP2, BASE, TMP2 // TMP2 = previous base. + | + | addiu TMP1, RD, -8 + | sw TMP2, L->base + | li_vmstate C + | lw TMP2, SAVE_NRES + | addiu BASE, BASE, -8 + | st_vmstate + | beqz TMP1, >2 + |. sll TMP2, TMP2, 3 + |1: + | addiu TMP1, TMP1, -8 + | ldc1 f0, 0(RA) + | addiu RA, RA, 8 + | sdc1 f0, 0(BASE) + | bnez TMP1, <1 + |. addiu BASE, BASE, 8 + | + |2: + | bne TMP2, RD, >6 + |3: + |. sw BASE, L->top // Store new top. + | + |->vm_leave_cp: + | lw TMP0, SAVE_CFRAME // Restore previous C frame. + | move CRET1, r0 // Ok return status for vm_pcall. + | sw TMP0, L->cframe + | + |->vm_leave_unw: + | restoreregs_ret + | + |6: + | lw TMP1, L->maxstack + | slt AT, TMP2, RD + | bnez AT, >7 // Less results wanted? + | // More results wanted. Check stack size and fill up results with nil. + |. slt AT, BASE, TMP1 + | beqz AT, >8 + |. nop + | sw TISNIL, HI(BASE) + | addiu RD, RD, 8 + | b <2 + |. addiu BASE, BASE, 8 + | + |7: // Less results wanted. + | subu TMP0, RD, TMP2 + | subu TMP0, BASE, TMP0 // Either keep top or shrink it. + | b <3 + |. movn BASE, TMP0, TMP2 // LUA_MULTRET+1 case? + | + |8: // Corner case: need to grow stack for filling up results. + | // This can happen if: + | // - A C function grows the stack (a lot). + | // - The GC shrinks the stack in between. + | // - A return back from a lua_call() with (high) nresults adjustment. + | load_got lj_state_growstack + | move MULTRES, RD + | move CARG2, TMP2 + | call_intern lj_state_growstack // (lua_State *L, int n) + |. move CARG1, L + | lw TMP2, SAVE_NRES + | lw BASE, L->top // Need the (realloced) L->top in BASE. + | move RD, MULTRES + | b <2 + |. sll TMP2, TMP2, 3 + | + |->vm_unwind_c: // Unwind C stack, return from vm_pcall. + | // (void *cframe, int errcode) + | move sp, CARG1 + | move CRET1, CARG2 + |->vm_unwind_c_eh: // Landing pad for external unwinder. + | lw L, SAVE_L + | li TMP0, ~LJ_VMST_C + | lw GL:TMP1, L->glref + | b ->vm_leave_unw + |. sw TMP0, GL:TMP1->vmstate + | + |->vm_unwind_ff: // Unwind C stack, return from ff pcall. + | // (void *cframe) + | li AT, -4 + | and sp, CARG1, AT + |->vm_unwind_ff_eh: // Landing pad for external unwinder. + | lw L, SAVE_L + | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). + | li TISNIL, LJ_TNIL + | lw BASE, L->base + | lw DISPATCH, L->glref // Setup pointer to dispatch table. + | mtc1 TMP3, TOBIT + | li TMP1, LJ_TFALSE + | li_vmstate INTERP + | lw PC, FRAME_PC(BASE) // Fetch PC of previous frame. + | cvt.d.s TOBIT, TOBIT + | addiu RA, BASE, -8 // Results start at BASE-8. + | addiu DISPATCH, DISPATCH, GG_G2DISP + | sw TMP1, HI(RA) // Prepend false to error message. + | st_vmstate + | b ->vm_returnc + |. li RD, 16 // 2 results: false + error message. + | + |//----------------------------------------------------------------------- + |//-- Grow stack for calls ----------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_growstack_c: // Grow stack for C function. + | b >2 + |. li CARG2, LUA_MINSTACK + | + |->vm_growstack_l: // Grow stack for Lua function. + | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC + | addu RC, BASE, RC + | subu RA, RA, BASE + | sw BASE, L->base + | addiu PC, PC, 4 // Must point after first instruction. + | sw RC, L->top + | srl CARG2, RA, 3 + |2: + | // L->base = new base, L->top = top + | load_got lj_state_growstack + | sw PC, SAVE_PC + | call_intern lj_state_growstack // (lua_State *L, int n) + |. move CARG1, L + | lw BASE, L->base + | lw RC, L->top + | lw LFUNC:RB, FRAME_FUNC(BASE) + | subu RC, RC, BASE + | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC + | ins_callt // Just retry the call. + | + |//----------------------------------------------------------------------- + |//-- Entry points into the assembler VM --------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_resume: // Setup C frame and resume thread. + | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0) + | saveregs + | move L, CARG1 + | lw DISPATCH, L->glref // Setup pointer to dispatch table. + | move BASE, CARG2 + | lbu TMP1, L->status + | sw L, SAVE_L + | li PC, FRAME_CP + | addiu TMP0, sp, CFRAME_RESUME + | addiu DISPATCH, DISPATCH, GG_G2DISP + | sw r0, SAVE_NRES + | sw r0, SAVE_ERRF + | sw TMP0, L->cframe + | sw r0, SAVE_CFRAME + | beqz TMP1, >3 + |. sw CARG1, SAVE_PC // Any value outside of bytecode is ok. + | + | // Resume after yield (like a return). + | move RA, BASE + | lw BASE, L->base + | lw TMP1, L->top + | lw PC, FRAME_PC(BASE) + | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). + | subu RD, TMP1, BASE + | mtc1 TMP3, TOBIT + | sb r0, L->status + | cvt.d.s TOBIT, TOBIT + | li_vmstate INTERP + | addiu RD, RD, 8 + | st_vmstate + | move MULTRES, RD + | andi TMP0, PC, FRAME_TYPE + | beqz TMP0, ->BC_RET_Z + |. li TISNIL, LJ_TNIL + | b ->vm_return + |. nop + | + |->vm_pcall: // Setup protected C frame and enter VM. + | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef) + | saveregs + | sw CARG4, SAVE_ERRF + | b >1 + |. li PC, FRAME_CP + | + |->vm_call: // Setup C frame and enter VM. + | // (lua_State *L, TValue *base, int nres1) + | saveregs + | li PC, FRAME_C + | + |1: // Entry point for vm_pcall above (PC = ftype). + | lw TMP1, L:CARG1->cframe + | sw CARG3, SAVE_NRES + | move L, CARG1 + | sw CARG1, SAVE_L + | move BASE, CARG2 + | sw sp, L->cframe // Add our C frame to cframe chain. + | lw DISPATCH, L->glref // Setup pointer to dispatch table. + | sw CARG1, SAVE_PC // Any value outside of bytecode is ok. + | sw TMP1, SAVE_CFRAME + | addiu DISPATCH, DISPATCH, GG_G2DISP + | + |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype). + | lw TMP2, L->base // TMP2 = old base (used in vmeta_call). + | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). + | lw TMP1, L->top + | mtc1 TMP3, TOBIT + | addu PC, PC, BASE + | subu NARGS8:RC, TMP1, BASE + | subu PC, PC, TMP2 // PC = frame delta + frame type + | cvt.d.s TOBIT, TOBIT + | li_vmstate INTERP + | li TISNIL, LJ_TNIL + | st_vmstate + | + |->vm_call_dispatch: + | // TMP2 = old base, BASE = new base, RC = nargs*8, PC = caller PC + | lw TMP0, FRAME_PC(BASE) + | li AT, LJ_TFUNC + | bne TMP0, AT, ->vmeta_call + |. lw LFUNC:RB, FRAME_FUNC(BASE) + | + |->vm_call_dispatch_f: + | ins_call + | // BASE = new base, RB = func, RC = nargs*8, PC = caller PC + | + |->vm_cpcall: // Setup protected C frame, call C. + | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp) + | saveregs + | move L, CARG1 + | lw TMP0, L:CARG1->stack + | sw CARG1, SAVE_L + | lw TMP1, L->top + | sw CARG1, SAVE_PC // Any value outside of bytecode is ok. + | subu TMP0, TMP0, TMP1 // Compute -savestack(L, L->top). + | lw TMP1, L->cframe + | sw sp, L->cframe // Add our C frame to cframe chain. + | sw TMP0, SAVE_NRES // Neg. delta means cframe w/o frame. + | sw r0, SAVE_ERRF // No error function. + | move CFUNCADDR, CARG4 + | jalr CARG4 // (lua_State *L, lua_CFunction func, void *ud) + |. sw TMP1, SAVE_CFRAME + | move BASE, CRET1 + | lw DISPATCH, L->glref // Setup pointer to dispatch table. + | li PC, FRAME_CP + | bnez CRET1, <3 // Else continue with the call. + |. addiu DISPATCH, DISPATCH, GG_G2DISP + | b ->vm_leave_cp // No base? Just remove C frame. + |. nop + | + |//----------------------------------------------------------------------- + |//-- Metamethod handling ------------------------------------------------ + |//----------------------------------------------------------------------- + | + |// The lj_meta_* functions (except for lj_meta_cat) don't reallocate the + |// stack, so BASE doesn't need to be reloaded across these calls. + | + |//-- Continuation dispatch ---------------------------------------------- + | + |->cont_dispatch: + | // BASE = meta base, RA = resultptr, RD = (nresults+1)*8 + | lw TMP0, -16+LO(BASE) // Continuation. + | move RB, BASE + | move BASE, TMP2 // Restore caller BASE. + | lw LFUNC:TMP1, FRAME_FUNC(TMP2) +#if LJ_HASFFI + | sltiu AT, TMP0, 2 +#endif + | lw PC, -16+HI(RB) // Restore PC from [cont|PC]. + | addu TMP2, RA, RD + | lw TMP1, LFUNC:TMP1->pc +#if LJ_HASFFI + | bnez AT, >1 +#endif + |. sw TISNIL, -8+HI(TMP2) // Ensure one valid arg. + | // BASE = base, RA = resultptr, RB = meta base + | jr TMP0 // Jump to continuation. + |. lw KBASE, PC2PROTO(k)(TMP1) + | +#if LJ_HASFFI + |1: + | bnez TMP0, ->cont_ffi_callback // cont = 1: return from FFI callback. + | // cont = 0: tailcall from C function. + |. addiu TMP1, RB, -16 + | b ->vm_call_tail + |. subu RC, TMP1, BASE +#endif + | + |->cont_cat: // RA = resultptr, RB = meta base + | lw INS, -4(PC) + | addiu CARG2, RB, -16 + | ldc1 f0, 0(RA) + | decode_RB8a MULTRES, INS + | decode_RA8a RA, INS + | decode_RB8b MULTRES + | decode_RA8b RA + | addu TMP1, BASE, MULTRES + | sw BASE, L->base + | subu CARG3, CARG2, TMP1 + | bne TMP1, CARG2, ->BC_CAT_Z + |. sdc1 f0, 0(CARG2) + | addu RA, BASE, RA + | b ->cont_nop + |. sdc1 f0, 0(RA) + | + |//-- Table indexing metamethods ----------------------------------------- + | + |->vmeta_tgets1: + | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) + | li TMP0, LJ_TSTR + | sw STR:RC, LO(CARG3) + | b >1 + |. sw TMP0, HI(CARG3) + | + |->vmeta_tgets: + | addiu CARG2, DISPATCH, DISPATCH_GL(tmptv) + | li TMP0, LJ_TTAB + | sw TAB:RB, LO(CARG2) + | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv2) + | sw TMP0, HI(CARG2) + | li TMP1, LJ_TSTR + | sw STR:RC, LO(CARG3) + | b >1 + |. sw TMP1, HI(CARG3) + | + |->vmeta_tgetb: // TMP0 = index + | mtc1 TMP0, f0 + | cvt.d.w f0, f0 + | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) + | sdc1 f0, 0(CARG3) + | + |->vmeta_tgetv: + |1: + | load_got lj_meta_tget + | sw BASE, L->base + | sw PC, SAVE_PC + | call_intern lj_meta_tget // (lua_State *L, TValue *o, TValue *k) + |. move CARG1, L + | // Returns TValue * (finished) or NULL (metamethod). + | beqz CRET1, >3 + |. addiu TMP1, BASE, -FRAME_CONT + | ldc1 f0, 0(CRET1) + | ins_next1 + | sdc1 f0, 0(RA) + | ins_next2 + | + |3: // Call __index metamethod. + | // BASE = base, L->top = new base, stack = cont/func/t/k + | lw BASE, L->top + | sw PC, -16+HI(BASE) // [cont|PC] + | subu PC, BASE, TMP1 + | lw LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. + | b ->vm_call_dispatch_f + |. li NARGS8:RC, 16 // 2 args for func(t, k). + | + |//----------------------------------------------------------------------- + | + |->vmeta_tsets1: + | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) + | li TMP0, LJ_TSTR + | sw STR:RC, LO(CARG3) + | b >1 + |. sw TMP0, HI(CARG3) + | + |->vmeta_tsets: + | addiu CARG2, DISPATCH, DISPATCH_GL(tmptv) + | li TMP0, LJ_TTAB + | sw TAB:RB, LO(CARG2) + | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv2) + | sw TMP0, HI(CARG2) + | li TMP1, LJ_TSTR + | sw STR:RC, LO(CARG3) + | b >1 + |. sw TMP1, HI(CARG3) + | + |->vmeta_tsetb: // TMP0 = index + | mtc1 TMP0, f0 + | cvt.d.w f0, f0 + | addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) + | sdc1 f0, 0(CARG3) + | + |->vmeta_tsetv: + |1: + | load_got lj_meta_tset + | sw BASE, L->base + | sw PC, SAVE_PC + | call_intern lj_meta_tset // (lua_State *L, TValue *o, TValue *k) + |. move CARG1, L + | // Returns TValue * (finished) or NULL (metamethod). + | beqz CRET1, >3 + |. ldc1 f0, 0(RA) + | // NOBARRIER: lj_meta_tset ensures the table is not black. + | ins_next1 + | sdc1 f0, 0(CRET1) + | ins_next2 + | + |3: // Call __newindex metamethod. + | // BASE = base, L->top = new base, stack = cont/func/t/k/(v) + | addiu TMP1, BASE, -FRAME_CONT + | lw BASE, L->top + | sw PC, -16+HI(BASE) // [cont|PC] + | subu PC, BASE, TMP1 + | lw LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. + | sdc1 f0, 16(BASE) // Copy value to third argument. + | b ->vm_call_dispatch_f + |. li NARGS8:RC, 24 // 3 args for func(t, k, v) + | + |//-- Comparison metamethods --------------------------------------------- + | + |->vmeta_comp: + | // CARG2, CARG3 are already set by BC_ISLT/BC_ISGE/BC_ISLE/BC_ISGT. + | load_got lj_meta_comp + | addiu PC, PC, -4 + | sw BASE, L->base + | sw PC, SAVE_PC + | decode_OP1 CARG4, INS + | call_intern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op) + |. move CARG1, L + | // Returns 0/1 or TValue * (metamethod). + |3: + | sltiu AT, CRET1, 2 + | beqz AT, ->vmeta_binop + | negu TMP2, CRET1 + |4: + | lhu RD, OFS_RD(PC) + | addiu PC, PC, 4 + | lui TMP1, (-(BCBIAS_J*4 >> 16) & 65535) + | sll RD, RD, 2 + | addu RD, RD, TMP1 + | and RD, RD, TMP2 + | addu PC, PC, RD + |->cont_nop: + | ins_next + | + |->cont_ra: // RA = resultptr + | lbu TMP1, -4+OFS_RA(PC) + | ldc1 f0, 0(RA) + | sll TMP1, TMP1, 3 + | addu TMP1, BASE, TMP1 + | b ->cont_nop + |. sdc1 f0, 0(TMP1) + | + |->cont_condt: // RA = resultptr + | lw TMP0, HI(RA) + | sltiu AT, TMP0, LJ_TISTRUECOND + | b <4 + |. negu TMP2, AT // Branch if result is true. + | + |->cont_condf: // RA = resultptr + | lw TMP0, HI(RA) + | sltiu AT, TMP0, LJ_TISTRUECOND + | b <4 + |. addiu TMP2, AT, -1 // Branch if result is false. + | + |->vmeta_equal: + | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV. + | load_got lj_meta_equal + | addiu PC, PC, -4 + | sw BASE, L->base + | sw PC, SAVE_PC + | call_intern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne) + |. move CARG1, L + | // Returns 0/1 or TValue * (metamethod). + | b <3 + |. nop + | + |->vmeta_equal_cd: +#if LJ_HASFFI + | load_got lj_meta_equal_cd + | move CARG2, INS + | addiu PC, PC, -4 + | sw BASE, L->base + | sw PC, SAVE_PC + | call_intern lj_meta_equal_cd // (lua_State *L, BCIns op) + |. move CARG1, L + | // Returns 0/1 or TValue * (metamethod). + | b <3 + |. nop +#endif + | + |//-- Arithmetic metamethods --------------------------------------------- + | + |->vmeta_unm: + | move CARG4, CARG3 + | + |->vmeta_arith: + | load_got lj_meta_arith + | decode_OP1 TMP0, INS + | sw BASE, L->base + | sw PC, SAVE_PC + | move CARG2, RA + | sw TMP0, ARG5 + | call_intern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op) + |. move CARG1, L + | // Returns NULL (finished) or TValue * (metamethod). + | beqz CRET1, ->cont_nop + |. nop + | + | // Call metamethod for binary op. + |->vmeta_binop: + | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2 + | subu TMP1, CRET1, BASE + | sw PC, -16+HI(CRET1) // [cont|PC] + | move TMP2, BASE + | addiu PC, TMP1, FRAME_CONT + | move BASE, CRET1 + | b ->vm_call_dispatch + |. li NARGS8:RC, 16 // 2 args for func(o1, o2). + | + |->vmeta_len: + | // CARG2 already set by BC_LEN. +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | move MULTRES, CARG1 +#endif + | load_got lj_meta_len + | sw BASE, L->base + | sw PC, SAVE_PC + | call_intern lj_meta_len // (lua_State *L, TValue *o) + |. move CARG1, L + | // Returns NULL (retry) or TValue * (metamethod base). +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | bnez CRET1, ->vmeta_binop // Binop call for compatibility. + |. nop + | b ->BC_LEN_Z + |. move CARG1, MULTRES +#else + | b ->vmeta_binop // Binop call for compatibility. + |. nop +#endif + | + |//-- Call metamethod ---------------------------------------------------- + | + |->vmeta_call: // Resolve and call __call metamethod. + | // TMP2 = old base, BASE = new base, RC = nargs*8 + | load_got lj_meta_call + | sw TMP2, L->base // This is the callers base! + | addiu CARG2, BASE, -8 + | sw PC, SAVE_PC + | addu CARG3, BASE, RC + | move MULTRES, NARGS8:RC + | call_intern lj_meta_call // (lua_State *L, TValue *func, TValue *top) + |. move CARG1, L + | lw LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. + | addiu NARGS8:RC, MULTRES, 8 // Got one more argument now. + | ins_call + | + |->vmeta_callt: // Resolve __call for BC_CALLT. + | // BASE = old base, RA = new base, RC = nargs*8 + | load_got lj_meta_call + | sw BASE, L->base + | addiu CARG2, RA, -8 + | sw PC, SAVE_PC + | addu CARG3, RA, RC + | move MULTRES, NARGS8:RC + | call_intern lj_meta_call // (lua_State *L, TValue *func, TValue *top) + |. move CARG1, L + | lw TMP1, FRAME_PC(BASE) + | lw LFUNC:RB, FRAME_FUNC(RA) // Guaranteed to be a function here. + | b ->BC_CALLT_Z + |. addiu NARGS8:RC, MULTRES, 8 // Got one more argument now. + | + |//-- Argument coercion for 'for' statement ------------------------------ + | + |->vmeta_for: + | load_got lj_meta_for + | sw BASE, L->base + | move CARG2, RA + | sw PC, SAVE_PC + | move MULTRES, INS + | call_intern lj_meta_for // (lua_State *L, TValue *base) + |. move CARG1, L +#if LJ_HASJIT + | decode_OP1 TMP0, MULTRES + | li AT, BC_JFORI +#endif + | decode_RA8a RA, MULTRES + | decode_RD8a RD, MULTRES + | decode_RA8b RA +#if LJ_HASJIT + | beq TMP0, AT, =>BC_JFORI + |. decode_RD8b RD + | b =>BC_FORI + |. nop +#else + | b =>BC_FORI + |. decode_RD8b RD +#endif + | + |//----------------------------------------------------------------------- + |//-- Fast functions ----------------------------------------------------- + |//----------------------------------------------------------------------- + | + |.macro .ffunc, name + |->ff_ .. name: + |.endmacro + | + |.macro .ffunc_1, name + |->ff_ .. name: + | beqz NARGS8:RC, ->fff_fallback + |. lw CARG3, HI(BASE) + | lw CARG1, LO(BASE) + |.endmacro + | + |.macro .ffunc_2, name + |->ff_ .. name: + | sltiu AT, NARGS8:RC, 16 + | lw CARG3, HI(BASE) + | bnez AT, ->fff_fallback + |. lw CARG4, 8+HI(BASE) + | lw CARG1, LO(BASE) + | lw CARG2, 8+LO(BASE) + |.endmacro + | + |.macro .ffunc_n, name // Caveat: has delay slot! + |->ff_ .. name: + | lw CARG3, HI(BASE) + | beqz NARGS8:RC, ->fff_fallback + |. ldc1 FARG1, 0(BASE) + | sltiu AT, CARG3, LJ_TISNUM + | beqz AT, ->fff_fallback + |.endmacro + | + |.macro .ffunc_nn, name // Caveat: has delay slot! + |->ff_ .. name: + | sltiu AT, NARGS8:RC, 16 + | lw CARG3, HI(BASE) + | bnez AT, ->fff_fallback + |. lw CARG4, 8+HI(BASE) + | ldc1 FARG1, 0(BASE) + | ldc1 FARG2, 8(BASE) + | sltiu TMP0, CARG3, LJ_TISNUM + | sltiu TMP1, CARG4, LJ_TISNUM + | and TMP0, TMP0, TMP1 + | beqz TMP0, ->fff_fallback + |.endmacro + | + |// Inlined GC threshold check. Caveat: uses TMP0 and TMP1 and has delay slot! + |.macro ffgccheck + | lw TMP0, DISPATCH_GL(gc.total)(DISPATCH) + | lw TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) + | subu AT, TMP0, TMP1 + | bgezal AT, ->fff_gcstep + |.endmacro + | + |//-- Base library: checks ----------------------------------------------- + | + |.ffunc_1 assert + | sltiu AT, CARG3, LJ_TISTRUECOND + | beqz AT, ->fff_fallback + |. addiu RA, BASE, -8 + | lw PC, FRAME_PC(BASE) + | addiu RD, NARGS8:RC, 8 // Compute (nresults+1)*8. + | addu TMP2, RA, NARGS8:RC + | sw CARG3, HI(RA) + | addiu TMP1, BASE, 8 + | beq BASE, TMP2, ->fff_res // Done if exactly 1 argument. + |. sw CARG1, LO(RA) + |1: + | ldc1 f0, 0(TMP1) + | sdc1 f0, -8(TMP1) + | bne TMP1, TMP2, <1 + |. addiu TMP1, TMP1, 8 + | b ->fff_res + |. nop + | + |.ffunc type + | lw CARG3, HI(BASE) + | li TMP1, LJ_TISNUM + | beqz NARGS8:RC, ->fff_fallback + |. sltiu TMP0, CARG3, LJ_TISNUM + | movz TMP1, CARG3, TMP0 + | not TMP1, TMP1 + | sll TMP1, TMP1, 3 + | addu TMP1, CFUNC:RB, TMP1 + | b ->fff_resn + |. ldc1 FRET1, CFUNC:TMP1->upvalue + | + |//-- Base library: getters and setters --------------------------------- + | + |.ffunc_1 getmetatable + | li AT, LJ_TTAB + | bne CARG3, AT, >6 + |. li AT, LJ_TUDATA + |1: // Field metatable must be at same offset for GCtab and GCudata! + | lw TAB:CARG1, TAB:CARG1->metatable + |2: + | lw STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH) + | beqz TAB:CARG1, ->fff_restv + |. li CARG3, LJ_TNIL + | lw TMP0, TAB:CARG1->hmask + | li CARG3, LJ_TTAB // Use metatable as default result. + | lw TMP1, STR:RC->hash + | lw NODE:TMP2, TAB:CARG1->node + | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask + | sll TMP0, TMP1, 5 + | sll TMP1, TMP1, 3 + | subu TMP1, TMP0, TMP1 + | addu NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) + | li AT, LJ_TSTR + |3: // Rearranged logic, because we expect _not_ to find the key. + | lw CARG4, offsetof(Node, key)+HI(NODE:TMP2) + | lw TMP0, offsetof(Node, key)+LO(NODE:TMP2) + | lw NODE:TMP3, NODE:TMP2->next + | bne CARG4, AT, >4 + |. lw CARG2, offsetof(Node, val)+HI(NODE:TMP2) + | beq TMP0, STR:RC, >5 + |. lw TMP1, offsetof(Node, val)+LO(NODE:TMP2) + |4: + | beqz NODE:TMP3, ->fff_restv // Not found, keep default result. + |. move NODE:TMP2, NODE:TMP3 + | b <3 + |. nop + |5: + | beq CARG2, TISNIL, ->fff_restv // Ditto for nil value. + |. nop + | move CARG3, CARG2 // Return value of mt.__metatable. + | b ->fff_restv + |. move CARG1, TMP1 + | + |6: + | beq CARG3, AT, <1 + |. sltiu TMP0, CARG3, LJ_TISNUM + | li TMP1, LJ_TISNUM + | movz TMP1, CARG3, TMP0 + | not TMP1, TMP1 + | sll TMP1, TMP1, 2 + | addu TMP1, DISPATCH, TMP1 + | b <2 + |. lw TAB:CARG1, DISPATCH_GL(gcroot[GCROOT_BASEMT])(TMP1) + | + |.ffunc_2 setmetatable + | // Fast path: no mt for table yet and not clearing the mt. + | li AT, LJ_TTAB + | bne CARG3, AT, ->fff_fallback + |. addiu CARG4, CARG4, -LJ_TTAB + | lw TAB:TMP1, TAB:CARG1->metatable + | lbu TMP3, TAB:CARG1->marked + | or AT, CARG4, TAB:TMP1 + | bnez AT, ->fff_fallback + |. andi AT, TMP3, LJ_GC_BLACK // isblack(table) + | beqz AT, ->fff_restv + |. sw TAB:CARG2, TAB:CARG1->metatable + | barrierback TAB:CARG1, TMP3, TMP0, ->fff_restv + | + |.ffunc rawget + | lw CARG4, HI(BASE) + | sltiu AT, NARGS8:RC, 16 + | lw TAB:CARG2, LO(BASE) + | load_got lj_tab_get + | addiu CARG4, CARG4, -LJ_TTAB + | or AT, AT, CARG4 + | bnez AT, ->fff_fallback + | addiu CARG3, BASE, 8 + | call_intern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key) + |. move CARG1, L + | // Returns cTValue *. + | b ->fff_resn + |. ldc1 FRET1, 0(CRET1) + | + |//-- Base library: conversions ------------------------------------------ + | + |.ffunc tonumber + | // Only handles the number case inline (without a base argument). + | lw CARG1, HI(BASE) + | xori AT, NARGS8:RC, 8 + | sltiu CARG1, CARG1, LJ_TISNUM + | movn CARG1, r0, AT + | beqz CARG1, ->fff_fallback // Exactly one number argument. + |. ldc1 FRET1, 0(BASE) + | b ->fff_resn + |. nop + | + |.ffunc_1 tostring + | // Only handles the string or number case inline. + | li AT, LJ_TSTR + | // A __tostring method in the string base metatable is ignored. + | beq CARG3, AT, ->fff_restv // String key? + | // Handle numbers inline, unless a number base metatable is present. + |. lw TMP1, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])(DISPATCH) + | sltiu TMP0, CARG3, LJ_TISNUM + | sltiu TMP1, TMP1, 1 + | and TMP0, TMP0, TMP1 + | beqz TMP0, ->fff_fallback + |. sw BASE, L->base // Add frame since C call can throw. + | ffgccheck + |. sw PC, SAVE_PC // Redundant (but a defined value). + | load_got lj_str_fromnum + | move CARG1, L + | call_intern lj_str_fromnum // (lua_State *L, lua_Number *np) + |. move CARG2, BASE + | // Returns GCstr *. + | li CARG3, LJ_TSTR + | b ->fff_restv + |. move CARG1, CRET1 + | + |//-- Base library: iterators ------------------------------------------- + | + |.ffunc next + | lw CARG1, HI(BASE) + | lw TAB:CARG2, 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 + |. 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. + | beqz CRET1, ->fff_restv // End of traversal: return nil. + |. li CARG3, LJ_TNIL + | ldc1 f0, 8(BASE) // Copy key and value to results. + | addiu RA, BASE, -8 + | ldc1 f2, 16(BASE) + | li RD, (2+1)*8 + | sdc1 f0, 0(RA) + | b ->fff_res + |. sdc1 f2, 8(RA) + | + |.ffunc_1 pairs + | li AT, LJ_TTAB + | bne CARG3, AT, ->fff_fallback + |. lw PC, FRAME_PC(BASE) +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | lw TAB:TMP2, TAB:CARG1->metatable + | ldc1 f0, CFUNC:RB->upvalue[0] + | bnez TAB:TMP2, ->fff_fallback +#else + | ldc1 f0, CFUNC:RB->upvalue[0] +#endif + |. addiu RA, BASE, -8 + | sw TISNIL, 8+HI(BASE) + | li RD, (3+1)*8 + | b ->fff_res + |. sdc1 f0, 0(RA) + | + |.ffunc ipairs_aux + | sltiu AT, NARGS8:RC, 16 + | lw CARG3, HI(BASE) + | lw TAB:CARG1, LO(BASE) + | lw CARG4, 8+HI(BASE) + | bnez AT, ->fff_fallback + |. ldc1 FARG2, 8(BASE) + | addiu CARG3, CARG3, -LJ_TTAB + | sltiu AT, CARG4, LJ_TISNUM + | li TMP0, 1 + | movn AT, r0, CARG3 + | mtc1 TMP0, FARG1 + | beqz AT, ->fff_fallback + |. lw PC, FRAME_PC(BASE) + | cvt.w.d FRET1, FARG2 + | cvt.d.w FARG1, FARG1 + | lw TMP0, TAB:CARG1->asize + | lw TMP1, TAB:CARG1->array + | mfc1 TMP2, FRET1 + | addiu RA, BASE, -8 + | add.d FARG2, FARG2, FARG1 + | addiu TMP2, TMP2, 1 + | sltu AT, TMP2, TMP0 + | sll TMP3, TMP2, 3 + | addu TMP3, TMP1, TMP3 + | beqz AT, >2 // Not in array part? + |. sdc1 FARG2, 0(RA) + | lw TMP2, HI(TMP3) + | ldc1 f0, 0(TMP3) + |1: + | beq TMP2, TISNIL, ->fff_res // End of iteration, return 0 results. + |. li RD, (0+1)*8 + | li RD, (2+1)*8 + | b ->fff_res + |. sdc1 f0, 8(RA) + |2: // Check for empty hash part first. Otherwise call C function. + | lw TMP0, TAB:CARG1->hmask + | load_got lj_tab_getinth + | beqz TMP0, ->fff_res + |. li RD, (0+1)*8 + | call_intern lj_tab_getinth // (GCtab *t, int32_t key) + |. move CARG2, TMP2 + | // Returns cTValue * or NULL. + | beqz CRET1, ->fff_res + |. li RD, (0+1)*8 + | lw TMP2, HI(CRET1) + | b <1 + |. ldc1 f0, 0(CRET1) + | + |.ffunc_1 ipairs + | li AT, LJ_TTAB + | bne CARG3, AT, ->fff_fallback + |. lw PC, FRAME_PC(BASE) +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | lw TAB:TMP2, TAB:CARG1->metatable + | ldc1 f0, CFUNC:RB->upvalue[0] + | bnez TAB:TMP2, ->fff_fallback +#else + | ldc1 f0, CFUNC:RB->upvalue[0] +#endif + |. addiu RA, BASE, -8 + | sw r0, 8+HI(BASE) + | sw r0, 8+LO(BASE) + | li RD, (3+1)*8 + | b ->fff_res + |. sdc1 f0, 0(RA) + | + |//-- Base library: catch errors ---------------------------------------- + | + |.ffunc pcall + | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | beqz NARGS8:RC, ->fff_fallback + | move TMP2, BASE + | addiu BASE, BASE, 8 + | // Remember active hook before pcall. + | srl TMP3, TMP3, HOOK_ACTIVE_SHIFT + | andi TMP3, TMP3, 1 + | addiu PC, TMP3, 8+FRAME_PCALL + | b ->vm_call_dispatch + |. addiu NARGS8:RC, NARGS8:RC, -8 + | + |.ffunc xpcall + | sltiu AT, NARGS8:RC, 16 + | lw CARG4, 8+HI(BASE) + | bnez AT, ->fff_fallback + |. ldc1 FARG2, 8(BASE) + | ldc1 FARG1, 0(BASE) + | lbu TMP1, DISPATCH_GL(hookmask)(DISPATCH) + | li AT, LJ_TFUNC + | move TMP2, BASE + | bne CARG4, AT, ->fff_fallback // Traceback must be a function. + | addiu BASE, BASE, 16 + | // Remember active hook before pcall. + | srl TMP3, TMP3, HOOK_ACTIVE_SHIFT + | sdc1 FARG2, 0(TMP2) // Swap function and traceback. + | andi TMP3, TMP3, 1 + | sdc1 FARG1, 8(TMP2) + | addiu PC, TMP3, 16+FRAME_PCALL + | b ->vm_call_dispatch + |. addiu NARGS8:RC, NARGS8:RC, -16 + | + |//-- Coroutine library -------------------------------------------------- + | + |.macro coroutine_resume_wrap, resume + |.if resume + |.ffunc_1 coroutine_resume + | li AT, LJ_TTHREAD + | bne CARG3, AT, ->fff_fallback + |.else + |.ffunc coroutine_wrap_aux + | lw L:CARG1, CFUNC:RB->upvalue[0].gcr + |.endif + | lbu TMP0, L:CARG1->status + | lw TMP1, L:CARG1->cframe + | lw CARG2, L:CARG1->top + | lw TMP2, L:CARG1->base + | addiu TMP3, TMP0, -LUA_YIELD + | bgtz TMP3, ->fff_fallback // st > LUA_YIELD? + |. xor TMP2, TMP2, CARG2 + | bnez TMP1, ->fff_fallback // cframe != 0? + |. or AT, TMP2, TMP0 + | lw TMP0, L:CARG1->maxstack + | beqz AT, ->fff_fallback // base == top && st == 0? + |. lw PC, FRAME_PC(BASE) + | addu TMP2, CARG2, NARGS8:RC + | sltu AT, TMP0, TMP2 + | bnez AT, ->fff_fallback // Stack overflow? + |. sw PC, SAVE_PC + | sw BASE, L->base + |1: + |.if resume + | addiu BASE, BASE, 8 // Keep resumed thread in stack for GC. + | addiu NARGS8:RC, NARGS8:RC, -8 + | addiu TMP2, TMP2, -8 + |.endif + | sw TMP2, L:CARG1->top + | addu TMP1, BASE, NARGS8:RC + | move CARG3, CARG2 + | sw BASE, L->top + |2: // Move args to coroutine. + | ldc1 f0, 0(BASE) + | sltu AT, BASE, TMP1 + | beqz AT, >3 + |. addiu BASE, BASE, 8 + | sdc1 f0, 0(CARG3) + | b <2 + |. addiu CARG3, CARG3, 8 + |3: + | bal ->vm_resume // (lua_State *L, TValue *base, 0, 0) + |. move L:RA, L:CARG1 + | // Returns thread status. + |4: + | lw TMP2, L:RA->base + | sltiu AT, CRET1, LUA_YIELD+1 + | lw TMP3, L:RA->top + | li_vmstate INTERP + | lw BASE, L->base + | st_vmstate + | beqz AT, >8 + |. subu RD, TMP3, TMP2 + | lw TMP0, L->maxstack + | beqz RD, >6 // No results? + |. addu TMP1, BASE, RD + | sltu AT, TMP0, TMP1 + | bnez AT, >9 // Need to grow stack? + |. addu TMP3, TMP2, RD + | sw TMP2, L:RA->top // Clear coroutine stack. + | move TMP1, BASE + |5: // Move results from coroutine. + | ldc1 f0, 0(TMP2) + | addiu TMP2, TMP2, 8 + | sltu AT, TMP2, TMP3 + | sdc1 f0, 0(TMP1) + | bnez AT, <5 + |. addiu TMP1, TMP1, 8 + |6: + | andi TMP0, PC, FRAME_TYPE + |.if resume + | li TMP1, LJ_TTRUE + | addiu RA, BASE, -8 + | sw TMP1, -8+HI(BASE) // Prepend true to results. + | addiu RD, RD, 16 + |.else + | move RA, BASE + | addiu RD, RD, 8 + |.endif + |7: + | sw PC, SAVE_PC + | beqz TMP0, ->BC_RET_Z + |. move MULTRES, RD + | b ->vm_return + |. nop + | + |8: // Coroutine returned with error (at co->top-1). + |.if resume + | addiu TMP3, TMP3, -8 + | li TMP1, LJ_TFALSE + | ldc1 f0, 0(TMP3) + | sw TMP3, L:RA->top // Remove error from coroutine stack. + | li RD, (2+1)*8 + | sw TMP1, -8+HI(BASE) // Prepend false to results. + | addiu RA, BASE, -8 + | sdc1 f0, 0(BASE) // Copy error message. + | b <7 + |. andi TMP0, PC, FRAME_TYPE + |.else + | load_got lj_ffh_coroutine_wrap_err + | move CARG2, L:RA + | call_intern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co) + |. move CARG1, L + |.endif + | + |9: // Handle stack expansion on return from yield. + | load_got lj_state_growstack + | srl CARG2, RD, 3 + | call_intern lj_state_growstack // (lua_State *L, int n) + |. move CARG1, L + | b <4 + |. li CRET1, 0 + |.endmacro + | + | coroutine_resume_wrap 1 // coroutine.resume + | coroutine_resume_wrap 0 // coroutine.wrap + | + |.ffunc coroutine_yield + | lw TMP0, L->cframe + | addu TMP1, BASE, NARGS8:RC + | sw BASE, L->base + | andi TMP0, TMP0, CFRAME_RESUME + | sw TMP1, L->top + | beqz TMP0, ->fff_fallback + |. li CRET1, LUA_YIELD + | sw r0, L->cframe + | b ->vm_leave_unw + |. sb CRET1, L->status + | + |//-- Math library ------------------------------------------------------- + | + |.ffunc_n math_abs + |. abs.d FRET1, FARG1 + |->fff_resn: + | lw PC, FRAME_PC(BASE) + | addiu RA, BASE, -8 + | b ->fff_res1 + |. sdc1 FRET1, -8(BASE) + | + |->fff_restv: + | // CARG3/CARG1 = TValue result. + | lw PC, FRAME_PC(BASE) + | sw CARG3, -8+HI(BASE) + | addiu RA, BASE, -8 + | sw CARG1, -8+LO(BASE) + |->fff_res1: + | // RA = results, PC = return. + | li RD, (1+1)*8 + |->fff_res: + | // RA = results, RD = (nresults+1)*8, PC = return. + | andi TMP0, PC, FRAME_TYPE + | bnez TMP0, ->vm_return + |. move MULTRES, RD + | lw INS, -4(PC) + | decode_RB8a RB, INS + | decode_RB8b RB + |5: + | sltu AT, RD, RB + | bnez AT, >6 // More results expected? + |. decode_RA8a TMP0, INS + | decode_RA8b TMP0 + | ins_next1 + | // Adjust BASE. KBASE is assumed to be set for the calling frame. + | subu BASE, RA, TMP0 + | ins_next2 + | + |6: // Fill up results with nil. + | addu TMP1, RA, RD + | addiu RD, RD, 8 + | b <5 + |. sw TISNIL, -8+HI(TMP1) + | + |.macro math_extern, func + |->ff_math_ .. func: + | lw CARG3, HI(BASE) + | beqz NARGS8:RC, ->fff_fallback + |. load_got func + | sltiu AT, CARG3, LJ_TISNUM + | beqz AT, ->fff_fallback + |. nop + | call_extern + |. ldc1 FARG1, 0(BASE) + | b ->fff_resn + |. nop + |.endmacro + | + |.macro math_extern2, func + | .ffunc_nn math_ .. func + |. load_got func + | call_extern + |. nop + | b ->fff_resn + |. nop + |.endmacro + | + |.macro math_round, func + | .ffunc_n math_ .. func + |. nop + | bal ->vm_ .. func + |. nop + | b ->fff_resn + |. nop + |.endmacro + | + | math_round floor + | math_round ceil + | + | math_extern log + | math_extern log10 + | math_extern exp + | math_extern sin + | math_extern cos + | math_extern tan + | math_extern asin + | math_extern acos + | math_extern atan + | math_extern sinh + | math_extern cosh + | math_extern tanh + | math_extern2 pow + | math_extern2 atan2 + | math_extern2 fmod + | + |.ffunc_n math_sqrt + |. sqrt.d FRET1, FARG1 + | b ->fff_resn + |. nop + | + |->ff_math_deg: + |.ffunc_n math_rad + |. ldc1 FARG2, CFUNC:RB->upvalue[0] + | b ->fff_resn + |. mul.d FRET1, FARG1, FARG2 + | + |.ffunc_nn math_ldexp + | cvt.w.d FARG2, FARG2 + | load_got ldexp + | mfc1 CARG3, FARG2 + | call_extern + |. nop + | b ->fff_resn + |. nop + | + |.ffunc_n math_frexp + | load_got frexp + | lw PC, FRAME_PC(BASE) + | call_extern + |. addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) + | lw TMP1, DISPATCH_GL(tmptv)(DISPATCH) + | addiu RA, BASE, -8 + | mtc1 TMP1, FARG2 + | sdc1 FRET1, 0(RA) + | cvt.d.w FARG2, FARG2 + | sdc1 FARG2, 8(RA) + | b ->fff_res + |. li RD, (2+1)*8 + | + |.ffunc_n math_modf + | load_got modf + | lw PC, FRAME_PC(BASE) + | call_extern + |. addiu CARG3, BASE, -8 + | addiu RA, BASE, -8 + | sdc1 FRET1, 0(BASE) + | b ->fff_res + |. li RD, (2+1)*8 + | + |.macro math_minmax, name, ismax + |->ff_ .. name: + | lw CARG3, HI(BASE) + | beqz NARGS8:RC, ->fff_fallback + |. ldc1 FRET1, 0(BASE) + | sltiu AT, CARG3, LJ_TISNUM + | beqz AT, ->fff_fallback + |. addu TMP2, BASE, NARGS8:RC + | addiu TMP1, BASE, 8 + | beq TMP1, TMP2, ->fff_resn + |1: + |. lw CARG3, HI(TMP1) + | ldc1 FARG1, 0(TMP1) + | addiu TMP1, TMP1, 8 + | sltiu AT, CARG3, LJ_TISNUM + | beqz AT, ->fff_fallback + |.if ismax + |. c.olt.d FARG1, FRET1 + |.else + |. c.olt.d FRET1, FARG1 + |.endif + | bne TMP1, TMP2, <1 + |. movf.d FRET1, FARG1 + | b ->fff_resn + |. nop + |.endmacro + | + | math_minmax math_min, 0 + | math_minmax math_max, 1 + | + |//-- String library ----------------------------------------------------- + | + |.ffunc_1 string_len + | li AT, LJ_TSTR + | bne CARG3, AT, ->fff_fallback + |. nop + | b ->fff_resi + |. lw CRET1, STR:CARG1->len + | + |.ffunc string_byte // Only handle the 1-arg case here. + | lw CARG3, HI(BASE) + | lw STR:CARG1, LO(BASE) + | xori AT, NARGS8:RC, 8 + | addiu CARG3, CARG3, -LJ_TSTR + | or AT, AT, CARG3 + | bnez AT, ->fff_fallback // Need exactly 1 string argument. + |. nop + | lw TMP0, STR:CARG1->len + | lbu TMP1, STR:CARG1[1] // Access is always ok (NUL at end). + | addiu RA, BASE, -8 + | sltu RD, r0, TMP0 + | mtc1 TMP1, f0 + | addiu RD, RD, 1 + | cvt.d.w f0, f0 + | lw PC, FRAME_PC(BASE) + | sll RD, RD, 3 // RD = ((str->len != 0)+1)*8 + | b ->fff_res + |. sdc1 f0, 0(RA) + | + |.ffunc string_char // Only handle the 1-arg case here. + | ffgccheck + | lw CARG3, HI(BASE) + | ldc1 FARG1, 0(BASE) + | li AT, 8 + | bne NARGS8:RC, AT, ->fff_fallback // Exactly 1 argument. + |. sltiu AT, CARG3, LJ_TISNUM + | beqz AT, ->fff_fallback + |. li CARG3, 1 + | cvt.w.d FARG1, FARG1 + | addiu CARG2, sp, ARG5_OFS + | sltiu AT, TMP0, 256 + | mfc1 TMP0, FARG1 + | beqz AT, ->fff_fallback + |. sw TMP0, ARG5 + |->fff_newstr: + | load_got lj_str_new + | sw BASE, L->base + | sw PC, SAVE_PC + | call_intern lj_str_new // (lua_State *L, char *str, size_t l) + |. move CARG1, L + | // Returns GCstr *. + | lw BASE, L->base + | move CARG1, CRET1 + | b ->fff_restv + |. li CARG3, LJ_TSTR + | + |.ffunc string_sub + | ffgccheck + | addiu AT, NARGS8:RC, -16 + | lw CARG3, 16+HI(BASE) + | ldc1 f0, 16(BASE) + | lw TMP0, HI(BASE) + | lw STR:CARG1, LO(BASE) + | bltz AT, ->fff_fallback + | lw CARG2, 8+HI(BASE) + | ldc1 f2, 8(BASE) + | beqz AT, >1 + |. li CARG4, -1 + | cvt.w.d f0, f0 + | sltiu AT, CARG3, LJ_TISNUM + | beqz AT, ->fff_fallback + |. mfc1 CARG4, f0 + |1: + | sltiu AT, CARG2, LJ_TISNUM + | beqz AT, ->fff_fallback + |. li AT, LJ_TSTR + | cvt.w.d f2, f2 + | bne TMP0, AT, ->fff_fallback + |. lw CARG2, STR:CARG1->len + | mfc1 CARG3, f2 + | // STR:CARG1 = str, CARG2 = str->len, CARG3 = start, CARG4 = end + | slt AT, CARG4, r0 + | addiu TMP0, CARG2, 1 + | addu TMP1, CARG4, TMP0 + | slt TMP3, CARG3, r0 + | movn CARG4, TMP1, AT // if (end < 0) end += len+1 + | addu TMP1, CARG3, TMP0 + | movn CARG3, TMP1, TMP3 // if (start < 0) start += len+1 + | li TMP2, 1 + | slt AT, CARG4, r0 + | slt TMP3, r0, CARG3 + | movn CARG4, r0, AT // if (end < 0) end = 0 + | movz CARG3, TMP2, TMP3 // if (start < 1) start = 1 + | slt AT, CARG2, CARG4 + | movn CARG4, CARG2, AT // if (end > len) end = len + | addu CARG2, STR:CARG1, CARG3 + | subu CARG3, CARG4, CARG3 // len = end - start + | addiu CARG2, CARG2, sizeof(GCstr)-1 + | bgez CARG3, ->fff_newstr + |. addiu CARG3, CARG3, 1 // len++ + |->fff_emptystr: // Return empty string. + | addiu STR:CARG1, DISPATCH, DISPATCH_GL(strempty) + | b ->fff_restv + |. li CARG3, LJ_TSTR + | + |.ffunc string_rep // Only handle the 1-char case inline. + | ffgccheck + | lw TMP0, HI(BASE) + | sltiu AT, NARGS8:RC, 16 + | lw CARG4, 8+HI(BASE) + | lw STR:CARG1, LO(BASE) + | addiu TMP0, TMP0, -LJ_TSTR + | ldc1 f0, 8(BASE) + | or AT, AT, TMP0 + | bnez AT, ->fff_fallback + |. sltiu AT, CARG4, LJ_TISNUM + | cvt.w.d f0, f0 + | beqz AT, ->fff_fallback + |. lw TMP0, STR:CARG1->len + | mfc1 CARG3, f0 + | lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) + | li AT, 1 + | blez CARG3, ->fff_emptystr // Count <= 0? + |. sltu AT, AT, TMP0 + | beqz TMP0, ->fff_emptystr // Zero length string? + |. sltu TMP0, TMP1, CARG3 + | or AT, AT, TMP0 + | lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) + | bnez AT, ->fff_fallback // Fallback for > 1-char strings. + |. lbu TMP0, STR:CARG1[1] + | addu TMP2, CARG2, CARG3 + |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). + | addiu TMP2, TMP2, -1 + | sltu AT, CARG2, TMP2 + | bnez AT, <1 + |. sb TMP0, 0(TMP2) + | b ->fff_newstr + |. nop + | + |.ffunc string_reverse + | ffgccheck + | lw CARG3, HI(BASE) + | lw STR:CARG1, LO(BASE) + | beqz NARGS8:RC, ->fff_fallback + |. li AT, LJ_TSTR + | bne CARG3, AT, ->fff_fallback + |. lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) + | lw CARG3, STR:CARG1->len + | addiu CARG1, STR:CARG1, #STR + | lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) + | sltu AT, TMP1, CARG3 + | bnez AT, ->fff_fallback + |. addu TMP3, CARG1, CARG3 + | addu CARG4, CARG2, CARG3 + |1: // Reverse string copy. + | lbu TMP1, 0(CARG1) + | sltu AT, CARG1, TMP3 + | beqz AT, ->fff_newstr + |. addiu CARG1, CARG1, 1 + | addiu CARG4, CARG4, -1 + | b <1 + | sb TMP1, 0(CARG4) + | + |.macro ffstring_case, name, lo + | .ffunc name + | ffgccheck + | lw CARG3, HI(BASE) + | lw STR:CARG1, LO(BASE) + | beqz NARGS8:RC, ->fff_fallback + |. li AT, LJ_TSTR + | bne CARG3, AT, ->fff_fallback + |. lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) + | lw CARG3, STR:CARG1->len + | addiu CARG1, STR:CARG1, #STR + | lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) + | sltu AT, TMP1, CARG3 + | bnez AT, ->fff_fallback + |. addu TMP3, CARG1, CARG3 + | move CARG4, CARG2 + |1: // ASCII case conversion. + | lbu TMP1, 0(CARG1) + | sltu AT, CARG1, TMP3 + | beqz AT, ->fff_newstr + |. addiu TMP0, TMP1, -lo + | xori TMP2, TMP1, 0x20 + | sltiu AT, TMP0, 26 + | movn TMP1, TMP2, AT + | addiu CARG1, CARG1, 1 + | sb TMP1, 0(CARG4) + | b <1 + |. addiu CARG4, CARG4, 1 + |.endmacro + | + |ffstring_case string_lower, 65 + |ffstring_case string_upper, 97 + | + |//-- Table library ------------------------------------------------------ + | + |.ffunc_1 table_getn + | li AT, LJ_TTAB + | bne CARG3, AT, ->fff_fallback + |. load_got lj_tab_len + | call_intern lj_tab_len // (GCtab *t) + |. nop + | // Returns uint32_t (but less than 2^31). + | b ->fff_resi + |. nop + | + |//-- Bit library -------------------------------------------------------- + | + |.macro .ffunc_bit, name + | .ffunc_n bit_..name + |. add.d FARG1, FARG1, TOBIT + | mfc1 CRET1, FARG1 + |.endmacro + | + |.macro .ffunc_bit_op, name, ins + | .ffunc_bit name + | addiu TMP1, BASE, 8 + | addu TMP2, BASE, NARGS8:RC + |1: + | lw CARG4, HI(TMP1) + | beq TMP1, TMP2, ->fff_resi + |. ldc1 FARG1, 0(TMP1) + | sltiu AT, CARG4, LJ_TISNUM + | beqz AT, ->fff_fallback + | add.d FARG1, FARG1, TOBIT + | mfc1 CARG2, FARG1 + | ins CRET1, CRET1, CARG2 + | b <1 + |. addiu TMP1, TMP1, 8 + |.endmacro + | + |.ffunc_bit_op band, and + |.ffunc_bit_op bor, or + |.ffunc_bit_op bxor, xor + | + |.ffunc_bit bswap + | srl TMP0, CRET1, 24 + | srl TMP2, CRET1, 8 + | sll TMP1, CRET1, 24 + | andi TMP2, TMP2, 0xff00 + | or TMP0, TMP0, TMP1 + | andi CRET1, CRET1, 0xff00 + | or TMP0, TMP0, TMP2 + | sll CRET1, CRET1, 8 + | b ->fff_resi + |. or CRET1, TMP0, CRET1 + | + |.ffunc_bit bnot + | b ->fff_resi + |. not CRET1, CRET1 + | + |.macro .ffunc_bit_sh, name, ins, shmod + | .ffunc_nn bit_..name + |. add.d FARG1, FARG1, TOBIT + | add.d FARG2, FARG2, TOBIT + | mfc1 CARG1, FARG1 + | mfc1 CARG2, FARG2 + |.if shmod == 1 + | li AT, 32 + | subu TMP0, AT, CARG2 + | sllv CARG2, CARG1, CARG2 + | srlv CARG1, CARG1, TMP0 + |.elif shmod == 2 + | li AT, 32 + | subu TMP0, AT, CARG2 + | srlv CARG2, CARG1, CARG2 + | sllv CARG1, CARG1, TMP0 + |.endif + | b ->fff_resi + |. ins CRET1, CARG1, CARG2 + |.endmacro + | + |.ffunc_bit_sh lshift, sllv, 0 + |.ffunc_bit_sh rshift, srlv, 0 + |.ffunc_bit_sh arshift, srav, 0 + |// Can't use rotrv, since it's only in MIPS32R2. + |.ffunc_bit_sh rol, or, 1 + |.ffunc_bit_sh ror, or, 2 + | + |.ffunc_bit tobit + |->fff_resi: + | mtc1 CRET1, FRET1 + | b ->fff_resn + |. cvt.d.w FRET1, FRET1 + | + |//----------------------------------------------------------------------- + | + |->fff_fallback: // Call fast function fallback handler. + | // BASE = new base, RB = CFUNC, RC = nargs*8 + | lw TMP3, CFUNC:RB->f + | addu TMP1, BASE, NARGS8:RC + | lw PC, FRAME_PC(BASE) // Fallback may overwrite PC. + | addiu TMP0, TMP1, 8*LUA_MINSTACK + | lw TMP2, L->maxstack + | sw PC, SAVE_PC // Redundant (but a defined value). + | sltu AT, TMP2, TMP0 + | sw BASE, L->base + | sw TMP1, L->top + | bnez AT, >5 // Need to grow stack. + |. move CFUNCADDR, TMP3 + | jalr TMP3 // (lua_State *L) + |. move CARG1, L + | // Either throws an error, or recovers and returns -1, 0 or nresults+1. + | lw BASE, L->base + | sll RD, CRET1, 3 + | bgtz CRET1, ->fff_res // Returned nresults+1? + |. addiu RA, BASE, -8 + |1: // Returned 0 or -1: retry fast path. + | lw TMP0, L->top + | lw LFUNC:RB, FRAME_FUNC(BASE) + | bnez CRET1, ->vm_call_tail // Returned -1? + |. subu NARGS8:RC, TMP0, BASE + | ins_callt // Returned 0: retry fast path. + | + |// Reconstruct previous base for vmeta_call during tailcall. + |->vm_call_tail: + | andi TMP0, PC, FRAME_TYPE + | li AT, -4 + | bnez TMP0, >3 + |. and TMP1, PC, AT + | lbu TMP1, OFS_RA(PC) + | sll TMP1, TMP1, 3 + | addiu TMP1, TMP1, 8 + |3: + | b ->vm_call_dispatch // Resolve again for tailcall. + |. subu TMP2, BASE, TMP1 + | + |5: // Grow stack for fallback handler. + | load_got lj_state_growstack + | li CARG2, LUA_MINSTACK + | call_intern lj_state_growstack // (lua_State *L, int n) + |. move CARG1, L + | lw BASE, L->base + | b <1 + |. li CRET1, 0 // Force retry. + | + |->fff_gcstep: // Call GC step function. + | // BASE = new base, RC = nargs*8 + | move MULTRES, ra + | load_got lj_gc_step + | sw BASE, L->base + | addu TMP0, BASE, NARGS8:RC + | sw PC, SAVE_PC // Redundant (but a defined value). + | sw TMP0, L->top + | call_intern lj_gc_step // (lua_State *L) + |. move CARG1, L + | lw BASE, L->base + | move ra, MULTRES + | lw TMP0, L->top + | lw CFUNC:RB, FRAME_FUNC(BASE) + | jr ra + |. subu NARGS8:RC, TMP0, BASE + | + |//----------------------------------------------------------------------- + |//-- Special dispatch targets ------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_record: // Dispatch target for recording phase. +#if LJ_HASJIT + | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | andi AT, TMP3, HOOK_VMEVENT // No recording while in vmevent. + | bnez AT, >5 + | // Decrement the hookcount for consistency, but always do the call. + |. lw TMP2, DISPATCH_GL(hookcount)(DISPATCH) + | andi AT, TMP3, HOOK_ACTIVE + | bnez AT, >1 + |. addiu TMP2, TMP2, -1 + | andi AT, TMP3, LUA_MASKLINE|LUA_MASKCOUNT + | beqz AT, >1 + |. nop + | b >1 + |. sw TMP2, DISPATCH_GL(hookcount)(DISPATCH) +#endif + | + |->vm_rethook: // Dispatch target for return hooks. + | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | andi AT, TMP3, HOOK_ACTIVE // Hook already active? + | beqz AT, >1 + |5: // Re-dispatch to static ins. + |. lw AT, GG_DISP2STATIC(TMP0) // Assumes TMP0 holds DISPATCH+OP*4. + | jr AT + |. nop + | + |->vm_inshook: // Dispatch target for instr/line hooks. + | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | lw TMP2, DISPATCH_GL(hookcount)(DISPATCH) + | andi AT, TMP3, HOOK_ACTIVE // Hook already active? + | bnez AT, <5 + |. andi AT, TMP3, LUA_MASKLINE|LUA_MASKCOUNT + | beqz AT, <5 + |. addiu TMP2, TMP2, -1 + | beqz TMP2, >1 + |. sw TMP2, DISPATCH_GL(hookcount)(DISPATCH) + | andi AT, TMP3, LUA_MASKLINE + | beqz AT, <5 + |1: + |. load_got lj_dispatch_ins + | sw MULTRES, SAVE_MULTRES + | move CARG2, PC + | sw BASE, L->base + | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. + | call_intern lj_dispatch_ins // (lua_State *L, const BCIns *pc) + |. move CARG1, L + |3: + | lw BASE, L->base + |4: // Re-dispatch to static ins. + | lw INS, -4(PC) + | decode_OP4a TMP1, INS + | decode_OP4b TMP1 + | addu TMP0, DISPATCH, TMP1 + | decode_RD8a RD, INS + | lw AT, GG_DISP2STATIC(TMP0) + | decode_RA8a RA, INS + | decode_RD8b RD + | jr AT + | decode_RA8b RA + | + |->cont_hook: // Continue from hook yield. + | addiu PC, PC, 4 + | b <4 + |. lw MULTRES, -24+LO(RB) // Restore MULTRES for *M ins. + | + |->vm_hotloop: // Hot loop counter underflow. +#if LJ_HASJIT + | lw LFUNC:TMP1, FRAME_FUNC(BASE) + | addiu CARG1, DISPATCH, GG_DISP2J + | sw PC, SAVE_PC + | lw TMP1, LFUNC:TMP1->pc + | move CARG2, PC + | sw L, DISPATCH_J(L)(DISPATCH) + | lbu TMP1, PC2PROTO(framesize)(TMP1) + | load_got lj_trace_hot + | sw BASE, L->base + | sll TMP1, TMP1, 3 + | addu TMP1, BASE, TMP1 + | call_intern lj_trace_hot // (jit_State *J, const BCIns *pc) + |. sw TMP1, L->top + | b <3 + |. nop +#endif + | + |->vm_callhook: // Dispatch target for call hooks. +#if LJ_HASJIT + | b >1 +#endif + |. move CARG2, PC + | + |->vm_hotcall: // Hot call counter underflow. +#if LJ_HASJIT + | ori CARG2, PC, 1 + |1: +#endif + | load_got lj_dispatch_call + | addu TMP0, BASE, RC + | sw PC, SAVE_PC + | sw BASE, L->base + | subu RA, RA, BASE + | sw TMP0, L->top + | call_intern lj_dispatch_call // (lua_State *L, const BCIns *pc) + |. move CARG1, L + | // Returns ASMFunction. + | lw BASE, L->base + | lw TMP0, L->top + | sw r0, SAVE_PC // Invalidate for subsequent line hook. + | subu NARGS8:RC, TMP0, BASE + | addu RA, BASE, RA + | lw LFUNC:RB, FRAME_FUNC(BASE) + | jr CRET1 + |. lw INS, -4(PC) + | + |//----------------------------------------------------------------------- + |//-- Trace exit handler ------------------------------------------------- + |//----------------------------------------------------------------------- + | + |.macro savex_, a, b + | sdc1 f..a, 16+a*8(sp) + | sw r..a, 16+32*8+a*4(sp) + | sw r..b, 16+32*8+b*4(sp) + |.endmacro + | + |->vm_exit_handler: +#if LJ_HASJIT + | addiu sp, sp, -(16+32*8+32*4) + | savex_ 0, 1 + | savex_ 2, 3 + | savex_ 4, 5 + | savex_ 6, 7 + | savex_ 8, 9 + | savex_ 10, 11 + | savex_ 12, 13 + | savex_ 14, 15 + | savex_ 16, 17 + | savex_ 18, 19 + | savex_ 20, 21 + | savex_ 22, 23 + | savex_ 24, 25 + | savex_ 26, 27 + | sdc1 f28, 16+28*8(sp) + | sw r28, 16+32*8+28*4(sp) + | sdc1 f30, 16+30*8(sp) + | sw r30, 16+32*8+30*4(sp) + | sw r0, 16+32*8+31*4(sp) // Clear RID_TMP. + | li_vmstate EXIT + | addiu TMP2, sp, 16+32*8+32*4 // Recompute original value of sp. + | addiu DISPATCH, JGL, -GG_DISP2G-32768 + | lw TMP1, 0(TMP2) // Load exit number. + | st_vmstate + | sw TMP2, 16+32*8+29*4(sp) // Store sp in RID_SP. + | lw L, DISPATCH_GL(jit_L)(DISPATCH) + | lw BASE, DISPATCH_GL(jit_base)(DISPATCH) + | load_got lj_trace_exit + | sw L, DISPATCH_J(L)(DISPATCH) + | sw ra, DISPATCH_J(parent)(DISPATCH) // Store trace number. + | sw TMP1, DISPATCH_J(exitno)(DISPATCH) // Store exit number. + | addiu CARG1, DISPATCH, GG_DISP2J + | sw BASE, L->base + | call_intern lj_trace_exit // (jit_State *J, ExitState *ex) + |. addiu CARG2, sp, 16 + | // Returns MULTRES (unscaled) or negated error code. + | lw TMP1, L->cframe + | li AT, -4 + | lw BASE, L->base + | and sp, TMP1, AT + | lw PC, SAVE_PC // Get SAVE_PC. + | b >1 + |. sw L, SAVE_L // Set SAVE_L (on-trace resume/yield). +#endif + |->vm_exit_interp: +#if LJ_HASJIT + | // CRET1 = MULTRES or negated error code, BASE, PC and JGL set. + | lw L, SAVE_L + | addiu DISPATCH, JGL, -GG_DISP2G-32768 + |1: + | bltz CRET1, >3 // Check for error from exit. + |. lw LFUNC:TMP1, FRAME_FUNC(BASE) + | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). + | sll MULTRES, CRET1, 3 + | li TISNIL, LJ_TNIL + | sw MULTRES, SAVE_MULTRES + | mtc1 TMP3, TOBIT + | lw TMP1, LFUNC:TMP1->pc + | sw r0, DISPATCH_GL(jit_L)(DISPATCH) + | lw KBASE, PC2PROTO(k)(TMP1) + | cvt.d.s TOBIT, TOBIT + | // Modified copy of ins_next which handles function header dispatch, too. + | lw INS, 0(PC) + | addiu PC, PC, 4 + | // Assumes TISNIL == ~LJ_VMST_INTERP == -1 + | sw TISNIL, DISPATCH_GL(vmstate)(DISPATCH) + | decode_OP4a TMP1, INS + | decode_OP4b TMP1 + | sltiu TMP2, TMP1, BC_FUNCF*4 // Function header? + | addu TMP0, DISPATCH, TMP1 + | decode_RD8a RD, INS + | lw AT, 0(TMP0) + | decode_RA8a RA, INS + | beqz TMP2, >2 + |. decode_RA8b RA + | jr AT + |. decode_RD8b RD + |2: + | addiu RC, MULTRES, -8 + | jr AT + |. add RA, RA, BASE + | + |3: // Rethrow error from the right C frame. + | load_got lj_err_throw + | negu CARG2, CRET1 + | call_intern lj_err_throw // (lua_State *L, int errcode) + |. move CARG1, L +#endif + | + |//----------------------------------------------------------------------- + |//-- Math helper functions ---------------------------------------------- + |//----------------------------------------------------------------------- + | + |// Modifies AT, TMP0, FRET1, FRET2, f4. Keeps all others incl. FARG1, FARG2. + |.macro vm_round, func + | lui TMP0, 0x4330 // Hiword of 2^52 (double). + | mtc1 r0, f4 + | mtc1 TMP0, f5 + | abs.d FRET2, FARG1 // |x| + | mfc1 AT, f13 + | c.olt.d 0, FRET2, f4 + | add.d FRET1, FRET2, f4 // (|x| + 2^52) - 2^52 + | bc1f 0, >1 // Truncate only if |x| < 2^52. + |. sub.d FRET1, FRET1, f4 + | slt AT, AT, r0 + |.if "func" == "ceil" + | lui TMP0, 0xbff0 // Hiword of -1 (double). Preserves -0. + |.else + | lui TMP0, 0x3ff0 // Hiword of +1 (double). + |.endif + |.if "func" == "trunc" + | mtc1 TMP0, f5 + | c.olt.d 0, FRET2, FRET1 // |x| < result? + | sub.d FRET2, FRET1, f4 + | movt.d FRET1, FRET2, 0 // If yes, subtract +1. + | neg.d FRET2, FRET1 + | jr ra + |. movn.d FRET1, FRET2, AT // Merge sign bit back in. + |.else + | neg.d FRET2, FRET1 + | mtc1 TMP0, f5 + | movn.d FRET1, FRET2, AT // Merge sign bit back in. + |.if "func" == "ceil" + | c.olt.d 0, FRET1, FARG1 // x > result? + |.else + | c.olt.d 0, FARG1, FRET1 // x < result? + |.endif + | sub.d FRET2, FRET1, f4 // If yes, subtract +-1. + | jr ra + |. movt.d FRET1, FRET2, 0 + |.endif + |1: + | jr ra + |. mov.d FRET1, FARG1 + |.endmacro + | + |->vm_floor: + | vm_round floor + |->vm_ceil: + | vm_round ceil + |->vm_trunc: +#if LJ_HASJIT + | vm_round trunc +#endif + | + |//----------------------------------------------------------------------- + |//-- Miscellaneous functions -------------------------------------------- + |//----------------------------------------------------------------------- + | + |//----------------------------------------------------------------------- + |//-- FFI helper functions ----------------------------------------------- + |//----------------------------------------------------------------------- + | + |// Handler for callback functions. Callback slot number in r1, g in r2. + |->vm_ffi_callback: +#if LJ_HASFFI + |.type CTSTATE, CTState, PC + | saveregs + | lw CTSTATE, GL:r2->ctype_state + | addiu DISPATCH, r2, GG_G2DISP + | load_got lj_ccallback_enter + | sw r1, CTSTATE->cb.slot + | sw CARG1, CTSTATE->cb.gpr[0] + | sw CARG2, CTSTATE->cb.gpr[1] + | sdc1 FARG1, CTSTATE->cb.fpr[0] + | sw CARG3, CTSTATE->cb.gpr[2] + | sw CARG4, CTSTATE->cb.gpr[3] + | sdc1 FARG2, CTSTATE->cb.fpr[1] + | addiu TMP0, sp, CFRAME_SPACE+16 + | sw TMP0, CTSTATE->cb.stack + | sw r0, SAVE_PC // Any value outside of bytecode is ok. + | move CARG2, sp + | call_intern lj_ccallback_enter // (CTState *cts, void *cf) + |. move CARG1, CTSTATE + | // Returns lua_State *. + | lw BASE, L:CRET1->base + | lw RC, L:CRET1->top + | move L, CRET1 + | lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). + | lw LFUNC:RB, FRAME_FUNC(BASE) + | mtc1 TMP3, TOBIT + | li_vmstate INTERP + | li TISNIL, LJ_TNIL + | subu RC, RC, BASE + | st_vmstate + | cvt.d.s TOBIT, TOBIT + | ins_callt +#endif + | + |->cont_ffi_callback: // Return from FFI callback. +#if LJ_HASFFI + | load_got lj_ccallback_leave + | lw CTSTATE, DISPATCH_GL(ctype_state)(DISPATCH) + | sw BASE, L->base + | sw RB, L->top + | sw L, CTSTATE->L + | move CARG2, RA + | call_intern lj_ccallback_leave // (CTState *cts, TValue *o) + |. move CARG1, CTSTATE + | lw CRET1, CTSTATE->cb.gpr[0] + | ldc1 FRET1, CTSTATE->cb.fpr[0] + | lw CRET2, CTSTATE->cb.gpr[1] + | b ->vm_leave_unw + |. ldc1 FRET2, CTSTATE->cb.fpr[1] +#endif + | + |->vm_ffi_call: // Call C function via FFI. + | // Caveat: needs special frame unwinding, see below. +#if LJ_HASFFI + | .type CCSTATE, CCallState, CARG1 + | lw TMP1, CCSTATE->spadj + | lbu CARG2, CCSTATE->nsp + | move TMP2, sp + | subu sp, sp, TMP1 + | sw ra, -4(TMP2) + | sll CARG2, CARG2, 2 + | sw r16, -8(TMP2) + | sw CCSTATE, -12(TMP2) + | move r16, TMP2 + | addiu TMP1, CCSTATE, offsetof(CCallState, stack) + | addiu TMP2, sp, 16 + | beqz CARG2, >2 + |. addu TMP3, TMP1, CARG2 + |1: + | lw TMP0, 0(TMP1) + | addiu TMP1, TMP1, 4 + | sltu AT, TMP1, TMP3 + | sw TMP0, 0(TMP2) + | bnez AT, <1 + |. addiu TMP2, TMP2, 4 + |2: + | lw CFUNCADDR, CCSTATE->func + | lw CARG2, CCSTATE->gpr[1] + | lw CARG3, CCSTATE->gpr[2] + | lw CARG4, CCSTATE->gpr[3] + | ldc1 FARG1, CCSTATE->fpr[0] + | ldc1 FARG2, CCSTATE->fpr[1] + | jalr CFUNCADDR + |. lw CARG1, CCSTATE->gpr[0] // Do this last, since CCSTATE is CARG1. + | lw CCSTATE:TMP1, -12(r16) + | lw TMP2, -8(r16) + | lw ra, -4(r16) + | sw CRET1, CCSTATE:TMP1->gpr[0] + | sw CRET2, CCSTATE:TMP1->gpr[1] + | sdc1 FRET1, CCSTATE:TMP1->fpr[0] + | sdc1 FRET2, CCSTATE:TMP1->fpr[1] + | move sp, r16 + | jr ra + |. move r16, TMP2 +#endif + |// Note: vm_ffi_call must be the last function in this object file! + | + |//----------------------------------------------------------------------- +} + +/* Generate the code for a single instruction. */ +static void build_ins(BuildCtx *ctx, BCOp op, int defop) +{ + int vk = 0; + |=>defop: + + switch (op) { + + /* -- Comparison ops ---------------------------------------------------- */ + + /* Remember: all ops branch for a true comparison, fall through otherwise. */ + + case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: + | // RA = src1*8, RD = src2*8, JMP with RD = target + | addu CARG2, BASE, RA + | addu CARG3, BASE, RD + | lw TMP0, HI(CARG2) + | lw TMP1, HI(CARG3) + | ldc1 f0, 0(CARG2) + | ldc1 f2, 0(CARG3) + | sltiu TMP0, TMP0, LJ_TISNUM + | sltiu TMP1, TMP1, LJ_TISNUM + | lhu TMP2, OFS_RD(PC) + | and TMP0, TMP0, TMP1 + | addiu PC, PC, 4 + | beqz TMP0, ->vmeta_comp + |. lui TMP1, (-(BCBIAS_J*4 >> 16) & 65535) + | decode_RD4b TMP2 + | addu TMP2, TMP2, TMP1 + if (op == BC_ISLT || op == BC_ISGE) { + | c.olt.d f0, f2 + } else { + | c.ole.d f0, f2 + } + if (op == BC_ISLT || op == BC_ISLE) { + | movf TMP2, r0 + } else { + | movt TMP2, r0 + } + | addu PC, PC, TMP2 + |1: + | ins_next + break; + + case BC_ISEQV: case BC_ISNEV: + vk = op == BC_ISEQV; + | // RA = src1*8, RD = src2*8, JMP with RD = target + | addu RA, BASE, RA + | addiu PC, PC, 4 + | lw TMP0, HI(RA) + | ldc1 f0, 0(RA) + | addu RD, BASE, RD + | lhu TMP2, -4+OFS_RD(PC) + | lw TMP1, HI(RD) + | ldc1 f2, 0(RD) + | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) + | sltiu AT, TMP0, LJ_TISNUM + | sltiu CARG1, TMP1, LJ_TISNUM + | decode_RD4b TMP2 + | and AT, AT, CARG1 + | beqz AT, >5 + |. addu TMP2, TMP2, TMP3 + | c.eq.d f0, f2 + if (vk) { + | movf TMP2, r0 + } else { + | movt TMP2, r0 + } + |1: + | addu PC, PC, TMP2 + | ins_next + |5: // Either or both types are not numbers. + | lw CARG2, LO(RA) + | lw CARG3, LO(RD) + if (LJ_HASFFI) { + | li TMP3, LJ_TCDATA + | beq TMP0, TMP3, ->vmeta_equal_cd + } + |. sltiu AT, TMP0, LJ_TISPRI // Not a primitive? + if (LJ_HASFFI) { + | beq TMP1, TMP3, ->vmeta_equal_cd + } + |. xor TMP3, CARG2, CARG3 // Same tv? + | xor TMP1, TMP1, TMP0 // Same type? + | sltiu CARG1, TMP0, LJ_TISTABUD+1 // Table or userdata? + | movz TMP3, r0, AT // Ignore tv if primitive. + | movn CARG1, r0, TMP1 // Tab/ud and same type? + | or AT, TMP1, TMP3 // Same type && (pri||same tv). + | movz CARG1, r0, AT + | beqz CARG1, <1 // Done if not tab/ud or not same type or same tv. + if (vk) { + |. movn TMP2, r0, AT + } else { + |. movz TMP2, r0, AT + } + | // Different tables or userdatas. Need to check __eq metamethod. + | // Field metatable must be at same offset for GCtab and GCudata! + | lw TAB:TMP1, TAB:CARG2->metatable + | beqz TAB:TMP1, <1 // No metatable? + |. nop + | lbu TMP1, TAB:TMP1->nomm + | andi TMP1, TMP1, 1<vmeta_equal // Handle __eq metamethod. + |. li CARG4, 1-vk // ne = 0 or 1. + break; + + case BC_ISEQS: case BC_ISNES: + vk = op == BC_ISEQS; + | // RA = src*8, RD = str_const*8 (~), JMP with RD = target + | addu RA, BASE, RA + | addiu PC, PC, 4 + | lw TMP0, HI(RA) + | srl RD, RD, 1 + | lw STR:TMP3, LO(RA) + | subu RD, KBASE, RD + | lhu TMP2, -4+OFS_RD(PC) + if (LJ_HASFFI) { + | li AT, LJ_TCDATA + | beq TMP0, AT, ->vmeta_equal_cd + } + |. lw STR:TMP1, -4(RD) // KBASE-4-str_const*4 + | addiu TMP0, TMP0, -LJ_TSTR + | decode_RD4b TMP2 + | xor TMP1, STR:TMP1, STR:TMP3 + | or TMP0, TMP0, TMP1 + | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) + | addu TMP2, TMP2, TMP3 + if (vk) { + | movn TMP2, r0, TMP0 + } else { + | movz TMP2, r0, TMP0 + } + | addu PC, PC, TMP2 + | ins_next + break; + + case BC_ISEQN: case BC_ISNEN: + vk = op == BC_ISEQN; + | // RA = src*8, RD = num_const*8, JMP with RD = target + | addu RA, BASE, RA + | addiu PC, PC, 4 + | lw TMP0, HI(RA) + | ldc1 f0, 0(RA) + | addu RD, KBASE, RD + | lhu TMP2, -4+OFS_RD(PC) + | ldc1 f2, 0(RD) + | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) + | sltiu AT, TMP0, LJ_TISNUM + | decode_RD4b TMP2 + if (LJ_HASFFI) { + | beqz AT, >5 + } else { + | beqz AT, >1 + } + |. addu TMP2, TMP2, TMP3 + | c.eq.d f0, f2 + if (vk) { + | movf TMP2, r0 + | addu PC, PC, TMP2 + |1: + } else { + | movt TMP2, r0 + |1: + | addu PC, PC, TMP2 + } + | ins_next + if (LJ_HASFFI) { + |5: + | li AT, LJ_TCDATA + | beq TMP0, AT, ->vmeta_equal_cd + |. nop + | b <1 + |. nop + } + break; + + case BC_ISEQP: case BC_ISNEP: + vk = op == BC_ISEQP; + | // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target + | addu RA, BASE, RA + | srl TMP1, RD, 3 + | lw TMP0, HI(RA) + | lhu TMP2, OFS_RD(PC) + | not TMP1, TMP1 + | addiu PC, PC, 4 + if (LJ_HASFFI) { + | li AT, LJ_TCDATA + | beq TMP0, AT, ->vmeta_equal_cd + } + |. xor TMP0, TMP0, TMP1 + | decode_RD4b TMP2 + | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) + | addu TMP2, TMP2, TMP3 + if (vk) { + | movn TMP2, r0, TMP0 + } else { + | movz TMP2, r0, TMP0 + } + | addu PC, PC, TMP2 + | ins_next + break; + + /* -- Unary test and copy ops ------------------------------------------- */ + + case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: + | // RA = dst*8 or unused, RD = src*8, JMP with RD = target + | addu RD, BASE, RD + | lhu TMP2, OFS_RD(PC) + | lw TMP0, HI(RD) + | addiu PC, PC, 4 + if (op == BC_IST || op == BC_ISF) { + | sltiu TMP0, TMP0, LJ_TISTRUECOND + | decode_RD4b TMP2 + | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) + | addu TMP2, TMP2, TMP3 + if (op == BC_IST) { + | movz TMP2, r0, TMP0 + } else { + | movn TMP2, r0, TMP0 + } + | addu PC, PC, TMP2 + } else { + | sltiu TMP0, TMP0, LJ_TISTRUECOND + | ldc1 f0, 0(RD) + if (op == BC_ISTC) { + | beqz TMP0, >1 + } else { + | bnez TMP0, >1 + } + |. addu RA, BASE, RA + | decode_RD4b TMP2 + | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) + | addu TMP2, TMP2, TMP3 + | sdc1 f0, 0(RA) + | addu PC, PC, TMP2 + |1: + } + | ins_next + break; + + /* -- Unary ops --------------------------------------------------------- */ + + case BC_MOV: + | // RA = dst*8, RD = src*8 + | addu RD, BASE, RD + | addu RA, BASE, RA + | ldc1 f0, 0(RD) + | ins_next1 + | sdc1 f0, 0(RA) + | ins_next2 + break; + case BC_NOT: + | // RA = dst*8, RD = src*8 + | addu RD, BASE, RD + | addu RA, BASE, RA + | lw TMP0, HI(RD) + | li TMP1, LJ_TFALSE + | sltiu TMP0, TMP0, LJ_TISTRUECOND + | addiu TMP1, TMP0, LJ_TTRUE + | ins_next1 + | sw TMP1, HI(RA) + | ins_next2 + break; + case BC_UNM: + | // RA = dst*8, RD = src*8 + | addu CARG3, BASE, RD + | addu RA, BASE, RA + | lw TMP0, HI(CARG3) + | ldc1 f0, 0(CARG3) + | sltiu AT, TMP0, LJ_TISNUM + | beqz AT, ->vmeta_unm + |. neg.d f0, f0 + | ins_next1 + | sdc1 f0, 0(RA) + | ins_next2 + break; + case BC_LEN: + | // RA = dst*8, RD = src*8 + | addu CARG2, BASE, RD + | addu RA, BASE, RA + | lw TMP0, HI(CARG2) + | lw CARG1, LO(CARG2) + | li AT, LJ_TSTR + | bne TMP0, AT, >2 + |. li AT, LJ_TTAB + | lw CRET1, STR:CARG1->len + |1: + | mtc1 CRET1, f0 + | cvt.d.w f0, f0 + | ins_next1 + | sdc1 f0, 0(RA) + | ins_next2 + |2: + | bne TMP0, AT, ->vmeta_len + |. nop +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | lw TAB:TMP2, TAB:CARG1->metatable + | bnez TAB:TMP2, >9 + |. nop + |3: +#endif + |->BC_LEN_Z: + | load_got lj_tab_len + | call_intern lj_tab_len // (GCtab *t) + |. nop + | // Returns uint32_t (but less than 2^31). + | b <1 + |. nop +#ifdef LUAJIT_ENABLE_LUA52COMPAT + |9: + | lbu TMP0, TAB:TMP2->nomm + | andi TMP0, TMP0, 1<vmeta_len + |. nop +#endif + break; + + /* -- Binary ops -------------------------------------------------------- */ + + |.macro ins_arithpre + ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); + | decode_RB8a RB, INS + | decode_RB8b RB + | decode_RDtoRC8 RC, RD + | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8 + ||switch (vk) { + ||case 0: + | addu CARG3, BASE, RB + | addu CARG4, KBASE, RC + | lw TMP1, HI(CARG3) + | ldc1 f20, 0(CARG3) + | ldc1 f22, 0(CARG4) + | sltiu AT, TMP1, LJ_TISNUM + || break; + ||case 1: + | addu CARG4, BASE, RB + | addu CARG3, KBASE, RC + | lw TMP1, HI(CARG4) + | ldc1 f22, 0(CARG4) + | ldc1 f20, 0(CARG3) + | sltiu AT, TMP1, LJ_TISNUM + || break; + ||default: + | addu CARG3, BASE, RB + | addu CARG4, BASE, RC + | lw TMP1, HI(CARG3) + | lw TMP2, HI(CARG4) + | ldc1 f20, 0(CARG3) + | ldc1 f22, 0(CARG4) + | sltiu AT, TMP1, LJ_TISNUM + | sltiu TMP0, TMP2, LJ_TISNUM + | and AT, AT, TMP0 + || break; + ||} + | beqz AT, ->vmeta_arith + |. addu RA, BASE, RA + |.endmacro + | + |.macro fpmod, a, b, c + |->BC_MODVN_Z: + | bal ->vm_floor // floor(b/c) + |. div.d FARG1, b, c + | mul.d a, FRET1, c + | sub.d a, b, a // b - floor(b/c)*c + |.endmacro + | + |.macro ins_arith, ins + | ins_arithpre + |.if "ins" == "fpmod_" + | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway. + |. nop + |.else + | ins f0, f20, f22 + | ins_next1 + | sdc1 f0, 0(RA) + | ins_next2 + |.endif + |.endmacro + + case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: + | ins_arith add.d + break; + case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: + | ins_arith sub.d + break; + case BC_MULVN: case BC_MULNV: case BC_MULVV: + | ins_arith mul.d + break; + case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: + | ins_arith div.d + break; + case BC_MODVN: + | ins_arith fpmod + break; + case BC_MODNV: case BC_MODVV: + | ins_arith fpmod_ + break; + case BC_POW: + | decode_RB8a RB, INS + | decode_RB8b RB + | decode_RDtoRC8 RC, RD + | addu CARG3, BASE, RB + | addu CARG4, BASE, RC + | lw TMP1, HI(CARG3) + | lw TMP2, HI(CARG4) + | ldc1 FARG1, 0(CARG3) + | ldc1 FARG2, 0(CARG4) + | sltiu AT, TMP1, LJ_TISNUM + | sltiu TMP0, TMP2, LJ_TISNUM + | and AT, AT, TMP0 + | load_got pow + | beqz AT, ->vmeta_arith + |. addu RA, BASE, RA + | call_extern + |. nop + | ins_next1 + | sdc1 FRET1, 0(RA) + | ins_next2 + break; + + case BC_CAT: + | // RA = dst*8, RB = src_start*8, RC = src_end*8 + | decode_RB8a RB, INS + | decode_RB8b RB + | decode_RDtoRC8 RC, RD + | subu CARG3, RC, RB + | sw BASE, L->base + | addu CARG2, BASE, RC + | move MULTRES, RB + |->BC_CAT_Z: + | load_got lj_meta_cat + | srl CARG3, CARG3, 3 + | sw PC, SAVE_PC + | call_intern lj_meta_cat // (lua_State *L, TValue *top, int left) + |. move CARG1, L + | // Returns NULL (finished) or TValue * (metamethod). + | bnez CRET1, ->vmeta_binop + |. lw BASE, L->base + | addu RB, BASE, MULTRES + | ldc1 f0, 0(RB) + | addu RA, BASE, RA + | ins_next1 + | sdc1 f0, 0(RA) // Copy result from RB to RA. + | ins_next2 + break; + + /* -- Constant ops ------------------------------------------------------ */ + + case BC_KSTR: + | // RA = dst*8, RD = str_const*8 (~) + | srl TMP1, RD, 1 + | subu TMP1, KBASE, TMP1 + | ins_next1 + | lw TMP0, -4(TMP1) // KBASE-4-str_const*4 + | addu RA, BASE, RA + | li TMP2, LJ_TSTR + | sw TMP0, LO(RA) + | sw TMP2, HI(RA) + | ins_next2 + break; + case BC_KCDATA: +#if LJ_HASFFI + | // RA = dst*8, RD = cdata_const*8 (~) + | srl TMP1, RD, 1 + | subu TMP1, KBASE, TMP1 + | ins_next1 + | lw TMP0, -4(TMP1) // KBASE-4-cdata_const*4 + | addu RA, BASE, RA + | li TMP2, LJ_TCDATA + | sw TMP0, LO(RA) + | sw TMP2, HI(RA) + | ins_next2 +#endif + break; + case BC_KSHORT: + | // RA = dst*8, RD = int16_literal*8 + | sra RD, INS, 16 + | mtc1 RD, f0 + | addu RA, BASE, RA + | cvt.d.w f0, f0 + | ins_next1 + | sdc1 f0, 0(RA) + | ins_next2 + break; + case BC_KNUM: + | // RA = dst*8, RD = num_const*8 + | addu RD, KBASE, RD + | addu RA, BASE, RA + | ldc1 f0, 0(RD) + | ins_next1 + | sdc1 f0, 0(RA) + | ins_next2 + break; + case BC_KPRI: + | // RA = dst*8, RD = primitive_type*8 (~) + | srl TMP1, RD, 3 + | addu RA, BASE, RA + | not TMP0, TMP1 + | ins_next1 + | sw TMP0, HI(RA) + | ins_next2 + break; + case BC_KNIL: + | // RA = base*8, RD = end*8 + | addu RA, BASE, RA + | sw TISNIL, HI(RA) + | addiu RA, RA, 8 + | addu RD, BASE, RD + |1: + | sw TISNIL, HI(RA) + | slt AT, RA, RD + | bnez AT, <1 + |. addiu RA, RA, 8 + | ins_next_ + break; + + /* -- Upvalue and function ops ------------------------------------------ */ + + case BC_UGET: + | // RA = dst*8, RD = uvnum*8 + | lw LFUNC:RB, FRAME_FUNC(BASE) + | srl RD, RD, 1 + | addu RD, RD, LFUNC:RB + | lw UPVAL:RB, LFUNC:RD->uvptr + | ins_next1 + | lw TMP1, UPVAL:RB->v + | ldc1 f0, 0(TMP1) + | addu RA, BASE, RA + | sdc1 f0, 0(RA) + | ins_next2 + break; + case BC_USETV: + | // RA = uvnum*8, RD = src*8 + | lw LFUNC:RB, FRAME_FUNC(BASE) + | srl RA, RA, 1 + | addu RD, BASE, RD + | addu RA, RA, LFUNC:RB + | ldc1 f0, 0(RD) + | lw UPVAL:RB, LFUNC:RA->uvptr + | lbu TMP3, UPVAL:RB->marked + | lw CARG2, UPVAL:RB->v + | andi TMP3, TMP3, LJ_GC_BLACK // isblack(uv) + | lbu TMP0, UPVAL:RB->closed + | lw TMP2, HI(RD) + | sdc1 f0, 0(CARG2) + | li AT, LJ_GC_BLACK|1 + | or TMP3, TMP3, TMP0 + | beq TMP3, AT, >2 // Upvalue is closed and black? + |. addiu TMP2, TMP2, -(LJ_TISNUM+1) + |1: + | ins_next + | + |2: // Check if new value is collectable. + | sltiu AT, TMP2, LJ_TISGCV - (LJ_TISNUM+1) + | beqz AT, <1 // tvisgcv(v) + |. lw TMP1, LO(RD) + | lbu TMP3, GCOBJ:TMP1->gch.marked + | andi TMP3, TMP3, LJ_GC_WHITES // iswhite(v) + | beqz TMP3, <1 + |. load_got lj_gc_barrieruv + | // Crossed a write barrier. Move the barrier forward. + | call_intern lj_gc_barrieruv // (global_State *g, TValue *tv) + |. addiu CARG1, DISPATCH, GG_DISP2G + | b <1 + |. nop + break; + case BC_USETS: + | // RA = uvnum*8, RD = str_const*8 (~) + | lw LFUNC:RB, FRAME_FUNC(BASE) + | srl RA, RA, 1 + | srl TMP1, RD, 1 + | addu RA, RA, LFUNC:RB + | subu TMP1, KBASE, TMP1 + | lw UPVAL:RB, LFUNC:RA->uvptr + | lw STR:TMP1, -4(TMP1) // KBASE-4-str_const*4 + | lbu TMP2, UPVAL:RB->marked + | lw CARG2, UPVAL:RB->v + | lbu TMP3, STR:TMP1->marked + | andi AT, TMP2, LJ_GC_BLACK // isblack(uv) + | lbu TMP2, UPVAL:RB->closed + | li TMP0, LJ_TSTR + | sw STR:TMP1, LO(CARG2) + | bnez AT, >2 + |. sw TMP0, HI(CARG2) + |1: + | ins_next + | + |2: // Check if string is white and ensure upvalue is closed. + | beqz TMP2, <1 + |. andi AT, TMP3, LJ_GC_WHITES // iswhite(str) + | beqz AT, <1 + |. load_got lj_gc_barrieruv + | // Crossed a write barrier. Move the barrier forward. + | call_intern lj_gc_barrieruv // (global_State *g, TValue *tv) + |. addiu CARG1, DISPATCH, GG_DISP2G + | b <1 + |. nop + break; + case BC_USETN: + | // RA = uvnum*8, RD = num_const*8 + | lw LFUNC:RB, FRAME_FUNC(BASE) + | srl RA, RA, 1 + | addu RD, KBASE, RD + | addu RA, RA, LFUNC:RB + | ldc1 f0, 0(RD) + | lw UPVAL:RB, LFUNC:RA->uvptr + | ins_next1 + | lw TMP1, UPVAL:RB->v + | sdc1 f0, 0(TMP1) + | ins_next2 + break; + case BC_USETP: + | // RA = uvnum*8, RD = primitive_type*8 (~) + | lw LFUNC:RB, FRAME_FUNC(BASE) + | srl RA, RA, 1 + | srl TMP0, RD, 3 + | addu RA, RA, LFUNC:RB + | not TMP0, TMP0 + | lw UPVAL:RB, LFUNC:RA->uvptr + | ins_next1 + | lw TMP1, UPVAL:RB->v + | sw TMP0, HI(TMP1) + | ins_next2 + break; + + case BC_UCLO: + | // RA = level*8, RD = target + | lw TMP2, L->openupval + | branch_RD // Do this first since RD is not saved. + | load_got lj_func_closeuv + | sw BASE, L->base + | beqz TMP2, >1 + |. move CARG1, L + | call_intern lj_func_closeuv // (lua_State *L, TValue *level) + |. addu CARG2, BASE, RA + | lw BASE, L->base + |1: + | ins_next + break; + + case BC_FNEW: + | // RA = dst*8, RD = proto_const*8 (~) (holding function prototype) + | srl TMP1, RD, 1 + | load_got lj_func_newL_gc + | subu TMP1, KBASE, TMP1 + | lw CARG3, FRAME_FUNC(BASE) + | lw CARG2, -4(TMP1) // KBASE-4-tab_const*4 + | sw BASE, L->base + | sw PC, SAVE_PC + | // (lua_State *L, GCproto *pt, GCfuncL *parent) + | call_intern lj_func_newL_gc + |. move CARG1, L + | // Returns GCfuncL *. + | lw BASE, L->base + | li TMP0, LJ_TFUNC + | ins_next1 + | addu RA, BASE, RA + | sw TMP0, HI(RA) + | sw LFUNC:CRET1, LO(RA) + | ins_next2 + break; + + /* -- Table ops --------------------------------------------------------- */ + + case BC_TNEW: + case BC_TDUP: + | // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~) + | lw TMP0, DISPATCH_GL(gc.total)(DISPATCH) + | lw TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) + | sw BASE, L->base + | sw PC, SAVE_PC + | sltu AT, TMP0, TMP1 + | beqz AT, >5 + |1: + if (op == BC_TNEW) { + | load_got lj_tab_new + | srl CARG2, RD, 3 + | andi CARG2, CARG2, 0x7ff + | li TMP0, 0x801 + | addiu AT, CARG2, -0x7ff + | srl CARG3, RD, 14 + | movz CARG2, TMP0, AT + | // (lua_State *L, int32_t asize, uint32_t hbits) + | call_intern lj_tab_new + |. move CARG1, L + | // Returns Table *. + } else { + | load_got lj_tab_dup + | srl TMP1, RD, 1 + | subu TMP1, KBASE, TMP1 + | move CARG1, L + | call_intern lj_tab_dup // (lua_State *L, Table *kt) + |. lw CARG2, -4(TMP1) // KBASE-4-str_const*4 + | // Returns Table *. + } + | lw BASE, L->base + | ins_next1 + | addu RA, BASE, RA + | li TMP0, LJ_TTAB + | sw TAB:CRET1, LO(RA) + | sw TMP0, HI(RA) + | ins_next2 + |5: + | load_got lj_gc_step_fixtop + | move MULTRES, RD + | call_intern lj_gc_step_fixtop // (lua_State *L) + |. move CARG1, L + | b <1 + |. move RD, MULTRES + break; + + case BC_GGET: + | // RA = dst*8, RD = str_const*8 (~) + case BC_GSET: + | // RA = src*8, RD = str_const*8 (~) + | lw LFUNC:TMP2, FRAME_FUNC(BASE) + | srl TMP1, RD, 1 + | subu TMP1, KBASE, TMP1 + | lw TAB:RB, LFUNC:TMP2->env + | lw STR:RC, -4(TMP1) // KBASE-4-str_const*4 + if (op == BC_GGET) { + | b ->BC_TGETS_Z + } else { + | b ->BC_TSETS_Z + } + |. addu RA, BASE, RA + break; + + case BC_TGETV: + | // RA = dst*8, RB = table*8, RC = key*8 + | decode_RB8a RB, INS + | decode_RB8b RB + | decode_RDtoRC8 RC, RD + | addu CARG2, BASE, RB + | addu CARG3, BASE, RC + | lw TMP1, HI(CARG2) + | lw TMP2, HI(CARG3) + | lw TAB:RB, LO(CARG2) + | li AT, LJ_TTAB + | ldc1 f0, 0(CARG3) + | bne TMP1, AT, ->vmeta_tgetv + |. addu RA, BASE, RA + | sltiu AT, TMP2, LJ_TISNUM + | beqz AT, >5 + |. li AT, LJ_TSTR + | + | // Convert number key to integer, check for integerness and range. + | cvt.w.d f2, f0 + | lw TMP0, TAB:RB->asize + | mfc1 TMP2, f2 + | cvt.d.w f4, f2 + | lw TMP1, TAB:RB->array + | c.eq.d f0, f4 + | sltu AT, TMP2, TMP0 + | movf AT, r0 + | sll TMP2, TMP2, 3 + | beqz AT, ->vmeta_tgetv // Integer key and in array part? + |. addu TMP2, TMP1, TMP2 + | lw TMP0, HI(TMP2) + | beq TMP0, TISNIL, >2 + |. ldc1 f0, 0(TMP2) + |1: + | ins_next1 + | sdc1 f0, 0(RA) + | ins_next2 + | + |2: // Check for __index if table value is nil. + | lw TAB:TMP2, TAB:RB->metatable + | beqz TAB:TMP2, <1 // No metatable: done. + |. nop + | lbu TMP0, TAB:TMP2->nomm + | andi TMP0, TMP0, 1<vmeta_tgetv + |. nop + | + |5: + | bne TMP2, AT, ->vmeta_tgetv + |. lw STR:RC, LO(CARG3) + | b ->BC_TGETS_Z // String key? + |. nop + break; + case BC_TGETS: + | // RA = dst*8, RB = table*8, RC = str_const*4 (~) + | decode_RB8a RB, INS + | decode_RB8b RB + | addu CARG2, BASE, RB + | decode_RC4a RC, INS + | lw TMP0, HI(CARG2) + | decode_RC4b RC + | li AT, LJ_TTAB + | lw TAB:RB, LO(CARG2) + | subu CARG3, KBASE, RC + | lw STR:RC, -4(CARG3) // KBASE-4-str_const*4 + | bne TMP0, AT, ->vmeta_tgets1 + |. addu RA, BASE, RA + |->BC_TGETS_Z: + | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8 + | lw TMP0, TAB:RB->hmask + | lw TMP1, STR:RC->hash + | lw NODE:TMP2, TAB:RB->node + | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask + | sll TMP0, TMP1, 5 + | sll TMP1, TMP1, 3 + | subu TMP1, TMP0, TMP1 + | addu NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) + |1: + | lw CARG1, offsetof(Node, key)+HI(NODE:TMP2) + | lw TMP0, offsetof(Node, key)+LO(NODE:TMP2) + | lw NODE:TMP1, NODE:TMP2->next + | lw CARG2, offsetof(Node, val)+HI(NODE:TMP2) + | addiu CARG1, CARG1, -LJ_TSTR + | xor TMP0, TMP0, STR:RC + | or AT, CARG1, TMP0 + | bnez AT, >4 + |. lw TAB:TMP3, TAB:RB->metatable + | beq CARG2, TISNIL, >5 // Key found, but nil value? + |. lw CARG1, offsetof(Node, val)+LO(NODE:TMP2) + |3: + | ins_next1 + | sw CARG2, HI(RA) + | sw CARG1, LO(RA) + | ins_next2 + | + |4: // Follow hash chain. + | bnez NODE:TMP1, <1 + |. move NODE:TMP2, NODE:TMP1 + | // End of hash chain: key not found, nil result. + | + |5: // Check for __index if table value is nil. + | beqz TAB:TMP3, <3 // No metatable: done. + |. li CARG2, LJ_TNIL + | lbu TMP0, TAB:TMP3->nomm + | andi TMP0, TMP0, 1<vmeta_tgets + |. nop + break; + case BC_TGETB: + | // RA = dst*8, RB = table*8, RC = index*8 + | decode_RB8a RB, INS + | decode_RB8b RB + | addu CARG2, BASE, RB + | decode_RDtoRC8 RC, RD + | lw CARG1, HI(CARG2) + | li AT, LJ_TTAB + | lw TAB:RB, LO(CARG2) + | addu RA, BASE, RA + | bne CARG1, AT, ->vmeta_tgetb + |. srl TMP0, RC, 3 + | lw TMP1, TAB:RB->asize + | lw TMP2, TAB:RB->array + | sltu AT, TMP0, TMP1 + | beqz AT, ->vmeta_tgetb + |. addu RC, TMP2, RC + | lw TMP1, HI(RC) + | beq TMP1, TISNIL, >5 + |. ldc1 f0, 0(RC) + |1: + | ins_next1 + | sdc1 f0, 0(RA) + | ins_next2 + | + |5: // Check for __index if table value is nil. + | lw TAB:TMP2, TAB:RB->metatable + | beqz TAB:TMP2, <1 // No metatable: done. + |. nop + | lbu TMP1, TAB:TMP2->nomm + | andi TMP1, TMP1, 1<vmeta_tgetb // Caveat: preserve TMP0! + |. nop + break; + + case BC_TSETV: + | // RA = src*8, RB = table*8, RC = key*8 + | decode_RB8a RB, INS + | decode_RB8b RB + | decode_RDtoRC8 RC, RD + | addu CARG2, BASE, RB + | addu CARG3, BASE, RC + | lw TMP1, HI(CARG2) + | lw TMP2, HI(CARG3) + | lw TAB:RB, LO(CARG2) + | li AT, LJ_TTAB + | ldc1 f0, 0(CARG3) + | bne TMP1, AT, ->vmeta_tsetv + |. addu RA, BASE, RA + | sltiu AT, TMP2, LJ_TISNUM + | beqz AT, >5 + |. li AT, LJ_TSTR + | + | // Convert number key to integer, check for integerness and range. + | cvt.w.d f2, f0 + | lw TMP0, TAB:RB->asize + | mfc1 TMP2, f2 + | cvt.d.w f4, f2 + | lw TMP1, TAB:RB->array + | c.eq.d f0, f4 + | sltu AT, TMP2, TMP0 + | movf AT, r0 + | sll TMP2, TMP2, 3 + | beqz AT, ->vmeta_tsetv // Integer key and in array part? + |. addu TMP1, TMP1, TMP2 + | lbu TMP3, TAB:RB->marked + | lw TMP0, HI(TMP1) + | beq TMP0, TISNIL, >3 + |. ldc1 f0, 0(RA) + |1: + | andi AT, TMP3, LJ_GC_BLACK // isblack(table) + | bnez AT, >7 + |. sdc1 f0, 0(TMP1) + |2: + | ins_next + | + |3: // Check for __newindex if previous value is nil. + | lw TAB:TMP2, TAB:RB->metatable + | beqz TAB:TMP2, <1 // No metatable: done. + |. nop + | lbu TMP2, TAB:TMP2->nomm + | andi TMP2, TMP2, 1<vmeta_tsetv + |. nop + | + |5: + | bne TMP2, AT, ->vmeta_tsetv + |. lw STR:RC, LO(CARG3) + | b ->BC_TSETS_Z // String key? + |. nop + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, TMP3, TMP0, <2 + break; + case BC_TSETS: + | // RA = src*8, RB = table*8, RC = str_const*8 (~) + | decode_RB8a RB, INS + | decode_RB8b RB + | addu CARG2, BASE, RB + | decode_RC4a RC, INS + | lw TMP0, HI(CARG2) + | decode_RC4b RC + | li AT, LJ_TTAB + | subu CARG3, KBASE, RC + | lw TAB:RB, LO(CARG2) + | lw STR:RC, -4(CARG3) // KBASE-4-str_const*4 + | bne TMP0, AT, ->vmeta_tsets1 + |. addu RA, BASE, RA + |->BC_TSETS_Z: + | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = BASE+src*8 + | lw TMP0, TAB:RB->hmask + | lw TMP1, STR:RC->hash + | lw NODE:TMP2, TAB:RB->node + | sb r0, TAB:RB->nomm // Clear metamethod cache. + | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask + | sll TMP0, TMP1, 5 + | sll TMP1, TMP1, 3 + | subu TMP1, TMP0, TMP1 + | addu NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) + | ldc1 f20, 0(RA) + |1: + | lw CARG1, offsetof(Node, key)+HI(NODE:TMP2) + | lw TMP0, offsetof(Node, key)+LO(NODE:TMP2) + | li AT, LJ_TSTR + | lw NODE:TMP1, NODE:TMP2->next + | bne CARG1, AT, >5 + |. lw CARG2, offsetof(Node, val)+HI(NODE:TMP2) + | bne TMP0, STR:RC, >5 + |. lbu TMP3, TAB:RB->marked + | beq CARG2, TISNIL, >4 // Key found, but nil value? + |. lw TAB:TMP0, TAB:RB->metatable + |2: + | andi AT, TMP3, LJ_GC_BLACK // isblack(table) + | bnez AT, >7 + |. sdc1 f20, NODE:TMP2->val + |3: + | ins_next + | + |4: // Check for __newindex if previous value is nil. + | beqz TAB:TMP0, <2 // No metatable: done. + |. nop + | lbu TMP0, TAB:TMP0->nomm + | andi TMP0, TMP0, 1<vmeta_tsets + |. nop + | + |5: // Follow hash chain. + | bnez NODE:TMP1, <1 + |. move NODE:TMP2, NODE:TMP1 + | // End of hash chain: key not found, add a new one + | + | // But check for __newindex first. + | lw TAB:TMP2, TAB:RB->metatable + | beqz TAB:TMP2, >6 // No metatable: continue. + |. addiu CARG3, DISPATCH, DISPATCH_GL(tmptv) + | lbu TMP0, TAB:TMP2->nomm + | andi TMP0, TMP0, 1<vmeta_tsets // 'no __newindex' flag NOT set: check. + |. li AT, LJ_TSTR + |6: + | load_got lj_tab_newkey + | sw STR:RC, LO(CARG3) + | sw AT, HI(CARG3) + | sw BASE, L->base + | move CARG2, TAB:RB + | sw PC, SAVE_PC + | call_intern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k + |. move CARG1, L + | // Returns TValue *. + | lw BASE, L->base + | b <3 // No 2nd write barrier needed. + |. sdc1 f20, 0(CRET1) + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, TMP3, TMP0, <3 + break; + case BC_TSETB: + | // RA = src*8, RB = table*8, RC = index*8 + | decode_RB8a RB, INS + | decode_RB8b RB + | addu CARG2, BASE, RB + | decode_RDtoRC8 RC, RD + | lw CARG1, HI(CARG2) + | li AT, LJ_TTAB + | lw TAB:RB, LO(CARG2) + | addu RA, BASE, RA + | bne CARG1, AT, ->vmeta_tsetb + |. srl TMP0, RC, 3 + | lw TMP1, TAB:RB->asize + | lw TMP2, TAB:RB->array + | sltu AT, TMP0, TMP1 + | beqz AT, ->vmeta_tsetb + |. addu RC, TMP2, RC + | lw TMP1, HI(RC) + | lbu TMP3, TAB:RB->marked + | beq TMP1, TISNIL, >5 + |. ldc1 f0, 0(RA) + |1: + | andi AT, TMP3, LJ_GC_BLACK // isblack(table) + | bnez AT, >7 + |. sdc1 f0, 0(RC) + |2: + | ins_next + | + |5: // Check for __newindex if previous value is nil. + | lw TAB:TMP2, TAB:RB->metatable + | beqz TAB:TMP2, <1 // No metatable: done. + |. nop + | lbu TMP1, TAB:TMP2->nomm + | andi TMP1, TMP1, 1<vmeta_tsetb // Caveat: preserve TMP0! + |. nop + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, TMP3, TMP0, <2 + break; + + case BC_TSETM: + | // RA = base*8 (table at base-1), RD = num_const*8 (start index) + | addu RA, BASE, RA + |1: + | addu TMP3, KBASE, RD + | lw TAB:CARG2, -8+LO(RA) // Guaranteed to be a table. + | addiu TMP0, MULTRES, -8 + | lw TMP3, LO(TMP3) // Integer constant is in lo-word. + | beqz TMP0, >4 // Nothing to copy? + |. srl CARG3, TMP0, 3 + | addu CARG3, CARG3, TMP3 + | lw TMP2, TAB:CARG2->asize + | sll TMP1, TMP3, 3 + | lbu TMP3, TAB:CARG2->marked + | lw CARG1, TAB:CARG2->array + | sltu AT, TMP2, CARG3 + | bnez AT, >5 + |. addu TMP2, RA, TMP0 + | addu TMP1, TMP1, CARG1 + | andi TMP0, TMP3, LJ_GC_BLACK // isblack(table) + |3: // Copy result slots to table. + | ldc1 f0, 0(RA) + | addiu RA, RA, 8 + | sltu AT, RA, TMP2 + | sdc1 f0, 0(TMP1) + | bnez AT, <3 + |. addiu TMP1, TMP1, 8 + | bnez TMP0, >7 + |. nop + |4: + | ins_next + | + |5: // Need to resize array part. + | load_got lj_tab_reasize + | sw BASE, L->base + | sw PC, SAVE_PC + | move BASE, RD + | call_intern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize) + |. move CARG1, L + | // Must not reallocate the stack. + | move RD, BASE + | b <1 + |. lw BASE, L->base // Reload BASE for lack of a saved register. + | + |7: // Possible table write barrier for any value. Skip valiswhite check. + | barrierback TAB:CARG2, TMP3, TMP0, <4 + break; + + /* -- Calls and vararg handling ----------------------------------------- */ + + case BC_CALLM: + | // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8 + | decode_RDtoRC8 NARGS8:RC, RD + | b ->BC_CALL_Z + |. addu NARGS8:RC, NARGS8:RC, MULTRES + break; + case BC_CALL: + | // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8 + | decode_RDtoRC8 NARGS8:RC, RD + |->BC_CALL_Z: + | move TMP2, BASE + | addu BASE, BASE, RA + | li AT, LJ_TFUNC + | lw TMP0, HI(BASE) + | lw LFUNC:RB, LO(BASE) + | addiu BASE, BASE, 8 + | bne TMP0, AT, ->vmeta_call + |. addiu NARGS8:RC, NARGS8:RC, -8 + | ins_call + break; + + case BC_CALLMT: + | // RA = base*8, (RB = 0,) RC = extra_nargs*8 + | addu NARGS8:RD, NARGS8:RD, MULTRES // BC_CALLT gets RC from RD. + | // Fall through. Assumes BC_CALLT follows. + break; + case BC_CALLT: + | // RA = base*8, (RB = 0,) RC = (nargs+1)*8 + | addu RA, BASE, RA + | li AT, LJ_TFUNC + | lw TMP0, HI(RA) + | lw LFUNC:RB, LO(RA) + | move NARGS8:RC, RD + | lw TMP1, FRAME_PC(BASE) + | addiu RA, RA, 8 + | bne TMP0, AT, ->vmeta_callt + |. addiu NARGS8:RC, NARGS8:RC, -8 + |->BC_CALLT_Z: + | andi TMP0, TMP1, FRAME_TYPE // Caveat: preserve TMP0 until the 'or'. + | lbu TMP3, LFUNC:RB->ffid + | bnez TMP0, >7 + |. xori TMP2, TMP1, FRAME_VARG + |1: + | sw LFUNC:RB, FRAME_FUNC(BASE) // Copy function down, but keep PC. + | sltiu AT, TMP3, 2 // (> FF_C) Calling a fast function? + | move TMP2, BASE + | beqz NARGS8:RC, >3 + |. move TMP3, NARGS8:RC + |2: + | ldc1 f0, 0(RA) + | addiu RA, RA, 8 + | addiu TMP3, TMP3, -8 + | sdc1 f0, 0(TMP2) + | bnez TMP3, <2 + |. addiu TMP2, TMP2, 8 + |3: + | or TMP0, TMP0, AT + | beqz TMP0, >5 + |. nop + |4: + | ins_callt + | + |5: // Tailcall to a fast function with a Lua frame below. + | lw INS, -4(TMP1) + | decode_RA8a RA, INS + | decode_RA8b RA + | subu TMP1, BASE, RA + | lw LFUNC:TMP1, -8+FRAME_FUNC(TMP1) + | lw TMP1, LFUNC:TMP1->pc + | b <4 + |. lw KBASE, PC2PROTO(k)(TMP1) // Need to prepare KBASE. + | + |7: // Tailcall from a vararg function. + | andi AT, TMP2, FRAME_TYPEP + | bnez AT, <1 // Vararg frame below? + |. subu TMP2, BASE, TMP2 // Relocate BASE down. + | move BASE, TMP2 + | lw TMP1, FRAME_PC(TMP2) + | b <1 + |. andi TMP0, TMP1, FRAME_TYPE + break; + + case BC_ITERC: + | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8)) + | move TMP2, BASE + | addu BASE, BASE, RA + | li AT, LJ_TFUNC + | lw TMP1, -24+HI(BASE) + | lw LFUNC:RB, -24+LO(BASE) + | ldc1 f2, -8(BASE) + | ldc1 f0, -16(BASE) + | sw TMP1, HI(BASE) // Copy callable. + | sw LFUNC:RB, LO(BASE) + | sdc1 f2, 16(BASE) // Copy control var. + | sdc1 f0, 8(BASE) // Copy state. + | addiu BASE, BASE, 8 + | bne TMP1, AT, ->vmeta_call + |. li NARGS8:RC, 16 // Iterators get 2 arguments. + | ins_call + break; + + case BC_ITERN: + | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) +#if LJ_HASJIT + | // NYI: add hotloop, record BC_ITERN. +#endif + | addu RA, BASE, RA + | lw TAB:RB, -16+LO(RA) + | lw RC, -8+LO(RA) // Get index from control var. + | lw TMP0, TAB:RB->asize + | lw TMP1, TAB:RB->array + | addiu PC, PC, 4 + |1: // Traverse array part. + | sltu AT, RC, TMP0 + | beqz AT, >5 // Index points after array part? + |. sll TMP3, RC, 3 + | addu TMP3, TMP1, TMP3 + | lw TMP2, HI(TMP3) + | ldc1 f0, 0(TMP3) + | mtc1 RC, f2 + | lhu RD, -4+OFS_RD(PC) + | beq TMP2, TISNIL, <1 // Skip holes in array part. + |. addiu RC, RC, 1 + | cvt.d.w f2, f2 + | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) + | sdc1 f0, 8(RA) + | decode_RD4b RD + | addu RD, RD, TMP3 + | sw RC, -8+LO(RA) // Update control var. + | addu PC, PC, RD + | sdc1 f2, 0(RA) + |3: + | ins_next + | + |5: // Traverse hash part. + | lw TMP1, TAB:RB->hmask + | subu RC, RC, TMP0 + | lw TMP2, TAB:RB->node + |6: + | sltu AT, TMP1, RC // End of iteration? Branch to ITERL+1. + | bnez AT, <3 + |. sll TMP3, RC, 5 + | sll RB, RC, 3 + | subu TMP3, TMP3, RB + | addu NODE:TMP3, TMP3, TMP2 + | lw RB, HI(NODE:TMP3) + | ldc1 f0, 0(NODE:TMP3) + | lhu RD, -4+OFS_RD(PC) + | beq RB, TISNIL, <6 // Skip holes in hash part. + |. addiu RC, RC, 1 + | ldc1 f2, NODE:TMP3->key + | lui TMP3, (-(BCBIAS_J*4 >> 16) & 65535) + | sdc1 f0, 8(RA) + | addu RC, RC, TMP0 + | decode_RD4b RD + | addu RD, RD, TMP3 + | sdc1 f2, 0(RA) + | addu PC, PC, RD + | b <3 + |. sw RC, -8+LO(RA) // Update control var. + break; + + case BC_ISNEXT: + | // RA = base*8, RD = target (points to ITERN) + | addu RA, BASE, RA + | lw TMP0, -24+HI(RA) + | lw CFUNC:TMP1, -24+LO(RA) + | lw TMP2, -16+HI(RA) + | lw TMP3, -8+HI(RA) + | li AT, LJ_TFUNC + | bne TMP0, AT, >5 + |. addiu TMP2, TMP2, -LJ_TTAB + | lbu TMP1, CFUNC:TMP1->ffid + | addiu TMP3, TMP3, -LJ_TNIL + | srl TMP0, RD, 1 + | or TMP2, TMP2, TMP3 + | addiu TMP1, TMP1, -FF_next_N + | addu TMP0, PC, TMP0 + | or TMP1, TMP1, TMP2 + | bnez TMP1, >5 + |. lui TMP2, (-(BCBIAS_J*4 >> 16) & 65535) + | addu PC, TMP0, TMP2 + | sw r0, -8+LO(RA) // Initialize control var. + |1: + | ins_next + |5: // Despecialize bytecode if any of the checks fail. + | li TMP3, BC_JMP + | li TMP1, BC_ITERC + | sb TMP3, -4+OFS_OP(PC) + | addu PC, TMP0, TMP2 + | b <1 + |. sb TMP1, OFS_OP(PC) + break; + + case BC_VARG: + | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8 + | lw TMP0, FRAME_PC(BASE) + | decode_RDtoRC8 RC, RD + | decode_RB8a RB, INS + | addu RC, BASE, RC + | decode_RB8b RB + | addu RA, BASE, RA + | addiu RC, RC, FRAME_VARG + | addu TMP2, RA, RB + | addiu TMP3, BASE, -8 // TMP3 = vtop + | subu RC, RC, TMP0 // RC = vbase + | // Note: RC may now be even _above_ BASE if nargs was < numparams. + | beqz RB, >5 // Copy all varargs? + |. subu TMP1, TMP3, RC + | addiu TMP2, TMP2, -16 + |1: // Copy vararg slots to destination slots. + | lw CARG1, HI(RC) + | sltu AT, RC, TMP3 + | lw CARG2, LO(RC) + | addiu RC, RC, 8 + | movz CARG1, TISNIL, AT + | sw CARG1, HI(RA) + | sw CARG2, LO(RA) + | sltu AT, RA, TMP2 + | bnez AT, <1 + |. addiu RA, RA, 8 + |3: + | ins_next + | + |5: // Copy all varargs. + | lw TMP0, L->maxstack + | blez TMP1, <3 // No vararg slots? + |. li MULTRES, 8 // MULTRES = (0+1)*8 + | addu TMP2, RA, TMP1 + | sltu AT, TMP0, TMP2 + | bnez AT, >7 + |. addiu MULTRES, TMP1, 8 + |6: + | ldc1 f0, 0(RC) + | addiu RC, RC, 8 + | sdc1 f0, 0(RA) + | sltu AT, RC, TMP3 + | bnez AT, <6 // More vararg slots? + |. addiu RA, RA, 8 + | b <3 + |. nop + | + |7: // Grow stack for varargs. + | load_got lj_state_growstack + | sw RA, L->top + | subu RA, RA, BASE + | sw BASE, L->base + | subu BASE, RC, BASE // Need delta, because BASE may change. + | sw PC, SAVE_PC + | srl CARG2, TMP1, 3 + | call_intern lj_state_growstack // (lua_State *L, int n) + |. move CARG1, L + | move RC, BASE + | lw BASE, L->base + | addu RA, BASE, RA + | addu RC, BASE, RC + | b <6 + |. addiu TMP3, BASE, -8 + break; + + /* -- Returns ----------------------------------------------------------- */ + + case BC_RETM: + | // RA = results*8, RD = extra_nresults*8 + | addu RD, RD, MULTRES // MULTRES >= 8, so RD >= 8. + | // Fall through. Assumes BC_RET follows. + break; + + case BC_RET: + | // RA = results*8, RD = (nresults+1)*8 + | lw PC, FRAME_PC(BASE) + | addu RA, BASE, RA + | move MULTRES, RD + |1: + | andi TMP0, PC, FRAME_TYPE + | bnez TMP0, ->BC_RETV_Z + |. xori TMP1, PC, FRAME_VARG + | + |->BC_RET_Z: + | // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return + | lw INS, -4(PC) + | addiu TMP2, BASE, -8 + | addiu RC, RD, -8 + | decode_RA8a TMP0, INS + | decode_RB8a RB, INS + | decode_RA8b TMP0 + | decode_RB8b RB + | addu TMP3, TMP2, RB + | beqz RC, >3 + |. subu BASE, TMP2, TMP0 + |2: + | ldc1 f0, 0(RA) + | addiu RA, RA, 8 + | addiu RC, RC, -8 + | sdc1 f0, 0(TMP2) + | bnez RC, <2 + |. addiu TMP2, TMP2, 8 + |3: + | addiu TMP3, TMP3, -8 + |5: + | sltu AT, TMP2, TMP3 + | bnez AT, >6 + |. lw LFUNC:TMP1, FRAME_FUNC(BASE) + | ins_next1 + | lw TMP1, LFUNC:TMP1->pc + | lw KBASE, PC2PROTO(k)(TMP1) + | ins_next2 + | + |6: // Fill up results with nil. + | sw TISNIL, HI(TMP2) + | b <5 + |. addiu TMP2, TMP2, 8 + | + |->BC_RETV_Z: // Non-standard return case. + | andi TMP2, TMP1, FRAME_TYPEP + | bnez TMP2, ->vm_return + |. nop + | // Return from vararg function: relocate BASE down. + | subu BASE, BASE, TMP1 + | b <1 + |. lw PC, FRAME_PC(BASE) + break; + + case BC_RET0: case BC_RET1: + | // RA = results*8, RD = (nresults+1)*8 + | lw PC, FRAME_PC(BASE) + | addu RA, BASE, RA + | move MULTRES, RD + | andi TMP0, PC, FRAME_TYPE + | bnez TMP0, ->BC_RETV_Z + |. xori TMP1, PC, FRAME_VARG + | + | lw INS, -4(PC) + | addiu TMP2, BASE, -8 + if (op == BC_RET1) { + | ldc1 f0, 0(RA) + } + | decode_RB8a RB, INS + | decode_RA8a RA, INS + | decode_RB8b RB + | decode_RA8b RA + if (op == BC_RET1) { + | sdc1 f0, 0(TMP2) + } + | subu BASE, TMP2, RA + |5: + | sltu AT, RD, RB + | bnez AT, >6 + |. lw LFUNC:TMP1, FRAME_FUNC(BASE) + | ins_next1 + | lw TMP1, LFUNC:TMP1->pc + | lw KBASE, PC2PROTO(k)(TMP1) + | ins_next2 + | + |6: // Fill up results with nil. + | addiu TMP2, TMP2, 8 + | addiu RD, RD, 8 + | b <5 + if (op == BC_RET1) { + |. sw TISNIL, HI(TMP2) + } else { + |. sw TISNIL, -8+HI(TMP2) + } + break; + + /* -- Loops and branches ------------------------------------------------ */ + + case BC_FORL: +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_IFORL follows. + break; + + case BC_JFORI: + case BC_JFORL: +#if !LJ_HASJIT + break; +#endif + case BC_FORI: + case BC_IFORL: + | // RA = base*8, RD = target (after end of loop or start of loop) + vk = (op == BC_IFORL || op == BC_JFORL); + | addu RA, BASE, RA + if (vk) { + | ldc1 f0, FORL_IDX*8(RA) + | ldc1 f4, FORL_STEP*8(RA) + | ldc1 f2, FORL_STOP*8(RA) + | lw TMP3, FORL_STEP*8+HI(RA) + | add.d f0, f0, f4 + | sdc1 f0, FORL_IDX*8(RA) + } else { + | lw TMP1, FORL_IDX*8+HI(RA) + | lw TMP3, FORL_STEP*8+HI(RA) + | lw TMP2, FORL_STOP*8+HI(RA) + | sltiu TMP1, TMP1, LJ_TISNUM + | sltiu TMP0, TMP3, LJ_TISNUM + | sltiu TMP2, TMP2, LJ_TISNUM + | and TMP1, TMP1, TMP0 + | and TMP1, TMP1, TMP2 + | ldc1 f0, FORL_IDX*8(RA) + | beqz TMP1, ->vmeta_for + |. ldc1 f2, FORL_STOP*8(RA) + } + if (op != BC_JFORL) { + | srl RD, RD, 1 + | lui TMP0, (-(BCBIAS_J*4 >> 16) & 65535) + } + | c.le.d 0, f0, f2 + | c.le.d 1, f2, f0 + | sdc1 f0, FORL_EXT*8(RA) + if (op == BC_JFORI) { + | li TMP1, 1 + | li TMP2, 1 + | addu TMP0, RD, TMP0 + | slt TMP3, TMP3, r0 + | movf TMP1, r0, 0 + | addu PC, PC, TMP0 + | movf TMP2, r0, 1 + | lhu RD, -4+OFS_RD(PC) + | movn TMP1, TMP2, TMP3 + | bnez TMP1, =>BC_JLOOP + |. decode_RD8b RD + } else if (op == BC_JFORL) { + | li TMP1, 1 + | li TMP2, 1 + | slt TMP3, TMP3, r0 + | movf TMP1, r0, 0 + | movf TMP2, r0, 1 + | movn TMP1, TMP2, TMP3 + | bnez TMP1, =>BC_JLOOP + |. nop + } else { + | addu TMP1, RD, TMP0 + | slt TMP3, TMP3, r0 + | move TMP2, TMP1 + if (op == BC_FORI) { + | movt TMP1, r0, 0 + | movt TMP2, r0, 1 + } else { + | movf TMP1, r0, 0 + | movf TMP2, r0, 1 + } + | movn TMP1, TMP2, TMP3 + | addu PC, PC, TMP1 + } + | ins_next + break; + + case BC_ITERL: +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_IITERL follows. + break; + + case BC_JITERL: +#if !LJ_HASJIT + break; +#endif + case BC_IITERL: + | // RA = base*8, RD = target + | addu RA, BASE, RA + | lw TMP1, HI(RA) + | beq TMP1, TISNIL, >1 // Stop if iterator returned nil. + |. lw TMP2, LO(RA) + if (op == BC_JITERL) { + | sw TMP1, -8+HI(RA) + | b =>BC_JLOOP + |. sw TMP2, -8+LO(RA) + } else { + | branch_RD // Otherwise save control var + branch. + | sw TMP1, -8+HI(RA) + | sw TMP2, -8+LO(RA) + } + |1: + | ins_next + break; + + case BC_LOOP: + | // RA = base*8, RD = target (loop extent) + | // Note: RA/RD is only used by trace recorder to determine scope/extent + | // This opcode does NOT jump, it's only purpose is to detect a hot loop. +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_ILOOP follows. + break; + + case BC_ILOOP: + | // RA = base*8, RD = target (loop extent) + | ins_next + break; + + case BC_JLOOP: +#if LJ_HASJIT + | // RA = base*8 (ignored), RD = traceno*8 + | lw TMP1, DISPATCH_J(trace)(DISPATCH) + | srl RD, RD, 1 + | li AT, 0 + | addu TMP1, TMP1, RD + | // Traces on MIPS don't store the trace number, so use 0. + | sw AT, DISPATCH_GL(vmstate)(DISPATCH) + | lw TRACE:TMP2, 0(TMP1) + | sw BASE, DISPATCH_GL(jit_base)(DISPATCH) + | sw L, DISPATCH_GL(jit_L)(DISPATCH) + | lw TMP2, TRACE:TMP2->mcode + | jr TMP2 + |. addiu JGL, DISPATCH, GG_DISP2G+32768 +#endif + break; + + case BC_JMP: + | // RA = base*8 (only used by trace recorder), RD = target + | branch_RD + | ins_next + break; + + /* -- Function headers -------------------------------------------------- */ + + case BC_FUNCF: +#if LJ_HASJIT + | hotcall +#endif + case BC_FUNCV: /* NYI: compiled vararg functions. */ + | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow. + break; + + case BC_JFUNCF: +#if !LJ_HASJIT + break; +#endif + case BC_IFUNCF: + | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 + | lw TMP2, L->maxstack + | lbu TMP1, -4+PC2PROTO(numparams)(PC) + | lw KBASE, -4+PC2PROTO(k)(PC) + | sltu AT, TMP2, RA + | bnez AT, ->vm_growstack_l + |. sll TMP1, TMP1, 3 + if (op != BC_JFUNCF) { + | ins_next1 + } + |2: + | sltu AT, NARGS8:RC, TMP1 // Check for missing parameters. + | bnez AT, >3 + |. addu AT, BASE, NARGS8:RC + if (op == BC_JFUNCF) { + | decode_RD8a RD, INS + | b =>BC_JLOOP + |. decode_RD8b RD + } else { + | ins_next2 + } + | + |3: // Clear missing parameters. + | sw TISNIL, HI(AT) + | b <2 + |. addiu NARGS8:RC, NARGS8:RC, 8 + break; + + case BC_JFUNCV: +#if !LJ_HASJIT + break; +#endif + | NYI // NYI: compiled vararg functions + break; /* NYI: compiled vararg functions. */ + + case BC_IFUNCV: + | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 + | addu TMP1, BASE, RC + | lw TMP2, L->maxstack + | addu TMP0, RA, RC + | sw LFUNC:RB, LO(TMP1) // Store copy of LFUNC. + | addiu TMP3, RC, 8+FRAME_VARG + | sltu AT, TMP0, TMP2 + | lw KBASE, -4+PC2PROTO(k)(PC) + | beqz AT, ->vm_growstack_l + |. sw TMP3, HI(TMP1) // Store delta + FRAME_VARG. + | lbu TMP2, -4+PC2PROTO(numparams)(PC) + | move RA, BASE + | move RC, TMP1 + | ins_next1 + | beqz TMP2, >3 + |. addiu BASE, TMP1, 8 + |1: + | lw TMP0, HI(RA) + | lw TMP3, LO(RA) + | sltu AT, RA, RC // Less args than parameters? + | move CARG1, TMP0 + | movz TMP0, TISNIL, AT // Clear missing parameters. + | movn CARG1, TISNIL, AT // Clear old fixarg slot (help the GC). + | sw TMP3, 8+LO(TMP1) + | addiu TMP2, TMP2, -1 + | sw TMP0, 8+HI(TMP1) + | addiu TMP1, TMP1, 8 + | sw CARG1, HI(RA) + | bnez TMP2, <1 + |. addiu RA, RA, 8 + |3: + | ins_next2 + break; + + case BC_FUNCC: + case BC_FUNCCW: + | // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8 + if (op == BC_FUNCC) { + | lw CFUNCADDR, CFUNC:RB->f + } else { + | lw CFUNCADDR, DISPATCH_GL(wrapf)(DISPATCH) + } + | addu TMP1, RA, NARGS8:RC + | lw TMP2, L->maxstack + | addu RC, BASE, NARGS8:RC + | sw BASE, L->base + | sltu AT, TMP2, TMP1 + | sw RC, L->top + | li_vmstate C + if (op == BC_FUNCCW) { + | lw CARG2, CFUNC:RB->f + } + | bnez AT, ->vm_growstack_c // Need to grow stack. + |. move CARG1, L + | jalr CFUNCADDR // (lua_State *L [, lua_CFunction f]) + |. st_vmstate + | // Returns nresults. + | lw BASE, L->base + | sll RD, CRET1, 3 + | lw TMP1, L->top + | li_vmstate INTERP + | lw PC, FRAME_PC(BASE) // Fetch PC of caller. + | subu RA, TMP1, RD // RA = L->top - nresults*8 + | b ->vm_returnc + |. st_vmstate + break; + + /* ---------------------------------------------------------------------- */ + + default: + fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); + exit(2); + break; + } +} + +static int build_backend(BuildCtx *ctx) +{ + int op; + + dasm_growpc(Dst, BC__MAX); + + build_subroutines(ctx); + + |.code_op + for (op = 0; op < BC__MAX; op++) + build_ins(ctx, (BCOp)op, op); + + return BC__MAX; +} + +/* Emit pseudo frame-info for all assembler functions. */ +static void emit_asm_debug(BuildCtx *ctx) +{ + int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); + int i; + switch (ctx->mode) { + case BUILD_elfasm: + fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); + fprintf(ctx->fp, + ".Lframe0:\n" + "\t.4byte .LECIE0-.LSCIE0\n" + ".LSCIE0:\n" + "\t.4byte 0xffffffff\n" + "\t.byte 0x1\n" + "\t.string \"\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -4\n" + "\t.byte 31\n" + "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n" + "\t.align 2\n" + ".LECIE0:\n\n"); + fprintf(ctx->fp, + ".LSFDE0:\n" + "\t.4byte .LEFDE0-.LASFDE0\n" + ".LASFDE0:\n" + "\t.4byte .Lframe0\n" + "\t.4byte .Lbegin\n" + "\t.4byte %d\n" + "\t.byte 0xe\n\t.uleb128 %d\n" + "\t.byte 0x9f\n\t.sleb128 1\n" + "\t.byte 0x9e\n\t.sleb128 2\n", + fcofs, CFRAME_SIZE); + for (i = 23; i >= 16; i--) + fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 26-i); + for (i = 30; i >= 20; i -= 2) + fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+32+i, 42-i); + fprintf(ctx->fp, + "\t.align 2\n" + ".LEFDE0:\n\n"); +#if LJ_HASFFI + fprintf(ctx->fp, + ".LSFDE1:\n" + "\t.4byte .LEFDE1-.LASFDE1\n" + ".LASFDE1:\n" + "\t.4byte .Lframe0\n" + "\t.4byte lj_vm_ffi_call\n" + "\t.4byte %d\n" + "\t.byte 0x9f\n\t.uleb128 1\n" + "\t.byte 0x90\n\t.uleb128 2\n" + "\t.byte 0xd\n\t.uleb128 0x10\n" + "\t.align 2\n" + ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); +#endif + fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n"); + fprintf(ctx->fp, + "\t.globl lj_err_unwind_dwarf\n" + ".Lframe1:\n" + "\t.4byte .LECIE1-.LSCIE1\n" + ".LSCIE1:\n" + "\t.4byte 0\n" + "\t.byte 0x1\n" + "\t.string \"zPR\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -4\n" + "\t.byte 31\n" + "\t.uleb128 6\n" /* augmentation length */ + "\t.byte 0\n" + "\t.4byte lj_err_unwind_dwarf\n" + "\t.byte 0\n" + "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n" + "\t.align 2\n" + ".LECIE1:\n\n"); + fprintf(ctx->fp, + ".LSFDE2:\n" + "\t.4byte .LEFDE2-.LASFDE2\n" + ".LASFDE2:\n" + "\t.4byte .LASFDE2-.Lframe1\n" + "\t.4byte .Lbegin\n" + "\t.4byte %d\n" + "\t.uleb128 0\n" /* augmentation length */ + "\t.byte 0xe\n\t.uleb128 %d\n" + "\t.byte 0x9f\n\t.sleb128 1\n" + "\t.byte 0x9e\n\t.sleb128 2\n", + fcofs, CFRAME_SIZE); + for (i = 23; i >= 16; i--) + fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+i, 26-i); + for (i = 30; i >= 20; i -= 2) + fprintf(ctx->fp, "\t.byte %d\n\t.uleb128 %d\n", 0x80+32+i, 42-i); + fprintf(ctx->fp, + "\t.align 2\n" + ".LEFDE2:\n\n"); +#if LJ_HASFFI + fprintf(ctx->fp, + ".Lframe2:\n" + "\t.4byte .LECIE2-.LSCIE2\n" + ".LSCIE2:\n" + "\t.4byte 0\n" + "\t.byte 0x1\n" + "\t.string \"zR\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -4\n" + "\t.byte 31\n" + "\t.uleb128 1\n" /* augmentation length */ + "\t.byte 0\n" + "\t.byte 0xc\n\t.uleb128 29\n\t.uleb128 0\n" + "\t.align 2\n" + ".LECIE2:\n\n"); + fprintf(ctx->fp, + ".LSFDE3:\n" + "\t.4byte .LEFDE3-.LASFDE3\n" + ".LASFDE3:\n" + "\t.4byte .LASFDE3-.Lframe2\n" + "\t.4byte lj_vm_ffi_call\n" + "\t.4byte %d\n" + "\t.uleb128 0\n" /* augmentation length */ + "\t.byte 0x9f\n\t.uleb128 1\n" + "\t.byte 0x90\n\t.uleb128 2\n" + "\t.byte 0xd\n\t.uleb128 0x10\n" + "\t.align 2\n" + ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); +#endif + break; + default: + break; + } +} + diff --git a/src/vm_ppc.dasc b/src/vm_ppc.dasc new file mode 100644 index 00000000..49f92d0a --- /dev/null +++ b/src/vm_ppc.dasc @@ -0,0 +1,4888 @@ +|// Low-level VM code for PowerPC CPUs. +|// Bytecode interpreter, fast functions and helper functions. +|// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +| +|.arch ppc +|.section code_op, code_sub +| +|.actionlist build_actionlist +|.globals GLOB_ +|.globalnames globnames +|.externnames extnames +| +|// Note: The ragged indentation of the instructions is intentional. +|// The starting columns indicate data dependencies. +| +|//----------------------------------------------------------------------- +| +|// Fixed register assignments for the interpreter. +|// Don't use: r1 = sp, r2 and r13 = reserved (TOC, TLS or SDATA) +| +|// The following must be C callee-save (but BASE is often refetched). +|.define BASE, r14 // Base of current Lua stack frame. +|.define KBASE, r15 // Constants of current Lua function. +|.define PC, r16 // Next PC. +|.define DISPATCH, r17 // Opcode dispatch table. +|.define LREG, r18 // Register holding lua_State (also in SAVE_L). +|.define MULTRES, r19 // Size of multi-result: (nresults+1)*8. +|.define JGL, r31 // On-trace: global_State + 32768. +| +|// Constants for type-comparisons, stores and conversions. C callee-save. +|.define TISNUM, r22 +|.define TISNIL, r23 +|.define ZERO, r24 +|.define TOBIT, f30 // 2^52 + 2^51. +|.define TONUM, f31 // 2^52 + 2^51 + 2^31. +| +|// The following temporaries are not saved across C calls, except for RA. +|.define RA, r20 // Callee-save. +|.define RB, r10 +|.define RC, r11 +|.define RD, r12 +|.define INS, r7 // Overlaps CARG5. +| +|.define TMP0, r0 +|.define TMP1, r8 +|.define TMP2, r9 +|.define TMP3, r6 // Overlaps CARG4. +| +|// Saved temporaries. +|.define SAVE0, r21 +| +|// Calling conventions. +|.define CARG1, r3 +|.define CARG2, r4 +|.define CARG3, r5 +|.define CARG4, r6 // Overlaps TMP3. +|.define CARG5, r7 // Overlaps INS. +| +|.define FARG1, f1 +|.define FARG2, f2 +| +|.define CRET1, r3 +|.define CRET2, r4 +| +|// Stack layout while in interpreter. Must match with lj_frame.h. +|.define SAVE_LR, 276(sp) +|.define CFRAME_SPACE, 272 // Delta for sp. +|// Back chain for sp: 272(sp) <-- sp entering interpreter +|.define SAVE_FPR_, 128 // .. 128+18*8: 64 bit FPR saves. +|.define SAVE_GPR_, 56 // .. 56+18*4: 32 bit GPR saves. +|.define SAVE_CR, 52(sp) // 32 bit CR save. +|.define SAVE_ERRF, 48(sp) // 32 bit C frame info. +|.define SAVE_NRES, 44(sp) +|.define SAVE_CFRAME, 40(sp) +|.define SAVE_L, 36(sp) +|.define SAVE_PC, 32(sp) +|.define SAVE_MULTRES, 28(sp) +|.define UNUSED1, 24(sp) +|.define TMPD_LO, 20(sp) +|.define TMPD_HI, 16(sp) +|.define TONUM_LO, 12(sp) +|.define TONUM_HI, 8(sp) +|// Next frame lr: 4(sp) +|// Back chain for sp: 0(sp) <-- sp while in interpreter +| +|.define TMPD_BLO, 23(sp) +|.define TMPD, TMPD_HI +|.define TONUM_D, TONUM_HI +| +|.macro save_, reg +| stw r..reg, SAVE_GPR_+(reg-14)*4(sp) +| stfd f..reg, SAVE_FPR_+(reg-14)*8(sp) +|.endmacro +|.macro rest_, reg +| lwz r..reg, SAVE_GPR_+(reg-14)*4(sp) +| lfd f..reg, SAVE_FPR_+(reg-14)*8(sp) +|.endmacro +| +|.macro saveregs +| stwu sp, -CFRAME_SPACE(sp) +| save_ 14; save_ 15; save_ 16 +| mflr r0 +| save_ 17; save_ 18; save_ 19; save_ 20; save_ 21; save_ 22 +| stw r0, SAVE_LR +| save_ 23; save_ 24; save_ 25 +| mfcr r0 +| save_ 26; save_ 27; save_ 28; save_ 29; save_ 30; save_ 31 +| stw r0, SAVE_CR +|.endmacro +| +|.macro restoreregs +| lwz r0, SAVE_LR; lwz r12, SAVE_CR +| rest_ 14; rest_ 15; rest_ 16; rest_ 17; rest_ 18; rest_ 19 +| mtlr r0; mtcrf 0x38, r12 +| rest_ 20; rest_ 21; rest_ 22; rest_ 23; rest_ 24; rest_ 25 +| rest_ 26; rest_ 27; rest_ 28; rest_ 29; rest_ 30; rest_ 31 +| addi sp, sp, CFRAME_SPACE +|.endmacro +| +|// Type definitions. Some of these are only used for documentation. +|.type L, lua_State, LREG +|.type GL, global_State +|.type TVALUE, TValue +|.type GCOBJ, GCobj +|.type STR, GCstr +|.type TAB, GCtab +|.type LFUNC, GCfuncL +|.type CFUNC, GCfuncC +|.type PROTO, GCproto +|.type UPVAL, GCupval +|.type NODE, Node +|.type NARGS8, int +|.type TRACE, GCtrace +| +|//----------------------------------------------------------------------- +| +|// These basic macros should really be part of DynASM. +|.macro srwi, rx, ry, n; rlwinm rx, ry, 32-n, n, 31; .endmacro +|.macro slwi, rx, ry, n; rlwinm rx, ry, n, 0, 31-n; .endmacro +|.macro rotlwi, rx, ry, n; rlwinm rx, ry, n, 0, 31; .endmacro +|.macro rotlw, rx, ry, rn; rlwnm rx, ry, rn, 0, 31; .endmacro +|.macro subi, rx, ry, i; addi rx, ry, -i; .endmacro +| +|// Trap for not-yet-implemented parts. +|.macro NYI; tw 4, sp, sp; .endmacro +| +|// int/FP conversions. +|.macro tonum_i, freg, reg +| xoris reg, reg, 0x8000 +| stw reg, TONUM_LO +| lfd freg, TONUM_D +| fsub freg, freg, TONUM +|.endmacro +| +|.macro tonum_u, freg, reg +| stw reg, TONUM_LO +| lfd freg, TONUM_D +| fsub freg, freg, TOBIT +|.endmacro +| +|.macro toint, reg, freg, tmpfreg +| fctiwz tmpfreg, freg +| stfd tmpfreg, TMPD +| lwz reg, TMPD_LO +|.endmacro +| +|.macro toint, reg, freg +| toint reg, freg, freg +|.endmacro +| +|//----------------------------------------------------------------------- +| +|// Access to frame relative to BASE. +|.define FRAME_PC, -8 +|.define FRAME_FUNC, -4 +| +|// Instruction decode. +|.macro decode_OP4, dst, ins; rlwinm dst, ins, 2, 22, 29; .endmacro +|.macro decode_RA8, dst, ins; rlwinm dst, ins, 27, 21, 28; .endmacro +|.macro decode_RB8, dst, ins; rlwinm dst, ins, 11, 21, 28; .endmacro +|.macro decode_RC8, dst, ins; rlwinm dst, ins, 19, 21, 28; .endmacro +|.macro decode_RD8, dst, ins; rlwinm dst, ins, 19, 13, 28; .endmacro +| +|.macro decode_OP1, dst, ins; rlwinm dst, ins, 0, 24, 31; .endmacro +|.macro decode_RD4, dst, ins; rlwinm dst, ins, 18, 14, 29; .endmacro +| +|// Instruction fetch. +|.macro ins_NEXT1 +| lwz INS, 0(PC) +| addi PC, PC, 4 +|.endmacro +|// Instruction decode+dispatch. Note: optimized for e300! +|.macro ins_NEXT2 +| decode_OP4 TMP1, INS +| lwzx TMP0, DISPATCH, TMP1 +| mtctr TMP0 +| decode_RB8 RB, INS +| decode_RD8 RD, INS +| decode_RA8 RA, INS +| decode_RC8 RC, INS +| bctr +|.endmacro +|.macro ins_NEXT +| ins_NEXT1 +| ins_NEXT2 +|.endmacro +| +|// Instruction footer. +|.if 1 +| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use. +| .define ins_next, ins_NEXT +| .define ins_next_, ins_NEXT +| .define ins_next1, ins_NEXT1 +| .define ins_next2, ins_NEXT2 +|.else +| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch. +| // Affects only certain kinds of benchmarks (and only with -j off). +| .macro ins_next +| b ->ins_next +| .endmacro +| .macro ins_next1 +| .endmacro +| .macro ins_next2 +| b ->ins_next +| .endmacro +| .macro ins_next_ +| ->ins_next: +| ins_NEXT +| .endmacro +|.endif +| +|// Call decode and dispatch. +|.macro ins_callt +| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC +| lwz PC, LFUNC:RB->pc +| lwz INS, 0(PC) +| addi PC, PC, 4 +| decode_OP4 TMP1, INS +| decode_RA8 RA, INS +| lwzx TMP0, DISPATCH, TMP1 +| add RA, RA, BASE +| mtctr TMP0 +| bctr +|.endmacro +| +|.macro ins_call +| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, PC = caller PC +| stw PC, FRAME_PC(BASE) +| ins_callt +|.endmacro +| +|//----------------------------------------------------------------------- +| +|// Macros to test operand types. +|.macro checknum, reg; cmplw reg, TISNUM; .endmacro +|.macro checknum, cr, reg; cmplw cr, reg, TISNUM; .endmacro +|.macro checkstr, reg; cmpwi reg, LJ_TSTR; .endmacro +|.macro checktab, reg; cmpwi reg, LJ_TTAB; .endmacro +|.macro checkfunc, reg; cmpwi reg, LJ_TFUNC; .endmacro +|.macro checknil, reg; cmpwi reg, LJ_TNIL; .endmacro +| +|.macro branch_RD +| srwi TMP0, RD, 1 +| addis PC, PC, -(BCBIAS_J*4 >> 16) +| add PC, PC, TMP0 +|.endmacro +| +|// Assumes DISPATCH is relative to GL. +#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) +#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) +| +#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) +| +|.macro hotcheck, delta, target +| rlwinm TMP1, PC, 31, 25, 30 +| addi TMP1, TMP1, GG_DISP2HOT +| lhzx TMP2, DISPATCH, TMP1 +| addic. TMP2, TMP2, -delta +| sthx TMP2, DISPATCH, TMP1 +| blt target +|.endmacro +| +|.macro hotloop +| hotcheck HOTCOUNT_LOOP, ->vm_hotloop +|.endmacro +| +|.macro hotcall +| hotcheck HOTCOUNT_CALL, ->vm_hotcall +|.endmacro +| +|// Set current VM state. Uses TMP0. +|.macro li_vmstate, st; li TMP0, ~LJ_VMST_..st; .endmacro +|.macro st_vmstate; stw TMP0, DISPATCH_GL(vmstate)(DISPATCH); .endmacro +| +|// Move table write barrier back. Overwrites mark and tmp. +|.macro barrierback, tab, mark, tmp +| lwz tmp, DISPATCH_GL(gc.grayagain)(DISPATCH) +| // Assumes LJ_GC_BLACK is 0x04. +| rlwinm mark, mark, 0, 30, 28 // black2gray(tab) +| stw tab, DISPATCH_GL(gc.grayagain)(DISPATCH) +| stb mark, tab->marked +| stw tmp, tab->gclist +|.endmacro +| +|//----------------------------------------------------------------------- + +/* Generate subroutines used by opcodes and other parts of the VM. */ +/* The .code_sub section should be last to help static branch prediction. */ +static void build_subroutines(BuildCtx *ctx) +{ + |.code_sub + | + |//----------------------------------------------------------------------- + |//-- Return handling ---------------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_returnp: + | // See vm_return. Also: TMP2 = previous base. + | andi. TMP0, PC, FRAME_P + | li TMP1, LJ_TTRUE + | beq ->cont_dispatch + | + | // Return from pcall or xpcall fast func. + | lwz PC, FRAME_PC(TMP2) // Fetch PC of previous frame. + | mr BASE, TMP2 // Restore caller base. + | // Prepending may overwrite the pcall frame, so do it at the end. + | stwu TMP1, FRAME_PC(RA) // Prepend true to results. + | + |->vm_returnc: + | andi. TMP0, PC, FRAME_TYPE + | addi RD, RD, 8 // RD = (nresults+1)*8. + | mr MULTRES, RD + | beq ->BC_RET_Z // Handle regular return to Lua. + | + |->vm_return: + | // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return + | // TMP0 = PC & FRAME_TYPE + | cmpwi TMP0, FRAME_C + | rlwinm TMP2, PC, 0, 0, 28 + | li_vmstate C + | sub TMP2, BASE, TMP2 // TMP2 = previous base. + | bney ->vm_returnp + | + | addic. TMP1, RD, -8 + | stw TMP2, L->base + | lwz TMP2, SAVE_NRES + | subi BASE, BASE, 8 + | st_vmstate + | slwi TMP2, TMP2, 3 + | beq >2 + |1: + | addic. TMP1, TMP1, -8 + | lfd f0, 0(RA) + | addi RA, RA, 8 + | stfd f0, 0(BASE) + | addi BASE, BASE, 8 + | bney <1 + | + |2: + | cmpw TMP2, RD // More/less results wanted? + | bne >6 + |3: + | stw BASE, L->top // Store new top. + | + |->vm_leave_cp: + | lwz TMP0, SAVE_CFRAME // Restore previous C frame. + | li CRET1, 0 // Ok return status for vm_pcall. + | stw TMP0, L->cframe + | + |->vm_leave_unw: + | restoreregs + | blr + | + |6: + | ble >7 // Less results wanted? + | // More results wanted. Check stack size and fill up results with nil. + | lwz TMP1, L->maxstack + | cmplw BASE, TMP1 + | bge >8 + | stw TISNIL, 0(BASE) + | addi RD, RD, 8 + | addi BASE, BASE, 8 + | b <2 + | + |7: // Less results wanted. + | subfic TMP3, TMP2, 0 // LUA_MULTRET+1 case? + | sub TMP0, RD, TMP2 + | subfe TMP1, TMP1, TMP1 // TMP1 = TMP2 == 0 ? 0 : -1 + | and TMP0, TMP0, TMP1 + | sub BASE, BASE, TMP0 // Either keep top or shrink it. + | b <3 + | + |8: // Corner case: need to grow stack for filling up results. + | // This can happen if: + | // - A C function grows the stack (a lot). + | // - The GC shrinks the stack in between. + | // - A return back from a lua_call() with (high) nresults adjustment. + | stw BASE, L->top // Save current top held in BASE (yes). + | mr SAVE0, RD + | mr CARG2, TMP2 + | mr CARG1, L + | bl extern lj_state_growstack // (lua_State *L, int n) + | lwz TMP2, SAVE_NRES + | mr RD, SAVE0 + | slwi TMP2, TMP2, 3 + | lwz BASE, L->top // Need the (realloced) L->top in BASE. + | b <2 + | + |->vm_unwind_c: // Unwind C stack, return from vm_pcall. + | // (void *cframe, int errcode) + | mr sp, CARG1 + | mr CRET1, CARG2 + |->vm_unwind_c_eh: // Landing pad for external unwinder. + | lwz L, SAVE_L + | li TMP0, ~LJ_VMST_C + | lwz GL:TMP1, L->glref + | stw TMP0, GL:TMP1->vmstate + | b ->vm_leave_unw + | + |->vm_unwind_ff: // Unwind C stack, return from ff pcall. + | // (void *cframe) + | rlwinm sp, CARG1, 0, 0, 29 + |->vm_unwind_ff_eh: // Landing pad for external unwinder. + | lwz L, SAVE_L + | li TISNUM, LJ_TISNUM // Setup type comparison constants. + | lwz BASE, L->base + | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). + | lwz DISPATCH, L->glref // Setup pointer to dispatch table. + | li ZERO, 0 + | stw TMP3, TMPD + | li TMP1, LJ_TFALSE + | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float). + | li TISNIL, LJ_TNIL + | li_vmstate INTERP + | lfs TOBIT, TMPD + | lwz PC, FRAME_PC(BASE) // Fetch PC of previous frame. + | la RA, -8(BASE) // Results start at BASE-8. + | stw TMP3, TMPD + | addi DISPATCH, DISPATCH, GG_G2DISP + | stw TMP1, 0(RA) // Prepend false to error message. + | li RD, 16 // 2 results: false + error message. + | st_vmstate + | lfs TONUM, TMPD + | b ->vm_returnc + | + |//----------------------------------------------------------------------- + |//-- Grow stack for calls ----------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_growstack_c: // Grow stack for C function. + | li CARG2, LUA_MINSTACK + | b >2 + | + |->vm_growstack_l: // Grow stack for Lua function. + | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC + | add RC, BASE, RC + | sub RA, RA, BASE + | stw BASE, L->base + | addi PC, PC, 4 // Must point after first instruction. + | stw RC, L->top + | srwi CARG2, RA, 3 + |2: + | // L->base = new base, L->top = top + | stw PC, SAVE_PC + | mr CARG1, L + | bl extern lj_state_growstack // (lua_State *L, int n) + | lwz BASE, L->base + | lwz RC, L->top + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | sub RC, RC, BASE + | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC + | ins_callt // Just retry the call. + | + |//----------------------------------------------------------------------- + |//-- Entry points into the assembler VM --------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_resume: // Setup C frame and resume thread. + | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0) + | saveregs + | mr L, CARG1 + | lwz DISPATCH, L->glref // Setup pointer to dispatch table. + | mr BASE, CARG2 + | lbz TMP1, L->status + | stw L, SAVE_L + | li PC, FRAME_CP + | addi TMP0, sp, CFRAME_RESUME + | addi DISPATCH, DISPATCH, GG_G2DISP + | stw CARG3, SAVE_NRES + | cmplwi TMP1, 0 + | stw CARG3, SAVE_ERRF + | stw TMP0, L->cframe + | stw CARG3, SAVE_CFRAME + | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. + | beq >3 + | + | // Resume after yield (like a return). + | mr RA, BASE + | lwz BASE, L->base + | li TISNUM, LJ_TISNUM // Setup type comparison constants. + | lwz TMP1, L->top + | lwz PC, FRAME_PC(BASE) + | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). + | stb CARG3, L->status + | stw TMP3, TMPD + | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float). + | lfs TOBIT, TMPD + | sub RD, TMP1, BASE + | stw TMP3, TMPD + | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double) + | addi RD, RD, 8 + | stw TMP0, TONUM_HI + | li_vmstate INTERP + | li ZERO, 0 + | st_vmstate + | andi. TMP0, PC, FRAME_TYPE + | mr MULTRES, RD + | lfs TONUM, TMPD + | li TISNIL, LJ_TNIL + | beq ->BC_RET_Z + | b ->vm_return + | + |->vm_pcall: // Setup protected C frame and enter VM. + | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef) + | saveregs + | li PC, FRAME_CP + | stw CARG4, SAVE_ERRF + | b >1 + | + |->vm_call: // Setup C frame and enter VM. + | // (lua_State *L, TValue *base, int nres1) + | saveregs + | li PC, FRAME_C + | + |1: // Entry point for vm_pcall above (PC = ftype). + | lwz TMP1, L:CARG1->cframe + | stw CARG3, SAVE_NRES + | mr L, CARG1 + | stw CARG1, SAVE_L + | mr BASE, CARG2 + | stw sp, L->cframe // Add our C frame to cframe chain. + | lwz DISPATCH, L->glref // Setup pointer to dispatch table. + | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. + | stw TMP1, SAVE_CFRAME + | addi DISPATCH, DISPATCH, GG_G2DISP + | + |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype). + | lwz TMP2, L->base // TMP2 = old base (used in vmeta_call). + | li TISNUM, LJ_TISNUM // Setup type comparison constants. + | lwz TMP1, L->top + | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). + | add PC, PC, BASE + | stw TMP3, TMPD + | li ZERO, 0 + | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float). + | lfs TOBIT, TMPD + | sub PC, PC, TMP2 // PC = frame delta + frame type + | stw TMP3, TMPD + | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double) + | sub NARGS8:RC, TMP1, BASE + | stw TMP0, TONUM_HI + | li_vmstate INTERP + | lfs TONUM, TMPD + | li TISNIL, LJ_TNIL + | st_vmstate + | + |->vm_call_dispatch: + | // TMP2 = old base, BASE = new base, RC = nargs*8, PC = caller PC + | lwz TMP0, FRAME_PC(BASE) + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | checkfunc TMP0; bne ->vmeta_call + | + |->vm_call_dispatch_f: + | ins_call + | // BASE = new base, RB = func, RC = nargs*8, PC = caller PC + | + |->vm_cpcall: // Setup protected C frame, call C. + | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp) + | saveregs + | mr L, CARG1 + | lwz TMP0, L:CARG1->stack + | stw CARG1, SAVE_L + | lwz TMP1, L->top + | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. + | sub TMP0, TMP0, TMP1 // Compute -savestack(L, L->top). + | lwz TMP1, L->cframe + | stw sp, L->cframe // Add our C frame to cframe chain. + | li TMP2, 0 + | stw TMP0, SAVE_NRES // Neg. delta means cframe w/o frame. + | stw TMP2, SAVE_ERRF // No error function. + | stw TMP1, SAVE_CFRAME + | mtctr CARG4 + | bctrl // (lua_State *L, lua_CFunction func, void *ud) + | mr. BASE, CRET1 + | lwz DISPATCH, L->glref // Setup pointer to dispatch table. + | li PC, FRAME_CP + | addi DISPATCH, DISPATCH, GG_G2DISP + | bne <3 // Else continue with the call. + | b ->vm_leave_cp // No base? Just remove C frame. + | + |//----------------------------------------------------------------------- + |//-- Metamethod handling ------------------------------------------------ + |//----------------------------------------------------------------------- + | + |// The lj_meta_* functions (except for lj_meta_cat) don't reallocate the + |// stack, so BASE doesn't need to be reloaded across these calls. + | + |//-- Continuation dispatch ---------------------------------------------- + | + |->cont_dispatch: + | // BASE = meta base, RA = resultptr, RD = (nresults+1)*8 + | lwz TMP0, -12(BASE) // Continuation. + | mr RB, BASE + | mr BASE, TMP2 // Restore caller BASE. + | lwz LFUNC:TMP1, FRAME_FUNC(TMP2) +#if LJ_HASFFI + | cmplwi TMP0, 1 +#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 LJ_HASFFI + | ble >1 +#endif + | lwz KBASE, PC2PROTO(k)(TMP1) + | // BASE = base, RA = resultptr, RB = meta base + | mtctr TMP0 + | bctr // Jump to continuation. + | +#if LJ_HASFFI + |1: + | beq ->cont_ffi_callback // cont = 1: return from FFI callback. + | // cont = 0: tailcall from C function. + | subi TMP1, RB, 16 + | sub RC, TMP1, BASE + | b ->vm_call_tail +#endif + | + |->cont_cat: // RA = resultptr, RB = meta base + | lwz INS, -4(PC) + | subi CARG2, RB, 16 + | decode_RB8 SAVE0, INS + | lfd f0, 0(RA) + | add TMP1, BASE, SAVE0 + | stw BASE, L->base + | cmplw TMP1, CARG2 + | sub CARG3, CARG2, TMP1 + | decode_RA8 RA, INS + | stfd f0, 0(CARG2) + | bney ->BC_CAT_Z + | stfdx f0, BASE, RA + | b ->cont_nop + | + |//-- Table indexing metamethods ----------------------------------------- + | + |->vmeta_tgets1: + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | li TMP0, LJ_TSTR + | decode_RB8 RB, INS + | stw STR:RC, 4(CARG3) + | add CARG2, BASE, RB + | stw TMP0, 0(CARG3) + | b >1 + | + |->vmeta_tgets: + | la CARG2, DISPATCH_GL(tmptv)(DISPATCH) + | li TMP0, LJ_TTAB + | stw TAB:RB, 4(CARG2) + | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH) + | stw TMP0, 0(CARG2) + | li TMP1, LJ_TSTR + | stw STR:RC, 4(CARG3) + | stw TMP1, 0(CARG3) + | b >1 + | + |->vmeta_tgetb: // TMP0 = index + if (!LJ_DUALNUM) { + | tonum_u f0, TMP0 + } + | decode_RB8 RB, INS + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | add CARG2, BASE, RB + if (LJ_DUALNUM) { + | stw TISNUM, 0(CARG3) + | stw TMP0, 4(CARG3) + } else { + | stfd f0, 0(CARG3) + } + | b >1 + | + |->vmeta_tgetv: + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | add CARG2, BASE, RB + | add CARG3, BASE, RC + |1: + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | bl extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k) + | // Returns TValue * (finished) or NULL (metamethod). + | cmplwi CRET1, 0 + | beq >3 + | lfd f0, 0(CRET1) + | ins_next1 + | stfdx f0, BASE, RA + | ins_next2 + | + |3: // Call __index metamethod. + | // BASE = base, L->top = new base, stack = cont/func/t/k + | subfic TMP1, BASE, FRAME_CONT + | lwz BASE, L->top + | stw PC, -16(BASE) // [cont|PC] + | add PC, TMP1, BASE + | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. + | li NARGS8:RC, 16 // 2 args for func(t, k). + | b ->vm_call_dispatch_f + | + |//----------------------------------------------------------------------- + | + |->vmeta_tsets1: + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | li TMP0, LJ_TSTR + | decode_RB8 RB, INS + | stw STR:RC, 4(CARG3) + | add CARG2, BASE, RB + | stw TMP0, 0(CARG3) + | b >1 + | + |->vmeta_tsets: + | la CARG2, DISPATCH_GL(tmptv)(DISPATCH) + | li TMP0, LJ_TTAB + | stw TAB:RB, 4(CARG2) + | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH) + | stw TMP0, 0(CARG2) + | li TMP1, LJ_TSTR + | stw STR:RC, 4(CARG3) + | stw TMP1, 0(CARG3) + | b >1 + | + |->vmeta_tsetb: // TMP0 = index + if (!LJ_DUALNUM) { + | tonum_u f0, TMP0 + } + | decode_RB8 RB, INS + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | add CARG2, BASE, RB + if (LJ_DUALNUM) { + | stw TISNUM, 0(CARG3) + | stw TMP0, 4(CARG3) + } else { + | stfd f0, 0(CARG3) + } + | b >1 + | + |->vmeta_tsetv: + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | add CARG2, BASE, RB + | add CARG3, BASE, RC + |1: + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | bl extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k) + | // Returns TValue * (finished) or NULL (metamethod). + | cmplwi CRET1, 0 + | lfdx f0, BASE, RA + | beq >3 + | // NOBARRIER: lj_meta_tset ensures the table is not black. + | ins_next1 + | stfd f0, 0(CRET1) + | ins_next2 + | + |3: // Call __newindex metamethod. + | // BASE = base, L->top = new base, stack = cont/func/t/k/(v) + | subfic TMP1, BASE, FRAME_CONT + | lwz BASE, L->top + | stw PC, -16(BASE) // [cont|PC] + | add PC, TMP1, BASE + | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. + | li NARGS8:RC, 24 // 3 args for func(t, k, v) + | stfd f0, 16(BASE) // Copy value to third argument. + | b ->vm_call_dispatch_f + | + |//-- Comparison metamethods --------------------------------------------- + | + |->vmeta_comp: + | mr CARG1, L + | subi PC, PC, 4 + if (LJ_DUALNUM) { + | mr CARG2, RA + } else { + | add CARG2, BASE, RA + } + | stw PC, SAVE_PC + if (LJ_DUALNUM) { + | mr CARG3, RD + } else { + | add CARG3, BASE, RD + } + | stw BASE, L->base + | decode_OP1 CARG4, INS + | bl extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op) + | // Returns 0/1 or TValue * (metamethod). + |3: + | cmplwi CRET1, 1 + | bgt ->vmeta_binop + | subfic CRET1, CRET1, 0 + |4: + | lwz INS, 0(PC) + | addi PC, PC, 4 + | decode_RD4 TMP2, INS + | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) + | and TMP2, TMP2, CRET1 + | add PC, PC, TMP2 + |->cont_nop: + | ins_next + | + |->cont_ra: // RA = resultptr + | lwz INS, -4(PC) + | lfd f0, 0(RA) + | decode_RA8 TMP1, INS + | stfdx f0, BASE, TMP1 + | b ->cont_nop + | + |->cont_condt: // RA = resultptr + | lwz TMP0, 0(RA) + | subfic TMP0, TMP0, LJ_TTRUE // Branch if result is true. + | subfe CRET1, CRET1, CRET1 + | not CRET1, CRET1 + | b <4 + | + |->cont_condf: // RA = resultptr + | lwz TMP0, 0(RA) + | subfic TMP0, TMP0, LJ_TTRUE // Branch if result is false. + | subfe CRET1, CRET1, CRET1 + | b <4 + | + |->vmeta_equal: + | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV. + | subi PC, PC, 4 + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | bl extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne) + | // Returns 0/1 or TValue * (metamethod). + | b <3 + | + |->vmeta_equal_cd: +#if LJ_HASFFI + | mr CARG2, INS + | subi PC, PC, 4 + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | bl extern lj_meta_equal_cd // (lua_State *L, BCIns op) + | // Returns 0/1 or TValue * (metamethod). + | b <3 +#endif + | + |//-- Arithmetic metamethods --------------------------------------------- + | + |->vmeta_arith_nv: + | add CARG3, KBASE, RC + | add CARG4, BASE, RB + | b >1 + |->vmeta_arith_nv2: + if (LJ_DUALNUM) { + | mr CARG3, RC + | mr CARG4, RB + | b >1 + } + | + |->vmeta_unm: + | mr CARG3, RD + | mr CARG4, RD + | b >1 + | + |->vmeta_arith_vn: + | add CARG3, BASE, RB + | add CARG4, KBASE, RC + | b >1 + | + |->vmeta_arith_vv: + | add CARG3, BASE, RB + | add CARG4, BASE, RC + if (LJ_DUALNUM) { + | b >1 + } + |->vmeta_arith_vn2: + |->vmeta_arith_vv2: + if (LJ_DUALNUM) { + | mr CARG3, RB + | mr CARG4, RC + } + |1: + | add CARG2, BASE, RA + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | decode_OP1 CARG5, INS // Caveat: CARG5 overlaps INS. + | bl extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op) + | // Returns NULL (finished) or TValue * (metamethod). + | cmplwi CRET1, 0 + | beq ->cont_nop + | + | // Call metamethod for binary op. + |->vmeta_binop: + | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2 + | sub TMP1, CRET1, BASE + | stw PC, -16(CRET1) // [cont|PC] + | mr TMP2, BASE + | addi PC, TMP1, FRAME_CONT + | mr BASE, CRET1 + | li NARGS8:RC, 16 // 2 args for func(o1, o2). + | b ->vm_call_dispatch + | + |->vmeta_len: +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | mr SAVE0, CARG1 +#endif + | mr CARG2, RD + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | bl extern lj_meta_len // (lua_State *L, TValue *o) + | // Returns NULL (retry) or TValue * (metamethod base). +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | cmplwi CRET1, 0 + | bne ->vmeta_binop // Binop call for compatibility. + | mr CARG1, SAVE0 + | b ->BC_LEN_Z +#else + | b ->vmeta_binop // Binop call for compatibility. +#endif + | + |//-- Call metamethod ---------------------------------------------------- + | + |->vmeta_call: // Resolve and call __call metamethod. + | // TMP2 = old base, BASE = new base, RC = nargs*8 + | mr CARG1, L + | stw TMP2, L->base // This is the callers base! + | subi CARG2, BASE, 8 + | stw PC, SAVE_PC + | add CARG3, BASE, RC + | mr SAVE0, NARGS8:RC + | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) + | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. + | addi NARGS8:RC, SAVE0, 8 // Got one more argument now. + | ins_call + | + |->vmeta_callt: // Resolve __call for BC_CALLT. + | // BASE = old base, RA = new base, RC = nargs*8 + | mr CARG1, L + | stw BASE, L->base + | subi CARG2, RA, 8 + | stw PC, SAVE_PC + | add CARG3, RA, RC + | mr SAVE0, NARGS8:RC + | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) + | lwz TMP1, FRAME_PC(BASE) + | addi NARGS8:RC, SAVE0, 8 // Got one more argument now. + | lwz LFUNC:RB, FRAME_FUNC(RA) // Guaranteed to be a function here. + | b ->BC_CALLT_Z + | + |//-- Argument coercion for 'for' statement ------------------------------ + | + |->vmeta_for: + | mr CARG1, L + | stw BASE, L->base + | mr CARG2, RA + | stw PC, SAVE_PC + | mr SAVE0, INS + | bl extern lj_meta_for // (lua_State *L, TValue *base) +#if LJ_HASJIT + | decode_OP1 TMP0, SAVE0 +#endif + | decode_RA8 RA, SAVE0 +#if LJ_HASJIT + | cmpwi TMP0, BC_JFORI +#endif + | decode_RD8 RD, SAVE0 +#if LJ_HASJIT + | beqy =>BC_JFORI +#endif + | b =>BC_FORI + | + |//----------------------------------------------------------------------- + |//-- Fast functions ----------------------------------------------------- + |//----------------------------------------------------------------------- + | + |.macro .ffunc, name + |->ff_ .. name: + |.endmacro + | + |.macro .ffunc_1, name + |->ff_ .. name: + | cmplwi NARGS8:RC, 8 + | lwz CARG3, 0(BASE) + | lwz CARG1, 4(BASE) + | blt ->fff_fallback + |.endmacro + | + |.macro .ffunc_2, name + |->ff_ .. name: + | cmplwi NARGS8:RC, 16 + | lwz CARG3, 0(BASE) + | lwz CARG4, 8(BASE) + | lwz CARG1, 4(BASE) + | lwz CARG2, 12(BASE) + | blt ->fff_fallback + |.endmacro + | + |.macro .ffunc_n, name + |->ff_ .. name: + | cmplwi NARGS8:RC, 8 + | lwz CARG3, 0(BASE) + | lfd FARG1, 0(BASE) + | blt ->fff_fallback + | checknum CARG3; bge ->fff_fallback + |.endmacro + | + |.macro .ffunc_nn, name + |->ff_ .. name: + | cmplwi NARGS8:RC, 16 + | lwz CARG3, 0(BASE) + | lfd FARG1, 0(BASE) + | lwz CARG4, 8(BASE) + | lfd FARG2, 8(BASE) + | blt ->fff_fallback + | checknum CARG3; bge ->fff_fallback + | checknum CARG4; bge ->fff_fallback + |.endmacro + | + |// Inlined GC threshold check. Caveat: uses TMP0 and TMP1. + |.macro ffgccheck + | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH) + | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) + | cmplw TMP0, TMP1 + | bgel ->fff_gcstep + |.endmacro + | + |//-- Base library: checks ----------------------------------------------- + | + |.ffunc_1 assert + | li TMP1, LJ_TFALSE + | la RA, -8(BASE) + | cmplw cr1, CARG3, TMP1 + | lwz PC, FRAME_PC(BASE) + | bge cr1, ->fff_fallback + | stw CARG3, 0(RA) + | addi RD, NARGS8:RC, 8 // Compute (nresults+1)*8. + | stw CARG1, 4(RA) + | beq ->fff_res // Done if exactly 1 argument. + | li TMP1, 8 + | subi RC, RC, 8 + |1: + | cmplw TMP1, RC + | lfdx f0, BASE, TMP1 + | stfdx f0, RA, TMP1 + | addi TMP1, TMP1, 8 + | bney <1 + | b ->fff_res + | + |.ffunc type + | cmplwi NARGS8:RC, 8 + | lwz CARG1, 0(BASE) + | blt ->fff_fallback + | subfc TMP0, TISNUM, CARG1 + | subfe TMP2, CARG1, CARG1 + | orc TMP1, TMP2, TMP0 + | addi TMP1, TMP1, ~LJ_TISNUM+1 + | slwi TMP1, TMP1, 3 + | la TMP2, CFUNC:RB->upvalue + | lfdx FARG1, TMP2, TMP1 + | b ->fff_resn + | + |//-- Base library: getters and setters --------------------------------- + | + |.ffunc_1 getmetatable + | checktab CARG3; bne >6 + |1: // Field metatable must be at same offset for GCtab and GCudata! + | lwz TAB:CARG1, TAB:CARG1->metatable + |2: + | li CARG3, LJ_TNIL + | cmplwi TAB:CARG1, 0 + | lwz STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH) + | beq ->fff_restv + | lwz TMP0, TAB:CARG1->hmask + | li CARG3, LJ_TTAB // Use metatable as default result. + | lwz TMP1, STR:RC->hash + | lwz NODE:TMP2, TAB:CARG1->node + | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask + | slwi TMP0, TMP1, 5 + | slwi TMP1, TMP1, 3 + | sub TMP1, TMP0, TMP1 + | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) + |3: // Rearranged logic, because we expect _not_ to find the key. + | lwz CARG4, NODE:TMP2->key + | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2) + | lwz CARG2, NODE:TMP2->val + | lwz TMP1, 4+offsetof(Node, val)(NODE:TMP2) + | checkstr CARG4; bne >4 + | cmpw TMP0, STR:RC; beq >5 + |4: + | lwz NODE:TMP2, NODE:TMP2->next + | cmplwi NODE:TMP2, 0 + | beq ->fff_restv // Not found, keep default result. + | b <3 + |5: + | checknil CARG2 + | beq ->fff_restv // Ditto for nil value. + | mr CARG3, CARG2 // Return value of mt.__metatable. + | mr CARG1, TMP1 + | b ->fff_restv + | + |6: + | cmpwi CARG3, LJ_TUDATA; beq <1 + | subfc TMP0, TISNUM, CARG3 + | subfe TMP2, CARG3, CARG3 + | orc TMP1, TMP2, TMP0 + | addi TMP1, TMP1, ~LJ_TISNUM+1 + | slwi TMP1, TMP1, 2 + | la TMP2, DISPATCH_GL(gcroot[GCROOT_BASEMT])(DISPATCH) + | lwzx TAB:CARG1, TMP2, TMP1 + | b <2 + | + |.ffunc_2 setmetatable + | // Fast path: no mt for table yet and not clearing the mt. + | checktab CARG3; bne ->fff_fallback + | lwz TAB:TMP1, TAB:CARG1->metatable + | checktab CARG4; bne ->fff_fallback + | cmplwi TAB:TMP1, 0 + | lbz TMP3, TAB:CARG1->marked + | bne ->fff_fallback + | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) + | stw TAB:CARG2, TAB:CARG1->metatable + | beq ->fff_restv + | barrierback TAB:CARG1, TMP3, TMP0 + | b ->fff_restv + | + |.ffunc rawget + | cmplwi NARGS8:RC, 16 + | lwz CARG4, 0(BASE) + | lwz TAB:CARG2, 4(BASE) + | blt ->fff_fallback + | checktab CARG4; bne ->fff_fallback + | la CARG3, 8(BASE) + | mr CARG1, L + | bl extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key) + | // Returns cTValue *. + | lfd FARG1, 0(CRET1) + | b ->fff_resn + | + |//-- Base library: conversions ------------------------------------------ + | + |.ffunc tonumber + | // Only handles the number case inline (without a base argument). + | cmplwi NARGS8:RC, 8 + | lwz CARG1, 0(BASE) + | lfd FARG1, 0(BASE) + | bne ->fff_fallback // Exactly one argument. + | checknum CARG1; bgt ->fff_fallback + | b ->fff_resn + | + |.ffunc_1 tostring + | // Only handles the string or number case inline. + | checkstr CARG3 + | // A __tostring method in the string base metatable is ignored. + | beq ->fff_restv // String key? + | // Handle numbers inline, unless a number base metatable is present. + | lwz TMP0, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])(DISPATCH) + | checknum CARG3 + | cmplwi cr1, TMP0, 0 + | stw BASE, L->base // Add frame since C call can throw. + | crorc 4*cr0+eq, 4*cr0+gt, 4*cr1+eq + | stw PC, SAVE_PC // Redundant (but a defined value). + | beq ->fff_fallback + | ffgccheck + | mr CARG1, L + | mr CARG2, BASE + if (LJ_DUALNUM) { + | bl extern lj_str_fromnumber // (lua_State *L, cTValue *o) + } else { + | bl extern lj_str_fromnum // (lua_State *L, lua_Number *np) + } + | // Returns GCstr *. + | li CARG3, LJ_TSTR + | b ->fff_restv + | + |//-- Base library: iterators ------------------------------------------- + | + |.ffunc next + | cmplwi NARGS8:RC, 8 + | lwz CARG1, 0(BASE) + | lwz TAB:CARG2, 4(BASE) + | blt ->fff_fallback + | stwx TISNIL, BASE, NARGS8:RC // Set missing 2nd arg to nil. + | checktab CARG1 + | lwz PC, FRAME_PC(BASE) + | bne ->fff_fallback + | stw BASE, L->base // Add frame since C call can throw. + | mr CARG1, L + | stw 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 + | li CARG3, LJ_TNIL + | beq ->fff_restv // End of traversal: return nil. + | lfd f0, 8(BASE) // Copy key and value to results. + | la RA, -8(BASE) + | lfd f1, 16(BASE) + | stfd f0, 0(RA) + | li RD, (2+1)*8 + | stfd f1, 8(RA) + | b ->fff_res + | + |.ffunc_1 pairs + | checktab CARG3 + | lwz PC, FRAME_PC(BASE) + | bne ->fff_fallback +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | lwz TAB:TMP2, TAB:CARG1->metatable + | lfd f0, CFUNC:RB->upvalue[0] + | cmplwi TAB:TMP2, 0 + | la RA, -8(BASE) + | bne ->fff_fallback +#else + | lfd f0, CFUNC:RB->upvalue[0] + | la RA, -8(BASE) +#endif + | stw TISNIL, 8(BASE) + | li RD, (3+1)*8 + | stfd f0, 0(RA) + | b ->fff_res + | + |.ffunc ipairs_aux + | cmplwi NARGS8:RC, 16 + | lwz CARG3, 0(BASE) + | lwz TAB:CARG1, 4(BASE) + | lwz CARG4, 8(BASE) + if (LJ_DUALNUM) { + | lwz TMP2, 12(BASE) + } else { + | lfd FARG2, 8(BASE) + } + | blt ->fff_fallback + | checktab CARG3 + | checknum cr1, CARG4 + | lwz PC, FRAME_PC(BASE) + if (LJ_DUALNUM) { + | bne ->fff_fallback + | bne cr1, ->fff_fallback + } else { + | lus TMP0, 0x3ff0 + | stw ZERO, TMPD_LO + | bne ->fff_fallback + | stw TMP0, TMPD_HI + | bge cr1, ->fff_fallback + | lfd FARG1, TMPD + | toint TMP2, FARG2, f0 + } + | lwz TMP0, TAB:CARG1->asize + | lwz TMP1, TAB:CARG1->array + if (!LJ_DUALNUM) { + | fadd FARG2, FARG2, FARG1 + } + | addi TMP2, TMP2, 1 + | la RA, -8(BASE) + | cmplw TMP0, TMP2 + if (LJ_DUALNUM) { + | stw TISNUM, 0(RA) + | slwi TMP3, TMP2, 3 + | stw TMP2, 4(RA) + } else { + | slwi TMP3, TMP2, 3 + | stfd FARG2, 0(RA) + } + | ble >2 // Not in array part? + | lwzx TMP2, TMP1, TMP3 + | lfdx f0, TMP1, TMP3 + |1: + | checknil TMP2 + | li RD, (0+1)*8 + | beq ->fff_res // End of iteration, return 0 results. + | li RD, (2+1)*8 + | stfd f0, 8(RA) + | b ->fff_res + |2: // Check for empty hash part first. Otherwise call C function. + | lwz TMP0, TAB:CARG1->hmask + | cmplwi TMP0, 0 + | li RD, (0+1)*8 + | beq ->fff_res + | mr CARG2, TMP2 + | bl extern lj_tab_getinth // (GCtab *t, int32_t key) + | // Returns cTValue * or NULL. + | cmplwi CRET1, 0 + | li RD, (0+1)*8 + | beq ->fff_res + | lwz TMP2, 0(CRET1) + | lfd f0, 0(CRET1) + | b <1 + | + |.ffunc_1 ipairs + | checktab CARG3 + | lwz PC, FRAME_PC(BASE) + | bne ->fff_fallback +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | lwz TAB:TMP2, TAB:CARG1->metatable + | lfd f0, CFUNC:RB->upvalue[0] + | cmplwi TAB:TMP2, 0 + | la RA, -8(BASE) + | bne ->fff_fallback +#else + | lfd f0, CFUNC:RB->upvalue[0] + | la RA, -8(BASE) +#endif + if (LJ_DUALNUM) { + | stw TISNUM, 8(BASE) + } else { + | stw ZERO, 8(BASE) + } + | stw ZERO, 12(BASE) + | li RD, (3+1)*8 + | stfd f0, 0(RA) + | b ->fff_res + | + |//-- Base library: catch errors ---------------------------------------- + | + |.ffunc pcall + | cmplwi NARGS8:RC, 8 + | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | blt ->fff_fallback + | mr TMP2, BASE + | la BASE, 8(BASE) + | // Remember active hook before pcall. + | rlwinm TMP3, TMP3, 32-HOOK_ACTIVE_SHIFT, 31, 31 + | subi NARGS8:RC, NARGS8:RC, 8 + | addi PC, TMP3, 8+FRAME_PCALL + | b ->vm_call_dispatch + | + |.ffunc xpcall + | cmplwi NARGS8:RC, 16 + | lwz CARG4, 8(BASE) + | lfd FARG2, 8(BASE) + | lfd FARG1, 0(BASE) + | blt ->fff_fallback + | lbz TMP1, DISPATCH_GL(hookmask)(DISPATCH) + | mr TMP2, BASE + | checkfunc CARG4; bne ->fff_fallback // Traceback must be a function. + | la BASE, 16(BASE) + | // Remember active hook before pcall. + | rlwinm TMP1, TMP1, 32-HOOK_ACTIVE_SHIFT, 31, 31 + | stfd FARG2, 0(TMP2) // Swap function and traceback. + | subi NARGS8:RC, NARGS8:RC, 16 + | stfd FARG1, 8(TMP2) + | addi PC, TMP1, 16+FRAME_PCALL + | b ->vm_call_dispatch + | + |//-- Coroutine library -------------------------------------------------- + | + |.macro coroutine_resume_wrap, resume + |.if resume + |.ffunc_1 coroutine_resume + | cmpwi CARG3, LJ_TTHREAD; bne ->fff_fallback + |.else + |.ffunc coroutine_wrap_aux + | lwz L:CARG1, CFUNC:RB->upvalue[0].gcr + |.endif + | lbz TMP0, L:CARG1->status + | lwz TMP1, L:CARG1->cframe + | lwz CARG2, L:CARG1->top + | cmplwi cr0, TMP0, LUA_YIELD + | lwz TMP2, L:CARG1->base + | cmplwi cr1, TMP1, 0 + | lwz TMP0, L:CARG1->maxstack + | cmplw cr7, CARG2, TMP2 + | lwz PC, FRAME_PC(BASE) + | crorc 4*cr6+lt, 4*cr0+gt, 4*cr1+eq // st>LUA_YIELD || cframe!=0 + | add TMP2, CARG2, NARGS8:RC + | crandc 4*cr6+gt, 4*cr7+eq, 4*cr0+eq // base==top && st!=LUA_YIELD + | cmplw cr1, TMP2, TMP0 + | cror 4*cr6+lt, 4*cr6+lt, 4*cr6+gt + | stw PC, SAVE_PC + | cror 4*cr6+lt, 4*cr6+lt, 4*cr1+gt // cond1 || cond2 || stackov + | stw BASE, L->base + | blt cr6, ->fff_fallback + |1: + |.if resume + | addi BASE, BASE, 8 // Keep resumed thread in stack for GC. + | subi NARGS8:RC, NARGS8:RC, 8 + | subi TMP2, TMP2, 8 + |.endif + | stw TMP2, L:CARG1->top + | li TMP1, 0 + | stw BASE, L->top + |2: // Move args to coroutine. + | cmpw TMP1, NARGS8:RC + | lfdx f0, BASE, TMP1 + | beq >3 + | stfdx f0, CARG2, TMP1 + | addi TMP1, TMP1, 8 + | b <2 + |3: + | li CARG3, 0 + | mr L:SAVE0, L:CARG1 + | li CARG4, 0 + | bl ->vm_resume // (lua_State *L, TValue *base, 0, 0) + | // Returns thread status. + |4: + | lwz TMP2, L:SAVE0->base + | cmplwi CRET1, LUA_YIELD + | lwz TMP3, L:SAVE0->top + | li_vmstate INTERP + | lwz BASE, L->base + | st_vmstate + | bgt >8 + | sub RD, TMP3, TMP2 + | lwz TMP0, L->maxstack + | cmplwi RD, 0 + | add TMP1, BASE, RD + | beq >6 // No results? + | cmplw TMP1, TMP0 + | li TMP1, 0 + | bgt >9 // Need to grow stack? + | + | subi TMP3, RD, 8 + | stw TMP2, L:SAVE0->top // Clear coroutine stack. + |5: // Move results from coroutine. + | cmplw TMP1, TMP3 + | lfdx f0, TMP2, TMP1 + | stfdx f0, BASE, TMP1 + | addi TMP1, TMP1, 8 + | bne <5 + |6: + | andi. TMP0, PC, FRAME_TYPE + |.if resume + | li TMP1, LJ_TTRUE + | la RA, -8(BASE) + | stw TMP1, -8(BASE) // Prepend true to results. + | addi RD, RD, 16 + |.else + | mr RA, BASE + | addi RD, RD, 8 + |.endif + |7: + | stw PC, SAVE_PC + | mr MULTRES, RD + | beq ->BC_RET_Z + | b ->vm_return + | + |8: // Coroutine returned with error (at co->top-1). + |.if resume + | andi. TMP0, PC, FRAME_TYPE + | la TMP3, -8(TMP3) + | li TMP1, LJ_TFALSE + | lfd f0, 0(TMP3) + | stw TMP3, L:SAVE0->top // Remove error from coroutine stack. + | li RD, (2+1)*8 + | stw TMP1, -8(BASE) // Prepend false to results. + | la RA, -8(BASE) + | stfd f0, 0(BASE) // Copy error message. + | b <7 + |.else + | mr CARG1, L + | mr CARG2, L:SAVE0 + | bl extern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co) + |.endif + | + |9: // Handle stack expansion on return from yield. + | mr CARG1, L + | srwi CARG2, RD, 3 + | bl extern lj_state_growstack // (lua_State *L, int n) + | li CRET1, 0 + | b <4 + |.endmacro + | + | coroutine_resume_wrap 1 // coroutine.resume + | coroutine_resume_wrap 0 // coroutine.wrap + | + |.ffunc coroutine_yield + | lwz TMP0, L->cframe + | add TMP1, BASE, NARGS8:RC + | stw BASE, L->base + | andi. TMP0, TMP0, CFRAME_RESUME + | stw TMP1, L->top + | li CRET1, LUA_YIELD + | beq ->fff_fallback + | stw ZERO, L->cframe + | stb CRET1, L->status + | b ->vm_leave_unw + | + |//-- Math library ------------------------------------------------------- + | + |.ffunc_1 math_abs + | checknum CARG3 + if (LJ_DUALNUM) { + | bne >2 + | srawi TMP1, CARG1, 31 + | xor TMP2, TMP1, CARG1 + | sub. CARG1, TMP2, TMP1 + | blt >1 + |->fff_resi: + | lwz PC, FRAME_PC(BASE) + | la RA, -8(BASE) + | stw TISNUM, -8(BASE) + | stw CRET1, -4(BASE) + | b ->fff_res1 + |1: + | lus CARG3, 0x41e0 // 2^31. + | li CARG1, 0 + | b ->fff_restv + |2: + } + | bge ->fff_fallback + | rlwinm CARG3, CARG3, 0, 1, 31 + | // Fallthrough. + | + |->fff_restv: + | // CARG3/CARG1 = TValue result. + | lwz PC, FRAME_PC(BASE) + | stw CARG3, -8(BASE) + | la RA, -8(BASE) + | stw CARG1, -4(BASE) + |->fff_res1: + | // RA = results, PC = return. + | li RD, (1+1)*8 + |->fff_res: + | // RA = results, RD = (nresults+1)*8, PC = return. + | andi. TMP0, PC, FRAME_TYPE + | mr MULTRES, RD + | bney ->vm_return + | lwz INS, -4(PC) + | decode_RB8 RB, INS + |5: + | cmplw RB, RD // More results expected? + | decode_RA8 TMP0, INS + | bgt >6 + | ins_next1 + | // Adjust BASE. KBASE is assumed to be set for the calling frame. + | sub BASE, RA, TMP0 + | ins_next2 + | + |6: // Fill up results with nil. + | subi TMP1, RD, 8 + | addi RD, RD, 8 + | stwx TISNIL, RA, TMP1 + | b <5 + | + |.macro math_extern, func + | .ffunc_n math_ .. func + | bl extern func + | b ->fff_resn + |.endmacro + | + |.macro math_extern2, func + | .ffunc_nn math_ .. func + | bl extern func + | b ->fff_resn + |.endmacro + | + |.macro math_round, func + | .ffunc_1 math_ .. func + | checknum CARG3; beqy ->fff_restv + | rlwinm TMP2, CARG3, 12, 21, 31 + | bge ->fff_fallback + | addic. TMP2, TMP2, -1023 // exp = exponent(x) - 1023 + | cmplwi cr1, TMP2, 31 // 0 <= exp < 31? + | subfic TMP0, TMP2, 31 + | blt >3 + | slwi TMP1, CARG3, 11 + | srwi TMP3, CARG1, 21 + | oris TMP1, TMP1, 0x8000 + | addi TMP2, TMP2, 1 + | or TMP1, TMP1, TMP3 + | slwi CARG2, CARG1, 11 + | bge cr1, >4 + | slw TMP3, TMP1, TMP2 + | srw CARG1, TMP1, TMP0 + | or TMP3, TMP3, CARG2 + | srawi TMP2, CARG3, 31 + |.if "func" == "floor" + | and TMP1, TMP3, TMP2 + | addic TMP0, TMP1, -1 + | subfe TMP1, TMP0, TMP1 + | add CARG1, CARG1, TMP1 + | xor CARG1, CARG1, TMP2 + | sub CARG1, CARG1, TMP2 + | b ->fff_resi + |.else + | andc TMP1, TMP3, TMP2 + | addic TMP0, TMP1, -1 + | subfe TMP1, TMP0, TMP1 + | addo. CARG1, CARG1, TMP1 + | xor CARG1, CARG1, TMP2 + | sub CARG1, CARG1, TMP2 + | bns ->fff_resi + | // Potential overflow. + | mcrxr cr0; bley ->fff_resi // Ignore unrelated overflow. + | lus CARG3, 0x41e0 // 2^31. + | li CARG1, 0 + | b ->fff_restv + |.endif + |3: // |x| < 1 + | add TMP2, CARG3, CARG3 + | srawi TMP1, CARG3, 31 + | or TMP2, CARG1, TMP2 // ztest = (hi+hi) | lo + |.if "func" == "floor" + | and TMP1, TMP2, TMP1 // (ztest & sign) == 0 ? 0 : -1 + | subfic TMP2, TMP1, 0 + | subfe CARG1, CARG1, CARG1 + |.else + | andc TMP1, TMP2, TMP1 // (ztest & ~sign) == 0 ? 0 : 1 + | addic TMP2, TMP1, -1 + | subfe CARG1, TMP2, TMP1 + |.endif + | b ->fff_resi + |4: // exp >= 31. Check for -(2^31). + | xoris TMP1, TMP1, 0x8000 + | srawi TMP2, CARG3, 31 + |.if "func" == "floor" + | or TMP1, TMP1, CARG2 + |.endif + | orc. TMP1, TMP1, TMP2 + | crand 4*cr0+eq, 4*cr0+eq, 4*cr1+eq + | lus CARG1, 0x8000 // -(2^31). + | beqy ->fff_resi + |5: + | lfd FARG1, 0(BASE) + | bl extern func + | b ->fff_resn + |.endmacro + | + if (LJ_DUALNUM) { + | math_round floor + | math_round ceil + } else { + | // NYI: use internal implementation. + | math_extern floor + | math_extern ceil + } + | + | math_extern sqrt + | math_extern log + | math_extern log10 + | math_extern exp + | math_extern sin + | math_extern cos + | math_extern tan + | math_extern asin + | math_extern acos + | math_extern atan + | math_extern sinh + | math_extern cosh + | math_extern tanh + | math_extern2 pow + | math_extern2 atan2 + | math_extern2 fmod + | + |->ff_math_deg: + |.ffunc_n math_rad + | lfd FARG2, CFUNC:RB->upvalue[0] + | fmul FARG1, FARG1, FARG2 + | b ->fff_resn + | + if (LJ_DUALNUM) { + |.ffunc math_ldexp + | cmplwi NARGS8:RC, 16 + | lwz CARG3, 0(BASE) + | lfd FARG1, 0(BASE) + | lwz CARG4, 8(BASE) + | lwz CARG1, 12(BASE) + | blt ->fff_fallback + | checknum CARG3; bge ->fff_fallback + | checknum CARG4; bne ->fff_fallback + } else { + |.ffunc_nn math_ldexp + | toint CARG1, FARG2 + } + | bl extern ldexp + | b ->fff_resn + | + |.ffunc_n math_frexp + | la CARG1, DISPATCH_GL(tmptv)(DISPATCH) + | lwz PC, FRAME_PC(BASE) + | bl extern frexp + | lwz TMP1, DISPATCH_GL(tmptv)(DISPATCH) + | la RA, -8(BASE) + if (!LJ_DUALNUM) { + | tonum_i FARG2, TMP1 + } + | stfd FARG1, 0(RA) + | li RD, (2+1)*8 + if (LJ_DUALNUM) { + | stw TISNUM, 8(RA) + | stw TMP1, 12(RA) + } else { + | stfd FARG2, 8(RA) + } + | b ->fff_res + | + |.ffunc_n math_modf + | la CARG1, -8(BASE) + | lwz PC, FRAME_PC(BASE) + | bl extern modf + | la RA, -8(BASE) + | stfd FARG1, 0(BASE) + | li RD, (2+1)*8 + | b ->fff_res + | + |.macro math_minmax, name, ismax + ||if (LJ_DUALNUM) { + | .ffunc_1 name + | checknum CARG3 + | addi TMP1, BASE, 8 + | add TMP2, BASE, NARGS8:RC + | bne >4 + |1: // Handle integers. + | lwz CARG4, 0(TMP1) + | cmplw cr1, TMP1, TMP2 + | lwz CARG2, 4(TMP1) + | bge cr1, ->fff_resi + | checknum CARG4 + | xoris TMP0, CARG1, 0x8000 + | xoris TMP3, CARG2, 0x8000 + | bne >3 + | subfc TMP3, TMP3, TMP0 + | subfe TMP0, TMP0, TMP0 + |.if ismax + | andc TMP3, TMP3, TMP0 + |.else + | and TMP3, TMP3, TMP0 + |.endif + | add CARG1, TMP3, CARG2 + | addi TMP1, TMP1, 8 + | b <1 + |3: + | bge ->fff_fallback + | // Convert intermediate result to number and continue below. + | tonum_i FARG1, CARG1 + | lfd FARG2, 0(TMP1) + | b >6 + |4: + | lfd FARG1, 0(BASE) + | bge ->fff_fallback + |5: // Handle numbers. + | lwz CARG4, 0(TMP1) + | cmplw cr1, TMP1, TMP2 + | lfd FARG2, 0(TMP1) + | bge cr1, ->fff_resn + | checknum CARG4; bge >7 + |6: + | fsub f0, FARG1, FARG2 + | addi TMP1, TMP1, 8 + |.if ismax + | fsel FARG1, f0, FARG1, FARG2 + |.else + | fsel FARG1, f0, FARG2, FARG1 + |.endif + | b <5 + |7: // Convert integer to number and continue above. + | lwz CARG2, 4(TMP1) + | bne ->fff_fallback + | tonum_i FARG2, CARG2 + | b <6 + ||} else { + | .ffunc_n name + | li TMP1, 8 + |1: + | lwzx CARG2, BASE, TMP1 + | lfdx FARG2, BASE, TMP1 + | cmplw cr1, TMP1, NARGS8:RC + | checknum CARG2 + | bge cr1, ->fff_resn + | bge ->fff_fallback + | fsub f0, FARG1, FARG2 + | addi TMP1, TMP1, 8 + |.if ismax + | fsel FARG1, f0, FARG1, FARG2 + |.else + | fsel FARG1, f0, FARG2, FARG1 + |.endif + | b <1 + ||} + |.endmacro + | + | math_minmax math_min, 0 + | math_minmax math_max, 1 + | + |//-- String library ----------------------------------------------------- + | + |.ffunc_1 string_len + | checkstr CARG3; bne ->fff_fallback + | lwz CRET1, STR:CARG1->len + | b ->fff_resi + | + |.ffunc string_byte // Only handle the 1-arg case here. + | cmplwi NARGS8:RC, 8 + | lwz CARG3, 0(BASE) + | lwz STR:CARG1, 4(BASE) + | bne ->fff_fallback // Need exactly 1 argument. + | checkstr CARG3 + | bne ->fff_fallback + | lwz TMP0, STR:CARG1->len + if (LJ_DUALNUM) { + | lbz CARG1, STR:CARG1[1] // Access is always ok (NUL at end). + | li RD, (0+1)*8 + | lwz PC, FRAME_PC(BASE) + | cmplwi TMP0, 0 + | la RA, -8(BASE) + | beqy ->fff_res + | b ->fff_resi + } else { + | lbz TMP1, STR:CARG1[1] // Access is always ok (NUL at end). + | addic TMP3, TMP0, -1 // RD = ((str->len != 0)+1)*8 + | subfe RD, TMP3, TMP0 + | stw TMP1, TONUM_LO // Inlined tonum_u f0, TMP1. + | addi RD, RD, 1 + | lfd f0, TONUM_D + | la RA, -8(BASE) + | lwz PC, FRAME_PC(BASE) + | fsub f0, f0, TOBIT + | slwi RD, RD, 3 + | stfd f0, 0(RA) + | b ->fff_res + } + | + |.ffunc string_char // Only handle the 1-arg case here. + | ffgccheck + | cmplwi NARGS8:RC, 8 + | lwz CARG3, 0(BASE) + if (LJ_DUALNUM) { + | lwz TMP0, 4(BASE) + | bne ->fff_fallback // Exactly 1 argument. + | checknum CARG3; bne ->fff_fallback + | la CARG2, 7(BASE) + } else { + | lfd FARG1, 0(BASE) + | bne ->fff_fallback // Exactly 1 argument. + | checknum CARG3; bge ->fff_fallback + | toint TMP0, FARG1 + | la CARG2, TMPD_BLO + } + | li CARG3, 1 + | cmplwi TMP0, 255; bgt ->fff_fallback + |->fff_newstr: + | mr CARG1, L + | stw BASE, L->base + | stw PC, SAVE_PC + | bl extern lj_str_new // (lua_State *L, char *str, size_t l) + | // Returns GCstr *. + | lwz BASE, L->base + | li CARG3, LJ_TSTR + | b ->fff_restv + | + |.ffunc string_sub + | ffgccheck + | cmplwi NARGS8:RC, 16 + | lwz CARG3, 16(BASE) + if (!LJ_DUALNUM) { + | lfd f0, 16(BASE) + } + | lwz TMP0, 0(BASE) + | lwz STR:CARG1, 4(BASE) + | blt ->fff_fallback + | lwz CARG2, 8(BASE) + if (LJ_DUALNUM) { + | lwz TMP1, 12(BASE) + } else { + | lfd f1, 8(BASE) + } + | li TMP2, -1 + | beq >1 + if (LJ_DUALNUM) { + | checknum CARG3 + | lwz TMP2, 20(BASE) + | bne ->fff_fallback + |1: + | checknum CARG2; bne ->fff_fallback + } else { + | checknum CARG3; bge ->fff_fallback + | toint TMP2, f0 + |1: + | checknum CARG2; bge ->fff_fallback + } + | checkstr TMP0; bne ->fff_fallback + if (!LJ_DUALNUM) { + | toint TMP1, f1 + } + | lwz TMP0, STR:CARG1->len + | cmplw TMP0, TMP2 // len < end? (unsigned compare) + | addi TMP3, TMP2, 1 + | blt >5 + |2: + | cmpwi TMP1, 0 // start <= 0? + | add TMP3, TMP1, TMP0 + | ble >7 + |3: + | sub CARG3, TMP2, TMP1 + | addi CARG2, STR:CARG1, #STR-1 + | srawi TMP0, CARG3, 31 + | addi CARG3, CARG3, 1 + | add CARG2, CARG2, TMP1 + | andc CARG3, CARG3, TMP0 + | b ->fff_newstr + | + |5: // Negative end or overflow. + | sub CARG2, TMP0, TMP2 + | srawi CARG2, CARG2, 31 + | andc TMP3, TMP3, CARG2 // end = end > len ? len : end+len+1 + | add TMP2, TMP0, TMP3 + | b <2 + | + |7: // Negative start or underflow. + | addic CARG3, TMP1, -1 + | subfe CARG3, CARG3, CARG3 + | srawi CARG2, TMP3, 31 // Note: modifies carry. + | andc TMP3, TMP3, CARG3 + | andc TMP1, TMP3, CARG2 + | addi TMP1, TMP1, 1 // start = 1 + (start ? start+len : 0) + | b <3 + | + |.ffunc string_rep // Only handle the 1-char case inline. + | ffgccheck + | cmplwi NARGS8:RC, 16 + | lwz TMP0, 0(BASE) + | lwz STR:CARG1, 4(BASE) + | lwz CARG4, 8(BASE) + if (LJ_DUALNUM) { + | lwz CARG3, 12(BASE) + } else { + | lfd FARG2, 8(BASE) + } + | blt ->fff_fallback + | checkstr TMP0; bne ->fff_fallback + if (LJ_DUALNUM) { + | checknum CARG4; bne ->fff_fallback + } else { + | checknum CARG4; bge ->fff_fallback + | toint CARG3, FARG2 + } + | lwz TMP0, STR:CARG1->len + | cmpwi CARG3, 0 + | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) + | ble >2 // Count <= 0? (or non-int) + | cmplwi TMP0, 1 + | subi TMP2, CARG3, 1 + | blt >2 // Zero length string? + | cmplw cr1, TMP1, CARG3 + | bne ->fff_fallback // Fallback for > 1-char strings. + | lbz TMP0, STR:CARG1[1] + | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) + | blt cr1, ->fff_fallback + |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). + | cmplwi TMP2, 0 + | stbx TMP0, CARG2, TMP2 + | subi TMP2, TMP2, 1 + | bne <1 + | b ->fff_newstr + |2: // Return empty string. + | la STR:CARG1, DISPATCH_GL(strempty)(DISPATCH) + | li CARG3, LJ_TSTR + | b ->fff_restv + | + |.ffunc string_reverse + | ffgccheck + | cmplwi NARGS8:RC, 8 + | lwz CARG3, 0(BASE) + | lwz STR:CARG1, 4(BASE) + | blt ->fff_fallback + | checkstr CARG3 + | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) + | bne ->fff_fallback + | lwz CARG3, STR:CARG1->len + | la CARG1, #STR(STR:CARG1) + | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) + | li TMP2, 0 + | cmplw TMP1, CARG3 + | subi TMP3, CARG3, 1 + | blt ->fff_fallback + |1: // Reverse string copy. + | cmpwi TMP3, 0 + | lbzx TMP1, CARG1, TMP2 + | blty ->fff_newstr + | stbx TMP1, CARG2, TMP3 + | subi TMP3, TMP3, 1 + | addi TMP2, TMP2, 1 + | b <1 + | + |.macro ffstring_case, name, lo + | .ffunc name + | ffgccheck + | cmplwi NARGS8:RC, 8 + | lwz CARG3, 0(BASE) + | lwz STR:CARG1, 4(BASE) + | blt ->fff_fallback + | checkstr CARG3 + | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) + | bne ->fff_fallback + | lwz CARG3, STR:CARG1->len + | la CARG1, #STR(STR:CARG1) + | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) + | cmplw TMP1, CARG3 + | li TMP2, 0 + | blt ->fff_fallback + |1: // ASCII case conversion. + | cmplw TMP2, CARG3 + | lbzx TMP1, CARG1, TMP2 + | bgey ->fff_newstr + | subi TMP0, TMP1, lo + | xori TMP3, TMP1, 0x20 + | addic TMP0, TMP0, -26 + | subfe TMP3, TMP3, TMP3 + | andi. TMP3, TMP3, 0x20 + | xor TMP1, TMP1, TMP3 + | stbx TMP1, CARG2, TMP2 + | addi TMP2, TMP2, 1 + | b <1 + |.endmacro + | + |ffstring_case string_lower, 65 + |ffstring_case string_upper, 97 + | + |//-- Table library ------------------------------------------------------ + | + |.ffunc_1 table_getn + | checktab CARG3; bne ->fff_fallback + | bl extern lj_tab_len // (GCtab *t) + | // Returns uint32_t (but less than 2^31). + | b ->fff_resi + | + |//-- Bit library -------------------------------------------------------- + | + |.macro .ffunc_bit, name + ||if (LJ_DUALNUM) { + | .ffunc_1 bit_..name + | checknum CARG3; bnel ->fff_tobit_fb + ||} else { + | .ffunc_n bit_..name + | fadd FARG1, FARG1, TOBIT + | stfd FARG1, TMPD + | lwz CARG1, TMPD_LO + ||} + |.endmacro + | + |.macro .ffunc_bit_op, name, ins + | .ffunc_bit name + | addi TMP1, BASE, 8 + | add TMP2, BASE, NARGS8:RC + |1: + | lwz CARG4, 0(TMP1) + | cmplw cr1, TMP1, TMP2 + ||if (LJ_DUALNUM) { + | lwz CARG2, 4(TMP1) + ||} else { + | lfd FARG1, 0(TMP1) + ||} + | bgey cr1, ->fff_resi + | checknum CARG4 + ||if (LJ_DUALNUM) { + | bnel ->fff_bitop_fb + ||} else { + | fadd FARG1, FARG1, TOBIT + | bge ->fff_fallback + | stfd FARG1, TMPD + | lwz CARG2, TMPD_LO + ||} + | ins CARG1, CARG1, CARG2 + | addi TMP1, TMP1, 8 + | b <1 + |.endmacro + | + |.ffunc_bit_op band, and + |.ffunc_bit_op bor, or + |.ffunc_bit_op bxor, xor + | + |.ffunc_bit bswap + | rotlwi TMP0, CARG1, 8 + | rlwimi TMP0, CARG1, 24, 0, 7 + | rlwimi TMP0, CARG1, 24, 16, 23 + | mr CRET1, TMP0 + | b ->fff_resi + | + |.ffunc_bit bnot + | not CRET1, CARG1 + | b ->fff_resi + | + |.macro .ffunc_bit_sh, name, ins, shmod + ||if (LJ_DUALNUM) { + | .ffunc_2 bit_..name + | checknum CARG3; bnel ->fff_tobit_fb + | // Note: no inline conversion from number for 2nd argument! + | checknum CARG4; bne ->fff_fallback + ||} else { + | .ffunc_nn bit_..name + | fadd FARG1, FARG1, TOBIT + | fadd FARG2, FARG2, TOBIT + | stfd FARG1, TMPD + | lwz CARG1, TMPD_LO + | stfd FARG2, TMPD + | lwz CARG2, TMPD_LO + ||} + |.if shmod == 1 + | rlwinm CARG2, CARG2, 0, 27, 31 + |.elif shmod == 2 + | neg CARG2, CARG2 + |.endif + | ins CRET1, CARG1, CARG2 + | b ->fff_resi + |.endmacro + | + |.ffunc_bit_sh lshift, slw, 1 + |.ffunc_bit_sh rshift, srw, 1 + |.ffunc_bit_sh arshift, sraw, 1 + |.ffunc_bit_sh rol, rotlw, 0 + |.ffunc_bit_sh ror, rotlw, 2 + | + |.ffunc_bit tobit + if (LJ_DUALNUM) { + | b ->fff_resi + } else { + |->fff_resi: + | tonum_i FARG1, CRET1 + } + |->fff_resn: + | lwz PC, FRAME_PC(BASE) + | la RA, -8(BASE) + | stfd FARG1, -8(BASE) + | b ->fff_res1 + | + |// Fallback FP number to bit conversion. + |->fff_tobit_fb: + if (LJ_DUALNUM) { + | lfd FARG1, 0(BASE) + | bgt ->fff_fallback + | fadd FARG1, FARG1, TOBIT + | stfd FARG1, TMPD + | lwz CARG1, TMPD_LO + | blr + } + |->fff_bitop_fb: + if (LJ_DUALNUM) { + | lfd FARG1, 0(TMP1) + | bgt ->fff_fallback + | fadd FARG1, FARG1, TOBIT + | stfd FARG1, TMPD + | lwz CARG2, TMPD_LO + | blr + } + | + |//----------------------------------------------------------------------- + | + |->fff_fallback: // Call fast function fallback handler. + | // BASE = new base, RB = CFUNC, RC = nargs*8 + | lwz TMP3, CFUNC:RB->f + | add TMP1, BASE, NARGS8:RC + | lwz PC, FRAME_PC(BASE) // Fallback may overwrite PC. + | addi TMP0, TMP1, 8*LUA_MINSTACK + | lwz TMP2, L->maxstack + | stw PC, SAVE_PC // Redundant (but a defined value). + | cmplw TMP0, TMP2 + | stw BASE, L->base + | stw TMP1, L->top + | mr CARG1, L + | bgt >5 // Need to grow stack. + | mtctr TMP3 + | bctrl // (lua_State *L) + | // Either throws an error, or recovers and returns -1, 0 or nresults+1. + | lwz BASE, L->base + | cmpwi CRET1, 0 + | slwi RD, CRET1, 3 + | la RA, -8(BASE) + | bgt ->fff_res // Returned nresults+1? + |1: // Returned 0 or -1: retry fast path. + | lwz TMP0, L->top + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | sub NARGS8:RC, TMP0, BASE + | bne ->vm_call_tail // Returned -1? + | ins_callt // Returned 0: retry fast path. + | + |// Reconstruct previous base for vmeta_call during tailcall. + |->vm_call_tail: + | andi. TMP0, PC, FRAME_TYPE + | rlwinm TMP1, PC, 0, 0, 28 + | bne >3 + | lwz INS, -4(PC) + | decode_RA8 TMP1, INS + | addi TMP1, TMP1, 8 + |3: + | sub TMP2, BASE, TMP1 + | b ->vm_call_dispatch // Resolve again for tailcall. + | + |5: // Grow stack for fallback handler. + | li CARG2, LUA_MINSTACK + | bl extern lj_state_growstack // (lua_State *L, int n) + | lwz BASE, L->base + | cmpw TMP0, TMP0 // Set 4*cr0+eq to force retry. + | b <1 + | + |->fff_gcstep: // Call GC step function. + | // BASE = new base, RC = nargs*8 + | mflr SAVE0 + | stw BASE, L->base + | add TMP0, BASE, NARGS8:RC + | stw PC, SAVE_PC // Redundant (but a defined value). + | stw TMP0, L->top + | mr CARG1, L + | bl extern lj_gc_step // (lua_State *L) + | lwz BASE, L->base + | mtlr SAVE0 + | lwz TMP0, L->top + | sub NARGS8:RC, TMP0, BASE + | lwz CFUNC:RB, FRAME_FUNC(BASE) + | blr + | + |//----------------------------------------------------------------------- + |//-- Special dispatch targets ------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_record: // Dispatch target for recording phase. +#if LJ_HASJIT + | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | andi. TMP0, TMP3, HOOK_VMEVENT // No recording while in vmevent. + | bne >5 + | // Decrement the hookcount for consistency, but always do the call. + | lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH) + | andi. TMP0, TMP3, HOOK_ACTIVE + | bne >1 + | subi TMP2, TMP2, 1 + | andi. TMP0, TMP3, LUA_MASKLINE|LUA_MASKCOUNT + | beqy >1 + | stw TMP2, DISPATCH_GL(hookcount)(DISPATCH) + | b >1 +#endif + | + |->vm_rethook: // Dispatch target for return hooks. + | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | andi. TMP0, TMP3, HOOK_ACTIVE // Hook already active? + | beq >1 + |5: // Re-dispatch to static ins. + | addi TMP1, TMP1, GG_DISP2STATIC // Assumes decode_OP4 TMP1, INS. + | lwzx TMP0, DISPATCH, TMP1 + | mtctr TMP0 + | bctr + | + |->vm_inshook: // Dispatch target for instr/line hooks. + | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH) + | andi. TMP0, TMP3, HOOK_ACTIVE // Hook already active? + | rlwinm TMP0, TMP3, 31-LUA_HOOKLINE, 31, 0 + | bne <5 + | + | cmpwi cr1, TMP0, 0 + | addic. TMP2, TMP2, -1 + | beq cr1, <5 + | stw TMP2, DISPATCH_GL(hookcount)(DISPATCH) + | beq >1 + | bge cr1, <5 + |1: + | mr CARG1, L + | stw MULTRES, SAVE_MULTRES + | mr CARG2, PC + | stw BASE, L->base + | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. + | bl extern lj_dispatch_ins // (lua_State *L, const BCIns *pc) + |3: + | lwz BASE, L->base + |4: // Re-dispatch to static ins. + | lwz INS, -4(PC) + | decode_OP4 TMP1, INS + | decode_RB8 RB, INS + | addi TMP1, TMP1, GG_DISP2STATIC + | decode_RD8 RD, INS + | lwzx TMP0, DISPATCH, TMP1 + | decode_RA8 RA, INS + | decode_RC8 RC, INS + | mtctr TMP0 + | bctr + | + |->cont_hook: // Continue from hook yield. + | addi PC, PC, 4 + | lwz MULTRES, -20(RB) // Restore MULTRES for *M ins. + | b <4 + | + |->vm_hotloop: // Hot loop counter underflow. +#if LJ_HASJIT + | lwz LFUNC:TMP1, FRAME_FUNC(BASE) + | addi CARG1, DISPATCH, GG_DISP2J + | stw PC, SAVE_PC + | lwz TMP1, LFUNC:TMP1->pc + | mr CARG2, PC + | stw L, DISPATCH_J(L)(DISPATCH) + | lbz TMP1, PC2PROTO(framesize)(TMP1) + | stw BASE, L->base + | slwi TMP1, TMP1, 3 + | add TMP1, BASE, TMP1 + | stw TMP1, L->top + | bl extern lj_trace_hot // (jit_State *J, const BCIns *pc) + | b <3 +#endif + | + |->vm_callhook: // Dispatch target for call hooks. + | mr CARG2, PC +#if LJ_HASJIT + | b >1 +#endif + | + |->vm_hotcall: // Hot call counter underflow. +#if LJ_HASJIT + | ori CARG2, PC, 1 + |1: +#endif + | add TMP0, BASE, RC + | stw PC, SAVE_PC + | mr CARG1, L + | stw BASE, L->base + | sub RA, RA, BASE + | stw TMP0, L->top + | bl extern lj_dispatch_call // (lua_State *L, const BCIns *pc) + | // Returns ASMFunction. + | lwz BASE, L->base + | lwz TMP0, L->top + | stw ZERO, SAVE_PC // Invalidate for subsequent line hook. + | sub NARGS8:RC, TMP0, BASE + | add RA, BASE, RA + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | lwz INS, -4(PC) + | mtctr CRET1 + | bctr + | + |//----------------------------------------------------------------------- + |//-- Trace exit handler ------------------------------------------------- + |//----------------------------------------------------------------------- + | + |.macro savex_, a, b, c, d + | stfd f..a, 16+a*8(sp) + | stfd f..b, 16+b*8(sp) + | stfd f..c, 16+c*8(sp) + | stfd f..d, 16+d*8(sp) + |.endmacro + | + |->vm_exit_handler: +#if LJ_HASJIT + | addi sp, sp, -(16+32*8+32*4) + | stmw r2, 16+32*8+2*4(sp) + | addi DISPATCH, JGL, -GG_DISP2G-32768 + | li CARG2, ~LJ_VMST_EXIT + | lwz CARG1, 16+32*8+32*4(sp) // Get stack chain. + | stw CARG2, DISPATCH_GL(vmstate)(DISPATCH) + | savex_ 0,1,2,3 + | stw CARG1, 0(sp) // Store extended stack chain. + | mcrxr cr0 // Clear SO flag. + | savex_ 4,5,6,7 + | addi CARG2, sp, 16+32*8+32*4 // Recompute original value of sp. + | savex_ 8,9,10,11 + | stw CARG2, 16+32*8+1*4(sp) // Store sp in RID_SP. + | savex_ 12,13,14,15 + | mflr CARG3 + | li TMP1, 0 + | savex_ 16,17,18,19 + | stw TMP1, 16+32*8+0*4(sp) // Clear RID_TMP. + | savex_ 20,21,22,23 + | lhz CARG4, 2(CARG3) // Load trace number. + | savex_ 24,25,26,27 + | lwz L, DISPATCH_GL(jit_L)(DISPATCH) + | savex_ 28,29,30,31 + | sub CARG3, TMP0, CARG3 // Compute exit number. + | lwz BASE, DISPATCH_GL(jit_base)(DISPATCH) + | srwi CARG3, CARG3, 2 + | stw L, DISPATCH_J(L)(DISPATCH) + | subi CARG3, CARG3, 2 + | stw TMP1, DISPATCH_GL(jit_L)(DISPATCH) + | stw CARG4, DISPATCH_J(parent)(DISPATCH) + | stw BASE, L->base + | addi CARG1, DISPATCH, GG_DISP2J + | stw CARG3, DISPATCH_J(exitno)(DISPATCH) + | addi CARG2, sp, 16 + | bl extern lj_trace_exit // (jit_State *J, ExitState *ex) + | // Returns MULTRES (unscaled) or negated error code. + | lwz TMP1, L->cframe + | lwz TMP2, 0(sp) + | lwz BASE, L->base + | rlwinm sp, TMP1, 0, 0, 29 + | lwz PC, SAVE_PC // Get SAVE_PC. + | stw TMP2, 0(sp) + | stw L, SAVE_L // Set SAVE_L (on-trace resume/yield). + | b >1 +#endif + |->vm_exit_interp: +#if LJ_HASJIT + | // CARG1 = MULTRES or negated error code, BASE, PC and JGL set. + | lwz L, SAVE_L + | addi DISPATCH, JGL, -GG_DISP2G-32768 + |1: + | cmpwi CARG1, 0 + | blt >3 // Check for error from exit. + | lwz LFUNC:TMP1, FRAME_FUNC(BASE) + | slwi MULTRES, CARG1, 3 + | li TMP2, 0 + | stw MULTRES, SAVE_MULTRES + | lwz TMP1, LFUNC:TMP1->pc + | stw TMP2, DISPATCH_GL(jit_L)(DISPATCH) + | lwz KBASE, PC2PROTO(k)(TMP1) + | // Setup type comparison constants. + | li TISNUM, LJ_TISNUM + | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). + | stw TMP3, TMPD + | li ZERO, 0 + | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float). + | lfs TOBIT, TMPD + | stw TMP3, TMPD + | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double) + | li TISNIL, LJ_TNIL + | stw TMP0, TONUM_HI + | lfs TONUM, TMPD + | // Modified copy of ins_next which handles function header dispatch, too. + | lwz INS, 0(PC) + | addi PC, PC, 4 + | // Assumes TISNIL == ~LJ_VMST_INTERP == -1. + | stw TISNIL, DISPATCH_GL(vmstate)(DISPATCH) + | decode_OP4 TMP1, INS + | decode_RA8 RA, INS + | lwzx TMP0, DISPATCH, TMP1 + | mtctr TMP0 + | cmplwi TMP1, BC_FUNCF*4 // Function header? + | bge >2 + | decode_RB8 RB, INS + | decode_RD8 RD, INS + | decode_RC8 RC, INS + | bctr + |2: + | subi RC, MULTRES, 8 + | add RA, RA, BASE + | bctr + | + |3: // Rethrow error from the right C frame. + | neg CARG2, CARG1 + | mr CARG1, L + | bl extern lj_err_throw // (lua_State *L, int errcode) +#endif + | + |//----------------------------------------------------------------------- + |//-- Math helper functions ---------------------------------------------- + |//----------------------------------------------------------------------- + | + | // NYI: Use internal implementation. + |->vm_floor: + | b extern floor + |->vm_ceil: + | b extern ceil + |->vm_trunc: +#if LJ_HASJIT + | b extern trunc +#endif + | + |->vm_modi: + | divwo. TMP0, CARG1, CARG2 + | bso >1 + | xor. CARG3, CARG1, CARG2 + | mullw TMP0, TMP0, CARG2 + | sub CARG1, CARG1, TMP0 + | bgelr + | cmpwi CARG1, 0; beqlr + | add CARG1, CARG1, CARG2 + | blr + |1: + | cmpwi CARG2, 0 + | li CARG1, 0 + | beqlr + | mcrxr cr0 // Clear SO for -2147483648 % -1 and return 0. + | blr + | + |// Callable from C: double lj_vm_foldarith(double x, double y, int op) + |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -) + |// and basic math functions. ORDER ARITH + |->vm_foldarith: + | cmplwi CARG1, 1 + | beq >1; bgt >2 + | fadd FARG1, FARG1, FARG2; blr + |1: + | fsub FARG1, FARG1, FARG2; blr + |2: + | cmplwi CARG1, 3; beq >1; bgt >2 + | fmul FARG1, FARG1, FARG2; blr + |1: + | fdiv FARG1, FARG1, FARG2; blr + |2: + | cmplwi CARG1, 5; beq >1; bgt >2 + | // NYI: Use internal implementation of floor and avoid spills. + | stwu sp, -32(sp); stfd f14, 16(sp); stfd f15, 24(sp) + | mflr r0 + | fmr f14, FARG1 + | fdiv FARG1, FARG1, FARG2 + | stw r0, 36(sp) + | fmr f15, FARG2 + | bl extern floor + | lwz r0, 36(sp) + | fmul FARG1, FARG1, f15 + | mtlr r0 + | fsub FARG1, f14, FARG1 + | lfd f14, 16(sp); lfd f15, 24(sp); addi sp, sp, 32; blr + |1: + | b extern pow + |2: + | cmplwi CARG1, 7; beq >1; bgt >2 + | fneg FARG1, FARG1; blr + |1: + | fabs FARG1, FARG1; blr + |2: +#if LJ_HASJIT + | cmplwi CARG1, 9; beq >9; bgt >2 + | b extern atan2 + | // No support needed for IR_LDEXP. + |2: + | cmplwi CARG1, 11; bgt >9 + | fsub f0, FARG1, FARG2 + | beq >1 + | fsel FARG1, f0, FARG2, FARG1 // IR_MAX + | blr + |1: + | fsel FARG1, f0, FARG1, FARG2 // IR_MIN + | blr + |9: + | NYI // Bad op. +#else + | NYI // Other operations only needed by JIT compiler. +#endif + | + |//----------------------------------------------------------------------- + |//-- Miscellaneous functions -------------------------------------------- + |//----------------------------------------------------------------------- + | + |// void lj_vm_cachesync(void *start, void *end) + |// Flush D-Cache and invalidate I-Cache. Assumes 32 byte cache line size. + |// This is a good lower bound, except for very ancient PPC models. + |->vm_cachesync: + | // Compute start of first cache line and number of cache lines. + | rlwinm CARG1, CARG1, 0, 0, 26 + | sub CARG2, CARG2, CARG1 + | addi CARG2, CARG2, 31 + | rlwinm. CARG2, CARG2, 27, 5, 31 + | beqlr + | mtctr CARG2 + | mr CARG3, CARG1 + |1: // Flush D-Cache. + | dcbst r0, CARG1 + | addi CARG1, CARG1, 32 + | bdnz <1 + | sync + | mtctr CARG2 + |1: // Invalidate I-Cache. + | icbi r0, CARG3 + | addi CARG3, CARG3, 32 + | bdnz <1 + | isync + | blr + | + |//----------------------------------------------------------------------- + |//-- FFI helper functions ----------------------------------------------- + |//----------------------------------------------------------------------- + | + |// Handler for callback functions. Callback slot number in r11, g in r12. + |->vm_ffi_callback: +#if LJ_HASFFI + |.type CTSTATE, CTState, PC + | saveregs + | lwz CTSTATE, GL:r12->ctype_state + | addi DISPATCH, r12, GG_G2DISP + | stw r11, CTSTATE->cb.slot + | stw r3, CTSTATE->cb.gpr[0] + | stfd f1, CTSTATE->cb.fpr[0] + | stw r4, CTSTATE->cb.gpr[1] + | stfd f2, CTSTATE->cb.fpr[1] + | stw r5, CTSTATE->cb.gpr[2] + | stfd f3, CTSTATE->cb.fpr[2] + | stw r6, CTSTATE->cb.gpr[3] + | stfd f4, CTSTATE->cb.fpr[3] + | stw r7, CTSTATE->cb.gpr[4] + | stfd f5, CTSTATE->cb.fpr[4] + | stw r8, CTSTATE->cb.gpr[5] + | stfd f6, CTSTATE->cb.fpr[5] + | stw r9, CTSTATE->cb.gpr[6] + | stfd f7, CTSTATE->cb.fpr[6] + | stw r10, CTSTATE->cb.gpr[7] + | stfd f8, CTSTATE->cb.fpr[7] + | addi TMP0, sp, CFRAME_SPACE+8 + | stw TMP0, CTSTATE->cb.stack + | mr CARG1, CTSTATE + | stw CTSTATE, SAVE_PC // Any value outside of bytecode is ok. + | mr CARG2, sp + | bl extern lj_ccallback_enter // (CTState *cts, void *cf) + | // Returns lua_State *. + | lwz BASE, L:CRET1->base + | li TISNUM, LJ_TISNUM // Setup type comparison constants. + | lwz RC, L:CRET1->top + | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). + | li ZERO, 0 + | mr L, CRET1 + | stw TMP3, TMPD + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float). + | li TISNIL, LJ_TNIL + | li_vmstate INTERP + | lfs TOBIT, TMPD + | stw TMP3, TMPD + | sub RC, RC, BASE + | st_vmstate + | lfs TONUM, TMPD + | ins_callt +#endif + | + |->cont_ffi_callback: // Return from FFI callback. +#if LJ_HASFFI + | lwz CTSTATE, DISPATCH_GL(ctype_state)(DISPATCH) + | stw BASE, L->base + | stw RB, L->top + | stw L, CTSTATE->L + | mr CARG1, CTSTATE + | mr CARG2, RA + | bl extern lj_ccallback_leave // (CTState *cts, TValue *o) + | lwz CRET1, CTSTATE->cb.gpr[0] + | lfd FARG1, CTSTATE->cb.fpr[0] + | lwz CRET2, CTSTATE->cb.gpr[1] + | b ->vm_leave_unw +#endif + | + |->vm_ffi_call: // Call C function via FFI. + | // Caveat: needs special frame unwinding, see below. +#if LJ_HASFFI + | .type CCSTATE, CCallState, CARG1 + | lwz TMP1, CCSTATE->spadj + | mflr TMP0 + | lbz CARG2, CCSTATE->nsp + | lbz CARG3, CCSTATE->nfpr + | neg TMP1, TMP1 + | stw TMP0, 4(sp) + | cmpwi cr1, CARG3, 0 + | mr TMP2, sp + | addic. CARG2, CARG2, -1 + | stwux sp, sp, TMP1 + | crnot 4*cr1+eq, 4*cr1+eq // For vararg calls. + | stw r14, -4(TMP2) + | stw CCSTATE, -8(TMP2) + | mr r14, TMP2 + | la TMP1, CCSTATE->stack + | slwi CARG2, CARG2, 2 + | blty >2 + | la TMP2, 8(sp) + |1: + | lwzx TMP0, TMP1, CARG2 + | stwx TMP0, TMP2, CARG2 + | addic. CARG2, CARG2, -4 + | bge <1 + |2: + | bney cr1, >3 + | lfd f1, CCSTATE->fpr[0] + | lfd f2, CCSTATE->fpr[1] + | lfd f3, CCSTATE->fpr[2] + | lfd f4, CCSTATE->fpr[3] + | lfd f5, CCSTATE->fpr[4] + | lfd f6, CCSTATE->fpr[5] + | lfd f7, CCSTATE->fpr[6] + | lfd f8, CCSTATE->fpr[7] + |3: + | lwz TMP0, CCSTATE->func + | lwz CARG2, CCSTATE->gpr[1] + | lwz CARG3, CCSTATE->gpr[2] + | lwz CARG4, CCSTATE->gpr[3] + | lwz CARG5, CCSTATE->gpr[4] + | mtctr TMP0 + | lwz r8, CCSTATE->gpr[5] + | lwz r9, CCSTATE->gpr[6] + | lwz r10, CCSTATE->gpr[7] + | lwz CARG1, CCSTATE->gpr[0] // Do this last, since CCSTATE is CARG1. + | bctrl + | lwz CCSTATE:TMP1, -8(r14) + | lwz TMP2, -4(r14) + | lwz TMP0, 4(r14) + | stw CARG1, CCSTATE:TMP1->gpr[0] + | stfd FARG1, CCSTATE:TMP1->fpr[0] + | stw CARG2, CCSTATE:TMP1->gpr[1] + | mtlr TMP0 + | stw CARG3, CCSTATE:TMP1->gpr[2] + | mr sp, r14 + | stw CARG4, CCSTATE:TMP1->gpr[3] + | mr r14, TMP2 + | blr +#endif + |// Note: vm_ffi_call must be the last function in this object file! + | + |//----------------------------------------------------------------------- +} + +/* Generate the code for a single instruction. */ +static void build_ins(BuildCtx *ctx, BCOp op, int defop) +{ + int vk = 0; + |=>defop: + + switch (op) { + + /* -- Comparison ops ---------------------------------------------------- */ + + /* Remember: all ops branch for a true comparison, fall through otherwise. */ + + case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: + | // RA = src1*8, RD = src2*8, JMP with RD = target + if (LJ_DUALNUM) { + | lwzux TMP0, RA, BASE + | addi PC, PC, 4 + | lwz CARG2, 4(RA) + | lwzux TMP1, RD, BASE + | lwz TMP2, -4(PC) + | checknum cr0, TMP0 + | lwz CARG3, 4(RD) + | decode_RD4 TMP2, TMP2 + | checknum cr1, TMP1 + | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) + | bne cr0, >7 + | bne cr1, >8 + | cmpw CARG2, CARG3 + if (op == BC_ISLT) { + | bge >2 + } else if (op == BC_ISGE) { + | blt >2 + } else if (op == BC_ISLE) { + | bgt >2 + } else { + | ble >2 + } + |1: + | add PC, PC, TMP2 + |2: + | ins_next + | + |7: // RA is not an integer. + | bgt cr0, ->vmeta_comp + | // RA is a number. + | lfd f0, 0(RA) + | bgt cr1, ->vmeta_comp + | blt cr1, >4 + | // RA is a number, RD is an integer. + | tonum_i f1, CARG3 + | b >5 + | + |8: // RA is an integer, RD is not an integer. + | bgt cr1, ->vmeta_comp + | // RA is an integer, RD is a number. + | tonum_i f0, CARG2 + |4: + | lfd f1, 0(RD) + |5: + | fcmpu cr0, f0, f1 + if (op == BC_ISLT) { + | bge <2 + } else if (op == BC_ISGE) { + | blt <2 + } else if (op == BC_ISLE) { + | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq + | bge <2 + } else { + | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq + | blt <2 + } + | b <1 + } else { + | lwzx TMP0, BASE, RA + | addi PC, PC, 4 + | lfdx f0, BASE, RA + | lwzx TMP1, BASE, RD + | checknum cr0, TMP0 + | lwz TMP2, -4(PC) + | lfdx f1, BASE, RD + | checknum cr1, TMP1 + | decode_RD4 TMP2, TMP2 + | bge cr0, ->vmeta_comp + | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) + | bge cr1, ->vmeta_comp + | fcmpu cr0, f0, f1 + if (op == BC_ISLT) { + | bge >1 + } else if (op == BC_ISGE) { + | blt >1 + } else if (op == BC_ISLE) { + | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq + | bge >1 + } else { + | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq + | blt >1 + } + | add PC, PC, TMP2 + |1: + | ins_next + } + break; + + case BC_ISEQV: case BC_ISNEV: + vk = op == BC_ISEQV; + | // RA = src1*8, RD = src2*8, JMP with RD = target + if (LJ_DUALNUM) { + | lwzux TMP0, RA, BASE + | addi PC, PC, 4 + | lwz CARG2, 4(RA) + | lwzux TMP1, RD, BASE + | checknum cr0, TMP0 + | lwz TMP2, -4(PC) + | checknum cr1, TMP1 + | decode_RD4 TMP2, TMP2 + | lwz CARG3, 4(RD) + | cror 4*cr7+gt, 4*cr0+gt, 4*cr1+gt + | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) + if (vk) { + | ble cr7, ->BC_ISEQN_Z + } else { + | ble cr7, ->BC_ISNEN_Z + } + } else { + | lwzux TMP0, RA, BASE + | lwz TMP2, 0(PC) + | lfd f0, 0(RA) + | addi PC, PC, 4 + | lwzux TMP1, RD, BASE + | checknum cr0, TMP0 + | decode_RD4 TMP2, TMP2 + | lfd f1, 0(RD) + | checknum cr1, TMP1 + | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) + | bge cr0, >5 + | bge cr1, >5 + | fcmpu cr0, f0, f1 + if (vk) { + | bne >1 + | add PC, PC, TMP2 + } else { + | beq >1 + | add PC, PC, TMP2 + } + |1: + | ins_next + } + |5: // Either or both types are not numbers. + if (!LJ_DUALNUM) { + | lwz CARG2, 4(RA) + | lwz CARG3, 4(RD) + } + if (LJ_HASFFI) { + | cmpwi cr7, TMP0, LJ_TCDATA + | cmpwi cr5, TMP1, LJ_TCDATA + } + | not TMP3, TMP0 + | cmplw TMP0, TMP1 + | cmplwi cr1, TMP3, ~LJ_TISPRI // Primitive? + if (LJ_HASFFI) { + | cror 4*cr7+eq, 4*cr7+eq, 4*cr5+eq + } + | cmplwi cr6, TMP3, ~LJ_TISTABUD // Table or userdata? + if (LJ_HASFFI) { + | beq cr7, ->vmeta_equal_cd + } + | cmplw cr5, CARG2, CARG3 + | crandc 4*cr0+gt, 4*cr0+eq, 4*cr1+gt // 2: Same type and primitive. + | crorc 4*cr0+lt, 4*cr5+eq, 4*cr0+eq // 1: Same tv or different type. + | crand 4*cr0+eq, 4*cr0+eq, 4*cr5+eq // 0: Same type and same tv. + | mr SAVE0, PC + | cror 4*cr0+eq, 4*cr0+eq, 4*cr0+gt // 0 or 2. + | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+gt // 1 or 2. + if (vk) { + | bne cr0, >6 + | add PC, PC, TMP2 + |6: + } else { + | beq cr0, >6 + | add PC, PC, TMP2 + |6: + } + if (LJ_DUALNUM) { + | bge cr0, >2 // Done if 1 or 2. + |1: + | ins_next + |2: + } else { + | blt cr0, <1 // Done if 1 or 2. + } + | blt cr6, <1 // Done if not tab/ud. + | + | // Different tables or userdatas. Need to check __eq metamethod. + | // Field metatable must be at same offset for GCtab and GCudata! + | lwz TAB:TMP2, TAB:CARG2->metatable + | li CARG4, 1-vk // ne = 0 or 1. + | cmplwi TAB:TMP2, 0 + | beq <1 // No metatable? + | lbz TMP2, TAB:TMP2->nomm + | andi. TMP2, TMP2, 1<vmeta_equal // Handle __eq metamethod. + break; + + case BC_ISEQS: case BC_ISNES: + vk = op == BC_ISEQS; + | // RA = src*8, RD = str_const*8 (~), JMP with RD = target + | lwzux TMP0, RA, BASE + | srwi RD, RD, 1 + | lwz STR:TMP3, 4(RA) + | lwz TMP2, 0(PC) + | subfic RD, RD, -4 + | addi PC, PC, 4 + if (LJ_HASFFI) { + | cmpwi TMP0, LJ_TCDATA + } + | lwzx STR:TMP1, KBASE, RD // KBASE-4-str_const*4 + | subfic TMP0, TMP0, LJ_TSTR + if (LJ_HASFFI) { + | beq ->vmeta_equal_cd + } + | sub TMP1, STR:TMP1, STR:TMP3 + | or TMP0, TMP0, TMP1 + | decode_RD4 TMP2, TMP2 + | subfic TMP0, TMP0, 0 + | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) + | subfe TMP1, TMP1, TMP1 + if (vk) { + | andc TMP2, TMP2, TMP1 + } else { + | and TMP2, TMP2, TMP1 + } + | add PC, PC, TMP2 + | ins_next + break; + + case BC_ISEQN: case BC_ISNEN: + vk = op == BC_ISEQN; + | // RA = src*8, RD = num_const*8, JMP with RD = target + if (LJ_DUALNUM) { + | lwzux TMP0, RA, BASE + | addi PC, PC, 4 + | lwz CARG2, 4(RA) + | lwzux TMP1, RD, KBASE + | checknum cr0, TMP0 + | lwz TMP2, -4(PC) + | checknum cr1, TMP1 + | decode_RD4 TMP2, TMP2 + | lwz CARG3, 4(RD) + | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) + if (vk) { + |->BC_ISEQN_Z: + } else { + |->BC_ISNEN_Z: + } + | bne cr0, >7 + | bne cr1, >8 + | cmpw CARG2, CARG3 + |4: + } else { + if (vk) { + |->BC_ISEQN_Z: // Dummy label. + } else { + |->BC_ISNEN_Z: // Dummy label. + } + | lwzx TMP0, BASE, RA + | addi PC, PC, 4 + | lfdx f0, BASE, RA + | lwz TMP2, -4(PC) + | lfdx f1, KBASE, RD + | decode_RD4 TMP2, TMP2 + | checknum TMP0 + | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) + | bge >3 + | fcmpu cr0, f0, f1 + } + if (vk) { + | bne >1 + | add PC, PC, TMP2 + |1: + if (!LJ_HASFFI) { + |3: + } + } else { + | beq >2 + |1: + if (!LJ_HASFFI) { + |3: + } + | add PC, PC, TMP2 + |2: + } + | ins_next + if (LJ_HASFFI) { + |3: + | cmpwi TMP0, LJ_TCDATA + | beq ->vmeta_equal_cd + | b <1 + } + if (LJ_DUALNUM) { + |7: // RA is not an integer. + | bge cr0, <3 + | // RA is a number. + | lfd f0, 0(RA) + | blt cr1, >1 + | // RA is a number, RD is an integer. + | tonum_i f1, CARG3 + | b >2 + | + |8: // RA is an integer, RD is a number. + | tonum_i f0, CARG2 + |1: + | lfd f1, 0(RD) + |2: + | fcmpu cr0, f0, f1 + | b <4 + } + break; + + case BC_ISEQP: case BC_ISNEP: + vk = op == BC_ISEQP; + | // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target + | lwzx TMP0, BASE, RA + | srwi TMP1, RD, 3 + | lwz TMP2, 0(PC) + | not TMP1, TMP1 + | addi PC, PC, 4 + if (LJ_HASFFI) { + | cmpwi TMP0, LJ_TCDATA + } + | sub TMP0, TMP0, TMP1 + if (LJ_HASFFI) { + | beq ->vmeta_equal_cd + } + | decode_RD4 TMP2, TMP2 + | addic TMP0, TMP0, -1 + | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) + | subfe TMP1, TMP1, TMP1 + if (vk) { + | and TMP2, TMP2, TMP1 + } else { + | andc TMP2, TMP2, TMP1 + } + | add PC, PC, TMP2 + | ins_next + break; + + /* -- Unary test and copy ops ------------------------------------------- */ + + case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: + | // RA = dst*8 or unused, RD = src*8, JMP with RD = target + | lwzx TMP0, BASE, RD + | lwz INS, 0(PC) + | addi PC, PC, 4 + if (op == BC_IST || op == BC_ISF) { + | subfic TMP0, TMP0, LJ_TTRUE + | decode_RD4 TMP2, INS + | subfe TMP1, TMP1, TMP1 + | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16) + if (op == BC_IST) { + | andc TMP2, TMP2, TMP1 + } else { + | and TMP2, TMP2, TMP1 + } + | add PC, PC, TMP2 + } else { + | li TMP1, LJ_TFALSE + | lfdx f0, BASE, RD + | cmplw TMP0, TMP1 + if (op == BC_ISTC) { + | bge >1 + } else { + | blt >1 + } + | addis PC, PC, -(BCBIAS_J*4 >> 16) + | decode_RD4 TMP2, INS + | stfdx f0, BASE, RA + | add PC, PC, TMP2 + |1: + } + | ins_next + break; + + /* -- Unary ops --------------------------------------------------------- */ + + case BC_MOV: + | // RA = dst*8, RD = src*8 + | ins_next1 + | lfdx f0, BASE, RD + | stfdx f0, BASE, RA + | ins_next2 + break; + case BC_NOT: + | // RA = dst*8, RD = src*8 + | ins_next1 + | lwzx TMP0, BASE, RD + | subfic TMP1, TMP0, LJ_TTRUE + | adde TMP0, TMP0, TMP1 + | stwx TMP0, BASE, RA + | ins_next2 + break; + case BC_UNM: + | // RA = dst*8, RD = src*8 + | lwzux TMP1, RD, BASE + | lwz TMP0, 4(RD) + | checknum TMP1 + if (LJ_DUALNUM) { + | bne >5 + | nego. TMP0, TMP0 + | bso >4 + |1: + | ins_next1 + | stwux TISNUM, RA, BASE + | stw TMP0, 4(RA) + |3: + | ins_next2 + |4: // Potential overflow. + | mcrxr cr0; bley <1 // Ignore unrelated overflow. + | lus TMP1, 0x41e0 // 2^31. + | li TMP0, 0 + | b >7 + } + |5: + | bge ->vmeta_unm + | xoris TMP1, TMP1, 0x8000 + |7: + | ins_next1 + | stwux TMP1, RA, BASE + | stw TMP0, 4(RA) + if (LJ_DUALNUM) { + | b <3 + } else { + | ins_next2 + } + break; + case BC_LEN: + | // RA = dst*8, RD = src*8 + | lwzux TMP0, RD, BASE + | lwz CARG1, 4(RD) + | checkstr TMP0; bne >2 + | lwz CRET1, STR:CARG1->len + |1: + if (LJ_DUALNUM) { + | ins_next1 + | stwux TISNUM, RA, BASE + | stw CRET1, 4(RA) + } else { + | tonum_u f0, CRET1 // Result is a non-negative integer. + | ins_next1 + | stfdx f0, BASE, RA + } + | ins_next2 + |2: + | checktab TMP0; bne ->vmeta_len +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | lwz TAB:TMP2, TAB:CARG1->metatable + | cmplwi TAB:TMP2, 0 + | bne >9 + |3: +#endif + |->BC_LEN_Z: + | bl extern lj_tab_len // (GCtab *t) + | // Returns uint32_t (but less than 2^31). + | b <1 +#ifdef LUAJIT_ENABLE_LUA52COMPAT + |9: + | lbz TMP0, TAB:TMP2->nomm + | andi. TMP0, TMP0, 1<vmeta_len +#endif + break; + + /* -- Binary ops -------------------------------------------------------- */ + + |.macro ins_arithpre + | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8 + ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); + ||switch (vk) { + ||case 0: + | lwzx TMP1, BASE, RB + ||if (LJ_DUALNUM) { + | lwzx TMP2, KBASE, RC + ||} + | lfdx f14, BASE, RB + | lfdx f15, KBASE, RC + ||if (LJ_DUALNUM) { + | checknum cr0, TMP1 + | checknum cr1, TMP2 + | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt + | bge ->vmeta_arith_vn + ||} else { + | checknum TMP1; bge ->vmeta_arith_vn + ||} + || break; + ||case 1: + | lwzx TMP1, BASE, RB + ||if (LJ_DUALNUM) { + | lwzx TMP2, KBASE, RC + ||} + | lfdx f15, BASE, RB + | lfdx f14, KBASE, RC + ||if (LJ_DUALNUM) { + | checknum cr0, TMP1 + | checknum cr1, TMP2 + | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt + | bge ->vmeta_arith_nv + ||} else { + | checknum TMP1; bge ->vmeta_arith_nv + ||} + || break; + ||default: + | lwzx TMP1, BASE, RB + | lwzx TMP2, BASE, RC + | lfdx f14, BASE, RB + | lfdx f15, BASE, RC + | checknum cr0, TMP1 + | checknum cr1, TMP2 + | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt + | bge ->vmeta_arith_vv + || break; + ||} + |.endmacro + | + |.macro ins_arithfallback, ins + ||switch (vk) { + ||case 0: + | ins ->vmeta_arith_vn2 + || break; + ||case 1: + | ins ->vmeta_arith_nv2 + || break; + ||default: + | ins ->vmeta_arith_vv2 + || break; + ||} + |.endmacro + | + |.macro intmod, a, b, c + | bl ->vm_modi + |.endmacro + | + |.macro fpmod, a, b, c + |->BC_MODVN_Z: + | fdiv FARG1, b, c + | // NYI: Use internal implementation of floor. + | bl extern floor // floor(b/c) + | fmul a, FARG1, c + | fsub a, b, a // b - floor(b/c)*c + |.endmacro + | + |.macro ins_arithfp, fpins + | ins_arithpre + |.if "fpins" == "fpmod_" + | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway. + |.else + | fpins f0, f14, f15 + | ins_next1 + | stfdx f0, BASE, RA + | ins_next2 + |.endif + |.endmacro + | + |.macro ins_arithdn, intins, fpins + | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8 + ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); + ||switch (vk) { + ||case 0: + | lwzux TMP1, RB, BASE + | lwzux TMP2, RC, KBASE + | lwz CARG1, 4(RB) + | checknum cr0, TMP1 + | lwz CARG2, 4(RC) + || break; + ||case 1: + | lwzux TMP1, RB, BASE + | lwzux TMP2, RC, KBASE + | lwz CARG2, 4(RB) + | checknum cr0, TMP1 + | lwz CARG1, 4(RC) + || break; + ||default: + | lwzux TMP1, RB, BASE + | lwzux TMP2, RC, BASE + | lwz CARG1, 4(RB) + | checknum cr0, TMP1 + | lwz CARG2, 4(RC) + || break; + ||} + | checknum cr1, TMP2 + | bne >5 + | bne cr1, >5 + | intins CARG1, CARG1, CARG2 + | bso >4 + |1: + | ins_next1 + | stwux TISNUM, RA, BASE + | stw CARG1, 4(RA) + |2: + | ins_next2 + |4: // Overflow. + | mcrxr cr0; bley <1 // Ignore unrelated overflow. + | ins_arithfallback b + |5: // FP variant. + ||if (vk == 1) { + | lfd f15, 0(RB) + | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt + | lfd f14, 0(RC) + ||} else { + | lfd f14, 0(RB) + | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt + | lfd f15, 0(RC) + ||} + | ins_arithfallback bge + |.if "fpins" == "fpmod_" + | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway. + |.else + | fpins f0, f14, f15 + | ins_next1 + | stfdx f0, BASE, RA + | b <2 + |.endif + |.endmacro + | + |.macro ins_arith, intins, fpins + ||if (LJ_DUALNUM) { + | ins_arithdn intins, fpins + ||} else { + | ins_arithfp fpins + ||} + |.endmacro + + case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: + | ins_arith addo., fadd + break; + case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: + | ins_arith subo., fsub + break; + case BC_MULVN: case BC_MULNV: case BC_MULVV: + | ins_arith mullwo., fmul + break; + case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: + | ins_arithfp fdiv + break; + case BC_MODVN: + | ins_arith intmod, fpmod + break; + case BC_MODNV: case BC_MODVV: + | ins_arith intmod, fpmod_ + break; + case BC_POW: + | // NYI: (partial) integer arithmetic. + | lwzx TMP1, BASE, RB + | lfdx FARG1, BASE, RB + | lwzx TMP2, BASE, RC + | lfdx FARG2, BASE, RC + | checknum cr0, TMP1 + | checknum cr1, TMP2 + | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt + | bge ->vmeta_arith_vv + | bl extern pow + | ins_next1 + | stfdx FARG1, BASE, RA + | ins_next2 + break; + + case BC_CAT: + | // RA = dst*8, RB = src_start*8, RC = src_end*8 + | sub CARG3, RC, RB + | stw BASE, L->base + | add CARG2, BASE, RC + | mr SAVE0, RB + |->BC_CAT_Z: + | stw PC, SAVE_PC + | mr CARG1, L + | srwi CARG3, CARG3, 3 + | bl extern lj_meta_cat // (lua_State *L, TValue *top, int left) + | // Returns NULL (finished) or TValue * (metamethod). + | cmplwi CRET1, 0 + | lwz BASE, L->base + | bne ->vmeta_binop + | ins_next1 + | lfdx f0, BASE, SAVE0 // Copy result from RB to RA. + | stfdx f0, BASE, RA + | ins_next2 + break; + + /* -- Constant ops ------------------------------------------------------ */ + + case BC_KSTR: + | // RA = dst*8, RD = str_const*8 (~) + | srwi TMP1, RD, 1 + | subfic TMP1, TMP1, -4 + | ins_next1 + | lwzx TMP0, KBASE, TMP1 // KBASE-4-str_const*4 + | li TMP2, LJ_TSTR + | stwux TMP2, RA, BASE + | stw TMP0, 4(RA) + | ins_next2 + break; + case BC_KCDATA: +#if LJ_HASFFI + | // RA = dst*8, RD = cdata_const*8 (~) + | srwi TMP1, RD, 1 + | subfic TMP1, TMP1, -4 + | ins_next1 + | lwzx TMP0, KBASE, TMP1 // KBASE-4-cdata_const*4 + | li TMP2, LJ_TCDATA + | stwux TMP2, RA, BASE + | stw TMP0, 4(RA) + | ins_next2 +#endif + break; + case BC_KSHORT: + | // RA = dst*8, RD = int16_literal*8 + if (LJ_DUALNUM) { + | slwi RD, RD, 13 + | srawi RD, RD, 16 + | ins_next1 + | stwux TISNUM, RA, BASE + | stw RD, 4(RA) + | ins_next2 + } else { + | // The soft-float approach is faster. + | slwi RD, RD, 13 + | srawi TMP1, RD, 31 + | xor TMP2, TMP1, RD + | sub TMP2, TMP2, TMP1 // TMP2 = abs(x) + | cntlzw TMP3, TMP2 + | subfic TMP1, TMP3, 0x40d // TMP1 = exponent-1 + | slw TMP2, TMP2, TMP3 // TMP2 = left aligned mantissa + | subfic TMP3, RD, 0 + | slwi TMP1, TMP1, 20 + | rlwimi RD, TMP2, 21, 1, 31 // hi = sign(x) | (mantissa>>11) + | subfe TMP0, TMP0, TMP0 + | add RD, RD, TMP1 // hi = hi + exponent-1 + | and RD, RD, TMP0 // hi = x == 0 ? 0 : hi + | ins_next1 + | stwux RD, RA, BASE + | stw ZERO, 4(RA) + | ins_next2 + } + break; + case BC_KNUM: + | // RA = dst*8, RD = num_const*8 + | ins_next1 + | lfdx f0, KBASE, RD + | stfdx f0, BASE, RA + | ins_next2 + break; + case BC_KPRI: + | // RA = dst*8, RD = primitive_type*8 (~) + | srwi TMP1, RD, 3 + | not TMP0, TMP1 + | ins_next1 + | stwx TMP0, BASE, RA + | ins_next2 + break; + case BC_KNIL: + | // RA = base*8, RD = end*8 + | stwx TISNIL, BASE, RA + | addi RA, RA, 8 + |1: + | stwx TISNIL, BASE, RA + | cmpw RA, RD + | addi RA, RA, 8 + | blt <1 + | ins_next_ + break; + + /* -- Upvalue and function ops ------------------------------------------ */ + + case BC_UGET: + | // RA = dst*8, RD = uvnum*8 + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | srwi RD, RD, 1 + | addi RD, RD, offsetof(GCfuncL, uvptr) + | lwzx UPVAL:RB, LFUNC:RB, RD + | ins_next1 + | lwz TMP1, UPVAL:RB->v + | lfd f0, 0(TMP1) + | stfdx f0, BASE, RA + | ins_next2 + break; + case BC_USETV: + | // RA = uvnum*8, RD = src*8 + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | srwi RA, RA, 1 + | addi RA, RA, offsetof(GCfuncL, uvptr) + | lfdux f0, RD, BASE + | lwzx UPVAL:RB, LFUNC:RB, RA + | lbz TMP3, UPVAL:RB->marked + | lwz CARG2, UPVAL:RB->v + | andi. TMP3, TMP3, LJ_GC_BLACK // isblack(uv) + | lbz TMP0, UPVAL:RB->closed + | lwz TMP2, 0(RD) + | stfd f0, 0(CARG2) + | cmplwi cr1, TMP0, 0 + | lwz TMP1, 4(RD) + | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq + | subi TMP2, TMP2, (LJ_TISNUM+1) + | bne >2 // Upvalue is closed and black? + |1: + | ins_next + | + |2: // Check if new value is collectable. + | cmplwi TMP2, LJ_TISGCV - (LJ_TISNUM+1) + | bge <1 // tvisgcv(v) + | lbz TMP3, GCOBJ:TMP1->gch.marked + | andi. TMP3, TMP3, LJ_GC_WHITES // iswhite(v) + | la CARG1, GG_DISP2G(DISPATCH) + | // Crossed a write barrier. Move the barrier forward. + | beq <1 + | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) + | b <1 + break; + case BC_USETS: + | // RA = uvnum*8, RD = str_const*8 (~) + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | srwi TMP1, RD, 1 + | srwi RA, RA, 1 + | subfic TMP1, TMP1, -4 + | addi RA, RA, offsetof(GCfuncL, uvptr) + | lwzx STR:TMP1, KBASE, TMP1 // KBASE-4-str_const*4 + | lwzx UPVAL:RB, LFUNC:RB, RA + | lbz TMP3, UPVAL:RB->marked + | lwz CARG2, UPVAL:RB->v + | andi. TMP3, TMP3, LJ_GC_BLACK // isblack(uv) + | lbz TMP3, STR:TMP1->marked + | lbz TMP2, UPVAL:RB->closed + | li TMP0, LJ_TSTR + | stw STR:TMP1, 4(CARG2) + | stw TMP0, 0(CARG2) + | bne >2 + |1: + | ins_next + | + |2: // Check if string is white and ensure upvalue is closed. + | andi. TMP3, TMP3, LJ_GC_WHITES // iswhite(str) + | cmplwi cr1, TMP2, 0 + | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq + | la CARG1, GG_DISP2G(DISPATCH) + | // Crossed a write barrier. Move the barrier forward. + | beq <1 + | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) + | b <1 + break; + case BC_USETN: + | // RA = uvnum*8, RD = num_const*8 + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | srwi RA, RA, 1 + | addi RA, RA, offsetof(GCfuncL, uvptr) + | lfdx f0, KBASE, RD + | lwzx UPVAL:RB, LFUNC:RB, RA + | ins_next1 + | lwz TMP1, UPVAL:RB->v + | stfd f0, 0(TMP1) + | ins_next2 + break; + case BC_USETP: + | // RA = uvnum*8, RD = primitive_type*8 (~) + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | srwi RA, RA, 1 + | srwi TMP0, RD, 3 + | addi RA, RA, offsetof(GCfuncL, uvptr) + | not TMP0, TMP0 + | lwzx UPVAL:RB, LFUNC:RB, RA + | ins_next1 + | lwz TMP1, UPVAL:RB->v + | stw TMP0, 0(TMP1) + | ins_next2 + break; + + case BC_UCLO: + | // RA = level*8, RD = target + | lwz TMP1, L->openupval + | branch_RD // Do this first since RD is not saved. + | stw BASE, L->base + | cmplwi TMP1, 0 + | mr CARG1, L + | beq >1 + | add CARG2, BASE, RA + | bl extern lj_func_closeuv // (lua_State *L, TValue *level) + | lwz BASE, L->base + |1: + | ins_next + break; + + case BC_FNEW: + | // RA = dst*8, RD = proto_const*8 (~) (holding function prototype) + | srwi TMP1, RD, 1 + | stw BASE, L->base + | subfic TMP1, TMP1, -4 + | stw PC, SAVE_PC + | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4 + | mr CARG1, L + | lwz CARG3, FRAME_FUNC(BASE) + | // (lua_State *L, GCproto *pt, GCfuncL *parent) + | bl extern lj_func_newL_gc + | // Returns GCfuncL *. + | lwz BASE, L->base + | li TMP0, LJ_TFUNC + | stwux TMP0, RA, BASE + | stw LFUNC:CRET1, 4(RA) + | ins_next + break; + + /* -- Table ops --------------------------------------------------------- */ + + case BC_TNEW: + case BC_TDUP: + | // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~) + | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH) + | mr CARG1, L + | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) + | stw BASE, L->base + | cmplw TMP0, TMP1 + | stw PC, SAVE_PC + | bge >5 + |1: + if (op == BC_TNEW) { + | rlwinm CARG2, RD, 29, 21, 31 + | rlwinm CARG3, RD, 18, 27, 31 + | cmpwi CARG2, 0x7ff; beq >3 + |2: + | bl extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits) + | // Returns Table *. + } else { + | srwi TMP1, RD, 1 + | subfic TMP1, TMP1, -4 + | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4 + | bl extern lj_tab_dup // (lua_State *L, Table *kt) + | // Returns Table *. + } + | lwz BASE, L->base + | li TMP0, LJ_TTAB + | stwux TMP0, RA, BASE + | stw TAB:CRET1, 4(RA) + | ins_next + if (op == BC_TNEW) { + |3: + | li CARG2, 0x801 + | b <2 + } + |5: + | mr SAVE0, RD + | bl extern lj_gc_step_fixtop // (lua_State *L) + | mr RD, SAVE0 + | mr CARG1, L + | b <1 + break; + + case BC_GGET: + | // RA = dst*8, RD = str_const*8 (~) + case BC_GSET: + | // RA = src*8, RD = str_const*8 (~) + | lwz LFUNC:TMP2, FRAME_FUNC(BASE) + | srwi TMP1, RD, 1 + | lwz TAB:RB, LFUNC:TMP2->env + | subfic TMP1, TMP1, -4 + | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 + if (op == BC_GGET) { + | b ->BC_TGETS_Z + } else { + | b ->BC_TSETS_Z + } + break; + + case BC_TGETV: + | // RA = dst*8, RB = table*8, RC = key*8 + | lwzux CARG1, RB, BASE + | lwzux CARG2, RC, BASE + | lwz TAB:RB, 4(RB) + if (LJ_DUALNUM) { + | lwz RC, 4(RC) + } else { + | lfd f0, 0(RC) + } + | checktab CARG1 + | checknum cr1, CARG2 + | bne ->vmeta_tgetv + if (LJ_DUALNUM) { + | lwz TMP0, TAB:RB->asize + | bne cr1, >5 + | lwz TMP1, TAB:RB->array + | cmplw TMP0, RC + | slwi TMP2, RC, 3 + } else { + | bge cr1, >5 + | // Convert number key to integer, check for integerness and range. + | fctiwz f1, f0 + | fadd f2, f0, TOBIT + | stfd f1, TMPD + | lwz TMP0, TAB:RB->asize + | fsub f2, f2, TOBIT + | lwz TMP2, TMPD_LO + | lwz TMP1, TAB:RB->array + | fcmpu cr1, f0, f2 + | cmplw cr0, TMP0, TMP2 + | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+eq + | slwi TMP2, TMP2, 3 + } + | ble ->vmeta_tgetv // Integer key and in array part? + | lwzx TMP0, TMP1, TMP2 + | lfdx f14, TMP1, TMP2 + | checknil TMP0; beq >2 + |1: + | ins_next1 + | stfdx f14, BASE, RA + | ins_next2 + | + |2: // Check for __index if table value is nil. + | lwz TAB:TMP2, TAB:RB->metatable + | cmplwi TAB:TMP2, 0 + | beq <1 // No metatable: done. + | lbz TMP0, TAB:TMP2->nomm + | andi. TMP0, TMP0, 1<vmeta_tgetv + | + |5: + | checkstr CARG2; bne ->vmeta_tgetv + if (!LJ_DUALNUM) { + | lwz STR:RC, 4(RC) + } + | b ->BC_TGETS_Z // String key? + break; + case BC_TGETS: + | // RA = dst*8, RB = table*8, RC = str_const*8 (~) + | lwzux CARG1, RB, BASE + | srwi TMP1, RC, 1 + | lwz TAB:RB, 4(RB) + | subfic TMP1, TMP1, -4 + | checktab CARG1 + | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 + | bne ->vmeta_tgets1 + |->BC_TGETS_Z: + | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8 + | lwz TMP0, TAB:RB->hmask + | lwz TMP1, STR:RC->hash + | lwz NODE:TMP2, TAB:RB->node + | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask + | slwi TMP0, TMP1, 5 + | slwi TMP1, TMP1, 3 + | sub TMP1, TMP0, TMP1 + | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) + |1: + | lwz CARG1, NODE:TMP2->key + | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2) + | lwz CARG2, NODE:TMP2->val + | lwz TMP1, 4+offsetof(Node, val)(NODE:TMP2) + | checkstr CARG1; bne >4 + | cmpw TMP0, STR:RC; bne >4 + | checknil CARG2; beq >5 // Key found, but nil value? + |3: + | stwux CARG2, RA, BASE + | stw TMP1, 4(RA) + | ins_next + | + |4: // Follow hash chain. + | lwz NODE:TMP2, NODE:TMP2->next + | cmplwi NODE:TMP2, 0 + | bne <1 + | // End of hash chain: key not found, nil result. + | li CARG2, LJ_TNIL + | + |5: // Check for __index if table value is nil. + | lwz TAB:TMP2, TAB:RB->metatable + | cmplwi TAB:TMP2, 0 + | beq <3 // No metatable: done. + | lbz TMP0, TAB:TMP2->nomm + | andi. TMP0, TMP0, 1<vmeta_tgets + break; + case BC_TGETB: + | // RA = dst*8, RB = table*8, RC = index*8 + | lwzux CARG1, RB, BASE + | srwi TMP0, RC, 3 + | lwz TAB:RB, 4(RB) + | checktab CARG1; bne ->vmeta_tgetb + | lwz TMP1, TAB:RB->asize + | lwz TMP2, TAB:RB->array + | cmplw TMP0, TMP1; bge ->vmeta_tgetb + | lwzx TMP1, TMP2, RC + | lfdx f0, TMP2, RC + | checknil TMP1; beq >5 + |1: + | ins_next1 + | stfdx f0, BASE, RA + | ins_next2 + | + |5: // Check for __index if table value is nil. + | lwz TAB:TMP2, TAB:RB->metatable + | cmplwi TAB:TMP2, 0 + | beq <1 // No metatable: done. + | lbz TMP2, TAB:TMP2->nomm + | andi. TMP2, TMP2, 1<vmeta_tgetb // Caveat: preserve TMP0! + break; + + case BC_TSETV: + | // RA = src*8, RB = table*8, RC = key*8 + | lwzux CARG1, RB, BASE + | lwzux CARG2, RC, BASE + | lwz TAB:RB, 4(RB) + if (LJ_DUALNUM) { + | lwz RC, 4(RC) + } else { + | lfd f0, 0(RC) + } + | checktab CARG1 + | checknum cr1, CARG2 + | bne ->vmeta_tsetv + if (LJ_DUALNUM) { + | lwz TMP0, TAB:RB->asize + | bne cr1, >5 + | lwz TMP1, TAB:RB->array + | cmplw TMP0, RC + | slwi TMP0, RC, 3 + } else { + | bge cr1, >5 + | // Convert number key to integer, check for integerness and range. + | fctiwz f1, f0 + | fadd f2, f0, TOBIT + | stfd f1, TMPD + | lwz TMP0, TAB:RB->asize + | fsub f2, f2, TOBIT + | lwz TMP2, TMPD_LO + | lwz TMP1, TAB:RB->array + | fcmpu cr1, f0, f2 + | cmplw cr0, TMP0, TMP2 + | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+eq + | slwi TMP0, TMP2, 3 + } + | ble ->vmeta_tsetv // Integer key and in array part? + | lwzx TMP2, TMP1, TMP0 + | lbz TMP3, TAB:RB->marked + | lfdx f14, BASE, RA + | checknil TMP2; beq >3 + |1: + | andi. TMP2, TMP3, LJ_GC_BLACK // isblack(table) + | stfdx f14, TMP1, TMP0 + | bne >7 + |2: + | ins_next + | + |3: // Check for __newindex if previous value is nil. + | lwz TAB:TMP2, TAB:RB->metatable + | cmplwi TAB:TMP2, 0 + | beq <1 // No metatable: done. + | lbz TMP2, TAB:TMP2->nomm + | andi. TMP2, TMP2, 1<vmeta_tsetv + | + |5: + | checkstr CARG2; bne ->vmeta_tsetv + if (!LJ_DUALNUM) { + | lwz STR:RC, 4(RC) + } + | b ->BC_TSETS_Z // String key? + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, TMP3, TMP0 + | b <2 + break; + case BC_TSETS: + | // RA = src*8, RB = table*8, RC = str_const*8 (~) + | lwzux CARG1, RB, BASE + | srwi TMP1, RC, 1 + | lwz TAB:RB, 4(RB) + | subfic TMP1, TMP1, -4 + | checktab CARG1 + | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 + | bne ->vmeta_tsets1 + |->BC_TSETS_Z: + | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = src*8 + | lwz TMP0, TAB:RB->hmask + | lwz TMP1, STR:RC->hash + | lwz NODE:TMP2, TAB:RB->node + | stb ZERO, TAB:RB->nomm // Clear metamethod cache. + | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask + | lfdx f14, BASE, RA + | slwi TMP0, TMP1, 5 + | slwi TMP1, TMP1, 3 + | sub TMP1, TMP0, TMP1 + | lbz TMP3, TAB:RB->marked + | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) + |1: + | lwz CARG1, NODE:TMP2->key + | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2) + | lwz CARG2, NODE:TMP2->val + | lwz NODE:TMP1, NODE:TMP2->next + | checkstr CARG1; bne >5 + | cmpw TMP0, STR:RC; bne >5 + | checknil CARG2; beq >4 // Key found, but nil value? + |2: + | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) + | stfd f14, NODE:TMP2->val + | bne >7 + |3: + | ins_next + | + |4: // Check for __newindex if previous value is nil. + | lwz TAB:TMP1, TAB:RB->metatable + | cmplwi TAB:TMP1, 0 + | beq <2 // No metatable: done. + | lbz TMP0, TAB:TMP1->nomm + | andi. TMP0, TMP0, 1<vmeta_tsets + | + |5: // Follow hash chain. + | cmplwi NODE:TMP1, 0 + | mr NODE:TMP2, NODE:TMP1 + | bne <1 + | // End of hash chain: key not found, add a new one. + | + | // But check for __newindex first. + | lwz TAB:TMP1, TAB:RB->metatable + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | stw PC, SAVE_PC + | mr CARG1, L + | cmplwi TAB:TMP1, 0 + | stw BASE, L->base + | beq >6 // No metatable: continue. + | lbz TMP0, TAB:TMP1->nomm + | andi. TMP0, TMP0, 1<vmeta_tsets // 'no __newindex' flag NOT set: check. + |6: + | li TMP0, LJ_TSTR + | stw STR:RC, 4(CARG3) + | mr CARG2, TAB:RB + | stw TMP0, 0(CARG3) + | bl extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k) + | // Returns TValue *. + | lwz BASE, L->base + | stfd f14, 0(CRET1) + | b <3 // No 2nd write barrier needed. + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, TMP3, TMP0 + | b <3 + break; + case BC_TSETB: + | // RA = src*8, RB = table*8, RC = index*8 + | lwzux CARG1, RB, BASE + | srwi TMP0, RC, 3 + | lwz TAB:RB, 4(RB) + | checktab CARG1; bne ->vmeta_tsetb + | lwz TMP1, TAB:RB->asize + | lwz TMP2, TAB:RB->array + | lbz TMP3, TAB:RB->marked + | cmplw TMP0, TMP1 + | lfdx f14, BASE, RA + | bge ->vmeta_tsetb + | lwzx TMP1, TMP2, RC + | checknil TMP1; beq >5 + |1: + | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) + | stfdx f14, TMP2, RC + | bne >7 + |2: + | ins_next + | + |5: // Check for __newindex if previous value is nil. + | lwz TAB:TMP1, TAB:RB->metatable + | cmplwi TAB:TMP1, 0 + | beq <1 // No metatable: done. + | lbz TMP1, TAB:TMP1->nomm + | andi. TMP1, TMP1, 1<vmeta_tsetb // Caveat: preserve TMP0! + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, TMP3, TMP0 + | b <2 + break; + + case BC_TSETM: + | // RA = base*8 (table at base-1), RD = num_const*8 (start index) + | add RA, BASE, RA + |1: + | add TMP3, KBASE, RD + | lwz TAB:CARG2, -4(RA) // Guaranteed to be a table. + | addic. TMP0, MULTRES, -8 + | lwz TMP3, 4(TMP3) // Integer constant is in lo-word. + | srwi CARG3, TMP0, 3 + | beq >4 // Nothing to copy? + | add CARG3, CARG3, TMP3 + | lwz TMP2, TAB:CARG2->asize + | slwi TMP1, TMP3, 3 + | lbz TMP3, TAB:CARG2->marked + | cmplw CARG3, TMP2 + | add TMP2, RA, TMP0 + | lwz TMP0, TAB:CARG2->array + | bgt >5 + | add TMP1, TMP1, TMP0 + | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) + |3: // Copy result slots to table. + | lfd f0, 0(RA) + | addi RA, RA, 8 + | cmpw cr1, RA, TMP2 + | stfd f0, 0(TMP1) + | addi TMP1, TMP1, 8 + | blt cr1, <3 + | bne >7 + |4: + | ins_next + | + |5: // Need to resize array part. + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | mr SAVE0, RD + | bl extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize) + | // Must not reallocate the stack. + | mr RD, SAVE0 + | b <1 + | + |7: // Possible table write barrier for any value. Skip valiswhite check. + | barrierback TAB:CARG2, TMP3, TMP0 + | b <4 + break; + + /* -- Calls and vararg handling ----------------------------------------- */ + + case BC_CALLM: + | // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8 + | add NARGS8:RC, NARGS8:RC, MULTRES + | // Fall through. Assumes BC_CALL follows. + break; + case BC_CALL: + | // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8 + | mr TMP2, BASE + | lwzux TMP0, BASE, RA + | lwz LFUNC:RB, 4(BASE) + | subi NARGS8:RC, NARGS8:RC, 8 + | addi BASE, BASE, 8 + | checkfunc TMP0; bne ->vmeta_call + | ins_call + break; + + case BC_CALLMT: + | // RA = base*8, (RB = 0,) RC = extra_nargs*8 + | add NARGS8:RC, NARGS8:RC, MULTRES + | // Fall through. Assumes BC_CALLT follows. + break; + case BC_CALLT: + | // RA = base*8, (RB = 0,) RC = (nargs+1)*8 + | lwzux TMP0, RA, BASE + | lwz LFUNC:RB, 4(RA) + | subi NARGS8:RC, NARGS8:RC, 8 + | lwz TMP1, FRAME_PC(BASE) + | checkfunc TMP0 + | addi RA, RA, 8 + | bne ->vmeta_callt + |->BC_CALLT_Z: + | andi. TMP0, TMP1, FRAME_TYPE // Caveat: preserve cr0 until the crand. + | lbz TMP3, LFUNC:RB->ffid + | xori TMP2, TMP1, FRAME_VARG + | cmplwi cr1, NARGS8:RC, 0 + | bne >7 + |1: + | stw LFUNC:RB, FRAME_FUNC(BASE) // Copy function down, but keep PC. + | li TMP2, 0 + | cmplwi cr7, TMP3, 1 // (> FF_C) Calling a fast function? + | beq cr1, >3 + |2: + | addi TMP3, TMP2, 8 + | lfdx f0, RA, TMP2 + | cmplw cr1, TMP3, NARGS8:RC + | stfdx f0, BASE, TMP2 + | mr TMP2, TMP3 + | bne cr1, <2 + |3: + | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+gt + | beq >5 + |4: + | ins_callt + | + |5: // Tailcall to a fast function with a Lua frame below. + | lwz INS, -4(TMP1) + | decode_RA8 RA, INS + | sub TMP1, BASE, RA + | lwz LFUNC:TMP1, FRAME_FUNC-8(TMP1) + | lwz TMP1, LFUNC:TMP1->pc + | lwz KBASE, PC2PROTO(k)(TMP1) // Need to prepare KBASE. + | b <4 + | + |7: // Tailcall from a vararg function. + | andi. TMP0, TMP2, FRAME_TYPEP + | bne <1 // Vararg frame below? + | sub BASE, BASE, TMP2 // Relocate BASE down. + | lwz TMP1, FRAME_PC(BASE) + | andi. TMP0, TMP1, FRAME_TYPE + | b <1 + break; + + case BC_ITERC: + | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8)) + | mr TMP2, BASE + | add BASE, BASE, RA + | lwz TMP1, -24(BASE) + | lwz LFUNC:RB, -20(BASE) + | lfd f1, -8(BASE) + | lfd f0, -16(BASE) + | stw TMP1, 0(BASE) // Copy callable. + | stw LFUNC:RB, 4(BASE) + | checkfunc TMP1 + | stfd f1, 16(BASE) // Copy control var. + | li NARGS8:RC, 16 // Iterators get 2 arguments. + | stfdu f0, 8(BASE) // Copy state. + | bne ->vmeta_call + | ins_call + break; + + case BC_ITERN: + | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) +#if LJ_HASJIT + | // NYI: add hotloop, record BC_ITERN. +#endif + | add RA, BASE, RA + | lwz TAB:RB, -12(RA) + | lwz RC, -4(RA) // Get index from control var. + | lwz TMP0, TAB:RB->asize + | lwz TMP1, TAB:RB->array + | addi PC, PC, 4 + |1: // Traverse array part. + | cmplw RC, TMP0 + | slwi TMP3, RC, 3 + | bge >5 // Index points after array part? + | lwzx TMP2, TMP1, TMP3 + | lfdx f0, TMP1, TMP3 + | checknil TMP2 + | lwz INS, -4(PC) + | beq >4 + if (LJ_DUALNUM) { + | stw RC, 4(RA) + | stw TISNUM, 0(RA) + } else { + | tonum_u f1, RC + } + | addi RC, RC, 1 + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | stfd f0, 8(RA) + | decode_RD4 TMP1, INS + | stw RC, -4(RA) // Update control var. + | add PC, TMP1, TMP3 + if (!LJ_DUALNUM) { + | stfd f1, 0(RA) + } + |3: + | ins_next + | + |4: // Skip holes in array part. + | addi RC, RC, 1 + | b <1 + | + |5: // Traverse hash part. + | lwz TMP1, TAB:RB->hmask + | sub RC, RC, TMP0 + | lwz TMP2, TAB:RB->node + |6: + | cmplw RC, TMP1 // End of iteration? Branch to ITERL+1. + | slwi TMP3, RC, 5 + | bgty <3 + | slwi RB, RC, 3 + | sub TMP3, TMP3, RB + | lwzx RB, TMP2, TMP3 + | lfdx f0, TMP2, TMP3 + | add NODE:TMP3, TMP2, TMP3 + | checknil RB + | lwz INS, -4(PC) + | beq >7 + | lfd f1, NODE:TMP3->key + | addis TMP2, PC, -(BCBIAS_J*4 >> 16) + | stfd f0, 8(RA) + | add RC, RC, TMP0 + | decode_RD4 TMP1, INS + | stfd f1, 0(RA) + | addi RC, RC, 1 + | add PC, TMP1, TMP2 + | stw RC, -4(RA) // Update control var. + | b <3 + | + |7: // Skip holes in hash part. + | addi RC, RC, 1 + | b <6 + break; + + case BC_ISNEXT: + | // RA = base*8, RD = target (points to ITERN) + | add RA, BASE, RA + | lwz TMP0, -24(RA) + | lwz CFUNC:TMP1, -20(RA) + | lwz TMP2, -16(RA) + | lwz TMP3, -8(RA) + | cmpwi cr0, TMP2, LJ_TTAB + | cmpwi cr1, TMP0, LJ_TFUNC + | cmpwi cr6, TMP3, LJ_TNIL + | bne cr1, >5 + | lbz TMP1, CFUNC:TMP1->ffid + | crand 4*cr0+eq, 4*cr0+eq, 4*cr6+eq + | cmpwi cr7, TMP1, FF_next_N + | srwi TMP0, RD, 1 + | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq + | add TMP3, PC, TMP0 + | bne cr0, >5 + | stw ZERO, -4(RA) // Initialize control var. + | addis PC, TMP3, -(BCBIAS_J*4 >> 16) + |1: + | ins_next + |5: // Despecialize bytecode if any of the checks fail. + | li TMP0, BC_JMP + | li TMP1, BC_ITERC + | stb TMP0, -1(PC) + | addis PC, TMP3, -(BCBIAS_J*4 >> 16) + | stb TMP1, 3(PC) + | b <1 + break; + + case BC_VARG: + | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8 + | lwz TMP0, FRAME_PC(BASE) + | add RC, BASE, RC + | add RA, BASE, RA + | addi RC, RC, FRAME_VARG + | add TMP2, RA, RB + | subi TMP3, BASE, 8 // TMP3 = vtop + | sub RC, RC, TMP0 // RC = vbase + | // Note: RC may now be even _above_ BASE if nargs was < numparams. + | cmplwi cr1, RB, 0 + | sub. TMP1, TMP3, RC + | beq cr1, >5 // Copy all varargs? + | subi TMP2, TMP2, 16 + | ble >2 // No vararg slots? + |1: // Copy vararg slots to destination slots. + | lfd f0, 0(RC) + | addi RC, RC, 8 + | stfd f0, 0(RA) + | cmplw RA, TMP2 + | cmplw cr1, RC, TMP3 + | bge >3 // All destination slots filled? + | addi RA, RA, 8 + | blt cr1, <1 // More vararg slots? + |2: // Fill up remainder with nil. + | stw TISNIL, 0(RA) + | cmplw RA, TMP2 + | addi RA, RA, 8 + | blt <2 + |3: + | ins_next + | + |5: // Copy all varargs. + | lwz TMP0, L->maxstack + | li MULTRES, 8 // MULTRES = (0+1)*8 + | bley <3 // No vararg slots? + | add TMP2, RA, TMP1 + | cmplw TMP2, TMP0 + | addi MULTRES, TMP1, 8 + | bgt >7 + |6: + | lfd f0, 0(RC) + | addi RC, RC, 8 + | stfd f0, 0(RA) + | cmplw RC, TMP3 + | addi RA, RA, 8 + | blt <6 // More vararg slots? + | b <3 + | + |7: // Grow stack for varargs. + | mr CARG1, L + | stw RA, L->top + | sub SAVE0, RC, BASE // Need delta, because BASE may change. + | stw BASE, L->base + | sub RA, RA, BASE + | stw PC, SAVE_PC + | srwi CARG2, TMP1, 3 + | bl extern lj_state_growstack // (lua_State *L, int n) + | lwz BASE, L->base + | add RA, BASE, RA + | add RC, BASE, SAVE0 + | subi TMP3, BASE, 8 + | b <6 + break; + + /* -- Returns ----------------------------------------------------------- */ + + case BC_RETM: + | // RA = results*8, RD = extra_nresults*8 + | add RD, RD, MULTRES // MULTRES >= 8, so RD >= 8. + | // Fall through. Assumes BC_RET follows. + break; + + case BC_RET: + | // RA = results*8, RD = (nresults+1)*8 + | lwz PC, FRAME_PC(BASE) + | add RA, BASE, RA + | mr MULTRES, RD + |1: + | andi. TMP0, PC, FRAME_TYPE + | xori TMP1, PC, FRAME_VARG + | bne ->BC_RETV_Z + | + |->BC_RET_Z: + | // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return + | lwz INS, -4(PC) + | cmpwi RD, 8 + | subi TMP2, BASE, 8 + | subi RC, RD, 8 + | decode_RB8 RB, INS + | beq >3 + | li TMP1, 0 + |2: + | addi TMP3, TMP1, 8 + | lfdx f0, RA, TMP1 + | cmpw TMP3, RC + | stfdx f0, TMP2, TMP1 + | beq >3 + | addi TMP1, TMP3, 8 + | lfdx f1, RA, TMP3 + | cmpw TMP1, RC + | stfdx f1, TMP2, TMP3 + | bne <2 + |3: + |5: + | cmplw RB, RD + | decode_RA8 RA, INS + | bgt >6 + | sub BASE, TMP2, RA + | lwz LFUNC:TMP1, FRAME_FUNC(BASE) + | ins_next1 + | lwz TMP1, LFUNC:TMP1->pc + | lwz KBASE, PC2PROTO(k)(TMP1) + | ins_next2 + | + |6: // Fill up results with nil. + | subi TMP1, RD, 8 + | addi RD, RD, 8 + | stwx TISNIL, TMP2, TMP1 + | b <5 + | + |->BC_RETV_Z: // Non-standard return case. + | andi. TMP2, TMP1, FRAME_TYPEP + | bne ->vm_return + | // Return from vararg function: relocate BASE down. + | sub BASE, BASE, TMP1 + | lwz PC, FRAME_PC(BASE) + | b <1 + break; + + case BC_RET0: case BC_RET1: + | // RA = results*8, RD = (nresults+1)*8 + | lwz PC, FRAME_PC(BASE) + | add RA, BASE, RA + | mr MULTRES, RD + | andi. TMP0, PC, FRAME_TYPE + | xori TMP1, PC, FRAME_VARG + | bney ->BC_RETV_Z + | + | lwz INS, -4(PC) + | subi TMP2, BASE, 8 + | decode_RB8 RB, INS + if (op == BC_RET1) { + | lfd f0, 0(RA) + | stfd f0, 0(TMP2) + } + |5: + | cmplw RB, RD + | decode_RA8 RA, INS + | bgt >6 + | sub BASE, TMP2, RA + | lwz LFUNC:TMP1, FRAME_FUNC(BASE) + | ins_next1 + | lwz TMP1, LFUNC:TMP1->pc + | lwz KBASE, PC2PROTO(k)(TMP1) + | ins_next2 + | + |6: // Fill up results with nil. + | subi TMP1, RD, 8 + | addi RD, RD, 8 + | stwx TISNIL, TMP2, TMP1 + | b <5 + break; + + /* -- Loops and branches ------------------------------------------------ */ + + case BC_FORL: +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_IFORL follows. + break; + + case BC_JFORI: + case BC_JFORL: +#if !LJ_HASJIT + break; +#endif + case BC_FORI: + case BC_IFORL: + | // RA = base*8, RD = target (after end of loop or start of loop) + vk = (op == BC_IFORL || op == BC_JFORL); + if (LJ_DUALNUM) { + | // Integer loop. + | lwzux TMP1, RA, BASE + | lwz CARG1, FORL_IDX*8+4(RA) + | cmplw cr0, TMP1, TISNUM + if (vk) { + | lwz CARG3, FORL_STEP*8+4(RA) + | bne >9 + | addo. CARG1, CARG1, CARG3 + | cmpwi cr6, CARG3, 0 + | lwz CARG2, FORL_STOP*8+4(RA) + | bso >6 + |4: + | stw CARG1, FORL_IDX*8+4(RA) + } else { + | lwz TMP3, FORL_STEP*8(RA) + | lwz CARG3, FORL_STEP*8+4(RA) + | lwz TMP2, FORL_STOP*8(RA) + | lwz CARG2, FORL_STOP*8+4(RA) + | cmplw cr7, TMP3, TISNUM + | cmplw cr1, TMP2, TISNUM + | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq + | crand 4*cr0+eq, 4*cr0+eq, 4*cr1+eq + | cmpwi cr6, CARG3, 0 + | bne >9 + } + | blt cr6, >5 + | cmpw CARG1, CARG2 + |1: + | stw TISNUM, FORL_EXT*8(RA) + if (op != BC_JFORL) { + | srwi RD, RD, 1 + } + | stw CARG1, FORL_EXT*8+4(RA) + if (op != BC_JFORL) { + | add RD, PC, RD + } + if (op == BC_FORI) { + | bgt >3 // See FP loop below. + } else if (op == BC_JFORI) { + | addis PC, RD, -(BCBIAS_J*4 >> 16) + | bley >7 + } else if (op == BC_IFORL) { + | bgt >2 + | addis PC, RD, -(BCBIAS_J*4 >> 16) + } else { + | bley =>BC_JLOOP + } + |2: + | ins_next + |5: // Invert check for negative step. + | cmpw CARG2, CARG1 + | b <1 + if (vk) { + |6: // Potential overflow. + | mcrxr cr0; bley <4 // Ignore unrelated overflow. + | b <2 + } + } + if (vk) { + if (LJ_DUALNUM) { + |9: // FP loop. + | lfd f1, FORL_IDX*8(RA) + } else { + | lfdux f1, RA, BASE + } + | lfd f3, FORL_STEP*8(RA) + | lfd f2, FORL_STOP*8(RA) + | lwz TMP3, FORL_STEP*8(RA) + | fadd f1, f1, f3 + | stfd f1, FORL_IDX*8(RA) + } else { + if (LJ_DUALNUM) { + |9: // FP loop. + } else { + | lwzux TMP1, RA, BASE + | lwz TMP3, FORL_STEP*8(RA) + | lwz TMP2, FORL_STOP*8(RA) + | cmplw cr0, TMP1, TISNUM + | cmplw cr7, TMP3, TISNUM + | cmplw cr1, TMP2, TISNUM + } + | lfd f1, FORL_IDX*8(RA) + | crand 4*cr0+lt, 4*cr0+lt, 4*cr7+lt + | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt + | lfd f2, FORL_STOP*8(RA) + | bge ->vmeta_for + } + | cmpwi cr6, TMP3, 0 + if (op != BC_JFORL) { + | srwi RD, RD, 1 + } + | stfd f1, FORL_EXT*8(RA) + if (op != BC_JFORL) { + | add RD, PC, RD + } + | fcmpu cr0, f1, f2 + if (op == BC_JFORI) { + | addis PC, RD, -(BCBIAS_J*4 >> 16) + } + | blt cr6, >5 + if (op == BC_FORI) { + | bgt >3 + } else if (op == BC_IFORL) { + if (LJ_DUALNUM) { + | bgty <2 + } else { + | bgt >2 + } + |1: + | addis PC, RD, -(BCBIAS_J*4 >> 16) + } else if (op == BC_JFORI) { + | bley >7 + } else { + | bley =>BC_JLOOP + } + if (LJ_DUALNUM) { + | b <2 + } else { + |2: + | ins_next + } + |5: // Negative step. + if (op == BC_FORI) { + | bge <2 + |3: // Used by integer loop, too. + | addis PC, RD, -(BCBIAS_J*4 >> 16) + } else if (op == BC_IFORL) { + | bgey <1 + } else if (op == BC_JFORI) { + | bgey >7 + } else { + | bgey =>BC_JLOOP + } + | b <2 + if (op == BC_JFORI) { + |7: + | lwz INS, -4(PC) + | decode_RD8 RD, INS + | b =>BC_JLOOP + } + break; + + case BC_ITERL: +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_IITERL follows. + break; + + case BC_JITERL: +#if !LJ_HASJIT + break; +#endif + case BC_IITERL: + | // RA = base*8, RD = target + | lwzux TMP1, RA, BASE + | lwz TMP2, 4(RA) + | checknil TMP1; beq >1 // Stop if iterator returned nil. + if (op == BC_JITERL) { + | stw TMP1, -8(RA) + | stw TMP2, -4(RA) + | b =>BC_JLOOP + } else { + | branch_RD // Otherwise save control var + branch. + | stw TMP1, -8(RA) + | stw TMP2, -4(RA) + } + |1: + | ins_next + break; + + case BC_LOOP: + | // RA = base*8, RD = target (loop extent) + | // Note: RA/RD is only used by trace recorder to determine scope/extent + | // This opcode does NOT jump, it's only purpose is to detect a hot loop. +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_ILOOP follows. + break; + + case BC_ILOOP: + | // RA = base*8, RD = target (loop extent) + | ins_next + break; + + case BC_JLOOP: +#if LJ_HASJIT + | // RA = base*8 (ignored), RD = traceno*8 + | lwz TMP1, DISPATCH_J(trace)(DISPATCH) + | srwi RD, RD, 1 + | // Traces on PPC don't store the trace number, so use 0. + | stw ZERO, DISPATCH_GL(vmstate)(DISPATCH) + | lwzx TRACE:TMP2, TMP1, RD + | mcrxr cr0 // Clear SO flag. + | lwz TMP2, TRACE:TMP2->mcode + | stw BASE, DISPATCH_GL(jit_base)(DISPATCH) + | mtctr TMP2 + | stw L, DISPATCH_GL(jit_L)(DISPATCH) + | addi JGL, DISPATCH, GG_DISP2G+32768 + | bctr +#endif + break; + + case BC_JMP: + | // RA = base*8 (only used by trace recorder), RD = target + | branch_RD + | ins_next + break; + + /* -- Function headers -------------------------------------------------- */ + + case BC_FUNCF: +#if LJ_HASJIT + | hotcall +#endif + case BC_FUNCV: /* NYI: compiled vararg functions. */ + | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow. + break; + + case BC_JFUNCF: +#if !LJ_HASJIT + break; +#endif + case BC_IFUNCF: + | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 + | lwz TMP2, L->maxstack + | lbz TMP1, -4+PC2PROTO(numparams)(PC) + | lwz KBASE, -4+PC2PROTO(k)(PC) + | cmplw RA, TMP2 + | slwi TMP1, TMP1, 3 + | bgt ->vm_growstack_l + if (op != BC_JFUNCF) { + | ins_next1 + } + |2: + | cmplw NARGS8:RC, TMP1 // Check for missing parameters. + | blt >3 + if (op == BC_JFUNCF) { + | decode_RD8 RD, INS + | b =>BC_JLOOP + } else { + | ins_next2 + } + | + |3: // Clear missing parameters. + | stwx TISNIL, BASE, NARGS8:RC + | addi NARGS8:RC, NARGS8:RC, 8 + | b <2 + break; + + case BC_JFUNCV: +#if !LJ_HASJIT + break; +#endif + | NYI // NYI: compiled vararg functions + break; /* NYI: compiled vararg functions. */ + + case BC_IFUNCV: + | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 + | lwz TMP2, L->maxstack + | add TMP1, BASE, RC + | add TMP0, RA, RC + | stw LFUNC:RB, 4(TMP1) // Store copy of LFUNC. + | addi TMP3, RC, 8+FRAME_VARG + | lwz KBASE, -4+PC2PROTO(k)(PC) + | cmplw TMP0, TMP2 + | stw TMP3, 0(TMP1) // Store delta + FRAME_VARG. + | bge ->vm_growstack_l + | lbz TMP2, -4+PC2PROTO(numparams)(PC) + | mr RA, BASE + | mr RC, TMP1 + | ins_next1 + | cmpwi TMP2, 0 + | addi BASE, TMP1, 8 + | beq >3 + |1: + | cmplw RA, RC // Less args than parameters? + | lwz TMP0, 0(RA) + | lwz TMP3, 4(RA) + | bge >4 + | stw TISNIL, 0(RA) // Clear old fixarg slot (help the GC). + | addi RA, RA, 8 + |2: + | addic. TMP2, TMP2, -1 + | stw TMP0, 8(TMP1) + | stw TMP3, 12(TMP1) + | addi TMP1, TMP1, 8 + | bne <1 + |3: + | ins_next2 + | + |4: // Clear missing parameters. + | li TMP0, LJ_TNIL + | b <2 + break; + + case BC_FUNCC: + case BC_FUNCCW: + | // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8 + if (op == BC_FUNCC) { + | lwz TMP3, CFUNC:RB->f + } else { + | lwz TMP3, DISPATCH_GL(wrapf)(DISPATCH) + } + | add TMP1, RA, NARGS8:RC + | lwz TMP2, L->maxstack + | add RC, BASE, NARGS8:RC + | stw BASE, L->base + | cmplw TMP1, TMP2 + | stw RC, L->top + | li_vmstate C + | mtctr TMP3 + if (op == BC_FUNCCW) { + | lwz CARG2, CFUNC:RB->f + } + | mr CARG1, L + | bgt ->vm_growstack_c // Need to grow stack. + | st_vmstate + | bctrl // (lua_State *L [, lua_CFunction f]) + | // Returns nresults. + | lwz BASE, L->base + | slwi RD, CRET1, 3 + | lwz TMP1, L->top + | li_vmstate INTERP + | lwz PC, FRAME_PC(BASE) // Fetch PC of caller. + | sub RA, TMP1, RD // RA = L->top - nresults*8 + | st_vmstate + | b ->vm_returnc + break; + + /* ---------------------------------------------------------------------- */ + + default: + fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); + exit(2); + break; + } +} + +static int build_backend(BuildCtx *ctx) +{ + int op; + + dasm_growpc(Dst, BC__MAX); + + build_subroutines(ctx); + + |.code_op + for (op = 0; op < BC__MAX; op++) + build_ins(ctx, (BCOp)op, op); + + return BC__MAX; +} + +/* Emit pseudo frame-info for all assembler functions. */ +static void emit_asm_debug(BuildCtx *ctx) +{ + int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); + int i; + switch (ctx->mode) { + case BUILD_elfasm: + fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); + fprintf(ctx->fp, + ".Lframe0:\n" + "\t.long .LECIE0-.LSCIE0\n" + ".LSCIE0:\n" + "\t.long 0xffffffff\n" + "\t.byte 0x1\n" + "\t.string \"\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -4\n" + "\t.byte 65\n" + "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n" + "\t.align 2\n" + ".LECIE0:\n\n"); + fprintf(ctx->fp, + ".LSFDE0:\n" + "\t.long .LEFDE0-.LASFDE0\n" + ".LASFDE0:\n" + "\t.long .Lframe0\n" + "\t.long .Lbegin\n" + "\t.long %d\n" + "\t.byte 0xe\n\t.uleb128 %d\n" + "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" + "\t.byte 0x5\n\t.uleb128 70\n\t.uleb128 55\n", + fcofs, CFRAME_SIZE); + for (i = 14; i <= 31; i++) + fprintf(ctx->fp, + "\t.byte %d\n\t.uleb128 %d\n" + "\t.byte %d\n\t.uleb128 %d\n", + 0x80+i, 37+(31-i), 0x80+32+i, 2+2*(31-i)); + fprintf(ctx->fp, + "\t.align 2\n" + ".LEFDE0:\n\n"); +#if LJ_HASFFI + fprintf(ctx->fp, + ".LSFDE1:\n" + "\t.long .LEFDE1-.LASFDE1\n" + ".LASFDE1:\n" + "\t.long .Lframe0\n" + "\t.long lj_vm_ffi_call\n" + "\t.long %d\n" + "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" + "\t.byte 0x8e\n\t.uleb128 2\n" + "\t.byte 0xd\n\t.uleb128 0xe\n" + "\t.align 2\n" + ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); +#endif + fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); + fprintf(ctx->fp, + ".Lframe1:\n" + "\t.long .LECIE1-.LSCIE1\n" + ".LSCIE1:\n" + "\t.long 0\n" + "\t.byte 0x1\n" + "\t.string \"zPR\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -4\n" + "\t.byte 65\n" + "\t.uleb128 6\n" /* augmentation length */ + "\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 1\n\t.uleb128 0\n" + "\t.align 2\n" + ".LECIE1:\n\n"); + fprintf(ctx->fp, + ".LSFDE2:\n" + "\t.long .LEFDE2-.LASFDE2\n" + ".LASFDE2:\n" + "\t.long .LASFDE2-.Lframe1\n" + "\t.long .Lbegin-.\n" + "\t.long %d\n" + "\t.uleb128 0\n" /* augmentation length */ + "\t.byte 0xe\n\t.uleb128 %d\n" + "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" + "\t.byte 0x5\n\t.uleb128 70\n\t.uleb128 55\n", + fcofs, CFRAME_SIZE); + for (i = 14; i <= 31; i++) + fprintf(ctx->fp, + "\t.byte %d\n\t.uleb128 %d\n" + "\t.byte %d\n\t.uleb128 %d\n", + 0x80+i, 37+(31-i), 0x80+32+i, 2+2*(31-i)); + fprintf(ctx->fp, + "\t.align 2\n" + ".LEFDE2:\n\n"); +#if LJ_HASFFI + fprintf(ctx->fp, + ".Lframe2:\n" + "\t.long .LECIE2-.LSCIE2\n" + ".LSCIE2:\n" + "\t.long 0\n" + "\t.byte 0x1\n" + "\t.string \"zR\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -4\n" + "\t.byte 65\n" + "\t.uleb128 1\n" /* augmentation length */ + "\t.byte 0x1b\n" /* pcrel|sdata4 */ + "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n" + "\t.align 2\n" + ".LECIE2:\n\n"); + fprintf(ctx->fp, + ".LSFDE3:\n" + "\t.long .LEFDE3-.LASFDE3\n" + ".LASFDE3:\n" + "\t.long .LASFDE3-.Lframe2\n" + "\t.long lj_vm_ffi_call-.\n" + "\t.long %d\n" + "\t.uleb128 0\n" /* augmentation length */ + "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" + "\t.byte 0x8e\n\t.uleb128 2\n" + "\t.byte 0xd\n\t.uleb128 0xe\n" + "\t.align 2\n" + ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); +#endif + break; + default: + break; + } +} + diff --git a/src/vm_ppcspe.dasc b/src/vm_ppcspe.dasc new file mode 100644 index 00000000..a7ef3ccd --- /dev/null +++ b/src/vm_ppcspe.dasc @@ -0,0 +1,3705 @@ +|// Low-level VM code for PowerPC/e500 CPUs. +|// Bytecode interpreter, fast functions and helper functions. +|// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +| +|.arch ppc +|.section code_op, code_sub +| +|.actionlist build_actionlist +|.globals GLOB_ +|.globalnames globnames +|.externnames extnames +| +|// Note: The ragged indentation of the instructions is intentional. +|// The starting columns indicate data dependencies. +| +|//----------------------------------------------------------------------- +| +|// Fixed register assignments for the interpreter. +|// Don't use: r1 = sp, r2 and r13 = reserved and/or small data area ptr +| +|// The following must be C callee-save (but BASE is often refetched). +|.define BASE, r14 // Base of current Lua stack frame. +|.define KBASE, r15 // Constants of current Lua function. +|.define PC, r16 // Next PC. +|.define DISPATCH, r17 // Opcode dispatch table. +|.define LREG, r18 // Register holding lua_State (also in SAVE_L). +|.define MULTRES, r19 // Size of multi-result: (nresults+1)*8. +| +|// Constants for vectorized type-comparisons (hi+low GPR). C callee-save. +|.define TISNUM, r22 +|.define TISSTR, r23 +|.define TISTAB, r24 +|.define TISFUNC, r25 +|.define TISNIL, r26 +|.define TOBIT, r27 +|.define ZERO, TOBIT // Zero in lo word. +| +|// The following temporaries are not saved across C calls, except for RA. +|.define RA, r20 // Callee-save. +|.define RB, r10 +|.define RC, r11 +|.define RD, r12 +|.define INS, r7 // Overlaps CARG5. +| +|.define TMP0, r0 +|.define TMP1, r8 +|.define TMP2, r9 +|.define TMP3, r6 // Overlaps CARG4. +| +|// Saved temporaries. +|.define SAVE0, r21 +| +|// Calling conventions. +|.define CARG1, r3 +|.define CARG2, r4 +|.define CARG3, r5 +|.define CARG4, r6 // Overlaps TMP3. +|.define CARG5, r7 // Overlaps INS. +| +|.define CRET1, r3 +|.define CRET2, r4 +| +|// Stack layout while in interpreter. Must match with lj_frame.h. +|.define SAVE_LR, 188(sp) +|.define CFRAME_SPACE, 184 // Delta for sp. +|// Back chain for sp: 184(sp) <-- sp entering interpreter +|.define SAVE_r31, 176(sp) // 64 bit register saves. +|.define SAVE_r30, 168(sp) +|.define SAVE_r29, 160(sp) +|.define SAVE_r28, 152(sp) +|.define SAVE_r27, 144(sp) +|.define SAVE_r26, 136(sp) +|.define SAVE_r25, 128(sp) +|.define SAVE_r24, 120(sp) +|.define SAVE_r23, 112(sp) +|.define SAVE_r22, 104(sp) +|.define SAVE_r21, 96(sp) +|.define SAVE_r20, 88(sp) +|.define SAVE_r19, 80(sp) +|.define SAVE_r18, 72(sp) +|.define SAVE_r17, 64(sp) +|.define SAVE_r16, 56(sp) +|.define SAVE_r15, 48(sp) +|.define SAVE_r14, 40(sp) +|.define SAVE_CR, 36(sp) +|.define UNUSED1, 32(sp) +|.define SAVE_ERRF, 28(sp) // 32 bit C frame info. +|.define SAVE_NRES, 24(sp) +|.define SAVE_CFRAME, 20(sp) +|.define SAVE_L, 16(sp) +|.define SAVE_PC, 12(sp) +|.define SAVE_MULTRES, 8(sp) +|// Next frame lr: 4(sp) +|// Back chain for sp: 0(sp) <-- sp while in interpreter +| +|.macro save_, reg; evstdd reg, SAVE_..reg; .endmacro +|.macro rest_, reg; evldd reg, SAVE_..reg; .endmacro +| +|.macro saveregs +| stwu sp, -CFRAME_SPACE(sp) +| save_ r14; save_ r15; save_ r16; save_ r17; save_ r18; save_ r19 +| mflr r0; mfcr r12 +| save_ r20; save_ r21; save_ r22; save_ r23; save_ r24; save_ r25 +| stw r0, SAVE_LR; stw r12, SAVE_CR +| save_ r26; save_ r27; save_ r28; save_ r29; save_ r30; save_ r31 +|.endmacro +| +|.macro restoreregs +| lwz r0, SAVE_LR; lwz r12, SAVE_CR +| rest_ r14; rest_ r15; rest_ r16; rest_ r17; rest_ r18; rest_ r19 +| mtlr r0; mtcrf 0x38, r12 +| rest_ r20; rest_ r21; rest_ r22; rest_ r23; rest_ r24; rest_ r25 +| rest_ r26; rest_ r27; rest_ r28; rest_ r29; rest_ r30; rest_ r31 +| addi sp, sp, CFRAME_SPACE +|.endmacro +| +|// Type definitions. Some of these are only used for documentation. +|.type L, lua_State, LREG +|.type GL, global_State +|.type TVALUE, TValue +|.type GCOBJ, GCobj +|.type STR, GCstr +|.type TAB, GCtab +|.type LFUNC, GCfuncL +|.type CFUNC, GCfuncC +|.type PROTO, GCproto +|.type UPVAL, GCupval +|.type NODE, Node +|.type NARGS8, int +|.type TRACE, GCtrace +| +|//----------------------------------------------------------------------- +| +|// These basic macros should really be part of DynASM. +|.macro srwi, rx, ry, n; rlwinm rx, ry, 32-n, n, 31; .endmacro +|.macro slwi, rx, ry, n; rlwinm rx, ry, n, 0, 31-n; .endmacro +|.macro rotlwi, rx, ry, n; rlwinm rx, ry, n, 0, 31; .endmacro +|.macro rotlw, rx, ry, rn; rlwnm rx, ry, rn, 0, 31; .endmacro +|.macro subi, rx, ry, i; addi rx, ry, -i; .endmacro +| +|// Trap for not-yet-implemented parts. +|.macro NYI; tw 4, sp, sp; .endmacro +| +|//----------------------------------------------------------------------- +| +|// Access to frame relative to BASE. +|.define FRAME_PC, -8 +|.define FRAME_FUNC, -4 +| +|// Instruction decode. +|.macro decode_OP4, dst, ins; rlwinm dst, ins, 2, 22, 29; .endmacro +|.macro decode_RA8, dst, ins; rlwinm dst, ins, 27, 21, 28; .endmacro +|.macro decode_RB8, dst, ins; rlwinm dst, ins, 11, 21, 28; .endmacro +|.macro decode_RC8, dst, ins; rlwinm dst, ins, 19, 21, 28; .endmacro +|.macro decode_RD8, dst, ins; rlwinm dst, ins, 19, 13, 28; .endmacro +| +|.macro decode_OP1, dst, ins; rlwinm dst, ins, 0, 24, 31; .endmacro +|.macro decode_RD4, dst, ins; rlwinm dst, ins, 18, 14, 29; .endmacro +| +|// Instruction fetch. +|.macro ins_NEXT1 +| lwz INS, 0(PC) +| addi PC, PC, 4 +|.endmacro +|// Instruction decode+dispatch. +|.macro ins_NEXT2 +| decode_OP4 TMP1, INS +| decode_RB8 RB, INS +| decode_RD8 RD, INS +| lwzx TMP0, DISPATCH, TMP1 +| decode_RA8 RA, INS +| decode_RC8 RC, INS +| mtctr TMP0 +| bctr +|.endmacro +|.macro ins_NEXT +| ins_NEXT1 +| ins_NEXT2 +|.endmacro +| +|// Instruction footer. +|.if 1 +| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use. +| .define ins_next, ins_NEXT +| .define ins_next_, ins_NEXT +| .define ins_next1, ins_NEXT1 +| .define ins_next2, ins_NEXT2 +|.else +| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch. +| // Affects only certain kinds of benchmarks (and only with -j off). +| .macro ins_next +| b ->ins_next +| .endmacro +| .macro ins_next1 +| .endmacro +| .macro ins_next2 +| b ->ins_next +| .endmacro +| .macro ins_next_ +| ->ins_next: +| ins_NEXT +| .endmacro +|.endif +| +|// Call decode and dispatch. +|.macro ins_callt +| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC +| lwz PC, LFUNC:RB->pc +| lwz INS, 0(PC) +| addi PC, PC, 4 +| decode_OP4 TMP1, INS +| decode_RA8 RA, INS +| lwzx TMP0, DISPATCH, TMP1 +| add RA, RA, BASE +| mtctr TMP0 +| bctr +|.endmacro +| +|.macro ins_call +| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, PC = caller PC +| stw PC, FRAME_PC(BASE) +| ins_callt +|.endmacro +| +|//----------------------------------------------------------------------- +| +|// Macros to test operand types. +|.macro checknum, reg; evcmpltu reg, TISNUM; .endmacro +|.macro checkstr, reg; evcmpeq reg, TISSTR; .endmacro +|.macro checktab, reg; evcmpeq reg, TISTAB; .endmacro +|.macro checkfunc, reg; evcmpeq reg, TISFUNC; .endmacro +|.macro checknil, reg; evcmpeq reg, TISNIL; .endmacro +|.macro checkok, label; blt label; .endmacro +|.macro checkfail, label; bge label; .endmacro +|.macro checkanyfail, label; bns label; .endmacro +|.macro checkallok, label; bso label; .endmacro +| +|.macro branch_RD +| srwi TMP0, RD, 1 +| add PC, PC, TMP0 +| addis PC, PC, -(BCBIAS_J*4 >> 16) +|.endmacro +| +|// Assumes DISPATCH is relative to GL. +#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) +#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) +| +#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) +| +|.macro hotloop +| NYI +|.endmacro +| +|.macro hotcall +| NYI +|.endmacro +| +|// Set current VM state. Uses TMP0. +|.macro li_vmstate, st; li TMP0, ~LJ_VMST_..st; .endmacro +|.macro st_vmstate; stw TMP0, DISPATCH_GL(vmstate)(DISPATCH); .endmacro +| +|// Move table write barrier back. Overwrites mark and tmp. +|.macro barrierback, tab, mark, tmp +| lwz tmp, DISPATCH_GL(gc.grayagain)(DISPATCH) +| // Assumes LJ_GC_BLACK is 0x04. +| rlwinm mark, mark, 0, 30, 28 // black2gray(tab) +| stw tab, DISPATCH_GL(gc.grayagain)(DISPATCH) +| stb mark, tab->marked +| stw tmp, tab->gclist +|.endmacro +| +|//----------------------------------------------------------------------- + +/* Generate subroutines used by opcodes and other parts of the VM. */ +/* The .code_sub section should be last to help static branch prediction. */ +static void build_subroutines(BuildCtx *ctx) +{ + |.code_sub + | + |//----------------------------------------------------------------------- + |//-- Return handling ---------------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_returnp: + | // See vm_return. Also: TMP2 = previous base. + | andi. TMP0, PC, FRAME_P + | evsplati TMP1, LJ_TTRUE + | beq ->cont_dispatch + | + | // Return from pcall or xpcall fast func. + | lwz PC, FRAME_PC(TMP2) // Fetch PC of previous frame. + | mr BASE, TMP2 // Restore caller base. + | // Prepending may overwrite the pcall frame, so do it at the end. + | stwu TMP1, FRAME_PC(RA) // Prepend true to results. + | + |->vm_returnc: + | andi. TMP0, PC, FRAME_TYPE + | addi RD, RD, 8 // RD = (nresults+1)*8. + | mr MULTRES, RD + | beq ->BC_RET_Z // Handle regular return to Lua. + | + |->vm_return: + | // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return + | // TMP0 = PC & FRAME_TYPE + | cmpwi TMP0, FRAME_C + | rlwinm TMP2, PC, 0, 0, 28 + | li_vmstate C + | sub TMP2, BASE, TMP2 // TMP2 = previous base. + | bne ->vm_returnp + | + | addic. TMP1, RD, -8 + | stw TMP2, L->base + | lwz TMP2, SAVE_NRES + | subi BASE, BASE, 8 + | st_vmstate + | slwi TMP2, TMP2, 3 + | beq >2 + |1: + | addic. TMP1, TMP1, -8 + | evldd TMP0, 0(RA) + | addi RA, RA, 8 + | evstdd TMP0, 0(BASE) + | addi BASE, BASE, 8 + | bne <1 + | + |2: + | cmpw TMP2, RD // More/less results wanted? + | bne >6 + |3: + | stw BASE, L->top // Store new top. + | + |->vm_leave_cp: + | lwz TMP0, SAVE_CFRAME // Restore previous C frame. + | li CRET1, 0 // Ok return status for vm_pcall. + | stw TMP0, L->cframe + | + |->vm_leave_unw: + | restoreregs + | blr + | + |6: + | ble >7 // Less results wanted? + | // More results wanted. Check stack size and fill up results with nil. + | lwz TMP1, L->maxstack + | cmplw BASE, TMP1 + | bge >8 + | evstdd TISNIL, 0(BASE) + | addi RD, RD, 8 + | addi BASE, BASE, 8 + | b <2 + | + |7: // Less results wanted. + | sub TMP0, RD, TMP2 + | cmpwi TMP2, 0 // LUA_MULTRET+1 case? + | sub TMP0, BASE, TMP0 // Subtract the difference. + | iseleq BASE, BASE, TMP0 // Either keep top or shrink it. + | b <3 + | + |8: // Corner case: need to grow stack for filling up results. + | // This can happen if: + | // - A C function grows the stack (a lot). + | // - The GC shrinks the stack in between. + | // - A return back from a lua_call() with (high) nresults adjustment. + | stw BASE, L->top // Save current top held in BASE (yes). + | mr SAVE0, RD + | mr CARG2, TMP2 + | mr CARG1, L + | bl extern lj_state_growstack // (lua_State *L, int n) + | lwz TMP2, SAVE_NRES + | mr RD, SAVE0 + | slwi TMP2, TMP2, 3 + | lwz BASE, L->top // Need the (realloced) L->top in BASE. + | b <2 + | + |->vm_unwind_c: // Unwind C stack, return from vm_pcall. + | // (void *cframe, int errcode) + | mr sp, CARG1 + | mr CRET1, CARG2 + |->vm_unwind_c_eh: // Landing pad for external unwinder. + | lwz L, SAVE_L + | li TMP0, ~LJ_VMST_C + | lwz GL:TMP1, L->glref + | stw TMP0, GL:TMP1->vmstate + | b ->vm_leave_unw + | + |->vm_unwind_ff: // Unwind C stack, return from ff pcall. + | // (void *cframe) + | rlwinm sp, CARG1, 0, 0, 29 + |->vm_unwind_ff_eh: // Landing pad for external unwinder. + | lwz L, SAVE_L + | evsplati TISNUM, LJ_TISNUM+1 // Setup type comparison constants. + | evsplati TISFUNC, LJ_TFUNC + | lus TOBIT, 0x4338 + | evsplati TISTAB, LJ_TTAB + | li TMP0, 0 + | lwz BASE, L->base + | evmergelo TOBIT, TOBIT, TMP0 + | lwz DISPATCH, L->glref // Setup pointer to dispatch table. + | evsplati TISSTR, LJ_TSTR + | li TMP1, LJ_TFALSE + | evsplati TISNIL, LJ_TNIL + | li_vmstate INTERP + | lwz PC, FRAME_PC(BASE) // Fetch PC of previous frame. + | la RA, -8(BASE) // Results start at BASE-8. + | addi DISPATCH, DISPATCH, GG_G2DISP + | stw TMP1, 0(RA) // Prepend false to error message. + | li RD, 16 // 2 results: false + error message. + | st_vmstate + | b ->vm_returnc + | + |//----------------------------------------------------------------------- + |//-- Grow stack for calls ----------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_growstack_c: // Grow stack for C function. + | li CARG2, LUA_MINSTACK + | b >2 + | + |->vm_growstack_l: // Grow stack for Lua function. + | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC + | add RC, BASE, RC + | sub RA, RA, BASE + | stw BASE, L->base + | addi PC, PC, 4 // Must point after first instruction. + | stw RC, L->top + | srwi CARG2, RA, 3 + |2: + | // L->base = new base, L->top = top + | stw PC, SAVE_PC + | mr CARG1, L + | bl extern lj_state_growstack // (lua_State *L, int n) + | lwz BASE, L->base + | lwz RC, L->top + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | sub RC, RC, BASE + | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC + | ins_callt // Just retry the call. + | + |//----------------------------------------------------------------------- + |//-- Entry points into the assembler VM --------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_resume: // Setup C frame and resume thread. + | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0) + | saveregs + | mr L, CARG1 + | lwz DISPATCH, L->glref // Setup pointer to dispatch table. + | mr BASE, CARG2 + | lbz TMP1, L->status + | stw L, SAVE_L + | li PC, FRAME_CP + | addi TMP0, sp, CFRAME_RESUME + | addi DISPATCH, DISPATCH, GG_G2DISP + | stw CARG3, SAVE_NRES + | cmplwi TMP1, 0 + | stw CARG3, SAVE_ERRF + | stw TMP0, L->cframe + | stw CARG3, SAVE_CFRAME + | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. + | beq >3 + | + | // Resume after yield (like a return). + | mr RA, BASE + | lwz BASE, L->base + | evsplati TISNUM, LJ_TISNUM+1 // Setup type comparison constants. + | lwz TMP1, L->top + | evsplati TISFUNC, LJ_TFUNC + | lus TOBIT, 0x4338 + | evsplati TISTAB, LJ_TTAB + | lwz PC, FRAME_PC(BASE) + | li TMP2, 0 + | evsplati TISSTR, LJ_TSTR + | sub RD, TMP1, BASE + | evmergelo TOBIT, TOBIT, TMP2 + | stb CARG3, L->status + | andi. TMP0, PC, FRAME_TYPE + | li_vmstate INTERP + | addi RD, RD, 8 + | evsplati TISNIL, LJ_TNIL + | mr MULTRES, RD + | st_vmstate + | beq ->BC_RET_Z + | b ->vm_return + | + |->vm_pcall: // Setup protected C frame and enter VM. + | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef) + | saveregs + | li PC, FRAME_CP + | stw CARG4, SAVE_ERRF + | b >1 + | + |->vm_call: // Setup C frame and enter VM. + | // (lua_State *L, TValue *base, int nres1) + | saveregs + | li PC, FRAME_C + | + |1: // Entry point for vm_pcall above (PC = ftype). + | lwz TMP1, L:CARG1->cframe + | stw CARG3, SAVE_NRES + | mr L, CARG1 + | stw CARG1, SAVE_L + | mr BASE, CARG2 + | stw sp, L->cframe // Add our C frame to cframe chain. + | lwz DISPATCH, L->glref // Setup pointer to dispatch table. + | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. + | stw TMP1, SAVE_CFRAME + | addi DISPATCH, DISPATCH, GG_G2DISP + | + |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype). + | lwz TMP2, L->base // TMP2 = old base (used in vmeta_call). + | evsplati TISNUM, LJ_TISNUM+1 // Setup type comparison constants. + | lwz TMP1, L->top + | evsplati TISFUNC, LJ_TFUNC + | add PC, PC, BASE + | evsplati TISTAB, LJ_TTAB + | lus TOBIT, 0x4338 + | li TMP0, 0 + | sub PC, PC, TMP2 // PC = frame delta + frame type + | evsplati TISSTR, LJ_TSTR + | sub NARGS8:RC, TMP1, BASE + | evmergelo TOBIT, TOBIT, TMP0 + | li_vmstate INTERP + | evsplati TISNIL, LJ_TNIL + | st_vmstate + | + |->vm_call_dispatch: + | // TMP2 = old base, BASE = new base, RC = nargs*8, PC = caller PC + | li TMP0, -8 + | evlddx LFUNC:RB, BASE, TMP0 + | checkfunc LFUNC:RB + | checkfail ->vmeta_call + | + |->vm_call_dispatch_f: + | ins_call + | // BASE = new base, RB = func, RC = nargs*8, PC = caller PC + | + |->vm_cpcall: // Setup protected C frame, call C. + | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp) + | saveregs + | mr L, CARG1 + | lwz TMP0, L:CARG1->stack + | stw CARG1, SAVE_L + | lwz TMP1, L->top + | stw CARG1, SAVE_PC // Any value outside of bytecode is ok. + | sub TMP0, TMP0, TMP1 // Compute -savestack(L, L->top). + | lwz TMP1, L->cframe + | stw sp, L->cframe // Add our C frame to cframe chain. + | li TMP2, 0 + | stw TMP0, SAVE_NRES // Neg. delta means cframe w/o frame. + | stw TMP2, SAVE_ERRF // No error function. + | stw TMP1, SAVE_CFRAME + | mtctr CARG4 + | bctrl // (lua_State *L, lua_CFunction func, void *ud) + | mr. BASE, CRET1 + | lwz DISPATCH, L->glref // Setup pointer to dispatch table. + | li PC, FRAME_CP + | addi DISPATCH, DISPATCH, GG_G2DISP + | bne <3 // Else continue with the call. + | b ->vm_leave_cp // No base? Just remove C frame. + | + |//----------------------------------------------------------------------- + |//-- Metamethod handling ------------------------------------------------ + |//----------------------------------------------------------------------- + | + |// The lj_meta_* functions (except for lj_meta_cat) don't reallocate the + |// stack, so BASE doesn't need to be reloaded across these calls. + | + |//-- Continuation dispatch ---------------------------------------------- + | + |->cont_dispatch: + | // BASE = meta base, RA = resultptr, RD = (nresults+1)*8 + | lwz TMP0, -12(BASE) // Continuation. + | mr RB, BASE + | mr BASE, TMP2 // Restore caller BASE. + | lwz LFUNC:TMP1, FRAME_FUNC(TMP2) + | cmplwi TMP0, 0 + | lwz PC, -16(RB) // Restore PC from [cont|PC]. + | beq >1 + | subi TMP2, RD, 8 + | lwz TMP1, LFUNC:TMP1->pc + | evstddx TISNIL, RA, TMP2 // Ensure one valid arg. + | lwz KBASE, PC2PROTO(k)(TMP1) + | // BASE = base, RA = resultptr, RB = meta base + | mtctr TMP0 + | bctr // Jump to continuation. + | + |1: // Tail call from C function. + | subi TMP1, RB, 16 + | sub RC, TMP1, BASE + | b ->vm_call_tail + | + |->cont_cat: // RA = resultptr, RB = meta base + | lwz INS, -4(PC) + | subi CARG2, RB, 16 + | decode_RB8 SAVE0, INS + | evldd TMP0, 0(RA) + | add TMP1, BASE, SAVE0 + | stw BASE, L->base + | cmplw TMP1, CARG2 + | sub CARG3, CARG2, TMP1 + | decode_RA8 RA, INS + | evstdd TMP0, 0(CARG2) + | bne ->BC_CAT_Z + | evstddx TMP0, BASE, RA + | b ->cont_nop + | + |//-- Table indexing metamethods ----------------------------------------- + | + |->vmeta_tgets1: + | evmergelo STR:RC, TISSTR, STR:RC + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | decode_RB8 RB, INS + | evstdd STR:RC, 0(CARG3) + | add CARG2, BASE, RB + | b >1 + | + |->vmeta_tgets: + | evmergelo TAB:RB, TISTAB, TAB:RB + | la CARG2, DISPATCH_GL(tmptv)(DISPATCH) + | evmergelo STR:RC, TISSTR, STR:RC + | evstdd TAB:RB, 0(CARG2) + | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH) + | evstdd STR:RC, 0(CARG3) + | b >1 + | + |->vmeta_tgetb: // TMP0 = index + | efdcfsi TMP0, TMP0 + | decode_RB8 RB, INS + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | add CARG2, BASE, RB + | evstdd TMP0, 0(CARG3) + | b >1 + | + |->vmeta_tgetv: + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | add CARG2, BASE, RB + | add CARG3, BASE, RC + |1: + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | bl extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k) + | // Returns TValue * (finished) or NULL (metamethod). + | cmplwi CRET1, 0 + | beq >3 + | evldd TMP0, 0(CRET1) + | evstddx TMP0, BASE, RA + | ins_next + | + |3: // Call __index metamethod. + | // BASE = base, L->top = new base, stack = cont/func/t/k + | subfic TMP1, BASE, FRAME_CONT + | lwz BASE, L->top + | stw PC, -16(BASE) // [cont|PC] + | add PC, TMP1, BASE + | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. + | li NARGS8:RC, 16 // 2 args for func(t, k). + | b ->vm_call_dispatch_f + | + |//----------------------------------------------------------------------- + | + |->vmeta_tsets1: + | evmergelo STR:RC, TISSTR, STR:RC + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | decode_RB8 RB, INS + | evstdd STR:RC, 0(CARG3) + | add CARG2, BASE, RB + | b >1 + | + |->vmeta_tsets: + | evmergelo TAB:RB, TISTAB, TAB:RB + | la CARG2, DISPATCH_GL(tmptv)(DISPATCH) + | evmergelo STR:RC, TISSTR, STR:RC + | evstdd TAB:RB, 0(CARG2) + | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH) + | evstdd STR:RC, 0(CARG3) + | b >1 + | + |->vmeta_tsetb: // TMP0 = index + | efdcfsi TMP0, TMP0 + | decode_RB8 RB, INS + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | add CARG2, BASE, RB + | evstdd TMP0, 0(CARG3) + | b >1 + | + |->vmeta_tsetv: + | decode_RB8 RB, INS + | decode_RC8 RC, INS + | add CARG2, BASE, RB + | add CARG3, BASE, RC + |1: + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | bl extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k) + | // Returns TValue * (finished) or NULL (metamethod). + | cmplwi CRET1, 0 + | evlddx TMP0, BASE, RA + | beq >3 + | // NOBARRIER: lj_meta_tset ensures the table is not black. + | evstdd TMP0, 0(CRET1) + | ins_next + | + |3: // Call __newindex metamethod. + | // BASE = base, L->top = new base, stack = cont/func/t/k/(v) + | subfic TMP1, BASE, FRAME_CONT + | lwz BASE, L->top + | stw PC, -16(BASE) // [cont|PC] + | add PC, TMP1, BASE + | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. + | li NARGS8:RC, 24 // 3 args for func(t, k, v) + | evstdd TMP0, 16(BASE) // Copy value to third argument. + | b ->vm_call_dispatch_f + | + |//-- Comparison metamethods --------------------------------------------- + | + |->vmeta_comp: + | mr CARG1, L + | subi PC, PC, 4 + | add CARG2, BASE, RA + | stw PC, SAVE_PC + | add CARG3, BASE, RD + | stw BASE, L->base + | decode_OP1 CARG4, INS + | bl extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op) + | // Returns 0/1 or TValue * (metamethod). + |3: + | cmplwi CRET1, 1 + | bgt ->vmeta_binop + |4: + | lwz INS, 0(PC) + | addi PC, PC, 4 + | decode_RD4 TMP2, INS + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | add TMP2, TMP2, TMP3 + | isellt PC, PC, TMP2 + |->cont_nop: + | ins_next + | + |->cont_ra: // RA = resultptr + | lwz INS, -4(PC) + | evldd TMP0, 0(RA) + | decode_RA8 TMP1, INS + | evstddx TMP0, BASE, TMP1 + | b ->cont_nop + | + |->cont_condt: // RA = resultptr + | lwz TMP0, 0(RA) + | li TMP1, LJ_TTRUE + | cmplw TMP1, TMP0 // Branch if result is true. + | b <4 + | + |->cont_condf: // RA = resultptr + | lwz TMP0, 0(RA) + | li TMP1, LJ_TFALSE + | cmplw TMP0, TMP1 // Branch if result is false. + | b <4 + | + |->vmeta_equal: + | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV. + | subi PC, PC, 4 + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | bl extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne) + | // Returns 0/1 or TValue * (metamethod). + | b <3 + | + |//-- Arithmetic metamethods --------------------------------------------- + | + |->vmeta_arith_vn: + | add CARG3, BASE, RB + | add CARG4, KBASE, RC + | b >1 + | + |->vmeta_arith_nv: + | add CARG3, KBASE, RC + | add CARG4, BASE, RB + | b >1 + | + |->vmeta_unm: + | add CARG3, BASE, RD + | mr CARG4, CARG3 + | b >1 + | + |->vmeta_arith_vv: + | add CARG3, BASE, RB + | add CARG4, BASE, RC + |1: + | add CARG2, BASE, RA + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | decode_OP1 CARG5, INS // Caveat: CARG5 overlaps INS. + | bl extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op) + | // Returns NULL (finished) or TValue * (metamethod). + | cmplwi CRET1, 0 + | beq ->cont_nop + | + | // Call metamethod for binary op. + |->vmeta_binop: + | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2 + | sub TMP1, CRET1, BASE + | stw PC, -16(CRET1) // [cont|PC] + | mr TMP2, BASE + | addi PC, TMP1, FRAME_CONT + | mr BASE, CRET1 + | li NARGS8:RC, 16 // 2 args for func(o1, o2). + | b ->vm_call_dispatch + | + |->vmeta_len: +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | mr SAVE0, CARG1 +#endif + | add CARG2, BASE, RD + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | bl extern lj_meta_len // (lua_State *L, TValue *o) + | // Returns NULL (retry) or TValue * (metamethod base). +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | cmplwi CRET1, 0 + | bne ->vmeta_binop // Binop call for compatibility. + | mr CARG1, SAVE0 + | b ->BC_LEN_Z +#else + | b ->vmeta_binop // Binop call for compatibility. +#endif + | + |//-- Call metamethod ---------------------------------------------------- + | + |->vmeta_call: // Resolve and call __call metamethod. + | // TMP2 = old base, BASE = new base, RC = nargs*8 + | mr CARG1, L + | stw TMP2, L->base // This is the callers base! + | subi CARG2, BASE, 8 + | stw PC, SAVE_PC + | add CARG3, BASE, RC + | mr SAVE0, NARGS8:RC + | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) + | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here. + | addi NARGS8:RC, SAVE0, 8 // Got one more argument now. + | ins_call + | + |->vmeta_callt: // Resolve __call for BC_CALLT. + | // BASE = old base, RA = new base, RC = nargs*8 + | mr CARG1, L + | stw BASE, L->base + | subi CARG2, RA, 8 + | stw PC, SAVE_PC + | add CARG3, RA, RC + | mr SAVE0, NARGS8:RC + | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) + | lwz TMP1, FRAME_PC(BASE) + | addi NARGS8:RC, SAVE0, 8 // Got one more argument now. + | lwz LFUNC:RB, FRAME_FUNC(RA) // Guaranteed to be a function here. + | b ->BC_CALLT_Z + | + |//-- Argument coercion for 'for' statement ------------------------------ + | + |->vmeta_for: + | mr CARG1, L + | stw BASE, L->base + | mr CARG2, RA + | stw PC, SAVE_PC + | mr SAVE0, INS + | bl extern lj_meta_for // (lua_State *L, TValue *base) +#if LJ_HASJIT + | decode_OP1 TMP0, SAVE0 +#endif + | decode_RA8 RA, SAVE0 +#if LJ_HASJIT + | cmpwi TMP0, BC_JFORI +#endif + | decode_RD8 RD, SAVE0 +#if LJ_HASJIT + | beq =>BC_JFORI +#endif + | b =>BC_FORI + | + |//----------------------------------------------------------------------- + |//-- Fast functions ----------------------------------------------------- + |//----------------------------------------------------------------------- + | + |.macro .ffunc, name + |->ff_ .. name: + |.endmacro + | + |.macro .ffunc_1, name + |->ff_ .. name: + | cmplwi NARGS8:RC, 8 + | evldd CARG1, 0(BASE) + | blt ->fff_fallback + |.endmacro + | + |.macro .ffunc_2, name + |->ff_ .. name: + | cmplwi NARGS8:RC, 16 + | evldd CARG1, 0(BASE) + | evldd CARG2, 8(BASE) + | blt ->fff_fallback + |.endmacro + | + |.macro .ffunc_n, name + | .ffunc_1 name + | checknum CARG1 + | checkfail ->fff_fallback + |.endmacro + | + |.macro .ffunc_nn, name + | .ffunc_2 name + | evmergehi TMP0, CARG1, CARG2 + | checknum TMP0 + | checkanyfail ->fff_fallback + |.endmacro + | + |// Inlined GC threshold check. Caveat: uses TMP0 and TMP1. + |.macro ffgccheck + | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH) + | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) + | cmplw TMP0, TMP1 + | bgel ->fff_gcstep + |.endmacro + | + |//-- Base library: checks ----------------------------------------------- + | + |.ffunc assert + | cmplwi NARGS8:RC, 8 + | evldd TMP0, 0(BASE) + | blt ->fff_fallback + | evaddw TMP1, TISNIL, TISNIL // Synthesize LJ_TFALSE. + | la RA, -8(BASE) + | evcmpltu cr1, TMP0, TMP1 + | lwz PC, FRAME_PC(BASE) + | bge cr1, ->fff_fallback + | evstdd TMP0, 0(RA) + | addi RD, NARGS8:RC, 8 // Compute (nresults+1)*8. + | beq ->fff_res // Done if exactly 1 argument. + | li TMP1, 8 + | subi RC, RC, 8 + |1: + | cmplw TMP1, RC + | evlddx TMP0, BASE, TMP1 + | evstddx TMP0, RA, TMP1 + | addi TMP1, TMP1, 8 + | bne <1 + | b ->fff_res + | + |.ffunc type + | cmplwi NARGS8:RC, 8 + | lwz CARG1, 0(BASE) + | blt ->fff_fallback + | li TMP2, ~LJ_TNUMX + | cmplw CARG1, TISNUM + | not TMP1, CARG1 + | isellt TMP1, TMP2, TMP1 + | slwi TMP1, TMP1, 3 + | la TMP2, CFUNC:RB->upvalue + | evlddx STR:CRET1, TMP2, TMP1 + | b ->fff_restv + | + |//-- Base library: getters and setters --------------------------------- + | + |.ffunc_1 getmetatable + | checktab CARG1 + | evmergehi TMP1, CARG1, CARG1 + | checkfail >6 + |1: // Field metatable must be at same offset for GCtab and GCudata! + | lwz TAB:RB, TAB:CARG1->metatable + |2: + | evmr CRET1, TISNIL + | cmplwi TAB:RB, 0 + | lwz STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH) + | beq ->fff_restv + | lwz TMP0, TAB:RB->hmask + | evmergelo CRET1, TISTAB, TAB:RB // Use metatable as default result. + | lwz TMP1, STR:RC->hash + | lwz NODE:TMP2, TAB:RB->node + | evmergelo STR:RC, TISSTR, STR:RC + | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask + | slwi TMP0, TMP1, 5 + | slwi TMP1, TMP1, 3 + | sub TMP1, TMP0, TMP1 + | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) + |3: // Rearranged logic, because we expect _not_ to find the key. + | evldd TMP0, NODE:TMP2->key + | evldd TMP1, NODE:TMP2->val + | evcmpeq TMP0, STR:RC + | lwz NODE:TMP2, NODE:TMP2->next + | checkallok >5 + | cmplwi NODE:TMP2, 0 + | beq ->fff_restv // Not found, keep default result. + | b <3 + |5: + | checknil TMP1 + | checkok ->fff_restv // Ditto for nil value. + | evmr CRET1, TMP1 // Return value of mt.__metatable. + | b ->fff_restv + | + |6: + | cmpwi TMP1, LJ_TUDATA + | not TMP1, TMP1 + | beq <1 + | checknum CARG1 + | slwi TMP1, TMP1, 2 + | li TMP2, 4*~LJ_TNUMX + | isellt TMP1, TMP2, TMP1 + | la TMP2, DISPATCH_GL(gcroot[GCROOT_BASEMT])(DISPATCH) + | lwzx TAB:RB, TMP2, TMP1 + | b <2 + | + |.ffunc_2 setmetatable + | // Fast path: no mt for table yet and not clearing the mt. + | evmergehi TMP0, TAB:CARG1, TAB:CARG2 + | checktab TMP0 + | checkanyfail ->fff_fallback + | lwz TAB:TMP1, TAB:CARG1->metatable + | cmplwi TAB:TMP1, 0 + | lbz TMP3, TAB:CARG1->marked + | bne ->fff_fallback + | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) + | stw TAB:CARG2, TAB:CARG1->metatable + | beq ->fff_restv + | barrierback TAB:CARG1, TMP3, TMP0 + | b ->fff_restv + | + |.ffunc rawget + | cmplwi NARGS8:RC, 16 + | evldd CARG2, 0(BASE) + | blt ->fff_fallback + | checktab CARG2 + | la CARG3, 8(BASE) + | checkfail ->fff_fallback + | mr CARG1, L + | bl extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key) + | // Returns cTValue *. + | evldd CRET1, 0(CRET1) + | b ->fff_restv + | + |//-- Base library: conversions ------------------------------------------ + | + |.ffunc tonumber + | // Only handles the number case inline (without a base argument). + | cmplwi NARGS8:RC, 8 + | evldd CARG1, 0(BASE) + | bne ->fff_fallback // Exactly one argument. + | checknum CARG1 + | checkok ->fff_restv + | b ->fff_fallback + | + |.ffunc_1 tostring + | // Only handles the string or number case inline. + | checkstr CARG1 + | // A __tostring method in the string base metatable is ignored. + | checkok ->fff_restv // String key? + | // Handle numbers inline, unless a number base metatable is present. + | lwz TMP0, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])(DISPATCH) + | checknum CARG1 + | cmplwi cr1, TMP0, 0 + | stw BASE, L->base // Add frame since C call can throw. + | crand 4*cr0+eq, 4*cr0+lt, 4*cr1+eq + | stw PC, SAVE_PC // Redundant (but a defined value). + | bne ->fff_fallback + | ffgccheck + | mr CARG1, L + | mr CARG2, BASE + | bl extern lj_str_fromnum // (lua_State *L, lua_Number *np) + | // Returns GCstr *. + | evmergelo STR:CRET1, TISSTR, STR:CRET1 + | b ->fff_restv + | + |//-- Base library: iterators ------------------------------------------- + | + |.ffunc next + | cmplwi NARGS8:RC, 8 + | evldd CARG2, 0(BASE) + | blt ->fff_fallback + | evstddx TISNIL, BASE, NARGS8:RC // Set missing 2nd arg to nil. + | checktab TAB:CARG2 + | lwz PC, FRAME_PC(BASE) + | checkfail ->fff_fallback + | stw BASE, L->base // Add frame since C call can throw. + | mr CARG1, L + | stw 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 + | evmr CRET1, TISNIL + | beq ->fff_restv // End of traversal: return nil. + | evldd TMP0, 8(BASE) // Copy key and value to results. + | la RA, -8(BASE) + | evldd TMP1, 16(BASE) + | evstdd TMP0, 0(RA) + | li RD, (2+1)*8 + | evstdd TMP1, 8(RA) + | b ->fff_res + | + |.ffunc_1 pairs + | checktab TAB:CARG1 + | lwz PC, FRAME_PC(BASE) + | checkfail ->fff_fallback +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | lwz TAB:TMP2, TAB:CARG1->metatable + | evldd CFUNC:TMP0, CFUNC:RB->upvalue[0] + | cmplwi TAB:TMP2, 0 + | la RA, -8(BASE) + | bne ->fff_fallback +#else + | evldd CFUNC:TMP0, CFUNC:RB->upvalue[0] + | la RA, -8(BASE) +#endif + | evstdd TISNIL, 8(BASE) + | li RD, (3+1)*8 + | evstdd CFUNC:TMP0, 0(RA) + | b ->fff_res + | + |.ffunc_2 ipairs_aux + | checktab TAB:CARG1 + | lwz PC, FRAME_PC(BASE) + | checkfail ->fff_fallback + | checknum CARG2 + | lus TMP3, 0x3ff0 + | checkfail ->fff_fallback + | efdctsi TMP2, CARG2 + | lwz TMP0, TAB:CARG1->asize + | evmergelo TMP3, TMP3, ZERO + | lwz TMP1, TAB:CARG1->array + | efdadd CARG2, CARG2, TMP3 + | addi TMP2, TMP2, 1 + | la RA, -8(BASE) + | cmplw TMP0, TMP2 + | slwi TMP3, TMP2, 3 + | evstdd CARG2, 0(RA) + | ble >2 // Not in array part? + | evlddx TMP1, TMP1, TMP3 + |1: + | checknil TMP1 + | li RD, (0+1)*8 + | checkok ->fff_res // End of iteration, return 0 results. + | li RD, (2+1)*8 + | evstdd TMP1, 8(RA) + | b ->fff_res + |2: // Check for empty hash part first. Otherwise call C function. + | lwz TMP0, TAB:CARG1->hmask + | cmplwi TMP0, 0 + | li RD, (0+1)*8 + | beq ->fff_res + | mr CARG2, TMP2 + | bl extern lj_tab_getinth // (GCtab *t, int32_t key) + | // Returns cTValue * or NULL. + | cmplwi CRET1, 0 + | li RD, (0+1)*8 + | beq ->fff_res + | evldd TMP1, 0(CRET1) + | b <1 + | + |.ffunc_1 ipairs + | checktab TAB:CARG1 + | lwz PC, FRAME_PC(BASE) + | checkfail ->fff_fallback +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | lwz TAB:TMP2, TAB:CARG1->metatable + | evldd CFUNC:TMP0, CFUNC:RB->upvalue[0] + | cmplwi TAB:TMP2, 0 + | la RA, -8(BASE) + | bne ->fff_fallback +#else + | evldd CFUNC:TMP0, CFUNC:RB->upvalue[0] + | la RA, -8(BASE) +#endif + | evsplati TMP1, 0 + | li RD, (3+1)*8 + | evstdd TMP1, 8(BASE) + | evstdd CFUNC:TMP0, 0(RA) + | b ->fff_res + | + |//-- Base library: catch errors ---------------------------------------- + | + |.ffunc pcall + | cmplwi NARGS8:RC, 8 + | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | blt ->fff_fallback + | mr TMP2, BASE + | la BASE, 8(BASE) + | // Remember active hook before pcall. + | rlwinm TMP3, TMP3, 32-HOOK_ACTIVE_SHIFT, 31, 31 + | subi NARGS8:RC, NARGS8:RC, 8 + | addi PC, TMP3, 8+FRAME_PCALL + | b ->vm_call_dispatch + | + |.ffunc_2 xpcall + | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | mr TMP2, BASE + | checkfunc CARG2 // Traceback must be a function. + | checkfail ->fff_fallback + | la BASE, 16(BASE) + | // Remember active hook before pcall. + | rlwinm TMP3, TMP3, 32-HOOK_ACTIVE_SHIFT, 31, 31 + | evstdd CARG2, 0(TMP2) // Swap function and traceback. + | subi NARGS8:RC, NARGS8:RC, 16 + | evstdd CARG1, 8(TMP2) + | addi PC, TMP3, 16+FRAME_PCALL + | b ->vm_call_dispatch + | + |//-- Coroutine library -------------------------------------------------- + | + |.macro coroutine_resume_wrap, resume + |.if resume + |.ffunc_1 coroutine_resume + | evmergehi TMP0, L:CARG1, L:CARG1 + |.else + |.ffunc coroutine_wrap_aux + | lwz L:CARG1, CFUNC:RB->upvalue[0].gcr + |.endif + |.if resume + | cmpwi TMP0, LJ_TTHREAD + | bne ->fff_fallback + |.endif + | lbz TMP0, L:CARG1->status + | lwz TMP1, L:CARG1->cframe + | lwz CARG2, L:CARG1->top + | cmplwi cr0, TMP0, LUA_YIELD + | lwz TMP2, L:CARG1->base + | cmplwi cr1, TMP1, 0 + | lwz TMP0, L:CARG1->maxstack + | cmplw cr7, CARG2, TMP2 + | lwz PC, FRAME_PC(BASE) + | crorc 4*cr6+lt, 4*cr0+gt, 4*cr1+eq // st>LUA_YIELD || cframe!=0 + | add TMP2, CARG2, NARGS8:RC + | crandc 4*cr6+gt, 4*cr7+eq, 4*cr0+eq // base==top && st!=LUA_YIELD + | cmplw cr1, TMP2, TMP0 + | cror 4*cr6+lt, 4*cr6+lt, 4*cr6+gt + | stw PC, SAVE_PC + | cror 4*cr6+lt, 4*cr6+lt, 4*cr1+gt // cond1 || cond2 || stackov + | stw BASE, L->base + | blt cr6, ->fff_fallback + |1: + |.if resume + | addi BASE, BASE, 8 // Keep resumed thread in stack for GC. + | subi NARGS8:RC, NARGS8:RC, 8 + | subi TMP2, TMP2, 8 + |.endif + | stw TMP2, L:CARG1->top + | li TMP1, 0 + | stw BASE, L->top + |2: // Move args to coroutine. + | cmpw TMP1, NARGS8:RC + | evlddx TMP0, BASE, TMP1 + | beq >3 + | evstddx TMP0, CARG2, TMP1 + | addi TMP1, TMP1, 8 + | b <2 + |3: + | li CARG3, 0 + | mr L:SAVE0, L:CARG1 + | li CARG4, 0 + | bl ->vm_resume // (lua_State *L, TValue *base, 0, 0) + | // Returns thread status. + |4: + | lwz TMP2, L:SAVE0->base + | cmplwi CRET1, LUA_YIELD + | lwz TMP3, L:SAVE0->top + | li_vmstate INTERP + | lwz BASE, L->base + | st_vmstate + | bgt >8 + | sub RD, TMP3, TMP2 + | lwz TMP0, L->maxstack + | cmplwi RD, 0 + | add TMP1, BASE, RD + | beq >6 // No results? + | cmplw TMP1, TMP0 + | li TMP1, 0 + | bgt >9 // Need to grow stack? + | + | subi TMP3, RD, 8 + | stw TMP2, L:SAVE0->top // Clear coroutine stack. + |5: // Move results from coroutine. + | cmplw TMP1, TMP3 + | evlddx TMP0, TMP2, TMP1 + | evstddx TMP0, BASE, TMP1 + | addi TMP1, TMP1, 8 + | bne <5 + |6: + | andi. TMP0, PC, FRAME_TYPE + |.if resume + | li TMP1, LJ_TTRUE + | la RA, -8(BASE) + | stw TMP1, -8(BASE) // Prepend true to results. + | addi RD, RD, 16 + |.else + | mr RA, BASE + | addi RD, RD, 8 + |.endif + |7: + | stw PC, SAVE_PC + | mr MULTRES, RD + | beq ->BC_RET_Z + | b ->vm_return + | + |8: // Coroutine returned with error (at co->top-1). + |.if resume + | andi. TMP0, PC, FRAME_TYPE + | la TMP3, -8(TMP3) + | li TMP1, LJ_TFALSE + | evldd TMP0, 0(TMP3) + | stw TMP3, L:SAVE0->top // Remove error from coroutine stack. + | li RD, (2+1)*8 + | stw TMP1, -8(BASE) // Prepend false to results. + | la RA, -8(BASE) + | evstdd TMP0, 0(BASE) // Copy error message. + | b <7 + |.else + | mr CARG1, L + | mr CARG2, L:SAVE0 + | bl extern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co) + |.endif + | + |9: // Handle stack expansion on return from yield. + | mr CARG1, L + | srwi CARG2, RD, 3 + | bl extern lj_state_growstack // (lua_State *L, int n) + | li CRET1, 0 + | b <4 + |.endmacro + | + | coroutine_resume_wrap 1 // coroutine.resume + | coroutine_resume_wrap 0 // coroutine.wrap + | + |.ffunc coroutine_yield + | lwz TMP0, L->cframe + | add TMP1, BASE, NARGS8:RC + | stw BASE, L->base + | andi. TMP0, TMP0, CFRAME_RESUME + | stw TMP1, L->top + | li CRET1, LUA_YIELD + | beq ->fff_fallback + | stw ZERO, L->cframe + | stb CRET1, L->status + | b ->vm_leave_unw + | + |//-- Math library ------------------------------------------------------- + | + |.ffunc_n math_abs + | efdabs CRET1, CARG1 + | // Fallthrough. + | + |->fff_restv: + | // CRET1 = TValue result. + | lwz PC, FRAME_PC(BASE) + | la RA, -8(BASE) + | evstdd CRET1, 0(RA) + |->fff_res1: + | // RA = results, PC = return. + | li RD, (1+1)*8 + |->fff_res: + | // RA = results, RD = (nresults+1)*8, PC = return. + | andi. TMP0, PC, FRAME_TYPE + | mr MULTRES, RD + | bne ->vm_return + | lwz INS, -4(PC) + | decode_RB8 RB, INS + |5: + | cmplw RB, RD // More results expected? + | decode_RA8 TMP0, INS + | bgt >6 + | ins_next1 + | // Adjust BASE. KBASE is assumed to be set for the calling frame. + | sub BASE, RA, TMP0 + | ins_next2 + | + |6: // Fill up results with nil. + | subi TMP1, RD, 8 + | addi RD, RD, 8 + | evstddx TISNIL, RA, TMP1 + | b <5 + | + |.macro math_extern, func + | .ffunc math_ .. func + | cmplwi NARGS8:RC, 8 + | evldd CARG2, 0(BASE) + | blt ->fff_fallback + | checknum CARG2 + | evmergehi CARG1, CARG2, CARG2 + | checkfail ->fff_fallback + | bl extern func + | evmergelo CRET1, CRET1, CRET2 + | b ->fff_restv + |.endmacro + | + |.macro math_extern2, func + | .ffunc math_ .. func + | cmplwi NARGS8:RC, 16 + | evldd CARG2, 0(BASE) + | evldd CARG4, 8(BASE) + | blt ->fff_fallback + | evmergehi CARG1, CARG4, CARG2 + | checknum CARG1 + | evmergehi CARG3, CARG4, CARG4 + | checkanyfail ->fff_fallback + | bl extern func + | evmergelo CRET1, CRET1, CRET2 + | b ->fff_restv + |.endmacro + | + |.macro math_round, func + | .ffunc math_ .. func + | cmplwi NARGS8:RC, 8 + | evldd CARG2, 0(BASE) + | blt ->fff_fallback + | checknum CARG2 + | evmergehi CARG1, CARG2, CARG2 + | checkfail ->fff_fallback + | lwz PC, FRAME_PC(BASE) + | bl ->vm_..func.._hilo; + | la RA, -8(BASE) + | evstdd CRET2, 0(RA) + | b ->fff_res1 + |.endmacro + | + | math_round floor + | math_round ceil + | + | math_extern sqrt + | math_extern log + | math_extern log10 + | math_extern exp + | math_extern sin + | math_extern cos + | math_extern tan + | math_extern asin + | math_extern acos + | math_extern atan + | math_extern sinh + | math_extern cosh + | math_extern tanh + | math_extern2 pow + | math_extern2 atan2 + | math_extern2 fmod + | + |->ff_math_deg: + |.ffunc_n math_rad + | evldd CARG2, CFUNC:RB->upvalue[0] + | efdmul CRET1, CARG1, CARG2 + | b ->fff_restv + | + |.ffunc math_ldexp + | cmplwi NARGS8:RC, 16 + | evldd CARG2, 0(BASE) + | evldd CARG4, 8(BASE) + | blt ->fff_fallback + | evmergehi CARG1, CARG4, CARG2 + | checknum CARG1 + | checkanyfail ->fff_fallback + | efdctsi CARG3, CARG4 + | bl extern ldexp + | evmergelo CRET1, CRET1, CRET2 + | b ->fff_restv + | + |.ffunc math_frexp + | cmplwi NARGS8:RC, 8 + | evldd CARG2, 0(BASE) + | blt ->fff_fallback + | checknum CARG2 + | evmergehi CARG1, CARG2, CARG2 + | checkfail ->fff_fallback + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | lwz PC, FRAME_PC(BASE) + | bl extern frexp + | lwz TMP1, DISPATCH_GL(tmptv)(DISPATCH) + | evmergelo CRET1, CRET1, CRET2 + | efdcfsi CRET2, TMP1 + | la RA, -8(BASE) + | evstdd CRET1, 0(RA) + | li RD, (2+1)*8 + | evstdd CRET2, 8(RA) + | b ->fff_res + | + |.ffunc math_modf + | cmplwi NARGS8:RC, 8 + | evldd CARG2, 0(BASE) + | blt ->fff_fallback + | checknum CARG2 + | evmergehi CARG1, CARG2, CARG2 + | checkfail ->fff_fallback + | la CARG3, -8(BASE) + | lwz PC, FRAME_PC(BASE) + | bl extern modf + | evmergelo CRET1, CRET1, CRET2 + | la RA, -8(BASE) + | evstdd CRET1, 0(BASE) + | li RD, (2+1)*8 + | b ->fff_res + | + |.macro math_minmax, name, cmpop + | .ffunc_1 name + | checknum CARG1 + | li TMP1, 8 + | checkfail ->fff_fallback + |1: + | evlddx CARG2, BASE, TMP1 + | cmplw cr1, TMP1, NARGS8:RC + | checknum CARG2 + | bge cr1, ->fff_restv // Ok, since CRET1 = CARG1. + | checkfail ->fff_fallback + | cmpop CARG2, CARG1 + | addi TMP1, TMP1, 8 + | crmove 4*cr0+lt, 4*cr0+gt + | evsel CARG1, CARG2, CARG1 + | b <1 + |.endmacro + | + | math_minmax math_min, efdtstlt + | math_minmax math_max, efdtstgt + | + |//-- String library ----------------------------------------------------- + | + |.ffunc_1 string_len + | checkstr STR:CARG1 + | checkfail ->fff_fallback + | lwz TMP0, STR:CARG1->len + | efdcfsi CRET1, TMP0 + | b ->fff_restv + | + |.ffunc string_byte // Only handle the 1-arg case here. + | cmplwi NARGS8:RC, 8 + | evldd STR:CARG1, 0(BASE) + | bne ->fff_fallback // Need exactly 1 argument. + | checkstr STR:CARG1 + | la RA, -8(BASE) + | checkfail ->fff_fallback + | lwz TMP0, STR:CARG1->len + | li RD, (0+1)*8 + | lbz TMP1, STR:CARG1[1] // Access is always ok (NUL at end). + | li TMP2, (1+1)*8 + | cmplwi TMP0, 0 + | lwz PC, FRAME_PC(BASE) + | efdcfsi CRET1, TMP1 + | iseleq RD, RD, TMP2 + | evstdd CRET1, 0(RA) + | b ->fff_res + | + |.ffunc string_char // Only handle the 1-arg case here. + | ffgccheck + | cmplwi NARGS8:RC, 8 + | evldd CARG1, 0(BASE) + | bne ->fff_fallback // Exactly 1 argument. + | checknum CARG1 + | la CARG2, DISPATCH_GL(tmptv)(DISPATCH) + | checkfail ->fff_fallback + | efdctsiz TMP0, CARG1 + | li CARG3, 1 + | cmplwi TMP0, 255 + | stb TMP0, 0(CARG2) + | bgt ->fff_fallback + |->fff_newstr: + | mr CARG1, L + | stw BASE, L->base + | stw PC, SAVE_PC + | bl extern lj_str_new // (lua_State *L, char *str, size_t l) + | // Returns GCstr *. + | lwz BASE, L->base + | evmergelo STR:CRET1, TISSTR, STR:CRET1 + | b ->fff_restv + | + |.ffunc string_sub + | ffgccheck + | cmplwi NARGS8:RC, 16 + | evldd CARG3, 16(BASE) + | evldd STR:CARG1, 0(BASE) + | blt ->fff_fallback + | evldd CARG2, 8(BASE) + | li TMP2, -1 + | beq >1 + | checknum CARG3 + | checkfail ->fff_fallback + | efdctsiz TMP2, CARG3 + |1: + | checknum CARG2 + | checkfail ->fff_fallback + | checkstr STR:CARG1 + | efdctsiz TMP1, CARG2 + | checkfail ->fff_fallback + | lwz TMP0, STR:CARG1->len + | cmplw TMP0, TMP2 // len < end? (unsigned compare) + | add TMP3, TMP2, TMP0 + | blt >5 + |2: + | cmpwi TMP1, 0 // start <= 0? + | add TMP3, TMP1, TMP0 + | ble >7 + |3: + | sub. CARG3, TMP2, TMP1 + | addi CARG2, STR:CARG1, #STR-1 + | addi CARG3, CARG3, 1 + | add CARG2, CARG2, TMP1 + | isellt CARG3, r0, CARG3 + | b ->fff_newstr + | + |5: // Negative end or overflow. + | cmpw TMP0, TMP2 + | addi TMP3, TMP3, 1 + | iselgt TMP2, TMP3, TMP0 // end = end > len ? len : end+len+1 + | b <2 + | + |7: // Negative start or underflow. + | cmpwi cr1, TMP3, 0 + | iseleq TMP1, r0, TMP3 + | isel TMP1, r0, TMP1, 4*cr1+lt + | addi TMP1, TMP1, 1 // start = 1 + (start ? start+len : 0) + | b <3 + | + |.ffunc string_rep // Only handle the 1-char case inline. + | ffgccheck + | cmplwi NARGS8:RC, 16 + | evldd CARG1, 0(BASE) + | evldd CARG2, 8(BASE) + | blt ->fff_fallback + | checknum CARG2 + | checkfail ->fff_fallback + | checkstr STR:CARG1 + | efdctsiz CARG3, CARG2 + | checkfail ->fff_fallback + | lwz TMP0, STR:CARG1->len + | cmpwi CARG3, 0 + | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) + | ble >2 // Count <= 0? (or non-int) + | cmplwi TMP0, 1 + | subi TMP2, CARG3, 1 + | blt >2 // Zero length string? + | cmplw cr1, TMP1, CARG3 + | bne ->fff_fallback // Fallback for > 1-char strings. + | lbz TMP0, STR:CARG1[1] + | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) + | blt cr1, ->fff_fallback + |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). + | cmplwi TMP2, 0 + | stbx TMP0, CARG2, TMP2 + | subi TMP2, TMP2, 1 + | bne <1 + | b ->fff_newstr + |2: // Return empty string. + | la STR:CRET1, DISPATCH_GL(strempty)(DISPATCH) + | evmergelo CRET1, TISSTR, STR:CRET1 + | b ->fff_restv + | + |.ffunc string_reverse + | ffgccheck + | cmplwi NARGS8:RC, 8 + | evldd CARG1, 0(BASE) + | blt ->fff_fallback + | checkstr STR:CARG1 + | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) + | checkfail ->fff_fallback + | lwz CARG3, STR:CARG1->len + | la CARG1, #STR(STR:CARG1) + | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) + | li TMP2, 0 + | cmplw TMP1, CARG3 + | subi TMP3, CARG3, 1 + | blt ->fff_fallback + |1: // Reverse string copy. + | cmpwi TMP3, 0 + | lbzx TMP1, CARG1, TMP2 + | blt ->fff_newstr + | stbx TMP1, CARG2, TMP3 + | subi TMP3, TMP3, 1 + | addi TMP2, TMP2, 1 + | b <1 + | + |.macro ffstring_case, name, lo + | .ffunc name + | ffgccheck + | cmplwi NARGS8:RC, 8 + | evldd CARG1, 0(BASE) + | blt ->fff_fallback + | checkstr STR:CARG1 + | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) + | checkfail ->fff_fallback + | lwz CARG3, STR:CARG1->len + | la CARG1, #STR(STR:CARG1) + | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) + | cmplw TMP1, CARG3 + | li TMP2, 0 + | blt ->fff_fallback + |1: // ASCII case conversion. + | cmplw TMP2, CARG3 + | lbzx TMP1, CARG1, TMP2 + | bge ->fff_newstr + | subi TMP0, TMP1, lo + | xori TMP3, TMP1, 0x20 + | cmplwi TMP0, 26 + | isellt TMP1, TMP3, TMP1 + | stbx TMP1, CARG2, TMP2 + | addi TMP2, TMP2, 1 + | b <1 + |.endmacro + | + |ffstring_case string_lower, 65 + |ffstring_case string_upper, 97 + | + |//-- Table library ------------------------------------------------------ + | + |.ffunc_1 table_getn + | checktab CARG1 + | checkfail ->fff_fallback + | bl extern lj_tab_len // (GCtab *t) + | // Returns uint32_t (but less than 2^31). + | efdcfsi CRET1, CRET1 + | b ->fff_restv + | + |//-- Bit library -------------------------------------------------------- + | + |.macro .ffunc_bit, name + | .ffunc_n bit_..name + | efdadd CARG1, CARG1, TOBIT + |.endmacro + | + |.ffunc_bit tobit + |->fff_resbit: + | efdcfsi CRET1, CARG1 + | b ->fff_restv + | + |.macro .ffunc_bit_op, name, ins + | .ffunc_bit name + | li TMP1, 8 + |1: + | evlddx CARG2, BASE, TMP1 + | cmplw cr1, TMP1, NARGS8:RC + | checknum CARG2 + | bge cr1, ->fff_resbit + | checkfail ->fff_fallback + | efdadd CARG2, CARG2, TOBIT + | ins CARG1, CARG1, CARG2 + | addi TMP1, TMP1, 8 + | b <1 + |.endmacro + | + |.ffunc_bit_op band, and + |.ffunc_bit_op bor, or + |.ffunc_bit_op bxor, xor + | + |.ffunc_bit bswap + | rotlwi TMP0, CARG1, 8 + | rlwimi TMP0, CARG1, 24, 0, 7 + | rlwimi TMP0, CARG1, 24, 16, 23 + | efdcfsi CRET1, TMP0 + | b ->fff_restv + | + |.ffunc_bit bnot + | not TMP0, CARG1 + | efdcfsi CRET1, TMP0 + | b ->fff_restv + | + |.macro .ffunc_bit_sh, name, ins, shmod + | .ffunc_nn bit_..name + | efdadd CARG2, CARG2, TOBIT + | efdadd CARG1, CARG1, TOBIT + |.if shmod == 1 + | rlwinm CARG2, CARG2, 0, 27, 31 + |.elif shmod == 2 + | neg CARG2, CARG2 + |.endif + | ins TMP0, CARG1, CARG2 + | efdcfsi CRET1, TMP0 + | b ->fff_restv + |.endmacro + | + |.ffunc_bit_sh lshift, slw, 1 + |.ffunc_bit_sh rshift, srw, 1 + |.ffunc_bit_sh arshift, sraw, 1 + |.ffunc_bit_sh rol, rotlw, 0 + |.ffunc_bit_sh ror, rotlw, 2 + | + |//----------------------------------------------------------------------- + | + |->fff_fallback: // Call fast function fallback handler. + | // BASE = new base, RB = CFUNC, RC = nargs*8 + | lwz TMP3, CFUNC:RB->f + | add TMP1, BASE, NARGS8:RC + | lwz PC, FRAME_PC(BASE) // Fallback may overwrite PC. + | addi TMP0, TMP1, 8*LUA_MINSTACK + | lwz TMP2, L->maxstack + | stw PC, SAVE_PC // Redundant (but a defined value). + | cmplw TMP0, TMP2 + | stw BASE, L->base + | stw TMP1, L->top + | mr CARG1, L + | bgt >5 // Need to grow stack. + | mtctr TMP3 + | bctrl // (lua_State *L) + | // Either throws an error, or recovers and returns -1, 0 or nresults+1. + | lwz BASE, L->base + | cmpwi CRET1, 0 + | slwi RD, CRET1, 3 + | la RA, -8(BASE) + | bgt ->fff_res // Returned nresults+1? + |1: // Returned 0 or -1: retry fast path. + | lwz TMP0, L->top + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | sub NARGS8:RC, TMP0, BASE + | bne ->vm_call_tail // Returned -1? + | ins_callt // Returned 0: retry fast path. + | + |// Reconstruct previous base for vmeta_call during tailcall. + |->vm_call_tail: + | andi. TMP0, PC, FRAME_TYPE + | rlwinm TMP1, PC, 0, 0, 28 + | bne >3 + | lwz INS, -4(PC) + | decode_RA8 TMP1, INS + | addi TMP1, TMP1, 8 + |3: + | sub TMP2, BASE, TMP1 + | b ->vm_call_dispatch // Resolve again for tailcall. + | + |5: // Grow stack for fallback handler. + | li CARG2, LUA_MINSTACK + | bl extern lj_state_growstack // (lua_State *L, int n) + | lwz BASE, L->base + | cmpw TMP0, TMP0 // Set 4*cr0+eq to force retry. + | b <1 + | + |->fff_gcstep: // Call GC step function. + | // BASE = new base, RC = nargs*8 + | mflr SAVE0 + | stw BASE, L->base + | add TMP0, BASE, NARGS8:RC + | stw PC, SAVE_PC // Redundant (but a defined value). + | stw TMP0, L->top + | mr CARG1, L + | bl extern lj_gc_step // (lua_State *L) + | lwz BASE, L->base + | mtlr SAVE0 + | lwz TMP0, L->top + | sub NARGS8:RC, TMP0, BASE + | lwz CFUNC:RB, FRAME_FUNC(BASE) + | blr + | + |//----------------------------------------------------------------------- + |//-- Special dispatch targets ------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_record: // Dispatch target for recording phase. +#if LJ_HASJIT + | NYI +#endif + | + |->vm_rethook: // Dispatch target for return hooks. + | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | andi. TMP0, TMP3, HOOK_ACTIVE // Hook already active? + | beq >1 + |5: // Re-dispatch to static ins. + | addi TMP1, TMP1, GG_DISP2STATIC // Assumes decode_OP4 TMP1, INS. + | lwzx TMP0, DISPATCH, TMP1 + | mtctr TMP0 + | bctr + | + |->vm_inshook: // Dispatch target for instr/line hooks. + | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH) + | lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH) + | andi. TMP0, TMP3, HOOK_ACTIVE // Hook already active? + | rlwinm TMP0, TMP3, 31-LUA_HOOKLINE, 31, 0 + | bne <5 + | + | cmpwi cr1, TMP0, 0 + | addic. TMP2, TMP2, -1 + | beq cr1, <5 + | stw TMP2, DISPATCH_GL(hookcount)(DISPATCH) + | beq >1 + | bge cr1, <5 + |1: + | mr CARG1, L + | stw MULTRES, SAVE_MULTRES + | mr CARG2, PC + | stw BASE, L->base + | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. + | bl extern lj_dispatch_ins // (lua_State *L, const BCIns *pc) + |3: + | lwz BASE, L->base + |4: // Re-dispatch to static ins. + | lwz INS, -4(PC) + | decode_OP4 TMP1, INS + | decode_RB8 RB, INS + | addi TMP1, TMP1, GG_DISP2STATIC + | decode_RD8 RD, INS + | lwzx TMP0, DISPATCH, TMP1 + | decode_RA8 RA, INS + | decode_RC8 RC, INS + | mtctr TMP0 + | bctr + | + |->cont_hook: // Continue from hook yield. + | addi PC, PC, 4 + | lwz MULTRES, -20(RB) // Restore MULTRES for *M ins. + | b <4 + | + |->vm_hotloop: // Hot loop counter underflow. +#if LJ_HASJIT + | NYI +#endif + | + |->vm_callhook: // Dispatch target for call hooks. + | mr CARG2, PC +#if LJ_HASJIT + | b >1 +#endif + | + |->vm_hotcall: // Hot call counter underflow. +#if LJ_HASJIT + | ori CARG2, PC, 1 + |1: +#endif + | add TMP0, BASE, RC + | stw PC, SAVE_PC + | mr CARG1, L + | stw BASE, L->base + | sub RA, RA, BASE + | stw TMP0, L->top + | bl extern lj_dispatch_call // (lua_State *L, const BCIns *pc) + | // Returns ASMFunction. + | lwz BASE, L->base + | lwz TMP0, L->top + | stw ZERO, SAVE_PC // Invalidate for subsequent line hook. + | sub NARGS8:RC, TMP0, BASE + | add RA, BASE, RA + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | mtctr CRET1 + | bctr + | + |//----------------------------------------------------------------------- + |//-- Trace exit handler ------------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_exit_handler: +#if LJ_HASJIT + | NYI +#endif + |->vm_exit_interp: +#if LJ_HASJIT + | NYI +#endif + | + |//----------------------------------------------------------------------- + |//-- Math helper functions ---------------------------------------------- + |//----------------------------------------------------------------------- + | + |// FP value rounding. Called by math.floor/math.ceil fast functions + |// and from JIT code. + |// + |// This can be inlined if the CPU has the frin/friz/frip/frim instructions. + |// The alternative hard-float approaches have a deep dependency chain. + |// The resulting latency is at least 3x-7x the double-precision FP latency + |// (e500v2: 6cy, e600: 5cy, Cell: 10cy) or around 20-70 cycles. + |// + |// The soft-float approach is tedious, but much faster (e500v2: ~11cy/~6cy). + |// However it relies on a fast way to transfer the FP value to GPRs + |// (e500v2: 0cy for lo-word, 1cy for hi-word). + |// + |.macro vm_round, name, mode + | // Used temporaries: TMP0, TMP1, TMP2, TMP3. + |->name.._efd: // Input: CARG2, output: CRET2 + | evmergehi CARG1, CARG2, CARG2 + |->name.._hilo: + | // Input: CARG1 (hi), CARG2 (hi, lo), output: CRET2 + | rlwinm TMP2, CARG1, 12, 21, 31 + | addic. TMP2, TMP2, -1023 // exp = exponent(x) - 1023 + | li TMP1, -1 + | cmplwi cr1, TMP2, 51 // 0 <= exp <= 51? + | subfic TMP0, TMP2, 52 + | bgt cr1, >1 + | lus TMP3, 0xfff0 + | slw TMP0, TMP1, TMP0 // lomask = -1 << (52-exp) + | sraw TMP1, TMP3, TMP2 // himask = (int32_t)0xfff00000 >> exp + |.if mode == 2 // trunc(x): + | evmergelo TMP0, TMP1, TMP0 + | evand CRET2, CARG2, TMP0 // hi &= himask, lo &= lomask + |.else + | andc TMP2, CARG2, TMP0 + | andc TMP3, CARG1, TMP1 + | or TMP2, TMP2, TMP3 // ztest = (hi&~himask) | (lo&~lomask) + | srawi TMP3, CARG1, 31 // signmask = (int32_t)hi >> 31 + |.if mode == 0 // floor(x): + | and. TMP2, TMP2, TMP3 // iszero = ((ztest & signmask) == 0) + |.else // ceil(x): + | andc. TMP2, TMP2, TMP3 // iszero = ((ztest & ~signmask) == 0) + |.endif + | and CARG2, CARG2, TMP0 // lo &= lomask + | and CARG1, CARG1, TMP1 // hi &= himask + | subc TMP0, CARG2, TMP0 + | iseleq TMP0, CARG2, TMP0 // lo = iszero ? lo : lo-lomask + | sube TMP1, CARG1, TMP1 + | iseleq TMP1, CARG1, TMP1 // hi = iszero ? hi : hi-himask+carry + | evmergelo CRET2, TMP1, TMP0 + |.endif + | blr + |1: + | bgtlr // Already done if >=2^52, +-inf or nan. + |.if mode == 2 // trunc(x): + | rlwinm TMP1, CARG1, 0, 0, 0 // hi = sign(x) + | li TMP0, 0 + | evmergelo CRET2, TMP1, TMP0 + |.else + | rlwinm TMP2, CARG1, 0, 1, 31 + | srawi TMP0, CARG1, 31 // signmask = (int32_t)hi >> 31 + | or TMP2, TMP2, CARG2 // ztest = abs(hi) | lo + | lus TMP1, 0x3ff0 + |.if mode == 0 // floor(x): + | and. TMP2, TMP2, TMP0 // iszero = ((ztest & signmask) == 0) + |.else // ceil(x): + | andc. TMP2, TMP2, TMP0 // iszero = ((ztest & ~signmask) == 0) + |.endif + | li TMP0, 0 + | iseleq TMP1, r0, TMP1 + | rlwimi CARG1, TMP1, 0, 1, 31 // hi = sign(x) | (iszero ? 0.0 : 1.0) + | evmergelo CRET2, CARG1, TMP0 + |.endif + | blr + |.endmacro + | + |->vm_floor: + | mflr CARG3 + | bl ->vm_floor_hilo + | mtlr CARG3 + | evmergehi CRET1, CRET2, CRET2 + | blr + | + | vm_round vm_floor, 0 + | vm_round vm_ceil, 1 +#if LJ_HASJIT + | vm_round vm_trunc, 2 +#else + |->vm_trunc_efd: + |->vm_trunc_hilo: +#endif + | + |// Callable from C: double lj_vm_foldarith(double x, double y, int op) + |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -) + |// and basic math functions. ORDER ARITH + |->vm_foldarith: + | evmergelo CARG2, CARG1, CARG2 + | cmplwi CARG5, 1 + | evmergelo CARG4, CARG3, CARG4 + | beq >1; bgt >2 + | efdadd CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr + |1: + | efdsub CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr + |2: + | cmplwi CARG5, 3; beq >1; bgt >2 + | efdmul CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr + |1: + | efddiv CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr + |2: + | cmplwi CARG5, 5; beq >1; bgt >2 + | evmr CARG3, CARG2; efddiv CRET2, CARG2, CARG4; evmr RB, CARG4 + | mflr RC; bl ->vm_floor_efd; mtlr RC + | efdmul CRET2, CRET2, RB; efdsub CRET2, CARG3, CRET2 + | evmergehi CRET1, CRET2, CRET2; blr + |1: + | b extern pow + |2: + | cmplwi CARG5, 7; beq >1; bgt >2 + | xoris CARG1, CARG1, 0x8000; blr + |1: + | rlwinm CARG1, CARG1, 0, 1, 31; blr + |2: + | NYI // Other operations only needed by JIT compiler. + | + |//----------------------------------------------------------------------- + |//-- Miscellaneous functions -------------------------------------------- + |//----------------------------------------------------------------------- + | + |//----------------------------------------------------------------------- + |//-- FFI helper functions ----------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_ffi_call: +#if LJ_HASFFI + | NYI +#endif + | + |//----------------------------------------------------------------------- +} + +/* Generate the code for a single instruction. */ +static void build_ins(BuildCtx *ctx, BCOp op, int defop) +{ + int vk = 0; + |=>defop: + + switch (op) { + + /* -- Comparison ops ---------------------------------------------------- */ + + /* Remember: all ops branch for a true comparison, fall through otherwise. */ + + case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: + | // RA = src1*8, RD = src2*8, JMP with RD = target + | evlddx TMP0, BASE, RA + | addi PC, PC, 4 + | evlddx TMP1, BASE, RD + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | lwz TMP2, -4(PC) + | evmergehi RB, TMP0, TMP1 + | decode_RD4 TMP2, TMP2 + | checknum RB + | add TMP2, TMP2, TMP3 + | checkanyfail ->vmeta_comp + | efdcmplt TMP0, TMP1 + if (op == BC_ISLE || op == BC_ISGT) { + | efdcmpeq cr1, TMP0, TMP1 + | cror 4*cr0+gt, 4*cr0+gt, 4*cr1+gt + } + if (op == BC_ISLT || op == BC_ISLE) { + | iselgt PC, TMP2, PC + } else { + | iselgt PC, PC, TMP2 + } + | ins_next + break; + + case BC_ISEQV: case BC_ISNEV: + vk = op == BC_ISEQV; + | // RA = src1*8, RD = src2*8, JMP with RD = target + | evlddx CARG2, BASE, RA + | addi PC, PC, 4 + | evlddx CARG3, BASE, RD + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | lwz TMP2, -4(PC) + | evmergehi RB, CARG2, CARG3 + | decode_RD4 TMP2, TMP2 + | checknum RB + | add TMP2, TMP2, TMP3 + | checkanyfail >5 + | efdcmpeq CARG2, CARG3 + if (vk) { + | iselgt PC, TMP2, PC + } else { + | iselgt PC, PC, TMP2 + } + |1: + | ins_next + | + |5: // Either or both types are not numbers. + | evcmpeq CARG2, CARG3 + | not TMP3, RB + | cmplwi cr1, TMP3, ~LJ_TISPRI // Primitive? + | crorc 4*cr7+lt, 4*cr0+so, 4*cr0+lt // 1: Same tv or different type. + | cmplwi cr6, TMP3, ~LJ_TISTABUD // Table or userdata? + | crandc 4*cr7+gt, 4*cr0+lt, 4*cr1+gt // 2: Same type and primitive. + | mr SAVE0, PC + if (vk) { + | isel PC, TMP2, PC, 4*cr7+gt + } else { + | isel TMP2, PC, TMP2, 4*cr7+gt + } + | cror 4*cr7+lt, 4*cr7+lt, 4*cr7+gt // 1 or 2. + if (vk) { + | isel PC, TMP2, PC, 4*cr0+so + } else { + | isel PC, PC, TMP2, 4*cr0+so + } + | blt cr7, <1 // Done if 1 or 2. + | blt cr6, <1 // Done if not tab/ud. + | + | // Different tables or userdatas. Need to check __eq metamethod. + | // Field metatable must be at same offset for GCtab and GCudata! + | lwz TAB:TMP2, TAB:CARG2->metatable + | li CARG4, 1-vk // ne = 0 or 1. + | cmplwi TAB:TMP2, 0 + | beq <1 // No metatable? + | lbz TMP2, TAB:TMP2->nomm + | andi. TMP2, TMP2, 1<vmeta_equal // Handle __eq metamethod. + break; + + case BC_ISEQS: case BC_ISNES: + vk = op == BC_ISEQS; + | // RA = src*8, RD = str_const*8 (~), JMP with RD = target + | evlddx TMP0, BASE, RA + | srwi RD, RD, 1 + | lwz INS, 0(PC) + | subfic RD, RD, -4 + | addi PC, PC, 4 + | lwzx STR:TMP1, KBASE, RD // KBASE-4-str_const*4 + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | decode_RD4 TMP2, INS + | evmergelo STR:TMP1, TISSTR, STR:TMP1 + | add TMP2, TMP2, TMP3 + | evcmpeq TMP0, STR:TMP1 + if (vk) { + | isel PC, TMP2, PC, 4*cr0+so + } else { + | isel PC, PC, TMP2, 4*cr0+so + } + | ins_next + break; + + case BC_ISEQN: case BC_ISNEN: + vk = op == BC_ISEQN; + | // RA = src*8, RD = num_const*8, JMP with RD = target + | evlddx TMP0, BASE, RA + | addi PC, PC, 4 + | evlddx TMP1, KBASE, RD + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | lwz INS, -4(PC) + | checknum TMP0 + | checkfail >5 + | efdcmpeq TMP0, TMP1 + |1: + | decode_RD4 TMP2, INS + | add TMP2, TMP2, TMP3 + if (vk) { + | iselgt PC, TMP2, PC + |5: + } else { + | iselgt PC, PC, TMP2 + } + |3: + | ins_next + if (!vk) { + |5: + | decode_RD4 TMP2, INS + | add PC, TMP2, TMP3 + | b <3 + } + break; + + case BC_ISEQP: case BC_ISNEP: + vk = op == BC_ISEQP; + | // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target + | lwzx TMP0, BASE, RA + | srwi TMP1, RD, 3 + | lwz INS, 0(PC) + | addi PC, PC, 4 + | not TMP1, TMP1 + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | cmplw TMP0, TMP1 + | decode_RD4 TMP2, INS + | add TMP2, TMP2, TMP3 + if (vk) { + | iseleq PC, TMP2, PC + } else { + | iseleq PC, PC, TMP2 + } + | ins_next + break; + + /* -- Unary test and copy ops ------------------------------------------- */ + + case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: + | // RA = dst*8 or unused, RD = src*8, JMP with RD = target + | evlddx TMP0, BASE, RD + | evaddw TMP1, TISNIL, TISNIL // Synthesize LJ_TFALSE. + | lwz INS, 0(PC) + | evcmpltu TMP0, TMP1 + | addi PC, PC, 4 + if (op == BC_IST || op == BC_ISF) { + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | decode_RD4 TMP2, INS + | add TMP2, TMP2, TMP3 + if (op == BC_IST) { + | isellt PC, TMP2, PC + } else { + | isellt PC, PC, TMP2 + } + } else { + if (op == BC_ISTC) { + | checkfail >1 + } else { + | checkok >1 + } + | addis PC, PC, -(BCBIAS_J*4 >> 16) + | decode_RD4 TMP2, INS + | evstddx TMP0, BASE, RA + | add PC, PC, TMP2 + |1: + } + | ins_next + break; + + /* -- Unary ops --------------------------------------------------------- */ + + case BC_MOV: + | // RA = dst*8, RD = src*8 + | ins_next1 + | evlddx TMP0, BASE, RD + | evstddx TMP0, BASE, RA + | ins_next2 + break; + case BC_NOT: + | // RA = dst*8, RD = src*8 + | ins_next1 + | lwzx TMP0, BASE, RD + | subfic TMP1, TMP0, LJ_TTRUE + | adde TMP0, TMP0, TMP1 + | stwx TMP0, BASE, RA + | ins_next2 + break; + case BC_UNM: + | // RA = dst*8, RD = src*8 + | evlddx TMP0, BASE, RD + | checknum TMP0 + | checkfail ->vmeta_unm + | efdneg TMP0, TMP0 + | ins_next1 + | evstddx TMP0, BASE, RA + | ins_next2 + break; + case BC_LEN: + | // RA = dst*8, RD = src*8 + | evlddx CARG1, BASE, RD + | checkstr CARG1 + | checkfail >2 + | lwz CRET1, STR:CARG1->len + |1: + | ins_next1 + | efdcfsi TMP0, CRET1 + | evstddx TMP0, BASE, RA + | ins_next2 + |2: + | checktab CARG1 + | checkfail ->vmeta_len +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | lwz TAB:TMP2, TAB:CARG1->metatable + | cmplwi TAB:TMP2, 0 + | bne >9 + |3: +#endif + |->BC_LEN_Z: + | bl extern lj_tab_len // (GCtab *t) + | // Returns uint32_t (but less than 2^31). + | b <1 +#ifdef LUAJIT_ENABLE_LUA52COMPAT + |9: + | lbz TMP0, TAB:TMP2->nomm + | andi. TMP0, TMP0, 1<vmeta_len +#endif + break; + + /* -- Binary ops -------------------------------------------------------- */ + + |.macro ins_arithpre, t0, t1 + | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8 + ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); + ||switch (vk) { + ||case 0: + | evlddx t0, BASE, RB + | checknum t0 + | evlddx t1, KBASE, RC + | checkfail ->vmeta_arith_vn + || break; + ||case 1: + | evlddx t1, BASE, RB + | checknum t1 + | evlddx t0, KBASE, RC + | checkfail ->vmeta_arith_nv + || break; + ||default: + | evlddx t0, BASE, RB + | evlddx t1, BASE, RC + | evmergehi TMP2, t0, t1 + | checknum TMP2 + | checkanyfail ->vmeta_arith_vv + || break; + ||} + |.endmacro + | + |.macro ins_arith, ins + | ins_arithpre TMP0, TMP1 + | ins_next1 + | ins TMP0, TMP0, TMP1 + | evstddx TMP0, BASE, RA + | ins_next2 + |.endmacro + + case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: + | ins_arith efdadd + break; + case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: + | ins_arith efdsub + break; + case BC_MULVN: case BC_MULNV: case BC_MULVV: + | ins_arith efdmul + break; + case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: + | ins_arith efddiv + break; + case BC_MODVN: + | ins_arithpre RD, SAVE0 + |->BC_MODVN_Z: + | efddiv CARG2, RD, SAVE0 + | bl ->vm_floor_efd // floor(b/c) + | efdmul TMP0, CRET2, SAVE0 + | ins_next1 + | efdsub TMP0, RD, TMP0 // b - floor(b/c)*c + | evstddx TMP0, BASE, RA + | ins_next2 + break; + case BC_MODNV: case BC_MODVV: + | ins_arithpre RD, SAVE0 + | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway. + break; + case BC_POW: + | evlddx CARG2, BASE, RB + | evlddx CARG4, BASE, RC + | evmergehi CARG1, CARG4, CARG2 + | checknum CARG1 + | evmergehi CARG3, CARG4, CARG4 + | checkanyfail ->vmeta_arith_vv + | bl extern pow + | evmergelo CRET2, CRET1, CRET2 + | evstddx CRET2, BASE, RA + | ins_next + break; + + case BC_CAT: + | // RA = dst*8, RB = src_start*8, RC = src_end*8 + | sub CARG3, RC, RB + | stw BASE, L->base + | add CARG2, BASE, RC + | mr SAVE0, RB + |->BC_CAT_Z: + | stw PC, SAVE_PC + | mr CARG1, L + | srwi CARG3, CARG3, 3 + | bl extern lj_meta_cat // (lua_State *L, TValue *top, int left) + | // Returns NULL (finished) or TValue * (metamethod). + | cmplwi CRET1, 0 + | lwz BASE, L->base + | bne ->vmeta_binop + | evlddx TMP0, BASE, SAVE0 // Copy result from RB to RA. + | evstddx TMP0, BASE, RA + | ins_next + break; + + /* -- Constant ops ------------------------------------------------------ */ + + case BC_KSTR: + | // RA = dst*8, RD = str_const*8 (~) + | ins_next1 + | srwi TMP1, RD, 1 + | subfic TMP1, TMP1, -4 + | lwzx TMP0, KBASE, TMP1 // KBASE-4-str_const*4 + | evmergelo TMP0, TISSTR, TMP0 + | evstddx TMP0, BASE, RA + | ins_next2 + break; + case BC_KCDATA: +#if LJ_HASFFI + | // RA = dst*8, RD = cdata_const*8 (~) + | ins_next1 + | srwi TMP1, RD, 1 + | subfic TMP1, TMP1, -4 + | lwzx TMP0, KBASE, TMP1 // KBASE-4-cdata_const*4 + | li TMP2, LJ_TCDATA + | evmergelo TMP0, TMP2, TMP0 + | evstddx TMP0, BASE, RA + | ins_next2 +#endif + break; + case BC_KSHORT: + | // RA = dst*8, RD = int16_literal*8 + | srwi TMP1, RD, 3 + | extsh TMP1, TMP1 + | ins_next1 + | efdcfsi TMP0, TMP1 + | evstddx TMP0, BASE, RA + | ins_next2 + break; + case BC_KNUM: + | // RA = dst*8, RD = num_const*8 + | evlddx TMP0, KBASE, RD + | ins_next1 + | evstddx TMP0, BASE, RA + | ins_next2 + break; + case BC_KPRI: + | // RA = dst*8, RD = primitive_type*8 (~) + | srwi TMP1, RD, 3 + | not TMP0, TMP1 + | ins_next1 + | stwx TMP0, BASE, RA + | ins_next2 + break; + case BC_KNIL: + | // RA = base*8, RD = end*8 + | evstddx TISNIL, BASE, RA + | addi RA, RA, 8 + |1: + | evstddx TISNIL, BASE, RA + | cmpw RA, RD + | addi RA, RA, 8 + | blt <1 + | ins_next_ + break; + + /* -- Upvalue and function ops ------------------------------------------ */ + + case BC_UGET: + | // RA = dst*8, RD = uvnum*8 + | ins_next1 + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | srwi RD, RD, 1 + | addi RD, RD, offsetof(GCfuncL, uvptr) + | lwzx UPVAL:RB, LFUNC:RB, RD + | lwz TMP1, UPVAL:RB->v + | evldd TMP0, 0(TMP1) + | evstddx TMP0, BASE, RA + | ins_next2 + break; + case BC_USETV: + | // RA = uvnum*8, RD = src*8 + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | srwi RA, RA, 1 + | addi RA, RA, offsetof(GCfuncL, uvptr) + | evlddx TMP1, BASE, RD + | lwzx UPVAL:RB, LFUNC:RB, RA + | lbz TMP3, UPVAL:RB->marked + | lwz CARG2, UPVAL:RB->v + | andi. TMP3, TMP3, LJ_GC_BLACK // isblack(uv) + | lbz TMP0, UPVAL:RB->closed + | evmergehi TMP2, TMP1, TMP1 + | evstdd TMP1, 0(CARG2) + | cmplwi cr1, TMP0, 0 + | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq + | subi TMP2, TMP2, (LJ_TISNUM+1) + | bne >2 // Upvalue is closed and black? + |1: + | ins_next + | + |2: // Check if new value is collectable. + | cmplwi TMP2, LJ_TISGCV - (LJ_TISNUM+1) + | bge <1 // tvisgcv(v) + | lbz TMP3, GCOBJ:TMP1->gch.marked + | andi. TMP3, TMP3, LJ_GC_WHITES // iswhite(v) + | la CARG1, GG_DISP2G(DISPATCH) + | // Crossed a write barrier. Move the barrier forward. + | beq <1 + | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) + | b <1 + break; + case BC_USETS: + | // RA = uvnum*8, RD = str_const*8 (~) + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | srwi TMP1, RD, 1 + | srwi RA, RA, 1 + | subfic TMP1, TMP1, -4 + | addi RA, RA, offsetof(GCfuncL, uvptr) + | lwzx STR:TMP1, KBASE, TMP1 // KBASE-4-str_const*4 + | lwzx UPVAL:RB, LFUNC:RB, RA + | evmergelo STR:TMP1, TISSTR, STR:TMP1 + | lbz TMP3, UPVAL:RB->marked + | lwz CARG2, UPVAL:RB->v + | andi. TMP3, TMP3, LJ_GC_BLACK // isblack(uv) + | lbz TMP3, STR:TMP1->marked + | lbz TMP2, UPVAL:RB->closed + | evstdd STR:TMP1, 0(CARG2) + | bne >2 + |1: + | ins_next + | + |2: // Check if string is white and ensure upvalue is closed. + | andi. TMP3, TMP3, LJ_GC_WHITES // iswhite(str) + | cmplwi cr1, TMP2, 0 + | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq + | la CARG1, GG_DISP2G(DISPATCH) + | // Crossed a write barrier. Move the barrier forward. + | beq <1 + | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv) + | b <1 + break; + case BC_USETN: + | // RA = uvnum*8, RD = num_const*8 + | ins_next1 + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | srwi RA, RA, 1 + | addi RA, RA, offsetof(GCfuncL, uvptr) + | evlddx TMP0, KBASE, RD + | lwzx UPVAL:RB, LFUNC:RB, RA + | lwz TMP1, UPVAL:RB->v + | evstdd TMP0, 0(TMP1) + | ins_next2 + break; + case BC_USETP: + | // RA = uvnum*8, RD = primitive_type*8 (~) + | ins_next1 + | lwz LFUNC:RB, FRAME_FUNC(BASE) + | srwi RA, RA, 1 + | addi RA, RA, offsetof(GCfuncL, uvptr) + | srwi TMP0, RD, 3 + | lwzx UPVAL:RB, LFUNC:RB, RA + | not TMP0, TMP0 + | lwz TMP1, UPVAL:RB->v + | stw TMP0, 0(TMP1) + | ins_next2 + break; + + case BC_UCLO: + | // RA = level*8, RD = target + | lwz TMP1, L->openupval + | branch_RD // Do this first since RD is not saved. + | stw BASE, L->base + | cmplwi TMP1, 0 + | mr CARG1, L + | beq >1 + | add CARG2, BASE, RA + | bl extern lj_func_closeuv // (lua_State *L, TValue *level) + | lwz BASE, L->base + |1: + | ins_next + break; + + case BC_FNEW: + | // RA = dst*8, RD = proto_const*8 (~) (holding function prototype) + | srwi TMP1, RD, 1 + | stw BASE, L->base + | subfic TMP1, TMP1, -4 + | stw PC, SAVE_PC + | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4 + | mr CARG1, L + | lwz CARG3, FRAME_FUNC(BASE) + | // (lua_State *L, GCproto *pt, GCfuncL *parent) + | bl extern lj_func_newL_gc + | // Returns GCfuncL *. + | lwz BASE, L->base + | evmergelo LFUNC:CRET1, TISFUNC, LFUNC:CRET1 + | evstddx LFUNC:CRET1, BASE, RA + | ins_next + break; + + /* -- Table ops --------------------------------------------------------- */ + + case BC_TNEW: + case BC_TDUP: + | // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~) + | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH) + | mr CARG1, L + | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH) + | stw BASE, L->base + | cmplw TMP0, TMP1 + | stw PC, SAVE_PC + | bge >5 + |1: + if (op == BC_TNEW) { + | rlwinm CARG2, RD, 29, 21, 31 + | rlwinm CARG3, RD, 18, 27, 31 + | cmpwi CARG2, 0x7ff + | li TMP1, 0x801 + | iseleq CARG2, TMP1, CARG2 + | bl extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits) + | // Returns Table *. + } else { + | srwi TMP1, RD, 1 + | subfic TMP1, TMP1, -4 + | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4 + | bl extern lj_tab_dup // (lua_State *L, Table *kt) + | // Returns Table *. + } + | lwz BASE, L->base + | evmergelo TAB:CRET1, TISTAB, TAB:CRET1 + | evstddx TAB:CRET1, BASE, RA + | ins_next + |5: + | mr SAVE0, RD + | bl extern lj_gc_step_fixtop // (lua_State *L) + | mr RD, SAVE0 + | mr CARG1, L + | b <1 + break; + + case BC_GGET: + | // RA = dst*8, RD = str_const*8 (~) + case BC_GSET: + | // RA = src*8, RD = str_const*8 (~) + | lwz LFUNC:TMP2, FRAME_FUNC(BASE) + | srwi TMP1, RD, 1 + | lwz TAB:RB, LFUNC:TMP2->env + | subfic TMP1, TMP1, -4 + | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 + if (op == BC_GGET) { + | b ->BC_TGETS_Z + } else { + | b ->BC_TSETS_Z + } + break; + + case BC_TGETV: + | // RA = dst*8, RB = table*8, RC = key*8 + | evlddx TAB:RB, BASE, RB + | evlddx RC, BASE, RC + | checktab TAB:RB + | checkfail ->vmeta_tgetv + | checknum RC + | checkfail >5 + | // Convert number key to integer + | efdctsi TMP2, RC + | lwz TMP0, TAB:RB->asize + | efdcfsi TMP1, TMP2 + | cmplw cr0, TMP0, TMP2 + | efdcmpeq cr1, RC, TMP1 + | lwz TMP1, TAB:RB->array + | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+gt + | slwi TMP2, TMP2, 3 + | ble ->vmeta_tgetv // Integer key and in array part? + | evlddx TMP1, TMP1, TMP2 + | checknil TMP1 + | checkok >2 + |1: + | evstddx TMP1, BASE, RA + | ins_next + | + |2: // Check for __index if table value is nil. + | lwz TAB:TMP2, TAB:RB->metatable + | cmplwi TAB:TMP2, 0 + | beq <1 // No metatable: done. + | lbz TMP0, TAB:TMP2->nomm + | andi. TMP0, TMP0, 1<vmeta_tgetv + | + |5: + | checkstr STR:RC // String key? + | checkok ->BC_TGETS_Z + | b ->vmeta_tgetv + break; + case BC_TGETS: + | // RA = dst*8, RB = table*8, RC = str_const*8 (~) + | evlddx TAB:RB, BASE, RB + | srwi TMP1, RC, 1 + | checktab TAB:RB + | subfic TMP1, TMP1, -4 + | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 + | checkfail ->vmeta_tgets1 + |->BC_TGETS_Z: + | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8 + | lwz TMP0, TAB:RB->hmask + | lwz TMP1, STR:RC->hash + | lwz NODE:TMP2, TAB:RB->node + | evmergelo STR:RC, TISSTR, STR:RC + | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask + | slwi TMP0, TMP1, 5 + | slwi TMP1, TMP1, 3 + | sub TMP1, TMP0, TMP1 + | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) + |1: + | evldd TMP0, NODE:TMP2->key + | evldd TMP1, NODE:TMP2->val + | evcmpeq TMP0, STR:RC + | checkanyfail >4 + | checknil TMP1 + | checkok >5 // Key found, but nil value? + |3: + | evstddx TMP1, BASE, RA + | ins_next + | + |4: // Follow hash chain. + | lwz NODE:TMP2, NODE:TMP2->next + | cmplwi NODE:TMP2, 0 + | bne <1 + | // End of hash chain: key not found, nil result. + | evmr TMP1, TISNIL + | + |5: // Check for __index if table value is nil. + | lwz TAB:TMP2, TAB:RB->metatable + | cmplwi TAB:TMP2, 0 + | beq <3 // No metatable: done. + | lbz TMP0, TAB:TMP2->nomm + | andi. TMP0, TMP0, 1<vmeta_tgets + break; + case BC_TGETB: + | // RA = dst*8, RB = table*8, RC = index*8 + | evlddx TAB:RB, BASE, RB + | srwi TMP0, RC, 3 + | checktab TAB:RB + | checkfail ->vmeta_tgetb + | lwz TMP1, TAB:RB->asize + | lwz TMP2, TAB:RB->array + | cmplw TMP0, TMP1 + | bge ->vmeta_tgetb + | evlddx TMP1, TMP2, RC + | checknil TMP1 + | checkok >5 + |1: + | ins_next1 + | evstddx TMP1, BASE, RA + | ins_next2 + | + |5: // Check for __index if table value is nil. + | lwz TAB:TMP2, TAB:RB->metatable + | cmplwi TAB:TMP2, 0 + | beq <1 // No metatable: done. + | lbz TMP2, TAB:TMP2->nomm + | andi. TMP2, TMP2, 1<vmeta_tgetb // Caveat: preserve TMP0! + break; + + case BC_TSETV: + | // RA = src*8, RB = table*8, RC = key*8 + | evlddx TAB:RB, BASE, RB + | evlddx RC, BASE, RC + | checktab TAB:RB + | checkfail ->vmeta_tsetv + | checknum RC + | checkfail >5 + | // Convert number key to integer + | efdctsi TMP2, RC + | evlddx SAVE0, BASE, RA + | lwz TMP0, TAB:RB->asize + | efdcfsi TMP1, TMP2 + | cmplw cr0, TMP0, TMP2 + | efdcmpeq cr1, RC, TMP1 + | lwz TMP1, TAB:RB->array + | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+gt + | slwi TMP0, TMP2, 3 + | ble ->vmeta_tsetv // Integer key and in array part? + | lbz TMP3, TAB:RB->marked + | evlddx TMP2, TMP1, TMP0 + | checknil TMP2 + | checkok >3 + |1: + | andi. TMP2, TMP3, LJ_GC_BLACK // isblack(table) + | evstddx SAVE0, TMP1, TMP0 + | bne >7 + |2: + | ins_next + | + |3: // Check for __newindex if previous value is nil. + | lwz TAB:TMP2, TAB:RB->metatable + | cmplwi TAB:TMP2, 0 + | beq <1 // No metatable: done. + | lbz TMP2, TAB:TMP2->nomm + | andi. TMP2, TMP2, 1<vmeta_tsetv + | + |5: + | checkstr STR:RC // String key? + | checkok ->BC_TSETS_Z + | b ->vmeta_tsetv + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, TMP3, TMP0 + | b <2 + break; + case BC_TSETS: + | // RA = src*8, RB = table*8, RC = str_const*8 (~) + | evlddx TAB:RB, BASE, RB + | srwi TMP1, RC, 1 + | checktab TAB:RB + | subfic TMP1, TMP1, -4 + | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4 + | checkfail ->vmeta_tsets1 + |->BC_TSETS_Z: + | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = src*8 + | lwz TMP0, TAB:RB->hmask + | lwz TMP1, STR:RC->hash + | lwz NODE:TMP2, TAB:RB->node + | evmergelo STR:RC, TISSTR, STR:RC + | stb ZERO, TAB:RB->nomm // Clear metamethod cache. + | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask + | evlddx SAVE0, BASE, RA + | slwi TMP0, TMP1, 5 + | slwi TMP1, TMP1, 3 + | sub TMP1, TMP0, TMP1 + | lbz TMP3, TAB:RB->marked + | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8) + |1: + | evldd TMP0, NODE:TMP2->key + | evldd TMP1, NODE:TMP2->val + | evcmpeq TMP0, STR:RC + | checkanyfail >5 + | checknil TMP1 + | checkok >4 // Key found, but nil value? + |2: + | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) + | evstdd SAVE0, NODE:TMP2->val + | bne >7 + |3: + | ins_next + | + |4: // Check for __newindex if previous value is nil. + | lwz TAB:TMP1, TAB:RB->metatable + | cmplwi TAB:TMP1, 0 + | beq <2 // No metatable: done. + | lbz TMP0, TAB:TMP1->nomm + | andi. TMP0, TMP0, 1<vmeta_tsets + | + |5: // Follow hash chain. + | lwz NODE:TMP2, NODE:TMP2->next + | cmplwi NODE:TMP2, 0 + | bne <1 + | // End of hash chain: key not found, add a new one. + | + | // But check for __newindex first. + | lwz TAB:TMP1, TAB:RB->metatable + | la CARG3, DISPATCH_GL(tmptv)(DISPATCH) + | stw PC, SAVE_PC + | mr CARG1, L + | cmplwi TAB:TMP1, 0 + | stw BASE, L->base + | beq >6 // No metatable: continue. + | lbz TMP0, TAB:TMP1->nomm + | andi. TMP0, TMP0, 1<vmeta_tsets // 'no __newindex' flag NOT set: check. + |6: + | mr CARG2, TAB:RB + | evstdd STR:RC, 0(CARG3) + | bl extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k) + | // Returns TValue *. + | lwz BASE, L->base + | evstdd SAVE0, 0(CRET1) + | b <3 // No 2nd write barrier needed. + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, TMP3, TMP0 + | b <3 + break; + case BC_TSETB: + | // RA = src*8, RB = table*8, RC = index*8 + | evlddx TAB:RB, BASE, RB + | srwi TMP0, RC, 3 + | checktab TAB:RB + | checkfail ->vmeta_tsetb + | lwz TMP1, TAB:RB->asize + | lwz TMP2, TAB:RB->array + | lbz TMP3, TAB:RB->marked + | cmplw TMP0, TMP1 + | evlddx SAVE0, BASE, RA + | bge ->vmeta_tsetb + | evlddx TMP1, TMP2, RC + | checknil TMP1 + | checkok >5 + |1: + | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) + | evstddx SAVE0, TMP2, RC + | bne >7 + |2: + | ins_next + | + |5: // Check for __newindex if previous value is nil. + | lwz TAB:TMP1, TAB:RB->metatable + | cmplwi TAB:TMP1, 0 + | beq <1 // No metatable: done. + | lbz TMP1, TAB:TMP1->nomm + | andi. TMP1, TMP1, 1<vmeta_tsetb // Caveat: preserve TMP0! + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, TMP3, TMP0 + | b <2 + break; + + case BC_TSETM: + | // RA = base*8 (table at base-1), RD = num_const*8 (start index) + | add RA, BASE, RA + |1: + | add TMP3, KBASE, RD + | lwz TAB:CARG2, -4(RA) // Guaranteed to be a table. + | addic. TMP0, MULTRES, -8 + | lwz TMP3, 4(TMP3) // Integer constant is in lo-word. + | srwi CARG3, TMP0, 3 + | beq >4 // Nothing to copy? + | add CARG3, CARG3, TMP3 + | lwz TMP2, TAB:CARG2->asize + | slwi TMP1, TMP3, 3 + | lbz TMP3, TAB:CARG2->marked + | cmplw CARG3, TMP2 + | add TMP2, RA, TMP0 + | lwz TMP0, TAB:CARG2->array + | bgt >5 + | add TMP1, TMP1, TMP0 + | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table) + |3: // Copy result slots to table. + | evldd TMP0, 0(RA) + | addi RA, RA, 8 + | cmpw cr1, RA, TMP2 + | evstdd TMP0, 0(TMP1) + | addi TMP1, TMP1, 8 + | blt cr1, <3 + | bne >7 + |4: + | ins_next + | + |5: // Need to resize array part. + | stw BASE, L->base + | mr CARG1, L + | stw PC, SAVE_PC + | mr SAVE0, RD + | bl extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize) + | // Must not reallocate the stack. + | mr RD, SAVE0 + | b <1 + | + |7: // Possible table write barrier for any value. Skip valiswhite check. + | barrierback TAB:CARG2, TMP3, TMP0 + | b <4 + break; + + /* -- Calls and vararg handling ----------------------------------------- */ + + case BC_CALLM: + | // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8 + | add NARGS8:RC, NARGS8:RC, MULTRES + | // Fall through. Assumes BC_CALL follows. + break; + case BC_CALL: + | // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8 + | evlddx LFUNC:RB, BASE, RA + | mr TMP2, BASE + | add BASE, BASE, RA + | subi NARGS8:RC, NARGS8:RC, 8 + | checkfunc LFUNC:RB + | addi BASE, BASE, 8 + | checkfail ->vmeta_call + | ins_call + break; + + case BC_CALLMT: + | // RA = base*8, (RB = 0,) RC = extra_nargs*8 + | add NARGS8:RC, NARGS8:RC, MULTRES + | // Fall through. Assumes BC_CALLT follows. + break; + case BC_CALLT: + | // RA = base*8, (RB = 0,) RC = (nargs+1)*8 + | evlddx LFUNC:RB, BASE, RA + | add RA, BASE, RA + | lwz TMP1, FRAME_PC(BASE) + | subi NARGS8:RC, NARGS8:RC, 8 + | checkfunc LFUNC:RB + | addi RA, RA, 8 + | checkfail ->vmeta_callt + |->BC_CALLT_Z: + | andi. TMP0, TMP1, FRAME_TYPE // Caveat: preserve cr0 until the crand. + | lbz TMP3, LFUNC:RB->ffid + | xori TMP2, TMP1, FRAME_VARG + | cmplwi cr1, NARGS8:RC, 0 + | bne >7 + |1: + | stw LFUNC:RB, FRAME_FUNC(BASE) // Copy function down, but keep PC. + | li TMP2, 0 + | cmplwi cr7, TMP3, 1 // (> FF_C) Calling a fast function? + | beq cr1, >3 + |2: + | addi TMP3, TMP2, 8 + | evlddx TMP0, RA, TMP2 + | cmplw cr1, TMP3, NARGS8:RC + | evstddx TMP0, BASE, TMP2 + | mr TMP2, TMP3 + | bne cr1, <2 + |3: + | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+gt + | beq >5 + |4: + | ins_callt + | + |5: // Tailcall to a fast function with a Lua frame below. + | lwz INS, -4(TMP1) + | decode_RA8 RA, INS + | sub TMP1, BASE, RA + | lwz LFUNC:TMP1, FRAME_FUNC-8(TMP1) + | lwz TMP1, LFUNC:TMP1->pc + | lwz KBASE, PC2PROTO(k)(TMP1) // Need to prepare KBASE. + | b <4 + | + |7: // Tailcall from a vararg function. + | andi. TMP0, TMP2, FRAME_TYPEP + | bne <1 // Vararg frame below? + | sub BASE, BASE, TMP2 // Relocate BASE down. + | lwz TMP1, FRAME_PC(BASE) + | andi. TMP0, TMP1, FRAME_TYPE + | b <1 + break; + + case BC_ITERC: + | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8)) + | subi RA, RA, 24 // evldd doesn't support neg. offsets. + | mr TMP2, BASE + | evlddx LFUNC:RB, BASE, RA + | add BASE, BASE, RA + | evldd TMP0, 8(BASE) + | evldd TMP1, 16(BASE) + | evstdd LFUNC:RB, 24(BASE) // Copy callable. + | checkfunc LFUNC:RB + | evstdd TMP0, 32(BASE) // Copy state. + | li NARGS8:RC, 16 // Iterators get 2 arguments. + | evstdd TMP1, 40(BASE) // Copy control var. + | addi BASE, BASE, 32 + | checkfail ->vmeta_call + | ins_call + break; + + case BC_ITERN: + | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8) +#if LJ_HASJIT + | // NYI: add hotloop, record BC_ITERN. +#endif + | add RA, BASE, RA + | lwz TAB:RB, -12(RA) + | lwz RC, -4(RA) // Get index from control var. + | lwz TMP0, TAB:RB->asize + | lwz TMP1, TAB:RB->array + | addi PC, PC, 4 + |1: // Traverse array part. + | cmplw RC, TMP0 + | slwi TMP3, RC, 3 + | bge >5 // Index points after array part? + | evlddx TMP2, TMP1, TMP3 + | checknil TMP2 + | lwz INS, -4(PC) + | checkok >4 + | efdcfsi TMP0, RC + | addi RC, RC, 1 + | addis TMP3, PC, -(BCBIAS_J*4 >> 16) + | evstdd TMP2, 8(RA) + | decode_RD4 TMP1, INS + | stw RC, -4(RA) // Update control var. + | add PC, TMP1, TMP3 + | evstdd TMP0, 0(RA) + |3: + | ins_next + | + |4: // Skip holes in array part. + | addi RC, RC, 1 + | b <1 + | + |5: // Traverse hash part. + | lwz TMP1, TAB:RB->hmask + | sub RC, RC, TMP0 + | lwz TMP2, TAB:RB->node + |6: + | cmplw RC, TMP1 // End of iteration? Branch to ITERL+1. + | slwi TMP3, RC, 5 + | bgt <3 + | slwi RB, RC, 3 + | sub TMP3, TMP3, RB + | evlddx RB, TMP2, TMP3 + | add NODE:TMP3, TMP2, TMP3 + | checknil RB + | lwz INS, -4(PC) + | checkok >7 + | evldd TMP3, NODE:TMP3->key + | addis TMP2, PC, -(BCBIAS_J*4 >> 16) + | evstdd RB, 8(RA) + | add RC, RC, TMP0 + | decode_RD4 TMP1, INS + | evstdd TMP3, 0(RA) + | addi RC, RC, 1 + | add PC, TMP1, TMP2 + | stw RC, -4(RA) // Update control var. + | b <3 + | + |7: // Skip holes in hash part. + | addi RC, RC, 1 + | b <6 + break; + + case BC_ISNEXT: + | // RA = base*8, RD = target (points to ITERN) + | add RA, BASE, RA + | li TMP2, -24 + | evlddx CFUNC:TMP1, RA, TMP2 + | lwz TMP2, -16(RA) + | lwz TMP3, -8(RA) + | evmergehi TMP0, CFUNC:TMP1, CFUNC:TMP1 + | cmpwi cr0, TMP2, LJ_TTAB + | cmpwi cr1, TMP0, LJ_TFUNC + | cmpwi cr6, TMP3, LJ_TNIL + | bne cr1, >5 + | lbz TMP1, CFUNC:TMP1->ffid + | crand 4*cr0+eq, 4*cr0+eq, 4*cr6+eq + | cmpwi cr7, TMP1, FF_next_N + | srwi TMP0, RD, 1 + | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq + | add TMP3, PC, TMP0 + | bne cr0, >5 + | stw ZERO, -4(RA) // Initialize control var. + | addis PC, TMP3, -(BCBIAS_J*4 >> 16) + |1: + | ins_next + |5: // Despecialize bytecode if any of the checks fail. + | li TMP0, BC_JMP + | li TMP1, BC_ITERC + | stb TMP0, -1(PC) + | addis PC, TMP3, -(BCBIAS_J*4 >> 16) + | stb TMP1, 3(PC) + | b <1 + break; + + case BC_VARG: + | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8 + | lwz TMP0, FRAME_PC(BASE) + | add RC, BASE, RC + | add RA, BASE, RA + | addi RC, RC, FRAME_VARG + | add TMP2, RA, RB + | subi TMP3, BASE, 8 // TMP3 = vtop + | sub RC, RC, TMP0 // RC = vbase + | // Note: RC may now be even _above_ BASE if nargs was < numparams. + | cmplwi cr1, RB, 0 + | sub. TMP1, TMP3, RC + | beq cr1, >5 // Copy all varargs? + | subi TMP2, TMP2, 16 + | ble >2 // No vararg slots? + |1: // Copy vararg slots to destination slots. + | evldd TMP0, 0(RC) + | addi RC, RC, 8 + | evstdd TMP0, 0(RA) + | cmplw RA, TMP2 + | cmplw cr1, RC, TMP3 + | bge >3 // All destination slots filled? + | addi RA, RA, 8 + | blt cr1, <1 // More vararg slots? + |2: // Fill up remainder with nil. + | evstdd TISNIL, 0(RA) + | cmplw RA, TMP2 + | addi RA, RA, 8 + | blt <2 + |3: + | ins_next + | + |5: // Copy all varargs. + | lwz TMP0, L->maxstack + | li MULTRES, 8 // MULTRES = (0+1)*8 + | ble <3 // No vararg slots? + | add TMP2, RA, TMP1 + | cmplw TMP2, TMP0 + | addi MULTRES, TMP1, 8 + | bgt >7 + |6: + | evldd TMP0, 0(RC) + | addi RC, RC, 8 + | evstdd TMP0, 0(RA) + | cmplw RC, TMP3 + | addi RA, RA, 8 + | blt <6 // More vararg slots? + | b <3 + | + |7: // Grow stack for varargs. + | mr CARG1, L + | stw RA, L->top + | sub SAVE0, RC, BASE // Need delta, because BASE may change. + | stw BASE, L->base + | sub RA, RA, BASE + | stw PC, SAVE_PC + | srwi CARG2, TMP1, 3 + | bl extern lj_state_growstack // (lua_State *L, int n) + | lwz BASE, L->base + | add RA, BASE, RA + | add RC, BASE, SAVE0 + | subi TMP3, BASE, 8 + | b <6 + break; + + /* -- Returns ----------------------------------------------------------- */ + + case BC_RETM: + | // RA = results*8, RD = extra_nresults*8 + | add RD, RD, MULTRES // MULTRES >= 8, so RD >= 8. + | // Fall through. Assumes BC_RET follows. + break; + + case BC_RET: + | // RA = results*8, RD = (nresults+1)*8 + | lwz PC, FRAME_PC(BASE) + | add RA, BASE, RA + | mr MULTRES, RD + |1: + | andi. TMP0, PC, FRAME_TYPE + | xori TMP1, PC, FRAME_VARG + | bne ->BC_RETV_Z + | + |->BC_RET_Z: + | // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return + | lwz INS, -4(PC) + | cmpwi RD, 8 + | subi TMP2, BASE, 8 + | subi RC, RD, 8 + | decode_RB8 RB, INS + | beq >3 + | li TMP1, 0 + |2: + | addi TMP3, TMP1, 8 + | evlddx TMP0, RA, TMP1 + | cmpw TMP3, RC + | evstddx TMP0, TMP2, TMP1 + | beq >3 + | addi TMP1, TMP3, 8 + | evlddx TMP0, RA, TMP3 + | cmpw TMP1, RC + | evstddx TMP0, TMP2, TMP3 + | bne <2 + |3: + |5: + | cmplw RB, RD + | decode_RA8 RA, INS + | bgt >6 + | sub BASE, TMP2, RA + | lwz LFUNC:TMP1, FRAME_FUNC(BASE) + | ins_next1 + | lwz TMP1, LFUNC:TMP1->pc + | lwz KBASE, PC2PROTO(k)(TMP1) + | ins_next2 + | + |6: // Fill up results with nil. + | subi TMP1, RD, 8 + | addi RD, RD, 8 + | evstddx TISNIL, TMP2, TMP1 + | b <5 + | + |->BC_RETV_Z: // Non-standard return case. + | andi. TMP2, TMP1, FRAME_TYPEP + | bne ->vm_return + | // Return from vararg function: relocate BASE down. + | sub BASE, BASE, TMP1 + | lwz PC, FRAME_PC(BASE) + | b <1 + break; + + case BC_RET0: case BC_RET1: + | // RA = results*8, RD = (nresults+1)*8 + | lwz PC, FRAME_PC(BASE) + | add RA, BASE, RA + | mr MULTRES, RD + | andi. TMP0, PC, FRAME_TYPE + | xori TMP1, PC, FRAME_VARG + | bne ->BC_RETV_Z + | + | lwz INS, -4(PC) + | subi TMP2, BASE, 8 + | decode_RB8 RB, INS + if (op == BC_RET1) { + | evldd TMP0, 0(RA) + | evstdd TMP0, 0(TMP2) + } + |5: + | cmplw RB, RD + | decode_RA8 RA, INS + | bgt >6 + | sub BASE, TMP2, RA + | lwz LFUNC:TMP1, FRAME_FUNC(BASE) + | ins_next1 + | lwz TMP1, LFUNC:TMP1->pc + | lwz KBASE, PC2PROTO(k)(TMP1) + | ins_next2 + | + |6: // Fill up results with nil. + | subi TMP1, RD, 8 + | addi RD, RD, 8 + | evstddx TISNIL, TMP2, TMP1 + | b <5 + break; + + /* -- Loops and branches ------------------------------------------------ */ + + case BC_FORL: +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_IFORL follows. + break; + + case BC_JFORI: + case BC_JFORL: +#if !LJ_HASJIT + break; +#endif + case BC_FORI: + case BC_IFORL: + | // RA = base*8, RD = target (after end of loop or start of loop) + vk = (op == BC_IFORL || op == BC_JFORL); + | add RA, BASE, RA + | evldd TMP1, FORL_IDX*8(RA) + | evldd TMP3, FORL_STEP*8(RA) + | evldd TMP2, FORL_STOP*8(RA) + if (!vk) { + | evcmpgtu cr0, TMP1, TISNUM + | evcmpgtu cr7, TMP3, TISNUM + | evcmpgtu cr1, TMP2, TISNUM + | cror 4*cr0+lt, 4*cr0+lt, 4*cr7+lt + | cror 4*cr0+lt, 4*cr0+lt, 4*cr1+lt + | blt ->vmeta_for + } + if (vk) { + | efdadd TMP1, TMP1, TMP3 + | evstdd TMP1, FORL_IDX*8(RA) + } + | evcmpgts TMP3, TISNIL + | evstdd TMP1, FORL_EXT*8(RA) + | bge >2 + | efdcmpgt TMP1, TMP2 + |1: + if (op != BC_JFORL) { + | srwi RD, RD, 1 + | add RD, PC, RD + if (op == BC_JFORI) { + | addis PC, RD, -(BCBIAS_J*4 >> 16) + } else { + | addis RD, RD, -(BCBIAS_J*4 >> 16) + } + } + if (op == BC_FORI) { + | iselgt PC, RD, PC + } else if (op == BC_IFORL) { + | iselgt PC, PC, RD + } else { + | ble =>BC_JLOOP + } + | ins_next + |2: + | efdcmpgt TMP2, TMP1 + | b <1 + break; + + case BC_ITERL: +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_IITERL follows. + break; + + case BC_JITERL: +#if !LJ_HASJIT + break; +#endif + case BC_IITERL: + | // RA = base*8, RD = target + | evlddx TMP1, BASE, RA + | subi RA, RA, 8 + | checknil TMP1 + | checkok >1 // Stop if iterator returned nil. + if (op == BC_JITERL) { + | NYI + } else { + | branch_RD // Otherwise save control var + branch. + | evstddx TMP1, BASE, RA + } + |1: + | ins_next + break; + + case BC_LOOP: + | // RA = base*8, RD = target (loop extent) + | // Note: RA/RD is only used by trace recorder to determine scope/extent + | // This opcode does NOT jump, it's only purpose is to detect a hot loop. +#if LJ_HASJIT + | hotloop +#endif + | // Fall through. Assumes BC_ILOOP follows. + break; + + case BC_ILOOP: + | // RA = base*8, RD = target (loop extent) + | ins_next + break; + + case BC_JLOOP: +#if LJ_HASJIT + | NYI +#endif + break; + + case BC_JMP: + | // RA = base*8 (only used by trace recorder), RD = target + | branch_RD + | ins_next + break; + + /* -- Function headers -------------------------------------------------- */ + + case BC_FUNCF: +#if LJ_HASJIT + | hotcall +#endif + case BC_FUNCV: /* NYI: compiled vararg functions. */ + | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow. + break; + + case BC_JFUNCF: +#if !LJ_HASJIT + break; +#endif + case BC_IFUNCF: + | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 + | lwz TMP2, L->maxstack + | lbz TMP1, -4+PC2PROTO(numparams)(PC) + | lwz KBASE, -4+PC2PROTO(k)(PC) + | cmplw RA, TMP2 + | slwi TMP1, TMP1, 3 + | bgt ->vm_growstack_l + | ins_next1 + |2: + | cmplw NARGS8:RC, TMP1 // Check for missing parameters. + | ble >3 + if (op == BC_JFUNCF) { + | NYI + } else { + | ins_next2 + } + | + |3: // Clear missing parameters. + | evstddx TISNIL, BASE, NARGS8:RC + | addi NARGS8:RC, NARGS8:RC, 8 + | b <2 + break; + + case BC_JFUNCV: +#if !LJ_HASJIT + break; +#endif + | NYI // NYI: compiled vararg functions + break; /* NYI: compiled vararg functions. */ + + case BC_IFUNCV: + | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 + | lwz TMP2, L->maxstack + | add TMP1, BASE, RC + | add TMP0, RA, RC + | stw LFUNC:RB, 4(TMP1) // Store copy of LFUNC. + | addi TMP3, RC, 8+FRAME_VARG + | lwz KBASE, -4+PC2PROTO(k)(PC) + | cmplw TMP0, TMP2 + | stw TMP3, 0(TMP1) // Store delta + FRAME_VARG. + | bge ->vm_growstack_l + | lbz TMP2, -4+PC2PROTO(numparams)(PC) + | mr RA, BASE + | mr RC, TMP1 + | ins_next1 + | cmpwi TMP2, 0 + | addi BASE, TMP1, 8 + | beq >3 + |1: + | cmplw RA, RC // Less args than parameters? + | evldd TMP0, 0(RA) + | bge >4 + | evstdd TISNIL, 0(RA) // Clear old fixarg slot (help the GC). + | addi RA, RA, 8 + |2: + | addic. TMP2, TMP2, -1 + | evstdd TMP0, 8(TMP1) + | addi TMP1, TMP1, 8 + | bne <1 + |3: + | ins_next2 + | + |4: // Clear missing parameters. + | evmr TMP0, TISNIL + | b <2 + break; + + case BC_FUNCC: + case BC_FUNCCW: + | // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8 + if (op == BC_FUNCC) { + | lwz TMP3, CFUNC:RB->f + } else { + | lwz TMP3, DISPATCH_GL(wrapf)(DISPATCH) + } + | add TMP1, RA, NARGS8:RC + | lwz TMP2, L->maxstack + | add RC, BASE, NARGS8:RC + | stw BASE, L->base + | cmplw TMP1, TMP2 + | stw RC, L->top + | li_vmstate C + | mtctr TMP3 + if (op == BC_FUNCCW) { + | lwz CARG2, CFUNC:RB->f + } + | mr CARG1, L + | bgt ->vm_growstack_c // Need to grow stack. + | st_vmstate + | bctrl // (lua_State *L [, lua_CFunction f]) + | // Returns nresults. + | lwz TMP1, L->top + | slwi RD, CRET1, 3 + | lwz BASE, L->base + | li_vmstate INTERP + | lwz PC, FRAME_PC(BASE) // Fetch PC of caller. + | sub RA, TMP1, RD // RA = L->top - nresults*8 + | st_vmstate + | b ->vm_returnc + break; + + /* ---------------------------------------------------------------------- */ + + default: + fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); + exit(2); + break; + } +} + +static int build_backend(BuildCtx *ctx) +{ + int op; + + dasm_growpc(Dst, BC__MAX); + + build_subroutines(ctx); + + |.code_op + for (op = 0; op < BC__MAX; op++) + build_ins(ctx, (BCOp)op, op); + + return BC__MAX; +} + +/* Emit pseudo frame-info for all assembler functions. */ +static void emit_asm_debug(BuildCtx *ctx) +{ + int i; + switch (ctx->mode) { + case BUILD_elfasm: + fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); + fprintf(ctx->fp, + ".Lframe0:\n" + "\t.long .LECIE0-.LSCIE0\n" + ".LSCIE0:\n" + "\t.long 0xffffffff\n" + "\t.byte 0x1\n" + "\t.string \"\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -4\n" + "\t.byte 65\n" + "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n" + "\t.align 2\n" + ".LECIE0:\n\n"); + fprintf(ctx->fp, + ".LSFDE0:\n" + "\t.long .LEFDE0-.LASFDE0\n" + ".LASFDE0:\n" + "\t.long .Lframe0\n" + "\t.long .Lbegin\n" + "\t.long %d\n" + "\t.byte 0xe\n\t.uleb128 %d\n" + "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" + "\t.byte 0x5\n\t.uleb128 70\n\t.sleb128 37\n", + (int)ctx->codesz, CFRAME_SIZE); + for (i = 14; i <= 31; i++) + fprintf(ctx->fp, + "\t.byte %d\n\t.uleb128 %d\n" + "\t.byte 5\n\t.uleb128 %d\n\t.uleb128 %d\n", + 0x80+i, 1+2*(31-i), 1200+i, 2+2*(31-i)); + fprintf(ctx->fp, + "\t.align 2\n" + ".LEFDE0:\n\n"); + fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); + fprintf(ctx->fp, + ".Lframe1:\n" + "\t.long .LECIE1-.LSCIE1\n" + ".LSCIE1:\n" + "\t.long 0\n" + "\t.byte 0x1\n" + "\t.string \"zPR\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -4\n" + "\t.byte 65\n" + "\t.uleb128 6\n" /* augmentation length */ + "\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 1\n\t.uleb128 0\n" + "\t.align 2\n" + ".LECIE1:\n\n"); + fprintf(ctx->fp, + ".LSFDE1:\n" + "\t.long .LEFDE1-.LASFDE1\n" + ".LASFDE1:\n" + "\t.long .LASFDE1-.Lframe1\n" + "\t.long .Lbegin-.\n" + "\t.long %d\n" + "\t.uleb128 0\n" /* augmentation length */ + "\t.byte 0xe\n\t.uleb128 %d\n" + "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n" + "\t.byte 0x5\n\t.uleb128 70\n\t.sleb128 37\n", + (int)ctx->codesz, CFRAME_SIZE); + for (i = 14; i <= 31; i++) + fprintf(ctx->fp, + "\t.byte %d\n\t.uleb128 %d\n" + "\t.byte 5\n\t.uleb128 %d\n\t.uleb128 %d\n", + 0x80+i, 1+2*(31-i), 1200+i, 2+2*(31-i)); + fprintf(ctx->fp, + "\t.align 2\n" + ".LEFDE1:\n\n"); + break; + default: + break; + } +} + diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc new file mode 100644 index 00000000..30ee5b67 --- /dev/null +++ b/src/vm_x86.dasc @@ -0,0 +1,6458 @@ +|// Low-level VM code for x86 CPUs. +|// Bytecode interpreter, fast functions and helper functions. +|// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h +| +|.if X64 +|.arch x64 +|.else +|.arch x86 +|.endif +|.section code_op, code_sub +| +|.actionlist build_actionlist +|.globals GLOB_ +|.globalnames globnames +|.externnames extnames +| +|//----------------------------------------------------------------------- +| +|// Fixed register assignments for the interpreter. +|// This is very fragile and has many dependencies. Caveat emptor. +|.define BASE, edx // Not C callee-save, refetched anyway. +|.if not X64 +|.define KBASE, edi // Must be C callee-save. +|.define KBASEa, KBASE +|.define PC, esi // Must be C callee-save. +|.define PCa, PC +|.define DISPATCH, ebx // Must be C callee-save. +|.elif X64WIN +|.define KBASE, edi // Must be C callee-save. +|.define KBASEa, rdi +|.define PC, esi // Must be C callee-save. +|.define PCa, rsi +|.define DISPATCH, ebx // Must be C callee-save. +|.else +|.define KBASE, r15d // Must be C callee-save. +|.define KBASEa, r15 +|.define PC, ebx // Must be C callee-save. +|.define PCa, rbx +|.define DISPATCH, r14d // Must be C callee-save. +|.endif +| +|.define RA, ecx +|.define RAH, ch +|.define RAL, cl +|.define RB, ebp // Must be ebp (C callee-save). +|.define RC, eax // Must be eax (fcomparepp and others). +|.define RCW, ax +|.define RCH, ah +|.define RCL, al +|.define OP, RB +|.define RD, RC +|.define RDW, RCW +|.define RDL, RCL +|.if X64 +|.define RAa, rcx +|.define RBa, rbp +|.define RCa, rax +|.define RDa, rax +|.else +|.define RAa, RA +|.define RBa, RB +|.define RCa, RC +|.define RDa, RD +|.endif +| +|.if not X64 +|.define FCARG1, ecx // x86 fastcall arguments. +|.define FCARG2, edx +|.elif X64WIN +|.define CARG1, rcx // x64/WIN64 C call arguments. +|.define CARG2, rdx +|.define CARG3, r8 +|.define CARG4, r9 +|.define CARG1d, ecx +|.define CARG2d, edx +|.define CARG3d, r8d +|.define CARG4d, r9d +|.define FCARG1, CARG1d // Upwards compatible to x86 fastcall. +|.define FCARG2, CARG2d +|.else +|.define CARG1, rdi // x64/POSIX C call arguments. +|.define CARG2, rsi +|.define CARG3, rdx +|.define CARG4, rcx +|.define CARG5, r8 +|.define CARG6, r9 +|.define CARG1d, edi +|.define CARG2d, esi +|.define CARG3d, edx +|.define CARG4d, ecx +|.define CARG5d, r8d +|.define CARG6d, r9d +|.define FCARG1, CARG1d // Simulate x86 fastcall. +|.define FCARG2, CARG2d +|.endif +| +|// Type definitions. Some of these are only used for documentation. +|.type L, lua_State +|.type GL, global_State +|.type TVALUE, TValue +|.type GCOBJ, GCobj +|.type STR, GCstr +|.type TAB, GCtab +|.type LFUNC, GCfuncL +|.type CFUNC, GCfuncC +|.type PROTO, GCproto +|.type UPVAL, GCupval +|.type NODE, Node +|.type NARGS, int +|.type TRACE, GCtrace +| +|// Stack layout while in interpreter. Must match with lj_frame.h. +|//----------------------------------------------------------------------- +|.if not X64 // x86 stack layout. +| +|.define CFRAME_SPACE, aword*7 // Delta for esp (see <--). +|.macro saveregs_ +| push edi; push esi; push ebx +| sub esp, CFRAME_SPACE +|.endmacro +|.macro saveregs +| push ebp; saveregs_ +|.endmacro +|.macro restoreregs +| add esp, CFRAME_SPACE +| pop ebx; pop esi; pop edi; pop ebp +|.endmacro +| +|.define SAVE_ERRF, aword [esp+aword*15] // vm_pcall/vm_cpcall only. +|.define SAVE_NRES, aword [esp+aword*14] +|.define SAVE_CFRAME, aword [esp+aword*13] +|.define SAVE_L, aword [esp+aword*12] +|//----- 16 byte aligned, ^^^ arguments from C caller +|.define SAVE_RET, aword [esp+aword*11] //<-- esp entering interpreter. +|.define SAVE_R4, aword [esp+aword*10] +|.define SAVE_R3, aword [esp+aword*9] +|.define SAVE_R2, aword [esp+aword*8] +|//----- 16 byte aligned +|.define SAVE_R1, aword [esp+aword*7] //<-- esp after register saves. +|.define SAVE_PC, aword [esp+aword*6] +|.define TMP2, aword [esp+aword*5] +|.define TMP1, aword [esp+aword*4] +|//----- 16 byte aligned +|.define ARG4, aword [esp+aword*3] +|.define ARG3, aword [esp+aword*2] +|.define ARG2, aword [esp+aword*1] +|.define ARG1, aword [esp] //<-- esp while in interpreter. +|//----- 16 byte aligned, ^^^ arguments for C callee +| +|// FPARGx overlaps ARGx and ARG(x+1) on x86. +|.define FPARG3, qword [esp+qword*1] +|.define FPARG1, qword [esp] +|// TMPQ overlaps TMP1/TMP2. ARG5/MULTRES overlap TMP1/TMP2 (and TMPQ). +|.define TMPQ, qword [esp+aword*4] +|.define TMP3, ARG4 +|.define ARG5, TMP1 +|.define TMPa, TMP1 +|.define MULTRES, TMP2 +| +|// Arguments for vm_call and vm_pcall. +|.define INARG_BASE, SAVE_CFRAME // Overwritten by SAVE_CFRAME! +| +|// Arguments for vm_cpcall. +|.define INARG_CP_CALL, SAVE_ERRF +|.define INARG_CP_UD, SAVE_NRES +|.define INARG_CP_FUNC, SAVE_CFRAME +| +|//----------------------------------------------------------------------- +|.elif X64WIN // x64/Windows stack layout +| +|.define CFRAME_SPACE, aword*5 // Delta for rsp (see <--). +|.macro saveregs_ +| push rdi; push rsi; push rbx +| sub rsp, CFRAME_SPACE +|.endmacro +|.macro saveregs +| push rbp; saveregs_ +|.endmacro +|.macro restoreregs +| add rsp, CFRAME_SPACE +| pop rbx; pop rsi; pop rdi; pop rbp +|.endmacro +| +|.define SAVE_CFRAME, aword [rsp+aword*13] +|.define SAVE_PC, dword [rsp+dword*25] +|.define SAVE_L, dword [rsp+dword*24] +|.define SAVE_ERRF, dword [rsp+dword*23] +|.define SAVE_NRES, dword [rsp+dword*22] +|.define TMP2, dword [rsp+dword*21] +|.define TMP1, dword [rsp+dword*20] +|//----- 16 byte aligned, ^^^ 32 byte register save area, owned by interpreter +|.define SAVE_RET, aword [rsp+aword*9] //<-- rsp entering interpreter. +|.define SAVE_R4, aword [rsp+aword*8] +|.define SAVE_R3, aword [rsp+aword*7] +|.define SAVE_R2, aword [rsp+aword*6] +|.define SAVE_R1, aword [rsp+aword*5] //<-- rsp after register saves. +|.define ARG5, aword [rsp+aword*4] +|.define CSAVE_4, aword [rsp+aword*3] +|.define CSAVE_3, aword [rsp+aword*2] +|.define CSAVE_2, aword [rsp+aword*1] +|.define CSAVE_1, aword [rsp] //<-- rsp while in interpreter. +|//----- 16 byte aligned, ^^^ 32 byte register save area, owned by callee +| +|// TMPQ overlaps TMP1/TMP2. MULTRES overlaps TMP2 (and TMPQ). +|.define TMPQ, qword [rsp+aword*10] +|.define MULTRES, TMP2 +|.define TMPa, ARG5 +|.define ARG5d, dword [rsp+aword*4] +|.define TMP3, ARG5d +| +|//----------------------------------------------------------------------- +|.else // x64/POSIX stack layout +| +|.define CFRAME_SPACE, aword*5 // Delta for rsp (see <--). +|.macro saveregs_ +| push rbx; push r15; push r14 +| sub rsp, CFRAME_SPACE +|.endmacro +|.macro saveregs +| push rbp; saveregs_ +|.endmacro +|.macro restoreregs +| add rsp, CFRAME_SPACE +| pop r14; pop r15; pop rbx; pop rbp +|.endmacro +| +|//----- 16 byte aligned, +|.define SAVE_RET, aword [rsp+aword*9] //<-- rsp entering interpreter. +|.define SAVE_R4, aword [rsp+aword*8] +|.define SAVE_R3, aword [rsp+aword*7] +|.define SAVE_R2, aword [rsp+aword*6] +|.define SAVE_R1, aword [rsp+aword*5] //<-- rsp after register saves. +|.define SAVE_CFRAME, aword [rsp+aword*4] +|.define SAVE_PC, dword [rsp+dword*7] +|.define SAVE_L, dword [rsp+dword*6] +|.define SAVE_ERRF, dword [rsp+dword*5] +|.define SAVE_NRES, dword [rsp+dword*4] +|.define TMPa, aword [rsp+aword*1] +|.define TMP2, dword [rsp+dword*1] +|.define TMP1, dword [rsp] //<-- rsp while in interpreter. +|//----- 16 byte aligned +| +|// TMPQ overlaps TMP1/TMP2. MULTRES overlaps TMP2 (and TMPQ). +|.define TMPQ, qword [rsp] +|.define TMP3, dword [rsp+aword*1] +|.define MULTRES, TMP2 +| +|.endif +| +|//----------------------------------------------------------------------- +| +|// Instruction headers. +|.macro ins_A; .endmacro +|.macro ins_AD; .endmacro +|.macro ins_AJ; .endmacro +|.macro ins_ABC; movzx RB, RCH; movzx RC, RCL; .endmacro +|.macro ins_AB_; movzx RB, RCH; .endmacro +|.macro ins_A_C; movzx RC, RCL; .endmacro +|.macro ins_AND; not RDa; .endmacro +| +|// Instruction decode+dispatch. Carefully tuned (nope, lodsd is not faster). +|.macro ins_NEXT +| mov RC, [PC] +| movzx RA, RCH +| movzx OP, RCL +| add PC, 4 +| shr RC, 16 +|.if X64 +| jmp aword [DISPATCH+OP*8] +|.else +| jmp aword [DISPATCH+OP*4] +|.endif +|.endmacro +| +|// Instruction footer. +|.if 1 +| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use. +| .define ins_next, ins_NEXT +| .define ins_next_, ins_NEXT +|.else +| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch. +| // Affects only certain kinds of benchmarks (and only with -j off). +| // Around 10%-30% slower on Core2, a lot more slower on P4. +| .macro ins_next +| jmp ->ins_next +| .endmacro +| .macro ins_next_ +| ->ins_next: +| ins_NEXT +| .endmacro +|.endif +| +|// Call decode and dispatch. +|.macro ins_callt +| // BASE = new base, RB = LFUNC, RD = nargs+1, [BASE-4] = PC +| mov PC, LFUNC:RB->pc +| mov RA, [PC] +| movzx OP, RAL +| movzx RA, RAH +| add PC, 4 +|.if X64 +| jmp aword [DISPATCH+OP*8] +|.else +| jmp aword [DISPATCH+OP*4] +|.endif +|.endmacro +| +|.macro ins_call +| // BASE = new base, RB = LFUNC, RD = nargs+1 +| mov [BASE-4], PC +| ins_callt +|.endmacro +| +|//----------------------------------------------------------------------- +| +|// Macros to test operand types. +|.macro checktp, reg, tp; cmp dword [BASE+reg*8+4], tp; .endmacro +|.macro checknum, reg, target; checktp reg, LJ_TISNUM; jae target; .endmacro +|.macro checkint, reg, target; checktp reg, LJ_TISNUM; jne target; .endmacro +|.macro checkstr, reg, target; checktp reg, LJ_TSTR; jne target; .endmacro +|.macro checktab, reg, target; checktp reg, LJ_TTAB; jne target; .endmacro +| +|// These operands must be used with movzx. +|.define PC_OP, byte [PC-4] +|.define PC_RA, byte [PC-3] +|.define PC_RB, byte [PC-1] +|.define PC_RC, byte [PC-2] +|.define PC_RD, word [PC-2] +| +|.macro branchPC, reg +| lea PC, [PC+reg*4-BCBIAS_J*4] +|.endmacro +| +|// Assumes DISPATCH is relative to GL. +#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) +#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) +| +#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) +| +|// Decrement hashed hotcount and trigger trace recorder if zero. +|.macro hotloop, reg +| mov reg, PC +| shr reg, 1 +| and reg, HOTCOUNT_PCMASK +| sub word [DISPATCH+reg+GG_DISP2HOT], HOTCOUNT_LOOP +| jb ->vm_hotloop +|.endmacro +| +|.macro hotcall, reg +| mov reg, PC +| shr reg, 1 +| and reg, HOTCOUNT_PCMASK +| sub word [DISPATCH+reg+GG_DISP2HOT], HOTCOUNT_CALL +| jb ->vm_hotcall +|.endmacro +| +|// Set current VM state. +|.macro set_vmstate, st +| mov dword [DISPATCH+DISPATCH_GL(vmstate)], ~LJ_VMST_..st +|.endmacro +| +|// Annoying x87 stuff: support for two compare variants. +|.macro fcomparepp // Compare and pop st0 >< st1. +||if (cmov) { +| fucomip st1 +| fpop +||} else { +| fucompp +| fnstsw ax // eax modified! +| sahf +||} +|.endmacro +| +|.macro fdup; fld st0; .endmacro +|.macro fpop1; fstp st1; .endmacro +| +|// Synthesize SSE FP constants. +|.macro sseconst_abs, reg, tmp // Synthesize abs mask. +|.if X64 +| mov64 tmp, U64x(7fffffff,ffffffff); movd reg, tmp +|.else +| pxor reg, reg; pcmpeqd reg, reg; psrlq reg, 1 +|.endif +|.endmacro +| +|.macro sseconst_hi, reg, tmp, val // Synthesize hi-32 bit const. +|.if X64 +| mov64 tmp, U64x(val,00000000); movd reg, tmp +|.else +| mov tmp, 0x .. val; movd reg, tmp; pshufd reg, reg, 0x51 +|.endif +|.endmacro +| +|.macro sseconst_sign, reg, tmp // Synthesize sign mask. +| sseconst_hi reg, tmp, 80000000 +|.endmacro +|.macro sseconst_1, reg, tmp // Synthesize 1.0. +| sseconst_hi reg, tmp, 3ff00000 +|.endmacro +|.macro sseconst_m1, reg, tmp // Synthesize -1.0. +| sseconst_hi reg, tmp, bff00000 +|.endmacro +|.macro sseconst_2p52, reg, tmp // Synthesize 2^52. +| sseconst_hi reg, tmp, 43300000 +|.endmacro +|.macro sseconst_tobit, reg, tmp // Synthesize 2^52 + 2^51. +| sseconst_hi reg, tmp, 43380000 +|.endmacro +| +|// Move table write barrier back. Overwrites reg. +|.macro barrierback, tab, reg +| and byte tab->marked, (uint8_t)~LJ_GC_BLACK // black2gray(tab) +| mov reg, [DISPATCH+DISPATCH_GL(gc.grayagain)] +| mov [DISPATCH+DISPATCH_GL(gc.grayagain)], tab +| mov tab->gclist, reg +|.endmacro +| +|//----------------------------------------------------------------------- + +/* Generate subroutines used by opcodes and other parts of the VM. */ +/* The .code_sub section should be last to help static branch prediction. */ +static void build_subroutines(BuildCtx *ctx, int cmov, int sse) +{ + |.code_sub + | + |//----------------------------------------------------------------------- + |//-- Return handling ---------------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_returnp: + | test PC, FRAME_P + | jz ->cont_dispatch + | + | // Return from pcall or xpcall fast func. + | and PC, -8 + | sub BASE, PC // Restore caller base. + | lea RAa, [RA+PC-8] // Rebase RA and prepend one result. + | mov PC, [BASE-4] // Fetch PC of previous frame. + | // Prepending may overwrite the pcall frame, so do it at the end. + | mov dword [BASE+RA+4], LJ_TTRUE // Prepend true to results. + | + |->vm_returnc: + | add RD, 1 // RD = nresults+1 + | mov MULTRES, RD + | test PC, FRAME_TYPE + | jz ->BC_RET_Z // Handle regular return to Lua. + | + |->vm_return: + | // BASE = base, RA = resultofs, RD = nresults+1 (= MULTRES), PC = return + | xor PC, FRAME_C + | test PC, FRAME_TYPE + | jnz ->vm_returnp + | + | // Return to C. + | set_vmstate C + | and PC, -8 + | sub PC, BASE + | neg PC // Previous base = BASE - delta. + | + | sub RD, 1 + | jz >2 + |1: // Move results down. + |.if X64 + | mov RBa, [BASE+RA] + | mov [BASE-8], RBa + |.else + | mov RB, [BASE+RA] + | mov [BASE-8], RB + | mov RB, [BASE+RA+4] + | mov [BASE-4], RB + |.endif + | add BASE, 8 + | sub RD, 1 + | jnz <1 + |2: + | mov L:RB, SAVE_L + | mov L:RB->base, PC + |3: + | mov RD, MULTRES + | mov RA, SAVE_NRES // RA = wanted nresults+1 + |4: + | cmp RA, RD + | jne >6 // More/less results wanted? + |5: + | sub BASE, 8 + | mov L:RB->top, BASE + | + |->vm_leave_cp: + | mov RAa, SAVE_CFRAME // Restore previous C frame. + | mov L:RB->cframe, RAa + | xor eax, eax // Ok return status for vm_pcall. + | + |->vm_leave_unw: + | restoreregs + | ret + | + |6: + | jb >7 // Less results wanted? + | // More results wanted. Check stack size and fill up results with nil. + | cmp BASE, L:RB->maxstack + | ja >8 + | mov dword [BASE-4], LJ_TNIL + | add BASE, 8 + | add RD, 1 + | jmp <4 + | + |7: // Less results wanted. + | test RA, RA + | jz <5 // But check for LUA_MULTRET+1. + | sub RA, RD // Negative result! + | lea BASE, [BASE+RA*8] // Correct top. + | jmp <5 + | + |8: // Corner case: need to grow stack for filling up results. + | // This can happen if: + | // - A C function grows the stack (a lot). + | // - The GC shrinks the stack in between. + | // - A return back from a lua_call() with (high) nresults adjustment. + | mov L:RB->top, BASE // Save current top held in BASE (yes). + | mov MULTRES, RD // Need to fill only remainder with nil. + | mov FCARG2, RA + | mov FCARG1, L:RB + | call extern lj_state_growstack@8 // (lua_State *L, int n) + | mov BASE, L:RB->top // Need the (realloced) L->top in BASE. + | jmp <3 + | + |->vm_unwind_c@8: // Unwind C stack, return from vm_pcall. + | // (void *cframe, int errcode) + |.if X64 + | mov eax, CARG2d // Error return status for vm_pcall. + | mov rsp, CARG1 + |.else + | mov eax, FCARG2 // Error return status for vm_pcall. + | mov esp, FCARG1 + |.endif + |->vm_unwind_c_eh: // Landing pad for external unwinder. + | mov L:RB, SAVE_L + | mov GL:RB, L:RB->glref + | mov dword GL:RB->vmstate, ~LJ_VMST_C + | jmp ->vm_leave_unw + | + |->vm_unwind_rethrow: + |.if X64 and not X64WIN + | mov FCARG1, SAVE_L + | mov FCARG2, eax + | restoreregs + | jmp extern lj_err_throw@8 // (lua_State *L, int errcode) + |.endif + | + |->vm_unwind_ff@4: // Unwind C stack, return from ff pcall. + | // (void *cframe) + |.if X64 + | and CARG1, CFRAME_RAWMASK + | mov rsp, CARG1 + |.else + | and FCARG1, CFRAME_RAWMASK + | mov esp, FCARG1 + |.endif + |->vm_unwind_ff_eh: // Landing pad for external unwinder. + | mov L:RB, SAVE_L + | mov RAa, -8 // Results start at BASE+RA = BASE-8. + | mov RD, 1+1 // Really 1+2 results, incr. later. + | mov BASE, L:RB->base + | mov DISPATCH, L:RB->glref // Setup pointer to dispatch table. + | add DISPATCH, GG_G2DISP + | mov PC, [BASE-4] // Fetch PC of previous frame. + | mov dword [BASE-4], LJ_TFALSE // Prepend false to error message. + | set_vmstate INTERP + | jmp ->vm_returnc // Increments RD/MULTRES and returns. + | + |//----------------------------------------------------------------------- + |//-- Grow stack for calls ----------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_growstack_c: // Grow stack for C function. + | mov FCARG2, LUA_MINSTACK + | jmp >2 + | + |->vm_growstack_v: // Grow stack for vararg Lua function. + | sub RD, 8 + | jmp >1 + | + |->vm_growstack_f: // Grow stack for fixarg Lua function. + | // BASE = new base, RD = nargs+1, RB = L, PC = first PC + | lea RD, [BASE+NARGS:RD*8-8] + |1: + | movzx RA, byte [PC-4+PC2PROTO(framesize)] + | add PC, 4 // Must point after first instruction. + | mov L:RB->base, BASE + | mov L:RB->top, RD + | mov SAVE_PC, PC + | mov FCARG2, RA + |2: + | // RB = L, L->base = new base, L->top = top + | mov FCARG1, L:RB + | call extern lj_state_growstack@8 // (lua_State *L, int n) + | mov BASE, L:RB->base + | mov RD, L:RB->top + | mov LFUNC:RB, [BASE-8] + | sub RD, BASE + | shr RD, 3 + | add NARGS:RD, 1 + | // BASE = new base, RB = LFUNC, RD = nargs+1 + | ins_callt // Just retry the call. + | + |//----------------------------------------------------------------------- + |//-- Entry points into the assembler VM --------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_resume: // Setup C frame and resume thread. + | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0) + | saveregs + |.if X64 + | mov L:RB, CARG1d // Caveat: CARG1d may be RA. + | mov SAVE_L, CARG1d + | mov RA, CARG2d + |.else + | mov L:RB, SAVE_L + | mov RA, INARG_BASE // Caveat: overlaps SAVE_CFRAME! + |.endif + | mov PC, FRAME_CP + | xor RD, RD + | lea KBASEa, [esp+CFRAME_RESUME] + | mov DISPATCH, L:RB->glref // Setup pointer to dispatch table. + | add DISPATCH, GG_G2DISP + | mov L:RB->cframe, KBASEa + | mov SAVE_PC, RD // Any value outside of bytecode is ok. + | mov SAVE_CFRAME, RDa + |.if X64 + | mov SAVE_NRES, RD + | mov SAVE_ERRF, RD + |.endif + | cmp byte L:RB->status, RDL + | je >3 // Initial resume (like a call). + | + | // Resume after yield (like a return). + | set_vmstate INTERP + | mov byte L:RB->status, RDL + | mov BASE, L:RB->base + | mov RD, L:RB->top + | sub RD, RA + | shr RD, 3 + | add RD, 1 // RD = nresults+1 + | sub RA, BASE // RA = resultofs + | mov PC, [BASE-4] + | mov MULTRES, RD + | test PC, FRAME_TYPE + | jz ->BC_RET_Z + | jmp ->vm_return + | + |->vm_pcall: // Setup protected C frame and enter VM. + | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef) + | saveregs + | mov PC, FRAME_CP + |.if X64 + | mov SAVE_ERRF, CARG4d + |.endif + | jmp >1 + | + |->vm_call: // Setup C frame and enter VM. + | // (lua_State *L, TValue *base, int nres1) + | saveregs + | mov PC, FRAME_C + | + |1: // Entry point for vm_pcall above (PC = ftype). + |.if X64 + | mov SAVE_NRES, CARG3d + | mov L:RB, CARG1d // Caveat: CARG1d may be RA. + | mov SAVE_L, CARG1d + | mov RA, CARG2d + |.else + | mov L:RB, SAVE_L + | mov RA, INARG_BASE // Caveat: overlaps SAVE_CFRAME! + |.endif + | + | mov KBASEa, L:RB->cframe // Add our C frame to cframe chain. + | mov SAVE_CFRAME, KBASEa + | mov SAVE_PC, L:RB // Any value outside of bytecode is ok. + |.if X64 + | mov L:RB->cframe, rsp + |.else + | mov L:RB->cframe, esp + |.endif + | + |2: // Entry point for vm_cpcall below (RA = base, RB = L, PC = ftype). + | mov DISPATCH, L:RB->glref // Setup pointer to dispatch table. + | add DISPATCH, GG_G2DISP + | + |3: // Entry point for vm_resume above (RA = base, RB = L, PC = ftype). + | set_vmstate INTERP + | mov BASE, L:RB->base // BASE = old base (used in vmeta_call). + | add PC, RA + | sub PC, BASE // PC = frame delta + frame type + | + | mov RD, L:RB->top + | sub RD, RA + | shr NARGS:RD, 3 + | add NARGS:RD, 1 // RD = nargs+1 + | + |->vm_call_dispatch: + | mov LFUNC:RB, [RA-8] + | cmp dword [RA-4], LJ_TFUNC + | jne ->vmeta_call // Ensure KBASE defined and != BASE. + | + |->vm_call_dispatch_f: + | mov BASE, RA + | ins_call + | // BASE = new base, RB = func, RD = nargs+1, PC = caller PC + | + |->vm_cpcall: // Setup protected C frame, call C. + | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp) + | saveregs + |.if X64 + | mov L:RB, CARG1d // Caveat: CARG1d may be RA. + | mov SAVE_L, CARG1d + |.else + | mov L:RB, SAVE_L + | // Caveat: INARG_CP_* and SAVE_CFRAME/SAVE_NRES/SAVE_ERRF overlap! + | mov RC, INARG_CP_UD // Get args before they are overwritten. + | mov RA, INARG_CP_FUNC + | mov BASE, INARG_CP_CALL + |.endif + | mov SAVE_PC, L:RB // Any value outside of bytecode is ok. + | + | mov KBASE, L:RB->stack // Compute -savestack(L, L->top). + | sub KBASE, L:RB->top + | mov SAVE_ERRF, 0 // No error function. + | mov SAVE_NRES, KBASE // Neg. delta means cframe w/o frame. + | // Handler may change cframe_nres(L->cframe) or cframe_errfunc(L->cframe). + | + |.if X64 + | mov KBASEa, L:RB->cframe // Add our C frame to cframe chain. + | mov SAVE_CFRAME, KBASEa + | mov L:RB->cframe, rsp + | + | call CARG4 // (lua_State *L, lua_CFunction func, void *ud) + |.else + | mov ARG3, RC // Have to copy args downwards. + | mov ARG2, RA + | mov ARG1, L:RB + | + | mov KBASE, L:RB->cframe // Add our C frame to cframe chain. + | mov SAVE_CFRAME, KBASE + | mov L:RB->cframe, esp + | + | call BASE // (lua_State *L, lua_CFunction func, void *ud) + |.endif + | // TValue * (new base) or NULL returned in eax (RC). + | test RC, RC + | jz ->vm_leave_cp // No base? Just remove C frame. + | mov RA, RC + | mov PC, FRAME_CP + | jmp <2 // Else continue with the call. + | + |//----------------------------------------------------------------------- + |//-- Metamethod handling ------------------------------------------------ + |//----------------------------------------------------------------------- + | + |//-- Continuation dispatch ---------------------------------------------- + | + |->cont_dispatch: + | // BASE = meta base, RA = resultofs, RD = nresults+1 (also in MULTRES) + | add RA, BASE + | and PC, -8 + | mov RB, BASE + | sub BASE, PC // Restore caller BASE. + | mov dword [RA+RD*8-4], LJ_TNIL // Ensure one valid arg. + | mov RC, RA // ... in [RC] + | mov PC, [RB-12] // Restore PC from [cont|PC]. + |.if X64 + | movsxd RAa, dword [RB-16] // May be negative on WIN64 with debug. +#if LJ_HASFFI + | cmp RA, 1 + | jbe >1 +#endif + | lea KBASEa, qword [=>0] + | add RAa, KBASEa + |.else + | mov RA, dword [RB-16] +#if LJ_HASFFI + | cmp RA, 1 + | jbe >1 +#endif + |.endif + | mov LFUNC:KBASE, [BASE-8] + | mov KBASE, LFUNC:KBASE->pc + | mov KBASE, [KBASE+PC2PROTO(k)] + | // BASE = base, RC = result, RB = meta base + | jmp RAa // Jump to continuation. + | +#if LJ_HASFFI + |1: + | je ->cont_ffi_callback // cont = 1: return from FFI callback. + | // cont = 0: Tail call from C function. + | sub RB, BASE + | shr RB, 3 + | lea RD, [RB-1] + | jmp ->vm_call_tail +#endif + | + |->cont_cat: // BASE = base, RC = result, RB = mbase + | movzx RA, PC_RB + | sub RB, 16 + | lea RA, [BASE+RA*8] + | sub RA, RB + | je ->cont_ra + | neg RA + | shr RA, 3 + |.if X64WIN + | mov CARG3d, RA + | mov L:CARG1d, SAVE_L + | mov L:CARG1d->base, BASE + | mov RCa, [RC] + | mov [RB], RCa + | mov CARG2d, RB + |.elif X64 + | mov L:CARG1d, SAVE_L + | mov L:CARG1d->base, BASE + | mov CARG3d, RA + | mov RAa, [RC] + | mov [RB], RAa + | mov CARG2d, RB + |.else + | mov ARG3, RA + | mov RA, [RC+4] + | mov RC, [RC] + | mov [RB+4], RA + | mov [RB], RC + | mov ARG2, RB + |.endif + | jmp ->BC_CAT_Z + | + |//-- Table indexing metamethods ----------------------------------------- + | + |->vmeta_tgets: + | mov TMP1, RC // RC = GCstr * + | mov TMP2, LJ_TSTR + | lea RCa, TMP1 // Store temp. TValue in TMP1/TMP2. + | cmp PC_OP, BC_GGET + | jne >1 + | lea RA, [DISPATCH+DISPATCH_GL(tmptv)] // Store fn->l.env in g->tmptv. + | mov [RA], TAB:RB // RB = GCtab * + | mov dword [RA+4], LJ_TTAB + | mov RB, RA + | jmp >2 + | + |->vmeta_tgetb: + | movzx RC, PC_RC + if (LJ_DUALNUM) { + | mov TMP2, LJ_TISNUM + | mov TMP1, RC + } else if (sse) { + | cvtsi2sd xmm0, RC + | movsd TMPQ, xmm0 + } else { + |.if not X64 + | mov ARG4, RC + | fild ARG4 + | fstp TMPQ + |.endif + } + | lea RCa, TMPQ // Store temp. TValue in TMPQ. + | jmp >1 + | + |->vmeta_tgetv: + | movzx RC, PC_RC // Reload TValue *k from RC. + | lea RC, [BASE+RC*8] + |1: + | movzx RB, PC_RB // Reload TValue *t from RB. + | lea RB, [BASE+RB*8] + |2: + |.if X64 + | mov L:CARG1d, SAVE_L + | mov L:CARG1d->base, BASE // Caveat: CARG2d/CARG3d may be BASE. + | mov CARG2d, RB + | mov CARG3, RCa // May be 64 bit ptr to stack. + | mov L:RB, L:CARG1d + |.else + | mov ARG2, RB + | mov L:RB, SAVE_L + | mov ARG3, RC + | mov ARG1, L:RB + | mov L:RB->base, BASE + |.endif + | mov SAVE_PC, PC + | call extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k) + | // TValue * (finished) or NULL (metamethod) returned in eax (RC). + | mov BASE, L:RB->base + | test RC, RC + | jz >3 + |->cont_ra: // BASE = base, RC = result + | movzx RA, PC_RA + |.if X64 + | mov RBa, [RC] + | mov [BASE+RA*8], RBa + |.else + | mov RB, [RC+4] + | mov RC, [RC] + | mov [BASE+RA*8+4], RB + | mov [BASE+RA*8], RC + |.endif + | ins_next + | + |3: // Call __index metamethod. + | // BASE = base, L->top = new base, stack = cont/func/t/k + | mov RA, L:RB->top + | mov [RA-12], PC // [cont|PC] + | lea PC, [RA+FRAME_CONT] + | sub PC, BASE + | mov LFUNC:RB, [RA-8] // Guaranteed to be a function here. + | mov NARGS:RD, 2+1 // 2 args for func(t, k). + | jmp ->vm_call_dispatch_f + | + |//----------------------------------------------------------------------- + | + |->vmeta_tsets: + | mov TMP1, RC // RC = GCstr * + | mov TMP2, LJ_TSTR + | lea RCa, TMP1 // Store temp. TValue in TMP1/TMP2. + | cmp PC_OP, BC_GSET + | jne >1 + | lea RA, [DISPATCH+DISPATCH_GL(tmptv)] // Store fn->l.env in g->tmptv. + | mov [RA], TAB:RB // RB = GCtab * + | mov dword [RA+4], LJ_TTAB + | mov RB, RA + | jmp >2 + | + |->vmeta_tsetb: + | movzx RC, PC_RC + if (LJ_DUALNUM) { + | mov TMP2, LJ_TISNUM + | mov TMP1, RC + } else if (sse) { + | cvtsi2sd xmm0, RC + | movsd TMPQ, xmm0 + } else { + |.if not X64 + | mov ARG4, RC + | fild ARG4 + | fstp TMPQ + |.endif + } + | lea RCa, TMPQ // Store temp. TValue in TMPQ. + | jmp >1 + | + |->vmeta_tsetv: + | movzx RC, PC_RC // Reload TValue *k from RC. + | lea RC, [BASE+RC*8] + |1: + | movzx RB, PC_RB // Reload TValue *t from RB. + | lea RB, [BASE+RB*8] + |2: + |.if X64 + | mov L:CARG1d, SAVE_L + | mov L:CARG1d->base, BASE // Caveat: CARG2d/CARG3d may be BASE. + | mov CARG2d, RB + | mov CARG3, RCa // May be 64 bit ptr to stack. + | mov L:RB, L:CARG1d + |.else + | mov ARG2, RB + | mov L:RB, SAVE_L + | mov ARG3, RC + | mov ARG1, L:RB + | mov L:RB->base, BASE + |.endif + | mov SAVE_PC, PC + | call extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k) + | // TValue * (finished) or NULL (metamethod) returned in eax (RC). + | mov BASE, L:RB->base + | test RC, RC + | jz >3 + | // NOBARRIER: lj_meta_tset ensures the table is not black. + | movzx RA, PC_RA + |.if X64 + | mov RBa, [BASE+RA*8] + | mov [RC], RBa + |.else + | mov RB, [BASE+RA*8+4] + | mov RA, [BASE+RA*8] + | mov [RC+4], RB + | mov [RC], RA + |.endif + |->cont_nop: // BASE = base, (RC = result) + | ins_next + | + |3: // Call __newindex metamethod. + | // BASE = base, L->top = new base, stack = cont/func/t/k/(v) + | mov RA, L:RB->top + | mov [RA-12], PC // [cont|PC] + | movzx RC, PC_RA + | // Copy value to third argument. + |.if X64 + | mov RBa, [BASE+RC*8] + | mov [RA+16], RBa + |.else + | mov RB, [BASE+RC*8+4] + | mov RC, [BASE+RC*8] + | mov [RA+20], RB + | mov [RA+16], RC + |.endif + | lea PC, [RA+FRAME_CONT] + | sub PC, BASE + | mov LFUNC:RB, [RA-8] // Guaranteed to be a function here. + | mov NARGS:RD, 3+1 // 3 args for func(t, k, v). + | jmp ->vm_call_dispatch_f + | + |//-- Comparison metamethods --------------------------------------------- + | + |->vmeta_comp: + |.if X64 + | mov L:RB, SAVE_L + | mov L:RB->base, BASE // Caveat: CARG2d/CARG3d == BASE. + |.if X64WIN + | lea CARG3d, [BASE+RD*8] + | lea CARG2d, [BASE+RA*8] + |.else + | lea CARG2d, [BASE+RA*8] + | lea CARG3d, [BASE+RD*8] + |.endif + | mov CARG1d, L:RB // Caveat: CARG1d/CARG4d == RA. + | movzx CARG4d, PC_OP + |.else + | movzx RB, PC_OP + | lea RD, [BASE+RD*8] + | lea RA, [BASE+RA*8] + | mov ARG4, RB + | mov L:RB, SAVE_L + | mov ARG3, RD + | mov ARG2, RA + | mov ARG1, L:RB + | mov L:RB->base, BASE + |.endif + | mov SAVE_PC, PC + | call extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op) + | // 0/1 or TValue * (metamethod) returned in eax (RC). + |3: + | mov BASE, L:RB->base + | cmp RC, 1 + | ja ->vmeta_binop + |4: + | lea PC, [PC+4] + | jb >6 + |5: + | movzx RD, PC_RD + | branchPC RD + |6: + | ins_next + | + |->cont_condt: // BASE = base, RC = result + | add PC, 4 + | cmp dword [RC+4], LJ_TISTRUECOND // Branch if result is true. + | jb <5 + | jmp <6 + | + |->cont_condf: // BASE = base, RC = result + | cmp dword [RC+4], LJ_TISTRUECOND // Branch if result is false. + | jmp <4 + | + |->vmeta_equal: + | sub PC, 4 + |.if X64WIN + | mov CARG3d, RD + | mov CARG4d, RB + | mov L:RB, SAVE_L + | mov L:RB->base, BASE // Caveat: CARG2d == BASE. + | mov CARG2d, RA + | mov CARG1d, L:RB // Caveat: CARG1d == RA. + |.elif X64 + | mov CARG2d, RA + | mov CARG4d, RB // Caveat: CARG4d == RA. + | mov L:RB, SAVE_L + | mov L:RB->base, BASE // Caveat: CARG3d == BASE. + | mov CARG3d, RD + | mov CARG1d, L:RB + |.else + | mov ARG4, RB + | mov L:RB, SAVE_L + | mov ARG3, RD + | mov ARG2, RA + | mov ARG1, L:RB + | mov L:RB->base, BASE + |.endif + | mov SAVE_PC, PC + | call extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne) + | // 0/1 or TValue * (metamethod) returned in eax (RC). + | jmp <3 + | + |->vmeta_equal_cd: +#if LJ_HASFFI + | sub PC, 4 + | mov L:RB, SAVE_L + | mov L:RB->base, BASE + | mov FCARG1, L:RB + | mov FCARG2, dword [PC-4] + | mov SAVE_PC, PC + | call extern lj_meta_equal_cd@8 // (lua_State *L, BCIns ins) + | // 0/1 or TValue * (metamethod) returned in eax (RC). + | jmp <3 +#endif + | + |//-- Arithmetic metamethods --------------------------------------------- + | + |->vmeta_arith_vno: +#if LJ_DUALNUM + | movzx RB, PC_RB +#endif + |->vmeta_arith_vn: + | lea RC, [KBASE+RC*8] + | jmp >1 + | + |->vmeta_arith_nvo: +#if LJ_DUALNUM + | movzx RC, PC_RC +#endif + |->vmeta_arith_nv: + | lea RC, [KBASE+RC*8] + | lea RB, [BASE+RB*8] + | xchg RB, RC + | jmp >2 + | + |->vmeta_unm: + | lea RC, [BASE+RD*8] + | mov RB, RC + | jmp >2 + | + |->vmeta_arith_vvo: +#if LJ_DUALNUM + | movzx RB, PC_RB +#endif + |->vmeta_arith_vv: + | lea RC, [BASE+RC*8] + |1: + | lea RB, [BASE+RB*8] + |2: + | lea RA, [BASE+RA*8] + |.if X64WIN + | mov CARG3d, RB + | mov CARG4d, RC + | movzx RC, PC_OP + | mov ARG5d, RC + | mov L:RB, SAVE_L + | mov L:RB->base, BASE // Caveat: CARG2d == BASE. + | mov CARG2d, RA + | mov CARG1d, L:RB // Caveat: CARG1d == RA. + |.elif X64 + | movzx CARG5d, PC_OP + | mov CARG2d, RA + | mov CARG4d, RC // Caveat: CARG4d == RA. + | mov L:CARG1d, SAVE_L + | mov L:CARG1d->base, BASE // Caveat: CARG3d == BASE. + | mov CARG3d, RB + | mov L:RB, L:CARG1d + |.else + | mov ARG3, RB + | mov L:RB, SAVE_L + | mov ARG4, RC + | movzx RC, PC_OP + | mov ARG2, RA + | mov ARG5, RC + | mov ARG1, L:RB + | mov L:RB->base, BASE + |.endif + | mov SAVE_PC, PC + | call extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op) + | // NULL (finished) or TValue * (metamethod) returned in eax (RC). + | mov BASE, L:RB->base + | test RC, RC + | jz ->cont_nop + | + | // Call metamethod for binary op. + |->vmeta_binop: + | // BASE = base, RC = new base, stack = cont/func/o1/o2 + | mov RA, RC + | sub RC, BASE + | mov [RA-12], PC // [cont|PC] + | lea PC, [RC+FRAME_CONT] + | mov NARGS:RD, 2+1 // 2 args for func(o1, o2). + | jmp ->vm_call_dispatch + | + |->vmeta_len: + | mov L:RB, SAVE_L + | mov L:RB->base, BASE + | lea FCARG2, [BASE+RD*8] // Caveat: FCARG2 == BASE + | mov L:FCARG1, L:RB + | mov SAVE_PC, PC + | call extern lj_meta_len@8 // (lua_State *L, TValue *o) + | // NULL (retry) or TValue * (metamethod) returned in eax (RC). + | mov BASE, L:RB->base +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | test RC, RC + | jne ->vmeta_binop // Binop call for compatibility. + | movzx RD, PC_RD + | mov TAB:FCARG1, [BASE+RD*8] + | jmp ->BC_LEN_Z +#else + | jmp ->vmeta_binop // Binop call for compatibility. +#endif + | + |//-- Call metamethod ---------------------------------------------------- + | + |->vmeta_call_ra: + | lea RA, [BASE+RA*8+8] + |->vmeta_call: // Resolve and call __call metamethod. + | // BASE = old base, RA = new base, RC = nargs+1, PC = return + | mov TMP2, RA // Save RA, RC for us. + | mov TMP1, NARGS:RD + | sub RA, 8 + |.if X64 + | mov L:RB, SAVE_L + | mov L:RB->base, BASE // Caveat: CARG2d/CARG3d may be BASE. + | mov CARG2d, RA + | lea CARG3d, [RA+NARGS:RD*8] + | mov CARG1d, L:RB // Caveat: CARG1d may be RA. + |.else + | lea RC, [RA+NARGS:RD*8] + | mov L:RB, SAVE_L + | mov ARG2, RA + | mov ARG3, RC + | mov ARG1, L:RB + | mov L:RB->base, BASE // This is the callers base! + |.endif + | mov SAVE_PC, PC + | call extern lj_meta_call // (lua_State *L, TValue *func, TValue *top) + | mov BASE, L:RB->base + | mov RA, TMP2 + | mov NARGS:RD, TMP1 + | mov LFUNC:RB, [RA-8] + | add NARGS:RD, 1 + | // This is fragile. L->base must not move, KBASE must always be defined. + | cmp KBASE, BASE // Continue with CALLT if flag set. + | je ->BC_CALLT_Z + | mov BASE, RA + | ins_call // Otherwise call resolved metamethod. + | + |//-- Argument coercion for 'for' statement ------------------------------ + | + |->vmeta_for: + | mov L:RB, SAVE_L + | mov L:RB->base, BASE + | mov FCARG2, RA // Caveat: FCARG2 == BASE + | mov L:FCARG1, L:RB // Caveat: FCARG1 == RA + | mov SAVE_PC, PC + | call extern lj_meta_for@8 // (lua_State *L, TValue *base) + | mov BASE, L:RB->base + | mov RC, [PC-4] + | movzx RA, RCH + | movzx OP, RCL + | shr RC, 16 + |.if X64 + | jmp aword [DISPATCH+OP*8+GG_DISP2STATIC] // Retry FORI or JFORI. + |.else + | jmp aword [DISPATCH+OP*4+GG_DISP2STATIC] // Retry FORI or JFORI. + |.endif + | + |//----------------------------------------------------------------------- + |//-- Fast functions ----------------------------------------------------- + |//----------------------------------------------------------------------- + | + |.macro .ffunc, name + |->ff_ .. name: + |.endmacro + | + |.macro .ffunc_1, name + |->ff_ .. name: + | cmp NARGS:RD, 1+1; jb ->fff_fallback + |.endmacro + | + |.macro .ffunc_2, name + |->ff_ .. name: + | cmp NARGS:RD, 2+1; jb ->fff_fallback + |.endmacro + | + |.macro .ffunc_n, name + | .ffunc_1 name + | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback + | fld qword [BASE] + |.endmacro + | + |.macro .ffunc_n, name, op + | .ffunc_1 name + | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback + | op + | fld qword [BASE] + |.endmacro + | + |.macro .ffunc_nsse, name, op + | .ffunc_1 name + | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback + | op xmm0, qword [BASE] + |.endmacro + | + |.macro .ffunc_nsse, name + | .ffunc_nsse name, movsd + |.endmacro + | + |.macro .ffunc_nn, name + | .ffunc_2 name + | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback + | cmp dword [BASE+12], LJ_TISNUM; jae ->fff_fallback + | fld qword [BASE] + | fld qword [BASE+8] + |.endmacro + | + |.macro .ffunc_nnsse, name + | .ffunc_2 name + | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback + | cmp dword [BASE+12], LJ_TISNUM; jae ->fff_fallback + | movsd xmm0, qword [BASE] + | movsd xmm1, qword [BASE+8] + |.endmacro + | + |.macro .ffunc_nnr, name + | .ffunc_2 name + | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback + | cmp dword [BASE+12], LJ_TISNUM; jae ->fff_fallback + | fld qword [BASE+8] + | fld qword [BASE] + |.endmacro + | + |// Inlined GC threshold check. Caveat: uses label 1. + |.macro ffgccheck + | mov RB, [DISPATCH+DISPATCH_GL(gc.total)] + | cmp RB, [DISPATCH+DISPATCH_GL(gc.threshold)] + | jb >1 + | call ->fff_gcstep + |1: + |.endmacro + | + |//-- Base library: checks ----------------------------------------------- + | + |.ffunc_1 assert + | mov RB, [BASE+4] + | cmp RB, LJ_TISTRUECOND; jae ->fff_fallback + | mov PC, [BASE-4] + | mov MULTRES, RD + | mov [BASE-4], RB + | mov RB, [BASE] + | mov [BASE-8], RB + | sub RD, 2 + | jz >2 + | mov RA, BASE + |1: + | add RA, 8 + |.if X64 + | mov RBa, [RA] + | mov [RA-8], RBa + |.else + | mov RB, [RA+4] + | mov [RA-4], RB + | mov RB, [RA] + | mov [RA-8], RB + |.endif + | sub RD, 1 + | jnz <1 + |2: + | mov RD, MULTRES + | jmp ->fff_res_ + | + |.ffunc_1 type + | mov RB, [BASE+4] + |.if X64 + | mov RA, RB + | sar RA, 15 + | cmp RA, -2 + | je >3 + |.endif + | mov RC, ~LJ_TNUMX + | not RB + | cmp RC, RB + ||if (cmov) { + | cmova RC, RB + ||} else { + | jbe >1; mov RC, RB; 1: + ||} + |2: + | mov CFUNC:RB, [BASE-8] + | mov STR:RC, [CFUNC:RB+RC*8+((char *)(&((GCfuncC *)0)->upvalue))] + | mov PC, [BASE-4] + | mov dword [BASE-4], LJ_TSTR + | mov [BASE-8], STR:RC + | jmp ->fff_res1 + |.if X64 + |3: + | mov RC, ~LJ_TLIGHTUD + | jmp <2 + |.endif + | + |//-- Base library: getters and setters --------------------------------- + | + |.ffunc_1 getmetatable + | mov RB, [BASE+4] + | mov PC, [BASE-4] + | cmp RB, LJ_TTAB; jne >6 + |1: // Field metatable must be at same offset for GCtab and GCudata! + | mov TAB:RB, [BASE] + | mov TAB:RB, TAB:RB->metatable + |2: + | test TAB:RB, TAB:RB + | mov dword [BASE-4], LJ_TNIL + | jz ->fff_res1 + | mov STR:RC, [DISPATCH+DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable)] + | mov dword [BASE-4], LJ_TTAB // Store metatable as default result. + | mov [BASE-8], TAB:RB + | mov RA, TAB:RB->hmask + | and RA, STR:RC->hash + | imul RA, #NODE + | add NODE:RA, TAB:RB->node + |3: // Rearranged logic, because we expect _not_ to find the key. + | cmp dword NODE:RA->key.it, LJ_TSTR + | jne >4 + | cmp dword NODE:RA->key.gcr, STR:RC + | je >5 + |4: + | mov NODE:RA, NODE:RA->next + | test NODE:RA, NODE:RA + | jnz <3 + | jmp ->fff_res1 // Not found, keep default result. + |5: + | mov RB, [RA+4] + | cmp RB, LJ_TNIL; je ->fff_res1 // Ditto for nil value. + | mov RC, [RA] + | mov [BASE-4], RB // Return value of mt.__metatable. + | mov [BASE-8], RC + | jmp ->fff_res1 + | + |6: + | cmp RB, LJ_TUDATA; je <1 + |.if X64 + | cmp RB, LJ_TNUMX; ja >8 + | cmp RB, LJ_TISNUM; jbe >7 + | mov RB, LJ_TLIGHTUD + | jmp >8 + |7: + |.else + | cmp RB, LJ_TISNUM; ja >8 + |.endif + | mov RB, LJ_TNUMX + |8: + | not RB + | mov TAB:RB, [DISPATCH+RB*4+DISPATCH_GL(gcroot[GCROOT_BASEMT])] + | jmp <2 + | + |.ffunc_2 setmetatable + | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback + | // Fast path: no mt for table yet and not clearing the mt. + | mov TAB:RB, [BASE] + | cmp dword TAB:RB->metatable, 0; jne ->fff_fallback + | cmp dword [BASE+12], LJ_TTAB; jne ->fff_fallback + | mov TAB:RC, [BASE+8] + | mov TAB:RB->metatable, TAB:RC + | mov PC, [BASE-4] + | mov dword [BASE-4], LJ_TTAB // Return original table. + | mov [BASE-8], TAB:RB + | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) + | jz >1 + | // Possible write barrier. Table is black, but skip iswhite(mt) check. + | barrierback TAB:RB, RC + |1: + | jmp ->fff_res1 + | + |.ffunc_2 rawget + | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback + |.if X64WIN + | mov RB, BASE // Save BASE. + | lea CARG3d, [BASE+8] + | mov CARG2d, [BASE] // Caveat: CARG2d == BASE. + | mov CARG1d, SAVE_L + |.elif X64 + | mov RB, BASE // Save BASE. + | mov CARG2d, [BASE] + | lea CARG3d, [BASE+8] // Caveat: CARG3d == BASE. + | mov CARG1d, SAVE_L + |.else + | mov TAB:RD, [BASE] + | mov L:RB, SAVE_L + | mov ARG2, TAB:RD + | mov ARG1, L:RB + | mov RB, BASE // Save BASE. + | add BASE, 8 + | mov ARG3, BASE + |.endif + | call extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key) + | // cTValue * returned in eax (RD). + | mov BASE, RB // Restore BASE. + | // Copy table slot. + |.if X64 + | mov RBa, [RD] + | mov PC, [BASE-4] + | mov [BASE-8], RBa + |.else + | mov RB, [RD] + | mov RD, [RD+4] + | mov PC, [BASE-4] + | mov [BASE-8], RB + | mov [BASE-4], RD + |.endif + | jmp ->fff_res1 + | + |//-- Base library: conversions ------------------------------------------ + | + |.ffunc tonumber + | // Only handles the number case inline (without a base argument). + | cmp NARGS:RD, 1+1; jne ->fff_fallback // Exactly one argument. + | cmp dword [BASE+4], LJ_TISNUM + if (LJ_DUALNUM) { + | jne >1 + | mov RB, dword [BASE]; jmp ->fff_resi + |1: + | ja ->fff_fallback + } else { + | jae ->fff_fallback + } + if (sse) { + | movsd xmm0, qword [BASE]; jmp ->fff_resxmm0 + } else { + | fld qword [BASE]; jmp ->fff_resn + } + | + |.ffunc_1 tostring + | // Only handles the string or number case inline. + | mov PC, [BASE-4] + | cmp dword [BASE+4], LJ_TSTR; jne >3 + | // A __tostring method in the string base metatable is ignored. + | mov STR:RD, [BASE] + |2: + | mov dword [BASE-4], LJ_TSTR + | mov [BASE-8], STR:RD + | jmp ->fff_res1 + |3: // Handle numbers inline, unless a number base metatable is present. + | cmp dword [BASE+4], LJ_TISNUM; ja ->fff_fallback + | cmp dword [DISPATCH+DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])], 0 + | jne ->fff_fallback + | ffgccheck // Caveat: uses label 1. + | mov L:RB, SAVE_L + | mov L:RB->base, BASE // Add frame since C call can throw. + | mov SAVE_PC, PC // Redundant (but a defined value). + |.if X64 and not X64WIN + | mov FCARG2, BASE // Otherwise: FCARG2 == BASE + |.endif + | mov L:FCARG1, L:RB + if (LJ_DUALNUM) { + | call extern lj_str_fromnumber@8 // (lua_State *L, cTValue *o) + } else { + | call extern lj_str_fromnum@8 // (lua_State *L, lua_Number *np) + } + | // GCstr returned in eax (RD). + | mov BASE, L:RB->base + | jmp <2 + | + |//-- Base library: iterators ------------------------------------------- + | + |.ffunc_1 next + | 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] + |.if X64WIN + | lea CARG3d, [BASE+8] + | mov CARG2d, [BASE] // Caveat: CARG2d == BASE. + | mov CARG1d, L:RB + |.elif X64 + | mov CARG2d, [BASE] + | lea CARG3d, [BASE+8] // Caveat: CARG3d == BASE. + | mov CARG1d, L:RB + |.else + | mov TAB:RD, [BASE] + | mov ARG2, TAB:RD + | mov ARG1, L:RB + | add BASE, 8 + | mov ARG3, BASE + |.endif + | mov SAVE_PC, PC // Redundant (but a defined value). + | 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 + |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] + | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | cmp dword TAB:RB->metatable, 0; jne ->fff_fallback +#endif + | mov CFUNC:RB, [BASE-8] + | mov CFUNC:RD, CFUNC:RB->upvalue[0] + | mov PC, [BASE-4] + | mov dword [BASE-4], LJ_TFUNC + | mov [BASE-8], CFUNC:RD + | mov dword [BASE+12], LJ_TNIL + | mov RD, 1+3 + | jmp ->fff_res + | + |.ffunc_1 ipairs_aux + | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback + | cmp dword [BASE+12], LJ_TISNUM + if (LJ_DUALNUM) { + | jne ->fff_fallback + } else { + | jae ->fff_fallback + } + | mov PC, [BASE-4] + if (LJ_DUALNUM) { + | mov RD, dword [BASE+8] + | add RD, 1 + | mov dword [BASE-4], LJ_TISNUM + | mov dword [BASE-8], RD + } else if (sse) { + | movsd xmm0, qword [BASE+8] + | sseconst_1 xmm1, RBa + | addsd xmm0, xmm1 + | cvtsd2si RD, xmm0 + | movsd qword [BASE-8], xmm0 + } else { + |.if not X64 + | fld qword [BASE+8] + | fld1 + | faddp st1 + | fist ARG1 + | fstp qword [BASE-8] + | mov RD, ARG1 + |.endif + } + | mov TAB:RB, [BASE] + | cmp RD, TAB:RB->asize; jae >2 // Not in array part? + | shl RD, 3 + | add RD, TAB:RB->array + |1: + | cmp dword [RD+4], LJ_TNIL; je ->fff_res0 + | // Copy array slot. + |.if X64 + | mov RBa, [RD] + | mov [BASE], RBa + |.else + | mov RB, [RD] + | mov RD, [RD+4] + | mov [BASE], RB + | mov [BASE+4], RD + |.endif + | jmp ->fff_res2 + |2: // Check for empty hash part first. Otherwise call C function. + | cmp dword TAB:RB->hmask, 0; je ->fff_res0 + | mov FCARG1, TAB:RB + | mov RB, BASE // Save BASE. + | mov FCARG2, RD // Caveat: FCARG2 == BASE + | call extern lj_tab_getinth@8 // (GCtab *t, int32_t key) + | // cTValue * or NULL returned in eax (RD). + | mov BASE, RB + | test RD, RD + | jnz <1 + |->fff_res0: + | mov RD, 1+0 + | jmp ->fff_res + | + |.ffunc_1 ipairs + | mov TAB:RB, [BASE] + | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | cmp dword TAB:RB->metatable, 0; jne ->fff_fallback +#endif + | mov CFUNC:RB, [BASE-8] + | mov CFUNC:RD, CFUNC:RB->upvalue[0] + | mov PC, [BASE-4] + | mov dword [BASE-4], LJ_TFUNC + | mov [BASE-8], CFUNC:RD + if (LJ_DUALNUM) { + | mov dword [BASE+12], LJ_TISNUM + | mov dword [BASE+8], 0 + } else if (sse) { + | xorps xmm0, xmm0 + | movsd qword [BASE+8], xmm0 + } else { + | fldz + | fstp qword [BASE+8] + } + | mov RD, 1+3 + | jmp ->fff_res + | + |//-- Base library: catch errors ---------------------------------------- + | + |.ffunc_1 pcall + | lea RA, [BASE+8] + | sub NARGS:RD, 1 + | mov PC, 8+FRAME_PCALL + |1: + | movzx RB, byte [DISPATCH+DISPATCH_GL(hookmask)] + | shr RB, HOOK_ACTIVE_SHIFT + | and RB, 1 + | add PC, RB // Remember active hook before pcall. + | jmp ->vm_call_dispatch + | + |.ffunc_2 xpcall + | cmp dword [BASE+12], LJ_TFUNC; jne ->fff_fallback + | mov RB, [BASE+4] // Swap function and traceback. + | mov [BASE+12], RB + | mov dword [BASE+4], LJ_TFUNC + | mov LFUNC:RB, [BASE] + | mov PC, [BASE+8] + | mov [BASE+8], LFUNC:RB + | mov [BASE], PC + | lea RA, [BASE+16] + | sub NARGS:RD, 2 + | mov PC, 16+FRAME_PCALL + | jmp <1 + | + |//-- Coroutine library -------------------------------------------------- + | + |.macro coroutine_resume_wrap, resume + |.if resume + |.ffunc_1 coroutine_resume + | mov L:RB, [BASE] + |.else + |.ffunc coroutine_wrap_aux + | mov CFUNC:RB, [BASE-8] + | mov L:RB, CFUNC:RB->upvalue[0].gcr + |.endif + | mov PC, [BASE-4] + | mov SAVE_PC, PC + |.if X64 + | mov TMP1, L:RB + |.else + | mov ARG1, L:RB + |.endif + |.if resume + | cmp dword [BASE+4], LJ_TTHREAD; jne ->fff_fallback + |.endif + | cmp aword L:RB->cframe, 0; jne ->fff_fallback + | cmp byte L:RB->status, LUA_YIELD; ja ->fff_fallback + | mov RA, L:RB->top + | je >1 // Status != LUA_YIELD (i.e. 0)? + | cmp RA, L:RB->base // Check for presence of initial func. + | je ->fff_fallback + |1: + |.if resume + | lea PC, [RA+NARGS:RD*8-16] // Check stack space (-1-thread). + |.else + | lea PC, [RA+NARGS:RD*8-8] // Check stack space (-1). + |.endif + | cmp PC, L:RB->maxstack; ja ->fff_fallback + | mov L:RB->top, PC + | + | mov L:RB, SAVE_L + | mov L:RB->base, BASE + |.if resume + | add BASE, 8 // Keep resumed thread in stack for GC. + |.endif + | mov L:RB->top, BASE + |.if resume + | lea RB, [BASE+NARGS:RD*8-24] // RB = end of source for stack move. + |.else + | lea RB, [BASE+NARGS:RD*8-16] // RB = end of source for stack move. + |.endif + | sub RBa, PCa // Relative to PC. + | + | cmp PC, RA + | je >3 + |2: // Move args to coroutine. + |.if X64 + | mov RCa, [PC+RB] + | mov [PC-8], RCa + |.else + | mov RC, [PC+RB+4] + | mov [PC-4], RC + | mov RC, [PC+RB] + | mov [PC-8], RC + |.endif + | sub PC, 8 + | cmp PC, RA + | jne <2 + |3: + |.if X64 + | mov CARG2d, RA + | mov CARG1d, TMP1 + |.else + | mov ARG2, RA + | xor RA, RA + | mov ARG4, RA + | mov ARG3, RA + |.endif + | call ->vm_resume // (lua_State *L, TValue *base, 0, 0) + | set_vmstate INTERP + | + | mov L:RB, SAVE_L + |.if X64 + | mov L:PC, TMP1 + |.else + | mov L:PC, ARG1 // The callee doesn't modify SAVE_L. + |.endif + | mov BASE, L:RB->base + | cmp eax, LUA_YIELD + | ja >8 + |4: + | mov RA, L:PC->base + | mov KBASE, L:PC->top + | mov L:PC->top, RA // Clear coroutine stack. + | mov PC, KBASE + | sub PC, RA + | je >6 // No results? + | lea RD, [BASE+PC] + | shr PC, 3 + | cmp RD, L:RB->maxstack + | ja >9 // Need to grow stack? + | + | mov RB, BASE + | sub RBa, RAa + |5: // Move results from coroutine. + |.if X64 + | mov RDa, [RA] + | mov [RA+RB], RDa + |.else + | mov RD, [RA] + | mov [RA+RB], RD + | mov RD, [RA+4] + | mov [RA+RB+4], RD + |.endif + | add RA, 8 + | cmp RA, KBASE + | jne <5 + |6: + |.if resume + | lea RD, [PC+2] // nresults+1 = 1 + true + results. + | mov dword [BASE-4], LJ_TTRUE // Prepend true to results. + |.else + | lea RD, [PC+1] // nresults+1 = 1 + results. + |.endif + |7: + | mov PC, SAVE_PC + | mov MULTRES, RD + |.if resume + | mov RAa, -8 + |.else + | xor RA, RA + |.endif + | test PC, FRAME_TYPE + | jz ->BC_RET_Z + | jmp ->vm_return + | + |8: // Coroutine returned with error (at co->top-1). + |.if resume + | mov dword [BASE-4], LJ_TFALSE // Prepend false to results. + | mov RA, L:PC->top + | sub RA, 8 + | mov L:PC->top, RA // Clear error from coroutine stack. + | // Copy error message. + |.if X64 + | mov RDa, [RA] + | mov [BASE], RDa + |.else + | mov RD, [RA] + | mov [BASE], RD + | mov RD, [RA+4] + | mov [BASE+4], RD + |.endif + | mov RD, 1+2 // nresults+1 = 1 + false + error. + | jmp <7 + |.else + | mov FCARG2, L:PC + | mov FCARG1, L:RB + | call extern lj_ffh_coroutine_wrap_err@8 // (lua_State *L, lua_State *co) + | // Error function does not return. + |.endif + | + |9: // Handle stack expansion on return from yield. + |.if X64 + | mov L:RA, TMP1 + |.else + | mov L:RA, ARG1 // The callee doesn't modify SAVE_L. + |.endif + | mov L:RA->top, KBASE // Undo coroutine stack clearing. + | mov FCARG2, PC + | mov FCARG1, L:RB + | call extern lj_state_growstack@8 // (lua_State *L, int n) + |.if X64 + | mov L:PC, TMP1 + |.else + | mov L:PC, ARG1 + |.endif + | mov BASE, L:RB->base + | jmp <4 // Retry the stack move. + |.endmacro + | + | coroutine_resume_wrap 1 // coroutine.resume + | coroutine_resume_wrap 0 // coroutine.wrap + | + |.ffunc coroutine_yield + | mov L:RB, SAVE_L + | test aword L:RB->cframe, CFRAME_RESUME + | jz ->fff_fallback + | mov L:RB->base, BASE + | lea RD, [BASE+NARGS:RD*8-8] + | mov L:RB->top, RD + | xor RD, RD + | mov aword L:RB->cframe, RDa + | mov al, LUA_YIELD + | mov byte L:RB->status, al + | jmp ->vm_leave_unw + | + |//-- Math library ------------------------------------------------------- + | + if (!LJ_DUALNUM) { + |->fff_resi: // Dummy. + } + if (sse) { + |->fff_resn: + | mov PC, [BASE-4] + | fstp qword [BASE-8] + | jmp ->fff_res1 + } + | .ffunc_1 math_abs + if (LJ_DUALNUM) { + | cmp dword [BASE+4], LJ_TISNUM; jne >2 + | mov RB, dword [BASE] + | cmp RB, 0; jns ->fff_resi + | neg RB; js >1 + |->fff_resbit: + |->fff_resi: + | mov PC, [BASE-4] + | mov dword [BASE-4], LJ_TISNUM + | mov dword [BASE-8], RB + | jmp ->fff_res1 + |1: + | mov PC, [BASE-4] + | mov dword [BASE-4], 0x41e00000 // 2^31. + | mov dword [BASE-8], 0 + | jmp ->fff_res1 + |2: + | ja ->fff_fallback + } else { + | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback + } + if (sse) { + | movsd xmm0, qword [BASE] + | sseconst_abs xmm1, RDa + | andps xmm0, xmm1 + |->fff_resxmm0: + | mov PC, [BASE-4] + | movsd qword [BASE-8], xmm0 + | // fallthrough + } else { + | fld qword [BASE] + | fabs + | // fallthrough + |->fff_resxmm0: // Dummy. + |->fff_resn: + | mov PC, [BASE-4] + | fstp qword [BASE-8] + } + |->fff_res1: + | mov RD, 1+1 + |->fff_res: + | mov MULTRES, RD + |->fff_res_: + | test PC, FRAME_TYPE + | jnz >7 + |5: + | cmp PC_RB, RDL // More results expected? + | ja >6 + | // Adjust BASE. KBASE is assumed to be set for the calling frame. + | movzx RA, PC_RA + | not RAa // Note: ~RA = -(RA+1) + | lea BASE, [BASE+RA*8] // base = base - (RA+1)*8 + | ins_next + | + |6: // Fill up results with nil. + | mov dword [BASE+RD*8-12], LJ_TNIL + | add RD, 1 + | jmp <5 + | + |7: // Non-standard return case. + | mov RAa, -8 // Results start at BASE+RA = BASE-8. + | jmp ->vm_return + | + |.macro math_round, func + | .ffunc math_ .. func + ||if (LJ_DUALNUM) { + | cmp dword [BASE+4], LJ_TISNUM; jne >1 + | mov RB, dword [BASE]; jmp ->fff_resi + |1: + | ja ->fff_fallback + ||} else { + | cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback + ||} + ||if (sse) { + | movsd xmm0, qword [BASE] + | call ->vm_ .. func + || if (LJ_DUALNUM) { + | cvtsd2si RB, xmm0 + | cmp RB, 0x80000000 + | jne ->fff_resi + | cvtsi2sd xmm1, RB + | ucomisd xmm0, xmm1 + | jp ->fff_resxmm0 + | je ->fff_resi + || } + | jmp ->fff_resxmm0 + ||} else { + | fld qword [BASE] + | call ->vm_ .. func + || if (LJ_DUALNUM) { + |.if not X64 + | fist ARG1 + | mov RB, ARG1 + | cmp RB, 0x80000000; jne >2 + | fdup + | fild ARG1 + | fcomparepp + | jp ->fff_resn + | jne ->fff_resn + |2: + | fpop + | jmp ->fff_resi + |.endif + || } else { + | jmp ->fff_resn + || } + ||} + |.endmacro + | + | math_round floor + | math_round ceil + | + if (sse) { + |.ffunc_nsse math_sqrt, sqrtsd; jmp ->fff_resxmm0 + } else { + |.ffunc_n math_sqrt; fsqrt; jmp ->fff_resn + } + |.ffunc_n math_log, fldln2; fyl2x; jmp ->fff_resn + |.ffunc_n math_log10, fldlg2; fyl2x; jmp ->fff_resn + |.ffunc_n math_exp; call ->vm_exp_x87; jmp ->fff_resn + | + |.ffunc_n math_sin; fsin; jmp ->fff_resn + |.ffunc_n math_cos; fcos; jmp ->fff_resn + |.ffunc_n math_tan; fptan; fpop; jmp ->fff_resn + | + |.ffunc_n math_asin + | fdup; fmul st0; fld1; fsubrp st1; fsqrt; fpatan + | jmp ->fff_resn + |.ffunc_n math_acos + | fdup; fmul st0; fld1; fsubrp st1; fsqrt; fxch; fpatan + | jmp ->fff_resn + |.ffunc_n math_atan; fld1; fpatan; jmp ->fff_resn + | + |.macro math_extern, func + ||if (sse) { + | .ffunc_nsse math_ .. func + | .if not X64 + | movsd FPARG1, xmm0 + | .endif + ||} else { + | .if not X64 + | .ffunc_n math_ .. func + | fstp FPARG1 + | .endif + ||} + | mov RB, BASE + | call extern lj_vm_ .. func + | mov BASE, RB + | .if X64 + | jmp ->fff_resxmm0 + | .else + | jmp ->fff_resn + | .endif + |.endmacro + | + | math_extern sinh + | math_extern cosh + | math_extern tanh + | + |->ff_math_deg: + if (sse) { + |.ffunc_nsse math_rad + | mov CFUNC:RB, [BASE-8] + | mulsd xmm0, qword CFUNC:RB->upvalue[0] + | jmp ->fff_resxmm0 + } else { + |.ffunc_n math_rad + | mov CFUNC:RB, [BASE-8] + | fmul qword CFUNC:RB->upvalue[0] + | jmp ->fff_resn + } + | + |.ffunc_nn math_atan2; fpatan; jmp ->fff_resn + |.ffunc_nnr math_ldexp; fscale; fpop1; jmp ->fff_resn + | + |.ffunc_1 math_frexp + | mov RB, [BASE+4] + | cmp RB, LJ_TISNUM; jae ->fff_fallback + | mov PC, [BASE-4] + | mov RC, [BASE] + | mov [BASE-4], RB; mov [BASE-8], RC + | shl RB, 1; cmp RB, 0xffe00000; jae >3 + | or RC, RB; jz >3 + | mov RC, 1022 + | cmp RB, 0x00200000; jb >4 + |1: + | shr RB, 21; sub RB, RC // Extract and unbias exponent. + if (sse) { + | cvtsi2sd xmm0, RB + } else { + | mov TMP1, RB; fild TMP1 + } + | mov RB, [BASE-4] + | and RB, 0x800fffff // Mask off exponent. + | or RB, 0x3fe00000 // Put mantissa in range [0.5,1) or 0. + | mov [BASE-4], RB + |2: + if (sse) { + | movsd qword [BASE], xmm0 + } else { + | fstp qword [BASE] + } + | mov RD, 1+2 + | jmp ->fff_res + |3: // Return +-0, +-Inf, NaN unmodified and an exponent of 0. + if (sse) { + | xorps xmm0, xmm0; jmp <2 + } else { + | fldz; jmp <2 + } + |4: // Handle denormals by multiplying with 2^54 and adjusting the bias. + if (sse) { + | movsd xmm0, qword [BASE] + | sseconst_hi xmm1, RBa, 43500000 // 2^54. + | mulsd xmm0, xmm1 + | movsd qword [BASE-8], xmm0 + } else { + | fld qword [BASE] + | mov TMP1, 0x5a800000; fmul TMP1 // x = x*2^54 + | fstp qword [BASE-8] + } + | mov RB, [BASE-4]; mov RC, 1076; shl RB, 1; jmp <1 + | + if (sse) { + |.ffunc_nsse math_modf + } else { + |.ffunc_n math_modf + } + | mov RB, [BASE+4] + | mov PC, [BASE-4] + | shl RB, 1; cmp RB, 0xffe00000; je >4 // +-Inf? + if (sse) { + | movaps xmm4, xmm0 + | call ->vm_trunc + | subsd xmm4, xmm0 + |1: + | movsd qword [BASE-8], xmm0 + | movsd qword [BASE], xmm4 + } else { + | fdup + | call ->vm_trunc + | fsub st1, st0 + |1: + | fstp qword [BASE-8] + | fstp qword [BASE] + } + | mov RC, [BASE-4]; mov RB, [BASE+4] + | xor RC, RB; js >3 // Need to adjust sign? + |2: + | mov RD, 1+2 + | jmp ->fff_res + |3: + | xor RB, 0x80000000; mov [BASE+4], RB // Flip sign of fraction. + | jmp <2 + |4: + if (sse) { + | xorps xmm4, xmm4; jmp <1 // Return +-Inf and +-0. + } else { + | fldz; fxch; jmp <1 // Return +-Inf and +-0. + } + | + |.ffunc_nnr math_fmod + |1: ; fprem; fnstsw ax; sahf; jp <1 + | fpop1 + | jmp ->fff_resn + | + if (sse) { + |.ffunc_nnsse math_pow; call ->vm_pow; jmp ->fff_resxmm0 + } else { + |.ffunc_nn math_pow; call ->vm_pow; jmp ->fff_resn + } + | + |.macro math_minmax, name, cmovop, fcmovop, nofcmovop, sseop + | .ffunc name + | mov RA, 2 + | cmp dword [BASE+4], LJ_TISNUM + ||if (LJ_DUALNUM) { + | jne >4 + | mov RB, dword [BASE] + |1: // Handle integers. + | cmp RA, RD; jae ->fff_resi + | cmp dword [BASE+RA*8-4], LJ_TISNUM; jne >3 + | cmp RB, dword [BASE+RA*8-8] + | cmovop RB, dword [BASE+RA*8-8] + | add RA, 1 + | jmp <1 + |3: + | ja ->fff_fallback + | // Convert intermediate result to number and continue below. + ||if (sse) { + | cvtsi2sd xmm0, RB + ||} else { + |.if not X64 + | mov TMP1, RB + | fild TMP1 + |.endif + ||} + | jmp >6 + |4: + | ja ->fff_fallback + ||} else { + | jae ->fff_fallback + ||} + | + ||if (sse) { + | movsd xmm0, qword [BASE] + |5: // Handle numbers or integers. + | cmp RA, RD; jae ->fff_resxmm0 + | cmp dword [BASE+RA*8-4], LJ_TISNUM + ||if (LJ_DUALNUM) { + | jb >6 + | ja ->fff_fallback + | cvtsi2sd xmm1, dword [BASE+RA*8-8] + | jmp >7 + ||} else { + | jae ->fff_fallback + ||} + |6: + | movsd xmm1, qword [BASE+RA*8-8] + |7: + | sseop xmm0, xmm1 + | add RA, 1 + | jmp <5 + ||} else { + |.if not X64 + | fld qword [BASE] + |5: // Handle numbers or integers. + | cmp RA, RD; jae ->fff_resn + | cmp dword [BASE+RA*8-4], LJ_TISNUM + ||if (LJ_DUALNUM) { + | jb >6 + | ja >9 + | fild dword [BASE+RA*8-8] + | jmp >7 + ||} else { + | jae >9 + ||} + |6: + | fld qword [BASE+RA*8-8] + |7: + ||if (cmov) { + | fucomi st1; fcmovop st1; fpop1 + ||} else { + | push eax + | fucom st1; fnstsw ax; test ah, 1; nofcmovop >2; fxch; 2: ; fpop + | pop eax + ||} + | add RA, 1 + | jmp <5 + |.endif + ||} + |.endmacro + | + | math_minmax math_min, cmovg, fcmovnbe, jz, minsd + | math_minmax math_max, cmovl, fcmovbe, jnz, maxsd + if (!sse) { + |9: + | fpop; jmp ->fff_fallback + } + | + |//-- String library ----------------------------------------------------- + | + |.ffunc_1 string_len + | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback + | mov STR:RB, [BASE] + if (LJ_DUALNUM) { + | mov RB, dword STR:RB->len; jmp ->fff_resi + } else if (sse) { + | cvtsi2sd xmm0, dword STR:RB->len; jmp ->fff_resxmm0 + } else { + | fild dword STR:RB->len; jmp ->fff_resn + } + | + |.ffunc string_byte // Only handle the 1-arg case here. + | cmp NARGS:RD, 1+1; jne ->fff_fallback + | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback + | mov STR:RB, [BASE] + | mov PC, [BASE-4] + | cmp dword STR:RB->len, 1 + | jb ->fff_res0 // Return no results for empty string. + | movzx RB, byte STR:RB[1] + if (LJ_DUALNUM) { + | jmp ->fff_resi + } else if (sse) { + | cvtsi2sd xmm0, RB; jmp ->fff_resxmm0 + } else { + | mov TMP1, RB; fild TMP1; jmp ->fff_resn + } + | + |.ffunc string_char // Only handle the 1-arg case here. + | ffgccheck + | cmp NARGS:RD, 1+1; jne ->fff_fallback // *Exactly* 1 arg. + | cmp dword [BASE+4], LJ_TISNUM + if (LJ_DUALNUM) { + | jne ->fff_fallback + | mov RB, dword [BASE] + | cmp RB, 255; ja ->fff_fallback + | mov TMP2, RB + } else if (sse) { + | jae ->fff_fallback + | cvttsd2si RB, qword [BASE] + | cmp RB, 255; ja ->fff_fallback + | mov TMP2, RB + } else { + | jae ->fff_fallback + | fld qword [BASE] + | fistp TMP2 + | cmp TMP2, 255; ja ->fff_fallback + } + |.if X64 + | mov TMP3, 1 + |.else + | mov ARG3, 1 + |.endif + | lea RDa, TMP2 // Points to stack. Little-endian. + |->fff_newstr: + | mov L:RB, SAVE_L + | mov L:RB->base, BASE + |.if X64 + | mov CARG3d, TMP3 // Zero-extended to size_t. + | mov CARG2, RDa // May be 64 bit ptr to stack. + | mov CARG1d, L:RB + |.else + | mov ARG2, RD + | mov ARG1, L:RB + |.endif + | mov SAVE_PC, PC + | call extern lj_str_new // (lua_State *L, char *str, size_t l) + | // GCstr * returned in eax (RD). + | mov BASE, L:RB->base + | mov PC, [BASE-4] + | mov dword [BASE-4], LJ_TSTR + | mov [BASE-8], STR:RD + | jmp ->fff_res1 + | + |.ffunc string_sub + | ffgccheck + | mov TMP2, -1 + | cmp NARGS:RD, 1+2; jb ->fff_fallback + | jna >1 + | cmp dword [BASE+20], LJ_TISNUM + if (LJ_DUALNUM) { + | jne ->fff_fallback + | mov RB, dword [BASE+16] + | mov TMP2, RB + } else if (sse) { + | jae ->fff_fallback + | cvttsd2si RB, qword [BASE+16] + | mov TMP2, RB + } else { + | jae ->fff_fallback + | fld qword [BASE+16] + | fistp TMP2 + } + |1: + | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback + | cmp dword [BASE+12], LJ_TISNUM + if (LJ_DUALNUM) { + | jne ->fff_fallback + } else { + | jae ->fff_fallback + } + | mov STR:RB, [BASE] + | mov TMP3, STR:RB + | mov RB, STR:RB->len + if (LJ_DUALNUM) { + | mov RA, dword [BASE+8] + } else if (sse) { + | cvttsd2si RA, qword [BASE+8] + } else { + |.if not X64 + | fld qword [BASE+8] + | fistp ARG3 + | mov RA, ARG3 + |.endif + } + | mov RC, TMP2 + | cmp RB, RC // len < end? (unsigned compare) + | jb >5 + |2: + | test RA, RA // start <= 0? + | jle >7 + |3: + | mov STR:RB, TMP3 + | sub RC, RA // start > end? + | jl ->fff_emptystr + | lea RB, [STR:RB+RA+#STR-1] + | add RC, 1 + |4: + |.if X64 + | mov TMP3, RC + |.else + | mov ARG3, RC + |.endif + | mov RD, RB + | jmp ->fff_newstr + | + |5: // Negative end or overflow. + | jl >6 + | lea RC, [RC+RB+1] // end = end+(len+1) + | jmp <2 + |6: // Overflow. + | mov RC, RB // end = len + | jmp <2 + | + |7: // Negative start or underflow. + | je >8 + | add RA, RB // start = start+(len+1) + | add RA, 1 + | jg <3 // start > 0? + |8: // Underflow. + | mov RA, 1 // start = 1 + | jmp <3 + | + |->fff_emptystr: // Range underflow. + | xor RC, RC // Zero length. Any ptr in RB is ok. + | jmp <4 + | + |.ffunc_2 string_rep // Only handle the 1-char case inline. + | ffgccheck + | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback + | cmp dword [BASE+12], LJ_TISNUM + | mov STR:RB, [BASE] + if (LJ_DUALNUM) { + | jne ->fff_fallback + | mov RC, dword [BASE+8] + } else if (sse) { + | jae ->fff_fallback + | cvttsd2si RC, qword [BASE+8] + } else { + | jae ->fff_fallback + | fld qword [BASE+8] + | fistp TMP2 + | mov RC, TMP2 + } + | test RC, RC + | jle ->fff_emptystr // Count <= 0? (or non-int) + | cmp dword STR:RB->len, 1 + | jb ->fff_emptystr // Zero length string? + | jne ->fff_fallback_2 // Fallback for > 1-char strings. + | cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC; jb ->fff_fallback_2 + | movzx RA, byte STR:RB[1] + | mov RB, [DISPATCH+DISPATCH_GL(tmpbuf.buf)] + |.if X64 + | mov TMP3, RC + |.else + | mov ARG3, RC + |.endif + |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). + | mov [RB], RAL + | add RB, 1 + | sub RC, 1 + | jnz <1 + | mov RD, [DISPATCH+DISPATCH_GL(tmpbuf.buf)] + | jmp ->fff_newstr + | + |.ffunc_1 string_reverse + | ffgccheck + | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback + | mov STR:RB, [BASE] + | mov RC, STR:RB->len + | test RC, RC + | jz ->fff_emptystr // Zero length string? + | cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC; jb ->fff_fallback_1 + | add RB, #STR + | mov TMP2, PC // Need another temp register. + |.if X64 + | mov TMP3, RC + |.else + | mov ARG3, RC + |.endif + | mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.buf)] + |1: + | movzx RA, byte [RB] + | add RB, 1 + | sub RC, 1 + | mov [PC+RC], RAL + | jnz <1 + | mov RD, PC + | mov PC, TMP2 + | jmp ->fff_newstr + | + |.macro ffstring_case, name, lo, hi + | .ffunc_1 name + | ffgccheck + | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback + | mov STR:RB, [BASE] + | mov RC, STR:RB->len + | cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC; jb ->fff_fallback_1 + | add RB, #STR + | mov TMP2, PC // Need another temp register. + |.if X64 + | mov TMP3, RC + |.else + | mov ARG3, RC + |.endif + | mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.buf)] + | jmp >3 + |1: // ASCII case conversion. Yes, this is suboptimal code (do you care?). + | movzx RA, byte [RB+RC] + | cmp RA, lo + | jb >2 + | cmp RA, hi + | ja >2 + | xor RA, 0x20 + |2: + | mov [PC+RC], RAL + |3: + | sub RC, 1 + | jns <1 + | mov RD, PC + | mov PC, TMP2 + | jmp ->fff_newstr + |.endmacro + | + |ffstring_case string_lower, 0x41, 0x5a + |ffstring_case string_upper, 0x61, 0x7a + | + |//-- Table library ------------------------------------------------------ + | + |.ffunc_1 table_getn + | cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback + | mov RB, BASE // Save BASE. + | mov TAB:FCARG1, [BASE] + | call extern lj_tab_len@4 // LJ_FASTCALL (GCtab *t) + | // Length of table returned in eax (RD). + | mov BASE, RB // Restore BASE. + if (LJ_DUALNUM) { + | mov RB, RD; jmp ->fff_resi + } else if (sse) { + | cvtsi2sd xmm0, RD; jmp ->fff_resxmm0 + } else { + |.if not X64 + | mov ARG1, RD; fild ARG1; jmp ->fff_resn + |.endif + } + | + |//-- Bit library -------------------------------------------------------- + | + |.define TOBIT_BIAS, 0x59c00000 // 2^52 + 2^51 (float, not double!). + | + |.macro .ffunc_bit, name, kind + | .ffunc_1 name + |.if kind == 2 + ||if (sse) { + | sseconst_tobit xmm1, RBa + ||} else { + | mov TMP1, TOBIT_BIAS + ||} + |.endif + | cmp dword [BASE+4], LJ_TISNUM + ||if (LJ_DUALNUM) { + | jne >1 + | mov RB, dword [BASE] + |.if kind > 0 + | jmp >2 + |.else + | jmp ->fff_resbit + |.endif + |1: + | ja ->fff_fallback + ||} else { + | jae ->fff_fallback + ||} + ||if (sse) { + | movsd xmm0, qword [BASE] + |.if kind < 2 + | sseconst_tobit xmm1, RBa + |.endif + | addsd xmm0, xmm1 + | movd RB, xmm0 + ||} else { + |.if not X64 + | fld qword [BASE] + |.if kind < 2 + | mov TMP1, TOBIT_BIAS + |.endif + | fadd TMP1 + | fstp FPARG1 + |.if kind > 0 + | mov RB, ARG1 + |.endif + |.endif + ||} + |2: + |.endmacro + | + |.ffunc_bit bit_tobit, 0 + if (LJ_DUALNUM || sse) { + if (!sse) { + |.if not X64 + | mov RB, ARG1 + |.endif + } + | jmp ->fff_resbit + } else { + |.if not X64 + | fild ARG1 + | jmp ->fff_resn + |.endif + } + | + |.macro .ffunc_bit_op, name, ins + | .ffunc_bit name, 2 + | mov TMP2, NARGS:RD // Save for fallback. + | lea RD, [BASE+NARGS:RD*8-16] + |1: + | cmp RD, BASE + | jbe ->fff_resbit + | cmp dword [RD+4], LJ_TISNUM + ||if (LJ_DUALNUM) { + | jne >2 + | ins RB, dword [RD] + | sub RD, 8 + | jmp <1 + |2: + | ja ->fff_fallback_bit_op + ||} else { + | jae ->fff_fallback_bit_op + ||} + ||if (sse) { + | movsd xmm0, qword [RD] + | addsd xmm0, xmm1 + | movd RA, xmm0 + | ins RB, RA + ||} else { + |.if not X64 + | fld qword [RD] + | fadd TMP1 + | fstp FPARG1 + | ins RB, ARG1 + |.endif + ||} + | sub RD, 8 + | jmp <1 + |.endmacro + | + |.ffunc_bit_op bit_band, and + |.ffunc_bit_op bit_bor, or + |.ffunc_bit_op bit_bxor, xor + | + |.ffunc_bit bit_bswap, 1 + | bswap RB + | jmp ->fff_resbit + | + |.ffunc_bit bit_bnot, 1 + | not RB + if (LJ_DUALNUM) { + | jmp ->fff_resbit + } else if (sse) { + |->fff_resbit: + | cvtsi2sd xmm0, RB + | jmp ->fff_resxmm0 + } else { + |.if not X64 + |->fff_resbit: + | mov ARG1, RB + | fild ARG1 + | jmp ->fff_resn + |.endif + } + | + |->fff_fallback_bit_op: + | mov NARGS:RD, TMP2 // Restore for fallback + | jmp ->fff_fallback + | + |.macro .ffunc_bit_sh, name, ins + ||if (LJ_DUALNUM) { + | .ffunc_bit name, 1 + | // Note: no inline conversion from number for 2nd argument! + | cmp dword [BASE+12], LJ_TISNUM; jne ->fff_fallback + | mov RA, dword [BASE+8] + ||} else if (sse) { + | .ffunc_nnsse name + | sseconst_tobit xmm2, RBa + | addsd xmm0, xmm2 + | addsd xmm1, xmm2 + | movd RB, xmm0 + | movd RA, xmm1 + ||} else { + |.if not X64 + | .ffunc_nn name + | mov TMP1, TOBIT_BIAS + | fadd TMP1 + | fstp FPARG3 + | fadd TMP1 + | fstp FPARG1 + | mov RA, ARG3 + | mov RB, ARG1 + |.endif + ||} + | ins RB, cl // Assumes RA is ecx. + | jmp ->fff_resbit + |.endmacro + | + |.ffunc_bit_sh bit_lshift, shl + |.ffunc_bit_sh bit_rshift, shr + |.ffunc_bit_sh bit_arshift, sar + |.ffunc_bit_sh bit_rol, rol + |.ffunc_bit_sh bit_ror, ror + | + |//----------------------------------------------------------------------- + | + |->fff_fallback_2: + | mov NARGS:RD, 1+2 // Other args are ignored, anyway. + | jmp ->fff_fallback + |->fff_fallback_1: + | mov NARGS:RD, 1+1 // Other args are ignored, anyway. + |->fff_fallback: // Call fast function fallback handler. + | // BASE = new base, RD = nargs+1 + | mov L:RB, SAVE_L + | mov PC, [BASE-4] // Fallback may overwrite PC. + | mov SAVE_PC, PC // Redundant (but a defined value). + | mov L:RB->base, BASE + | lea RD, [BASE+NARGS:RD*8-8] + | lea RA, [RD+8*LUA_MINSTACK] // Ensure enough space for handler. + | mov L:RB->top, RD + | mov CFUNC:RD, [BASE-8] + | cmp RA, L:RB->maxstack + | ja >5 // Need to grow stack. + |.if X64 + | mov CARG1d, L:RB + |.else + | mov ARG1, L:RB + |.endif + | call aword CFUNC:RD->f // (lua_State *L) + | mov BASE, L:RB->base + | // Either throws an error, or recovers and returns -1, 0 or nresults+1. + | test RD, RD; jg ->fff_res // Returned nresults+1? + |1: + | mov RA, L:RB->top + | sub RA, BASE + | shr RA, 3 + | test RD, RD + | lea NARGS:RD, [RA+1] + | mov LFUNC:RB, [BASE-8] + | jne ->vm_call_tail // Returned -1? + | ins_callt // Returned 0: retry fast path. + | + |// Reconstruct previous base for vmeta_call during tailcall. + |->vm_call_tail: + | mov RA, BASE + | test PC, FRAME_TYPE + | jnz >3 + | movzx RB, PC_RA + | not RBa // Note: ~RB = -(RB+1) + | lea BASE, [BASE+RB*8] // base = base - (RB+1)*8 + | jmp ->vm_call_dispatch // Resolve again for tailcall. + |3: + | mov RB, PC + | and RB, -8 + | sub BASE, RB + | jmp ->vm_call_dispatch // Resolve again for tailcall. + | + |5: // Grow stack for fallback handler. + | mov FCARG2, LUA_MINSTACK + | mov FCARG1, L:RB + | call extern lj_state_growstack@8 // (lua_State *L, int n) + | mov BASE, L:RB->base + | xor RD, RD // Simulate a return 0. + | jmp <1 // Dumb retry (goes through ff first). + | + |->fff_gcstep: // Call GC step function. + | // BASE = new base, RD = nargs+1 + | pop RBa // Must keep stack at same level. + | mov TMPa, RBa // Save return address + | mov L:RB, SAVE_L + | mov SAVE_PC, PC // Redundant (but a defined value). + | mov L:RB->base, BASE + | lea RD, [BASE+NARGS:RD*8-8] + | mov FCARG1, L:RB + | mov L:RB->top, RD + | call extern lj_gc_step@4 // (lua_State *L) + | mov BASE, L:RB->base + | mov RD, L:RB->top + | sub RD, BASE + | shr RD, 3 + | add NARGS:RD, 1 + | mov RBa, TMPa + | push RBa // Restore return address. + | ret + | + |//----------------------------------------------------------------------- + |//-- Special dispatch targets ------------------------------------------- + |//----------------------------------------------------------------------- + | + |->vm_record: // Dispatch target for recording phase. +#if LJ_HASJIT + | movzx RD, byte [DISPATCH+DISPATCH_GL(hookmask)] + | test RDL, HOOK_VMEVENT // No recording while in vmevent. + | jnz >5 + | // Decrement the hookcount for consistency, but always do the call. + | test RDL, HOOK_ACTIVE + | jnz >1 + | test RDL, LUA_MASKLINE|LUA_MASKCOUNT + | jz >1 + | dec dword [DISPATCH+DISPATCH_GL(hookcount)] + | jmp >1 +#endif + | + |->vm_rethook: // Dispatch target for return hooks. + | movzx RD, byte [DISPATCH+DISPATCH_GL(hookmask)] + | test RDL, HOOK_ACTIVE // Hook already active? + | jnz >5 + | jmp >1 + | + |->vm_inshook: // Dispatch target for instr/line hooks. + | movzx RD, byte [DISPATCH+DISPATCH_GL(hookmask)] + | test RDL, HOOK_ACTIVE // Hook already active? + | jnz >5 + | + | test RDL, LUA_MASKLINE|LUA_MASKCOUNT + | jz >5 + | dec dword [DISPATCH+DISPATCH_GL(hookcount)] + | jz >1 + | test RDL, LUA_MASKLINE + | jz >5 + |1: + | mov L:RB, SAVE_L + | mov L:RB->base, BASE + | mov FCARG2, PC // Caveat: FCARG2 == BASE + | mov FCARG1, L:RB + | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC. + | call extern lj_dispatch_ins@8 // (lua_State *L, BCIns *pc) + |3: + | mov BASE, L:RB->base + |4: + | movzx RA, PC_RA + |5: + | movzx OP, PC_OP + | movzx RD, PC_RD + |.if X64 + | jmp aword [DISPATCH+OP*8+GG_DISP2STATIC] // Re-dispatch to static ins. + |.else + | jmp aword [DISPATCH+OP*4+GG_DISP2STATIC] // Re-dispatch to static ins. + |.endif + | + |->cont_hook: // Continue from hook yield. + | add PC, 4 + | mov RA, [RB-24] + | mov MULTRES, RA // Restore MULTRES for *M ins. + | jmp <4 + | + |->vm_hotloop: // Hot loop counter underflow. +#if LJ_HASJIT + | mov LFUNC:RB, [BASE-8] // Same as curr_topL(L). + | mov RB, LFUNC:RB->pc + | movzx RD, byte [RB+PC2PROTO(framesize)] + | lea RD, [BASE+RD*8] + | mov L:RB, SAVE_L + | mov L:RB->base, BASE + | mov L:RB->top, RD + | mov FCARG2, PC + | lea FCARG1, [DISPATCH+GG_DISP2J] + | mov aword [DISPATCH+DISPATCH_J(L)], L:RBa + | mov SAVE_PC, PC + | call extern lj_trace_hot@8 // (jit_State *J, const BCIns *pc) + | jmp <3 +#endif + | + |->vm_callhook: // Dispatch target for call hooks. + | mov SAVE_PC, PC +#if LJ_HASJIT + | jmp >1 +#endif + | + |->vm_hotcall: // Hot call counter underflow. +#if LJ_HASJIT + | mov SAVE_PC, PC + | or PC, 1 // Marker for hot call. + |1: +#endif + | lea RD, [BASE+NARGS:RD*8-8] + | mov L:RB, SAVE_L + | mov L:RB->base, BASE + | mov L:RB->top, RD + | mov FCARG2, PC + | mov FCARG1, L:RB + | call extern lj_dispatch_call@8 // (lua_State *L, const BCIns *pc) + | // ASMFunction returned in eax/rax (RDa). + | mov SAVE_PC, 0 // Invalidate for subsequent line hook. +#if LJ_HASJIT + | and PC, -2 +#endif + | mov BASE, L:RB->base + | mov RAa, RDa + | mov RD, L:RB->top + | sub RD, BASE + | mov RBa, RAa + | movzx RA, PC_RA + | shr RD, 3 + | add NARGS:RD, 1 + | jmp RBa + | + |//----------------------------------------------------------------------- + |//-- Trace exit handler ------------------------------------------------- + |//----------------------------------------------------------------------- + | + |// Called from an exit stub with the exit number on the stack. + |// The 16 bit exit number is stored with two (sign-extended) push imm8. + |->vm_exit_handler: +#if LJ_HASJIT + |.if X64 + | push r13; push r12 + | push r11; push r10; push r9; push r8 + | push rdi; push rsi; push rbp; lea rbp, [rsp+88]; push rbp + | push rbx; push rdx; push rcx; push rax + | movzx RC, byte [rbp-8] // Reconstruct exit number. + | mov RCH, byte [rbp-16] + | mov [rbp-8], r15; mov [rbp-16], r14 + |.else + | push ebp; lea ebp, [esp+12]; push ebp + | push ebx; push edx; push ecx; push eax + | movzx RC, byte [ebp-4] // Reconstruct exit number. + | mov RCH, byte [ebp-8] + | mov [ebp-4], edi; mov [ebp-8], esi + |.endif + | // Caveat: DISPATCH is ebx. + | mov DISPATCH, [ebp] + | mov RA, [DISPATCH+DISPATCH_GL(vmstate)] // Get trace number. + | set_vmstate EXIT + | mov [DISPATCH+DISPATCH_J(exitno)], RC + | mov [DISPATCH+DISPATCH_J(parent)], RA + |.if X64 + |.if X64WIN + | sub rsp, 16*8+4*8 // Room for SSE regs + save area. + |.else + | sub rsp, 16*8 // Room for SSE regs. + |.endif + | add rbp, -128 + | movsd qword [rbp-8], xmm15; movsd qword [rbp-16], xmm14 + | movsd qword [rbp-24], xmm13; movsd qword [rbp-32], xmm12 + | movsd qword [rbp-40], xmm11; movsd qword [rbp-48], xmm10 + | movsd qword [rbp-56], xmm9; movsd qword [rbp-64], xmm8 + | movsd qword [rbp-72], xmm7; movsd qword [rbp-80], xmm6 + | movsd qword [rbp-88], xmm5; movsd qword [rbp-96], xmm4 + | movsd qword [rbp-104], xmm3; movsd qword [rbp-112], xmm2 + | movsd qword [rbp-120], xmm1; movsd qword [rbp-128], xmm0 + |.else + | sub esp, 8*8+16 // Room for SSE regs + args. + | movsd qword [ebp-40], xmm7; movsd qword [ebp-48], xmm6 + | movsd qword [ebp-56], xmm5; movsd qword [ebp-64], xmm4 + | movsd qword [ebp-72], xmm3; movsd qword [ebp-80], xmm2 + | movsd qword [ebp-88], xmm1; movsd qword [ebp-96], xmm0 + |.endif + | // Caveat: RB is ebp. + | mov L:RB, [DISPATCH+DISPATCH_GL(jit_L)] + | mov BASE, [DISPATCH+DISPATCH_GL(jit_base)] + | mov aword [DISPATCH+DISPATCH_J(L)], L:RBa + | mov dword [DISPATCH+DISPATCH_GL(jit_L)], 0 + | mov L:RB->base, BASE + |.if X64WIN + | lea CARG2, [rsp+4*8] + |.elif X64 + | mov CARG2, rsp + |.else + | lea FCARG2, [esp+16] + |.endif + | lea FCARG1, [DISPATCH+GG_DISP2J] + | call extern lj_trace_exit@8 // (jit_State *J, ExitState *ex) + | // MULTRES or negated error code returned in eax (RD). + | mov RAa, L:RB->cframe + | and RAa, CFRAME_RAWMASK + |.if X64WIN + | // Reposition stack later. + |.elif X64 + | mov rsp, RAa // Reposition stack to C frame. + |.else + | mov esp, RAa // Reposition stack to C frame. + |.endif + | mov [RAa+CFRAME_OFS_L], L:RB // Set SAVE_L (on-trace resume/yield). + | mov BASE, L:RB->base + | mov PC, [RAa+CFRAME_OFS_PC] // Get SAVE_PC. + |.if X64 + | jmp >1 + |.endif +#endif + |->vm_exit_interp: + | // RD = MULTRES or negated error code, BASE, PC and DISPATCH set. +#if LJ_HASJIT + |.if X64 + | // Restore additional callee-save registers only used in compiled code. + |.if X64WIN + | lea RAa, [rsp+9*16+4*8] + |1: + | movdqa xmm15, [RAa-9*16] + | movdqa xmm14, [RAa-8*16] + | movdqa xmm13, [RAa-7*16] + | movdqa xmm12, [RAa-6*16] + | movdqa xmm11, [RAa-5*16] + | movdqa xmm10, [RAa-4*16] + | movdqa xmm9, [RAa-3*16] + | movdqa xmm8, [RAa-2*16] + | movdqa xmm7, [RAa-1*16] + | mov rsp, RAa // Reposition stack to C frame. + | movdqa xmm6, [RAa] + | mov r15, CSAVE_3 + | mov r14, CSAVE_4 + |.else + | add rsp, 16 // Reposition stack to C frame. + |1: + |.endif + | mov r13, TMPa + | mov r12, TMPQ + |.endif + | test RD, RD; js >3 // Check for error from exit. + | mov MULTRES, RD + | mov LFUNC:KBASE, [BASE-8] + | mov KBASE, LFUNC:KBASE->pc + | mov KBASE, [KBASE+PC2PROTO(k)] + | mov dword [DISPATCH+DISPATCH_GL(jit_L)], 0 + | set_vmstate INTERP + | // Modified copy of ins_next which handles function header dispatch, too. + | mov RC, [PC] + | movzx RA, RCH + | movzx OP, RCL + | add PC, 4 + | shr RC, 16 + | cmp OP, BC_FUNCF // Function header? + | jb >2 + | mov RC, MULTRES // RC/RD holds nres+1. + |2: + |.if X64 + | jmp aword [DISPATCH+OP*8] + |.else + | jmp aword [DISPATCH+OP*4] + |.endif + | + |3: // Rethrow error from the right C frame. + | neg RD + | mov FCARG1, L:RB + | mov FCARG2, RD + | call extern lj_err_throw@8 // (lua_State *L, int errcode) +#endif + | + |//----------------------------------------------------------------------- + |//-- Math helper functions ---------------------------------------------- + |//----------------------------------------------------------------------- + | + |// FP value rounding. Called by math.floor/math.ceil fast functions + |// and from JIT code. + | + |// x87 variant: Arg/ret on x87 stack. No int/xmm registers modified. + |.macro vm_round_x87, mode1, mode2 + | fnstcw word [esp+4] // Caveat: overwrites ARG1 and ARG2. + | mov [esp+8], eax + | mov ax, mode1 + | or ax, [esp+4] + |.if mode2 ~= 0xffff + | and ax, mode2 + |.endif + | mov [esp+6], ax + | fldcw word [esp+6] + | frndint + | fldcw word [esp+4] + | mov eax, [esp+8] + | ret + |.endmacro + | + |// SSE variant: arg/ret is xmm0. xmm0-xmm3 and RD (eax) modified. + |.macro vm_round_sse, mode + | sseconst_abs xmm2, RDa + | sseconst_2p52 xmm3, RDa + | movaps xmm1, xmm0 + | andpd xmm1, xmm2 // |x| + | ucomisd xmm3, xmm1 // No truncation if 2^52 <= |x|. + | jbe >1 + | andnpd xmm2, xmm0 // Isolate sign bit. + |.if mode == 2 // trunc(x)? + | movaps xmm0, xmm1 + | addsd xmm1, xmm3 // (|x| + 2^52) - 2^52 + | subsd xmm1, xmm3 + | sseconst_1 xmm3, RDa + | cmpsd xmm0, xmm1, 1 // |x| < result? + | andpd xmm0, xmm3 + | subsd xmm1, xmm0 // If yes, subtract -1. + | orpd xmm1, xmm2 // Merge sign bit back in. + |.else + | addsd xmm1, xmm3 // (|x| + 2^52) - 2^52 + | subsd xmm1, xmm3 + | orpd xmm1, xmm2 // Merge sign bit back in. + | .if mode == 1 // ceil(x)? + | sseconst_m1 xmm2, RDa // Must subtract -1 to preserve -0. + | cmpsd xmm0, xmm1, 6 // x > result? + | .else // floor(x)? + | sseconst_1 xmm2, RDa + | cmpsd xmm0, xmm1, 1 // x < result? + | .endif + | andpd xmm0, xmm2 + | subsd xmm1, xmm0 // If yes, subtract +-1. + |.endif + | movaps xmm0, xmm1 + |1: + | ret + |.endmacro + | + |.macro vm_round, name, ssemode, mode1, mode2 + |->name: + ||if (!sse) { + | vm_round_x87 mode1, mode2 + ||} + |->name .. _sse: + | vm_round_sse ssemode + |.endmacro + | + | vm_round vm_floor, 0, 0x0400, 0xf7ff + | vm_round vm_ceil, 1, 0x0800, 0xfbff + | vm_round vm_trunc, 2, 0x0c00, 0xffff + | + |// FP modulo x%y. Called by BC_MOD* and vm_arith. + |->vm_mod: + if (sse) { + |// Args in xmm0/xmm1, return value in xmm0. + |// Caveat: xmm0-xmm5 and RC (eax) modified! + | movaps xmm5, xmm0 + | divsd xmm0, xmm1 + | sseconst_abs xmm2, RDa + | sseconst_2p52 xmm3, RDa + | movaps xmm4, xmm0 + | andpd xmm4, xmm2 // |x/y| + | ucomisd xmm3, xmm4 // No truncation if 2^52 <= |x/y|. + | jbe >1 + | andnpd xmm2, xmm0 // Isolate sign bit. + | addsd xmm4, xmm3 // (|x/y| + 2^52) - 2^52 + | subsd xmm4, xmm3 + | orpd xmm4, xmm2 // Merge sign bit back in. + | sseconst_1 xmm2, RDa + | cmpsd xmm0, xmm4, 1 // x/y < result? + | andpd xmm0, xmm2 + | subsd xmm4, xmm0 // If yes, subtract 1.0. + | movaps xmm0, xmm5 + | mulsd xmm1, xmm4 + | subsd xmm0, xmm1 + | ret + |1: + | mulsd xmm1, xmm0 + | movaps xmm0, xmm5 + | subsd xmm0, xmm1 + | ret + } else { + |// Args/ret on x87 stack (y on top). No xmm registers modified. + |// Caveat: needs 3 slots on x87 stack! RC (eax) modified! + | fld st1 + | fdiv st1 + | fnstcw word [esp+4] + | mov ax, 0x0400 + | or ax, [esp+4] + | and ax, 0xf7ff + | mov [esp+6], ax + | fldcw word [esp+6] + | frndint + | fldcw word [esp+4] + | fmulp st1 + | fsubp st1 + | ret + } + | + |// FP exponentiation e^x and 2^x. Called by math.exp fast function and + |// from JIT code. Arg/ret on x87 stack. No int/xmm regs modified. + |// Caveat: needs 3 slots on x87 stack! + |->vm_exp_x87: + | fldl2e; fmulp st1 // e^x ==> 2^(x*log2(e)) + |->vm_exp2_x87: + | .if X64WIN + | .define expscratch, dword [rsp+8] // Use scratch area. + | .elif X64 + | .define expscratch, dword [rsp-8] // Use red zone. + | .else + | .define expscratch, dword [esp+4] // Needs 4 byte scratch area. + | .endif + | fst expscratch // Caveat: overwrites ARG1. + | cmp expscratch, 0x7f800000; je >1 // Special case: e^+Inf = +Inf + | cmp expscratch, 0xff800000; je >2 // Special case: e^-Inf = 0 + |->vm_exp2raw: // Entry point for vm_pow. Without +-Inf check. + | fdup; frndint; fsub st1, st0; fxch // Split into frac/int part. + | f2xm1; fld1; faddp st1; fscale; fpop1 // ==> (2^frac-1 +1) << int + |1: + | ret + |2: + | fpop; fldz; ret + | + |// Generic power function x^y. Called by BC_POW, math.pow fast function, + |// and vm_arith. + if (!sse) { + |.if not X64 + |// Args/ret on x87 stack (y on top). RC (eax) modified. + |// Caveat: needs 3 slots on x87 stack! + |->vm_pow: + | fist dword [esp+4] // Store/reload int before comparison. + | fild dword [esp+4] // Integral exponent used in vm_powi. + ||if (cmov) { + | fucomip st1 + ||} else { + | fucomp st1; fnstsw ax; sahf + ||} + | jnz >8 // Branch for FP exponents. + | jp >9 // Branch for NaN exponent. + | fpop // Pop y and fallthrough to vm_powi. + | + |// FP/int power function x^i. Arg1/ret on x87 stack. + |// Arg2 (int) on C stack. RC (eax) modified. + |// Caveat: needs 2 slots on x87 stack! + | mov eax, [esp+4] + | cmp eax, 1; jle >6 // i<=1? + | // Now 1 < (unsigned)i <= 0x80000000. + |1: // Handle leading zeros. + | test eax, 1; jnz >2 + | fmul st0 + | shr eax, 1 + | jmp <1 + |2: + | shr eax, 1; jz >5 + | fdup + |3: // Handle trailing bits. + | fmul st0 + | shr eax, 1; jz >4 + | jnc <3 + | fmul st1, st0 + | jmp <3 + |4: + | fmulp st1 + |5: + | ret + |6: + | je <5 // x^1 ==> x + | jb >7 + | fld1; fdivrp st1 + | neg eax + | cmp eax, 1; je <5 // x^-1 ==> 1/x + | jmp <1 // x^-i ==> (1/x)^i + |7: + | fpop; fld1 // x^0 ==> 1 + | ret + | + |8: // FP/FP power function x^y. + | fst dword [esp+4] + | fxch + | fst dword [esp+8] + | mov eax, [esp+4]; shl eax, 1 + | cmp eax, 0xff000000; je >2 // x^+-Inf? + | mov eax, [esp+8]; shl eax, 1; je >4 // +-0^y? + | cmp eax, 0xff000000; je >4 // +-Inf^y? + | fyl2x + | jmp ->vm_exp2raw + | + |9: // Handle x^NaN. + | fld1 + ||if (cmov) { + | fucomip st2 + ||} else { + | fucomp st2; fnstsw ax; sahf + ||} + | je >1 // 1^NaN ==> 1 + | fxch // x^NaN ==> NaN + |1: + | fpop + | ret + | + |2: // Handle x^+-Inf. + | fabs + | fld1 + ||if (cmov) { + | fucomip st1 + ||} else { + | fucomp st1; fnstsw ax; sahf + ||} + | je >3 // +-1^+-Inf ==> 1 + | fpop; fabs; fldz; mov eax, 0; setc al + | ror eax, 1; xor eax, [esp+4]; jns >3 // |x|<>1, x^+-Inf ==> +Inf/0 + | fxch + |3: + | fpop1; fabs + | ret + | + |4: // Handle +-0^y or +-Inf^y. + | cmp dword [esp+4], 0; jge <3 // y >= 0, x^y ==> |x| + | fpop; fpop + | test eax, eax; jz >5 // y < 0, +-0^y ==> +Inf + | fldz // y < 0, +-Inf^y ==> 0 + | ret + |5: + | mov dword [esp+4], 0x7f800000 // Return +Inf. + | fld dword [esp+4] + | ret + |.endif + } else { + |->vm_pow: + } + | + |// Args in xmm0/xmm1. Ret in xmm0. xmm0-xmm2 and RC (eax) modified. + |// Needs 16 byte scratch area for x86. Also called from JIT code. + |->vm_pow_sse: + | cvtsd2si eax, xmm1 + | cvtsi2sd xmm2, eax + | ucomisd xmm1, xmm2 + | jnz >8 // Branch for FP exponents. + | jp >9 // Branch for NaN exponent. + | // Fallthrough to vm_powi_sse. + | + |// Args in xmm0/eax. Ret in xmm0. xmm0-xmm1 and eax modified. + |->vm_powi_sse: + | cmp eax, 1; jle >6 // i<=1? + | // Now 1 < (unsigned)i <= 0x80000000. + |1: // Handle leading zeros. + | test eax, 1; jnz >2 + | mulsd xmm0, xmm0 + | shr eax, 1 + | jmp <1 + |2: + | shr eax, 1; jz >5 + | movaps xmm1, xmm0 + |3: // Handle trailing bits. + | mulsd xmm0, xmm0 + | shr eax, 1; jz >4 + | jnc <3 + | mulsd xmm1, xmm0 + | jmp <3 + |4: + | mulsd xmm0, xmm1 + |5: + | ret + |6: + | je <5 // x^1 ==> x + | jb >7 // x^0 ==> 1 + | neg eax + | call <1 + | sseconst_1 xmm1, RDa + | divsd xmm1, xmm0 + | movaps xmm0, xmm1 + | ret + |7: + | sseconst_1 xmm0, RDa + | ret + | + |8: // FP/FP power function x^y. + |.if X64 + | movd rax, xmm1; shl rax, 1 + | rol rax, 12; cmp rax, 0xffe; je >2 // x^+-Inf? + | movd rax, xmm0; shl rax, 1; je >4 // +-0^y? + | rol rax, 12; cmp rax, 0xffe; je >5 // +-Inf^y? + | .if X64WIN + | movsd qword [rsp+16], xmm1 // Use scratch area. + | movsd qword [rsp+8], xmm0 + | fld qword [rsp+16] + | fld qword [rsp+8] + | .else + | movsd qword [rsp-16], xmm1 // Use red zone. + | movsd qword [rsp-8], xmm0 + | fld qword [rsp-16] + | fld qword [rsp-8] + | .endif + |.else + | movsd qword [esp+12], xmm1 // Needs 16 byte scratch area. + | movsd qword [esp+4], xmm0 + | cmp dword [esp+12], 0; jne >1 + | mov eax, [esp+16]; shl eax, 1 + | cmp eax, 0xffe00000; je >2 // x^+-Inf? + |1: + | cmp dword [esp+4], 0; jne >1 + | mov eax, [esp+8]; shl eax, 1; je >4 // +-0^y? + | cmp eax, 0xffe00000; je >5 // +-Inf^y? + |1: + | fld qword [esp+12] + | fld qword [esp+4] + |.endif + | fyl2x // y*log2(x) + | fdup; frndint; fsub st1, st0; fxch // Split into frac/int part. + | f2xm1; fld1; faddp st1; fscale; fpop1 // ==> (2^frac-1 +1) << int + |.if X64WIN + | fstp qword [rsp+8] // Use scratch area. + | movsd xmm0, qword [rsp+8] + |.elif X64 + | fstp qword [rsp-8] // Use red zone. + | movsd xmm0, qword [rsp-8] + |.else + | fstp qword [esp+4] // Needs 8 byte scratch area. + | movsd xmm0, qword [esp+4] + |.endif + | ret + | + |9: // Handle x^NaN. + | sseconst_1 xmm2, RDa + | ucomisd xmm0, xmm2; je >1 // 1^NaN ==> 1 + | movaps xmm0, xmm1 // x^NaN ==> NaN + |1: + | ret + | + |2: // Handle x^+-Inf. + | sseconst_abs xmm2, RDa + | andpd xmm0, xmm2 // |x| + | sseconst_1 xmm2, RDa + | ucomisd xmm0, xmm2; je <1 // +-1^+-Inf ==> 1 + | movmskpd eax, xmm1 + | xorps xmm0, xmm0 + | mov ah, al; setc al; xor al, ah; jne <1 // |x|<>1, x^+-Inf ==> +Inf/0 + |3: + | sseconst_hi xmm0, RDa, 7ff00000 // +Inf + | ret + | + |4: // Handle +-0^y. + | movmskpd eax, xmm1; test eax, eax; jnz <3 // y < 0, +-0^y ==> +Inf + | xorps xmm0, xmm0 // y >= 0, +-0^y ==> 0 + | ret + | + |5: // Handle +-Inf^y. + | movmskpd eax, xmm1; test eax, eax; jz <3 // y >= 0, +-Inf^y ==> +Inf + | xorps xmm0, xmm0 // y < 0, +-Inf^y ==> 0 + | ret + | + |// Callable from C: double lj_vm_foldfpm(double x, int fpm) + |// Computes fpm(x) for extended math functions. ORDER FPM. + |->vm_foldfpm: +#if LJ_HASJIT + if (sse) { + |.if X64 + | + | .if X64WIN + | .define fpmop, CARG2d + | .else + | .define fpmop, CARG1d + | .endif + | cmp fpmop, 1; jb ->vm_floor; je ->vm_ceil + | cmp fpmop, 3; jb ->vm_trunc; ja >2 + | sqrtsd xmm0, xmm0; ret + |2: + | .if X64WIN + | movsd qword [rsp+8], xmm0 // Use scratch area. + | fld qword [rsp+8] + | .else + | movsd qword [rsp-8], xmm0 // Use red zone. + | fld qword [rsp-8] + | .endif + | cmp fpmop, 5; ja >2 + | .if X64WIN; pop rax; .endif + | je >1 + | call ->vm_exp_x87 + | .if X64WIN; push rax; .endif + | jmp >7 + |1: + | call ->vm_exp2_x87 + | .if X64WIN; push rax; .endif + | jmp >7 + |2: ; cmp fpmop, 7; je >1; ja >2 + | fldln2; fxch; fyl2x; jmp >7 + |1: ; fld1; fxch; fyl2x; jmp >7 + |2: ; cmp fpmop, 9; je >1; ja >2 + | fldlg2; fxch; fyl2x; jmp >7 + |1: ; fsin; jmp >7 + |2: ; cmp fpmop, 11; je >1; ja >9 + | fcos; jmp >7 + |1: ; fptan; fpop + |7: + | .if X64WIN + | fstp qword [rsp+8] // Use scratch area. + | movsd xmm0, qword [rsp+8] + | .else + | fstp qword [rsp-8] // Use red zone. + | movsd xmm0, qword [rsp-8] + | .endif + | ret + | + |.else // x86 calling convention. + | + | .define fpmop, eax + | mov fpmop, [esp+12] + | movsd xmm0, qword [esp+4] + | cmp fpmop, 1; je >1; ja >2 + | call ->vm_floor; jmp >7 + |1: ; call ->vm_ceil; jmp >7 + |2: ; cmp fpmop, 3; je >1; ja >2 + | call ->vm_trunc; jmp >7 + |1: + | sqrtsd xmm0, xmm0 + |7: + | movsd qword [esp+4], xmm0 // Overwrite callee-owned args. + | fld qword [esp+4] + | ret + |2: ; fld qword [esp+4] + | cmp fpmop, 5; jb ->vm_exp_x87; je ->vm_exp2_x87 + |2: ; cmp fpmop, 7; je >1; ja >2 + | fldln2; fxch; fyl2x; ret + |1: ; fld1; fxch; fyl2x; ret + |2: ; cmp fpmop, 9; je >1; ja >2 + | fldlg2; fxch; fyl2x; ret + |1: ; fsin; ret + |2: ; cmp fpmop, 11; je >1; ja >9 + | fcos; ret + |1: ; fptan; fpop; ret + | + |.endif + } else { + | mov fpmop, [esp+12] + | fld qword [esp+4] + | cmp fpmop, 1; jb ->vm_floor; je ->vm_ceil + | cmp fpmop, 3; jb ->vm_trunc; ja >2 + | fsqrt; ret + |2: ; cmp fpmop, 5; jb ->vm_exp_x87; je ->vm_exp2_x87 + | cmp fpmop, 7; je >1; ja >2 + | fldln2; fxch; fyl2x; ret + |1: ; fld1; fxch; fyl2x; ret + |2: ; cmp fpmop, 9; je >1; ja >2 + | fldlg2; fxch; fyl2x; ret + |1: ; fsin; ret + |2: ; cmp fpmop, 11; je >1; ja >9 + | fcos; ret + |1: ; fptan; fpop; ret + } + |9: ; int3 // Bad fpm. +#endif + | + |// Callable from C: double lj_vm_foldarith(double x, double y, int op) + |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -) + |// and basic math functions. ORDER ARITH + |->vm_foldarith: + if (sse) { + |.if X64 + | + | .if X64WIN + | .define foldop, CARG3d + | .else + | .define foldop, CARG1d + | .endif + | cmp foldop, 1; je >1; ja >2 + | addsd xmm0, xmm1; ret + |1: ; subsd xmm0, xmm1; ret + |2: ; cmp foldop, 3; je >1; ja >2 + | mulsd xmm0, xmm1; ret + |1: ; divsd xmm0, xmm1; ret + |2: ; cmp foldop, 5; jb ->vm_mod; je ->vm_pow + | cmp foldop, 7; je >1; ja >2 + | sseconst_sign xmm1, RDa; xorps xmm0, xmm1; ret + |1: ; sseconst_abs xmm1, RDa; andps xmm0, xmm1; ret + |2: ; cmp foldop, 9; ja >2 + |.if X64WIN + | movsd qword [rsp+8], xmm0 // Use scratch area. + | movsd qword [rsp+16], xmm1 + | fld qword [rsp+8] + | fld qword [rsp+16] + |.else + | movsd qword [rsp-8], xmm0 // Use red zone. + | movsd qword [rsp-16], xmm1 + | fld qword [rsp-8] + | fld qword [rsp-16] + |.endif + | je >1 + | fpatan + |7: + |.if X64WIN + | fstp qword [rsp+8] // Use scratch area. + | movsd xmm0, qword [rsp+8] + |.else + | fstp qword [rsp-8] // Use red zone. + | movsd xmm0, qword [rsp-8] + |.endif + | ret + |1: ; fxch; fscale; fpop1; jmp <7 + |2: ; cmp foldop, 11; je >1; ja >9 + | minsd xmm0, xmm1; ret + |1: ; maxsd xmm0, xmm1; ret + |9: ; int3 // Bad op. + | + |.else // x86 calling convention. + | + | .define foldop, eax + | mov foldop, [esp+20] + | movsd xmm0, qword [esp+4] + | movsd xmm1, qword [esp+12] + | cmp foldop, 1; je >1; ja >2 + | addsd xmm0, xmm1 + |7: + | movsd qword [esp+4], xmm0 // Overwrite callee-owned args. + | fld qword [esp+4] + | ret + |1: ; subsd xmm0, xmm1; jmp <7 + |2: ; cmp foldop, 3; je >1; ja >2 + | mulsd xmm0, xmm1; jmp <7 + |1: ; divsd xmm0, xmm1; jmp <7 + |2: ; cmp foldop, 5 + | je >1; ja >2 + | call ->vm_mod; jmp <7 + |1: ; pop edx; call ->vm_pow; push edx; jmp <7 // Writes to scratch area. + |2: ; cmp foldop, 7; je >1; ja >2 + | sseconst_sign xmm1, RDa; xorps xmm0, xmm1; jmp <7 + |1: ; sseconst_abs xmm1, RDa; andps xmm0, xmm1; jmp <7 + |2: ; cmp foldop, 9; ja >2 + | fld qword [esp+4] // Reload from stack + | fld qword [esp+12] + | je >1 + | fpatan; ret + |1: ; fxch; fscale; fpop1; ret + |2: ; cmp foldop, 11; je >1; ja >9 + | minsd xmm0, xmm1; jmp <7 + |1: ; maxsd xmm0, xmm1; jmp <7 + |9: ; int3 // Bad op. + | + |.endif + } else { + | mov eax, [esp+20] + | fld qword [esp+4] + | fld qword [esp+12] + | cmp eax, 1; je >1; ja >2 + | faddp st1; ret + |1: ; fsubp st1; ret + |2: ; cmp eax, 3; je >1; ja >2 + | fmulp st1; ret + |1: ; fdivp st1; ret + |2: ; cmp eax, 5; jb ->vm_mod; je ->vm_pow + | cmp eax, 7; je >1; ja >2 + | fpop; fchs; ret + |1: ; fpop; fabs; ret + |2: ; cmp eax, 9; je >1; ja >2 + | fpatan; ret + |1: ; fxch; fscale; fpop1; ret + |2: ; cmp eax, 11; je >1; ja >9 + ||if (cmov) { + | fucomi st1; fcmovnbe st1; fpop1; ret + |1: ; fucomi st1; fcmovbe st1; fpop1; ret + ||} else { + | fucom st1; fnstsw ax; test ah, 1; jz >2; fxch; 2: ; fpop; ret + |1: ; fucom st1; fnstsw ax; test ah, 1; jnz >2; fxch; 2: ; fpop; ret + ||} + |9: ; int3 // Bad op. + } + | + |//----------------------------------------------------------------------- + |//-- Miscellaneous functions -------------------------------------------- + |//----------------------------------------------------------------------- + | + |// int lj_vm_cpuid(uint32_t f, uint32_t res[4]) + |->vm_cpuid: + |.if X64 + | mov eax, CARG1d + | .if X64WIN; push rsi; mov rsi, CARG2; .endif + | push rbx + | cpuid + | mov [rsi], eax + | mov [rsi+4], ebx + | mov [rsi+8], ecx + | mov [rsi+12], edx + | pop rbx + | .if X64WIN; pop rsi; .endif + | ret + |.else + | pushfd + | pop edx + | mov ecx, edx + | xor edx, 0x00200000 // Toggle ID bit in flags. + | push edx + | popfd + | pushfd + | pop edx + | xor eax, eax // Zero means no features supported. + | cmp ecx, edx + | jz >1 // No ID toggle means no CPUID support. + | mov eax, [esp+4] // Argument 1 is function number. + | push edi + | push ebx + | cpuid + | mov edi, [esp+16] // Argument 2 is result area. + | mov [edi], eax + | mov [edi+4], ebx + | mov [edi+8], ecx + | mov [edi+12], edx + | pop ebx + | pop edi + |1: + | ret + |.endif + | + |//----------------------------------------------------------------------- + |//-- Assertions --------------------------------------------------------- + |//----------------------------------------------------------------------- + | + |->assert_bad_for_arg_type: +#ifdef LUA_USE_ASSERT + | int3 +#endif + | int3 + | + |//----------------------------------------------------------------------- + |//-- FFI helper functions ----------------------------------------------- + |//----------------------------------------------------------------------- + | + |// Handler for callback functions. Callback slot number in ah/al. + |->vm_ffi_callback: +#if LJ_HASFFI + |.type CTSTATE, CTState, PC + |.if not X64 + | sub esp, 16 // Leave room for SAVE_ERRF etc. + |.endif + | saveregs_ // ebp/rbp already saved. ebp now holds global_State *. + | lea DISPATCH, [ebp+GG_G2DISP] + | mov CTSTATE, GL:ebp->ctype_state + | movzx eax, ax + | mov CTSTATE->cb.slot, eax + |.if X64 + | mov CTSTATE->cb.gpr[0], CARG1 + | mov CTSTATE->cb.gpr[1], CARG2 + | mov CTSTATE->cb.gpr[2], CARG3 + | mov CTSTATE->cb.gpr[3], CARG4 + | movsd qword CTSTATE->cb.fpr[0], xmm0 + | movsd qword CTSTATE->cb.fpr[1], xmm1 + | movsd qword CTSTATE->cb.fpr[2], xmm2 + | movsd qword CTSTATE->cb.fpr[3], xmm3 + |.if X64WIN + | lea rax, [rsp+CFRAME_SIZE+4*8] + |.else + | lea rax, [rsp+CFRAME_SIZE] + | mov CTSTATE->cb.gpr[4], CARG5 + | mov CTSTATE->cb.gpr[5], CARG6 + | movsd qword CTSTATE->cb.fpr[4], xmm4 + | movsd qword CTSTATE->cb.fpr[5], xmm5 + | movsd qword CTSTATE->cb.fpr[6], xmm6 + | movsd qword CTSTATE->cb.fpr[7], xmm7 + |.endif + | mov CTSTATE->cb.stack, rax + | mov CARG2, rsp + |.else + | lea eax, [esp+CFRAME_SIZE+16] + | mov CTSTATE->cb.gpr[0], FCARG1 + | mov CTSTATE->cb.gpr[1], FCARG2 + | mov CTSTATE->cb.stack, eax + | mov FCARG1, [esp+CFRAME_SIZE+12] // Move around misplaced retaddr/ebp. + | mov FCARG2, [esp+CFRAME_SIZE+8] + | mov SAVE_RET, FCARG1 + | mov SAVE_R4, FCARG2 + | mov FCARG2, esp + |.endif + | mov SAVE_PC, CTSTATE // Any value outside of bytecode is ok. + | mov FCARG1, CTSTATE + | call extern lj_ccallback_enter@8 // (CTState *cts, void *cf) + | // lua_State * returned in eax (RD). + | set_vmstate INTERP + | mov BASE, L:RD->base + | mov RD, L:RD->top + | sub RD, BASE + | mov LFUNC:RB, [BASE-8] + | shr RD, 3 + | add RD, 1 + | ins_callt +#endif + | + |->cont_ffi_callback: // Return from FFI callback. +#if LJ_HASFFI + | mov L:RA, SAVE_L + | mov CTSTATE, [DISPATCH+DISPATCH_GL(ctype_state)] + | mov aword CTSTATE->L, L:RAa + | mov L:RA->base, BASE + | mov L:RA->top, RB + | mov FCARG1, CTSTATE + | mov FCARG2, RC + | call extern lj_ccallback_leave@8 // (CTState *cts, TValue *o) + |.if X64 + | mov rax, CTSTATE->cb.gpr[0] + | movsd xmm0, qword CTSTATE->cb.fpr[0] + | jmp ->vm_leave_unw + |.else + | mov L:RB, SAVE_L + | mov eax, CTSTATE->cb.gpr[0] + | mov edx, CTSTATE->cb.gpr[1] + | cmp dword CTSTATE->cb.gpr[2], 1 + | jb >7 + | je >6 + | fld qword CTSTATE->cb.fpr[0].d + | jmp >7 + |6: + | fld dword CTSTATE->cb.fpr[0].f + |7: + | mov ecx, L:RB->top + | movzx ecx, word [ecx+6] // Get stack adjustment and copy up. + | mov SAVE_L, ecx // Must be one slot above SAVE_RET + | restoreregs + | pop ecx // Move return addr from SAVE_RET. + | add esp, [esp] // Adjust stack. + | add esp, 16 + | push ecx + | ret + |.endif +#endif + | + |->vm_ffi_call@4: // Call C function via FFI. + | // Caveat: needs special frame unwinding, see below. +#if LJ_HASFFI + |.if X64 + | .type CCSTATE, CCallState, rbx + | push rbp; mov rbp, rsp; push rbx; mov CCSTATE, CARG1 + |.else + | .type CCSTATE, CCallState, ebx + | push ebp; mov ebp, esp; push ebx; mov CCSTATE, FCARG1 + |.endif + | + | // Readjust stack. + |.if X64 + | mov eax, CCSTATE->spadj + | sub rsp, rax + |.else + | sub esp, CCSTATE->spadj +#if LJ_TARGET_WINDOWS + | mov CCSTATE->spadj, esp +#endif + |.endif + | + | // Copy stack slots. + | movzx ecx, byte CCSTATE->nsp + | sub ecx, 1 + | js >2 + |1: + |.if X64 + | mov rax, [CCSTATE+rcx*8+offsetof(CCallState, stack)] + | mov [rsp+rcx*8+CCALL_SPS_EXTRA*8], rax + |.else + | mov eax, [CCSTATE+ecx*4+offsetof(CCallState, stack)] + | mov [esp+ecx*4], eax + |.endif + | sub ecx, 1 + | jns <1 + |2: + | + |.if X64 + | movzx eax, byte CCSTATE->nfpr + | mov CARG1, CCSTATE->gpr[0] + | mov CARG2, CCSTATE->gpr[1] + | mov CARG3, CCSTATE->gpr[2] + | mov CARG4, CCSTATE->gpr[3] + |.if not X64WIN + | mov CARG5, CCSTATE->gpr[4] + | mov CARG6, CCSTATE->gpr[5] + |.endif + | test eax, eax; jz >5 + | movaps xmm0, CCSTATE->fpr[0] + | movaps xmm1, CCSTATE->fpr[1] + | movaps xmm2, CCSTATE->fpr[2] + | movaps xmm3, CCSTATE->fpr[3] + |.if not X64WIN + | cmp eax, 4; jbe >5 + | movaps xmm4, CCSTATE->fpr[4] + | movaps xmm5, CCSTATE->fpr[5] + | movaps xmm6, CCSTATE->fpr[6] + | movaps xmm7, CCSTATE->fpr[7] + |.endif + |5: + |.else + | mov FCARG1, CCSTATE->gpr[0] + | mov FCARG2, CCSTATE->gpr[1] + |.endif + | + | call aword CCSTATE->func + | + |.if X64 + | mov CCSTATE->gpr[0], rax + | movaps CCSTATE->fpr[0], xmm0 + |.if not X64WIN + | mov CCSTATE->gpr[1], rdx + | movaps CCSTATE->fpr[1], xmm1 + |.endif + |.else + | mov CCSTATE->gpr[0], eax + | mov CCSTATE->gpr[1], edx + | cmp byte CCSTATE->resx87, 1 + | jb >7 + | je >6 + | fstp qword CCSTATE->fpr[0].d[0] + | jmp >7 + |6: + | fstp dword CCSTATE->fpr[0].f[0] + |7: +#if LJ_TARGET_WINDOWS + | sub CCSTATE->spadj, esp +#endif + |.endif + | + |.if X64 + | mov rbx, [rbp-8]; leave; ret + |.else + | mov ebx, [ebp-4]; leave; ret + |.endif +#endif + |// Note: vm_ffi_call must be the last function in this object file! + | + |//----------------------------------------------------------------------- +} + +/* Generate the code for a single instruction. */ +static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse) +{ + int vk = 0; + |// Note: aligning all instructions does not pay off. + |=>defop: + + switch (op) { + + /* -- Comparison ops ---------------------------------------------------- */ + + /* Remember: all ops branch for a true comparison, fall through otherwise. */ + + |.macro jmp_comp, lt, ge, le, gt, target + ||switch (op) { + ||case BC_ISLT: + | lt target + ||break; + ||case BC_ISGE: + | ge target + ||break; + ||case BC_ISLE: + | le target + ||break; + ||case BC_ISGT: + | gt target + ||break; + ||default: break; /* Shut up GCC. */ + ||} + |.endmacro + + case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: + | // RA = src1, RD = src2, JMP with RD = target + | ins_AD + if (LJ_DUALNUM) { + | checkint RA, >7 + | checkint RD, >8 + | mov RB, dword [BASE+RA*8] + | add PC, 4 + | cmp RB, dword [BASE+RD*8] + | jmp_comp jge, jl, jg, jle, >9 + |6: + | movzx RD, PC_RD + | branchPC RD + |9: + | ins_next + | + |7: // RA is not an integer. + | ja ->vmeta_comp + | // RA is a number. + | cmp dword [BASE+RD*8+4], LJ_TISNUM; jb >1; jne ->vmeta_comp + | // RA is a number, RD is an integer. + if (sse) { + | cvtsi2sd xmm0, dword [BASE+RD*8] + | jmp >2 + } else { + | fld qword [BASE+RA*8] + | fild dword [BASE+RD*8] + | jmp >3 + } + | + |8: // RA is an integer, RD is not an integer. + | ja ->vmeta_comp + | // RA is an integer, RD is a number. + if (sse) { + | cvtsi2sd xmm1, dword [BASE+RA*8] + | movsd xmm0, qword [BASE+RD*8] + | add PC, 4 + | ucomisd xmm0, xmm1 + | jmp_comp jbe, ja, jb, jae, <9 + | jmp <6 + } else { + | fild dword [BASE+RA*8] + | jmp >2 + } + } else { + | checknum RA, ->vmeta_comp + | checknum RD, ->vmeta_comp + } + if (sse) { + |1: + | movsd xmm0, qword [BASE+RD*8] + |2: + | add PC, 4 + | ucomisd xmm0, qword [BASE+RA*8] + |3: + } else { + |1: + | fld qword [BASE+RA*8] // Reverse order, i.e like cmp D, A. + |2: + | fld qword [BASE+RD*8] + |3: + | add PC, 4 + | fcomparepp // eax (RD) modified! + } + | // Unordered: all of ZF CF PF set, ordered: PF clear. + | // To preserve NaN semantics GE/GT branch on unordered, but LT/LE don't. + if (LJ_DUALNUM) { + | jmp_comp jbe, ja, jb, jae, <9 + | jmp <6 + } else { + | jmp_comp jbe, ja, jb, jae, >1 + | movzx RD, PC_RD + | branchPC RD + |1: + | ins_next + } + break; + + case BC_ISEQV: case BC_ISNEV: + vk = op == BC_ISEQV; + | ins_AD // RA = src1, RD = src2, JMP with RD = target + | mov RB, [BASE+RD*8+4] + | add PC, 4 + if (LJ_DUALNUM) { + | cmp RB, LJ_TISNUM; jne >7 + | checkint RA, >8 + | mov RB, dword [BASE+RD*8] + | cmp RB, dword [BASE+RA*8] + if (vk) { + | jne >9 + } else { + | je >9 + } + | movzx RD, PC_RD + | branchPC RD + |9: + | ins_next + | + |7: // RD is not an integer. + | ja >5 + | // RD is a number. + | cmp dword [BASE+RA*8+4], LJ_TISNUM; jb >1; jne >5 + | // RD is a number, RA is an integer. + if (sse) { + | cvtsi2sd xmm0, dword [BASE+RA*8] + } else { + | fild dword [BASE+RA*8] + } + | jmp >2 + | + |8: // RD is an integer, RA is not an integer. + | ja >5 + | // RD is an integer, RA is a number. + if (sse) { + | cvtsi2sd xmm0, dword [BASE+RD*8] + | ucomisd xmm0, qword [BASE+RA*8] + } else { + | fild dword [BASE+RD*8] + | fld qword [BASE+RA*8] + } + | jmp >4 + | + } else { + | cmp RB, LJ_TISNUM; jae >5 + | checknum RA, >5 + } + if (sse) { + |1: + | movsd xmm0, qword [BASE+RA*8] + |2: + | ucomisd xmm0, qword [BASE+RD*8] + |4: + } else { + |1: + | fld qword [BASE+RA*8] + |2: + | fld qword [BASE+RD*8] + |4: + | fcomparepp // eax (RD) modified! + } + iseqne_fp: + if (vk) { + | jp >2 // Unordered means not equal. + | jne >2 + } else { + | jp >2 // Unordered means not equal. + | je >1 + } + iseqne_end: + if (vk) { + |1: // EQ: Branch to the target. + | movzx RD, PC_RD + | branchPC RD + |2: // NE: Fallthrough to next instruction. + if (!LJ_HASFFI) { + |3: + } + } else { + if (!LJ_HASFFI) { + |3: + } + |2: // NE: Branch to the target. + | movzx RD, PC_RD + | branchPC RD + |1: // EQ: Fallthrough to next instruction. + } + if (LJ_DUALNUM && (op == BC_ISEQV || op == BC_ISNEV || + op == BC_ISEQN || op == BC_ISNEN)) { + | jmp <9 + } else { + | ins_next + } + | + if (op == BC_ISEQV || op == BC_ISNEV) { + |5: // Either or both types are not numbers. + if (LJ_HASFFI) { + | cmp RB, LJ_TCDATA; je ->vmeta_equal_cd + | checktp RA, LJ_TCDATA; je ->vmeta_equal_cd + } + | checktp RA, RB // Compare types. + | jne <2 // Not the same type? + | cmp RB, LJ_TISPRI + | jae <1 // Same type and primitive type? + | + | // Same types and not a primitive type. Compare GCobj or pvalue. + | mov RA, [BASE+RA*8] + | mov RD, [BASE+RD*8] + | cmp RA, RD + | je <1 // Same GCobjs or pvalues? + | cmp RB, LJ_TISTABUD + | ja <2 // Different objects and not table/ud? + |.if X64 + | cmp RB, LJ_TUDATA // And not 64 bit lightuserdata. + | jb <2 + |.endif + | + | // Different tables or userdatas. Need to check __eq metamethod. + | // Field metatable must be at same offset for GCtab and GCudata! + | mov TAB:RB, TAB:RA->metatable + | test TAB:RB, TAB:RB + | jz <2 // No metatable? + | test byte TAB:RB->nomm, 1<vmeta_equal // Handle __eq metamethod. + } else if (LJ_HASFFI) { + |3: + | cmp RB, LJ_TCDATA + if (LJ_DUALNUM && vk) { + | jne <9 + } else { + | jne <2 + } + | jmp ->vmeta_equal_cd + } + break; + case BC_ISEQS: case BC_ISNES: + vk = op == BC_ISEQS; + | ins_AND // RA = src, RD = str const, JMP with RD = target + | mov RB, [BASE+RA*8+4] + | add PC, 4 + | cmp RB, LJ_TSTR; jne >3 + | mov RA, [BASE+RA*8] + | cmp RA, [KBASE+RD*4] + iseqne_test: + if (vk) { + | jne >2 + } else { + | je >1 + } + goto iseqne_end; + case BC_ISEQN: case BC_ISNEN: + vk = op == BC_ISEQN; + | ins_AD // RA = src, RD = num const, JMP with RD = target + | mov RB, [BASE+RA*8+4] + | add PC, 4 + if (LJ_DUALNUM) { + | cmp RB, LJ_TISNUM; jne >7 + | cmp dword [KBASE+RD*8+4], LJ_TISNUM; jne >8 + | mov RB, dword [KBASE+RD*8] + | cmp RB, dword [BASE+RA*8] + if (vk) { + | jne >9 + } else { + | je >9 + } + | movzx RD, PC_RD + | branchPC RD + |9: + | ins_next + | + |7: // RA is not an integer. + | ja >3 + | // RA is a number. + | cmp dword [KBASE+RD*8+4], LJ_TISNUM; jb >1 + | // RA is a number, RD is an integer. + if (sse) { + | cvtsi2sd xmm0, dword [KBASE+RD*8] + } else { + | fild dword [KBASE+RD*8] + } + | jmp >2 + | + |8: // RA is an integer, RD is a number. + if (sse) { + | cvtsi2sd xmm0, dword [BASE+RA*8] + | ucomisd xmm0, qword [KBASE+RD*8] + } else { + | fild dword [BASE+RA*8] + | fld qword [KBASE+RD*8] + } + | jmp >4 + } else { + | cmp RB, LJ_TISNUM; jae >3 + } + if (sse) { + |1: + | movsd xmm0, qword [KBASE+RD*8] + |2: + | ucomisd xmm0, qword [BASE+RA*8] + |4: + } else { + |1: + | fld qword [KBASE+RD*8] + |2: + | fld qword [BASE+RA*8] + |4: + | fcomparepp // eax (RD) modified! + } + goto iseqne_fp; + case BC_ISEQP: case BC_ISNEP: + vk = op == BC_ISEQP; + | ins_AND // RA = src, RD = primitive type (~), JMP with RD = target + | mov RB, [BASE+RA*8+4] + | add PC, 4 + | cmp RB, RD + if (!LJ_HASFFI) goto iseqne_test; + if (vk) { + | jne >3 + | movzx RD, PC_RD + | branchPC RD + |2: + | ins_next + |3: + | cmp RB, LJ_TCDATA; jne <2 + | jmp ->vmeta_equal_cd + } else { + | je >2 + | cmp RB, LJ_TCDATA; je ->vmeta_equal_cd + | movzx RD, PC_RD + | branchPC RD + |2: + | ins_next + } + break; + + /* -- Unary test and copy ops ------------------------------------------- */ + + case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: + | ins_AD // RA = dst or unused, RD = src, JMP with RD = target + | mov RB, [BASE+RD*8+4] + | add PC, 4 + | cmp RB, LJ_TISTRUECOND + if (op == BC_IST || op == BC_ISTC) { + | jae >1 + } else { + | jb >1 + } + if (op == BC_ISTC || op == BC_ISFC) { + | mov [BASE+RA*8+4], RB + | mov RB, [BASE+RD*8] + | mov [BASE+RA*8], RB + } + | movzx RD, PC_RD + | branchPC RD + |1: // Fallthrough to the next instruction. + | ins_next + break; + + /* -- Unary ops --------------------------------------------------------- */ + + case BC_MOV: + | ins_AD // RA = dst, RD = src + |.if X64 + | mov RBa, [BASE+RD*8] + | mov [BASE+RA*8], RBa + |.else + | mov RB, [BASE+RD*8+4] + | mov RD, [BASE+RD*8] + | mov [BASE+RA*8+4], RB + | mov [BASE+RA*8], RD + |.endif + | ins_next_ + break; + case BC_NOT: + | ins_AD // RA = dst, RD = src + | xor RB, RB + | checktp RD, LJ_TISTRUECOND + | adc RB, LJ_TTRUE + | mov [BASE+RA*8+4], RB + | ins_next + break; + case BC_UNM: + | ins_AD // RA = dst, RD = src + if (LJ_DUALNUM) { + | checkint RD, >5 + | mov RB, [BASE+RD*8] + | neg RB + | jo >4 + | mov dword [BASE+RA*8+4], LJ_TISNUM + | mov dword [BASE+RA*8], RB + |9: + | ins_next + |4: + | mov dword [BASE+RA*8+4], 0x41e00000 // 2^31. + | mov dword [BASE+RA*8], 0 + | jmp <9 + |5: + | ja ->vmeta_unm + } else { + | checknum RD, ->vmeta_unm + } + if (sse) { + | movsd xmm0, qword [BASE+RD*8] + | sseconst_sign xmm1, RDa + | xorps xmm0, xmm1 + | movsd qword [BASE+RA*8], xmm0 + } else { + | fld qword [BASE+RD*8] + | fchs + | fstp qword [BASE+RA*8] + } + if (LJ_DUALNUM) { + | jmp <9 + } else { + | ins_next + } + break; + case BC_LEN: + | ins_AD // RA = dst, RD = src + | checkstr RD, >2 + | mov STR:RD, [BASE+RD*8] + if (LJ_DUALNUM) { + | mov RD, dword STR:RD->len + |1: + | mov dword [BASE+RA*8+4], LJ_TISNUM + | mov dword [BASE+RA*8], RD + } else if (sse) { + | xorps xmm0, xmm0 + | cvtsi2sd xmm0, dword STR:RD->len + |1: + | movsd qword [BASE+RA*8], xmm0 + } else { + | fild dword STR:RD->len + |1: + | fstp qword [BASE+RA*8] + } + | ins_next + |2: + | checktab RD, ->vmeta_len + | mov TAB:FCARG1, [BASE+RD*8] +#ifdef LUAJIT_ENABLE_LUA52COMPAT + | mov TAB:RB, TAB:FCARG1->metatable + | cmp TAB:RB, 0 + | jnz >9 + |3: +#endif + |->BC_LEN_Z: + | mov RB, BASE // Save BASE. + | call extern lj_tab_len@4 // (GCtab *t) + | // Length of table returned in eax (RD). + if (LJ_DUALNUM) { + | // Nothing to do. + } else if (sse) { + | cvtsi2sd xmm0, RD + } else { + |.if not X64 + | mov ARG1, RD + | fild ARG1 + |.endif + } + | mov BASE, RB // Restore BASE. + | movzx RA, PC_RA + | jmp <1 +#ifdef LUAJIT_ENABLE_LUA52COMPAT + |9: // Check for __len. + | test byte TAB:RB->nomm, 1<vmeta_len // 'no __len' flag NOT set: check. +#endif + break; + + /* -- Binary ops -------------------------------------------------------- */ + + |.macro ins_arithpre, x87ins, sseins, ssereg + | ins_ABC + ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); + ||switch (vk) { + ||case 0: + | checknum RB, ->vmeta_arith_vn + ||if (LJ_DUALNUM) { + | cmp dword [KBASE+RC*8+4], LJ_TISNUM; jae ->vmeta_arith_vn + ||} + ||if (sse) { + | movsd xmm0, qword [BASE+RB*8] + | sseins ssereg, qword [KBASE+RC*8] + ||} else { + | fld qword [BASE+RB*8] + | x87ins qword [KBASE+RC*8] + ||} + || break; + ||case 1: + | checknum RB, ->vmeta_arith_nv + ||if (LJ_DUALNUM) { + | cmp dword [KBASE+RC*8+4], LJ_TISNUM; jae ->vmeta_arith_nv + ||} + ||if (sse) { + | movsd xmm0, qword [KBASE+RC*8] + | sseins ssereg, qword [BASE+RB*8] + ||} else { + | fld qword [KBASE+RC*8] + | x87ins qword [BASE+RB*8] + ||} + || break; + ||default: + | checknum RB, ->vmeta_arith_vv + | checknum RC, ->vmeta_arith_vv + ||if (sse) { + | movsd xmm0, qword [BASE+RB*8] + | sseins ssereg, qword [BASE+RC*8] + ||} else { + | fld qword [BASE+RB*8] + | x87ins qword [BASE+RC*8] + ||} + || break; + ||} + |.endmacro + | + |.macro ins_arithdn, intins + | ins_ABC + ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN); + ||switch (vk) { + ||case 0: + | checkint RB, ->vmeta_arith_vn + | cmp dword [KBASE+RC*8+4], LJ_TISNUM; jne ->vmeta_arith_vn + | mov RB, [BASE+RB*8] + | intins RB, [KBASE+RC*8]; jo ->vmeta_arith_vno + || break; + ||case 1: + | checkint RB, ->vmeta_arith_nv + | cmp dword [KBASE+RC*8+4], LJ_TISNUM; jne ->vmeta_arith_nv + | mov RC, [KBASE+RC*8] + | intins RC, [BASE+RB*8]; jo ->vmeta_arith_nvo + || break; + ||default: + | checkint RB, ->vmeta_arith_vv + | checkint RC, ->vmeta_arith_vv + | mov RB, [BASE+RB*8] + | intins RB, [BASE+RC*8]; jo ->vmeta_arith_vvo + || break; + ||} + | mov dword [BASE+RA*8+4], LJ_TISNUM + ||if (vk == 1) { + | mov dword [BASE+RA*8], RC + ||} else { + | mov dword [BASE+RA*8], RB + ||} + | ins_next + |.endmacro + | + |.macro ins_arithpost + ||if (sse) { + | movsd qword [BASE+RA*8], xmm0 + ||} else { + | fstp qword [BASE+RA*8] + ||} + |.endmacro + | + |.macro ins_arith, x87ins, sseins + | ins_arithpre x87ins, sseins, xmm0 + | ins_arithpost + | ins_next + |.endmacro + | + |.macro ins_arith, intins, x87ins, sseins + ||if (LJ_DUALNUM) { + | ins_arithdn intins + ||} else { + | ins_arith, x87ins, sseins + ||} + |.endmacro + + | // RA = dst, RB = src1 or num const, RC = src2 or num const + case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: + | ins_arith add, fadd, addsd + break; + case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: + | ins_arith sub, fsub, subsd + break; + case BC_MULVN: case BC_MULNV: case BC_MULVV: + | ins_arith imul, fmul, mulsd + break; + case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: + | ins_arith fdiv, divsd + break; + case BC_MODVN: + | ins_arithpre fld, movsd, xmm1 + |->BC_MODVN_Z: + | call ->vm_mod + | ins_arithpost + | ins_next + break; + case BC_MODNV: case BC_MODVV: + | ins_arithpre fld, movsd, xmm1 + | jmp ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway. + break; + case BC_POW: + | ins_arithpre fld, movsd, xmm1 + | call ->vm_pow + | ins_arithpost + | ins_next + break; + + case BC_CAT: + | ins_ABC // RA = dst, RB = src_start, RC = src_end + |.if X64 + | mov L:CARG1d, SAVE_L + | mov L:CARG1d->base, BASE + | lea CARG2d, [BASE+RC*8] + | mov CARG3d, RC + | sub CARG3d, RB + |->BC_CAT_Z: + | mov L:RB, L:CARG1d + |.else + | lea RA, [BASE+RC*8] + | sub RC, RB + | mov ARG2, RA + | mov ARG3, RC + |->BC_CAT_Z: + | mov L:RB, SAVE_L + | mov ARG1, L:RB + | mov L:RB->base, BASE + |.endif + | mov SAVE_PC, PC + | call extern lj_meta_cat // (lua_State *L, TValue *top, int left) + | // NULL (finished) or TValue * (metamethod) returned in eax (RC). + | mov BASE, L:RB->base + | test RC, RC + | jnz ->vmeta_binop + | movzx RB, PC_RB // Copy result to Stk[RA] from Stk[RB]. + | movzx RA, PC_RA + |.if X64 + | mov RCa, [BASE+RB*8] + | mov [BASE+RA*8], RCa + |.else + | mov RC, [BASE+RB*8+4] + | mov RB, [BASE+RB*8] + | mov [BASE+RA*8+4], RC + | mov [BASE+RA*8], RB + |.endif + | ins_next + break; + + /* -- Constant ops ------------------------------------------------------ */ + + case BC_KSTR: + | ins_AND // RA = dst, RD = str const (~) + | mov RD, [KBASE+RD*4] + | mov dword [BASE+RA*8+4], LJ_TSTR + | mov [BASE+RA*8], RD + | ins_next + break; + case BC_KCDATA: +#if LJ_HASFFI + | ins_AND // RA = dst, RD = cdata const (~) + | mov RD, [KBASE+RD*4] + | mov dword [BASE+RA*8+4], LJ_TCDATA + | mov [BASE+RA*8], RD + | ins_next +#endif + break; + case BC_KSHORT: + | ins_AD // RA = dst, RD = signed int16 literal + if (LJ_DUALNUM) { + | movsx RD, RDW + | mov dword [BASE+RA*8+4], LJ_TISNUM + | mov dword [BASE+RA*8], RD + } else if (sse) { + | movsx RD, RDW // Sign-extend literal. + | cvtsi2sd xmm0, RD + | movsd qword [BASE+RA*8], xmm0 + } else { + | fild PC_RD // Refetch signed RD from instruction. + | fstp qword [BASE+RA*8] + } + | ins_next + break; + case BC_KNUM: + | ins_AD // RA = dst, RD = num const + if (sse) { + | movsd xmm0, qword [KBASE+RD*8] + | movsd qword [BASE+RA*8], xmm0 + } else { + | fld qword [KBASE+RD*8] + | fstp qword [BASE+RA*8] + } + | ins_next + break; + case BC_KPRI: + | ins_AND // RA = dst, RD = primitive type (~) + | mov [BASE+RA*8+4], RD + | ins_next + break; + case BC_KNIL: + | ins_AD // RA = dst_start, RD = dst_end + | lea RA, [BASE+RA*8+12] + | lea RD, [BASE+RD*8+4] + | mov RB, LJ_TNIL + | mov [RA-8], RB // Sets minimum 2 slots. + |1: + | mov [RA], RB + | add RA, 8 + | cmp RA, RD + | jbe <1 + | ins_next + break; + + /* -- Upvalue and function ops ------------------------------------------ */ + + case BC_UGET: + | ins_AD // RA = dst, RD = upvalue # + | mov LFUNC:RB, [BASE-8] + | mov UPVAL:RB, [LFUNC:RB+RD*4+offsetof(GCfuncL, uvptr)] + | mov RB, UPVAL:RB->v + |.if X64 + | mov RDa, [RB] + | mov [BASE+RA*8], RDa + |.else + | mov RD, [RB+4] + | mov RB, [RB] + | mov [BASE+RA*8+4], RD + | mov [BASE+RA*8], RB + |.endif + | ins_next + break; + case BC_USETV: +#define TV2MARKOFS \ + ((int32_t)offsetof(GCupval, marked)-(int32_t)offsetof(GCupval, tv)) + | ins_AD // RA = upvalue #, RD = src + | mov LFUNC:RB, [BASE-8] + | mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)] + | cmp byte UPVAL:RB->closed, 0 + | mov RB, UPVAL:RB->v + | mov RA, [BASE+RD*8] + | mov RD, [BASE+RD*8+4] + | mov [RB], RA + | mov [RB+4], RD + | jz >1 + | // Check barrier for closed upvalue. + | test byte [RB+TV2MARKOFS], LJ_GC_BLACK // isblack(uv) + | jnz >2 + |1: + | ins_next + | + |2: // Upvalue is black. Check if new value is collectable and white. + | sub RD, LJ_TISGCV + | cmp RD, LJ_TISNUM - LJ_TISGCV // tvisgcv(v) + | jbe <1 + | test byte GCOBJ:RA->gch.marked, LJ_GC_WHITES // iswhite(v) + | jz <1 + | // Crossed a write barrier. Move the barrier forward. + |.if X64 and not X64WIN + | mov FCARG2, RB + | mov RB, BASE // Save BASE. + |.else + | xchg FCARG2, RB // Save BASE (FCARG2 == BASE). + |.endif + | lea GL:FCARG1, [DISPATCH+GG_DISP2G] + | call extern lj_gc_barrieruv@8 // (global_State *g, TValue *tv) + | mov BASE, RB // Restore BASE. + | jmp <1 + break; +#undef TV2MARKOFS + case BC_USETS: + | ins_AND // RA = upvalue #, RD = str const (~) + | mov LFUNC:RB, [BASE-8] + | mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)] + | mov GCOBJ:RA, [KBASE+RD*4] + | mov RD, UPVAL:RB->v + | mov [RD], GCOBJ:RA + | mov dword [RD+4], LJ_TSTR + | test byte UPVAL:RB->marked, LJ_GC_BLACK // isblack(uv) + | jnz >2 + |1: + | ins_next + | + |2: // Check if string is white and ensure upvalue is closed. + | test byte GCOBJ:RA->gch.marked, LJ_GC_WHITES // iswhite(str) + | jz <1 + | cmp byte UPVAL:RB->closed, 0 + | jz <1 + | // Crossed a write barrier. Move the barrier forward. + | mov RB, BASE // Save BASE (FCARG2 == BASE). + | mov FCARG2, RD + | lea GL:FCARG1, [DISPATCH+GG_DISP2G] + | call extern lj_gc_barrieruv@8 // (global_State *g, TValue *tv) + | mov BASE, RB // Restore BASE. + | jmp <1 + break; + case BC_USETN: + | ins_AD // RA = upvalue #, RD = num const + | mov LFUNC:RB, [BASE-8] + if (sse) { + | movsd xmm0, qword [KBASE+RD*8] + } else { + | fld qword [KBASE+RD*8] + } + | mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)] + | mov RA, UPVAL:RB->v + if (sse) { + | movsd qword [RA], xmm0 + } else { + | fstp qword [RA] + } + | ins_next + break; + case BC_USETP: + | ins_AND // RA = upvalue #, RD = primitive type (~) + | mov LFUNC:RB, [BASE-8] + | mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)] + | mov RA, UPVAL:RB->v + | mov [RA+4], RD + | ins_next + break; + case BC_UCLO: + | ins_AD // RA = level, RD = target + | branchPC RD // Do this first to free RD. + | mov L:RB, SAVE_L + | cmp dword L:RB->openupval, 0 + | je >1 + | mov L:RB->base, BASE + | lea FCARG2, [BASE+RA*8] // Caveat: FCARG2 == BASE + | mov L:FCARG1, L:RB // Caveat: FCARG1 == RA + | call extern lj_func_closeuv@8 // (lua_State *L, TValue *level) + | mov BASE, L:RB->base + |1: + | ins_next + break; + + case BC_FNEW: + | ins_AND // RA = dst, RD = proto const (~) (holding function prototype) + |.if X64 + | mov L:RB, SAVE_L + | mov L:RB->base, BASE // Caveat: CARG2d/CARG3d may be BASE. + | mov CARG3d, [BASE-8] + | mov CARG2d, [KBASE+RD*4] // Fetch GCproto *. + | mov CARG1d, L:RB + |.else + | mov LFUNC:RA, [BASE-8] + | mov PROTO:RD, [KBASE+RD*4] // Fetch GCproto *. + | mov L:RB, SAVE_L + | mov ARG3, LFUNC:RA + | mov ARG2, PROTO:RD + | mov ARG1, L:RB + | mov L:RB->base, BASE + |.endif + | mov SAVE_PC, PC + | // (lua_State *L, GCproto *pt, GCfuncL *parent) + | call extern lj_func_newL_gc + | // GCfuncL * returned in eax (RC). + | mov BASE, L:RB->base + | movzx RA, PC_RA + | mov [BASE+RA*8], LFUNC:RC + | mov dword [BASE+RA*8+4], LJ_TFUNC + | ins_next + break; + + /* -- Table ops --------------------------------------------------------- */ + + case BC_TNEW: + | ins_AD // RA = dst, RD = hbits|asize + | mov L:RB, SAVE_L + | mov L:RB->base, BASE + | mov RA, [DISPATCH+DISPATCH_GL(gc.total)] + | cmp RA, [DISPATCH+DISPATCH_GL(gc.threshold)] + | mov SAVE_PC, PC + | jae >5 + |1: + |.if X64 + | mov CARG3d, RD + | and RD, 0x7ff + | shr CARG3d, 11 + |.else + | mov RA, RD + | and RD, 0x7ff + | shr RA, 11 + | mov ARG3, RA + |.endif + | cmp RD, 0x7ff + | je >3 + |2: + |.if X64 + | mov L:CARG1d, L:RB + | mov CARG2d, RD + |.else + | mov ARG1, L:RB + | mov ARG2, RD + |.endif + | call extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits) + | // Table * returned in eax (RC). + | mov BASE, L:RB->base + | movzx RA, PC_RA + | mov [BASE+RA*8], TAB:RC + | mov dword [BASE+RA*8+4], LJ_TTAB + | ins_next + |3: // Turn 0x7ff into 0x801. + | mov RD, 0x801 + | jmp <2 + |5: + | mov L:FCARG1, L:RB + | call extern lj_gc_step_fixtop@4 // (lua_State *L) + | movzx RD, PC_RD + | jmp <1 + break; + case BC_TDUP: + | ins_AND // RA = dst, RD = table const (~) (holding template table) + | mov L:RB, SAVE_L + | mov RA, [DISPATCH+DISPATCH_GL(gc.total)] + | mov SAVE_PC, PC + | cmp RA, [DISPATCH+DISPATCH_GL(gc.threshold)] + | mov L:RB->base, BASE + | jae >3 + |2: + | mov TAB:FCARG2, [KBASE+RD*4] // Caveat: FCARG2 == BASE + | mov L:FCARG1, L:RB // Caveat: FCARG1 == RA + | call extern lj_tab_dup@8 // (lua_State *L, Table *kt) + | // Table * returned in eax (RC). + | mov BASE, L:RB->base + | movzx RA, PC_RA + | mov [BASE+RA*8], TAB:RC + | mov dword [BASE+RA*8+4], LJ_TTAB + | ins_next + |3: + | mov L:FCARG1, L:RB + | call extern lj_gc_step_fixtop@4 // (lua_State *L) + | movzx RD, PC_RD // Need to reload RD. + | not RDa + | jmp <2 + break; + + case BC_GGET: + | ins_AND // RA = dst, RD = str const (~) + | mov LFUNC:RB, [BASE-8] + | mov TAB:RB, LFUNC:RB->env + | mov STR:RC, [KBASE+RD*4] + | jmp ->BC_TGETS_Z + break; + case BC_GSET: + | ins_AND // RA = src, RD = str const (~) + | mov LFUNC:RB, [BASE-8] + | mov TAB:RB, LFUNC:RB->env + | mov STR:RC, [KBASE+RD*4] + | jmp ->BC_TSETS_Z + break; + + case BC_TGETV: + | ins_ABC // RA = dst, RB = table, RC = key + | checktab RB, ->vmeta_tgetv + | mov TAB:RB, [BASE+RB*8] + | + | // Integer key? + if (LJ_DUALNUM) { + | checkint RC, >5 + | mov RC, dword [BASE+RC*8] + } else { + | // Convert number to int and back and compare. + | checknum RC, >5 + if (sse) { + | movsd xmm0, qword [BASE+RC*8] + | cvtsd2si RC, xmm0 + | cvtsi2sd xmm1, RC + | ucomisd xmm0, xmm1 + } else { + |.if not X64 + | fld qword [BASE+RC*8] + | fist ARG1 + | fild ARG1 + | fcomparepp // eax (RC) modified! + | mov RC, ARG1 + |.endif + } + | jne ->vmeta_tgetv // Generic numeric key? Use fallback. + } + | cmp RC, TAB:RB->asize // Takes care of unordered, too. + | jae ->vmeta_tgetv // Not in array part? Use fallback. + | shl RC, 3 + | add RC, TAB:RB->array + | cmp dword [RC+4], LJ_TNIL // Avoid overwriting RB in fastpath. + | je >2 + | // Get array slot. + |.if X64 + | mov RBa, [RC] + | mov [BASE+RA*8], RBa + |.else + | mov RB, [RC] + | mov RC, [RC+4] + | mov [BASE+RA*8], RB + | mov [BASE+RA*8+4], RC + |.endif + |1: + | ins_next + | + |2: // Check for __index if table value is nil. + | cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath. + | jz >3 + | mov TAB:RA, TAB:RB->metatable + | test byte TAB:RA->nomm, 1<vmeta_tgetv // 'no __index' flag NOT set: check. + | movzx RA, PC_RA // Restore RA. + |3: + | mov dword [BASE+RA*8+4], LJ_TNIL + | jmp <1 + | + |5: // String key? + | checkstr RC, ->vmeta_tgetv + | mov STR:RC, [BASE+RC*8] + | jmp ->BC_TGETS_Z + break; + case BC_TGETS: + | ins_ABC // RA = dst, RB = table, RC = str const (~) + | not RCa + | mov STR:RC, [KBASE+RC*4] + | checktab RB, ->vmeta_tgets + | mov TAB:RB, [BASE+RB*8] + |->BC_TGETS_Z: // RB = GCtab *, RC = GCstr *, refetches PC_RA. + | mov RA, TAB:RB->hmask + | and RA, STR:RC->hash + | imul RA, #NODE + | add NODE:RA, TAB:RB->node + |1: + | cmp dword NODE:RA->key.it, LJ_TSTR + | jne >4 + | cmp dword NODE:RA->key.gcr, STR:RC + | jne >4 + | // Ok, key found. Assumes: offsetof(Node, val) == 0 + | cmp dword [RA+4], LJ_TNIL // Avoid overwriting RB in fastpath. + | je >5 // Key found, but nil value? + | movzx RC, PC_RA + | // Get node value. + |.if X64 + | mov RBa, [RA] + | mov [BASE+RC*8], RBa + |.else + | mov RB, [RA] + | mov RA, [RA+4] + | mov [BASE+RC*8], RB + | mov [BASE+RC*8+4], RA + |.endif + |2: + | ins_next + | + |3: + | movzx RC, PC_RA + | mov dword [BASE+RC*8+4], LJ_TNIL + | jmp <2 + | + |4: // Follow hash chain. + | mov NODE:RA, NODE:RA->next + | test NODE:RA, NODE:RA + | jnz <1 + | // End of hash chain: key not found, nil result. + | + |5: // Check for __index if table value is nil. + | mov TAB:RA, TAB:RB->metatable + | test TAB:RA, TAB:RA + | jz <3 // No metatable: done. + | test byte TAB:RA->nomm, 1<vmeta_tgets // Caveat: preserve STR:RC. + break; + case BC_TGETB: + | ins_ABC // RA = dst, RB = table, RC = byte literal + | checktab RB, ->vmeta_tgetb + | mov TAB:RB, [BASE+RB*8] + | cmp RC, TAB:RB->asize + | jae ->vmeta_tgetb + | shl RC, 3 + | add RC, TAB:RB->array + | cmp dword [RC+4], LJ_TNIL // Avoid overwriting RB in fastpath. + | je >2 + | // Get array slot. + |.if X64 + | mov RBa, [RC] + | mov [BASE+RA*8], RBa + |.else + | mov RB, [RC] + | mov RC, [RC+4] + | mov [BASE+RA*8], RB + | mov [BASE+RA*8+4], RC + |.endif + |1: + | ins_next + | + |2: // Check for __index if table value is nil. + | cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath. + | jz >3 + | mov TAB:RA, TAB:RB->metatable + | test byte TAB:RA->nomm, 1<vmeta_tgetb // 'no __index' flag NOT set: check. + | movzx RA, PC_RA // Restore RA. + |3: + | mov dword [BASE+RA*8+4], LJ_TNIL + | jmp <1 + break; + + case BC_TSETV: + | ins_ABC // RA = src, RB = table, RC = key + | checktab RB, ->vmeta_tsetv + | mov TAB:RB, [BASE+RB*8] + | + | // Integer key? + if (LJ_DUALNUM) { + | checkint RC, >5 + | mov RC, dword [BASE+RC*8] + } else { + | // Convert number to int and back and compare. + | checknum RC, >5 + if (sse) { + | movsd xmm0, qword [BASE+RC*8] + | cvtsd2si RC, xmm0 + | cvtsi2sd xmm1, RC + | ucomisd xmm0, xmm1 + } else { + |.if not X64 + | fld qword [BASE+RC*8] + | fist ARG1 + | fild ARG1 + | fcomparepp // eax (RC) modified! + | mov RC, ARG1 + |.endif + } + | jne ->vmeta_tsetv // Generic numeric key? Use fallback. + } + | cmp RC, TAB:RB->asize // Takes care of unordered, too. + | jae ->vmeta_tsetv + | shl RC, 3 + | add RC, TAB:RB->array + | cmp dword [RC+4], LJ_TNIL + | je >3 // Previous value is nil? + |1: + | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) + | jnz >7 + |2: // Set array slot. + |.if X64 + | mov RBa, [BASE+RA*8] + | mov [RC], RBa + |.else + | mov RB, [BASE+RA*8+4] + | mov RA, [BASE+RA*8] + | mov [RC+4], RB + | mov [RC], RA + |.endif + | ins_next + | + |3: // Check for __newindex if previous value is nil. + | cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath. + | jz <1 + | mov TAB:RA, TAB:RB->metatable + | test byte TAB:RA->nomm, 1<vmeta_tsetv // 'no __newindex' flag NOT set: check. + | movzx RA, PC_RA // Restore RA. + | jmp <1 + | + |5: // String key? + | checkstr RC, ->vmeta_tsetv + | mov STR:RC, [BASE+RC*8] + | jmp ->BC_TSETS_Z + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, RA + | movzx RA, PC_RA // Restore RA. + | jmp <2 + break; + case BC_TSETS: + | ins_ABC // RA = src, RB = table, RC = str const (~) + | not RCa + | mov STR:RC, [KBASE+RC*4] + | checktab RB, ->vmeta_tsets + | mov TAB:RB, [BASE+RB*8] + |->BC_TSETS_Z: // RB = GCtab *, RC = GCstr *, refetches PC_RA. + | mov RA, TAB:RB->hmask + | and RA, STR:RC->hash + | imul RA, #NODE + | mov byte TAB:RB->nomm, 0 // Clear metamethod cache. + | add NODE:RA, TAB:RB->node + |1: + | cmp dword NODE:RA->key.it, LJ_TSTR + | jne >5 + | cmp dword NODE:RA->key.gcr, STR:RC + | jne >5 + | // Ok, key found. Assumes: offsetof(Node, val) == 0 + | cmp dword [RA+4], LJ_TNIL + | je >4 // Previous value is nil? + |2: + | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) + | jnz >7 + |3: // Set node value. + | movzx RC, PC_RA + |.if X64 + | mov RBa, [BASE+RC*8] + | mov [RA], RBa + |.else + | mov RB, [BASE+RC*8+4] + | mov RC, [BASE+RC*8] + | mov [RA+4], RB + | mov [RA], RC + |.endif + | ins_next + | + |4: // Check for __newindex if previous value is nil. + | cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath. + | jz <2 + | mov TMP1, RA // Save RA. + | mov TAB:RA, TAB:RB->metatable + | test byte TAB:RA->nomm, 1<vmeta_tsets // 'no __newindex' flag NOT set: check. + | mov RA, TMP1 // Restore RA. + | jmp <2 + | + |5: // Follow hash chain. + | mov NODE:RA, NODE:RA->next + | test NODE:RA, NODE:RA + | jnz <1 + | // End of hash chain: key not found, add a new one. + | + | // But check for __newindex first. + | mov TAB:RA, TAB:RB->metatable + | test TAB:RA, TAB:RA + | jz >6 // No metatable: continue. + | test byte TAB:RA->nomm, 1<vmeta_tsets // 'no __newindex' flag NOT set: check. + |6: + | mov TMP1, STR:RC + | mov TMP2, LJ_TSTR + | mov TMP3, TAB:RB // Save TAB:RB for us. + |.if X64 + | mov L:CARG1d, SAVE_L + | mov L:CARG1d->base, BASE + | lea CARG3, TMP1 + | mov CARG2d, TAB:RB + | mov L:RB, L:CARG1d + |.else + | lea RC, TMP1 // Store temp. TValue in TMP1/TMP2. + | mov ARG2, TAB:RB + | mov L:RB, SAVE_L + | mov ARG3, RC + | mov ARG1, L:RB + | mov L:RB->base, BASE + |.endif + | mov SAVE_PC, PC + | call extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k) + | // Handles write barrier for the new key. TValue * returned in eax (RC). + | mov BASE, L:RB->base + | mov TAB:RB, TMP3 // Need TAB:RB for barrier. + | mov RA, eax + | jmp <2 // Must check write barrier for value. + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, RC // Destroys STR:RC. + | jmp <3 + break; + case BC_TSETB: + | ins_ABC // RA = src, RB = table, RC = byte literal + | checktab RB, ->vmeta_tsetb + | mov TAB:RB, [BASE+RB*8] + | cmp RC, TAB:RB->asize + | jae ->vmeta_tsetb + | shl RC, 3 + | add RC, TAB:RB->array + | cmp dword [RC+4], LJ_TNIL + | je >3 // Previous value is nil? + |1: + | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) + | jnz >7 + |2: // Set array slot. + |.if X64 + | mov RAa, [BASE+RA*8] + | mov [RC], RAa + |.else + | mov RB, [BASE+RA*8+4] + | mov RA, [BASE+RA*8] + | mov [RC+4], RB + | mov [RC], RA + |.endif + | ins_next + | + |3: // Check for __newindex if previous value is nil. + | cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath. + | jz <1 + | mov TAB:RA, TAB:RB->metatable + | test byte TAB:RA->nomm, 1<vmeta_tsetb // 'no __newindex' flag NOT set: check. + | movzx RA, PC_RA // Restore RA. + | jmp <1 + | + |7: // Possible table write barrier for the value. Skip valiswhite check. + | barrierback TAB:RB, RA + | movzx RA, PC_RA // Restore RA. + | jmp <2 + break; + + case BC_TSETM: + | ins_AD // RA = base (table at base-1), RD = num const (start index) + | mov TMP1, KBASE // Need one more free register. + | mov KBASE, dword [KBASE+RD*8] // Integer constant is in lo-word. + |1: + | lea RA, [BASE+RA*8] + | mov TAB:RB, [RA-8] // Guaranteed to be a table. + | test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table) + | jnz >7 + |2: + | mov RD, MULTRES + | sub RD, 1 + | jz >4 // Nothing to copy? + | add RD, KBASE // Compute needed size. + | cmp RD, TAB:RB->asize + | ja >5 // Doesn't fit into array part? + | sub RD, KBASE + | shl KBASE, 3 + | add KBASE, TAB:RB->array + |3: // Copy result slots to table. + |.if X64 + | mov RBa, [RA] + | add RA, 8 + | mov [KBASE], RBa + |.else + | mov RB, [RA] + | mov [KBASE], RB + | mov RB, [RA+4] + | add RA, 8 + | mov [KBASE+4], RB + |.endif + | add KBASE, 8 + | sub RD, 1 + | jnz <3 + |4: + | mov KBASE, TMP1 + | ins_next + | + |5: // Need to resize array part. + |.if X64 + | mov L:CARG1d, SAVE_L + | mov L:CARG1d->base, BASE // Caveat: CARG2d/CARG3d may be BASE. + | mov CARG2d, TAB:RB + | mov CARG3d, RD + | mov L:RB, L:CARG1d + |.else + | mov ARG2, TAB:RB + | mov L:RB, SAVE_L + | mov L:RB->base, BASE + | mov ARG3, RD + | mov ARG1, L:RB + |.endif + | mov SAVE_PC, PC + | call extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize) + | mov BASE, L:RB->base + | movzx RA, PC_RA // Restore RA. + | jmp <1 // Retry. + | + |7: // Possible table write barrier for any value. Skip valiswhite check. + | barrierback TAB:RB, RD + | jmp <2 + break; + + /* -- Calls and vararg handling ----------------------------------------- */ + + case BC_CALL: case BC_CALLM: + | ins_A_C // RA = base, (RB = nresults+1,) RC = nargs+1 | extra_nargs + if (op == BC_CALLM) { + | add NARGS:RD, MULTRES + } + | cmp dword [BASE+RA*8+4], LJ_TFUNC + | mov LFUNC:RB, [BASE+RA*8] + | jne ->vmeta_call_ra + | lea BASE, [BASE+RA*8+8] + | ins_call + break; + + case BC_CALLMT: + | ins_AD // RA = base, RD = extra_nargs + | add NARGS:RD, MULTRES + | // Fall through. Assumes BC_CALLT follows and ins_AD is a no-op. + break; + case BC_CALLT: + | ins_AD // RA = base, RD = nargs+1 + | lea RA, [BASE+RA*8+8] + | mov KBASE, BASE // Use KBASE for move + vmeta_call hint. + | mov LFUNC:RB, [RA-8] + | cmp dword [RA-4], LJ_TFUNC + | jne ->vmeta_call + |->BC_CALLT_Z: + | mov PC, [BASE-4] + | test PC, FRAME_TYPE + | jnz >7 + |1: + | mov [BASE-8], LFUNC:RB // Copy function down, reloaded below. + | mov MULTRES, NARGS:RD + | sub NARGS:RD, 1 + | jz >3 + |2: // Move args down. + |.if X64 + | mov RBa, [RA] + | add RA, 8 + | mov [KBASE], RBa + |.else + | mov RB, [RA] + | mov [KBASE], RB + | mov RB, [RA+4] + | add RA, 8 + | mov [KBASE+4], RB + |.endif + | add KBASE, 8 + | sub NARGS:RD, 1 + | jnz <2 + | + | mov LFUNC:RB, [BASE-8] + |3: + | mov NARGS:RD, MULTRES + | cmp byte LFUNC:RB->ffid, 1 // (> FF_C) Calling a fast function? + | ja >5 + |4: + | ins_callt + | + |5: // Tailcall to a fast function. + | test PC, FRAME_TYPE // Lua frame below? + | jnz <4 + | movzx RA, PC_RA + | not RAa + | lea RA, [BASE+RA*8] + | mov LFUNC:KBASE, [RA-8] // Need to prepare KBASE. + | mov KBASE, LFUNC:KBASE->pc + | mov KBASE, [KBASE+PC2PROTO(k)] + | jmp <4 + | + |7: // Tailcall from a vararg function. + | sub PC, FRAME_VARG + | test PC, FRAME_TYPEP + | jnz >8 // Vararg frame below? + | sub BASE, PC // Need to relocate BASE/KBASE down. + | mov KBASE, BASE + | mov PC, [BASE-4] + | jmp <1 + |8: + | add PC, FRAME_VARG + | jmp <1 + break; + + case BC_ITERC: + | ins_A // RA = base, (RB = nresults+1,) RC = nargs+1 (2+1) + | lea RA, [BASE+RA*8+8] // fb = base+1 + |.if X64 + | mov RBa, [RA-24] // Copy state. fb[0] = fb[-3]. + | mov RCa, [RA-16] // Copy control var. fb[1] = fb[-2]. + | mov [RA], RBa + | mov [RA+8], RCa + |.else + | mov RB, [RA-24] // Copy state. fb[0] = fb[-3]. + | mov RC, [RA-20] + | mov [RA], RB + | mov [RA+4], RC + | mov RB, [RA-16] // Copy control var. fb[1] = fb[-2]. + | mov RC, [RA-12] + | mov [RA+8], RB + | mov [RA+12], RC + |.endif + | mov LFUNC:RB, [RA-32] // Copy callable. fb[-1] = fb[-4] + | mov RC, [RA-28] + | mov [RA-8], LFUNC:RB + | mov [RA-4], RC + | cmp RC, LJ_TFUNC // Handle like a regular 2-arg call. + | mov NARGS:RD, 2+1 + | jne ->vmeta_call + | mov BASE, RA + | ins_call + break; + + case BC_ITERN: + | ins_A // RA = base, (RB = nresults+1, RC = nargs+1 (2+1)) +#if LJ_HASJIT + | // NYI: add hotloop, record BC_ITERN. +#endif + | mov TMP1, KBASE // Need two more free registers. + | mov TMP2, DISPATCH + | mov TAB:RB, [BASE+RA*8-16] + | mov RC, [BASE+RA*8-8] // Get index from control var. + | mov DISPATCH, TAB:RB->asize + | add PC, 4 + | mov KBASE, TAB:RB->array + |1: // Traverse array part. + | cmp RC, DISPATCH; jae >5 // Index points after array part? + | cmp dword [KBASE+RC*8+4], LJ_TNIL; je >4 + if (LJ_DUALNUM) { + | mov dword [BASE+RA*8+4], LJ_TISNUM + | mov dword [BASE+RA*8], RC + } else if (sse) { + | cvtsi2sd xmm0, RC + } else { + | fild dword [BASE+RA*8-8] + } + | // Copy array slot to returned value. + |.if X64 + | mov RBa, [KBASE+RC*8] + | mov [BASE+RA*8+8], RBa + |.else + | mov RB, [KBASE+RC*8+4] + | mov [BASE+RA*8+12], RB + | mov RB, [KBASE+RC*8] + | mov [BASE+RA*8+8], RB + |.endif + | add RC, 1 + | // Return array index as a numeric key. + if (LJ_DUALNUM) { + | // See above. + } else if (sse) { + | movsd qword [BASE+RA*8], xmm0 + } else { + | fstp qword [BASE+RA*8] + } + | mov [BASE+RA*8-8], RC // Update control var. + |2: + | movzx RD, PC_RD // Get target from ITERL. + | branchPC RD + |3: + | mov DISPATCH, TMP2 + | mov KBASE, TMP1 + | ins_next + | + |4: // Skip holes in array part. + | add RC, 1 + if (!LJ_DUALNUM && !sse) { + | mov [BASE+RA*8-8], RC + } + | jmp <1 + | + |5: // Traverse hash part. + | sub RC, DISPATCH + |6: + | cmp RC, TAB:RB->hmask; ja <3 // End of iteration? Branch to ITERL+1. + | imul KBASE, RC, #NODE + | add NODE:KBASE, TAB:RB->node + | cmp dword NODE:KBASE->val.it, LJ_TNIL; je >7 + | lea DISPATCH, [RC+DISPATCH+1] + | // Copy key and value from hash slot. + |.if X64 + | mov RBa, NODE:KBASE->key + | mov RCa, NODE:KBASE->val + | mov [BASE+RA*8], RBa + | mov [BASE+RA*8+8], RCa + |.else + | mov RB, NODE:KBASE->key.gcr + | mov RC, NODE:KBASE->key.it + | mov [BASE+RA*8], RB + | mov [BASE+RA*8+4], RC + | mov RB, NODE:KBASE->val.gcr + | mov RC, NODE:KBASE->val.it + | mov [BASE+RA*8+8], RB + | mov [BASE+RA*8+12], RC + |.endif + | mov [BASE+RA*8-8], DISPATCH + | jmp <2 + | + |7: // Skip holes in hash part. + | add RC, 1 + | jmp <6 + break; + + case BC_ISNEXT: + | ins_AD // RA = base, RD = target (points to ITERN) + | cmp dword [BASE+RA*8-20], LJ_TFUNC; jne >5 + | mov CFUNC:RB, [BASE+RA*8-24] + | cmp dword [BASE+RA*8-12], LJ_TTAB; jne >5 + | cmp dword [BASE+RA*8-4], LJ_TNIL; jne >5 + | cmp byte CFUNC:RB->ffid, FF_next_N; jne >5 + | branchPC RD + | mov dword [BASE+RA*8-8], 0 // Initialize control var. + |1: + | ins_next + |5: // Despecialize bytecode if any of the checks fail. + | mov PC_OP, BC_JMP + | branchPC RD + | mov byte [PC], BC_ITERC + | jmp <1 + break; + + case BC_VARG: + | ins_ABC // RA = base, RB = nresults+1, RC = numparams + | mov TMP1, KBASE // Need one more free register. + | lea KBASE, [BASE+RC*8+(8+FRAME_VARG)] + | lea RA, [BASE+RA*8] + | sub KBASE, [BASE-4] + | // Note: KBASE may now be even _above_ BASE if nargs was < numparams. + | test RB, RB + | jz >5 // Copy all varargs? + | lea RB, [RA+RB*8-8] + | cmp KBASE, BASE // No vararg slots? + | jnb >2 + |1: // Copy vararg slots to destination slots. + |.if X64 + | mov RCa, [KBASE-8] + | add KBASE, 8 + | mov [RA], RCa + |.else + | mov RC, [KBASE-8] + | mov [RA], RC + | mov RC, [KBASE-4] + | add KBASE, 8 + | mov [RA+4], RC + |.endif + | add RA, 8 + | cmp RA, RB // All destination slots filled? + | jnb >3 + | cmp KBASE, BASE // No more vararg slots? + | jb <1 + |2: // Fill up remainder with nil. + | mov dword [RA+4], LJ_TNIL + | add RA, 8 + | cmp RA, RB + | jb <2 + |3: + | mov KBASE, TMP1 + | ins_next + | + |5: // Copy all varargs. + | mov MULTRES, 1 // MULTRES = 0+1 + | mov RC, BASE + | sub RC, KBASE + | jbe <3 // No vararg slots? + | mov RB, RC + | shr RB, 3 + | add RB, 1 + | mov MULTRES, RB // MULTRES = #varargs+1 + | mov L:RB, SAVE_L + | add RC, RA + | cmp RC, L:RB->maxstack + | ja >7 // Need to grow stack? + |6: // Copy all vararg slots. + |.if X64 + | mov RCa, [KBASE-8] + | add KBASE, 8 + | mov [RA], RCa + |.else + | mov RC, [KBASE-8] + | mov [RA], RC + | mov RC, [KBASE-4] + | add KBASE, 8 + | mov [RA+4], RC + |.endif + | add RA, 8 + | cmp KBASE, BASE // No more vararg slots? + | jb <6 + | jmp <3 + | + |7: // Grow stack for varargs. + | mov L:RB->base, BASE + | mov L:RB->top, RA + | mov SAVE_PC, PC + | sub KBASE, BASE // Need delta, because BASE may change. + | mov FCARG2, MULTRES + | sub FCARG2, 1 + | mov FCARG1, L:RB + | call extern lj_state_growstack@8 // (lua_State *L, int n) + | mov BASE, L:RB->base + | mov RA, L:RB->top + | add KBASE, BASE + | jmp <6 + break; + + /* -- Returns ----------------------------------------------------------- */ + + case BC_RETM: + | ins_AD // RA = results, RD = extra_nresults + | add RD, MULTRES // MULTRES >=1, so RD >=1. + | // Fall through. Assumes BC_RET follows and ins_AD is a no-op. + break; + + case BC_RET: case BC_RET0: case BC_RET1: + | ins_AD // RA = results, RD = nresults+1 + if (op != BC_RET0) { + | shl RA, 3 + } + |1: + | mov PC, [BASE-4] + | mov MULTRES, RD // Save nresults+1. + | test PC, FRAME_TYPE // Check frame type marker. + | jnz >7 // Not returning to a fixarg Lua func? + switch (op) { + case BC_RET: + |->BC_RET_Z: + | mov KBASE, BASE // Use KBASE for result move. + | sub RD, 1 + | jz >3 + |2: // Move results down. + |.if X64 + | mov RBa, [KBASE+RA] + | mov [KBASE-8], RBa + |.else + | mov RB, [KBASE+RA] + | mov [KBASE-8], RB + | mov RB, [KBASE+RA+4] + | mov [KBASE-4], RB + |.endif + | add KBASE, 8 + | sub RD, 1 + | jnz <2 + |3: + | mov RD, MULTRES // Note: MULTRES may be >255. + | movzx RB, PC_RB // So cannot compare with RDL! + |5: + | cmp RB, RD // More results expected? + | ja >6 + break; + case BC_RET1: + |.if X64 + | mov RBa, [BASE+RA] + | mov [BASE-8], RBa + |.else + | mov RB, [BASE+RA+4] + | mov [BASE-4], RB + | mov RB, [BASE+RA] + | mov [BASE-8], RB + |.endif + /* fallthrough */ + case BC_RET0: + |5: + | cmp PC_RB, RDL // More results expected? + | ja >6 + default: + break; + } + | movzx RA, PC_RA + | not RAa // Note: ~RA = -(RA+1) + | lea BASE, [BASE+RA*8] // base = base - (RA+1)*8 + | mov LFUNC:KBASE, [BASE-8] + | mov KBASE, LFUNC:KBASE->pc + | mov KBASE, [KBASE+PC2PROTO(k)] + | ins_next + | + |6: // Fill up results with nil. + if (op == BC_RET) { + | mov dword [KBASE-4], LJ_TNIL // Note: relies on shifted base. + | add KBASE, 8 + } else { + | mov dword [BASE+RD*8-12], LJ_TNIL + } + | add RD, 1 + | jmp <5 + | + |7: // Non-standard return case. + | lea RB, [PC-FRAME_VARG] + | test RB, FRAME_TYPEP + | jnz ->vm_return + | // Return from vararg function: relocate BASE down and RA up. + | sub BASE, RB + if (op != BC_RET0) { + | add RA, RB + } + | jmp <1 + break; + + /* -- Loops and branches ------------------------------------------------ */ + + |.define FOR_IDX, [RA]; .define FOR_TIDX, dword [RA+4] + |.define FOR_STOP, [RA+8]; .define FOR_TSTOP, dword [RA+12] + |.define FOR_STEP, [RA+16]; .define FOR_TSTEP, dword [RA+20] + |.define FOR_EXT, [RA+24]; .define FOR_TEXT, dword [RA+28] + + case BC_FORL: +#if LJ_HASJIT + | hotloop RB +#endif + | // Fall through. Assumes BC_IFORL follows and ins_AJ is a no-op. + break; + + case BC_JFORI: + case BC_JFORL: +#if !LJ_HASJIT + break; +#endif + case BC_FORI: + case BC_IFORL: + vk = (op == BC_IFORL || op == BC_JFORL); + | ins_AJ // RA = base, RD = target (after end of loop or start of loop) + | lea RA, [BASE+RA*8] + if (LJ_DUALNUM) { + | cmp FOR_TIDX, LJ_TISNUM; jne >9 + if (!vk) { + | cmp FOR_TSTOP, LJ_TISNUM; jne ->vmeta_for + | cmp FOR_TSTEP, LJ_TISNUM; jne ->vmeta_for + | mov RB, dword FOR_IDX + | cmp dword FOR_STEP, 0; jl >5 + } else { +#ifdef LUA_USE_ASSERT + | cmp FOR_TSTOP, LJ_TISNUM; jne ->assert_bad_for_arg_type + | cmp FOR_TSTEP, LJ_TISNUM; jne ->assert_bad_for_arg_type +#endif + | mov RB, dword FOR_STEP + | test RB, RB; js >5 + | add RB, dword FOR_IDX; jo >1 + | mov dword FOR_IDX, RB + } + | cmp RB, dword FOR_STOP + | mov FOR_TEXT, LJ_TISNUM + | mov dword FOR_EXT, RB + if (op == BC_FORI) { + | jle >7 + |1: + |6: + | branchPC RD + } else if (op == BC_JFORI) { + | branchPC RD + | movzx RD, PC_RD + | jle =>BC_JLOOP + |1: + |6: + } else if (op == BC_IFORL) { + | jg >7 + |6: + | branchPC RD + |1: + } else { + | jle =>BC_JLOOP + |1: + |6: + } + |7: + | ins_next + | + |5: // Invert check for negative step. + if (vk) { + | add RB, dword FOR_IDX; jo <1 + | mov dword FOR_IDX, RB + } + | cmp RB, dword FOR_STOP + | mov FOR_TEXT, LJ_TISNUM + | mov dword FOR_EXT, RB + if (op == BC_FORI) { + | jge <7 + } else if (op == BC_JFORI) { + | branchPC RD + | movzx RD, PC_RD + | jge =>BC_JLOOP + } else if (op == BC_IFORL) { + | jl <7 + } else { + | jge =>BC_JLOOP + } + | jmp <6 + |9: // Fallback to FP variant. + } else if (!vk) { + | cmp FOR_TIDX, LJ_TISNUM + } + if (!vk) { + | jae ->vmeta_for + | cmp FOR_TSTOP, LJ_TISNUM; jae ->vmeta_for + } else { +#ifdef LUA_USE_ASSERT + | cmp FOR_TSTOP, LJ_TISNUM; jae ->assert_bad_for_arg_type + | cmp FOR_TSTEP, LJ_TISNUM; jae ->assert_bad_for_arg_type +#endif + } + | mov RB, FOR_TSTEP // Load type/hiword of for step. + if (!vk) { + | cmp RB, LJ_TISNUM; jae ->vmeta_for + } + if (sse) { + | movsd xmm0, qword FOR_IDX + | movsd xmm1, qword FOR_STOP + if (vk) { + | addsd xmm0, qword FOR_STEP + | movsd qword FOR_IDX, xmm0 + | test RB, RB; js >3 + } else { + | jl >3 + } + | ucomisd xmm1, xmm0 + |1: + | movsd qword FOR_EXT, xmm0 + } else { + | fld qword FOR_STOP + | fld qword FOR_IDX + if (vk) { + | fadd qword FOR_STEP // nidx = idx + step + | fst qword FOR_IDX + | fst qword FOR_EXT + | test RB, RB; js >1 + } else { + | fst qword FOR_EXT + | jl >1 + } + | fxch // Swap lim/(n)idx if step non-negative. + |1: + | fcomparepp // eax (RD) modified if !cmov. + if (!cmov) { + | movzx RD, PC_RD // Need to reload RD. + } + } + if (op == BC_FORI) { + if (LJ_DUALNUM) { + | jnb <7 + } else { + | jnb >2 + | branchPC RD + } + } else if (op == BC_JFORI) { + | branchPC RD + | movzx RD, PC_RD + | jnb =>BC_JLOOP + } else if (op == BC_IFORL) { + if (LJ_DUALNUM) { + | jb <7 + } else { + | jb >2 + | branchPC RD + } + } else { + | jnb =>BC_JLOOP + } + if (LJ_DUALNUM) { + | jmp <6 + } else { + |2: + | ins_next + } + if (sse) { + |3: // Invert comparison if step is negative. + | ucomisd xmm0, xmm1 + | jmp <1 + } + break; + + case BC_ITERL: +#if LJ_HASJIT + | hotloop RB +#endif + | // Fall through. Assumes BC_IITERL follows and ins_AJ is a no-op. + break; + + case BC_JITERL: +#if !LJ_HASJIT + break; +#endif + case BC_IITERL: + | ins_AJ // RA = base, RD = target + | lea RA, [BASE+RA*8] + | mov RB, [RA+4] + | cmp RB, LJ_TNIL; je >1 // Stop if iterator returned nil. + if (op == BC_JITERL) { + | mov [RA-4], RB + | mov RB, [RA] + | mov [RA-8], RB + | jmp =>BC_JLOOP + } else { + | branchPC RD // Otherwise save control var + branch. + | mov RD, [RA] + | mov [RA-4], RB + | mov [RA-8], RD + } + |1: + | ins_next + break; + + case BC_LOOP: + | ins_A // RA = base, RD = target (loop extent) + | // Note: RA/RD is only used by trace recorder to determine scope/extent + | // This opcode does NOT jump, it's only purpose is to detect a hot loop. +#if LJ_HASJIT + | hotloop RB +#endif + | // Fall through. Assumes BC_ILOOP follows and ins_A is a no-op. + break; + + case BC_ILOOP: + | ins_A // RA = base, RD = target (loop extent) + | ins_next + break; + + case BC_JLOOP: +#if LJ_HASJIT + | ins_AD // RA = base (ignored), RD = traceno + | mov RA, [DISPATCH+DISPATCH_J(trace)] + | mov TRACE:RD, [RA+RD*4] + | mov RDa, TRACE:RD->mcode + | mov L:RB, SAVE_L + | mov [DISPATCH+DISPATCH_GL(jit_base)], BASE + | mov [DISPATCH+DISPATCH_GL(jit_L)], L:RB + | // Save additional callee-save registers only used in compiled code. + |.if X64WIN + | mov TMPQ, r12 + | mov TMPa, r13 + | mov CSAVE_4, r14 + | mov CSAVE_3, r15 + | mov RAa, rsp + | sub rsp, 9*16+4*8 + | movdqa [RAa], xmm6 + | movdqa [RAa-1*16], xmm7 + | movdqa [RAa-2*16], xmm8 + | movdqa [RAa-3*16], xmm9 + | movdqa [RAa-4*16], xmm10 + | movdqa [RAa-5*16], xmm11 + | movdqa [RAa-6*16], xmm12 + | movdqa [RAa-7*16], xmm13 + | movdqa [RAa-8*16], xmm14 + | movdqa [RAa-9*16], xmm15 + |.elif X64 + | mov TMPQ, r12 + | mov TMPa, r13 + | sub rsp, 16 + |.endif + | jmp RDa +#endif + break; + + case BC_JMP: + | ins_AJ // RA = unused, RD = target + | branchPC RD + | ins_next + break; + + /* -- Function headers -------------------------------------------------- */ + + /* + ** Reminder: A function may be called with func/args above L->maxstack, + ** i.e. occupying EXTRA_STACK slots. And vmeta_call may add one extra slot, + ** too. This means all FUNC* ops (including fast functions) must check + ** for stack overflow _before_ adding more slots! + */ + + case BC_FUNCF: +#if LJ_HASJIT + | hotcall RB +#endif + case BC_FUNCV: /* NYI: compiled vararg functions. */ + | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow and ins_AD is a no-op. + break; + + case BC_JFUNCF: +#if !LJ_HASJIT + break; +#endif + case BC_IFUNCF: + | ins_AD // BASE = new base, RA = framesize, RD = nargs+1 + | mov KBASE, [PC-4+PC2PROTO(k)] + | mov L:RB, SAVE_L + | lea RA, [BASE+RA*8] // Top of frame. + | cmp RA, L:RB->maxstack + | ja ->vm_growstack_f + | movzx RA, byte [PC-4+PC2PROTO(numparams)] + | cmp NARGS:RD, RA // Check for missing parameters. + | jbe >3 + |2: + if (op == BC_JFUNCF) { + | movzx RD, PC_RD + | jmp =>BC_JLOOP + } else { + | ins_next + } + | + |3: // Clear missing parameters. + | mov dword [BASE+NARGS:RD*8-4], LJ_TNIL + | add NARGS:RD, 1 + | cmp NARGS:RD, RA + | jbe <3 + | jmp <2 + break; + + case BC_JFUNCV: +#if !LJ_HASJIT + break; +#endif + | int3 // NYI: compiled vararg functions + break; /* NYI: compiled vararg functions. */ + + case BC_IFUNCV: + | ins_AD // BASE = new base, RA = framesize, RD = nargs+1 + | lea RB, [NARGS:RD*8+FRAME_VARG] + | lea RD, [BASE+NARGS:RD*8] + | mov LFUNC:KBASE, [BASE-8] + | mov [RD-4], RB // Store delta + FRAME_VARG. + | mov [RD-8], LFUNC:KBASE // Store copy of LFUNC. + | mov L:RB, SAVE_L + | lea RA, [RD+RA*8] + | cmp RA, L:RB->maxstack + | ja ->vm_growstack_v // Need to grow stack. + | mov RA, BASE + | mov BASE, RD + | movzx RB, byte [PC-4+PC2PROTO(numparams)] + | test RB, RB + | jz >2 + |1: // Copy fixarg slots up to new frame. + | add RA, 8 + | cmp RA, BASE + | jnb >3 // Less args than parameters? + | mov KBASE, [RA-8] + | mov [RD], KBASE + | mov KBASE, [RA-4] + | mov [RD+4], KBASE + | add RD, 8 + | mov dword [RA-4], LJ_TNIL // Clear old fixarg slot (help the GC). + | sub RB, 1 + | jnz <1 + |2: + if (op == BC_JFUNCV) { + | movzx RD, PC_RD + | jmp =>BC_JLOOP + } else { + | mov KBASE, [PC-4+PC2PROTO(k)] + | ins_next + } + | + |3: // Clear missing parameters. + | mov dword [RD+4], LJ_TNIL + | add RD, 8 + | sub RB, 1 + | jnz <3 + | jmp <2 + break; + + case BC_FUNCC: + case BC_FUNCCW: + | ins_AD // BASE = new base, RA = ins RA|RD (unused), RD = nargs+1 + | mov CFUNC:RB, [BASE-8] + | mov KBASEa, CFUNC:RB->f + | mov L:RB, SAVE_L + | lea RD, [BASE+NARGS:RD*8-8] + | mov L:RB->base, BASE + | lea RA, [RD+8*LUA_MINSTACK] + | cmp RA, L:RB->maxstack + | mov L:RB->top, RD + if (op == BC_FUNCC) { + |.if X64 + | mov CARG1d, L:RB // Caveat: CARG1d may be RA. + |.else + | mov ARG1, L:RB + |.endif + } else { + |.if X64 + | mov CARG2, KBASEa + | mov CARG1d, L:RB // Caveat: CARG1d may be RA. + |.else + | mov ARG2, KBASEa + | mov ARG1, L:RB + |.endif + } + | ja ->vm_growstack_c // Need to grow stack. + | set_vmstate C + if (op == BC_FUNCC) { + | call KBASEa // (lua_State *L) + } else { + | // (lua_State *L, lua_CFunction f) + | call aword [DISPATCH+DISPATCH_GL(wrapf)] + } + | set_vmstate INTERP + | // nresults returned in eax (RD). + | mov BASE, L:RB->base + | lea RA, [BASE+RD*8] + | neg RA + | add RA, L:RB->top // RA = (L->top-(L->base+nresults))*8 + | mov PC, [BASE-4] // Fetch PC of caller. + | jmp ->vm_returnc + break; + + /* ---------------------------------------------------------------------- */ + + default: + fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); + exit(2); + break; + } +} + +static int build_backend(BuildCtx *ctx) +{ + int op; + int cmov = 1; + int sse = 0; +#ifdef LUAJIT_CPU_NOCMOV + cmov = 0; +#endif +#if defined(LUAJIT_CPU_SSE2) || defined(LJ_TARGET_X64) + sse = 1; +#endif + + dasm_growpc(Dst, BC__MAX); + + build_subroutines(ctx, cmov, sse); + + |.code_op + for (op = 0; op < BC__MAX; op++) + build_ins(ctx, (BCOp)op, op, cmov, sse); + + return BC__MAX; +} + +/* Emit pseudo frame-info for all assembler functions. */ +static void emit_asm_debug(BuildCtx *ctx) +{ + int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code); +#if LJ_64 +#define SZPTR "8" +#define BSZPTR "3" +#define REG_SP "0x7" +#define REG_RA "0x10" +#else +#define SZPTR "4" +#define BSZPTR "2" +#define REG_SP "0x4" +#define REG_RA "0x8" +#endif + switch (ctx->mode) { + case BUILD_elfasm: + fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n"); + fprintf(ctx->fp, + ".Lframe0:\n" + "\t.long .LECIE0-.LSCIE0\n" + ".LSCIE0:\n" + "\t.long 0xffffffff\n" + "\t.byte 0x1\n" + "\t.string \"\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -" SZPTR "\n" + "\t.byte " REG_RA "\n" + "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" + "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" + "\t.align " SZPTR "\n" + ".LECIE0:\n\n"); + fprintf(ctx->fp, + ".LSFDE0:\n" + "\t.long .LEFDE0-.LASFDE0\n" + ".LASFDE0:\n" + "\t.long .Lframe0\n" +#if LJ_64 + "\t.quad .Lbegin\n" + "\t.quad %d\n" + "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ + "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ + "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ + "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ + "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ +#else + "\t.long .Lbegin\n" + "\t.long %d\n" + "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ + "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ + "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ + "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ + "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ +#endif + "\t.align " SZPTR "\n" + ".LEFDE0:\n\n", fcofs, CFRAME_SIZE); +#if LJ_HASFFI + fprintf(ctx->fp, + ".LSFDE1:\n" + "\t.long .LEFDE1-.LASFDE1\n" + ".LASFDE1:\n" + "\t.long .Lframe0\n" +#if LJ_64 + "\t.quad lj_vm_ffi_call\n" + "\t.quad %d\n" + "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ + "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ + "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ + "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ +#else + "\t.long lj_vm_ffi_call\n" + "\t.long %d\n" + "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */ + "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ + "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */ + "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */ +#endif + "\t.align " SZPTR "\n" + ".LEFDE1:\n\n", (int)ctx->codesz - fcofs); +#endif +#if (defined(__sun__) && defined(__svr4__)) || defined(__solaris_) + fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n"); +#else + fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n"); +#endif + fprintf(ctx->fp, + ".Lframe1:\n" + "\t.long .LECIE1-.LSCIE1\n" + ".LSCIE1:\n" + "\t.long 0\n" + "\t.byte 0x1\n" + "\t.string \"zPR\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -" SZPTR "\n" + "\t.byte " REG_RA "\n" + "\t.uleb128 6\n" /* augmentation length */ + "\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 " REG_SP "\n\t.uleb128 " SZPTR "\n" + "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" + "\t.align " SZPTR "\n" + ".LECIE1:\n\n"); + fprintf(ctx->fp, + ".LSFDE2:\n" + "\t.long .LEFDE2-.LASFDE2\n" + ".LASFDE2:\n" + "\t.long .LASFDE2-.Lframe1\n" + "\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 */ +#if LJ_64 + "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ + "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ + "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ + "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ +#else + "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ + "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ + "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ + "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ +#endif + "\t.align " SZPTR "\n" + ".LEFDE2:\n\n", fcofs, CFRAME_SIZE); +#if LJ_HASFFI + fprintf(ctx->fp, + ".Lframe2:\n" + "\t.long .LECIE2-.LSCIE2\n" + ".LSCIE2:\n" + "\t.long 0\n" + "\t.byte 0x1\n" + "\t.string \"zR\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -" SZPTR "\n" + "\t.byte " REG_RA "\n" + "\t.uleb128 1\n" /* augmentation length */ + "\t.byte 0x1b\n" /* pcrel|sdata4 */ + "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" + "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" + "\t.align " SZPTR "\n" + ".LECIE2:\n\n"); + fprintf(ctx->fp, + ".LSFDE3:\n" + "\t.long .LEFDE3-.LASFDE3\n" + ".LASFDE3:\n" + "\t.long .LASFDE3-.Lframe2\n" + "\t.long lj_vm_ffi_call-.\n" + "\t.long %d\n" + "\t.uleb128 0\n" /* augmentation length */ +#if LJ_64 + "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */ + "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ + "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ + "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ +#else + "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */ + "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ + "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */ + "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */ +#endif + "\t.align " SZPTR "\n" + ".LEFDE3:\n\n", (int)ctx->codesz - fcofs); +#endif + break; + case BUILD_coffasm: + fprintf(ctx->fp, "\t.section .eh_frame,\"dr\"\n"); + fprintf(ctx->fp, + "\t.def %slj_err_unwind_dwarf; .scl 2; .type 32; .endef\n", + LJ_32 ? "_" : ""); + fprintf(ctx->fp, + "Lframe1:\n" + "\t.long LECIE1-LSCIE1\n" + "LSCIE1:\n" + "\t.long 0\n" + "\t.byte 0x1\n" + "\t.string \"zP\"\n" + "\t.uleb128 0x1\n" + "\t.sleb128 -" SZPTR "\n" + "\t.byte " REG_RA "\n" + "\t.uleb128 5\n" /* augmentation length */ + "\t.byte 0x00\n" /* absptr */ + "\t.long %slj_err_unwind_dwarf\n" + "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n" + "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n" + "\t.align " SZPTR "\n" + "LECIE1:\n\n", LJ_32 ? "_" : ""); + fprintf(ctx->fp, + "LSFDE1:\n" + "\t.long LEFDE1-LASFDE1\n" + "LASFDE1:\n" + "\t.long LASFDE1-Lframe1\n" + "\t.long %slj_vm_asm_begin\n" + "\t.long %d\n" + "\t.uleb128 0\n" /* augmentation length */ + "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */ +#if LJ_64 + "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */ + "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */ + "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */ + "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */ +#else + "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */ + "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */ + "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */ + "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */ +#endif + "\t.align " SZPTR "\n" + "LEFDE1:\n\n", LJ_32 ? "_" : "", (int)ctx->codesz, CFRAME_SIZE); + break; + /* Mental note: never let Apple design an assembler. + ** Or a linker. Or a plastic case. But I digress. + */ + case BUILD_machasm: { +#if LJ_HASFFI + int fcsize = 0; +#endif + int i; + 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.byte 0x1\n" + "\t.byte 128-" SZPTR "\n" + "\t.byte " REG_RA "\n" + "\t.byte 6\n" /* augmentation length */ + "\t.byte 0x9b\n" /* indirect|pcrel|sdata4 */ +#if LJ_64 + "\t.long _lj_err_unwind_dwarf+4@GOTPCREL\n" + "\t.byte 0x1b\n" /* pcrel|sdata4 */ + "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n" +#else + "\t.long L_lj_err_unwind_dwarf$non_lazy_ptr-.\n" + "\t.byte 0x1b\n" /* pcrel|sdata4 */ + "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH-O. */ +#endif + "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n" + "\t.align " BSZPTR "\n" + "LECIEX:\n\n"); + for (i = 0; i < ctx->nsym; i++) { + const char *name = ctx->sym[i].name; + int32_t size = ctx->sym[i+1].ofs - ctx->sym[i].ofs; + if (size == 0) continue; +#if LJ_HASFFI + if (!strcmp(name, "_lj_vm_ffi_call")) { fcsize = size; continue; } +#endif + fprintf(ctx->fp, + "%s.eh:\n" + "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.byte 0\n" /* augmentation length */ + "\t.byte 0xe\n\t.byte %d\n" /* def_cfa_offset */ +#if LJ_64 + "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */ + "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */ + "\t.byte 0x8f\n\t.byte 0x4\n" /* offset r15 */ + "\t.byte 0x8e\n\t.byte 0x5\n" /* offset r14 */ +#else + "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/ + "\t.byte 0x87\n\t.byte 0x3\n" /* offset edi */ + "\t.byte 0x86\n\t.byte 0x4\n" /* offset esi */ + "\t.byte 0x83\n\t.byte 0x5\n" /* offset ebx */ +#endif + "\t.align " BSZPTR "\n" + "LEFDE%d:\n\n", + name, i, i, i, i, i, i, i, name, size, CFRAME_SIZE, i); + } +#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.byte 0x1\n" + "\t.byte 128-" SZPTR "\n" + "\t.byte " REG_RA "\n" + "\t.byte 1\n" /* augmentation length */ +#if LJ_64 + "\t.byte 0x1b\n" /* pcrel|sdata4 */ + "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n" +#else + "\t.byte 0x1b\n" /* pcrel|sdata4 */ + "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH. */ +#endif + "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n" + "\t.align " BSZPTR "\n" + "LECIEY:\n\n"); + fprintf(ctx->fp, + "_lj_vm_ffi_call.eh:\n" + "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.byte 0\n" /* augmentation length */ +#if LJ_64 + "\t.byte 0xe\n\t.byte 16\n" /* def_cfa_offset */ + "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */ + "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */ + "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */ +#else + "\t.byte 0xe\n\t.byte 8\n" /* def_cfa_offset */ + "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/ + "\t.byte 0xd\n\t.uleb128 0x4\n" /* def_cfa_register ebp */ + "\t.byte 0x83\n\t.byte 0x3\n" /* offset ebx */ +#endif + "\t.align " BSZPTR "\n" + "LEFDEY:\n\n", fcsize); + } +#endif +#if LJ_64 + fprintf(ctx->fp, "\t.subsections_via_symbols\n"); +#else + fprintf(ctx->fp, + "\t.non_lazy_symbol_pointer\n" + "L_lj_err_unwind_dwarf$non_lazy_ptr:\n" + ".indirect_symbol _lj_err_unwind_dwarf\n" + ".long 0\n"); +#endif + } + break; + default: /* Difficult for other modes. */ + break; + } +} + -- cgit v1.2.3-55-g6feb