mirror of
https://github.com/love2d/love-android.git
synced 2026-08-12 08:31:04 +02:00
Update LuaJIT to LuaJIT/LuaJIT@1e66d0f9e6
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
*.[oa]
|
||||
*.so
|
||||
*.obj
|
||||
*.lib
|
||||
*.exp
|
||||
*.dll
|
||||
*.exe
|
||||
*.manifest
|
||||
*.dmp
|
||||
*.swp
|
||||
.tags
|
||||
@@ -1,9 +0,0 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := libluajit
|
||||
LOCAL_SRC_FILES := android/$(TARGET_ARCH_ABI)/libluajit.a
|
||||
LOCAL_EXPORT_C_INCLUDES := ${LOCAL_PATH}/src
|
||||
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
@@ -1,7 +1,7 @@
|
||||
===============================================================================
|
||||
LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
|
||||
LuaJIT -- a Just-In-Time Compiler for Lua. https://luajit.org/
|
||||
|
||||
Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
[ MIT license: http://www.opensource.org/licenses/mit-license.php ]
|
||||
[ MIT license: https://www.opensource.org/licenses/mit-license.php ]
|
||||
|
||||
===============================================================================
|
||||
[ LuaJIT includes code from Lua 5.1/5.2, which has this license statement: ]
|
||||
@@ -51,6 +51,6 @@ THE SOFTWARE.
|
||||
|
||||
This is a version (aka dlmalloc) of malloc/free/realloc written by
|
||||
Doug Lea and released to the public domain, as explained at
|
||||
http://creativecommons.org/licenses/publicdomain
|
||||
https://creativecommons.org/licenses/publicdomain
|
||||
|
||||
===============================================================================
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
# For MSVC, please follow the instructions given in src/msvcbuild.bat.
|
||||
# For MinGW and Cygwin, cd to src and run make with the Makefile there.
|
||||
#
|
||||
# Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
# Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
##############################################################################
|
||||
|
||||
MAJVER= 2
|
||||
MINVER= 1
|
||||
RELVER= 0
|
||||
PREREL= -beta1
|
||||
PREREL= -beta3
|
||||
VERSION= $(MAJVER).$(MINVER).$(RELVER)$(PREREL)
|
||||
ABIVER= 5.1
|
||||
|
||||
@@ -47,17 +47,18 @@ INSTALL_PKGCONFIG= $(INSTALL_LIB)/pkgconfig
|
||||
INSTALL_TNAME= luajit-$(VERSION)
|
||||
INSTALL_TSYMNAME= luajit
|
||||
INSTALL_ANAME= libluajit-$(ABIVER).a
|
||||
INSTALL_SONAME= libluajit-$(ABIVER).so.$(MAJVER).$(MINVER).$(RELVER)
|
||||
INSTALL_SOSHORT= libluajit-$(ABIVER).so
|
||||
INSTALL_DYLIBNAME= libluajit-$(ABIVER).$(MAJVER).$(MINVER).$(RELVER).dylib
|
||||
INSTALL_SOSHORT1= libluajit-$(ABIVER).so
|
||||
INSTALL_SOSHORT2= libluajit-$(ABIVER).so.$(MAJVER)
|
||||
INSTALL_SONAME= $(INSTALL_SOSHORT2).$(MINVER).$(RELVER)
|
||||
INSTALL_DYLIBSHORT1= libluajit-$(ABIVER).dylib
|
||||
INSTALL_DYLIBSHORT2= libluajit-$(ABIVER).$(MAJVER).dylib
|
||||
INSTALL_DYLIBNAME= libluajit-$(ABIVER).$(MAJVER).$(MINVER).$(RELVER).dylib
|
||||
INSTALL_PCNAME= luajit.pc
|
||||
|
||||
INSTALL_STATIC= $(INSTALL_LIB)/$(INSTALL_ANAME)
|
||||
INSTALL_DYN= $(INSTALL_LIB)/$(INSTALL_SONAME)
|
||||
INSTALL_SHORT1= $(INSTALL_LIB)/$(INSTALL_SOSHORT)
|
||||
INSTALL_SHORT2= $(INSTALL_LIB)/$(INSTALL_SOSHORT)
|
||||
INSTALL_SHORT1= $(INSTALL_LIB)/$(INSTALL_SOSHORT1)
|
||||
INSTALL_SHORT2= $(INSTALL_LIB)/$(INSTALL_SOSHORT2)
|
||||
INSTALL_T= $(INSTALL_BIN)/$(INSTALL_TNAME)
|
||||
INSTALL_TSYM= $(INSTALL_BIN)/$(INSTALL_TSYMNAME)
|
||||
INSTALL_PC= $(INSTALL_PKGCONFIG)/$(INSTALL_PCNAME)
|
||||
@@ -74,7 +75,7 @@ SYMLINK= ln -sf
|
||||
INSTALL_X= install -m 0755
|
||||
INSTALL_F= install -m 0644
|
||||
UNINSTALL= $(RM)
|
||||
LDCONFIG= ldconfig -n
|
||||
LDCONFIG= ldconfig -n 2>/dev/null
|
||||
SED_PC= sed -e "s|^prefix=.*|prefix=$(PREFIX)|" \
|
||||
-e "s|^multilib=.*|multilib=$(MULTILIB)|"
|
||||
|
||||
@@ -85,16 +86,22 @@ FILE_MAN= luajit.1
|
||||
FILE_PC= luajit.pc
|
||||
FILES_INC= lua.h lualib.h lauxlib.h luaconf.h lua.hpp luajit.h
|
||||
FILES_JITLIB= bc.lua bcsave.lua dump.lua p.lua v.lua zone.lua \
|
||||
dis_x86.lua dis_x64.lua dis_arm.lua dis_ppc.lua \
|
||||
dis_mips.lua dis_mipsel.lua vmdef.lua
|
||||
dis_x86.lua dis_x64.lua dis_arm.lua dis_arm64.lua \
|
||||
dis_arm64be.lua dis_ppc.lua dis_mips.lua dis_mipsel.lua \
|
||||
dis_mips64.lua dis_mips64el.lua vmdef.lua
|
||||
|
||||
ifeq (,$(findstring Windows,$(OS)))
|
||||
ifeq (Darwin,$(shell uname -s))
|
||||
INSTALL_SONAME= $(INSTALL_DYLIBNAME)
|
||||
INSTALL_SHORT1= $(INSTALL_LIB)/$(INSTALL_DYLIBSHORT1)
|
||||
INSTALL_SHORT2= $(INSTALL_LIB)/$(INSTALL_DYLIBSHORT2)
|
||||
LDCONFIG= :
|
||||
endif
|
||||
HOST_SYS:= $(shell uname -s)
|
||||
else
|
||||
HOST_SYS= Windows
|
||||
endif
|
||||
TARGET_SYS?= $(HOST_SYS)
|
||||
|
||||
ifeq (Darwin,$(TARGET_SYS))
|
||||
INSTALL_SONAME= $(INSTALL_DYLIBNAME)
|
||||
INSTALL_SOSHORT1= $(INSTALL_DYLIBSHORT1)
|
||||
INSTALL_SOSHORT2= $(INSTALL_DYLIBSHORT2)
|
||||
LDCONFIG= :
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
@@ -114,7 +121,7 @@ install: $(INSTALL_DEP)
|
||||
$(RM) $(INSTALL_DYN) $(INSTALL_SHORT1) $(INSTALL_SHORT2)
|
||||
cd src && test -f $(FILE_SO) && \
|
||||
$(INSTALL_X) $(FILE_SO) $(INSTALL_DYN) && \
|
||||
$(LDCONFIG) $(INSTALL_LIB) && \
|
||||
( $(LDCONFIG) $(INSTALL_LIB) || : ) && \
|
||||
$(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT1) && \
|
||||
$(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT2) || :
|
||||
cd etc && $(INSTALL_F) $(FILE_MAN) $(INSTALL_MAN)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
README for LuaJIT 2.1.0-beta1
|
||||
README for LuaJIT 2.1.0-beta3
|
||||
-----------------------------
|
||||
|
||||
LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.
|
||||
|
||||
Project Homepage: http://luajit.org/
|
||||
Project Homepage: https://luajit.org/
|
||||
|
||||
LuaJIT is Copyright (C) 2005-2015 Mike Pall.
|
||||
LuaJIT is Copyright (C) 2005-2021 Mike Pall.
|
||||
LuaJIT is free software, released under the MIT license.
|
||||
See full Copyright Notice in the COPYRIGHT file or in luajit.h.
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,65 @@
|
||||
rem Build instruction assume using WSL + Clang for Windows (with MSVC x86+x64 toolset for -m32 switch)
|
||||
rem This assume NDK r19 or later. See https://github.com/LuaJIT/LuaJIT/issues/477 for more information.
|
||||
|
||||
rem Make sure LuaJIT and the prebuilt is already in your PATH environment variable.
|
||||
rem As of commit 384d6d5 in LuaJIT v2.1 repository, lj_ircall.h.patch is no longer needed.
|
||||
|
||||
rem If you're confused which one should be added your path:
|
||||
rem <NDK_ROOT>\toolchains\llvm\prebuilt\windows-x86_64\bin
|
||||
|
||||
mkdir android\arm64-v8a
|
||||
mkdir android\armeabi-v7a
|
||||
mkdir android\x86
|
||||
mkdir android\x86_64
|
||||
|
||||
rem Reset error level
|
||||
type nul
|
||||
|
||||
rem ARMv8
|
||||
if not exist android\arm64-v8a\libluajit.a (
|
||||
wsl make clean
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
wsl make HOST_LUA=luajit.exe HOST_CC=clang.exe HOST_CFLAGS=-D_CRT_SECURE_NO_WARNINGS CC=clang CROSS=aarch64-linux-android- STATIC_CC=aarch64-linux-android21-clang "DYNAMIC_CC=aarch64-linux-android21-clang -fPIC" "TARGET_AR=aarch64-linux-android-ar.exe rcus" TARGET_LD=aarch64-linux-android21-clang TARGET_STRIP=aarch64-linux-android-strip.exe amalg -j4
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
copy src\libluajit.a android\arm64-v8a\libluajit.a
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
)
|
||||
|
||||
rem ARMv7
|
||||
if not exist android\armeabi-v7a\libluajit.a (
|
||||
wsl make clean
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
wsl make HOST_LUA=luajit.exe "HOST_CC=clang.exe -m32" HOST_CFLAGS=-D_CRT_SECURE_NO_WARNINGS CC=clang CROSS=arm-linux-android- STATIC_CC=armv7a-linux-androideabi16-clang "DYNAMIC_CC=armv7a-linux-androideabi16-clang -fPIC" "TARGET_AR=arm-linux-androideabi-ar.exe rcus" TARGET_LD=armv7a-linux-androideabi16-clang TARGET_STRIP=arm-linux-androideabi-strip.exe amalg -j4
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
copy src\libluajit.a android\armeabi-v7a\libluajit.a
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
)
|
||||
|
||||
rem x86
|
||||
if not exist android\x86\libluajit.a (
|
||||
wsl make clean
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
wsl make HOST_LUA=luajit.exe "HOST_CC=clang.exe -m32" HOST_CFLAGS=-D_CRT_SECURE_NO_WARNINGS CC=clang CROSS=i686-linux-android- STATIC_CC=i686-linux-android16-clang "DYNAMIC_CC=i686-linux-android16-clang -fPIC" "TARGET_AR=i686-linux-android-ar.exe rcus" TARGET_LD=i686-linux-android16-clang TARGET_STRIP=i686-linux-android-strip.exe amalg -j4
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
copy src\libluajit.a android\x86\libluajit.a
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
)
|
||||
|
||||
rem x86_64
|
||||
if not exist android\x86_64\libluajit.a (
|
||||
wsl make clean
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
wsl make HOST_LUA=luajit.exe HOST_CC=clang.exe HOST_CFLAGS=-D_CRT_SECURE_NO_WARNINGS CC=clang CROSS=x86_64-linux-android- STATIC_CC=x86_64-linux-android21-clang "DYNAMIC_CC=x86_64-linux-android21-clang -fPIC" "TARGET_AR=x86_64-linux-android-ar.exe rcus" TARGET_LD=x86_64-linux-android21-clang TARGET_STRIP=x86_64-linux-android-strip.exe amalg -j4
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
copy src\libluajit.a android\x86_64\libluajit.a
|
||||
if "%ERRORLEVEL%" == "1" goto :error
|
||||
)
|
||||
|
||||
goto :done
|
||||
|
||||
:error
|
||||
exit /b 1
|
||||
|
||||
:done
|
||||
wsl make clean
|
||||
exit /b 0
|
||||
@@ -1,79 +0,0 @@
|
||||
#!/bin/bash
|
||||
#================================================================#
|
||||
# Build script based on
|
||||
# https://github.com/moai/moai-dev/blob/master/ant/libmoai/jni/luajit/build.sh
|
||||
#================================================================#
|
||||
|
||||
host_os=`uname -s | tr "[:upper:]" "[:lower:]"`
|
||||
host_arch=`uname -m`
|
||||
|
||||
if [ -f android/armeabi/libluajit.a ] &&
|
||||
[ -f android/armeabi-v7a/libluajit.a ] &&
|
||||
[ -f android/x86/libluajit.a ]; then
|
||||
echo "LuaJIT Already built"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
NDK_BUILD_LOCATION=${ANDROID_NDK}
|
||||
if [[ x$NDK_BUILD_LOCATION = "x" ]]; then
|
||||
echo "The Android NDK must be on your path."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NDK="${NDK_BUILD_LOCATION%/ndk-build}"
|
||||
|
||||
if [[ x$NDK = "x" ]]; then
|
||||
echo "The Android NDK must be on your path."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NDKABI=16
|
||||
|
||||
# Since OSX still has bash 3, we don't have associative arrays, fake them instead
|
||||
armeabi=0
|
||||
armeabiv7a=1
|
||||
x86=2
|
||||
|
||||
NDKVER[$armeabi]="$NDK/toolchains/arm-linux-androideabi-4.9"
|
||||
NDKP[$armeabi]="${NDKVER[$armeabi]}/prebuilt/${host_os}-${host_arch}/bin/arm-linux-androideabi-"
|
||||
NDKF[$armeabi]="--sysroot \"$NDK/platforms/android-$NDKABI/arch-arm\""
|
||||
CFLAGS[$armeabi]="-I \"$NDK/sysroot/usr/include\" -I \"$NDK/sysroot/usr/include/arm-linux-androideabi\""
|
||||
|
||||
NDKVER[$armeabiv7a]="${NDKVER[$armeabi]}"
|
||||
NDKP[$armeabiv7a]="${NDKP[$armeabi]}"
|
||||
NDKF[$armeabiv7a]="${NDKF[$armeabi]}"
|
||||
CFLAGS[$armeabiv7a]="${CFLAGS[$armeabi]}"
|
||||
|
||||
NDKVER[$x86]="$NDK/toolchains/x86-4.9"
|
||||
NDKP[$x86]="${NDKVER[$x86]}/prebuilt/${host_os}-${host_arch}/bin/i686-linux-android-"
|
||||
NDKF[$x86]="--sysroot \"$NDK/platforms/android-$NDKABI/arch-x86\""
|
||||
CFLAGS[$x86]="-I \"$NDK/sysroot/usr/include\" -I \"$NDK/sysroot/usr/include/i686-linux-android\" -DLUAJIT_NO_LOG2"
|
||||
|
||||
buildLuaJIT()
|
||||
{
|
||||
archkey="$1"
|
||||
arch="$2"
|
||||
ndkarch="$3"
|
||||
DESTDIR=../android/$arch
|
||||
mkdir -p $DESTDIR 2>/dev/null
|
||||
rm "$DESTDIR"/*.a 2>/dev/null
|
||||
make clean
|
||||
make HOST_CC="gcc -m32" CROSS="${NDKP[$archkey]}" TARGET_SYS=Linux TARGET_FLAGS="${NDKF[$archkey]} $ndkarch" TARGET_CFLAGS="${CFLAGS[$archkey]}" libluajit.a -j4
|
||||
|
||||
if [ -f libluajit.a ]; then
|
||||
mv libluajit.a $DESTDIR/libluajit.a
|
||||
fi;
|
||||
}
|
||||
|
||||
cd src
|
||||
|
||||
# Android/ARM, armeabi (ARMv5TE soft-float), Android 2.2+ (Froyo)
|
||||
buildLuaJIT $armeabi armeabi
|
||||
|
||||
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.0+ (ICS)
|
||||
buildLuaJIT $armeabiv7a armeabi-v7a "-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -Wl,--fix-cortex-a8"
|
||||
|
||||
# Android/x86
|
||||
buildLuaJIT $x86 x86
|
||||
|
||||
make clean
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2004-2015 Mike Pall.
|
||||
/* Copyright (C) 2004-2021 Mike Pall.
|
||||
*
|
||||
* You are welcome to use the general ideas of this design for your own sites.
|
||||
* But please do not steal the stylesheet, the layout or the color scheme.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2004-2015 Mike Pall.
|
||||
/* Copyright (C) 2004-2021 Mike Pall.
|
||||
*
|
||||
* You are welcome to use the general ideas of this design for your own sites.
|
||||
* But please do not steal the stylesheet, the layout or the color scheme.
|
||||
|
||||
@@ -1,807 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>LuaJIT Change History</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
<style type="text/css">
|
||||
div.major { max-width: 600px; padding: 1em; margin: 1em 0 1em 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>LuaJIT Change History</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
<a href="running.html">Running</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="extensions.html">Extensions</a>
|
||||
<ul><li>
|
||||
<a href="ext_ffi.html">FFI Library</a>
|
||||
<ul><li>
|
||||
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
|
||||
</li><li>
|
||||
<a href="ext_ffi_api.html">ffi.* API</a>
|
||||
</li><li>
|
||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="ext_jit.html">jit.* Library</a>
|
||||
</li><li>
|
||||
<a href="ext_c_api.html">Lua/C API</a>
|
||||
</li><li>
|
||||
<a href="ext_profiler.html">Profiler</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a class="current" href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
This is a list of changes between the released versions of LuaJIT.<br>
|
||||
The current <span style="color: #0000c0;">stable version</span> is <strong>LuaJIT 2.0.4</strong>.<br>
|
||||
</p>
|
||||
<p>
|
||||
Please check the
|
||||
<a href="http://luajit.org/changes.html"><span class="ext">»</span> Online Change History</a>
|
||||
to see whether newer versions are available.
|
||||
</p>
|
||||
|
||||
<div class="major" style="background: #d0d0ff;">
|
||||
<h2 id="LuaJIT-2.1.0-beta1">LuaJIT 2.1.0-beta1 — 2015-08-25</h2>
|
||||
<p>
|
||||
This is a brief summary of the major changes in LuaJIT 2.1 compared to 2.0.
|
||||
Please take a look at the commit history for more details.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Changes to the VM core:
|
||||
<ul>
|
||||
<li>Add low-overhead profiler (<tt>-jp</tt>).</li>
|
||||
<li>Add <tt>LJ_GC64</tt> mode: 64 bit GC object references (really: 47 bit). Interpreter-only for now.</li>
|
||||
<li>Add <tt>LJ_FR2</tt> mode: Two-slot frame info. Required by <tt>LJ_GC64</tt> mode.</li>
|
||||
<li>Add <tt>table.new()</tt> and <tt>table.clear()</tt>.</li>
|
||||
<li>Parse Unicode escape <tt>'\u{XX...}'</tt> in string literals.</li>
|
||||
<li>Parse binary number literals (<tt>0bxxx</tt>).</li>
|
||||
</ul></li>
|
||||
<li>Improvements to the JIT compiler:
|
||||
<ul>
|
||||
<li>Add trace stitching.</li>
|
||||
<li>Compile various builtins: <tt>string.char()</tt>, <tt>string.reverse()</tt>, <tt>string.lower()</tt>, <tt>string.upper()</tt>, <tt>string.rep()</tt>, <tt>string.format()</tt>, <tt>table.concat()</tt>, <tt>bit.tohex()</tt>, <tt>getfenv(0)</tt>, <tt>debug.getmetatable()</tt>.</li>
|
||||
<li>Compile <tt>string.find()</tt> for fixed string searches (no patterns).</li>
|
||||
<li>Compile <tt>BC_TSETM</tt>, e.g. <tt>{1,2,3,f()}</tt>.</li>
|
||||
<li>Compile string concatenations (<tt>BC_CAT</tt>).</li>
|
||||
<li>Compile <tt>__concat</tt> metamethod.</li>
|
||||
<li>Various minor optimizations.</li>
|
||||
</ul></li>
|
||||
<li>Internal Changes:
|
||||
<ul>
|
||||
<li>Add support for embedding LuaJIT bytecode for builtins.</li>
|
||||
<li>Replace various builtins with embedded bytecode.</li>
|
||||
<li>Refactor string buffers and string formatting.</li>
|
||||
<li>Remove obsolete non-truncating number to integer conversions.</li>
|
||||
</ul></li>
|
||||
<li>Ports:
|
||||
<ul>
|
||||
<li>Add Xbox One port (<tt>LJ_GC64</tt> mode).</li>
|
||||
<li>ARM64: Add port of the interpreter (<tt>LJ_GC64</tt> mode).</li>
|
||||
<li>x64: Add separate port of the interpreter to <tt>LJ_GC64</tt> mode.</li>
|
||||
<li>x86/x64: Drop internal x87 math functions. Use libm functions.</li>
|
||||
<li>x86: Remove x87 support from interpreter. SSE2 is mandatory now.</li>
|
||||
<li>x86/x64: Add support for AES-NI, AVX and AVX2 to DynASM.</li>
|
||||
<li>PPC/e500: Drop support for this architecture.</li>
|
||||
</ul></li>
|
||||
<li>FFI library:
|
||||
<ul>
|
||||
<li>FFI: Add 64 bit bitwise operations.</li>
|
||||
<li>FFI: Compile VLA/VLS and large cdata allocations with default initialization.</li>
|
||||
<li>FFI: Compile conversions from functions to function pointers.</li>
|
||||
<li>FFI: Compile lightuserdata to <tt>void *</tt> conversion.</li>
|
||||
<li>FFI: Compile <tt>ffi.gc(cdata, nil)</tt>, too.</li>
|
||||
<li>FFI: Add <tt>ffi.typeinfo()</tt>.</li>
|
||||
<li>FFI: Add <tt>ssize_t</tt> declaration.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="major" style="background: #ffffd0;">
|
||||
<h2 id="LuaJIT-2.0.4">LuaJIT 2.0.4 — 2015-05-14</h2>
|
||||
<ul>
|
||||
<li>Fix stack check in narrowing optimization.</li>
|
||||
<li>Fix Lua/C API typecheck error for special indexes.</li>
|
||||
<li>Fix string to number conversion.</li>
|
||||
<li>Fix lexer error for chunks without tokens.</li>
|
||||
<li>Don't compile <tt>IR_RETF</tt> after <tt>CALLT</tt> to ff with-side effects.</li>
|
||||
<li>Fix <tt>BC_UCLO</tt>/<tt>BC_JMP</tt> join optimization in Lua parser.</li>
|
||||
<li>Fix corner case in string to number conversion.</li>
|
||||
<li>Gracefully handle <tt>lua_error()</tt> for a suspended coroutine.</li>
|
||||
<li>Avoid error messages when building with Clang.</li>
|
||||
<li>Fix snapshot #0 handling for traces with a stack check on entry.</li>
|
||||
<li>Fix fused constant loads under high register pressure.</li>
|
||||
<li>Invalidate backpropagation cache after DCE.</li>
|
||||
<li>Fix ABC elimination.</li>
|
||||
<li>Fix debug info for main chunk of stripped bytecode.</li>
|
||||
<li>Fix FOLD rule for <tt>string.sub(s, ...) == k</tt>.</li>
|
||||
<li>Fix FOLD rule for <tt>STRREF</tt> of <tt>SNEW</tt>.</li>
|
||||
<li>Fix frame traversal while searching for error function.</li>
|
||||
<li>Prevent GC estimate miscalculation due to buffer growth.</li>
|
||||
<li>Prevent adding side traces for stack checks.</li>
|
||||
<li>Fix top slot calculation for snapshots with continuations.</li>
|
||||
<li>Fix check for reuse of SCEV results in <tt>FORL</tt>.</li>
|
||||
<li>Add PS Vita port.</li>
|
||||
<li>Fix compatibility issues with Illumos.</li>
|
||||
<li>Fix DragonFly build (unsupported).</li>
|
||||
<li>OpenBSD/x86: Better executable memory allocation for W^X mode.</li>
|
||||
<li>x86: Fix argument checks for <tt>ipairs()</tt> iterator.</li>
|
||||
<li>x86: <tt>lj_math_random_step()</tt> clobbers XMM regs on OSX Clang.</li>
|
||||
<li>x86: Fix code generation for unused result of <tt>math.random()</tt>.</li>
|
||||
<li>x64: Allow building with <tt>LUAJIT_USE_SYSMALLOC</tt> and <tt>LUAJIT_USE_VALGRIND</tt>.</li>
|
||||
<li>x86/x64: Fix argument check for bit shifts.</li>
|
||||
<li>x86/x64: Fix code generation for fused test/arith ops.</li>
|
||||
<li>ARM: Fix write barrier check in <tt>BC_USETS</tt>.</li>
|
||||
<li>PPC: Fix red zone overflow in machine code generation.</li>
|
||||
<li>PPC: Don't use <tt>mcrxr</tt> on PPE.</li>
|
||||
<li>Various archs: Fix excess stack growth in interpreter.</li>
|
||||
<li>FFI: Fix FOLD rule for <tt>TOBIT</tt> + <tt>CONV num.u32</tt>.</li>
|
||||
<li>FFI: Prevent DSE across <tt>ffi.string()</tt>.</li>
|
||||
<li>FFI: No meta fallback when indexing pointer to incomplete struct.</li>
|
||||
<li>FFI: Fix initialization of unions of subtypes.</li>
|
||||
<li>FFI: Fix cdata vs. non-cdata arithmetic and comparisons.</li>
|
||||
<li>FFI: Fix <tt>__index</tt>/<tt>__newindex</tt> metamethod resolution for ctypes.</li>
|
||||
<li>FFI: Fix compilation of reference field access.</li>
|
||||
<li>FFI: Fix frame traversal for backtraces with FFI callbacks.</li>
|
||||
<li>FFI: Fix recording of indexing a struct pointer ctype object itself.</li>
|
||||
<li>FFI: Allow non-scalar cdata to be compared for equality by address.</li>
|
||||
<li>FFI: Fix pseudo type conversions for type punning.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.3">LuaJIT 2.0.3 — 2014-03-12</h2>
|
||||
<ul>
|
||||
<li>Add PS4 port.</li>
|
||||
<li>Add support for multilib distro builds.</li>
|
||||
<li>Fix OSX build.</li>
|
||||
<li>Fix MinGW build.</li>
|
||||
<li>Fix Xbox 360 build.</li>
|
||||
<li>Improve ULOAD forwarding for open upvalues.</li>
|
||||
<li>Fix GC steps threshold handling when called by JIT-compiled code.</li>
|
||||
<li>Fix argument checks for <tt>math.deg()</tt> and <tt>math.rad()</tt>.</li>
|
||||
<li>Fix <tt>jit.flush(func|true)</tt>.</li>
|
||||
<li>Respect <tt>jit.off(func)</tt> when returning to a function, too.</li>
|
||||
<li>Fix compilation of <tt>string.byte(s, nil, n)</tt>.</li>
|
||||
<li>Fix line number for relocated bytecode after closure fixup</li>
|
||||
<li>Fix frame traversal for backtraces.</li>
|
||||
<li>Fix ABC elimination.</li>
|
||||
<li>Fix handling of redundant PHIs.</li>
|
||||
<li>Fix snapshot restore for exit to function header.</li>
|
||||
<li>Fix type punning alias analysis for constified pointers</li>
|
||||
<li>Fix call unroll checks in the presence of metamethod frames.</li>
|
||||
<li>Fix initial maxslot for down-recursive traces.</li>
|
||||
<li>Prevent BASE register coalescing if parent uses <tt>IR_RETF</tt>.</li>
|
||||
<li>Don't purge modified function from stack slots in <tt>BC_RET</tt>.</li>
|
||||
<li>Fix recording of <tt>BC_VARG</tt>.</li>
|
||||
<li>Don't access dangling reference to reallocated IR.</li>
|
||||
<li>Fix frame depth display for bytecode dump in <tt>-jdump</tt>.</li>
|
||||
<li>ARM: Fix register allocation when rematerializing FPRs.</li>
|
||||
<li>x64: Fix store to upvalue for lightuserdata values.</li>
|
||||
<li>FFI: Add missing GC steps for callback argument conversions.</li>
|
||||
<li>FFI: Properly unload loaded DLLs.</li>
|
||||
<li>FFI: Fix argument checks for <tt>ffi.string()</tt>.</li>
|
||||
<li>FFI/x64: Fix passing of vector arguments to calls.</li>
|
||||
<li>FFI: Rehash finalizer table after GC cycle, if needed.</li>
|
||||
<li>FFI: Fix <tt>cts->L</tt> for cdata unsinking in snapshot restore.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.2">LuaJIT 2.0.2 — 2013-06-03</h2>
|
||||
<ul>
|
||||
<li>Fix memory access check for fast string interning.</li>
|
||||
<li>Fix MSVC intrinsics for older versions.</li>
|
||||
<li>Add missing GC steps for <tt>io.*</tt> functions.</li>
|
||||
<li>Fix spurious red zone overflows in machine code generation.</li>
|
||||
<li>Fix jump-range constrained mcode allocation.</li>
|
||||
<li>Inhibit DSE for implicit loads via calls.</li>
|
||||
<li>Fix builtin string to number conversion for overflow digits.</li>
|
||||
<li>Fix optional argument handling while recording builtins.</li>
|
||||
<li>Fix optional argument handling in <tt>table.concat()</tt>.</li>
|
||||
<li>Add partial support for building with MingW64 GCC 4.8-SEH.</li>
|
||||
<li>Add missing PHI barrier to <tt>string.sub(str, a, b) == kstr</tt> FOLD rule.</li>
|
||||
<li>Fix compatibility issues with Illumos.</li>
|
||||
<li>ARM: Fix cache flush/sync for exit stubs of JIT-compiled code.</li>
|
||||
<li>MIPS: Fix cache flush/sync for JIT-compiled code jump area.</li>
|
||||
<li>PPC: Add <tt>plt</tt> suffix for external calls from assembler code.</li>
|
||||
<li>FFI: Fix snapshot substitution in SPLIT pass.</li>
|
||||
<li>FFI/x86: Fix register allocation for 64 bit comparisons.</li>
|
||||
<li>FFI: Fix tailcall in lowest frame to C function with bool result.</li>
|
||||
<li>FFI: Ignore <tt>long</tt> type specifier in <tt>ffi.istype()</tt>.</li>
|
||||
<li>FFI: Fix calling conventions for 32 bit OSX and iOS simulator (struct returns).</li>
|
||||
<li>FFI: Fix calling conventions for ARM hard-float EABI (nested structs).</li>
|
||||
<li>FFI: Improve error messages for arithmetic and comparison operators.</li>
|
||||
<li>FFI: Insert no-op type conversion for pointer to integer cast.</li>
|
||||
<li>FFI: Fix unroll limit for <tt>ffi.fill()</tt>.</li>
|
||||
<li>FFI: Must sink <tt>XBAR</tt> together with <tt>XSTORE</tt>s.</li>
|
||||
<li>FFI: Preserve intermediate string for <tt>const char *</tt> conversion.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.1">LuaJIT 2.0.1 — 2013-02-19</h2>
|
||||
<ul>
|
||||
<li>Don't clear frame for out-of-memory error.</li>
|
||||
<li>Leave hook when resume catches error thrown from hook.</li>
|
||||
<li>Add missing GC steps for template table creation.</li>
|
||||
<li>Fix discharge order of comparisons in Lua parser.</li>
|
||||
<li>Improve buffer handling for <tt>io.read()</tt>.</li>
|
||||
<li>OSX: Add support for Mach-O object files to <tt>-b</tt> option.</li>
|
||||
<li>Fix PS3 port.</li>
|
||||
<li>Fix/enable Xbox 360 port.</li>
|
||||
<li>x86/x64: Always mark ref for shift count as non-weak.</li>
|
||||
<li>x64: Don't fuse implicitly 32-to-64 extended operands.</li>
|
||||
<li>ARM: Fix armhf call argument handling.</li>
|
||||
<li>ARM: Fix code generation for integer math.min/math.max.</li>
|
||||
<li>PPC/e500: Fix <tt>lj_vm_floor()</tt> for Inf/NaN.</li>
|
||||
<li>FFI: Change priority of table initializer variants for structs.</li>
|
||||
<li>FFI: Fix code generation for bool call result check on x86/x64.</li>
|
||||
<li>FFI: Load FFI library on-demand for bytecode with cdata literals.</li>
|
||||
<li>FFI: Fix handling of qualified transparent structs/unions.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0">LuaJIT 2.0.0 — 2012-11-08</h2>
|
||||
<ul>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix Android/x86 build.</li>
|
||||
<li>Fix recording of equality comparisons with <tt>__eq</tt> metamethods.</li>
|
||||
<li>Fix detection of immutable upvalues.</li>
|
||||
<li>Replace error with PANIC for callbacks from JIT-compiled code.</li>
|
||||
<li>Fix builtin string to number conversion for <tt>INT_MIN</tt>.</li>
|
||||
<li>Don't create unneeded array part for template tables.</li>
|
||||
<li>Fix <tt>CONV.num.int</tt> sinking.</li>
|
||||
<li>Don't propagate implicitly widened number to index metamethods.</li>
|
||||
<li>ARM: Fix ordered comparisons of number vs. non-number.</li>
|
||||
<li>FFI: Fix code generation for replay of sunk float fields.</li>
|
||||
<li>FFI: Fix signedness of bool.</li>
|
||||
<li>FFI: Fix recording of bool call result check on x86/x64.</li>
|
||||
<li>FFI: Fix stack-adjustment for <tt>__thiscall</tt> callbacks.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta11">LuaJIT 2.0.0-beta11 — 2012-10-16</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>Use ARM VFP instructions, if available (build-time detection).</li>
|
||||
<li>Add support for ARM hard-float EABI (<tt>armhf</tt>).</li>
|
||||
<li>Add PS3 port.</li>
|
||||
<li>Add many features from Lua 5.2, e.g. <tt>goto</tt>/labels.
|
||||
Refer to <a href="extensions.html#lua52">this list</a>.</li>
|
||||
<li>FFI: Add parameterized C types.</li>
|
||||
<li>FFI: Add support for copy constructors.</li>
|
||||
<li>FFI: Equality comparisons never raise an error (treat as unequal instead).</li>
|
||||
<li>FFI: Box all accessed or returned enums.</li>
|
||||
<li>FFI: Check for <tt>__new</tt> metamethod when calling a constructor.</li>
|
||||
<li>FFI: Handle <tt>__pairs</tt>/<tt>__ipairs</tt> metamethods for cdata objects.</li>
|
||||
<li>FFI: Convert <tt>io.*</tt> file handle to <tt>FILE *</tt> pointer (but as a <tt>void *</tt>).</li>
|
||||
<li>FFI: Detect and support type punning through unions.</li>
|
||||
<li>FFI: Improve various error messages.</li>
|
||||
</ul></li>
|
||||
<li>Build-system reorganization:
|
||||
<ul>
|
||||
<li>Reorganize directory layout:<br>
|
||||
<tt>lib/*</tt> → <tt>src/jit/*</tt><br>
|
||||
<tt>src/buildvm_*.dasc</tt> → <tt>src/vm_*.dasc</tt><br>
|
||||
<tt>src/buildvm_*.h</tt> → removed<br>
|
||||
<tt>src/buildvm*</tt> → <tt>src/host/*</tt></li>
|
||||
<li>Add minified Lua interpreter plus Lua BitOp (<tt>minilua</tt>) to run DynASM.</li>
|
||||
<li>Change DynASM bit operations to use Lua BitOp</li>
|
||||
<li>Translate only <tt>vm_*.dasc</tt> for detected target architecture.</li>
|
||||
<li>Improve target detection for <tt>msvcbuild.bat</tt>.</li>
|
||||
<li>Fix build issues on Cygwin and MinGW with optional MSys.</li>
|
||||
<li>Handle cross-compiles with FPU/no-FPU or hard-fp/soft-fp ABI mismatch.</li>
|
||||
<li>Remove some library functions for no-JIT/no-FFI builds.</li>
|
||||
<li>Add uninstall target to top-level Makefile.</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Preserve snapshot #0 PC for all traces.</li>
|
||||
<li>Fix argument checks for <tt>coroutine.create()</tt>.</li>
|
||||
<li>Command line prints version and JIT status to <tt>stdout</tt>, not <tt>stderr</tt>.</li>
|
||||
<li>Fix userdata <tt>__gc</tt> separations at Lua state close.</li>
|
||||
<li>Fix <tt>TDUP</tt> to <tt>HLOAD</tt> forwarding for <tt>LJ_DUALNUM</tt> builds.</li>
|
||||
<li>Fix buffer check in bytecode writer.</li>
|
||||
<li>Make <tt>os.date()</tt> thread-safe.</li>
|
||||
<li>Add missing declarations for MSVC intrinsics.</li>
|
||||
<li>Fix dispatch table modifications for return hooks.</li>
|
||||
<li>Workaround for MSVC conversion bug (<tt>double</tt> → <tt>uint32_t</tt> → <tt>int32_t</tt>).</li>
|
||||
<li>Fix FOLD rule <tt>(i-j)-i => 0-j</tt>.</li>
|
||||
<li>Never use DWARF unwinder on Windows.</li>
|
||||
<li>Fix shrinking of direct mapped blocks in builtin allocator.</li>
|
||||
<li>Limit recursion depth in <tt>string.match()</tt> et al.</li>
|
||||
<li>Fix late despecialization of <tt>ITERN</tt> after loop has been entered.</li>
|
||||
<li>Fix <tt>'f'</tt> and <tt>'L'</tt> options for <tt>debug.getinfo()</tt> and <tt>lua_getinfo()</tt>.</li>
|
||||
<li>Fix <tt>package.searchpath()</tt>.</li>
|
||||
<li>OSX: Change dylib names to be consistent with other platforms.</li>
|
||||
<li>Android: Workaround for broken <tt>sprintf("%g", -0.0)</tt>.</li>
|
||||
<li>x86: Remove support for ancient CPUs without <tt>CMOV</tt> (before Pentium Pro).</li>
|
||||
<li>x86: Fix register allocation for calls returning register pair.</li>
|
||||
<li>x86/x64: Fix fusion of unsigned byte comparisons with swapped operands.</li>
|
||||
<li>ARM: Fix <tt>tonumber()</tt> argument check.</li>
|
||||
<li>ARM: Fix modulo operator and <tt>math.floor()</tt>/<tt>math.ceil()</tt> for <tt>inf</tt>/<tt>nan</tt>.</li>
|
||||
<li>ARM: Invoke SPLIT pass for leftover <tt>IR_TOBIT</tt>.</li>
|
||||
<li>ARM: Fix BASE register coalescing.</li>
|
||||
<li>PPC: Fix interpreter state setup in callbacks.</li>
|
||||
<li>PPC: Fix <tt>string.sub()</tt> range check.</li>
|
||||
<li>MIPS: Support generation of MIPS/MIPSEL bytecode object files.</li>
|
||||
<li>MIPS: Fix calls to <tt>floor()</tt>/<tt>ceil()</tt><tt>/trunc()</tt>.</li>
|
||||
<li>ARM/PPC: Detect more target architecture variants.</li>
|
||||
<li>ARM/PPC/e500/MIPS: Fix tailcalls from fast functions, esp. <tt>tostring()</tt>.</li>
|
||||
<li>ARM/PPC/MIPS: Fix rematerialization of FP constants.</li>
|
||||
<li>FFI: Don't call <tt>FreeLibrary()</tt> on our own EXE/DLL.</li>
|
||||
<li>FFI: Resolve metamethods for constructors, too.</li>
|
||||
<li>FFI: Properly disable callbacks on iOS (would require executable memory).</li>
|
||||
<li>FFI: Fix cdecl string parsing during recording.</li>
|
||||
<li>FFI: Show address pointed to for <tt>tostring(ref)</tt>, too.</li>
|
||||
<li>FFI: Fix alignment of C call argument/return structure.</li>
|
||||
<li>FFI: Initialize all fields of standard types.</li>
|
||||
<li>FFI: Fix callback handling when new C types are declared in callback.</li>
|
||||
<li>FFI: Fix recording of constructors for pointers.</li>
|
||||
<li>FFI: Always resolve metamethods for pointers to structs.</li>
|
||||
<li>FFI: Correctly propagate alignment when interning nested types.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Add allocation sinking and store sinking optimization.</li>
|
||||
<li>Constify immutable upvalues.</li>
|
||||
<li>Add builtin string to integer or FP number conversion. Improves cross-platform consistency and correctness.</li>
|
||||
<li>Create string hash slots in template tables for non-const values, too. Avoids later table resizes.</li>
|
||||
<li>Eliminate <tt>HREFK</tt> guard for template table references.</li>
|
||||
<li>Add various new FOLD rules.</li>
|
||||
<li>Don't use stack unwinding for <tt>lua_yield()</tt> (slow on x64).</li>
|
||||
<li>ARM, PPC, MIPS: Improve <tt>XLOAD</tt> operand fusion and register hinting.</li>
|
||||
<li>PPC, MIPS: Compile <tt>math.sqrt()</tt> to sqrt instruction, if available.</li>
|
||||
<li>FFI: Fold <tt>KPTR</tt> + constant offset in SPLIT pass.</li>
|
||||
<li>FFI: Optimize/inline <tt>ffi.copy()</tt> and <tt>ffi.fill()</tt>.</li>
|
||||
<li>FFI: Compile and optimize array/struct copies.</li>
|
||||
<li>FFI: Compile <tt>ffi.typeof(cdata|ctype)</tt>, <tt>ffi.sizeof()</tt>, <tt>ffi.alignof()</tt>, <tt>ffi.offsetof()</tt> and <tt>ffi.gc()</tt>.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta10">LuaJIT 2.0.0-beta10 — 2012-05-09</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>The MIPS of LuaJIT is complete. It requires a CPU conforming to the
|
||||
MIPS32 R1 architecture with hardware FPU. O32 hard-fp ABI,
|
||||
little-endian or big-endian.</li>
|
||||
<li>Auto-detect target arch via cross-compiler. No need for
|
||||
<tt>TARGET=arch</tt> anymore.</li>
|
||||
<li>Make DynASM compatible with Lua 5.2.</li>
|
||||
<li>From Lua 5.2: Try <tt>__tostring</tt> metamethod on non-string error
|
||||
messages..</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix parsing of hex literals with exponents.</li>
|
||||
<li>Fix bytecode dump for certain number constants.</li>
|
||||
<li>Fix argument type in error message for relative arguments.</li>
|
||||
<li>Fix argument error handling on Lua stacks without a frame.</li>
|
||||
<li>Add missing mcode limit check in assembler backend.</li>
|
||||
<li>Fix compilation on OpenBSD.</li>
|
||||
<li>Avoid recursive GC steps after GC-triggered trace exit.</li>
|
||||
<li>Replace <tt><unwind.h></tt> definitions with our own.</li>
|
||||
<li>Fix OSX build issues. Bump minimum required OSX version to 10.4.</li>
|
||||
<li>Fix discharge order of comparisons in Lua parser.</li>
|
||||
<li>Ensure running <tt>__gc</tt> of userdata created in <tt>__gc</tt>
|
||||
at state close.</li>
|
||||
<li>Limit number of userdata <tt>__gc</tt> separations at state close.</li>
|
||||
<li>Fix bytecode <tt>JMP</tt> slot range when optimizing
|
||||
<tt>and</tt>/<tt>or</tt> with constant LHS.</li>
|
||||
<li>Fix DSE of <tt>USTORE</tt>.</li>
|
||||
<li>Make <tt>lua_concat()</tt> work from C hook with partial frame.</li>
|
||||
<li>Add required PHIs for implicit conversions, e.g. via <tt>XREF</tt>
|
||||
forwarding.</li>
|
||||
<li>Add more comparison variants to Valgrind suppressions file.</li>
|
||||
<li>Disable loading bytecode with an extra header (BOM or <tt>#!</tt>).</li>
|
||||
<li>Fix PHI stack slot syncing.</li>
|
||||
<li>ARM: Reorder type/value tests to silence Valgrind.</li>
|
||||
<li>ARM: Fix register allocation for <tt>ldrd</tt>-optimized
|
||||
<tt>HREFK</tt>.</li>
|
||||
<li>ARM: Fix conditional branch fixup for <tt>OBAR</tt>.</li>
|
||||
<li>ARM: Invoke SPLIT pass for <tt>double</tt> args in FFI call.</li>
|
||||
<li>ARM: Handle all <tt>CALL*</tt> ops with <tt>double</tt> results in
|
||||
SPLIT pass.</li>
|
||||
<li>ARM: Fix rejoin of <tt>POW</tt> in SPLIT pass.</li>
|
||||
<li>ARM: Fix compilation of <tt>math.sinh</tt>, <tt>math.cosh</tt>,
|
||||
<tt>math.tanh</tt>.</li>
|
||||
<li>ARM, PPC: Avoid pointless arg clearing in <tt>BC_IFUNCF</tt>.</li>
|
||||
<li>PPC: Fix resume after yield from hook.</li>
|
||||
<li>PPC: Fix argument checking for <tt>rawget()</tt>.</li>
|
||||
<li>PPC: Fix fusion of floating-point <tt>XLOAD</tt>/<tt>XSTORE</tt>.</li>
|
||||
<li>PPC: Fix <tt>HREFK</tt> code generation for huge tables.</li>
|
||||
<li>PPC: Use builtin D-Cache/I-Cache sync code.</li>
|
||||
</ul></li>
|
||||
<li>FFI library:
|
||||
<ul>
|
||||
<li>Ignore empty statements in <tt>ffi.cdef()</tt>.</li>
|
||||
<li>Ignore number parsing errors while skipping definitions.</li>
|
||||
<li>Don't touch frame in callbacks with tailcalls to fast functions.</li>
|
||||
<li>Fix library unloading on POSIX systems.</li>
|
||||
<li>Finalize cdata before userdata when closing the state.</li>
|
||||
<li>Change <tt>ffi.load()</tt> library name resolution for Cygwin.</li>
|
||||
<li>Fix resolving of function name redirects on Windows/x86.</li>
|
||||
<li>Fix symbol resolving error messages on Windows.</li>
|
||||
<li>Fix blacklisting of C functions calling callbacks.</li>
|
||||
<li>Fix result type of pointer difference.</li>
|
||||
<li>Use correct PC in FFI metamethod error message.</li>
|
||||
<li>Allow <tt>'typedef _Bool int BOOL;'</tt> for the Windows API.</li>
|
||||
<li>Don't record test for bool result of call, if ignored.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta9">LuaJIT 2.0.0-beta9 — 2011-12-14</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>PPC port of LuaJIT is complete. Default is the dual-number port
|
||||
(usually faster). Single-number port selectable via <tt>src/Makefile</tt>
|
||||
at build time.</li>
|
||||
<li>Add FFI callback support.</li>
|
||||
<li>Extend <tt>-b</tt> to generate <tt>.c</tt>, <tt>.h</tt> or <tt>.obj/.o</tt>
|
||||
files with embedded bytecode.</li>
|
||||
<li>Allow loading embedded bytecode with <tt>require()</tt>.</li>
|
||||
<li>From Lua 5.2: Change to <tt>'\z'</tt> escape. Reject undefined escape
|
||||
sequences.</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix OSX 10.7 build. Fix <tt>install_name</tt> and versioning on OSX.</li>
|
||||
<li>Fix iOS build.</li>
|
||||
<li>Install <tt>dis_arm.lua</tt>, too.</li>
|
||||
<li>Mark installed shared library as executable.</li>
|
||||
<li>Add debug option to <tt>msvcbuild.bat</tt> and improve error handling.</li>
|
||||
<li>Fix data-flow analysis for iterators.</li>
|
||||
<li>Fix forced unwinding triggered by external unwinder.</li>
|
||||
<li>Record missing <tt>for</tt> loop slot loads (return to lower frame).</li>
|
||||
<li>Always use ANSI variants of Windows system functions.</li>
|
||||
<li>Fix GC barrier for multi-result table constructor (<tt>TSETM</tt>).</li>
|
||||
<li>Fix/add various FOLD rules.</li>
|
||||
<li>Add potential PHI for number conversions due to type instability.</li>
|
||||
<li>Do not eliminate PHIs only referenced from other PHIs.</li>
|
||||
<li>Correctly anchor implicit number to string conversions in Lua/C API.</li>
|
||||
<li>Fix various stack limit checks.</li>
|
||||
<li>x64: Use thread-safe exceptions for external unwinding (GCC platforms).</li>
|
||||
<li>x64: Fix result type of cdata index conversions.</li>
|
||||
<li>x64: Fix <tt>math.random()</tt> and <tt>bit.bswap()</tt> code generation.</li>
|
||||
<li>x64: Fix <tt>lightuserdata</tt> comparisons.</li>
|
||||
<li>x64: Always extend stack-passed arguments to pointer size.</li>
|
||||
<li>ARM: Many fixes to code generation backend.</li>
|
||||
<li>PPC/e500: Fix dispatch for binop metamethods.</li>
|
||||
<li>PPC/e500: Save/restore condition registers when entering/leaving the VM.</li>
|
||||
<li>PPC/e500: Fix write barrier in stores of strings to upvalues.</li>
|
||||
</ul></li>
|
||||
<li>FFI library:
|
||||
<ul>
|
||||
<li>Fix C comment parsing.</li>
|
||||
<li>Fix snapshot optimization for cdata comparisons.</li>
|
||||
<li>Fix recording of const/enum lookups in namespaces.</li>
|
||||
<li>Fix call argument and return handling for <tt>I8/U8/I16/U16</tt> types.</li>
|
||||
<li>Fix unfused loads of float fields.</li>
|
||||
<li>Fix <tt>ffi.string()</tt> recording.</li>
|
||||
<li>Save <tt>GetLastError()</tt> around <tt>ffi.load()</tt> and symbol
|
||||
resolving, too.</li>
|
||||
<li>Improve ld script detection in <tt>ffi.load()</tt>.</li>
|
||||
<li>Record loads/stores to external variables in namespaces.</li>
|
||||
<li>Compile calls to stdcall, fastcall and vararg functions.</li>
|
||||
<li>Treat function ctypes like pointers in comparisons.</li>
|
||||
<li>Resolve <tt>__call</tt> metamethod for pointers, too.</li>
|
||||
<li>Record C function calls with bool return values.</li>
|
||||
<li>Record <tt>ffi.errno()</tt>.</li>
|
||||
<li>x86: Fix number to <tt>uint32_t</tt> conversion rounding.</li>
|
||||
<li>x86: Fix 64 bit arithmetic in assembler backend.</li>
|
||||
<li>x64: Fix struct-by-value calling conventions.</li>
|
||||
<li>ARM: Ensure invocation of SPLIT pass for float conversions.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Display trace types with <tt>-jv</tt> and <tt>-jdump</tt>.</li>
|
||||
<li>Record isolated calls. But prefer recording loops over calls.</li>
|
||||
<li>Specialize to prototype for non-monomorphic functions. Solves the
|
||||
trace-explosion problem for closure-heavy programming styles.</li>
|
||||
<li>Always generate a portable <tt>vmdef.lua</tt>. Easier for distros.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta8">LuaJIT 2.0.0-beta8 — 2011-06-23</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>Soft-float ARM port of LuaJIT is complete.</li>
|
||||
<li>Add support for bytecode loading/saving and <tt>-b</tt> command line
|
||||
option.</li>
|
||||
<li>From Lua 5.2: <tt>__len</tt> metamethod for tables
|
||||
(disabled by default).</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>ARM: Misc. fixes for interpreter.</li>
|
||||
<li>x86/x64: Fix <tt>bit.*</tt> argument checking in interpreter.</li>
|
||||
<li>Catch early out-of-memory in memory allocator initialization.</li>
|
||||
<li>Fix data-flow analysis for paths leading to an upvalue close.</li>
|
||||
<li>Fix check for missing arguments in <tt>string.format()</tt>.</li>
|
||||
<li>Fix Solaris/x86 build (note: not a supported target).</li>
|
||||
<li>Fix recording of loops with instable directions in side traces.</li>
|
||||
<li>x86/x64: Fix fusion of comparisons with <tt>u8</tt>/<tt>u16</tt>
|
||||
<tt>XLOAD</tt>.</li>
|
||||
<li>x86/x64: Fix register allocation for variable shifts.</li>
|
||||
</ul></li>
|
||||
<li>FFI library:
|
||||
<ul>
|
||||
<li>Add <tt>ffi.errno()</tt>. Save <tt>errno</tt>/<tt>GetLastError()</tt>
|
||||
around allocations etc.</li>
|
||||
<li>Fix <tt>__gc</tt> for VLA/VLS cdata objects.</li>
|
||||
<li>Fix recording of casts from 32 bit cdata pointers to integers.</li>
|
||||
<li><tt>tonumber(cdata)</tt> returns <tt>nil</tt> for non-numbers.</li>
|
||||
<li>Show address pointed to for <tt>tostring(pointer)</tt>.</li>
|
||||
<li>Print <tt>NULL</tt> pointers as <tt>"cdata<... *>: NULL"</tt>.</li>
|
||||
<li>Support <tt>__tostring</tt> metamethod for pointers to structs, too.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>More tuning for loop unrolling heuristics.</li>
|
||||
<li>Flatten and compress in-memory debug info (saves ~70%).</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta7">LuaJIT 2.0.0-beta7 — 2011-05-05</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>ARM port of the LuaJIT interpreter is complete.</li>
|
||||
<li>FFI library: Add <tt>ffi.gc()</tt>, <tt>ffi.metatype()</tt>,
|
||||
<tt>ffi.istype()</tt>.</li>
|
||||
<li>FFI library: Resolve ld script redirection in <tt>ffi.load()</tt>.</li>
|
||||
<li>From Lua 5.2: <tt>package.searchpath()</tt>, <tt>fp:read("*L")</tt>,
|
||||
<tt>load(string)</tt>.</li>
|
||||
<li>From Lua 5.2, disabled by default: empty statement,
|
||||
<tt>table.unpack()</tt>, modified <tt>coroutine.running()</tt>.</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>FFI library: numerous fixes.</li>
|
||||
<li>Fix type mismatches in store-to-load forwarding.</li>
|
||||
<li>Fix error handling within metamethods.</li>
|
||||
<li>Fix <tt>table.maxn()</tt>.</li>
|
||||
<li>Improve accuracy of <tt>x^-k</tt> on x64.</li>
|
||||
<li>Fix code generation for Intel Atom in x64 mode.</li>
|
||||
<li>Fix narrowing of POW.</li>
|
||||
<li>Fix recording of retried fast functions.</li>
|
||||
<li>Fix code generation for <tt>bit.bnot()</tt> and multiplies.</li>
|
||||
<li>Fix error location within cpcall frames.</li>
|
||||
<li>Add workaround for old libgcc unwind bug.</li>
|
||||
<li>Fix <tt>lua_yield()</tt> and <tt>getmetatable(lightuserdata)</tt> on x64.</li>
|
||||
<li>Misc. fixes for PPC/e500 interpreter.</li>
|
||||
<li>Fix stack slot updates for down-recursion.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Add dual-number mode (int/double) for the VM. Enabled for ARM.</li>
|
||||
<li>Improve narrowing of arithmetic operators and <tt>for</tt> loops.</li>
|
||||
<li>Tune loop unrolling heuristics and increase trace recorder limits.</li>
|
||||
<li>Eliminate dead slots in snapshots using bytecode data-flow analysis.</li>
|
||||
<li>Avoid phantom stores to proxy tables.</li>
|
||||
<li>Optimize lookups in empty proxy tables.</li>
|
||||
<li>Improve bytecode optimization of <tt>and</tt>/<tt>or</tt> operators.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta6">LuaJIT 2.0.0-beta6 — 2011-02-11</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>PowerPC/e500v2 port of the LuaJIT interpreter is complete.</li>
|
||||
<li>Various minor features from Lua 5.2: Hex escapes in literals,
|
||||
<tt>'\*'</tt> escape, reversible <tt>string.format("%q",s)</tt>,
|
||||
<tt>"%g"</tt> pattern, <tt>table.sort</tt> checks callbacks,
|
||||
<tt>os.exit(status|true|false[,close])</tt>.</li>
|
||||
<li>Lua 5.2 <tt>__pairs</tt> and <tt>__ipairs</tt> metamethods
|
||||
(disabled by default).</li>
|
||||
<li>Initial release of the FFI library.</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix <tt>string.format()</tt> for non-finite numbers.</li>
|
||||
<li>Fix memory leak when compiled to use the built-in allocator.</li>
|
||||
<li>x86/x64: Fix unnecessary resize in <tt>TSETM</tt> bytecode.</li>
|
||||
<li>Fix various GC issues with traces and <tt>jit.flush()</tt>.</li>
|
||||
<li>x64: Fix fusion of indexes for array references.</li>
|
||||
<li>x86/x64: Fix stack overflow handling for coroutine results.</li>
|
||||
<li>Enable low-2GB memory allocation on FreeBSD/x64.</li>
|
||||
<li>Fix <tt>collectgarbage("count")</tt> result if more than 2GB is in use.</li>
|
||||
<li>Fix parsing of hex floats.</li>
|
||||
<li>x86/x64: Fix loop branch inversion with trailing
|
||||
<tt>HREF+NE/EQ</tt>.</li>
|
||||
<li>Add <tt>jit.os</tt> string.</li>
|
||||
<li><tt>coroutine.create()</tt> permits running C functions, too.</li>
|
||||
<li>Fix OSX build to work with newer ld64 versions.</li>
|
||||
<li>Fix bytecode optimization of <tt>and</tt>/<tt>or</tt> operators.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Emit specialized bytecode for <tt>pairs()</tt>/<tt>next()</tt>.</li>
|
||||
<li>Improve bytecode coalescing of <tt>nil</tt> constants.</li>
|
||||
<li>Compile calls to vararg functions.</li>
|
||||
<li>Compile <tt>select()</tt>.</li>
|
||||
<li>Improve alias analysis, esp. for loads from allocations.</li>
|
||||
<li>Tuning of various compiler heuristics.</li>
|
||||
<li>Refactor and extend IR conversion instructions.</li>
|
||||
<li>x86/x64: Various backend enhancements related to the FFI.</li>
|
||||
<li>Add SPLIT pass to split 64 bit IR instructions for 32 bit CPUs.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta5">LuaJIT 2.0.0-beta5 — 2010-08-24</h2>
|
||||
<ul>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix trace exit dispatch to function headers.</li>
|
||||
<li>Fix Windows and OSX builds with LUAJIT_DISABLE_JIT.</li>
|
||||
<li>Reorganize and fix placement of generated machine code on x64.</li>
|
||||
<li>Fix TNEW in x64 interpreter.</li>
|
||||
<li>Do not eliminate PHIs for values only referenced from side exits.</li>
|
||||
<li>OS-independent canonicalization of strings for non-finite numbers.</li>
|
||||
<li>Fix <tt>string.char()</tt> range check on x64.</li>
|
||||
<li>Fix <tt>tostring()</tt> resolving within <tt>print()</tt>.</li>
|
||||
<li>Fix error handling for <tt>next()</tt>.</li>
|
||||
<li>Fix passing of constant arguments to external calls on x64.</li>
|
||||
<li>Fix interpreter argument check for two-argument SSE math functions.</li>
|
||||
<li>Fix C frame chain corruption caused by <tt>lua_cpcall()</tt>.</li>
|
||||
<li>Fix return from <tt>pcall()</tt> within active hook.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Replace on-trace GC frame syncing with interpreter exit.</li>
|
||||
<li>Improve hash lookup specialization by not removing dead keys during GC.</li>
|
||||
<li>Turn traces into true GC objects.</li>
|
||||
<li>Avoid starting a GC cycle immediately after library init.</li>
|
||||
<li>Add weak guards to improve dead-code elimination.</li>
|
||||
<li>Speed up string interning.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta4">LuaJIT 2.0.0-beta4 — 2010-03-28</h2>
|
||||
<ul>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix precondition for on-trace creation of table keys.</li>
|
||||
<li>Fix <tt>{f()}</tt> on x64 when table is resized.</li>
|
||||
<li>Fix folding of ordered comparisons with same references.</li>
|
||||
<li>Fix snapshot restores for multi-result bytecodes.</li>
|
||||
<li>Fix potential hang when recording bytecode with nested closures.</li>
|
||||
<li>Fix recording of <tt>getmetatable()</tt>, <tt>tonumber()</tt> and bad argument types.</li>
|
||||
<li>Fix SLOAD fusion across returns to lower frames.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Add array bounds check elimination. <tt>-Oabc</tt> is enabled by default.</li>
|
||||
<li>More tuning for x64, e.g. smaller table objects.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta3">LuaJIT 2.0.0-beta3 — 2010-03-07</h2>
|
||||
<ul>
|
||||
<li>LuaJIT x64 port:
|
||||
<ul>
|
||||
<li>Port integrated memory allocator to Linux/x64, Windows/x64 and OSX/x64.</li>
|
||||
<li>Port interpreter and JIT compiler to x64.</li>
|
||||
<li>Port DynASM to x64.</li>
|
||||
<li>Many 32/64 bit cleanups in the VM.</li>
|
||||
<li>Allow building the interpreter with either x87 or SSE2 arithmetics.</li>
|
||||
<li>Add external unwinding and C++ exception interop (default on x64).</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix constructor bytecode generation for certain conditional values.</li>
|
||||
<li>Fix some cases of ordered string comparisons.</li>
|
||||
<li>Fix <tt>lua_tocfunction()</tt>.</li>
|
||||
<li>Fix cutoff register in JMP bytecode for some conditional expressions.</li>
|
||||
<li>Fix PHI marking algorithm for references from variant slots.</li>
|
||||
<li>Fix <tt>package.cpath</tt> for non-default PREFIX.</li>
|
||||
<li>Fix DWARF2 frame unwind information for interpreter on OSX.</li>
|
||||
<li>Drive the GC forward on string allocations in the parser.</li>
|
||||
<li>Implement call/return hooks (zero-cost if disabled).</li>
|
||||
<li>Implement yield from C hooks.</li>
|
||||
<li>Disable JIT compiler on older non-SSE2 CPUs instead of aborting.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Compile recursive code (tail-, up- and down-recursion).</li>
|
||||
<li>Improve heuristics for bytecode penalties and blacklisting.</li>
|
||||
<li>Split CALL/FUNC recording and clean up fast function call semantics.</li>
|
||||
<li>Major redesign of internal function call handling.</li>
|
||||
<li>Improve FOR loop const specialization and integerness checks.</li>
|
||||
<li>Switch to pre-initialized stacks. Avoid frame-clearing.</li>
|
||||
<li>Colocation of prototypes and related data: bytecode, constants, debug info.</li>
|
||||
<li>Cleanup parser and streamline bytecode generation.</li>
|
||||
<li>Add support for weak IR references to register allocator.</li>
|
||||
<li>Switch to compressed, extensible snapshots.</li>
|
||||
<li>Compile returns to frames below the start frame.</li>
|
||||
<li>Improve alias analysis of upvalues using a disambiguation hash value.</li>
|
||||
<li>Compile floor/ceil/trunc to SSE2 helper calls or SSE4.1 instructions.</li>
|
||||
<li>Add generic C call handling to IR and backend.</li>
|
||||
<li>Improve KNUM fuse vs. load heuristics.</li>
|
||||
<li>Compile various <tt>io.*()</tt> functions.</li>
|
||||
<li>Compile <tt>math.sinh()</tt>, <tt>math.cosh()</tt>, <tt>math.tanh()</tt>
|
||||
and <tt>math.random()</tt>.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta2">LuaJIT 2.0.0-beta2 — 2009-11-09</h2>
|
||||
<ul>
|
||||
<li>Reorganize build system. Build static+shared library on POSIX.</li>
|
||||
<li>Allow C++ exception conversion on all platforms
|
||||
using a wrapper function.</li>
|
||||
<li>Automatically catch C++ exceptions and rethrow Lua error
|
||||
(DWARF2 only).</li>
|
||||
<li>Check for the correct x87 FPU precision at strategic points.</li>
|
||||
<li>Always use wrappers for libm functions.</li>
|
||||
<li>Resurrect metamethod name strings before copying them.</li>
|
||||
<li>Mark current trace, even if compiler is idle.</li>
|
||||
<li>Ensure FILE metatable is created only once.</li>
|
||||
<li>Fix type comparisons when different integer types are involved.</li>
|
||||
<li>Fix <tt>getmetatable()</tt> recording.</li>
|
||||
<li>Fix TDUP with dead keys in template table.</li>
|
||||
<li><tt>jit.flush(tr)</tt> returns status.
|
||||
Prevent manual flush of a trace that's still linked.</li>
|
||||
<li>Improve register allocation heuristics for invariant references.</li>
|
||||
<li>Compile the push/pop variants of <tt>table.insert()</tt> and
|
||||
<tt>table.remove()</tt>.</li>
|
||||
<li>Compatibility with MSVC <tt>link /debug</tt>.</li>
|
||||
<li>Fix <tt>lua_iscfunction()</tt>.</li>
|
||||
<li>Fix <tt>math.random()</tt> when compiled with <tt>-fpic</tt> (OSX).</li>
|
||||
<li>Fix <tt>table.maxn()</tt>.</li>
|
||||
<li>Bump <tt>MACOSX_DEPLOYMENT_TARGET</tt> to <tt>10.4</tt></li>
|
||||
<li><tt>luaL_check*()</tt> and <tt>luaL_opt*()</tt> now support
|
||||
negative arguments, too.<br>
|
||||
This matches the behavior of Lua 5.1, but not the specification.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta1">LuaJIT 2.0.0-beta1 — 2009-10-31</h2>
|
||||
<ul>
|
||||
<li>This is the first public release of LuaJIT 2.0.</li>
|
||||
<li>The whole VM has been rewritten from the ground up, so there's
|
||||
no point in listing differences over earlier versions.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,15 +3,14 @@
|
||||
<head>
|
||||
<title>Contact</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Contact</h1>
|
||||
@@ -20,7 +19,7 @@
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -46,23 +45,25 @@
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
If you want to report bugs, propose fixes or suggest enhancements,
|
||||
please use the
|
||||
<a href="https://github.com/LuaJIT/LuaJIT/issues"><span class="ext">»</span> GitHub issue tracker</a>.
|
||||
</p>
|
||||
<p>
|
||||
Please send general questions to the
|
||||
<a href="http://luajit.org/list.html"><span class="ext">»</span> LuaJIT mailing list</a>.
|
||||
<a href="https://luajit.org/list.html"><span class="ext">»</span> LuaJIT mailing list</a>.
|
||||
</p>
|
||||
<p>
|
||||
You can also send any questions you have directly to me:
|
||||
</p>
|
||||
|
||||
@@ -86,7 +87,7 @@ xD("fyZKB8xv\"FJytmz8.KAB0u52D")
|
||||
<h2>Copyright</h2>
|
||||
<p>
|
||||
All documentation is
|
||||
Copyright © 2005-2015 Mike Pall.
|
||||
Copyright © 2005-2021 Mike Pall.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -94,7 +95,7 @@ Copyright © 2005-2015 Mike Pall.
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,15 +3,14 @@
|
||||
<head>
|
||||
<title>Lua/C API Extensions</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Lua/C API Extensions</h1>
|
||||
@@ -20,7 +19,7 @@
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -46,17 +45,12 @@
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
@@ -91,8 +85,8 @@ other Lua/C API functions).
|
||||
</p>
|
||||
<p>
|
||||
The third argument specifies the mode, which is 'or'ed with a flag.
|
||||
The flag can be <tt>LUAJIT_MODE_OFF</tt> to turn a feature on,
|
||||
<tt>LUAJIT_MODE_ON</tt> to turn a feature off, or
|
||||
The flag can be <tt>LUAJIT_MODE_OFF</tt> to turn a feature off,
|
||||
<tt>LUAJIT_MODE_ON</tt> to turn a feature on, or
|
||||
<tt>LUAJIT_MODE_FLUSH</tt> to flush cached code.
|
||||
</p>
|
||||
<p>
|
||||
@@ -179,7 +173,7 @@ Also note that this mechanism is not without overhead.
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,15 +3,14 @@
|
||||
<head>
|
||||
<title>FFI Library</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>FFI Library</h1>
|
||||
@@ -20,7 +19,7 @@
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -46,17 +45,12 @@
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
@@ -322,7 +316,7 @@ without undue conversion penalties.
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<head>
|
||||
<title>ffi.* API Functions</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
@@ -16,7 +15,7 @@ td.abiparam { font-weight: bold; width: 6em; }
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1><tt>ffi.*</tt> API Functions</h1>
|
||||
@@ -25,7 +24,7 @@ td.abiparam { font-weight: bold; width: 6em; }
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -51,17 +50,12 @@ td.abiparam { font-weight: bold; width: 6em; }
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
@@ -261,7 +255,7 @@ contents of an <tt>__index</tt> table (if any) may be modified
|
||||
afterwards. The associated metatable automatically applies to all uses
|
||||
of this type, no matter how the objects are created or where they
|
||||
originate from. Note that pre-defined operations on types have
|
||||
precedence (e.g. declared field names cannot be overriden).
|
||||
precedence (e.g. declared field names cannot be overridden).
|
||||
</p>
|
||||
<p>
|
||||
All standard Lua metamethods are implemented. These are called directly,
|
||||
@@ -469,6 +463,8 @@ otherwise. The following parameters are currently defined:
|
||||
<tr class="odd">
|
||||
<td class="abiparam">win</td><td class="abidesc">Windows variant of the standard ABI</td></tr>
|
||||
<tr class="even">
|
||||
<td class="abiparam">uwp</td><td class="abidesc">Universal Windows Platform</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="abiparam">gc64</td><td class="abidesc">64 bit GC references</td></tr>
|
||||
</table>
|
||||
|
||||
@@ -560,7 +556,7 @@ named <tt>i</tt>.
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<head>
|
||||
<title>FFI Semantics</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
@@ -16,7 +15,7 @@ td.convop { font-style: italic; width: 40%; }
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>FFI Semantics</h1>
|
||||
@@ -25,7 +24,7 @@ td.convop { font-style: italic; width: 40%; }
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -51,17 +50,12 @@ td.convop { font-style: italic; width: 40%; }
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
@@ -678,7 +672,7 @@ through unions is explicitly detected and allowed.
|
||||
<a href="ext_ffi_api.html#ffi_new">constructor</a>. This is equivalent
|
||||
to <tt>ffi.new(ct, ...)</tt>, unless a <tt>__new</tt> metamethod is
|
||||
defined. The <tt>__new</tt> metamethod is called with the ctype object
|
||||
plus any other arguments passed to the contructor. Note that you have to
|
||||
plus any other arguments passed to the constructor. Note that you have to
|
||||
use <tt>ffi.new</tt> inside of it, since calling <tt>ct(...)</tt> would
|
||||
cause infinite recursion.</li>
|
||||
|
||||
@@ -864,7 +858,7 @@ place of a type, you'd need to use <tt>ffi.typeof("int")</tt> instead.
|
||||
<p>
|
||||
The main use for parameterized types are libraries implementing abstract
|
||||
data types
|
||||
(<a href="http://www.freelists.org/post/luajit/ffi-type-of-pointer-to,8"><span class="ext">»</span> example</a>),
|
||||
(<a href="https://www.freelists.org/post/luajit/ffi-type-of-pointer-to,8"><span class="ext">»</span> example</a>),
|
||||
similar to what can be achieved with C++ template metaprogramming.
|
||||
Another use case are derived types of anonymous structs, which avoids
|
||||
pollution of the global struct namespace.
|
||||
@@ -1221,13 +1215,12 @@ The following operations are currently not compiled and may exhibit
|
||||
suboptimal performance, especially when used in inner loops:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Bitfield accesses and initializations.</li>
|
||||
<li>Vector operations.</li>
|
||||
<li>Table initializers.</li>
|
||||
<li>Initialization of nested <tt>struct</tt>/<tt>union</tt> types.</li>
|
||||
<li>Non-default initialization of VLA/VLS or large C types
|
||||
(> 128 bytes or > 16 array elements.</li>
|
||||
<li>Conversions from lightuserdata to <tt>void *</tt>.</li>
|
||||
(> 128 bytes or > 16 array elements).</li>
|
||||
<li>Bitfield initializations.</li>
|
||||
<li>Pointer differences for element sizes that are not a power of
|
||||
two.</li>
|
||||
<li>Calls to C functions with aggregates passed or returned by
|
||||
@@ -1253,7 +1246,7 @@ compiled.</li>
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<head>
|
||||
<title>FFI Tutorial</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
@@ -18,7 +17,7 @@ td.idiomlua b { font-weight: normal; color: #2142bf; }
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>FFI Tutorial</h1>
|
||||
@@ -27,7 +26,7 @@ td.idiomlua b { font-weight: normal; color: #2142bf; }
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -53,17 +52,12 @@ td.idiomlua b { font-weight: normal; color: #2142bf; }
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
@@ -222,7 +216,7 @@ a fascinating best-selling game is left as an exercise for the reader.
|
||||
<h2 id="zlib">Accessing the zlib Compression Library</h2>
|
||||
<p>
|
||||
The following code shows how to access the <a
|
||||
href="http://zlib.net/">zlib</a> compression library from Lua code.
|
||||
href="https://zlib.net/"><span class="ext">»</span> zlib</a> compression library from Lua code.
|
||||
We'll define two convenience wrapper functions that take a string and
|
||||
compress or uncompress it to another string:
|
||||
</p>
|
||||
@@ -305,7 +299,7 @@ comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any
|
||||
missing standard prefixes/suffixes, we can simply load the
|
||||
<tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and
|
||||
you'll have to download it first from the
|
||||
<a href="http://zlib.net/"><span class="ext">»</span> zlib site</a>. The check for
|
||||
<a href="https://zlib.net/"><span class="ext">»</span> zlib site</a>. The check for
|
||||
<tt>ffi.os</tt> makes sure we pass the right name to
|
||||
<tt>ffi.load()</tt>.
|
||||
</p>
|
||||
@@ -593,7 +587,7 @@ it to a local variable in the function scope is unnecessary.
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,15 +3,14 @@
|
||||
<head>
|
||||
<title>jit.* Library</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1><tt>jit.*</tt> Library</h1>
|
||||
@@ -20,7 +19,7 @@
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -46,17 +45,12 @@
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
@@ -153,7 +147,7 @@ Contains the target OS name:
|
||||
<h3 id="jit_arch"><tt>jit.arch</tt></h3>
|
||||
<p>
|
||||
Contains the target architecture name:
|
||||
"x86", "x64", "arm", "ppc", or "mips".
|
||||
"x86", "x64", "arm", "arm64", "arm64be", "ppc", "mips", "mipsel", "mips64", "mips64el", "mips64r6", "mips64r6el".
|
||||
</p>
|
||||
|
||||
<h2 id="jit_opt"><tt>jit.opt.*</tt> — JIT compiler optimization control</h2>
|
||||
@@ -191,7 +185,7 @@ if you want to know more.
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,15 +3,14 @@
|
||||
<head>
|
||||
<title>Profiler</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Profiler</h1>
|
||||
@@ -20,7 +19,7 @@
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -46,17 +45,12 @@
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
@@ -355,7 +349,7 @@ use.
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<head>
|
||||
<title>Extensions</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
@@ -28,7 +27,7 @@ td.excinterop {
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Extensions</h1>
|
||||
@@ -37,7 +36,7 @@ td.excinterop {
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -63,25 +62,20 @@ td.excinterop {
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
LuaJIT is fully upwards-compatible with Lua 5.1. It supports all
|
||||
<a href="http://www.lua.org/manual/5.1/manual.html#5"><span class="ext">»</span> standard Lua
|
||||
<a href="https://www.lua.org/manual/5.1/manual.html#5"><span class="ext">»</span> standard Lua
|
||||
library functions</a> and the full set of
|
||||
<a href="http://www.lua.org/manual/5.1/manual.html#3"><span class="ext">»</span> Lua/C API
|
||||
<a href="https://www.lua.org/manual/5.1/manual.html#3"><span class="ext">»</span> Lua/C API
|
||||
functions</a>.
|
||||
</p>
|
||||
<p>
|
||||
@@ -105,7 +99,7 @@ LuaJIT comes with several built-in extension modules:
|
||||
<h3 id="bit"><tt>bit.*</tt> — Bitwise operations</h3>
|
||||
<p>
|
||||
LuaJIT supports all bitwise operations as defined by
|
||||
<a href="http://bitop.luajit.org"><span class="ext">»</span> Lua BitOp</a>:
|
||||
<a href="https://bitop.luajit.org"><span class="ext">»</span> Lua BitOp</a>:
|
||||
</p>
|
||||
<pre class="code">
|
||||
bit.tobit bit.tohex bit.bnot bit.band bit.bor bit.bxor
|
||||
@@ -114,7 +108,7 @@ bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap
|
||||
<p>
|
||||
This module is a LuaJIT built-in — you don't need to download or
|
||||
install Lua BitOp. The Lua BitOp site has full documentation for all
|
||||
<a href="http://bitop.luajit.org/api.html"><span class="ext">»</span> Lua BitOp API functions</a>.
|
||||
<a href="https://bitop.luajit.org/api.html"><span class="ext">»</span> Lua BitOp API functions</a>.
|
||||
The FFI adds support for
|
||||
<a href="ext_ffi_semantics.html#cdata_arith">64 bit bitwise operations</a>,
|
||||
using the same API functions.
|
||||
@@ -209,8 +203,8 @@ bytecode (e.g. from Lua 5.1) is incompatible and cannot be loaded.
|
||||
</p>
|
||||
<p>
|
||||
Note: <tt>LJ_GC64</tt> mode requires a different frame layout, which implies
|
||||
a different, incompatible bytecode format for ports that use this mode (e.g.
|
||||
ARM64). This may be rectified in the future.
|
||||
a different, incompatible bytecode format for all 64 bit ports. This may be
|
||||
rectified in the future.
|
||||
</p>
|
||||
|
||||
<h3 id="table_new"><tt>table.new(narray, nhash)</tt> allocates a pre-sized table</h3>
|
||||
@@ -253,6 +247,10 @@ for every call. The result is uniformly distributed between 0.0 and 1.0.
|
||||
It's correctly scaled up and rounded for <tt>math.random(n [,m])</tt> to
|
||||
preserve uniformity.
|
||||
</p>
|
||||
<p>
|
||||
Important: Neither this nor any other PRNG based on the simplistic
|
||||
<tt>math.random()</tt> API is suitable for cryptographic use.
|
||||
</p>
|
||||
|
||||
<h3 id="io"><tt>io.*</tt> functions handle 64 bit file offsets</h3>
|
||||
<p>
|
||||
@@ -291,8 +289,8 @@ enabled:
|
||||
<li><tt>load(string|reader [, chunkname [,mode [,env]]])</tt>.</li>
|
||||
<li><tt>loadstring()</tt> is an alias for <tt>load()</tt>.</li>
|
||||
<li><tt>loadfile(filename [,mode [,env]])</tt>.</li>
|
||||
<li><tt>math.log(x [,base])</tt>.
|
||||
<li><tt>string.rep(s, n [,sep])</tt>.
|
||||
<li><tt>math.log(x [,base])</tt>.</li>
|
||||
<li><tt>string.rep(s, n [,sep])</tt>.</li>
|
||||
<li><tt>string.format()</tt>: <tt>%q</tt> reversible.
|
||||
<tt>%s</tt> checks <tt>__tostring</tt>.
|
||||
<tt>%a</tt> and <tt>"%A</tt> added.</li>
|
||||
@@ -311,6 +309,26 @@ indexes for varargs.</li>
|
||||
<li><tt>debug.getupvalue()</tt> and <tt>debug.setupvalue()</tt> handle
|
||||
C functions.</li>
|
||||
<li><tt>debug.upvalueid()</tt> and <tt>debug.upvaluejoin()</tt>.</li>
|
||||
<li>Lua/C API extensions:
|
||||
<tt>lua_version()</tt>
|
||||
<tt>lua_upvalueid()</tt>
|
||||
<tt>lua_upvaluejoin()</tt>
|
||||
<tt>lua_loadx()</tt>
|
||||
<tt>lua_copy()</tt>
|
||||
<tt>lua_tonumberx()</tt>
|
||||
<tt>lua_tointegerx()</tt>
|
||||
<tt>luaL_fileresult()</tt>
|
||||
<tt>luaL_execresult()</tt>
|
||||
<tt>luaL_loadfilex()</tt>
|
||||
<tt>luaL_loadbufferx()</tt>
|
||||
<tt>luaL_traceback()</tt>
|
||||
<tt>luaL_setfuncs()</tt>
|
||||
<tt>luaL_pushmodule()</tt>
|
||||
<tt>luaL_newlibtable()</tt>
|
||||
<tt>luaL_newlib()</tt>
|
||||
<tt>luaL_testudata()</tt>
|
||||
<tt>luaL_setmetatable()</tt>
|
||||
</li>
|
||||
<li>Command line option <tt>-E</tt>.</li>
|
||||
<li>Command line checks <tt>__tostring</tt> for errors.</li>
|
||||
</ul>
|
||||
@@ -335,7 +353,9 @@ instead of <tt>true</tt>.</li>
|
||||
exit status.</li>
|
||||
<li><tt>debug.setmetatable()</tt> returns object.</li>
|
||||
<li><tt>debug.getuservalue()</tt> and <tt>debug.setuservalue()</tt>.</li>
|
||||
<li>Remove <tt>math.mod()</tt>, <tt>string.gfind()</tt>.
|
||||
<li>Remove <tt>math.mod()</tt>, <tt>string.gfind()</tt>.</li>
|
||||
<li><tt>package.searchers</tt>.</li>
|
||||
<li><tt>module()</tt> returns the module table.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Note: this provides only partial compatibility with Lua 5.2 at the
|
||||
@@ -349,6 +369,14 @@ break the Lua/C API and ABI (e.g. <tt>_ENV</tt>).
|
||||
LuaJIT supports some extensions from Lua 5.3:
|
||||
<ul>
|
||||
<li>Unicode escape <tt>'\u{XX...}'</tt> embeds the UTF-8 encoding in string literals.</li>
|
||||
<li>The argument table <tt>arg</tt> can be read (and modified) by <tt>LUA_INIT</tt> and <tt>-e</tt> chunks.</li>
|
||||
<li><tt>io.read()</tt> and <tt>file:read()</tt> accept formats with or without a leading <tt>*</tt>.</li>
|
||||
<li><tt>assert()</tt> accepts any type of error object.</li>
|
||||
<li><tt>table.move(a1, f, e, t [,a2])</tt>.</li>
|
||||
<li><tt>coroutine.isyieldable()</tt>.</li>
|
||||
<li>Lua/C API extensions:
|
||||
<tt>lua_isyieldable()</tt>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="exceptions">C++ Exception Interoperability</h2>
|
||||
@@ -365,25 +393,30 @@ the toolchain used to compile LuaJIT:
|
||||
</tr>
|
||||
<tr class="odd separate">
|
||||
<td class="excplatform">POSIX/x64, DWARF2 unwinding</td>
|
||||
<td class="exccompiler">GCC 4.3+</td>
|
||||
<td class="exccompiler">GCC 4.3+, Clang</td>
|
||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="excplatform">ARM <tt>-DLUAJIT_UNWIND_EXTERNAL</tt></td>
|
||||
<td class="exccompiler">GCC, Clang</td>
|
||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td class="excplatform">Other platforms, DWARF2 unwinding</td>
|
||||
<td class="exccompiler">GCC</td>
|
||||
<td class="exccompiler">GCC, Clang</td>
|
||||
<td class="excinterop"><b style="color: #c06000;">Limited</b></td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<tr class="even">
|
||||
<td class="excplatform">Windows/x64</td>
|
||||
<td class="exccompiler">MSVC or WinSDK</td>
|
||||
<td class="exccompiler">MSVC</td>
|
||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td class="excplatform">Windows/x86</td>
|
||||
<td class="exccompiler">Any</td>
|
||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="excplatform">Windows/x86</td>
|
||||
<td class="exccompiler">Any</td>
|
||||
<td class="excinterop"><b style="color: #a00000;">No</b></td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td class="excplatform">Other platforms</td>
|
||||
<td class="exccompiler">Other compilers</td>
|
||||
<td class="excinterop"><b style="color: #a00000;">No</b></td>
|
||||
@@ -432,20 +465,12 @@ C++ destructors.</li>
|
||||
<li>Lua errors <b>cannot</b> be caught on the C++ side.</li>
|
||||
<li>Throwing Lua errors across C++ frames will <b>not</b> call
|
||||
C++ destructors.</li>
|
||||
<li>Additionally, on Windows/x86 with SEH-based C++ exceptions:
|
||||
it's <b>not</b> safe to throw a Lua error across any frames containing
|
||||
a C++ function with any try/catch construct or using variables with
|
||||
(implicit) destructors. This also applies to any functions which may be
|
||||
inlined in such a function. It doesn't matter whether <tt>lua_error()</tt>
|
||||
is called inside or outside of a try/catch or whether any object actually
|
||||
needs to be destroyed: the SEH chain is corrupted and this will eventually
|
||||
lead to the termination of the process.</li>
|
||||
</ul>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<head>
|
||||
<title>Frequently Asked Questions (FAQ)</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
@@ -14,7 +13,7 @@ dd { margin-left: 1.5em; }
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Frequently Asked Questions (FAQ)</h1>
|
||||
@@ -23,7 +22,7 @@ dd { margin-left: 1.5em; }
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -49,67 +48,60 @@ dd { margin-left: 1.5em; }
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a class="current" href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<dl>
|
||||
<dl id="info">
|
||||
<dt>Q: Where can I learn more about LuaJIT and Lua?</dt>
|
||||
<dd>
|
||||
<ul style="padding: 0;">
|
||||
<li>The <a href="http://luajit.org/list.html"><span class="ext">»</span> LuaJIT mailing list</a> focuses on topics
|
||||
<li>The <a href="https://luajit.org/list.html"><span class="ext">»</span> LuaJIT mailing list</a> focuses on topics
|
||||
related to LuaJIT.</li>
|
||||
<li>The <a href="http://wiki.luajit.org/"><span class="ext">»</span> LuaJIT wiki</a> gathers community
|
||||
resources about LuaJIT.</li>
|
||||
<li>News about Lua itself can be found at the
|
||||
<a href="http://www.lua.org/lua-l.html"><span class="ext">»</span> Lua mailing list</a>.
|
||||
<a href="https://www.lua.org/lua-l.html"><span class="ext">»</span> Lua mailing list</a>.
|
||||
The mailing list archives are worth checking out for older postings
|
||||
about LuaJIT.</li>
|
||||
<li>The <a href="http://lua.org"><span class="ext">»</span> main Lua.org site</a> has complete
|
||||
<a href="http://www.lua.org/docs.html"><span class="ext">»</span> documentation</a> of the language
|
||||
<li>The <a href="https://lua.org"><span class="ext">»</span> main Lua.org site</a> has complete
|
||||
<a href="https://www.lua.org/docs.html"><span class="ext">»</span> documentation</a> of the language
|
||||
and links to books and papers about Lua.</li>
|
||||
<li>The community-managed <a href="http://lua-users.org/wiki/"><span class="ext">»</span> Lua Wiki</a>
|
||||
has information about diverse topics.</li>
|
||||
</ul>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dl id="tech">
|
||||
<dt>Q: Where can I learn more about the compiler technology used by LuaJIT?</dt>
|
||||
<dd>
|
||||
I'm planning to write more documentation about the internals of LuaJIT.
|
||||
In the meantime, please use the following Google Scholar searches
|
||||
to find relevant papers:<br>
|
||||
Search for: <a href="http://scholar.google.com/scholar?q=Trace+Compiler"><span class="ext">»</span> Trace Compiler</a><br>
|
||||
Search for: <a href="http://scholar.google.com/scholar?q=JIT+Compiler"><span class="ext">»</span> JIT Compiler</a><br>
|
||||
Search for: <a href="http://scholar.google.com/scholar?q=Dynamic+Language+Optimizations"><span class="ext">»</span> Dynamic Language Optimizations</a><br>
|
||||
Search for: <a href="http://scholar.google.com/scholar?q=SSA+Form"><span class="ext">»</span> SSA Form</a><br>
|
||||
Search for: <a href="http://scholar.google.com/scholar?q=Linear+Scan+Register+Allocation"><span class="ext">»</span> Linear Scan Register Allocation</a><br>
|
||||
Here is a list of the <a href="http://article.gmane.org/gmane.comp.lang.lua.general/58908"><span class="ext">»</span> innovative features in LuaJIT</a>.<br>
|
||||
And, you know, reading the source is of course the only way to enlightenment. :-)
|
||||
Please use the following Google Scholar searches to find relevant papers:<br>
|
||||
Search for: <a href="https://scholar.google.com/scholar?q=Trace+Compiler"><span class="ext">»</span> Trace Compiler</a><br>
|
||||
Search for: <a href="https://scholar.google.com/scholar?q=JIT+Compiler"><span class="ext">»</span> JIT Compiler</a><br>
|
||||
Search for: <a href="https://scholar.google.com/scholar?q=Dynamic+Language+Optimizations"><span class="ext">»</span> Dynamic Language Optimizations</a><br>
|
||||
Search for: <a href="https://scholar.google.com/scholar?q=SSA+Form"><span class="ext">»</span> SSA Form</a><br>
|
||||
Search for: <a href="https://scholar.google.com/scholar?q=Linear+Scan+Register+Allocation"><span class="ext">»</span> Linear Scan Register Allocation</a><br>
|
||||
Here is a list of the <a href="http://lua-users.org/lists/lua-l/2009-11/msg00089.html"><span class="ext">»</span> innovative features in LuaJIT</a>.<br>
|
||||
And, you know, reading the source is of course the only way to enlightenment.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dl id="arg">
|
||||
<dt>Q: Why do I get this error: "attempt to index global 'arg' (a nil value)"?<br>
|
||||
Q: My vararg functions fail after switching to LuaJIT!</dt>
|
||||
<dd>LuaJIT is compatible to the Lua 5.1 language standard. It doesn't
|
||||
support the implicit <tt>arg</tt> parameter for old-style vararg
|
||||
functions from Lua 5.0.<br>Please convert your code to the
|
||||
<a href="http://www.lua.org/manual/5.1/manual.html#2.5.9"><span class="ext">»</span> Lua 5.1
|
||||
<a href="https://www.lua.org/manual/5.1/manual.html#2.5.9"><span class="ext">»</span> Lua 5.1
|
||||
vararg syntax</a>.</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dl id="x87">
|
||||
<dt>Q: Why do I get this error: "bad FPU precision"?<br>
|
||||
<dt>Q: I get weird behavior after initializing Direct3D.<br>
|
||||
<dt>Q: Some FPU operations crash after I load a Delphi DLL.<br>
|
||||
@@ -131,52 +123,59 @@ Please check the Delphi docs for the Set8087CW method.
|
||||
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dl id="ctrlc">
|
||||
<dt>Q: Sometimes Ctrl-C fails to stop my Lua program. Why?</dt>
|
||||
<dd>The interrupt signal handler sets a Lua debug hook. But this is
|
||||
currently ignored by compiled code (this will eventually be fixed). If
|
||||
your program is running in a tight loop and never falls back to the
|
||||
interpreter, the debug hook never runs and can't throw the
|
||||
"interrupted!" error.<br> In the meantime you have to press Ctrl-C
|
||||
twice to get stop your program. That's similar to when it's stuck
|
||||
running inside a C function under the Lua interpreter.</dd>
|
||||
ignored by compiled code. If your program is running in a tight loop
|
||||
and never falls back to the interpreter, the debug hook never runs and
|
||||
can't throw the "interrupted!" error.<br>
|
||||
You have to press Ctrl-C twice to get stop your program. That's similar
|
||||
to when it's stuck running inside a C function under the Lua interpreter.</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Q: Why doesn't my favorite power-patch for Lua apply against LuaJIT?</dt>
|
||||
<dd>Because it's a completely redesigned VM and has very little code
|
||||
in common with Lua anymore. Also, if the patch introduces changes to
|
||||
the Lua semantics, these would need to be reflected everywhere in the
|
||||
VM, from the interpreter up to all stages of the compiler.<br> Please
|
||||
use only standard Lua language constructs. For many common needs you
|
||||
can use source transformations or use wrapper or proxy functions.
|
||||
The compiler will happily optimize away such indirections.</dd>
|
||||
<dl id="sandbox">
|
||||
<dt>Q: Can Lua code be safely sandboxed?</dt>
|
||||
<dd>
|
||||
Maybe for an extremly restricted subset of Lua and if you relentlessly
|
||||
scrutinize every single interface function you offer to the untrusted code.<br>
|
||||
|
||||
Although Lua provides some sandboxing functionality (<tt>setfenv()</tt>, hooks),
|
||||
it's very hard to get this right even for the Lua core libraries. Of course,
|
||||
you'll need to inspect any extension library, too. And there are libraries
|
||||
that are inherently unsafe, e.g. the <a href="ext_ffi.html">FFI library</a>.<br>
|
||||
|
||||
More reading material at the <a href="http://lua-users.org/wiki/SandBoxes"><span class="ext">»</span> Lua Wiki</a> and <a href="https://en.wikipedia.org/wiki/Sandbox_(computer_security)"><span class="ext">»</span> Wikipedia</a>.<br><br>
|
||||
|
||||
Relatedly, <b>loading untrusted bytecode is not safe!</b><br>
|
||||
|
||||
It's trivial to crash the Lua or LuaJIT VM with maliciously crafted bytecode.
|
||||
This is well known and there's no bytecode verification on purpose, so please
|
||||
don't report a bug about it. Check the <tt>mode</tt> parameter for the
|
||||
<tt>load*()</tt> functions to disable loading of bytecode.<br><br>
|
||||
|
||||
<b>In general, the only promising approach is to sandbox Lua code at the
|
||||
process level and not the VM level.</b>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dl id="arch">
|
||||
<dt>Q: Lua runs everywhere. Why doesn't LuaJIT support my CPU?</dt>
|
||||
<dd>Because it's a compiler — it needs to generate native
|
||||
machine code. This means the code generator must be ported to each
|
||||
architecture. And the fast interpreter is written in assembler and
|
||||
must be ported, too. This is quite an undertaking.<br>
|
||||
The <a href="install.html">install documentation</a> shows the supported
|
||||
architectures. Other architectures will follow based on sufficient user
|
||||
demand and/or sponsoring.</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Q: When will feature X be added? When will the next version be released?</dt>
|
||||
<dd>When it's ready.<br>
|
||||
C'mon, it's open source — I'm doing it on my own time and you're
|
||||
getting it for free. You can either contribute a patch or sponsor
|
||||
the development of certain features, if they are important to you.
|
||||
</dd>
|
||||
architectures.<br>
|
||||
Other architectures may follow based on sufficient user demand and
|
||||
market-relevance of the architecture. Sponsoring is required to develop
|
||||
the port itself, to integrate it and to continuously maintain it in the
|
||||
actively developed branches.</dd>
|
||||
</dl>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<head>
|
||||
<title>Installation</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
@@ -39,7 +38,7 @@ td.compatno {
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Installation</h1>
|
||||
@@ -48,7 +47,7 @@ td.compatno {
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a class="current" href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -74,17 +73,12 @@ td.compatno {
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
@@ -109,22 +103,22 @@ operating systems, CPUs and compilers:
|
||||
<td class="compatcpu">CPU / OS</td>
|
||||
<td class="compatos"><a href="#posix">Linux</a> or<br><a href="#android">Android</a></td>
|
||||
<td class="compatos"><a href="#posix">*BSD, Other</a></td>
|
||||
<td class="compatos"><a href="#posix">OSX 10.4+</a> or<br><a href="#ios">iOS 3.0+</a></td>
|
||||
<td class="compatos"><a href="#windows">Windows<br>XP/Vista/7</a></td>
|
||||
<td class="compatos"><a href="#posix">macOS 10.4+</a> or<br><a href="#ios">iOS 3.0+</a></td>
|
||||
<td class="compatos"><a href="#windows">Windows 7<br>or later</a></td>
|
||||
</tr>
|
||||
<tr class="odd separate">
|
||||
<td class="compatcpu">x86 (32 bit)</td>
|
||||
<td class="compatos">GCC 4.2+</td>
|
||||
<td class="compatos">GCC 4.2+</td>
|
||||
<td class="compatos">XCode 5.0+<br>Clang</td>
|
||||
<td class="compatos">MSVC, MSVC/EE<br>WinSDK<br>MinGW, Cygwin</td>
|
||||
<td class="compatos">MSVC<br>MinGW, Cygwin</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="compatcpu">x64 (64 bit)</td>
|
||||
<td class="compatos">GCC 4.2+</td>
|
||||
<td class="compatos">ORBIS (<a href="#ps4">PS4</a>)</td>
|
||||
<td class="compatos">GCC 4.2+<br>ORBIS (<a href="#ps4">PS4</a>)</td>
|
||||
<td class="compatos">XCode 5.0+<br>Clang</td>
|
||||
<td class="compatos">MSVC + SDK v7.0<br>WinSDK v7.0<br>Durango (<a href="#xboxone">Xbox One</a>)</td>
|
||||
<td class="compatos">MSVC<br>Durango (<a href="#xboxone">Xbox One</a>)</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td class="compatcpu"><a href="#cross2">ARMv5+<br>ARM9E+</a></td>
|
||||
@@ -134,7 +128,7 @@ operating systems, CPUs and compilers:
|
||||
<td class="compatos compatno"> </td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="compatcpu"><a href="#cross2">ARM64</a></td>
|
||||
<td class="compatcpu"><a href="#cross2">ARM64<br>ARM64be</a></td>
|
||||
<td class="compatos">GCC 4.8+</td>
|
||||
<td class="compatos compatno"> </td>
|
||||
<td class="compatos">XCode 6.0+<br>Clang 3.5+</td>
|
||||
@@ -148,7 +142,7 @@ operating systems, CPUs and compilers:
|
||||
<td class="compatos">XEDK (<a href="#xbox360">Xbox 360</a>)</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="compatcpu"><a href="#cross2">MIPS</a></td>
|
||||
<td class="compatcpu"><a href="#cross2">MIPS32<br>MIPS64<br>MIPS64r6</a></td>
|
||||
<td class="compatos">GCC 4.3+</td>
|
||||
<td class="compatos">GCC 4.3+</td>
|
||||
<td class="compatos compatno"> </td>
|
||||
@@ -169,14 +163,21 @@ only).</li>
|
||||
<li><tt>src/Makefile</tt> has settings for <b>compiling</b> LuaJIT
|
||||
under POSIX, MinGW or Cygwin.</li>
|
||||
<li><tt>src/msvcbuild.bat</tt> has settings for compiling LuaJIT with
|
||||
MSVC or WinSDK.</li>
|
||||
MSVC (Visual Studio).</li>
|
||||
</ul>
|
||||
<p>
|
||||
Please read the instructions given in these files, before changing
|
||||
any settings.
|
||||
</p>
|
||||
<p>
|
||||
All LuaJIT 64 bit ports use 64 bit GC objects by default (<tt>LJ_GC64</tt>).
|
||||
For x64, you can select the old 32-on-64 bit mode by adding
|
||||
<tt>XCFLAGS=-DLUAJIT_DISABLE_GC64</tt> to the make command.
|
||||
Please check the note about the
|
||||
<a href="extensions.html#string_dump">bytecode format</a> differences, too.
|
||||
</p>
|
||||
|
||||
<h2 id="posix">POSIX Systems (Linux, OSX, *BSD etc.)</h2>
|
||||
<h2 id="posix">POSIX Systems (Linux, macOS, *BSD etc.)</h2>
|
||||
<h3>Prerequisites</h3>
|
||||
<p>
|
||||
Depending on your distribution, you may need to install a package for
|
||||
@@ -184,14 +185,15 @@ GCC, the development headers and/or a complete SDK. E.g. on a current
|
||||
Debian/Ubuntu, install <tt>libc6-dev</tt> with the package manager.
|
||||
</p>
|
||||
<p>
|
||||
Download the current source package of LuaJIT (pick the .tar.gz),
|
||||
if you haven't already done so. Move it to a directory of your choice,
|
||||
The recommended way to fetch the latest version is to do a pull from
|
||||
the git repository. Alternatively download the latest source package of
|
||||
LuaJIT (pick the .tar.gz). Move it to a directory of your choice,
|
||||
open a terminal window and change to this directory. Now unpack the archive
|
||||
and change to the newly created directory:
|
||||
</p>
|
||||
<pre class="code">
|
||||
tar zxf LuaJIT-2.0.4.tar.gz
|
||||
cd LuaJIT-2.0.4</pre>
|
||||
tar zxf LuaJIT-2.1.0-beta3.tar.gz
|
||||
cd LuaJIT-2.1.0-beta3</pre>
|
||||
<h3>Building LuaJIT</h3>
|
||||
<p>
|
||||
The supplied Makefiles try to auto-detect the settings needed for your
|
||||
@@ -202,7 +204,7 @@ which is probably the default on your system, anyway. Simply run:
|
||||
make
|
||||
</pre>
|
||||
<p>
|
||||
This always builds a native x86, x64 or PPC binary, depending on the host OS
|
||||
This always builds a native binary, depending on the host OS
|
||||
you're running this command on. Check the section on
|
||||
<a href="#cross">cross-compilation</a> for more options.
|
||||
</p>
|
||||
@@ -215,8 +217,8 @@ You can add an extra prefix to the search paths by appending the
|
||||
make PREFIX=/home/myself/lj2
|
||||
</pre>
|
||||
<p>
|
||||
Note for OSX: if the <tt>MACOSX_DEPLOYMENT_TARGET</tt> environment
|
||||
variable is not set, then it's forced to <tt>10.4</tt>.
|
||||
Note for macOS: you must set the <tt>MACOSX_DEPLOYMENT_TARGET</tt>
|
||||
environment variable to a value supported by your toolchain.
|
||||
</p>
|
||||
<h3>Installing LuaJIT</h3>
|
||||
<p>
|
||||
@@ -244,27 +246,18 @@ Obviously the prefixes given during build and installation need to be the same.
|
||||
<p>
|
||||
Either install one of the open source SDKs
|
||||
(<a href="http://mingw.org/"><span class="ext">»</span> MinGW</a> or
|
||||
<a href="http://www.cygwin.com/"><span class="ext">»</span> Cygwin</a>), which come with a modified
|
||||
<a href="https://www.cygwin.com/"><span class="ext">»</span> Cygwin</a>), which come with a modified
|
||||
GCC plus the required development headers.
|
||||
Or install Microsoft's Visual Studio (MSVC).
|
||||
</p>
|
||||
<p>
|
||||
Or install Microsoft's Visual C++ (MSVC). The freely downloadable
|
||||
<a href="http://www.microsoft.com/Express/VC/"><span class="ext">»</span> Express Edition</a>
|
||||
works just fine, but only contains an x86 compiler.
|
||||
</p>
|
||||
<p>
|
||||
The freely downloadable
|
||||
<a href="http://msdn.microsoft.com/en-us/windowsserver/bb980924.aspx"><span class="ext">»</span> Windows SDK</a>
|
||||
only comes with command line tools, but this is all you need to build LuaJIT.
|
||||
It contains x86 and x64 compilers.
|
||||
</p>
|
||||
<p>
|
||||
Next, download the source package and unpack it using an archive manager
|
||||
(e.g. the Windows Explorer) to a directory of your choice.
|
||||
Next, pull from the git repository or download the source package and
|
||||
unpack it using an archive manager (e.g. the Windows Explorer) to
|
||||
a directory of your choice.
|
||||
</p>
|
||||
<h3>Building with MSVC</h3>
|
||||
<p>
|
||||
Open a "Visual Studio .NET Command Prompt", <tt>cd</tt> to the
|
||||
Open a "Visual Studio Command Prompt" (either x86 or x64), <tt>cd</tt> to the
|
||||
directory where you've unpacked the sources and run these commands:
|
||||
</p>
|
||||
<pre class="code">
|
||||
@@ -272,37 +265,14 @@ cd src
|
||||
msvcbuild
|
||||
</pre>
|
||||
<p>
|
||||
Then follow the installation instructions below.
|
||||
</p>
|
||||
<h3>Building with the Windows SDK</h3>
|
||||
<p>
|
||||
Open a "Windows SDK Command Shell" and select the x86 compiler:
|
||||
</p>
|
||||
<pre class="code">
|
||||
setenv /release /x86
|
||||
</pre>
|
||||
<p>
|
||||
Or select the x64 compiler:
|
||||
</p>
|
||||
<pre class="code">
|
||||
setenv /release /x64
|
||||
</pre>
|
||||
<p>
|
||||
Then <tt>cd</tt> to the directory where you've unpacked the sources
|
||||
and run these commands:
|
||||
</p>
|
||||
<pre class="code">
|
||||
cd src
|
||||
msvcbuild
|
||||
</pre>
|
||||
<p>
|
||||
Check the <tt>msvcbuild.bat</tt> file for more options.
|
||||
Then follow the installation instructions below.
|
||||
</p>
|
||||
<h3>Building with MinGW or Cygwin</h3>
|
||||
<p>
|
||||
Open a command prompt window and make sure the MinGW or Cygwin programs
|
||||
are in your path. Then <tt>cd</tt> to the directory where
|
||||
you've unpacked the sources and run this command for MinGW:
|
||||
are in your path. Then <tt>cd</tt> to the directory of the git repository
|
||||
or where you've unpacked the sources. Then run this command for MinGW:
|
||||
</p>
|
||||
<pre class="code">
|
||||
mingw32-make
|
||||
@@ -333,22 +303,36 @@ directory where <tt>luajit.exe</tt> is installed
|
||||
|
||||
<h2 id="cross">Cross-compiling LuaJIT</h2>
|
||||
<p>
|
||||
The GNU Makefile-based build system allows cross-compiling on any host
|
||||
for any supported target, as long as both architectures have the same
|
||||
pointer size. If you want to cross-compile to any 32 bit target on an
|
||||
x64 OS, you need to install the multilib development package (e.g.
|
||||
<tt>libc6-dev-i386</tt> on Debian/Ubuntu) and build a 32 bit host part
|
||||
(<tt>HOST_CC="gcc -m32"</tt>).
|
||||
First, let's clear up some terminology:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Host: This is your development system, usually based on a x64 or x86 CPU.</li>
|
||||
<li>Target: This is the target system you want LuaJIT to run on, e.g. Android/ARM.</li>
|
||||
<li>Toolchain: This comprises a C compiler, linker, assembler and a matching C library.</li>
|
||||
<li>Host (or system) toolchain: This is the toolchain used to build native binaries for your host system.</li>
|
||||
<li>Cross-compile toolchain: This is the toolchain used to build binaries for the target system. They can only be run on the target system.</li>
|
||||
</ul>
|
||||
<p>
|
||||
The GNU Makefile-based build system allows cross-compiling on any host
|
||||
for any supported target:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Yes, you need a toolchain for both your host <em>and</em> your target!</li>
|
||||
<li>Both host and target architectures must have the same pointer size.</li>
|
||||
<li>E.g. if you want to cross-compile to a 32 bit target on a 64 bit host, you need to install the multilib development package (e.g. <tt>libc6-dev-i386</tt> on Debian/Ubuntu) and build a 32 bit host part (<tt>HOST_CC="gcc -m32"</tt>).</li>
|
||||
<li>64 bit targets always require compilation on a 64 bit host.</li>
|
||||
</ul>
|
||||
<p>
|
||||
You need to specify <tt>TARGET_SYS</tt> whenever the host OS and the
|
||||
target OS differ, or you'll get assembler or linker errors. E.g. if
|
||||
you're compiling on a Windows or OSX host for embedded Linux or Android,
|
||||
you need to add <tt>TARGET_SYS=Linux</tt> to the examples below. For a
|
||||
minimal target OS, you may need to disable the built-in allocator in
|
||||
<tt>src/Makefile</tt> and use <tt>TARGET_SYS=Other</tt>. The examples
|
||||
below only show some popular targets — please check the comments
|
||||
in <tt>src/Makefile</tt> for more details.
|
||||
target OS differ, or you'll get assembler or linker errors:
|
||||
</p>
|
||||
<ul>
|
||||
<li>E.g. if you're compiling on a Windows or macOS host for embedded Linux or Android, you need to add <tt>TARGET_SYS=Linux</tt> to the examples below.</li>
|
||||
<li>For a minimal target OS, you may need to disable the built-in allocator in <tt>src/Makefile</tt> and use <tt>TARGET_SYS=Other</tt>.</li>
|
||||
<li>Don't forget to specify the same <tt>TARGET_SYS</tt> for the install step, too.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Here are some examples where host and target have the same CPU:
|
||||
</p>
|
||||
<pre class="code">
|
||||
# Cross-compile to a 32 bit binary on a multilib x64 OS
|
||||
@@ -366,83 +350,71 @@ use the canonical toolchain triplets for Linux.
|
||||
</p>
|
||||
<p>
|
||||
Since there's often no easy way to detect CPU features at runtime, it's
|
||||
important to compile with the proper CPU or architecture settings. You
|
||||
can specify these when building the toolchain yourself. Or add
|
||||
<tt>-mcpu=...</tt> or <tt>-march=...</tt> to <tt>TARGET_CFLAGS</tt>. For
|
||||
ARM it's important to have the correct <tt>-mfloat-abi=...</tt> setting,
|
||||
too. Otherwise LuaJIT may not run at the full performance of your target
|
||||
CPU.
|
||||
important to compile with the proper CPU or architecture settings:
|
||||
</o>
|
||||
<ul>
|
||||
<li>The best way to get consistent results is to specify the correct settings when building the toolchain yourself.</li>
|
||||
<li>For a pre-built, generic toolchain add <tt>-mcpu=...</tt> or <tt>-march=...</tt> and other necessary flags to <tt>TARGET_CFLAGS</tt>.</li>
|
||||
<li>For ARM it's important to have the correct <tt>-mfloat-abi=...</tt> setting, too. Otherwise LuaJIT may not run at the full performance of your target CPU.</li>
|
||||
<li>For MIPS it's important to select a supported ABI (o32 on MIPS32, n64 on MIPS64) and consistently compile your project either with hard-float or soft-float compiler settings.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Here are some examples for targets with a different CPU than the host:
|
||||
</p>
|
||||
<pre class="code">
|
||||
# ARM soft-float
|
||||
make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
|
||||
TARGET_CFLAGS="-mfloat-abi=soft"
|
||||
|
||||
# ARM soft-float ABI with VFP (example for Cortex-A8)
|
||||
# ARM soft-float ABI with VFP (example for Cortex-A9)
|
||||
make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
|
||||
TARGET_CFLAGS="-mcpu=cortex-a8 -mfloat-abi=softfp"
|
||||
TARGET_CFLAGS="-mcpu=cortex-a9 -mfloat-abi=softfp"
|
||||
|
||||
# ARM hard-float ABI with VFP (armhf, requires recent toolchain)
|
||||
# ARM hard-float ABI with VFP (armhf, most modern toolchains)
|
||||
make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabihf-
|
||||
|
||||
# ARM64 (requires x64 host)
|
||||
# ARM64
|
||||
make CROSS=aarch64-linux-
|
||||
|
||||
# PPC
|
||||
make HOST_CC="gcc -m32" CROSS=powerpc-linux-gnu-
|
||||
|
||||
# MIPS big-endian
|
||||
# MIPS32 big-endian
|
||||
make HOST_CC="gcc -m32" CROSS=mips-linux-
|
||||
# MIPS little-endian
|
||||
# MIPS32 little-endian
|
||||
make HOST_CC="gcc -m32" CROSS=mipsel-linux-
|
||||
|
||||
# MIPS64 big-endian
|
||||
make CROSS=mips-linux- TARGET_CFLAGS="-mips64r2 -mabi=64"
|
||||
# MIPS64 little-endian
|
||||
make CROSS=mipsel-linux- TARGET_CFLAGS="-mips64r2 -mabi=64"
|
||||
</pre>
|
||||
<p>
|
||||
You can cross-compile for <b id="android">Android</b> using the <a href="http://developer.android.com/sdk/ndk/index.html"><span class="ext">»</span> Android NDK</a>.
|
||||
The environment variables need to match the install locations and the
|
||||
desired target platform. E.g. Android 4.0 corresponds to ABI level 14.
|
||||
For details check the folder <tt>docs</tt> in the NDK directory.
|
||||
</p>
|
||||
<p>
|
||||
Only a few common variations for the different CPUs, ABIs and platforms
|
||||
are listed. Please use your own judgement for which combination you want
|
||||
to build/deploy or which lowest common denominator you want to pick:
|
||||
You can cross-compile for <b id="android">Android</b> using the <a href="https://developer.android.com/ndk/"><span class="ext">»</span> Android NDK</a>.
|
||||
Please adapt the environment variables to match the install locations and the
|
||||
desired target platform. E.g. Android 4.1 corresponds to ABI level 16.
|
||||
</p>
|
||||
<pre class="code">
|
||||
# Android/ARM, armeabi (ARMv5TE soft-float), Android 2.2+ (Froyo)
|
||||
NDK=/opt/android/ndk
|
||||
NDKABI=8
|
||||
NDKVER=$NDK/toolchains/arm-linux-androideabi-4.6
|
||||
NDKP=$NDKVER/prebuilt/linux-x86/bin/arm-linux-androideabi-
|
||||
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm"
|
||||
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF"
|
||||
# Android/ARM64, aarch64, Android 5.0+ (L)
|
||||
NDKDIR=/opt/android/ndk
|
||||
NDKBIN=$NDKDIR/toolchains/llvm/prebuilt/linux-x86_64/bin
|
||||
NDKCROSS=$NDKBIN/aarch64-linux-android-
|
||||
NDKCC=$NDKBIN/aarch64-linux-android21-clang
|
||||
make CROSS=$NDKCROSS \
|
||||
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
|
||||
TARGET_LD=$NDKCC
|
||||
|
||||
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.0+ (ICS)
|
||||
NDK=/opt/android/ndk
|
||||
NDKABI=14
|
||||
NDKVER=$NDK/toolchains/arm-linux-androideabi-4.6
|
||||
NDKP=$NDKVER/prebuilt/linux-x86/bin/arm-linux-androideabi-
|
||||
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm"
|
||||
NDKARCH="-march=armv7-a -mfloat-abi=softfp -Wl,--fix-cortex-a8"
|
||||
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF $NDKARCH"
|
||||
|
||||
# Android/MIPS, mips (MIPS32R1 hard-float), Android 4.0+ (ICS)
|
||||
NDK=/opt/android/ndk
|
||||
NDKABI=14
|
||||
NDKVER=$NDK/toolchains/mipsel-linux-android-4.6
|
||||
NDKP=$NDKVER/prebuilt/linux-x86/bin/mipsel-linux-android-
|
||||
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-mips"
|
||||
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF"
|
||||
|
||||
# Android/x86, x86 (i686 SSE3), Android 4.0+ (ICS)
|
||||
NDK=/opt/android/ndk
|
||||
NDKABI=14
|
||||
NDKVER=$NDK/toolchains/x86-4.6
|
||||
NDKP=$NDKVER/prebuilt/linux-x86/bin/i686-linux-android-
|
||||
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-x86"
|
||||
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF"
|
||||
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.1+ (JB)
|
||||
NDKDIR=/opt/android/ndk
|
||||
NDKBIN=$NDKDIR/toolchains/llvm/prebuilt/linux-x86_64/bin
|
||||
NDKCROSS=$NDKBIN/arm-linux-androideabi-
|
||||
NDKCC=$NDKBIN/armv7a-linux-androideabi16-clang
|
||||
make HOST_CC="gcc -m32" CROSS=$NDKCROSS \
|
||||
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
|
||||
TARGET_LD=$NDKCC
|
||||
</pre>
|
||||
<p>
|
||||
You can cross-compile for <b id="ios">iOS 3.0+</b> (iPhone/iPad) using the <a href="http://developer.apple.com/devcenter/ios/index.action"><span class="ext">»</span> iOS SDK</a>:
|
||||
You can cross-compile for <b id="ios">iOS 3.0+</b> (iPhone/iPad) using the <a href="https://developer.apple.com/ios/"><span class="ext">»</span> iOS SDK</a>:
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
Note: <b>the JIT compiler is disabled for iOS</b>, because regular iOS Apps
|
||||
@@ -452,18 +424,12 @@ much slower than the JIT compiler. Please complain to Apple, not me.
|
||||
Or use Android. :-p
|
||||
</p>
|
||||
<pre class="code">
|
||||
# iOS/ARM (32 bit)
|
||||
ISDKP=$(xcrun --sdk iphoneos --show-sdk-path)
|
||||
ICC=$(xcrun --sdk iphoneos --find clang)
|
||||
ISDKF="-arch armv7 -isysroot $ISDKP"
|
||||
make HOST_CC="clang -m32 -arch i386" CROSS="$(dirname $ICC)/" \
|
||||
TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS
|
||||
|
||||
# iOS/ARM64
|
||||
ISDKP=$(xcrun --sdk iphoneos --show-sdk-path)
|
||||
ICC=$(xcrun --sdk iphoneos --find clang)
|
||||
ISDKF="-arch arm64 -isysroot $ISDKP"
|
||||
make CROSS="$(dirname $ICC)/" TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS
|
||||
make DEFAULT_CC=clang CROSS="$(dirname $ICC)/" \
|
||||
TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS
|
||||
</pre>
|
||||
|
||||
<h3 id="consoles">Cross-compiling for consoles</h3>
|
||||
@@ -558,17 +524,6 @@ the DLL). You may link LuaJIT statically on Windows only if you don't
|
||||
intend to load Lua/C modules at runtime.
|
||||
</li></ul>
|
||||
</li>
|
||||
<li>
|
||||
If you're building a 64 bit application on OSX which links directly or
|
||||
indirectly against LuaJIT, you need to link your main executable
|
||||
with these flags:
|
||||
<pre class="code">
|
||||
-pagezero_size 10000 -image_base 100000000
|
||||
</pre>
|
||||
Also, it's recommended to <tt>rebase</tt> all (self-compiled) shared libraries
|
||||
which are loaded at runtime on OSX/x64 (e.g. C extension modules for Lua).
|
||||
See: <tt>man rebase</tt>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Additional hints for initializing LuaJIT using the C API functions:</p>
|
||||
<ul>
|
||||
@@ -577,7 +532,7 @@ See: <tt>man rebase</tt>
|
||||
for embedding Lua or LuaJIT into your application.</li>
|
||||
<li>Make sure you use <tt>luaL_newstate</tt>. Avoid using
|
||||
<tt>lua_newstate</tt>, since this uses the (slower) default memory
|
||||
allocator from your system (no support for this on x64).</li>
|
||||
allocator from your system (no support for this on 64 bit architectures).</li>
|
||||
<li>Make sure you use <tt>luaL_openlibs</tt> and not the old Lua 5.0 style
|
||||
of calling <tt>luaopen_base</tt> etc. directly.</li>
|
||||
<li>To change or extend the list of standard libraries to load, copy
|
||||
@@ -586,7 +541,7 @@ Make sure the <tt>jit</tt> library is loaded or the JIT compiler
|
||||
will not be activated.</li>
|
||||
<li>The <tt>bit.*</tt> module for bitwise operations
|
||||
is already built-in. There's no need to statically link
|
||||
<a href="http://bitop.luajit.org/"><span class="ext">»</span> Lua BitOp</a> to your application.</li>
|
||||
<a href="https://bitop.luajit.org/"><span class="ext">»</span> Lua BitOp</a> to your application.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="distro">Hints for Distribution Maintainers</h2>
|
||||
@@ -653,7 +608,7 @@ to me (the upstream) and not you (the package maintainer), anyway.
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<head>
|
||||
<title>LuaJIT</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
@@ -96,7 +95,7 @@ table.feature small {
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>LuaJIT</h1>
|
||||
@@ -105,7 +104,7 @@ table.feature small {
|
||||
<ul><li>
|
||||
<a class="current" href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -131,36 +130,31 @@ table.feature small {
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
LuaJIT is a <b>Just-In-Time Compiler</b> (JIT) for the
|
||||
<a href="http://www.lua.org/"><span class="ext">»</span> Lua</a> programming language.
|
||||
<a href="https://www.lua.org/"><span class="ext">»</span> Lua</a> programming language.
|
||||
Lua is a powerful, dynamic and light-weight programming language.
|
||||
It may be embedded or used as a general-purpose, stand-alone language.
|
||||
</p>
|
||||
<p>
|
||||
LuaJIT is Copyright © 2005-2015 Mike Pall, released under the
|
||||
<a href="http://www.opensource.org/licenses/mit-license.php"><span class="ext">»</span> MIT open source license</a>.
|
||||
LuaJIT is Copyright © 2005-2021 Mike Pall, released under the
|
||||
<a href="https://www.opensource.org/licenses/mit-license.php"><span class="ext">»</span> MIT open source license</a>.
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
|
||||
<h2>Compatibility</h2>
|
||||
<table class="feature os os1">
|
||||
<tr><td>Windows</td><td>Linux</td><td>BSD</td><td>OSX</td><td>POSIX</td></tr>
|
||||
<tr><td>Windows</td><td>Linux</td><td>BSD</td><td>macOS</td><td>POSIX</td></tr>
|
||||
</table>
|
||||
<table class="feature os os2">
|
||||
<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td></tr>
|
||||
@@ -169,10 +163,10 @@ LuaJIT is Copyright © 2005-2015 Mike Pall, released under the
|
||||
<tr><td>PS3</td><td>PS4</td><td>PS Vita</td><td>Xbox 360</td><td>Xbox One</td></tr>
|
||||
</table>
|
||||
<table class="feature compiler">
|
||||
<tr><td>GCC</td><td>CLANG<br>LLVM</td><td>MSVC</td></tr>
|
||||
<tr><td>GCC</td><td>Clang<br>LLVM</td><td>MSVC</td></tr>
|
||||
</table>
|
||||
<table class="feature cpu">
|
||||
<tr><td>x86</td><td>x64</td><td>ARM</td><td>ARM64</td><td>PPC</td><td>MIPS</td></tr>
|
||||
<tr><td>x86<br>x64</td><td>ARM<br>ARM64</td><td>PPC</td><td>MIPS32<br>MIPS64</td></tr>
|
||||
</table>
|
||||
<table class="feature fcompat">
|
||||
<tr><td>Lua 5.1<br>API+ABI</td><td>+ JIT</td><td>+ BitOp</td><td>+ FFI</td><td>Drop-in<br>DLL/.so</td></tr>
|
||||
@@ -194,7 +188,7 @@ LuaJIT has been successfully used as a <b>scripting middleware</b> in
|
||||
games, appliances, network and graphics apps, numerical simulations,
|
||||
trading platforms and many other specialty applications. It scales from
|
||||
embedded devices, smartphones, desktops up to server farms. It combines
|
||||
high flexibility with <a href="http://luajit.org/performance.html"><span class="ext">»</span> high performance</a>
|
||||
high flexibility with high performance
|
||||
and an unmatched <b>low memory footprint</b>.
|
||||
</p>
|
||||
<p>
|
||||
@@ -226,7 +220,7 @@ Please select a sub-topic in the navigation bar to learn more about LuaJIT.
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<head>
|
||||
<title>Running LuaJIT</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
@@ -33,7 +32,7 @@ td.param_default {
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Running LuaJIT</h1>
|
||||
@@ -42,7 +41,7 @@ td.param_default {
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -68,17 +67,12 @@ td.param_default {
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
@@ -95,7 +89,7 @@ The <tt>luajit</tt> stand-alone executable is just a slightly modified
|
||||
version of the regular <tt>lua</tt> stand-alone executable.
|
||||
It supports the same basic options, too. <tt>luajit -h</tt>
|
||||
prints a short list of the available options. Please have a look at the
|
||||
<a href="http://www.lua.org/manual/5.1/manual.html#6"><span class="ext">»</span> Lua manual</a>
|
||||
<a href="https://www.lua.org/manual/5.1/manual.html#6"><span class="ext">»</span> Lua manual</a>
|
||||
for details.
|
||||
</p>
|
||||
<p>
|
||||
@@ -189,7 +183,7 @@ itself. For a description of their options and output format, please
|
||||
read the comment block at the start of their source.
|
||||
They can be found in the <tt>lib</tt> directory of the source
|
||||
distribution or installed under the <tt>jit</tt> directory. By default
|
||||
this is <tt>/usr/local/share/luajit-2.0.4/jit</tt> on POSIX
|
||||
this is <tt>/usr/local/share/luajit-2.1.0-beta3/jit</tt> on POSIX
|
||||
systems.
|
||||
</p>
|
||||
|
||||
@@ -299,7 +293,7 @@ Here are the parameters and their default settings:
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<head>
|
||||
<title>Status</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2015, Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||
<meta name="Language" content="en">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||
@@ -14,7 +13,7 @@ ul li { padding-bottom: 0.3em; }
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Status</h1>
|
||||
@@ -23,7 +22,7 @@ ul li { padding-bottom: 0.3em; }
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
@@ -49,24 +48,25 @@ ul li { padding-bottom: 0.3em; }
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a class="current" href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
<span style="color: #0000c0;">LuaJIT 2.0</span> is the current
|
||||
<span style="color: #0000c0;">stable branch</span>. This branch is in
|
||||
feature-freeze — new features will only be added to LuaJIT 2.1.
|
||||
This documentation is for LuaJIT 2.1.0-beta3. Please check the <tt>doc</tt>
|
||||
directory in each git branch for the version-specific documentation.
|
||||
</p>
|
||||
<p>
|
||||
The currently developed branches are LuaJIT 2.1 and LuaJIT 2.0.
|
||||
</p>
|
||||
<p>
|
||||
LuaJIT 2.0 is in feature-freeze — new features will only
|
||||
be added to LuaJIT 2.1.
|
||||
</p>
|
||||
|
||||
<h2>Current Status</h2>
|
||||
@@ -91,24 +91,17 @@ hooks for non-Lua functions) and shows slightly different behavior
|
||||
in LuaJIT (no per-coroutine hooks, no tail call counting).
|
||||
</li>
|
||||
<li>
|
||||
Some checks are missing in the JIT-compiled code for obscure situations
|
||||
with <b>open upvalues aliasing</b> one of the SSA slots later on (or
|
||||
vice versa). Bonus points, if you can find a real world test case for
|
||||
this.
|
||||
</li>
|
||||
<li>
|
||||
Currently some <b>out-of-memory</b> errors from <b>on-trace code</b> are not
|
||||
handled correctly. The error may fall through an on-trace
|
||||
<tt>pcall</tt> or it may be passed on to the function set with
|
||||
<tt>lua_atpanic</tt> on x64. This issue will be fixed with the new
|
||||
garbage collector.
|
||||
<tt>lua_atpanic</tt> on x64.
|
||||
</li>
|
||||
</ul>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2015 Mike Pall
|
||||
Copyright © 2005-2021
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** DynASM ARM encoding engine.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
@@ -254,6 +254,7 @@ void dasm_put(Dst_DECL, int start, ...)
|
||||
case DASM_IMMV8:
|
||||
CK((n & 3) == 0, RANGE_I);
|
||||
n >>= 2;
|
||||
/* fallthrough */
|
||||
case DASM_IMML8:
|
||||
case DASM_IMML12:
|
||||
CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) :
|
||||
@@ -371,6 +372,7 @@ int dasm_encode(Dst_DECL, void *buffer)
|
||||
break;
|
||||
case DASM_REL_LG:
|
||||
CK(n >= 0, UNDEF_LG);
|
||||
/* fallthrough */
|
||||
case DASM_REL_PC:
|
||||
CK(n >= 0, UNDEF_PC);
|
||||
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- DynASM ARM module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** DynASM ARM64 encoding engine.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
@@ -427,6 +427,7 @@ int dasm_encode(Dst_DECL, void *buffer)
|
||||
break;
|
||||
case DASM_REL_LG:
|
||||
CK(n >= 0, UNDEF_LG);
|
||||
/* fallthrough */
|
||||
case DASM_REL_PC:
|
||||
CK(n >= 0, UNDEF_PC);
|
||||
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) + 4;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- DynASM ARM64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** DynASM MIPS encoding engine.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,7 @@ enum {
|
||||
/* The following actions need a buffer position. */
|
||||
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
|
||||
/* The following actions also have an argument. */
|
||||
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM,
|
||||
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMS,
|
||||
DASM__MAX
|
||||
};
|
||||
|
||||
@@ -231,7 +231,7 @@ void dasm_put(Dst_DECL, int start, ...)
|
||||
*pl = -pos; /* Label exists now. */
|
||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||
break;
|
||||
case DASM_IMM:
|
||||
case DASM_IMM: case DASM_IMMS:
|
||||
#ifdef DASM_CHECKS
|
||||
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
|
||||
#endif
|
||||
@@ -299,7 +299,7 @@ int dasm_link(Dst_DECL, size_t *szp)
|
||||
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
|
||||
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
|
||||
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
|
||||
case DASM_IMM: pos++; break;
|
||||
case DASM_IMM: case DASM_IMMS: pos++; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
@@ -350,23 +350,28 @@ int dasm_encode(Dst_DECL, void *buffer)
|
||||
break;
|
||||
case DASM_REL_LG:
|
||||
CK(n >= 0, UNDEF_LG);
|
||||
/* fallthrough */
|
||||
case DASM_REL_PC:
|
||||
CK(n >= 0, UNDEF_PC);
|
||||
n = *DASM_POS2PTR(D, n);
|
||||
if (ins & 2048)
|
||||
n = n - (int)((char *)cp - base);
|
||||
n = (n + (int)(size_t)base) & 0x0fffffff;
|
||||
else
|
||||
n = (n + (int)base) & 0x0fffffff;
|
||||
patchrel:
|
||||
n = n - (int)((char *)cp - base);
|
||||
patchrel: {
|
||||
unsigned int e = 16 + ((ins >> 12) & 15);
|
||||
CK((n & 3) == 0 &&
|
||||
((n + ((ins & 2048) ? 0x00020000 : 0)) >>
|
||||
((ins & 2048) ? 18 : 28)) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n>>2) & ((ins & 2048) ? 0x0000ffff: 0x03ffffff));
|
||||
((n + ((ins & 2048) ? 0 : (1<<(e+1)))) >> (e+2)) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n>>2) & ((1<<e)-1));
|
||||
}
|
||||
break;
|
||||
case DASM_LABEL_LG:
|
||||
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
|
||||
break;
|
||||
case DASM_LABEL_PC: break;
|
||||
case DASM_IMMS:
|
||||
cp[-1] |= ((n>>3) & 4); n &= 0x1f;
|
||||
/* fallthrough */
|
||||
case DASM_IMM:
|
||||
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
|
||||
break;
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- DynASM MIPS module.
|
||||
-- DynASM MIPS32/MIPS64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local mips64 = mips64
|
||||
local mipsr6 = _map_def.MIPSR6
|
||||
|
||||
-- Module information:
|
||||
local _info = {
|
||||
arch = "mips",
|
||||
description = "DynASM MIPS module",
|
||||
arch = mips64 and "mips64" or "mips",
|
||||
description = "DynASM MIPS32/MIPS64 module",
|
||||
version = "1.4.0",
|
||||
vernum = 10400,
|
||||
release = "2015-10-18",
|
||||
release = "2020-01-20",
|
||||
author = "Mike Pall",
|
||||
license = "MIT",
|
||||
}
|
||||
@@ -27,7 +30,8 @@ local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
|
||||
local match, gmatch = _s.match, _s.gmatch
|
||||
local concat, sort = table.concat, table.sort
|
||||
local bit = bit or require("bit")
|
||||
local band, shl, sar, tohex = bit.band, bit.lshift, bit.arshift, bit.tohex
|
||||
local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
|
||||
local tohex = bit.tohex
|
||||
|
||||
-- Inherited tables and callbacks.
|
||||
local g_opt, g_arch
|
||||
@@ -38,7 +42,7 @@ local wline, werror, wfatal, wwarn
|
||||
local action_names = {
|
||||
"STOP", "SECTION", "ESC", "REL_EXT",
|
||||
"ALIGN", "REL_LG", "LABEL_LG",
|
||||
"REL_PC", "LABEL_PC", "IMM",
|
||||
"REL_PC", "LABEL_PC", "IMM", "IMMS",
|
||||
}
|
||||
|
||||
-- Maximum number of section buffer positions for dasm_put().
|
||||
@@ -235,7 +239,6 @@ local map_op = {
|
||||
bne_3 = "14000000STB",
|
||||
blez_2 = "18000000SB",
|
||||
bgtz_2 = "1c000000SB",
|
||||
addi_3 = "20000000TSI",
|
||||
li_2 = "24000000TI",
|
||||
addiu_3 = "24000000TSI",
|
||||
slti_3 = "28000000TSI",
|
||||
@@ -245,70 +248,52 @@ local map_op = {
|
||||
ori_3 = "34000000TSU",
|
||||
xori_3 = "38000000TSU",
|
||||
lui_2 = "3c000000TU",
|
||||
beqzl_2 = "50000000SB",
|
||||
beql_3 = "50000000STB",
|
||||
bnezl_2 = "54000000SB",
|
||||
bnel_3 = "54000000STB",
|
||||
blezl_2 = "58000000SB",
|
||||
bgtzl_2 = "5c000000SB",
|
||||
daddiu_3 = mips64 and "64000000TSI",
|
||||
ldl_2 = mips64 and "68000000TO",
|
||||
ldr_2 = mips64 and "6c000000TO",
|
||||
lb_2 = "80000000TO",
|
||||
lh_2 = "84000000TO",
|
||||
lwl_2 = "88000000TO",
|
||||
lw_2 = "8c000000TO",
|
||||
lbu_2 = "90000000TO",
|
||||
lhu_2 = "94000000TO",
|
||||
lwr_2 = "98000000TO",
|
||||
lwu_2 = mips64 and "9c000000TO",
|
||||
sb_2 = "a0000000TO",
|
||||
sh_2 = "a4000000TO",
|
||||
swl_2 = "a8000000TO",
|
||||
sw_2 = "ac000000TO",
|
||||
swr_2 = "b8000000TO",
|
||||
cache_2 = "bc000000NO",
|
||||
ll_2 = "c0000000TO",
|
||||
lwc1_2 = "c4000000HO",
|
||||
pref_2 = "cc000000NO",
|
||||
ldc1_2 = "d4000000HO",
|
||||
sc_2 = "e0000000TO",
|
||||
ld_2 = mips64 and "dc000000TO",
|
||||
swc1_2 = "e4000000HO",
|
||||
sdc1_2 = "f4000000HO",
|
||||
sd_2 = mips64 and "fc000000TO",
|
||||
|
||||
-- Opcode SPECIAL.
|
||||
nop_0 = "00000000",
|
||||
sll_3 = "00000000DTA",
|
||||
movf_2 = "00000001DS",
|
||||
movf_3 = "00000001DSC",
|
||||
movt_2 = "00010001DS",
|
||||
movt_3 = "00010001DSC",
|
||||
sextw_2 = "00000000DT",
|
||||
srl_3 = "00000002DTA",
|
||||
rotr_3 = "00200002DTA",
|
||||
sra_3 = "00000003DTA",
|
||||
sllv_3 = "00000004DTS",
|
||||
srlv_3 = "00000006DTS",
|
||||
rotrv_3 = "00000046DTS",
|
||||
drotrv_3 = mips64 and "00000056DTS",
|
||||
srav_3 = "00000007DTS",
|
||||
jr_1 = "00000008S",
|
||||
jalr_1 = "0000f809S",
|
||||
jalr_2 = "00000009DS",
|
||||
movz_3 = "0000000aDST",
|
||||
movn_3 = "0000000bDST",
|
||||
syscall_0 = "0000000c",
|
||||
syscall_1 = "0000000cY",
|
||||
break_0 = "0000000d",
|
||||
break_1 = "0000000dY",
|
||||
sync_0 = "0000000f",
|
||||
mfhi_1 = "00000010D",
|
||||
mthi_1 = "00000011S",
|
||||
mflo_1 = "00000012D",
|
||||
mtlo_1 = "00000013S",
|
||||
mult_2 = "00000018ST",
|
||||
multu_2 = "00000019ST",
|
||||
div_2 = "0000001aST",
|
||||
divu_2 = "0000001bST",
|
||||
dsllv_3 = mips64 and "00000014DTS",
|
||||
dsrlv_3 = mips64 and "00000016DTS",
|
||||
dsrav_3 = mips64 and "00000017DTS",
|
||||
add_3 = "00000020DST",
|
||||
move_2 = "00000021DS",
|
||||
move_2 = mips64 and "00000025DS" or "00000021DS",
|
||||
addu_3 = "00000021DST",
|
||||
sub_3 = "00000022DST",
|
||||
negu_2 = "00000023DT",
|
||||
negu_2 = mips64 and "0000002fDT" or "00000023DT",
|
||||
subu_3 = "00000023DST",
|
||||
and_3 = "00000024DST",
|
||||
or_3 = "00000025DST",
|
||||
@@ -317,6 +302,10 @@ local map_op = {
|
||||
nor_3 = "00000027DST",
|
||||
slt_3 = "0000002aDST",
|
||||
sltu_3 = "0000002bDST",
|
||||
dadd_3 = mips64 and "0000002cDST",
|
||||
daddu_3 = mips64 and "0000002dDST",
|
||||
dsub_3 = mips64 and "0000002eDST",
|
||||
dsubu_3 = mips64 and "0000002fDST",
|
||||
tge_2 = "00000030ST",
|
||||
tge_3 = "00000030STZ",
|
||||
tgeu_2 = "00000031ST",
|
||||
@@ -329,40 +318,36 @@ local map_op = {
|
||||
teq_3 = "00000034STZ",
|
||||
tne_2 = "00000036ST",
|
||||
tne_3 = "00000036STZ",
|
||||
dsll_3 = mips64 and "00000038DTa",
|
||||
dsrl_3 = mips64 and "0000003aDTa",
|
||||
drotr_3 = mips64 and "0020003aDTa",
|
||||
dsra_3 = mips64 and "0000003bDTa",
|
||||
dsll32_3 = mips64 and "0000003cDTA",
|
||||
dsrl32_3 = mips64 and "0000003eDTA",
|
||||
drotr32_3 = mips64 and "0020003eDTA",
|
||||
dsra32_3 = mips64 and "0000003fDTA",
|
||||
|
||||
-- Opcode REGIMM.
|
||||
bltz_2 = "04000000SB",
|
||||
bgez_2 = "04010000SB",
|
||||
bltzl_2 = "04020000SB",
|
||||
bgezl_2 = "04030000SB",
|
||||
tgei_2 = "04080000SI",
|
||||
tgeiu_2 = "04090000SI",
|
||||
tlti_2 = "040a0000SI",
|
||||
tltiu_2 = "040b0000SI",
|
||||
teqi_2 = "040c0000SI",
|
||||
tnei_2 = "040e0000SI",
|
||||
bltzal_2 = "04100000SB",
|
||||
bal_1 = "04110000B",
|
||||
bgezal_2 = "04110000SB",
|
||||
bltzall_2 = "04120000SB",
|
||||
bgezall_2 = "04130000SB",
|
||||
synci_1 = "041f0000O",
|
||||
|
||||
-- Opcode SPECIAL2.
|
||||
madd_2 = "70000000ST",
|
||||
maddu_2 = "70000001ST",
|
||||
mul_3 = "70000002DST",
|
||||
msub_2 = "70000004ST",
|
||||
msubu_2 = "70000005ST",
|
||||
clz_2 = "70000020DS=",
|
||||
clo_2 = "70000021DS=",
|
||||
sdbbp_0 = "7000003f",
|
||||
sdbbp_1 = "7000003fY",
|
||||
|
||||
-- Opcode SPECIAL3.
|
||||
ext_4 = "7c000000TSAM", -- Note: last arg is msbd = size-1
|
||||
dextm_4 = mips64 and "7c000001TSAM", -- Args: pos | size-1-32
|
||||
dextu_4 = mips64 and "7c000002TSAM", -- Args: pos-32 | size-1
|
||||
dext_4 = mips64 and "7c000003TSAM", -- Args: pos | size-1
|
||||
zextw_2 = mips64 and "7c00f803TS",
|
||||
ins_4 = "7c000004TSAM", -- Note: last arg is msb = pos+size-1
|
||||
dinsm_4 = mips64 and "7c000005TSAM", -- Args: pos | pos+size-33
|
||||
dinsu_4 = mips64 and "7c000006TSAM", -- Args: pos-32 | pos+size-33
|
||||
dins_4 = mips64 and "7c000007TSAM", -- Args: pos | pos+size-1
|
||||
wsbh_2 = "7c0000a0DT",
|
||||
dsbh_2 = mips64 and "7c0000a4DT",
|
||||
dshd_2 = mips64 and "7c000164DT",
|
||||
seb_2 = "7c000420DT",
|
||||
seh_2 = "7c000620DT",
|
||||
rdhwr_2 = "7c00003bTD",
|
||||
@@ -370,8 +355,12 @@ local map_op = {
|
||||
-- Opcode COP0.
|
||||
mfc0_2 = "40000000TD",
|
||||
mfc0_3 = "40000000TDW",
|
||||
dmfc0_2 = mips64 and "40200000TD",
|
||||
dmfc0_3 = mips64 and "40200000TDW",
|
||||
mtc0_2 = "40800000TD",
|
||||
mtc0_3 = "40800000TDW",
|
||||
dmtc0_2 = mips64 and "40a00000TD",
|
||||
dmtc0_3 = mips64 and "40a00000TDW",
|
||||
rdpgpr_2 = "41400000DT",
|
||||
di_0 = "41606000",
|
||||
di_1 = "41606000T",
|
||||
@@ -388,21 +377,14 @@ local map_op = {
|
||||
|
||||
-- Opcode COP1.
|
||||
mfc1_2 = "44000000TG",
|
||||
dmfc1_2 = mips64 and "44200000TG",
|
||||
cfc1_2 = "44400000TG",
|
||||
mfhc1_2 = "44600000TG",
|
||||
mtc1_2 = "44800000TG",
|
||||
dmtc1_2 = mips64 and "44a00000TG",
|
||||
ctc1_2 = "44c00000TG",
|
||||
mthc1_2 = "44e00000TG",
|
||||
|
||||
bc1f_1 = "45000000B",
|
||||
bc1f_2 = "45000000CB",
|
||||
bc1t_1 = "45010000B",
|
||||
bc1t_2 = "45010000CB",
|
||||
bc1fl_1 = "45020000B",
|
||||
bc1fl_2 = "45020000CB",
|
||||
bc1tl_1 = "45030000B",
|
||||
bc1tl_2 = "45030000CB",
|
||||
|
||||
["add.s_3"] = "46000000FGH",
|
||||
["sub.s_3"] = "46000001FGH",
|
||||
["mul.s_3"] = "46000002FGH",
|
||||
@@ -419,51 +401,11 @@ local map_op = {
|
||||
["trunc.w.s_2"] = "4600000dFG",
|
||||
["ceil.w.s_2"] = "4600000eFG",
|
||||
["floor.w.s_2"] = "4600000fFG",
|
||||
["movf.s_2"] = "46000011FG",
|
||||
["movf.s_3"] = "46000011FGC",
|
||||
["movt.s_2"] = "46010011FG",
|
||||
["movt.s_3"] = "46010011FGC",
|
||||
["movz.s_3"] = "46000012FGT",
|
||||
["movn.s_3"] = "46000013FGT",
|
||||
["recip.s_2"] = "46000015FG",
|
||||
["rsqrt.s_2"] = "46000016FG",
|
||||
["cvt.d.s_2"] = "46000021FG",
|
||||
["cvt.w.s_2"] = "46000024FG",
|
||||
["cvt.l.s_2"] = "46000025FG",
|
||||
["cvt.ps.s_3"] = "46000026FGH",
|
||||
["c.f.s_2"] = "46000030GH",
|
||||
["c.f.s_3"] = "46000030VGH",
|
||||
["c.un.s_2"] = "46000031GH",
|
||||
["c.un.s_3"] = "46000031VGH",
|
||||
["c.eq.s_2"] = "46000032GH",
|
||||
["c.eq.s_3"] = "46000032VGH",
|
||||
["c.ueq.s_2"] = "46000033GH",
|
||||
["c.ueq.s_3"] = "46000033VGH",
|
||||
["c.olt.s_2"] = "46000034GH",
|
||||
["c.olt.s_3"] = "46000034VGH",
|
||||
["c.ult.s_2"] = "46000035GH",
|
||||
["c.ult.s_3"] = "46000035VGH",
|
||||
["c.ole.s_2"] = "46000036GH",
|
||||
["c.ole.s_3"] = "46000036VGH",
|
||||
["c.ule.s_2"] = "46000037GH",
|
||||
["c.ule.s_3"] = "46000037VGH",
|
||||
["c.sf.s_2"] = "46000038GH",
|
||||
["c.sf.s_3"] = "46000038VGH",
|
||||
["c.ngle.s_2"] = "46000039GH",
|
||||
["c.ngle.s_3"] = "46000039VGH",
|
||||
["c.seq.s_2"] = "4600003aGH",
|
||||
["c.seq.s_3"] = "4600003aVGH",
|
||||
["c.ngl.s_2"] = "4600003bGH",
|
||||
["c.ngl.s_3"] = "4600003bVGH",
|
||||
["c.lt.s_2"] = "4600003cGH",
|
||||
["c.lt.s_3"] = "4600003cVGH",
|
||||
["c.nge.s_2"] = "4600003dGH",
|
||||
["c.nge.s_3"] = "4600003dVGH",
|
||||
["c.le.s_2"] = "4600003eGH",
|
||||
["c.le.s_3"] = "4600003eVGH",
|
||||
["c.ngt.s_2"] = "4600003fGH",
|
||||
["c.ngt.s_3"] = "4600003fVGH",
|
||||
|
||||
["add.d_3"] = "46200000FGH",
|
||||
["sub.d_3"] = "46200001FGH",
|
||||
["mul.d_3"] = "46200002FGH",
|
||||
@@ -480,130 +422,410 @@ local map_op = {
|
||||
["trunc.w.d_2"] = "4620000dFG",
|
||||
["ceil.w.d_2"] = "4620000eFG",
|
||||
["floor.w.d_2"] = "4620000fFG",
|
||||
["movf.d_2"] = "46200011FG",
|
||||
["movf.d_3"] = "46200011FGC",
|
||||
["movt.d_2"] = "46210011FG",
|
||||
["movt.d_3"] = "46210011FGC",
|
||||
["movz.d_3"] = "46200012FGT",
|
||||
["movn.d_3"] = "46200013FGT",
|
||||
["recip.d_2"] = "46200015FG",
|
||||
["rsqrt.d_2"] = "46200016FG",
|
||||
["cvt.s.d_2"] = "46200020FG",
|
||||
["cvt.w.d_2"] = "46200024FG",
|
||||
["cvt.l.d_2"] = "46200025FG",
|
||||
["c.f.d_2"] = "46200030GH",
|
||||
["c.f.d_3"] = "46200030VGH",
|
||||
["c.un.d_2"] = "46200031GH",
|
||||
["c.un.d_3"] = "46200031VGH",
|
||||
["c.eq.d_2"] = "46200032GH",
|
||||
["c.eq.d_3"] = "46200032VGH",
|
||||
["c.ueq.d_2"] = "46200033GH",
|
||||
["c.ueq.d_3"] = "46200033VGH",
|
||||
["c.olt.d_2"] = "46200034GH",
|
||||
["c.olt.d_3"] = "46200034VGH",
|
||||
["c.ult.d_2"] = "46200035GH",
|
||||
["c.ult.d_3"] = "46200035VGH",
|
||||
["c.ole.d_2"] = "46200036GH",
|
||||
["c.ole.d_3"] = "46200036VGH",
|
||||
["c.ule.d_2"] = "46200037GH",
|
||||
["c.ule.d_3"] = "46200037VGH",
|
||||
["c.sf.d_2"] = "46200038GH",
|
||||
["c.sf.d_3"] = "46200038VGH",
|
||||
["c.ngle.d_2"] = "46200039GH",
|
||||
["c.ngle.d_3"] = "46200039VGH",
|
||||
["c.seq.d_2"] = "4620003aGH",
|
||||
["c.seq.d_3"] = "4620003aVGH",
|
||||
["c.ngl.d_2"] = "4620003bGH",
|
||||
["c.ngl.d_3"] = "4620003bVGH",
|
||||
["c.lt.d_2"] = "4620003cGH",
|
||||
["c.lt.d_3"] = "4620003cVGH",
|
||||
["c.nge.d_2"] = "4620003dGH",
|
||||
["c.nge.d_3"] = "4620003dVGH",
|
||||
["c.le.d_2"] = "4620003eGH",
|
||||
["c.le.d_3"] = "4620003eVGH",
|
||||
["c.ngt.d_2"] = "4620003fGH",
|
||||
["c.ngt.d_3"] = "4620003fVGH",
|
||||
|
||||
["add.ps_3"] = "46c00000FGH",
|
||||
["sub.ps_3"] = "46c00001FGH",
|
||||
["mul.ps_3"] = "46c00002FGH",
|
||||
["abs.ps_2"] = "46c00005FG",
|
||||
["mov.ps_2"] = "46c00006FG",
|
||||
["neg.ps_2"] = "46c00007FG",
|
||||
["movf.ps_2"] = "46c00011FG",
|
||||
["movf.ps_3"] = "46c00011FGC",
|
||||
["movt.ps_2"] = "46c10011FG",
|
||||
["movt.ps_3"] = "46c10011FGC",
|
||||
["movz.ps_3"] = "46c00012FGT",
|
||||
["movn.ps_3"] = "46c00013FGT",
|
||||
["cvt.s.pu_2"] = "46c00020FG",
|
||||
["cvt.s.pl_2"] = "46c00028FG",
|
||||
["pll.ps_3"] = "46c0002cFGH",
|
||||
["plu.ps_3"] = "46c0002dFGH",
|
||||
["pul.ps_3"] = "46c0002eFGH",
|
||||
["puu.ps_3"] = "46c0002fFGH",
|
||||
["c.f.ps_2"] = "46c00030GH",
|
||||
["c.f.ps_3"] = "46c00030VGH",
|
||||
["c.un.ps_2"] = "46c00031GH",
|
||||
["c.un.ps_3"] = "46c00031VGH",
|
||||
["c.eq.ps_2"] = "46c00032GH",
|
||||
["c.eq.ps_3"] = "46c00032VGH",
|
||||
["c.ueq.ps_2"] = "46c00033GH",
|
||||
["c.ueq.ps_3"] = "46c00033VGH",
|
||||
["c.olt.ps_2"] = "46c00034GH",
|
||||
["c.olt.ps_3"] = "46c00034VGH",
|
||||
["c.ult.ps_2"] = "46c00035GH",
|
||||
["c.ult.ps_3"] = "46c00035VGH",
|
||||
["c.ole.ps_2"] = "46c00036GH",
|
||||
["c.ole.ps_3"] = "46c00036VGH",
|
||||
["c.ule.ps_2"] = "46c00037GH",
|
||||
["c.ule.ps_3"] = "46c00037VGH",
|
||||
["c.sf.ps_2"] = "46c00038GH",
|
||||
["c.sf.ps_3"] = "46c00038VGH",
|
||||
["c.ngle.ps_2"] = "46c00039GH",
|
||||
["c.ngle.ps_3"] = "46c00039VGH",
|
||||
["c.seq.ps_2"] = "46c0003aGH",
|
||||
["c.seq.ps_3"] = "46c0003aVGH",
|
||||
["c.ngl.ps_2"] = "46c0003bGH",
|
||||
["c.ngl.ps_3"] = "46c0003bVGH",
|
||||
["c.lt.ps_2"] = "46c0003cGH",
|
||||
["c.lt.ps_3"] = "46c0003cVGH",
|
||||
["c.nge.ps_2"] = "46c0003dGH",
|
||||
["c.nge.ps_3"] = "46c0003dVGH",
|
||||
["c.le.ps_2"] = "46c0003eGH",
|
||||
["c.le.ps_3"] = "46c0003eVGH",
|
||||
["c.ngt.ps_2"] = "46c0003fGH",
|
||||
["c.ngt.ps_3"] = "46c0003fVGH",
|
||||
|
||||
["cvt.s.w_2"] = "46800020FG",
|
||||
["cvt.d.w_2"] = "46800021FG",
|
||||
|
||||
["cvt.s.l_2"] = "46a00020FG",
|
||||
["cvt.d.l_2"] = "46a00021FG",
|
||||
|
||||
-- Opcode COP1X.
|
||||
lwxc1_2 = "4c000000FX",
|
||||
ldxc1_2 = "4c000001FX",
|
||||
luxc1_2 = "4c000005FX",
|
||||
swxc1_2 = "4c000008FX",
|
||||
sdxc1_2 = "4c000009FX",
|
||||
suxc1_2 = "4c00000dFX",
|
||||
prefx_2 = "4c00000fMX",
|
||||
["alnv.ps_4"] = "4c00001eFGHS",
|
||||
["madd.s_4"] = "4c000020FRGH",
|
||||
["madd.d_4"] = "4c000021FRGH",
|
||||
["madd.ps_4"] = "4c000026FRGH",
|
||||
["msub.s_4"] = "4c000028FRGH",
|
||||
["msub.d_4"] = "4c000029FRGH",
|
||||
["msub.ps_4"] = "4c00002eFRGH",
|
||||
["nmadd.s_4"] = "4c000030FRGH",
|
||||
["nmadd.d_4"] = "4c000031FRGH",
|
||||
["nmadd.ps_4"] = "4c000036FRGH",
|
||||
["nmsub.s_4"] = "4c000038FRGH",
|
||||
["nmsub.d_4"] = "4c000039FRGH",
|
||||
["nmsub.ps_4"] = "4c00003eFRGH",
|
||||
}
|
||||
|
||||
if mipsr6 then -- Instructions added with MIPSR6.
|
||||
|
||||
for k,v in pairs({
|
||||
|
||||
-- Add immediate to upper bits.
|
||||
aui_3 = "3c000000TSI",
|
||||
daui_3 = mips64 and "74000000TSI",
|
||||
dahi_2 = mips64 and "04060000SI",
|
||||
dati_2 = mips64 and "041e0000SI",
|
||||
|
||||
-- TODO: addiupc, auipc, aluipc, lwpc, lwupc, ldpc.
|
||||
|
||||
-- Compact branches.
|
||||
blezalc_2 = "18000000TB", -- rt != 0.
|
||||
bgezalc_2 = "18000000T=SB", -- rt != 0.
|
||||
bgtzalc_2 = "1c000000TB", -- rt != 0.
|
||||
bltzalc_2 = "1c000000T=SB", -- rt != 0.
|
||||
|
||||
blezc_2 = "58000000TB", -- rt != 0.
|
||||
bgezc_2 = "58000000T=SB", -- rt != 0.
|
||||
bgec_3 = "58000000STB", -- rs != rt.
|
||||
blec_3 = "58000000TSB", -- rt != rs.
|
||||
|
||||
bgtzc_2 = "5c000000TB", -- rt != 0.
|
||||
bltzc_2 = "5c000000T=SB", -- rt != 0.
|
||||
bltc_3 = "5c000000STB", -- rs != rt.
|
||||
bgtc_3 = "5c000000TSB", -- rt != rs.
|
||||
|
||||
bgeuc_3 = "18000000STB", -- rs != rt.
|
||||
bleuc_3 = "18000000TSB", -- rt != rs.
|
||||
bltuc_3 = "1c000000STB", -- rs != rt.
|
||||
bgtuc_3 = "1c000000TSB", -- rt != rs.
|
||||
|
||||
beqzalc_2 = "20000000TB", -- rt != 0.
|
||||
bnezalc_2 = "60000000TB", -- rt != 0.
|
||||
beqc_3 = "20000000STB", -- rs < rt.
|
||||
bnec_3 = "60000000STB", -- rs < rt.
|
||||
bovc_3 = "20000000STB", -- rs >= rt.
|
||||
bnvc_3 = "60000000STB", -- rs >= rt.
|
||||
|
||||
beqzc_2 = "d8000000SK", -- rs != 0.
|
||||
bnezc_2 = "f8000000SK", -- rs != 0.
|
||||
jic_2 = "d8000000TI",
|
||||
jialc_2 = "f8000000TI",
|
||||
bc_1 = "c8000000L",
|
||||
balc_1 = "e8000000L",
|
||||
|
||||
-- Opcode SPECIAL.
|
||||
jr_1 = "00000009S",
|
||||
sdbbp_0 = "0000000e",
|
||||
sdbbp_1 = "0000000eY",
|
||||
lsa_4 = "00000005DSTA",
|
||||
dlsa_4 = mips64 and "00000015DSTA",
|
||||
seleqz_3 = "00000035DST",
|
||||
selnez_3 = "00000037DST",
|
||||
clz_2 = "00000050DS",
|
||||
clo_2 = "00000051DS",
|
||||
dclz_2 = mips64 and "00000052DS",
|
||||
dclo_2 = mips64 and "00000053DS",
|
||||
mul_3 = "00000098DST",
|
||||
muh_3 = "000000d8DST",
|
||||
mulu_3 = "00000099DST",
|
||||
muhu_3 = "000000d9DST",
|
||||
div_3 = "0000009aDST",
|
||||
mod_3 = "000000daDST",
|
||||
divu_3 = "0000009bDST",
|
||||
modu_3 = "000000dbDST",
|
||||
dmul_3 = mips64 and "0000009cDST",
|
||||
dmuh_3 = mips64 and "000000dcDST",
|
||||
dmulu_3 = mips64 and "0000009dDST",
|
||||
dmuhu_3 = mips64 and "000000ddDST",
|
||||
ddiv_3 = mips64 and "0000009eDST",
|
||||
dmod_3 = mips64 and "000000deDST",
|
||||
ddivu_3 = mips64 and "0000009fDST",
|
||||
dmodu_3 = mips64 and "000000dfDST",
|
||||
|
||||
-- Opcode SPECIAL3.
|
||||
align_4 = "7c000220DSTA",
|
||||
dalign_4 = mips64 and "7c000224DSTA",
|
||||
bitswap_2 = "7c000020DT",
|
||||
dbitswap_2 = mips64 and "7c000024DT",
|
||||
|
||||
-- Opcode COP1.
|
||||
bc1eqz_2 = "45200000HB",
|
||||
bc1nez_2 = "45a00000HB",
|
||||
|
||||
["sel.s_3"] = "46000010FGH",
|
||||
["seleqz.s_3"] = "46000014FGH",
|
||||
["selnez.s_3"] = "46000017FGH",
|
||||
["maddf.s_3"] = "46000018FGH",
|
||||
["msubf.s_3"] = "46000019FGH",
|
||||
["rint.s_2"] = "4600001aFG",
|
||||
["class.s_2"] = "4600001bFG",
|
||||
["min.s_3"] = "4600001cFGH",
|
||||
["mina.s_3"] = "4600001dFGH",
|
||||
["max.s_3"] = "4600001eFGH",
|
||||
["maxa.s_3"] = "4600001fFGH",
|
||||
["cmp.af.s_3"] = "46800000FGH",
|
||||
["cmp.un.s_3"] = "46800001FGH",
|
||||
["cmp.or.s_3"] = "46800011FGH",
|
||||
["cmp.eq.s_3"] = "46800002FGH",
|
||||
["cmp.une.s_3"] = "46800012FGH",
|
||||
["cmp.ueq.s_3"] = "46800003FGH",
|
||||
["cmp.ne.s_3"] = "46800013FGH",
|
||||
["cmp.lt.s_3"] = "46800004FGH",
|
||||
["cmp.ult.s_3"] = "46800005FGH",
|
||||
["cmp.le.s_3"] = "46800006FGH",
|
||||
["cmp.ule.s_3"] = "46800007FGH",
|
||||
["cmp.saf.s_3"] = "46800008FGH",
|
||||
["cmp.sun.s_3"] = "46800009FGH",
|
||||
["cmp.sor.s_3"] = "46800019FGH",
|
||||
["cmp.seq.s_3"] = "4680000aFGH",
|
||||
["cmp.sune.s_3"] = "4680001aFGH",
|
||||
["cmp.sueq.s_3"] = "4680000bFGH",
|
||||
["cmp.sne.s_3"] = "4680001bFGH",
|
||||
["cmp.slt.s_3"] = "4680000cFGH",
|
||||
["cmp.sult.s_3"] = "4680000dFGH",
|
||||
["cmp.sle.s_3"] = "4680000eFGH",
|
||||
["cmp.sule.s_3"] = "4680000fFGH",
|
||||
|
||||
["sel.d_3"] = "46200010FGH",
|
||||
["seleqz.d_3"] = "46200014FGH",
|
||||
["selnez.d_3"] = "46200017FGH",
|
||||
["maddf.d_3"] = "46200018FGH",
|
||||
["msubf.d_3"] = "46200019FGH",
|
||||
["rint.d_2"] = "4620001aFG",
|
||||
["class.d_2"] = "4620001bFG",
|
||||
["min.d_3"] = "4620001cFGH",
|
||||
["mina.d_3"] = "4620001dFGH",
|
||||
["max.d_3"] = "4620001eFGH",
|
||||
["maxa.d_3"] = "4620001fFGH",
|
||||
["cmp.af.d_3"] = "46a00000FGH",
|
||||
["cmp.un.d_3"] = "46a00001FGH",
|
||||
["cmp.or.d_3"] = "46a00011FGH",
|
||||
["cmp.eq.d_3"] = "46a00002FGH",
|
||||
["cmp.une.d_3"] = "46a00012FGH",
|
||||
["cmp.ueq.d_3"] = "46a00003FGH",
|
||||
["cmp.ne.d_3"] = "46a00013FGH",
|
||||
["cmp.lt.d_3"] = "46a00004FGH",
|
||||
["cmp.ult.d_3"] = "46a00005FGH",
|
||||
["cmp.le.d_3"] = "46a00006FGH",
|
||||
["cmp.ule.d_3"] = "46a00007FGH",
|
||||
["cmp.saf.d_3"] = "46a00008FGH",
|
||||
["cmp.sun.d_3"] = "46a00009FGH",
|
||||
["cmp.sor.d_3"] = "46a00019FGH",
|
||||
["cmp.seq.d_3"] = "46a0000aFGH",
|
||||
["cmp.sune.d_3"] = "46a0001aFGH",
|
||||
["cmp.sueq.d_3"] = "46a0000bFGH",
|
||||
["cmp.sne.d_3"] = "46a0001bFGH",
|
||||
["cmp.slt.d_3"] = "46a0000cFGH",
|
||||
["cmp.sult.d_3"] = "46a0000dFGH",
|
||||
["cmp.sle.d_3"] = "46a0000eFGH",
|
||||
["cmp.sule.d_3"] = "46a0000fFGH",
|
||||
|
||||
}) do map_op[k] = v end
|
||||
|
||||
else -- Instructions removed by MIPSR6.
|
||||
|
||||
for k,v in pairs({
|
||||
-- Traps, don't use.
|
||||
addi_3 = "20000000TSI",
|
||||
daddi_3 = mips64 and "60000000TSI",
|
||||
|
||||
-- Branch on likely, don't use.
|
||||
beqzl_2 = "50000000SB",
|
||||
beql_3 = "50000000STB",
|
||||
bnezl_2 = "54000000SB",
|
||||
bnel_3 = "54000000STB",
|
||||
blezl_2 = "58000000SB",
|
||||
bgtzl_2 = "5c000000SB",
|
||||
|
||||
lwl_2 = "88000000TO",
|
||||
lwr_2 = "98000000TO",
|
||||
swl_2 = "a8000000TO",
|
||||
sdl_2 = mips64 and "b0000000TO",
|
||||
sdr_2 = mips64 and "b1000000TO",
|
||||
swr_2 = "b8000000TO",
|
||||
cache_2 = "bc000000NO",
|
||||
ll_2 = "c0000000TO",
|
||||
pref_2 = "cc000000NO",
|
||||
sc_2 = "e0000000TO",
|
||||
scd_2 = mips64 and "f0000000TO",
|
||||
|
||||
-- Opcode SPECIAL.
|
||||
movf_2 = "00000001DS",
|
||||
movf_3 = "00000001DSC",
|
||||
movt_2 = "00010001DS",
|
||||
movt_3 = "00010001DSC",
|
||||
jr_1 = "00000008S",
|
||||
movz_3 = "0000000aDST",
|
||||
movn_3 = "0000000bDST",
|
||||
mfhi_1 = "00000010D",
|
||||
mthi_1 = "00000011S",
|
||||
mflo_1 = "00000012D",
|
||||
mtlo_1 = "00000013S",
|
||||
mult_2 = "00000018ST",
|
||||
multu_2 = "00000019ST",
|
||||
div_3 = "0000001aST",
|
||||
divu_3 = "0000001bST",
|
||||
ddiv_3 = mips64 and "0000001eST",
|
||||
ddivu_3 = mips64 and "0000001fST",
|
||||
dmult_2 = mips64 and "0000001cST",
|
||||
dmultu_2 = mips64 and "0000001dST",
|
||||
|
||||
-- Opcode REGIMM.
|
||||
tgei_2 = "04080000SI",
|
||||
tgeiu_2 = "04090000SI",
|
||||
tlti_2 = "040a0000SI",
|
||||
tltiu_2 = "040b0000SI",
|
||||
teqi_2 = "040c0000SI",
|
||||
tnei_2 = "040e0000SI",
|
||||
bltzal_2 = "04100000SB",
|
||||
bgezal_2 = "04110000SB",
|
||||
bltzall_2 = "04120000SB",
|
||||
bgezall_2 = "04130000SB",
|
||||
|
||||
-- Opcode SPECIAL2.
|
||||
madd_2 = "70000000ST",
|
||||
maddu_2 = "70000001ST",
|
||||
mul_3 = "70000002DST",
|
||||
msub_2 = "70000004ST",
|
||||
msubu_2 = "70000005ST",
|
||||
clz_2 = "70000020D=TS",
|
||||
clo_2 = "70000021D=TS",
|
||||
dclz_2 = mips64 and "70000024D=TS",
|
||||
dclo_2 = mips64 and "70000025D=TS",
|
||||
sdbbp_0 = "7000003f",
|
||||
sdbbp_1 = "7000003fY",
|
||||
|
||||
-- Opcode COP1.
|
||||
bc1f_1 = "45000000B",
|
||||
bc1f_2 = "45000000CB",
|
||||
bc1t_1 = "45010000B",
|
||||
bc1t_2 = "45010000CB",
|
||||
bc1fl_1 = "45020000B",
|
||||
bc1fl_2 = "45020000CB",
|
||||
bc1tl_1 = "45030000B",
|
||||
bc1tl_2 = "45030000CB",
|
||||
|
||||
["movf.s_2"] = "46000011FG",
|
||||
["movf.s_3"] = "46000011FGC",
|
||||
["movt.s_2"] = "46010011FG",
|
||||
["movt.s_3"] = "46010011FGC",
|
||||
["movz.s_3"] = "46000012FGT",
|
||||
["movn.s_3"] = "46000013FGT",
|
||||
["cvt.ps.s_3"] = "46000026FGH",
|
||||
["c.f.s_2"] = "46000030GH",
|
||||
["c.f.s_3"] = "46000030VGH",
|
||||
["c.un.s_2"] = "46000031GH",
|
||||
["c.un.s_3"] = "46000031VGH",
|
||||
["c.eq.s_2"] = "46000032GH",
|
||||
["c.eq.s_3"] = "46000032VGH",
|
||||
["c.ueq.s_2"] = "46000033GH",
|
||||
["c.ueq.s_3"] = "46000033VGH",
|
||||
["c.olt.s_2"] = "46000034GH",
|
||||
["c.olt.s_3"] = "46000034VGH",
|
||||
["c.ult.s_2"] = "46000035GH",
|
||||
["c.ult.s_3"] = "46000035VGH",
|
||||
["c.ole.s_2"] = "46000036GH",
|
||||
["c.ole.s_3"] = "46000036VGH",
|
||||
["c.ule.s_2"] = "46000037GH",
|
||||
["c.ule.s_3"] = "46000037VGH",
|
||||
["c.sf.s_2"] = "46000038GH",
|
||||
["c.sf.s_3"] = "46000038VGH",
|
||||
["c.ngle.s_2"] = "46000039GH",
|
||||
["c.ngle.s_3"] = "46000039VGH",
|
||||
["c.seq.s_2"] = "4600003aGH",
|
||||
["c.seq.s_3"] = "4600003aVGH",
|
||||
["c.ngl.s_2"] = "4600003bGH",
|
||||
["c.ngl.s_3"] = "4600003bVGH",
|
||||
["c.lt.s_2"] = "4600003cGH",
|
||||
["c.lt.s_3"] = "4600003cVGH",
|
||||
["c.nge.s_2"] = "4600003dGH",
|
||||
["c.nge.s_3"] = "4600003dVGH",
|
||||
["c.le.s_2"] = "4600003eGH",
|
||||
["c.le.s_3"] = "4600003eVGH",
|
||||
["c.ngt.s_2"] = "4600003fGH",
|
||||
["c.ngt.s_3"] = "4600003fVGH",
|
||||
["movf.d_2"] = "46200011FG",
|
||||
["movf.d_3"] = "46200011FGC",
|
||||
["movt.d_2"] = "46210011FG",
|
||||
["movt.d_3"] = "46210011FGC",
|
||||
["movz.d_3"] = "46200012FGT",
|
||||
["movn.d_3"] = "46200013FGT",
|
||||
["c.f.d_2"] = "46200030GH",
|
||||
["c.f.d_3"] = "46200030VGH",
|
||||
["c.un.d_2"] = "46200031GH",
|
||||
["c.un.d_3"] = "46200031VGH",
|
||||
["c.eq.d_2"] = "46200032GH",
|
||||
["c.eq.d_3"] = "46200032VGH",
|
||||
["c.ueq.d_2"] = "46200033GH",
|
||||
["c.ueq.d_3"] = "46200033VGH",
|
||||
["c.olt.d_2"] = "46200034GH",
|
||||
["c.olt.d_3"] = "46200034VGH",
|
||||
["c.ult.d_2"] = "46200035GH",
|
||||
["c.ult.d_3"] = "46200035VGH",
|
||||
["c.ole.d_2"] = "46200036GH",
|
||||
["c.ole.d_3"] = "46200036VGH",
|
||||
["c.ule.d_2"] = "46200037GH",
|
||||
["c.ule.d_3"] = "46200037VGH",
|
||||
["c.sf.d_2"] = "46200038GH",
|
||||
["c.sf.d_3"] = "46200038VGH",
|
||||
["c.ngle.d_2"] = "46200039GH",
|
||||
["c.ngle.d_3"] = "46200039VGH",
|
||||
["c.seq.d_2"] = "4620003aGH",
|
||||
["c.seq.d_3"] = "4620003aVGH",
|
||||
["c.ngl.d_2"] = "4620003bGH",
|
||||
["c.ngl.d_3"] = "4620003bVGH",
|
||||
["c.lt.d_2"] = "4620003cGH",
|
||||
["c.lt.d_3"] = "4620003cVGH",
|
||||
["c.nge.d_2"] = "4620003dGH",
|
||||
["c.nge.d_3"] = "4620003dVGH",
|
||||
["c.le.d_2"] = "4620003eGH",
|
||||
["c.le.d_3"] = "4620003eVGH",
|
||||
["c.ngt.d_2"] = "4620003fGH",
|
||||
["c.ngt.d_3"] = "4620003fVGH",
|
||||
["add.ps_3"] = "46c00000FGH",
|
||||
["sub.ps_3"] = "46c00001FGH",
|
||||
["mul.ps_3"] = "46c00002FGH",
|
||||
["abs.ps_2"] = "46c00005FG",
|
||||
["mov.ps_2"] = "46c00006FG",
|
||||
["neg.ps_2"] = "46c00007FG",
|
||||
["movf.ps_2"] = "46c00011FG",
|
||||
["movf.ps_3"] = "46c00011FGC",
|
||||
["movt.ps_2"] = "46c10011FG",
|
||||
["movt.ps_3"] = "46c10011FGC",
|
||||
["movz.ps_3"] = "46c00012FGT",
|
||||
["movn.ps_3"] = "46c00013FGT",
|
||||
["cvt.s.pu_2"] = "46c00020FG",
|
||||
["cvt.s.pl_2"] = "46c00028FG",
|
||||
["pll.ps_3"] = "46c0002cFGH",
|
||||
["plu.ps_3"] = "46c0002dFGH",
|
||||
["pul.ps_3"] = "46c0002eFGH",
|
||||
["puu.ps_3"] = "46c0002fFGH",
|
||||
["c.f.ps_2"] = "46c00030GH",
|
||||
["c.f.ps_3"] = "46c00030VGH",
|
||||
["c.un.ps_2"] = "46c00031GH",
|
||||
["c.un.ps_3"] = "46c00031VGH",
|
||||
["c.eq.ps_2"] = "46c00032GH",
|
||||
["c.eq.ps_3"] = "46c00032VGH",
|
||||
["c.ueq.ps_2"] = "46c00033GH",
|
||||
["c.ueq.ps_3"] = "46c00033VGH",
|
||||
["c.olt.ps_2"] = "46c00034GH",
|
||||
["c.olt.ps_3"] = "46c00034VGH",
|
||||
["c.ult.ps_2"] = "46c00035GH",
|
||||
["c.ult.ps_3"] = "46c00035VGH",
|
||||
["c.ole.ps_2"] = "46c00036GH",
|
||||
["c.ole.ps_3"] = "46c00036VGH",
|
||||
["c.ule.ps_2"] = "46c00037GH",
|
||||
["c.ule.ps_3"] = "46c00037VGH",
|
||||
["c.sf.ps_2"] = "46c00038GH",
|
||||
["c.sf.ps_3"] = "46c00038VGH",
|
||||
["c.ngle.ps_2"] = "46c00039GH",
|
||||
["c.ngle.ps_3"] = "46c00039VGH",
|
||||
["c.seq.ps_2"] = "46c0003aGH",
|
||||
["c.seq.ps_3"] = "46c0003aVGH",
|
||||
["c.ngl.ps_2"] = "46c0003bGH",
|
||||
["c.ngl.ps_3"] = "46c0003bVGH",
|
||||
["c.lt.ps_2"] = "46c0003cGH",
|
||||
["c.lt.ps_3"] = "46c0003cVGH",
|
||||
["c.nge.ps_2"] = "46c0003dGH",
|
||||
["c.nge.ps_3"] = "46c0003dVGH",
|
||||
["c.le.ps_2"] = "46c0003eGH",
|
||||
["c.le.ps_3"] = "46c0003eVGH",
|
||||
["c.ngt.ps_2"] = "46c0003fGH",
|
||||
["c.ngt.ps_3"] = "46c0003fVGH",
|
||||
|
||||
-- Opcode COP1X.
|
||||
lwxc1_2 = "4c000000FX",
|
||||
ldxc1_2 = "4c000001FX",
|
||||
luxc1_2 = "4c000005FX",
|
||||
swxc1_2 = "4c000008FX",
|
||||
sdxc1_2 = "4c000009FX",
|
||||
suxc1_2 = "4c00000dFX",
|
||||
prefx_2 = "4c00000fMX",
|
||||
["alnv.ps_4"] = "4c00001eFGHS",
|
||||
["madd.s_4"] = "4c000020FRGH",
|
||||
["madd.d_4"] = "4c000021FRGH",
|
||||
["madd.ps_4"] = "4c000026FRGH",
|
||||
["msub.s_4"] = "4c000028FRGH",
|
||||
["msub.d_4"] = "4c000029FRGH",
|
||||
["msub.ps_4"] = "4c00002eFRGH",
|
||||
["nmadd.s_4"] = "4c000030FRGH",
|
||||
["nmadd.d_4"] = "4c000031FRGH",
|
||||
["nmadd.ps_4"] = "4c000036FRGH",
|
||||
["nmsub.s_4"] = "4c000038FRGH",
|
||||
["nmsub.d_4"] = "4c000039FRGH",
|
||||
["nmsub.ps_4"] = "4c00003eFRGH",
|
||||
|
||||
}) do map_op[k] = v end
|
||||
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local function parse_gpr(expr)
|
||||
@@ -633,7 +855,7 @@ local function parse_fpr(expr)
|
||||
werror("bad register name `"..expr.."'")
|
||||
end
|
||||
|
||||
local function parse_imm(imm, bits, shift, scale, signed)
|
||||
local function parse_imm(imm, bits, shift, scale, signed, action)
|
||||
local n = tonumber(imm)
|
||||
if n then
|
||||
local m = sar(n, scale)
|
||||
@@ -651,7 +873,8 @@ local function parse_imm(imm, bits, shift, scale, signed)
|
||||
match(imm, "^([%w_]+):([rf][1-3]?[0-9])$") then
|
||||
werror("expected immediate operand, got register")
|
||||
else
|
||||
waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
|
||||
waction(action or "IMM",
|
||||
(signed and 32768 or 0)+shl(scale, 10)+shl(bits, 5)+shift, imm)
|
||||
return 0
|
||||
end
|
||||
end
|
||||
@@ -756,13 +979,18 @@ map_op[".template__"] = function(params, template, nparams)
|
||||
op = op + parse_disp(params[n]); n = n + 1
|
||||
elseif p == "X" then
|
||||
op = op + parse_index(params[n]); n = n + 1
|
||||
elseif p == "B" or p == "J" then
|
||||
local mode, n, s = parse_label(params[n], false)
|
||||
if p == "B" then n = n + 2048 end
|
||||
waction("REL_"..mode, n, s, 1)
|
||||
elseif p == "B" or p == "J" or p == "K" or p == "L" then
|
||||
local mode, m, s = parse_label(params[n], false)
|
||||
if p == "J" then m = m + 0xa800
|
||||
elseif p == "K" then m = m + 0x5000
|
||||
elseif p == "L" then m = m + 0xa000 end
|
||||
waction("REL_"..mode, m, s, 1)
|
||||
n = n + 1
|
||||
elseif p == "A" then
|
||||
op = op + parse_imm(params[n], 5, 6, 0, false); n = n + 1
|
||||
elseif p == "a" then
|
||||
local m = parse_imm(params[n], 6, 6, 0, false, "IMMS"); n = n + 1
|
||||
op = op + band(m, 0x7c0) + band(shr(m, 9), 4)
|
||||
elseif p == "M" then
|
||||
op = op + parse_imm(params[n], 5, 11, 0, false); n = n + 1
|
||||
elseif p == "N" then
|
||||
@@ -778,7 +1006,7 @@ map_op[".template__"] = function(params, template, nparams)
|
||||
elseif p == "Z" then
|
||||
op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1
|
||||
elseif p == "=" then
|
||||
op = op + shl(band(op, 0xf800), 5) -- Copy D to T for clz, clo.
|
||||
n = n - 1 -- Re-use previous parameter for next template char.
|
||||
else
|
||||
assert(false)
|
||||
end
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- DynASM MIPS64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
|
||||
-- All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
mips64 = true -- Using a global is an ugly, but effective solution.
|
||||
return require("dasm_mips")
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** DynASM PPC/PPC64 encoding engine.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
@@ -354,6 +354,7 @@ int dasm_encode(Dst_DECL, void *buffer)
|
||||
break;
|
||||
case DASM_REL_LG:
|
||||
CK(n >= 0, UNDEF_LG);
|
||||
/* fallthrough */
|
||||
case DASM_REL_PC:
|
||||
CK(n >= 0, UNDEF_PC);
|
||||
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- DynASM PPC/PPC64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
--
|
||||
-- Support for various extensions contributed by Caio Souza Oliveira.
|
||||
@@ -1722,9 +1722,9 @@ op_template = function(params, template, nparams)
|
||||
elseif p == "M" then
|
||||
op = op + parse_shiftmask(params[n], false); n = n + 1
|
||||
elseif p == "J" or p == "K" then
|
||||
local mode, n, s = parse_label(params[n], false)
|
||||
if p == "K" then n = n + 2048 end
|
||||
waction("REL_"..mode, n, s, 1)
|
||||
local mode, m, s = parse_label(params[n], false)
|
||||
if p == "K" then m = m + 2048 end
|
||||
waction("REL_"..mode, m, s, 1)
|
||||
n = n + 1
|
||||
elseif p == "0" then
|
||||
if band(shr(op, rs), 31) == 0 then werror("cannot use r0") end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** DynASM encoding engine prototypes.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- DynASM x64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
-- This module just sets 64 bit mode for the combined x86/x64 module.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** DynASM x86 encoding engine.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
@@ -170,7 +170,7 @@ void dasm_put(Dst_DECL, int start, ...)
|
||||
dasm_State *D = Dst_REF;
|
||||
dasm_ActList p = D->actionlist + start;
|
||||
dasm_Section *sec = D->section;
|
||||
int pos = sec->pos, ofs = sec->ofs, mrm = 4;
|
||||
int pos = sec->pos, ofs = sec->ofs, mrm = -1;
|
||||
int *b;
|
||||
|
||||
if (pos >= sec->epos) {
|
||||
@@ -193,20 +193,28 @@ void dasm_put(Dst_DECL, int start, ...)
|
||||
b[pos++] = n;
|
||||
switch (action) {
|
||||
case DASM_DISP:
|
||||
if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; }
|
||||
case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob;
|
||||
if (n == 0) { if (mrm < 0) mrm = p[-2]; if ((mrm&7) != 5) break; }
|
||||
/* fallthrough */
|
||||
case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */
|
||||
case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */
|
||||
case DASM_IMM_D: ofs += 4; break;
|
||||
case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob;
|
||||
case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break;
|
||||
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob;
|
||||
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */
|
||||
case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break;
|
||||
case DASM_SPACE: p++; ofs += n; break;
|
||||
case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */
|
||||
case DASM_VREG: CK((n&-8) == 0 && (n != 4 || (*p&1) == 0), RANGE_VREG);
|
||||
if (*p++ == 1 && *p == DASM_DISP) mrm = n; continue;
|
||||
case DASM_VREG: CK((n&-16) == 0 && (n != 4 || (*p>>5) != 2), RANGE_VREG);
|
||||
if (*p < 0x40 && p[1] == DASM_DISP) mrm = n;
|
||||
if (*p < 0x20 && (n&7) == 4) ofs++;
|
||||
switch ((*p++ >> 3) & 3) {
|
||||
case 3: n |= b[pos-3]; /* fallthrough */
|
||||
case 2: n |= b[pos-2]; /* fallthrough */
|
||||
case 1: if (n <= 7) { b[pos-1] |= 0x10; ofs--; }
|
||||
}
|
||||
continue;
|
||||
}
|
||||
mrm = 4;
|
||||
mrm = -1;
|
||||
} else {
|
||||
int *pl, n;
|
||||
switch (action) {
|
||||
@@ -297,11 +305,13 @@ int dasm_link(Dst_DECL, size_t *szp)
|
||||
|
||||
while (pos != lastpos) {
|
||||
dasm_ActList p = D->actionlist + b[pos++];
|
||||
int op = 0;
|
||||
while (1) {
|
||||
int op, action = *p++;
|
||||
int action = *p++;
|
||||
switch (action) {
|
||||
case DASM_REL_LG: p++; op = p[-3]; goto rel_pc;
|
||||
case DASM_REL_PC: op = p[-2]; rel_pc: {
|
||||
case DASM_REL_LG: p++;
|
||||
/* fallthrough */
|
||||
case DASM_REL_PC: {
|
||||
int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0);
|
||||
if (shrink) { /* Shrinkable branch opcode? */
|
||||
int lofs, lpos = b[pos];
|
||||
@@ -322,17 +332,21 @@ int dasm_link(Dst_DECL, size_t *szp)
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++;
|
||||
/* fallthrough */
|
||||
case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W:
|
||||
case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB:
|
||||
case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break;
|
||||
case DASM_LABEL_LG: p++;
|
||||
/* fallthrough */
|
||||
case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */
|
||||
case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */
|
||||
case DASM_EXTERN: p += 2; break;
|
||||
case DASM_ESC: p++; break;
|
||||
case DASM_ESC: op = *p++; break;
|
||||
case DASM_MARK: break;
|
||||
case DASM_SECTION: case DASM_STOP: goto stop;
|
||||
default: op = action; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
@@ -384,22 +398,42 @@ int dasm_encode(Dst_DECL, void *buffer)
|
||||
if (mrm != 5) { mm[-1] -= 0x80; break; } }
|
||||
if (((n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40;
|
||||
}
|
||||
/* fallthrough */
|
||||
case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break;
|
||||
case DASM_IMM_DB: if (((n+128)&-256) == 0) {
|
||||
db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb;
|
||||
} else mark = NULL;
|
||||
/* fallthrough */
|
||||
case DASM_IMM_D: wd: dasmd(n); break;
|
||||
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL;
|
||||
/* fallthrough */
|
||||
case DASM_IMM_W: dasmw(n); break;
|
||||
case DASM_VREG: {
|
||||
int t = *p++;
|
||||
if (t >= 5) n <<= 4; else if (t >= 2) n <<= 3;
|
||||
unsigned char *ex = cp - (t&7);
|
||||
if ((n & 8) && t < 0xa0) {
|
||||
if (*ex & 0x80) ex[1] ^= 0x20 << (t>>6); else *ex ^= 1 << (t>>6);
|
||||
n &= 7;
|
||||
} else if (n & 0x10) {
|
||||
if (*ex & 0x80) {
|
||||
*ex = 0xc5; ex[1] = (ex[1] & 0x80) | ex[2]; ex += 2;
|
||||
}
|
||||
while (++ex < cp) ex[-1] = *ex;
|
||||
if (mark) mark--;
|
||||
cp--;
|
||||
n &= 7;
|
||||
}
|
||||
if (t >= 0xc0) n <<= 4;
|
||||
else if (t >= 0x40) n <<= 3;
|
||||
else if (n == 4 && t < 0x20) { cp[-1] ^= n; *cp++ = 0x20; }
|
||||
cp[-1] ^= n;
|
||||
break;
|
||||
}
|
||||
case DASM_REL_LG: p++; if (n >= 0) goto rel_pc;
|
||||
b++; n = (int)(ptrdiff_t)D->globals[-n];
|
||||
case DASM_REL_A: rel_a: n -= (int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */
|
||||
/* fallthrough */
|
||||
case DASM_REL_A: rel_a:
|
||||
n -= (unsigned int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */
|
||||
case DASM_REL_PC: rel_pc: {
|
||||
int shrink = *b++;
|
||||
int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; }
|
||||
@@ -410,6 +444,7 @@ int dasm_encode(Dst_DECL, void *buffer)
|
||||
}
|
||||
case DASM_IMM_LG:
|
||||
p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; }
|
||||
/* fallthrough */
|
||||
case DASM_IMM_PC: {
|
||||
int *pb = DASM_POS2PTR(D, n);
|
||||
n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base);
|
||||
@@ -430,6 +465,7 @@ int dasm_encode(Dst_DECL, void *buffer)
|
||||
case DASM_EXTERN: n = DASM_EXTERN(Dst, cp, p[1], *p); p += 2; goto wd;
|
||||
case DASM_MARK: mark = cp; break;
|
||||
case DASM_ESC: action = *p++;
|
||||
/* fallthrough */
|
||||
default: *cp++ = action; break;
|
||||
case DASM_SECTION: case DASM_STOP: goto stop;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- DynASM x86/x64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
@@ -41,7 +41,7 @@ local action_names = {
|
||||
-- int arg, 1 buffer pos:
|
||||
"DISP", "IMM_S", "IMM_B", "IMM_W", "IMM_D", "IMM_WB", "IMM_DB",
|
||||
-- action arg (1 byte), int arg, 1 buffer pos (reg/num):
|
||||
"VREG", "SPACE", -- !x64: VREG support NYI.
|
||||
"VREG", "SPACE",
|
||||
-- ptrdiff_t arg, 1 buffer pos (address): !x64
|
||||
"SETLABEL", "REL_A",
|
||||
-- action arg (1 byte) or int arg, 2 buffer pos (link, offset):
|
||||
@@ -83,6 +83,21 @@ local actargs = { 0 }
|
||||
-- Current number of section buffer positions for dasm_put().
|
||||
local secpos = 1
|
||||
|
||||
-- VREG kind encodings, pre-shifted by 5 bits.
|
||||
local map_vreg = {
|
||||
["modrm.rm.m"] = 0x00,
|
||||
["modrm.rm.r"] = 0x20,
|
||||
["opcode"] = 0x20,
|
||||
["sib.base"] = 0x20,
|
||||
["sib.index"] = 0x40,
|
||||
["modrm.reg"] = 0x80,
|
||||
["vex.v"] = 0xa0,
|
||||
["imm.hi"] = 0xc0,
|
||||
}
|
||||
|
||||
-- Current number of VREG actions contributing to REX/VEX shrinkage.
|
||||
local vreg_shrink_count = 0
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- Compute action numbers for action names.
|
||||
@@ -134,6 +149,21 @@ local function waction(action, a, num)
|
||||
if a or num then secpos = secpos + (num or 1) end
|
||||
end
|
||||
|
||||
-- Optionally add a VREG action.
|
||||
local function wvreg(kind, vreg, psz, sk, defer)
|
||||
if not vreg then return end
|
||||
waction("VREG", vreg)
|
||||
local b = assert(map_vreg[kind], "bad vreg kind `"..vreg.."'")
|
||||
if b < (sk or 0) then
|
||||
vreg_shrink_count = vreg_shrink_count + 1
|
||||
end
|
||||
if not defer then
|
||||
b = b + vreg_shrink_count * 8
|
||||
vreg_shrink_count = 0
|
||||
end
|
||||
wputxb(b + (psz or 0))
|
||||
end
|
||||
|
||||
-- Add call to embedded DynASM C code.
|
||||
local function wcall(func, args)
|
||||
wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true)
|
||||
@@ -326,6 +356,7 @@ mkrmap("w", "Rw", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"})
|
||||
mkrmap("b", "Rb", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"})
|
||||
map_reg_valid_index[map_archdef.esp] = false
|
||||
if x64 then map_reg_valid_index[map_archdef.rsp] = false end
|
||||
if x64 then map_reg_needrex[map_archdef.Rb] = true end
|
||||
map_archdef["Ra"] = "@"..addrsize
|
||||
|
||||
-- FP registers (internally tword sized, but use "f" as operand size).
|
||||
@@ -463,16 +494,24 @@ local function wputszarg(sz, n)
|
||||
end
|
||||
|
||||
-- Put multi-byte opcode with operand-size dependent modifications.
|
||||
local function wputop(sz, op, rex, vex)
|
||||
local function wputop(sz, op, rex, vex, vregr, vregxb)
|
||||
local psz, sk = 0, nil
|
||||
if vex then
|
||||
local tail
|
||||
if vex.m == 1 and band(rex, 11) == 0 then
|
||||
wputb(0xc5)
|
||||
if x64 and vregxb then
|
||||
sk = map_vreg["modrm.reg"]
|
||||
else
|
||||
wputb(0xc5)
|
||||
tail = shl(bxor(band(rex, 4), 4), 5)
|
||||
else
|
||||
psz = 3
|
||||
end
|
||||
end
|
||||
if not tail then
|
||||
wputb(0xc4)
|
||||
wputb(shl(bxor(band(rex, 7), 7), 5) + vex.m)
|
||||
tail = shl(band(rex, 8), 4)
|
||||
psz = 4
|
||||
end
|
||||
local reg, vreg = 0, nil
|
||||
if vex.v then
|
||||
@@ -482,12 +521,18 @@ local function wputop(sz, op, rex, vex)
|
||||
end
|
||||
if sz == "y" or vex.l then tail = tail + 4 end
|
||||
wputb(tail + shl(bxor(reg, 15), 3) + vex.p)
|
||||
if vreg then waction("VREG", vreg); wputxb(4) end
|
||||
wvreg("vex.v", vreg)
|
||||
rex = 0
|
||||
if op >= 256 then werror("bad vex opcode") end
|
||||
else
|
||||
if rex ~= 0 then
|
||||
if not x64 then werror("bad operand size") end
|
||||
elseif (vregr or vregxb) and x64 then
|
||||
rex = 0x10
|
||||
sk = map_vreg["vex.v"]
|
||||
end
|
||||
end
|
||||
local r
|
||||
if rex ~= 0 and not x64 then werror("bad operand size") end
|
||||
if sz == "w" then wputb(102) end
|
||||
-- Needs >32 bit numbers, but only for crc32 eax, word [ebx]
|
||||
if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end
|
||||
@@ -496,20 +541,20 @@ local function wputop(sz, op, rex, vex)
|
||||
if rex ~= 0 then
|
||||
local opc3 = band(op, 0xffff00)
|
||||
if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then
|
||||
wputb(64 + band(rex, 15)); rex = 0
|
||||
wputb(64 + band(rex, 15)); rex = 0; psz = 2
|
||||
end
|
||||
end
|
||||
wputb(shr(op, 16)); op = band(op, 0xffff)
|
||||
wputb(shr(op, 16)); op = band(op, 0xffff); psz = psz + 1
|
||||
end
|
||||
if op >= 256 then
|
||||
local b = shr(op, 8)
|
||||
if b == 15 and rex ~= 0 then wputb(64 + band(rex, 15)); rex = 0 end
|
||||
wputb(b)
|
||||
op = band(op, 255)
|
||||
if b == 15 and rex ~= 0 then wputb(64 + band(rex, 15)); rex = 0; psz = 2 end
|
||||
wputb(b); op = band(op, 255); psz = psz + 1
|
||||
end
|
||||
if rex ~= 0 then wputb(64 + band(rex, 15)) end
|
||||
if rex ~= 0 then wputb(64 + band(rex, 15)); psz = 2 end
|
||||
if sz == "b" then op = op - 1 end
|
||||
wputb(op)
|
||||
return psz, sk
|
||||
end
|
||||
|
||||
-- Put ModRM or SIB formatted byte.
|
||||
@@ -519,7 +564,7 @@ local function wputmodrm(m, s, rm, vs, vrm)
|
||||
end
|
||||
|
||||
-- Put ModRM/SIB plus optional displacement.
|
||||
local function wputmrmsib(t, imark, s, vsreg)
|
||||
local function wputmrmsib(t, imark, s, vsreg, psz, sk)
|
||||
local vreg, vxreg
|
||||
local reg, xreg = t.reg, t.xreg
|
||||
if reg and reg < 0 then reg = 0; vreg = t.vreg end
|
||||
@@ -529,8 +574,8 @@ local function wputmrmsib(t, imark, s, vsreg)
|
||||
-- Register mode.
|
||||
if sub(t.mode, 1, 1) == "r" then
|
||||
wputmodrm(3, s, reg)
|
||||
if vsreg then waction("VREG", vsreg); wputxb(2) end
|
||||
if vreg then waction("VREG", vreg); wputxb(0) end
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk, vreg)
|
||||
wvreg("modrm.rm.r", vreg, psz+1, sk)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -544,21 +589,22 @@ local function wputmrmsib(t, imark, s, vsreg)
|
||||
-- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp)
|
||||
wputmodrm(0, s, 4)
|
||||
if imark == "I" then waction("MARK") end
|
||||
if vsreg then waction("VREG", vsreg); wputxb(2) end
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk, vxreg)
|
||||
wputmodrm(t.xsc, xreg, 5)
|
||||
if vxreg then waction("VREG", vxreg); wputxb(3) end
|
||||
wvreg("sib.index", vxreg, psz+2, sk)
|
||||
else
|
||||
-- Pure 32 bit displacement.
|
||||
if x64 and tdisp ~= "table" then
|
||||
wputmodrm(0, s, 4) -- [disp] -> (0, s, esp) (0, esp, ebp)
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk)
|
||||
if imark == "I" then waction("MARK") end
|
||||
wputmodrm(0, 4, 5)
|
||||
else
|
||||
riprel = x64
|
||||
wputmodrm(0, s, 5) -- [disp|rip-label] -> (0, s, ebp)
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk)
|
||||
if imark == "I" then waction("MARK") end
|
||||
end
|
||||
if vsreg then waction("VREG", vsreg); wputxb(2) end
|
||||
end
|
||||
if riprel then -- Emit rip-relative displacement.
|
||||
if match("UWSiI", imark) then
|
||||
@@ -586,16 +632,16 @@ local function wputmrmsib(t, imark, s, vsreg)
|
||||
if xreg or band(reg, 7) == 4 then
|
||||
wputmodrm(m or 2, s, 4) -- ModRM.
|
||||
if m == nil or imark == "I" then waction("MARK") end
|
||||
if vsreg then waction("VREG", vsreg); wputxb(2) end
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk, vxreg or vreg)
|
||||
wputmodrm(t.xsc or 0, xreg or 4, reg) -- SIB.
|
||||
if vxreg then waction("VREG", vxreg); wputxb(3) end
|
||||
if vreg then waction("VREG", vreg); wputxb(1) end
|
||||
wvreg("sib.index", vxreg, psz+2, sk, vreg)
|
||||
wvreg("sib.base", vreg, psz+2, sk)
|
||||
else
|
||||
wputmodrm(m or 2, s, reg) -- ModRM.
|
||||
if (imark == "I" and (m == 1 or m == 2)) or
|
||||
(m == nil and (vsreg or vreg)) then waction("MARK") end
|
||||
if vsreg then waction("VREG", vsreg); wputxb(2) end
|
||||
if vreg then waction("VREG", vreg); wputxb(1) end
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk, vreg)
|
||||
wvreg("modrm.rm.m", vreg, psz+1, sk)
|
||||
end
|
||||
|
||||
-- Put displacement.
|
||||
@@ -909,6 +955,7 @@ end
|
||||
-- "u" Use VEX encoding, vvvv unused.
|
||||
-- "v"/"V" Use VEX encoding, vvvv from 1st/2nd operand (the operand is
|
||||
-- removed from the list used by future characters).
|
||||
-- "w" Use VEX encoding, vvvv from 3rd operand.
|
||||
-- "L" Force VEX.L
|
||||
--
|
||||
-- All of the following characters force a flush of the opcode:
|
||||
@@ -1490,8 +1537,8 @@ local map_op = {
|
||||
vrcpss_3 = "rrro:F30FV53rM|rrx/ood:",
|
||||
vrsqrtps_2 = "rmoy:0Fu52rM",
|
||||
vrsqrtss_3 = "rrro:F30FV52rM|rrx/ood:",
|
||||
vroundpd_3 = "rmioy:660F3AV09rMU",
|
||||
vroundps_3 = "rmioy:660F3AV08rMU",
|
||||
vroundpd_3 = "rmioy:660F3Au09rMU",
|
||||
vroundps_3 = "rmioy:660F3Au08rMU",
|
||||
vroundsd_4 = "rrrio:660F3AV0BrMU|rrxi/ooq:",
|
||||
vroundss_4 = "rrrio:660F3AV0ArMU|rrxi/ood:",
|
||||
vshufpd_4 = "rrmioy:660FVC6rMU",
|
||||
@@ -1521,6 +1568,12 @@ local map_op = {
|
||||
|
||||
-- AVX, AVX2 integer ops
|
||||
-- In general, xmm requires AVX, ymm requires AVX2.
|
||||
vaesdec_3 = "rrmo:660F38VDErM",
|
||||
vaesdeclast_3 = "rrmo:660F38VDFrM",
|
||||
vaesenc_3 = "rrmo:660F38VDCrM",
|
||||
vaesenclast_3 = "rrmo:660F38VDDrM",
|
||||
vaesimc_2 = "rmo:660F38uDBrM",
|
||||
vaeskeygenassist_3 = "rmio:660F3AuDFrMU",
|
||||
vlddqu_2 = "rxoy:F20FuF0rM",
|
||||
vmaskmovdqu_2 = "rro:660FuF7rM",
|
||||
vmovdqa_2 = "rmoy:660Fu6FrM|mroy:660Fu7FRm",
|
||||
@@ -1621,6 +1674,95 @@ local map_op = {
|
||||
vpsravd_3 = "rrmoy:660F38V46rM",
|
||||
vpsrlvd_3 = "rrmoy:660F38V45rM",
|
||||
vpsrlvq_3 = "rrmoy:660F38VX45rM",
|
||||
|
||||
-- Intel ADX
|
||||
adcx_2 = "rmqd:660F38F6rM",
|
||||
adox_2 = "rmqd:F30F38F6rM",
|
||||
|
||||
-- BMI1
|
||||
andn_3 = "rrmqd:0F38VF2rM",
|
||||
bextr_3 = "rmrqd:0F38wF7rM",
|
||||
blsi_2 = "rmqd:0F38vF33m",
|
||||
blsmsk_2 = "rmqd:0F38vF32m",
|
||||
blsr_2 = "rmqd:0F38vF31m",
|
||||
tzcnt_2 = "rmqdw:F30FBCrM",
|
||||
|
||||
-- BMI2
|
||||
bzhi_3 = "rmrqd:0F38wF5rM",
|
||||
mulx_3 = "rrmqd:F20F38VF6rM",
|
||||
pdep_3 = "rrmqd:F20F38VF5rM",
|
||||
pext_3 = "rrmqd:F30F38VF5rM",
|
||||
rorx_3 = "rmSqd:F20F3AuF0rMS",
|
||||
sarx_3 = "rmrqd:F30F38wF7rM",
|
||||
shrx_3 = "rmrqd:F20F38wF7rM",
|
||||
shlx_3 = "rmrqd:660F38wF7rM",
|
||||
|
||||
-- FMA3
|
||||
vfmaddsub132pd_3 = "rrmoy:660F38VX96rM",
|
||||
vfmaddsub132ps_3 = "rrmoy:660F38V96rM",
|
||||
vfmaddsub213pd_3 = "rrmoy:660F38VXA6rM",
|
||||
vfmaddsub213ps_3 = "rrmoy:660F38VA6rM",
|
||||
vfmaddsub231pd_3 = "rrmoy:660F38VXB6rM",
|
||||
vfmaddsub231ps_3 = "rrmoy:660F38VB6rM",
|
||||
|
||||
vfmsubadd132pd_3 = "rrmoy:660F38VX97rM",
|
||||
vfmsubadd132ps_3 = "rrmoy:660F38V97rM",
|
||||
vfmsubadd213pd_3 = "rrmoy:660F38VXA7rM",
|
||||
vfmsubadd213ps_3 = "rrmoy:660F38VA7rM",
|
||||
vfmsubadd231pd_3 = "rrmoy:660F38VXB7rM",
|
||||
vfmsubadd231ps_3 = "rrmoy:660F38VB7rM",
|
||||
|
||||
vfmadd132pd_3 = "rrmoy:660F38VX98rM",
|
||||
vfmadd132ps_3 = "rrmoy:660F38V98rM",
|
||||
vfmadd132sd_3 = "rrro:660F38VX99rM|rrx/ooq:",
|
||||
vfmadd132ss_3 = "rrro:660F38V99rM|rrx/ood:",
|
||||
vfmadd213pd_3 = "rrmoy:660F38VXA8rM",
|
||||
vfmadd213ps_3 = "rrmoy:660F38VA8rM",
|
||||
vfmadd213sd_3 = "rrro:660F38VXA9rM|rrx/ooq:",
|
||||
vfmadd213ss_3 = "rrro:660F38VA9rM|rrx/ood:",
|
||||
vfmadd231pd_3 = "rrmoy:660F38VXB8rM",
|
||||
vfmadd231ps_3 = "rrmoy:660F38VB8rM",
|
||||
vfmadd231sd_3 = "rrro:660F38VXB9rM|rrx/ooq:",
|
||||
vfmadd231ss_3 = "rrro:660F38VB9rM|rrx/ood:",
|
||||
|
||||
vfmsub132pd_3 = "rrmoy:660F38VX9ArM",
|
||||
vfmsub132ps_3 = "rrmoy:660F38V9ArM",
|
||||
vfmsub132sd_3 = "rrro:660F38VX9BrM|rrx/ooq:",
|
||||
vfmsub132ss_3 = "rrro:660F38V9BrM|rrx/ood:",
|
||||
vfmsub213pd_3 = "rrmoy:660F38VXAArM",
|
||||
vfmsub213ps_3 = "rrmoy:660F38VAArM",
|
||||
vfmsub213sd_3 = "rrro:660F38VXABrM|rrx/ooq:",
|
||||
vfmsub213ss_3 = "rrro:660F38VABrM|rrx/ood:",
|
||||
vfmsub231pd_3 = "rrmoy:660F38VXBArM",
|
||||
vfmsub231ps_3 = "rrmoy:660F38VBArM",
|
||||
vfmsub231sd_3 = "rrro:660F38VXBBrM|rrx/ooq:",
|
||||
vfmsub231ss_3 = "rrro:660F38VBBrM|rrx/ood:",
|
||||
|
||||
vfnmadd132pd_3 = "rrmoy:660F38VX9CrM",
|
||||
vfnmadd132ps_3 = "rrmoy:660F38V9CrM",
|
||||
vfnmadd132sd_3 = "rrro:660F38VX9DrM|rrx/ooq:",
|
||||
vfnmadd132ss_3 = "rrro:660F38V9DrM|rrx/ood:",
|
||||
vfnmadd213pd_3 = "rrmoy:660F38VXACrM",
|
||||
vfnmadd213ps_3 = "rrmoy:660F38VACrM",
|
||||
vfnmadd213sd_3 = "rrro:660F38VXADrM|rrx/ooq:",
|
||||
vfnmadd213ss_3 = "rrro:660F38VADrM|rrx/ood:",
|
||||
vfnmadd231pd_3 = "rrmoy:660F38VXBCrM",
|
||||
vfnmadd231ps_3 = "rrmoy:660F38VBCrM",
|
||||
vfnmadd231sd_3 = "rrro:660F38VXBDrM|rrx/ooq:",
|
||||
vfnmadd231ss_3 = "rrro:660F38VBDrM|rrx/ood:",
|
||||
|
||||
vfnmsub132pd_3 = "rrmoy:660F38VX9ErM",
|
||||
vfnmsub132ps_3 = "rrmoy:660F38V9ErM",
|
||||
vfnmsub132sd_3 = "rrro:660F38VX9FrM|rrx/ooq:",
|
||||
vfnmsub132ss_3 = "rrro:660F38V9FrM|rrx/ood:",
|
||||
vfnmsub213pd_3 = "rrmoy:660F38VXAErM",
|
||||
vfnmsub213ps_3 = "rrmoy:660F38VAErM",
|
||||
vfnmsub213sd_3 = "rrro:660F38VXAFrM|rrx/ooq:",
|
||||
vfnmsub213ss_3 = "rrro:660F38VAFrM|rrx/ood:",
|
||||
vfnmsub231pd_3 = "rrmoy:660F38VXBErM",
|
||||
vfnmsub231ps_3 = "rrmoy:660F38VBErM",
|
||||
vfnmsub231sd_3 = "rrro:660F38VXBFrM|rrx/ooq:",
|
||||
vfnmsub231ss_3 = "rrro:660F38VBFrM|rrx/ood:",
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@@ -1710,7 +1852,7 @@ end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local map_vexarg = { u = false, v = 1, V = 2 }
|
||||
local map_vexarg = { u = false, v = 1, V = 2, w = 3 }
|
||||
|
||||
-- Process pattern string.
|
||||
local function dopattern(pat, args, sz, op, needrex)
|
||||
@@ -1761,10 +1903,11 @@ local function dopattern(pat, args, sz, op, needrex)
|
||||
if t.xreg and t.xreg > 7 then rex = rex + 2 end
|
||||
if s > 7 then rex = rex + 4 end
|
||||
if needrex then rex = rex + 16 end
|
||||
wputop(szov, opcode, rex, vex); opcode = nil
|
||||
local psz, sk = wputop(szov, opcode, rex, vex, s < 0, t.vreg or t.vxreg)
|
||||
opcode = nil
|
||||
local imark = sub(pat, -1) -- Force a mark (ugly).
|
||||
-- Put ModRM/SIB with regno/last digit as spare.
|
||||
wputmrmsib(t, imark, s, addin and addin.vreg)
|
||||
wputmrmsib(t, imark, s, addin and addin.vreg, psz, sk)
|
||||
addin = nil
|
||||
elseif map_vexarg[c] ~= nil then -- Encode using VEX prefix
|
||||
local b = band(opcode, 255); opcode = shr(opcode, 8)
|
||||
@@ -1791,8 +1934,8 @@ local function dopattern(pat, args, sz, op, needrex)
|
||||
if szov == "q" and rex == 0 then rex = rex + 8 end
|
||||
if needrex then rex = rex + 16 end
|
||||
if addin and addin.reg == -1 then
|
||||
wputop(szov, opcode - 7, rex, vex)
|
||||
waction("VREG", addin.vreg); wputxb(0)
|
||||
local psz, sk = wputop(szov, opcode - 7, rex, vex, true)
|
||||
wvreg("opcode", addin.vreg, psz, sk)
|
||||
else
|
||||
if addin and addin.reg > 7 then rex = rex + 1 end
|
||||
wputop(szov, opcode, rex, vex)
|
||||
@@ -1836,7 +1979,7 @@ local function dopattern(pat, args, sz, op, needrex)
|
||||
local reg = a.reg
|
||||
if reg < 0 then
|
||||
wputb(0)
|
||||
waction("VREG", a.vreg); wputxb(5)
|
||||
wvreg("imm.hi", a.vreg)
|
||||
else
|
||||
wputb(shl(reg, 4))
|
||||
end
|
||||
@@ -1988,8 +2131,8 @@ if x64 then
|
||||
rex = a.reg > 7 and 9 or 8
|
||||
end
|
||||
end
|
||||
wputop(sz, opcode, rex)
|
||||
if vreg then waction("VREG", vreg); wputxb(0) end
|
||||
local psz, sk = wputop(sz, opcode, rex, nil, vreg)
|
||||
wvreg("opcode", vreg, psz, sk)
|
||||
waction("IMM_D", format("(unsigned int)(%s)", op64))
|
||||
waction("IMM_D", format("(unsigned int)((%s)>>32)", op64))
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- DynASM. A dynamic assembler for code generation engines.
|
||||
-- Originally designed and implemented for LuaJIT.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- See below for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
@@ -14,10 +14,10 @@ local _info = {
|
||||
vernum = 10400,
|
||||
release = "2015-10-18",
|
||||
author = "Mike Pall",
|
||||
url = "http://luajit.org/dynasm.html",
|
||||
url = "https://luajit.org/dynasm.html",
|
||||
license = "MIT",
|
||||
copyright = [[
|
||||
Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -38,7 +38,7 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
[ MIT license: http://www.opensource.org/licenses/mit-license.php ]
|
||||
[ MIT license: https://www.opensource.org/licenses/mit-license.php ]
|
||||
]],
|
||||
}
|
||||
|
||||
@@ -630,6 +630,7 @@ end
|
||||
-- Load architecture-specific module.
|
||||
local function loadarch(arch)
|
||||
if not match(arch, "^[%w_]+$") then return "bad arch name" end
|
||||
_G._map_def = map_def
|
||||
local ok, m_arch = pcall(require, "dasm_"..arch)
|
||||
if not ok then return "cannot load module: "..m_arch end
|
||||
g_arch = m_arch
|
||||
|
||||
@@ -6,7 +6,7 @@ luajit \- Just-In-Time Compiler for the Lua Language
|
||||
.B luajit
|
||||
[\fIoptions\fR]... [\fIscript\fR [\fIargs\fR]...]
|
||||
.SH "WEB SITE"
|
||||
.IR http://luajit.org
|
||||
.IR https://luajit.org
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
This is the command-line program to run Lua programs with \fBLuaJIT\fR.
|
||||
@@ -74,15 +74,15 @@ luajit \-jv \-e "for i=1,10 do for j=1,10 do for k=1,100 do end end end"
|
||||
Runs some nested loops and shows the resulting traces.
|
||||
.SH COPYRIGHT
|
||||
.PP
|
||||
\fBLuaJIT\fR is Copyright \(co 2005-2015 Mike Pall.
|
||||
\fBLuaJIT\fR is Copyright \(co 2005-2021 Mike Pall.
|
||||
.br
|
||||
\fBLuaJIT\fR is open source software, released under the MIT license.
|
||||
.SH SEE ALSO
|
||||
.PP
|
||||
More details in the provided HTML docs or at:
|
||||
.IR http://luajit.org
|
||||
.IR https://luajit.org
|
||||
.br
|
||||
More about the Lua language can be found at:
|
||||
.IR http://lua.org/docs.html
|
||||
.IR https://lua.org/docs.html
|
||||
.PP
|
||||
lua(1)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
majver=2
|
||||
minver=1
|
||||
relver=0
|
||||
version=${majver}.${minver}.${relver}-beta1
|
||||
version=${majver}.${minver}.${relver}-beta3
|
||||
abiver=5.1
|
||||
|
||||
prefix=/usr/local
|
||||
@@ -17,7 +17,7 @@ INSTALL_CMOD=${prefix}/${multilib}/lua/${abiver}
|
||||
|
||||
Name: LuaJIT
|
||||
Description: Just-in-time compiler for Lua
|
||||
URL: http://luajit.org
|
||||
URL: https://luajit.org
|
||||
Version: ${version}
|
||||
Requires:
|
||||
Libs: -L${libdir} -l${libname}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# Also works with MinGW and Cygwin on Windows.
|
||||
# Please check msvcbuild.bat for building with MSVC on Windows.
|
||||
#
|
||||
# Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
# Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
##############################################################################
|
||||
|
||||
MAJVER= 2
|
||||
@@ -110,6 +110,9 @@ XCFLAGS=
|
||||
#XCFLAGS+= -DLUAJIT_NUMMODE=1
|
||||
#XCFLAGS+= -DLUAJIT_NUMMODE=2
|
||||
#
|
||||
# Disable LJ_GC64 mode for x64.
|
||||
#XCFLAGS+= -DLUAJIT_DISABLE_GC64
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
@@ -121,15 +124,14 @@ XCFLAGS=
|
||||
#
|
||||
# Use the system provided memory allocator (realloc) instead of the
|
||||
# bundled memory allocator. This is slower, but sometimes helpful for
|
||||
# debugging. This option cannot be enabled on x64, since realloc usually
|
||||
# doesn't return addresses in the right address range.
|
||||
# debugging. This option cannot be enabled on x64 without GC64, since
|
||||
# realloc usually doesn't return addresses in the right address range.
|
||||
# OTOH this option is mandatory for Valgrind's memcheck tool on x64 and
|
||||
# the only way to get useful results from it for all other architectures.
|
||||
#XCFLAGS+= -DLUAJIT_USE_SYSMALLOC
|
||||
#
|
||||
# This define is required to run LuaJIT under Valgrind. The Valgrind
|
||||
# header files must be installed. You should enable debug information, too.
|
||||
# Use --suppressions=lj.supp to avoid some false positives.
|
||||
#XCFLAGS+= -DLUAJIT_USE_VALGRIND
|
||||
#
|
||||
# This is the client for the GDB JIT API. GDB 7.0 or higher is required
|
||||
@@ -155,21 +157,20 @@ XCFLAGS=
|
||||
|
||||
ifeq (Windows,$(findstring Windows,$(OS))$(MSYSTEM)$(TERM))
|
||||
HOST_SYS= Windows
|
||||
HOST_RM= del
|
||||
else
|
||||
HOST_SYS:= $(shell uname -s)
|
||||
ifneq (,$(findstring MINGW,$(HOST_SYS)))
|
||||
HOST_SYS= Windows
|
||||
HOST_MSYS= mingw
|
||||
endif
|
||||
ifneq (,$(findstring MSYS,$(HOST_SYS)))
|
||||
HOST_SYS= Windows
|
||||
HOST_MSYS= mingw
|
||||
endif
|
||||
ifneq (,$(findstring CYGWIN,$(HOST_SYS)))
|
||||
HOST_SYS= Windows
|
||||
HOST_MSYS= cygwin
|
||||
endif
|
||||
# Use Clang for OSX host.
|
||||
ifeq (Darwin,$(HOST_SYS))
|
||||
DEFAULT_CC= clang
|
||||
endif
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
@@ -192,7 +193,7 @@ CCOPTIONS= $(CCDEBUG) $(ASOPTIONS)
|
||||
LDOPTIONS= $(CCDEBUG) $(LDFLAGS)
|
||||
|
||||
HOST_CC= $(CC)
|
||||
HOST_RM= rm -f
|
||||
HOST_RM?= rm -f
|
||||
# If left blank, minilua is built and used. You can supply an installed
|
||||
# copy of (plain) Lua 5.1 or 5.2, plus Lua BitOp. E.g. with: HOST_LUA=lua
|
||||
HOST_LUA=
|
||||
@@ -210,7 +211,7 @@ TARGET_CC= $(STATIC_CC)
|
||||
TARGET_STCC= $(STATIC_CC)
|
||||
TARGET_DYNCC= $(DYNAMIC_CC)
|
||||
TARGET_LD= $(CROSS)$(CC)
|
||||
TARGET_AR= $(CROSS)ar rcus
|
||||
TARGET_AR= $(CROSS)ar rcus 2>/dev/null
|
||||
TARGET_STRIP= $(CROSS)strip
|
||||
|
||||
TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib)
|
||||
@@ -218,6 +219,7 @@ TARGET_SONAME= libluajit-$(ABIVER).so.$(MAJVER)
|
||||
TARGET_DYLIBNAME= libluajit-$(ABIVER).$(MAJVER).dylib
|
||||
TARGET_DYLIBPATH= $(TARGET_LIBPATH)/$(TARGET_DYLIBNAME)
|
||||
TARGET_DLLNAME= lua$(NODOTABIVER).dll
|
||||
TARGET_DLLDOTANAME= libluajit-$(ABIVER).dll.a
|
||||
TARGET_XSHLDFLAGS= -shared -fPIC -Wl,-soname,$(TARGET_SONAME)
|
||||
TARGET_DYNXLDOPTS=
|
||||
|
||||
@@ -243,6 +245,9 @@ ifneq (,$(findstring LJ_TARGET_ARM ,$(TARGET_TESTARCH)))
|
||||
TARGET_LJARCH= arm
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_ARM64 ,$(TARGET_TESTARCH)))
|
||||
ifneq (,$(findstring __AARCH64EB__ ,$(TARGET_TESTARCH)))
|
||||
TARGET_ARCH= -D__AARCH64EB__=1
|
||||
endif
|
||||
TARGET_LJARCH= arm64
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_PPC ,$(TARGET_TESTARCH)))
|
||||
@@ -257,7 +262,11 @@ ifneq (,$(findstring LJ_TARGET_MIPS ,$(TARGET_TESTARCH)))
|
||||
ifneq (,$(findstring MIPSEL ,$(TARGET_TESTARCH)))
|
||||
TARGET_ARCH= -D__MIPSEL__=1
|
||||
endif
|
||||
TARGET_LJARCH= mips
|
||||
ifneq (,$(findstring LJ_TARGET_MIPS64 ,$(TARGET_TESTARCH)))
|
||||
TARGET_LJARCH= mips64
|
||||
else
|
||||
TARGET_LJARCH= mips
|
||||
endif
|
||||
else
|
||||
$(error Unsupported target architecture)
|
||||
endif
|
||||
@@ -299,7 +308,7 @@ endif
|
||||
TARGET_SYS?= $(HOST_SYS)
|
||||
ifeq (Windows,$(TARGET_SYS))
|
||||
TARGET_STRIP+= --strip-unneeded
|
||||
TARGET_XSHLDFLAGS= -shared
|
||||
TARGET_XSHLDFLAGS= -shared -Wl,--out-implib,$(TARGET_DLLDOTANAME)
|
||||
TARGET_DYNXLDOPTS=
|
||||
else
|
||||
ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1))
|
||||
@@ -307,10 +316,9 @@ ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector
|
||||
endif
|
||||
ifeq (Darwin,$(TARGET_SYS))
|
||||
ifeq (,$(MACOSX_DEPLOYMENT_TARGET))
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.4
|
||||
$(error missing: export MACOSX_DEPLOYMENT_TARGET=XX.YY)
|
||||
endif
|
||||
TARGET_STRIP+= -x
|
||||
TARGET_AR+= 2>/dev/null
|
||||
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)
|
||||
@@ -321,7 +329,6 @@ ifeq (Darwin,$(TARGET_SYS))
|
||||
else
|
||||
ifeq (iOS,$(TARGET_SYS))
|
||||
TARGET_STRIP+= -x
|
||||
TARGET_AR+= 2>/dev/null
|
||||
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)
|
||||
@@ -355,7 +362,7 @@ ifneq ($(HOST_SYS),$(TARGET_SYS))
|
||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX
|
||||
else
|
||||
ifeq (iOS,$(TARGET_SYS))
|
||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX
|
||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX -DTARGET_OS_IPHONE=1
|
||||
else
|
||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OTHER
|
||||
endif
|
||||
@@ -388,6 +395,11 @@ DASM_XFLAGS=
|
||||
DASM_AFLAGS=
|
||||
DASM_ARCH= $(TARGET_LJARCH)
|
||||
|
||||
ifneq (,$(findstring LJ_LE 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D ENDIAN_LE
|
||||
else
|
||||
DASM_AFLAGS+= -D ENDIAN_BE
|
||||
endif
|
||||
ifneq (,$(findstring LJ_ARCH_BITS 64,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D P64
|
||||
endif
|
||||
@@ -430,6 +442,9 @@ ifeq (arm,$(TARGET_LJARCH))
|
||||
DASM_AFLAGS+= -D IOS
|
||||
endif
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_MIPSR6 ,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D MIPSR6
|
||||
endif
|
||||
ifeq (ppc,$(TARGET_LJARCH))
|
||||
ifneq (,$(findstring LJ_ARCH_SQRT 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D SQRT
|
||||
@@ -443,9 +458,6 @@ ifeq (ppc,$(TARGET_LJARCH))
|
||||
ifeq (PS3,$(TARGET_SYS))
|
||||
DASM_AFLAGS+= -D PPE -D TOC
|
||||
endif
|
||||
ifneq (,$(findstring LJ_ARCH_PPC64 ,$(TARGET_TESTARCH)))
|
||||
DASM_ARCH= ppc64
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -470,10 +482,10 @@ LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \
|
||||
lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o
|
||||
LJLIB_C= $(LJLIB_O:.o=.c)
|
||||
|
||||
LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \
|
||||
LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \
|
||||
lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \
|
||||
lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_strscan.o \
|
||||
lj_strfmt.o lj_api.o lj_profile.o \
|
||||
lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \
|
||||
lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \
|
||||
lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \
|
||||
lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \
|
||||
lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
|
||||
@@ -548,6 +560,7 @@ ifeq (Windows,$(HOST_SYS))
|
||||
MINILUA_X= host\minilua
|
||||
BUILDVM_X= host\buildvm
|
||||
ALL_RM:= $(subst /,\,$(ALL_RM))
|
||||
HOST_RM= del
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -588,7 +601,6 @@ E= @echo
|
||||
default all: $(TARGET_T)
|
||||
|
||||
amalg:
|
||||
@grep "^[+|]" ljamalg.c
|
||||
$(MAKE) all "LJCORE_O=ljamalg.o"
|
||||
|
||||
clean:
|
||||
@@ -622,7 +634,7 @@ $(MINILUA_T): $(MINILUA_O)
|
||||
$(E) "HOSTLINK $@"
|
||||
$(Q)$(HOST_CC) $(HOST_ALDFLAGS) -o $@ $(MINILUA_O) $(MINILUA_LIBS) $(HOST_ALIBS)
|
||||
|
||||
host/buildvm_arch.h: $(DASM_DASC) $(DASM_DEP)
|
||||
host/buildvm_arch.h: $(DASM_DASC) $(DASM_DEP) $(DASM_DIR)/*.lua lj_arch.h lua.h luaconf.h
|
||||
$(E) "DYNASM $@"
|
||||
$(Q)$(DASM) $(DASM_FLAGS) -o $@ $(DASM_DASC)
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
|
||||
lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \
|
||||
lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h lj_alloc.h
|
||||
lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h
|
||||
lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
|
||||
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \
|
||||
lj_tab.h lj_meta.h lj_state.h lj_ctype.h lj_cconv.h lj_bc.h lj_ff.h \
|
||||
lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \
|
||||
lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \
|
||||
lj_ff.h lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \
|
||||
lj_strfmt.h lj_lib.h lj_libdef.h
|
||||
lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
|
||||
lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_strscan.h \
|
||||
@@ -28,7 +28,7 @@ lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
|
||||
lj_target.h lj_target_*.h lj_trace.h lj_dispatch.h lj_traceerr.h \
|
||||
lj_vm.h lj_vmevent.h lj_lib.h luajit.h lj_libdef.h
|
||||
lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
|
||||
lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_libdef.h
|
||||
lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_prng.h lj_libdef.h
|
||||
lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
|
||||
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_lib.h \
|
||||
lj_libdef.h
|
||||
@@ -41,7 +41,8 @@ lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
|
||||
lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
|
||||
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \
|
||||
lj_tab.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h
|
||||
lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h
|
||||
lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h \
|
||||
lj_prng.h
|
||||
lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||
lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \
|
||||
lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \
|
||||
@@ -51,6 +52,7 @@ lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||
lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h lj_traceerr.h \
|
||||
lj_snap.h lj_asm.h lj_vm.h lj_target.h lj_target_*.h lj_emit_*.h \
|
||||
lj_asm_*.h
|
||||
lj_assert.o: lj_assert.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h
|
||||
lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \
|
||||
lj_bcdef.h
|
||||
lj_bcread.o: lj_bcread.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
@@ -94,7 +96,7 @@ lj_crecord.o: lj_crecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_crecord.h lj_strfmt.h
|
||||
lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_strfmt.h lj_ctype.h \
|
||||
lj_ccallback.h
|
||||
lj_ccallback.h lj_buf.h
|
||||
lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \
|
||||
lj_state.h lj_frame.h lj_bc.h lj_strfmt.h lj_jit.h lj_ir.h
|
||||
@@ -125,7 +127,7 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||
lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \
|
||||
lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \
|
||||
lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h
|
||||
lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_prng.h
|
||||
lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||
lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \
|
||||
lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \
|
||||
@@ -139,7 +141,7 @@ lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
|
||||
lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h
|
||||
lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h \
|
||||
lj_dispatch.h lj_bc.h lj_traceerr.h lj_vm.h
|
||||
lj_dispatch.h lj_bc.h lj_traceerr.h lj_prng.h lj_vm.h
|
||||
lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||
lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_meta.h lj_frame.h \
|
||||
lj_bc.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h
|
||||
@@ -155,7 +157,7 @@ lj_opt_loop.o: lj_opt_loop.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_iropt.h lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h \
|
||||
lj_vm.h
|
||||
lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_ircall.h
|
||||
lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_ircall.h lj_dispatch.h lj_bc.h
|
||||
lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \
|
||||
lj_arch.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \
|
||||
lj_traceerr.h lj_vm.h lj_strscan.h
|
||||
@@ -163,7 +165,7 @@ lj_opt_sink.o: lj_opt_sink.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_ir.h lj_jit.h lj_iropt.h lj_target.h lj_target_*.h
|
||||
lj_opt_split.o: lj_opt_split.c lj_obj.h lua.h luaconf.h lj_def.h \
|
||||
lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_ir.h \
|
||||
lj_jit.h lj_ircall.h lj_iropt.h lj_vm.h
|
||||
lj_jit.h lj_ircall.h lj_iropt.h lj_dispatch.h lj_bc.h lj_vm.h
|
||||
lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_str.h lj_tab.h \
|
||||
lj_func.h lj_state.h lj_bc.h lj_ctype.h lj_strfmt.h lj_lex.h lj_parse.h \
|
||||
@@ -171,11 +173,12 @@ lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \
|
||||
lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h
|
||||
lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h
|
||||
lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \
|
||||
lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \
|
||||
lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \
|
||||
lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h
|
||||
lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h
|
||||
lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||
lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \
|
||||
lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \
|
||||
@@ -183,11 +186,14 @@ lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||
lj_state.o: lj_state.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_func.h \
|
||||
lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_trace.h lj_jit.h \
|
||||
lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_alloc.h luajit.h
|
||||
lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \
|
||||
lj_alloc.h luajit.h
|
||||
lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||
lj_err.h lj_errmsg.h lj_str.h lj_char.h
|
||||
lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_buf.h lj_gc.h lj_str.h lj_state.h lj_char.h lj_strfmt.h
|
||||
lj_strfmt_num.o: lj_strfmt_num.c lj_obj.h lua.h luaconf.h lj_def.h \
|
||||
lj_arch.h lj_buf.h lj_gc.h lj_str.h lj_strfmt.h
|
||||
lj_strscan.o: lj_strscan.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_char.h lj_strscan.h
|
||||
lj_tab.o: lj_tab.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||
@@ -196,7 +202,7 @@ lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_frame.h lj_bc.h \
|
||||
lj_state.h lj_ir.h lj_jit.h lj_iropt.h lj_mcode.h lj_trace.h \
|
||||
lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \
|
||||
lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h
|
||||
lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h
|
||||
lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_gc.h lj_udata.h
|
||||
lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
@@ -204,23 +210,24 @@ lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_vm.h lj_vmevent.h
|
||||
lj_vmmath.o: lj_vmmath.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_ir.h lj_vm.h
|
||||
ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \
|
||||
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h \
|
||||
lj_func.h lj_udata.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h \
|
||||
lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h \
|
||||
lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h lj_char.c \
|
||||
lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c lj_tab.c \
|
||||
lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \
|
||||
lj_state.c lj_lex.h lj_alloc.h luajit.h lj_dispatch.c lj_ccallback.h \
|
||||
lj_profile.h lj_vmevent.c lj_vmevent.h lj_vmmath.c lj_strscan.c \
|
||||
lj_strfmt.c lj_api.c lj_profile.c lj_lex.c lualib.h lj_parse.h \
|
||||
lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c \
|
||||
lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c \
|
||||
lj_target.h lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c \
|
||||
lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h \
|
||||
lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c \
|
||||
lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c \
|
||||
lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
|
||||
ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_assert.c lj_obj.h \
|
||||
lj_def.h lj_arch.h lj_gc.c lj_gc.h lj_err.h lj_errmsg.h lj_buf.h \
|
||||
lj_str.h lj_tab.h lj_func.h lj_udata.h lj_meta.h lj_state.h lj_frame.h \
|
||||
lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
|
||||
lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \
|
||||
lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \
|
||||
lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \
|
||||
lj_prng.c lj_prng.h lj_state.c lj_lex.h lj_alloc.h luajit.h \
|
||||
lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \
|
||||
lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_api.c \
|
||||
lj_profile.c lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c \
|
||||
lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h \
|
||||
lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h \
|
||||
lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h \
|
||||
lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h lj_iropt.h \
|
||||
lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \
|
||||
lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \
|
||||
lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
|
||||
lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \
|
||||
lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \
|
||||
lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** LuaJIT VM builder.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 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
|
||||
@@ -110,7 +110,7 @@ static const char *sym_decorate(BuildCtx *ctx,
|
||||
if (p) {
|
||||
#if LJ_TARGET_X86ORX64
|
||||
if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj))
|
||||
name[0] = '@';
|
||||
name[0] = name[1] == 'R' ? '_' : '@'; /* Just for _RtlUnwind@16. */
|
||||
else
|
||||
*p = '\0';
|
||||
#elif LJ_TARGET_PPC && !LJ_TARGET_CONSOLE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** LuaJIT VM builder.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _BUILDVM_H
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** LuaJIT VM builder: Assembler source code emitter.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#include "buildvm.h"
|
||||
@@ -93,10 +93,14 @@ static void emit_asm_words(BuildCtx *ctx, uint8_t *p, int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n; i += 4) {
|
||||
uint32_t ins = *(uint32_t *)(p+i);
|
||||
#if LJ_TARGET_ARM64 && LJ_BE
|
||||
ins = lj_bswap(ins); /* ARM64 instructions are always little-endian. */
|
||||
#endif
|
||||
if ((i & 15) == 0)
|
||||
fprintf(ctx->fp, "\t.long 0x%08x", *(uint32_t *)(p+i));
|
||||
fprintf(ctx->fp, "\t.long 0x%08x", ins);
|
||||
else
|
||||
fprintf(ctx->fp, ",0x%08x", *(uint32_t *)(p+i));
|
||||
fprintf(ctx->fp, ",0x%08x", ins);
|
||||
if ((i & 15) == 12) putc('\n', ctx->fp);
|
||||
}
|
||||
if ((n & 15) != 0) putc('\n', ctx->fp);
|
||||
@@ -140,14 +144,6 @@ static void emit_asm_wordreloc(BuildCtx *ctx, uint8_t *p, int n,
|
||||
fprintf(ctx->fp, "\t%s %d, %d, " TOCPREFIX "%s\n",
|
||||
(ins & 1) ? "bcl" : "bc", (ins >> 21) & 31, (ins >> 16) & 31, sym);
|
||||
} else if ((ins >> 26) == 18) {
|
||||
#if LJ_ARCH_PPC64
|
||||
const char *suffix = strchr(sym, '@');
|
||||
if (suffix && suffix[1] == 'h') {
|
||||
fprintf(ctx->fp, "\taddis 11, 2, %s\n", sym);
|
||||
} else if (suffix && suffix[1] == 'l') {
|
||||
fprintf(ctx->fp, "\tld 12, %s\n", sym);
|
||||
} else
|
||||
#endif
|
||||
fprintf(ctx->fp, "\t%s " TOCPREFIX "%s\n", (ins & 1) ? "bl" : "b", sym);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
@@ -214,7 +210,8 @@ static void emit_asm_label(BuildCtx *ctx, const char *name, int size, int isfunc
|
||||
case BUILD_machasm:
|
||||
fprintf(ctx->fp,
|
||||
"\n\t.private_extern %s\n"
|
||||
"%s:\n", name, name);
|
||||
"\t.no_dead_strip %s\n"
|
||||
"%s:\n", name, name, name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -245,9 +242,6 @@ void emit_asm(BuildCtx *ctx)
|
||||
int i, rel;
|
||||
|
||||
fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch);
|
||||
#if LJ_ARCH_PPC64
|
||||
fprintf(ctx->fp, "\t.abiversion 2\n");
|
||||
#endif
|
||||
fprintf(ctx->fp, "\t.text\n");
|
||||
emit_asm_align(ctx, 4);
|
||||
|
||||
@@ -261,11 +255,20 @@ void emit_asm(BuildCtx *ctx)
|
||||
|
||||
#if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND
|
||||
/* This should really be moved into buildvm_arm.dasc. */
|
||||
#if LJ_ARCH_HASFPU
|
||||
fprintf(ctx->fp,
|
||||
".fnstart\n"
|
||||
".save {r5, r6, r7, r8, r9, r10, r11, lr}\n"
|
||||
".vsave {d8-d15}\n"
|
||||
".save {r4}\n"
|
||||
".pad #28\n");
|
||||
#else
|
||||
fprintf(ctx->fp,
|
||||
".fnstart\n"
|
||||
".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n"
|
||||
".pad #28\n");
|
||||
#endif
|
||||
#endif
|
||||
#if LJ_TARGET_MIPS
|
||||
fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n");
|
||||
#endif
|
||||
@@ -324,7 +327,7 @@ void emit_asm(BuildCtx *ctx)
|
||||
#if !(LJ_TARGET_PS3 || LJ_TARGET_PSVITA)
|
||||
fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n");
|
||||
#endif
|
||||
#if LJ_TARGET_PPC && !LJ_TARGET_PS3
|
||||
#if LJ_TARGET_PPC && !LJ_TARGET_PS3 && !LJ_ABI_SOFTFP
|
||||
/* Hard-float ABI. */
|
||||
fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n");
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** LuaJIT VM builder: IR folding hash table generator.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#include "buildvm.h"
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
/* Context for the folding hash table generator. */
|
||||
static int lineno;
|
||||
static int funcidx;
|
||||
static uint32_t funcidx;
|
||||
static uint32_t foldkeys[BUILD_MAX_FOLD];
|
||||
static uint32_t nkeys;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** LuaJIT VM builder: library definition compiler.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#include "buildvm.h"
|
||||
|
||||
@@ -15,7 +15,12 @@ static const uint8_t libbc_code[] = {
|
||||
8,2,0,0,88,3,23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,16,1,14,
|
||||
0,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2,
|
||||
0,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4,
|
||||
2,0,76,3,2,0,75,0,1,0,0,2,0
|
||||
2,0,76,3,2,0,75,0,1,0,0,2,0,5,12,0,0,0,35,16,0,12,0,16,1,14,0,16,2,14,0,16,
|
||||
3,14,0,11,4,0,0,88,5,1,128,18,4,0,0,16,4,12,0,3,1,2,0,88,5,24,128,33,5,1,3,
|
||||
0,2,3,0,88,6,4,128,2,3,1,0,88,6,2,128,4,4,0,0,88,6,9,128,18,6,1,0,18,7,2,0,
|
||||
41,8,1,0,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,6,252,127,88,6,8,128,
|
||||
18,6,2,0,18,7,1,0,41,8,255,255,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,
|
||||
6,252,127,76,4,2,0,0
|
||||
#else
|
||||
0,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0,
|
||||
0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3,
|
||||
@@ -28,7 +33,12 @@ static const uint8_t libbc_code[] = {
|
||||
8,2,0,0,88,3,23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,16,1,14,
|
||||
0,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2,
|
||||
0,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4,
|
||||
2,0,76,3,2,0,75,0,1,0,0,2,0
|
||||
2,0,76,3,2,0,75,0,1,0,0,2,0,5,12,0,0,0,35,16,0,12,0,16,1,14,0,16,2,14,0,16,
|
||||
3,14,0,11,4,0,0,88,5,1,128,18,4,0,0,16,4,12,0,3,1,2,0,88,5,24,128,33,5,1,3,
|
||||
0,2,3,0,88,6,4,128,2,3,1,0,88,6,2,128,4,4,0,0,88,6,9,128,18,6,1,0,18,7,2,0,
|
||||
41,8,1,0,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,6,252,127,88,6,8,128,
|
||||
18,6,2,0,18,7,1,0,41,8,255,255,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,
|
||||
6,252,127,76,4,2,0,0
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -40,6 +50,7 @@ static const struct { const char *name; int ofs; } libbc_map[] = {
|
||||
{"table_foreach",136},
|
||||
{"table_getn",207},
|
||||
{"table_remove",226},
|
||||
{NULL,355}
|
||||
{"table_move",355},
|
||||
{NULL,502}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** LuaJIT VM builder: PE object emitter.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 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.
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "buildvm.h"
|
||||
#include "lj_bc.h"
|
||||
|
||||
#if LJ_TARGET_X86ORX64 || LJ_TARGET_PPC
|
||||
#if LJ_TARGET_X86ORX64
|
||||
|
||||
/* Context for PE object emitter. */
|
||||
static char *strtab;
|
||||
@@ -93,12 +93,6 @@ typedef struct PEsymaux {
|
||||
#define PEOBJ_RELOC_ADDR32NB 0x03
|
||||
#define PEOBJ_RELOC_OFS 0
|
||||
#define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */
|
||||
#elif LJ_TARGET_PPC
|
||||
#define PEOBJ_ARCH_TARGET 0x01f2
|
||||
#define PEOBJ_RELOC_REL32 0x06
|
||||
#define PEOBJ_RELOC_DIR32 0x02
|
||||
#define PEOBJ_RELOC_OFS (-4)
|
||||
#define PEOBJ_TEXT_FLAGS 0x60400020 /* 60=r+x, 40=align8, 20=code. */
|
||||
#endif
|
||||
|
||||
/* Section numbers (0-based). */
|
||||
@@ -109,6 +103,8 @@ enum {
|
||||
#if LJ_TARGET_X64
|
||||
PEOBJ_SECT_PDATA,
|
||||
PEOBJ_SECT_XDATA,
|
||||
#elif LJ_TARGET_X86
|
||||
PEOBJ_SECT_SXDATA,
|
||||
#endif
|
||||
PEOBJ_SECT_RDATA_Z,
|
||||
PEOBJ_NSECTIONS
|
||||
@@ -208,6 +204,13 @@ void emit_peobj(BuildCtx *ctx)
|
||||
sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE;
|
||||
/* Flags: 40 = read, 30 = align4, 40 = initialized data. */
|
||||
pesect[PEOBJ_SECT_XDATA].flags = 0x40300040;
|
||||
#elif LJ_TARGET_X86
|
||||
memcpy(pesect[PEOBJ_SECT_SXDATA].name, ".sxdata", sizeof(".sxdata")-1);
|
||||
pesect[PEOBJ_SECT_SXDATA].ofs = sofs;
|
||||
sofs += (pesect[PEOBJ_SECT_SXDATA].size = 4);
|
||||
pesect[PEOBJ_SECT_SXDATA].relocofs = sofs;
|
||||
/* Flags: 40 = read, 30 = align4, 02 = lnk_info, 40 = initialized data. */
|
||||
pesect[PEOBJ_SECT_SXDATA].flags = 0x40300240;
|
||||
#endif
|
||||
|
||||
memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1);
|
||||
@@ -232,7 +235,7 @@ void emit_peobj(BuildCtx *ctx)
|
||||
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. */
|
||||
pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win. */
|
||||
#endif
|
||||
|
||||
/* Write PE object header and all sections. */
|
||||
@@ -242,15 +245,8 @@ void emit_peobj(BuildCtx *ctx)
|
||||
/* Write .text section. */
|
||||
host_endian.u = 1;
|
||||
if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) {
|
||||
#if LJ_TARGET_PPC
|
||||
uint32_t *p = (uint32_t *)ctx->code;
|
||||
int n = (int)(ctx->codesz >> 2);
|
||||
for (i = 0; i < n; i++, p++)
|
||||
*p = lj_bswap(*p); /* Byteswap .text section. */
|
||||
#else
|
||||
fprintf(stderr, "Error: different byte order for host and target\n");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
owrite(ctx, ctx->code, ctx->codesz);
|
||||
for (i = 0; i < ctx->nreloc; i++) {
|
||||
@@ -312,6 +308,19 @@ void emit_peobj(BuildCtx *ctx)
|
||||
reloc.type = PEOBJ_RELOC_ADDR32NB;
|
||||
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
|
||||
}
|
||||
#elif LJ_TARGET_X86
|
||||
/* Write .sxdata section. */
|
||||
for (i = 0; i < nrsym; i++) {
|
||||
if (!strcmp(ctx->relocsym[i], "_lj_err_unwind_win")) {
|
||||
uint32_t symidx = 1+2+i;
|
||||
owrite(ctx, &symidx, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == nrsym) {
|
||||
fprintf(stderr, "Error: extern lj_err_unwind_win not used\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write .rdata$Z section. */
|
||||
@@ -333,8 +342,10 @@ void emit_peobj(BuildCtx *ctx)
|
||||
#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,
|
||||
emit_peobj_sym(ctx, "lj_err_unwind_win", 0,
|
||||
PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
|
||||
#elif LJ_TARGET_X86
|
||||
emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_SXDATA);
|
||||
#endif
|
||||
|
||||
emit_peobj_sym(ctx, ctx->beginsym, 0,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- Lua script to dump the bytecode of the library functions written in Lua.
|
||||
-- The resulting 'buildvm_libbc.h' is used for the build process of LuaJIT.
|
||||
----------------------------------------------------------------------------
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- Lua script to generate a customized, minified version of Lua.
|
||||
-- The resulting 'minilua' is used for the build process of LuaJIT.
|
||||
----------------------------------------------------------------------------
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
@@ -157,11 +157,11 @@ local function merge_includes(src)
|
||||
if includes[name] then return "" end
|
||||
includes[name] = true
|
||||
local fp = assert(io.open(LUA_SOURCE..name, "r"))
|
||||
local src = fp:read("*a")
|
||||
local inc = fp:read("*a")
|
||||
assert(fp:close())
|
||||
src = gsub(src, "#ifndef%s+%w+_h\n#define%s+%w+_h\n", "")
|
||||
src = gsub(src, "#endif%s*$", "")
|
||||
return merge_includes(src)
|
||||
inc = gsub(inc, "#ifndef%s+%w+_h\n#define%s+%w+_h\n", "")
|
||||
inc = gsub(inc, "#endif%s*$", "")
|
||||
return merge_includes(inc)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -300,6 +300,7 @@ local function strip_unused3(src)
|
||||
src = gsub(src, "if%([^\n]*hookmask[^\n]*&&\n[^\n]*%b{}\n", "")
|
||||
src = gsub(src, "(twoto%b()%()", "%1(size_t)")
|
||||
src = gsub(src, "i<sizenode", "i<(int)sizenode")
|
||||
src = gsub(src, "cast%(unsigned int,key%-1%)", "cast(unsigned int,key)-1")
|
||||
return gsub(src, "\n\n+", "\n")
|
||||
end
|
||||
|
||||
|
||||
@@ -1606,7 +1606,7 @@ luaC_barriert(L,t,key);
|
||||
return gval(mp);
|
||||
}
|
||||
static const TValue*luaH_getnum(Table*t,int key){
|
||||
if(cast(unsigned int,key-1)<cast(unsigned int,t->sizearray))
|
||||
if(cast(unsigned int,key)-1<cast(unsigned int,t->sizearray))
|
||||
return&t->array[key-1];
|
||||
else{
|
||||
lua_Number nk=cast_num(key);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT bytecode listing module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT module to save/list bytecode.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
@@ -17,6 +17,10 @@ local bit = require("bit")
|
||||
-- Symbol name prefix for LuaJIT bytecode.
|
||||
local LJBC_PREFIX = "luaJIT_BC_"
|
||||
|
||||
local type, assert = type, assert
|
||||
local format = string.format
|
||||
local tremove, tconcat = table.remove, table.concat
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local function usage()
|
||||
@@ -63,8 +67,18 @@ local map_type = {
|
||||
}
|
||||
|
||||
local map_arch = {
|
||||
x86 = true, x64 = true, arm = true, arm64 = true, ppc = true,
|
||||
mips = true, mipsel = true,
|
||||
x86 = { e = "le", b = 32, m = 3, p = 0x14c, },
|
||||
x64 = { e = "le", b = 64, m = 62, p = 0x8664, },
|
||||
arm = { e = "le", b = 32, m = 40, p = 0x1c0, },
|
||||
arm64 = { e = "le", b = 64, m = 183, p = 0xaa64, },
|
||||
arm64be = { e = "be", b = 64, m = 183, },
|
||||
ppc = { e = "be", b = 32, m = 20, },
|
||||
mips = { e = "be", b = 32, m = 8, f = 0x50001006, },
|
||||
mipsel = { e = "le", b = 32, m = 8, f = 0x50001006, },
|
||||
mips64 = { e = "be", b = 64, m = 8, f = 0x80000007, },
|
||||
mips64el = { e = "le", b = 64, m = 8, f = 0x80000007, },
|
||||
mips64r6 = { e = "be", b = 64, m = 8, f = 0xa0000407, },
|
||||
mips64r6el = { e = "le", b = 64, m = 8, f = 0xa0000407, },
|
||||
}
|
||||
|
||||
local map_os = {
|
||||
@@ -73,33 +87,33 @@ local map_os = {
|
||||
}
|
||||
|
||||
local function checkarg(str, map, err)
|
||||
str = string.lower(str)
|
||||
str = str:lower()
|
||||
local s = check(map[str], "unknown ", err)
|
||||
return s == true and str or s
|
||||
return type(s) == "string" and s or str
|
||||
end
|
||||
|
||||
local function detecttype(str)
|
||||
local ext = string.match(string.lower(str), "%.(%a+)$")
|
||||
local ext = str:lower():match("%.(%a+)$")
|
||||
return map_type[ext] or "raw"
|
||||
end
|
||||
|
||||
local function checkmodname(str)
|
||||
check(string.match(str, "^[%w_.%-]+$"), "bad module name")
|
||||
return string.gsub(str, "[%.%-]", "_")
|
||||
check(str:match("^[%w_.%-]+$"), "bad module name")
|
||||
return str:gsub("[%.%-]", "_")
|
||||
end
|
||||
|
||||
local function detectmodname(str)
|
||||
if type(str) == "string" then
|
||||
local tail = string.match(str, "[^/\\]+$")
|
||||
local tail = str:match("[^/\\]+$")
|
||||
if tail then str = tail end
|
||||
local head = string.match(str, "^(.*)%.[^.]*$")
|
||||
local head = str:match("^(.*)%.[^.]*$")
|
||||
if head then str = head end
|
||||
str = string.match(str, "^[%w_.%-]+")
|
||||
str = str:match("^[%w_.%-]+")
|
||||
else
|
||||
str = nil
|
||||
end
|
||||
check(str, "cannot derive module name, use -n name")
|
||||
return string.gsub(str, "[%.%-]", "_")
|
||||
return str:gsub("[%.%-]", "_")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@@ -118,19 +132,19 @@ end
|
||||
local function bcsave_c(ctx, output, s)
|
||||
local fp = savefile(output, "w")
|
||||
if ctx.type == "c" then
|
||||
fp:write(string.format([[
|
||||
#ifdef _cplusplus
|
||||
fp:write(format([[
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
const char %s%s[] = {
|
||||
const unsigned char %s%s[] = {
|
||||
]], LJBC_PREFIX, ctx.modname))
|
||||
else
|
||||
fp:write(string.format([[
|
||||
fp:write(format([[
|
||||
#define %s%s_SIZE %d
|
||||
static const char %s%s[] = {
|
||||
static const unsigned char %s%s[] = {
|
||||
]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname))
|
||||
end
|
||||
local t, n, m = {}, 0, 0
|
||||
@@ -138,13 +152,13 @@ static const char %s%s[] = {
|
||||
local b = tostring(string.byte(s, i))
|
||||
m = m + #b + 1
|
||||
if m > 78 then
|
||||
fp:write(table.concat(t, ",", 1, n), ",\n")
|
||||
fp:write(tconcat(t, ",", 1, n), ",\n")
|
||||
n, m = 0, #b + 1
|
||||
end
|
||||
n = n + 1
|
||||
t[n] = b
|
||||
end
|
||||
bcsave_tail(fp, output, table.concat(t, ",", 1, n).."\n};\n")
|
||||
bcsave_tail(fp, output, tconcat(t, ",", 1, n).."\n};\n")
|
||||
end
|
||||
|
||||
local function bcsave_elfobj(ctx, output, s, ffi)
|
||||
@@ -199,12 +213,8 @@ typedef struct {
|
||||
} ELF64obj;
|
||||
]]
|
||||
local symname = LJBC_PREFIX..ctx.modname
|
||||
local is64, isbe = false, false
|
||||
if ctx.arch == "x64" or ctx.arch == "arm64" then
|
||||
is64 = true
|
||||
elseif ctx.arch == "ppc" or ctx.arch == "mips" then
|
||||
isbe = true
|
||||
end
|
||||
local ai = assert(map_arch[ctx.arch])
|
||||
local is64, isbe = ai.b == 64, ai.e == "be"
|
||||
|
||||
-- Handle different host/target endianess.
|
||||
local function f32(x) return x end
|
||||
@@ -237,10 +247,8 @@ typedef struct {
|
||||
hdr.eendian = isbe and 2 or 1
|
||||
hdr.eversion = 1
|
||||
hdr.type = f16(1)
|
||||
hdr.machine = f16(({ x86=3, x64=62, arm=40, arm64=183, ppc=20, mips=8, mipsel=8 })[ctx.arch])
|
||||
if ctx.arch == "mips" or ctx.arch == "mipsel" then
|
||||
hdr.flags = 0x50001006
|
||||
end
|
||||
hdr.machine = f16(ai.m)
|
||||
hdr.flags = f32(ai.f or 0)
|
||||
hdr.version = f32(1)
|
||||
hdr.shofs = fofs(ffi.offsetof(o, "sect"))
|
||||
hdr.ehsize = f16(ffi.sizeof(hdr))
|
||||
@@ -275,7 +283,7 @@ typedef struct {
|
||||
o.sect[2].size = fofs(ofs)
|
||||
o.sect[3].type = f32(3) -- .strtab
|
||||
o.sect[3].ofs = fofs(sofs + ofs)
|
||||
o.sect[3].size = fofs(#symname+1)
|
||||
o.sect[3].size = fofs(#symname+2)
|
||||
ffi.copy(o.space+ofs+1, symname)
|
||||
ofs = ofs + #symname + 2
|
||||
o.sect[4].type = f32(1) -- .rodata
|
||||
@@ -336,12 +344,8 @@ typedef struct {
|
||||
} PEobj;
|
||||
]]
|
||||
local symname = LJBC_PREFIX..ctx.modname
|
||||
local is64 = false
|
||||
if ctx.arch == "x86" then
|
||||
symname = "_"..symname
|
||||
elseif ctx.arch == "x64" then
|
||||
is64 = true
|
||||
end
|
||||
local ai = assert(map_arch[ctx.arch])
|
||||
local is64 = ai.b == 64
|
||||
local symexport = " /EXPORT:"..symname..",DATA "
|
||||
|
||||
-- The file format is always little-endian. Swap if the host is big-endian.
|
||||
@@ -355,7 +359,7 @@ typedef struct {
|
||||
-- Create PE object and fill in header.
|
||||
local o = ffi.new("PEobj")
|
||||
local hdr = o.hdr
|
||||
hdr.arch = f16(({ x86=0x14c, x64=0x8664, arm=0x1c0, ppc=0x1f2, mips=0x366, mipsel=0x366 })[ctx.arch])
|
||||
hdr.arch = f16(assert(ai.p))
|
||||
hdr.nsects = f16(2)
|
||||
hdr.symtabofs = f32(ffi.offsetof(o, "sym0"))
|
||||
hdr.nsyms = f32(6)
|
||||
@@ -605,16 +609,16 @@ local function docmd(...)
|
||||
local n = 1
|
||||
local list = false
|
||||
local ctx = {
|
||||
strip = true, arch = jit.arch, os = string.lower(jit.os),
|
||||
strip = true, arch = jit.arch, os = jit.os:lower(),
|
||||
type = false, modname = false,
|
||||
}
|
||||
while n <= #arg do
|
||||
local a = arg[n]
|
||||
if type(a) == "string" and string.sub(a, 1, 1) == "-" and a ~= "-" then
|
||||
table.remove(arg, n)
|
||||
if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then
|
||||
tremove(arg, n)
|
||||
if a == "--" then break end
|
||||
for m=2,#a do
|
||||
local opt = string.sub(a, m, m)
|
||||
local opt = a:sub(m, m)
|
||||
if opt == "l" then
|
||||
list = true
|
||||
elseif opt == "s" then
|
||||
@@ -627,13 +631,13 @@ local function docmd(...)
|
||||
if n ~= 1 then usage() end
|
||||
arg[1] = check(loadstring(arg[1]))
|
||||
elseif opt == "n" then
|
||||
ctx.modname = checkmodname(table.remove(arg, n))
|
||||
ctx.modname = checkmodname(tremove(arg, n))
|
||||
elseif opt == "t" then
|
||||
ctx.type = checkarg(table.remove(arg, n), map_type, "file type")
|
||||
ctx.type = checkarg(tremove(arg, n), map_type, "file type")
|
||||
elseif opt == "a" then
|
||||
ctx.arch = checkarg(table.remove(arg, n), map_arch, "architecture")
|
||||
ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture")
|
||||
elseif opt == "o" then
|
||||
ctx.os = checkarg(table.remove(arg, n), map_os, "OS name")
|
||||
ctx.os = checkarg(tremove(arg, n), map_os, "OS name")
|
||||
else
|
||||
usage()
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT ARM disassembler module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
local type = type
|
||||
local sub, byte, format = string.sub, string.byte, string.format
|
||||
local match, gmatch, gsub = string.match, string.gmatch, string.gsub
|
||||
local match, gmatch = string.match, string.gmatch
|
||||
local concat = table.concat
|
||||
local bit = require("bit")
|
||||
local band, bor, ror, tohex = bit.band, bit.bor, bit.ror, bit.tohex
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT ARM64BE disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- ARM64 instructions are always little-endian. So just forward to the
|
||||
-- common ARM64 disassembler module. All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
return require((string.match(..., ".*%.") or "").."dis_arm64")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT MIPS disassembler module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT/X license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||
@@ -11,20 +11,41 @@
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local type = type
|
||||
local sub, byte, format = string.sub, string.byte, string.format
|
||||
local match, gmatch, gsub = string.match, string.gmatch, string.gsub
|
||||
local byte, format = string.byte, string.format
|
||||
local match, gmatch = string.match, string.gmatch
|
||||
local concat = table.concat
|
||||
local bit = require("bit")
|
||||
local band, bor, tohex = bit.band, bit.bor, bit.tohex
|
||||
local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Primary and extended opcode maps
|
||||
-- Extended opcode maps common to all MIPS releases
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", }
|
||||
local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", }
|
||||
|
||||
local map_cop0 = {
|
||||
shift = 25, mask = 1,
|
||||
[0] = {
|
||||
shift = 21, mask = 15,
|
||||
[0] = "mfc0TDW", [4] = "mtc0TDW",
|
||||
[10] = "rdpgprDT",
|
||||
[11] = { shift = 5, mask = 1, [0] = "diT0", "eiT0", },
|
||||
[14] = "wrpgprDT",
|
||||
}, {
|
||||
shift = 0, mask = 63,
|
||||
[1] = "tlbr", [2] = "tlbwi", [6] = "tlbwr", [8] = "tlbp",
|
||||
[24] = "eret", [31] = "deret",
|
||||
[32] = "wait",
|
||||
},
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Primary and extended opcode maps for MIPS R1-R5
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local map_movci = { shift = 16, mask = 1, [0] = "movfDSC", "movtDSC", }
|
||||
local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", }
|
||||
local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", }
|
||||
|
||||
local map_special = {
|
||||
shift = 0, mask = 63,
|
||||
@@ -34,15 +55,17 @@ local map_special = {
|
||||
"jrS", "jalrD1S", "movzDST", "movnDST",
|
||||
"syscallY", "breakY", false, "sync",
|
||||
"mfhiD", "mthiS", "mfloD", "mtloS",
|
||||
false, false, false, false,
|
||||
"dsllvDST", false, "dsrlvDST", "dsravDST",
|
||||
"multST", "multuST", "divST", "divuST",
|
||||
false, false, false, false,
|
||||
"dmultST", "dmultuST", "ddivST", "ddivuST",
|
||||
"addDST", "addu|moveDST0", "subDST", "subu|neguDS0T",
|
||||
"andDST", "orDST", "xorDST", "nor|notDST0",
|
||||
"andDST", "or|moveDST0", "xorDST", "nor|notDST0",
|
||||
false, false, "sltDST", "sltuDST",
|
||||
false, false, false, false,
|
||||
"daddDST", "dadduDST", "dsubDST", "dsubuDST",
|
||||
"tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ",
|
||||
"teqSTZ", false, "tneSTZ",
|
||||
"teqSTZ", false, "tneSTZ", false,
|
||||
"dsllDTA", false, "dsrlDTA", "dsraDTA",
|
||||
"dsll32DTA", false, "dsrl32DTA", "dsra32DTA",
|
||||
}
|
||||
|
||||
local map_special2 = {
|
||||
@@ -60,11 +83,17 @@ local map_bshfl = {
|
||||
[24] = "sehDT",
|
||||
}
|
||||
|
||||
local map_dbshfl = {
|
||||
shift = 6, mask = 31,
|
||||
[2] = "dsbhDT",
|
||||
[5] = "dshdDT",
|
||||
}
|
||||
|
||||
local map_special3 = {
|
||||
shift = 0, mask = 63,
|
||||
[0] = "extTSAK", [4] = "insTSAL",
|
||||
[32] = map_bshfl,
|
||||
[59] = "rdhwrTD",
|
||||
[0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK",
|
||||
[4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL",
|
||||
[32] = map_bshfl, [36] = map_dbshfl, [59] = "rdhwrTD",
|
||||
}
|
||||
|
||||
local map_regimm = {
|
||||
@@ -79,22 +108,6 @@ local map_regimm = {
|
||||
false, false, false, "synciSO",
|
||||
}
|
||||
|
||||
local map_cop0 = {
|
||||
shift = 25, mask = 1,
|
||||
[0] = {
|
||||
shift = 21, mask = 15,
|
||||
[0] = "mfc0TDW", [4] = "mtc0TDW",
|
||||
[10] = "rdpgprDT",
|
||||
[11] = { shift = 5, mask = 1, [0] = "diT0", "eiT0", },
|
||||
[14] = "wrpgprDT",
|
||||
}, {
|
||||
shift = 0, mask = 63,
|
||||
[1] = "tlbr", [2] = "tlbwi", [6] = "tlbwr", [8] = "tlbp",
|
||||
[24] = "eret", [31] = "deret",
|
||||
[32] = "wait",
|
||||
},
|
||||
}
|
||||
|
||||
local map_cop1s = {
|
||||
shift = 0, mask = 63,
|
||||
[0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH",
|
||||
@@ -178,8 +191,8 @@ local map_cop1bc = {
|
||||
|
||||
local map_cop1 = {
|
||||
shift = 21, mask = 31,
|
||||
[0] = "mfc1TG", false, "cfc1TG", "mfhc1TG",
|
||||
"mtc1TG", false, "ctc1TG", "mthc1TG",
|
||||
[0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG",
|
||||
"mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG",
|
||||
map_cop1bc, false, false, false,
|
||||
false, false, false, false,
|
||||
map_cop1s, map_cop1d, false, false,
|
||||
@@ -213,16 +226,218 @@ local map_pri = {
|
||||
"andiTSU", "ori|liTS0U", "xoriTSU", "luiTU",
|
||||
map_cop0, map_cop1, false, map_cop1x,
|
||||
"beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB",
|
||||
false, false, false, false,
|
||||
map_special2, false, false, map_special3,
|
||||
"daddiTSI", "daddiuTSI", false, false,
|
||||
map_special2, "jalxJ", false, map_special3,
|
||||
"lbTSO", "lhTSO", "lwlTSO", "lwTSO",
|
||||
"lbuTSO", "lhuTSO", "lwrTSO", false,
|
||||
"sbTSO", "shTSO", "swlTSO", "swTSO",
|
||||
false, false, "swrTSO", "cacheNSO",
|
||||
"llTSO", "lwc1HSO", "lwc2TSO", "prefNSO",
|
||||
false, "ldc1HSO", "ldc2TSO", false,
|
||||
false, "ldc1HSO", "ldc2TSO", "ldTSO",
|
||||
"scTSO", "swc1HSO", "swc2TSO", false,
|
||||
false, "sdc1HSO", "sdc2TSO", false,
|
||||
false, "sdc1HSO", "sdc2TSO", "sdTSO",
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Primary and extended opcode maps for MIPS R6
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local map_mul_r6 = { shift = 6, mask = 3, [2] = "mulDST", [3] = "muhDST" }
|
||||
local map_mulu_r6 = { shift = 6, mask = 3, [2] = "muluDST", [3] = "muhuDST" }
|
||||
local map_div_r6 = { shift = 6, mask = 3, [2] = "divDST", [3] = "modDST" }
|
||||
local map_divu_r6 = { shift = 6, mask = 3, [2] = "divuDST", [3] = "moduDST" }
|
||||
local map_dmul_r6 = { shift = 6, mask = 3, [2] = "dmulDST", [3] = "dmuhDST" }
|
||||
local map_dmulu_r6 = { shift = 6, mask = 3, [2] = "dmuluDST", [3] = "dmuhuDST" }
|
||||
local map_ddiv_r6 = { shift = 6, mask = 3, [2] = "ddivDST", [3] = "dmodDST" }
|
||||
local map_ddivu_r6 = { shift = 6, mask = 3, [2] = "ddivuDST", [3] = "dmoduDST" }
|
||||
|
||||
local map_special_r6 = {
|
||||
shift = 0, mask = 63,
|
||||
[0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" },
|
||||
false, map_srl, "sraDTA",
|
||||
"sllvDTS", false, map_srlv, "sravDTS",
|
||||
"jrS", "jalrD1S", false, false,
|
||||
"syscallY", "breakY", false, "sync",
|
||||
"clzDS", "cloDS", "dclzDS", "dcloDS",
|
||||
"dsllvDST", "dlsaDSTA", "dsrlvDST", "dsravDST",
|
||||
map_mul_r6, map_mulu_r6, map_div_r6, map_divu_r6,
|
||||
map_dmul_r6, map_dmulu_r6, map_ddiv_r6, map_ddivu_r6,
|
||||
"addDST", "addu|moveDST0", "subDST", "subu|neguDS0T",
|
||||
"andDST", "or|moveDST0", "xorDST", "nor|notDST0",
|
||||
false, false, "sltDST", "sltuDST",
|
||||
"daddDST", "dadduDST", "dsubDST", "dsubuDST",
|
||||
"tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ",
|
||||
"teqSTZ", "seleqzDST", "tneSTZ", "selnezDST",
|
||||
"dsllDTA", false, "dsrlDTA", "dsraDTA",
|
||||
"dsll32DTA", false, "dsrl32DTA", "dsra32DTA",
|
||||
}
|
||||
|
||||
local map_bshfl_r6 = {
|
||||
shift = 9, mask = 3,
|
||||
[1] = "alignDSTa",
|
||||
_ = {
|
||||
shift = 6, mask = 31,
|
||||
[0] = "bitswapDT",
|
||||
[2] = "wsbhDT",
|
||||
[16] = "sebDT",
|
||||
[24] = "sehDT",
|
||||
}
|
||||
}
|
||||
|
||||
local map_dbshfl_r6 = {
|
||||
shift = 9, mask = 3,
|
||||
[1] = "dalignDSTa",
|
||||
_ = {
|
||||
shift = 6, mask = 31,
|
||||
[0] = "dbitswapDT",
|
||||
[2] = "dsbhDT",
|
||||
[5] = "dshdDT",
|
||||
}
|
||||
}
|
||||
|
||||
local map_special3_r6 = {
|
||||
shift = 0, mask = 63,
|
||||
[0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK",
|
||||
[4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL",
|
||||
[32] = map_bshfl_r6, [36] = map_dbshfl_r6, [59] = "rdhwrTD",
|
||||
}
|
||||
|
||||
local map_regimm_r6 = {
|
||||
shift = 16, mask = 31,
|
||||
[0] = "bltzSB", [1] = "bgezSB",
|
||||
[6] = "dahiSI", [30] = "datiSI",
|
||||
[23] = "sigrieI", [31] = "synciSO",
|
||||
}
|
||||
|
||||
local map_pcrel_r6 = {
|
||||
shift = 19, mask = 3,
|
||||
[0] = "addiupcS2", "lwpcS2", "lwupcS2", {
|
||||
shift = 18, mask = 1,
|
||||
[0] = "ldpcS3", { shift = 16, mask = 3, [2] = "auipcSI", [3] = "aluipcSI" }
|
||||
}
|
||||
}
|
||||
|
||||
local map_cop1s_r6 = {
|
||||
shift = 0, mask = 63,
|
||||
[0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH",
|
||||
"sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG",
|
||||
"round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG",
|
||||
"round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG",
|
||||
"sel.sFGH", false, false, false,
|
||||
"seleqz.sFGH", "recip.sFG", "rsqrt.sFG", "selnez.sFGH",
|
||||
"maddf.sFGH", "msubf.sFGH", "rint.sFG", "class.sFG",
|
||||
"min.sFGH", "mina.sFGH", "max.sFGH", "maxa.sFGH",
|
||||
false, "cvt.d.sFG", false, false,
|
||||
"cvt.w.sFG", "cvt.l.sFG",
|
||||
}
|
||||
|
||||
local map_cop1d_r6 = {
|
||||
shift = 0, mask = 63,
|
||||
[0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH",
|
||||
"sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG",
|
||||
"round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG",
|
||||
"round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG",
|
||||
"sel.dFGH", false, false, false,
|
||||
"seleqz.dFGH", "recip.dFG", "rsqrt.dFG", "selnez.dFGH",
|
||||
"maddf.dFGH", "msubf.dFGH", "rint.dFG", "class.dFG",
|
||||
"min.dFGH", "mina.dFGH", "max.dFGH", "maxa.dFGH",
|
||||
"cvt.s.dFG", false, false, false,
|
||||
"cvt.w.dFG", "cvt.l.dFG",
|
||||
}
|
||||
|
||||
local map_cop1w_r6 = {
|
||||
shift = 0, mask = 63,
|
||||
[0] = "cmp.af.sFGH", "cmp.un.sFGH", "cmp.eq.sFGH", "cmp.ueq.sFGH",
|
||||
"cmp.lt.sFGH", "cmp.ult.sFGH", "cmp.le.sFGH", "cmp.ule.sFGH",
|
||||
"cmp.saf.sFGH", "cmp.sun.sFGH", "cmp.seq.sFGH", "cmp.sueq.sFGH",
|
||||
"cmp.slt.sFGH", "cmp.sult.sFGH", "cmp.sle.sFGH", "cmp.sule.sFGH",
|
||||
false, "cmp.or.sFGH", "cmp.une.sFGH", "cmp.ne.sFGH",
|
||||
false, false, false, false,
|
||||
false, "cmp.sor.sFGH", "cmp.sune.sFGH", "cmp.sne.sFGH",
|
||||
false, false, false, false,
|
||||
"cvt.s.wFG", "cvt.d.wFG",
|
||||
}
|
||||
|
||||
local map_cop1l_r6 = {
|
||||
shift = 0, mask = 63,
|
||||
[0] = "cmp.af.dFGH", "cmp.un.dFGH", "cmp.eq.dFGH", "cmp.ueq.dFGH",
|
||||
"cmp.lt.dFGH", "cmp.ult.dFGH", "cmp.le.dFGH", "cmp.ule.dFGH",
|
||||
"cmp.saf.dFGH", "cmp.sun.dFGH", "cmp.seq.dFGH", "cmp.sueq.dFGH",
|
||||
"cmp.slt.dFGH", "cmp.sult.dFGH", "cmp.sle.dFGH", "cmp.sule.dFGH",
|
||||
false, "cmp.or.dFGH", "cmp.une.dFGH", "cmp.ne.dFGH",
|
||||
false, false, false, false,
|
||||
false, "cmp.sor.dFGH", "cmp.sune.dFGH", "cmp.sne.dFGH",
|
||||
false, false, false, false,
|
||||
"cvt.s.lFG", "cvt.d.lFG",
|
||||
}
|
||||
|
||||
local map_cop1_r6 = {
|
||||
shift = 21, mask = 31,
|
||||
[0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG",
|
||||
"mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG",
|
||||
false, "bc1eqzHB", false, false,
|
||||
false, "bc1nezHB", false, false,
|
||||
map_cop1s_r6, map_cop1d_r6, false, false,
|
||||
map_cop1w_r6, map_cop1l_r6,
|
||||
}
|
||||
|
||||
local function maprs_popTS(rs, rt)
|
||||
if rt == 0 then return 0 elseif rs == 0 then return 1
|
||||
elseif rs == rt then return 2 else return 3 end
|
||||
end
|
||||
|
||||
local map_pop06_r6 = {
|
||||
maprs = maprs_popTS, [0] = "blezSB", "blezalcTB", "bgezalcTB", "bgeucSTB"
|
||||
}
|
||||
local map_pop07_r6 = {
|
||||
maprs = maprs_popTS, [0] = "bgtzSB", "bgtzalcTB", "bltzalcTB", "bltucSTB"
|
||||
}
|
||||
local map_pop26_r6 = {
|
||||
maprs = maprs_popTS, "blezcTB", "bgezcTB", "bgecSTB"
|
||||
}
|
||||
local map_pop27_r6 = {
|
||||
maprs = maprs_popTS, "bgtzcTB", "bltzcTB", "bltcSTB"
|
||||
}
|
||||
|
||||
local function maprs_popS(rs, rt)
|
||||
if rs == 0 then return 0 else return 1 end
|
||||
end
|
||||
|
||||
local map_pop66_r6 = {
|
||||
maprs = maprs_popS, [0] = "jicTI", "beqzcSb"
|
||||
}
|
||||
local map_pop76_r6 = {
|
||||
maprs = maprs_popS, [0] = "jialcTI", "bnezcSb"
|
||||
}
|
||||
|
||||
local function maprs_popST(rs, rt)
|
||||
if rs >= rt then return 0 elseif rs == 0 then return 1 else return 2 end
|
||||
end
|
||||
|
||||
local map_pop10_r6 = {
|
||||
maprs = maprs_popST, [0] = "bovcSTB", "beqzalcTB", "beqcSTB"
|
||||
}
|
||||
local map_pop30_r6 = {
|
||||
maprs = maprs_popST, [0] = "bnvcSTB", "bnezalcTB", "bnecSTB"
|
||||
}
|
||||
|
||||
local map_pri_r6 = {
|
||||
[0] = map_special_r6, map_regimm_r6, "jJ", "jalJ",
|
||||
"beq|beqz|bST00B", "bne|bnezST0B", map_pop06_r6, map_pop07_r6,
|
||||
map_pop10_r6, "addiu|liTS0I", "sltiTSI", "sltiuTSI",
|
||||
"andiTSU", "ori|liTS0U", "xoriTSU", "aui|luiTS0U",
|
||||
map_cop0, map_cop1_r6, false, false,
|
||||
false, false, map_pop26_r6, map_pop27_r6,
|
||||
map_pop30_r6, "daddiuTSI", false, false,
|
||||
false, "dauiTSI", false, map_special3_r6,
|
||||
"lbTSO", "lhTSO", false, "lwTSO",
|
||||
"lbuTSO", "lhuTSO", false, false,
|
||||
"sbTSO", "shTSO", false, "swTSO",
|
||||
false, false, false, false,
|
||||
false, "lwc1HSO", "bc#", false,
|
||||
false, "ldc1HSO", map_pop66_r6, "ldTSO",
|
||||
false, "swc1HSO", "balc#", map_pcrel_r6,
|
||||
false, "sdc1HSO", map_pop76_r6, "sdTSO",
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@@ -279,10 +494,14 @@ local function disass_ins(ctx)
|
||||
ctx.op = op
|
||||
ctx.rel = nil
|
||||
|
||||
local opat = map_pri[rshift(op, 26)]
|
||||
local opat = ctx.map_pri[rshift(op, 26)]
|
||||
while type(opat) ~= "string" do
|
||||
if not opat then return unknown(ctx) end
|
||||
opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._
|
||||
if opat.maprs then
|
||||
opat = opat[opat.maprs(band(rshift(op,21),31), band(rshift(op,16),31))]
|
||||
else
|
||||
opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._
|
||||
end
|
||||
end
|
||||
local name, pat = match(opat, "^([a-z0-9_.]*)(.*)")
|
||||
local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)")
|
||||
@@ -306,6 +525,10 @@ local function disass_ins(ctx)
|
||||
x = "f"..band(rshift(op, 21), 31)
|
||||
elseif p == "A" then
|
||||
x = band(rshift(op, 6), 31)
|
||||
elseif p == "a" then
|
||||
x = band(rshift(op, 6), 7)
|
||||
elseif p == "E" then
|
||||
x = band(rshift(op, 6), 31) + 32
|
||||
elseif p == "M" then
|
||||
x = band(rshift(op, 11), 31)
|
||||
elseif p == "N" then
|
||||
@@ -315,10 +538,18 @@ local function disass_ins(ctx)
|
||||
if x == 0 then x = nil end
|
||||
elseif p == "K" then
|
||||
x = band(rshift(op, 11), 31) + 1
|
||||
elseif p == "P" then
|
||||
x = band(rshift(op, 11), 31) + 33
|
||||
elseif p == "L" then
|
||||
x = band(rshift(op, 11), 31) - last + 1
|
||||
elseif p == "Q" then
|
||||
x = band(rshift(op, 11), 31) - last + 33
|
||||
elseif p == "I" then
|
||||
x = arshift(lshift(op, 16), 16)
|
||||
elseif p == "2" then
|
||||
x = arshift(lshift(op, 13), 11)
|
||||
elseif p == "3" then
|
||||
x = arshift(lshift(op, 14), 11)
|
||||
elseif p == "U" then
|
||||
x = band(op, 0xffff)
|
||||
elseif p == "O" then
|
||||
@@ -328,13 +559,22 @@ local function disass_ins(ctx)
|
||||
local index = map_gpr[band(rshift(op, 16), 31)]
|
||||
operands[#operands] = format("%s(%s)", index, last)
|
||||
elseif p == "B" then
|
||||
x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 16)*4 + 4
|
||||
x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 14) + 4
|
||||
ctx.rel = x
|
||||
x = "0x"..tohex(x)
|
||||
x = format("0x%08x", x)
|
||||
elseif p == "b" then
|
||||
x = ctx.addr + ctx.pos + arshift(lshift(op, 11), 9) + 4
|
||||
ctx.rel = x
|
||||
x = format("0x%08x", x)
|
||||
elseif p == "#" then
|
||||
x = ctx.addr + ctx.pos + arshift(lshift(op, 6), 4) + 4
|
||||
ctx.rel = x
|
||||
x = format("0x%08x", x)
|
||||
elseif p == "J" then
|
||||
x = band(ctx.addr + ctx.pos, 0xf0000000) + band(op, 0x03ffffff)*4
|
||||
local a = ctx.addr + ctx.pos
|
||||
x = a - band(a, 0x0fffffff) + band(op, 0x03ffffff)*4
|
||||
ctx.rel = x
|
||||
x = "0x"..tohex(x)
|
||||
x = format("0x%08x", x)
|
||||
elseif p == "V" then
|
||||
x = band(rshift(op, 8), 7)
|
||||
if x == 0 then x = nil end
|
||||
@@ -393,6 +633,7 @@ local function create(code, addr, out)
|
||||
ctx.disass = disass_block
|
||||
ctx.hexdump = 8
|
||||
ctx.get = get_be
|
||||
ctx.map_pri = map_pri
|
||||
return ctx
|
||||
end
|
||||
|
||||
@@ -402,6 +643,19 @@ local function create_el(code, addr, out)
|
||||
return ctx
|
||||
end
|
||||
|
||||
local function create_r6(code, addr, out)
|
||||
local ctx = create(code, addr, out)
|
||||
ctx.map_pri = map_pri_r6
|
||||
return ctx
|
||||
end
|
||||
|
||||
local function create_r6_el(code, addr, out)
|
||||
local ctx = create(code, addr, out)
|
||||
ctx.get = get_le
|
||||
ctx.map_pri = map_pri_r6
|
||||
return ctx
|
||||
end
|
||||
|
||||
-- Simple API: disassemble code (a string) at address and output via out.
|
||||
local function disass(code, addr, out)
|
||||
create(code, addr, out):disass()
|
||||
@@ -411,6 +665,14 @@ local function disass_el(code, addr, out)
|
||||
create_el(code, addr, out):disass()
|
||||
end
|
||||
|
||||
local function disass_r6(code, addr, out)
|
||||
create_r6(code, addr, out):disass()
|
||||
end
|
||||
|
||||
local function disass_r6_el(code, addr, out)
|
||||
create_r6_el(code, addr, out):disass()
|
||||
end
|
||||
|
||||
-- Return register name for RID.
|
||||
local function regname(r)
|
||||
if r < 32 then return map_gpr[r] end
|
||||
@@ -421,8 +683,12 @@ end
|
||||
return {
|
||||
create = create,
|
||||
create_el = create_el,
|
||||
create_r6 = create_r6,
|
||||
create_r6_el = create_r6_el,
|
||||
disass = disass,
|
||||
disass_el = disass_el,
|
||||
disass_r6 = disass_r6,
|
||||
disass_r6_el = disass_r6_el,
|
||||
regname = regname
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT MIPS64 disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This module just exports the big-endian functions from the
|
||||
-- MIPS disassembler module. All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
|
||||
return {
|
||||
create = dis_mips.create,
|
||||
disass = dis_mips.disass,
|
||||
regname = dis_mips.regname
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT MIPS64EL disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This module just exports the little-endian functions from the
|
||||
-- MIPS disassembler module. All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
|
||||
return {
|
||||
create = dis_mips.create_el,
|
||||
disass = dis_mips.disass_el,
|
||||
regname = dis_mips.regname
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT MIPS64R6 disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This module just exports the r6 big-endian functions from the
|
||||
-- MIPS disassembler module. All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
|
||||
return {
|
||||
create = dis_mips.create_r6,
|
||||
disass = dis_mips.disass_r6,
|
||||
regname = dis_mips.regname
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT MIPS64R6EL disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This module just exports the r6 little-endian functions from the
|
||||
-- MIPS disassembler module. All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
|
||||
return {
|
||||
create = dis_mips.create_r6_el,
|
||||
disass = dis_mips.disass_r6_el,
|
||||
regname = dis_mips.regname
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT MIPSEL disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This module just exports the little-endian functions from the
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT PPC disassembler module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT/X license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||
@@ -13,7 +13,7 @@
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local type = type
|
||||
local sub, byte, format = string.sub, string.byte, string.format
|
||||
local byte, format = string.byte, string.format
|
||||
local match, gmatch, gsub = string.match, string.gmatch, string.gsub
|
||||
local concat = table.concat
|
||||
local bit = require("bit")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT x64 disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This module just exports the 64 bit functions from the combined
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT x86/x64 disassembler module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||
@@ -158,8 +158,8 @@ local map_opc2 = {
|
||||
"||punpcklqdqXrvm","||punpckhqdqXrvm",
|
||||
"movPrVSm","movqMrm|movdquXrm|movdqaXrm",
|
||||
--7x
|
||||
"pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pmu",
|
||||
"pshiftd!Pmu","pshiftq!Mmu||pshiftdq!Xmu",
|
||||
"pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pvmu",
|
||||
"pshiftd!Pvmu","pshiftq!Mvmu||pshiftdq!Xvmu",
|
||||
"pcmpeqbPrvm","pcmpeqwPrvm","pcmpeqdPrvm","emms*|",
|
||||
"vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$",
|
||||
nil,nil,
|
||||
@@ -239,8 +239,30 @@ nil,"||psrlvVSXrvm","||psravdXrvm","||psllvVSXrvm",
|
||||
--8x
|
||||
[0x8c] = "||pmaskmovXrvVSm",
|
||||
[0x8e] = "||pmaskmovVSmXvr",
|
||||
--9x
|
||||
[0x96] = "||fmaddsub132pHXrvm",[0x97] = "||fmsubadd132pHXrvm",
|
||||
[0x98] = "||fmadd132pHXrvm",[0x99] = "||fmadd132sHXrvm",
|
||||
[0x9a] = "||fmsub132pHXrvm",[0x9b] = "||fmsub132sHXrvm",
|
||||
[0x9c] = "||fnmadd132pHXrvm",[0x9d] = "||fnmadd132sHXrvm",
|
||||
[0x9e] = "||fnmsub132pHXrvm",[0x9f] = "||fnmsub132sHXrvm",
|
||||
--Ax
|
||||
[0xa6] = "||fmaddsub213pHXrvm",[0xa7] = "||fmsubadd213pHXrvm",
|
||||
[0xa8] = "||fmadd213pHXrvm",[0xa9] = "||fmadd213sHXrvm",
|
||||
[0xaa] = "||fmsub213pHXrvm",[0xab] = "||fmsub213sHXrvm",
|
||||
[0xac] = "||fnmadd213pHXrvm",[0xad] = "||fnmadd213sHXrvm",
|
||||
[0xae] = "||fnmsub213pHXrvm",[0xaf] = "||fnmsub213sHXrvm",
|
||||
--Bx
|
||||
[0xb6] = "||fmaddsub231pHXrvm",[0xb7] = "||fmsubadd231pHXrvm",
|
||||
[0xb8] = "||fmadd231pHXrvm",[0xb9] = "||fmadd231sHXrvm",
|
||||
[0xba] = "||fmsub231pHXrvm",[0xbb] = "||fmsub231sHXrvm",
|
||||
[0xbc] = "||fnmadd231pHXrvm",[0xbd] = "||fnmadd231sHXrvm",
|
||||
[0xbe] = "||fnmsub231pHXrvm",[0xbf] = "||fnmsub231sHXrvm",
|
||||
--Dx
|
||||
[0xdc] = "||aesencXrvm", [0xdd] = "||aesenclastXrvm",
|
||||
[0xde] = "||aesdecXrvm", [0xdf] = "||aesdeclastXrvm",
|
||||
--Fx
|
||||
[0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt",
|
||||
[0xf7] = "| sarxVrmv| shlxVrmv| shrxVrmv",
|
||||
},
|
||||
|
||||
["3a"] = { -- [66] 0f 3a xx
|
||||
@@ -262,12 +284,16 @@ nil,nil,nil,nil,
|
||||
[0x40] = "||dppsXrvmu",
|
||||
[0x41] = "||dppdXrvmu",
|
||||
[0x42] = "||mpsadbwXrvmu",
|
||||
[0x44] = "||pclmulqdqXrvmu",
|
||||
[0x46] = "||perm2i128Xrvmu",
|
||||
[0x4a] = "||blendvpsXrvmb",[0x4b] = "||blendvpdXrvmb",
|
||||
[0x4c] = "||pblendvbXrvmb",
|
||||
--6x
|
||||
[0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu",
|
||||
[0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu",
|
||||
[0xdf] = "||aeskeygenassistXrmu",
|
||||
--Fx
|
||||
[0xf0] = "||| rorxVrmu",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -409,8 +435,8 @@ local function putop(ctx, text, operands)
|
||||
(ctx.rexx and "x" or "")..(ctx.rexb and "b" or "")..
|
||||
(ctx.vexl and "l" or "")
|
||||
if ctx.vexv and ctx.vexv ~= 0 then t = t.."v"..ctx.vexv end
|
||||
if t ~= "" then text = ctx.rex.."."..t.." "..text
|
||||
elseif ctx.rex == "vex" then text = "v"..text end
|
||||
if t ~= "" then text = ctx.rex.."."..t.." "..gsub(text, "^ ", "")
|
||||
elseif ctx.rex == "vex" then text = gsub("v"..text, "^v ", "") end
|
||||
ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false
|
||||
ctx.rex = false; ctx.vexl = false; ctx.vexv = false
|
||||
end
|
||||
@@ -475,7 +501,7 @@ local function putpat(ctx, name, pat)
|
||||
local operands, regs, sz, mode, sp, rm, sc, rx, sdisp
|
||||
local code, pos, stop, vexl = ctx.code, ctx.pos, ctx.stop, ctx.vexl
|
||||
|
||||
-- Chars used: 1DFGIMPQRSTUVWXYabcdfgijlmoprstuvwxyz
|
||||
-- Chars used: 1DFGHIMPQRSTUVWXYabcdfgijlmoprstuvwxyz
|
||||
for p in gmatch(pat, ".") do
|
||||
local x = nil
|
||||
if p == "V" or p == "U" then
|
||||
@@ -498,6 +524,9 @@ local function putpat(ctx, name, pat)
|
||||
sz = ctx.o16 and "X" or "M"; ctx.o16 = false
|
||||
if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end
|
||||
regs = map_regs[sz]
|
||||
elseif p == "H" then
|
||||
name = name..(ctx.rexw and "d" or "s")
|
||||
ctx.rexw = false
|
||||
elseif p == "S" then
|
||||
name = name..lower(sz)
|
||||
elseif p == "s" then
|
||||
@@ -727,6 +756,7 @@ map_act = {
|
||||
V = putpat, U = putpat, T = putpat,
|
||||
M = putpat, X = putpat, P = putpat,
|
||||
F = putpat, G = putpat, Y = putpat,
|
||||
H = putpat,
|
||||
|
||||
-- Collect prefixes.
|
||||
[":"] = function(ctx, name, pat)
|
||||
@@ -810,7 +840,7 @@ map_act = {
|
||||
m = b%32; b = (b-m)/32
|
||||
local nb = b%2; b = (b-nb)/2
|
||||
if nb == 0 then ctx.rexb = true end
|
||||
local nx = b%2; b = (b-nx)/2
|
||||
local nx = b%2
|
||||
if nx == 0 then ctx.rexx = true end
|
||||
b = byte(ctx.code, pos, pos)
|
||||
if not b then return incomplete(ctx) end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT compiler dump module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
@@ -63,9 +63,9 @@ local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek
|
||||
local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap
|
||||
local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr
|
||||
local bit = require("bit")
|
||||
local band, shl, shr, tohex = bit.band, bit.lshift, bit.rshift, bit.tohex
|
||||
local band, shr, tohex = bit.band, bit.rshift, bit.tohex
|
||||
local sub, gsub, format = string.sub, string.gsub, string.format
|
||||
local byte, char, rep = string.byte, string.char, string.rep
|
||||
local byte, rep = string.byte, string.rep
|
||||
local type, tostring = type, tostring
|
||||
local stdout, stderr = io.stdout, io.stderr
|
||||
|
||||
@@ -85,7 +85,7 @@ local nexitsym = 0
|
||||
local function fillsymtab_tr(tr, nexit)
|
||||
local t = {}
|
||||
symtabmt.__index = t
|
||||
if jit.arch == "mips" or jit.arch == "mipsel" then
|
||||
if jit.arch:sub(1, 4) == "mips" then
|
||||
t[traceexitstub(tr, 0)] = "exit"
|
||||
return
|
||||
end
|
||||
@@ -213,7 +213,7 @@ local colortype_ansi = {
|
||||
"\027[35m%s\027[m",
|
||||
}
|
||||
|
||||
local function colorize_text(s, t)
|
||||
local function colorize_text(s)
|
||||
return s
|
||||
end
|
||||
|
||||
@@ -310,15 +310,19 @@ local function fmtfunc(func, pc)
|
||||
end
|
||||
end
|
||||
|
||||
local function formatk(tr, idx)
|
||||
local function formatk(tr, idx, sn)
|
||||
local k, t, slot = tracek(tr, idx)
|
||||
local tn = type(k)
|
||||
local s
|
||||
if tn == "number" then
|
||||
if k == 2^52+2^51 then
|
||||
if t < 12 then
|
||||
s = k == 0 and "NULL" or format("[0x%08x]", k)
|
||||
elseif band(sn or 0, 0x30000) ~= 0 then
|
||||
s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz"
|
||||
elseif k == 2^52+2^51 then
|
||||
s = "bias"
|
||||
else
|
||||
s = format("%+.14g", k)
|
||||
s = format(0 < k and k < 0x1p-1026 and "%+a" or "%+.14g", k)
|
||||
end
|
||||
elseif tn == "string" then
|
||||
s = format(#k > 20 and '"%.20s"~' or '"%s"', gsub(k, "%c", ctlsub))
|
||||
@@ -331,11 +335,13 @@ local function formatk(tr, idx)
|
||||
s = format("userdata:%p", k)
|
||||
else
|
||||
s = format("[%p]", k)
|
||||
if s == "[0x00000000]" then s = "NULL" end
|
||||
if s == "[NULL]" then s = "NULL" end
|
||||
end
|
||||
elseif t == 21 then -- int64_t
|
||||
s = sub(tostring(k), 1, -3)
|
||||
if sub(s, 1, 1) ~= "-" then s = "+"..s end
|
||||
elseif sn == 0x1057fff then -- SNAP(1, SNAP_FRAME | SNAP_NORESTORE, REF_NIL)
|
||||
return "----" -- Special case for LJ_FR2 slot 1.
|
||||
else
|
||||
s = tostring(k) -- For primitives.
|
||||
end
|
||||
@@ -354,7 +360,7 @@ local function printsnap(tr, snap)
|
||||
n = n + 1
|
||||
local ref = band(sn, 0xffff) - 0x8000 -- REF_BIAS
|
||||
if ref < 0 then
|
||||
out:write(formatk(tr, ref))
|
||||
out:write(formatk(tr, ref, sn))
|
||||
elseif band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM
|
||||
out:write(colorize(format("%04d/%04d", ref, ref+1), 14))
|
||||
else
|
||||
@@ -552,7 +558,7 @@ local function dump_trace(what, tr, func, pc, otr, oex)
|
||||
if what == "start" then
|
||||
if dumpmode.H then out:write('<pre class="ljdump">\n') end
|
||||
out:write("---- TRACE ", tr, " ", what)
|
||||
if otr then out:write(" ", otr, "/", oex) end
|
||||
if otr then out:write(" ", otr, "/", oex == -1 and "stitch" or oex) end
|
||||
out:write(" ", fmtfunc(func, pc), "\n")
|
||||
elseif what == "stop" or what == "abort" then
|
||||
out:write("---- TRACE ", tr, " ", what)
|
||||
@@ -578,7 +584,7 @@ local function dump_trace(what, tr, func, pc, otr, oex)
|
||||
end
|
||||
|
||||
-- Dump recorded bytecode.
|
||||
local function dump_record(tr, func, pc, depth, callee)
|
||||
local function dump_record(tr, func, pc, depth)
|
||||
if depth ~= recdepth then
|
||||
recdepth = depth
|
||||
recprefix = rep(" .", depth)
|
||||
@@ -589,7 +595,6 @@ local function dump_record(tr, func, pc, depth, callee)
|
||||
if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end
|
||||
else
|
||||
line = "0000 "..recprefix.." FUNCC \n"
|
||||
callee = func
|
||||
end
|
||||
if pc <= 0 then
|
||||
out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n")
|
||||
@@ -603,12 +608,15 @@ end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local gpr64 = jit.arch:match("64")
|
||||
local fprmips32 = jit.arch == "mips" or jit.arch == "mipsel"
|
||||
|
||||
-- Dump taken trace exits.
|
||||
local function dump_texit(tr, ex, ngpr, nfpr, ...)
|
||||
out:write("---- TRACE ", tr, " exit ", ex, "\n")
|
||||
if dumpmode.X then
|
||||
local regs = {...}
|
||||
if jit.arch == "x64" then
|
||||
if gpr64 then
|
||||
for i=1,ngpr do
|
||||
out:write(format(" %016x", regs[i]))
|
||||
if i % 4 == 0 then out:write("\n") end
|
||||
@@ -619,7 +627,7 @@ local function dump_texit(tr, ex, ngpr, nfpr, ...)
|
||||
if i % 8 == 0 then out:write("\n") end
|
||||
end
|
||||
end
|
||||
if jit.arch == "mips" or jit.arch == "mipsel" then
|
||||
if fprmips32 then
|
||||
for i=1,nfpr,2 do
|
||||
out:write(format(" %+17.14g", regs[ngpr+i]))
|
||||
if i % 8 == 7 then out:write("\n") end
|
||||
@@ -651,7 +659,8 @@ end
|
||||
local function dumpon(opt, outfile)
|
||||
if active then dumpoff() end
|
||||
|
||||
local colormode = os.getenv("COLORTERM") and "A" or "T"
|
||||
local term = os.getenv("TERM")
|
||||
local colormode = (term and term:match("color") or os.getenv("COLORTERM")) and "A" or "T"
|
||||
if opt then
|
||||
opt = gsub(opt, "[TAH]", function(mode) colormode = mode; return ""; end)
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT profiler.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
@@ -120,7 +120,7 @@ end
|
||||
-- Show top N list.
|
||||
local function prof_top(count1, count2, samples, indent)
|
||||
local t, n = {}, 0
|
||||
for k, v in pairs(count1) do
|
||||
for k in pairs(count1) do
|
||||
n = n + 1
|
||||
t[n] = k
|
||||
end
|
||||
@@ -156,6 +156,7 @@ local function prof_annotate(count1, samples)
|
||||
ms = math.max(ms, v)
|
||||
if pct >= prof_min then
|
||||
local file, line = k:match("^(.*):(%d+)$")
|
||||
if not file then file = k; line = 0 end
|
||||
local fl = files[file]
|
||||
if not fl then fl = {}; files[file] = fl; files[#files+1] = file end
|
||||
line = tonumber(line)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- Verbose mode of the LuaJIT compiler.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
@@ -99,7 +99,7 @@ end
|
||||
local function dump_trace(what, tr, func, pc, otr, oex)
|
||||
if what == "start" then
|
||||
startloc = fmtfunc(func, pc)
|
||||
startex = otr and "("..otr.."/"..oex..") " or ""
|
||||
startex = otr and "("..otr.."/"..(oex == -1 and "stitch" or oex)..") " or ""
|
||||
else
|
||||
if what == "abort" then
|
||||
local loc = fmtfunc(func, pc)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT profiler zones.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
#define luaL_getn(L,i) ((int)lua_objlen(L, i))
|
||||
#define luaL_setn(L,i,j) ((void)0) /* no op! */
|
||||
|
||||
/* extra error code for `luaL_load' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
@@ -58,6 +55,10 @@ LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
|
||||
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
|
||||
const char *const lst[]);
|
||||
|
||||
/* pre-defined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||
|
||||
@@ -84,6 +85,11 @@ LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name, const char *mode);
|
||||
LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
|
||||
int level);
|
||||
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
|
||||
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
|
||||
int sizehint);
|
||||
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
|
||||
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
|
||||
|
||||
|
||||
/*
|
||||
@@ -113,6 +119,11 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
|
||||
|
||||
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
|
||||
|
||||
/* From Lua 5.2. */
|
||||
#define luaL_newlibtable(L, l) \
|
||||
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
|
||||
#define luaL_newlib(L, l) (luaL_newlibtable(L, l), luaL_setfuncs(L, l, 0))
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
@@ -147,21 +158,4 @@ LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
/* compatibility with ref system */
|
||||
|
||||
/* pre-defined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
|
||||
(lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
|
||||
|
||||
#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
|
||||
|
||||
#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
|
||||
|
||||
|
||||
#define luaL_reg luaL_Reg
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Auxiliary library for the Lua/C API.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major parts taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
@@ -107,38 +107,36 @@ LUALIB_API const char *luaL_findtable(lua_State *L, int idx,
|
||||
static int libsize(const luaL_Reg *l)
|
||||
{
|
||||
int size = 0;
|
||||
for (; l->name; l++) size++;
|
||||
for (; l && l->name; l++) size++;
|
||||
return size;
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_pushmodule(lua_State *L, const char *modname, int sizehint)
|
||||
{
|
||||
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
|
||||
lua_getfield(L, -1, modname);
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, sizehint) != NULL)
|
||||
lj_err_callerv(L, LJ_ERR_BADMODN, modname);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, modname); /* _LOADED[modname] = new table. */
|
||||
}
|
||||
lua_remove(L, -2); /* Remove _LOADED table. */
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
|
||||
const luaL_Reg *l, int nup)
|
||||
{
|
||||
lj_lib_checkfpu(L);
|
||||
if (libname) {
|
||||
int size = libsize(l);
|
||||
/* check whether lib already exists */
|
||||
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
|
||||
lua_getfield(L, -1, libname); /* get _LOADED[libname] */
|
||||
if (!lua_istable(L, -1)) { /* not found? */
|
||||
lua_pop(L, 1); /* remove previous result */
|
||||
/* try global variable (and create one if it does not exist) */
|
||||
if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
|
||||
lj_err_callerv(L, LJ_ERR_BADMODN, libname);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
|
||||
}
|
||||
lua_remove(L, -2); /* remove _LOADED table */
|
||||
lua_insert(L, -(nup+1)); /* move library table to below upvalues */
|
||||
luaL_pushmodule(L, libname, libsize(l));
|
||||
lua_insert(L, -(nup + 1)); /* Move module table below upvalues. */
|
||||
}
|
||||
for (; l->name; l++) {
|
||||
int i;
|
||||
for (i = 0; i < nup; i++) /* copy upvalues to the top */
|
||||
lua_pushvalue(L, -nup);
|
||||
lua_pushcclosure(L, l->func, nup);
|
||||
lua_setfield(L, -(nup+2), l->name);
|
||||
}
|
||||
lua_pop(L, nup); /* remove upvalues */
|
||||
if (l)
|
||||
luaL_setfuncs(L, l, nup);
|
||||
else
|
||||
lua_pop(L, nup); /* Remove upvalues. */
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_register(lua_State *L, const char *libname,
|
||||
@@ -147,6 +145,19 @@ LUALIB_API void luaL_register(lua_State *L, const char *libname,
|
||||
luaL_openlib(L, libname, l, 0);
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
|
||||
{
|
||||
luaL_checkstack(L, nup, "too many upvalues");
|
||||
for (; l->name; l++) {
|
||||
int i;
|
||||
for (i = 0; i < nup; i++) /* Copy upvalues to the top. */
|
||||
lua_pushvalue(L, -nup);
|
||||
lua_pushcclosure(L, l->func, nup);
|
||||
lua_setfield(L, -(nup + 2), l->name);
|
||||
}
|
||||
lua_pop(L, nup); /* Remove upvalues. */
|
||||
}
|
||||
|
||||
LUALIB_API const char *luaL_gsub(lua_State *L, const char *s,
|
||||
const char *p, const char *r)
|
||||
{
|
||||
@@ -207,8 +218,15 @@ LUALIB_API char *luaL_prepbuffer(luaL_Buffer *B)
|
||||
|
||||
LUALIB_API void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l)
|
||||
{
|
||||
while (l--)
|
||||
luaL_addchar(B, *s++);
|
||||
if (l <= bufffree(B)) {
|
||||
memcpy(B->p, s, l);
|
||||
B->p += l;
|
||||
} else {
|
||||
emptybuffer(B);
|
||||
lua_pushlstring(B->L, s, l);
|
||||
B->lvl++;
|
||||
adjuststack(B);
|
||||
}
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_addstring(luaL_Buffer *B, const char *s)
|
||||
@@ -302,7 +320,7 @@ static int panic(lua_State *L)
|
||||
|
||||
#ifdef LUAJIT_USE_SYSMALLOC
|
||||
|
||||
#if LJ_64 && !defined(LUAJIT_USE_VALGRIND)
|
||||
#if LJ_64 && !LJ_GC64 && !defined(LUAJIT_USE_VALGRIND)
|
||||
#error "Must use builtin allocator for 64 bit target"
|
||||
#endif
|
||||
|
||||
@@ -327,23 +345,19 @@ LUALIB_API lua_State *luaL_newstate(void)
|
||||
|
||||
#else
|
||||
|
||||
#include "lj_alloc.h"
|
||||
|
||||
LUALIB_API lua_State *luaL_newstate(void)
|
||||
{
|
||||
lua_State *L;
|
||||
void *ud = lj_alloc_create();
|
||||
if (ud == NULL) return NULL;
|
||||
#if LJ_64
|
||||
L = lj_state_newstate(lj_alloc_f, ud);
|
||||
#if LJ_64 && !LJ_GC64
|
||||
L = lj_state_newstate(LJ_ALLOCF_INTERNAL, NULL);
|
||||
#else
|
||||
L = lua_newstate(lj_alloc_f, ud);
|
||||
L = lua_newstate(LJ_ALLOCF_INTERNAL, NULL);
|
||||
#endif
|
||||
if (L) G(L)->panic = panic;
|
||||
return L;
|
||||
}
|
||||
|
||||
#if LJ_64
|
||||
#if LJ_64 && !LJ_GC64
|
||||
LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
|
||||
{
|
||||
UNUSED(f); UNUSED(ud);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Base and coroutine library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "lj_tab.h"
|
||||
#include "lj_meta.h"
|
||||
#include "lj_state.h"
|
||||
#include "lj_frame.h"
|
||||
#if LJ_HASFFI
|
||||
#include "lj_ctype.h"
|
||||
#include "lj_cconv.h"
|
||||
@@ -41,13 +42,13 @@
|
||||
|
||||
LJLIB_ASM(assert) LJLIB_REC(.)
|
||||
{
|
||||
GCstr *s;
|
||||
lj_lib_checkany(L, 1);
|
||||
s = lj_lib_optstr(L, 2);
|
||||
if (s)
|
||||
lj_err_callermsg(L, strdata(s));
|
||||
else
|
||||
if (L->top == L->base+1)
|
||||
lj_err_caller(L, LJ_ERR_ASSERT);
|
||||
else if (tvisstr(L->base+1) || tvisnumber(L->base+1))
|
||||
lj_err_callermsg(L, strdata(lj_lib_checkstr(L, 2)));
|
||||
else
|
||||
lj_err_run(L);
|
||||
return FFH_UNREACHABLE;
|
||||
}
|
||||
|
||||
@@ -223,9 +224,11 @@ LJLIB_CF(unpack)
|
||||
int32_t n, i = lj_lib_optint(L, 2, 1);
|
||||
int32_t e = (L->base+3-1 < L->top && !tvisnil(L->base+3-1)) ?
|
||||
lj_lib_checkint(L, 3) : (int32_t)lj_tab_len(t);
|
||||
uint32_t nu;
|
||||
if (i > e) return 0;
|
||||
n = e - i + 1;
|
||||
if (n <= 0 || !lua_checkstack(L, n))
|
||||
nu = (uint32_t)e - (uint32_t)i;
|
||||
n = (int32_t)(nu+1);
|
||||
if (nu >= LUAI_MAXCSTACK || !lua_checkstack(L, n))
|
||||
lj_err_caller(L, LJ_ERR_UNPACK);
|
||||
do {
|
||||
cTValue *tv = lj_tab_getint(t, i);
|
||||
@@ -286,18 +289,27 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
|
||||
} else {
|
||||
const char *p = strdata(lj_lib_checkstr(L, 1));
|
||||
char *ep;
|
||||
unsigned int neg = 0;
|
||||
unsigned long ul;
|
||||
if (base < 2 || base > 36)
|
||||
lj_err_arg(L, 2, LJ_ERR_BASERNG);
|
||||
ul = strtoul(p, &ep, base);
|
||||
if (p != ep) {
|
||||
while (lj_char_isspace((unsigned char)(*ep))) ep++;
|
||||
if (*ep == '\0') {
|
||||
if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u))
|
||||
setintV(L->base-1-LJ_FR2, (int32_t)ul);
|
||||
else
|
||||
setnumV(L->base-1-LJ_FR2, (lua_Number)ul);
|
||||
return FFH_RES(1);
|
||||
while (lj_char_isspace((unsigned char)(*p))) p++;
|
||||
if (*p == '-') { p++; neg = 1; } else if (*p == '+') { p++; }
|
||||
if (lj_char_isalnum((unsigned char)(*p))) {
|
||||
ul = strtoul(p, &ep, base);
|
||||
if (p != ep) {
|
||||
while (lj_char_isspace((unsigned char)(*ep))) ep++;
|
||||
if (*ep == '\0') {
|
||||
if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u+neg)) {
|
||||
if (neg) ul = (unsigned long)-(long)ul;
|
||||
setintV(L->base-1-LJ_FR2, (int32_t)ul);
|
||||
} else {
|
||||
lua_Number n = (lua_Number)ul;
|
||||
if (neg) n = -n;
|
||||
setnumV(L->base-1-LJ_FR2, n);
|
||||
}
|
||||
return FFH_RES(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -345,7 +357,7 @@ LJLIB_ASM_(xpcall) LJLIB_REC(.)
|
||||
|
||||
static int load_aux(lua_State *L, int status, int envarg)
|
||||
{
|
||||
if (status == 0) {
|
||||
if (status == LUA_OK) {
|
||||
if (tvistab(L->base+envarg-1)) {
|
||||
GCfunc *fn = funcV(L->top-1);
|
||||
GCtab *t = tabV(L->base+envarg-1);
|
||||
@@ -418,7 +430,7 @@ LJLIB_CF(dofile)
|
||||
GCstr *fname = lj_lib_optstr(L, 1);
|
||||
setnilV(L->top);
|
||||
L->top = L->base+1;
|
||||
if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != 0)
|
||||
if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != LUA_OK)
|
||||
lua_error(L);
|
||||
lua_call(L, 0, LUA_MULTRET);
|
||||
return (int)(L->top - L->base) - 1;
|
||||
@@ -492,14 +504,14 @@ LJLIB_CF(print)
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
tv = L->top-1;
|
||||
}
|
||||
shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring);
|
||||
shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring) &&
|
||||
!gcrefu(basemt_it(G(L), LJ_TNUMX));
|
||||
for (i = 0; i < nargs; i++) {
|
||||
cTValue *o = &L->base[i];
|
||||
char buf[STRFMT_MAXBUF_NUM];
|
||||
const char *str;
|
||||
size_t size;
|
||||
MSize len;
|
||||
if (shortcut && (str = lj_strfmt_wstrnum(buf, o, &len)) != NULL) {
|
||||
if (shortcut && (str = lj_strfmt_wstrnum(L, o, &len)) != NULL) {
|
||||
size = len;
|
||||
} else {
|
||||
copyTV(L, L->top+1, o);
|
||||
@@ -537,7 +549,7 @@ LJLIB_CF(coroutine_status)
|
||||
co = threadV(L->base);
|
||||
if (co == L) s = "running";
|
||||
else if (co->status == LUA_YIELD) s = "suspended";
|
||||
else if (co->status != 0) s = "dead";
|
||||
else if (co->status != LUA_OK) s = "dead";
|
||||
else if (co->base > tvref(co->stack)+1+LJ_FR2) s = "normal";
|
||||
else if (co->top == co->base) s = "dead";
|
||||
else s = "suspended";
|
||||
@@ -558,6 +570,12 @@ LJLIB_CF(coroutine_running)
|
||||
#endif
|
||||
}
|
||||
|
||||
LJLIB_CF(coroutine_isyieldable)
|
||||
{
|
||||
setboolV(L->top++, cframe_canyield(L->cframe));
|
||||
return 1;
|
||||
}
|
||||
|
||||
LJLIB_CF(coroutine_create)
|
||||
{
|
||||
lua_State *L1;
|
||||
@@ -577,7 +595,7 @@ LJLIB_ASM(coroutine_yield)
|
||||
static int ffh_resume(lua_State *L, lua_State *co, int wrap)
|
||||
{
|
||||
if (co->cframe != NULL || co->status > LUA_YIELD ||
|
||||
(co->status == 0 && co->top == co->base)) {
|
||||
(co->status == LUA_OK && co->top == co->base)) {
|
||||
ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD;
|
||||
if (wrap) lj_err_caller(L, em);
|
||||
setboolV(L->base-1-LJ_FR2, 0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Bit manipulation library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#define lib_bit_c
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Debug library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
@@ -231,8 +231,8 @@ LJLIB_CF(debug_upvalueid)
|
||||
int32_t n = lj_lib_checkint(L, 2) - 1;
|
||||
if ((uint32_t)n >= fn->l.nupvalues)
|
||||
lj_err_arg(L, 2, LJ_ERR_IDXRNG);
|
||||
setlightudV(L->top-1, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
|
||||
(void *)&fn->c.upvalue[n]);
|
||||
lua_pushlightuserdata(L, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
|
||||
(void *)&fn->c.upvalue[n]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -283,13 +283,13 @@ LJLIB_CF(debug_setuservalue)
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static const char KEY_HOOK = 'h';
|
||||
#define KEY_HOOK (U64x(80000000,00000000)|'h')
|
||||
|
||||
static void hookf(lua_State *L, lua_Debug *ar)
|
||||
{
|
||||
static const char *const hooknames[] =
|
||||
{"call", "return", "line", "count", "tail return"};
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
(L->top++)->u64 = KEY_HOOK;
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
if (lua_isfunction(L, -1)) {
|
||||
lua_pushstring(L, hooknames[(int)ar->event]);
|
||||
@@ -334,7 +334,7 @@ LJLIB_CF(debug_sethook)
|
||||
count = luaL_optint(L, arg+3, 0);
|
||||
func = hookf; mask = makemask(smask, count);
|
||||
}
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
(L->top++)->u64 = KEY_HOOK;
|
||||
lua_pushvalue(L, arg+1);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
lua_sethook(L, func, mask, count);
|
||||
@@ -349,7 +349,7 @@ LJLIB_CF(debug_gethook)
|
||||
if (hook != NULL && hook != hookf) { /* external hook? */
|
||||
lua_pushliteral(L, "external hook");
|
||||
} else {
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
(L->top++)->u64 = KEY_HOOK;
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
|
||||
}
|
||||
lua_pushstring(L, unmakemask(mask, buff));
|
||||
@@ -369,7 +369,8 @@ LJLIB_CF(debug_debug)
|
||||
return 0;
|
||||
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
|
||||
lua_pcall(L, 0, 0, 0)) {
|
||||
fputs(lua_tostring(L, -1), stderr);
|
||||
const char *s = lua_tostring(L, -1);
|
||||
fputs(s ? s : "(error object is not a string)", stderr);
|
||||
fputs("\n", stderr);
|
||||
}
|
||||
lua_settop(L, 0); /* remove eventual returns */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** FFI library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#define lib_ffi_c
|
||||
@@ -505,10 +505,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.)
|
||||
}
|
||||
if (sz == CTSIZE_INVALID)
|
||||
lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE);
|
||||
if (!(info & CTF_VLA) && ctype_align(info) <= CT_MEMALIGN)
|
||||
cd = lj_cdata_new(cts, id, sz);
|
||||
else
|
||||
cd = lj_cdata_newv(L, id, sz, ctype_align(info));
|
||||
cd = lj_cdata_newx(cts, id, sz, info);
|
||||
setcdataV(L, o-1, cd); /* Anchor the uninitialized cdata. */
|
||||
lj_cconv_ct_init(cts, ct, sz, cdataptr(cd),
|
||||
o, (MSize)(L->top - o)); /* Initialize cdata. */
|
||||
@@ -723,47 +720,47 @@ LJLIB_CF(ffi_fill) LJLIB_REC(.)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
|
||||
|
||||
/* Test ABI string. */
|
||||
LJLIB_CF(ffi_abi) LJLIB_REC(.)
|
||||
{
|
||||
GCstr *s = lj_lib_checkstr(L, 1);
|
||||
int b = 0;
|
||||
switch (s->hash) {
|
||||
int b = lj_cparse_case(s,
|
||||
#if LJ_64
|
||||
case H_(849858eb,ad35fd06): b = 1; break; /* 64bit */
|
||||
"\00564bit"
|
||||
#else
|
||||
case H_(662d3c79,d0e22477): b = 1; break; /* 32bit */
|
||||
"\00532bit"
|
||||
#endif
|
||||
#if LJ_ARCH_HASFPU
|
||||
case H_(e33ee463,e33ee463): b = 1; break; /* fpu */
|
||||
"\003fpu"
|
||||
#endif
|
||||
#if LJ_ABI_SOFTFP
|
||||
case H_(61211a23,c2e8c81c): b = 1; break; /* softfp */
|
||||
"\006softfp"
|
||||
#else
|
||||
case H_(539417a8,8ce0812f): b = 1; break; /* hardfp */
|
||||
"\006hardfp"
|
||||
#endif
|
||||
#if LJ_ABI_EABI
|
||||
case H_(2182df8f,f2ed1152): b = 1; break; /* eabi */
|
||||
"\004eabi"
|
||||
#endif
|
||||
#if LJ_ABI_WIN
|
||||
case H_(4ab624a8,4ab624a8): b = 1; break; /* win */
|
||||
"\003win"
|
||||
#endif
|
||||
#if LJ_TARGET_UWP
|
||||
"\003uwp"
|
||||
#endif
|
||||
#if LJ_LE
|
||||
"\002le"
|
||||
#else
|
||||
"\002be"
|
||||
#endif
|
||||
case H_(3af93066,1f001464): b = 1; break; /* le/be */
|
||||
#if LJ_GC64
|
||||
case H_(9e89d2c9,13c83c92): b = 1; break; /* gc64 */
|
||||
"\004gc64"
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
) >= 0;
|
||||
setboolV(L->top-1, b);
|
||||
setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef H_
|
||||
|
||||
LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */
|
||||
|
||||
LJLIB_CF(ffi_metatype)
|
||||
@@ -832,7 +829,7 @@ static GCtab *ffi_finalizer(lua_State *L)
|
||||
settabV(L, L->top++, t);
|
||||
setgcref(t->metatable, obj2gco(t));
|
||||
setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")),
|
||||
lj_str_newlit(L, "K"));
|
||||
lj_str_newlit(L, "k"));
|
||||
t->nomm = (uint8_t)(~(1u<<MM_mode));
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Library initialization.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major parts taken verbatim from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** I/O library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
@@ -99,11 +99,8 @@ static int io_file_close(lua_State *L, IOFileUD *iof)
|
||||
int stat = -1;
|
||||
#if LJ_TARGET_POSIX
|
||||
stat = pclose(iof->fp);
|
||||
#elif LJ_TARGET_WINDOWS && !LJ_TARGET_XBOXONE
|
||||
#elif LJ_TARGET_WINDOWS && !LJ_TARGET_XBOXONE && !LJ_TARGET_UWP
|
||||
stat = _pclose(iof->fp);
|
||||
#else
|
||||
lua_assert(0);
|
||||
return 0;
|
||||
#endif
|
||||
#if LJ_52
|
||||
iof->fp = NULL;
|
||||
@@ -112,7 +109,8 @@ static int io_file_close(lua_State *L, IOFileUD *iof)
|
||||
ok = (stat != -1);
|
||||
#endif
|
||||
} else {
|
||||
lua_assert((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_STDF);
|
||||
lj_assertL((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_STDF,
|
||||
"close of unknown FILE* type");
|
||||
setnilV(L->top++);
|
||||
lua_pushliteral(L, "cannot close standard file");
|
||||
return 2;
|
||||
@@ -203,13 +201,12 @@ static int io_file_read(lua_State *L, FILE *fp, int start)
|
||||
for (n = start; nargs-- && ok; n++) {
|
||||
if (tvisstr(L->base+n)) {
|
||||
const char *p = strVdata(L->base+n);
|
||||
if (p[0] != '*')
|
||||
lj_err_arg(L, n+1, LJ_ERR_INVOPT);
|
||||
if (p[1] == 'n')
|
||||
if (p[0] == '*') p++;
|
||||
if (p[0] == 'n')
|
||||
ok = io_file_readnum(L, fp);
|
||||
else if ((p[1] & ~0x20) == 'L')
|
||||
ok = io_file_readline(L, fp, (p[1] == 'l'));
|
||||
else if (p[1] == 'a')
|
||||
else if ((p[0] & ~0x20) == 'L')
|
||||
ok = io_file_readline(L, fp, (p[0] == 'l'));
|
||||
else if (p[0] == 'a')
|
||||
io_file_readall(L, fp);
|
||||
else
|
||||
lj_err_arg(L, n+1, LJ_ERR_INVFMT);
|
||||
@@ -232,9 +229,8 @@ static int io_file_write(lua_State *L, FILE *fp, int start)
|
||||
cTValue *tv;
|
||||
int status = 1;
|
||||
for (tv = L->base+start; tv < L->top; tv++) {
|
||||
char buf[STRFMT_MAXBUF_NUM];
|
||||
MSize len;
|
||||
const char *p = lj_strfmt_wstrnum(buf, tv, &len);
|
||||
const char *p = lj_strfmt_wstrnum(L, tv, &len);
|
||||
if (!p)
|
||||
lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING);
|
||||
status = status && (fwrite(p, 1, len, fp) == len);
|
||||
@@ -308,6 +304,14 @@ LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0)
|
||||
return luaL_fileresult(L, fflush(io_tofile(L)->fp) == 0, NULL);
|
||||
}
|
||||
|
||||
#if LJ_32 && defined(__ANDROID__) && __ANDROID_API__ < 24
|
||||
/* The Android NDK is such an unmatched marvel of engineering. */
|
||||
extern int fseeko32(FILE *, long int, int) __asm__("fseeko");
|
||||
extern long int ftello32(FILE *) __asm__("ftello");
|
||||
#define fseeko(fp, pos, whence) (fseeko32((fp), (pos), (whence)))
|
||||
#define ftello(fp) (ftello32((fp)))
|
||||
#endif
|
||||
|
||||
LJLIB_CF(io_method_seek)
|
||||
{
|
||||
FILE *fp = io_tofile(L)->fp;
|
||||
@@ -408,7 +412,7 @@ LJLIB_CF(io_open)
|
||||
|
||||
LJLIB_CF(io_popen)
|
||||
{
|
||||
#if LJ_TARGET_POSIX || (LJ_TARGET_WINDOWS && !LJ_TARGET_XBOXONE)
|
||||
#if LJ_TARGET_POSIX || (LJ_TARGET_WINDOWS && !LJ_TARGET_XBOXONE && !LJ_TARGET_UWP)
|
||||
const char *fname = strdata(lj_lib_checkstr(L, 1));
|
||||
GCstr *s = lj_lib_optstr(L, 2);
|
||||
const char *mode = s ? strdata(s) : "r";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** JIT library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#define lib_jit_c
|
||||
@@ -104,8 +104,8 @@ LJLIB_CF(jit_status)
|
||||
jit_State *J = L2J(L);
|
||||
L->top = L->base;
|
||||
setboolV(L->top++, (J->flags & JIT_F_ON) ? 1 : 0);
|
||||
flagbits_to_strings(L, J->flags, JIT_F_CPU_FIRST, JIT_F_CPUSTRING);
|
||||
flagbits_to_strings(L, J->flags, JIT_F_OPT_FIRST, JIT_F_OPTSTRING);
|
||||
flagbits_to_strings(L, J->flags, JIT_F_CPU, JIT_F_CPUSTRING);
|
||||
flagbits_to_strings(L, J->flags, JIT_F_OPT, JIT_F_OPTSTRING);
|
||||
return (int)(L->top - L->base);
|
||||
#else
|
||||
setboolV(L->top++, 0);
|
||||
@@ -113,6 +113,13 @@ LJLIB_CF(jit_status)
|
||||
#endif
|
||||
}
|
||||
|
||||
LJLIB_CF(jit_security)
|
||||
{
|
||||
int idx = lj_lib_checkopt(L, 1, -1, LJ_SECURITY_MODESTRING);
|
||||
setintV(L->top++, ((LJ_SECURITY_MODE >> (2*idx)) & 3));
|
||||
return 1;
|
||||
}
|
||||
|
||||
LJLIB_CF(jit_attach)
|
||||
{
|
||||
#ifdef LUAJIT_DISABLE_VMEVENT
|
||||
@@ -204,6 +211,7 @@ LJLIB_CF(jit_util_funcinfo)
|
||||
lua_setfield(L, -2, "source");
|
||||
lj_debug_pushloc(L, pt, pc);
|
||||
lua_setfield(L, -2, "loc");
|
||||
setprotoV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "proto")), pt);
|
||||
} else {
|
||||
GCfunc *fn = funcV(L->base);
|
||||
GCtab *t;
|
||||
@@ -226,7 +234,7 @@ LJLIB_CF(jit_util_funcbc)
|
||||
if (pc < pt->sizebc) {
|
||||
BCIns ins = proto_bc(pt)[pc];
|
||||
BCOp op = bc_op(ins);
|
||||
lua_assert(op < BC__MAX);
|
||||
lj_assertL(op < BC__MAX, "bad bytecode op %d", op);
|
||||
setintV(L->top, ins);
|
||||
setintV(L->top+1, lj_bc_mode[op]);
|
||||
L->top += 2;
|
||||
@@ -470,7 +478,7 @@ static int jitopt_flag(jit_State *J, const char *str)
|
||||
str += str[2] == '-' ? 3 : 2;
|
||||
set = 0;
|
||||
}
|
||||
for (opt = JIT_F_OPT_FIRST; ; opt <<= 1) {
|
||||
for (opt = JIT_F_OPT; ; opt <<= 1) {
|
||||
size_t len = *(const uint8_t *)lst;
|
||||
if (len == 0)
|
||||
break;
|
||||
@@ -490,7 +498,7 @@ static int jitopt_param(jit_State *J, const char *str)
|
||||
int i;
|
||||
for (i = 0; i < JIT_P__MAX; i++) {
|
||||
size_t len = *(const uint8_t *)lst;
|
||||
lua_assert(len != 0);
|
||||
lj_assertJ(len != 0, "bad JIT_P_STRING");
|
||||
if (strncmp(str, lst+1, len) == 0 && str[len] == '=') {
|
||||
int32_t n = 0;
|
||||
const char *p = &str[len+1];
|
||||
@@ -539,15 +547,15 @@ LJLIB_CF(jit_opt_start)
|
||||
|
||||
/* Not loaded by default, use: local profile = require("jit.profile") */
|
||||
|
||||
static const char KEY_PROFILE_THREAD = 't';
|
||||
static const char KEY_PROFILE_FUNC = 'f';
|
||||
#define KEY_PROFILE_THREAD (U64x(80000000,00000000)|'t')
|
||||
#define KEY_PROFILE_FUNC (U64x(80000000,00000000)|'f')
|
||||
|
||||
static void jit_profile_callback(lua_State *L2, lua_State *L, int samples,
|
||||
int vmstate)
|
||||
{
|
||||
TValue key;
|
||||
cTValue *tv;
|
||||
setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
|
||||
key.u64 = KEY_PROFILE_FUNC;
|
||||
tv = lj_tab_get(L, tabV(registry(L)), &key);
|
||||
if (tvisfunc(tv)) {
|
||||
char vmst = (char)vmstate;
|
||||
@@ -574,9 +582,9 @@ LJLIB_CF(jit_profile_start)
|
||||
lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */
|
||||
TValue key;
|
||||
/* Anchor thread and function in registry. */
|
||||
setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
|
||||
key.u64 = KEY_PROFILE_THREAD;
|
||||
setthreadV(L, lj_tab_set(L, registry, &key), L2);
|
||||
setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
|
||||
key.u64 = KEY_PROFILE_FUNC;
|
||||
setfuncV(L, lj_tab_set(L, registry, &key), func);
|
||||
lj_gc_anybarriert(L, registry);
|
||||
luaJIT_profile_start(L, mode ? strdata(mode) : "",
|
||||
@@ -591,9 +599,9 @@ LJLIB_CF(jit_profile_stop)
|
||||
TValue key;
|
||||
luaJIT_profile_stop(L);
|
||||
registry = tabV(registry(L));
|
||||
setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
|
||||
key.u64 = KEY_PROFILE_THREAD;
|
||||
setnilV(lj_tab_set(L, registry, &key));
|
||||
setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
|
||||
key.u64 = KEY_PROFILE_FUNC;
|
||||
setnilV(lj_tab_set(L, registry, &key));
|
||||
lj_gc_anybarriert(L, registry);
|
||||
return 0;
|
||||
@@ -639,54 +647,41 @@ JIT_PARAMDEF(JIT_PARAMINIT)
|
||||
#undef JIT_PARAMINIT
|
||||
0
|
||||
};
|
||||
#endif
|
||||
|
||||
#if LJ_TARGET_ARM && LJ_TARGET_LINUX
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
/* Arch-dependent CPU detection. */
|
||||
static uint32_t jit_cpudetect(lua_State *L)
|
||||
/* Arch-dependent CPU feature detection. */
|
||||
static uint32_t jit_cpudetect(void)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
#if LJ_TARGET_X86ORX64
|
||||
|
||||
uint32_t vendor[4];
|
||||
uint32_t features[4];
|
||||
if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) {
|
||||
#if !LJ_HASJIT
|
||||
#define JIT_F_SSE2 2
|
||||
#endif
|
||||
flags |= ((features[3] >> 26)&1) * JIT_F_SSE2;
|
||||
#if LJ_HASJIT
|
||||
flags |= ((features[2] >> 0)&1) * JIT_F_SSE3;
|
||||
flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1;
|
||||
if (vendor[2] == 0x6c65746e) { /* Intel. */
|
||||
if ((features[0] & 0x0fff0ff0) == 0x000106c0) /* Atom. */
|
||||
flags |= JIT_F_LEA_AGU;
|
||||
} else if (vendor[2] == 0x444d4163) { /* AMD. */
|
||||
uint32_t fam = (features[0] & 0x0ff00f00);
|
||||
if (fam >= 0x00000f00) /* K8, K10. */
|
||||
flags |= JIT_F_PREFER_IMUL;
|
||||
if (vendor[0] >= 7) {
|
||||
uint32_t xfeatures[4];
|
||||
lj_vm_cpuid(7, xfeatures);
|
||||
flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* Check for required instruction set support on x86 (unnecessary on x64). */
|
||||
#if LJ_TARGET_X86
|
||||
if (!(flags & JIT_F_SSE2))
|
||||
luaL_error(L, "CPU with SSE2 required");
|
||||
#endif
|
||||
/* Don't bother checking for SSE2 -- the VM will crash before getting here. */
|
||||
|
||||
#elif LJ_TARGET_ARM
|
||||
#if LJ_HASJIT
|
||||
|
||||
int ver = LJ_ARCH_VERSION; /* Compile-time ARM CPU detection. */
|
||||
#if LJ_TARGET_LINUX
|
||||
if (ver < 70) { /* Runtime ARM CPU detection. */
|
||||
struct utsname ut;
|
||||
uname(&ut);
|
||||
if (strncmp(ut.machine, "armv", 4) == 0) {
|
||||
if (ut.machine[4] >= '7')
|
||||
ver = 70;
|
||||
else if (ut.machine[4] == '6')
|
||||
ver = 60;
|
||||
if (ut.machine[4] >= '8') ver = 80;
|
||||
else if (ut.machine[4] == '7') ver = 70;
|
||||
else if (ut.machine[4] == '6') ver = 60;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -694,58 +689,61 @@ static uint32_t jit_cpudetect(lua_State *L)
|
||||
ver >= 61 ? JIT_F_ARMV6T2_ :
|
||||
ver >= 60 ? JIT_F_ARMV6_ : 0;
|
||||
flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2;
|
||||
#endif
|
||||
|
||||
#elif LJ_TARGET_ARM64
|
||||
|
||||
/* No optional CPU features to detect (for now). */
|
||||
|
||||
#elif LJ_TARGET_PPC
|
||||
#if LJ_HASJIT
|
||||
|
||||
#if LJ_ARCH_SQRT
|
||||
flags |= JIT_F_SQRT;
|
||||
#endif
|
||||
#if LJ_ARCH_ROUND
|
||||
flags |= JIT_F_ROUND;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif LJ_TARGET_MIPS
|
||||
#if LJ_HASJIT
|
||||
|
||||
/* Compile-time MIPS CPU detection. */
|
||||
#if LJ_ARCH_VERSION >= 20
|
||||
flags |= JIT_F_MIPS32R2;
|
||||
flags |= JIT_F_MIPSXXR2;
|
||||
#endif
|
||||
/* Runtime MIPS CPU detection. */
|
||||
#if defined(__GNUC__)
|
||||
if (!(flags & JIT_F_MIPS32R2)) {
|
||||
if (!(flags & JIT_F_MIPSXXR2)) {
|
||||
int x;
|
||||
#ifdef __mips16
|
||||
x = 0; /* Runtime detection is difficult. Ensure optimal -march flags. */
|
||||
#else
|
||||
/* On MIPS32R1 rotr is treated as srl. rotr r2,r2,1 -> srl r2,r2,1. */
|
||||
__asm__("li $2, 1\n\t.long 0x00221042\n\tmove %0, $2" : "=r"(x) : : "$2");
|
||||
if (x) flags |= JIT_F_MIPS32R2; /* Either 0x80000000 (R2) or 0 (R1). */
|
||||
#endif
|
||||
if (x) flags |= JIT_F_MIPSXXR2; /* Either 0x80000000 (R2) or 0 (R1). */
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error "Missing CPU detection for this architecture"
|
||||
#endif
|
||||
UNUSED(L);
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* Initialize JIT compiler. */
|
||||
static void jit_init(lua_State *L)
|
||||
{
|
||||
uint32_t flags = jit_cpudetect(L);
|
||||
#if LJ_HASJIT
|
||||
jit_State *J = L2J(L);
|
||||
J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT;
|
||||
J->flags = jit_cpudetect() | JIT_F_ON | JIT_F_OPT_DEFAULT;
|
||||
memcpy(J->param, jit_param_default, sizeof(J->param));
|
||||
lj_dispatch_update(G(L));
|
||||
#else
|
||||
UNUSED(flags);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
LUALIB_API int luaopen_jit(lua_State *L)
|
||||
{
|
||||
#if LJ_HASJIT
|
||||
jit_init(L);
|
||||
#endif
|
||||
lua_pushliteral(L, LJ_OS_NAME);
|
||||
lua_pushliteral(L, LJ_ARCH_NAME);
|
||||
lua_pushinteger(L, LUAJIT_VERSION_NUM);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Math library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "lj_obj.h"
|
||||
#include "lj_lib.h"
|
||||
#include "lj_vm.h"
|
||||
#include "lj_prng.h"
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
@@ -33,19 +34,19 @@ LJLIB_ASM(math_sqrt) LJLIB_REC(math_unary IRFPM_SQRT)
|
||||
lj_lib_checknum(L, 1);
|
||||
return FFH_RETRY;
|
||||
}
|
||||
LJLIB_ASM_(math_log10) LJLIB_REC(math_unary IRFPM_LOG10)
|
||||
LJLIB_ASM_(math_exp) LJLIB_REC(math_unary IRFPM_EXP)
|
||||
LJLIB_ASM_(math_sin) LJLIB_REC(math_unary IRFPM_SIN)
|
||||
LJLIB_ASM_(math_cos) LJLIB_REC(math_unary IRFPM_COS)
|
||||
LJLIB_ASM_(math_tan) LJLIB_REC(math_unary IRFPM_TAN)
|
||||
LJLIB_ASM_(math_asin) LJLIB_REC(math_atrig FF_math_asin)
|
||||
LJLIB_ASM_(math_acos) LJLIB_REC(math_atrig FF_math_acos)
|
||||
LJLIB_ASM_(math_atan) LJLIB_REC(math_atrig FF_math_atan)
|
||||
LJLIB_ASM_(math_sinh) LJLIB_REC(math_htrig IRCALL_sinh)
|
||||
LJLIB_ASM_(math_cosh) LJLIB_REC(math_htrig IRCALL_cosh)
|
||||
LJLIB_ASM_(math_tanh) LJLIB_REC(math_htrig IRCALL_tanh)
|
||||
LJLIB_ASM_(math_log10) LJLIB_REC(math_call IRCALL_log10)
|
||||
LJLIB_ASM_(math_exp) LJLIB_REC(math_call IRCALL_exp)
|
||||
LJLIB_ASM_(math_sin) LJLIB_REC(math_call IRCALL_sin)
|
||||
LJLIB_ASM_(math_cos) LJLIB_REC(math_call IRCALL_cos)
|
||||
LJLIB_ASM_(math_tan) LJLIB_REC(math_call IRCALL_tan)
|
||||
LJLIB_ASM_(math_asin) LJLIB_REC(math_call IRCALL_asin)
|
||||
LJLIB_ASM_(math_acos) LJLIB_REC(math_call IRCALL_acos)
|
||||
LJLIB_ASM_(math_atan) LJLIB_REC(math_call IRCALL_atan)
|
||||
LJLIB_ASM_(math_sinh) LJLIB_REC(math_call IRCALL_sinh)
|
||||
LJLIB_ASM_(math_cosh) LJLIB_REC(math_call IRCALL_cosh)
|
||||
LJLIB_ASM_(math_tanh) LJLIB_REC(math_call IRCALL_tanh)
|
||||
LJLIB_ASM_(math_frexp)
|
||||
LJLIB_ASM_(math_modf) LJLIB_REC(.)
|
||||
LJLIB_ASM_(math_modf)
|
||||
|
||||
LJLIB_ASM(math_log) LJLIB_REC(math_log)
|
||||
{
|
||||
@@ -105,34 +106,11 @@ LJLIB_PUSH(1e310) LJLIB_SET(huge)
|
||||
** Full-period ME-CF generator with L=64, J=4, k=223, N1=49.
|
||||
*/
|
||||
|
||||
/* PRNG state. */
|
||||
struct RandomState {
|
||||
uint64_t gen[4]; /* State of the 4 LFSR generators. */
|
||||
int valid; /* State is valid. */
|
||||
};
|
||||
|
||||
/* Union needed for bit-pattern conversion between uint64_t and double. */
|
||||
typedef union { uint64_t u64; double d; } U64double;
|
||||
|
||||
/* Update generator i and compute a running xor of all states. */
|
||||
#define TW223_GEN(i, k, q, s) \
|
||||
z = rs->gen[i]; \
|
||||
z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \
|
||||
r ^= z; rs->gen[i] = z;
|
||||
|
||||
/* PRNG step function. Returns a double in the range 1.0 <= d < 2.0. */
|
||||
LJ_NOINLINE uint64_t LJ_FASTCALL lj_math_random_step(RandomState *rs)
|
||||
{
|
||||
uint64_t z, r = 0;
|
||||
TW223_GEN(0, 63, 31, 18)
|
||||
TW223_GEN(1, 58, 19, 28)
|
||||
TW223_GEN(2, 55, 24, 7)
|
||||
TW223_GEN(3, 47, 21, 8)
|
||||
return (r & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000);
|
||||
}
|
||||
|
||||
/* PRNG initialization function. */
|
||||
static void random_init(RandomState *rs, double d)
|
||||
/* PRNG seeding function. */
|
||||
static void random_seed(PRNGState *rs, double d)
|
||||
{
|
||||
uint32_t r = 0x11090601; /* 64-k[i] as four 8 bit constants. */
|
||||
int i;
|
||||
@@ -141,24 +119,22 @@ static void random_init(RandomState *rs, double d)
|
||||
uint32_t m = 1u << (r&255);
|
||||
r >>= 8;
|
||||
u.d = d = d * 3.14159265358979323846 + 2.7182818284590452354;
|
||||
if (u.u64 < m) u.u64 += m; /* Ensure k[i] MSB of gen[i] are non-zero. */
|
||||
rs->gen[i] = u.u64;
|
||||
if (u.u64 < m) u.u64 += m; /* Ensure k[i] MSB of u[i] are non-zero. */
|
||||
rs->u[i] = u.u64;
|
||||
}
|
||||
rs->valid = 1;
|
||||
for (i = 0; i < 10; i++)
|
||||
lj_math_random_step(rs);
|
||||
(void)lj_prng_u64(rs);
|
||||
}
|
||||
|
||||
/* PRNG extract function. */
|
||||
LJLIB_PUSH(top-2) /* Upvalue holds userdata with RandomState. */
|
||||
LJLIB_PUSH(top-2) /* Upvalue holds userdata with PRNGState. */
|
||||
LJLIB_CF(math_random) LJLIB_REC(.)
|
||||
{
|
||||
int n = (int)(L->top - L->base);
|
||||
RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
|
||||
PRNGState *rs = (PRNGState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
|
||||
U64double u;
|
||||
double d;
|
||||
if (LJ_UNLIKELY(!rs->valid)) random_init(rs, 0.0);
|
||||
u.u64 = lj_math_random_step(rs);
|
||||
u.u64 = lj_prng_u64d(rs);
|
||||
d = u.d - 1.0;
|
||||
if (n > 0) {
|
||||
#if LJ_DUALNUM
|
||||
@@ -203,11 +179,11 @@ LJLIB_CF(math_random) LJLIB_REC(.)
|
||||
}
|
||||
|
||||
/* PRNG seed function. */
|
||||
LJLIB_PUSH(top-2) /* Upvalue holds userdata with RandomState. */
|
||||
LJLIB_PUSH(top-2) /* Upvalue holds userdata with PRNGState. */
|
||||
LJLIB_CF(math_randomseed)
|
||||
{
|
||||
RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
|
||||
random_init(rs, lj_lib_checknum(L, 1));
|
||||
PRNGState *rs = (PRNGState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
|
||||
random_seed(rs, lj_lib_checknum(L, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -217,14 +193,9 @@ LJLIB_CF(math_randomseed)
|
||||
|
||||
LUALIB_API int luaopen_math(lua_State *L)
|
||||
{
|
||||
RandomState *rs;
|
||||
rs = (RandomState *)lua_newuserdata(L, sizeof(RandomState));
|
||||
rs->valid = 0; /* Use lazy initialization to save some time on startup. */
|
||||
PRNGState *rs = (PRNGState *)lua_newuserdata(L, sizeof(PRNGState));
|
||||
lj_prng_seed_fixed(rs);
|
||||
LJ_LIB_REG(L, LUA_MATHLIBNAME, math);
|
||||
#if defined(LUA_COMPAT_MOD) && !LJ_52
|
||||
lua_getfield(L, -1, "fmod");
|
||||
lua_setfield(L, -2, "mod");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** OS library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
@@ -205,12 +205,12 @@ LJLIB_CF(os_date)
|
||||
setboolfield(L, "isdst", stm->tm_isdst);
|
||||
} else if (*s) {
|
||||
SBuf *sb = &G(L)->tmpbuf;
|
||||
MSize sz = 0;
|
||||
MSize sz = 0, retry = 4;
|
||||
const char *q;
|
||||
for (q = s; *q; q++)
|
||||
sz += (*q == '%') ? 30 : 1; /* Overflow doesn't matter. */
|
||||
setsbufL(sb, L);
|
||||
for (;;) {
|
||||
while (retry--) { /* Limit growth for invalid format or empty result. */
|
||||
char *buf = lj_buf_need(sb, sz);
|
||||
size_t len = strftime(buf, sbufsz(sb), s, stm);
|
||||
if (len) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Package library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2012 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
@@ -76,6 +76,20 @@ static const char *ll_bcsym(void *lib, const char *sym)
|
||||
BOOL WINAPI GetModuleHandleExA(DWORD, LPCSTR, HMODULE*);
|
||||
#endif
|
||||
|
||||
#if LJ_TARGET_UWP
|
||||
void *LJ_WIN_LOADLIBA(const char *path)
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
wchar_t wpath[256];
|
||||
HANDLE lib = NULL;
|
||||
if (MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, 256) > 0) {
|
||||
lib = LoadPackagedLibrary(wpath, 0);
|
||||
}
|
||||
SetLastError(err);
|
||||
return lib;
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef setprogdir
|
||||
|
||||
static void setprogdir(lua_State *L)
|
||||
@@ -119,7 +133,7 @@ static void ll_unloadlib(void *lib)
|
||||
|
||||
static void *ll_load(lua_State *L, const char *path, int gl)
|
||||
{
|
||||
HINSTANCE lib = LoadLibraryExA(path, NULL, 0);
|
||||
HINSTANCE lib = LJ_WIN_LOADLIBA(path);
|
||||
if (lib == NULL) pusherror(L);
|
||||
UNUSED(gl);
|
||||
return lib;
|
||||
@@ -132,17 +146,25 @@ static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym)
|
||||
return f;
|
||||
}
|
||||
|
||||
#if LJ_TARGET_UWP
|
||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||
#endif
|
||||
|
||||
static const char *ll_bcsym(void *lib, const char *sym)
|
||||
{
|
||||
if (lib) {
|
||||
return (const char *)GetProcAddress((HINSTANCE)lib, sym);
|
||||
} else {
|
||||
#if LJ_TARGET_UWP
|
||||
return (const char *)GetProcAddress((HINSTANCE)&__ImageBase, sym);
|
||||
#else
|
||||
HINSTANCE h = GetModuleHandleA(NULL);
|
||||
const char *p = (const char *)GetProcAddress(h, sym);
|
||||
if (p == NULL && GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
(const char *)ll_bcsym, &h))
|
||||
p = (const char *)GetProcAddress(h, sym);
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,8 +215,7 @@ static void **ll_register(lua_State *L, const char *path)
|
||||
lua_pop(L, 1);
|
||||
plib = (void **)lua_newuserdata(L, sizeof(void *));
|
||||
*plib = NULL;
|
||||
luaL_getmetatable(L, "_LOADLIB");
|
||||
lua_setmetatable(L, -2);
|
||||
luaL_setmetatable(L, "_LOADLIB");
|
||||
lua_pushfstring(L, "LOADLIB: %s", path);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, LUA_REGISTRYINDEX);
|
||||
@@ -216,7 +237,12 @@ static const char *mksymname(lua_State *L, const char *modname,
|
||||
|
||||
static int ll_loadfunc(lua_State *L, const char *path, const char *name, int r)
|
||||
{
|
||||
void **reg = ll_register(L, path);
|
||||
void **reg;
|
||||
if (strlen(path) >= 4096) {
|
||||
lua_pushliteral(L, "path too long");
|
||||
return PACKAGE_ERR_LIB;
|
||||
}
|
||||
reg = ll_register(L, path);
|
||||
if (*reg == NULL) *reg = ll_load(L, path, (*name == '*'));
|
||||
if (*reg == NULL) {
|
||||
return PACKAGE_ERR_LIB; /* Unable to load library. */
|
||||
@@ -234,7 +260,7 @@ static int ll_loadfunc(lua_State *L, const char *path, const char *name, int r)
|
||||
const char *bcdata = ll_bcsym(*reg, mksymname(L, name, SYMPREFIX_BC));
|
||||
lua_pop(L, 1);
|
||||
if (bcdata) {
|
||||
if (luaL_loadbuffer(L, bcdata, LJ_MAX_BUF, name) != 0)
|
||||
if (luaL_loadbuffer(L, bcdata, ~(size_t)0, name) != 0)
|
||||
return PACKAGE_ERR_LOAD;
|
||||
return 0;
|
||||
}
|
||||
@@ -391,7 +417,7 @@ static int lj_cf_package_loader_preload(lua_State *L)
|
||||
if (lua_isnil(L, -1)) { /* Not found? */
|
||||
const char *bcname = mksymname(L, name, SYMPREFIX_BC);
|
||||
const char *bcdata = ll_bcsym(NULL, bcname);
|
||||
if (bcdata == NULL || luaL_loadbuffer(L, bcdata, LJ_MAX_BUF, name) != 0)
|
||||
if (bcdata == NULL || luaL_loadbuffer(L, bcdata, ~(size_t)0, name) != 0)
|
||||
lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
|
||||
}
|
||||
return 1;
|
||||
@@ -399,8 +425,7 @@ static int lj_cf_package_loader_preload(lua_State *L)
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static const int sentinel_ = 0;
|
||||
#define sentinel ((void *)&sentinel_)
|
||||
#define KEY_SENTINEL (U64x(80000000,00000000)|'s')
|
||||
|
||||
static int lj_cf_package_require(lua_State *L)
|
||||
{
|
||||
@@ -410,7 +435,7 @@ static int lj_cf_package_require(lua_State *L)
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
|
||||
lua_getfield(L, 2, name);
|
||||
if (lua_toboolean(L, -1)) { /* is it there? */
|
||||
if (lua_touserdata(L, -1) == sentinel) /* check loops */
|
||||
if ((L->top-1)->u64 == KEY_SENTINEL) /* check loops */
|
||||
luaL_error(L, "loop or previous error loading module " LUA_QS, name);
|
||||
return 1; /* package is already loaded */
|
||||
}
|
||||
@@ -433,14 +458,14 @@ static int lj_cf_package_require(lua_State *L)
|
||||
else
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pushlightuserdata(L, sentinel);
|
||||
(L->top++)->u64 = KEY_SENTINEL;
|
||||
lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
|
||||
lua_pushstring(L, name); /* pass name as argument to module */
|
||||
lua_call(L, 1, 1); /* run loaded module */
|
||||
if (!lua_isnil(L, -1)) /* non-nil return? */
|
||||
lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
|
||||
lua_getfield(L, 2, name);
|
||||
if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */
|
||||
if ((L->top-1)->u64 == KEY_SENTINEL) { /* module did not set a value? */
|
||||
lua_pushboolean(L, 1); /* use true as result */
|
||||
lua_pushvalue(L, -1); /* extra copy to be returned */
|
||||
lua_setfield(L, 2, name); /* _LOADED[name] = true */
|
||||
@@ -490,29 +515,19 @@ static void modinit(lua_State *L, const char *modname)
|
||||
static int lj_cf_package_module(lua_State *L)
|
||||
{
|
||||
const char *modname = luaL_checkstring(L, 1);
|
||||
int loaded = lua_gettop(L) + 1; /* index of _LOADED table */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
|
||||
lua_getfield(L, loaded, modname); /* get _LOADED[modname] */
|
||||
if (!lua_istable(L, -1)) { /* not found? */
|
||||
lua_pop(L, 1); /* remove previous result */
|
||||
/* try global variable (and create one if it does not exist) */
|
||||
if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
|
||||
lj_err_callerv(L, LJ_ERR_BADMODN, modname);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */
|
||||
}
|
||||
/* check whether table already has a _NAME field */
|
||||
int lastarg = (int)(L->top - L->base);
|
||||
luaL_pushmodule(L, modname, 1);
|
||||
lua_getfield(L, -1, "_NAME");
|
||||
if (!lua_isnil(L, -1)) { /* is table an initialized module? */
|
||||
if (!lua_isnil(L, -1)) { /* Module already initialized? */
|
||||
lua_pop(L, 1);
|
||||
} else { /* no; initialize it */
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
modinit(L, modname);
|
||||
}
|
||||
lua_pushvalue(L, -1);
|
||||
setfenv(L);
|
||||
dooptions(L, loaded - 1);
|
||||
return 0;
|
||||
dooptions(L, lastarg);
|
||||
return LJ_52;
|
||||
}
|
||||
|
||||
static int lj_cf_package_seeall(lua_State *L)
|
||||
@@ -583,13 +598,16 @@ LUALIB_API int luaopen_package(lua_State *L)
|
||||
lj_lib_pushcf(L, lj_cf_package_unloadlib, 1);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
luaL_register(L, LUA_LOADLIBNAME, package_lib);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_replace(L, LUA_ENVIRONINDEX);
|
||||
lua_copy(L, -1, LUA_ENVIRONINDEX);
|
||||
lua_createtable(L, sizeof(package_loaders)/sizeof(package_loaders[0])-1, 0);
|
||||
for (i = 0; package_loaders[i] != NULL; i++) {
|
||||
lj_lib_pushcf(L, package_loaders[i], 1);
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
#if LJ_52
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, "searchers");
|
||||
#endif
|
||||
lua_setfield(L, -2, "loaders");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
|
||||
noenv = lua_toboolean(L, -1);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** String library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
@@ -136,7 +136,7 @@ LJLIB_CF(string_dump)
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* macro to `unsign' a character */
|
||||
#define uchar(c) ((unsigned char)(c))
|
||||
#define uchar(c) ((unsigned char)(c))
|
||||
|
||||
#define CAP_UNFINISHED (-1)
|
||||
#define CAP_POSITION (-2)
|
||||
@@ -645,7 +645,7 @@ static GCstr *string_fmt_tostring(lua_State *L, int arg, int retry)
|
||||
{
|
||||
TValue *o = L->base+arg-1;
|
||||
cTValue *mo;
|
||||
lua_assert(o < L->top); /* Caller already checks for existence. */
|
||||
lj_assertL(o < L->top, "bad usage"); /* Caller already checks for existence. */
|
||||
if (LJ_LIKELY(tvisstr(o)))
|
||||
return strV(o);
|
||||
if (retry != 2 && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
|
||||
@@ -714,10 +714,10 @@ again:
|
||||
lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg));
|
||||
break;
|
||||
case STRFMT_PTR: /* No formatting. */
|
||||
lj_strfmt_putptr(sb, lj_obj_ptr(L->base+arg-1));
|
||||
lj_strfmt_putptr(sb, lj_obj_ptr(G(L), L->base+arg-1));
|
||||
break;
|
||||
default:
|
||||
lua_assert(0);
|
||||
lj_assertL(0, "bad string format type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -737,10 +737,6 @@ LUALIB_API int luaopen_string(lua_State *L)
|
||||
GCtab *mt;
|
||||
global_State *g;
|
||||
LJ_LIB_REG(L, LUA_STRLIBNAME, string);
|
||||
#if defined(LUA_COMPAT_GFIND) && !LJ_52
|
||||
lua_getfield(L, -1, "gmatch");
|
||||
lua_setfield(L, -2, "gfind");
|
||||
#endif
|
||||
mt = lj_tab_new(L, 0, 1);
|
||||
/* NOBARRIER: basemt is a GC root. */
|
||||
g = G(L);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Table library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
@@ -129,6 +129,26 @@ LJLIB_LUA(table_remove) /*
|
||||
end
|
||||
*/
|
||||
|
||||
LJLIB_LUA(table_move) /*
|
||||
function(a1, f, e, t, a2)
|
||||
CHECK_tab(a1)
|
||||
CHECK_int(f)
|
||||
CHECK_int(e)
|
||||
CHECK_int(t)
|
||||
if a2 == nil then a2 = a1 end
|
||||
CHECK_tab(a2)
|
||||
if e >= f then
|
||||
local d = t - f
|
||||
if t > e or t <= f or a2 ~= a1 then
|
||||
for i=f,e do a2[i+d] = a1[i] end
|
||||
else
|
||||
for i=e,f,-1 do a2[i+d] = a1[i] end
|
||||
end
|
||||
end
|
||||
return a2
|
||||
end
|
||||
*/
|
||||
|
||||
LJLIB_CF(table_concat) LJLIB_REC(.)
|
||||
{
|
||||
GCtab *t = lj_lib_checktab(L, 1);
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
# Valgrind suppression file for LuaJIT 2.0.
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Addr4
|
||||
fun:lj_str_cmp
|
||||
}
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Addr1
|
||||
fun:lj_str_cmp
|
||||
}
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Addr4
|
||||
fun:lj_str_new
|
||||
}
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Addr1
|
||||
fun:lj_str_new
|
||||
}
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Cond
|
||||
fun:lj_str_new
|
||||
}
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Addr4
|
||||
fun:lj_str_fastcmp
|
||||
}
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Addr1
|
||||
fun:lj_str_fastcmp
|
||||
}
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Cond
|
||||
fun:lj_str_fastcmp
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
**
|
||||
** This is a version (aka dlmalloc) of malloc/free/realloc written by
|
||||
** Doug Lea and released to the public domain, as explained at
|
||||
** http://creativecommons.org/licenses/publicdomain.
|
||||
** https://creativecommons.org/licenses/publicdomain.
|
||||
**
|
||||
** * Version pre-2.8.4 Wed Mar 29 19:46:29 2006 (dl at gee)
|
||||
**
|
||||
@@ -16,8 +16,8 @@
|
||||
** If you want to use dlmalloc in another project, you should get
|
||||
** the original from: ftp://gee.cs.oswego.edu/pub/misc/
|
||||
** For thread-safe derivatives, take a look at:
|
||||
** - ptmalloc: http://www.malloc.de/
|
||||
** - nedmalloc: http://www.nedprod.com/programs/portable/nedmalloc/
|
||||
** - ptmalloc: https://www.malloc.de/
|
||||
** - nedmalloc: https://www.nedprod.com/programs/portable/nedmalloc/
|
||||
*/
|
||||
|
||||
#define lj_alloc_c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "lj_def.h"
|
||||
#include "lj_arch.h"
|
||||
#include "lj_alloc.h"
|
||||
#include "lj_prng.h"
|
||||
|
||||
#ifndef LUAJIT_USE_SYSMALLOC
|
||||
|
||||
@@ -72,15 +73,58 @@
|
||||
|
||||
#define IS_DIRECT_BIT (SIZE_T_ONE)
|
||||
|
||||
|
||||
/* Determine system-specific block allocation method. */
|
||||
#if LJ_TARGET_WINDOWS
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#if LJ_64 && !LJ_GC64
|
||||
#define LJ_ALLOC_VIRTUALALLOC 1
|
||||
|
||||
#if LJ_64 && !LJ_GC64
|
||||
#define LJ_ALLOC_NTAVM 1
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <errno.h>
|
||||
/* If this include fails, then rebuild with: -DLUAJIT_USE_SYSMALLOC */
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define LJ_ALLOC_MMAP 1
|
||||
|
||||
#if LJ_64
|
||||
|
||||
#define LJ_ALLOC_MMAP_PROBE 1
|
||||
|
||||
#if LJ_GC64
|
||||
#define LJ_ALLOC_MBITS 47 /* 128 TB in LJ_GC64 mode. */
|
||||
#elif LJ_TARGET_X64 && LJ_HASJIT
|
||||
/* Due to limitations in the x64 compiler backend. */
|
||||
#define LJ_ALLOC_MBITS 31 /* 2 GB on x64 with !LJ_GC64. */
|
||||
#else
|
||||
#define LJ_ALLOC_MBITS 32 /* 4 GB on other archs with !LJ_GC64. */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if LJ_64 && !LJ_GC64 && defined(MAP_32BIT)
|
||||
#define LJ_ALLOC_MMAP32 1
|
||||
#endif
|
||||
|
||||
#if LJ_TARGET_LINUX
|
||||
#define LJ_ALLOC_MREMAP 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if LJ_ALLOC_VIRTUALALLOC
|
||||
|
||||
#if LJ_ALLOC_NTAVM
|
||||
/* Undocumented, but hey, that's what we all love so much about Windows. */
|
||||
typedef long (*PNTAVM)(HANDLE handle, void **addr, ULONG zbits,
|
||||
typedef long (*PNTAVM)(HANDLE handle, void **addr, ULONG_PTR zbits,
|
||||
size_t *size, ULONG alloctype, ULONG prot);
|
||||
static PNTAVM ntavm;
|
||||
|
||||
@@ -89,14 +133,15 @@ static PNTAVM ntavm;
|
||||
*/
|
||||
#define NTAVM_ZEROBITS 1
|
||||
|
||||
static void INIT_MMAP(void)
|
||||
static void init_mmap(void)
|
||||
{
|
||||
ntavm = (PNTAVM)GetProcAddress(GetModuleHandleA("ntdll.dll"),
|
||||
"NtAllocateVirtualMemory");
|
||||
}
|
||||
#define INIT_MMAP() init_mmap()
|
||||
|
||||
/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */
|
||||
static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
static void *mmap_plain(size_t size)
|
||||
{
|
||||
DWORD olderr = GetLastError();
|
||||
void *ptr = NULL;
|
||||
@@ -107,7 +152,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
}
|
||||
|
||||
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
|
||||
static LJ_AINLINE void *DIRECT_MMAP(size_t size)
|
||||
static void *direct_mmap(size_t size)
|
||||
{
|
||||
DWORD olderr = GetLastError();
|
||||
void *ptr = NULL;
|
||||
@@ -119,31 +164,32 @@ static LJ_AINLINE void *DIRECT_MMAP(size_t size)
|
||||
|
||||
#else
|
||||
|
||||
#define INIT_MMAP() ((void)0)
|
||||
|
||||
/* Win32 MMAP via VirtualAlloc */
|
||||
static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
static void *mmap_plain(size_t size)
|
||||
{
|
||||
DWORD olderr = GetLastError();
|
||||
void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
||||
void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
||||
SetLastError(olderr);
|
||||
return ptr ? ptr : MFAIL;
|
||||
}
|
||||
|
||||
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
|
||||
static LJ_AINLINE void *DIRECT_MMAP(size_t size)
|
||||
static void *direct_mmap(size_t size)
|
||||
{
|
||||
DWORD olderr = GetLastError();
|
||||
void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
|
||||
PAGE_READWRITE);
|
||||
void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
|
||||
PAGE_READWRITE);
|
||||
SetLastError(olderr);
|
||||
return ptr ? ptr : MFAIL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define CALL_MMAP(prng, size) mmap_plain(size)
|
||||
#define DIRECT_MMAP(prng, size) direct_mmap(size)
|
||||
|
||||
/* This function supports releasing coalesed segments */
|
||||
static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
|
||||
static int CALL_MUNMAP(void *ptr, size_t size)
|
||||
{
|
||||
DWORD olderr = GetLastError();
|
||||
MEMORY_BASIC_INFORMATION minfo;
|
||||
@@ -163,10 +209,7 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#elif LJ_ALLOC_MMAP
|
||||
|
||||
#define MMAP_PROT (PROT_READ|PROT_WRITE)
|
||||
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
|
||||
@@ -174,107 +217,134 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
|
||||
#endif
|
||||
#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
|
||||
|
||||
#if LJ_64 && !LJ_GC64
|
||||
/* 64 bit mode with 32 bit pointers needs special support for allocating
|
||||
** memory in the lower 2GB.
|
||||
*/
|
||||
#if LJ_ALLOC_MMAP_PROBE
|
||||
|
||||
#if defined(MAP_32BIT)
|
||||
|
||||
#if defined(__sun__)
|
||||
#define MMAP_REGION_START ((uintptr_t)0x1000)
|
||||
#ifdef MAP_TRYFIXED
|
||||
#define MMAP_FLAGS_PROBE (MMAP_FLAGS|MAP_TRYFIXED)
|
||||
#else
|
||||
/* Actually this only gives us max. 1GB in current Linux kernels. */
|
||||
#define MMAP_REGION_START ((uintptr_t)0)
|
||||
#define MMAP_FLAGS_PROBE MMAP_FLAGS
|
||||
#endif
|
||||
|
||||
static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
#define LJ_ALLOC_MMAP_PROBE_MAX 30
|
||||
#define LJ_ALLOC_MMAP_PROBE_LINEAR 5
|
||||
|
||||
#define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000)
|
||||
|
||||
static void *mmap_probe(PRNGState *rs, size_t size)
|
||||
{
|
||||
int olderr = errno;
|
||||
void *ptr = mmap((void *)MMAP_REGION_START, size, MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0);
|
||||
errno = olderr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#elif LJ_TARGET_OSX || LJ_TARGET_PS4 || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun__) || defined(__CYGWIN__)
|
||||
|
||||
/* OSX and FreeBSD mmap() use a naive first-fit linear search.
|
||||
** That's perfect for us. Except that -pagezero_size must be set for OSX,
|
||||
** otherwise the lower 4GB are blocked. And the 32GB RLIMIT_DATA needs
|
||||
** to be reduced to 250MB on FreeBSD.
|
||||
*/
|
||||
#if LJ_TARGET_OSX || defined(__DragonFly__)
|
||||
#define MMAP_REGION_START ((uintptr_t)0x10000)
|
||||
#elif LJ_TARGET_PS4
|
||||
#define MMAP_REGION_START ((uintptr_t)0x4000)
|
||||
#else
|
||||
#define MMAP_REGION_START ((uintptr_t)0x10000000)
|
||||
#endif
|
||||
#define MMAP_REGION_END ((uintptr_t)0x80000000)
|
||||
|
||||
#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
{
|
||||
int olderr = errno;
|
||||
/* Hint for next allocation. Doesn't need to be thread-safe. */
|
||||
static uintptr_t alloc_hint = MMAP_REGION_START;
|
||||
int retry = 0;
|
||||
#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
|
||||
static int rlimit_modified = 0;
|
||||
if (LJ_UNLIKELY(rlimit_modified == 0)) {
|
||||
struct rlimit rlim;
|
||||
rlim.rlim_cur = rlim.rlim_max = MMAP_REGION_START;
|
||||
setrlimit(RLIMIT_DATA, &rlim); /* Ignore result. May fail below. */
|
||||
rlimit_modified = 1;
|
||||
}
|
||||
#endif
|
||||
for (;;) {
|
||||
void *p = mmap((void *)alloc_hint, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
|
||||
if ((uintptr_t)p >= MMAP_REGION_START &&
|
||||
(uintptr_t)p + size < MMAP_REGION_END) {
|
||||
alloc_hint = (uintptr_t)p + size;
|
||||
static uintptr_t hint_addr = 0;
|
||||
int olderr = errno;
|
||||
int retry;
|
||||
for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) {
|
||||
void *p = mmap((void *)hint_addr, size, MMAP_PROT, MMAP_FLAGS_PROBE, -1, 0);
|
||||
uintptr_t addr = (uintptr_t)p;
|
||||
if ((addr >> LJ_ALLOC_MBITS) == 0 && addr >= LJ_ALLOC_MMAP_PROBE_LOWER &&
|
||||
((addr + size) >> LJ_ALLOC_MBITS) == 0) {
|
||||
/* We got a suitable address. Bump the hint address. */
|
||||
hint_addr = addr + size;
|
||||
errno = olderr;
|
||||
return p;
|
||||
}
|
||||
if (p != CMFAIL) munmap(p, size);
|
||||
#if defined(__sun__) || defined(__DragonFly__)
|
||||
alloc_hint += 0x1000000; /* Need near-exhaustive linear scan. */
|
||||
if (alloc_hint + size < MMAP_REGION_END) continue;
|
||||
#endif
|
||||
if (retry) break;
|
||||
retry = 1;
|
||||
alloc_hint = MMAP_REGION_START;
|
||||
if (p != MFAIL) {
|
||||
munmap(p, size);
|
||||
} else if (errno == ENOMEM) {
|
||||
return MFAIL;
|
||||
}
|
||||
if (hint_addr) {
|
||||
/* First, try linear probing. */
|
||||
if (retry < LJ_ALLOC_MMAP_PROBE_LINEAR) {
|
||||
hint_addr += 0x1000000;
|
||||
if (((hint_addr + size) >> LJ_ALLOC_MBITS) != 0)
|
||||
hint_addr = 0;
|
||||
continue;
|
||||
} else if (retry == LJ_ALLOC_MMAP_PROBE_LINEAR) {
|
||||
/* Next, try a no-hint probe to get back an ASLR address. */
|
||||
hint_addr = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Finally, try pseudo-random probing. */
|
||||
do {
|
||||
hint_addr = lj_prng_u64(rs) & (((uintptr_t)1<<LJ_ALLOC_MBITS)-LJ_PAGESIZE);
|
||||
} while (hint_addr < LJ_ALLOC_MMAP_PROBE_LOWER);
|
||||
}
|
||||
errno = olderr;
|
||||
return CMFAIL;
|
||||
return MFAIL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error "NYI: need an equivalent of MAP_32BIT for this 64 bit OS"
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if LJ_ALLOC_MMAP32
|
||||
|
||||
/* 32 bit mode and GC64 mode is easy. */
|
||||
static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
#if LJ_TARGET_SOLARIS
|
||||
#define LJ_ALLOC_MMAP32_START ((uintptr_t)0x1000)
|
||||
#else
|
||||
#define LJ_ALLOC_MMAP32_START ((uintptr_t)0)
|
||||
#endif
|
||||
|
||||
#if LJ_ALLOC_MMAP_PROBE
|
||||
static void *mmap_map32(PRNGState *rs, size_t size)
|
||||
#else
|
||||
static void *mmap_map32(size_t size)
|
||||
#endif
|
||||
{
|
||||
#if LJ_ALLOC_MMAP_PROBE
|
||||
static int fallback = 0;
|
||||
if (fallback)
|
||||
return mmap_probe(rs, size);
|
||||
#endif
|
||||
{
|
||||
int olderr = errno;
|
||||
void *ptr = mmap((void *)LJ_ALLOC_MMAP32_START, size, MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0);
|
||||
errno = olderr;
|
||||
/* This only allows 1GB on Linux. So fallback to probing to get 2GB. */
|
||||
#if LJ_ALLOC_MMAP_PROBE
|
||||
if (ptr == MFAIL) {
|
||||
fallback = 1;
|
||||
return mmap_probe(rs, size);
|
||||
}
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LJ_ALLOC_MMAP32
|
||||
#if LJ_ALLOC_MMAP_PROBE
|
||||
#define CALL_MMAP(prng, size) mmap_map32(prng, size)
|
||||
#else
|
||||
#define CALL_MMAP(prng, size) mmap_map32(size)
|
||||
#endif
|
||||
#elif LJ_ALLOC_MMAP_PROBE
|
||||
#define CALL_MMAP(prng, size) mmap_probe(prng, size)
|
||||
#else
|
||||
static void *mmap_plain(size_t size)
|
||||
{
|
||||
int olderr = errno;
|
||||
void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
|
||||
errno = olderr;
|
||||
return ptr;
|
||||
}
|
||||
#define CALL_MMAP(prng, size) mmap_plain(size)
|
||||
#endif
|
||||
|
||||
#if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
|
||||
|
||||
#include <sys/resource.h>
|
||||
|
||||
static void init_mmap(void)
|
||||
{
|
||||
struct rlimit rlim;
|
||||
rlim.rlim_cur = rlim.rlim_max = 0x10000;
|
||||
setrlimit(RLIMIT_DATA, &rlim); /* Ignore result. May fail later. */
|
||||
}
|
||||
#define INIT_MMAP() init_mmap()
|
||||
|
||||
#endif
|
||||
|
||||
#define INIT_MMAP() ((void)0)
|
||||
#define DIRECT_MMAP(s) CALL_MMAP(s)
|
||||
|
||||
static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
|
||||
static int CALL_MUNMAP(void *ptr, size_t size)
|
||||
{
|
||||
int olderr = errno;
|
||||
int ret = munmap(ptr, size);
|
||||
@@ -282,10 +352,9 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if LJ_TARGET_LINUX
|
||||
#if LJ_ALLOC_MREMAP
|
||||
/* Need to define _GNU_SOURCE to get the mremap prototype. */
|
||||
static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz,
|
||||
int flags)
|
||||
static void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, int flags)
|
||||
{
|
||||
int olderr = errno;
|
||||
ptr = mremap(ptr, osz, nsz, flags);
|
||||
@@ -305,6 +374,15 @@ static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz,
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef INIT_MMAP
|
||||
#define INIT_MMAP() ((void)0)
|
||||
#endif
|
||||
|
||||
#ifndef DIRECT_MMAP
|
||||
#define DIRECT_MMAP(prng, s) CALL_MMAP(prng, s)
|
||||
#endif
|
||||
|
||||
#ifndef CALL_MREMAP
|
||||
#define CALL_MREMAP(addr, osz, nsz, mv) ((void)osz, MFAIL)
|
||||
#endif
|
||||
@@ -461,6 +539,7 @@ struct malloc_state {
|
||||
mchunkptr smallbins[(NSMALLBINS+1)*2];
|
||||
tbinptr treebins[NTREEBINS];
|
||||
msegment seg;
|
||||
PRNGState *prng;
|
||||
};
|
||||
|
||||
typedef struct malloc_state *mstate;
|
||||
@@ -518,7 +597,7 @@ static int has_segment_link(mstate m, msegmentptr ss)
|
||||
noncontiguous segments are added.
|
||||
*/
|
||||
#define TOP_FOOT_SIZE\
|
||||
(align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
|
||||
(align_offset(TWO_SIZE_T_SIZES)+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
|
||||
|
||||
/* ---------------------------- Indexing Bins ---------------------------- */
|
||||
|
||||
@@ -743,11 +822,11 @@ static int has_segment_link(mstate m, msegmentptr ss)
|
||||
|
||||
/* ----------------------- Direct-mmapping chunks ----------------------- */
|
||||
|
||||
static void *direct_alloc(size_t nb)
|
||||
static void *direct_alloc(mstate m, size_t nb)
|
||||
{
|
||||
size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
|
||||
if (LJ_LIKELY(mmsize > nb)) { /* Check for wrap around 0 */
|
||||
char *mm = (char *)(DIRECT_MMAP(mmsize));
|
||||
char *mm = (char *)(DIRECT_MMAP(m->prng, mmsize));
|
||||
if (mm != CMFAIL) {
|
||||
size_t offset = align_offset(chunk2mem(mm));
|
||||
size_t psize = mmsize - offset - DIRECT_FOOT_PAD;
|
||||
@@ -759,6 +838,7 @@ static void *direct_alloc(size_t nb)
|
||||
return chunk2mem(p);
|
||||
}
|
||||
}
|
||||
UNUSED(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -907,7 +987,7 @@ static void *alloc_sys(mstate m, size_t nb)
|
||||
|
||||
/* Directly map large chunks */
|
||||
if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) {
|
||||
void *mem = direct_alloc(nb);
|
||||
void *mem = direct_alloc(m, nb);
|
||||
if (mem != 0)
|
||||
return mem;
|
||||
}
|
||||
@@ -916,7 +996,7 @@ static void *alloc_sys(mstate m, size_t nb)
|
||||
size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
|
||||
size_t rsize = granularity_align(req);
|
||||
if (LJ_LIKELY(rsize > nb)) { /* Fail if wraps around zero */
|
||||
char *mp = (char *)(CALL_MMAP(rsize));
|
||||
char *mp = (char *)(CALL_MMAP(m->prng, rsize));
|
||||
if (mp != CMFAIL) {
|
||||
tbase = mp;
|
||||
tsize = rsize;
|
||||
@@ -1143,12 +1223,13 @@ static void *tmalloc_small(mstate m, size_t nb)
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
void *lj_alloc_create(void)
|
||||
void *lj_alloc_create(PRNGState *rs)
|
||||
{
|
||||
size_t tsize = DEFAULT_GRANULARITY;
|
||||
char *tbase;
|
||||
INIT_MMAP();
|
||||
tbase = (char *)(CALL_MMAP(tsize));
|
||||
UNUSED(rs);
|
||||
tbase = (char *)(CALL_MMAP(rs, tsize));
|
||||
if (tbase != CMFAIL) {
|
||||
size_t msize = pad_request(sizeof(struct malloc_state));
|
||||
mchunkptr mn;
|
||||
@@ -1167,6 +1248,12 @@ void *lj_alloc_create(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void lj_alloc_setprng(void *msp, PRNGState *rs)
|
||||
{
|
||||
mstate ms = (mstate)msp;
|
||||
ms->prng = rs;
|
||||
}
|
||||
|
||||
void lj_alloc_destroy(void *msp)
|
||||
{
|
||||
mstate ms = (mstate)msp;
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
#include "lj_def.h"
|
||||
|
||||
#ifndef LUAJIT_USE_SYSMALLOC
|
||||
LJ_FUNC void *lj_alloc_create(void);
|
||||
LJ_FUNC void *lj_alloc_create(PRNGState *rs);
|
||||
LJ_FUNC void lj_alloc_setprng(void *msp, PRNGState *rs);
|
||||
LJ_FUNC void lj_alloc_destroy(void *msp);
|
||||
LJ_FUNC void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize);
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Public Lua/C API.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
@@ -28,8 +28,8 @@
|
||||
|
||||
/* -- Common helper functions --------------------------------------------- */
|
||||
|
||||
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
|
||||
#define api_checkvalidindex(L, i) api_check(L, (i) != niltv(L))
|
||||
#define lj_checkapi_slot(idx) \
|
||||
lj_checkapi((idx) <= (L->top - L->base), "stack slot %d out of range", (idx))
|
||||
|
||||
static TValue *index2adr(lua_State *L, int idx)
|
||||
{
|
||||
@@ -37,7 +37,8 @@ static TValue *index2adr(lua_State *L, int idx)
|
||||
TValue *o = L->base + (idx - 1);
|
||||
return o < L->top ? o : niltv(L);
|
||||
} else if (idx > LUA_REGISTRYINDEX) {
|
||||
api_check(L, idx != 0 && -idx <= L->top - L->base);
|
||||
lj_checkapi(idx != 0 && -idx <= L->top - L->base,
|
||||
"bad stack slot %d", idx);
|
||||
return L->top + idx;
|
||||
} else if (idx == LUA_GLOBALSINDEX) {
|
||||
TValue *o = &G(L)->tmptv;
|
||||
@@ -47,7 +48,8 @@ static TValue *index2adr(lua_State *L, int idx)
|
||||
return registry(L);
|
||||
} else {
|
||||
GCfunc *fn = curr_func(L);
|
||||
api_check(L, fn->c.gct == ~LJ_TFUNC && !isluafunc(fn));
|
||||
lj_checkapi(fn->c.gct == ~LJ_TFUNC && !isluafunc(fn),
|
||||
"calling frame is not a C function");
|
||||
if (idx == LUA_ENVIRONINDEX) {
|
||||
TValue *o = &G(L)->tmptv;
|
||||
settabV(L, o, tabref(fn->c.env));
|
||||
@@ -59,13 +61,27 @@ static TValue *index2adr(lua_State *L, int idx)
|
||||
}
|
||||
}
|
||||
|
||||
static TValue *stkindex2adr(lua_State *L, int idx)
|
||||
static LJ_AINLINE TValue *index2adr_check(lua_State *L, int idx)
|
||||
{
|
||||
TValue *o = index2adr(L, idx);
|
||||
lj_checkapi(o != niltv(L), "invalid stack slot %d", idx);
|
||||
return o;
|
||||
}
|
||||
|
||||
static TValue *index2adr_stack(lua_State *L, int idx)
|
||||
{
|
||||
if (idx > 0) {
|
||||
TValue *o = L->base + (idx - 1);
|
||||
if (o < L->top) {
|
||||
return o;
|
||||
} else {
|
||||
lj_checkapi(0, "invalid stack slot %d", idx);
|
||||
return niltv(L);
|
||||
}
|
||||
return o < L->top ? o : niltv(L);
|
||||
} else {
|
||||
api_check(L, idx != 0 && -idx <= L->top - L->base);
|
||||
lj_checkapi(idx != 0 && -idx <= L->top - L->base,
|
||||
"invalid stack slot %d", idx);
|
||||
return L->top + idx;
|
||||
}
|
||||
}
|
||||
@@ -99,17 +115,24 @@ LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
|
||||
lj_err_callerv(L, LJ_ERR_STKOVM, msg);
|
||||
}
|
||||
|
||||
LUA_API void lua_xmove(lua_State *from, lua_State *to, int n)
|
||||
LUA_API void lua_xmove(lua_State *L, lua_State *to, int n)
|
||||
{
|
||||
TValue *f, *t;
|
||||
if (from == to) return;
|
||||
api_checknelems(from, n);
|
||||
api_check(from, G(from) == G(to));
|
||||
if (L == to) return;
|
||||
lj_checkapi_slot(n);
|
||||
lj_checkapi(G(L) == G(to), "move across global states");
|
||||
lj_state_checkstack(to, (MSize)n);
|
||||
f = from->top;
|
||||
f = L->top;
|
||||
t = to->top = to->top + n;
|
||||
while (--n >= 0) copyTV(to, --t, --f);
|
||||
from->top = f;
|
||||
L->top = f;
|
||||
}
|
||||
|
||||
LUA_API const lua_Number *lua_version(lua_State *L)
|
||||
{
|
||||
static const lua_Number version = LUA_VERSION_NUM;
|
||||
UNUSED(L);
|
||||
return &version;
|
||||
}
|
||||
|
||||
/* -- Stack manipulation -------------------------------------------------- */
|
||||
@@ -122,7 +145,7 @@ LUA_API int lua_gettop(lua_State *L)
|
||||
LUA_API void lua_settop(lua_State *L, int idx)
|
||||
{
|
||||
if (idx >= 0) {
|
||||
api_check(L, idx <= tvref(L->maxstack) - L->base);
|
||||
lj_checkapi(idx <= tvref(L->maxstack) - L->base, "bad stack slot %d", idx);
|
||||
if (L->base + idx > L->top) {
|
||||
if (L->base + idx >= tvref(L->maxstack))
|
||||
lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base));
|
||||
@@ -131,51 +154,58 @@ LUA_API void lua_settop(lua_State *L, int idx)
|
||||
L->top = L->base + idx;
|
||||
}
|
||||
} else {
|
||||
api_check(L, -(idx+1) <= (L->top - L->base));
|
||||
lj_checkapi(-(idx+1) <= (L->top - L->base), "bad stack slot %d", idx);
|
||||
L->top += idx+1; /* Shrinks top (idx < 0). */
|
||||
}
|
||||
}
|
||||
|
||||
LUA_API void lua_remove(lua_State *L, int idx)
|
||||
{
|
||||
TValue *p = stkindex2adr(L, idx);
|
||||
api_checkvalidindex(L, p);
|
||||
TValue *p = index2adr_stack(L, idx);
|
||||
while (++p < L->top) copyTV(L, p-1, p);
|
||||
L->top--;
|
||||
}
|
||||
|
||||
LUA_API void lua_insert(lua_State *L, int idx)
|
||||
{
|
||||
TValue *q, *p = stkindex2adr(L, idx);
|
||||
api_checkvalidindex(L, p);
|
||||
TValue *q, *p = index2adr_stack(L, idx);
|
||||
for (q = L->top; q > p; q--) copyTV(L, q, q-1);
|
||||
copyTV(L, p, L->top);
|
||||
}
|
||||
|
||||
LUA_API void lua_replace(lua_State *L, int idx)
|
||||
static void copy_slot(lua_State *L, TValue *f, int idx)
|
||||
{
|
||||
api_checknelems(L, 1);
|
||||
if (idx == LUA_GLOBALSINDEX) {
|
||||
api_check(L, tvistab(L->top-1));
|
||||
lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
|
||||
/* NOBARRIER: A thread (i.e. L) is never black. */
|
||||
setgcref(L->env, obj2gco(tabV(L->top-1)));
|
||||
setgcref(L->env, obj2gco(tabV(f)));
|
||||
} else if (idx == LUA_ENVIRONINDEX) {
|
||||
GCfunc *fn = curr_func(L);
|
||||
if (fn->c.gct != ~LJ_TFUNC)
|
||||
lj_err_msg(L, LJ_ERR_NOENV);
|
||||
api_check(L, tvistab(L->top-1));
|
||||
setgcref(fn->c.env, obj2gco(tabV(L->top-1)));
|
||||
lj_gc_barrier(L, fn, L->top-1);
|
||||
lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
|
||||
setgcref(fn->c.env, obj2gco(tabV(f)));
|
||||
lj_gc_barrier(L, fn, f);
|
||||
} else {
|
||||
TValue *o = index2adr(L, idx);
|
||||
api_checkvalidindex(L, o);
|
||||
copyTV(L, o, L->top-1);
|
||||
TValue *o = index2adr_check(L, idx);
|
||||
copyTV(L, o, f);
|
||||
if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */
|
||||
lj_gc_barrier(L, curr_func(L), L->top-1);
|
||||
lj_gc_barrier(L, curr_func(L), f);
|
||||
}
|
||||
}
|
||||
|
||||
LUA_API void lua_replace(lua_State *L, int idx)
|
||||
{
|
||||
lj_checkapi_slot(1);
|
||||
copy_slot(L, L->top - 1, idx);
|
||||
L->top--;
|
||||
}
|
||||
|
||||
LUA_API void lua_copy(lua_State *L, int fromidx, int toidx)
|
||||
{
|
||||
copy_slot(L, index2adr(L, fromidx), toidx);
|
||||
}
|
||||
|
||||
LUA_API void lua_pushvalue(lua_State *L, int idx)
|
||||
{
|
||||
copyTV(L, L->top, index2adr(L, idx));
|
||||
@@ -202,7 +232,7 @@ LUA_API int lua_type(lua_State *L, int idx)
|
||||
#else
|
||||
int tt = (int)(((t < 8 ? 0x98042110u : 0x75a06u) >> 4*(t&7)) & 15u);
|
||||
#endif
|
||||
lua_assert(tt != LUA_TNIL || tvisnil(o));
|
||||
lj_assertL(tt != LUA_TNIL || tvisnil(o), "bad tag conversion");
|
||||
return tt;
|
||||
}
|
||||
}
|
||||
@@ -325,6 +355,22 @@ LUA_API lua_Number lua_tonumber(lua_State *L, int idx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUA_API lua_Number lua_tonumberx(lua_State *L, int idx, int *ok)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
TValue tmp;
|
||||
if (LJ_LIKELY(tvisnumber(o))) {
|
||||
if (ok) *ok = 1;
|
||||
return numberVnum(o);
|
||||
} else if (tvisstr(o) && lj_strscan_num(strV(o), &tmp)) {
|
||||
if (ok) *ok = 1;
|
||||
return numV(&tmp);
|
||||
} else {
|
||||
if (ok) *ok = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
@@ -362,7 +408,7 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
|
||||
if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp)))
|
||||
return 0;
|
||||
if (tvisint(&tmp))
|
||||
return (lua_Integer)intV(&tmp);
|
||||
return intV(&tmp);
|
||||
n = numV(&tmp);
|
||||
}
|
||||
#if LJ_64
|
||||
@@ -372,6 +418,35 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
|
||||
#endif
|
||||
}
|
||||
|
||||
LUA_API lua_Integer lua_tointegerx(lua_State *L, int idx, int *ok)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
TValue tmp;
|
||||
lua_Number n;
|
||||
if (LJ_LIKELY(tvisint(o))) {
|
||||
if (ok) *ok = 1;
|
||||
return intV(o);
|
||||
} else if (LJ_LIKELY(tvisnum(o))) {
|
||||
n = numV(o);
|
||||
} else {
|
||||
if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) {
|
||||
if (ok) *ok = 0;
|
||||
return 0;
|
||||
}
|
||||
if (tvisint(&tmp)) {
|
||||
if (ok) *ok = 1;
|
||||
return intV(&tmp);
|
||||
}
|
||||
n = numV(&tmp);
|
||||
}
|
||||
if (ok) *ok = 1;
|
||||
#if LJ_64
|
||||
return (lua_Integer)n;
|
||||
#else
|
||||
return lj_num2int(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
@@ -533,7 +608,7 @@ LUA_API void *lua_touserdata(lua_State *L, int idx)
|
||||
if (tvisudata(o))
|
||||
return uddata(udataV(o));
|
||||
else if (tvislightud(o))
|
||||
return lightudV(o);
|
||||
return lightudV(G(L), o);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@@ -546,7 +621,7 @@ LUA_API lua_State *lua_tothread(lua_State *L, int idx)
|
||||
|
||||
LUA_API const void *lua_topointer(lua_State *L, int idx)
|
||||
{
|
||||
return lj_obj_ptr(index2adr(L, idx));
|
||||
return lj_obj_ptr(G(L), index2adr(L, idx));
|
||||
}
|
||||
|
||||
/* -- Stack setters (object creation) ------------------------------------- */
|
||||
@@ -615,14 +690,14 @@ LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction f, int n)
|
||||
{
|
||||
GCfunc *fn;
|
||||
lj_gc_check(L);
|
||||
api_checknelems(L, n);
|
||||
lj_checkapi_slot(n);
|
||||
fn = lj_func_newC(L, (MSize)n, getcurrenv(L));
|
||||
fn->c.f = f;
|
||||
L->top -= n;
|
||||
while (n--)
|
||||
copyTV(L, &fn->c.upvalue[n], L->top+n);
|
||||
setfuncV(L, L->top, fn);
|
||||
lua_assert(iswhite(obj2gco(fn)));
|
||||
lj_assertL(iswhite(obj2gco(fn)), "new GC object is not white");
|
||||
incr_top(L);
|
||||
}
|
||||
|
||||
@@ -632,9 +707,38 @@ LUA_API void lua_pushboolean(lua_State *L, int b)
|
||||
incr_top(L);
|
||||
}
|
||||
|
||||
#if LJ_64
|
||||
static void *lightud_intern(lua_State *L, void *p)
|
||||
{
|
||||
global_State *g = G(L);
|
||||
uint64_t u = (uint64_t)p;
|
||||
uint32_t up = lightudup(u);
|
||||
uint32_t *segmap = mref(g->gc.lightudseg, uint32_t);
|
||||
MSize segnum = g->gc.lightudnum;
|
||||
if (segmap) {
|
||||
MSize seg;
|
||||
for (seg = 0; seg <= segnum; seg++)
|
||||
if (segmap[seg] == up) /* Fast path. */
|
||||
return (void *)(((uint64_t)seg << LJ_LIGHTUD_BITS_LO) | lightudlo(u));
|
||||
segnum++;
|
||||
}
|
||||
if (!((segnum-1) & segnum) && segnum != 1) {
|
||||
if (segnum >= (1 << LJ_LIGHTUD_BITS_SEG)) lj_err_msg(L, LJ_ERR_BADLU);
|
||||
lj_mem_reallocvec(L, segmap, segnum, segnum ? 2*segnum : 2u, uint32_t);
|
||||
setmref(g->gc.lightudseg, segmap);
|
||||
}
|
||||
g->gc.lightudnum = segnum;
|
||||
segmap[segnum] = up;
|
||||
return (void *)(((uint64_t)segnum << LJ_LIGHTUD_BITS_LO) | lightudlo(u));
|
||||
}
|
||||
#endif
|
||||
|
||||
LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
|
||||
{
|
||||
setlightudV(L->top, checklightudptr(L, p));
|
||||
#if LJ_64
|
||||
p = lightud_intern(L, p);
|
||||
#endif
|
||||
setrawlightudV(L->top, p);
|
||||
incr_top(L);
|
||||
}
|
||||
|
||||
@@ -692,7 +796,7 @@ LUA_API void *lua_newuserdata(lua_State *L, size_t size)
|
||||
|
||||
LUA_API void lua_concat(lua_State *L, int n)
|
||||
{
|
||||
api_checknelems(L, n);
|
||||
lj_checkapi_slot(n);
|
||||
if (n >= 2) {
|
||||
n--;
|
||||
do {
|
||||
@@ -718,9 +822,8 @@ LUA_API void lua_concat(lua_State *L, int n)
|
||||
|
||||
LUA_API void lua_gettable(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *v, *t = index2adr(L, idx);
|
||||
api_checkvalidindex(L, t);
|
||||
v = lj_meta_tget(L, t, L->top-1);
|
||||
cTValue *t = index2adr_check(L, idx);
|
||||
cTValue *v = lj_meta_tget(L, t, L->top-1);
|
||||
if (v == NULL) {
|
||||
L->top += 2;
|
||||
lj_vm_call(L, L->top-2, 1+1);
|
||||
@@ -732,9 +835,8 @@ LUA_API void lua_gettable(lua_State *L, int idx)
|
||||
|
||||
LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
|
||||
{
|
||||
cTValue *v, *t = index2adr(L, idx);
|
||||
cTValue *v, *t = index2adr_check(L, idx);
|
||||
TValue key;
|
||||
api_checkvalidindex(L, t);
|
||||
setstrV(L, &key, lj_str_newz(L, k));
|
||||
v = lj_meta_tget(L, t, &key);
|
||||
if (v == NULL) {
|
||||
@@ -750,14 +852,14 @@ LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
|
||||
LUA_API void lua_rawget(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *t = index2adr(L, idx);
|
||||
api_check(L, tvistab(t));
|
||||
lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
|
||||
copyTV(L, L->top-1, lj_tab_get(L, tabV(t), L->top-1));
|
||||
}
|
||||
|
||||
LUA_API void lua_rawgeti(lua_State *L, int idx, int n)
|
||||
{
|
||||
cTValue *v, *t = index2adr(L, idx);
|
||||
api_check(L, tvistab(t));
|
||||
lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
|
||||
v = lj_tab_getint(tabV(t), n);
|
||||
if (v) {
|
||||
copyTV(L, L->top, v);
|
||||
@@ -799,8 +901,7 @@ LUALIB_API int luaL_getmetafield(lua_State *L, int idx, const char *field)
|
||||
|
||||
LUA_API void lua_getfenv(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
api_checkvalidindex(L, o);
|
||||
cTValue *o = index2adr_check(L, idx);
|
||||
if (tvisfunc(o)) {
|
||||
settabV(L, L->top, tabref(funcV(o)->c.env));
|
||||
} else if (tvisudata(o)) {
|
||||
@@ -817,7 +918,7 @@ LUA_API int lua_next(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *t = index2adr(L, idx);
|
||||
int more;
|
||||
api_check(L, tvistab(t));
|
||||
lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
|
||||
more = lj_tab_next(L, tabV(t), L->top-1);
|
||||
if (more) {
|
||||
incr_top(L); /* Return new key and value slot. */
|
||||
@@ -830,7 +931,8 @@ LUA_API int lua_next(lua_State *L, int idx)
|
||||
LUA_API const char *lua_getupvalue(lua_State *L, int idx, int n)
|
||||
{
|
||||
TValue *val;
|
||||
const char *name = lj_debug_uvnamev(index2adr(L, idx), (uint32_t)(n-1), &val);
|
||||
GCobj *o;
|
||||
const char *name = lj_debug_uvnamev(index2adr(L, idx), (uint32_t)(n-1), &val, &o);
|
||||
if (name) {
|
||||
copyTV(L, L->top, val);
|
||||
incr_top(L);
|
||||
@@ -842,7 +944,7 @@ LUA_API void *lua_upvalueid(lua_State *L, int idx, int n)
|
||||
{
|
||||
GCfunc *fn = funcV(index2adr(L, idx));
|
||||
n--;
|
||||
api_check(L, (uint32_t)n < fn->l.nupvalues);
|
||||
lj_checkapi((uint32_t)n < fn->l.nupvalues, "bad upvalue %d", n);
|
||||
return isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
|
||||
(void *)&fn->c.upvalue[n];
|
||||
}
|
||||
@@ -852,13 +954,15 @@ LUA_API void lua_upvaluejoin(lua_State *L, int idx1, int n1, int idx2, int n2)
|
||||
GCfunc *fn1 = funcV(index2adr(L, idx1));
|
||||
GCfunc *fn2 = funcV(index2adr(L, idx2));
|
||||
n1--; n2--;
|
||||
api_check(L, isluafunc(fn1) && (uint32_t)n1 < fn1->l.nupvalues);
|
||||
api_check(L, isluafunc(fn2) && (uint32_t)n2 < fn2->l.nupvalues);
|
||||
lj_checkapi(isluafunc(fn1), "stack slot %d is not a Lua function", idx1);
|
||||
lj_checkapi(isluafunc(fn2), "stack slot %d is not a Lua function", idx2);
|
||||
lj_checkapi((uint32_t)n1 < fn1->l.nupvalues, "bad upvalue %d", n1+1);
|
||||
lj_checkapi((uint32_t)n2 < fn2->l.nupvalues, "bad upvalue %d", n2+1);
|
||||
setgcrefr(fn1->l.uvptr[n1], fn2->l.uvptr[n2]);
|
||||
lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1]));
|
||||
}
|
||||
|
||||
LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
|
||||
LUALIB_API void *luaL_testudata(lua_State *L, int idx, const char *tname)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
if (tvisudata(o)) {
|
||||
@@ -867,8 +971,14 @@ LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
|
||||
if (tv && tvistab(tv) && tabV(tv) == tabref(ud->metatable))
|
||||
return uddata(ud);
|
||||
}
|
||||
lj_err_argtype(L, idx, tname);
|
||||
return NULL; /* unreachable */
|
||||
return NULL; /* value is not a userdata with a metatable */
|
||||
}
|
||||
|
||||
LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
|
||||
{
|
||||
void *p = luaL_testudata(L, idx, tname);
|
||||
if (!p) lj_err_argtype(L, idx, tname);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* -- Object setters ------------------------------------------------------ */
|
||||
@@ -876,9 +986,8 @@ LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
|
||||
LUA_API void lua_settable(lua_State *L, int idx)
|
||||
{
|
||||
TValue *o;
|
||||
cTValue *t = index2adr(L, idx);
|
||||
api_checknelems(L, 2);
|
||||
api_checkvalidindex(L, t);
|
||||
cTValue *t = index2adr_check(L, idx);
|
||||
lj_checkapi_slot(2);
|
||||
o = lj_meta_tset(L, t, L->top-2);
|
||||
if (o) {
|
||||
/* NOBARRIER: lj_meta_tset ensures the table is not black. */
|
||||
@@ -897,9 +1006,8 @@ LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
|
||||
{
|
||||
TValue *o;
|
||||
TValue key;
|
||||
cTValue *t = index2adr(L, idx);
|
||||
api_checknelems(L, 1);
|
||||
api_checkvalidindex(L, t);
|
||||
cTValue *t = index2adr_check(L, idx);
|
||||
lj_checkapi_slot(1);
|
||||
setstrV(L, &key, lj_str_newz(L, k));
|
||||
o = lj_meta_tset(L, t, &key);
|
||||
if (o) {
|
||||
@@ -918,7 +1026,7 @@ LUA_API void lua_rawset(lua_State *L, int idx)
|
||||
{
|
||||
GCtab *t = tabV(index2adr(L, idx));
|
||||
TValue *dst, *key;
|
||||
api_checknelems(L, 2);
|
||||
lj_checkapi_slot(2);
|
||||
key = L->top-2;
|
||||
dst = lj_tab_set(L, t, key);
|
||||
copyTV(L, dst, key+1);
|
||||
@@ -930,7 +1038,7 @@ LUA_API void lua_rawseti(lua_State *L, int idx, int n)
|
||||
{
|
||||
GCtab *t = tabV(index2adr(L, idx));
|
||||
TValue *dst, *src;
|
||||
api_checknelems(L, 1);
|
||||
lj_checkapi_slot(1);
|
||||
dst = lj_tab_setint(L, t, n);
|
||||
src = L->top-1;
|
||||
copyTV(L, dst, src);
|
||||
@@ -942,13 +1050,12 @@ LUA_API int lua_setmetatable(lua_State *L, int idx)
|
||||
{
|
||||
global_State *g;
|
||||
GCtab *mt;
|
||||
cTValue *o = index2adr(L, idx);
|
||||
api_checknelems(L, 1);
|
||||
api_checkvalidindex(L, o);
|
||||
cTValue *o = index2adr_check(L, idx);
|
||||
lj_checkapi_slot(1);
|
||||
if (tvisnil(L->top-1)) {
|
||||
mt = NULL;
|
||||
} else {
|
||||
api_check(L, tvistab(L->top-1));
|
||||
lj_checkapi(tvistab(L->top-1), "top stack slot is not a table");
|
||||
mt = tabV(L->top-1);
|
||||
}
|
||||
g = G(L);
|
||||
@@ -977,13 +1084,18 @@ LUA_API int lua_setmetatable(lua_State *L, int idx)
|
||||
return 1;
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
|
||||
{
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, tname);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
LUA_API int lua_setfenv(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
cTValue *o = index2adr_check(L, idx);
|
||||
GCtab *t;
|
||||
api_checknelems(L, 1);
|
||||
api_checkvalidindex(L, o);
|
||||
api_check(L, tvistab(L->top-1));
|
||||
lj_checkapi_slot(1);
|
||||
lj_checkapi(tvistab(L->top-1), "top stack slot is not a table");
|
||||
t = tabV(L->top-1);
|
||||
if (tvisfunc(o)) {
|
||||
setgcref(funcV(o)->c.env, obj2gco(t));
|
||||
@@ -1004,13 +1116,14 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n)
|
||||
{
|
||||
cTValue *f = index2adr(L, idx);
|
||||
TValue *val;
|
||||
GCobj *o;
|
||||
const char *name;
|
||||
api_checknelems(L, 1);
|
||||
name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val);
|
||||
lj_checkapi_slot(1);
|
||||
name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val, &o);
|
||||
if (name) {
|
||||
L->top--;
|
||||
copyTV(L, val, L->top);
|
||||
lj_gc_barrier(L, funcV(f), L->top);
|
||||
lj_gc_barrier(L, o, L->top);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
@@ -1032,8 +1145,9 @@ static TValue *api_call_base(lua_State *L, int nargs)
|
||||
|
||||
LUA_API void lua_call(lua_State *L, int nargs, int nresults)
|
||||
{
|
||||
api_check(L, L->status == 0 || L->status == LUA_ERRERR);
|
||||
api_checknelems(L, nargs+1);
|
||||
lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
|
||||
"thread called in wrong state %d", L->status);
|
||||
lj_checkapi_slot(nargs+1);
|
||||
lj_vm_call(L, api_call_base(L, nargs), nresults+1);
|
||||
}
|
||||
|
||||
@@ -1043,13 +1157,13 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
|
||||
uint8_t oldh = hook_save(g);
|
||||
ptrdiff_t ef;
|
||||
int status;
|
||||
api_check(L, L->status == 0 || L->status == LUA_ERRERR);
|
||||
api_checknelems(L, nargs+1);
|
||||
lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
|
||||
"thread called in wrong state %d", L->status);
|
||||
lj_checkapi_slot(nargs+1);
|
||||
if (errfunc == 0) {
|
||||
ef = 0;
|
||||
} else {
|
||||
cTValue *o = stkindex2adr(L, errfunc);
|
||||
api_checkvalidindex(L, o);
|
||||
cTValue *o = index2adr_stack(L, errfunc);
|
||||
ef = savestack(L, o);
|
||||
}
|
||||
status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef);
|
||||
@@ -1064,7 +1178,10 @@ static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
|
||||
fn->c.f = func;
|
||||
setfuncV(L, top++, fn);
|
||||
if (LJ_FR2) setnilV(top++);
|
||||
setlightudV(top++, checklightudptr(L, ud));
|
||||
#if LJ_64
|
||||
ud = lightud_intern(L, ud);
|
||||
#endif
|
||||
setrawlightudV(top++, ud);
|
||||
cframe_nres(L->cframe) = 1+0; /* Zero results. */
|
||||
L->top = top;
|
||||
return top-1; /* Now call the newly allocated C function. */
|
||||
@@ -1075,7 +1192,8 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
|
||||
global_State *g = G(L);
|
||||
uint8_t oldh = hook_save(g);
|
||||
int status;
|
||||
api_check(L, L->status == 0 || L->status == LUA_ERRERR);
|
||||
lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
|
||||
"thread called in wrong state %d", L->status);
|
||||
status = lj_vm_cpcall(L, func, ud, cpcall);
|
||||
if (status) hook_restore(g, oldh);
|
||||
return status;
|
||||
@@ -1096,6 +1214,11 @@ LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field)
|
||||
|
||||
/* -- Coroutine yield and resume ------------------------------------------ */
|
||||
|
||||
LUA_API int lua_isyieldable(lua_State *L)
|
||||
{
|
||||
return cframe_canyield(L->cframe);
|
||||
}
|
||||
|
||||
LUA_API int lua_yield(lua_State *L, int nresults)
|
||||
{
|
||||
void *cf = L->cframe;
|
||||
@@ -1119,11 +1242,12 @@ LUA_API int lua_yield(lua_State *L, int nresults)
|
||||
setcont(top, lj_cont_hook);
|
||||
if (LJ_FR2) top++;
|
||||
setframe_pc(top, cframe_pc(cf)-1);
|
||||
if (LJ_FR2) top++;
|
||||
top++;
|
||||
setframe_gc(top, obj2gco(L), LJ_TTHREAD);
|
||||
if (LJ_FR2) top++;
|
||||
setframe_ftsz(top, ((char *)(top+1)-(char *)L->base)+FRAME_CONT);
|
||||
L->top = L->base = top+1;
|
||||
#if LJ_TARGET_X64
|
||||
#if ((defined(__GNUC__) || defined(__clang__)) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND) || LJ_TARGET_WINDOWS
|
||||
lj_err_throw(L, LUA_YIELD);
|
||||
#else
|
||||
L->cframe = NULL;
|
||||
@@ -1140,7 +1264,7 @@ LUA_API int lua_resume(lua_State *L, int nargs)
|
||||
{
|
||||
if (L->cframe == NULL && L->status <= LUA_YIELD)
|
||||
return lj_vm_resume(L,
|
||||
L->status == 0 ? api_call_base(L, nargs) : L->top - nargs,
|
||||
L->status == LUA_OK ? api_call_base(L, nargs) : L->top - nargs,
|
||||
0, 0);
|
||||
L->top = L->base;
|
||||
setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Target architecture selection.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_ARCH_H
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
/* -- Target definitions -------------------------------------------------- */
|
||||
|
||||
/* Target endianess. */
|
||||
#define LUAJIT_LE 0
|
||||
#define LUAJIT_BE 1
|
||||
@@ -25,6 +27,10 @@
|
||||
#define LUAJIT_ARCH_ppc 5
|
||||
#define LUAJIT_ARCH_MIPS 6
|
||||
#define LUAJIT_ARCH_mips 6
|
||||
#define LUAJIT_ARCH_MIPS32 6
|
||||
#define LUAJIT_ARCH_mips32 6
|
||||
#define LUAJIT_ARCH_MIPS64 7
|
||||
#define LUAJIT_ARCH_mips64 7
|
||||
|
||||
/* Target OS. */
|
||||
#define LUAJIT_OS_OTHER 0
|
||||
@@ -34,6 +40,14 @@
|
||||
#define LUAJIT_OS_BSD 4
|
||||
#define LUAJIT_OS_POSIX 5
|
||||
|
||||
/* Number mode. */
|
||||
#define LJ_NUMMODE_SINGLE 0 /* Single-number mode only. */
|
||||
#define LJ_NUMMODE_SINGLE_DUAL 1 /* Default to single-number mode. */
|
||||
#define LJ_NUMMODE_DUAL 2 /* Dual-number mode only. */
|
||||
#define LJ_NUMMODE_DUAL_SINGLE 3 /* Default to dual-number mode. */
|
||||
|
||||
/* -- Target detection ---------------------------------------------------- */
|
||||
|
||||
/* Select native target if no target defined. */
|
||||
#ifndef LUAJIT_TARGET
|
||||
|
||||
@@ -47,8 +61,10 @@
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_ARM64
|
||||
#elif defined(__ppc__) || defined(__ppc) || defined(__PPC__) || defined(__PPC) || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) || defined(__POWERPC) || defined(_M_PPC)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_PPC
|
||||
#elif defined(__mips64__) || defined(__mips64) || defined(__MIPS64__) || defined(__MIPS64)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_MIPS64
|
||||
#elif defined(__mips__) || defined(__mips) || defined(__MIPS__) || defined(__MIPS)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_MIPS
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_MIPS32
|
||||
#else
|
||||
#error "No support for this architecture (yet)"
|
||||
#endif
|
||||
@@ -63,12 +79,19 @@
|
||||
#elif defined(__linux__)
|
||||
#define LUAJIT_OS LUAJIT_OS_LINUX
|
||||
#elif defined(__MACH__) && defined(__APPLE__)
|
||||
#include "TargetConditionals.h"
|
||||
#define LUAJIT_OS LUAJIT_OS_OSX
|
||||
#elif (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__DragonFly__)) && !defined(__ORBIS__)
|
||||
#define LUAJIT_OS LUAJIT_OS_BSD
|
||||
#elif (defined(__sun__) && defined(__svr4__)) || defined(__CYGWIN__)
|
||||
#elif (defined(__sun__) && defined(__svr4__))
|
||||
#define LJ_TARGET_SOLARIS 1
|
||||
#define LUAJIT_OS LUAJIT_OS_POSIX
|
||||
#elif defined(__HAIKU__)
|
||||
#define LUAJIT_OS LUAJIT_OS_POSIX
|
||||
#elif defined(__CYGWIN__)
|
||||
#define LJ_TARGET_CYGWIN 1
|
||||
#define LUAJIT_OS LUAJIT_OS_POSIX
|
||||
#else
|
||||
#define LUAJIT_OS LUAJIT_OS_OTHER
|
||||
@@ -94,10 +117,16 @@
|
||||
#define LJ_TARGET_WINDOWS (LUAJIT_OS == LUAJIT_OS_WINDOWS)
|
||||
#define LJ_TARGET_LINUX (LUAJIT_OS == LUAJIT_OS_LINUX)
|
||||
#define LJ_TARGET_OSX (LUAJIT_OS == LUAJIT_OS_OSX)
|
||||
#define LJ_TARGET_IOS (LJ_TARGET_OSX && (LUAJIT_TARGET == LUAJIT_ARCH_ARM || LUAJIT_TARGET == LUAJIT_ARCH_ARM64))
|
||||
#define LJ_TARGET_BSD (LUAJIT_OS == LUAJIT_OS_BSD)
|
||||
#define LJ_TARGET_POSIX (LUAJIT_OS > LUAJIT_OS_WINDOWS)
|
||||
#define LJ_TARGET_DLOPEN LJ_TARGET_POSIX
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#define LJ_TARGET_IOS 1
|
||||
#else
|
||||
#define LJ_TARGET_IOS 0
|
||||
#endif
|
||||
|
||||
#ifdef __CELLOS_LV2__
|
||||
#define LJ_TARGET_PS3 1
|
||||
#define LJ_TARGET_CONSOLE 1
|
||||
@@ -126,10 +155,14 @@
|
||||
#define LJ_TARGET_GC64 1
|
||||
#endif
|
||||
|
||||
#define LJ_NUMMODE_SINGLE 0 /* Single-number mode only. */
|
||||
#define LJ_NUMMODE_SINGLE_DUAL 1 /* Default to single-number mode. */
|
||||
#define LJ_NUMMODE_DUAL 2 /* Dual-number mode only. */
|
||||
#define LJ_NUMMODE_DUAL_SINGLE 3 /* Default to dual-number mode. */
|
||||
#ifdef _UWP
|
||||
#define LJ_TARGET_UWP 1
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_X64
|
||||
#define LJ_TARGET_GC64 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* -- Arch-specific settings ---------------------------------------------- */
|
||||
|
||||
/* Set target architecture properties. */
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_X86
|
||||
@@ -137,7 +170,7 @@
|
||||
#define LJ_ARCH_NAME "x86"
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#if LJ_TARGET_WINDOWS || __CYGWIN__
|
||||
#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
|
||||
#define LJ_ABI_WIN 1
|
||||
#else
|
||||
#define LJ_ABI_WIN 0
|
||||
@@ -155,7 +188,7 @@
|
||||
#define LJ_ARCH_NAME "x64"
|
||||
#define LJ_ARCH_BITS 64
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#if LJ_TARGET_WINDOWS || __CYGWIN__
|
||||
#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
|
||||
#define LJ_ABI_WIN 1
|
||||
#else
|
||||
#define LJ_ABI_WIN 0
|
||||
@@ -168,7 +201,7 @@
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNALIGNED 1
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE_DUAL
|
||||
#ifdef LUAJIT_ENABLE_GC64
|
||||
#ifndef LUAJIT_DISABLE_GC64
|
||||
#define LJ_TARGET_GC64 1
|
||||
#endif
|
||||
|
||||
@@ -192,13 +225,13 @@
|
||||
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||
|
||||
#if __ARM_ARCH____ARM_ARCH_8__ || __ARM_ARCH_8A__
|
||||
#if __ARM_ARCH == 8 || __ARM_ARCH_8__ || __ARM_ARCH_8A__
|
||||
#define LJ_ARCH_VERSION 80
|
||||
#elif __ARM_ARCH_7__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH_7S__ || __ARM_ARCH_7VE__
|
||||
#elif __ARM_ARCH == 7 || __ARM_ARCH_7__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH_7S__ || __ARM_ARCH_7VE__
|
||||
#define LJ_ARCH_VERSION 70
|
||||
#elif __ARM_ARCH_6T2__
|
||||
#define LJ_ARCH_VERSION 61
|
||||
#elif __ARM_ARCH_6__ || __ARM_ARCH_6J__ || __ARM_ARCH_6K__ || __ARM_ARCH_6Z__ || __ARM_ARCH_6ZK__
|
||||
#elif __ARM_ARCH == 6 || __ARM_ARCH_6__ || __ARM_ARCH_6J__ || __ARM_ARCH_6K__ || __ARM_ARCH_6Z__ || __ARM_ARCH_6ZK__
|
||||
#define LJ_ARCH_VERSION 60
|
||||
#else
|
||||
#define LJ_ARCH_VERSION 50
|
||||
@@ -206,9 +239,14 @@
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM64
|
||||
|
||||
#define LJ_ARCH_NAME "arm64"
|
||||
#define LJ_ARCH_BITS 64
|
||||
#if defined(__AARCH64EB__)
|
||||
#define LJ_ARCH_NAME "arm64be"
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||
#else
|
||||
#define LJ_ARCH_NAME "arm64"
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#endif
|
||||
#define LJ_TARGET_ARM64 1
|
||||
#define LJ_TARGET_EHRETREG 0
|
||||
#define LJ_TARGET_JUMPRANGE 27 /* +-2^27 = +-128MB */
|
||||
@@ -217,7 +255,6 @@
|
||||
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
||||
#define LJ_TARGET_GC64 1
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||
#define LJ_ARCH_NOJIT 1 /* NYI */
|
||||
|
||||
#define LJ_ARCH_VERSION 80
|
||||
|
||||
@@ -241,6 +278,28 @@
|
||||
#else
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_ARCH_NAME "ppc"
|
||||
|
||||
#if !defined(LJ_ARCH_HASFPU)
|
||||
#if defined(_SOFT_FLOAT) || defined(_SOFT_DOUBLE)
|
||||
#define LJ_ARCH_HASFPU 0
|
||||
#else
|
||||
#define LJ_ARCH_HASFPU 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(LJ_ABI_SOFTFP)
|
||||
#if defined(_SOFT_FLOAT) || defined(_SOFT_DOUBLE)
|
||||
#define LJ_ABI_SOFTFP 1
|
||||
#else
|
||||
#define LJ_ABI_SOFTFP 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LJ_ABI_SOFTFP
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||
#else
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL_SINGLE
|
||||
#endif
|
||||
|
||||
#define LJ_TARGET_PPC 1
|
||||
@@ -249,15 +308,12 @@
|
||||
#define LJ_TARGET_MASKSHIFT 0
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNIFYROT 1 /* Want only IR_BROL. */
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL_SINGLE
|
||||
|
||||
#if LJ_TARGET_CONSOLE
|
||||
#define LJ_ARCH_PPC32ON64 1
|
||||
#define LJ_ARCH_NOFFI 1
|
||||
#elif LJ_ARCH_BITS == 64
|
||||
#define LJ_ARCH_PPC64 1
|
||||
#define LJ_TARGET_GC64 1
|
||||
#define LJ_ARCH_NOJIT 1 /* NYI */
|
||||
#error "No support for PPC64"
|
||||
#endif
|
||||
|
||||
#if _ARCH_PWR7
|
||||
@@ -286,25 +342,79 @@
|
||||
#define LJ_ARCH_XENON 1
|
||||
#endif
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_MIPS
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_MIPS32 || LUAJIT_TARGET == LUAJIT_ARCH_MIPS64
|
||||
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
|
||||
#if __mips_isa_rev >= 6
|
||||
#define LJ_TARGET_MIPSR6 1
|
||||
#define LJ_TARGET_UNALIGNED 1
|
||||
#endif
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||
#if LJ_TARGET_MIPSR6
|
||||
#define LJ_ARCH_NAME "mips32r6el"
|
||||
#else
|
||||
#define LJ_ARCH_NAME "mipsel"
|
||||
#endif
|
||||
#else
|
||||
#if LJ_TARGET_MIPSR6
|
||||
#define LJ_ARCH_NAME "mips64r6el"
|
||||
#else
|
||||
#define LJ_ARCH_NAME "mips64el"
|
||||
#endif
|
||||
#endif
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#else
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||
#if LJ_TARGET_MIPSR6
|
||||
#define LJ_ARCH_NAME "mips32r6"
|
||||
#else
|
||||
#define LJ_ARCH_NAME "mips"
|
||||
#endif
|
||||
#else
|
||||
#if LJ_TARGET_MIPSR6
|
||||
#define LJ_ARCH_NAME "mips64r6"
|
||||
#else
|
||||
#define LJ_ARCH_NAME "mips64"
|
||||
#endif
|
||||
#endif
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||
#endif
|
||||
|
||||
#if !defined(LJ_ARCH_HASFPU)
|
||||
#ifdef __mips_soft_float
|
||||
#define LJ_ARCH_HASFPU 0
|
||||
#else
|
||||
#define LJ_ARCH_HASFPU 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(LJ_ABI_SOFTFP)
|
||||
#ifdef __mips_soft_float
|
||||
#define LJ_ABI_SOFTFP 1
|
||||
#else
|
||||
#define LJ_ABI_SOFTFP 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_TARGET_MIPS32 1
|
||||
#else
|
||||
#define LJ_ARCH_BITS 64
|
||||
#define LJ_TARGET_MIPS64 1
|
||||
#define LJ_TARGET_GC64 1
|
||||
#endif
|
||||
#define LJ_TARGET_MIPS 1
|
||||
#define LJ_TARGET_EHRETREG 4
|
||||
#define LJ_TARGET_JUMPRANGE 27 /* 2*2^27 = 256MB-aligned region */
|
||||
#define LJ_TARGET_MASKSHIFT 1
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||
|
||||
#if _MIPS_ARCH_MIPS32R2
|
||||
#if LJ_TARGET_MIPSR6
|
||||
#define LJ_ARCH_VERSION 60
|
||||
#elif _MIPS_ARCH_MIPS32R2 || _MIPS_ARCH_MIPS64R2
|
||||
#define LJ_ARCH_VERSION 20
|
||||
#else
|
||||
#define LJ_ARCH_VERSION 10
|
||||
@@ -314,9 +424,7 @@
|
||||
#error "No target architecture defined"
|
||||
#endif
|
||||
|
||||
#ifndef LJ_PAGESIZE
|
||||
#define LJ_PAGESIZE 4096
|
||||
#endif
|
||||
/* -- Checks for requirements --------------------------------------------- */
|
||||
|
||||
/* Check for minimum required compiler versions. */
|
||||
#if defined(__GNUC__)
|
||||
@@ -334,7 +442,7 @@
|
||||
#endif
|
||||
#elif LJ_TARGET_ARM64
|
||||
#if __clang__
|
||||
#if (__clang_major__ < 3) || ((__clang_major__ == 3) && __clang_minor__ < 5)
|
||||
#if ((__clang_major__ < 3) || ((__clang_major__ == 3) && __clang_minor__ < 5)) && !defined(__NX_TOOLCHAIN_MAJOR__)
|
||||
#error "Need at least Clang 3.5 or newer"
|
||||
#endif
|
||||
#else
|
||||
@@ -366,35 +474,34 @@
|
||||
#error "Only ARM EABI or iOS 3.0+ ABI is supported"
|
||||
#endif
|
||||
#elif LJ_TARGET_ARM64
|
||||
#if defined(__AARCH64EB__)
|
||||
#error "No support for big-endian ARM64"
|
||||
#endif
|
||||
#if defined(_ILP32)
|
||||
#error "No support for ILP32 model on ARM64"
|
||||
#endif
|
||||
#elif LJ_TARGET_PPC
|
||||
#if defined(_SOFT_FLOAT) || defined(_SOFT_DOUBLE)
|
||||
#error "No support for PowerPC CPUs without double-precision FPU"
|
||||
#endif
|
||||
#if !LJ_ARCH_PPC64 && LJ_ARCH_ENDIAN == LUAJIT_LE
|
||||
#if defined(_LITTLE_ENDIAN) && (!defined(_BYTE_ORDER) || (_BYTE_ORDER == _LITTLE_ENDIAN))
|
||||
#error "No support for little-endian PPC32"
|
||||
#endif
|
||||
#if LJ_ARCH_PPC64
|
||||
#error "No support for PowerPC 64 bit mode (yet)"
|
||||
#endif
|
||||
#ifdef __NO_FPRS__
|
||||
#if defined(__NO_FPRS__) && !defined(_SOFT_FLOAT)
|
||||
#error "No support for PPC/e500 anymore (use LuaJIT 2.0)"
|
||||
#endif
|
||||
#elif LJ_TARGET_MIPS
|
||||
#if defined(__mips_soft_float)
|
||||
#error "No support for MIPS CPUs without FPU"
|
||||
#elif LJ_TARGET_MIPS32
|
||||
#if !((defined(_MIPS_SIM_ABI32) && _MIPS_SIM == _MIPS_SIM_ABI32) || (defined(_ABIO32) && _MIPS_SIM == _ABIO32))
|
||||
#error "Only o32 ABI supported for MIPS32"
|
||||
#endif
|
||||
#if defined(_LP64)
|
||||
#error "No support for MIPS64"
|
||||
#if LJ_TARGET_MIPSR6
|
||||
/* Not that useful, since most available r6 CPUs are 64 bit. */
|
||||
#error "No support for MIPS32R6"
|
||||
#endif
|
||||
#elif LJ_TARGET_MIPS64
|
||||
#if !((defined(_MIPS_SIM_ABI64) && _MIPS_SIM == _MIPS_SIM_ABI64) || (defined(_ABI64) && _MIPS_SIM == _ABI64))
|
||||
/* MIPS32ON64 aka n32 ABI support might be desirable, but difficult. */
|
||||
#error "Only n64 ABI supported for MIPS64"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* -- Derived defines ----------------------------------------------------- */
|
||||
|
||||
/* Enable or disable the dual-number mode for the VM. */
|
||||
#if (LJ_ARCH_NUMMODE == LJ_NUMMODE_SINGLE && LUAJIT_NUMMODE == 2) || \
|
||||
(LJ_ARCH_NUMMODE == LJ_NUMMODE_DUAL && LUAJIT_NUMMODE == 1)
|
||||
@@ -431,7 +538,7 @@
|
||||
#endif
|
||||
|
||||
/* Disable or enable the JIT compiler. */
|
||||
#if defined(LUAJIT_DISABLE_JIT) || defined(LJ_ARCH_NOJIT) || defined(LJ_OS_NOJIT) || LJ_FR2 || LJ_GC64
|
||||
#if defined(LUAJIT_DISABLE_JIT) || defined(LJ_ARCH_NOJIT) || defined(LJ_OS_NOJIT)
|
||||
#define LJ_HASJIT 0
|
||||
#else
|
||||
#define LJ_HASJIT 1
|
||||
@@ -466,6 +573,7 @@
|
||||
#define LJ_ABI_SOFTFP 0
|
||||
#endif
|
||||
#define LJ_SOFTFP (!LJ_ARCH_HASFPU)
|
||||
#define LJ_SOFTFP32 (LJ_SOFTFP && LJ_32)
|
||||
|
||||
#if LJ_ARCH_ENDIAN == LUAJIT_BE
|
||||
#define LJ_LE 0
|
||||
@@ -491,21 +599,39 @@
|
||||
#define LJ_TARGET_UNALIGNED 0
|
||||
#endif
|
||||
|
||||
/* Various workarounds for embedded operating systems or weak C runtimes. */
|
||||
#if (defined(__ANDROID__) && !defined(LJ_TARGET_X86ORX64)) || defined(__symbian__) || LJ_TARGET_XBOX360 || LJ_TARGET_WINDOWS
|
||||
#define LUAJIT_NO_LOG2
|
||||
#ifndef LJ_PAGESIZE
|
||||
#define LJ_PAGESIZE 4096
|
||||
#endif
|
||||
#if defined(__symbian__) || LJ_TARGET_WINDOWS
|
||||
#define LUAJIT_NO_EXP2
|
||||
|
||||
/* Various workarounds for embedded operating systems or weak C runtimes. */
|
||||
#if defined(__ANDROID__) || defined(__symbian__) || LJ_TARGET_XBOX360 || LJ_TARGET_WINDOWS
|
||||
#define LUAJIT_NO_LOG2
|
||||
#endif
|
||||
#if LJ_TARGET_CONSOLE || (LJ_TARGET_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0)
|
||||
#define LJ_NO_SYSTEM 1
|
||||
#endif
|
||||
|
||||
#if !defined(LUAJIT_NO_UNWIND) && __GNU_COMPACT_EH__
|
||||
/* NYI: no support for compact unwind specification, yet. */
|
||||
#define LUAJIT_NO_UNWIND 1
|
||||
#endif
|
||||
|
||||
#if defined(LUAJIT_NO_UNWIND) || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4
|
||||
#define LJ_NO_UNWIND 1
|
||||
#endif
|
||||
|
||||
#if LJ_TARGET_WINDOWS
|
||||
#if LJ_TARGET_UWP
|
||||
#define LJ_WIN_VALLOC VirtualAllocFromApp
|
||||
#define LJ_WIN_VPROTECT VirtualProtectFromApp
|
||||
extern void *LJ_WIN_LOADLIBA(const char *path);
|
||||
#else
|
||||
#define LJ_WIN_VALLOC VirtualAlloc
|
||||
#define LJ_WIN_VPROTECT VirtualProtect
|
||||
#define LJ_WIN_LOADLIBA(path) LoadLibraryExA((path), NULL, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Compatibility with Lua 5.1 vs. 5.2. */
|
||||
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|
||||
#define LJ_52 1
|
||||
@@ -513,4 +639,46 @@
|
||||
#define LJ_52 0
|
||||
#endif
|
||||
|
||||
/* -- VM security --------------------------------------------------------- */
|
||||
|
||||
/* Don't make any changes here. Instead build with:
|
||||
** make "XCFLAGS=-DLUAJIT_SECURITY_flag=value"
|
||||
**
|
||||
** Important note to distro maintainers: DO NOT change the defaults for a
|
||||
** regular distro build -- neither upwards, nor downwards!
|
||||
** These build-time configurable security flags are intended for embedders
|
||||
** who may have specific needs wrt. security vs. performance.
|
||||
*/
|
||||
|
||||
/* Security defaults. */
|
||||
#ifndef LUAJIT_SECURITY_PRNG
|
||||
/* PRNG init: 0 = fixed/insecure, 1 = secure from OS. */
|
||||
#define LUAJIT_SECURITY_PRNG 1
|
||||
#endif
|
||||
|
||||
#ifndef LUAJIT_SECURITY_STRHASH
|
||||
/* String hash: 0 = sparse only, 1 = sparse + dense. */
|
||||
#define LUAJIT_SECURITY_STRHASH 1
|
||||
#endif
|
||||
|
||||
#ifndef LUAJIT_SECURITY_STRID
|
||||
/* String IDs: 0 = linear, 1 = reseed < 255, 2 = reseed < 15, 3 = random. */
|
||||
#define LUAJIT_SECURITY_STRID 1
|
||||
#endif
|
||||
|
||||
#ifndef LUAJIT_SECURITY_MCODE
|
||||
/* Machine code page protection: 0 = insecure RWX, 1 = secure RW^X. */
|
||||
#define LUAJIT_SECURITY_MCODE 1
|
||||
#endif
|
||||
|
||||
#define LJ_SECURITY_MODE \
|
||||
( 0u \
|
||||
| ((LUAJIT_SECURITY_PRNG & 3) << 0) \
|
||||
| ((LUAJIT_SECURITY_STRHASH & 3) << 2) \
|
||||
| ((LUAJIT_SECURITY_STRID & 3) << 4) \
|
||||
| ((LUAJIT_SECURITY_MCODE & 3) << 6) \
|
||||
)
|
||||
#define LJ_SECURITY_MODESTRING \
|
||||
"\004prng\007strhash\005strid\005mcode"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** IR assembler (SSA IR -> machine code).
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#define lj_asm_c
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "lj_ircall.h"
|
||||
#include "lj_iropt.h"
|
||||
#include "lj_mcode.h"
|
||||
#include "lj_iropt.h"
|
||||
#include "lj_trace.h"
|
||||
#include "lj_snap.h"
|
||||
#include "lj_asm.h"
|
||||
@@ -91,12 +90,18 @@ typedef struct ASMState {
|
||||
MCode *realign; /* Realign loop if not NULL. */
|
||||
|
||||
#ifdef RID_NUM_KREF
|
||||
int32_t krefk[RID_NUM_KREF];
|
||||
intptr_t krefk[RID_NUM_KREF];
|
||||
#endif
|
||||
IRRef1 phireg[RID_MAX]; /* PHI register references. */
|
||||
uint16_t parentmap[LJ_MAX_JSLOTS]; /* Parent instruction to RegSP map. */
|
||||
} ASMState;
|
||||
|
||||
#ifdef LUA_USE_ASSERT
|
||||
#define lj_assertA(c, ...) lj_assertG_(J2G(as->J), (c), __VA_ARGS__)
|
||||
#else
|
||||
#define lj_assertA(c, ...) ((void)as)
|
||||
#endif
|
||||
|
||||
#define IR(ref) (&as->ir[(ref)])
|
||||
|
||||
#define ASMREF_TMP1 REF_TRUE /* Temp. register. */
|
||||
@@ -128,9 +133,8 @@ static LJ_AINLINE void checkmclim(ASMState *as)
|
||||
#ifdef LUA_USE_ASSERT
|
||||
if (as->mcp + MCLIM_REDZONE < as->mcp_prev) {
|
||||
IRIns *ir = IR(as->curins+1);
|
||||
fprintf(stderr, "RED ZONE OVERFLOW: %p IR %04d %02d %04d %04d\n", as->mcp,
|
||||
as->curins+1-REF_BIAS, ir->o, ir->op1-REF_BIAS, ir->op2-REF_BIAS);
|
||||
lua_assert(0);
|
||||
lj_assertA(0, "red zone overflow: %p IR %04d %02d %04d %04d\n", as->mcp,
|
||||
as->curins+1-REF_BIAS, ir->o, ir->op1-REF_BIAS, ir->op2-REF_BIAS);
|
||||
}
|
||||
#endif
|
||||
if (LJ_UNLIKELY(as->mcp < as->mclim)) asm_mclimit(as);
|
||||
@@ -144,7 +148,7 @@ static LJ_AINLINE void checkmclim(ASMState *as)
|
||||
#define ra_krefreg(ref) ((Reg)(RID_MIN_KREF + (Reg)(ref)))
|
||||
#define ra_krefk(as, ref) (as->krefk[(ref)])
|
||||
|
||||
static LJ_AINLINE void ra_setkref(ASMState *as, Reg r, int32_t k)
|
||||
static LJ_AINLINE void ra_setkref(ASMState *as, Reg r, intptr_t k)
|
||||
{
|
||||
IRRef ref = (IRRef)(r - RID_MIN_KREF);
|
||||
as->krefk[ref] = k;
|
||||
@@ -171,6 +175,8 @@ IRFLDEF(FLOFS)
|
||||
#include "lj_emit_x86.h"
|
||||
#elif LJ_TARGET_ARM
|
||||
#include "lj_emit_arm.h"
|
||||
#elif LJ_TARGET_ARM64
|
||||
#include "lj_emit_arm64.h"
|
||||
#elif LJ_TARGET_PPC
|
||||
#include "lj_emit_ppc.h"
|
||||
#elif LJ_TARGET_MIPS
|
||||
@@ -242,7 +248,7 @@ static void ra_dprintf(ASMState *as, const char *fmt, ...)
|
||||
*p++ = *q >= 'A' && *q <= 'Z' ? *q + 0x20 : *q;
|
||||
} else {
|
||||
*p++ = '?';
|
||||
lua_assert(0);
|
||||
lj_assertA(0, "bad register %d for debug format \"%s\"", r, fmt);
|
||||
}
|
||||
} else if (e[1] == 'f' || e[1] == 'i') {
|
||||
IRRef ref;
|
||||
@@ -260,7 +266,7 @@ static void ra_dprintf(ASMState *as, const char *fmt, ...)
|
||||
} else if (e[1] == 'x') {
|
||||
p += sprintf(p, "%08x", va_arg(argp, int32_t));
|
||||
} else {
|
||||
lua_assert(0);
|
||||
lj_assertA(0, "bad debug format code");
|
||||
}
|
||||
fmt = e+2;
|
||||
}
|
||||
@@ -319,37 +325,51 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
||||
Reg r;
|
||||
if (ra_iskref(ref)) {
|
||||
r = ra_krefreg(ref);
|
||||
lua_assert(!rset_test(as->freeset, r));
|
||||
lj_assertA(!rset_test(as->freeset, r), "rematk of free reg %d", r);
|
||||
ra_free(as, r);
|
||||
ra_modified(as, r);
|
||||
#if LJ_64
|
||||
emit_loadu64(as, r, ra_krefk(as, ref));
|
||||
#else
|
||||
emit_loadi(as, r, ra_krefk(as, ref));
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
ir = IR(ref);
|
||||
r = ir->r;
|
||||
lua_assert(ra_hasreg(r) && !ra_hasspill(ir->s));
|
||||
lj_assertA(ra_hasreg(r), "rematk of K%03d has no reg", REF_BIAS - ref);
|
||||
lj_assertA(!ra_hasspill(ir->s),
|
||||
"rematk of K%03d has spill slot [%x]", REF_BIAS - ref, ir->s);
|
||||
ra_free(as, r);
|
||||
ra_modified(as, r);
|
||||
ir->r = RID_INIT; /* Do not keep any hint. */
|
||||
RA_DBGX((as, "remat $i $r", ir, r));
|
||||
#if !LJ_SOFTFP
|
||||
#if !LJ_SOFTFP32
|
||||
if (ir->o == IR_KNUM) {
|
||||
emit_loadn(as, r, ir_knum(ir));
|
||||
emit_loadk64(as, r, ir);
|
||||
} else
|
||||
#endif
|
||||
if (emit_canremat(REF_BASE) && ir->o == IR_BASE) {
|
||||
ra_sethint(ir->r, RID_BASE); /* Restore BASE register hint. */
|
||||
emit_getgl(as, r, jit_base);
|
||||
} else if (emit_canremat(ASMREF_L) && ir->o == IR_KPRI) {
|
||||
lua_assert(irt_isnil(ir->t)); /* REF_NIL stores ASMREF_L register. */
|
||||
/* REF_NIL stores ASMREF_L register. */
|
||||
lj_assertA(irt_isnil(ir->t), "rematk of bad ASMREF_L");
|
||||
emit_getgl(as, r, cur_L);
|
||||
#if LJ_64
|
||||
} else if (ir->o == IR_KINT64) {
|
||||
emit_loadu64(as, r, ir_kint64(ir)->u64);
|
||||
#if LJ_GC64
|
||||
} else if (ir->o == IR_KGC) {
|
||||
emit_loadu64(as, r, (uintptr_t)ir_kgc(ir));
|
||||
} else if (ir->o == IR_KPTR || ir->o == IR_KKPTR) {
|
||||
emit_loadu64(as, r, (uintptr_t)ir_kptr(ir));
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
lua_assert(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL);
|
||||
lj_assertA(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL,
|
||||
"rematk of bad IR op %d", ir->o);
|
||||
emit_loadi(as, r, ir->i);
|
||||
}
|
||||
return r;
|
||||
@@ -359,7 +379,8 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
||||
static int32_t ra_spill(ASMState *as, IRIns *ir)
|
||||
{
|
||||
int32_t slot = ir->s;
|
||||
lua_assert(ir >= as->ir + REF_TRUE);
|
||||
lj_assertA(ir >= as->ir + REF_TRUE,
|
||||
"spill of K%03d", REF_BIAS - (int)(ir - as->ir));
|
||||
if (!ra_hasspill(slot)) {
|
||||
if (irt_is64(ir->t)) {
|
||||
slot = as->evenspill;
|
||||
@@ -384,7 +405,9 @@ static Reg ra_releasetmp(ASMState *as, IRRef ref)
|
||||
{
|
||||
IRIns *ir = IR(ref);
|
||||
Reg r = ir->r;
|
||||
lua_assert(ra_hasreg(r) && !ra_hasspill(ir->s));
|
||||
lj_assertA(ra_hasreg(r), "release of TMP%d has no reg", ref-ASMREF_TMP1+1);
|
||||
lj_assertA(!ra_hasspill(ir->s),
|
||||
"release of TMP%d has spill slot [%x]", ref-ASMREF_TMP1+1, ir->s);
|
||||
ra_free(as, r);
|
||||
ra_modified(as, r);
|
||||
ir->r = RID_INIT;
|
||||
@@ -400,7 +423,7 @@ static Reg ra_restore(ASMState *as, IRRef ref)
|
||||
IRIns *ir = IR(ref);
|
||||
int32_t ofs = ra_spill(as, ir); /* Force a spill slot. */
|
||||
Reg r = ir->r;
|
||||
lua_assert(ra_hasreg(r));
|
||||
lj_assertA(ra_hasreg(r), "restore of IR %04d has no reg", ref - REF_BIAS);
|
||||
ra_sethint(ir->r, r); /* Keep hint. */
|
||||
ra_free(as, r);
|
||||
if (!rset_test(as->weakset, r)) { /* Only restore non-weak references. */
|
||||
@@ -429,14 +452,15 @@ static Reg ra_evict(ASMState *as, RegSet allow)
|
||||
{
|
||||
IRRef ref;
|
||||
RegCost cost = ~(RegCost)0;
|
||||
lua_assert(allow != RSET_EMPTY);
|
||||
lj_assertA(allow != RSET_EMPTY, "evict from empty set");
|
||||
if (RID_NUM_FPR == 0 || allow < RID2RSET(RID_MAX_GPR)) {
|
||||
GPRDEF(MINCOST)
|
||||
} else {
|
||||
FPRDEF(MINCOST)
|
||||
}
|
||||
ref = regcost_ref(cost);
|
||||
lua_assert(ra_iskref(ref) || (ref >= as->T->nk && ref < as->T->nins));
|
||||
lj_assertA(ra_iskref(ref) || (ref >= as->T->nk && ref < as->T->nins),
|
||||
"evict of out-of-range IR %04d", ref - REF_BIAS);
|
||||
/* Preferably pick any weak ref instead of a non-weak, non-const ref. */
|
||||
if (!irref_isk(ref) && (as->weakset & allow)) {
|
||||
IRIns *ir = IR(ref);
|
||||
@@ -518,7 +542,7 @@ static void ra_evictk(ASMState *as)
|
||||
|
||||
#ifdef RID_NUM_KREF
|
||||
/* Allocate a register for a constant. */
|
||||
static Reg ra_allock(ASMState *as, int32_t k, RegSet allow)
|
||||
static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow)
|
||||
{
|
||||
/* First try to find a register which already holds the same constant. */
|
||||
RegSet pick, work = ~as->freeset & RSET_GPR;
|
||||
@@ -527,9 +551,31 @@ static Reg ra_allock(ASMState *as, int32_t k, RegSet allow)
|
||||
IRRef ref;
|
||||
r = rset_pickbot(work);
|
||||
ref = regcost_ref(as->cost[r]);
|
||||
#if LJ_64
|
||||
if (ref < ASMREF_L) {
|
||||
if (ra_iskref(ref)) {
|
||||
if (k == ra_krefk(as, ref))
|
||||
return r;
|
||||
} else {
|
||||
IRIns *ir = IR(ref);
|
||||
if ((ir->o == IR_KINT64 && k == (int64_t)ir_kint64(ir)->u64) ||
|
||||
#if LJ_GC64
|
||||
(ir->o == IR_KINT && k == ir->i) ||
|
||||
(ir->o == IR_KGC && k == (intptr_t)ir_kgc(ir)) ||
|
||||
((ir->o == IR_KPTR || ir->o == IR_KKPTR) &&
|
||||
k == (intptr_t)ir_kptr(ir))
|
||||
#else
|
||||
(ir->o != IR_KINT64 && k == ir->i)
|
||||
#endif
|
||||
)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (ref < ASMREF_L &&
|
||||
k == (ra_iskref(ref) ? ra_krefk(as, ref) : IR(ref)->i))
|
||||
return r;
|
||||
#endif
|
||||
rset_clear(work, r);
|
||||
}
|
||||
pick = as->freeset & allow;
|
||||
@@ -549,7 +595,7 @@ static Reg ra_allock(ASMState *as, int32_t k, RegSet allow)
|
||||
}
|
||||
|
||||
/* Allocate a specific register for a constant. */
|
||||
static void ra_allockreg(ASMState *as, int32_t k, Reg r)
|
||||
static void ra_allockreg(ASMState *as, intptr_t k, Reg r)
|
||||
{
|
||||
Reg kr = ra_allock(as, k, RID2RSET(r));
|
||||
if (kr != r) {
|
||||
@@ -572,7 +618,8 @@ static Reg ra_allocref(ASMState *as, IRRef ref, RegSet allow)
|
||||
IRIns *ir = IR(ref);
|
||||
RegSet pick = as->freeset & allow;
|
||||
Reg r;
|
||||
lua_assert(ra_noreg(ir->r));
|
||||
lj_assertA(ra_noreg(ir->r),
|
||||
"IR %04d already has reg %d", ref - REF_BIAS, ir->r);
|
||||
if (pick) {
|
||||
/* First check register hint from propagation or PHI. */
|
||||
if (ra_hashint(ir->r)) {
|
||||
@@ -619,15 +666,27 @@ static Reg ra_alloc1(ASMState *as, IRRef ref, RegSet allow)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Add a register rename to the IR. */
|
||||
static void ra_addrename(ASMState *as, Reg down, IRRef ref, SnapNo snapno)
|
||||
{
|
||||
IRRef ren;
|
||||
lj_ir_set(as->J, IRT(IR_RENAME, IRT_NIL), ref, snapno);
|
||||
ren = tref_ref(lj_ir_emit(as->J));
|
||||
as->J->cur.ir[ren].r = (uint8_t)down;
|
||||
as->J->cur.ir[ren].s = SPS_NONE;
|
||||
}
|
||||
|
||||
/* Rename register allocation and emit move. */
|
||||
static void ra_rename(ASMState *as, Reg down, Reg up)
|
||||
{
|
||||
IRRef ren, ref = regcost_ref(as->cost[up] = as->cost[down]);
|
||||
IRRef ref = regcost_ref(as->cost[up] = as->cost[down]);
|
||||
IRIns *ir = IR(ref);
|
||||
ir->r = (uint8_t)up;
|
||||
as->cost[down] = 0;
|
||||
lua_assert((down < RID_MAX_GPR) == (up < RID_MAX_GPR));
|
||||
lua_assert(!rset_test(as->freeset, down) && rset_test(as->freeset, up));
|
||||
lj_assertA((down < RID_MAX_GPR) == (up < RID_MAX_GPR),
|
||||
"rename between GPR/FPR %d and %d", down, up);
|
||||
lj_assertA(!rset_test(as->freeset, down), "rename from free reg %d", down);
|
||||
lj_assertA(rset_test(as->freeset, up), "rename to non-free reg %d", up);
|
||||
ra_free(as, down); /* 'down' is free ... */
|
||||
ra_modified(as, down);
|
||||
rset_clear(as->freeset, up); /* ... and 'up' is now allocated. */
|
||||
@@ -635,11 +694,7 @@ static void ra_rename(ASMState *as, Reg down, Reg up)
|
||||
RA_DBGX((as, "rename $f $r $r", regcost_ref(as->cost[up]), down, up));
|
||||
emit_movrr(as, ir, down, up); /* Backwards codegen needs inverse move. */
|
||||
if (!ra_hasspill(IR(ref)->s)) { /* Add the rename to the IR. */
|
||||
lj_ir_set(as->J, IRT(IR_RENAME, IRT_NIL), ref, as->snapno);
|
||||
ren = tref_ref(lj_ir_emit(as->J));
|
||||
as->ir = as->T->ir; /* The IR may have been reallocated. */
|
||||
IR(ren)->r = (uint8_t)down;
|
||||
IR(ren)->s = SPS_NONE;
|
||||
ra_addrename(as, down, ref, as->snapno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -672,7 +727,7 @@ static void ra_destreg(ASMState *as, IRIns *ir, Reg r)
|
||||
{
|
||||
Reg dest = ra_dest(as, ir, RID2RSET(r));
|
||||
if (dest != r) {
|
||||
lua_assert(rset_test(as->freeset, r));
|
||||
lj_assertA(rset_test(as->freeset, r), "dest reg %d is not free", r);
|
||||
ra_modified(as, r);
|
||||
emit_movrr(as, ir, dest, r);
|
||||
}
|
||||
@@ -689,20 +744,25 @@ static void ra_left(ASMState *as, Reg dest, IRRef lref)
|
||||
if (ra_noreg(left)) {
|
||||
if (irref_isk(lref)) {
|
||||
if (ir->o == IR_KNUM) {
|
||||
cTValue *tv = ir_knum(ir);
|
||||
/* FP remat needs a load except for +0. Still better than eviction. */
|
||||
if (tvispzero(tv) || !(as->freeset & RSET_FPR)) {
|
||||
emit_loadn(as, dest, tv);
|
||||
if (tvispzero(ir_knum(ir)) || !(as->freeset & RSET_FPR)) {
|
||||
emit_loadk64(as, dest, ir);
|
||||
return;
|
||||
}
|
||||
#if LJ_64
|
||||
} else if (ir->o == IR_KINT64) {
|
||||
emit_loadu64(as, dest, ir_kint64(ir)->u64);
|
||||
emit_loadk64(as, dest, ir);
|
||||
return;
|
||||
#if LJ_GC64
|
||||
} else if (ir->o == IR_KGC || ir->o == IR_KPTR || ir->o == IR_KKPTR) {
|
||||
emit_loadk64(as, dest, ir);
|
||||
return;
|
||||
#endif
|
||||
#endif
|
||||
} else if (ir->o != IR_KPRI) {
|
||||
lua_assert(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL);
|
||||
lj_assertA(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL,
|
||||
"K%03d has bad IR op %d", REF_BIAS - lref, ir->o);
|
||||
emit_loadi(as, dest, ir->i);
|
||||
return;
|
||||
}
|
||||
@@ -844,11 +904,14 @@ static void asm_snap_alloc1(ASMState *as, IRRef ref)
|
||||
#endif
|
||||
{ /* Allocate stored values for TNEW, TDUP and CNEW. */
|
||||
IRIns *irs;
|
||||
lua_assert(ir->o == IR_TNEW || ir->o == IR_TDUP || ir->o == IR_CNEW);
|
||||
lj_assertA(ir->o == IR_TNEW || ir->o == IR_TDUP || ir->o == IR_CNEW,
|
||||
"sink of IR %04d has bad op %d", ref - REF_BIAS, ir->o);
|
||||
for (irs = IR(as->snapref-1); irs > ir; irs--)
|
||||
if (irs->r == RID_SINK && asm_sunk_store(as, ir, irs)) {
|
||||
lua_assert(irs->o == IR_ASTORE || irs->o == IR_HSTORE ||
|
||||
irs->o == IR_FSTORE || irs->o == IR_XSTORE);
|
||||
lj_assertA(irs->o == IR_ASTORE || irs->o == IR_HSTORE ||
|
||||
irs->o == IR_FSTORE || irs->o == IR_XSTORE,
|
||||
"sunk store IR %04d has bad op %d",
|
||||
(int)(irs - as->ir) - REF_BIAS, irs->o);
|
||||
asm_snap_alloc1(as, irs->op2);
|
||||
if (LJ_32 && (irs+1)->o == IR_HIOP)
|
||||
asm_snap_alloc1(as, (irs+1)->op2);
|
||||
@@ -895,7 +958,9 @@ static void asm_snap_alloc(ASMState *as)
|
||||
if (!irref_isk(ref)) {
|
||||
asm_snap_alloc1(as, ref);
|
||||
if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) {
|
||||
lua_assert(irt_type(IR(ref+1)->t) == IRT_SOFTFP);
|
||||
lj_assertA(irt_type(IR(ref+1)->t) == IRT_SOFTFP,
|
||||
"snap %d[%d] points to bad SOFTFP IR %04d",
|
||||
as->snapno, n, ref - REF_BIAS);
|
||||
asm_snap_alloc1(as, ref+1);
|
||||
}
|
||||
}
|
||||
@@ -941,7 +1006,7 @@ static void asm_snap_prep(ASMState *as)
|
||||
} else {
|
||||
/* Process any renames above the highwater mark. */
|
||||
for (; as->snaprename < as->T->nins; as->snaprename++) {
|
||||
IRIns *ir = IR(as->snaprename);
|
||||
IRIns *ir = &as->T->ir[as->snaprename];
|
||||
if (asm_snap_checkrename(as, ir->op1))
|
||||
ir->op2 = REF_BIAS-1; /* Kill rename. */
|
||||
}
|
||||
@@ -959,21 +1024,26 @@ static int32_t asm_stack_adjust(ASMState *as)
|
||||
}
|
||||
|
||||
/* Must match with hash*() in lj_tab.c. */
|
||||
static uint32_t ir_khash(IRIns *ir)
|
||||
static uint32_t ir_khash(ASMState *as, IRIns *ir)
|
||||
{
|
||||
uint32_t lo, hi;
|
||||
UNUSED(as);
|
||||
if (irt_isstr(ir->t)) {
|
||||
return ir_kstr(ir)->hash;
|
||||
return ir_kstr(ir)->sid;
|
||||
} else if (irt_isnum(ir->t)) {
|
||||
lo = ir_knum(ir)->u32.lo;
|
||||
hi = ir_knum(ir)->u32.hi << 1;
|
||||
} else if (irt_ispri(ir->t)) {
|
||||
lua_assert(!irt_isnil(ir->t));
|
||||
lj_assertA(!irt_isnil(ir->t), "hash of nil key");
|
||||
return irt_type(ir->t)-IRT_FALSE;
|
||||
} else {
|
||||
lua_assert(irt_isgcv(ir->t));
|
||||
lj_assertA(irt_isgcv(ir->t), "hash of bad IR type %d", irt_type(ir->t));
|
||||
lo = u32ptr(ir_kgc(ir));
|
||||
#if LJ_GC64
|
||||
hi = (uint32_t)(u64ptr(ir_kgc(ir)) >> 32) | (irt_toitype(ir->t) << 15);
|
||||
#else
|
||||
hi = lo + HASH_BIAS;
|
||||
#endif
|
||||
}
|
||||
return hashrot(lo, hi);
|
||||
}
|
||||
@@ -1055,7 +1125,7 @@ static void asm_bufhdr(ASMState *as, IRIns *ir)
|
||||
}
|
||||
} else {
|
||||
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
|
||||
/* Passing ir isn't strictly correct, but it's an IRT_P32, too. */
|
||||
/* Passing ir isn't strictly correct, but it's an IRT_PGC, too. */
|
||||
emit_storeofs(as, ir, tmp, sb, offsetof(SBuf, p));
|
||||
emit_loadofs(as, ir, tmp, sb, offsetof(SBuf, b));
|
||||
}
|
||||
@@ -1071,15 +1141,16 @@ static void asm_bufput(ASMState *as, IRIns *ir)
|
||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_buf_putstr];
|
||||
IRRef args[3];
|
||||
IRIns *irs;
|
||||
int kchar = -1;
|
||||
int kchar = -129;
|
||||
args[0] = ir->op1; /* SBuf * */
|
||||
args[1] = ir->op2; /* GCstr * */
|
||||
irs = IR(ir->op2);
|
||||
lua_assert(irt_isstr(irs->t));
|
||||
lj_assertA(irt_isstr(irs->t),
|
||||
"BUFPUT of non-string IR %04d", ir->op2 - REF_BIAS);
|
||||
if (irs->o == IR_KGC) {
|
||||
GCstr *s = ir_kstr(irs);
|
||||
if (s->len == 1) { /* Optimize put of single-char string constant. */
|
||||
kchar = strdata(s)[0];
|
||||
kchar = (int8_t)strdata(s)[0]; /* Signed! */
|
||||
args[1] = ASMREF_TMP1; /* int, truncated to char */
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_buf_putchar];
|
||||
}
|
||||
@@ -1089,7 +1160,8 @@ static void asm_bufput(ASMState *as, IRIns *ir)
|
||||
args[1] = ASMREF_TMP1; /* TValue * */
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_putnum];
|
||||
} else {
|
||||
lua_assert(irt_isinteger(IR(irs->op1)->t));
|
||||
lj_assertA(irt_isinteger(IR(irs->op1)->t),
|
||||
"TOSTR of non-numeric IR %04d", irs->op1);
|
||||
args[1] = irs->op1; /* int */
|
||||
if (irs->op2 == IRTOSTR_INT)
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_putint];
|
||||
@@ -1106,7 +1178,7 @@ static void asm_bufput(ASMState *as, IRIns *ir)
|
||||
asm_gencall(as, ci, args);
|
||||
if (args[1] == ASMREF_TMP1) {
|
||||
Reg tmp = ra_releasetmp(as, ASMREF_TMP1);
|
||||
if (kchar == -1)
|
||||
if (kchar == -129)
|
||||
asm_tvptr(as, tmp, irs->op1);
|
||||
else
|
||||
ra_allockreg(as, kchar, tmp);
|
||||
@@ -1154,7 +1226,8 @@ static void asm_conv64(ASMState *as, IRIns *ir)
|
||||
IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH);
|
||||
IRCallID id;
|
||||
IRRef args[2];
|
||||
lua_assert((ir-1)->o == IR_CONV && ir->o == IR_HIOP);
|
||||
lj_assertA((ir-1)->o == IR_CONV && ir->o == IR_HIOP,
|
||||
"not a CONV/HIOP pair at IR %04d", (int)(ir - as->ir) - REF_BIAS);
|
||||
args[LJ_BE] = (ir-1)->op1;
|
||||
args[LJ_LE] = ir->op1;
|
||||
if (st == IRT_NUM || st == IRT_FLOAT) {
|
||||
@@ -1209,15 +1282,16 @@ static void asm_collectargs(ASMState *as, IRIns *ir,
|
||||
const CCallInfo *ci, IRRef *args)
|
||||
{
|
||||
uint32_t n = CCI_XNARGS(ci);
|
||||
lua_assert(n <= CCI_NARGS_MAX*2); /* Account for split args. */
|
||||
/* Account for split args. */
|
||||
lj_assertA(n <= CCI_NARGS_MAX*2, "too many args %d to collect", n);
|
||||
if ((ci->flags & CCI_L)) { *args++ = ASMREF_L; n--; }
|
||||
while (n-- > 1) {
|
||||
ir = IR(ir->op1);
|
||||
lua_assert(ir->o == IR_CARG);
|
||||
lj_assertA(ir->o == IR_CARG, "malformed CALL arg tree");
|
||||
args[n] = ir->op2 == REF_NIL ? 0 : ir->op2;
|
||||
}
|
||||
args[0] = ir->op1 == REF_NIL ? 0 : ir->op1;
|
||||
lua_assert(IR(ir->op1)->o != IR_CARG);
|
||||
lj_assertA(IR(ir->op1)->o != IR_CARG, "malformed CALL arg tree");
|
||||
}
|
||||
|
||||
/* Reconstruct CCallInfo flags for CALLX*. */
|
||||
@@ -1261,32 +1335,6 @@ static void asm_call(ASMState *as, IRIns *ir)
|
||||
asm_gencall(as, ci, args);
|
||||
}
|
||||
|
||||
#if !LJ_SOFTFP
|
||||
static void asm_fppow(ASMState *as, IRIns *ir, IRRef lref, IRRef rref)
|
||||
{
|
||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_pow];
|
||||
IRRef args[2];
|
||||
args[0] = lref;
|
||||
args[1] = rref;
|
||||
asm_setupresult(as, ir, ci);
|
||||
asm_gencall(as, ci, args);
|
||||
}
|
||||
|
||||
static int asm_fpjoin_pow(ASMState *as, IRIns *ir)
|
||||
{
|
||||
IRIns *irp = IR(ir->op1);
|
||||
if (irp == ir-1 && irp->o == IR_MUL && !ra_used(irp)) {
|
||||
IRIns *irpp = IR(irp->op1);
|
||||
if (irpp == ir-2 && irpp->o == IR_FPMATH &&
|
||||
irpp->op2 == IRFPM_LOG2 && !ra_used(irpp)) {
|
||||
asm_fppow(as, ir, irpp->op1, irp->op2);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- PHI and loop handling ----------------------------------------------- */
|
||||
|
||||
/* Break a PHI cycle by renaming to a free register (evict if needed). */
|
||||
@@ -1472,12 +1520,7 @@ static void asm_phi_fixup(ASMState *as)
|
||||
irt_clearmark(ir->t);
|
||||
/* Left PHI gained a spill slot before the loop? */
|
||||
if (ra_hasspill(ir->s)) {
|
||||
IRRef ren;
|
||||
lj_ir_set(as->J, IRT(IR_RENAME, IRT_NIL), lref, as->loopsnapno);
|
||||
ren = tref_ref(lj_ir_emit(as->J));
|
||||
as->ir = as->T->ir; /* The IR may have been reallocated. */
|
||||
IR(ren)->r = (uint8_t)r;
|
||||
IR(ren)->s = SPS_NONE;
|
||||
ra_addrename(as, r, lref, as->loopsnapno);
|
||||
}
|
||||
}
|
||||
rset_clear(work, r);
|
||||
@@ -1552,6 +1595,8 @@ static void asm_loop(ASMState *as)
|
||||
#include "lj_asm_x86.h"
|
||||
#elif LJ_TARGET_ARM
|
||||
#include "lj_asm_arm.h"
|
||||
#elif LJ_TARGET_ARM64
|
||||
#include "lj_asm_arm64.h"
|
||||
#elif LJ_TARGET_PPC
|
||||
#include "lj_asm_ppc.h"
|
||||
#elif LJ_TARGET_MIPS
|
||||
@@ -1560,6 +1605,68 @@ static void asm_loop(ASMState *as)
|
||||
#error "Missing assembler for target CPU"
|
||||
#endif
|
||||
|
||||
/* -- Common instruction helpers ------------------------------------------ */
|
||||
|
||||
#if !LJ_SOFTFP32
|
||||
#if !LJ_TARGET_X86ORX64
|
||||
#define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp)
|
||||
#define asm_fppowi(as, ir) asm_callid(as, ir, IRCALL_lj_vm_powi)
|
||||
#endif
|
||||
|
||||
static void asm_pow(ASMState *as, IRIns *ir)
|
||||
{
|
||||
#if LJ_64 && LJ_HASFFI
|
||||
if (!irt_isnum(ir->t))
|
||||
asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 :
|
||||
IRCALL_lj_carith_powu64);
|
||||
else
|
||||
#endif
|
||||
if (irt_isnum(IR(ir->op2)->t))
|
||||
asm_callid(as, ir, IRCALL_pow);
|
||||
else
|
||||
asm_fppowi(as, ir);
|
||||
}
|
||||
|
||||
static void asm_div(ASMState *as, IRIns *ir)
|
||||
{
|
||||
#if LJ_64 && LJ_HASFFI
|
||||
if (!irt_isnum(ir->t))
|
||||
asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_divi64 :
|
||||
IRCALL_lj_carith_divu64);
|
||||
else
|
||||
#endif
|
||||
asm_fpdiv(as, ir);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void asm_mod(ASMState *as, IRIns *ir)
|
||||
{
|
||||
#if LJ_64 && LJ_HASFFI
|
||||
if (!irt_isint(ir->t))
|
||||
asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 :
|
||||
IRCALL_lj_carith_modu64);
|
||||
else
|
||||
#endif
|
||||
asm_callid(as, ir, IRCALL_lj_vm_modi);
|
||||
}
|
||||
|
||||
static void asm_fuseequal(ASMState *as, IRIns *ir)
|
||||
{
|
||||
/* Fuse HREF + EQ/NE. */
|
||||
if ((ir-1)->o == IR_HREF && ir->op1 == as->curins-1) {
|
||||
as->curins--;
|
||||
asm_href(as, ir-1, (IROp)ir->o);
|
||||
} else {
|
||||
asm_equal(as, ir);
|
||||
}
|
||||
}
|
||||
|
||||
static void asm_alen(ASMState *as, IRIns *ir)
|
||||
{
|
||||
asm_callid(as, ir, ir->op2 == REF_NIL ? IRCALL_lj_tab_len :
|
||||
IRCALL_lj_tab_len_hint);
|
||||
}
|
||||
|
||||
/* -- Instruction dispatch ------------------------------------------------ */
|
||||
|
||||
/* Assemble a single instruction. */
|
||||
@@ -1568,7 +1675,10 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
||||
switch ((IROp)ir->o) {
|
||||
/* Miscellaneous ops. */
|
||||
case IR_LOOP: asm_loop(as); break;
|
||||
case IR_NOP: case IR_XBAR: lua_assert(!ra_used(ir)); break;
|
||||
case IR_NOP: case IR_XBAR:
|
||||
lj_assertA(!ra_used(ir),
|
||||
"IR %04d not unused", (int)(ir - as->ir) - REF_BIAS);
|
||||
break;
|
||||
case IR_USE:
|
||||
ra_alloc1(as, ir->op1, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); break;
|
||||
case IR_PHI: asm_phi(as, ir); break;
|
||||
@@ -1582,14 +1692,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
||||
case IR_ABC:
|
||||
asm_comp(as, ir);
|
||||
break;
|
||||
case IR_EQ: case IR_NE:
|
||||
if ((ir-1)->o == IR_HREF && ir->op1 == as->curins-1) {
|
||||
as->curins--;
|
||||
asm_href(as, ir-1, (IROp)ir->o);
|
||||
} else {
|
||||
asm_equal(as, ir);
|
||||
}
|
||||
break;
|
||||
case IR_EQ: case IR_NE: asm_fuseequal(as, ir); break;
|
||||
|
||||
case IR_RETF: asm_retf(as, ir); break;
|
||||
|
||||
@@ -1609,16 +1712,25 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
||||
case IR_ADD: asm_add(as, ir); break;
|
||||
case IR_SUB: asm_sub(as, ir); break;
|
||||
case IR_MUL: asm_mul(as, ir); break;
|
||||
case IR_DIV: asm_div(as, ir); break;
|
||||
case IR_MOD: asm_mod(as, ir); break;
|
||||
case IR_POW: asm_pow(as, ir); break;
|
||||
case IR_NEG: asm_neg(as, ir); break;
|
||||
#if LJ_SOFTFP32
|
||||
case IR_DIV: case IR_POW: case IR_ABS:
|
||||
case IR_LDEXP: case IR_FPMATH: case IR_TOBIT:
|
||||
/* Unused for LJ_SOFTFP32. */
|
||||
lj_assertA(0, "IR %04d with unused op %d",
|
||||
(int)(ir - as->ir) - REF_BIAS, ir->o);
|
||||
break;
|
||||
#else
|
||||
case IR_DIV: asm_div(as, ir); break;
|
||||
case IR_POW: asm_pow(as, ir); break;
|
||||
case IR_ABS: asm_abs(as, ir); break;
|
||||
case IR_ATAN2: asm_atan2(as, ir); break;
|
||||
case IR_LDEXP: asm_ldexp(as, ir); break;
|
||||
case IR_FPMATH: asm_fpmath(as, ir); break;
|
||||
case IR_TOBIT: asm_tobit(as, ir); break;
|
||||
#endif
|
||||
case IR_MIN: asm_min(as, ir); break;
|
||||
case IR_MAX: asm_max(as, ir); break;
|
||||
case IR_FPMATH: asm_fpmath(as, ir); break;
|
||||
|
||||
/* Overflow-checking arithmetic ops. */
|
||||
case IR_ADDOV: asm_addov(as, ir); break;
|
||||
@@ -1642,6 +1754,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
||||
case IR_FLOAD: asm_fload(as, ir); break;
|
||||
case IR_XLOAD: asm_xload(as, ir); break;
|
||||
case IR_SLOAD: asm_sload(as, ir); break;
|
||||
case IR_ALEN: asm_alen(as, ir); break;
|
||||
|
||||
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: asm_ahustore(as, ir); break;
|
||||
case IR_FSTORE: asm_fstore(as, ir); break;
|
||||
@@ -1651,7 +1764,14 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
||||
case IR_SNEW: case IR_XSNEW: asm_snew(as, ir); break;
|
||||
case IR_TNEW: asm_tnew(as, ir); break;
|
||||
case IR_TDUP: asm_tdup(as, ir); break;
|
||||
case IR_CNEW: case IR_CNEWI: asm_cnew(as, ir); break;
|
||||
case IR_CNEW: case IR_CNEWI:
|
||||
#if LJ_HASFFI
|
||||
asm_cnew(as, ir);
|
||||
#else
|
||||
lj_assertA(0, "IR %04d with unused op %d",
|
||||
(int)(ir - as->ir) - REF_BIAS, ir->o);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* Buffer operations. */
|
||||
case IR_BUFHDR: asm_bufhdr(as, ir); break;
|
||||
@@ -1663,7 +1783,6 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
||||
case IR_OBAR: asm_obar(as, ir); break;
|
||||
|
||||
/* Type conversions. */
|
||||
case IR_TOBIT: asm_tobit(as, ir); break;
|
||||
case IR_CONV: asm_conv(as, ir); break;
|
||||
case IR_TOSTR: asm_tostr(as, ir); break;
|
||||
case IR_STRTO: asm_strto(as, ir); break;
|
||||
@@ -1728,8 +1847,10 @@ static void asm_head_side(ASMState *as)
|
||||
for (i = as->stopins; i > REF_BASE; i--) {
|
||||
IRIns *ir = IR(i);
|
||||
RegSP rs;
|
||||
lua_assert((ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_PARENT)) ||
|
||||
(LJ_SOFTFP && ir->o == IR_HIOP) || ir->o == IR_PVAL);
|
||||
lj_assertA((ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_PARENT)) ||
|
||||
(LJ_SOFTFP && ir->o == IR_HIOP) || ir->o == IR_PVAL,
|
||||
"IR %04d has bad parent op %d",
|
||||
(int)(ir - as->ir) - REF_BIAS, ir->o);
|
||||
rs = as->parentmap[i - REF_FIRST];
|
||||
if (ra_hasreg(ir->r)) {
|
||||
rset_clear(allow, ir->r);
|
||||
@@ -1881,7 +2002,7 @@ static BCReg asm_baseslot(ASMState *as, SnapShot *snap, int *gotframe)
|
||||
SnapEntry sn = map[n-1];
|
||||
if ((sn & SNAP_FRAME)) {
|
||||
*gotframe = 1;
|
||||
return snap_slot(sn);
|
||||
return snap_slot(sn) - LJ_FR2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -1901,16 +2022,20 @@ static void asm_tail_link(ASMState *as)
|
||||
|
||||
if (as->T->link == 0) {
|
||||
/* Setup fixed registers for exit to interpreter. */
|
||||
const BCIns *pc = snap_pc(as->T->snapmap[snap->mapofs + snap->nent]);
|
||||
const BCIns *pc = snap_pc(&as->T->snapmap[snap->mapofs + snap->nent]);
|
||||
int32_t mres;
|
||||
if (bc_op(*pc) == BC_JLOOP) { /* NYI: find a better way to do this. */
|
||||
BCIns *retpc = &traceref(as->J, bc_d(*pc))->startins;
|
||||
if (bc_isret(bc_op(*retpc)))
|
||||
pc = retpc;
|
||||
}
|
||||
#if LJ_GC64
|
||||
emit_loadu64(as, RID_LPC, u64ptr(pc));
|
||||
#else
|
||||
ra_allockreg(as, i32ptr(J2GG(as->J)->dispatch), RID_DISPATCH);
|
||||
ra_allockreg(as, i32ptr(pc), RID_LPC);
|
||||
mres = (int32_t)(snap->nslots - baseslot);
|
||||
#endif
|
||||
mres = (int32_t)(snap->nslots - baseslot - LJ_FR2);
|
||||
switch (bc_op(*pc)) {
|
||||
case BC_CALLM: case BC_CALLMT:
|
||||
mres -= (int32_t)(1 + LJ_FR2 + bc_a(*pc) + bc_c(*pc)); break;
|
||||
@@ -1925,6 +2050,11 @@ static void asm_tail_link(ASMState *as)
|
||||
}
|
||||
emit_addptr(as, RID_BASE, 8*(int32_t)baseslot);
|
||||
|
||||
if (as->J->ktrace) { /* Patch ktrace slot with the final GCtrace pointer. */
|
||||
setgcref(IR(as->J->ktrace)[LJ_GC64].gcr, obj2gco(as->J->curfinal));
|
||||
IR(as->J->ktrace)->o = IR_KGC;
|
||||
}
|
||||
|
||||
/* Sync the interpreter state with the on-trace state. */
|
||||
asm_stack_restore(as, snap);
|
||||
|
||||
@@ -1950,17 +2080,23 @@ static void asm_setup_regsp(ASMState *as)
|
||||
ra_setup(as);
|
||||
|
||||
/* Clear reg/sp for constants. */
|
||||
for (ir = IR(T->nk), lastir = IR(REF_BASE); ir < lastir; ir++)
|
||||
for (ir = IR(T->nk), lastir = IR(REF_BASE); ir < lastir; ir++) {
|
||||
ir->prev = REGSP_INIT;
|
||||
if (irt_is64(ir->t) && ir->o != IR_KNULL) {
|
||||
#if LJ_GC64
|
||||
/* The false-positive of irt_is64() for ASMREF_L (REF_NIL) is OK here. */
|
||||
ir->i = 0; /* Will become non-zero only for RIP-relative addresses. */
|
||||
#else
|
||||
/* Make life easier for backends by putting address of constant in i. */
|
||||
ir->i = (int32_t)(intptr_t)(ir+1);
|
||||
#endif
|
||||
ir++;
|
||||
}
|
||||
}
|
||||
|
||||
/* REF_BASE is used for implicit references to the BASE register. */
|
||||
lastir->prev = REGSP_HINT(RID_BASE);
|
||||
|
||||
ir = IR(nins-1);
|
||||
if (ir->o == IR_RENAME) {
|
||||
do { ir--; nins--; } while (ir->o == IR_RENAME);
|
||||
T->nins = nins; /* Remove any renames left over from ASM restart. */
|
||||
}
|
||||
as->snaprename = nins;
|
||||
as->snapref = nins;
|
||||
as->snapno = T->nsnap;
|
||||
@@ -1973,7 +2109,7 @@ static void asm_setup_regsp(ASMState *as)
|
||||
ir = IR(REF_FIRST);
|
||||
if (as->parent) {
|
||||
uint16_t *p;
|
||||
lastir = lj_snap_regspmap(as->parent, as->J->exitno, ir);
|
||||
lastir = lj_snap_regspmap(as->J, as->parent, as->J->exitno, ir);
|
||||
if (lastir - ir > LJ_MAX_JSLOTS)
|
||||
lj_trace_err(as->J, LJ_TRERR_NYICOAL);
|
||||
as->stopins = (IRRef)((lastir-1) - as->ir);
|
||||
@@ -2046,8 +2182,8 @@ static void asm_setup_regsp(ASMState *as)
|
||||
ir->prev = REGSP_HINT(RID_FPRET);
|
||||
continue;
|
||||
}
|
||||
/* fallthrough */
|
||||
#endif
|
||||
/* fallthrough */
|
||||
case IR_CALLN: case IR_CALLXS:
|
||||
#if LJ_SOFTFP
|
||||
case IR_MIN: case IR_MAX:
|
||||
@@ -2063,8 +2199,8 @@ static void asm_setup_regsp(ASMState *as)
|
||||
#if LJ_SOFTFP
|
||||
case IR_MIN: case IR_MAX:
|
||||
if ((ir+1)->o != IR_HIOP) break;
|
||||
/* fallthrough */
|
||||
#endif
|
||||
/* fallthrough */
|
||||
/* C calls evict all scratch regs and return results in RID_RET. */
|
||||
case IR_SNEW: case IR_XSNEW: case IR_NEWREF: case IR_BUFPUT:
|
||||
if (REGARG_NUMGPR < 3 && as->evenspill < 3)
|
||||
@@ -2075,9 +2211,12 @@ static void asm_setup_regsp(ASMState *as)
|
||||
if (ir->op2 != REF_NIL && as->evenspill < 4)
|
||||
as->evenspill = 4; /* lj_cdata_newv needs 4 args. */
|
||||
}
|
||||
/* fallthrough */
|
||||
#else
|
||||
/* fallthrough */
|
||||
case IR_CNEW:
|
||||
#endif
|
||||
/* fallthrough */
|
||||
case IR_TNEW: case IR_TDUP: case IR_CNEWI: case IR_TOSTR:
|
||||
case IR_BUFSTR:
|
||||
ir->prev = REGSP_HINT(RID_RET);
|
||||
@@ -2089,27 +2228,27 @@ static void asm_setup_regsp(ASMState *as)
|
||||
as->modset = RSET_SCRATCH;
|
||||
break;
|
||||
#if !LJ_SOFTFP
|
||||
case IR_ATAN2:
|
||||
#if LJ_TARGET_X86
|
||||
if (as->evenspill < 4) /* Leave room to call atan2(). */
|
||||
as->evenspill = 4;
|
||||
#endif
|
||||
#if !LJ_TARGET_X86ORX64
|
||||
case IR_LDEXP:
|
||||
#endif
|
||||
#endif
|
||||
/* fallthrough */
|
||||
case IR_POW:
|
||||
if (!LJ_SOFTFP && irt_isnum(ir->t)) {
|
||||
if (inloop)
|
||||
as->modset |= RSET_SCRATCH;
|
||||
#if LJ_TARGET_X86
|
||||
if (irt_isnum(IR(ir->op2)->t)) {
|
||||
if (as->evenspill < 4) /* Leave room to call pow(). */
|
||||
as->evenspill = 4;
|
||||
}
|
||||
break;
|
||||
#else
|
||||
ir->prev = REGSP_HINT(RID_FPRET);
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
/* fallthrough for integer POW */
|
||||
/* fallthrough */ /* for integer POW */
|
||||
case IR_DIV: case IR_MOD:
|
||||
if (!irt_isnum(ir->t)) {
|
||||
ir->prev = REGSP_HINT(RID_RET);
|
||||
@@ -2128,9 +2267,6 @@ static void asm_setup_regsp(ASMState *as)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else if (ir->op2 == IRFPM_EXP2 && !LJ_64) {
|
||||
if (as->evenspill < 4) /* Leave room to call pow(). */
|
||||
as->evenspill = 4;
|
||||
}
|
||||
#endif
|
||||
if (inloop)
|
||||
@@ -2143,7 +2279,11 @@ static void asm_setup_regsp(ASMState *as)
|
||||
#endif
|
||||
#if LJ_TARGET_X86ORX64
|
||||
/* Non-constant shift counts need to be in RID_ECX on x86/x64. */
|
||||
case IR_BSHL: case IR_BSHR: case IR_BSAR: case IR_BROL: case IR_BROR:
|
||||
case IR_BSHL: case IR_BSHR: case IR_BSAR:
|
||||
if ((as->flags & JIT_F_BMI2)) /* Except if BMI2 is available. */
|
||||
break;
|
||||
/* fallthrough */
|
||||
case IR_BROL: case IR_BROR:
|
||||
if (!irref_isk(ir->op2) && !ra_hashint(IR(ir->op2)->r)) {
|
||||
IR(ir->op2)->r = REGSP_HINT(RID_ECX);
|
||||
if (inloop)
|
||||
@@ -2189,14 +2329,25 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
||||
ASMState *as = &as_;
|
||||
MCode *origtop;
|
||||
|
||||
/* Remove nops/renames left over from ASM restart due to LJ_TRERR_MCODELM. */
|
||||
{
|
||||
IRRef nins = T->nins;
|
||||
IRIns *ir = &T->ir[nins-1];
|
||||
if (ir->o == IR_NOP || ir->o == IR_RENAME) {
|
||||
do { ir--; nins--; } while (ir->o == IR_NOP || ir->o == IR_RENAME);
|
||||
T->nins = nins;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure an initialized instruction beyond the last one for HIOP checks. */
|
||||
J->cur.nins = lj_ir_nextins(J);
|
||||
J->cur.ir[J->cur.nins].o = IR_NOP;
|
||||
/* This also allows one RENAME to be added without reallocating curfinal. */
|
||||
as->orignins = lj_ir_nextins(J);
|
||||
lj_ir_nop(&J->cur.ir[as->orignins]);
|
||||
|
||||
/* Setup initial state. Copy some fields to reduce indirections. */
|
||||
as->J = J;
|
||||
as->T = T;
|
||||
as->ir = T->ir;
|
||||
J->curfinal = lj_trace_alloc(J->L, T); /* This copies the IR, too. */
|
||||
as->flags = J->flags;
|
||||
as->loopref = J->loopref;
|
||||
as->realign = NULL;
|
||||
@@ -2209,12 +2360,41 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
||||
as->mclim = as->mcbot + MCLIM_REDZONE;
|
||||
asm_setup_target(as);
|
||||
|
||||
do {
|
||||
/*
|
||||
** This is a loop, because the MCode may have to be (re-)assembled
|
||||
** multiple times:
|
||||
**
|
||||
** 1. as->realign is set (and the assembly aborted), if the arch-specific
|
||||
** backend wants the MCode to be aligned differently.
|
||||
**
|
||||
** This is currently only the case on x86/x64, where small loops get
|
||||
** an aligned loop body plus a short branch. Not much effort is wasted,
|
||||
** because the abort happens very quickly and only once.
|
||||
**
|
||||
** 2. The IR is immovable, since the MCode embeds pointers to various
|
||||
** constants inside the IR. But RENAMEs may need to be added to the IR
|
||||
** during assembly, which might grow and reallocate the IR. We check
|
||||
** at the end if the IR (in J->cur.ir) has actually grown, resize the
|
||||
** copy (in J->curfinal.ir) and try again.
|
||||
**
|
||||
** 95% of all traces have zero RENAMEs, 3% have one RENAME, 1.5% have
|
||||
** 2 RENAMEs and only 0.5% have more than that. That's why we opt to
|
||||
** always have one spare slot in the IR (see above), which means we
|
||||
** have to redo the assembly for only ~2% of all traces.
|
||||
**
|
||||
** Very, very rarely, this needs to be done repeatedly, since the
|
||||
** location of constants inside the IR (actually, reachability from
|
||||
** a global pointer) may affect register allocation and thus the
|
||||
** number of RENAMEs.
|
||||
*/
|
||||
for (;;) {
|
||||
as->mcp = as->mctop;
|
||||
#ifdef LUA_USE_ASSERT
|
||||
as->mcp_prev = as->mcp;
|
||||
#endif
|
||||
as->curins = T->nins;
|
||||
as->ir = J->curfinal->ir; /* Use the copied IR. */
|
||||
as->curins = J->cur.nins = as->orignins;
|
||||
|
||||
RA_DBG_START();
|
||||
RA_DBGX((as, "===== STOP ====="));
|
||||
|
||||
@@ -2233,7 +2413,10 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
||||
/* Assemble a trace in linear backwards order. */
|
||||
for (as->curins--; as->curins > as->stopins; as->curins--) {
|
||||
IRIns *ir = IR(as->curins);
|
||||
lua_assert(!(LJ_32 && irt_isint64(ir->t))); /* Handled by SPLIT. */
|
||||
/* 64 bit types handled by SPLIT for 32 bit archs. */
|
||||
lj_assertA(!(LJ_32 && irt_isint64(ir->t)),
|
||||
"IR %04d has unsplit 64 bit type",
|
||||
(int)(ir - as->ir) - REF_BIAS);
|
||||
if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE))
|
||||
continue; /* Dead-code elimination can be soooo easy. */
|
||||
if (irt_isguard(ir->t))
|
||||
@@ -2242,22 +2425,40 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
||||
checkmclim(as);
|
||||
asm_ir(as, ir);
|
||||
}
|
||||
} while (as->realign); /* Retry in case the MCode needs to be realigned. */
|
||||
|
||||
/* Emit head of trace. */
|
||||
RA_DBG_REF();
|
||||
checkmclim(as);
|
||||
if (as->gcsteps > 0) {
|
||||
as->curins = as->T->snap[0].ref;
|
||||
asm_snap_prep(as); /* The GC check is a guard. */
|
||||
asm_gc_check(as);
|
||||
if (as->realign && J->curfinal->nins >= T->nins)
|
||||
continue; /* Retry in case only the MCode needs to be realigned. */
|
||||
|
||||
/* Emit head of trace. */
|
||||
RA_DBG_REF();
|
||||
checkmclim(as);
|
||||
if (as->gcsteps > 0) {
|
||||
as->curins = as->T->snap[0].ref;
|
||||
asm_snap_prep(as); /* The GC check is a guard. */
|
||||
asm_gc_check(as);
|
||||
as->curins = as->stopins;
|
||||
}
|
||||
ra_evictk(as);
|
||||
if (as->parent)
|
||||
asm_head_side(as);
|
||||
else
|
||||
asm_head_root(as);
|
||||
asm_phi_fixup(as);
|
||||
|
||||
if (J->curfinal->nins >= T->nins) { /* IR didn't grow? */
|
||||
lj_assertA(J->curfinal->nk == T->nk, "unexpected IR constant growth");
|
||||
memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins,
|
||||
(T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */
|
||||
T->nins = J->curfinal->nins;
|
||||
break; /* Done. */
|
||||
}
|
||||
|
||||
/* Otherwise try again with a bigger IR. */
|
||||
lj_trace_free(J2G(J), J->curfinal);
|
||||
J->curfinal = NULL; /* In case lj_trace_alloc() OOMs. */
|
||||
J->curfinal = lj_trace_alloc(J->L, T);
|
||||
as->realign = NULL;
|
||||
}
|
||||
ra_evictk(as);
|
||||
if (as->parent)
|
||||
asm_head_side(as);
|
||||
else
|
||||
asm_head_root(as);
|
||||
asm_phi_fixup(as);
|
||||
|
||||
RA_DBGX((as, "===== START ===="));
|
||||
RA_DBG_FLUSH();
|
||||
@@ -2270,6 +2471,9 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
||||
if (!as->loopref)
|
||||
asm_tail_fixup(as, T->link); /* Note: this may change as->mctop! */
|
||||
T->szmcode = (MSize)((char *)as->mctop - (char *)as->mcp);
|
||||
#if LJ_TARGET_MCODE_FIXUP
|
||||
asm_mcode_fixup(T->mcode, T->szmcode);
|
||||
#endif
|
||||
lj_mcode_sync(T->mcode, origtop);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** IR assembler (SSA IR -> machine code).
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_ASM_H
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** ARM IR assembler (SSA IR -> machine code).
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
/* -- Register allocator extensions --------------------------------------- */
|
||||
@@ -41,7 +41,7 @@ static Reg ra_scratchpair(ASMState *as, RegSet allow)
|
||||
}
|
||||
}
|
||||
}
|
||||
lua_assert(rset_test(RSET_GPREVEN, r));
|
||||
lj_assertA(rset_test(RSET_GPREVEN, r), "odd reg %d", r);
|
||||
ra_modified(as, r);
|
||||
ra_modified(as, r+1);
|
||||
RA_DBGX((as, "scratchpair $r $r", r, r+1));
|
||||
@@ -269,7 +269,7 @@ static void asm_fusexref(ASMState *as, ARMIns ai, Reg rd, IRRef ref,
|
||||
return;
|
||||
}
|
||||
} else if (ir->o == IR_STRREF && !(!LJ_SOFTFP && (ai & 0x08000000))) {
|
||||
lua_assert(ofs == 0);
|
||||
lj_assertA(ofs == 0, "bad usage");
|
||||
ofs = (int32_t)sizeof(GCstr);
|
||||
if (irref_isk(ir->op2)) {
|
||||
ofs += IR(ir->op2)->i;
|
||||
@@ -389,9 +389,11 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
||||
as->freeset |= (of & RSET_RANGE(REGARG_FIRSTGPR, REGARG_LASTGPR+1));
|
||||
if (irt_isnum(ir->t)) gpr = (gpr+1) & ~1u;
|
||||
if (gpr <= REGARG_LASTGPR) {
|
||||
lua_assert(rset_test(as->freeset, gpr)); /* Must have been evicted. */
|
||||
lj_assertA(rset_test(as->freeset, gpr),
|
||||
"reg %d not free", gpr); /* Must have been evicted. */
|
||||
if (irt_isnum(ir->t)) {
|
||||
lua_assert(rset_test(as->freeset, gpr+1)); /* Ditto. */
|
||||
lj_assertA(rset_test(as->freeset, gpr+1),
|
||||
"reg %d not free", gpr+1); /* Ditto. */
|
||||
emit_dnm(as, ARMI_VMOV_RR_D, gpr, gpr+1, (src & 15));
|
||||
gpr += 2;
|
||||
} else {
|
||||
@@ -408,7 +410,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
||||
#endif
|
||||
{
|
||||
if (gpr <= REGARG_LASTGPR) {
|
||||
lua_assert(rset_test(as->freeset, gpr)); /* Must have been evicted. */
|
||||
lj_assertA(rset_test(as->freeset, gpr),
|
||||
"reg %d not free", gpr); /* Must have been evicted. */
|
||||
if (ref) ra_leftov(as, gpr, ref);
|
||||
gpr++;
|
||||
} else {
|
||||
@@ -426,14 +429,14 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
||||
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
||||
{
|
||||
RegSet drop = RSET_SCRATCH;
|
||||
int hiop = ((ir+1)->o == IR_HIOP);
|
||||
int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
|
||||
if (ra_hasreg(ir->r))
|
||||
rset_clear(drop, ir->r); /* Dest reg handled below. */
|
||||
if (hiop && ra_hasreg((ir+1)->r))
|
||||
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
|
||||
ra_evictset(as, drop); /* Evictions must be performed first. */
|
||||
if (ra_used(ir)) {
|
||||
lua_assert(!irt_ispri(ir->t));
|
||||
lj_assertA(!irt_ispri(ir->t), "PRI dest");
|
||||
if (!LJ_SOFTFP && irt_isfp(ir->t)) {
|
||||
if (LJ_ABI_SOFTFP || (ci->flags & (CCI_CASTU64|CCI_VARARG))) {
|
||||
Reg dest = (ra_dest(as, ir, RSET_FPR) & 15);
|
||||
@@ -520,8 +523,6 @@ static void asm_tobit(ASMState *as, IRIns *ir)
|
||||
emit_dn(as, ARMI_VMOV_R_S, dest, (tmp & 15));
|
||||
emit_dnm(as, ARMI_VADD_D, (tmp & 15), (left & 15), (right & 15));
|
||||
}
|
||||
#else
|
||||
#define asm_tobit(as, ir) lua_assert(0)
|
||||
#endif
|
||||
|
||||
static void asm_conv(ASMState *as, IRIns *ir)
|
||||
@@ -532,13 +533,17 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
||||
#endif
|
||||
IRRef lref = ir->op1;
|
||||
/* 64 bit integer conversions are handled by SPLIT. */
|
||||
lua_assert(!irt_isint64(ir->t) && !(st == IRT_I64 || st == IRT_U64));
|
||||
lj_assertA(!irt_isint64(ir->t) && !(st == IRT_I64 || st == IRT_U64),
|
||||
"IR %04d has unsplit 64 bit type",
|
||||
(int)(ir - as->ir) - REF_BIAS);
|
||||
#if LJ_SOFTFP
|
||||
/* FP conversions are handled by SPLIT. */
|
||||
lua_assert(!irt_isfp(ir->t) && !(st == IRT_NUM || st == IRT_FLOAT));
|
||||
lj_assertA(!irt_isfp(ir->t) && !(st == IRT_NUM || st == IRT_FLOAT),
|
||||
"IR %04d has FP type",
|
||||
(int)(ir - as->ir) - REF_BIAS);
|
||||
/* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. */
|
||||
#else
|
||||
lua_assert(irt_type(ir->t) != st);
|
||||
lj_assertA(irt_type(ir->t) != st, "inconsistent types for CONV");
|
||||
if (irt_isfp(ir->t)) {
|
||||
Reg dest = ra_dest(as, ir, RSET_FPR);
|
||||
if (stfp) { /* FP to FP conversion. */
|
||||
@@ -555,7 +560,8 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
||||
} else if (stfp) { /* FP to integer conversion. */
|
||||
if (irt_isguard(ir->t)) {
|
||||
/* Checked conversions are only supported from number to int. */
|
||||
lua_assert(irt_isint(ir->t) && st == IRT_NUM);
|
||||
lj_assertA(irt_isint(ir->t) && st == IRT_NUM,
|
||||
"bad type for checked CONV");
|
||||
asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
|
||||
} else {
|
||||
Reg left = ra_alloc1(as, lref, RSET_FPR);
|
||||
@@ -574,7 +580,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||
if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */
|
||||
Reg left = ra_alloc1(as, lref, RSET_GPR);
|
||||
lua_assert(irt_isint(ir->t) || irt_isu32(ir->t));
|
||||
lj_assertA(irt_isint(ir->t) || irt_isu32(ir->t), "bad type for CONV EXT");
|
||||
if ((as->flags & JIT_F_ARMV6)) {
|
||||
ARMIns ai = st == IRT_I8 ? ARMI_SXTB :
|
||||
st == IRT_U8 ? ARMI_UXTB :
|
||||
@@ -669,7 +675,7 @@ static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
|
||||
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
|
||||
} else {
|
||||
#if LJ_SOFTFP
|
||||
lua_assert(0);
|
||||
lj_assertA(0, "unsplit FP op");
|
||||
#else
|
||||
/* Otherwise force a spill and use the spill slot. */
|
||||
emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
|
||||
@@ -813,16 +819,16 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
||||
*l_loop = ARMF_CC(ARMI_B, CC_NE) | ((as->mcp-l_loop-2) & 0x00ffffffu);
|
||||
|
||||
/* Load main position relative to tab->node into dest. */
|
||||
khash = irref_isk(refkey) ? ir_khash(irkey) : 1;
|
||||
khash = irref_isk(refkey) ? ir_khash(as, irkey) : 1;
|
||||
if (khash == 0) {
|
||||
emit_lso(as, ARMI_LDR, dest, tab, (int32_t)offsetof(GCtab, node));
|
||||
} else {
|
||||
emit_dnm(as, ARMI_ADD|ARMF_SH(ARMSH_LSL, 3), dest, dest, tmp);
|
||||
emit_dnm(as, ARMI_ADD|ARMF_SH(ARMSH_LSL, 1), tmp, tmp, tmp);
|
||||
if (irt_isstr(kt)) { /* Fetch of str->hash is cheaper than ra_allock. */
|
||||
if (irt_isstr(kt)) { /* Fetch of str->sid is cheaper than ra_allock. */
|
||||
emit_dnm(as, ARMI_AND, tmp, tmp+1, RID_TMP);
|
||||
emit_lso(as, ARMI_LDR, dest, tab, (int32_t)offsetof(GCtab, node));
|
||||
emit_lso(as, ARMI_LDR, tmp+1, key, (int32_t)offsetof(GCstr, hash));
|
||||
emit_lso(as, ARMI_LDR, tmp+1, key, (int32_t)offsetof(GCstr, sid));
|
||||
emit_lso(as, ARMI_LDR, RID_TMP, tab, (int32_t)offsetof(GCtab, hmask));
|
||||
} else if (irref_isk(refkey)) {
|
||||
emit_opk(as, ARMI_AND, tmp, RID_TMP, (int32_t)khash,
|
||||
@@ -869,7 +875,7 @@ static void asm_hrefk(ASMState *as, IRIns *ir)
|
||||
Reg node = ra_alloc1(as, ir->op1, RSET_GPR);
|
||||
Reg key = RID_NONE, type = RID_TMP, idx = node;
|
||||
RegSet allow = rset_exclude(RSET_GPR, node);
|
||||
lua_assert(ofs % sizeof(Node) == 0);
|
||||
lj_assertA(ofs % sizeof(Node) == 0, "unaligned HREFK slot");
|
||||
if (ofs > 4095) {
|
||||
idx = dest;
|
||||
rset_clear(allow, dest);
|
||||
@@ -911,7 +917,6 @@ static void asm_hrefk(ASMState *as, IRIns *ir)
|
||||
|
||||
static void asm_uref(ASMState *as, IRIns *ir)
|
||||
{
|
||||
/* NYI: Check that UREFO is still open and not aliasing a slot. */
|
||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||
if (irref_isk(ir->op1)) {
|
||||
GCfunc *fn = ir_kfunc(IR(ir->op1));
|
||||
@@ -937,7 +942,7 @@ static void asm_uref(ASMState *as, IRIns *ir)
|
||||
static void asm_fref(ASMState *as, IRIns *ir)
|
||||
{
|
||||
UNUSED(as); UNUSED(ir);
|
||||
lua_assert(!ra_used(ir));
|
||||
lj_assertA(!ra_used(ir), "unfused FREF");
|
||||
}
|
||||
|
||||
static void asm_strref(ASMState *as, IRIns *ir)
|
||||
@@ -974,26 +979,28 @@ static void asm_strref(ASMState *as, IRIns *ir)
|
||||
|
||||
/* -- Loads and stores ---------------------------------------------------- */
|
||||
|
||||
static ARMIns asm_fxloadins(IRIns *ir)
|
||||
static ARMIns asm_fxloadins(ASMState *as, IRIns *ir)
|
||||
{
|
||||
UNUSED(as);
|
||||
switch (irt_type(ir->t)) {
|
||||
case IRT_I8: return ARMI_LDRSB;
|
||||
case IRT_U8: return ARMI_LDRB;
|
||||
case IRT_I16: return ARMI_LDRSH;
|
||||
case IRT_U16: return ARMI_LDRH;
|
||||
case IRT_NUM: lua_assert(!LJ_SOFTFP); return ARMI_VLDR_D;
|
||||
case IRT_FLOAT: if (!LJ_SOFTFP) return ARMI_VLDR_S;
|
||||
case IRT_NUM: lj_assertA(!LJ_SOFTFP, "unsplit FP op"); return ARMI_VLDR_D;
|
||||
case IRT_FLOAT: if (!LJ_SOFTFP) return ARMI_VLDR_S; /* fallthrough */
|
||||
default: return ARMI_LDR;
|
||||
}
|
||||
}
|
||||
|
||||
static ARMIns asm_fxstoreins(IRIns *ir)
|
||||
static ARMIns asm_fxstoreins(ASMState *as, IRIns *ir)
|
||||
{
|
||||
UNUSED(as);
|
||||
switch (irt_type(ir->t)) {
|
||||
case IRT_I8: case IRT_U8: return ARMI_STRB;
|
||||
case IRT_I16: case IRT_U16: return ARMI_STRH;
|
||||
case IRT_NUM: lua_assert(!LJ_SOFTFP); return ARMI_VSTR_D;
|
||||
case IRT_FLOAT: if (!LJ_SOFTFP) return ARMI_VSTR_S;
|
||||
case IRT_NUM: lj_assertA(!LJ_SOFTFP, "unsplit FP op"); return ARMI_VSTR_D;
|
||||
case IRT_FLOAT: if (!LJ_SOFTFP) return ARMI_VSTR_S; /* fallthrough */
|
||||
default: return ARMI_STR;
|
||||
}
|
||||
}
|
||||
@@ -1001,17 +1008,23 @@ static ARMIns asm_fxstoreins(IRIns *ir)
|
||||
static void asm_fload(ASMState *as, IRIns *ir)
|
||||
{
|
||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||
Reg idx = ra_alloc1(as, ir->op1, RSET_GPR);
|
||||
ARMIns ai = asm_fxloadins(ir);
|
||||
ARMIns ai = asm_fxloadins(as, ir);
|
||||
Reg idx;
|
||||
int32_t ofs;
|
||||
if (ir->op2 == IRFL_TAB_ARRAY) {
|
||||
ofs = asm_fuseabase(as, ir->op1);
|
||||
if (ofs) { /* Turn the t->array load into an add for colocated arrays. */
|
||||
emit_dn(as, ARMI_ADD|ARMI_K12|ofs, dest, idx);
|
||||
return;
|
||||
if (ir->op1 == REF_NIL) { /* FLOAD from GG_State with offset. */
|
||||
idx = ra_allock(as, (int32_t)(ir->op2<<2) + (int32_t)J2GG(as->J), RSET_GPR);
|
||||
ofs = 0;
|
||||
} else {
|
||||
idx = ra_alloc1(as, ir->op1, RSET_GPR);
|
||||
if (ir->op2 == IRFL_TAB_ARRAY) {
|
||||
ofs = asm_fuseabase(as, ir->op1);
|
||||
if (ofs) { /* Turn the t->array load into an add for colocated arrays. */
|
||||
emit_dn(as, ARMI_ADD|ARMI_K12|ofs, dest, idx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ofs = field_ofs[ir->op2];
|
||||
}
|
||||
ofs = field_ofs[ir->op2];
|
||||
if ((ai & 0x04000000))
|
||||
emit_lso(as, ai, dest, idx, ofs);
|
||||
else
|
||||
@@ -1025,7 +1038,7 @@ static void asm_fstore(ASMState *as, IRIns *ir)
|
||||
IRIns *irf = IR(ir->op1);
|
||||
Reg idx = ra_alloc1(as, irf->op1, rset_exclude(RSET_GPR, src));
|
||||
int32_t ofs = field_ofs[irf->op2];
|
||||
ARMIns ai = asm_fxstoreins(ir);
|
||||
ARMIns ai = asm_fxstoreins(as, ir);
|
||||
if ((ai & 0x04000000))
|
||||
emit_lso(as, ai, src, idx, ofs);
|
||||
else
|
||||
@@ -1037,8 +1050,8 @@ static void asm_xload(ASMState *as, IRIns *ir)
|
||||
{
|
||||
Reg dest = ra_dest(as, ir,
|
||||
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
||||
lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED));
|
||||
asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0);
|
||||
lj_assertA(!(ir->op2 & IRXLOAD_UNALIGNED), "unaligned XLOAD");
|
||||
asm_fusexref(as, asm_fxloadins(as, ir), dest, ir->op1, RSET_GPR, 0);
|
||||
}
|
||||
|
||||
static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
|
||||
@@ -1046,7 +1059,7 @@ static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
|
||||
if (ir->r != RID_SINK) {
|
||||
Reg src = ra_alloc1(as, ir->op2,
|
||||
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
||||
asm_fusexref(as, asm_fxstoreins(ir), src, ir->op1,
|
||||
asm_fusexref(as, asm_fxstoreins(as, ir), src, ir->op1,
|
||||
rset_exclude(RSET_GPR, src), ofs);
|
||||
}
|
||||
}
|
||||
@@ -1065,8 +1078,9 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
||||
rset_clear(allow, type);
|
||||
}
|
||||
if (ra_used(ir)) {
|
||||
lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
|
||||
irt_isint(ir->t) || irt_isaddr(ir->t));
|
||||
lj_assertA((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
|
||||
irt_isint(ir->t) || irt_isaddr(ir->t),
|
||||
"bad load type %d", irt_type(ir->t));
|
||||
dest = ra_dest(as, ir, (!LJ_SOFTFP && t == IRT_NUM) ? RSET_FPR : allow);
|
||||
rset_clear(allow, dest);
|
||||
}
|
||||
@@ -1132,10 +1146,13 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
||||
IRType t = hiop ? IRT_NUM : irt_type(ir->t);
|
||||
Reg dest = RID_NONE, type = RID_NONE, base;
|
||||
RegSet allow = RSET_GPR;
|
||||
lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */
|
||||
lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK));
|
||||
lj_assertA(!(ir->op2 & IRSLOAD_PARENT),
|
||||
"bad parent SLOAD"); /* Handled by asm_head_side(). */
|
||||
lj_assertA(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK),
|
||||
"inconsistent SLOAD variant");
|
||||
#if LJ_SOFTFP
|
||||
lua_assert(!(ir->op2 & IRSLOAD_CONVERT)); /* Handled by LJ_SOFTFP SPLIT. */
|
||||
lj_assertA(!(ir->op2 & IRSLOAD_CONVERT),
|
||||
"unsplit SLOAD convert"); /* Handled by LJ_SOFTFP SPLIT. */
|
||||
if (hiop && ra_used(ir+1)) {
|
||||
type = ra_dest(as, ir+1, allow);
|
||||
rset_clear(allow, type);
|
||||
@@ -1151,8 +1168,9 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
||||
Reg tmp = RID_NONE;
|
||||
if ((ir->op2 & IRSLOAD_CONVERT))
|
||||
tmp = ra_scratch(as, t == IRT_INT ? RSET_FPR : RSET_GPR);
|
||||
lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
|
||||
irt_isint(ir->t) || irt_isaddr(ir->t));
|
||||
lj_assertA((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
|
||||
irt_isint(ir->t) || irt_isaddr(ir->t),
|
||||
"bad SLOAD type %d", irt_type(ir->t));
|
||||
dest = ra_dest(as, ir, (!LJ_SOFTFP && t == IRT_NUM) ? RSET_FPR : allow);
|
||||
rset_clear(allow, dest);
|
||||
base = ra_alloc1(as, REF_BASE, allow);
|
||||
@@ -1217,7 +1235,8 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
||||
IRRef args[4];
|
||||
RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
|
||||
RegSet drop = RSET_SCRATCH;
|
||||
lua_assert(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL));
|
||||
lj_assertA(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL),
|
||||
"bad CNEW/CNEWI operands");
|
||||
|
||||
as->gcsteps++;
|
||||
if (ra_hasreg(ir->r))
|
||||
@@ -1229,10 +1248,10 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
||||
/* Initialize immutable cdata object. */
|
||||
if (ir->o == IR_CNEWI) {
|
||||
int32_t ofs = sizeof(GCcdata);
|
||||
lua_assert(sz == 4 || sz == 8);
|
||||
lj_assertA(sz == 4 || sz == 8, "bad CNEWI size %d", sz);
|
||||
if (sz == 8) {
|
||||
ofs += 4; ir++;
|
||||
lua_assert(ir->o == IR_HIOP);
|
||||
lj_assertA(ir->o == IR_HIOP, "expected HIOP for CNEWI");
|
||||
}
|
||||
for (;;) {
|
||||
Reg r = ra_alloc1(as, ir->op2, allow);
|
||||
@@ -1267,8 +1286,6 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
||||
ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
|
||||
ra_releasetmp(as, ASMREF_TMP1));
|
||||
}
|
||||
#else
|
||||
#define asm_cnew(as, ir) ((void)0)
|
||||
#endif
|
||||
|
||||
/* -- Write barriers ------------------------------------------------------ */
|
||||
@@ -1300,7 +1317,7 @@ static void asm_obar(ASMState *as, IRIns *ir)
|
||||
MCLabel l_end;
|
||||
Reg obj, val, tmp;
|
||||
/* No need for other object barriers (yet). */
|
||||
lua_assert(IR(ir->op1)->o == IR_UREFC);
|
||||
lj_assertA(IR(ir->op1)->o == IR_UREFC, "bad OBAR type");
|
||||
ra_evictset(as, RSET_SCRATCH);
|
||||
l_end = emit_label(as);
|
||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||
@@ -1363,8 +1380,6 @@ static void asm_callround(ASMState *as, IRIns *ir, int id)
|
||||
|
||||
static void asm_fpmath(ASMState *as, IRIns *ir)
|
||||
{
|
||||
if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir))
|
||||
return;
|
||||
if (ir->op2 <= IRFPM_TRUNC)
|
||||
asm_callround(as, ir, ir->op2);
|
||||
else if (ir->op2 == IRFPM_SQRT)
|
||||
@@ -1372,8 +1387,6 @@ static void asm_fpmath(ASMState *as, IRIns *ir)
|
||||
else
|
||||
asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2);
|
||||
}
|
||||
#else
|
||||
#define asm_fpmath(as, ir) lua_assert(0)
|
||||
#endif
|
||||
|
||||
static int asm_swapops(ASMState *as, IRRef lref, IRRef rref)
|
||||
@@ -1413,14 +1426,29 @@ static void asm_intop(ASMState *as, IRIns *ir, ARMIns ai)
|
||||
emit_dn(as, ai^m, dest, left);
|
||||
}
|
||||
|
||||
/* Try to drop cmp r, #0. */
|
||||
static ARMIns asm_drop_cmp0(ASMState *as, ARMIns ai)
|
||||
{
|
||||
if (as->flagmcp == as->mcp) {
|
||||
uint32_t cc = (as->mcp[1] >> 28);
|
||||
as->flagmcp = NULL;
|
||||
if (cc <= CC_NE) {
|
||||
as->mcp++;
|
||||
ai |= ARMI_S;
|
||||
} else if (cc == CC_GE) {
|
||||
*++as->mcp ^= ((CC_GE^CC_PL) << 28);
|
||||
ai |= ARMI_S;
|
||||
} else if (cc == CC_LT) {
|
||||
*++as->mcp ^= ((CC_LT^CC_MI) << 28);
|
||||
ai |= ARMI_S;
|
||||
} /* else: other conds don't work in general. */
|
||||
}
|
||||
return ai;
|
||||
}
|
||||
|
||||
static void asm_intop_s(ASMState *as, IRIns *ir, ARMIns ai)
|
||||
{
|
||||
if (as->flagmcp == as->mcp) { /* Drop cmp r, #0. */
|
||||
as->flagmcp = NULL;
|
||||
as->mcp++;
|
||||
ai |= ARMI_S;
|
||||
}
|
||||
asm_intop(as, ir, ai);
|
||||
asm_intop(as, ir, asm_drop_cmp0(as, ai));
|
||||
}
|
||||
|
||||
static void asm_intneg(ASMState *as, IRIns *ir, ARMIns ai)
|
||||
@@ -1492,22 +1520,11 @@ static void asm_mul(ASMState *as, IRIns *ir)
|
||||
#define asm_subov(as, ir) asm_sub(as, ir)
|
||||
#define asm_mulov(as, ir) asm_mul(as, ir)
|
||||
|
||||
#if LJ_SOFTFP
|
||||
#define asm_div(as, ir) lua_assert(0)
|
||||
#define asm_pow(as, ir) lua_assert(0)
|
||||
#define asm_abs(as, ir) lua_assert(0)
|
||||
#define asm_atan2(as, ir) lua_assert(0)
|
||||
#define asm_ldexp(as, ir) lua_assert(0)
|
||||
#else
|
||||
#define asm_div(as, ir) asm_fparith(as, ir, ARMI_VDIV_D)
|
||||
#define asm_pow(as, ir) asm_callid(as, ir, IRCALL_lj_vm_powi)
|
||||
#if !LJ_SOFTFP
|
||||
#define asm_fpdiv(as, ir) asm_fparith(as, ir, ARMI_VDIV_D)
|
||||
#define asm_abs(as, ir) asm_fpunary(as, ir, ARMI_VABS_D)
|
||||
#define asm_atan2(as, ir) asm_callid(as, ir, IRCALL_atan2)
|
||||
#define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp)
|
||||
#endif
|
||||
|
||||
#define asm_mod(as, ir) asm_callid(as, ir, IRCALL_lj_vm_modi)
|
||||
|
||||
static void asm_neg(ASMState *as, IRIns *ir)
|
||||
{
|
||||
#if !LJ_SOFTFP
|
||||
@@ -1521,20 +1538,7 @@ static void asm_neg(ASMState *as, IRIns *ir)
|
||||
|
||||
static void asm_bitop(ASMState *as, IRIns *ir, ARMIns ai)
|
||||
{
|
||||
if (as->flagmcp == as->mcp) { /* Try to drop cmp r, #0. */
|
||||
uint32_t cc = (as->mcp[1] >> 28);
|
||||
as->flagmcp = NULL;
|
||||
if (cc <= CC_NE) {
|
||||
as->mcp++;
|
||||
ai |= ARMI_S;
|
||||
} else if (cc == CC_GE) {
|
||||
*++as->mcp ^= ((CC_GE^CC_PL) << 28);
|
||||
ai |= ARMI_S;
|
||||
} else if (cc == CC_LT) {
|
||||
*++as->mcp ^= ((CC_LT^CC_MI) << 28);
|
||||
ai |= ARMI_S;
|
||||
} /* else: other conds don't work with bit ops. */
|
||||
}
|
||||
ai = asm_drop_cmp0(as, ai);
|
||||
if (ir->op2 == 0) {
|
||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||
uint32_t m = asm_fuseopm(as, ai, ir->op1, RSET_GPR);
|
||||
@@ -1589,7 +1593,7 @@ static void asm_bitshift(ASMState *as, IRIns *ir, ARMShift sh)
|
||||
#define asm_bshr(as, ir) asm_bitshift(as, ir, ARMSH_LSR)
|
||||
#define asm_bsar(as, ir) asm_bitshift(as, ir, ARMSH_ASR)
|
||||
#define asm_bror(as, ir) asm_bitshift(as, ir, ARMSH_ROR)
|
||||
#define asm_brol(as, ir) lua_assert(0)
|
||||
#define asm_brol(as, ir) lj_assertA(0, "unexpected BROL")
|
||||
|
||||
static void asm_intmin_max(ASMState *as, IRIns *ir, int cc)
|
||||
{
|
||||
@@ -1664,8 +1668,8 @@ static void asm_min_max(ASMState *as, IRIns *ir, int cc, int fcc)
|
||||
asm_intmin_max(as, ir, cc);
|
||||
}
|
||||
|
||||
#define asm_min(as, ir) asm_min_max(as, ir, CC_GT, CC_HI)
|
||||
#define asm_max(as, ir) asm_min_max(as, ir, CC_LT, CC_LO)
|
||||
#define asm_min(as, ir) asm_min_max(as, ir, CC_GT, CC_PL)
|
||||
#define asm_max(as, ir) asm_min_max(as, ir, CC_LT, CC_LE)
|
||||
|
||||
/* -- Comparisons --------------------------------------------------------- */
|
||||
|
||||
@@ -1740,7 +1744,8 @@ static void asm_intcomp(ASMState *as, IRIns *ir)
|
||||
Reg left;
|
||||
uint32_t m;
|
||||
int cmpprev0 = 0;
|
||||
lua_assert(irt_isint(ir->t) || irt_isu32(ir->t) || irt_isaddr(ir->t));
|
||||
lj_assertA(irt_isint(ir->t) || irt_isu32(ir->t) || irt_isaddr(ir->t),
|
||||
"bad comparison data type %d", irt_type(ir->t));
|
||||
if (asm_swapops(as, lref, rref)) {
|
||||
Reg tmp = lref; lref = rref; rref = tmp;
|
||||
if (cc >= CC_GE) cc ^= 7; /* LT <-> GT, LE <-> GE */
|
||||
@@ -1857,7 +1862,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
||||
} else if ((ir-1)->o == IR_MIN || (ir-1)->o == IR_MAX) {
|
||||
as->curins--; /* Always skip the loword min/max. */
|
||||
if (uselo || usehi)
|
||||
asm_sfpmin_max(as, ir-1, (ir-1)->o == IR_MIN ? CC_HI : CC_LO);
|
||||
asm_sfpmin_max(as, ir-1, (ir-1)->o == IR_MIN ? CC_PL : CC_LE);
|
||||
return;
|
||||
#elif LJ_HASFFI
|
||||
} else if ((ir-1)->o == IR_CONV) {
|
||||
@@ -1909,10 +1914,11 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
||||
case IR_CNEWI:
|
||||
/* Nothing to do here. Handled by lo op itself. */
|
||||
break;
|
||||
default: lua_assert(0); break;
|
||||
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||
}
|
||||
#else
|
||||
UNUSED(as); UNUSED(ir); lua_assert(0);
|
||||
/* Unused without SOFTFP or FFI. */
|
||||
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1937,7 +1943,7 @@ static void asm_stack_check(ASMState *as, BCReg topslot,
|
||||
if (irp) {
|
||||
if (!ra_hasspill(irp->s)) {
|
||||
pbase = irp->r;
|
||||
lua_assert(ra_hasreg(pbase));
|
||||
lj_assertA(ra_hasreg(pbase), "base reg lost");
|
||||
} else if (allow) {
|
||||
pbase = rset_pickbot(allow);
|
||||
} else {
|
||||
@@ -1949,7 +1955,7 @@ static void asm_stack_check(ASMState *as, BCReg topslot,
|
||||
}
|
||||
emit_branch(as, ARMF_CC(ARMI_BL, CC_LS), exitstub_addr(as->J, exitno));
|
||||
k = emit_isk12(0, (int32_t)(8*topslot));
|
||||
lua_assert(k);
|
||||
lj_assertA(k, "slot offset %d does not fit in K12", 8*topslot);
|
||||
emit_n(as, ARMI_CMP^k, RID_TMP);
|
||||
emit_dnm(as, ARMI_SUB, RID_TMP, RID_TMP, pbase);
|
||||
emit_lso(as, ARMI_LDR, RID_TMP, RID_TMP,
|
||||
@@ -1986,7 +1992,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
||||
#if LJ_SOFTFP
|
||||
RegSet odd = rset_exclude(RSET_GPRODD, RID_BASE);
|
||||
Reg tmp;
|
||||
lua_assert(irref_isk(ref)); /* LJ_SOFTFP: must be a number constant. */
|
||||
/* LJ_SOFTFP: must be a number constant. */
|
||||
lj_assertA(irref_isk(ref), "unsplit FP op");
|
||||
tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.lo,
|
||||
rset_exclude(RSET_GPREVEN, RID_BASE));
|
||||
emit_lso(as, ARMI_STR, tmp, RID_BASE, ofs);
|
||||
@@ -2000,7 +2007,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
||||
} else {
|
||||
RegSet odd = rset_exclude(RSET_GPRODD, RID_BASE);
|
||||
Reg type;
|
||||
lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t) || irt_isinteger(ir->t));
|
||||
lj_assertA(irt_ispri(ir->t) || irt_isaddr(ir->t) || irt_isinteger(ir->t),
|
||||
"restore of IR type %d", irt_type(ir->t));
|
||||
if (!irt_ispri(ir->t)) {
|
||||
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPREVEN, RID_BASE));
|
||||
emit_lso(as, ARMI_STR, src, RID_BASE, ofs);
|
||||
@@ -2020,11 +2028,14 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
||||
}
|
||||
checkmclim(as);
|
||||
}
|
||||
lua_assert(map + nent == flinks);
|
||||
lj_assertA(map + nent == flinks, "inconsistent frames in snapshot");
|
||||
}
|
||||
|
||||
/* -- GC handling --------------------------------------------------------- */
|
||||
|
||||
/* Marker to prevent patching the GC check exit. */
|
||||
#define ARM_NOPATCH_GC_CHECK (ARMI_BIC|ARMI_K12)
|
||||
|
||||
/* Check GC threshold and do one or more GC steps. */
|
||||
static void asm_gc_check(ASMState *as)
|
||||
{
|
||||
@@ -2036,6 +2047,7 @@ static void asm_gc_check(ASMState *as)
|
||||
l_end = emit_label(as);
|
||||
/* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
|
||||
asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */
|
||||
*--as->mcp = ARM_NOPATCH_GC_CHECK;
|
||||
emit_n(as, ARMI_CMP|ARMI_K12|0, RID_RET);
|
||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||
args[1] = ASMREF_TMP2; /* MSize steps */
|
||||
@@ -2106,7 +2118,7 @@ static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
|
||||
rset_clear(allow, ra_dest(as, ir, allow));
|
||||
} else {
|
||||
Reg r = irp->r;
|
||||
lua_assert(ra_hasreg(r));
|
||||
lj_assertA(ra_hasreg(r), "base reg lost");
|
||||
rset_clear(allow, r);
|
||||
if (r != ir->r && !rset_test(as->freeset, r))
|
||||
ra_restore(as, regcost_ref(as->cost[r]));
|
||||
@@ -2128,7 +2140,7 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk)
|
||||
} else {
|
||||
/* Patch stack adjustment. */
|
||||
uint32_t k = emit_isk12(ARMI_ADD, spadj);
|
||||
lua_assert(k);
|
||||
lj_assertA(k, "stack adjustment %d does not fit in K12", spadj);
|
||||
p[-2] = (ARMI_ADD^k) | ARMF_D(RID_SP) | ARMF_N(RID_SP);
|
||||
}
|
||||
/* Patch exit branch. */
|
||||
@@ -2204,13 +2216,14 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
||||
/* Look for bl_cc exitstub, replace with b_cc target. */
|
||||
uint32_t ins = *p;
|
||||
if ((ins & 0x0f000000u) == 0x0b000000u && ins < 0xf0000000u &&
|
||||
((ins ^ (px-p)) & 0x00ffffffu) == 0) {
|
||||
((ins ^ (px-p)) & 0x00ffffffu) == 0 &&
|
||||
p[-1] != ARM_NOPATCH_GC_CHECK) {
|
||||
*p = (ins & 0xfe000000u) | (((target-p)-2) & 0x00ffffffu);
|
||||
cend = p+1;
|
||||
if (!cstart) cstart = p;
|
||||
}
|
||||
}
|
||||
lua_assert(cstart != NULL);
|
||||
lj_assertJ(cstart != NULL, "exit stub %d not found", exitno);
|
||||
lj_mcode_sync(cstart, cend);
|
||||
lj_mcode_patch(J, mcarea, 1);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user