mirror of
https://github.com/love2d/megasource.git
synced 2026-08-19 04:05:09 +02:00
Update LuaJIT to the latest 2.1.0 source (1d8b747)
This commit is contained in:
+1
-1
@@ -167,7 +167,7 @@ endif()
|
|||||||
|
|
||||||
set(MEGA_ZLIB_VER "1.2.11")
|
set(MEGA_ZLIB_VER "1.2.11")
|
||||||
set(MEGA_LUA51_VER "5.1.5")
|
set(MEGA_LUA51_VER "5.1.5")
|
||||||
set(MEGA_LUAJIT_VER "2.1.0-0bee44c")
|
set(MEGA_LUAJIT_VER "2.1.0-1d8b747")
|
||||||
set(MEGA_LIBOGG_VER "1.3.2")
|
set(MEGA_LIBOGG_VER "1.3.2")
|
||||||
set(MEGA_LIBVORBIS_VER "1.3.5")
|
set(MEGA_LIBVORBIS_VER "1.3.5")
|
||||||
set(MEGA_LIBTHEORA_VER "1.1.1")
|
set(MEGA_LIBTHEORA_VER "1.1.1")
|
||||||
|
|||||||
@@ -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-2017 Mike Pall. All rights reserved.
|
Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
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: ]
|
[ 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
|
This is a version (aka dlmalloc) of malloc/free/realloc written by
|
||||||
Doug Lea and released to the public domain, as explained at
|
Doug Lea and released to the public domain, as explained at
|
||||||
http://creativecommons.org/licenses/publicdomain
|
https://creativecommons.org/licenses/publicdomain
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
# For MSVC, please follow the instructions given in src/msvcbuild.bat.
|
# 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.
|
# For MinGW and Cygwin, cd to src and run make with the Makefile there.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
# Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
MAJVER= 2
|
MAJVER= 2
|
||||||
@@ -75,7 +75,7 @@ SYMLINK= ln -sf
|
|||||||
INSTALL_X= install -m 0755
|
INSTALL_X= install -m 0755
|
||||||
INSTALL_F= install -m 0644
|
INSTALL_F= install -m 0644
|
||||||
UNINSTALL= $(RM)
|
UNINSTALL= $(RM)
|
||||||
LDCONFIG= ldconfig -n
|
LDCONFIG= ldconfig -n 2>/dev/null
|
||||||
SED_PC= sed -e "s|^prefix=.*|prefix=$(PREFIX)|" \
|
SED_PC= sed -e "s|^prefix=.*|prefix=$(PREFIX)|" \
|
||||||
-e "s|^multilib=.*|multilib=$(MULTILIB)|"
|
-e "s|^multilib=.*|multilib=$(MULTILIB)|"
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ install: $(INSTALL_DEP)
|
|||||||
$(RM) $(INSTALL_DYN) $(INSTALL_SHORT1) $(INSTALL_SHORT2)
|
$(RM) $(INSTALL_DYN) $(INSTALL_SHORT1) $(INSTALL_SHORT2)
|
||||||
cd src && test -f $(FILE_SO) && \
|
cd src && test -f $(FILE_SO) && \
|
||||||
$(INSTALL_X) $(FILE_SO) $(INSTALL_DYN) && \
|
$(INSTALL_X) $(FILE_SO) $(INSTALL_DYN) && \
|
||||||
$(LDCONFIG) $(INSTALL_LIB) && \
|
( $(LDCONFIG) $(INSTALL_LIB) || : ) && \
|
||||||
$(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT1) && \
|
$(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT1) && \
|
||||||
$(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT2) || :
|
$(SYMLINK) $(INSTALL_SONAME) $(INSTALL_SHORT2) || :
|
||||||
cd etc && $(INSTALL_F) $(FILE_MAN) $(INSTALL_MAN)
|
cd etc && $(INSTALL_F) $(FILE_MAN) $(INSTALL_MAN)
|
||||||
|
|||||||
+2
-2
@@ -3,9 +3,9 @@ README for LuaJIT 2.1.0-beta3
|
|||||||
|
|
||||||
LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.
|
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-2017 Mike Pall.
|
LuaJIT is Copyright (C) 2005-2020 Mike Pall.
|
||||||
LuaJIT is free software, released under the MIT license.
|
LuaJIT is free software, released under the MIT license.
|
||||||
See full Copyright Notice in the COPYRIGHT file or in luajit.h.
|
See full Copyright Notice in the COPYRIGHT file or in luajit.h.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2004-2018 Mike Pall.
|
/* Copyright (C) 2004-2020 Mike Pall.
|
||||||
*
|
*
|
||||||
* You are welcome to use the general ideas of this design for your own sites.
|
* 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.
|
* But please do not steal the stylesheet, the layout or the color scheme.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2004-2018 Mike Pall.
|
/* Copyright (C) 2004-2020 Mike Pall.
|
||||||
*
|
*
|
||||||
* You are welcome to use the general ideas of this design for your own sites.
|
* 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.
|
* But please do not steal the stylesheet, the layout or the color scheme.
|
||||||
|
|||||||
@@ -1,882 +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="Copyright" content="Copyright (C) 2005-2018">
|
|
||||||
<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.5</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-beta3">LuaJIT 2.1.0-beta3 — 2017-05-01</h2>
|
|
||||||
<ul>
|
|
||||||
<li>Rewrite memory block allocator.</li>
|
|
||||||
<li>Add various extension from Lua 5.2/5.3.</li>
|
|
||||||
<li>Remove old Lua 5.0 compatibility defines.</li>
|
|
||||||
<li>Set arg table before evaluating <tt>LUA_INIT</tt> and <tt>-e</tt> chunks.</li>
|
|
||||||
<li>Fix FOLD rules for <tt>math.abs()</tt> and FP negation.</li>
|
|
||||||
<li>Fix soft-float <tt>math.abs()</tt> and negation.</li>
|
|
||||||
<li>Fix formatting of some small denormals at low precision.</li>
|
|
||||||
<li>LJ_GC64: Add JIT compiler support.</li>
|
|
||||||
<li>x64/LJ_GC64: Add JIT compiler backend.</li>
|
|
||||||
<li>x86/x64: Generate BMI2 shifts and rotates, if available.</li>
|
|
||||||
<li>Windows/x86: Add full exception interoperability.</li>
|
|
||||||
<li>ARM64: Add big-endian support.</li>
|
|
||||||
<li>ARM64: Add JIT compiler backend.</li>
|
|
||||||
<li>MIPS: Fix <tt>TSETR</tt> barrier.</li>
|
|
||||||
<li>MIPS: Support MIPS16 interlinking.</li>
|
|
||||||
<li>MIPS soft-float: Fix code generation for <tt>HREF</tt>.</li>
|
|
||||||
<li>MIPS64: Add MIPS64 hard-float JIT compiler backend.</li>
|
|
||||||
<li>MIPS64: Add MIPS64 hard-float/soft-float support to interpreter.</li>
|
|
||||||
<li>FFI: Compile bitfield loads/stores.</li>
|
|
||||||
<li>Various fixes common with the 2.0 branch.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 id="LuaJIT-2.1.0-beta2">LuaJIT 2.1.0-beta2 — 2016-03-03</h2>
|
|
||||||
<ul>
|
|
||||||
<li>Enable trace stitching.</li>
|
|
||||||
<li>Use internal implementation for converting FP numbers to strings.</li>
|
|
||||||
<li>Parse Unicode escape <tt>'\u{XX...}'</tt> in string literals.</li>
|
|
||||||
<li>Add MIPS soft-float support.</li>
|
|
||||||
<li>Switch MIPS port to dual-number mode.</li>
|
|
||||||
<li>x86/x64: Add support for AES-NI, AVX and AVX2 to DynASM.</li>
|
|
||||||
<li>FFI: Add <tt>ssize_t</tt> declaration.</li>
|
|
||||||
<li>FFI: Parse <tt>#line NN</tt> and <tt>#NN</tt>.</li>
|
|
||||||
<li>Various minor fixes.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<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 binary number literals (<tt>0bxxx</tt>).</li>
|
|
||||||
</ul></li>
|
|
||||||
<li>Improvements to the JIT compiler:
|
|
||||||
<ul>
|
|
||||||
<li>Add trace stitching (disabled for now).</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>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>
|
|
||||||
</ul></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="major" style="background: #ffffd0;">
|
|
||||||
<h2 id="LuaJIT-2.0.5">LuaJIT 2.0.5 — 2017-05-01</h2>
|
|
||||||
<ul>
|
|
||||||
<li>Add workaround for MSVC 2015 stdio changes.</li>
|
|
||||||
<li>Limit mcode alloc probing, depending on the available pool size.</li>
|
|
||||||
<li>Fix overly restrictive range calculation in mcode allocation.</li>
|
|
||||||
<li>Fix out-of-scope goto handling in parser.</li>
|
|
||||||
<li>Remove internal <tt>__mode = "K"</tt> and replace with safe check.</li>
|
|
||||||
<li>Add "proto" field to <tt>jit.util.funcinfo()</tt>.</li>
|
|
||||||
<li>Fix GC step size calculation.</li>
|
|
||||||
<li>Initialize <tt>uv->immutable</tt> for upvalues of loaded chunks.</li>
|
|
||||||
<li>Fix for cdata vs. non-cdata arithmetics/comparisons.</li>
|
|
||||||
<li>Drop leftover regs in 'for' iterator assignment, too.</li>
|
|
||||||
<li>Fix PHI remarking in SINK pass.</li>
|
|
||||||
<li>Don't try to record outermost <tt>pcall()</tt> return to lower frame.</li>
|
|
||||||
<li>Add guard for obscure aliasing between open upvalues and SSA slots.</li>
|
|
||||||
<li>Remove assumption that <tt>lj_math_random_step()</tt> doesn't clobber FPRs.</li>
|
|
||||||
<li>Fix handling of non-numeric strings in arithmetic coercions.</li>
|
|
||||||
<li>Fix recording of <tt>select(n, ...)</tt> with off-trace varargs</li>
|
|
||||||
<li>Fix install for cross-builds.</li>
|
|
||||||
<li>Don't allocate unused 2nd result register in JIT compiler backend.</li>
|
|
||||||
<li>Drop marks from replayed instructions when sinking.</li>
|
|
||||||
<li>Fix unsinking check.</li>
|
|
||||||
<li>Properly handle OOM in <tt>trace_save()</tt>.</li>
|
|
||||||
<li>Limit number of arguments given to <tt>io.lines()</tt> and <tt>fp:lines()</tt>.</li>
|
|
||||||
<li>Fix narrowing of <tt>TOBIT</tt>.</li>
|
|
||||||
<li>OSX: Fix build with recent XCode.</li>
|
|
||||||
<li>x86/x64: Don't spill an explicit <tt>REF_BASE</tt> in the IR.</li>
|
|
||||||
<li>x86/x64: Fix instruction length decoder.</li>
|
|
||||||
<li>x86/x64: Search for exit jumps with instruction length decoder.</li>
|
|
||||||
<li>ARM: Fix <tt>BLX</tt> encoding for Thumb interworking calls.</li>
|
|
||||||
<li>MIPS: Don't use <tt>RID_GP</tt> as a scratch register.</li>
|
|
||||||
<li>MIPS: Fix emitted code for U32 to float conversion.</li>
|
|
||||||
<li>MIPS: Backport workaround for compact unwind tables.</li>
|
|
||||||
<li>MIPS: Fix cross-endian jit.bcsave.</li>
|
|
||||||
<li>MIPS: Fix <tt>BC_ISNEXT</tt> fallback path.</li>
|
|
||||||
<li>MIPS: Fix use of ffgccheck delay slots in interpreter.</li>
|
|
||||||
<li>FFI: Fix FOLD rules for <tt>int64_t</tt> comparisons.</li>
|
|
||||||
<li>FFI: Fix SPLIT pass for <tt>CONV i64.u64</tt>.</li>
|
|
||||||
<li>FFI: Fix <tt>ipairs()</tt> recording.</li>
|
|
||||||
<li>FFI: Don't propagate qualifiers into subtypes of complex.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<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-2018
|
|
||||||
<span class="noprint">
|
|
||||||
·
|
|
||||||
<a href="contact.html">Contact</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -3,14 +3,14 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Contact</title>
|
<title>Contact</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>Contact</h1>
|
<h1>Contact</h1>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -45,28 +45,23 @@
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<p>
|
<p>
|
||||||
If you want to report bugs, propose fixes or suggest enhancements,
|
If you want to report bugs, propose fixes or suggest enhancements,
|
||||||
please use the
|
please use the
|
||||||
<a href="https://github.com/LuaJIT/LuaJIT/issues">GitHub issue tracker</a>.
|
<a href="https://github.com/LuaJIT/LuaJIT/issues"><span class="ext">»</span> GitHub issue tracker</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Please send general questions to the
|
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>
|
||||||
<p>
|
<p>
|
||||||
You can also send any questions you have directly to me:
|
You can also send any questions you have directly to me:
|
||||||
@@ -92,7 +87,7 @@ xD("fyZKB8xv\"FJytmz8.KAB0u52D")
|
|||||||
<h2>Copyright</h2>
|
<h2>Copyright</h2>
|
||||||
<p>
|
<p>
|
||||||
All documentation is
|
All documentation is
|
||||||
Copyright © 2005-2018 Mike Pall.
|
Copyright © 2005-2020 Mike Pall.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
@@ -100,7 +95,7 @@ Copyright © 2005-2018 Mike Pall.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Lua/C API Extensions</title>
|
<title>Lua/C API Extensions</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>Lua/C API Extensions</h1>
|
<h1>Lua/C API Extensions</h1>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -45,17 +45,12 @@
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
@@ -178,7 +173,7 @@ Also note that this mechanism is not without overhead.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>FFI Library</title>
|
<title>FFI Library</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>FFI Library</h1>
|
<h1>FFI Library</h1>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -45,17 +45,12 @@
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
@@ -321,7 +316,7 @@ without undue conversion penalties.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>ffi.* API Functions</title>
|
<title>ffi.* API Functions</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -15,7 +15,7 @@ td.abiparam { font-weight: bold; width: 6em; }
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1><tt>ffi.*</tt> API Functions</h1>
|
<h1><tt>ffi.*</tt> API Functions</h1>
|
||||||
@@ -24,7 +24,7 @@ td.abiparam { font-weight: bold; width: 6em; }
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -50,17 +50,12 @@ td.abiparam { font-weight: bold; width: 6em; }
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
@@ -260,7 +255,7 @@ contents of an <tt>__index</tt> table (if any) may be modified
|
|||||||
afterwards. The associated metatable automatically applies to all uses
|
afterwards. The associated metatable automatically applies to all uses
|
||||||
of this type, no matter how the objects are created or where they
|
of this type, no matter how the objects are created or where they
|
||||||
originate from. Note that pre-defined operations on types have
|
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>
|
||||||
<p>
|
<p>
|
||||||
All standard Lua metamethods are implemented. These are called directly,
|
All standard Lua metamethods are implemented. These are called directly,
|
||||||
@@ -561,7 +556,7 @@ named <tt>i</tt>.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>FFI Semantics</title>
|
<title>FFI Semantics</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -15,7 +15,7 @@ td.convop { font-style: italic; width: 40%; }
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>FFI Semantics</h1>
|
<h1>FFI Semantics</h1>
|
||||||
@@ -24,7 +24,7 @@ td.convop { font-style: italic; width: 40%; }
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -50,17 +50,12 @@ td.convop { font-style: italic; width: 40%; }
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
@@ -677,7 +672,7 @@ through unions is explicitly detected and allowed.
|
|||||||
<a href="ext_ffi_api.html#ffi_new">constructor</a>. This is equivalent
|
<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
|
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
|
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
|
use <tt>ffi.new</tt> inside of it, since calling <tt>ct(...)</tt> would
|
||||||
cause infinite recursion.</li>
|
cause infinite recursion.</li>
|
||||||
|
|
||||||
@@ -863,7 +858,7 @@ place of a type, you'd need to use <tt>ffi.typeof("int")</tt> instead.
|
|||||||
<p>
|
<p>
|
||||||
The main use for parameterized types are libraries implementing abstract
|
The main use for parameterized types are libraries implementing abstract
|
||||||
data types
|
data types
|
||||||
(<a href="https://www.freelists.org/post/luajit/ffi-type-of-pointer-to,8">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.
|
similar to what can be achieved with C++ template metaprogramming.
|
||||||
Another use case are derived types of anonymous structs, which avoids
|
Another use case are derived types of anonymous structs, which avoids
|
||||||
pollution of the global struct namespace.
|
pollution of the global struct namespace.
|
||||||
@@ -1224,7 +1219,7 @@ suboptimal performance, especially when used in inner loops:
|
|||||||
<li>Table initializers.</li>
|
<li>Table initializers.</li>
|
||||||
<li>Initialization of nested <tt>struct</tt>/<tt>union</tt> types.</li>
|
<li>Initialization of nested <tt>struct</tt>/<tt>union</tt> types.</li>
|
||||||
<li>Non-default initialization of VLA/VLS or large C types
|
<li>Non-default initialization of VLA/VLS or large C types
|
||||||
(> 128 bytes or > 16 array elements.</li>
|
(> 128 bytes or > 16 array elements).</li>
|
||||||
<li>Bitfield initializations.</li>
|
<li>Bitfield initializations.</li>
|
||||||
<li>Pointer differences for element sizes that are not a power of
|
<li>Pointer differences for element sizes that are not a power of
|
||||||
two.</li>
|
two.</li>
|
||||||
@@ -1251,7 +1246,7 @@ compiled.</li>
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>FFI Tutorial</title>
|
<title>FFI Tutorial</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -17,7 +17,7 @@ td.idiomlua b { font-weight: normal; color: #2142bf; }
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>FFI Tutorial</h1>
|
<h1>FFI Tutorial</h1>
|
||||||
@@ -26,7 +26,7 @@ td.idiomlua b { font-weight: normal; color: #2142bf; }
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -52,17 +52,12 @@ td.idiomlua b { font-weight: normal; color: #2142bf; }
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
@@ -221,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>
|
<h2 id="zlib">Accessing the zlib Compression Library</h2>
|
||||||
<p>
|
<p>
|
||||||
The following code shows how to access the <a
|
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
|
We'll define two convenience wrapper functions that take a string and
|
||||||
compress or uncompress it to another string:
|
compress or uncompress it to another string:
|
||||||
</p>
|
</p>
|
||||||
@@ -304,7 +299,7 @@ comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any
|
|||||||
missing standard prefixes/suffixes, we can simply load the
|
missing standard prefixes/suffixes, we can simply load the
|
||||||
<tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and
|
<tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and
|
||||||
you'll have to download it first from the
|
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.os</tt> makes sure we pass the right name to
|
||||||
<tt>ffi.load()</tt>.
|
<tt>ffi.load()</tt>.
|
||||||
</p>
|
</p>
|
||||||
@@ -592,7 +587,7 @@ it to a local variable in the function scope is unnecessary.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>jit.* Library</title>
|
<title>jit.* Library</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1><tt>jit.*</tt> Library</h1>
|
<h1><tt>jit.*</tt> Library</h1>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -45,17 +45,12 @@
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
@@ -190,7 +185,7 @@ if you want to know more.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Profiler</title>
|
<title>Profiler</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>Profiler</h1>
|
<h1>Profiler</h1>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -45,17 +45,12 @@
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
@@ -354,7 +349,7 @@ use.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Extensions</title>
|
<title>Extensions</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -27,7 +27,7 @@ td.excinterop {
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>Extensions</h1>
|
<h1>Extensions</h1>
|
||||||
@@ -36,7 +36,7 @@ td.excinterop {
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -62,25 +62,20 @@ td.excinterop {
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<p>
|
<p>
|
||||||
LuaJIT is fully upwards-compatible with Lua 5.1. It supports all
|
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
|
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>.
|
functions</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -104,7 +99,7 @@ LuaJIT comes with several built-in extension modules:
|
|||||||
<h3 id="bit"><tt>bit.*</tt> — Bitwise operations</h3>
|
<h3 id="bit"><tt>bit.*</tt> — Bitwise operations</h3>
|
||||||
<p>
|
<p>
|
||||||
LuaJIT supports all bitwise operations as defined by
|
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>
|
</p>
|
||||||
<pre class="code">
|
<pre class="code">
|
||||||
bit.tobit bit.tohex bit.bnot bit.band bit.bor bit.bxor
|
bit.tobit bit.tohex bit.bnot bit.band bit.bor bit.bxor
|
||||||
@@ -113,7 +108,7 @@ bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap
|
|||||||
<p>
|
<p>
|
||||||
This module is a LuaJIT built-in — you don't need to download or
|
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
|
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
|
The FFI adds support for
|
||||||
<a href="ext_ffi_semantics.html#cdata_arith">64 bit bitwise operations</a>,
|
<a href="ext_ffi_semantics.html#cdata_arith">64 bit bitwise operations</a>,
|
||||||
using the same API functions.
|
using the same API functions.
|
||||||
@@ -413,7 +408,7 @@ the toolchain used to compile LuaJIT:
|
|||||||
</tr>
|
</tr>
|
||||||
<tr class="even">
|
<tr class="even">
|
||||||
<td class="excplatform">Windows/x64</td>
|
<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>
|
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="odd">
|
<tr class="odd">
|
||||||
@@ -475,7 +470,7 @@ C++ destructors.</li>
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
+48
-29
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Frequently Asked Questions (FAQ)</title>
|
<title>Frequently Asked Questions (FAQ)</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -13,7 +13,7 @@ dd { margin-left: 1.5em; }
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>Frequently Asked Questions (FAQ)</h1>
|
<h1>Frequently Asked Questions (FAQ)</h1>
|
||||||
@@ -22,7 +22,7 @@ dd { margin-left: 1.5em; }
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -48,67 +48,62 @@ dd { margin-left: 1.5em; }
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a class="current" href="faq.html">FAQ</a>
|
<a class="current" href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<dl>
|
<dl id="info">
|
||||||
<dt>Q: Where can I learn more about LuaJIT and Lua?</dt>
|
<dt>Q: Where can I learn more about LuaJIT and Lua?</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<ul style="padding: 0;">
|
<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>
|
related to LuaJIT.</li>
|
||||||
<li>The <a href="http://wiki.luajit.org/"><span class="ext">»</span> LuaJIT wiki</a> gathers community
|
<li>The <a href="http://wiki.luajit.org/"><span class="ext">»</span> LuaJIT wiki</a> gathers community
|
||||||
resources about LuaJIT.</li>
|
resources about LuaJIT.</li>
|
||||||
<li>News about Lua itself can be found at the
|
<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
|
The mailing list archives are worth checking out for older postings
|
||||||
about LuaJIT.</li>
|
about LuaJIT.</li>
|
||||||
<li>The <a href="http://lua.org"><span class="ext">»</span> main Lua.org site</a> has complete
|
<li>The <a href="https://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
|
<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>
|
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>
|
<li>The community-managed <a href="http://lua-users.org/wiki/"><span class="ext">»</span> Lua Wiki</a>
|
||||||
has information about diverse topics.</li>
|
has information about diverse topics.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl>
|
<dl id="tech">
|
||||||
<dt>Q: Where can I learn more about the compiler technology used by LuaJIT?</dt>
|
<dt>Q: Where can I learn more about the compiler technology used by LuaJIT?</dt>
|
||||||
<dd>
|
<dd>
|
||||||
I'm planning to write more documentation about the internals of LuaJIT.
|
I'm planning to write more documentation about the internals of LuaJIT.
|
||||||
In the meantime, please use the following Google Scholar searches
|
In the meantime, please use the following Google Scholar searches
|
||||||
to find relevant papers:<br>
|
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="https://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="https://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="https://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="https://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>
|
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://article.gmane.org/gmane.comp.lang.lua.general/58908"><span class="ext">»</span> innovative features in LuaJIT</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. :-)
|
And, you know, reading the source is of course the only way to enlightenment. :-)
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl>
|
<dl id="arg">
|
||||||
<dt>Q: Why do I get this error: "attempt to index global 'arg' (a nil value)"?<br>
|
<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>
|
Q: My vararg functions fail after switching to LuaJIT!</dt>
|
||||||
<dd>LuaJIT is compatible to the Lua 5.1 language standard. It doesn't
|
<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
|
support the implicit <tt>arg</tt> parameter for old-style vararg
|
||||||
functions from Lua 5.0.<br>Please convert your code to the
|
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>
|
vararg syntax</a>.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl>
|
<dl id="x87">
|
||||||
<dt>Q: Why do I get this error: "bad FPU precision"?<br>
|
<dt>Q: Why do I get this error: "bad FPU precision"?<br>
|
||||||
<dt>Q: I get weird behavior after initializing Direct3D.<br>
|
<dt>Q: I get weird behavior after initializing Direct3D.<br>
|
||||||
<dt>Q: Some FPU operations crash after I load a Delphi DLL.<br>
|
<dt>Q: Some FPU operations crash after I load a Delphi DLL.<br>
|
||||||
@@ -130,7 +125,7 @@ Please check the Delphi docs for the Set8087CW method.
|
|||||||
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl>
|
<dl id="ctrlc">
|
||||||
<dt>Q: Sometimes Ctrl-C fails to stop my Lua program. Why?</dt>
|
<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
|
<dd>The interrupt signal handler sets a Lua debug hook. But this is
|
||||||
currently ignored by compiled code (this will eventually be fixed). If
|
currently ignored by compiled code (this will eventually be fixed). If
|
||||||
@@ -141,7 +136,31 @@ twice to get stop your program. That's similar to when it's stuck
|
|||||||
running inside a C function under the Lua interpreter.</dd>
|
running inside a C function under the Lua interpreter.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl>
|
<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>
|
||||||
|
|
||||||
|
Relatedly, <b>loading untrusted bytecode is not safe!</b> 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>
|
||||||
|
|
||||||
|
In general, the only promising approach is to sandbox Lua code at the
|
||||||
|
process level and not the VM level.<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>.
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<dl id="patches">
|
||||||
<dt>Q: Why doesn't my favorite power-patch for Lua apply against LuaJIT?</dt>
|
<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
|
<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
|
in common with Lua anymore. Also, if the patch introduces changes to
|
||||||
@@ -152,7 +171,7 @@ can use source transformations or use wrapper or proxy functions.
|
|||||||
The compiler will happily optimize away such indirections.</dd>
|
The compiler will happily optimize away such indirections.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl>
|
<dl id="arch">
|
||||||
<dt>Q: Lua runs everywhere. Why doesn't LuaJIT support my CPU?</dt>
|
<dt>Q: Lua runs everywhere. Why doesn't LuaJIT support my CPU?</dt>
|
||||||
<dd>Because it's a compiler — it needs to generate native
|
<dd>Because it's a compiler — it needs to generate native
|
||||||
machine code. This means the code generator must be ported to each
|
machine code. This means the code generator must be ported to each
|
||||||
@@ -163,7 +182,7 @@ architectures. Other architectures will follow based on sufficient user
|
|||||||
demand and/or sponsoring.</dd>
|
demand and/or sponsoring.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl>
|
<dl id="when">
|
||||||
<dt>Q: When will feature X be added? When will the next version be released?</dt>
|
<dt>Q: When will feature X be added? When will the next version be released?</dt>
|
||||||
<dd>When it's ready.<br>
|
<dd>When it's ready.<br>
|
||||||
C'mon, it's open source — I'm doing it on my own time and you're
|
C'mon, it's open source — I'm doing it on my own time and you're
|
||||||
@@ -175,7 +194,7 @@ the development of certain features, if they are important to you.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Installation</title>
|
<title>Installation</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -38,7 +38,7 @@ td.compatno {
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>Installation</h1>
|
<h1>Installation</h1>
|
||||||
@@ -47,7 +47,7 @@ td.compatno {
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a class="current" href="install.html">Installation</a>
|
<a class="current" href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -73,17 +73,12 @@ td.compatno {
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
@@ -250,7 +245,7 @@ Obviously the prefixes given during build and installation need to be the same.
|
|||||||
<p>
|
<p>
|
||||||
Either install one of the open source SDKs
|
Either install one of the open source SDKs
|
||||||
(<a href="http://mingw.org/"><span class="ext">»</span> MinGW</a> or
|
(<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.
|
GCC plus the required development headers.
|
||||||
Or install Microsoft's Visual Studio (MSVC).
|
Or install Microsoft's Visual Studio (MSVC).
|
||||||
</p>
|
</p>
|
||||||
@@ -393,7 +388,7 @@ make CROSS=mips-linux- TARGET_CFLAGS="-mips64r2 -mabi=64"
|
|||||||
make CROSS=mipsel-linux- TARGET_CFLAGS="-mips64r2 -mabi=64"
|
make CROSS=mipsel-linux- TARGET_CFLAGS="-mips64r2 -mabi=64"
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
You can cross-compile for <b id="android">Android</b> using the <a href="http://developer.android.com/ndk/"><span class="ext">»</span> Android NDK</a>.
|
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
|
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.
|
desired target platform. E.g. Android 4.1 corresponds to ABI level 16.
|
||||||
</p>
|
</p>
|
||||||
@@ -417,7 +412,7 @@ make HOST_CC="gcc -m32" CROSS=$NDKCROSS \
|
|||||||
TARGET_LD=$NDKCC
|
TARGET_LD=$NDKCC
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
You can cross-compile for <b id="ios">iOS 3.0+</b> (iPhone/iPad) using the <a href="http://developer.apple.com/ios/"><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>
|
||||||
<p style="font-size: 8pt;">
|
<p style="font-size: 8pt;">
|
||||||
Note: <b>the JIT compiler is disabled for iOS</b>, because regular iOS Apps
|
Note: <b>the JIT compiler is disabled for iOS</b>, because regular iOS Apps
|
||||||
@@ -552,7 +547,7 @@ Make sure the <tt>jit</tt> library is loaded or the JIT compiler
|
|||||||
will not be activated.</li>
|
will not be activated.</li>
|
||||||
<li>The <tt>bit.*</tt> module for bitwise operations
|
<li>The <tt>bit.*</tt> module for bitwise operations
|
||||||
is already built-in. There's no need to statically link
|
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>
|
</ul>
|
||||||
|
|
||||||
<h2 id="distro">Hints for Distribution Maintainers</h2>
|
<h2 id="distro">Hints for Distribution Maintainers</h2>
|
||||||
@@ -619,7 +614,7 @@ to me (the upstream) and not you (the package maintainer), anyway.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>LuaJIT</title>
|
<title>LuaJIT</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -95,7 +95,7 @@ table.feature small {
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>LuaJIT</h1>
|
<h1>LuaJIT</h1>
|
||||||
@@ -104,7 +104,7 @@ table.feature small {
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a class="current" href="luajit.html">LuaJIT</a>
|
<a class="current" href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -130,29 +130,24 @@ table.feature small {
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<p>
|
<p>
|
||||||
LuaJIT is a <b>Just-In-Time Compiler</b> (JIT) for the
|
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.
|
Lua is a powerful, dynamic and light-weight programming language.
|
||||||
It may be embedded or used as a general-purpose, stand-alone language.
|
It may be embedded or used as a general-purpose, stand-alone language.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
LuaJIT is Copyright © 2005-2018 Mike Pall, released under the
|
LuaJIT is Copyright © 2005-2020 Mike Pall, released under the
|
||||||
<a href="http://www.opensource.org/licenses/mit-license.php"><span class="ext">»</span> MIT open source license</a>.
|
<a href="https://www.opensource.org/licenses/mit-license.php"><span class="ext">»</span> MIT open source license</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
</p>
|
</p>
|
||||||
@@ -193,7 +188,7 @@ LuaJIT has been successfully used as a <b>scripting middleware</b> in
|
|||||||
games, appliances, network and graphics apps, numerical simulations,
|
games, appliances, network and graphics apps, numerical simulations,
|
||||||
trading platforms and many other specialty applications. It scales from
|
trading platforms and many other specialty applications. It scales from
|
||||||
embedded devices, smartphones, desktops up to server farms. It combines
|
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>.
|
and an unmatched <b>low memory footprint</b>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -225,7 +220,7 @@ Please select a sub-topic in the navigation bar to learn more about LuaJIT.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Running LuaJIT</title>
|
<title>Running LuaJIT</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -32,7 +32,7 @@ td.param_default {
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>Running LuaJIT</h1>
|
<h1>Running LuaJIT</h1>
|
||||||
@@ -41,7 +41,7 @@ td.param_default {
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -67,17 +67,12 @@ td.param_default {
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="status.html">Status</a>
|
<a href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
@@ -94,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.
|
version of the regular <tt>lua</tt> stand-alone executable.
|
||||||
It supports the same basic options, too. <tt>luajit -h</tt>
|
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
|
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.
|
for details.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -298,7 +293,7 @@ Here are the parameters and their default settings:
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Status</title>
|
<title>Status</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2018">
|
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -13,7 +13,7 @@ ul li { padding-bottom: 0.3em; }
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="site">
|
<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>
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1>Status</h1>
|
<h1>Status</h1>
|
||||||
@@ -22,7 +22,7 @@ ul li { padding-bottom: 0.3em; }
|
|||||||
<ul><li>
|
<ul><li>
|
||||||
<a href="luajit.html">LuaJIT</a>
|
<a href="luajit.html">LuaJIT</a>
|
||||||
<ul><li>
|
<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>
|
</li><li>
|
||||||
<a href="install.html">Installation</a>
|
<a href="install.html">Installation</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
@@ -48,17 +48,12 @@ ul li { padding-bottom: 0.3em; }
|
|||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a class="current" href="status.html">Status</a>
|
<a class="current" href="status.html">Status</a>
|
||||||
<ul><li>
|
|
||||||
<a href="changes.html">Changes</a>
|
|
||||||
</li></ul>
|
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="faq.html">FAQ</a>
|
<a href="faq.html">FAQ</a>
|
||||||
</li><li>
|
</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>
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
</li><li>
|
</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>
|
</li></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
@@ -96,23 +91,12 @@ handled correctly. The error may fall through an on-trace
|
|||||||
<tt>lua_atpanic</tt> on x64. This issue will be fixed with the new
|
<tt>lua_atpanic</tt> on x64. This issue will be fixed with the new
|
||||||
garbage collector.
|
garbage collector.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
LuaJIT on 64 bit systems provides a <b>limited range</b> of 47 bits for the
|
|
||||||
<b>legacy <tt>lightuserdata</tt></b> data type.
|
|
||||||
This is only relevant on x64 systems which use the negative part of the
|
|
||||||
virtual address space in user mode, e.g. Solaris/x64, and on ARM64 systems
|
|
||||||
configured with a 48 bit or 52 bit VA.
|
|
||||||
Avoid using <tt>lightuserdata</tt> to hold pointers that may point outside
|
|
||||||
of that range, e.g. variables on the stack. In general, avoid this data
|
|
||||||
type for new code and replace it with (much more performant) FFI bindings.
|
|
||||||
FFI cdata pointers can address the full 64 bit range.
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<br class="flush">
|
<br class="flush">
|
||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2018
|
Copyright © 2005-2020
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM ARM encoding engine.
|
** DynASM ARM encoding engine.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM ARM module.
|
-- DynASM ARM module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM ARM64 encoding engine.
|
** DynASM ARM64 encoding engine.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM ARM64 module.
|
-- DynASM ARM64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM MIPS encoding engine.
|
** DynASM MIPS encoding engine.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -355,14 +355,15 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||||||
CK(n >= 0, UNDEF_PC);
|
CK(n >= 0, UNDEF_PC);
|
||||||
n = *DASM_POS2PTR(D, n);
|
n = *DASM_POS2PTR(D, n);
|
||||||
if (ins & 2048)
|
if (ins & 2048)
|
||||||
n = n - (int)((char *)cp - base);
|
|
||||||
else
|
|
||||||
n = (n + (int)(size_t)base) & 0x0fffffff;
|
n = (n + (int)(size_t)base) & 0x0fffffff;
|
||||||
patchrel:
|
else
|
||||||
|
n = n - (int)((char *)cp - base);
|
||||||
|
patchrel: {
|
||||||
|
unsigned int e = 16 + ((ins >> 12) & 15);
|
||||||
CK((n & 3) == 0 &&
|
CK((n & 3) == 0 &&
|
||||||
((n + ((ins & 2048) ? 0x00020000 : 0)) >>
|
((n + ((ins & 2048) ? 0 : (1<<(e+1)))) >> (e+2)) == 0, RANGE_REL);
|
||||||
((ins & 2048) ? 18 : 28)) == 0, RANGE_REL);
|
cp[-1] |= ((n>>2) & ((1<<e)-1));
|
||||||
cp[-1] |= ((n>>2) & ((ins & 2048) ? 0x0000ffff: 0x03ffffff));
|
}
|
||||||
break;
|
break;
|
||||||
case DASM_LABEL_LG:
|
case DASM_LABEL_LG:
|
||||||
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
|
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
|
||||||
|
|||||||
+401
-228
@@ -1,11 +1,12 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM MIPS32/MIPS64 module.
|
-- DynASM MIPS32/MIPS64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
local mips64 = mips64
|
local mips64 = mips64
|
||||||
|
local mipsr6 = _map_def.MIPSR6
|
||||||
|
|
||||||
-- Module information:
|
-- Module information:
|
||||||
local _info = {
|
local _info = {
|
||||||
@@ -13,7 +14,7 @@ local _info = {
|
|||||||
description = "DynASM MIPS32/MIPS64 module",
|
description = "DynASM MIPS32/MIPS64 module",
|
||||||
version = "1.4.0",
|
version = "1.4.0",
|
||||||
vernum = 10400,
|
vernum = 10400,
|
||||||
release = "2016-05-24",
|
release = "2020-01-20",
|
||||||
author = "Mike Pall",
|
author = "Mike Pall",
|
||||||
license = "MIT",
|
license = "MIT",
|
||||||
}
|
}
|
||||||
@@ -238,7 +239,6 @@ local map_op = {
|
|||||||
bne_3 = "14000000STB",
|
bne_3 = "14000000STB",
|
||||||
blez_2 = "18000000SB",
|
blez_2 = "18000000SB",
|
||||||
bgtz_2 = "1c000000SB",
|
bgtz_2 = "1c000000SB",
|
||||||
addi_3 = "20000000TSI",
|
|
||||||
li_2 = "24000000TI",
|
li_2 = "24000000TI",
|
||||||
addiu_3 = "24000000TSI",
|
addiu_3 = "24000000TSI",
|
||||||
slti_3 = "28000000TSI",
|
slti_3 = "28000000TSI",
|
||||||
@@ -248,40 +248,22 @@ local map_op = {
|
|||||||
ori_3 = "34000000TSU",
|
ori_3 = "34000000TSU",
|
||||||
xori_3 = "38000000TSU",
|
xori_3 = "38000000TSU",
|
||||||
lui_2 = "3c000000TU",
|
lui_2 = "3c000000TU",
|
||||||
beqzl_2 = "50000000SB",
|
|
||||||
beql_3 = "50000000STB",
|
|
||||||
bnezl_2 = "54000000SB",
|
|
||||||
bnel_3 = "54000000STB",
|
|
||||||
blezl_2 = "58000000SB",
|
|
||||||
bgtzl_2 = "5c000000SB",
|
|
||||||
daddi_3 = mips64 and "60000000TSI",
|
|
||||||
daddiu_3 = mips64 and "64000000TSI",
|
daddiu_3 = mips64 and "64000000TSI",
|
||||||
ldl_2 = mips64 and "68000000TO",
|
ldl_2 = mips64 and "68000000TO",
|
||||||
ldr_2 = mips64 and "6c000000TO",
|
ldr_2 = mips64 and "6c000000TO",
|
||||||
lb_2 = "80000000TO",
|
lb_2 = "80000000TO",
|
||||||
lh_2 = "84000000TO",
|
lh_2 = "84000000TO",
|
||||||
lwl_2 = "88000000TO",
|
|
||||||
lw_2 = "8c000000TO",
|
lw_2 = "8c000000TO",
|
||||||
lbu_2 = "90000000TO",
|
lbu_2 = "90000000TO",
|
||||||
lhu_2 = "94000000TO",
|
lhu_2 = "94000000TO",
|
||||||
lwr_2 = "98000000TO",
|
|
||||||
lwu_2 = mips64 and "9c000000TO",
|
lwu_2 = mips64 and "9c000000TO",
|
||||||
sb_2 = "a0000000TO",
|
sb_2 = "a0000000TO",
|
||||||
sh_2 = "a4000000TO",
|
sh_2 = "a4000000TO",
|
||||||
swl_2 = "a8000000TO",
|
|
||||||
sw_2 = "ac000000TO",
|
sw_2 = "ac000000TO",
|
||||||
sdl_2 = mips64 and "b0000000TO",
|
|
||||||
sdr_2 = mips64 and "b1000000TO",
|
|
||||||
swr_2 = "b8000000TO",
|
|
||||||
cache_2 = "bc000000NO",
|
|
||||||
ll_2 = "c0000000TO",
|
|
||||||
lwc1_2 = "c4000000HO",
|
lwc1_2 = "c4000000HO",
|
||||||
pref_2 = "cc000000NO",
|
|
||||||
ldc1_2 = "d4000000HO",
|
ldc1_2 = "d4000000HO",
|
||||||
ld_2 = mips64 and "dc000000TO",
|
ld_2 = mips64 and "dc000000TO",
|
||||||
sc_2 = "e0000000TO",
|
|
||||||
swc1_2 = "e4000000HO",
|
swc1_2 = "e4000000HO",
|
||||||
scd_2 = mips64 and "f0000000TO",
|
|
||||||
sdc1_2 = "f4000000HO",
|
sdc1_2 = "f4000000HO",
|
||||||
sd_2 = mips64 and "fc000000TO",
|
sd_2 = mips64 and "fc000000TO",
|
||||||
|
|
||||||
@@ -289,10 +271,6 @@ local map_op = {
|
|||||||
nop_0 = "00000000",
|
nop_0 = "00000000",
|
||||||
sll_3 = "00000000DTA",
|
sll_3 = "00000000DTA",
|
||||||
sextw_2 = "00000000DT",
|
sextw_2 = "00000000DT",
|
||||||
movf_2 = "00000001DS",
|
|
||||||
movf_3 = "00000001DSC",
|
|
||||||
movt_2 = "00010001DS",
|
|
||||||
movt_3 = "00010001DSC",
|
|
||||||
srl_3 = "00000002DTA",
|
srl_3 = "00000002DTA",
|
||||||
rotr_3 = "00200002DTA",
|
rotr_3 = "00200002DTA",
|
||||||
sra_3 = "00000003DTA",
|
sra_3 = "00000003DTA",
|
||||||
@@ -301,31 +279,16 @@ local map_op = {
|
|||||||
rotrv_3 = "00000046DTS",
|
rotrv_3 = "00000046DTS",
|
||||||
drotrv_3 = mips64 and "00000056DTS",
|
drotrv_3 = mips64 and "00000056DTS",
|
||||||
srav_3 = "00000007DTS",
|
srav_3 = "00000007DTS",
|
||||||
jr_1 = "00000008S",
|
|
||||||
jalr_1 = "0000f809S",
|
jalr_1 = "0000f809S",
|
||||||
jalr_2 = "00000009DS",
|
jalr_2 = "00000009DS",
|
||||||
movz_3 = "0000000aDST",
|
|
||||||
movn_3 = "0000000bDST",
|
|
||||||
syscall_0 = "0000000c",
|
syscall_0 = "0000000c",
|
||||||
syscall_1 = "0000000cY",
|
syscall_1 = "0000000cY",
|
||||||
break_0 = "0000000d",
|
break_0 = "0000000d",
|
||||||
break_1 = "0000000dY",
|
break_1 = "0000000dY",
|
||||||
sync_0 = "0000000f",
|
sync_0 = "0000000f",
|
||||||
mfhi_1 = "00000010D",
|
|
||||||
mthi_1 = "00000011S",
|
|
||||||
mflo_1 = "00000012D",
|
|
||||||
mtlo_1 = "00000013S",
|
|
||||||
dsllv_3 = mips64 and "00000014DTS",
|
dsllv_3 = mips64 and "00000014DTS",
|
||||||
dsrlv_3 = mips64 and "00000016DTS",
|
dsrlv_3 = mips64 and "00000016DTS",
|
||||||
dsrav_3 = mips64 and "00000017DTS",
|
dsrav_3 = mips64 and "00000017DTS",
|
||||||
mult_2 = "00000018ST",
|
|
||||||
multu_2 = "00000019ST",
|
|
||||||
div_2 = "0000001aST",
|
|
||||||
divu_2 = "0000001bST",
|
|
||||||
dmult_2 = mips64 and "0000001cST",
|
|
||||||
dmultu_2 = mips64 and "0000001dST",
|
|
||||||
ddiv_2 = mips64 and "0000001eST",
|
|
||||||
ddivu_2 = mips64 and "0000001fST",
|
|
||||||
add_3 = "00000020DST",
|
add_3 = "00000020DST",
|
||||||
move_2 = mips64 and "00000025DS" or "00000021DS",
|
move_2 = mips64 and "00000025DS" or "00000021DS",
|
||||||
addu_3 = "00000021DST",
|
addu_3 = "00000021DST",
|
||||||
@@ -369,32 +332,9 @@ local map_op = {
|
|||||||
bgez_2 = "04010000SB",
|
bgez_2 = "04010000SB",
|
||||||
bltzl_2 = "04020000SB",
|
bltzl_2 = "04020000SB",
|
||||||
bgezl_2 = "04030000SB",
|
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",
|
bal_1 = "04110000B",
|
||||||
bgezal_2 = "04110000SB",
|
|
||||||
bltzall_2 = "04120000SB",
|
|
||||||
bgezall_2 = "04130000SB",
|
|
||||||
synci_1 = "041f0000O",
|
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=",
|
|
||||||
dclz_2 = mips64 and "70000024DS=",
|
|
||||||
dclo_2 = mips64 and "70000025DS=",
|
|
||||||
sdbbp_0 = "7000003f",
|
|
||||||
sdbbp_1 = "7000003fY",
|
|
||||||
|
|
||||||
-- Opcode SPECIAL3.
|
-- Opcode SPECIAL3.
|
||||||
ext_4 = "7c000000TSAM", -- Note: last arg is msbd = size-1
|
ext_4 = "7c000000TSAM", -- Note: last arg is msbd = size-1
|
||||||
dextm_4 = mips64 and "7c000001TSAM", -- Args: pos | size-1-32
|
dextm_4 = mips64 and "7c000001TSAM", -- Args: pos | size-1-32
|
||||||
@@ -445,15 +385,6 @@ local map_op = {
|
|||||||
ctc1_2 = "44c00000TG",
|
ctc1_2 = "44c00000TG",
|
||||||
mthc1_2 = "44e00000TG",
|
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",
|
["add.s_3"] = "46000000FGH",
|
||||||
["sub.s_3"] = "46000001FGH",
|
["sub.s_3"] = "46000001FGH",
|
||||||
["mul.s_3"] = "46000002FGH",
|
["mul.s_3"] = "46000002FGH",
|
||||||
@@ -470,51 +401,11 @@ local map_op = {
|
|||||||
["trunc.w.s_2"] = "4600000dFG",
|
["trunc.w.s_2"] = "4600000dFG",
|
||||||
["ceil.w.s_2"] = "4600000eFG",
|
["ceil.w.s_2"] = "4600000eFG",
|
||||||
["floor.w.s_2"] = "4600000fFG",
|
["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",
|
["recip.s_2"] = "46000015FG",
|
||||||
["rsqrt.s_2"] = "46000016FG",
|
["rsqrt.s_2"] = "46000016FG",
|
||||||
["cvt.d.s_2"] = "46000021FG",
|
["cvt.d.s_2"] = "46000021FG",
|
||||||
["cvt.w.s_2"] = "46000024FG",
|
["cvt.w.s_2"] = "46000024FG",
|
||||||
["cvt.l.s_2"] = "46000025FG",
|
["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",
|
["add.d_3"] = "46200000FGH",
|
||||||
["sub.d_3"] = "46200001FGH",
|
["sub.d_3"] = "46200001FGH",
|
||||||
["mul.d_3"] = "46200002FGH",
|
["mul.d_3"] = "46200002FGH",
|
||||||
@@ -531,130 +422,410 @@ local map_op = {
|
|||||||
["trunc.w.d_2"] = "4620000dFG",
|
["trunc.w.d_2"] = "4620000dFG",
|
||||||
["ceil.w.d_2"] = "4620000eFG",
|
["ceil.w.d_2"] = "4620000eFG",
|
||||||
["floor.w.d_2"] = "4620000fFG",
|
["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",
|
["recip.d_2"] = "46200015FG",
|
||||||
["rsqrt.d_2"] = "46200016FG",
|
["rsqrt.d_2"] = "46200016FG",
|
||||||
["cvt.s.d_2"] = "46200020FG",
|
["cvt.s.d_2"] = "46200020FG",
|
||||||
["cvt.w.d_2"] = "46200024FG",
|
["cvt.w.d_2"] = "46200024FG",
|
||||||
["cvt.l.d_2"] = "46200025FG",
|
["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.s.w_2"] = "46800020FG",
|
||||||
["cvt.d.w_2"] = "46800021FG",
|
["cvt.d.w_2"] = "46800021FG",
|
||||||
|
|
||||||
["cvt.s.l_2"] = "46a00020FG",
|
["cvt.s.l_2"] = "46a00020FG",
|
||||||
["cvt.d.l_2"] = "46a00021FG",
|
["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)
|
local function parse_gpr(expr)
|
||||||
@@ -808,9 +979,11 @@ map_op[".template__"] = function(params, template, nparams)
|
|||||||
op = op + parse_disp(params[n]); n = n + 1
|
op = op + parse_disp(params[n]); n = n + 1
|
||||||
elseif p == "X" then
|
elseif p == "X" then
|
||||||
op = op + parse_index(params[n]); n = n + 1
|
op = op + parse_index(params[n]); n = n + 1
|
||||||
elseif p == "B" or p == "J" then
|
elseif p == "B" or p == "J" or p == "K" or p == "L" then
|
||||||
local mode, m, s = parse_label(params[n], false)
|
local mode, m, s = parse_label(params[n], false)
|
||||||
if p == "B" then m = m + 2048 end
|
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)
|
waction("REL_"..mode, m, s, 1)
|
||||||
n = n + 1
|
n = n + 1
|
||||||
elseif p == "A" then
|
elseif p == "A" then
|
||||||
@@ -833,7 +1006,7 @@ map_op[".template__"] = function(params, template, nparams)
|
|||||||
elseif p == "Z" then
|
elseif p == "Z" then
|
||||||
op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1
|
op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1
|
||||||
elseif p == "=" then
|
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
|
else
|
||||||
assert(false)
|
assert(false)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM MIPS64 module.
|
-- DynASM MIPS64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
|
-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM PPC/PPC64 encoding engine.
|
** DynASM PPC/PPC64 encoding engine.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM PPC/PPC64 module.
|
-- DynASM PPC/PPC64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
--
|
--
|
||||||
-- Support for various extensions contributed by Caio Souza Oliveira.
|
-- Support for various extensions contributed by Caio Souza Oliveira.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM encoding engine prototypes.
|
** DynASM encoding engine prototypes.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM x64 module.
|
-- DynASM x64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- This module just sets 64 bit mode for the combined x86/x64 module.
|
-- This module just sets 64 bit mode for the combined x86/x64 module.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM x86 encoding engine.
|
** DynASM x86 encoding engine.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -305,11 +305,13 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||||||
|
|
||||||
while (pos != lastpos) {
|
while (pos != lastpos) {
|
||||||
dasm_ActList p = D->actionlist + b[pos++];
|
dasm_ActList p = D->actionlist + b[pos++];
|
||||||
|
int op = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
int op, action = *p++;
|
int action = *p++;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case DASM_REL_LG: p++; op = p[-3]; goto rel_pc;
|
case DASM_REL_LG: p++;
|
||||||
case DASM_REL_PC: op = p[-2]; rel_pc: {
|
/* fallthrough */
|
||||||
|
case DASM_REL_PC: {
|
||||||
int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0);
|
int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0);
|
||||||
if (shrink) { /* Shrinkable branch opcode? */
|
if (shrink) { /* Shrinkable branch opcode? */
|
||||||
int lofs, lpos = b[pos];
|
int lofs, lpos = b[pos];
|
||||||
@@ -341,9 +343,10 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||||||
case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */
|
case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */
|
||||||
case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */
|
case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */
|
||||||
case DASM_EXTERN: p += 2; break;
|
case DASM_EXTERN: p += 2; break;
|
||||||
case DASM_ESC: p++; break;
|
case DASM_ESC: op = *p++; break;
|
||||||
case DASM_MARK: break;
|
case DASM_MARK: break;
|
||||||
case DASM_SECTION: case DASM_STOP: goto stop;
|
case DASM_SECTION: case DASM_STOP: goto stop;
|
||||||
|
default: op = action; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stop: (void)0;
|
stop: (void)0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM x86/x64 module.
|
-- DynASM x86/x64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -1852,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.
|
-- Process pattern string.
|
||||||
local function dopattern(pat, args, sz, op, needrex)
|
local function dopattern(pat, args, sz, op, needrex)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
-- DynASM. A dynamic assembler for code generation engines.
|
-- DynASM. A dynamic assembler for code generation engines.
|
||||||
-- Originally designed and implemented for LuaJIT.
|
-- Originally designed and implemented for LuaJIT.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- See below for full copyright notice.
|
-- See below for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -14,10 +14,10 @@ local _info = {
|
|||||||
vernum = 10400,
|
vernum = 10400,
|
||||||
release = "2015-10-18",
|
release = "2015-10-18",
|
||||||
author = "Mike Pall",
|
author = "Mike Pall",
|
||||||
url = "http://luajit.org/dynasm.html",
|
url = "https://luajit.org/dynasm.html",
|
||||||
license = "MIT",
|
license = "MIT",
|
||||||
copyright = [[
|
copyright = [[
|
||||||
Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
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
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
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.
|
-- Load architecture-specific module.
|
||||||
local function loadarch(arch)
|
local function loadarch(arch)
|
||||||
if not match(arch, "^[%w_]+$") then return "bad arch name" end
|
if not match(arch, "^[%w_]+$") then return "bad arch name" end
|
||||||
|
_G._map_def = map_def
|
||||||
local ok, m_arch = pcall(require, "dasm_"..arch)
|
local ok, m_arch = pcall(require, "dasm_"..arch)
|
||||||
if not ok then return "cannot load module: "..m_arch end
|
if not ok then return "cannot load module: "..m_arch end
|
||||||
g_arch = m_arch
|
g_arch = m_arch
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ luajit \- Just-In-Time Compiler for the Lua Language
|
|||||||
.B luajit
|
.B luajit
|
||||||
[\fIoptions\fR]... [\fIscript\fR [\fIargs\fR]...]
|
[\fIoptions\fR]... [\fIscript\fR [\fIargs\fR]...]
|
||||||
.SH "WEB SITE"
|
.SH "WEB SITE"
|
||||||
.IR http://luajit.org
|
.IR https://luajit.org
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.PP
|
.PP
|
||||||
This is the command-line program to run Lua programs with \fBLuaJIT\fR.
|
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.
|
Runs some nested loops and shows the resulting traces.
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
.PP
|
.PP
|
||||||
\fBLuaJIT\fR is Copyright \(co 2005-2017 Mike Pall.
|
\fBLuaJIT\fR is Copyright \(co 2005-2020 Mike Pall.
|
||||||
.br
|
.br
|
||||||
\fBLuaJIT\fR is open source software, released under the MIT license.
|
\fBLuaJIT\fR is open source software, released under the MIT license.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.PP
|
.PP
|
||||||
More details in the provided HTML docs or at:
|
More details in the provided HTML docs or at:
|
||||||
.IR http://luajit.org
|
.IR https://luajit.org
|
||||||
.br
|
.br
|
||||||
More about the Lua language can be found at:
|
More about the Lua language can be found at:
|
||||||
.IR http://lua.org/docs.html
|
.IR https://lua.org/docs.html
|
||||||
.PP
|
.PP
|
||||||
lua(1)
|
lua(1)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ INSTALL_CMOD=${prefix}/${multilib}/lua/${abiver}
|
|||||||
|
|
||||||
Name: LuaJIT
|
Name: LuaJIT
|
||||||
Description: Just-in-time compiler for Lua
|
Description: Just-in-time compiler for Lua
|
||||||
URL: http://luajit.org
|
URL: https://luajit.org
|
||||||
Version: ${version}
|
Version: ${version}
|
||||||
Requires:
|
Requires:
|
||||||
Libs: -L${libdir} -l${libname}
|
Libs: -L${libdir} -l${libname}
|
||||||
|
|||||||
+11
-14
@@ -7,7 +7,7 @@
|
|||||||
# Also works with MinGW and Cygwin on Windows.
|
# Also works with MinGW and Cygwin on Windows.
|
||||||
# Please check msvcbuild.bat for building with MSVC on Windows.
|
# Please check msvcbuild.bat for building with MSVC on Windows.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
# Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
MAJVER= 2
|
MAJVER= 2
|
||||||
@@ -132,7 +132,6 @@ XCFLAGS=
|
|||||||
#
|
#
|
||||||
# This define is required to run LuaJIT under Valgrind. The Valgrind
|
# This define is required to run LuaJIT under Valgrind. The Valgrind
|
||||||
# header files must be installed. You should enable debug information, too.
|
# header files must be installed. You should enable debug information, too.
|
||||||
# Use --suppressions=lj.supp to avoid some false positives.
|
|
||||||
#XCFLAGS+= -DLUAJIT_USE_VALGRIND
|
#XCFLAGS+= -DLUAJIT_USE_VALGRIND
|
||||||
#
|
#
|
||||||
# This is the client for the GDB JIT API. GDB 7.0 or higher is required
|
# This is the client for the GDB JIT API. GDB 7.0 or higher is required
|
||||||
@@ -212,7 +211,7 @@ TARGET_CC= $(STATIC_CC)
|
|||||||
TARGET_STCC= $(STATIC_CC)
|
TARGET_STCC= $(STATIC_CC)
|
||||||
TARGET_DYNCC= $(DYNAMIC_CC)
|
TARGET_DYNCC= $(DYNAMIC_CC)
|
||||||
TARGET_LD= $(CROSS)$(CC)
|
TARGET_LD= $(CROSS)$(CC)
|
||||||
TARGET_AR= $(CROSS)ar rcus
|
TARGET_AR= $(CROSS)ar rcus 2>/dev/null
|
||||||
TARGET_STRIP= $(CROSS)strip
|
TARGET_STRIP= $(CROSS)strip
|
||||||
|
|
||||||
TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib)
|
TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib)
|
||||||
@@ -311,9 +310,7 @@ ifeq (Windows,$(TARGET_SYS))
|
|||||||
TARGET_STRIP+= --strip-unneeded
|
TARGET_STRIP+= --strip-unneeded
|
||||||
TARGET_XSHLDFLAGS= -shared -Wl,--out-implib,$(TARGET_DLLDOTANAME)
|
TARGET_XSHLDFLAGS= -shared -Wl,--out-implib,$(TARGET_DLLDOTANAME)
|
||||||
TARGET_DYNXLDOPTS=
|
TARGET_DYNXLDOPTS=
|
||||||
HOST_RM= del
|
|
||||||
else
|
else
|
||||||
TARGET_AR+= 2>/dev/null
|
|
||||||
ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1))
|
ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1))
|
||||||
TARGET_XCFLAGS+= -fno-stack-protector
|
TARGET_XCFLAGS+= -fno-stack-protector
|
||||||
endif
|
endif
|
||||||
@@ -365,7 +362,7 @@ ifneq ($(HOST_SYS),$(TARGET_SYS))
|
|||||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX
|
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX
|
||||||
else
|
else
|
||||||
ifeq (iOS,$(TARGET_SYS))
|
ifeq (iOS,$(TARGET_SYS))
|
||||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX
|
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX -DTARGET_OS_IPHONE=1
|
||||||
else
|
else
|
||||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OTHER
|
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OTHER
|
||||||
endif
|
endif
|
||||||
@@ -445,6 +442,9 @@ ifeq (arm,$(TARGET_LJARCH))
|
|||||||
DASM_AFLAGS+= -D IOS
|
DASM_AFLAGS+= -D IOS
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
|
ifneq (,$(findstring LJ_TARGET_MIPSR6 ,$(TARGET_TESTARCH)))
|
||||||
|
DASM_AFLAGS+= -D MIPSR6
|
||||||
|
endif
|
||||||
ifeq (ppc,$(TARGET_LJARCH))
|
ifeq (ppc,$(TARGET_LJARCH))
|
||||||
ifneq (,$(findstring LJ_ARCH_SQRT 1,$(TARGET_TESTARCH)))
|
ifneq (,$(findstring LJ_ARCH_SQRT 1,$(TARGET_TESTARCH)))
|
||||||
DASM_AFLAGS+= -D SQRT
|
DASM_AFLAGS+= -D SQRT
|
||||||
@@ -458,9 +458,6 @@ ifeq (ppc,$(TARGET_LJARCH))
|
|||||||
ifeq (PS3,$(TARGET_SYS))
|
ifeq (PS3,$(TARGET_SYS))
|
||||||
DASM_AFLAGS+= -D PPE -D TOC
|
DASM_AFLAGS+= -D PPE -D TOC
|
||||||
endif
|
endif
|
||||||
ifneq (,$(findstring LJ_ARCH_PPC64 ,$(TARGET_TESTARCH)))
|
|
||||||
DASM_ARCH= ppc64
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
@@ -485,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
|
lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o
|
||||||
LJLIB_C= $(LJLIB_O:.o=.c)
|
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_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_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \
|
||||||
lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \
|
lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \
|
||||||
lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.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_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 \
|
lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
|
||||||
@@ -563,6 +560,7 @@ ifeq (Windows,$(HOST_SYS))
|
|||||||
MINILUA_X= host\minilua
|
MINILUA_X= host\minilua
|
||||||
BUILDVM_X= host\buildvm
|
BUILDVM_X= host\buildvm
|
||||||
ALL_RM:= $(subst /,\,$(ALL_RM))
|
ALL_RM:= $(subst /,\,$(ALL_RM))
|
||||||
|
HOST_RM= del
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -603,7 +601,6 @@ E= @echo
|
|||||||
default all: $(TARGET_T)
|
default all: $(TARGET_T)
|
||||||
|
|
||||||
amalg:
|
amalg:
|
||||||
@grep "^[+|]" ljamalg.c
|
|
||||||
$(MAKE) all "LJCORE_O=ljamalg.o"
|
$(MAKE) all "LJCORE_O=ljamalg.o"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@@ -637,7 +634,7 @@ $(MINILUA_T): $(MINILUA_O)
|
|||||||
$(E) "HOSTLINK $@"
|
$(E) "HOSTLINK $@"
|
||||||
$(Q)$(HOST_CC) $(HOST_ALDFLAGS) -o $@ $(MINILUA_O) $(MINILUA_LIBS) $(HOST_ALIBS)
|
$(Q)$(HOST_CC) $(HOST_ALDFLAGS) -o $@ $(MINILUA_O) $(MINILUA_LIBS) $(HOST_ALIBS)
|
||||||
|
|
||||||
host/buildvm_arch.h: $(DASM_DASC) $(DASM_DEP) $(DASM_DIR)/*.lua
|
host/buildvm_arch.h: $(DASM_DASC) $(DASM_DEP) $(DASM_DIR)/*.lua lj_arch.h lua.h luaconf.h
|
||||||
$(E) "DYNASM $@"
|
$(E) "DYNASM $@"
|
||||||
$(Q)$(DASM) $(DASM_FLAGS) -o $@ $(DASM_DASC)
|
$(Q)$(DASM) $(DASM_FLAGS) -o $@ $(DASM_DASC)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
|
lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
|
||||||
lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.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 \
|
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_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \
|
||||||
lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \
|
lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.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_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
|
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 \
|
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 \
|
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_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_lib.h \
|
||||||
lj_libdef.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 \
|
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_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_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_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_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 \
|
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_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_snap.h lj_asm.h lj_vm.h lj_target.h lj_target_*.h lj_emit_*.h \
|
||||||
lj_asm_*.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_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_bcdef.h
|
||||||
lj_bcread.o: lj_bcread.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_bcread.o: lj_bcread.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.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_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_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_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_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 \
|
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 \
|
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_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_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_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_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_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
|
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_iropt.h lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h \
|
||||||
lj_vm.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_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_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_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
|
lj_traceerr.h lj_vm.h lj_strscan.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_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_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_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_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_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_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_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_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_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 \
|
lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \
|
||||||
@@ -183,7 +186,8 @@ 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_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_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_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_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||||
lj_err.h lj_errmsg.h lj_str.h lj_char.h
|
lj_err.h lj_errmsg.h lj_str.h lj_char.h
|
||||||
lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
@@ -198,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_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_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_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_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
lj_gc.h lj_udata.h
|
lj_gc.h lj_udata.h
|
||||||
lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
@@ -206,28 +210,29 @@ 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_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_vmmath.o: lj_vmmath.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
lj_ir.h lj_vm.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 \
|
ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_assert.c lj_obj.h \
|
||||||
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h \
|
lj_def.h lj_arch.h lj_gc.c lj_gc.h lj_err.h lj_errmsg.h lj_buf.h \
|
||||||
lj_func.h lj_udata.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h \
|
lj_str.h lj_tab.h lj_func.h lj_udata.h lj_meta.h lj_state.h lj_frame.h \
|
||||||
lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h \
|
lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
|
||||||
lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h lj_char.c \
|
lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \
|
||||||
lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c lj_tab.c \
|
lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \
|
||||||
lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.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_prng.c lj_prng.h lj_state.c lj_lex.h lj_alloc.h luajit.h \
|
||||||
lj_profile.h lj_vmevent.c lj_vmevent.h lj_vmmath.c lj_strscan.c \
|
lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \
|
||||||
lj_strfmt.c lj_strfmt_num.c lj_api.c lj_profile.c lj_lex.c lualib.h \
|
lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_api.c \
|
||||||
lj_parse.h lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c \
|
lj_profile.c lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c \
|
||||||
lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h \
|
lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h \
|
||||||
lj_ccallback.c lj_target.h lj_target_*.h lj_mcode.h lj_carith.c \
|
lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h \
|
||||||
lj_carith.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c \
|
lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h \
|
||||||
lj_ircall.h lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h \
|
lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h lj_iropt.h \
|
||||||
lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c \
|
lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \
|
||||||
lj_opt_sink.c lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h \
|
lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \
|
||||||
lj_crecord.c lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h \
|
lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
|
||||||
lj_emit_*.h lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c \
|
lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \
|
||||||
lib_aux.c lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c \
|
lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \
|
||||||
lib_io.c lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c \
|
lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \
|
||||||
lib_ffi.c lib_init.c
|
lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \
|
||||||
|
lib_init.c
|
||||||
luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
|
luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
|
||||||
host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \
|
host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \
|
||||||
lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \
|
lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder.
|
** LuaJIT VM builder.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** This is a tool to build the hand-tuned assembler code required for
|
** This is a tool to build the hand-tuned assembler code required for
|
||||||
** LuaJIT's bytecode interpreter. It supports a variety of output formats
|
** LuaJIT's bytecode interpreter. It supports a variety of output formats
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder.
|
** LuaJIT VM builder.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _BUILDVM_H
|
#ifndef _BUILDVM_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder: Assembler source code emitter.
|
** LuaJIT VM builder: Assembler source code emitter.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "buildvm.h"
|
#include "buildvm.h"
|
||||||
@@ -144,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",
|
fprintf(ctx->fp, "\t%s %d, %d, " TOCPREFIX "%s\n",
|
||||||
(ins & 1) ? "bcl" : "bc", (ins >> 21) & 31, (ins >> 16) & 31, sym);
|
(ins & 1) ? "bcl" : "bc", (ins >> 21) & 31, (ins >> 16) & 31, sym);
|
||||||
} else if ((ins >> 26) == 18) {
|
} 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);
|
fprintf(ctx->fp, "\t%s " TOCPREFIX "%s\n", (ins & 1) ? "bl" : "b", sym);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -250,9 +242,6 @@ void emit_asm(BuildCtx *ctx)
|
|||||||
int i, rel;
|
int i, rel;
|
||||||
|
|
||||||
fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch);
|
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");
|
fprintf(ctx->fp, "\t.text\n");
|
||||||
emit_asm_align(ctx, 4);
|
emit_asm_align(ctx, 4);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder: IR folding hash table generator.
|
** LuaJIT VM builder: IR folding hash table generator.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "buildvm.h"
|
#include "buildvm.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder: library definition compiler.
|
** LuaJIT VM builder: library definition compiler.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "buildvm.h"
|
#include "buildvm.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder: PE object emitter.
|
** LuaJIT VM builder: PE object emitter.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Only used for building on Windows, since we cannot assume the presence
|
** Only used for building on Windows, since we cannot assume the presence
|
||||||
** of a suitable assembler. The host and target byte order must match.
|
** of a suitable assembler. The host and target byte order must match.
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "buildvm.h"
|
#include "buildvm.h"
|
||||||
#include "lj_bc.h"
|
#include "lj_bc.h"
|
||||||
|
|
||||||
#if LJ_TARGET_X86ORX64 || LJ_TARGET_PPC
|
#if LJ_TARGET_X86ORX64
|
||||||
|
|
||||||
/* Context for PE object emitter. */
|
/* Context for PE object emitter. */
|
||||||
static char *strtab;
|
static char *strtab;
|
||||||
@@ -93,12 +93,6 @@ typedef struct PEsymaux {
|
|||||||
#define PEOBJ_RELOC_ADDR32NB 0x03
|
#define PEOBJ_RELOC_ADDR32NB 0x03
|
||||||
#define PEOBJ_RELOC_OFS 0
|
#define PEOBJ_RELOC_OFS 0
|
||||||
#define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */
|
#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
|
#endif
|
||||||
|
|
||||||
/* Section numbers (0-based). */
|
/* Section numbers (0-based). */
|
||||||
@@ -251,15 +245,8 @@ void emit_peobj(BuildCtx *ctx)
|
|||||||
/* Write .text section. */
|
/* Write .text section. */
|
||||||
host_endian.u = 1;
|
host_endian.u = 1;
|
||||||
if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) {
|
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");
|
fprintf(stderr, "Error: different byte order for host and target\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
owrite(ctx, ctx->code, ctx->codesz);
|
owrite(ctx, ctx->code, ctx->codesz);
|
||||||
for (i = 0; i < ctx->nreloc; i++) {
|
for (i = 0; i < ctx->nreloc; i++) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
-- Lua script to dump the bytecode of the library functions written in Lua.
|
-- 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.
|
-- The resulting 'buildvm_libbc.h' is used for the build process of LuaJIT.
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- 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.
|
-- Lua script to generate a customized, minified version of Lua.
|
||||||
-- The resulting 'minilua' is used for the build process of LuaJIT.
|
-- The resulting 'minilua' is used for the build process of LuaJIT.
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT bytecode listing module.
|
-- LuaJIT bytecode listing module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT module to save/list bytecode.
|
-- LuaJIT module to save/list bytecode.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- 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.
|
-- Symbol name prefix for LuaJIT bytecode.
|
||||||
local LJBC_PREFIX = "luaJIT_BC_"
|
local LJBC_PREFIX = "luaJIT_BC_"
|
||||||
|
|
||||||
|
local type, assert = type, assert
|
||||||
|
local format = string.format
|
||||||
|
local tremove, tconcat = table.remove, table.concat
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function usage()
|
local function usage()
|
||||||
@@ -63,8 +67,18 @@ local map_type = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local map_arch = {
|
local map_arch = {
|
||||||
x86 = true, x64 = true, arm = true, arm64 = true, arm64be = true,
|
x86 = { e = "le", b = 32, m = 3, p = 0x14c, },
|
||||||
ppc = true, mips = true, mipsel = true,
|
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 = {
|
local map_os = {
|
||||||
@@ -73,33 +87,33 @@ local map_os = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local function checkarg(str, map, err)
|
local function checkarg(str, map, err)
|
||||||
str = string.lower(str)
|
str = str:lower()
|
||||||
local s = check(map[str], "unknown ", err)
|
local s = check(map[str], "unknown ", err)
|
||||||
return s == true and str or s
|
return type(s) == "string" and s or str
|
||||||
end
|
end
|
||||||
|
|
||||||
local function detecttype(str)
|
local function detecttype(str)
|
||||||
local ext = string.match(string.lower(str), "%.(%a+)$")
|
local ext = str:lower():match("%.(%a+)$")
|
||||||
return map_type[ext] or "raw"
|
return map_type[ext] or "raw"
|
||||||
end
|
end
|
||||||
|
|
||||||
local function checkmodname(str)
|
local function checkmodname(str)
|
||||||
check(string.match(str, "^[%w_.%-]+$"), "bad module name")
|
check(str:match("^[%w_.%-]+$"), "bad module name")
|
||||||
return string.gsub(str, "[%.%-]", "_")
|
return str:gsub("[%.%-]", "_")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function detectmodname(str)
|
local function detectmodname(str)
|
||||||
if type(str) == "string" then
|
if type(str) == "string" then
|
||||||
local tail = string.match(str, "[^/\\]+$")
|
local tail = str:match("[^/\\]+$")
|
||||||
if tail then str = tail end
|
if tail then str = tail end
|
||||||
local head = string.match(str, "^(.*)%.[^.]*$")
|
local head = str:match("^(.*)%.[^.]*$")
|
||||||
if head then str = head end
|
if head then str = head end
|
||||||
str = string.match(str, "^[%w_.%-]+")
|
str = str:match("^[%w_.%-]+")
|
||||||
else
|
else
|
||||||
str = nil
|
str = nil
|
||||||
end
|
end
|
||||||
check(str, "cannot derive module name, use -n name")
|
check(str, "cannot derive module name, use -n name")
|
||||||
return string.gsub(str, "[%.%-]", "_")
|
return str:gsub("[%.%-]", "_")
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@@ -118,8 +132,8 @@ end
|
|||||||
local function bcsave_c(ctx, output, s)
|
local function bcsave_c(ctx, output, s)
|
||||||
local fp = savefile(output, "w")
|
local fp = savefile(output, "w")
|
||||||
if ctx.type == "c" then
|
if ctx.type == "c" then
|
||||||
fp:write(string.format([[
|
fp:write(format([[
|
||||||
#ifdef _cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
#endif
|
#endif
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -128,7 +142,7 @@ __declspec(dllexport)
|
|||||||
const unsigned char %s%s[] = {
|
const unsigned char %s%s[] = {
|
||||||
]], LJBC_PREFIX, ctx.modname))
|
]], LJBC_PREFIX, ctx.modname))
|
||||||
else
|
else
|
||||||
fp:write(string.format([[
|
fp:write(format([[
|
||||||
#define %s%s_SIZE %d
|
#define %s%s_SIZE %d
|
||||||
static const unsigned char %s%s[] = {
|
static const unsigned char %s%s[] = {
|
||||||
]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname))
|
]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname))
|
||||||
@@ -138,13 +152,13 @@ static const unsigned char %s%s[] = {
|
|||||||
local b = tostring(string.byte(s, i))
|
local b = tostring(string.byte(s, i))
|
||||||
m = m + #b + 1
|
m = m + #b + 1
|
||||||
if m > 78 then
|
if m > 78 then
|
||||||
fp:write(table.concat(t, ",", 1, n), ",\n")
|
fp:write(tconcat(t, ",", 1, n), ",\n")
|
||||||
n, m = 0, #b + 1
|
n, m = 0, #b + 1
|
||||||
end
|
end
|
||||||
n = n + 1
|
n = n + 1
|
||||||
t[n] = b
|
t[n] = b
|
||||||
end
|
end
|
||||||
bcsave_tail(fp, output, table.concat(t, ",", 1, n).."\n};\n")
|
bcsave_tail(fp, output, tconcat(t, ",", 1, n).."\n};\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function bcsave_elfobj(ctx, output, s, ffi)
|
local function bcsave_elfobj(ctx, output, s, ffi)
|
||||||
@@ -199,12 +213,8 @@ typedef struct {
|
|||||||
} ELF64obj;
|
} ELF64obj;
|
||||||
]]
|
]]
|
||||||
local symname = LJBC_PREFIX..ctx.modname
|
local symname = LJBC_PREFIX..ctx.modname
|
||||||
local is64, isbe = false, false
|
local ai = assert(map_arch[ctx.arch])
|
||||||
if ctx.arch == "x64" or ctx.arch == "arm64" or ctx.arch == "arm64be" then
|
local is64, isbe = ai.b == 64, ai.e == "be"
|
||||||
is64 = true
|
|
||||||
elseif ctx.arch == "ppc" or ctx.arch == "mips" then
|
|
||||||
isbe = true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Handle different host/target endianess.
|
-- Handle different host/target endianess.
|
||||||
local function f32(x) return x end
|
local function f32(x) return x end
|
||||||
@@ -237,10 +247,8 @@ typedef struct {
|
|||||||
hdr.eendian = isbe and 2 or 1
|
hdr.eendian = isbe and 2 or 1
|
||||||
hdr.eversion = 1
|
hdr.eversion = 1
|
||||||
hdr.type = f16(1)
|
hdr.type = f16(1)
|
||||||
hdr.machine = f16(({ x86=3, x64=62, arm=40, arm64=183, arm64be=183, ppc=20, mips=8, mipsel=8 })[ctx.arch])
|
hdr.machine = f16(ai.m)
|
||||||
if ctx.arch == "mips" or ctx.arch == "mipsel" then
|
hdr.flags = f32(ai.f or 0)
|
||||||
hdr.flags = f32(0x50001006)
|
|
||||||
end
|
|
||||||
hdr.version = f32(1)
|
hdr.version = f32(1)
|
||||||
hdr.shofs = fofs(ffi.offsetof(o, "sect"))
|
hdr.shofs = fofs(ffi.offsetof(o, "sect"))
|
||||||
hdr.ehsize = f16(ffi.sizeof(hdr))
|
hdr.ehsize = f16(ffi.sizeof(hdr))
|
||||||
@@ -336,12 +344,8 @@ typedef struct {
|
|||||||
} PEobj;
|
} PEobj;
|
||||||
]]
|
]]
|
||||||
local symname = LJBC_PREFIX..ctx.modname
|
local symname = LJBC_PREFIX..ctx.modname
|
||||||
local is64 = false
|
local ai = assert(map_arch[ctx.arch])
|
||||||
if ctx.arch == "x86" then
|
local is64 = ai.b == 64
|
||||||
symname = "_"..symname
|
|
||||||
elseif ctx.arch == "x64" then
|
|
||||||
is64 = true
|
|
||||||
end
|
|
||||||
local symexport = " /EXPORT:"..symname..",DATA "
|
local symexport = " /EXPORT:"..symname..",DATA "
|
||||||
|
|
||||||
-- The file format is always little-endian. Swap if the host is big-endian.
|
-- 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.
|
-- Create PE object and fill in header.
|
||||||
local o = ffi.new("PEobj")
|
local o = ffi.new("PEobj")
|
||||||
local hdr = o.hdr
|
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.nsects = f16(2)
|
||||||
hdr.symtabofs = f32(ffi.offsetof(o, "sym0"))
|
hdr.symtabofs = f32(ffi.offsetof(o, "sym0"))
|
||||||
hdr.nsyms = f32(6)
|
hdr.nsyms = f32(6)
|
||||||
@@ -605,16 +609,16 @@ local function docmd(...)
|
|||||||
local n = 1
|
local n = 1
|
||||||
local list = false
|
local list = false
|
||||||
local ctx = {
|
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,
|
type = false, modname = false,
|
||||||
}
|
}
|
||||||
while n <= #arg do
|
while n <= #arg do
|
||||||
local a = arg[n]
|
local a = arg[n]
|
||||||
if type(a) == "string" and string.sub(a, 1, 1) == "-" and a ~= "-" then
|
if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then
|
||||||
table.remove(arg, n)
|
tremove(arg, n)
|
||||||
if a == "--" then break end
|
if a == "--" then break end
|
||||||
for m=2,#a do
|
for m=2,#a do
|
||||||
local opt = string.sub(a, m, m)
|
local opt = a:sub(m, m)
|
||||||
if opt == "l" then
|
if opt == "l" then
|
||||||
list = true
|
list = true
|
||||||
elseif opt == "s" then
|
elseif opt == "s" then
|
||||||
@@ -627,13 +631,13 @@ local function docmd(...)
|
|||||||
if n ~= 1 then usage() end
|
if n ~= 1 then usage() end
|
||||||
arg[1] = check(loadstring(arg[1]))
|
arg[1] = check(loadstring(arg[1]))
|
||||||
elseif opt == "n" then
|
elseif opt == "n" then
|
||||||
ctx.modname = checkmodname(table.remove(arg, n))
|
ctx.modname = checkmodname(tremove(arg, n))
|
||||||
elseif opt == "t" then
|
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
|
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
|
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
|
else
|
||||||
usage()
|
usage()
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT ARM disassembler module.
|
-- LuaJIT ARM disassembler module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT ARM64 disassembler module.
|
-- LuaJIT ARM64 disassembler module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
--
|
--
|
||||||
-- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
|
-- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT ARM64BE disassembler wrapper module.
|
-- LuaJIT ARM64BE disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- ARM64 instructions are always little-endian. So just forward to the
|
-- ARM64 instructions are always little-endian. So just forward to the
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT MIPS disassembler module.
|
-- LuaJIT MIPS disassembler module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT/X license. See Copyright Notice in luajit.h
|
-- 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.
|
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||||
@@ -19,12 +19,33 @@ local band, bor, tohex = bit.band, bit.bor, bit.tohex
|
|||||||
local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift
|
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_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 = {
|
local map_special = {
|
||||||
shift = 0, mask = 63,
|
shift = 0, mask = 63,
|
||||||
@@ -87,22 +108,6 @@ local map_regimm = {
|
|||||||
false, false, false, "synciSO",
|
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 = {
|
local map_cop1s = {
|
||||||
shift = 0, mask = 63,
|
shift = 0, mask = 63,
|
||||||
[0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH",
|
[0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH",
|
||||||
@@ -233,6 +238,208 @@ local map_pri = {
|
|||||||
false, "sdc1HSO", "sdc2TSO", "sdTSO",
|
false, "sdc1HSO", "sdc2TSO", "sdTSO",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Primary and extended opcode maps for MIPS R6
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local map_mul_r6 = { shift = 6, mask = 3, [2] = "mulDST", [3] = "muhDST" }
|
||||||
|
local map_mulu_r6 = { shift = 6, mask = 3, [2] = "muluDST", [3] = "muhuDST" }
|
||||||
|
local map_div_r6 = { shift = 6, mask = 3, [2] = "divDST", [3] = "modDST" }
|
||||||
|
local map_divu_r6 = { shift = 6, mask = 3, [2] = "divuDST", [3] = "moduDST" }
|
||||||
|
local map_dmul_r6 = { shift = 6, mask = 3, [2] = "dmulDST", [3] = "dmuhDST" }
|
||||||
|
local map_dmulu_r6 = { shift = 6, mask = 3, [2] = "dmuluDST", [3] = "dmuhuDST" }
|
||||||
|
local map_ddiv_r6 = { shift = 6, mask = 3, [2] = "ddivDST", [3] = "dmodDST" }
|
||||||
|
local map_ddivu_r6 = { shift = 6, mask = 3, [2] = "ddivuDST", [3] = "dmoduDST" }
|
||||||
|
|
||||||
|
local map_special_r6 = {
|
||||||
|
shift = 0, mask = 63,
|
||||||
|
[0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" },
|
||||||
|
false, map_srl, "sraDTA",
|
||||||
|
"sllvDTS", false, map_srlv, "sravDTS",
|
||||||
|
"jrS", "jalrD1S", false, false,
|
||||||
|
"syscallY", "breakY", false, "sync",
|
||||||
|
"clzDS", "cloDS", "dclzDS", "dcloDS",
|
||||||
|
"dsllvDST", "dlsaDSTA", "dsrlvDST", "dsravDST",
|
||||||
|
map_mul_r6, map_mulu_r6, map_div_r6, map_divu_r6,
|
||||||
|
map_dmul_r6, map_dmulu_r6, map_ddiv_r6, map_ddivu_r6,
|
||||||
|
"addDST", "addu|moveDST0", "subDST", "subu|neguDS0T",
|
||||||
|
"andDST", "or|moveDST0", "xorDST", "nor|notDST0",
|
||||||
|
false, false, "sltDST", "sltuDST",
|
||||||
|
"daddDST", "dadduDST", "dsubDST", "dsubuDST",
|
||||||
|
"tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ",
|
||||||
|
"teqSTZ", "seleqzDST", "tneSTZ", "selnezDST",
|
||||||
|
"dsllDTA", false, "dsrlDTA", "dsraDTA",
|
||||||
|
"dsll32DTA", false, "dsrl32DTA", "dsra32DTA",
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_bshfl_r6 = {
|
||||||
|
shift = 9, mask = 3,
|
||||||
|
[1] = "alignDSTa",
|
||||||
|
_ = {
|
||||||
|
shift = 6, mask = 31,
|
||||||
|
[0] = "bitswapDT",
|
||||||
|
[2] = "wsbhDT",
|
||||||
|
[16] = "sebDT",
|
||||||
|
[24] = "sehDT",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_dbshfl_r6 = {
|
||||||
|
shift = 9, mask = 3,
|
||||||
|
[1] = "dalignDSTa",
|
||||||
|
_ = {
|
||||||
|
shift = 6, mask = 31,
|
||||||
|
[0] = "dbitswapDT",
|
||||||
|
[2] = "dsbhDT",
|
||||||
|
[5] = "dshdDT",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_special3_r6 = {
|
||||||
|
shift = 0, mask = 63,
|
||||||
|
[0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK",
|
||||||
|
[4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL",
|
||||||
|
[32] = map_bshfl_r6, [36] = map_dbshfl_r6, [59] = "rdhwrTD",
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_regimm_r6 = {
|
||||||
|
shift = 16, mask = 31,
|
||||||
|
[0] = "bltzSB", [1] = "bgezSB",
|
||||||
|
[6] = "dahiSI", [30] = "datiSI",
|
||||||
|
[23] = "sigrieI", [31] = "synciSO",
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_pcrel_r6 = {
|
||||||
|
shift = 19, mask = 3,
|
||||||
|
[0] = "addiupcS2", "lwpcS2", "lwupcS2", {
|
||||||
|
shift = 18, mask = 1,
|
||||||
|
[0] = "ldpcS3", { shift = 16, mask = 3, [2] = "auipcSI", [3] = "aluipcSI" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_cop1s_r6 = {
|
||||||
|
shift = 0, mask = 63,
|
||||||
|
[0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH",
|
||||||
|
"sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG",
|
||||||
|
"round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG",
|
||||||
|
"round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG",
|
||||||
|
"sel.sFGH", false, false, false,
|
||||||
|
"seleqz.sFGH", "recip.sFG", "rsqrt.sFG", "selnez.sFGH",
|
||||||
|
"maddf.sFGH", "msubf.sFGH", "rint.sFG", "class.sFG",
|
||||||
|
"min.sFGH", "mina.sFGH", "max.sFGH", "maxa.sFGH",
|
||||||
|
false, "cvt.d.sFG", false, false,
|
||||||
|
"cvt.w.sFG", "cvt.l.sFG",
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_cop1d_r6 = {
|
||||||
|
shift = 0, mask = 63,
|
||||||
|
[0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH",
|
||||||
|
"sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG",
|
||||||
|
"round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG",
|
||||||
|
"round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG",
|
||||||
|
"sel.dFGH", false, false, false,
|
||||||
|
"seleqz.dFGH", "recip.dFG", "rsqrt.dFG", "selnez.dFGH",
|
||||||
|
"maddf.dFGH", "msubf.dFGH", "rint.dFG", "class.dFG",
|
||||||
|
"min.dFGH", "mina.dFGH", "max.dFGH", "maxa.dFGH",
|
||||||
|
"cvt.s.dFG", false, false, false,
|
||||||
|
"cvt.w.dFG", "cvt.l.dFG",
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_cop1w_r6 = {
|
||||||
|
shift = 0, mask = 63,
|
||||||
|
[0] = "cmp.af.sFGH", "cmp.un.sFGH", "cmp.eq.sFGH", "cmp.ueq.sFGH",
|
||||||
|
"cmp.lt.sFGH", "cmp.ult.sFGH", "cmp.le.sFGH", "cmp.ule.sFGH",
|
||||||
|
"cmp.saf.sFGH", "cmp.sun.sFGH", "cmp.seq.sFGH", "cmp.sueq.sFGH",
|
||||||
|
"cmp.slt.sFGH", "cmp.sult.sFGH", "cmp.sle.sFGH", "cmp.sule.sFGH",
|
||||||
|
false, "cmp.or.sFGH", "cmp.une.sFGH", "cmp.ne.sFGH",
|
||||||
|
false, false, false, false,
|
||||||
|
false, "cmp.sor.sFGH", "cmp.sune.sFGH", "cmp.sne.sFGH",
|
||||||
|
false, false, false, false,
|
||||||
|
"cvt.s.wFG", "cvt.d.wFG",
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_cop1l_r6 = {
|
||||||
|
shift = 0, mask = 63,
|
||||||
|
[0] = "cmp.af.dFGH", "cmp.un.dFGH", "cmp.eq.dFGH", "cmp.ueq.dFGH",
|
||||||
|
"cmp.lt.dFGH", "cmp.ult.dFGH", "cmp.le.dFGH", "cmp.ule.dFGH",
|
||||||
|
"cmp.saf.dFGH", "cmp.sun.dFGH", "cmp.seq.dFGH", "cmp.sueq.dFGH",
|
||||||
|
"cmp.slt.dFGH", "cmp.sult.dFGH", "cmp.sle.dFGH", "cmp.sule.dFGH",
|
||||||
|
false, "cmp.or.dFGH", "cmp.une.dFGH", "cmp.ne.dFGH",
|
||||||
|
false, false, false, false,
|
||||||
|
false, "cmp.sor.dFGH", "cmp.sune.dFGH", "cmp.sne.dFGH",
|
||||||
|
false, false, false, false,
|
||||||
|
"cvt.s.lFG", "cvt.d.lFG",
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_cop1_r6 = {
|
||||||
|
shift = 21, mask = 31,
|
||||||
|
[0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG",
|
||||||
|
"mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG",
|
||||||
|
false, "bc1eqzHB", false, false,
|
||||||
|
false, "bc1nezHB", false, false,
|
||||||
|
map_cop1s_r6, map_cop1d_r6, false, false,
|
||||||
|
map_cop1w_r6, map_cop1l_r6,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function maprs_popTS(rs, rt)
|
||||||
|
if rt == 0 then return 0 elseif rs == 0 then return 1
|
||||||
|
elseif rs == rt then return 2 else return 3 end
|
||||||
|
end
|
||||||
|
|
||||||
|
local map_pop06_r6 = {
|
||||||
|
maprs = maprs_popTS, [0] = "blezSB", "blezalcTB", "bgezalcTB", "bgeucSTB"
|
||||||
|
}
|
||||||
|
local map_pop07_r6 = {
|
||||||
|
maprs = maprs_popTS, [0] = "bgtzSB", "bgtzalcTB", "bltzalcTB", "bltucSTB"
|
||||||
|
}
|
||||||
|
local map_pop26_r6 = {
|
||||||
|
maprs = maprs_popTS, "blezcTB", "bgezcTB", "bgecSTB"
|
||||||
|
}
|
||||||
|
local map_pop27_r6 = {
|
||||||
|
maprs = maprs_popTS, "bgtzcTB", "bltzcTB", "bltcSTB"
|
||||||
|
}
|
||||||
|
|
||||||
|
local function maprs_popS(rs, rt)
|
||||||
|
if rs == 0 then return 0 else return 1 end
|
||||||
|
end
|
||||||
|
|
||||||
|
local map_pop66_r6 = {
|
||||||
|
maprs = maprs_popS, [0] = "jicTI", "beqzcSb"
|
||||||
|
}
|
||||||
|
local map_pop76_r6 = {
|
||||||
|
maprs = maprs_popS, [0] = "jialcTI", "bnezcSb"
|
||||||
|
}
|
||||||
|
|
||||||
|
local function maprs_popST(rs, rt)
|
||||||
|
if rs >= rt then return 0 elseif rs == 0 then return 1 else return 2 end
|
||||||
|
end
|
||||||
|
|
||||||
|
local map_pop10_r6 = {
|
||||||
|
maprs = maprs_popST, [0] = "bovcSTB", "beqzalcTB", "beqcSTB"
|
||||||
|
}
|
||||||
|
local map_pop30_r6 = {
|
||||||
|
maprs = maprs_popST, [0] = "bnvcSTB", "bnezalcTB", "bnecSTB"
|
||||||
|
}
|
||||||
|
|
||||||
|
local map_pri_r6 = {
|
||||||
|
[0] = map_special_r6, map_regimm_r6, "jJ", "jalJ",
|
||||||
|
"beq|beqz|bST00B", "bne|bnezST0B", map_pop06_r6, map_pop07_r6,
|
||||||
|
map_pop10_r6, "addiu|liTS0I", "sltiTSI", "sltiuTSI",
|
||||||
|
"andiTSU", "ori|liTS0U", "xoriTSU", "aui|luiTS0U",
|
||||||
|
map_cop0, map_cop1_r6, false, false,
|
||||||
|
false, false, map_pop26_r6, map_pop27_r6,
|
||||||
|
map_pop30_r6, "daddiuTSI", false, false,
|
||||||
|
false, "dauiTSI", false, map_special3_r6,
|
||||||
|
"lbTSO", "lhTSO", false, "lwTSO",
|
||||||
|
"lbuTSO", "lhuTSO", false, false,
|
||||||
|
"sbTSO", "shTSO", false, "swTSO",
|
||||||
|
false, false, false, false,
|
||||||
|
false, "lwc1HSO", "bc#", false,
|
||||||
|
false, "ldc1HSO", map_pop66_r6, "ldTSO",
|
||||||
|
false, "swc1HSO", "balc#", map_pcrel_r6,
|
||||||
|
false, "sdc1HSO", map_pop76_r6, "sdTSO",
|
||||||
|
}
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
local map_gpr = {
|
local map_gpr = {
|
||||||
@@ -287,10 +494,14 @@ local function disass_ins(ctx)
|
|||||||
ctx.op = op
|
ctx.op = op
|
||||||
ctx.rel = nil
|
ctx.rel = nil
|
||||||
|
|
||||||
local opat = map_pri[rshift(op, 26)]
|
local opat = ctx.map_pri[rshift(op, 26)]
|
||||||
while type(opat) ~= "string" do
|
while type(opat) ~= "string" do
|
||||||
if not opat then return unknown(ctx) end
|
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
|
end
|
||||||
local name, pat = match(opat, "^([a-z0-9_.]*)(.*)")
|
local name, pat = match(opat, "^([a-z0-9_.]*)(.*)")
|
||||||
local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)")
|
local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)")
|
||||||
@@ -314,6 +525,8 @@ local function disass_ins(ctx)
|
|||||||
x = "f"..band(rshift(op, 21), 31)
|
x = "f"..band(rshift(op, 21), 31)
|
||||||
elseif p == "A" then
|
elseif p == "A" then
|
||||||
x = band(rshift(op, 6), 31)
|
x = band(rshift(op, 6), 31)
|
||||||
|
elseif p == "a" then
|
||||||
|
x = band(rshift(op, 6), 7)
|
||||||
elseif p == "E" then
|
elseif p == "E" then
|
||||||
x = band(rshift(op, 6), 31) + 32
|
x = band(rshift(op, 6), 31) + 32
|
||||||
elseif p == "M" then
|
elseif p == "M" then
|
||||||
@@ -333,6 +546,10 @@ local function disass_ins(ctx)
|
|||||||
x = band(rshift(op, 11), 31) - last + 33
|
x = band(rshift(op, 11), 31) - last + 33
|
||||||
elseif p == "I" then
|
elseif p == "I" then
|
||||||
x = arshift(lshift(op, 16), 16)
|
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
|
elseif p == "U" then
|
||||||
x = band(op, 0xffff)
|
x = band(op, 0xffff)
|
||||||
elseif p == "O" then
|
elseif p == "O" then
|
||||||
@@ -342,7 +559,15 @@ local function disass_ins(ctx)
|
|||||||
local index = map_gpr[band(rshift(op, 16), 31)]
|
local index = map_gpr[band(rshift(op, 16), 31)]
|
||||||
operands[#operands] = format("%s(%s)", index, last)
|
operands[#operands] = format("%s(%s)", index, last)
|
||||||
elseif p == "B" then
|
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 = 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
|
ctx.rel = x
|
||||||
x = format("0x%08x", x)
|
x = format("0x%08x", x)
|
||||||
elseif p == "J" then
|
elseif p == "J" then
|
||||||
@@ -408,6 +633,7 @@ local function create(code, addr, out)
|
|||||||
ctx.disass = disass_block
|
ctx.disass = disass_block
|
||||||
ctx.hexdump = 8
|
ctx.hexdump = 8
|
||||||
ctx.get = get_be
|
ctx.get = get_be
|
||||||
|
ctx.map_pri = map_pri
|
||||||
return ctx
|
return ctx
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -417,6 +643,19 @@ local function create_el(code, addr, out)
|
|||||||
return ctx
|
return ctx
|
||||||
end
|
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.
|
-- Simple API: disassemble code (a string) at address and output via out.
|
||||||
local function disass(code, addr, out)
|
local function disass(code, addr, out)
|
||||||
create(code, addr, out):disass()
|
create(code, addr, out):disass()
|
||||||
@@ -426,6 +665,14 @@ local function disass_el(code, addr, out)
|
|||||||
create_el(code, addr, out):disass()
|
create_el(code, addr, out):disass()
|
||||||
end
|
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.
|
-- Return register name for RID.
|
||||||
local function regname(r)
|
local function regname(r)
|
||||||
if r < 32 then return map_gpr[r] end
|
if r < 32 then return map_gpr[r] end
|
||||||
@@ -436,8 +683,12 @@ end
|
|||||||
return {
|
return {
|
||||||
create = create,
|
create = create,
|
||||||
create_el = create_el,
|
create_el = create_el,
|
||||||
|
create_r6 = create_r6,
|
||||||
|
create_r6_el = create_r6_el,
|
||||||
disass = disass,
|
disass = disass,
|
||||||
disass_el = disass_el,
|
disass_el = disass_el,
|
||||||
|
disass_r6 = disass_r6,
|
||||||
|
disass_r6_el = disass_r6_el,
|
||||||
regname = regname
|
regname = regname
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT MIPS64 disassembler wrapper module.
|
-- LuaJIT MIPS64 disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This module just exports the big-endian functions from the
|
-- This module just exports the big-endian functions from the
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT MIPS64EL disassembler wrapper module.
|
-- LuaJIT MIPS64EL disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This module just exports the little-endian functions from the
|
-- This module just exports the little-endian functions from the
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
----------------------------------------------------------------------------
|
||||||
|
-- LuaJIT MIPS64R6 disassembler wrapper module.
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2005-2020 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-2020 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.
|
-- LuaJIT MIPSEL disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This module just exports the little-endian functions from the
|
-- This module just exports the little-endian functions from the
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT PPC disassembler module.
|
-- LuaJIT PPC disassembler module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT/X license. See Copyright Notice in luajit.h
|
-- 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.
|
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT x64 disassembler wrapper module.
|
-- LuaJIT x64 disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This module just exports the 64 bit functions from the combined
|
-- This module just exports the 64 bit functions from the combined
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT x86/x64 disassembler module.
|
-- LuaJIT x86/x64 disassembler module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT compiler dump module.
|
-- LuaJIT compiler dump module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
@@ -315,7 +315,9 @@ local function formatk(tr, idx, sn)
|
|||||||
local tn = type(k)
|
local tn = type(k)
|
||||||
local s
|
local s
|
||||||
if tn == "number" then
|
if tn == "number" then
|
||||||
if band(sn or 0, 0x30000) ~= 0 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"
|
s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz"
|
||||||
elseif k == 2^52+2^51 then
|
elseif k == 2^52+2^51 then
|
||||||
s = "bias"
|
s = "bias"
|
||||||
@@ -612,7 +614,7 @@ local function dump_texit(tr, ex, ngpr, nfpr, ...)
|
|||||||
out:write("---- TRACE ", tr, " exit ", ex, "\n")
|
out:write("---- TRACE ", tr, " exit ", ex, "\n")
|
||||||
if dumpmode.X then
|
if dumpmode.X then
|
||||||
local regs = {...}
|
local regs = {...}
|
||||||
if jit.arch == "x64" then
|
if jit.arch:sub(-2) == "64" then
|
||||||
for i=1,ngpr do
|
for i=1,ngpr do
|
||||||
out:write(format(" %016x", regs[i]))
|
out:write(format(" %016x", regs[i]))
|
||||||
if i % 4 == 0 then out:write("\n") end
|
if i % 4 == 0 then out:write("\n") end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT profiler.
|
-- LuaJIT profiler.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- Verbose mode of the LuaJIT compiler.
|
-- Verbose mode of the LuaJIT compiler.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT profiler zones.
|
-- LuaJIT profiler zones.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Auxiliary library for the Lua/C API.
|
** Auxiliary library for the Lua/C API.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major parts taken verbatim or adapted from the Lua interpreter.
|
** Major parts taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
@@ -345,17 +345,13 @@ LUALIB_API lua_State *luaL_newstate(void)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include "lj_alloc.h"
|
|
||||||
|
|
||||||
LUALIB_API lua_State *luaL_newstate(void)
|
LUALIB_API lua_State *luaL_newstate(void)
|
||||||
{
|
{
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
void *ud = lj_alloc_create();
|
|
||||||
if (ud == NULL) return NULL;
|
|
||||||
#if LJ_64 && !LJ_GC64
|
#if LJ_64 && !LJ_GC64
|
||||||
L = lj_state_newstate(lj_alloc_f, ud);
|
L = lj_state_newstate(LJ_ALLOCF_INTERNAL, NULL);
|
||||||
#else
|
#else
|
||||||
L = lua_newstate(lj_alloc_f, ud);
|
L = lua_newstate(LJ_ALLOCF_INTERNAL, NULL);
|
||||||
#endif
|
#endif
|
||||||
if (L) G(L)->panic = panic;
|
if (L) G(L)->panic = panic;
|
||||||
return L;
|
return L;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Base and coroutine library.
|
** Base and coroutine library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
@@ -224,9 +224,11 @@ LJLIB_CF(unpack)
|
|||||||
int32_t n, i = lj_lib_optint(L, 2, 1);
|
int32_t n, i = lj_lib_optint(L, 2, 1);
|
||||||
int32_t e = (L->base+3-1 < L->top && !tvisnil(L->base+3-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);
|
lj_lib_checkint(L, 3) : (int32_t)lj_tab_len(t);
|
||||||
|
uint32_t nu;
|
||||||
if (i > e) return 0;
|
if (i > e) return 0;
|
||||||
n = e - i + 1;
|
nu = (uint32_t)e - (uint32_t)i;
|
||||||
if (n <= 0 || !lua_checkstack(L, n))
|
n = (int32_t)(nu+1);
|
||||||
|
if (nu >= LUAI_MAXCSTACK || !lua_checkstack(L, n))
|
||||||
lj_err_caller(L, LJ_ERR_UNPACK);
|
lj_err_caller(L, LJ_ERR_UNPACK);
|
||||||
do {
|
do {
|
||||||
cTValue *tv = lj_tab_getint(t, i);
|
cTValue *tv = lj_tab_getint(t, i);
|
||||||
@@ -299,7 +301,7 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
|
|||||||
while (lj_char_isspace((unsigned char)(*ep))) ep++;
|
while (lj_char_isspace((unsigned char)(*ep))) ep++;
|
||||||
if (*ep == '\0') {
|
if (*ep == '\0') {
|
||||||
if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u+neg)) {
|
if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u+neg)) {
|
||||||
if (neg) ul = -ul;
|
if (neg) ul = (unsigned long)-(long)ul;
|
||||||
setintV(L->base-1-LJ_FR2, (int32_t)ul);
|
setintV(L->base-1-LJ_FR2, (int32_t)ul);
|
||||||
} else {
|
} else {
|
||||||
lua_Number n = (lua_Number)ul;
|
lua_Number n = (lua_Number)ul;
|
||||||
@@ -502,8 +504,8 @@ LJLIB_CF(print)
|
|||||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||||
tv = L->top-1;
|
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));
|
!gcrefu(basemt_it(G(L), LJ_TNUMX));
|
||||||
for (i = 0; i < nargs; i++) {
|
for (i = 0; i < nargs; i++) {
|
||||||
cTValue *o = &L->base[i];
|
cTValue *o = &L->base[i];
|
||||||
const char *str;
|
const char *str;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bit manipulation library.
|
** Bit manipulation library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lib_bit_c
|
#define lib_bit_c
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Debug library.
|
** Debug library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** 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;
|
int32_t n = lj_lib_checkint(L, 2) - 1;
|
||||||
if ((uint32_t)n >= fn->l.nupvalues)
|
if ((uint32_t)n >= fn->l.nupvalues)
|
||||||
lj_err_arg(L, 2, LJ_ERR_IDXRNG);
|
lj_err_arg(L, 2, LJ_ERR_IDXRNG);
|
||||||
setlightudV(L->top-1, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
|
lua_pushlightuserdata(L, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
|
||||||
(void *)&fn->c.upvalue[n]);
|
(void *)&fn->c.upvalue[n]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,13 +283,13 @@ LJLIB_CF(debug_setuservalue)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
#define KEY_HOOK ((void *)0x3004)
|
#define KEY_HOOK (U64x(80000000,00000000)|'h')
|
||||||
|
|
||||||
static void hookf(lua_State *L, lua_Debug *ar)
|
static void hookf(lua_State *L, lua_Debug *ar)
|
||||||
{
|
{
|
||||||
static const char *const hooknames[] =
|
static const char *const hooknames[] =
|
||||||
{"call", "return", "line", "count", "tail return"};
|
{"call", "return", "line", "count", "tail return"};
|
||||||
lua_pushlightuserdata(L, KEY_HOOK);
|
(L->top++)->u64 = KEY_HOOK;
|
||||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||||
if (lua_isfunction(L, -1)) {
|
if (lua_isfunction(L, -1)) {
|
||||||
lua_pushstring(L, hooknames[(int)ar->event]);
|
lua_pushstring(L, hooknames[(int)ar->event]);
|
||||||
@@ -334,7 +334,7 @@ LJLIB_CF(debug_sethook)
|
|||||||
count = luaL_optint(L, arg+3, 0);
|
count = luaL_optint(L, arg+3, 0);
|
||||||
func = hookf; mask = makemask(smask, count);
|
func = hookf; mask = makemask(smask, count);
|
||||||
}
|
}
|
||||||
lua_pushlightuserdata(L, KEY_HOOK);
|
(L->top++)->u64 = KEY_HOOK;
|
||||||
lua_pushvalue(L, arg+1);
|
lua_pushvalue(L, arg+1);
|
||||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||||
lua_sethook(L, func, mask, count);
|
lua_sethook(L, func, mask, count);
|
||||||
@@ -349,7 +349,7 @@ LJLIB_CF(debug_gethook)
|
|||||||
if (hook != NULL && hook != hookf) { /* external hook? */
|
if (hook != NULL && hook != hookf) { /* external hook? */
|
||||||
lua_pushliteral(L, "external hook");
|
lua_pushliteral(L, "external hook");
|
||||||
} else {
|
} else {
|
||||||
lua_pushlightuserdata(L, KEY_HOOK);
|
(L->top++)->u64 = KEY_HOOK;
|
||||||
lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
|
lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
|
||||||
}
|
}
|
||||||
lua_pushstring(L, unmakemask(mask, buff));
|
lua_pushstring(L, unmakemask(mask, buff));
|
||||||
@@ -369,7 +369,8 @@ LJLIB_CF(debug_debug)
|
|||||||
return 0;
|
return 0;
|
||||||
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
|
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
|
||||||
lua_pcall(L, 0, 0, 0)) {
|
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);
|
fputs("\n", stderr);
|
||||||
}
|
}
|
||||||
lua_settop(L, 0); /* remove eventual returns */
|
lua_settop(L, 0); /* remove eventual returns */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** FFI library.
|
** FFI library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lib_ffi_c
|
#define lib_ffi_c
|
||||||
@@ -194,7 +194,7 @@ LJLIB_CF(ffi_meta___eq) LJLIB_REC(cdata_arith MM_eq)
|
|||||||
|
|
||||||
LJLIB_CF(ffi_meta___len) LJLIB_REC(cdata_arith MM_len)
|
LJLIB_CF(ffi_meta___len) LJLIB_REC(cdata_arith MM_len)
|
||||||
{
|
{
|
||||||
return lj_carith_len(L);
|
return ffi_arith(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
LJLIB_CF(ffi_meta___lt) LJLIB_REC(cdata_arith MM_lt)
|
LJLIB_CF(ffi_meta___lt) LJLIB_REC(cdata_arith MM_lt)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Library initialization.
|
** Library initialization.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major parts taken verbatim from the Lua interpreter.
|
** Major parts taken verbatim from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** I/O library.
|
** I/O library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
@@ -101,9 +101,6 @@ static int io_file_close(lua_State *L, IOFileUD *iof)
|
|||||||
stat = pclose(iof->fp);
|
stat = pclose(iof->fp);
|
||||||
#elif LJ_TARGET_WINDOWS && !LJ_TARGET_XBOXONE && !LJ_TARGET_UWP
|
#elif LJ_TARGET_WINDOWS && !LJ_TARGET_XBOXONE && !LJ_TARGET_UWP
|
||||||
stat = _pclose(iof->fp);
|
stat = _pclose(iof->fp);
|
||||||
#else
|
|
||||||
lua_assert(0);
|
|
||||||
return 0;
|
|
||||||
#endif
|
#endif
|
||||||
#if LJ_52
|
#if LJ_52
|
||||||
iof->fp = NULL;
|
iof->fp = NULL;
|
||||||
@@ -112,7 +109,8 @@ static int io_file_close(lua_State *L, IOFileUD *iof)
|
|||||||
ok = (stat != -1);
|
ok = (stat != -1);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} 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++);
|
setnilV(L->top++);
|
||||||
lua_pushliteral(L, "cannot close standard file");
|
lua_pushliteral(L, "cannot close standard file");
|
||||||
return 2;
|
return 2;
|
||||||
@@ -306,6 +304,14 @@ LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0)
|
|||||||
return luaL_fileresult(L, fflush(io_tofile(L)->fp) == 0, NULL);
|
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)
|
LJLIB_CF(io_method_seek)
|
||||||
{
|
{
|
||||||
FILE *fp = io_tofile(L)->fp;
|
FILE *fp = io_tofile(L)->fp;
|
||||||
|
|||||||
+40
-52
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** JIT library.
|
** JIT library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lib_jit_c
|
#define lib_jit_c
|
||||||
@@ -104,8 +104,8 @@ LJLIB_CF(jit_status)
|
|||||||
jit_State *J = L2J(L);
|
jit_State *J = L2J(L);
|
||||||
L->top = L->base;
|
L->top = L->base;
|
||||||
setboolV(L->top++, (J->flags & JIT_F_ON) ? 1 : 0);
|
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_CPU, JIT_F_CPUSTRING);
|
||||||
flagbits_to_strings(L, J->flags, JIT_F_OPT_FIRST, JIT_F_OPTSTRING);
|
flagbits_to_strings(L, J->flags, JIT_F_OPT, JIT_F_OPTSTRING);
|
||||||
return (int)(L->top - L->base);
|
return (int)(L->top - L->base);
|
||||||
#else
|
#else
|
||||||
setboolV(L->top++, 0);
|
setboolV(L->top++, 0);
|
||||||
@@ -113,6 +113,13 @@ LJLIB_CF(jit_status)
|
|||||||
#endif
|
#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)
|
LJLIB_CF(jit_attach)
|
||||||
{
|
{
|
||||||
#ifdef LUAJIT_DISABLE_VMEVENT
|
#ifdef LUAJIT_DISABLE_VMEVENT
|
||||||
@@ -227,7 +234,7 @@ LJLIB_CF(jit_util_funcbc)
|
|||||||
if (pc < pt->sizebc) {
|
if (pc < pt->sizebc) {
|
||||||
BCIns ins = proto_bc(pt)[pc];
|
BCIns ins = proto_bc(pt)[pc];
|
||||||
BCOp op = bc_op(ins);
|
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, ins);
|
||||||
setintV(L->top+1, lj_bc_mode[op]);
|
setintV(L->top+1, lj_bc_mode[op]);
|
||||||
L->top += 2;
|
L->top += 2;
|
||||||
@@ -471,7 +478,7 @@ static int jitopt_flag(jit_State *J, const char *str)
|
|||||||
str += str[2] == '-' ? 3 : 2;
|
str += str[2] == '-' ? 3 : 2;
|
||||||
set = 0;
|
set = 0;
|
||||||
}
|
}
|
||||||
for (opt = JIT_F_OPT_FIRST; ; opt <<= 1) {
|
for (opt = JIT_F_OPT; ; opt <<= 1) {
|
||||||
size_t len = *(const uint8_t *)lst;
|
size_t len = *(const uint8_t *)lst;
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
break;
|
break;
|
||||||
@@ -491,7 +498,7 @@ static int jitopt_param(jit_State *J, const char *str)
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < JIT_P__MAX; i++) {
|
for (i = 0; i < JIT_P__MAX; i++) {
|
||||||
size_t len = *(const uint8_t *)lst;
|
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] == '=') {
|
if (strncmp(str, lst+1, len) == 0 && str[len] == '=') {
|
||||||
int32_t n = 0;
|
int32_t n = 0;
|
||||||
const char *p = &str[len+1];
|
const char *p = &str[len+1];
|
||||||
@@ -540,15 +547,15 @@ LJLIB_CF(jit_opt_start)
|
|||||||
|
|
||||||
/* Not loaded by default, use: local profile = require("jit.profile") */
|
/* Not loaded by default, use: local profile = require("jit.profile") */
|
||||||
|
|
||||||
static const char KEY_PROFILE_THREAD = 't';
|
#define KEY_PROFILE_THREAD (U64x(80000000,00000000)|'t')
|
||||||
static const char KEY_PROFILE_FUNC = 'f';
|
#define KEY_PROFILE_FUNC (U64x(80000000,00000000)|'f')
|
||||||
|
|
||||||
static void jit_profile_callback(lua_State *L2, lua_State *L, int samples,
|
static void jit_profile_callback(lua_State *L2, lua_State *L, int samples,
|
||||||
int vmstate)
|
int vmstate)
|
||||||
{
|
{
|
||||||
TValue key;
|
TValue key;
|
||||||
cTValue *tv;
|
cTValue *tv;
|
||||||
setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
|
key.u64 = KEY_PROFILE_FUNC;
|
||||||
tv = lj_tab_get(L, tabV(registry(L)), &key);
|
tv = lj_tab_get(L, tabV(registry(L)), &key);
|
||||||
if (tvisfunc(tv)) {
|
if (tvisfunc(tv)) {
|
||||||
char vmst = (char)vmstate;
|
char vmst = (char)vmstate;
|
||||||
@@ -575,9 +582,9 @@ LJLIB_CF(jit_profile_start)
|
|||||||
lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */
|
lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */
|
||||||
TValue key;
|
TValue key;
|
||||||
/* Anchor thread and function in registry. */
|
/* 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);
|
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);
|
setfuncV(L, lj_tab_set(L, registry, &key), func);
|
||||||
lj_gc_anybarriert(L, registry);
|
lj_gc_anybarriert(L, registry);
|
||||||
luaJIT_profile_start(L, mode ? strdata(mode) : "",
|
luaJIT_profile_start(L, mode ? strdata(mode) : "",
|
||||||
@@ -592,9 +599,9 @@ LJLIB_CF(jit_profile_stop)
|
|||||||
TValue key;
|
TValue key;
|
||||||
luaJIT_profile_stop(L);
|
luaJIT_profile_stop(L);
|
||||||
registry = tabV(registry(L));
|
registry = tabV(registry(L));
|
||||||
setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
|
key.u64 = KEY_PROFILE_THREAD;
|
||||||
setnilV(lj_tab_set(L, registry, &key));
|
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));
|
setnilV(lj_tab_set(L, registry, &key));
|
||||||
lj_gc_anybarriert(L, registry);
|
lj_gc_anybarriert(L, registry);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -640,59 +647,41 @@ JIT_PARAMDEF(JIT_PARAMINIT)
|
|||||||
#undef JIT_PARAMINIT
|
#undef JIT_PARAMINIT
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LJ_TARGET_ARM && LJ_TARGET_LINUX
|
#if LJ_TARGET_ARM && LJ_TARGET_LINUX
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Arch-dependent CPU detection. */
|
/* Arch-dependent CPU feature detection. */
|
||||||
static uint32_t jit_cpudetect(lua_State *L)
|
static uint32_t jit_cpudetect(void)
|
||||||
{
|
{
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
#if LJ_TARGET_X86ORX64
|
#if LJ_TARGET_X86ORX64
|
||||||
|
|
||||||
uint32_t vendor[4];
|
uint32_t vendor[4];
|
||||||
uint32_t features[4];
|
uint32_t features[4];
|
||||||
if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) {
|
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] >> 0)&1) * JIT_F_SSE3;
|
||||||
flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1;
|
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) {
|
if (vendor[0] >= 7) {
|
||||||
uint32_t xfeatures[4];
|
uint32_t xfeatures[4];
|
||||||
lj_vm_cpuid(7, xfeatures);
|
lj_vm_cpuid(7, xfeatures);
|
||||||
flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2;
|
flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/* Check for required instruction set support on x86 (unnecessary on x64). */
|
/* Don't bother checking for SSE2 -- the VM will crash before getting here. */
|
||||||
#if LJ_TARGET_X86
|
|
||||||
if (!(flags & JIT_F_SSE2))
|
|
||||||
luaL_error(L, "CPU with SSE2 required");
|
|
||||||
#endif
|
|
||||||
#elif LJ_TARGET_ARM
|
#elif LJ_TARGET_ARM
|
||||||
#if LJ_HASJIT
|
|
||||||
int ver = LJ_ARCH_VERSION; /* Compile-time ARM CPU detection. */
|
int ver = LJ_ARCH_VERSION; /* Compile-time ARM CPU detection. */
|
||||||
#if LJ_TARGET_LINUX
|
#if LJ_TARGET_LINUX
|
||||||
if (ver < 70) { /* Runtime ARM CPU detection. */
|
if (ver < 70) { /* Runtime ARM CPU detection. */
|
||||||
struct utsname ut;
|
struct utsname ut;
|
||||||
uname(&ut);
|
uname(&ut);
|
||||||
if (strncmp(ut.machine, "armv", 4) == 0) {
|
if (strncmp(ut.machine, "armv", 4) == 0) {
|
||||||
if (ut.machine[4] >= '7')
|
if (ut.machine[4] >= '8') ver = 80;
|
||||||
ver = 70;
|
else if (ut.machine[4] == '7') ver = 70;
|
||||||
else if (ut.machine[4] == '6')
|
else if (ut.machine[4] == '6') ver = 60;
|
||||||
ver = 60;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -700,20 +689,22 @@ static uint32_t jit_cpudetect(lua_State *L)
|
|||||||
ver >= 61 ? JIT_F_ARMV6T2_ :
|
ver >= 61 ? JIT_F_ARMV6T2_ :
|
||||||
ver >= 60 ? JIT_F_ARMV6_ : 0;
|
ver >= 60 ? JIT_F_ARMV6_ : 0;
|
||||||
flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2;
|
flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2;
|
||||||
#endif
|
|
||||||
#elif LJ_TARGET_ARM64
|
#elif LJ_TARGET_ARM64
|
||||||
|
|
||||||
/* No optional CPU features to detect (for now). */
|
/* No optional CPU features to detect (for now). */
|
||||||
|
|
||||||
#elif LJ_TARGET_PPC
|
#elif LJ_TARGET_PPC
|
||||||
#if LJ_HASJIT
|
|
||||||
#if LJ_ARCH_SQRT
|
#if LJ_ARCH_SQRT
|
||||||
flags |= JIT_F_SQRT;
|
flags |= JIT_F_SQRT;
|
||||||
#endif
|
#endif
|
||||||
#if LJ_ARCH_ROUND
|
#if LJ_ARCH_ROUND
|
||||||
flags |= JIT_F_ROUND;
|
flags |= JIT_F_ROUND;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#elif LJ_TARGET_MIPS
|
#elif LJ_TARGET_MIPS
|
||||||
#if LJ_HASJIT
|
|
||||||
/* Compile-time MIPS CPU detection. */
|
/* Compile-time MIPS CPU detection. */
|
||||||
#if LJ_ARCH_VERSION >= 20
|
#if LJ_ARCH_VERSION >= 20
|
||||||
flags |= JIT_F_MIPSXXR2;
|
flags |= JIT_F_MIPSXXR2;
|
||||||
@@ -731,31 +722,28 @@ static uint32_t jit_cpudetect(lua_State *L)
|
|||||||
if (x) flags |= JIT_F_MIPSXXR2; /* Either 0x80000000 (R2) or 0 (R1). */
|
if (x) flags |= JIT_F_MIPSXXR2; /* Either 0x80000000 (R2) or 0 (R1). */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#error "Missing CPU detection for this architecture"
|
#error "Missing CPU detection for this architecture"
|
||||||
#endif
|
#endif
|
||||||
UNUSED(L);
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize JIT compiler. */
|
/* Initialize JIT compiler. */
|
||||||
static void jit_init(lua_State *L)
|
static void jit_init(lua_State *L)
|
||||||
{
|
{
|
||||||
uint32_t flags = jit_cpudetect(L);
|
|
||||||
#if LJ_HASJIT
|
|
||||||
jit_State *J = L2J(L);
|
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));
|
memcpy(J->param, jit_param_default, sizeof(J->param));
|
||||||
lj_dispatch_update(G(L));
|
lj_dispatch_update(G(L));
|
||||||
#else
|
|
||||||
UNUSED(flags);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
LUALIB_API int luaopen_jit(lua_State *L)
|
LUALIB_API int luaopen_jit(lua_State *L)
|
||||||
{
|
{
|
||||||
|
#if LJ_HASJIT
|
||||||
jit_init(L);
|
jit_init(L);
|
||||||
|
#endif
|
||||||
lua_pushliteral(L, LJ_OS_NAME);
|
lua_pushliteral(L, LJ_OS_NAME);
|
||||||
lua_pushliteral(L, LJ_ARCH_NAME);
|
lua_pushliteral(L, LJ_ARCH_NAME);
|
||||||
lua_pushinteger(L, LUAJIT_VERSION_NUM);
|
lua_pushinteger(L, LUAJIT_VERSION_NUM);
|
||||||
|
|||||||
+27
-52
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Math library.
|
** Math library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "lj_obj.h"
|
#include "lj_obj.h"
|
||||||
#include "lj_lib.h"
|
#include "lj_lib.h"
|
||||||
#include "lj_vm.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);
|
lj_lib_checknum(L, 1);
|
||||||
return FFH_RETRY;
|
return FFH_RETRY;
|
||||||
}
|
}
|
||||||
LJLIB_ASM_(math_log10) LJLIB_REC(math_unary IRFPM_LOG10)
|
LJLIB_ASM_(math_log10) LJLIB_REC(math_call IRCALL_log10)
|
||||||
LJLIB_ASM_(math_exp) LJLIB_REC(math_unary IRFPM_EXP)
|
LJLIB_ASM_(math_exp) LJLIB_REC(math_call IRCALL_exp)
|
||||||
LJLIB_ASM_(math_sin) LJLIB_REC(math_unary IRFPM_SIN)
|
LJLIB_ASM_(math_sin) LJLIB_REC(math_call IRCALL_sin)
|
||||||
LJLIB_ASM_(math_cos) LJLIB_REC(math_unary IRFPM_COS)
|
LJLIB_ASM_(math_cos) LJLIB_REC(math_call IRCALL_cos)
|
||||||
LJLIB_ASM_(math_tan) LJLIB_REC(math_unary IRFPM_TAN)
|
LJLIB_ASM_(math_tan) LJLIB_REC(math_call IRCALL_tan)
|
||||||
LJLIB_ASM_(math_asin) LJLIB_REC(math_atrig FF_math_asin)
|
LJLIB_ASM_(math_asin) LJLIB_REC(math_call IRCALL_asin)
|
||||||
LJLIB_ASM_(math_acos) LJLIB_REC(math_atrig FF_math_acos)
|
LJLIB_ASM_(math_acos) LJLIB_REC(math_call IRCALL_acos)
|
||||||
LJLIB_ASM_(math_atan) LJLIB_REC(math_atrig FF_math_atan)
|
LJLIB_ASM_(math_atan) LJLIB_REC(math_call IRCALL_atan)
|
||||||
LJLIB_ASM_(math_sinh) LJLIB_REC(math_htrig IRCALL_sinh)
|
LJLIB_ASM_(math_sinh) LJLIB_REC(math_call IRCALL_sinh)
|
||||||
LJLIB_ASM_(math_cosh) LJLIB_REC(math_htrig IRCALL_cosh)
|
LJLIB_ASM_(math_cosh) LJLIB_REC(math_call IRCALL_cosh)
|
||||||
LJLIB_ASM_(math_tanh) LJLIB_REC(math_htrig IRCALL_tanh)
|
LJLIB_ASM_(math_tanh) LJLIB_REC(math_call IRCALL_tanh)
|
||||||
LJLIB_ASM_(math_frexp)
|
LJLIB_ASM_(math_frexp)
|
||||||
LJLIB_ASM_(math_modf) LJLIB_REC(.)
|
LJLIB_ASM_(math_modf)
|
||||||
|
|
||||||
LJLIB_ASM(math_log) LJLIB_REC(math_log)
|
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.
|
** 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. */
|
/* Union needed for bit-pattern conversion between uint64_t and double. */
|
||||||
typedef union { uint64_t u64; double d; } U64double;
|
typedef union { uint64_t u64; double d; } U64double;
|
||||||
|
|
||||||
/* Update generator i and compute a running xor of all states. */
|
/* PRNG seeding function. */
|
||||||
#define TW223_GEN(i, k, q, s) \
|
static void random_seed(PRNGState *rs, double d)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
uint32_t r = 0x11090601; /* 64-k[i] as four 8 bit constants. */
|
uint32_t r = 0x11090601; /* 64-k[i] as four 8 bit constants. */
|
||||||
int i;
|
int i;
|
||||||
@@ -141,24 +119,22 @@ static void random_init(RandomState *rs, double d)
|
|||||||
uint32_t m = 1u << (r&255);
|
uint32_t m = 1u << (r&255);
|
||||||
r >>= 8;
|
r >>= 8;
|
||||||
u.d = d = d * 3.14159265358979323846 + 2.7182818284590452354;
|
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. */
|
if (u.u64 < m) u.u64 += m; /* Ensure k[i] MSB of u[i] are non-zero. */
|
||||||
rs->gen[i] = u.u64;
|
rs->u[i] = u.u64;
|
||||||
}
|
}
|
||||||
rs->valid = 1;
|
|
||||||
for (i = 0; i < 10; i++)
|
for (i = 0; i < 10; i++)
|
||||||
lj_math_random_step(rs);
|
(void)lj_prng_u64(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PRNG extract function. */
|
/* 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(.)
|
LJLIB_CF(math_random) LJLIB_REC(.)
|
||||||
{
|
{
|
||||||
int n = (int)(L->top - L->base);
|
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;
|
U64double u;
|
||||||
double d;
|
double d;
|
||||||
if (LJ_UNLIKELY(!rs->valid)) random_init(rs, 0.0);
|
u.u64 = lj_prng_u64d(rs);
|
||||||
u.u64 = lj_math_random_step(rs);
|
|
||||||
d = u.d - 1.0;
|
d = u.d - 1.0;
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
#if LJ_DUALNUM
|
#if LJ_DUALNUM
|
||||||
@@ -203,11 +179,11 @@ LJLIB_CF(math_random) LJLIB_REC(.)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* PRNG seed function. */
|
/* 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)
|
LJLIB_CF(math_randomseed)
|
||||||
{
|
{
|
||||||
RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
|
PRNGState *rs = (PRNGState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
|
||||||
random_init(rs, lj_lib_checknum(L, 1));
|
random_seed(rs, lj_lib_checknum(L, 1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,9 +193,8 @@ LJLIB_CF(math_randomseed)
|
|||||||
|
|
||||||
LUALIB_API int luaopen_math(lua_State *L)
|
LUALIB_API int luaopen_math(lua_State *L)
|
||||||
{
|
{
|
||||||
RandomState *rs;
|
PRNGState *rs = (PRNGState *)lua_newuserdata(L, sizeof(PRNGState));
|
||||||
rs = (RandomState *)lua_newuserdata(L, sizeof(RandomState));
|
lj_prng_seed_fixed(rs);
|
||||||
rs->valid = 0; /* Use lazy initialization to save some time on startup. */
|
|
||||||
LJ_LIB_REG(L, LUA_MATHLIBNAME, math);
|
LJ_LIB_REG(L, LUA_MATHLIBNAME, math);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** OS library.
|
** OS library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Package library.
|
** Package library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2012 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2012 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
@@ -237,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)
|
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) *reg = ll_load(L, path, (*name == '*'));
|
||||||
if (*reg == NULL) {
|
if (*reg == NULL) {
|
||||||
return PACKAGE_ERR_LIB; /* Unable to load library. */
|
return PACKAGE_ERR_LIB; /* Unable to load library. */
|
||||||
@@ -255,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));
|
const char *bcdata = ll_bcsym(*reg, mksymname(L, name, SYMPREFIX_BC));
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
if (bcdata) {
|
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 PACKAGE_ERR_LOAD;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -412,7 +417,7 @@ static int lj_cf_package_loader_preload(lua_State *L)
|
|||||||
if (lua_isnil(L, -1)) { /* Not found? */
|
if (lua_isnil(L, -1)) { /* Not found? */
|
||||||
const char *bcname = mksymname(L, name, SYMPREFIX_BC);
|
const char *bcname = mksymname(L, name, SYMPREFIX_BC);
|
||||||
const char *bcdata = ll_bcsym(NULL, bcname);
|
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);
|
lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -420,7 +425,7 @@ static int lj_cf_package_loader_preload(lua_State *L)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
#define sentinel ((void *)0x4004)
|
#define KEY_SENTINEL (U64x(80000000,00000000)|'s')
|
||||||
|
|
||||||
static int lj_cf_package_require(lua_State *L)
|
static int lj_cf_package_require(lua_State *L)
|
||||||
{
|
{
|
||||||
@@ -430,7 +435,7 @@ static int lj_cf_package_require(lua_State *L)
|
|||||||
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
|
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
|
||||||
lua_getfield(L, 2, name);
|
lua_getfield(L, 2, name);
|
||||||
if (lua_toboolean(L, -1)) { /* is it there? */
|
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);
|
luaL_error(L, "loop or previous error loading module " LUA_QS, name);
|
||||||
return 1; /* package is already loaded */
|
return 1; /* package is already loaded */
|
||||||
}
|
}
|
||||||
@@ -453,14 +458,14 @@ static int lj_cf_package_require(lua_State *L)
|
|||||||
else
|
else
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
lua_pushlightuserdata(L, sentinel);
|
(L->top++)->u64 = KEY_SENTINEL;
|
||||||
lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
|
lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
|
||||||
lua_pushstring(L, name); /* pass name as argument to module */
|
lua_pushstring(L, name); /* pass name as argument to module */
|
||||||
lua_call(L, 1, 1); /* run loaded module */
|
lua_call(L, 1, 1); /* run loaded module */
|
||||||
if (!lua_isnil(L, -1)) /* non-nil return? */
|
if (!lua_isnil(L, -1)) /* non-nil return? */
|
||||||
lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
|
lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
|
||||||
lua_getfield(L, 2, name);
|
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_pushboolean(L, 1); /* use true as result */
|
||||||
lua_pushvalue(L, -1); /* extra copy to be returned */
|
lua_pushvalue(L, -1); /* extra copy to be returned */
|
||||||
lua_setfield(L, 2, name); /* _LOADED[name] = true */
|
lua_setfield(L, 2, name); /* _LOADED[name] = true */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** String library.
|
** String library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** 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 */
|
/* macro to `unsign' a character */
|
||||||
#define uchar(c) ((unsigned char)(c))
|
#define uchar(c) ((unsigned char)(c))
|
||||||
|
|
||||||
#define CAP_UNFINISHED (-1)
|
#define CAP_UNFINISHED (-1)
|
||||||
#define CAP_POSITION (-2)
|
#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;
|
TValue *o = L->base+arg-1;
|
||||||
cTValue *mo;
|
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)))
|
if (LJ_LIKELY(tvisstr(o)))
|
||||||
return strV(o);
|
return strV(o);
|
||||||
if (retry != 2 && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
|
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));
|
lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg));
|
||||||
break;
|
break;
|
||||||
case STRFMT_PTR: /* No formatting. */
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
lua_assert(0);
|
lj_assertL(0, "bad string format type");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Table library.
|
** Table library.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
|
|||||||
@@ -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:str_fastcmp
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Optimized string compare
|
|
||||||
Memcheck:Addr1
|
|
||||||
fun:str_fastcmp
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Optimized string compare
|
|
||||||
Memcheck:Cond
|
|
||||||
fun:str_fastcmp
|
|
||||||
}
|
|
||||||
+48
-53
@@ -6,7 +6,7 @@
|
|||||||
**
|
**
|
||||||
** This is a version (aka dlmalloc) of malloc/free/realloc written by
|
** This is a version (aka dlmalloc) of malloc/free/realloc written by
|
||||||
** Doug Lea and released to the public domain, as explained at
|
** 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)
|
** * 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
|
** If you want to use dlmalloc in another project, you should get
|
||||||
** the original from: ftp://gee.cs.oswego.edu/pub/misc/
|
** the original from: ftp://gee.cs.oswego.edu/pub/misc/
|
||||||
** For thread-safe derivatives, take a look at:
|
** For thread-safe derivatives, take a look at:
|
||||||
** - ptmalloc: http://www.malloc.de/
|
** - ptmalloc: https://www.malloc.de/
|
||||||
** - nedmalloc: http://www.nedprod.com/programs/portable/nedmalloc/
|
** - nedmalloc: https://www.nedprod.com/programs/portable/nedmalloc/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_alloc_c
|
#define lj_alloc_c
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "lj_def.h"
|
#include "lj_def.h"
|
||||||
#include "lj_arch.h"
|
#include "lj_arch.h"
|
||||||
#include "lj_alloc.h"
|
#include "lj_alloc.h"
|
||||||
|
#include "lj_prng.h"
|
||||||
|
|
||||||
#ifndef LUAJIT_USE_SYSMALLOC
|
#ifndef LUAJIT_USE_SYSMALLOC
|
||||||
|
|
||||||
@@ -123,7 +124,7 @@
|
|||||||
|
|
||||||
#if LJ_ALLOC_NTAVM
|
#if LJ_ALLOC_NTAVM
|
||||||
/* Undocumented, but hey, that's what we all love so much about Windows. */
|
/* 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);
|
size_t *size, ULONG alloctype, ULONG prot);
|
||||||
static PNTAVM ntavm;
|
static PNTAVM ntavm;
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ static void init_mmap(void)
|
|||||||
#define INIT_MMAP() init_mmap()
|
#define INIT_MMAP() init_mmap()
|
||||||
|
|
||||||
/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */
|
/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */
|
||||||
static void *CALL_MMAP(size_t size)
|
static void *mmap_plain(size_t size)
|
||||||
{
|
{
|
||||||
DWORD olderr = GetLastError();
|
DWORD olderr = GetLastError();
|
||||||
void *ptr = NULL;
|
void *ptr = NULL;
|
||||||
@@ -151,7 +152,7 @@ static void *CALL_MMAP(size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
|
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
|
||||||
static void *DIRECT_MMAP(size_t size)
|
static void *direct_mmap(size_t size)
|
||||||
{
|
{
|
||||||
DWORD olderr = GetLastError();
|
DWORD olderr = GetLastError();
|
||||||
void *ptr = NULL;
|
void *ptr = NULL;
|
||||||
@@ -164,7 +165,7 @@ static void *DIRECT_MMAP(size_t size)
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
/* Win32 MMAP via VirtualAlloc */
|
/* Win32 MMAP via VirtualAlloc */
|
||||||
static void *CALL_MMAP(size_t size)
|
static void *mmap_plain(size_t size)
|
||||||
{
|
{
|
||||||
DWORD olderr = GetLastError();
|
DWORD olderr = GetLastError();
|
||||||
void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
||||||
@@ -173,7 +174,7 @@ static void *CALL_MMAP(size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
|
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
|
||||||
static void *DIRECT_MMAP(size_t size)
|
static void *direct_mmap(size_t size)
|
||||||
{
|
{
|
||||||
DWORD olderr = GetLastError();
|
DWORD olderr = GetLastError();
|
||||||
void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
|
void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
|
||||||
@@ -184,6 +185,9 @@ static void *DIRECT_MMAP(size_t size)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CALL_MMAP(prng, size) mmap_plain(size)
|
||||||
|
#define DIRECT_MMAP(prng, size) direct_mmap(size)
|
||||||
|
|
||||||
/* This function supports releasing coalesed segments */
|
/* This function supports releasing coalesed segments */
|
||||||
static int CALL_MUNMAP(void *ptr, size_t size)
|
static int CALL_MUNMAP(void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
@@ -226,30 +230,10 @@ static int CALL_MUNMAP(void *ptr, size_t size)
|
|||||||
|
|
||||||
#define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000)
|
#define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000)
|
||||||
|
|
||||||
/* No point in a giant ifdef mess. Just try to open /dev/urandom.
|
static void *mmap_probe(PRNGState *rs, size_t size)
|
||||||
** It doesn't really matter if this fails, since we get some ASLR bits from
|
|
||||||
** every unsuitable allocation, too. And we prefer linear allocation, anyway.
|
|
||||||
*/
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
static uintptr_t mmap_probe_seed(void)
|
|
||||||
{
|
|
||||||
uintptr_t val;
|
|
||||||
int fd = open("/dev/urandom", O_RDONLY);
|
|
||||||
if (fd != -1) {
|
|
||||||
int ok = ((size_t)read(fd, &val, sizeof(val)) == sizeof(val));
|
|
||||||
(void)close(fd);
|
|
||||||
if (ok) return val;
|
|
||||||
}
|
|
||||||
return 1; /* Punt. */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *mmap_probe(size_t size)
|
|
||||||
{
|
{
|
||||||
/* Hint for next allocation. Doesn't need to be thread-safe. */
|
/* Hint for next allocation. Doesn't need to be thread-safe. */
|
||||||
static uintptr_t hint_addr = 0;
|
static uintptr_t hint_addr = 0;
|
||||||
static uintptr_t hint_prng = 0;
|
|
||||||
int olderr = errno;
|
int olderr = errno;
|
||||||
int retry;
|
int retry;
|
||||||
for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) {
|
for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) {
|
||||||
@@ -281,15 +265,8 @@ static void *mmap_probe(size_t size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Finally, try pseudo-random probing. */
|
/* Finally, try pseudo-random probing. */
|
||||||
if (LJ_UNLIKELY(hint_prng == 0)) {
|
do {
|
||||||
hint_prng = mmap_probe_seed();
|
hint_addr = lj_prng_u64(rs) & (((uintptr_t)1<<LJ_ALLOC_MBITS)-LJ_PAGESIZE);
|
||||||
}
|
|
||||||
/* The unsuitable address we got has some ASLR PRNG bits. */
|
|
||||||
hint_addr ^= addr & ~((uintptr_t)(LJ_PAGESIZE-1));
|
|
||||||
do { /* The PRNG itself is very weak, but see above. */
|
|
||||||
hint_prng = hint_prng * 1103515245 + 12345;
|
|
||||||
hint_addr ^= hint_prng * (uintptr_t)LJ_PAGESIZE;
|
|
||||||
hint_addr &= (((uintptr_t)1 << LJ_ALLOC_MBITS)-1);
|
|
||||||
} while (hint_addr < LJ_ALLOC_MMAP_PROBE_LOWER);
|
} while (hint_addr < LJ_ALLOC_MMAP_PROBE_LOWER);
|
||||||
}
|
}
|
||||||
errno = olderr;
|
errno = olderr;
|
||||||
@@ -300,18 +277,22 @@ static void *mmap_probe(size_t size)
|
|||||||
|
|
||||||
#if LJ_ALLOC_MMAP32
|
#if LJ_ALLOC_MMAP32
|
||||||
|
|
||||||
#if defined(__sun__)
|
#if LJ_TARGET_SOLARIS
|
||||||
#define LJ_ALLOC_MMAP32_START ((uintptr_t)0x1000)
|
#define LJ_ALLOC_MMAP32_START ((uintptr_t)0x1000)
|
||||||
#else
|
#else
|
||||||
#define LJ_ALLOC_MMAP32_START ((uintptr_t)0)
|
#define LJ_ALLOC_MMAP32_START ((uintptr_t)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LJ_ALLOC_MMAP_PROBE
|
||||||
|
static void *mmap_map32(PRNGState *rs, size_t size)
|
||||||
|
#else
|
||||||
static void *mmap_map32(size_t size)
|
static void *mmap_map32(size_t size)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
#if LJ_ALLOC_MMAP_PROBE
|
#if LJ_ALLOC_MMAP_PROBE
|
||||||
static int fallback = 0;
|
static int fallback = 0;
|
||||||
if (fallback)
|
if (fallback)
|
||||||
return mmap_probe(size);
|
return mmap_probe(rs, size);
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int olderr = errno;
|
int olderr = errno;
|
||||||
@@ -321,7 +302,7 @@ static void *mmap_map32(size_t size)
|
|||||||
#if LJ_ALLOC_MMAP_PROBE
|
#if LJ_ALLOC_MMAP_PROBE
|
||||||
if (ptr == MFAIL) {
|
if (ptr == MFAIL) {
|
||||||
fallback = 1;
|
fallback = 1;
|
||||||
return mmap_probe(size);
|
return mmap_probe(rs, size);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return ptr;
|
return ptr;
|
||||||
@@ -331,17 +312,22 @@ static void *mmap_map32(size_t size)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LJ_ALLOC_MMAP32
|
#if LJ_ALLOC_MMAP32
|
||||||
#define CALL_MMAP(size) mmap_map32(size)
|
#if LJ_ALLOC_MMAP_PROBE
|
||||||
#elif LJ_ALLOC_MMAP_PROBE
|
#define CALL_MMAP(prng, size) mmap_map32(prng, size)
|
||||||
#define CALL_MMAP(size) mmap_probe(size)
|
|
||||||
#else
|
#else
|
||||||
static void *CALL_MMAP(size_t size)
|
#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;
|
int olderr = errno;
|
||||||
void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
|
void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
|
||||||
errno = olderr;
|
errno = olderr;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
#define CALL_MMAP(prng, size) mmap_plain(size)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
|
#if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
|
||||||
@@ -394,7 +380,7 @@ static void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, int flags)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DIRECT_MMAP
|
#ifndef DIRECT_MMAP
|
||||||
#define DIRECT_MMAP(s) CALL_MMAP(s)
|
#define DIRECT_MMAP(prng, s) CALL_MMAP(prng, s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CALL_MREMAP
|
#ifndef CALL_MREMAP
|
||||||
@@ -553,6 +539,7 @@ struct malloc_state {
|
|||||||
mchunkptr smallbins[(NSMALLBINS+1)*2];
|
mchunkptr smallbins[(NSMALLBINS+1)*2];
|
||||||
tbinptr treebins[NTREEBINS];
|
tbinptr treebins[NTREEBINS];
|
||||||
msegment seg;
|
msegment seg;
|
||||||
|
PRNGState *prng;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct malloc_state *mstate;
|
typedef struct malloc_state *mstate;
|
||||||
@@ -610,7 +597,7 @@ static int has_segment_link(mstate m, msegmentptr ss)
|
|||||||
noncontiguous segments are added.
|
noncontiguous segments are added.
|
||||||
*/
|
*/
|
||||||
#define TOP_FOOT_SIZE\
|
#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 ---------------------------- */
|
/* ---------------------------- Indexing Bins ---------------------------- */
|
||||||
|
|
||||||
@@ -835,11 +822,11 @@ static int has_segment_link(mstate m, msegmentptr ss)
|
|||||||
|
|
||||||
/* ----------------------- Direct-mmapping chunks ----------------------- */
|
/* ----------------------- 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);
|
size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
|
||||||
if (LJ_LIKELY(mmsize > nb)) { /* Check for wrap around 0 */
|
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) {
|
if (mm != CMFAIL) {
|
||||||
size_t offset = align_offset(chunk2mem(mm));
|
size_t offset = align_offset(chunk2mem(mm));
|
||||||
size_t psize = mmsize - offset - DIRECT_FOOT_PAD;
|
size_t psize = mmsize - offset - DIRECT_FOOT_PAD;
|
||||||
@@ -851,6 +838,7 @@ static void *direct_alloc(size_t nb)
|
|||||||
return chunk2mem(p);
|
return chunk2mem(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UNUSED(m);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,7 +987,7 @@ static void *alloc_sys(mstate m, size_t nb)
|
|||||||
|
|
||||||
/* Directly map large chunks */
|
/* Directly map large chunks */
|
||||||
if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) {
|
if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) {
|
||||||
void *mem = direct_alloc(nb);
|
void *mem = direct_alloc(m, nb);
|
||||||
if (mem != 0)
|
if (mem != 0)
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
@@ -1008,7 +996,7 @@ static void *alloc_sys(mstate m, size_t nb)
|
|||||||
size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
|
size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
|
||||||
size_t rsize = granularity_align(req);
|
size_t rsize = granularity_align(req);
|
||||||
if (LJ_LIKELY(rsize > nb)) { /* Fail if wraps around zero */
|
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) {
|
if (mp != CMFAIL) {
|
||||||
tbase = mp;
|
tbase = mp;
|
||||||
tsize = rsize;
|
tsize = rsize;
|
||||||
@@ -1235,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;
|
size_t tsize = DEFAULT_GRANULARITY;
|
||||||
char *tbase;
|
char *tbase;
|
||||||
INIT_MMAP();
|
INIT_MMAP();
|
||||||
tbase = (char *)(CALL_MMAP(tsize));
|
UNUSED(rs);
|
||||||
|
tbase = (char *)(CALL_MMAP(rs, tsize));
|
||||||
if (tbase != CMFAIL) {
|
if (tbase != CMFAIL) {
|
||||||
size_t msize = pad_request(sizeof(struct malloc_state));
|
size_t msize = pad_request(sizeof(struct malloc_state));
|
||||||
mchunkptr mn;
|
mchunkptr mn;
|
||||||
@@ -1259,6 +1248,12 @@ void *lj_alloc_create(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lj_alloc_setprng(void *msp, PRNGState *rs)
|
||||||
|
{
|
||||||
|
mstate ms = (mstate)msp;
|
||||||
|
ms->prng = rs;
|
||||||
|
}
|
||||||
|
|
||||||
void lj_alloc_destroy(void *msp)
|
void lj_alloc_destroy(void *msp)
|
||||||
{
|
{
|
||||||
mstate ms = (mstate)msp;
|
mstate ms = (mstate)msp;
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
#include "lj_def.h"
|
#include "lj_def.h"
|
||||||
|
|
||||||
#ifndef LUAJIT_USE_SYSMALLOC
|
#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_destroy(void *msp);
|
||||||
LJ_FUNC void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize);
|
LJ_FUNC void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+119
-74
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Public Lua/C API.
|
** Public Lua/C API.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
|
|
||||||
/* -- Common helper functions --------------------------------------------- */
|
/* -- Common helper functions --------------------------------------------- */
|
||||||
|
|
||||||
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
|
#define lj_checkapi_slot(idx) \
|
||||||
#define api_checkvalidindex(L, i) api_check(L, (i) != niltv(L))
|
lj_checkapi((idx) <= (L->top - L->base), "stack slot %d out of range", (idx))
|
||||||
|
|
||||||
static TValue *index2adr(lua_State *L, int 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);
|
TValue *o = L->base + (idx - 1);
|
||||||
return o < L->top ? o : niltv(L);
|
return o < L->top ? o : niltv(L);
|
||||||
} else if (idx > LUA_REGISTRYINDEX) {
|
} 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;
|
return L->top + idx;
|
||||||
} else if (idx == LUA_GLOBALSINDEX) {
|
} else if (idx == LUA_GLOBALSINDEX) {
|
||||||
TValue *o = &G(L)->tmptv;
|
TValue *o = &G(L)->tmptv;
|
||||||
@@ -47,7 +48,8 @@ static TValue *index2adr(lua_State *L, int idx)
|
|||||||
return registry(L);
|
return registry(L);
|
||||||
} else {
|
} else {
|
||||||
GCfunc *fn = curr_func(L);
|
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) {
|
if (idx == LUA_ENVIRONINDEX) {
|
||||||
TValue *o = &G(L)->tmptv;
|
TValue *o = &G(L)->tmptv;
|
||||||
settabV(L, o, tabref(fn->c.env));
|
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) {
|
if (idx > 0) {
|
||||||
TValue *o = L->base + (idx - 1);
|
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);
|
return o < L->top ? o : niltv(L);
|
||||||
} else {
|
} 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;
|
return L->top + idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,17 +115,17 @@ LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
|
|||||||
lj_err_callerv(L, LJ_ERR_STKOVM, 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;
|
TValue *f, *t;
|
||||||
if (from == to) return;
|
if (L == to) return;
|
||||||
api_checknelems(from, n);
|
lj_checkapi_slot(n);
|
||||||
api_check(from, G(from) == G(to));
|
lj_checkapi(G(L) == G(to), "move across global states");
|
||||||
lj_state_checkstack(to, (MSize)n);
|
lj_state_checkstack(to, (MSize)n);
|
||||||
f = from->top;
|
f = L->top;
|
||||||
t = to->top = to->top + n;
|
t = to->top = to->top + n;
|
||||||
while (--n >= 0) copyTV(to, --t, --f);
|
while (--n >= 0) copyTV(to, --t, --f);
|
||||||
from->top = f;
|
L->top = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
LUA_API const lua_Number *lua_version(lua_State *L)
|
LUA_API const lua_Number *lua_version(lua_State *L)
|
||||||
@@ -129,7 +145,7 @@ LUA_API int lua_gettop(lua_State *L)
|
|||||||
LUA_API void lua_settop(lua_State *L, int idx)
|
LUA_API void lua_settop(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
if (idx >= 0) {
|
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 > L->top) {
|
||||||
if (L->base + idx >= tvref(L->maxstack))
|
if (L->base + idx >= tvref(L->maxstack))
|
||||||
lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base));
|
lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base));
|
||||||
@@ -138,23 +154,21 @@ LUA_API void lua_settop(lua_State *L, int idx)
|
|||||||
L->top = L->base + idx;
|
L->top = L->base + idx;
|
||||||
}
|
}
|
||||||
} else {
|
} 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). */
|
L->top += idx+1; /* Shrinks top (idx < 0). */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LUA_API void lua_remove(lua_State *L, int idx)
|
LUA_API void lua_remove(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
TValue *p = stkindex2adr(L, idx);
|
TValue *p = index2adr_stack(L, idx);
|
||||||
api_checkvalidindex(L, p);
|
|
||||||
while (++p < L->top) copyTV(L, p-1, p);
|
while (++p < L->top) copyTV(L, p-1, p);
|
||||||
L->top--;
|
L->top--;
|
||||||
}
|
}
|
||||||
|
|
||||||
LUA_API void lua_insert(lua_State *L, int idx)
|
LUA_API void lua_insert(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
TValue *q, *p = stkindex2adr(L, idx);
|
TValue *q, *p = index2adr_stack(L, idx);
|
||||||
api_checkvalidindex(L, p);
|
|
||||||
for (q = L->top; q > p; q--) copyTV(L, q, q-1);
|
for (q = L->top; q > p; q--) copyTV(L, q, q-1);
|
||||||
copyTV(L, p, L->top);
|
copyTV(L, p, L->top);
|
||||||
}
|
}
|
||||||
@@ -162,19 +176,18 @@ LUA_API void lua_insert(lua_State *L, int idx)
|
|||||||
static void copy_slot(lua_State *L, TValue *f, int idx)
|
static void copy_slot(lua_State *L, TValue *f, int idx)
|
||||||
{
|
{
|
||||||
if (idx == LUA_GLOBALSINDEX) {
|
if (idx == LUA_GLOBALSINDEX) {
|
||||||
api_check(L, tvistab(f));
|
lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
|
||||||
/* NOBARRIER: A thread (i.e. L) is never black. */
|
/* NOBARRIER: A thread (i.e. L) is never black. */
|
||||||
setgcref(L->env, obj2gco(tabV(f)));
|
setgcref(L->env, obj2gco(tabV(f)));
|
||||||
} else if (idx == LUA_ENVIRONINDEX) {
|
} else if (idx == LUA_ENVIRONINDEX) {
|
||||||
GCfunc *fn = curr_func(L);
|
GCfunc *fn = curr_func(L);
|
||||||
if (fn->c.gct != ~LJ_TFUNC)
|
if (fn->c.gct != ~LJ_TFUNC)
|
||||||
lj_err_msg(L, LJ_ERR_NOENV);
|
lj_err_msg(L, LJ_ERR_NOENV);
|
||||||
api_check(L, tvistab(f));
|
lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
|
||||||
setgcref(fn->c.env, obj2gco(tabV(f)));
|
setgcref(fn->c.env, obj2gco(tabV(f)));
|
||||||
lj_gc_barrier(L, fn, f);
|
lj_gc_barrier(L, fn, f);
|
||||||
} else {
|
} else {
|
||||||
TValue *o = index2adr(L, idx);
|
TValue *o = index2adr_check(L, idx);
|
||||||
api_checkvalidindex(L, o);
|
|
||||||
copyTV(L, o, f);
|
copyTV(L, o, f);
|
||||||
if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */
|
if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */
|
||||||
lj_gc_barrier(L, curr_func(L), f);
|
lj_gc_barrier(L, curr_func(L), f);
|
||||||
@@ -183,7 +196,7 @@ static void copy_slot(lua_State *L, TValue *f, int idx)
|
|||||||
|
|
||||||
LUA_API void lua_replace(lua_State *L, int idx)
|
LUA_API void lua_replace(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
api_checknelems(L, 1);
|
lj_checkapi_slot(1);
|
||||||
copy_slot(L, L->top - 1, idx);
|
copy_slot(L, L->top - 1, idx);
|
||||||
L->top--;
|
L->top--;
|
||||||
}
|
}
|
||||||
@@ -219,7 +232,7 @@ LUA_API int lua_type(lua_State *L, int idx)
|
|||||||
#else
|
#else
|
||||||
int tt = (int)(((t < 8 ? 0x98042110u : 0x75a06u) >> 4*(t&7)) & 15u);
|
int tt = (int)(((t < 8 ? 0x98042110u : 0x75a06u) >> 4*(t&7)) & 15u);
|
||||||
#endif
|
#endif
|
||||||
lua_assert(tt != LUA_TNIL || tvisnil(o));
|
lj_assertL(tt != LUA_TNIL || tvisnil(o), "bad tag conversion");
|
||||||
return tt;
|
return tt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,7 +608,7 @@ LUA_API void *lua_touserdata(lua_State *L, int idx)
|
|||||||
if (tvisudata(o))
|
if (tvisudata(o))
|
||||||
return uddata(udataV(o));
|
return uddata(udataV(o));
|
||||||
else if (tvislightud(o))
|
else if (tvislightud(o))
|
||||||
return lightudV(o);
|
return lightudV(G(L), o);
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -608,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)
|
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) ------------------------------------- */
|
/* -- Stack setters (object creation) ------------------------------------- */
|
||||||
@@ -677,14 +690,14 @@ LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction f, int n)
|
|||||||
{
|
{
|
||||||
GCfunc *fn;
|
GCfunc *fn;
|
||||||
lj_gc_check(L);
|
lj_gc_check(L);
|
||||||
api_checknelems(L, n);
|
lj_checkapi_slot(n);
|
||||||
fn = lj_func_newC(L, (MSize)n, getcurrenv(L));
|
fn = lj_func_newC(L, (MSize)n, getcurrenv(L));
|
||||||
fn->c.f = f;
|
fn->c.f = f;
|
||||||
L->top -= n;
|
L->top -= n;
|
||||||
while (n--)
|
while (n--)
|
||||||
copyTV(L, &fn->c.upvalue[n], L->top+n);
|
copyTV(L, &fn->c.upvalue[n], L->top+n);
|
||||||
setfuncV(L, L->top, fn);
|
setfuncV(L, L->top, fn);
|
||||||
lua_assert(iswhite(obj2gco(fn)));
|
lj_assertL(iswhite(obj2gco(fn)), "new GC object is not white");
|
||||||
incr_top(L);
|
incr_top(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,9 +707,38 @@ LUA_API void lua_pushboolean(lua_State *L, int b)
|
|||||||
incr_top(L);
|
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)
|
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);
|
incr_top(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,7 +796,7 @@ LUA_API void *lua_newuserdata(lua_State *L, size_t size)
|
|||||||
|
|
||||||
LUA_API void lua_concat(lua_State *L, int n)
|
LUA_API void lua_concat(lua_State *L, int n)
|
||||||
{
|
{
|
||||||
api_checknelems(L, n);
|
lj_checkapi_slot(n);
|
||||||
if (n >= 2) {
|
if (n >= 2) {
|
||||||
n--;
|
n--;
|
||||||
do {
|
do {
|
||||||
@@ -780,9 +822,8 @@ LUA_API void lua_concat(lua_State *L, int n)
|
|||||||
|
|
||||||
LUA_API void lua_gettable(lua_State *L, int idx)
|
LUA_API void lua_gettable(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
cTValue *v, *t = index2adr(L, idx);
|
cTValue *t = index2adr_check(L, idx);
|
||||||
api_checkvalidindex(L, t);
|
cTValue *v = lj_meta_tget(L, t, L->top-1);
|
||||||
v = lj_meta_tget(L, t, L->top-1);
|
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
L->top += 2;
|
L->top += 2;
|
||||||
lj_vm_call(L, L->top-2, 1+1);
|
lj_vm_call(L, L->top-2, 1+1);
|
||||||
@@ -794,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)
|
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;
|
TValue key;
|
||||||
api_checkvalidindex(L, t);
|
|
||||||
setstrV(L, &key, lj_str_newz(L, k));
|
setstrV(L, &key, lj_str_newz(L, k));
|
||||||
v = lj_meta_tget(L, t, &key);
|
v = lj_meta_tget(L, t, &key);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
@@ -812,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)
|
LUA_API void lua_rawget(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
cTValue *t = index2adr(L, 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));
|
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)
|
LUA_API void lua_rawgeti(lua_State *L, int idx, int n)
|
||||||
{
|
{
|
||||||
cTValue *v, *t = index2adr(L, idx);
|
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);
|
v = lj_tab_getint(tabV(t), n);
|
||||||
if (v) {
|
if (v) {
|
||||||
copyTV(L, L->top, v);
|
copyTV(L, L->top, v);
|
||||||
@@ -861,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)
|
LUA_API void lua_getfenv(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
cTValue *o = index2adr(L, idx);
|
cTValue *o = index2adr_check(L, idx);
|
||||||
api_checkvalidindex(L, o);
|
|
||||||
if (tvisfunc(o)) {
|
if (tvisfunc(o)) {
|
||||||
settabV(L, L->top, tabref(funcV(o)->c.env));
|
settabV(L, L->top, tabref(funcV(o)->c.env));
|
||||||
} else if (tvisudata(o)) {
|
} else if (tvisudata(o)) {
|
||||||
@@ -879,7 +918,7 @@ LUA_API int lua_next(lua_State *L, int idx)
|
|||||||
{
|
{
|
||||||
cTValue *t = index2adr(L, idx);
|
cTValue *t = index2adr(L, idx);
|
||||||
int more;
|
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);
|
more = lj_tab_next(L, tabV(t), L->top-1);
|
||||||
if (more) {
|
if (more) {
|
||||||
incr_top(L); /* Return new key and value slot. */
|
incr_top(L); /* Return new key and value slot. */
|
||||||
@@ -892,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)
|
LUA_API const char *lua_getupvalue(lua_State *L, int idx, int n)
|
||||||
{
|
{
|
||||||
TValue *val;
|
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) {
|
if (name) {
|
||||||
copyTV(L, L->top, val);
|
copyTV(L, L->top, val);
|
||||||
incr_top(L);
|
incr_top(L);
|
||||||
@@ -904,7 +944,7 @@ LUA_API void *lua_upvalueid(lua_State *L, int idx, int n)
|
|||||||
{
|
{
|
||||||
GCfunc *fn = funcV(index2adr(L, idx));
|
GCfunc *fn = funcV(index2adr(L, idx));
|
||||||
n--;
|
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]) :
|
return isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
|
||||||
(void *)&fn->c.upvalue[n];
|
(void *)&fn->c.upvalue[n];
|
||||||
}
|
}
|
||||||
@@ -914,8 +954,10 @@ LUA_API void lua_upvaluejoin(lua_State *L, int idx1, int n1, int idx2, int n2)
|
|||||||
GCfunc *fn1 = funcV(index2adr(L, idx1));
|
GCfunc *fn1 = funcV(index2adr(L, idx1));
|
||||||
GCfunc *fn2 = funcV(index2adr(L, idx2));
|
GCfunc *fn2 = funcV(index2adr(L, idx2));
|
||||||
n1--; n2--;
|
n1--; n2--;
|
||||||
api_check(L, isluafunc(fn1) && (uint32_t)n1 < fn1->l.nupvalues);
|
lj_checkapi(isluafunc(fn1), "stack slot %d is not a Lua function", idx1);
|
||||||
api_check(L, isluafunc(fn2) && (uint32_t)n2 < fn2->l.nupvalues);
|
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]);
|
setgcrefr(fn1->l.uvptr[n1], fn2->l.uvptr[n2]);
|
||||||
lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1]));
|
lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1]));
|
||||||
}
|
}
|
||||||
@@ -944,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)
|
LUA_API void lua_settable(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
TValue *o;
|
TValue *o;
|
||||||
cTValue *t = index2adr(L, idx);
|
cTValue *t = index2adr_check(L, idx);
|
||||||
api_checknelems(L, 2);
|
lj_checkapi_slot(2);
|
||||||
api_checkvalidindex(L, t);
|
|
||||||
o = lj_meta_tset(L, t, L->top-2);
|
o = lj_meta_tset(L, t, L->top-2);
|
||||||
if (o) {
|
if (o) {
|
||||||
/* NOBARRIER: lj_meta_tset ensures the table is not black. */
|
/* NOBARRIER: lj_meta_tset ensures the table is not black. */
|
||||||
@@ -965,9 +1006,8 @@ LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
|
|||||||
{
|
{
|
||||||
TValue *o;
|
TValue *o;
|
||||||
TValue key;
|
TValue key;
|
||||||
cTValue *t = index2adr(L, idx);
|
cTValue *t = index2adr_check(L, idx);
|
||||||
api_checknelems(L, 1);
|
lj_checkapi_slot(1);
|
||||||
api_checkvalidindex(L, t);
|
|
||||||
setstrV(L, &key, lj_str_newz(L, k));
|
setstrV(L, &key, lj_str_newz(L, k));
|
||||||
o = lj_meta_tset(L, t, &key);
|
o = lj_meta_tset(L, t, &key);
|
||||||
if (o) {
|
if (o) {
|
||||||
@@ -986,7 +1026,7 @@ LUA_API void lua_rawset(lua_State *L, int idx)
|
|||||||
{
|
{
|
||||||
GCtab *t = tabV(index2adr(L, idx));
|
GCtab *t = tabV(index2adr(L, idx));
|
||||||
TValue *dst, *key;
|
TValue *dst, *key;
|
||||||
api_checknelems(L, 2);
|
lj_checkapi_slot(2);
|
||||||
key = L->top-2;
|
key = L->top-2;
|
||||||
dst = lj_tab_set(L, t, key);
|
dst = lj_tab_set(L, t, key);
|
||||||
copyTV(L, dst, key+1);
|
copyTV(L, dst, key+1);
|
||||||
@@ -998,7 +1038,7 @@ LUA_API void lua_rawseti(lua_State *L, int idx, int n)
|
|||||||
{
|
{
|
||||||
GCtab *t = tabV(index2adr(L, idx));
|
GCtab *t = tabV(index2adr(L, idx));
|
||||||
TValue *dst, *src;
|
TValue *dst, *src;
|
||||||
api_checknelems(L, 1);
|
lj_checkapi_slot(1);
|
||||||
dst = lj_tab_setint(L, t, n);
|
dst = lj_tab_setint(L, t, n);
|
||||||
src = L->top-1;
|
src = L->top-1;
|
||||||
copyTV(L, dst, src);
|
copyTV(L, dst, src);
|
||||||
@@ -1010,13 +1050,12 @@ LUA_API int lua_setmetatable(lua_State *L, int idx)
|
|||||||
{
|
{
|
||||||
global_State *g;
|
global_State *g;
|
||||||
GCtab *mt;
|
GCtab *mt;
|
||||||
cTValue *o = index2adr(L, idx);
|
cTValue *o = index2adr_check(L, idx);
|
||||||
api_checknelems(L, 1);
|
lj_checkapi_slot(1);
|
||||||
api_checkvalidindex(L, o);
|
|
||||||
if (tvisnil(L->top-1)) {
|
if (tvisnil(L->top-1)) {
|
||||||
mt = NULL;
|
mt = NULL;
|
||||||
} else {
|
} 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);
|
mt = tabV(L->top-1);
|
||||||
}
|
}
|
||||||
g = G(L);
|
g = G(L);
|
||||||
@@ -1053,11 +1092,10 @@ LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
|
|||||||
|
|
||||||
LUA_API int lua_setfenv(lua_State *L, int idx)
|
LUA_API int lua_setfenv(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
cTValue *o = index2adr(L, idx);
|
cTValue *o = index2adr_check(L, idx);
|
||||||
GCtab *t;
|
GCtab *t;
|
||||||
api_checknelems(L, 1);
|
lj_checkapi_slot(1);
|
||||||
api_checkvalidindex(L, o);
|
lj_checkapi(tvistab(L->top-1), "top stack slot is not a table");
|
||||||
api_check(L, tvistab(L->top-1));
|
|
||||||
t = tabV(L->top-1);
|
t = tabV(L->top-1);
|
||||||
if (tvisfunc(o)) {
|
if (tvisfunc(o)) {
|
||||||
setgcref(funcV(o)->c.env, obj2gco(t));
|
setgcref(funcV(o)->c.env, obj2gco(t));
|
||||||
@@ -1078,13 +1116,14 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n)
|
|||||||
{
|
{
|
||||||
cTValue *f = index2adr(L, idx);
|
cTValue *f = index2adr(L, idx);
|
||||||
TValue *val;
|
TValue *val;
|
||||||
|
GCobj *o;
|
||||||
const char *name;
|
const char *name;
|
||||||
api_checknelems(L, 1);
|
lj_checkapi_slot(1);
|
||||||
name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val);
|
name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val, &o);
|
||||||
if (name) {
|
if (name) {
|
||||||
L->top--;
|
L->top--;
|
||||||
copyTV(L, val, L->top);
|
copyTV(L, val, L->top);
|
||||||
lj_gc_barrier(L, funcV(f), L->top);
|
lj_gc_barrier(L, o, L->top);
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -1106,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)
|
LUA_API void lua_call(lua_State *L, int nargs, int nresults)
|
||||||
{
|
{
|
||||||
api_check(L, L->status == LUA_OK || L->status == LUA_ERRERR);
|
lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
|
||||||
api_checknelems(L, nargs+1);
|
"thread called in wrong state %d", L->status);
|
||||||
|
lj_checkapi_slot(nargs+1);
|
||||||
lj_vm_call(L, api_call_base(L, nargs), nresults+1);
|
lj_vm_call(L, api_call_base(L, nargs), nresults+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1117,13 +1157,13 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
|
|||||||
uint8_t oldh = hook_save(g);
|
uint8_t oldh = hook_save(g);
|
||||||
ptrdiff_t ef;
|
ptrdiff_t ef;
|
||||||
int status;
|
int status;
|
||||||
api_check(L, L->status == LUA_OK || L->status == LUA_ERRERR);
|
lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
|
||||||
api_checknelems(L, nargs+1);
|
"thread called in wrong state %d", L->status);
|
||||||
|
lj_checkapi_slot(nargs+1);
|
||||||
if (errfunc == 0) {
|
if (errfunc == 0) {
|
||||||
ef = 0;
|
ef = 0;
|
||||||
} else {
|
} else {
|
||||||
cTValue *o = stkindex2adr(L, errfunc);
|
cTValue *o = index2adr_stack(L, errfunc);
|
||||||
api_checkvalidindex(L, o);
|
|
||||||
ef = savestack(L, o);
|
ef = savestack(L, o);
|
||||||
}
|
}
|
||||||
status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef);
|
status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef);
|
||||||
@@ -1138,7 +1178,10 @@ static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
|
|||||||
fn->c.f = func;
|
fn->c.f = func;
|
||||||
setfuncV(L, top++, fn);
|
setfuncV(L, top++, fn);
|
||||||
if (LJ_FR2) setnilV(top++);
|
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. */
|
cframe_nres(L->cframe) = 1+0; /* Zero results. */
|
||||||
L->top = top;
|
L->top = top;
|
||||||
return top-1; /* Now call the newly allocated C function. */
|
return top-1; /* Now call the newly allocated C function. */
|
||||||
@@ -1149,7 +1192,8 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
|
|||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
uint8_t oldh = hook_save(g);
|
uint8_t oldh = hook_save(g);
|
||||||
int status;
|
int status;
|
||||||
api_check(L, L->status == LUA_OK || 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);
|
status = lj_vm_cpcall(L, func, ud, cpcall);
|
||||||
if (status) hook_restore(g, oldh);
|
if (status) hook_restore(g, oldh);
|
||||||
return status;
|
return status;
|
||||||
@@ -1198,11 +1242,12 @@ LUA_API int lua_yield(lua_State *L, int nresults)
|
|||||||
setcont(top, lj_cont_hook);
|
setcont(top, lj_cont_hook);
|
||||||
if (LJ_FR2) top++;
|
if (LJ_FR2) top++;
|
||||||
setframe_pc(top, cframe_pc(cf)-1);
|
setframe_pc(top, cframe_pc(cf)-1);
|
||||||
if (LJ_FR2) top++;
|
top++;
|
||||||
setframe_gc(top, obj2gco(L), LJ_TTHREAD);
|
setframe_gc(top, obj2gco(L), LJ_TTHREAD);
|
||||||
|
if (LJ_FR2) top++;
|
||||||
setframe_ftsz(top, ((char *)(top+1)-(char *)L->base)+FRAME_CONT);
|
setframe_ftsz(top, ((char *)(top+1)-(char *)L->base)+FRAME_CONT);
|
||||||
L->top = L->base = top+1;
|
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);
|
lj_err_throw(L, LUA_YIELD);
|
||||||
#else
|
#else
|
||||||
L->cframe = NULL;
|
L->cframe = NULL;
|
||||||
|
|||||||
+106
-21
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Target architecture selection.
|
** Target architecture selection.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_ARCH_H
|
#ifndef _LJ_ARCH_H
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
/* -- Target definitions -------------------------------------------------- */
|
||||||
|
|
||||||
/* Target endianess. */
|
/* Target endianess. */
|
||||||
#define LUAJIT_LE 0
|
#define LUAJIT_LE 0
|
||||||
#define LUAJIT_BE 1
|
#define LUAJIT_BE 1
|
||||||
@@ -38,6 +40,14 @@
|
|||||||
#define LUAJIT_OS_BSD 4
|
#define LUAJIT_OS_BSD 4
|
||||||
#define LUAJIT_OS_POSIX 5
|
#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. */
|
/* Select native target if no target defined. */
|
||||||
#ifndef LUAJIT_TARGET
|
#ifndef LUAJIT_TARGET
|
||||||
|
|
||||||
@@ -69,12 +79,16 @@
|
|||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
#define LUAJIT_OS LUAJIT_OS_LINUX
|
#define LUAJIT_OS LUAJIT_OS_LINUX
|
||||||
#elif defined(__MACH__) && defined(__APPLE__)
|
#elif defined(__MACH__) && defined(__APPLE__)
|
||||||
|
#include "TargetConditionals.h"
|
||||||
#define LUAJIT_OS LUAJIT_OS_OSX
|
#define LUAJIT_OS LUAJIT_OS_OSX
|
||||||
#elif (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
|
#elif (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
|
||||||
defined(__NetBSD__) || defined(__OpenBSD__) || \
|
defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||||
defined(__DragonFly__)) && !defined(__ORBIS__)
|
defined(__DragonFly__)) && !defined(__ORBIS__)
|
||||||
#define LUAJIT_OS LUAJIT_OS_BSD
|
#define LUAJIT_OS LUAJIT_OS_BSD
|
||||||
#elif (defined(__sun__) && defined(__svr4__)) || defined(__HAIKU__)
|
#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
|
#define LUAJIT_OS LUAJIT_OS_POSIX
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
#define LJ_TARGET_CYGWIN 1
|
#define LJ_TARGET_CYGWIN 1
|
||||||
@@ -103,10 +117,16 @@
|
|||||||
#define LJ_TARGET_WINDOWS (LUAJIT_OS == LUAJIT_OS_WINDOWS)
|
#define LJ_TARGET_WINDOWS (LUAJIT_OS == LUAJIT_OS_WINDOWS)
|
||||||
#define LJ_TARGET_LINUX (LUAJIT_OS == LUAJIT_OS_LINUX)
|
#define LJ_TARGET_LINUX (LUAJIT_OS == LUAJIT_OS_LINUX)
|
||||||
#define LJ_TARGET_OSX (LUAJIT_OS == LUAJIT_OS_OSX)
|
#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_POSIX (LUAJIT_OS > LUAJIT_OS_WINDOWS)
|
||||||
#define LJ_TARGET_DLOPEN LJ_TARGET_POSIX
|
#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__
|
#ifdef __CELLOS_LV2__
|
||||||
#define LJ_TARGET_PS3 1
|
#define LJ_TARGET_PS3 1
|
||||||
#define LJ_TARGET_CONSOLE 1
|
#define LJ_TARGET_CONSOLE 1
|
||||||
@@ -142,10 +162,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LJ_NUMMODE_SINGLE 0 /* Single-number mode only. */
|
/* -- Arch-specific settings ---------------------------------------------- */
|
||||||
#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. */
|
|
||||||
|
|
||||||
/* Set target architecture properties. */
|
/* Set target architecture properties. */
|
||||||
#if LUAJIT_TARGET == LUAJIT_ARCH_X86
|
#if LUAJIT_TARGET == LUAJIT_ARCH_X86
|
||||||
@@ -208,13 +225,13 @@
|
|||||||
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
||||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||||
|
|
||||||
#if __ARM_ARCH_8__ || __ARM_ARCH_8A__
|
#if __ARM_ARCH == 8 || __ARM_ARCH_8__ || __ARM_ARCH_8A__
|
||||||
#define LJ_ARCH_VERSION 80
|
#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
|
#define LJ_ARCH_VERSION 70
|
||||||
#elif __ARM_ARCH_6T2__
|
#elif __ARM_ARCH_6T2__
|
||||||
#define LJ_ARCH_VERSION 61
|
#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
|
#define LJ_ARCH_VERSION 60
|
||||||
#else
|
#else
|
||||||
#define LJ_ARCH_VERSION 50
|
#define LJ_ARCH_VERSION 50
|
||||||
@@ -296,9 +313,7 @@
|
|||||||
#define LJ_ARCH_PPC32ON64 1
|
#define LJ_ARCH_PPC32ON64 1
|
||||||
#define LJ_ARCH_NOFFI 1
|
#define LJ_ARCH_NOFFI 1
|
||||||
#elif LJ_ARCH_BITS == 64
|
#elif LJ_ARCH_BITS == 64
|
||||||
#define LJ_ARCH_PPC64 1
|
#error "No support for PPC64"
|
||||||
#define LJ_TARGET_GC64 1
|
|
||||||
#define LJ_ARCH_NOJIT 1 /* NYI */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _ARCH_PWR7
|
#if _ARCH_PWR7
|
||||||
@@ -330,18 +345,38 @@
|
|||||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_MIPS32 || LUAJIT_TARGET == LUAJIT_ARCH_MIPS64
|
#elif LUAJIT_TARGET == LUAJIT_ARCH_MIPS32 || LUAJIT_TARGET == LUAJIT_ARCH_MIPS64
|
||||||
|
|
||||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
|
#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 LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||||
|
#if LJ_TARGET_MIPSR6
|
||||||
|
#define LJ_ARCH_NAME "mips32r6el"
|
||||||
|
#else
|
||||||
#define LJ_ARCH_NAME "mipsel"
|
#define LJ_ARCH_NAME "mipsel"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if LJ_TARGET_MIPSR6
|
||||||
|
#define LJ_ARCH_NAME "mips64r6el"
|
||||||
#else
|
#else
|
||||||
#define LJ_ARCH_NAME "mips64el"
|
#define LJ_ARCH_NAME "mips64el"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||||
#else
|
#else
|
||||||
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||||
|
#if LJ_TARGET_MIPSR6
|
||||||
|
#define LJ_ARCH_NAME "mips32r6"
|
||||||
|
#else
|
||||||
#define LJ_ARCH_NAME "mips"
|
#define LJ_ARCH_NAME "mips"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if LJ_TARGET_MIPSR6
|
||||||
|
#define LJ_ARCH_NAME "mips64r6"
|
||||||
#else
|
#else
|
||||||
#define LJ_ARCH_NAME "mips64"
|
#define LJ_ARCH_NAME "mips64"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -377,7 +412,9 @@
|
|||||||
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
||||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||||
|
|
||||||
#if _MIPS_ARCH_MIPS32R2 || _MIPS_ARCH_MIPS64R2
|
#if LJ_TARGET_MIPSR6
|
||||||
|
#define LJ_ARCH_VERSION 60
|
||||||
|
#elif _MIPS_ARCH_MIPS32R2 || _MIPS_ARCH_MIPS64R2
|
||||||
#define LJ_ARCH_VERSION 20
|
#define LJ_ARCH_VERSION 20
|
||||||
#else
|
#else
|
||||||
#define LJ_ARCH_VERSION 10
|
#define LJ_ARCH_VERSION 10
|
||||||
@@ -387,9 +424,7 @@
|
|||||||
#error "No target architecture defined"
|
#error "No target architecture defined"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LJ_PAGESIZE
|
/* -- Checks for requirements --------------------------------------------- */
|
||||||
#define LJ_PAGESIZE 4096
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check for minimum required compiler versions. */
|
/* Check for minimum required compiler versions. */
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
@@ -443,7 +478,7 @@
|
|||||||
#error "No support for ILP32 model on ARM64"
|
#error "No support for ILP32 model on ARM64"
|
||||||
#endif
|
#endif
|
||||||
#elif LJ_TARGET_PPC
|
#elif LJ_TARGET_PPC
|
||||||
#if !LJ_ARCH_PPC64 && (defined(_LITTLE_ENDIAN) && (!defined(_BYTE_ORDER) || (_BYTE_ORDER == _LITTLE_ENDIAN)))
|
#if defined(_LITTLE_ENDIAN) && (!defined(_BYTE_ORDER) || (_BYTE_ORDER == _LITTLE_ENDIAN))
|
||||||
#error "No support for little-endian PPC32"
|
#error "No support for little-endian PPC32"
|
||||||
#endif
|
#endif
|
||||||
#if defined(__NO_FPRS__) && !defined(_SOFT_FLOAT)
|
#if defined(__NO_FPRS__) && !defined(_SOFT_FLOAT)
|
||||||
@@ -453,13 +488,20 @@
|
|||||||
#if !((defined(_MIPS_SIM_ABI32) && _MIPS_SIM == _MIPS_SIM_ABI32) || (defined(_ABIO32) && _MIPS_SIM == _ABIO32))
|
#if !((defined(_MIPS_SIM_ABI32) && _MIPS_SIM == _MIPS_SIM_ABI32) || (defined(_ABIO32) && _MIPS_SIM == _ABIO32))
|
||||||
#error "Only o32 ABI supported for MIPS32"
|
#error "Only o32 ABI supported for MIPS32"
|
||||||
#endif
|
#endif
|
||||||
|
#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
|
#elif LJ_TARGET_MIPS64
|
||||||
#if !((defined(_MIPS_SIM_ABI64) && _MIPS_SIM == _MIPS_SIM_ABI64) || (defined(_ABI64) && _MIPS_SIM == _ABI64))
|
#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"
|
#error "Only n64 ABI supported for MIPS64"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* -- Derived defines ----------------------------------------------------- */
|
||||||
|
|
||||||
/* Enable or disable the dual-number mode for the VM. */
|
/* Enable or disable the dual-number mode for the VM. */
|
||||||
#if (LJ_ARCH_NUMMODE == LJ_NUMMODE_SINGLE && LUAJIT_NUMMODE == 2) || \
|
#if (LJ_ARCH_NUMMODE == LJ_NUMMODE_SINGLE && LUAJIT_NUMMODE == 2) || \
|
||||||
(LJ_ARCH_NUMMODE == LJ_NUMMODE_DUAL && LUAJIT_NUMMODE == 1)
|
(LJ_ARCH_NUMMODE == LJ_NUMMODE_DUAL && LUAJIT_NUMMODE == 1)
|
||||||
@@ -557,13 +599,14 @@
|
|||||||
#define LJ_TARGET_UNALIGNED 0
|
#define LJ_TARGET_UNALIGNED 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LJ_PAGESIZE
|
||||||
|
#define LJ_PAGESIZE 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Various workarounds for embedded operating systems or weak C runtimes. */
|
/* Various workarounds for embedded operating systems or weak C runtimes. */
|
||||||
#if defined(__ANDROID__) || defined(__symbian__) || LJ_TARGET_XBOX360 || LJ_TARGET_WINDOWS
|
#if defined(__ANDROID__) || defined(__symbian__) || LJ_TARGET_XBOX360 || LJ_TARGET_WINDOWS
|
||||||
#define LUAJIT_NO_LOG2
|
#define LUAJIT_NO_LOG2
|
||||||
#endif
|
#endif
|
||||||
#if defined(__symbian__) || LJ_TARGET_WINDOWS
|
|
||||||
#define LUAJIT_NO_EXP2
|
|
||||||
#endif
|
|
||||||
#if LJ_TARGET_CONSOLE || (LJ_TARGET_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0)
|
#if LJ_TARGET_CONSOLE || (LJ_TARGET_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0)
|
||||||
#define LJ_NO_SYSTEM 1
|
#define LJ_NO_SYSTEM 1
|
||||||
#endif
|
#endif
|
||||||
@@ -596,4 +639,46 @@ extern void *LJ_WIN_LOADLIBA(const char *path);
|
|||||||
#define LJ_52 0
|
#define LJ_52 0
|
||||||
#endif
|
#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
|
#endif
|
||||||
|
|||||||
+159
-90
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** IR assembler (SSA IR -> machine code).
|
** IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_asm_c
|
#define lj_asm_c
|
||||||
@@ -96,6 +96,12 @@ typedef struct ASMState {
|
|||||||
uint16_t parentmap[LJ_MAX_JSLOTS]; /* Parent instruction to RegSP map. */
|
uint16_t parentmap[LJ_MAX_JSLOTS]; /* Parent instruction to RegSP map. */
|
||||||
} ASMState;
|
} 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 IR(ref) (&as->ir[(ref)])
|
||||||
|
|
||||||
#define ASMREF_TMP1 REF_TRUE /* Temp. register. */
|
#define ASMREF_TMP1 REF_TRUE /* Temp. register. */
|
||||||
@@ -127,9 +133,8 @@ static LJ_AINLINE void checkmclim(ASMState *as)
|
|||||||
#ifdef LUA_USE_ASSERT
|
#ifdef LUA_USE_ASSERT
|
||||||
if (as->mcp + MCLIM_REDZONE < as->mcp_prev) {
|
if (as->mcp + MCLIM_REDZONE < as->mcp_prev) {
|
||||||
IRIns *ir = IR(as->curins+1);
|
IRIns *ir = IR(as->curins+1);
|
||||||
fprintf(stderr, "RED ZONE OVERFLOW: %p IR %04d %02d %04d %04d\n", as->mcp,
|
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);
|
as->curins+1-REF_BIAS, ir->o, ir->op1-REF_BIAS, ir->op2-REF_BIAS);
|
||||||
lua_assert(0);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (LJ_UNLIKELY(as->mcp < as->mclim)) asm_mclimit(as);
|
if (LJ_UNLIKELY(as->mcp < as->mclim)) asm_mclimit(as);
|
||||||
@@ -243,7 +248,7 @@ static void ra_dprintf(ASMState *as, const char *fmt, ...)
|
|||||||
*p++ = *q >= 'A' && *q <= 'Z' ? *q + 0x20 : *q;
|
*p++ = *q >= 'A' && *q <= 'Z' ? *q + 0x20 : *q;
|
||||||
} else {
|
} else {
|
||||||
*p++ = '?';
|
*p++ = '?';
|
||||||
lua_assert(0);
|
lj_assertA(0, "bad register %d for debug format \"%s\"", r, fmt);
|
||||||
}
|
}
|
||||||
} else if (e[1] == 'f' || e[1] == 'i') {
|
} else if (e[1] == 'f' || e[1] == 'i') {
|
||||||
IRRef ref;
|
IRRef ref;
|
||||||
@@ -261,7 +266,7 @@ static void ra_dprintf(ASMState *as, const char *fmt, ...)
|
|||||||
} else if (e[1] == 'x') {
|
} else if (e[1] == 'x') {
|
||||||
p += sprintf(p, "%08x", va_arg(argp, int32_t));
|
p += sprintf(p, "%08x", va_arg(argp, int32_t));
|
||||||
} else {
|
} else {
|
||||||
lua_assert(0);
|
lj_assertA(0, "bad debug format code");
|
||||||
}
|
}
|
||||||
fmt = e+2;
|
fmt = e+2;
|
||||||
}
|
}
|
||||||
@@ -320,7 +325,7 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
|||||||
Reg r;
|
Reg r;
|
||||||
if (ra_iskref(ref)) {
|
if (ra_iskref(ref)) {
|
||||||
r = ra_krefreg(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_free(as, r);
|
||||||
ra_modified(as, r);
|
ra_modified(as, r);
|
||||||
#if LJ_64
|
#if LJ_64
|
||||||
@@ -332,7 +337,9 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
|||||||
}
|
}
|
||||||
ir = IR(ref);
|
ir = IR(ref);
|
||||||
r = ir->r;
|
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_free(as, r);
|
||||||
ra_modified(as, r);
|
ra_modified(as, r);
|
||||||
ir->r = RID_INIT; /* Do not keep any hint. */
|
ir->r = RID_INIT; /* Do not keep any hint. */
|
||||||
@@ -346,7 +353,8 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
|||||||
ra_sethint(ir->r, RID_BASE); /* Restore BASE register hint. */
|
ra_sethint(ir->r, RID_BASE); /* Restore BASE register hint. */
|
||||||
emit_getgl(as, r, jit_base);
|
emit_getgl(as, r, jit_base);
|
||||||
} else if (emit_canremat(ASMREF_L) && ir->o == IR_KPRI) {
|
} 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);
|
emit_getgl(as, r, cur_L);
|
||||||
#if LJ_64
|
#if LJ_64
|
||||||
} else if (ir->o == IR_KINT64) {
|
} else if (ir->o == IR_KINT64) {
|
||||||
@@ -359,8 +367,9 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
lua_assert(ir->o == IR_KINT || ir->o == IR_KGC ||
|
lj_assertA(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL);
|
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);
|
emit_loadi(as, r, ir->i);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
@@ -370,7 +379,8 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
|||||||
static int32_t ra_spill(ASMState *as, IRIns *ir)
|
static int32_t ra_spill(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
int32_t slot = ir->s;
|
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 (!ra_hasspill(slot)) {
|
||||||
if (irt_is64(ir->t)) {
|
if (irt_is64(ir->t)) {
|
||||||
slot = as->evenspill;
|
slot = as->evenspill;
|
||||||
@@ -395,7 +405,9 @@ static Reg ra_releasetmp(ASMState *as, IRRef ref)
|
|||||||
{
|
{
|
||||||
IRIns *ir = IR(ref);
|
IRIns *ir = IR(ref);
|
||||||
Reg r = ir->r;
|
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_free(as, r);
|
||||||
ra_modified(as, r);
|
ra_modified(as, r);
|
||||||
ir->r = RID_INIT;
|
ir->r = RID_INIT;
|
||||||
@@ -411,7 +423,7 @@ static Reg ra_restore(ASMState *as, IRRef ref)
|
|||||||
IRIns *ir = IR(ref);
|
IRIns *ir = IR(ref);
|
||||||
int32_t ofs = ra_spill(as, ir); /* Force a spill slot. */
|
int32_t ofs = ra_spill(as, ir); /* Force a spill slot. */
|
||||||
Reg r = ir->r;
|
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_sethint(ir->r, r); /* Keep hint. */
|
||||||
ra_free(as, r);
|
ra_free(as, r);
|
||||||
if (!rset_test(as->weakset, r)) { /* Only restore non-weak references. */
|
if (!rset_test(as->weakset, r)) { /* Only restore non-weak references. */
|
||||||
@@ -440,14 +452,15 @@ static Reg ra_evict(ASMState *as, RegSet allow)
|
|||||||
{
|
{
|
||||||
IRRef ref;
|
IRRef ref;
|
||||||
RegCost cost = ~(RegCost)0;
|
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)) {
|
if (RID_NUM_FPR == 0 || allow < RID2RSET(RID_MAX_GPR)) {
|
||||||
GPRDEF(MINCOST)
|
GPRDEF(MINCOST)
|
||||||
} else {
|
} else {
|
||||||
FPRDEF(MINCOST)
|
FPRDEF(MINCOST)
|
||||||
}
|
}
|
||||||
ref = regcost_ref(cost);
|
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. */
|
/* Preferably pick any weak ref instead of a non-weak, non-const ref. */
|
||||||
if (!irref_isk(ref) && (as->weakset & allow)) {
|
if (!irref_isk(ref) && (as->weakset & allow)) {
|
||||||
IRIns *ir = IR(ref);
|
IRIns *ir = IR(ref);
|
||||||
@@ -605,7 +618,8 @@ static Reg ra_allocref(ASMState *as, IRRef ref, RegSet allow)
|
|||||||
IRIns *ir = IR(ref);
|
IRIns *ir = IR(ref);
|
||||||
RegSet pick = as->freeset & allow;
|
RegSet pick = as->freeset & allow;
|
||||||
Reg r;
|
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) {
|
if (pick) {
|
||||||
/* First check register hint from propagation or PHI. */
|
/* First check register hint from propagation or PHI. */
|
||||||
if (ra_hashint(ir->r)) {
|
if (ra_hashint(ir->r)) {
|
||||||
@@ -669,8 +683,10 @@ static void ra_rename(ASMState *as, Reg down, Reg up)
|
|||||||
IRIns *ir = IR(ref);
|
IRIns *ir = IR(ref);
|
||||||
ir->r = (uint8_t)up;
|
ir->r = (uint8_t)up;
|
||||||
as->cost[down] = 0;
|
as->cost[down] = 0;
|
||||||
lua_assert((down < RID_MAX_GPR) == (up < RID_MAX_GPR));
|
lj_assertA((down < RID_MAX_GPR) == (up < RID_MAX_GPR),
|
||||||
lua_assert(!rset_test(as->freeset, down) && rset_test(as->freeset, up));
|
"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_free(as, down); /* 'down' is free ... */
|
||||||
ra_modified(as, down);
|
ra_modified(as, down);
|
||||||
rset_clear(as->freeset, up); /* ... and 'up' is now allocated. */
|
rset_clear(as->freeset, up); /* ... and 'up' is now allocated. */
|
||||||
@@ -711,7 +727,7 @@ static void ra_destreg(ASMState *as, IRIns *ir, Reg r)
|
|||||||
{
|
{
|
||||||
Reg dest = ra_dest(as, ir, RID2RSET(r));
|
Reg dest = ra_dest(as, ir, RID2RSET(r));
|
||||||
if (dest != 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);
|
ra_modified(as, r);
|
||||||
emit_movrr(as, ir, dest, r);
|
emit_movrr(as, ir, dest, r);
|
||||||
}
|
}
|
||||||
@@ -744,8 +760,9 @@ static void ra_left(ASMState *as, Reg dest, IRRef lref)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
} else if (ir->o != IR_KPRI) {
|
} else if (ir->o != IR_KPRI) {
|
||||||
lua_assert(ir->o == IR_KINT || ir->o == IR_KGC ||
|
lj_assertA(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL);
|
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);
|
emit_loadi(as, dest, ir->i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -887,11 +904,14 @@ static void asm_snap_alloc1(ASMState *as, IRRef ref)
|
|||||||
#endif
|
#endif
|
||||||
{ /* Allocate stored values for TNEW, TDUP and CNEW. */
|
{ /* Allocate stored values for TNEW, TDUP and CNEW. */
|
||||||
IRIns *irs;
|
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--)
|
for (irs = IR(as->snapref-1); irs > ir; irs--)
|
||||||
if (irs->r == RID_SINK && asm_sunk_store(as, ir, irs)) {
|
if (irs->r == RID_SINK && asm_sunk_store(as, ir, irs)) {
|
||||||
lua_assert(irs->o == IR_ASTORE || irs->o == IR_HSTORE ||
|
lj_assertA(irs->o == IR_ASTORE || irs->o == IR_HSTORE ||
|
||||||
irs->o == IR_FSTORE || irs->o == IR_XSTORE);
|
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);
|
asm_snap_alloc1(as, irs->op2);
|
||||||
if (LJ_32 && (irs+1)->o == IR_HIOP)
|
if (LJ_32 && (irs+1)->o == IR_HIOP)
|
||||||
asm_snap_alloc1(as, (irs+1)->op2);
|
asm_snap_alloc1(as, (irs+1)->op2);
|
||||||
@@ -938,7 +958,9 @@ static void asm_snap_alloc(ASMState *as)
|
|||||||
if (!irref_isk(ref)) {
|
if (!irref_isk(ref)) {
|
||||||
asm_snap_alloc1(as, ref);
|
asm_snap_alloc1(as, ref);
|
||||||
if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) {
|
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);
|
asm_snap_alloc1(as, ref+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1002,19 +1024,20 @@ static int32_t asm_stack_adjust(ASMState *as)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Must match with hash*() in lj_tab.c. */
|
/* 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;
|
uint32_t lo, hi;
|
||||||
|
UNUSED(as);
|
||||||
if (irt_isstr(ir->t)) {
|
if (irt_isstr(ir->t)) {
|
||||||
return ir_kstr(ir)->hash;
|
return ir_kstr(ir)->sid;
|
||||||
} else if (irt_isnum(ir->t)) {
|
} else if (irt_isnum(ir->t)) {
|
||||||
lo = ir_knum(ir)->u32.lo;
|
lo = ir_knum(ir)->u32.lo;
|
||||||
hi = ir_knum(ir)->u32.hi << 1;
|
hi = ir_knum(ir)->u32.hi << 1;
|
||||||
} else if (irt_ispri(ir->t)) {
|
} 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;
|
return irt_type(ir->t)-IRT_FALSE;
|
||||||
} else {
|
} 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));
|
lo = u32ptr(ir_kgc(ir));
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
hi = (uint32_t)(u64ptr(ir_kgc(ir)) >> 32) | (irt_toitype(ir->t) << 15);
|
hi = (uint32_t)(u64ptr(ir_kgc(ir)) >> 32) | (irt_toitype(ir->t) << 15);
|
||||||
@@ -1122,7 +1145,8 @@ static void asm_bufput(ASMState *as, IRIns *ir)
|
|||||||
args[0] = ir->op1; /* SBuf * */
|
args[0] = ir->op1; /* SBuf * */
|
||||||
args[1] = ir->op2; /* GCstr * */
|
args[1] = ir->op2; /* GCstr * */
|
||||||
irs = IR(ir->op2);
|
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) {
|
if (irs->o == IR_KGC) {
|
||||||
GCstr *s = ir_kstr(irs);
|
GCstr *s = ir_kstr(irs);
|
||||||
if (s->len == 1) { /* Optimize put of single-char string constant. */
|
if (s->len == 1) { /* Optimize put of single-char string constant. */
|
||||||
@@ -1136,7 +1160,8 @@ static void asm_bufput(ASMState *as, IRIns *ir)
|
|||||||
args[1] = ASMREF_TMP1; /* TValue * */
|
args[1] = ASMREF_TMP1; /* TValue * */
|
||||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_putnum];
|
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_putnum];
|
||||||
} else {
|
} 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 */
|
args[1] = irs->op1; /* int */
|
||||||
if (irs->op2 == IRTOSTR_INT)
|
if (irs->op2 == IRTOSTR_INT)
|
||||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_putint];
|
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_putint];
|
||||||
@@ -1201,7 +1226,8 @@ static void asm_conv64(ASMState *as, IRIns *ir)
|
|||||||
IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH);
|
IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH);
|
||||||
IRCallID id;
|
IRCallID id;
|
||||||
IRRef args[2];
|
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_BE] = (ir-1)->op1;
|
||||||
args[LJ_LE] = ir->op1;
|
args[LJ_LE] = ir->op1;
|
||||||
if (st == IRT_NUM || st == IRT_FLOAT) {
|
if (st == IRT_NUM || st == IRT_FLOAT) {
|
||||||
@@ -1256,15 +1282,16 @@ static void asm_collectargs(ASMState *as, IRIns *ir,
|
|||||||
const CCallInfo *ci, IRRef *args)
|
const CCallInfo *ci, IRRef *args)
|
||||||
{
|
{
|
||||||
uint32_t n = CCI_XNARGS(ci);
|
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--; }
|
if ((ci->flags & CCI_L)) { *args++ = ASMREF_L; n--; }
|
||||||
while (n-- > 1) {
|
while (n-- > 1) {
|
||||||
ir = IR(ir->op1);
|
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[n] = ir->op2 == REF_NIL ? 0 : ir->op2;
|
||||||
}
|
}
|
||||||
args[0] = ir->op1 == REF_NIL ? 0 : ir->op1;
|
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*. */
|
/* Reconstruct CCallInfo flags for CALLX*. */
|
||||||
@@ -1308,32 +1335,6 @@ static void asm_call(ASMState *as, IRIns *ir)
|
|||||||
asm_gencall(as, ci, args);
|
asm_gencall(as, ci, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !LJ_SOFTFP32
|
|
||||||
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 ----------------------------------------------- */
|
/* -- PHI and loop handling ----------------------------------------------- */
|
||||||
|
|
||||||
/* Break a PHI cycle by renaming to a free register (evict if needed). */
|
/* Break a PHI cycle by renaming to a free register (evict if needed). */
|
||||||
@@ -1604,6 +1605,68 @@ static void asm_loop(ASMState *as)
|
|||||||
#error "Missing assembler for target CPU"
|
#error "Missing assembler for target CPU"
|
||||||
#endif
|
#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 ------------------------------------------------ */
|
/* -- Instruction dispatch ------------------------------------------------ */
|
||||||
|
|
||||||
/* Assemble a single instruction. */
|
/* Assemble a single instruction. */
|
||||||
@@ -1612,7 +1675,10 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
|||||||
switch ((IROp)ir->o) {
|
switch ((IROp)ir->o) {
|
||||||
/* Miscellaneous ops. */
|
/* Miscellaneous ops. */
|
||||||
case IR_LOOP: asm_loop(as); break;
|
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:
|
case IR_USE:
|
||||||
ra_alloc1(as, ir->op1, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); break;
|
ra_alloc1(as, ir->op1, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); break;
|
||||||
case IR_PHI: asm_phi(as, ir); break;
|
case IR_PHI: asm_phi(as, ir); break;
|
||||||
@@ -1626,14 +1692,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
|||||||
case IR_ABC:
|
case IR_ABC:
|
||||||
asm_comp(as, ir);
|
asm_comp(as, ir);
|
||||||
break;
|
break;
|
||||||
case IR_EQ: case IR_NE:
|
case IR_EQ: case IR_NE: asm_fuseequal(as, ir); break;
|
||||||
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_RETF: asm_retf(as, ir); break;
|
case IR_RETF: asm_retf(as, ir); break;
|
||||||
|
|
||||||
@@ -1657,14 +1716,15 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
|||||||
case IR_NEG: asm_neg(as, ir); break;
|
case IR_NEG: asm_neg(as, ir); break;
|
||||||
#if LJ_SOFTFP32
|
#if LJ_SOFTFP32
|
||||||
case IR_DIV: case IR_POW: case IR_ABS:
|
case IR_DIV: case IR_POW: case IR_ABS:
|
||||||
case IR_ATAN2: case IR_LDEXP: case IR_FPMATH: case IR_TOBIT:
|
case IR_LDEXP: case IR_FPMATH: case IR_TOBIT:
|
||||||
lua_assert(0); /* Unused for LJ_SOFTFP32. */
|
/* Unused for LJ_SOFTFP32. */
|
||||||
|
lj_assertA(0, "IR %04d with unused op %d",
|
||||||
|
(int)(ir - as->ir) - REF_BIAS, ir->o);
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
case IR_DIV: asm_div(as, ir); break;
|
case IR_DIV: asm_div(as, ir); break;
|
||||||
case IR_POW: asm_pow(as, ir); break;
|
case IR_POW: asm_pow(as, ir); break;
|
||||||
case IR_ABS: asm_abs(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_LDEXP: asm_ldexp(as, ir); break;
|
||||||
case IR_FPMATH: asm_fpmath(as, ir); break;
|
case IR_FPMATH: asm_fpmath(as, ir); break;
|
||||||
case IR_TOBIT: asm_tobit(as, ir); break;
|
case IR_TOBIT: asm_tobit(as, ir); break;
|
||||||
@@ -1694,6 +1754,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
|||||||
case IR_FLOAD: asm_fload(as, ir); break;
|
case IR_FLOAD: asm_fload(as, ir); break;
|
||||||
case IR_XLOAD: asm_xload(as, ir); break;
|
case IR_XLOAD: asm_xload(as, ir); break;
|
||||||
case IR_SLOAD: asm_sload(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_ASTORE: case IR_HSTORE: case IR_USTORE: asm_ahustore(as, ir); break;
|
||||||
case IR_FSTORE: asm_fstore(as, ir); break;
|
case IR_FSTORE: asm_fstore(as, ir); break;
|
||||||
@@ -1703,7 +1764,14 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
|||||||
case IR_SNEW: case IR_XSNEW: asm_snew(as, ir); break;
|
case IR_SNEW: case IR_XSNEW: asm_snew(as, ir); break;
|
||||||
case IR_TNEW: asm_tnew(as, ir); break;
|
case IR_TNEW: asm_tnew(as, ir); break;
|
||||||
case IR_TDUP: asm_tdup(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. */
|
/* Buffer operations. */
|
||||||
case IR_BUFHDR: asm_bufhdr(as, ir); break;
|
case IR_BUFHDR: asm_bufhdr(as, ir); break;
|
||||||
@@ -1779,8 +1847,10 @@ static void asm_head_side(ASMState *as)
|
|||||||
for (i = as->stopins; i > REF_BASE; i--) {
|
for (i = as->stopins; i > REF_BASE; i--) {
|
||||||
IRIns *ir = IR(i);
|
IRIns *ir = IR(i);
|
||||||
RegSP rs;
|
RegSP rs;
|
||||||
lua_assert((ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_PARENT)) ||
|
lj_assertA((ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_PARENT)) ||
|
||||||
(LJ_SOFTFP && ir->o == IR_HIOP) || ir->o == IR_PVAL);
|
(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];
|
rs = as->parentmap[i - REF_FIRST];
|
||||||
if (ra_hasreg(ir->r)) {
|
if (ra_hasreg(ir->r)) {
|
||||||
rset_clear(allow, ir->r);
|
rset_clear(allow, ir->r);
|
||||||
@@ -2039,7 +2109,7 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
ir = IR(REF_FIRST);
|
ir = IR(REF_FIRST);
|
||||||
if (as->parent) {
|
if (as->parent) {
|
||||||
uint16_t *p;
|
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)
|
if (lastir - ir > LJ_MAX_JSLOTS)
|
||||||
lj_trace_err(as->J, LJ_TRERR_NYICOAL);
|
lj_trace_err(as->J, LJ_TRERR_NYICOAL);
|
||||||
as->stopins = (IRRef)((lastir-1) - as->ir);
|
as->stopins = (IRRef)((lastir-1) - as->ir);
|
||||||
@@ -2112,8 +2182,8 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
ir->prev = REGSP_HINT(RID_FPRET);
|
ir->prev = REGSP_HINT(RID_FPRET);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* fallthrough */
|
|
||||||
#endif
|
#endif
|
||||||
|
/* fallthrough */
|
||||||
case IR_CALLN: case IR_CALLXS:
|
case IR_CALLN: case IR_CALLXS:
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
case IR_MIN: case IR_MAX:
|
case IR_MIN: case IR_MAX:
|
||||||
@@ -2158,11 +2228,6 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
as->modset = RSET_SCRATCH;
|
as->modset = RSET_SCRATCH;
|
||||||
break;
|
break;
|
||||||
#if !LJ_SOFTFP
|
#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
|
#if !LJ_TARGET_X86ORX64
|
||||||
case IR_LDEXP:
|
case IR_LDEXP:
|
||||||
#endif
|
#endif
|
||||||
@@ -2173,6 +2238,10 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
if (inloop)
|
if (inloop)
|
||||||
as->modset |= RSET_SCRATCH;
|
as->modset |= RSET_SCRATCH;
|
||||||
#if LJ_TARGET_X86
|
#if LJ_TARGET_X86
|
||||||
|
if (irt_isnum(IR(ir->op2)->t)) {
|
||||||
|
if (as->evenspill < 4) /* Leave room to call pow(). */
|
||||||
|
as->evenspill = 4;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
ir->prev = REGSP_HINT(RID_FPRET);
|
ir->prev = REGSP_HINT(RID_FPRET);
|
||||||
@@ -2198,9 +2267,6 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (ir->op2 == IRFPM_EXP2 && !LJ_64) {
|
|
||||||
if (as->evenspill < 4) /* Leave room to call pow(). */
|
|
||||||
as->evenspill = 4;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (inloop)
|
if (inloop)
|
||||||
@@ -2276,7 +2342,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||||||
/* Ensure an initialized instruction beyond the last one for HIOP checks. */
|
/* Ensure an initialized instruction beyond the last one for HIOP checks. */
|
||||||
/* This also allows one RENAME to be added without reallocating curfinal. */
|
/* This also allows one RENAME to be added without reallocating curfinal. */
|
||||||
as->orignins = lj_ir_nextins(J);
|
as->orignins = lj_ir_nextins(J);
|
||||||
J->cur.ir[as->orignins].o = IR_NOP;
|
lj_ir_nop(&J->cur.ir[as->orignins]);
|
||||||
|
|
||||||
/* Setup initial state. Copy some fields to reduce indirections. */
|
/* Setup initial state. Copy some fields to reduce indirections. */
|
||||||
as->J = J;
|
as->J = J;
|
||||||
@@ -2347,7 +2413,10 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||||||
/* Assemble a trace in linear backwards order. */
|
/* Assemble a trace in linear backwards order. */
|
||||||
for (as->curins--; as->curins > as->stopins; as->curins--) {
|
for (as->curins--; as->curins > as->stopins; as->curins--) {
|
||||||
IRIns *ir = IR(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))
|
if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE))
|
||||||
continue; /* Dead-code elimination can be soooo easy. */
|
continue; /* Dead-code elimination can be soooo easy. */
|
||||||
if (irt_isguard(ir->t))
|
if (irt_isguard(ir->t))
|
||||||
@@ -2377,7 +2446,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||||||
asm_phi_fixup(as);
|
asm_phi_fixup(as);
|
||||||
|
|
||||||
if (J->curfinal->nins >= T->nins) { /* IR didn't grow? */
|
if (J->curfinal->nins >= T->nins) { /* IR didn't grow? */
|
||||||
lua_assert(J->curfinal->nk == T->nk);
|
lj_assertA(J->curfinal->nk == T->nk, "unexpected IR constant growth");
|
||||||
memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins,
|
memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins,
|
||||||
(T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */
|
(T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */
|
||||||
T->nins = J->curfinal->nins;
|
T->nins = J->curfinal->nins;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** IR assembler (SSA IR -> machine code).
|
** IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_ASM_H
|
#ifndef _LJ_ASM_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** ARM IR assembler (SSA IR -> machine code).
|
** ARM IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* -- Register allocator extensions --------------------------------------- */
|
/* -- 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);
|
||||||
ra_modified(as, r+1);
|
ra_modified(as, r+1);
|
||||||
RA_DBGX((as, "scratchpair $r $r", r, 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;
|
return;
|
||||||
}
|
}
|
||||||
} else if (ir->o == IR_STRREF && !(!LJ_SOFTFP && (ai & 0x08000000))) {
|
} 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);
|
ofs = (int32_t)sizeof(GCstr);
|
||||||
if (irref_isk(ir->op2)) {
|
if (irref_isk(ir->op2)) {
|
||||||
ofs += IR(ir->op2)->i;
|
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));
|
as->freeset |= (of & RSET_RANGE(REGARG_FIRSTGPR, REGARG_LASTGPR+1));
|
||||||
if (irt_isnum(ir->t)) gpr = (gpr+1) & ~1u;
|
if (irt_isnum(ir->t)) gpr = (gpr+1) & ~1u;
|
||||||
if (gpr <= REGARG_LASTGPR) {
|
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)) {
|
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));
|
emit_dnm(as, ARMI_VMOV_RR_D, gpr, gpr+1, (src & 15));
|
||||||
gpr += 2;
|
gpr += 2;
|
||||||
} else {
|
} else {
|
||||||
@@ -408,7 +410,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (gpr <= REGARG_LASTGPR) {
|
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);
|
if (ref) ra_leftov(as, gpr, ref);
|
||||||
gpr++;
|
gpr++;
|
||||||
} else {
|
} else {
|
||||||
@@ -433,7 +436,7 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
|||||||
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
|
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
|
||||||
ra_evictset(as, drop); /* Evictions must be performed first. */
|
ra_evictset(as, drop); /* Evictions must be performed first. */
|
||||||
if (ra_used(ir)) {
|
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_SOFTFP && irt_isfp(ir->t)) {
|
||||||
if (LJ_ABI_SOFTFP || (ci->flags & (CCI_CASTU64|CCI_VARARG))) {
|
if (LJ_ABI_SOFTFP || (ci->flags & (CCI_CASTU64|CCI_VARARG))) {
|
||||||
Reg dest = (ra_dest(as, ir, RSET_FPR) & 15);
|
Reg dest = (ra_dest(as, ir, RSET_FPR) & 15);
|
||||||
@@ -530,13 +533,17 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
#endif
|
#endif
|
||||||
IRRef lref = ir->op1;
|
IRRef lref = ir->op1;
|
||||||
/* 64 bit integer conversions are handled by SPLIT. */
|
/* 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
|
#if LJ_SOFTFP
|
||||||
/* FP conversions are handled by SPLIT. */
|
/* 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. */
|
/* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. */
|
||||||
#else
|
#else
|
||||||
lua_assert(irt_type(ir->t) != st);
|
lj_assertA(irt_type(ir->t) != st, "inconsistent types for CONV");
|
||||||
if (irt_isfp(ir->t)) {
|
if (irt_isfp(ir->t)) {
|
||||||
Reg dest = ra_dest(as, ir, RSET_FPR);
|
Reg dest = ra_dest(as, ir, RSET_FPR);
|
||||||
if (stfp) { /* FP to FP conversion. */
|
if (stfp) { /* FP to FP conversion. */
|
||||||
@@ -553,7 +560,8 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
} else if (stfp) { /* FP to integer conversion. */
|
} else if (stfp) { /* FP to integer conversion. */
|
||||||
if (irt_isguard(ir->t)) {
|
if (irt_isguard(ir->t)) {
|
||||||
/* Checked conversions are only supported from number to int. */
|
/* 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));
|
asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
|
||||||
} else {
|
} else {
|
||||||
Reg left = ra_alloc1(as, lref, RSET_FPR);
|
Reg left = ra_alloc1(as, lref, RSET_FPR);
|
||||||
@@ -572,7 +580,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */
|
if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */
|
||||||
Reg left = ra_alloc1(as, lref, RSET_GPR);
|
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)) {
|
if ((as->flags & JIT_F_ARMV6)) {
|
||||||
ARMIns ai = st == IRT_I8 ? ARMI_SXTB :
|
ARMIns ai = st == IRT_I8 ? ARMI_SXTB :
|
||||||
st == IRT_U8 ? ARMI_UXTB :
|
st == IRT_U8 ? ARMI_UXTB :
|
||||||
@@ -667,7 +675,7 @@ static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
|
|||||||
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
|
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
|
||||||
} else {
|
} else {
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
lua_assert(0);
|
lj_assertA(0, "unsplit FP op");
|
||||||
#else
|
#else
|
||||||
/* Otherwise force a spill and use the spill slot. */
|
/* Otherwise force a spill and use the spill slot. */
|
||||||
emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
|
emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
|
||||||
@@ -811,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);
|
*l_loop = ARMF_CC(ARMI_B, CC_NE) | ((as->mcp-l_loop-2) & 0x00ffffffu);
|
||||||
|
|
||||||
/* Load main position relative to tab->node into dest. */
|
/* 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) {
|
if (khash == 0) {
|
||||||
emit_lso(as, ARMI_LDR, dest, tab, (int32_t)offsetof(GCtab, node));
|
emit_lso(as, ARMI_LDR, dest, tab, (int32_t)offsetof(GCtab, node));
|
||||||
} else {
|
} else {
|
||||||
emit_dnm(as, ARMI_ADD|ARMF_SH(ARMSH_LSL, 3), dest, dest, tmp);
|
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);
|
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_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, 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));
|
emit_lso(as, ARMI_LDR, RID_TMP, tab, (int32_t)offsetof(GCtab, hmask));
|
||||||
} else if (irref_isk(refkey)) {
|
} else if (irref_isk(refkey)) {
|
||||||
emit_opk(as, ARMI_AND, tmp, RID_TMP, (int32_t)khash,
|
emit_opk(as, ARMI_AND, tmp, RID_TMP, (int32_t)khash,
|
||||||
@@ -867,7 +875,7 @@ static void asm_hrefk(ASMState *as, IRIns *ir)
|
|||||||
Reg node = ra_alloc1(as, ir->op1, RSET_GPR);
|
Reg node = ra_alloc1(as, ir->op1, RSET_GPR);
|
||||||
Reg key = RID_NONE, type = RID_TMP, idx = node;
|
Reg key = RID_NONE, type = RID_TMP, idx = node;
|
||||||
RegSet allow = rset_exclude(RSET_GPR, 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) {
|
if (ofs > 4095) {
|
||||||
idx = dest;
|
idx = dest;
|
||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
@@ -934,7 +942,7 @@ static void asm_uref(ASMState *as, IRIns *ir)
|
|||||||
static void asm_fref(ASMState *as, IRIns *ir)
|
static void asm_fref(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
UNUSED(as); UNUSED(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)
|
static void asm_strref(ASMState *as, IRIns *ir)
|
||||||
@@ -971,25 +979,27 @@ static void asm_strref(ASMState *as, IRIns *ir)
|
|||||||
|
|
||||||
/* -- Loads and stores ---------------------------------------------------- */
|
/* -- Loads and stores ---------------------------------------------------- */
|
||||||
|
|
||||||
static ARMIns asm_fxloadins(IRIns *ir)
|
static ARMIns asm_fxloadins(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
|
UNUSED(as);
|
||||||
switch (irt_type(ir->t)) {
|
switch (irt_type(ir->t)) {
|
||||||
case IRT_I8: return ARMI_LDRSB;
|
case IRT_I8: return ARMI_LDRSB;
|
||||||
case IRT_U8: return ARMI_LDRB;
|
case IRT_U8: return ARMI_LDRB;
|
||||||
case IRT_I16: return ARMI_LDRSH;
|
case IRT_I16: return ARMI_LDRSH;
|
||||||
case IRT_U16: return ARMI_LDRH;
|
case IRT_U16: return ARMI_LDRH;
|
||||||
case IRT_NUM: lua_assert(!LJ_SOFTFP); return ARMI_VLDR_D;
|
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 */
|
case IRT_FLOAT: if (!LJ_SOFTFP) return ARMI_VLDR_S; /* fallthrough */
|
||||||
default: return ARMI_LDR;
|
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)) {
|
switch (irt_type(ir->t)) {
|
||||||
case IRT_I8: case IRT_U8: return ARMI_STRB;
|
case IRT_I8: case IRT_U8: return ARMI_STRB;
|
||||||
case IRT_I16: case IRT_U16: return ARMI_STRH;
|
case IRT_I16: case IRT_U16: return ARMI_STRH;
|
||||||
case IRT_NUM: lua_assert(!LJ_SOFTFP); return ARMI_VSTR_D;
|
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 */
|
case IRT_FLOAT: if (!LJ_SOFTFP) return ARMI_VSTR_S; /* fallthrough */
|
||||||
default: return ARMI_STR;
|
default: return ARMI_STR;
|
||||||
}
|
}
|
||||||
@@ -997,13 +1007,15 @@ static ARMIns asm_fxstoreins(IRIns *ir)
|
|||||||
|
|
||||||
static void asm_fload(ASMState *as, IRIns *ir)
|
static void asm_fload(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
if (ir->op1 == REF_NIL) {
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
lua_assert(!ra_used(ir)); /* We can end up here if DCE is turned off. */
|
ARMIns ai = asm_fxloadins(as, ir);
|
||||||
|
Reg idx;
|
||||||
|
int32_t ofs;
|
||||||
|
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 {
|
} else {
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
idx = ra_alloc1(as, ir->op1, RSET_GPR);
|
||||||
Reg idx = ra_alloc1(as, ir->op1, RSET_GPR);
|
|
||||||
ARMIns ai = asm_fxloadins(ir);
|
|
||||||
int32_t ofs;
|
|
||||||
if (ir->op2 == IRFL_TAB_ARRAY) {
|
if (ir->op2 == IRFL_TAB_ARRAY) {
|
||||||
ofs = asm_fuseabase(as, ir->op1);
|
ofs = asm_fuseabase(as, ir->op1);
|
||||||
if (ofs) { /* Turn the t->array load into an add for colocated arrays. */
|
if (ofs) { /* Turn the t->array load into an add for colocated arrays. */
|
||||||
@@ -1012,11 +1024,11 @@ static void asm_fload(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ofs = field_ofs[ir->op2];
|
ofs = field_ofs[ir->op2];
|
||||||
if ((ai & 0x04000000))
|
|
||||||
emit_lso(as, ai, dest, idx, ofs);
|
|
||||||
else
|
|
||||||
emit_lsox(as, ai, dest, idx, ofs);
|
|
||||||
}
|
}
|
||||||
|
if ((ai & 0x04000000))
|
||||||
|
emit_lso(as, ai, dest, idx, ofs);
|
||||||
|
else
|
||||||
|
emit_lsox(as, ai, dest, idx, ofs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_fstore(ASMState *as, IRIns *ir)
|
static void asm_fstore(ASMState *as, IRIns *ir)
|
||||||
@@ -1026,7 +1038,7 @@ static void asm_fstore(ASMState *as, IRIns *ir)
|
|||||||
IRIns *irf = IR(ir->op1);
|
IRIns *irf = IR(ir->op1);
|
||||||
Reg idx = ra_alloc1(as, irf->op1, rset_exclude(RSET_GPR, src));
|
Reg idx = ra_alloc1(as, irf->op1, rset_exclude(RSET_GPR, src));
|
||||||
int32_t ofs = field_ofs[irf->op2];
|
int32_t ofs = field_ofs[irf->op2];
|
||||||
ARMIns ai = asm_fxstoreins(ir);
|
ARMIns ai = asm_fxstoreins(as, ir);
|
||||||
if ((ai & 0x04000000))
|
if ((ai & 0x04000000))
|
||||||
emit_lso(as, ai, src, idx, ofs);
|
emit_lso(as, ai, src, idx, ofs);
|
||||||
else
|
else
|
||||||
@@ -1038,8 +1050,8 @@ static void asm_xload(ASMState *as, IRIns *ir)
|
|||||||
{
|
{
|
||||||
Reg dest = ra_dest(as, ir,
|
Reg dest = ra_dest(as, ir,
|
||||||
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
||||||
lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED));
|
lj_assertA(!(ir->op2 & IRXLOAD_UNALIGNED), "unaligned XLOAD");
|
||||||
asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0);
|
asm_fusexref(as, asm_fxloadins(as, ir), dest, ir->op1, RSET_GPR, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
|
static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
|
||||||
@@ -1047,7 +1059,7 @@ static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
|
|||||||
if (ir->r != RID_SINK) {
|
if (ir->r != RID_SINK) {
|
||||||
Reg src = ra_alloc1(as, ir->op2,
|
Reg src = ra_alloc1(as, ir->op2,
|
||||||
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
(!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);
|
rset_exclude(RSET_GPR, src), ofs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1066,8 +1078,9 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
rset_clear(allow, type);
|
rset_clear(allow, type);
|
||||||
}
|
}
|
||||||
if (ra_used(ir)) {
|
if (ra_used(ir)) {
|
||||||
lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
|
lj_assertA((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
|
||||||
irt_isint(ir->t) || irt_isaddr(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);
|
dest = ra_dest(as, ir, (!LJ_SOFTFP && t == IRT_NUM) ? RSET_FPR : allow);
|
||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
}
|
}
|
||||||
@@ -1133,10 +1146,13 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
IRType t = hiop ? IRT_NUM : irt_type(ir->t);
|
IRType t = hiop ? IRT_NUM : irt_type(ir->t);
|
||||||
Reg dest = RID_NONE, type = RID_NONE, base;
|
Reg dest = RID_NONE, type = RID_NONE, base;
|
||||||
RegSet allow = RSET_GPR;
|
RegSet allow = RSET_GPR;
|
||||||
lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */
|
lj_assertA(!(ir->op2 & IRSLOAD_PARENT),
|
||||||
lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK));
|
"bad parent SLOAD"); /* Handled by asm_head_side(). */
|
||||||
|
lj_assertA(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK),
|
||||||
|
"inconsistent SLOAD variant");
|
||||||
#if LJ_SOFTFP
|
#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)) {
|
if (hiop && ra_used(ir+1)) {
|
||||||
type = ra_dest(as, ir+1, allow);
|
type = ra_dest(as, ir+1, allow);
|
||||||
rset_clear(allow, type);
|
rset_clear(allow, type);
|
||||||
@@ -1152,8 +1168,9 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
Reg tmp = RID_NONE;
|
Reg tmp = RID_NONE;
|
||||||
if ((ir->op2 & IRSLOAD_CONVERT))
|
if ((ir->op2 & IRSLOAD_CONVERT))
|
||||||
tmp = ra_scratch(as, t == IRT_INT ? RSET_FPR : RSET_GPR);
|
tmp = ra_scratch(as, t == IRT_INT ? RSET_FPR : RSET_GPR);
|
||||||
lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
|
lj_assertA((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
|
||||||
irt_isint(ir->t) || irt_isaddr(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);
|
dest = ra_dest(as, ir, (!LJ_SOFTFP && t == IRT_NUM) ? RSET_FPR : allow);
|
||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
base = ra_alloc1(as, REF_BASE, allow);
|
base = ra_alloc1(as, REF_BASE, allow);
|
||||||
@@ -1218,7 +1235,8 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
IRRef args[4];
|
IRRef args[4];
|
||||||
RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
|
RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
|
||||||
RegSet drop = 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++;
|
as->gcsteps++;
|
||||||
if (ra_hasreg(ir->r))
|
if (ra_hasreg(ir->r))
|
||||||
@@ -1230,10 +1248,10 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
/* Initialize immutable cdata object. */
|
/* Initialize immutable cdata object. */
|
||||||
if (ir->o == IR_CNEWI) {
|
if (ir->o == IR_CNEWI) {
|
||||||
int32_t ofs = sizeof(GCcdata);
|
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) {
|
if (sz == 8) {
|
||||||
ofs += 4; ir++;
|
ofs += 4; ir++;
|
||||||
lua_assert(ir->o == IR_HIOP);
|
lj_assertA(ir->o == IR_HIOP, "expected HIOP for CNEWI");
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Reg r = ra_alloc1(as, ir->op2, allow);
|
Reg r = ra_alloc1(as, ir->op2, allow);
|
||||||
@@ -1268,8 +1286,6 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
|
ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
|
||||||
ra_releasetmp(as, ASMREF_TMP1));
|
ra_releasetmp(as, ASMREF_TMP1));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define asm_cnew(as, ir) ((void)0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -- Write barriers ------------------------------------------------------ */
|
/* -- Write barriers ------------------------------------------------------ */
|
||||||
@@ -1301,7 +1317,7 @@ static void asm_obar(ASMState *as, IRIns *ir)
|
|||||||
MCLabel l_end;
|
MCLabel l_end;
|
||||||
Reg obj, val, tmp;
|
Reg obj, val, tmp;
|
||||||
/* No need for other object barriers (yet). */
|
/* 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);
|
ra_evictset(as, RSET_SCRATCH);
|
||||||
l_end = emit_label(as);
|
l_end = emit_label(as);
|
||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
@@ -1364,8 +1380,6 @@ static void asm_callround(ASMState *as, IRIns *ir, int id)
|
|||||||
|
|
||||||
static void asm_fpmath(ASMState *as, IRIns *ir)
|
static void asm_fpmath(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir))
|
|
||||||
return;
|
|
||||||
if (ir->op2 <= IRFPM_TRUNC)
|
if (ir->op2 <= IRFPM_TRUNC)
|
||||||
asm_callround(as, ir, ir->op2);
|
asm_callround(as, ir, ir->op2);
|
||||||
else if (ir->op2 == IRFPM_SQRT)
|
else if (ir->op2 == IRFPM_SQRT)
|
||||||
@@ -1507,15 +1521,10 @@ static void asm_mul(ASMState *as, IRIns *ir)
|
|||||||
#define asm_mulov(as, ir) asm_mul(as, ir)
|
#define asm_mulov(as, ir) asm_mul(as, ir)
|
||||||
|
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
#define asm_div(as, ir) asm_fparith(as, ir, ARMI_VDIV_D)
|
#define asm_fpdiv(as, ir) asm_fparith(as, ir, ARMI_VDIV_D)
|
||||||
#define asm_pow(as, ir) asm_callid(as, ir, IRCALL_lj_vm_powi)
|
|
||||||
#define asm_abs(as, ir) asm_fpunary(as, ir, ARMI_VABS_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
|
#endif
|
||||||
|
|
||||||
#define asm_mod(as, ir) asm_callid(as, ir, IRCALL_lj_vm_modi)
|
|
||||||
|
|
||||||
static void asm_neg(ASMState *as, IRIns *ir)
|
static void asm_neg(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
@@ -1584,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_bshr(as, ir) asm_bitshift(as, ir, ARMSH_LSR)
|
||||||
#define asm_bsar(as, ir) asm_bitshift(as, ir, ARMSH_ASR)
|
#define asm_bsar(as, ir) asm_bitshift(as, ir, ARMSH_ASR)
|
||||||
#define asm_bror(as, ir) asm_bitshift(as, ir, ARMSH_ROR)
|
#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)
|
static void asm_intmin_max(ASMState *as, IRIns *ir, int cc)
|
||||||
{
|
{
|
||||||
@@ -1659,8 +1668,8 @@ static void asm_min_max(ASMState *as, IRIns *ir, int cc, int fcc)
|
|||||||
asm_intmin_max(as, ir, cc);
|
asm_intmin_max(as, ir, cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define asm_min(as, ir) asm_min_max(as, ir, CC_GT, CC_HI)
|
#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_LO)
|
#define asm_max(as, ir) asm_min_max(as, ir, CC_LT, CC_LE)
|
||||||
|
|
||||||
/* -- Comparisons --------------------------------------------------------- */
|
/* -- Comparisons --------------------------------------------------------- */
|
||||||
|
|
||||||
@@ -1735,7 +1744,8 @@ static void asm_intcomp(ASMState *as, IRIns *ir)
|
|||||||
Reg left;
|
Reg left;
|
||||||
uint32_t m;
|
uint32_t m;
|
||||||
int cmpprev0 = 0;
|
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)) {
|
if (asm_swapops(as, lref, rref)) {
|
||||||
Reg tmp = lref; lref = rref; rref = tmp;
|
Reg tmp = lref; lref = rref; rref = tmp;
|
||||||
if (cc >= CC_GE) cc ^= 7; /* LT <-> GT, LE <-> GE */
|
if (cc >= CC_GE) cc ^= 7; /* LT <-> GT, LE <-> GE */
|
||||||
@@ -1852,7 +1862,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
} else if ((ir-1)->o == IR_MIN || (ir-1)->o == IR_MAX) {
|
} else if ((ir-1)->o == IR_MIN || (ir-1)->o == IR_MAX) {
|
||||||
as->curins--; /* Always skip the loword min/max. */
|
as->curins--; /* Always skip the loword min/max. */
|
||||||
if (uselo || usehi)
|
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;
|
return;
|
||||||
#elif LJ_HASFFI
|
#elif LJ_HASFFI
|
||||||
} else if ((ir-1)->o == IR_CONV) {
|
} else if ((ir-1)->o == IR_CONV) {
|
||||||
@@ -1904,10 +1914,11 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
case IR_CNEWI:
|
case IR_CNEWI:
|
||||||
/* Nothing to do here. Handled by lo op itself. */
|
/* Nothing to do here. Handled by lo op itself. */
|
||||||
break;
|
break;
|
||||||
default: lua_assert(0); break;
|
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
UNUSED(as); UNUSED(ir); lua_assert(0);
|
/* Unused without SOFTFP or FFI. */
|
||||||
|
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1932,7 +1943,7 @@ static void asm_stack_check(ASMState *as, BCReg topslot,
|
|||||||
if (irp) {
|
if (irp) {
|
||||||
if (!ra_hasspill(irp->s)) {
|
if (!ra_hasspill(irp->s)) {
|
||||||
pbase = irp->r;
|
pbase = irp->r;
|
||||||
lua_assert(ra_hasreg(pbase));
|
lj_assertA(ra_hasreg(pbase), "base reg lost");
|
||||||
} else if (allow) {
|
} else if (allow) {
|
||||||
pbase = rset_pickbot(allow);
|
pbase = rset_pickbot(allow);
|
||||||
} else {
|
} else {
|
||||||
@@ -1944,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));
|
emit_branch(as, ARMF_CC(ARMI_BL, CC_LS), exitstub_addr(as->J, exitno));
|
||||||
k = emit_isk12(0, (int32_t)(8*topslot));
|
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_n(as, ARMI_CMP^k, RID_TMP);
|
||||||
emit_dnm(as, ARMI_SUB, RID_TMP, RID_TMP, pbase);
|
emit_dnm(as, ARMI_SUB, RID_TMP, RID_TMP, pbase);
|
||||||
emit_lso(as, ARMI_LDR, RID_TMP, RID_TMP,
|
emit_lso(as, ARMI_LDR, RID_TMP, RID_TMP,
|
||||||
@@ -1981,7 +1992,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
RegSet odd = rset_exclude(RSET_GPRODD, RID_BASE);
|
RegSet odd = rset_exclude(RSET_GPRODD, RID_BASE);
|
||||||
Reg tmp;
|
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,
|
tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.lo,
|
||||||
rset_exclude(RSET_GPREVEN, RID_BASE));
|
rset_exclude(RSET_GPREVEN, RID_BASE));
|
||||||
emit_lso(as, ARMI_STR, tmp, RID_BASE, ofs);
|
emit_lso(as, ARMI_STR, tmp, RID_BASE, ofs);
|
||||||
@@ -1995,7 +2007,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
} else {
|
} else {
|
||||||
RegSet odd = rset_exclude(RSET_GPRODD, RID_BASE);
|
RegSet odd = rset_exclude(RSET_GPRODD, RID_BASE);
|
||||||
Reg type;
|
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)) {
|
if (!irt_ispri(ir->t)) {
|
||||||
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPREVEN, RID_BASE));
|
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPREVEN, RID_BASE));
|
||||||
emit_lso(as, ARMI_STR, src, RID_BASE, ofs);
|
emit_lso(as, ARMI_STR, src, RID_BASE, ofs);
|
||||||
@@ -2015,11 +2028,14 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
}
|
}
|
||||||
checkmclim(as);
|
checkmclim(as);
|
||||||
}
|
}
|
||||||
lua_assert(map + nent == flinks);
|
lj_assertA(map + nent == flinks, "inconsistent frames in snapshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- GC handling --------------------------------------------------------- */
|
/* -- 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. */
|
/* Check GC threshold and do one or more GC steps. */
|
||||||
static void asm_gc_check(ASMState *as)
|
static void asm_gc_check(ASMState *as)
|
||||||
{
|
{
|
||||||
@@ -2031,6 +2047,7 @@ static void asm_gc_check(ASMState *as)
|
|||||||
l_end = emit_label(as);
|
l_end = emit_label(as);
|
||||||
/* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
|
/* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
|
||||||
asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */
|
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);
|
emit_n(as, ARMI_CMP|ARMI_K12|0, RID_RET);
|
||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
args[1] = ASMREF_TMP2; /* MSize steps */
|
args[1] = ASMREF_TMP2; /* MSize steps */
|
||||||
@@ -2101,7 +2118,7 @@ static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
|
|||||||
rset_clear(allow, ra_dest(as, ir, allow));
|
rset_clear(allow, ra_dest(as, ir, allow));
|
||||||
} else {
|
} else {
|
||||||
Reg r = irp->r;
|
Reg r = irp->r;
|
||||||
lua_assert(ra_hasreg(r));
|
lj_assertA(ra_hasreg(r), "base reg lost");
|
||||||
rset_clear(allow, r);
|
rset_clear(allow, r);
|
||||||
if (r != ir->r && !rset_test(as->freeset, r))
|
if (r != ir->r && !rset_test(as->freeset, r))
|
||||||
ra_restore(as, regcost_ref(as->cost[r]));
|
ra_restore(as, regcost_ref(as->cost[r]));
|
||||||
@@ -2123,7 +2140,7 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk)
|
|||||||
} else {
|
} else {
|
||||||
/* Patch stack adjustment. */
|
/* Patch stack adjustment. */
|
||||||
uint32_t k = emit_isk12(ARMI_ADD, spadj);
|
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);
|
p[-2] = (ARMI_ADD^k) | ARMF_D(RID_SP) | ARMF_N(RID_SP);
|
||||||
}
|
}
|
||||||
/* Patch exit branch. */
|
/* Patch exit branch. */
|
||||||
@@ -2199,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. */
|
/* Look for bl_cc exitstub, replace with b_cc target. */
|
||||||
uint32_t ins = *p;
|
uint32_t ins = *p;
|
||||||
if ((ins & 0x0f000000u) == 0x0b000000u && ins < 0xf0000000u &&
|
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);
|
*p = (ins & 0xfe000000u) | (((target-p)-2) & 0x00ffffffu);
|
||||||
cend = p+1;
|
cend = p+1;
|
||||||
if (!cstart) cstart = p;
|
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_sync(cstart, cend);
|
||||||
lj_mcode_patch(J, mcarea, 1);
|
lj_mcode_patch(J, mcarea, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** ARM64 IR assembler (SSA IR -> machine code).
|
** ARM64 IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
|
** Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
|
||||||
** Sponsored by Cisco Systems, Inc.
|
** Sponsored by Cisco Systems, Inc.
|
||||||
@@ -213,7 +213,7 @@ static uint32_t asm_fuseopm(ASMState *as, A64Ins ai, IRRef ref, RegSet allow)
|
|||||||
return A64F_M(ir->r);
|
return A64F_M(ir->r);
|
||||||
} else if (irref_isk(ref)) {
|
} else if (irref_isk(ref)) {
|
||||||
uint32_t m;
|
uint32_t m;
|
||||||
int64_t k = get_k64val(ir);
|
int64_t k = get_k64val(as, ref);
|
||||||
if ((ai & 0x1f000000) == 0x0a000000)
|
if ((ai & 0x1f000000) == 0x0a000000)
|
||||||
m = emit_isk13(k, irt_is64(ir->t));
|
m = emit_isk13(k, irt_is64(ir->t));
|
||||||
else
|
else
|
||||||
@@ -354,9 +354,9 @@ static int asm_fusemadd(ASMState *as, IRIns *ir, A64Ins ai, A64Ins air)
|
|||||||
static int asm_fuseandshift(ASMState *as, IRIns *ir)
|
static int asm_fuseandshift(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
IRIns *irl = IR(ir->op1);
|
IRIns *irl = IR(ir->op1);
|
||||||
lua_assert(ir->o == IR_BAND);
|
lj_assertA(ir->o == IR_BAND, "bad usage");
|
||||||
if (canfuse(as, irl) && irref_isk(ir->op2)) {
|
if (canfuse(as, irl) && irref_isk(ir->op2)) {
|
||||||
uint64_t mask = get_k64val(IR(ir->op2));
|
uint64_t mask = get_k64val(as, ir->op2);
|
||||||
if (irref_isk(irl->op2) && (irl->o == IR_BSHR || irl->o == IR_BSHL)) {
|
if (irref_isk(irl->op2) && (irl->o == IR_BSHR || irl->o == IR_BSHL)) {
|
||||||
int32_t shmask = irt_is64(irl->t) ? 63 : 31;
|
int32_t shmask = irt_is64(irl->t) ? 63 : 31;
|
||||||
int32_t shift = (IR(irl->op2)->i & shmask);
|
int32_t shift = (IR(irl->op2)->i & shmask);
|
||||||
@@ -384,7 +384,7 @@ static int asm_fuseandshift(ASMState *as, IRIns *ir)
|
|||||||
static int asm_fuseorshift(ASMState *as, IRIns *ir)
|
static int asm_fuseorshift(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
IRIns *irl = IR(ir->op1), *irr = IR(ir->op2);
|
IRIns *irl = IR(ir->op1), *irr = IR(ir->op2);
|
||||||
lua_assert(ir->o == IR_BOR);
|
lj_assertA(ir->o == IR_BOR, "bad usage");
|
||||||
if (canfuse(as, irl) && canfuse(as, irr) &&
|
if (canfuse(as, irl) && canfuse(as, irr) &&
|
||||||
((irl->o == IR_BSHR && irr->o == IR_BSHL) ||
|
((irl->o == IR_BSHR && irr->o == IR_BSHL) ||
|
||||||
(irl->o == IR_BSHL && irr->o == IR_BSHR))) {
|
(irl->o == IR_BSHL && irr->o == IR_BSHR))) {
|
||||||
@@ -428,7 +428,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
if (ref) {
|
if (ref) {
|
||||||
if (irt_isfp(ir->t)) {
|
if (irt_isfp(ir->t)) {
|
||||||
if (fpr <= REGARG_LASTFPR) {
|
if (fpr <= REGARG_LASTFPR) {
|
||||||
lua_assert(rset_test(as->freeset, fpr)); /* Must have been evicted. */
|
lj_assertA(rset_test(as->freeset, fpr),
|
||||||
|
"reg %d not free", fpr); /* Must have been evicted. */
|
||||||
ra_leftov(as, fpr, ref);
|
ra_leftov(as, fpr, ref);
|
||||||
fpr++;
|
fpr++;
|
||||||
} else {
|
} else {
|
||||||
@@ -438,7 +439,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (gpr <= REGARG_LASTGPR) {
|
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. */
|
||||||
ra_leftov(as, gpr, ref);
|
ra_leftov(as, gpr, ref);
|
||||||
gpr++;
|
gpr++;
|
||||||
} else {
|
} else {
|
||||||
@@ -459,7 +461,7 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
|||||||
rset_clear(drop, ir->r); /* Dest reg handled below. */
|
rset_clear(drop, ir->r); /* Dest reg handled below. */
|
||||||
ra_evictset(as, drop); /* Evictions must be performed first. */
|
ra_evictset(as, drop); /* Evictions must be performed first. */
|
||||||
if (ra_used(ir)) {
|
if (ra_used(ir)) {
|
||||||
lua_assert(!irt_ispri(ir->t));
|
lj_assertA(!irt_ispri(ir->t), "PRI dest");
|
||||||
if (irt_isfp(ir->t)) {
|
if (irt_isfp(ir->t)) {
|
||||||
if (ci->flags & CCI_CASTU64) {
|
if (ci->flags & CCI_CASTU64) {
|
||||||
Reg dest = ra_dest(as, ir, RSET_FPR) & 31;
|
Reg dest = ra_dest(as, ir, RSET_FPR) & 31;
|
||||||
@@ -546,7 +548,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
int st64 = (st == IRT_I64 || st == IRT_U64 || st == IRT_P64);
|
int st64 = (st == IRT_I64 || st == IRT_U64 || st == IRT_P64);
|
||||||
int stfp = (st == IRT_NUM || st == IRT_FLOAT);
|
int stfp = (st == IRT_NUM || st == IRT_FLOAT);
|
||||||
IRRef lref = ir->op1;
|
IRRef lref = ir->op1;
|
||||||
lua_assert(irt_type(ir->t) != st);
|
lj_assertA(irt_type(ir->t) != st, "inconsistent types for CONV");
|
||||||
if (irt_isfp(ir->t)) {
|
if (irt_isfp(ir->t)) {
|
||||||
Reg dest = ra_dest(as, ir, RSET_FPR);
|
Reg dest = ra_dest(as, ir, RSET_FPR);
|
||||||
if (stfp) { /* FP to FP conversion. */
|
if (stfp) { /* FP to FP conversion. */
|
||||||
@@ -566,7 +568,8 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
} else if (stfp) { /* FP to integer conversion. */
|
} else if (stfp) { /* FP to integer conversion. */
|
||||||
if (irt_isguard(ir->t)) {
|
if (irt_isguard(ir->t)) {
|
||||||
/* Checked conversions are only supported from number to int. */
|
/* 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));
|
asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
|
||||||
} else {
|
} else {
|
||||||
Reg left = ra_alloc1(as, lref, RSET_FPR);
|
Reg left = ra_alloc1(as, lref, RSET_FPR);
|
||||||
@@ -586,7 +589,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
A64Ins ai = st == IRT_I8 ? A64I_SXTBw :
|
A64Ins ai = st == IRT_I8 ? A64I_SXTBw :
|
||||||
st == IRT_U8 ? A64I_UXTBw :
|
st == IRT_U8 ? A64I_UXTBw :
|
||||||
st == IRT_I16 ? A64I_SXTHw : A64I_UXTHw;
|
st == IRT_I16 ? A64I_SXTHw : A64I_UXTHw;
|
||||||
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");
|
||||||
emit_dn(as, ai, dest, left);
|
emit_dn(as, ai, dest, left);
|
||||||
} else {
|
} else {
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
@@ -650,7 +653,8 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
|
|||||||
{
|
{
|
||||||
RegSet allow = rset_exclude(RSET_GPR, base);
|
RegSet allow = rset_exclude(RSET_GPR, base);
|
||||||
IRIns *ir = IR(ref);
|
IRIns *ir = IR(ref);
|
||||||
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),
|
||||||
|
"store of IR type %d", irt_type(ir->t));
|
||||||
if (irref_isk(ref)) {
|
if (irref_isk(ref)) {
|
||||||
TValue k;
|
TValue k;
|
||||||
lj_ir_kvalue(as->J->L, &k, ir);
|
lj_ir_kvalue(as->J->L, &k, ir);
|
||||||
@@ -770,7 +774,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
}
|
}
|
||||||
rset_clear(allow, scr);
|
rset_clear(allow, scr);
|
||||||
} else {
|
} else {
|
||||||
lua_assert(irt_ispri(kt) && !irt_isnil(kt));
|
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
|
||||||
type = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow);
|
type = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow);
|
||||||
scr = ra_scratch(as, rset_clear(allow, type));
|
scr = ra_scratch(as, rset_clear(allow, type));
|
||||||
rset_clear(allow, scr);
|
rset_clear(allow, scr);
|
||||||
@@ -831,7 +835,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
rset_clear(allow, type);
|
rset_clear(allow, type);
|
||||||
}
|
}
|
||||||
/* Load main position relative to tab->node into dest. */
|
/* Load main position relative to tab->node into dest. */
|
||||||
khash = isk ? ir_khash(irkey) : 1;
|
khash = isk ? ir_khash(as, irkey) : 1;
|
||||||
if (khash == 0) {
|
if (khash == 0) {
|
||||||
emit_lso(as, A64I_LDRx, dest, tab, offsetof(GCtab, node));
|
emit_lso(as, A64I_LDRx, dest, tab, offsetof(GCtab, node));
|
||||||
} else {
|
} else {
|
||||||
@@ -843,9 +847,9 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
emit_dnm(as, A64I_ANDw, dest, dest, tmphash);
|
emit_dnm(as, A64I_ANDw, dest, dest, tmphash);
|
||||||
emit_lso(as, A64I_LDRw, dest, tab, offsetof(GCtab, hmask));
|
emit_lso(as, A64I_LDRw, dest, tab, offsetof(GCtab, hmask));
|
||||||
} else if (irt_isstr(kt)) {
|
} else if (irt_isstr(kt)) {
|
||||||
/* Fetch of str->hash is cheaper than ra_allock. */
|
/* Fetch of str->sid is cheaper than ra_allock. */
|
||||||
emit_dnm(as, A64I_ANDw, dest, dest, tmp);
|
emit_dnm(as, A64I_ANDw, dest, dest, tmp);
|
||||||
emit_lso(as, A64I_LDRw, tmp, key, offsetof(GCstr, hash));
|
emit_lso(as, A64I_LDRw, tmp, key, offsetof(GCstr, sid));
|
||||||
emit_lso(as, A64I_LDRw, dest, tab, offsetof(GCtab, hmask));
|
emit_lso(as, A64I_LDRw, dest, tab, offsetof(GCtab, hmask));
|
||||||
} else { /* Must match with hash*() in lj_tab.c. */
|
} else { /* Must match with hash*() in lj_tab.c. */
|
||||||
emit_dnm(as, A64I_ANDw, dest, dest, tmp);
|
emit_dnm(as, A64I_ANDw, dest, dest, tmp);
|
||||||
@@ -886,7 +890,7 @@ static void asm_hrefk(ASMState *as, IRIns *ir)
|
|||||||
Reg key, idx = node;
|
Reg key, idx = node;
|
||||||
RegSet allow = rset_exclude(RSET_GPR, node);
|
RegSet allow = rset_exclude(RSET_GPR, node);
|
||||||
uint64_t k;
|
uint64_t k;
|
||||||
lua_assert(ofs % sizeof(Node) == 0);
|
lj_assertA(ofs % sizeof(Node) == 0, "unaligned HREFK slot");
|
||||||
if (bigofs) {
|
if (bigofs) {
|
||||||
idx = dest;
|
idx = dest;
|
||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
@@ -936,7 +940,7 @@ static void asm_uref(ASMState *as, IRIns *ir)
|
|||||||
static void asm_fref(ASMState *as, IRIns *ir)
|
static void asm_fref(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
UNUSED(as); UNUSED(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)
|
static void asm_strref(ASMState *as, IRIns *ir)
|
||||||
@@ -988,7 +992,7 @@ static void asm_fload(ASMState *as, IRIns *ir)
|
|||||||
Reg idx;
|
Reg idx;
|
||||||
A64Ins ai = asm_fxloadins(ir);
|
A64Ins ai = asm_fxloadins(ir);
|
||||||
int32_t ofs;
|
int32_t ofs;
|
||||||
if (ir->op1 == REF_NIL) {
|
if (ir->op1 == REF_NIL) { /* FLOAD from GG_State with offset. */
|
||||||
idx = RID_GL;
|
idx = RID_GL;
|
||||||
ofs = (ir->op2 << 2) - GG_OFS(g);
|
ofs = (ir->op2 << 2) - GG_OFS(g);
|
||||||
} else {
|
} else {
|
||||||
@@ -1019,7 +1023,7 @@ static void asm_fstore(ASMState *as, IRIns *ir)
|
|||||||
static void asm_xload(ASMState *as, IRIns *ir)
|
static void asm_xload(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
Reg dest = ra_dest(as, ir, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR);
|
Reg dest = ra_dest(as, ir, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR);
|
||||||
lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED));
|
lj_assertA(!(ir->op2 & IRXLOAD_UNALIGNED), "unaligned XLOAD");
|
||||||
asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR);
|
asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1037,8 +1041,9 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
Reg idx, tmp, type;
|
Reg idx, tmp, type;
|
||||||
int32_t ofs = 0;
|
int32_t ofs = 0;
|
||||||
RegSet gpr = RSET_GPR, allow = irt_isnum(ir->t) ? RSET_FPR : RSET_GPR;
|
RegSet gpr = RSET_GPR, allow = irt_isnum(ir->t) ? RSET_FPR : RSET_GPR;
|
||||||
lua_assert(irt_isnum(ir->t) || irt_ispri(ir->t) || irt_isaddr(ir->t) ||
|
lj_assertA(irt_isnum(ir->t) || irt_ispri(ir->t) || irt_isaddr(ir->t) ||
|
||||||
irt_isint(ir->t));
|
irt_isint(ir->t),
|
||||||
|
"bad load type %d", irt_type(ir->t));
|
||||||
if (ra_used(ir)) {
|
if (ra_used(ir)) {
|
||||||
Reg dest = ra_dest(as, ir, allow);
|
Reg dest = ra_dest(as, ir, allow);
|
||||||
tmp = irt_isnum(ir->t) ? ra_scratch(as, rset_clear(gpr, dest)) : dest;
|
tmp = irt_isnum(ir->t) ? ra_scratch(as, rset_clear(gpr, dest)) : dest;
|
||||||
@@ -1057,7 +1062,8 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
/* Always do the type check, even if the load result is unused. */
|
/* Always do the type check, even if the load result is unused. */
|
||||||
asm_guardcc(as, irt_isnum(ir->t) ? CC_LS : CC_NE);
|
asm_guardcc(as, irt_isnum(ir->t) ? CC_LS : CC_NE);
|
||||||
if (irt_type(ir->t) >= IRT_NUM) {
|
if (irt_type(ir->t) >= IRT_NUM) {
|
||||||
lua_assert(irt_isinteger(ir->t) || irt_isnum(ir->t));
|
lj_assertA(irt_isinteger(ir->t) || irt_isnum(ir->t),
|
||||||
|
"bad load type %d", irt_type(ir->t));
|
||||||
emit_nm(as, A64I_CMPx | A64F_SH(A64SH_LSR, 32),
|
emit_nm(as, A64I_CMPx | A64F_SH(A64SH_LSR, 32),
|
||||||
ra_allock(as, LJ_TISNUM << 15, rset_exclude(gpr, idx)), tmp);
|
ra_allock(as, LJ_TISNUM << 15, rset_exclude(gpr, idx)), tmp);
|
||||||
} else if (irt_isaddr(ir->t)) {
|
} else if (irt_isaddr(ir->t)) {
|
||||||
@@ -1067,7 +1073,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
emit_n(as, (A64I_CMNx^A64I_K12) | A64F_U12(1), tmp);
|
emit_n(as, (A64I_CMNx^A64I_K12) | A64F_U12(1), tmp);
|
||||||
} else {
|
} else {
|
||||||
emit_nm(as, A64I_CMPx | A64F_SH(A64SH_LSR, 32),
|
emit_nm(as, A64I_CMPx | A64F_SH(A64SH_LSR, 32),
|
||||||
ra_allock(as, (irt_toitype(ir->t) << 15) | 0x7fff, allow), tmp);
|
ra_allock(as, (irt_toitype(ir->t) << 15) | 0x7fff, gpr), tmp);
|
||||||
}
|
}
|
||||||
if (ofs & FUSE_REG)
|
if (ofs & FUSE_REG)
|
||||||
emit_dnm(as, (A64I_LDRx^A64I_LS_R)|A64I_LS_UXTWx|A64I_LS_SH, tmp, idx, (ofs & 31));
|
emit_dnm(as, (A64I_LDRx^A64I_LS_R)|A64I_LS_UXTWx|A64I_LS_SH, tmp, idx, (ofs & 31));
|
||||||
@@ -1122,8 +1128,10 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
IRType1 t = ir->t;
|
IRType1 t = ir->t;
|
||||||
Reg dest = RID_NONE, base;
|
Reg dest = RID_NONE, base;
|
||||||
RegSet allow = RSET_GPR;
|
RegSet allow = RSET_GPR;
|
||||||
lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */
|
lj_assertA(!(ir->op2 & IRSLOAD_PARENT),
|
||||||
lua_assert(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK));
|
"bad parent SLOAD"); /* Handled by asm_head_side(). */
|
||||||
|
lj_assertA(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK),
|
||||||
|
"inconsistent SLOAD variant");
|
||||||
if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) {
|
if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) {
|
||||||
dest = ra_scratch(as, RSET_FPR);
|
dest = ra_scratch(as, RSET_FPR);
|
||||||
asm_tointg(as, ir, dest);
|
asm_tointg(as, ir, dest);
|
||||||
@@ -1132,7 +1140,8 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
Reg tmp = RID_NONE;
|
Reg tmp = RID_NONE;
|
||||||
if ((ir->op2 & IRSLOAD_CONVERT))
|
if ((ir->op2 & IRSLOAD_CONVERT))
|
||||||
tmp = ra_scratch(as, irt_isint(t) ? RSET_FPR : RSET_GPR);
|
tmp = ra_scratch(as, irt_isint(t) ? RSET_FPR : RSET_GPR);
|
||||||
lua_assert((irt_isnum(t)) || irt_isint(t) || irt_isaddr(t));
|
lj_assertA((irt_isnum(t)) || irt_isint(t) || irt_isaddr(t),
|
||||||
|
"bad SLOAD type %d", irt_type(t));
|
||||||
dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : allow);
|
dest = ra_dest(as, ir, irt_isnum(t) ? RSET_FPR : allow);
|
||||||
base = ra_alloc1(as, REF_BASE, rset_clear(allow, dest));
|
base = ra_alloc1(as, REF_BASE, rset_clear(allow, dest));
|
||||||
if (irt_isaddr(t)) {
|
if (irt_isaddr(t)) {
|
||||||
@@ -1172,7 +1181,8 @@ dotypecheck:
|
|||||||
/* Need type check, even if the load result is unused. */
|
/* Need type check, even if the load result is unused. */
|
||||||
asm_guardcc(as, irt_isnum(t) ? CC_LS : CC_NE);
|
asm_guardcc(as, irt_isnum(t) ? CC_LS : CC_NE);
|
||||||
if (irt_type(t) >= IRT_NUM) {
|
if (irt_type(t) >= IRT_NUM) {
|
||||||
lua_assert(irt_isinteger(t) || irt_isnum(t));
|
lj_assertA(irt_isinteger(t) || irt_isnum(t),
|
||||||
|
"bad SLOAD type %d", irt_type(t));
|
||||||
emit_nm(as, A64I_CMPx | A64F_SH(A64SH_LSR, 32),
|
emit_nm(as, A64I_CMPx | A64F_SH(A64SH_LSR, 32),
|
||||||
ra_allock(as, LJ_TISNUM << 15, allow), tmp);
|
ra_allock(as, LJ_TISNUM << 15, allow), tmp);
|
||||||
} else if (irt_isnil(t)) {
|
} else if (irt_isnil(t)) {
|
||||||
@@ -1207,7 +1217,8 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
|
||||||
IRRef args[4];
|
IRRef args[4];
|
||||||
RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
|
RegSet allow = (RSET_GPR & ~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++;
|
as->gcsteps++;
|
||||||
asm_setupresult(as, ir, ci); /* GCcdata * */
|
asm_setupresult(as, ir, ci); /* GCcdata * */
|
||||||
@@ -1215,7 +1226,7 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
if (ir->o == IR_CNEWI) {
|
if (ir->o == IR_CNEWI) {
|
||||||
int32_t ofs = sizeof(GCcdata);
|
int32_t ofs = sizeof(GCcdata);
|
||||||
Reg r = ra_alloc1(as, ir->op2, allow);
|
Reg r = ra_alloc1(as, ir->op2, allow);
|
||||||
lua_assert(sz == 4 || sz == 8);
|
lj_assertA(sz == 4 || sz == 8, "bad CNEWI size %d", sz);
|
||||||
emit_lso(as, sz == 8 ? A64I_STRx : A64I_STRw, r, RID_RET, ofs);
|
emit_lso(as, sz == 8 ? A64I_STRx : A64I_STRw, r, RID_RET, ofs);
|
||||||
} else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
|
} else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
|
||||||
ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
|
ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
|
||||||
@@ -1242,8 +1253,6 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
|
ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
|
||||||
ra_releasetmp(as, ASMREF_TMP1));
|
ra_releasetmp(as, ASMREF_TMP1));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define asm_cnew(as, ir) ((void)0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -- Write barriers ------------------------------------------------------ */
|
/* -- Write barriers ------------------------------------------------------ */
|
||||||
@@ -1276,7 +1285,7 @@ static void asm_obar(ASMState *as, IRIns *ir)
|
|||||||
RegSet allow = RSET_GPR;
|
RegSet allow = RSET_GPR;
|
||||||
Reg obj, val, tmp;
|
Reg obj, val, tmp;
|
||||||
/* No need for other object barriers (yet). */
|
/* 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);
|
ra_evictset(as, RSET_SCRATCH);
|
||||||
l_end = emit_label(as);
|
l_end = emit_label(as);
|
||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
@@ -1320,8 +1329,6 @@ static void asm_fpmath(ASMState *as, IRIns *ir)
|
|||||||
} else if (fpm <= IRFPM_TRUNC) {
|
} else if (fpm <= IRFPM_TRUNC) {
|
||||||
asm_fpunary(as, ir, fpm == IRFPM_FLOOR ? A64I_FRINTMd :
|
asm_fpunary(as, ir, fpm == IRFPM_FLOOR ? A64I_FRINTMd :
|
||||||
fpm == IRFPM_CEIL ? A64I_FRINTPd : A64I_FRINTZd);
|
fpm == IRFPM_CEIL ? A64I_FRINTPd : A64I_FRINTZd);
|
||||||
} else if (fpm == IRFPM_EXP2 && asm_fpjoin_pow(as, ir)) {
|
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
asm_callid(as, ir, IRCALL_lj_vm_floor + fpm);
|
asm_callid(as, ir, IRCALL_lj_vm_floor + fpm);
|
||||||
}
|
}
|
||||||
@@ -1428,46 +1435,12 @@ static void asm_mul(ASMState *as, IRIns *ir)
|
|||||||
asm_intmul(as, ir);
|
asm_intmul(as, ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_div(ASMState *as, IRIns *ir)
|
|
||||||
{
|
|
||||||
#if 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_fparith(as, ir, A64I_FDIVd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void asm_pow(ASMState *as, IRIns *ir)
|
|
||||||
{
|
|
||||||
#if 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
|
|
||||||
asm_callid(as, ir, IRCALL_lj_vm_powi);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define asm_addov(as, ir) asm_add(as, ir)
|
#define asm_addov(as, ir) asm_add(as, ir)
|
||||||
#define asm_subov(as, ir) asm_sub(as, ir)
|
#define asm_subov(as, ir) asm_sub(as, ir)
|
||||||
#define asm_mulov(as, ir) asm_mul(as, ir)
|
#define asm_mulov(as, ir) asm_mul(as, ir)
|
||||||
|
|
||||||
|
#define asm_fpdiv(as, ir) asm_fparith(as, ir, A64I_FDIVd)
|
||||||
#define asm_abs(as, ir) asm_fpunary(as, ir, A64I_FABS)
|
#define asm_abs(as, ir) asm_fpunary(as, ir, A64I_FABS)
|
||||||
#define asm_atan2(as, ir) asm_callid(as, ir, IRCALL_atan2)
|
|
||||||
#define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp)
|
|
||||||
|
|
||||||
static void asm_mod(ASMState *as, IRIns *ir)
|
|
||||||
{
|
|
||||||
#if 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_neg(ASMState *as, IRIns *ir)
|
static void asm_neg(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
@@ -1582,7 +1555,7 @@ static void asm_bitshift(ASMState *as, IRIns *ir, A64Ins ai, A64Shift sh)
|
|||||||
#define asm_bshr(as, ir) asm_bitshift(as, ir, A64I_UBFMw, A64SH_LSR)
|
#define asm_bshr(as, ir) asm_bitshift(as, ir, A64I_UBFMw, A64SH_LSR)
|
||||||
#define asm_bsar(as, ir) asm_bitshift(as, ir, A64I_SBFMw, A64SH_ASR)
|
#define asm_bsar(as, ir) asm_bitshift(as, ir, A64I_SBFMw, A64SH_ASR)
|
||||||
#define asm_bror(as, ir) asm_bitshift(as, ir, A64I_EXTRw, A64SH_ROR)
|
#define asm_bror(as, ir) asm_bitshift(as, ir, A64I_EXTRw, A64SH_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, A64CC cc)
|
static void asm_intmin_max(ASMState *as, IRIns *ir, A64CC cc)
|
||||||
{
|
{
|
||||||
@@ -1598,7 +1571,7 @@ static void asm_fpmin_max(ASMState *as, IRIns *ir, A64CC fcc)
|
|||||||
Reg dest = (ra_dest(as, ir, RSET_FPR) & 31);
|
Reg dest = (ra_dest(as, ir, RSET_FPR) & 31);
|
||||||
Reg right, left = ra_alloc2(as, ir, RSET_FPR);
|
Reg right, left = ra_alloc2(as, ir, RSET_FPR);
|
||||||
right = ((left >> 8) & 31); left &= 31;
|
right = ((left >> 8) & 31); left &= 31;
|
||||||
emit_dnm(as, A64I_FCSELd | A64F_CC(fcc), dest, left, right);
|
emit_dnm(as, A64I_FCSELd | A64F_CC(fcc), dest, right, left);
|
||||||
emit_nm(as, A64I_FCMPd, left, right);
|
emit_nm(as, A64I_FCMPd, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1610,8 +1583,8 @@ static void asm_min_max(ASMState *as, IRIns *ir, A64CC cc, A64CC fcc)
|
|||||||
asm_intmin_max(as, ir, cc);
|
asm_intmin_max(as, ir, cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define asm_max(as, ir) asm_min_max(as, ir, CC_GT, CC_HI)
|
#define asm_min(as, ir) asm_min_max(as, ir, CC_LT, CC_PL)
|
||||||
#define asm_min(as, ir) asm_min_max(as, ir, CC_LT, CC_LO)
|
#define asm_max(as, ir) asm_min_max(as, ir, CC_GT, CC_LE)
|
||||||
|
|
||||||
/* -- Comparisons --------------------------------------------------------- */
|
/* -- Comparisons --------------------------------------------------------- */
|
||||||
|
|
||||||
@@ -1663,15 +1636,16 @@ static void asm_intcomp(ASMState *as, IRIns *ir)
|
|||||||
Reg left;
|
Reg left;
|
||||||
uint32_t m;
|
uint32_t m;
|
||||||
int cmpprev0 = 0;
|
int cmpprev0 = 0;
|
||||||
lua_assert(irt_is64(ir->t) || irt_isint(ir->t) ||
|
lj_assertA(irt_is64(ir->t) || irt_isint(ir->t) ||
|
||||||
irt_isu32(ir->t) || irt_isaddr(ir->t) || irt_isu8(ir->t));
|
irt_isu32(ir->t) || irt_isaddr(ir->t) || irt_isu8(ir->t),
|
||||||
|
"bad comparison data type %d", irt_type(ir->t));
|
||||||
if (asm_swapops(as, lref, rref)) {
|
if (asm_swapops(as, lref, rref)) {
|
||||||
IRRef tmp = lref; lref = rref; rref = tmp;
|
IRRef tmp = lref; lref = rref; rref = tmp;
|
||||||
if (cc >= CC_GE) cc ^= 7; /* LT <-> GT, LE <-> GE */
|
if (cc >= CC_GE) cc ^= 7; /* LT <-> GT, LE <-> GE */
|
||||||
else if (cc > CC_NE) cc ^= 11; /* LO <-> HI, LS <-> HS */
|
else if (cc > CC_NE) cc ^= 11; /* LO <-> HI, LS <-> HS */
|
||||||
}
|
}
|
||||||
oldcc = cc;
|
oldcc = cc;
|
||||||
if (irref_isk(rref) && get_k64val(IR(rref)) == 0) {
|
if (irref_isk(rref) && get_k64val(as, rref) == 0) {
|
||||||
IRIns *irl = IR(lref);
|
IRIns *irl = IR(lref);
|
||||||
if (cc == CC_GE) cc = CC_PL;
|
if (cc == CC_GE) cc = CC_PL;
|
||||||
else if (cc == CC_LT) cc = CC_MI;
|
else if (cc == CC_LT) cc = CC_MI;
|
||||||
@@ -1686,7 +1660,7 @@ static void asm_intcomp(ASMState *as, IRIns *ir)
|
|||||||
Reg tmp = blref; blref = brref; brref = tmp;
|
Reg tmp = blref; blref = brref; brref = tmp;
|
||||||
}
|
}
|
||||||
if (irref_isk(brref)) {
|
if (irref_isk(brref)) {
|
||||||
uint64_t k = get_k64val(IR(brref));
|
uint64_t k = get_k64val(as, brref);
|
||||||
if (k && !(k & (k-1)) && (cc == CC_EQ || cc == CC_NE)) {
|
if (k && !(k & (k-1)) && (cc == CC_EQ || cc == CC_NE)) {
|
||||||
asm_guardtnb(as, cc == CC_EQ ? A64I_TBZ : A64I_TBNZ,
|
asm_guardtnb(as, cc == CC_EQ ? A64I_TBZ : A64I_TBNZ,
|
||||||
ra_alloc1(as, blref, RSET_GPR), emit_ctz64(k));
|
ra_alloc1(as, blref, RSET_GPR), emit_ctz64(k));
|
||||||
@@ -1735,7 +1709,8 @@ static void asm_comp(ASMState *as, IRIns *ir)
|
|||||||
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */
|
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */
|
||||||
static void asm_hiop(ASMState *as, IRIns *ir)
|
static void asm_hiop(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
UNUSED(as); UNUSED(ir); lua_assert(0); /* Unused on 64 bit. */
|
UNUSED(as); UNUSED(ir);
|
||||||
|
lj_assertA(0, "unexpected HIOP"); /* Unused on 64 bit. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Profiling ----------------------------------------------------------- */
|
/* -- Profiling ----------------------------------------------------------- */
|
||||||
@@ -1743,7 +1718,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
static void asm_prof(ASMState *as, IRIns *ir)
|
static void asm_prof(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
uint32_t k = emit_isk13(HOOK_PROFILE, 0);
|
uint32_t k = emit_isk13(HOOK_PROFILE, 0);
|
||||||
lua_assert(k != 0);
|
lj_assertA(k != 0, "HOOK_PROFILE does not fit in K13");
|
||||||
UNUSED(ir);
|
UNUSED(ir);
|
||||||
asm_guardcc(as, CC_NE);
|
asm_guardcc(as, CC_NE);
|
||||||
emit_n(as, A64I_TSTw^k, RID_TMP);
|
emit_n(as, A64I_TSTw^k, RID_TMP);
|
||||||
@@ -1761,7 +1736,7 @@ static void asm_stack_check(ASMState *as, BCReg topslot,
|
|||||||
if (irp) {
|
if (irp) {
|
||||||
if (!ra_hasspill(irp->s)) {
|
if (!ra_hasspill(irp->s)) {
|
||||||
pbase = irp->r;
|
pbase = irp->r;
|
||||||
lua_assert(ra_hasreg(pbase));
|
lj_assertA(ra_hasreg(pbase), "base reg lost");
|
||||||
} else if (allow) {
|
} else if (allow) {
|
||||||
pbase = rset_pickbot(allow);
|
pbase = rset_pickbot(allow);
|
||||||
} else {
|
} else {
|
||||||
@@ -1773,7 +1748,7 @@ static void asm_stack_check(ASMState *as, BCReg topslot,
|
|||||||
}
|
}
|
||||||
emit_cond_branch(as, CC_LS, asm_exitstub_addr(as, exitno));
|
emit_cond_branch(as, CC_LS, asm_exitstub_addr(as, exitno));
|
||||||
k = emit_isk12((8*topslot));
|
k = emit_isk12((8*topslot));
|
||||||
lua_assert(k);
|
lj_assertA(k, "slot offset %d does not fit in K12", 8*topslot);
|
||||||
emit_n(as, A64I_CMPx^k, RID_TMP);
|
emit_n(as, A64I_CMPx^k, RID_TMP);
|
||||||
emit_dnm(as, A64I_SUBx, RID_TMP, RID_TMP, pbase);
|
emit_dnm(as, A64I_SUBx, RID_TMP, RID_TMP, pbase);
|
||||||
emit_lso(as, A64I_LDRx, RID_TMP, RID_TMP,
|
emit_lso(as, A64I_LDRx, RID_TMP, RID_TMP,
|
||||||
@@ -1814,11 +1789,15 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
}
|
}
|
||||||
checkmclim(as);
|
checkmclim(as);
|
||||||
}
|
}
|
||||||
lua_assert(map + nent == flinks);
|
lj_assertA(map + nent == flinks, "inconsistent frames in snapshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- GC handling --------------------------------------------------------- */
|
/* -- GC handling --------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Marker to prevent patching the GC check exit. */
|
||||||
|
#define ARM64_NOPATCH_GC_CHECK \
|
||||||
|
(A64I_ORRx|A64F_D(RID_TMP)|A64F_M(RID_TMP)|A64F_N(RID_TMP))
|
||||||
|
|
||||||
/* Check GC threshold and do one or more GC steps. */
|
/* Check GC threshold and do one or more GC steps. */
|
||||||
static void asm_gc_check(ASMState *as)
|
static void asm_gc_check(ASMState *as)
|
||||||
{
|
{
|
||||||
@@ -1830,6 +1809,7 @@ static void asm_gc_check(ASMState *as)
|
|||||||
l_end = emit_label(as);
|
l_end = emit_label(as);
|
||||||
/* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
|
/* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
|
||||||
asm_guardcnb(as, A64I_CBNZ, RID_RET); /* Assumes asm_snap_prep() is done. */
|
asm_guardcnb(as, A64I_CBNZ, RID_RET); /* Assumes asm_snap_prep() is done. */
|
||||||
|
*--as->mcp = ARM64_NOPATCH_GC_CHECK;
|
||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
args[1] = ASMREF_TMP2; /* MSize steps */
|
args[1] = ASMREF_TMP2; /* MSize steps */
|
||||||
asm_gencall(as, ci, args);
|
asm_gencall(as, ci, args);
|
||||||
@@ -1902,7 +1882,7 @@ static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
|
|||||||
rset_clear(allow, ra_dest(as, ir, allow));
|
rset_clear(allow, ra_dest(as, ir, allow));
|
||||||
} else {
|
} else {
|
||||||
Reg r = irp->r;
|
Reg r = irp->r;
|
||||||
lua_assert(ra_hasreg(r));
|
lj_assertA(ra_hasreg(r), "base reg lost");
|
||||||
rset_clear(allow, r);
|
rset_clear(allow, r);
|
||||||
if (r != ir->r && !rset_test(as->freeset, r))
|
if (r != ir->r && !rset_test(as->freeset, r))
|
||||||
ra_restore(as, regcost_ref(as->cost[r]));
|
ra_restore(as, regcost_ref(as->cost[r]));
|
||||||
@@ -1926,7 +1906,7 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk)
|
|||||||
} else {
|
} else {
|
||||||
/* Patch stack adjustment. */
|
/* Patch stack adjustment. */
|
||||||
uint32_t k = emit_isk12(spadj);
|
uint32_t k = emit_isk12(spadj);
|
||||||
lua_assert(k);
|
lj_assertA(k, "stack adjustment %d does not fit in K12", spadj);
|
||||||
p[-2] = (A64I_ADDx^k) | A64F_D(RID_SP) | A64F_N(RID_SP);
|
p[-2] = (A64I_ADDx^k) | A64F_D(RID_SP) | A64F_N(RID_SP);
|
||||||
}
|
}
|
||||||
/* Patch exit branch. */
|
/* Patch exit branch. */
|
||||||
@@ -1997,6 +1977,7 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
|||||||
MCode *cstart = NULL;
|
MCode *cstart = NULL;
|
||||||
MCode *mcarea = lj_mcode_patch(J, p, 0);
|
MCode *mcarea = lj_mcode_patch(J, p, 0);
|
||||||
MCode *px = exitstub_trace_addr(T, exitno);
|
MCode *px = exitstub_trace_addr(T, exitno);
|
||||||
|
int patchlong = 1;
|
||||||
/* Note: this assumes a trace exit is only ever patched once. */
|
/* Note: this assumes a trace exit is only ever patched once. */
|
||||||
for (; p < pe; p++) {
|
for (; p < pe; p++) {
|
||||||
/* Look for exitstub branch, replace with branch to target. */
|
/* Look for exitstub branch, replace with branch to target. */
|
||||||
@@ -2012,13 +1993,15 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
|||||||
} else if ((ins & 0xfc000000u) == 0x14000000u &&
|
} else if ((ins & 0xfc000000u) == 0x14000000u &&
|
||||||
((ins ^ (px-p)) & 0x03ffffffu) == 0) {
|
((ins ^ (px-p)) & 0x03ffffffu) == 0) {
|
||||||
/* Patch b. */
|
/* Patch b. */
|
||||||
lua_assert(A64F_S_OK(delta, 26));
|
lj_assertJ(A64F_S_OK(delta, 26), "branch target out of range");
|
||||||
*p = A64I_LE((ins & 0xfc000000u) | A64F_S26(delta));
|
*p = A64I_LE((ins & 0xfc000000u) | A64F_S26(delta));
|
||||||
if (!cstart) cstart = p;
|
if (!cstart) cstart = p;
|
||||||
} else if ((ins & 0x7e000000u) == 0x34000000u &&
|
} else if ((ins & 0x7e000000u) == 0x34000000u &&
|
||||||
((ins ^ ((px-p)<<5)) & 0x00ffffe0u) == 0) {
|
((ins ^ ((px-p)<<5)) & 0x00ffffe0u) == 0) {
|
||||||
/* Patch cbz/cbnz, if within range. */
|
/* Patch cbz/cbnz, if within range. */
|
||||||
if (A64F_S_OK(delta, 19)) {
|
if (p[-1] == ARM64_NOPATCH_GC_CHECK) {
|
||||||
|
patchlong = 0;
|
||||||
|
} else if (A64F_S_OK(delta, 19)) {
|
||||||
*p = A64I_LE((ins & 0xff00001fu) | A64F_S19(delta));
|
*p = A64I_LE((ins & 0xff00001fu) | A64F_S19(delta));
|
||||||
if (!cstart) cstart = p;
|
if (!cstart) cstart = p;
|
||||||
}
|
}
|
||||||
@@ -2031,13 +2014,14 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ /* Always patch long-range branch in exit stub itself. */
|
/* Always patch long-range branch in exit stub itself. Except, if we can't. */
|
||||||
|
if (patchlong) {
|
||||||
ptrdiff_t delta = target - px;
|
ptrdiff_t delta = target - px;
|
||||||
lua_assert(A64F_S_OK(delta, 26));
|
lj_assertJ(A64F_S_OK(delta, 26), "branch target out of range");
|
||||||
*px = A64I_B | A64F_S26(delta);
|
*px = A64I_B | A64F_S26(delta);
|
||||||
if (!cstart) cstart = px;
|
if (!cstart) cstart = px;
|
||||||
}
|
}
|
||||||
lj_mcode_sync(cstart, px+1);
|
if (cstart) lj_mcode_sync(cstart, px+1);
|
||||||
lj_mcode_patch(J, mcarea, 1);
|
lj_mcode_patch(J, mcarea, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+198
-118
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** MIPS IR assembler (SSA IR -> machine code).
|
** MIPS IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* -- Register allocator extensions --------------------------------------- */
|
/* -- Register allocator extensions --------------------------------------- */
|
||||||
@@ -23,7 +23,7 @@ static Reg ra_alloc1z(ASMState *as, IRRef ref, RegSet allow)
|
|||||||
{
|
{
|
||||||
Reg r = IR(ref)->r;
|
Reg r = IR(ref)->r;
|
||||||
if (ra_noreg(r)) {
|
if (ra_noreg(r)) {
|
||||||
if (!(allow & RSET_FPR) && irref_isk(ref) && get_kval(IR(ref)) == 0)
|
if (!(allow & RSET_FPR) && irref_isk(ref) && get_kval(as, ref) == 0)
|
||||||
return RID_ZERO;
|
return RID_ZERO;
|
||||||
r = ra_allocref(as, ref, allow);
|
r = ra_allocref(as, ref, allow);
|
||||||
} else {
|
} else {
|
||||||
@@ -66,10 +66,10 @@ static void asm_sparejump_setup(ASMState *as)
|
|||||||
{
|
{
|
||||||
MCode *mxp = as->mcbot;
|
MCode *mxp = as->mcbot;
|
||||||
if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == sizeof(MCLink)) {
|
if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == sizeof(MCLink)) {
|
||||||
lua_assert(MIPSI_NOP == 0);
|
lj_assertA(MIPSI_NOP == 0, "bad NOP");
|
||||||
memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode));
|
memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode));
|
||||||
mxp += MIPS_SPAREJUMP*2;
|
mxp += MIPS_SPAREJUMP*2;
|
||||||
lua_assert(mxp < as->mctop);
|
lj_assertA(mxp < as->mctop, "MIPS_SPAREJUMP too big");
|
||||||
lj_mcode_sync(as->mcbot, mxp);
|
lj_mcode_sync(as->mcbot, mxp);
|
||||||
lj_mcode_commitbot(as->J, mxp);
|
lj_mcode_commitbot(as->J, mxp);
|
||||||
as->mcbot = mxp;
|
as->mcbot = mxp;
|
||||||
@@ -84,7 +84,8 @@ static void asm_exitstub_setup(ASMState *as)
|
|||||||
/* sw TMP, 0(sp); j ->vm_exit_handler; li TMP, traceno */
|
/* sw TMP, 0(sp); j ->vm_exit_handler; li TMP, traceno */
|
||||||
*--mxp = MIPSI_LI|MIPSF_T(RID_TMP)|as->T->traceno;
|
*--mxp = MIPSI_LI|MIPSF_T(RID_TMP)|as->T->traceno;
|
||||||
*--mxp = MIPSI_J|((((uintptr_t)(void *)lj_vm_exit_handler)>>2)&0x03ffffffu);
|
*--mxp = MIPSI_J|((((uintptr_t)(void *)lj_vm_exit_handler)>>2)&0x03ffffffu);
|
||||||
lua_assert(((uintptr_t)mxp ^ (uintptr_t)(void *)lj_vm_exit_handler)>>28 == 0);
|
lj_assertA(((uintptr_t)mxp ^ (uintptr_t)(void *)lj_vm_exit_handler)>>28 == 0,
|
||||||
|
"branch target out of range");
|
||||||
*--mxp = MIPSI_SW|MIPSF_T(RID_TMP)|MIPSF_S(RID_SP)|0;
|
*--mxp = MIPSI_SW|MIPSF_T(RID_TMP)|MIPSF_S(RID_SP)|0;
|
||||||
as->mctop = mxp;
|
as->mctop = mxp;
|
||||||
}
|
}
|
||||||
@@ -101,7 +102,12 @@ static void asm_guard(ASMState *as, MIPSIns mi, Reg rs, Reg rt)
|
|||||||
as->invmcp = NULL;
|
as->invmcp = NULL;
|
||||||
as->loopinv = 1;
|
as->loopinv = 1;
|
||||||
as->mcp = p+1;
|
as->mcp = p+1;
|
||||||
|
#if !LJ_TARGET_MIPSR6
|
||||||
mi = mi ^ ((mi>>28) == 1 ? 0x04000000u : 0x00010000u); /* Invert cond. */
|
mi = mi ^ ((mi>>28) == 1 ? 0x04000000u : 0x00010000u); /* Invert cond. */
|
||||||
|
#else
|
||||||
|
mi = mi ^ ((mi>>28) == 1 ? 0x04000000u :
|
||||||
|
(mi>>28) == 4 ? 0x00800000u : 0x00010000u); /* Invert cond. */
|
||||||
|
#endif
|
||||||
target = p; /* Patch target later in asm_loop_fixup. */
|
target = p; /* Patch target later in asm_loop_fixup. */
|
||||||
}
|
}
|
||||||
emit_ti(as, MIPSI_LI, RID_TMP, as->snapno);
|
emit_ti(as, MIPSI_LI, RID_TMP, as->snapno);
|
||||||
@@ -190,20 +196,20 @@ static void asm_fusexref(ASMState *as, MIPSIns mi, Reg rt, IRRef ref,
|
|||||||
if (ra_noreg(ir->r) && canfuse(as, ir)) {
|
if (ra_noreg(ir->r) && canfuse(as, ir)) {
|
||||||
if (ir->o == IR_ADD) {
|
if (ir->o == IR_ADD) {
|
||||||
intptr_t ofs2;
|
intptr_t ofs2;
|
||||||
if (irref_isk(ir->op2) && (ofs2 = ofs + get_kval(IR(ir->op2)),
|
if (irref_isk(ir->op2) && (ofs2 = ofs + get_kval(as, ir->op2),
|
||||||
checki16(ofs2))) {
|
checki16(ofs2))) {
|
||||||
ref = ir->op1;
|
ref = ir->op1;
|
||||||
ofs = (int32_t)ofs2;
|
ofs = (int32_t)ofs2;
|
||||||
}
|
}
|
||||||
} else if (ir->o == IR_STRREF) {
|
} else if (ir->o == IR_STRREF) {
|
||||||
intptr_t ofs2 = 65536;
|
intptr_t ofs2 = 65536;
|
||||||
lua_assert(ofs == 0);
|
lj_assertA(ofs == 0, "bad usage");
|
||||||
ofs = (int32_t)sizeof(GCstr);
|
ofs = (int32_t)sizeof(GCstr);
|
||||||
if (irref_isk(ir->op2)) {
|
if (irref_isk(ir->op2)) {
|
||||||
ofs2 = ofs + get_kval(IR(ir->op2));
|
ofs2 = ofs + get_kval(as, ir->op2);
|
||||||
ref = ir->op1;
|
ref = ir->op1;
|
||||||
} else if (irref_isk(ir->op1)) {
|
} else if (irref_isk(ir->op1)) {
|
||||||
ofs2 = ofs + get_kval(IR(ir->op1));
|
ofs2 = ofs + get_kval(as, ir->op1);
|
||||||
ref = ir->op2;
|
ref = ir->op2;
|
||||||
}
|
}
|
||||||
if (!checki16(ofs2)) {
|
if (!checki16(ofs2)) {
|
||||||
@@ -247,7 +253,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
if (irt_isfp(ir->t) && fpr <= REGARG_LASTFPR &&
|
if (irt_isfp(ir->t) && fpr <= REGARG_LASTFPR &&
|
||||||
!(ci->flags & CCI_VARARG)) {
|
!(ci->flags & CCI_VARARG)) {
|
||||||
lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */
|
lj_assertA(rset_test(as->freeset, fpr),
|
||||||
|
"reg %d not free", fpr); /* Already evicted. */
|
||||||
ra_leftov(as, fpr, ref);
|
ra_leftov(as, fpr, ref);
|
||||||
fpr += LJ_32 ? 2 : 1;
|
fpr += LJ_32 ? 2 : 1;
|
||||||
gpr += (LJ_32 && irt_isnum(ir->t)) ? 2 : 1;
|
gpr += (LJ_32 && irt_isnum(ir->t)) ? 2 : 1;
|
||||||
@@ -259,7 +266,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
#endif
|
#endif
|
||||||
if (LJ_32 && irt_isnum(ir->t)) gpr = (gpr+1) & ~1;
|
if (LJ_32 && irt_isnum(ir->t)) gpr = (gpr+1) & ~1;
|
||||||
if (gpr <= REGARG_LASTGPR) {
|
if (gpr <= REGARG_LASTGPR) {
|
||||||
lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */
|
lj_assertA(rset_test(as->freeset, gpr),
|
||||||
|
"reg %d not free", gpr); /* Already evicted. */
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
if (irt_isfp(ir->t)) {
|
if (irt_isfp(ir->t)) {
|
||||||
RegSet of = as->freeset;
|
RegSet of = as->freeset;
|
||||||
@@ -272,7 +280,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
#if LJ_32
|
#if LJ_32
|
||||||
emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?0:1), r+1);
|
emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?0:1), r+1);
|
||||||
emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?1:0), r);
|
emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?1:0), r);
|
||||||
lua_assert(rset_test(as->freeset, gpr+1)); /* Already evicted. */
|
lj_assertA(rset_test(as->freeset, gpr+1),
|
||||||
|
"reg %d not free", gpr+1); /* Already evicted. */
|
||||||
gpr += 2;
|
gpr += 2;
|
||||||
#else
|
#else
|
||||||
emit_tg(as, MIPSI_DMFC1, gpr, r);
|
emit_tg(as, MIPSI_DMFC1, gpr, r);
|
||||||
@@ -342,7 +351,7 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
|||||||
#endif
|
#endif
|
||||||
ra_evictset(as, drop); /* Evictions must be performed first. */
|
ra_evictset(as, drop); /* Evictions must be performed first. */
|
||||||
if (ra_used(ir)) {
|
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_SOFTFP && irt_isfp(ir->t)) {
|
||||||
if ((ci->flags & CCI_CASTU64)) {
|
if ((ci->flags & CCI_CASTU64)) {
|
||||||
int32_t ofs = sps_scale(ir->s);
|
int32_t ofs = sps_scale(ir->s);
|
||||||
@@ -390,7 +399,7 @@ static void asm_callx(ASMState *as, IRIns *ir)
|
|||||||
func = ir->op2; irf = IR(func);
|
func = ir->op2; irf = IR(func);
|
||||||
if (irf->o == IR_CARG) { func = irf->op1; irf = IR(func); }
|
if (irf->o == IR_CARG) { func = irf->op1; irf = IR(func); }
|
||||||
if (irref_isk(func)) { /* Call to constant address. */
|
if (irref_isk(func)) { /* Call to constant address. */
|
||||||
ci.func = (ASMFunction)(void *)get_kval(irf);
|
ci.func = (ASMFunction)(void *)get_kval(as, func);
|
||||||
} else { /* Need specific register for indirect calls. */
|
} else { /* Need specific register for indirect calls. */
|
||||||
Reg r = ra_alloc1(as, func, RID2RSET(RID_CFUNCADDR));
|
Reg r = ra_alloc1(as, func, RID2RSET(RID_CFUNCADDR));
|
||||||
MCode *p = as->mcp;
|
MCode *p = as->mcp;
|
||||||
@@ -410,7 +419,11 @@ static void asm_callround(ASMState *as, IRIns *ir, IRCallID id)
|
|||||||
{
|
{
|
||||||
/* The modified regs must match with the *.dasc implementation. */
|
/* The modified regs must match with the *.dasc implementation. */
|
||||||
RegSet drop = RID2RSET(RID_R1)|RID2RSET(RID_R12)|RID2RSET(RID_FPRET)|
|
RegSet drop = RID2RSET(RID_R1)|RID2RSET(RID_R12)|RID2RSET(RID_FPRET)|
|
||||||
RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(REGARG_FIRSTFPR);
|
RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(REGARG_FIRSTFPR)
|
||||||
|
#if LJ_TARGET_MIPSR6
|
||||||
|
|RID2RSET(RID_F21)
|
||||||
|
#endif
|
||||||
|
;
|
||||||
if (ra_hasreg(ir->r)) rset_clear(drop, ir->r);
|
if (ra_hasreg(ir->r)) rset_clear(drop, ir->r);
|
||||||
ra_evictset(as, drop);
|
ra_evictset(as, drop);
|
||||||
ra_destreg(as, ir, RID_FPRET);
|
ra_destreg(as, ir, RID_FPRET);
|
||||||
@@ -444,8 +457,13 @@ static void asm_tointg(ASMState *as, IRIns *ir, Reg left)
|
|||||||
{
|
{
|
||||||
Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left));
|
Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left));
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
|
#if !LJ_TARGET_MIPSR6
|
||||||
asm_guard(as, MIPSI_BC1F, 0, 0);
|
asm_guard(as, MIPSI_BC1F, 0, 0);
|
||||||
emit_fgh(as, MIPSI_C_EQ_D, 0, tmp, left);
|
emit_fgh(as, MIPSI_C_EQ_D, 0, tmp, left);
|
||||||
|
#else
|
||||||
|
asm_guard(as, MIPSI_BC1EQZ, 0, (tmp&31));
|
||||||
|
emit_fgh(as, MIPSI_CMP_EQ_D, tmp, tmp, left);
|
||||||
|
#endif
|
||||||
emit_fg(as, MIPSI_CVT_D_W, tmp, tmp);
|
emit_fg(as, MIPSI_CVT_D_W, tmp, tmp);
|
||||||
emit_tg(as, MIPSI_MFC1, dest, tmp);
|
emit_tg(as, MIPSI_MFC1, dest, tmp);
|
||||||
emit_fg(as, MIPSI_CVT_W_D, tmp, left);
|
emit_fg(as, MIPSI_CVT_W_D, tmp, left);
|
||||||
@@ -498,15 +516,19 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
#endif
|
#endif
|
||||||
IRRef lref = ir->op1;
|
IRRef lref = ir->op1;
|
||||||
#if LJ_32
|
#if LJ_32
|
||||||
lua_assert(!(irt_isint64(ir->t) ||
|
/* 64 bit integer conversions are handled by SPLIT. */
|
||||||
(st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */
|
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);
|
||||||
#endif
|
#endif
|
||||||
#if LJ_SOFTFP32
|
#if LJ_SOFTFP32
|
||||||
/* FP conversions are handled by SPLIT. */
|
/* 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. */
|
/* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. */
|
||||||
#else
|
#else
|
||||||
lua_assert(irt_type(ir->t) != st);
|
lj_assertA(irt_type(ir->t) != st, "inconsistent types for CONV");
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
if (irt_isfp(ir->t)) {
|
if (irt_isfp(ir->t)) {
|
||||||
Reg dest = ra_dest(as, ir, RSET_FPR);
|
Reg dest = ra_dest(as, ir, RSET_FPR);
|
||||||
@@ -565,7 +587,8 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
} else if (stfp) { /* FP to integer conversion. */
|
} else if (stfp) { /* FP to integer conversion. */
|
||||||
if (irt_isguard(ir->t)) {
|
if (irt_isguard(ir->t)) {
|
||||||
/* Checked conversions are only supported from number to int. */
|
/* 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));
|
asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
|
||||||
} else {
|
} else {
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
@@ -599,8 +622,13 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
(void *)&as->J->k64[LJ_K64_M2P64],
|
(void *)&as->J->k64[LJ_K64_M2P64],
|
||||||
rset_exclude(RSET_GPR, dest));
|
rset_exclude(RSET_GPR, dest));
|
||||||
emit_fg(as, MIPSI_TRUNC_L_D, tmp, left); /* Delay slot. */
|
emit_fg(as, MIPSI_TRUNC_L_D, tmp, left); /* Delay slot. */
|
||||||
emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
|
#if !LJ_TARGET_MIPSR6
|
||||||
emit_fgh(as, MIPSI_C_OLT_D, 0, left, tmp);
|
emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
|
||||||
|
emit_fgh(as, MIPSI_C_OLT_D, 0, left, tmp);
|
||||||
|
#else
|
||||||
|
emit_branch(as, MIPSI_BC1NEZ, 0, (left&31), l_end);
|
||||||
|
emit_fgh(as, MIPSI_CMP_LT_D, left, left, tmp);
|
||||||
|
#endif
|
||||||
emit_lsptr(as, MIPSI_LDC1, (tmp & 31),
|
emit_lsptr(as, MIPSI_LDC1, (tmp & 31),
|
||||||
(void *)&as->J->k64[LJ_K64_2P63],
|
(void *)&as->J->k64[LJ_K64_2P63],
|
||||||
rset_exclude(RSET_GPR, dest));
|
rset_exclude(RSET_GPR, dest));
|
||||||
@@ -611,8 +639,13 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
(void *)&as->J->k32[LJ_K32_M2P64],
|
(void *)&as->J->k32[LJ_K32_M2P64],
|
||||||
rset_exclude(RSET_GPR, dest));
|
rset_exclude(RSET_GPR, dest));
|
||||||
emit_fg(as, MIPSI_TRUNC_L_S, tmp, left); /* Delay slot. */
|
emit_fg(as, MIPSI_TRUNC_L_S, tmp, left); /* Delay slot. */
|
||||||
emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
|
#if !LJ_TARGET_MIPSR6
|
||||||
emit_fgh(as, MIPSI_C_OLT_S, 0, left, tmp);
|
emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
|
||||||
|
emit_fgh(as, MIPSI_C_OLT_S, 0, left, tmp);
|
||||||
|
#else
|
||||||
|
emit_branch(as, MIPSI_BC1NEZ, 0, (left&31), l_end);
|
||||||
|
emit_fgh(as, MIPSI_CMP_LT_S, left, left, tmp);
|
||||||
|
#endif
|
||||||
emit_lsptr(as, MIPSI_LWC1, (tmp & 31),
|
emit_lsptr(as, MIPSI_LWC1, (tmp & 31),
|
||||||
(void *)&as->J->k32[LJ_K32_2P63],
|
(void *)&as->J->k32[LJ_K32_2P63],
|
||||||
rset_exclude(RSET_GPR, dest));
|
rset_exclude(RSET_GPR, dest));
|
||||||
@@ -655,7 +688,8 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
} else if (stfp) { /* FP to integer conversion. */
|
} else if (stfp) { /* FP to integer conversion. */
|
||||||
if (irt_isguard(ir->t)) {
|
if (irt_isguard(ir->t)) {
|
||||||
/* Checked conversions are only supported from number to int. */
|
/* 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, RID_NONE);
|
asm_tointg(as, ir, RID_NONE);
|
||||||
} else {
|
} else {
|
||||||
IRCallID cid = irt_is64(ir->t) ?
|
IRCallID cid = irt_is64(ir->t) ?
|
||||||
@@ -674,7 +708,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */
|
if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */
|
||||||
Reg left = ra_alloc1(as, ir->op1, RSET_GPR);
|
Reg left = ra_alloc1(as, ir->op1, 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 ((ir->op2 & IRCONV_SEXT)) {
|
if ((ir->op2 & IRCONV_SEXT)) {
|
||||||
if (LJ_64 || (as->flags & JIT_F_MIPSXXR2)) {
|
if (LJ_64 || (as->flags & JIT_F_MIPSXXR2)) {
|
||||||
emit_dst(as, st == IRT_I8 ? MIPSI_SEB : MIPSI_SEH, dest, 0, left);
|
emit_dst(as, st == IRT_I8 ? MIPSI_SEB : MIPSI_SEH, dest, 0, left);
|
||||||
@@ -771,7 +805,8 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
|
|||||||
{
|
{
|
||||||
RegSet allow = rset_exclude(RSET_GPR, base);
|
RegSet allow = rset_exclude(RSET_GPR, base);
|
||||||
IRIns *ir = IR(ref);
|
IRIns *ir = IR(ref);
|
||||||
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),
|
||||||
|
"store of IR type %d", irt_type(ir->t));
|
||||||
if (irref_isk(ref)) {
|
if (irref_isk(ref)) {
|
||||||
TValue k;
|
TValue k;
|
||||||
lj_ir_kvalue(as->J->L, &k, ir);
|
lj_ir_kvalue(as->J->L, &k, ir);
|
||||||
@@ -840,8 +875,12 @@ static void asm_aref(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
base = ra_alloc1(as, ir->op1, RSET_GPR);
|
base = ra_alloc1(as, ir->op1, RSET_GPR);
|
||||||
idx = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, base));
|
idx = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, base));
|
||||||
|
#if !LJ_TARGET_MIPSR6
|
||||||
emit_dst(as, MIPSI_AADDU, dest, RID_TMP, base);
|
emit_dst(as, MIPSI_AADDU, dest, RID_TMP, base);
|
||||||
emit_dta(as, MIPSI_SLL, RID_TMP, idx, 3);
|
emit_dta(as, MIPSI_SLL, RID_TMP, idx, 3);
|
||||||
|
#else
|
||||||
|
emit_dst(as, MIPSI_ALSA | MIPSF_A(3-1), dest, idx, base);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inlined hash lookup. Specialized for key type and for const keys.
|
/* Inlined hash lookup. Specialized for key type and for const keys.
|
||||||
@@ -916,7 +955,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
if (isk && irt_isaddr(kt)) {
|
if (isk && irt_isaddr(kt)) {
|
||||||
k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64;
|
k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64;
|
||||||
} else {
|
} else {
|
||||||
lua_assert(irt_ispri(kt) && !irt_isnil(kt));
|
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
|
||||||
k = ~((int64_t)~irt_toitype(ir->t) << 47);
|
k = ~((int64_t)~irt_toitype(ir->t) << 47);
|
||||||
}
|
}
|
||||||
cmp64 = ra_allock(as, k, allow);
|
cmp64 = ra_allock(as, k, allow);
|
||||||
@@ -944,8 +983,13 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
l_end = asm_exitstub_addr(as);
|
l_end = asm_exitstub_addr(as);
|
||||||
}
|
}
|
||||||
if (!LJ_SOFTFP && irt_isnum(kt)) {
|
if (!LJ_SOFTFP && irt_isnum(kt)) {
|
||||||
|
#if !LJ_TARGET_MIPSR6
|
||||||
emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
|
emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
|
||||||
emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key);
|
emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key);
|
||||||
|
#else
|
||||||
|
emit_branch(as, MIPSI_BC1NEZ, 0, (tmpnum&31), l_end);
|
||||||
|
emit_fgh(as, MIPSI_CMP_EQ_D, tmpnum, tmpnum, key);
|
||||||
|
#endif
|
||||||
*--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */
|
*--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */
|
||||||
emit_branch(as, MIPSI_BEQ, tmp1, RID_ZERO, l_next);
|
emit_branch(as, MIPSI_BEQ, tmp1, RID_ZERO, l_next);
|
||||||
emit_tsi(as, MIPSI_SLTIU, tmp1, tmp1, (int32_t)LJ_TISNUM);
|
emit_tsi(as, MIPSI_SLTIU, tmp1, tmp1, (int32_t)LJ_TISNUM);
|
||||||
@@ -979,7 +1023,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Load main position relative to tab->node into dest. */
|
/* Load main position relative to tab->node into dest. */
|
||||||
khash = isk ? ir_khash(irkey) : 1;
|
khash = isk ? ir_khash(as, irkey) : 1;
|
||||||
if (khash == 0) {
|
if (khash == 0) {
|
||||||
emit_tsi(as, MIPSI_AL, dest, tab, (int32_t)offsetof(GCtab, node));
|
emit_tsi(as, MIPSI_AL, dest, tab, (int32_t)offsetof(GCtab, node));
|
||||||
} else {
|
} else {
|
||||||
@@ -987,7 +1031,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
if (isk)
|
if (isk)
|
||||||
tmphash = ra_allock(as, khash, allow);
|
tmphash = ra_allock(as, khash, allow);
|
||||||
emit_dst(as, MIPSI_AADDU, dest, dest, tmp1);
|
emit_dst(as, MIPSI_AADDU, dest, dest, tmp1);
|
||||||
lua_assert(sizeof(Node) == 24);
|
lj_assertA(sizeof(Node) == 24, "bad Node size");
|
||||||
emit_dst(as, MIPSI_SUBU, tmp1, tmp2, tmp1);
|
emit_dst(as, MIPSI_SUBU, tmp1, tmp2, tmp1);
|
||||||
emit_dta(as, MIPSI_SLL, tmp1, tmp1, 3);
|
emit_dta(as, MIPSI_SLL, tmp1, tmp1, 3);
|
||||||
emit_dta(as, MIPSI_SLL, tmp2, tmp1, 5);
|
emit_dta(as, MIPSI_SLL, tmp2, tmp1, 5);
|
||||||
@@ -997,7 +1041,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
if (isk) {
|
if (isk) {
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
} else if (irt_isstr(kt)) {
|
} else if (irt_isstr(kt)) {
|
||||||
emit_tsi(as, MIPSI_LW, tmp1, key, (int32_t)offsetof(GCstr, hash));
|
emit_tsi(as, MIPSI_LW, tmp1, key, (int32_t)offsetof(GCstr, sid));
|
||||||
} else { /* Must match with hash*() in lj_tab.c. */
|
} else { /* Must match with hash*() in lj_tab.c. */
|
||||||
emit_dst(as, MIPSI_SUBU, tmp1, tmp1, tmp2);
|
emit_dst(as, MIPSI_SUBU, tmp1, tmp1, tmp2);
|
||||||
emit_rotr(as, tmp2, tmp2, dest, (-HASH_ROT3)&31);
|
emit_rotr(as, tmp2, tmp2, dest, (-HASH_ROT3)&31);
|
||||||
@@ -1065,7 +1109,7 @@ static void asm_hrefk(ASMState *as, IRIns *ir)
|
|||||||
Reg key = ra_scratch(as, allow);
|
Reg key = ra_scratch(as, allow);
|
||||||
int64_t k;
|
int64_t k;
|
||||||
#endif
|
#endif
|
||||||
lua_assert(ofs % sizeof(Node) == 0);
|
lj_assertA(ofs % sizeof(Node) == 0, "unaligned HREFK slot");
|
||||||
if (ofs > 32736) {
|
if (ofs > 32736) {
|
||||||
idx = dest;
|
idx = dest;
|
||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
@@ -1094,7 +1138,7 @@ nolo:
|
|||||||
emit_tsi(as, MIPSI_LW, type, idx, kofs+(LJ_BE?0:4));
|
emit_tsi(as, MIPSI_LW, type, idx, kofs+(LJ_BE?0:4));
|
||||||
#else
|
#else
|
||||||
if (irt_ispri(irkey->t)) {
|
if (irt_ispri(irkey->t)) {
|
||||||
lua_assert(!irt_isnil(irkey->t));
|
lj_assertA(!irt_isnil(irkey->t), "bad HREFK key type");
|
||||||
k = ~((int64_t)~irt_toitype(irkey->t) << 47);
|
k = ~((int64_t)~irt_toitype(irkey->t) << 47);
|
||||||
} else if (irt_isnum(irkey->t)) {
|
} else if (irt_isnum(irkey->t)) {
|
||||||
k = (int64_t)ir_knum(irkey)->u64;
|
k = (int64_t)ir_knum(irkey)->u64;
|
||||||
@@ -1133,7 +1177,7 @@ static void asm_uref(ASMState *as, IRIns *ir)
|
|||||||
static void asm_fref(ASMState *as, IRIns *ir)
|
static void asm_fref(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
UNUSED(as); UNUSED(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)
|
static void asm_strref(ASMState *as, IRIns *ir)
|
||||||
@@ -1188,26 +1232,36 @@ static void asm_strref(ASMState *as, IRIns *ir)
|
|||||||
|
|
||||||
/* -- Loads and stores ---------------------------------------------------- */
|
/* -- Loads and stores ---------------------------------------------------- */
|
||||||
|
|
||||||
static MIPSIns asm_fxloadins(IRIns *ir)
|
static MIPSIns asm_fxloadins(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
|
UNUSED(as);
|
||||||
switch (irt_type(ir->t)) {
|
switch (irt_type(ir->t)) {
|
||||||
case IRT_I8: return MIPSI_LB;
|
case IRT_I8: return MIPSI_LB;
|
||||||
case IRT_U8: return MIPSI_LBU;
|
case IRT_U8: return MIPSI_LBU;
|
||||||
case IRT_I16: return MIPSI_LH;
|
case IRT_I16: return MIPSI_LH;
|
||||||
case IRT_U16: return MIPSI_LHU;
|
case IRT_U16: return MIPSI_LHU;
|
||||||
case IRT_NUM: lua_assert(!LJ_SOFTFP32); if (!LJ_SOFTFP) return MIPSI_LDC1;
|
case IRT_NUM:
|
||||||
|
lj_assertA(!LJ_SOFTFP32, "unsplit FP op");
|
||||||
|
if (!LJ_SOFTFP) return MIPSI_LDC1;
|
||||||
|
/* fallthrough */
|
||||||
case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_LWC1;
|
case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_LWC1;
|
||||||
|
/* fallthrough */
|
||||||
default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_LD : MIPSI_LW;
|
default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_LD : MIPSI_LW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static MIPSIns asm_fxstoreins(IRIns *ir)
|
static MIPSIns asm_fxstoreins(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
|
UNUSED(as);
|
||||||
switch (irt_type(ir->t)) {
|
switch (irt_type(ir->t)) {
|
||||||
case IRT_I8: case IRT_U8: return MIPSI_SB;
|
case IRT_I8: case IRT_U8: return MIPSI_SB;
|
||||||
case IRT_I16: case IRT_U16: return MIPSI_SH;
|
case IRT_I16: case IRT_U16: return MIPSI_SH;
|
||||||
case IRT_NUM: lua_assert(!LJ_SOFTFP32); if (!LJ_SOFTFP) return MIPSI_SDC1;
|
case IRT_NUM:
|
||||||
|
lj_assertA(!LJ_SOFTFP32, "unsplit FP op");
|
||||||
|
if (!LJ_SOFTFP) return MIPSI_SDC1;
|
||||||
|
/* fallthrough */
|
||||||
case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_SWC1;
|
case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_SWC1;
|
||||||
|
/* fallthrough */
|
||||||
default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_SD : MIPSI_SW;
|
default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_SD : MIPSI_SW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1215,10 +1269,10 @@ static MIPSIns asm_fxstoreins(IRIns *ir)
|
|||||||
static void asm_fload(ASMState *as, IRIns *ir)
|
static void asm_fload(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
MIPSIns mi = asm_fxloadins(ir);
|
MIPSIns mi = asm_fxloadins(as, ir);
|
||||||
Reg idx;
|
Reg idx;
|
||||||
int32_t ofs;
|
int32_t ofs;
|
||||||
if (ir->op1 == REF_NIL) {
|
if (ir->op1 == REF_NIL) { /* FLOAD from GG_State with offset. */
|
||||||
idx = RID_JGL;
|
idx = RID_JGL;
|
||||||
ofs = (ir->op2 << 2) - 32768 - GG_OFS(g);
|
ofs = (ir->op2 << 2) - 32768 - GG_OFS(g);
|
||||||
} else {
|
} else {
|
||||||
@@ -1232,7 +1286,7 @@ static void asm_fload(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
ofs = field_ofs[ir->op2];
|
ofs = field_ofs[ir->op2];
|
||||||
}
|
}
|
||||||
lua_assert(!irt_isfp(ir->t));
|
lj_assertA(!irt_isfp(ir->t), "bad FP FLOAD");
|
||||||
emit_tsi(as, mi, dest, idx, ofs);
|
emit_tsi(as, mi, dest, idx, ofs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1243,8 +1297,8 @@ static void asm_fstore(ASMState *as, IRIns *ir)
|
|||||||
IRIns *irf = IR(ir->op1);
|
IRIns *irf = IR(ir->op1);
|
||||||
Reg idx = ra_alloc1(as, irf->op1, rset_exclude(RSET_GPR, src));
|
Reg idx = ra_alloc1(as, irf->op1, rset_exclude(RSET_GPR, src));
|
||||||
int32_t ofs = field_ofs[irf->op2];
|
int32_t ofs = field_ofs[irf->op2];
|
||||||
MIPSIns mi = asm_fxstoreins(ir);
|
MIPSIns mi = asm_fxstoreins(as, ir);
|
||||||
lua_assert(!irt_isfp(ir->t));
|
lj_assertA(!irt_isfp(ir->t), "bad FP FSTORE");
|
||||||
emit_tsi(as, mi, src, idx, ofs);
|
emit_tsi(as, mi, src, idx, ofs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1253,8 +1307,9 @@ static void asm_xload(ASMState *as, IRIns *ir)
|
|||||||
{
|
{
|
||||||
Reg dest = ra_dest(as, ir,
|
Reg dest = ra_dest(as, ir,
|
||||||
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
||||||
lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED));
|
lj_assertA(LJ_TARGET_UNALIGNED || !(ir->op2 & IRXLOAD_UNALIGNED),
|
||||||
asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0);
|
"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)
|
static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
|
||||||
@@ -1262,7 +1317,7 @@ static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
|
|||||||
if (ir->r != RID_SINK) {
|
if (ir->r != RID_SINK) {
|
||||||
Reg src = ra_alloc1z(as, ir->op2,
|
Reg src = ra_alloc1z(as, ir->op2,
|
||||||
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
(!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);
|
rset_exclude(RSET_GPR, src), ofs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1284,8 +1339,9 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ra_used(ir)) {
|
if (ra_used(ir)) {
|
||||||
lua_assert((LJ_SOFTFP32 ? 0 : irt_isnum(ir->t)) ||
|
lj_assertA((LJ_SOFTFP32 ? 0 : irt_isnum(ir->t)) ||
|
||||||
irt_isint(ir->t) || irt_isaddr(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 && irt_isnum(t)) ? RSET_FPR : allow);
|
dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow);
|
||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
#if LJ_64
|
#if LJ_64
|
||||||
@@ -1390,10 +1446,13 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
#else
|
#else
|
||||||
int32_t ofs = 8*((int32_t)ir->op1-2);
|
int32_t ofs = 8*((int32_t)ir->op1-2);
|
||||||
#endif
|
#endif
|
||||||
lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */
|
lj_assertA(!(ir->op2 & IRSLOAD_PARENT),
|
||||||
lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK));
|
"bad parent SLOAD"); /* Handled by asm_head_side(). */
|
||||||
|
lj_assertA(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK),
|
||||||
|
"inconsistent SLOAD variant");
|
||||||
#if LJ_SOFTFP32
|
#if LJ_SOFTFP32
|
||||||
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)) {
|
if (hiop && ra_used(ir+1)) {
|
||||||
type = ra_dest(as, ir+1, allow);
|
type = ra_dest(as, ir+1, allow);
|
||||||
rset_clear(allow, type);
|
rset_clear(allow, type);
|
||||||
@@ -1406,8 +1465,9 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (ra_used(ir)) {
|
if (ra_used(ir)) {
|
||||||
lua_assert((LJ_SOFTFP32 ? 0 : irt_isnum(ir->t)) ||
|
lj_assertA((LJ_SOFTFP32 ? 0 : irt_isnum(ir->t)) ||
|
||||||
irt_isint(ir->t) || irt_isaddr(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 && irt_isnum(t)) ? RSET_FPR : allow);
|
dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow);
|
||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
base = ra_alloc1(as, REF_BASE, allow);
|
base = ra_alloc1(as, REF_BASE, allow);
|
||||||
@@ -1517,7 +1577,8 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
|
||||||
IRRef args[4];
|
IRRef args[4];
|
||||||
RegSet drop = 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++;
|
as->gcsteps++;
|
||||||
if (ra_hasreg(ir->r))
|
if (ra_hasreg(ir->r))
|
||||||
@@ -1533,7 +1594,7 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
int32_t ofs = sizeof(GCcdata);
|
int32_t ofs = sizeof(GCcdata);
|
||||||
if (sz == 8) {
|
if (sz == 8) {
|
||||||
ofs += 4;
|
ofs += 4;
|
||||||
lua_assert((ir+1)->o == IR_HIOP);
|
lj_assertA((ir+1)->o == IR_HIOP, "expected HIOP for CNEWI");
|
||||||
if (LJ_LE) ir++;
|
if (LJ_LE) ir++;
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -1544,10 +1605,10 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
ofs -= 4; if (LJ_BE) ir++; else ir--;
|
ofs -= 4; if (LJ_BE) ir++; else ir--;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
emit_tsi(as, MIPSI_SD, ra_alloc1(as, ir->op2, allow),
|
emit_tsi(as, sz == 8 ? MIPSI_SD : MIPSI_SW, ra_alloc1(as, ir->op2, allow),
|
||||||
RID_RET, sizeof(GCcdata));
|
RID_RET, sizeof(GCcdata));
|
||||||
#endif
|
#endif
|
||||||
lua_assert(sz == 4 || sz == 8);
|
lj_assertA(sz == 4 || sz == 8, "bad CNEWI size %d", sz);
|
||||||
} else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
|
} else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
|
||||||
ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
|
ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
|
||||||
args[0] = ASMREF_L; /* lua_State *L */
|
args[0] = ASMREF_L; /* lua_State *L */
|
||||||
@@ -1570,8 +1631,6 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
|
ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
|
||||||
ra_releasetmp(as, ASMREF_TMP1));
|
ra_releasetmp(as, ASMREF_TMP1));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define asm_cnew(as, ir) ((void)0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -- Write barriers ------------------------------------------------------ */
|
/* -- Write barriers ------------------------------------------------------ */
|
||||||
@@ -1599,7 +1658,7 @@ static void asm_obar(ASMState *as, IRIns *ir)
|
|||||||
MCLabel l_end;
|
MCLabel l_end;
|
||||||
Reg obj, val, tmp;
|
Reg obj, val, tmp;
|
||||||
/* No need for other object barriers (yet). */
|
/* 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);
|
ra_evictset(as, RSET_SCRATCH);
|
||||||
l_end = emit_label(as);
|
l_end = emit_label(as);
|
||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
@@ -1640,8 +1699,6 @@ static void asm_fpunary(ASMState *as, IRIns *ir, MIPSIns mi)
|
|||||||
#if !LJ_SOFTFP32
|
#if !LJ_SOFTFP32
|
||||||
static void asm_fpmath(ASMState *as, IRIns *ir)
|
static void asm_fpmath(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir))
|
|
||||||
return;
|
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
if (ir->op2 <= IRFPM_TRUNC)
|
if (ir->op2 <= IRFPM_TRUNC)
|
||||||
asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2);
|
asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2);
|
||||||
@@ -1672,10 +1729,11 @@ static void asm_add(ASMState *as, IRIns *ir)
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
/* TODO MIPSR6: Fuse ADD(BSHL(a,1-4),b) or ADD(ADD(a,a),b) to MIPSI_ALSA. */
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
|
Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
|
||||||
if (irref_isk(ir->op2)) {
|
if (irref_isk(ir->op2)) {
|
||||||
intptr_t k = get_kval(IR(ir->op2));
|
intptr_t k = get_kval(as, ir->op2);
|
||||||
if (checki16(k)) {
|
if (checki16(k)) {
|
||||||
emit_tsi(as, (LJ_64 && irt_is64(t)) ? MIPSI_DADDIU : MIPSI_ADDIU, dest,
|
emit_tsi(as, (LJ_64 && irt_is64(t)) ? MIPSI_DADDIU : MIPSI_ADDIU, dest,
|
||||||
left, k);
|
left, k);
|
||||||
@@ -1716,49 +1774,25 @@ static void asm_mul(ASMState *as, IRIns *ir)
|
|||||||
Reg right, left = ra_alloc2(as, ir, RSET_GPR);
|
Reg right, left = ra_alloc2(as, ir, RSET_GPR);
|
||||||
right = (left >> 8); left &= 255;
|
right = (left >> 8); left &= 255;
|
||||||
if (LJ_64 && irt_is64(ir->t)) {
|
if (LJ_64 && irt_is64(ir->t)) {
|
||||||
|
#if !LJ_TARGET_MIPSR6
|
||||||
emit_dst(as, MIPSI_MFLO, dest, 0, 0);
|
emit_dst(as, MIPSI_MFLO, dest, 0, 0);
|
||||||
emit_dst(as, MIPSI_DMULT, 0, left, right);
|
emit_dst(as, MIPSI_DMULT, 0, left, right);
|
||||||
|
#else
|
||||||
|
emit_dst(as, MIPSI_DMUL, dest, left, right);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
emit_dst(as, MIPSI_MUL, dest, left, right);
|
emit_dst(as, MIPSI_MUL, dest, left, right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !LJ_SOFTFP32
|
#if !LJ_SOFTFP32
|
||||||
static void asm_pow(ASMState *as, IRIns *ir)
|
static void asm_fpdiv(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
|
|
||||||
asm_callid(as, ir, IRCALL_lj_vm_powi);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
asm_fparith(as, ir, MIPSI_DIV_D);
|
asm_fparith(as, ir, MIPSI_DIV_D);
|
||||||
#else
|
#else
|
||||||
asm_callid(as, ir, IRCALL_softfp_div);
|
asm_callid(as, ir, IRCALL_softfp_div);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1796,13 +1830,11 @@ static void asm_abs(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define asm_atan2(as, ir) asm_callid(as, ir, IRCALL_atan2)
|
|
||||||
#define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp)
|
|
||||||
|
|
||||||
static void asm_arithov(ASMState *as, IRIns *ir)
|
static void asm_arithov(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
|
/* TODO MIPSR6: bovc/bnvc. Caveat: no delay slot to load RID_TMP. */
|
||||||
Reg right, left, tmp, dest = ra_dest(as, ir, RSET_GPR);
|
Reg right, left, tmp, dest = ra_dest(as, ir, RSET_GPR);
|
||||||
lua_assert(!irt_is64(ir->t));
|
lj_assertA(!irt_is64(ir->t), "bad usage");
|
||||||
if (irref_isk(ir->op2)) {
|
if (irref_isk(ir->op2)) {
|
||||||
int k = IR(ir->op2)->i;
|
int k = IR(ir->op2)->i;
|
||||||
if (ir->o == IR_SUBOV) k = -k;
|
if (ir->o == IR_SUBOV) k = -k;
|
||||||
@@ -1845,9 +1877,14 @@ static void asm_mulov(ASMState *as, IRIns *ir)
|
|||||||
right), dest));
|
right), dest));
|
||||||
asm_guard(as, MIPSI_BNE, RID_TMP, tmp);
|
asm_guard(as, MIPSI_BNE, RID_TMP, tmp);
|
||||||
emit_dta(as, MIPSI_SRA, RID_TMP, dest, 31);
|
emit_dta(as, MIPSI_SRA, RID_TMP, dest, 31);
|
||||||
|
#if !LJ_TARGET_MIPSR6
|
||||||
emit_dst(as, MIPSI_MFHI, tmp, 0, 0);
|
emit_dst(as, MIPSI_MFHI, tmp, 0, 0);
|
||||||
emit_dst(as, MIPSI_MFLO, dest, 0, 0);
|
emit_dst(as, MIPSI_MFLO, dest, 0, 0);
|
||||||
emit_dst(as, MIPSI_MULT, 0, left, right);
|
emit_dst(as, MIPSI_MULT, 0, left, right);
|
||||||
|
#else
|
||||||
|
emit_dst(as, MIPSI_MUL, dest, left, right);
|
||||||
|
emit_dst(as, MIPSI_MUH, tmp, left, right);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LJ_32 && LJ_HASFFI
|
#if LJ_32 && LJ_HASFFI
|
||||||
@@ -1984,7 +2021,7 @@ static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik)
|
|||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
|
Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
|
||||||
if (irref_isk(ir->op2)) {
|
if (irref_isk(ir->op2)) {
|
||||||
intptr_t k = get_kval(IR(ir->op2));
|
intptr_t k = get_kval(as, ir->op2);
|
||||||
if (checku16(k)) {
|
if (checku16(k)) {
|
||||||
emit_tsi(as, mik, dest, left, k);
|
emit_tsi(as, mik, dest, left, k);
|
||||||
return;
|
return;
|
||||||
@@ -2017,7 +2054,7 @@ static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik)
|
|||||||
#define asm_bshl(as, ir) asm_bitshift(as, ir, MIPSI_SLLV, MIPSI_SLL)
|
#define asm_bshl(as, ir) asm_bitshift(as, ir, MIPSI_SLLV, MIPSI_SLL)
|
||||||
#define asm_bshr(as, ir) asm_bitshift(as, ir, MIPSI_SRLV, MIPSI_SRL)
|
#define asm_bshr(as, ir) asm_bitshift(as, ir, MIPSI_SRLV, MIPSI_SRL)
|
||||||
#define asm_bsar(as, ir) asm_bitshift(as, ir, MIPSI_SRAV, MIPSI_SRA)
|
#define asm_bsar(as, ir) asm_bitshift(as, ir, MIPSI_SRAV, MIPSI_SRA)
|
||||||
#define asm_brol(as, ir) lua_assert(0)
|
#define asm_brol(as, ir) lj_assertA(0, "unexpected BROL")
|
||||||
|
|
||||||
static void asm_bror(ASMState *as, IRIns *ir)
|
static void asm_bror(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
@@ -2071,26 +2108,45 @@ static void asm_min_max(ASMState *as, IRIns *ir, int ismax)
|
|||||||
Reg dest = ra_dest(as, ir, RSET_FPR);
|
Reg dest = ra_dest(as, ir, RSET_FPR);
|
||||||
Reg right, left = ra_alloc2(as, ir, RSET_FPR);
|
Reg right, left = ra_alloc2(as, ir, RSET_FPR);
|
||||||
right = (left >> 8); left &= 255;
|
right = (left >> 8); left &= 255;
|
||||||
|
#if !LJ_TARGET_MIPSR6
|
||||||
if (dest == left) {
|
if (dest == left) {
|
||||||
emit_fg(as, MIPSI_MOVT_D, dest, right);
|
emit_fg(as, MIPSI_MOVF_D, dest, right);
|
||||||
} else {
|
} else {
|
||||||
emit_fg(as, MIPSI_MOVF_D, dest, left);
|
emit_fg(as, MIPSI_MOVT_D, dest, left);
|
||||||
if (dest != right) emit_fg(as, MIPSI_MOV_D, dest, right);
|
if (dest != right) emit_fg(as, MIPSI_MOV_D, dest, right);
|
||||||
}
|
}
|
||||||
emit_fgh(as, MIPSI_C_OLT_D, 0, ismax ? left : right, ismax ? right : left);
|
emit_fgh(as, MIPSI_C_OLT_D, 0, ismax ? right : left, ismax ? left : right);
|
||||||
|
#else
|
||||||
|
emit_fgh(as, ismax ? MIPSI_MAX_D : MIPSI_MIN_D, dest, left, right);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
Reg right, left = ra_alloc2(as, ir, RSET_GPR);
|
Reg right, left = ra_alloc2(as, ir, RSET_GPR);
|
||||||
right = (left >> 8); left &= 255;
|
right = (left >> 8); left &= 255;
|
||||||
if (dest == left) {
|
if (left == right) {
|
||||||
emit_dst(as, MIPSI_MOVN, dest, right, RID_TMP);
|
if (dest != left) emit_move(as, dest, left);
|
||||||
} else {
|
} else {
|
||||||
emit_dst(as, MIPSI_MOVZ, dest, left, RID_TMP);
|
#if !LJ_TARGET_MIPSR6
|
||||||
if (dest != right) emit_move(as, dest, right);
|
if (dest == left) {
|
||||||
|
emit_dst(as, MIPSI_MOVN, dest, right, RID_TMP);
|
||||||
|
} else {
|
||||||
|
emit_dst(as, MIPSI_MOVZ, dest, left, RID_TMP);
|
||||||
|
if (dest != right) emit_move(as, dest, right);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
emit_dst(as, MIPSI_OR, dest, dest, RID_TMP);
|
||||||
|
if (dest != right) {
|
||||||
|
emit_dst(as, MIPSI_SELNEZ, RID_TMP, right, RID_TMP);
|
||||||
|
emit_dst(as, MIPSI_SELEQZ, dest, left, RID_TMP);
|
||||||
|
} else {
|
||||||
|
emit_dst(as, MIPSI_SELEQZ, RID_TMP, left, RID_TMP);
|
||||||
|
emit_dst(as, MIPSI_SELNEZ, dest, right, RID_TMP);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
emit_dst(as, MIPSI_SLT, RID_TMP,
|
||||||
|
ismax ? left : right, ismax ? right : left);
|
||||||
}
|
}
|
||||||
emit_dst(as, MIPSI_SLT, RID_TMP,
|
|
||||||
ismax ? left : right, ismax ? right : left);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2174,21 +2230,29 @@ static void asm_comp(ASMState *as, IRIns *ir)
|
|||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
asm_sfpcomp(as, ir);
|
asm_sfpcomp(as, ir);
|
||||||
#else
|
#else
|
||||||
|
#if !LJ_TARGET_MIPSR6
|
||||||
Reg right, left = ra_alloc2(as, ir, RSET_FPR);
|
Reg right, left = ra_alloc2(as, ir, RSET_FPR);
|
||||||
right = (left >> 8); left &= 255;
|
right = (left >> 8); left &= 255;
|
||||||
asm_guard(as, (op&1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
|
asm_guard(as, (op&1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
|
||||||
emit_fgh(as, MIPSI_C_OLT_D + ((op&3) ^ ((op>>2)&1)), 0, left, right);
|
emit_fgh(as, MIPSI_C_OLT_D + ((op&3) ^ ((op>>2)&1)), 0, left, right);
|
||||||
|
#else
|
||||||
|
Reg tmp, right, left = ra_alloc2(as, ir, RSET_FPR);
|
||||||
|
right = (left >> 8); left &= 255;
|
||||||
|
tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_FPR, left), right));
|
||||||
|
asm_guard(as, (op&1) ? MIPSI_BC1NEZ : MIPSI_BC1EQZ, 0, (tmp&31));
|
||||||
|
emit_fgh(as, MIPSI_CMP_LT_D + ((op&3) ^ ((op>>2)&1)), tmp, left, right);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR);
|
Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR);
|
||||||
if (op == IR_ABC) op = IR_UGT;
|
if (op == IR_ABC) op = IR_UGT;
|
||||||
if ((op&4) == 0 && irref_isk(ir->op2) && get_kval(IR(ir->op2)) == 0) {
|
if ((op&4) == 0 && irref_isk(ir->op2) && get_kval(as, ir->op2) == 0) {
|
||||||
MIPSIns mi = (op&2) ? ((op&1) ? MIPSI_BLEZ : MIPSI_BGTZ) :
|
MIPSIns mi = (op&2) ? ((op&1) ? MIPSI_BLEZ : MIPSI_BGTZ) :
|
||||||
((op&1) ? MIPSI_BLTZ : MIPSI_BGEZ);
|
((op&1) ? MIPSI_BLTZ : MIPSI_BGEZ);
|
||||||
asm_guard(as, mi, left, 0);
|
asm_guard(as, mi, left, 0);
|
||||||
} else {
|
} else {
|
||||||
if (irref_isk(ir->op2)) {
|
if (irref_isk(ir->op2)) {
|
||||||
intptr_t k = get_kval(IR(ir->op2));
|
intptr_t k = get_kval(as, ir->op2);
|
||||||
if ((op&2)) k++;
|
if ((op&2)) k++;
|
||||||
if (checki16(k)) {
|
if (checki16(k)) {
|
||||||
asm_guard(as, (op&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO);
|
asm_guard(as, (op&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO);
|
||||||
@@ -2213,9 +2277,13 @@ static void asm_equal(ASMState *as, IRIns *ir)
|
|||||||
if (!LJ_SOFTFP32 && irt_isnum(ir->t)) {
|
if (!LJ_SOFTFP32 && irt_isnum(ir->t)) {
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
asm_sfpcomp(as, ir);
|
asm_sfpcomp(as, ir);
|
||||||
#else
|
#elif !LJ_TARGET_MIPSR6
|
||||||
asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
|
asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
|
||||||
emit_fgh(as, MIPSI_C_EQ_D, 0, left, right);
|
emit_fgh(as, MIPSI_C_EQ_D, 0, left, right);
|
||||||
|
#else
|
||||||
|
Reg tmp = ra_scratch(as, rset_exclude(rset_exclude(RSET_FPR, left), right));
|
||||||
|
asm_guard(as, (ir->o & 1) ? MIPSI_BC1NEZ : MIPSI_BC1EQZ, 0, (tmp&31));
|
||||||
|
emit_fgh(as, MIPSI_CMP_EQ_D, tmp, left, right);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
asm_guard(as, (ir->o & 1) ? MIPSI_BEQ : MIPSI_BNE, left, right);
|
asm_guard(as, (ir->o & 1) ? MIPSI_BEQ : MIPSI_BNE, left, right);
|
||||||
@@ -2340,10 +2408,11 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
case IR_CNEWI:
|
case IR_CNEWI:
|
||||||
/* Nothing to do here. Handled by lo op itself. */
|
/* Nothing to do here. Handled by lo op itself. */
|
||||||
break;
|
break;
|
||||||
default: lua_assert(0); break;
|
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
UNUSED(as); UNUSED(ir); lua_assert(0); /* Unused without FFI. */
|
/* Unused on MIPS64 or without SOFTFP or FFI. */
|
||||||
|
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2412,7 +2481,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
#if LJ_SOFTFP32
|
#if LJ_SOFTFP32
|
||||||
Reg tmp;
|
Reg tmp;
|
||||||
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
|
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
|
||||||
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, allow);
|
tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, allow);
|
||||||
emit_tsi(as, MIPSI_SW, tmp, RID_BASE, ofs+(LJ_BE?4:0));
|
emit_tsi(as, MIPSI_SW, tmp, RID_BASE, ofs+(LJ_BE?4:0));
|
||||||
if (rset_test(as->freeset, tmp+1)) allow = RID2RSET(tmp+1);
|
if (rset_test(as->freeset, tmp+1)) allow = RID2RSET(tmp+1);
|
||||||
@@ -2429,7 +2499,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
#if LJ_32
|
#if LJ_32
|
||||||
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
|
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
|
||||||
Reg type;
|
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)) {
|
if (!irt_ispri(ir->t)) {
|
||||||
Reg src = ra_alloc1(as, ref, allow);
|
Reg src = ra_alloc1(as, ref, allow);
|
||||||
rset_clear(allow, src);
|
rset_clear(allow, src);
|
||||||
@@ -2452,11 +2523,14 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
}
|
}
|
||||||
checkmclim(as);
|
checkmclim(as);
|
||||||
}
|
}
|
||||||
lua_assert(map + nent == flinks);
|
lj_assertA(map + nent == flinks, "inconsistent frames in snapshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- GC handling --------------------------------------------------------- */
|
/* -- GC handling --------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Marker to prevent patching the GC check exit. */
|
||||||
|
#define MIPS_NOPATCH_GC_CHECK MIPSI_OR
|
||||||
|
|
||||||
/* Check GC threshold and do one or more GC steps. */
|
/* Check GC threshold and do one or more GC steps. */
|
||||||
static void asm_gc_check(ASMState *as)
|
static void asm_gc_check(ASMState *as)
|
||||||
{
|
{
|
||||||
@@ -2472,6 +2546,7 @@ static void asm_gc_check(ASMState *as)
|
|||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
args[1] = ASMREF_TMP2; /* MSize steps */
|
args[1] = ASMREF_TMP2; /* MSize steps */
|
||||||
asm_gencall(as, ci, args);
|
asm_gencall(as, ci, args);
|
||||||
|
l_end[-3] = MIPS_NOPATCH_GC_CHECK; /* Replace the nop after the call. */
|
||||||
emit_tsi(as, MIPSI_AADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768);
|
emit_tsi(as, MIPSI_AADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768);
|
||||||
tmp = ra_releasetmp(as, ASMREF_TMP2);
|
tmp = ra_releasetmp(as, ASMREF_TMP2);
|
||||||
emit_loadi(as, tmp, as->gcsteps);
|
emit_loadi(as, tmp, as->gcsteps);
|
||||||
@@ -2618,7 +2693,12 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
|||||||
if (((p[-1] ^ (px-p)) & 0xffffu) == 0 &&
|
if (((p[-1] ^ (px-p)) & 0xffffu) == 0 &&
|
||||||
((p[-1] & 0xf0000000u) == MIPSI_BEQ ||
|
((p[-1] & 0xf0000000u) == MIPSI_BEQ ||
|
||||||
(p[-1] & 0xfc1e0000u) == MIPSI_BLTZ ||
|
(p[-1] & 0xfc1e0000u) == MIPSI_BLTZ ||
|
||||||
(p[-1] & 0xffe00000u) == MIPSI_BC1F)) {
|
#if !LJ_TARGET_MIPSR6
|
||||||
|
(p[-1] & 0xffe00000u) == MIPSI_BC1F
|
||||||
|
#else
|
||||||
|
(p[-1] & 0xff600000u) == MIPSI_BC1EQZ
|
||||||
|
#endif
|
||||||
|
) && p[-2] != MIPS_NOPATCH_GC_CHECK) {
|
||||||
ptrdiff_t delta = target - p;
|
ptrdiff_t delta = target - p;
|
||||||
if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */
|
if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */
|
||||||
patchbranch:
|
patchbranch:
|
||||||
@@ -2645,7 +2725,7 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
|||||||
}
|
}
|
||||||
} else if (p+1 == pe) {
|
} else if (p+1 == pe) {
|
||||||
/* Patch NOP after code for inverted loop branch. Use of J is ok. */
|
/* Patch NOP after code for inverted loop branch. Use of J is ok. */
|
||||||
lua_assert(p[1] == MIPSI_NOP);
|
lj_assertJ(p[1] == MIPSI_NOP, "expected NOP");
|
||||||
p[1] = tjump;
|
p[1] = tjump;
|
||||||
*p = MIPSI_NOP; /* Replace the load of the exit number. */
|
*p = MIPSI_NOP; /* Replace the load of the exit number. */
|
||||||
cstop = p+2;
|
cstop = p+2;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** PPC IR assembler (SSA IR -> machine code).
|
** PPC IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* -- Register allocator extensions --------------------------------------- */
|
/* -- Register allocator extensions --------------------------------------- */
|
||||||
@@ -181,7 +181,7 @@ static void asm_fusexref(ASMState *as, PPCIns pi, Reg rt, IRRef ref,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (ir->o == IR_STRREF) {
|
} else if (ir->o == IR_STRREF) {
|
||||||
lua_assert(ofs == 0);
|
lj_assertA(ofs == 0, "bad usage");
|
||||||
ofs = (int32_t)sizeof(GCstr);
|
ofs = (int32_t)sizeof(GCstr);
|
||||||
if (irref_isk(ir->op2)) {
|
if (irref_isk(ir->op2)) {
|
||||||
ofs += IR(ir->op2)->i;
|
ofs += IR(ir->op2)->i;
|
||||||
@@ -268,7 +268,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
if (irt_isfp(ir->t)) {
|
if (irt_isfp(ir->t)) {
|
||||||
if (fpr <= REGARG_LASTFPR) {
|
if (fpr <= REGARG_LASTFPR) {
|
||||||
lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */
|
lj_assertA(rset_test(as->freeset, fpr),
|
||||||
|
"reg %d not free", fpr); /* Already evicted. */
|
||||||
ra_leftov(as, fpr, ref);
|
ra_leftov(as, fpr, ref);
|
||||||
fpr++;
|
fpr++;
|
||||||
} else {
|
} else {
|
||||||
@@ -281,7 +282,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (gpr <= REGARG_LASTGPR) {
|
if (gpr <= REGARG_LASTGPR) {
|
||||||
lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */
|
lj_assertA(rset_test(as->freeset, gpr),
|
||||||
|
"reg %d not free", gpr); /* Already evicted. */
|
||||||
ra_leftov(as, gpr, ref);
|
ra_leftov(as, gpr, ref);
|
||||||
gpr++;
|
gpr++;
|
||||||
} else {
|
} else {
|
||||||
@@ -319,7 +321,7 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
|||||||
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
|
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
|
||||||
ra_evictset(as, drop); /* Evictions must be performed first. */
|
ra_evictset(as, drop); /* Evictions must be performed first. */
|
||||||
if (ra_used(ir)) {
|
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_SOFTFP && irt_isfp(ir->t)) {
|
||||||
if ((ci->flags & CCI_CASTU64)) {
|
if ((ci->flags & CCI_CASTU64)) {
|
||||||
/* Use spill slot or temp slots. */
|
/* Use spill slot or temp slots. */
|
||||||
@@ -431,14 +433,18 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
int stfp = (st == IRT_NUM || st == IRT_FLOAT);
|
int stfp = (st == IRT_NUM || st == IRT_FLOAT);
|
||||||
#endif
|
#endif
|
||||||
IRRef lref = ir->op1;
|
IRRef lref = ir->op1;
|
||||||
lua_assert(!(irt_isint64(ir->t) ||
|
/* 64 bit integer conversions are handled by SPLIT. */
|
||||||
(st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */
|
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
|
#if LJ_SOFTFP
|
||||||
/* FP conversions are handled by SPLIT. */
|
/* 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. */
|
/* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. */
|
||||||
#else
|
#else
|
||||||
lua_assert(irt_type(ir->t) != st);
|
lj_assertA(irt_type(ir->t) != st, "inconsistent types for CONV");
|
||||||
if (irt_isfp(ir->t)) {
|
if (irt_isfp(ir->t)) {
|
||||||
Reg dest = ra_dest(as, ir, RSET_FPR);
|
Reg dest = ra_dest(as, ir, RSET_FPR);
|
||||||
if (stfp) { /* FP to FP conversion. */
|
if (stfp) { /* FP to FP conversion. */
|
||||||
@@ -467,7 +473,8 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
} else if (stfp) { /* FP to integer conversion. */
|
} else if (stfp) { /* FP to integer conversion. */
|
||||||
if (irt_isguard(ir->t)) {
|
if (irt_isguard(ir->t)) {
|
||||||
/* Checked conversions are only supported from number to int. */
|
/* 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));
|
asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
|
||||||
} else {
|
} else {
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
@@ -503,7 +510,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */
|
if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */
|
||||||
Reg left = ra_alloc1(as, ir->op1, RSET_GPR);
|
Reg left = ra_alloc1(as, ir->op1, 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 ((ir->op2 & IRCONV_SEXT))
|
if ((ir->op2 & IRCONV_SEXT))
|
||||||
emit_as(as, st == IRT_I8 ? PPCI_EXTSB : PPCI_EXTSH, dest, left);
|
emit_as(as, st == IRT_I8 ? PPCI_EXTSB : PPCI_EXTSH, dest, left);
|
||||||
else
|
else
|
||||||
@@ -699,7 +706,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
(((char *)as->mcp-(char *)l_loop) & 0xffffu);
|
(((char *)as->mcp-(char *)l_loop) & 0xffffu);
|
||||||
|
|
||||||
/* Load main position relative to tab->node into dest. */
|
/* Load main position relative to tab->node into dest. */
|
||||||
khash = isk ? ir_khash(irkey) : 1;
|
khash = isk ? ir_khash(as, irkey) : 1;
|
||||||
if (khash == 0) {
|
if (khash == 0) {
|
||||||
emit_tai(as, PPCI_LWZ, dest, tab, (int32_t)offsetof(GCtab, node));
|
emit_tai(as, PPCI_LWZ, dest, tab, (int32_t)offsetof(GCtab, node));
|
||||||
} else {
|
} else {
|
||||||
@@ -714,7 +721,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
if (isk) {
|
if (isk) {
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
} else if (irt_isstr(kt)) {
|
} else if (irt_isstr(kt)) {
|
||||||
emit_tai(as, PPCI_LWZ, tmp1, key, (int32_t)offsetof(GCstr, hash));
|
emit_tai(as, PPCI_LWZ, tmp1, key, (int32_t)offsetof(GCstr, sid));
|
||||||
} else { /* Must match with hash*() in lj_tab.c. */
|
} else { /* Must match with hash*() in lj_tab.c. */
|
||||||
emit_tab(as, PPCI_SUBF, tmp1, tmp2, tmp1);
|
emit_tab(as, PPCI_SUBF, tmp1, tmp2, tmp1);
|
||||||
emit_rotlwi(as, tmp2, tmp2, HASH_ROT3);
|
emit_rotlwi(as, tmp2, tmp2, HASH_ROT3);
|
||||||
@@ -754,7 +761,7 @@ static void asm_hrefk(ASMState *as, IRIns *ir)
|
|||||||
Reg node = ra_alloc1(as, ir->op1, RSET_GPR);
|
Reg node = ra_alloc1(as, ir->op1, RSET_GPR);
|
||||||
Reg key = RID_NONE, type = RID_TMP, idx = node;
|
Reg key = RID_NONE, type = RID_TMP, idx = node;
|
||||||
RegSet allow = rset_exclude(RSET_GPR, 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 > 32736) {
|
if (ofs > 32736) {
|
||||||
idx = dest;
|
idx = dest;
|
||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
@@ -813,7 +820,7 @@ static void asm_uref(ASMState *as, IRIns *ir)
|
|||||||
static void asm_fref(ASMState *as, IRIns *ir)
|
static void asm_fref(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
UNUSED(as); UNUSED(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)
|
static void asm_strref(ASMState *as, IRIns *ir)
|
||||||
@@ -853,25 +860,27 @@ static void asm_strref(ASMState *as, IRIns *ir)
|
|||||||
|
|
||||||
/* -- Loads and stores ---------------------------------------------------- */
|
/* -- Loads and stores ---------------------------------------------------- */
|
||||||
|
|
||||||
static PPCIns asm_fxloadins(IRIns *ir)
|
static PPCIns asm_fxloadins(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
|
UNUSED(as);
|
||||||
switch (irt_type(ir->t)) {
|
switch (irt_type(ir->t)) {
|
||||||
case IRT_I8: return PPCI_LBZ; /* Needs sign-extension. */
|
case IRT_I8: return PPCI_LBZ; /* Needs sign-extension. */
|
||||||
case IRT_U8: return PPCI_LBZ;
|
case IRT_U8: return PPCI_LBZ;
|
||||||
case IRT_I16: return PPCI_LHA;
|
case IRT_I16: return PPCI_LHA;
|
||||||
case IRT_U16: return PPCI_LHZ;
|
case IRT_U16: return PPCI_LHZ;
|
||||||
case IRT_NUM: lua_assert(!LJ_SOFTFP); return PPCI_LFD;
|
case IRT_NUM: lj_assertA(!LJ_SOFTFP, "unsplit FP op"); return PPCI_LFD;
|
||||||
case IRT_FLOAT: if (!LJ_SOFTFP) return PPCI_LFS;
|
case IRT_FLOAT: if (!LJ_SOFTFP) return PPCI_LFS;
|
||||||
default: return PPCI_LWZ;
|
default: return PPCI_LWZ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PPCIns asm_fxstoreins(IRIns *ir)
|
static PPCIns asm_fxstoreins(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
|
UNUSED(as);
|
||||||
switch (irt_type(ir->t)) {
|
switch (irt_type(ir->t)) {
|
||||||
case IRT_I8: case IRT_U8: return PPCI_STB;
|
case IRT_I8: case IRT_U8: return PPCI_STB;
|
||||||
case IRT_I16: case IRT_U16: return PPCI_STH;
|
case IRT_I16: case IRT_U16: return PPCI_STH;
|
||||||
case IRT_NUM: lua_assert(!LJ_SOFTFP); return PPCI_STFD;
|
case IRT_NUM: lj_assertA(!LJ_SOFTFP, "unsplit FP op"); return PPCI_STFD;
|
||||||
case IRT_FLOAT: if (!LJ_SOFTFP) return PPCI_STFS;
|
case IRT_FLOAT: if (!LJ_SOFTFP) return PPCI_STFS;
|
||||||
default: return PPCI_STW;
|
default: return PPCI_STW;
|
||||||
}
|
}
|
||||||
@@ -880,10 +889,10 @@ static PPCIns asm_fxstoreins(IRIns *ir)
|
|||||||
static void asm_fload(ASMState *as, IRIns *ir)
|
static void asm_fload(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
PPCIns pi = asm_fxloadins(ir);
|
PPCIns pi = asm_fxloadins(as, ir);
|
||||||
Reg idx;
|
Reg idx;
|
||||||
int32_t ofs;
|
int32_t ofs;
|
||||||
if (ir->op1 == REF_NIL) {
|
if (ir->op1 == REF_NIL) { /* FLOAD from GG_State with offset. */
|
||||||
idx = RID_JGL;
|
idx = RID_JGL;
|
||||||
ofs = (ir->op2 << 2) - 32768;
|
ofs = (ir->op2 << 2) - 32768;
|
||||||
} else {
|
} else {
|
||||||
@@ -897,7 +906,7 @@ static void asm_fload(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
ofs = field_ofs[ir->op2];
|
ofs = field_ofs[ir->op2];
|
||||||
}
|
}
|
||||||
lua_assert(!irt_isi8(ir->t));
|
lj_assertA(!irt_isi8(ir->t), "unsupported FLOAD I8");
|
||||||
emit_tai(as, pi, dest, idx, ofs);
|
emit_tai(as, pi, dest, idx, ofs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -908,7 +917,7 @@ static void asm_fstore(ASMState *as, IRIns *ir)
|
|||||||
IRIns *irf = IR(ir->op1);
|
IRIns *irf = IR(ir->op1);
|
||||||
Reg idx = ra_alloc1(as, irf->op1, rset_exclude(RSET_GPR, src));
|
Reg idx = ra_alloc1(as, irf->op1, rset_exclude(RSET_GPR, src));
|
||||||
int32_t ofs = field_ofs[irf->op2];
|
int32_t ofs = field_ofs[irf->op2];
|
||||||
PPCIns pi = asm_fxstoreins(ir);
|
PPCIns pi = asm_fxstoreins(as, ir);
|
||||||
emit_tai(as, pi, src, idx, ofs);
|
emit_tai(as, pi, src, idx, ofs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -917,10 +926,10 @@ static void asm_xload(ASMState *as, IRIns *ir)
|
|||||||
{
|
{
|
||||||
Reg dest = ra_dest(as, ir,
|
Reg dest = ra_dest(as, ir,
|
||||||
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
||||||
lua_assert(!(ir->op2 & IRXLOAD_UNALIGNED));
|
lj_assertA(!(ir->op2 & IRXLOAD_UNALIGNED), "unaligned XLOAD");
|
||||||
if (irt_isi8(ir->t))
|
if (irt_isi8(ir->t))
|
||||||
emit_as(as, PPCI_EXTSB, dest, dest);
|
emit_as(as, PPCI_EXTSB, dest, dest);
|
||||||
asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0);
|
asm_fusexref(as, asm_fxloadins(as, ir), dest, ir->op1, RSET_GPR, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
|
static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
|
||||||
@@ -936,7 +945,7 @@ static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
|
|||||||
} else {
|
} else {
|
||||||
Reg src = ra_alloc1(as, ir->op2,
|
Reg src = ra_alloc1(as, ir->op2,
|
||||||
(!LJ_SOFTFP && irt_isfp(ir->t)) ? RSET_FPR : RSET_GPR);
|
(!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);
|
rset_exclude(RSET_GPR, src), ofs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -958,8 +967,9 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
ofs = 0;
|
ofs = 0;
|
||||||
}
|
}
|
||||||
if (ra_used(ir)) {
|
if (ra_used(ir)) {
|
||||||
lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
|
lj_assertA((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
|
||||||
irt_isint(ir->t) || irt_isaddr(ir->t));
|
irt_isint(ir->t) || irt_isaddr(ir->t),
|
||||||
|
"bad load type %d", irt_type(ir->t));
|
||||||
if (LJ_SOFTFP || !irt_isnum(t)) ofs = 0;
|
if (LJ_SOFTFP || !irt_isnum(t)) ofs = 0;
|
||||||
dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow);
|
dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow);
|
||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
@@ -1042,12 +1052,16 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
int hiop = (LJ_SOFTFP && (ir+1)->o == IR_HIOP);
|
int hiop = (LJ_SOFTFP && (ir+1)->o == IR_HIOP);
|
||||||
if (hiop)
|
if (hiop)
|
||||||
t.irt = IRT_NUM;
|
t.irt = IRT_NUM;
|
||||||
lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */
|
lj_assertA(!(ir->op2 & IRSLOAD_PARENT),
|
||||||
lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK));
|
"bad parent SLOAD"); /* Handled by asm_head_side(). */
|
||||||
lua_assert(LJ_DUALNUM ||
|
lj_assertA(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK),
|
||||||
!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)));
|
"inconsistent SLOAD variant");
|
||||||
|
lj_assertA(LJ_DUALNUM ||
|
||||||
|
!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)),
|
||||||
|
"bad SLOAD type");
|
||||||
#if LJ_SOFTFP
|
#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)) {
|
if (hiop && ra_used(ir+1)) {
|
||||||
type = ra_dest(as, ir+1, allow);
|
type = ra_dest(as, ir+1, allow);
|
||||||
rset_clear(allow, type);
|
rset_clear(allow, type);
|
||||||
@@ -1060,7 +1074,8 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (ra_used(ir)) {
|
if (ra_used(ir)) {
|
||||||
lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t));
|
lj_assertA(irt_isnum(t) || irt_isint(t) || irt_isaddr(t),
|
||||||
|
"bad SLOAD type %d", irt_type(ir->t));
|
||||||
dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow);
|
dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow);
|
||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
base = ra_alloc1(as, REF_BASE, allow);
|
base = ra_alloc1(as, REF_BASE, allow);
|
||||||
@@ -1127,7 +1142,8 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
|
||||||
IRRef args[4];
|
IRRef args[4];
|
||||||
RegSet drop = 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++;
|
as->gcsteps++;
|
||||||
if (ra_hasreg(ir->r))
|
if (ra_hasreg(ir->r))
|
||||||
@@ -1140,10 +1156,10 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
if (ir->o == IR_CNEWI) {
|
if (ir->o == IR_CNEWI) {
|
||||||
RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
|
RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
|
||||||
int32_t ofs = sizeof(GCcdata);
|
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) {
|
if (sz == 8) {
|
||||||
ofs += 4;
|
ofs += 4;
|
||||||
lua_assert((ir+1)->o == IR_HIOP);
|
lj_assertA((ir+1)->o == IR_HIOP, "expected HIOP for CNEWI");
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Reg r = ra_alloc1(as, ir->op2, allow);
|
Reg r = ra_alloc1(as, ir->op2, allow);
|
||||||
@@ -1174,8 +1190,6 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
|
ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
|
||||||
ra_releasetmp(as, ASMREF_TMP1));
|
ra_releasetmp(as, ASMREF_TMP1));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define asm_cnew(as, ir) ((void)0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -- Write barriers ------------------------------------------------------ */
|
/* -- Write barriers ------------------------------------------------------ */
|
||||||
@@ -1189,7 +1203,7 @@ static void asm_tbar(ASMState *as, IRIns *ir)
|
|||||||
emit_tai(as, PPCI_STW, link, tab, (int32_t)offsetof(GCtab, gclist));
|
emit_tai(as, PPCI_STW, link, tab, (int32_t)offsetof(GCtab, gclist));
|
||||||
emit_tai(as, PPCI_STB, mark, tab, (int32_t)offsetof(GCtab, marked));
|
emit_tai(as, PPCI_STB, mark, tab, (int32_t)offsetof(GCtab, marked));
|
||||||
emit_setgl(as, tab, gc.grayagain);
|
emit_setgl(as, tab, gc.grayagain);
|
||||||
lua_assert(LJ_GC_BLACK == 0x04);
|
lj_assertA(LJ_GC_BLACK == 0x04, "bad LJ_GC_BLACK");
|
||||||
emit_rot(as, PPCI_RLWINM, mark, mark, 0, 30, 28); /* Clear black bit. */
|
emit_rot(as, PPCI_RLWINM, mark, mark, 0, 30, 28); /* Clear black bit. */
|
||||||
emit_getgl(as, link, gc.grayagain);
|
emit_getgl(as, link, gc.grayagain);
|
||||||
emit_condbranch(as, PPCI_BC|PPCF_Y, CC_EQ, l_end);
|
emit_condbranch(as, PPCI_BC|PPCF_Y, CC_EQ, l_end);
|
||||||
@@ -1204,7 +1218,7 @@ static void asm_obar(ASMState *as, IRIns *ir)
|
|||||||
MCLabel l_end;
|
MCLabel l_end;
|
||||||
Reg obj, val, tmp;
|
Reg obj, val, tmp;
|
||||||
/* No need for other object barriers (yet). */
|
/* 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);
|
ra_evictset(as, RSET_SCRATCH);
|
||||||
l_end = emit_label(as);
|
l_end = emit_label(as);
|
||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
@@ -1246,8 +1260,6 @@ static void asm_fpunary(ASMState *as, IRIns *ir, PPCIns pi)
|
|||||||
|
|
||||||
static void asm_fpmath(ASMState *as, IRIns *ir)
|
static void asm_fpmath(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir))
|
|
||||||
return;
|
|
||||||
if (ir->op2 == IRFPM_SQRT && (as->flags & JIT_F_SQRT))
|
if (ir->op2 == IRFPM_SQRT && (as->flags & JIT_F_SQRT))
|
||||||
asm_fpunary(as, ir, PPCI_FSQRT);
|
asm_fpunary(as, ir, PPCI_FSQRT);
|
||||||
else
|
else
|
||||||
@@ -1361,9 +1373,7 @@ static void asm_mul(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define asm_div(as, ir) asm_fparith(as, ir, PPCI_FDIV)
|
#define asm_fpdiv(as, ir) asm_fparith(as, ir, PPCI_FDIV)
|
||||||
#define asm_mod(as, ir) asm_callid(as, ir, IRCALL_lj_vm_modi)
|
|
||||||
#define asm_pow(as, ir) asm_callid(as, ir, IRCALL_lj_vm_powi)
|
|
||||||
|
|
||||||
static void asm_neg(ASMState *as, IRIns *ir)
|
static void asm_neg(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
@@ -1387,8 +1397,6 @@ static void asm_neg(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define asm_abs(as, ir) asm_fpunary(as, ir, PPCI_FABS)
|
#define asm_abs(as, ir) asm_fpunary(as, ir, PPCI_FABS)
|
||||||
#define asm_atan2(as, ir) asm_callid(as, ir, IRCALL_atan2)
|
|
||||||
#define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp)
|
|
||||||
|
|
||||||
static void asm_arithov(ASMState *as, IRIns *ir, PPCIns pi)
|
static void asm_arithov(ASMState *as, IRIns *ir, PPCIns pi)
|
||||||
{
|
{
|
||||||
@@ -1681,7 +1689,7 @@ static void asm_bitshift(ASMState *as, IRIns *ir, PPCIns pi, PPCIns pik)
|
|||||||
#define asm_brol(as, ir) \
|
#define asm_brol(as, ir) \
|
||||||
asm_bitshift(as, ir, PPCI_RLWNM|PPCF_MB(0)|PPCF_ME(31), \
|
asm_bitshift(as, ir, PPCI_RLWNM|PPCF_MB(0)|PPCF_ME(31), \
|
||||||
PPCI_RLWINM|PPCF_MB(0)|PPCF_ME(31))
|
PPCI_RLWINM|PPCF_MB(0)|PPCF_ME(31))
|
||||||
#define asm_bror(as, ir) lua_assert(0)
|
#define asm_bror(as, ir) lj_assertA(0, "unexpected BROR")
|
||||||
|
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
static void asm_sfpmin_max(ASMState *as, IRIns *ir)
|
static void asm_sfpmin_max(ASMState *as, IRIns *ir)
|
||||||
@@ -1724,9 +1732,8 @@ static void asm_min_max(ASMState *as, IRIns *ir, int ismax)
|
|||||||
if (tmp == left || tmp == right)
|
if (tmp == left || tmp == right)
|
||||||
tmp = ra_scratch(as, rset_exclude(rset_exclude(rset_exclude(RSET_FPR,
|
tmp = ra_scratch(as, rset_exclude(rset_exclude(rset_exclude(RSET_FPR,
|
||||||
dest), left), right));
|
dest), left), right));
|
||||||
emit_facb(as, PPCI_FSEL, dest, tmp,
|
emit_facb(as, PPCI_FSEL, dest, tmp, left, right);
|
||||||
ismax ? left : right, ismax ? right : left);
|
emit_fab(as, PPCI_FSUB, tmp, ismax ? left : right, ismax ? right : left);
|
||||||
emit_fab(as, PPCI_FSUB, tmp, left, right);
|
|
||||||
} else {
|
} else {
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
Reg tmp1 = RID_TMP, tmp2 = dest;
|
Reg tmp1 = RID_TMP, tmp2 = dest;
|
||||||
@@ -1956,10 +1963,11 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
case IR_CNEWI:
|
case IR_CNEWI:
|
||||||
/* Nothing to do here. Handled by lo op itself. */
|
/* Nothing to do here. Handled by lo op itself. */
|
||||||
break;
|
break;
|
||||||
default: lua_assert(0); break;
|
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
UNUSED(as); UNUSED(ir); lua_assert(0); /* Unused without FFI. */
|
/* Unused without SOFTFP or FFI. */
|
||||||
|
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2019,7 +2027,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
Reg tmp;
|
Reg tmp;
|
||||||
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
|
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
|
||||||
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, allow);
|
tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, allow);
|
||||||
emit_tai(as, PPCI_STW, tmp, RID_BASE, ofs+(LJ_BE?4:0));
|
emit_tai(as, PPCI_STW, tmp, RID_BASE, ofs+(LJ_BE?4:0));
|
||||||
if (rset_test(as->freeset, tmp+1)) allow = RID2RSET(tmp+1);
|
if (rset_test(as->freeset, tmp+1)) allow = RID2RSET(tmp+1);
|
||||||
@@ -2032,7 +2041,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
} else {
|
} else {
|
||||||
Reg type;
|
Reg type;
|
||||||
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
|
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
|
||||||
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)) {
|
if (!irt_ispri(ir->t)) {
|
||||||
Reg src = ra_alloc1(as, ref, allow);
|
Reg src = ra_alloc1(as, ref, allow);
|
||||||
rset_clear(allow, src);
|
rset_clear(allow, src);
|
||||||
@@ -2052,11 +2062,14 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
}
|
}
|
||||||
checkmclim(as);
|
checkmclim(as);
|
||||||
}
|
}
|
||||||
lua_assert(map + nent == flinks);
|
lj_assertA(map + nent == flinks, "inconsistent frames in snapshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- GC handling --------------------------------------------------------- */
|
/* -- GC handling --------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Marker to prevent patching the GC check exit. */
|
||||||
|
#define PPC_NOPATCH_GC_CHECK PPCI_ORIS
|
||||||
|
|
||||||
/* Check GC threshold and do one or more GC steps. */
|
/* Check GC threshold and do one or more GC steps. */
|
||||||
static void asm_gc_check(ASMState *as)
|
static void asm_gc_check(ASMState *as)
|
||||||
{
|
{
|
||||||
@@ -2068,6 +2081,7 @@ static void asm_gc_check(ASMState *as)
|
|||||||
l_end = emit_label(as);
|
l_end = emit_label(as);
|
||||||
/* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
|
/* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
|
||||||
asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */
|
asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */
|
||||||
|
*--as->mcp = PPC_NOPATCH_GC_CHECK;
|
||||||
emit_ai(as, PPCI_CMPWI, RID_RET, 0);
|
emit_ai(as, PPCI_CMPWI, RID_RET, 0);
|
||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
args[1] = ASMREF_TMP2; /* MSize steps */
|
args[1] = ASMREF_TMP2; /* MSize steps */
|
||||||
@@ -2150,7 +2164,7 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk)
|
|||||||
as->mctop = p;
|
as->mctop = p;
|
||||||
} else {
|
} else {
|
||||||
/* Patch stack adjustment. */
|
/* Patch stack adjustment. */
|
||||||
lua_assert(checki16(CFRAME_SIZE+spadj));
|
lj_assertA(checki16(CFRAME_SIZE+spadj), "stack adjustment out of range");
|
||||||
p[-3] = PPCI_ADDI | PPCF_T(RID_TMP) | PPCF_A(RID_SP) | (CFRAME_SIZE+spadj);
|
p[-3] = PPCI_ADDI | PPCF_T(RID_TMP) | PPCF_A(RID_SP) | (CFRAME_SIZE+spadj);
|
||||||
p[-2] = PPCI_STWU | PPCF_T(RID_TMP) | PPCF_A(RID_SP) | spadj;
|
p[-2] = PPCI_STWU | PPCF_T(RID_TMP) | PPCF_A(RID_SP) | spadj;
|
||||||
}
|
}
|
||||||
@@ -2207,7 +2221,7 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
|||||||
MCode *px = exitstub_trace_addr(T, exitno);
|
MCode *px = exitstub_trace_addr(T, exitno);
|
||||||
MCode *cstart = NULL;
|
MCode *cstart = NULL;
|
||||||
MCode *mcarea = lj_mcode_patch(J, p, 0);
|
MCode *mcarea = lj_mcode_patch(J, p, 0);
|
||||||
int clearso = 0;
|
int clearso = 0, patchlong = 1;
|
||||||
for (; p < pe; p++) {
|
for (; p < pe; p++) {
|
||||||
/* Look for exitstub branch, try to replace with branch to target. */
|
/* Look for exitstub branch, try to replace with branch to target. */
|
||||||
uint32_t ins = *p;
|
uint32_t ins = *p;
|
||||||
@@ -2219,7 +2233,9 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
|||||||
delta -= sizeof(MCode);
|
delta -= sizeof(MCode);
|
||||||
}
|
}
|
||||||
/* Many, but not all short-range branches can be patched directly. */
|
/* Many, but not all short-range branches can be patched directly. */
|
||||||
if (((delta + 0x8000) >> 16) == 0) {
|
if (p[-1] == PPC_NOPATCH_GC_CHECK) {
|
||||||
|
patchlong = 0;
|
||||||
|
} else if (((delta + 0x8000) >> 16) == 0) {
|
||||||
*p = (ins & 0xffdf0000u) | ((uint32_t)delta & 0xffffu) |
|
*p = (ins & 0xffdf0000u) | ((uint32_t)delta & 0xffffu) |
|
||||||
((delta & 0x8000) * (PPCF_Y/0x8000));
|
((delta & 0x8000) * (PPCF_Y/0x8000));
|
||||||
if (!cstart) cstart = p;
|
if (!cstart) cstart = p;
|
||||||
@@ -2227,14 +2243,17 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
|||||||
} else if ((ins & 0xfc000000u) == PPCI_B &&
|
} else if ((ins & 0xfc000000u) == PPCI_B &&
|
||||||
((ins ^ ((char *)px-(char *)p)) & 0x03ffffffu) == 0) {
|
((ins ^ ((char *)px-(char *)p)) & 0x03ffffffu) == 0) {
|
||||||
ptrdiff_t delta = (char *)target - (char *)p;
|
ptrdiff_t delta = (char *)target - (char *)p;
|
||||||
lua_assert(((delta + 0x02000000) >> 26) == 0);
|
lj_assertJ(((delta + 0x02000000) >> 26) == 0,
|
||||||
|
"branch target out of range");
|
||||||
*p = PPCI_B | ((uint32_t)delta & 0x03ffffffu);
|
*p = PPCI_B | ((uint32_t)delta & 0x03ffffffu);
|
||||||
if (!cstart) cstart = p;
|
if (!cstart) cstart = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ /* Always patch long-range branch in exit stub itself. */
|
/* Always patch long-range branch in exit stub itself. Except, if we can't. */
|
||||||
|
if (patchlong) {
|
||||||
ptrdiff_t delta = (char *)target - (char *)px - clearso;
|
ptrdiff_t delta = (char *)target - (char *)px - clearso;
|
||||||
lua_assert(((delta + 0x02000000) >> 26) == 0);
|
lj_assertJ(((delta + 0x02000000) >> 26) == 0,
|
||||||
|
"branch target out of range");
|
||||||
*px = PPCI_B | ((uint32_t)delta & 0x03ffffffu);
|
*px = PPCI_B | ((uint32_t)delta & 0x03ffffffu);
|
||||||
}
|
}
|
||||||
if (!cstart) cstart = px;
|
if (!cstart) cstart = px;
|
||||||
|
|||||||
+118
-137
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** x86/x64 IR assembler (SSA IR -> machine code).
|
** x86/x64 IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* -- Guard handling ------------------------------------------------------ */
|
/* -- Guard handling ------------------------------------------------------ */
|
||||||
@@ -31,7 +31,7 @@ static MCode *asm_exitstub_gen(ASMState *as, ExitNo group)
|
|||||||
#endif
|
#endif
|
||||||
/* Jump to exit handler which fills in the ExitState. */
|
/* Jump to exit handler which fills in the ExitState. */
|
||||||
*mxp++ = XI_JMP; mxp += 4;
|
*mxp++ = XI_JMP; mxp += 4;
|
||||||
*((int32_t *)(mxp-4)) = jmprel(mxp, (MCode *)(void *)lj_vm_exit_handler);
|
*((int32_t *)(mxp-4)) = jmprel(as->J, mxp, (MCode *)(void *)lj_vm_exit_handler);
|
||||||
/* Commit the code for this group (even if assembly fails later on). */
|
/* Commit the code for this group (even if assembly fails later on). */
|
||||||
lj_mcode_commitbot(as->J, mxp);
|
lj_mcode_commitbot(as->J, mxp);
|
||||||
as->mcbot = mxp;
|
as->mcbot = mxp;
|
||||||
@@ -60,7 +60,7 @@ static void asm_guardcc(ASMState *as, int cc)
|
|||||||
MCode *p = as->mcp;
|
MCode *p = as->mcp;
|
||||||
if (LJ_UNLIKELY(p == as->invmcp)) {
|
if (LJ_UNLIKELY(p == as->invmcp)) {
|
||||||
as->loopinv = 1;
|
as->loopinv = 1;
|
||||||
*(int32_t *)(p+1) = jmprel(p+5, target);
|
*(int32_t *)(p+1) = jmprel(as->J, p+5, target);
|
||||||
target = p;
|
target = p;
|
||||||
cc ^= 1;
|
cc ^= 1;
|
||||||
if (as->realign) {
|
if (as->realign) {
|
||||||
@@ -131,7 +131,7 @@ static IRRef asm_fuseabase(ASMState *as, IRRef ref)
|
|||||||
as->mrm.ofs = 0;
|
as->mrm.ofs = 0;
|
||||||
if (irb->o == IR_FLOAD) {
|
if (irb->o == IR_FLOAD) {
|
||||||
IRIns *ira = IR(irb->op1);
|
IRIns *ira = IR(irb->op1);
|
||||||
lua_assert(irb->op2 == IRFL_TAB_ARRAY);
|
lj_assertA(irb->op2 == IRFL_TAB_ARRAY, "expected FLOAD TAB_ARRAY");
|
||||||
/* We can avoid the FLOAD of t->array for colocated arrays. */
|
/* We can avoid the FLOAD of t->array for colocated arrays. */
|
||||||
if (ira->o == IR_TNEW && ira->op1 <= LJ_MAX_COLOSIZE &&
|
if (ira->o == IR_TNEW && ira->op1 <= LJ_MAX_COLOSIZE &&
|
||||||
!neverfuse(as) && noconflict(as, irb->op1, IR_NEWREF, 1)) {
|
!neverfuse(as) && noconflict(as, irb->op1, IR_NEWREF, 1)) {
|
||||||
@@ -150,7 +150,7 @@ static IRRef asm_fuseabase(ASMState *as, IRRef ref)
|
|||||||
static void asm_fusearef(ASMState *as, IRIns *ir, RegSet allow)
|
static void asm_fusearef(ASMState *as, IRIns *ir, RegSet allow)
|
||||||
{
|
{
|
||||||
IRIns *irx;
|
IRIns *irx;
|
||||||
lua_assert(ir->o == IR_AREF);
|
lj_assertA(ir->o == IR_AREF, "expected AREF");
|
||||||
as->mrm.base = (uint8_t)ra_alloc1(as, asm_fuseabase(as, ir->op1), allow);
|
as->mrm.base = (uint8_t)ra_alloc1(as, asm_fuseabase(as, ir->op1), allow);
|
||||||
irx = IR(ir->op2);
|
irx = IR(ir->op2);
|
||||||
if (irref_isk(ir->op2)) {
|
if (irref_isk(ir->op2)) {
|
||||||
@@ -217,8 +217,9 @@ static void asm_fuseahuref(ASMState *as, IRRef ref, RegSet allow)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lua_assert(ir->o == IR_HREF || ir->o == IR_NEWREF || ir->o == IR_UREFO ||
|
lj_assertA(ir->o == IR_HREF || ir->o == IR_NEWREF || ir->o == IR_UREFO ||
|
||||||
ir->o == IR_KKPTR);
|
ir->o == IR_KKPTR,
|
||||||
|
"bad IR op %d", ir->o);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,9 +231,10 @@ static void asm_fuseahuref(ASMState *as, IRRef ref, RegSet allow)
|
|||||||
/* Fuse FLOAD/FREF reference into memory operand. */
|
/* Fuse FLOAD/FREF reference into memory operand. */
|
||||||
static void asm_fusefref(ASMState *as, IRIns *ir, RegSet allow)
|
static void asm_fusefref(ASMState *as, IRIns *ir, RegSet allow)
|
||||||
{
|
{
|
||||||
lua_assert(ir->o == IR_FLOAD || ir->o == IR_FREF);
|
lj_assertA(ir->o == IR_FLOAD || ir->o == IR_FREF,
|
||||||
|
"bad IR op %d", ir->o);
|
||||||
as->mrm.idx = RID_NONE;
|
as->mrm.idx = RID_NONE;
|
||||||
if (ir->op1 == REF_NIL) {
|
if (ir->op1 == REF_NIL) { /* FLOAD from GG_State with offset. */
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
as->mrm.ofs = (int32_t)(ir->op2 << 2) - GG_OFS(dispatch);
|
as->mrm.ofs = (int32_t)(ir->op2 << 2) - GG_OFS(dispatch);
|
||||||
as->mrm.base = RID_DISPATCH;
|
as->mrm.base = RID_DISPATCH;
|
||||||
@@ -271,7 +273,7 @@ static void asm_fusefref(ASMState *as, IRIns *ir, RegSet allow)
|
|||||||
static void asm_fusestrref(ASMState *as, IRIns *ir, RegSet allow)
|
static void asm_fusestrref(ASMState *as, IRIns *ir, RegSet allow)
|
||||||
{
|
{
|
||||||
IRIns *irr;
|
IRIns *irr;
|
||||||
lua_assert(ir->o == IR_STRREF);
|
lj_assertA(ir->o == IR_STRREF, "bad IR op %d", ir->o);
|
||||||
as->mrm.base = as->mrm.idx = RID_NONE;
|
as->mrm.base = as->mrm.idx = RID_NONE;
|
||||||
as->mrm.scale = XM_SCALE1;
|
as->mrm.scale = XM_SCALE1;
|
||||||
as->mrm.ofs = sizeof(GCstr);
|
as->mrm.ofs = sizeof(GCstr);
|
||||||
@@ -378,9 +380,10 @@ static Reg asm_fuseloadk64(ASMState *as, IRIns *ir)
|
|||||||
checki32(mctopofs(as, k)) && checki32(mctopofs(as, k+1))) {
|
checki32(mctopofs(as, k)) && checki32(mctopofs(as, k+1))) {
|
||||||
as->mrm.ofs = (int32_t)mcpofs(as, k);
|
as->mrm.ofs = (int32_t)mcpofs(as, k);
|
||||||
as->mrm.base = RID_RIP;
|
as->mrm.base = RID_RIP;
|
||||||
} else {
|
} else { /* Intern 64 bit constant at bottom of mcode. */
|
||||||
if (ir->i) {
|
if (ir->i) {
|
||||||
lua_assert(*k == *(uint64_t*)(as->mctop - ir->i));
|
lj_assertA(*k == *(uint64_t*)(as->mctop - ir->i),
|
||||||
|
"bad interned 64 bit constant");
|
||||||
} else {
|
} else {
|
||||||
while ((uintptr_t)as->mcbot & 7) *as->mcbot++ = XI_INT3;
|
while ((uintptr_t)as->mcbot & 7) *as->mcbot++ = XI_INT3;
|
||||||
*(uint64_t*)as->mcbot = *k;
|
*(uint64_t*)as->mcbot = *k;
|
||||||
@@ -420,12 +423,12 @@ static Reg asm_fuseload(ASMState *as, IRRef ref, RegSet allow)
|
|||||||
}
|
}
|
||||||
if (ir->o == IR_KNUM) {
|
if (ir->o == IR_KNUM) {
|
||||||
RegSet avail = as->freeset & ~as->modset & RSET_FPR;
|
RegSet avail = as->freeset & ~as->modset & RSET_FPR;
|
||||||
lua_assert(allow != RSET_EMPTY);
|
lj_assertA(allow != RSET_EMPTY, "no register allowed");
|
||||||
if (!(avail & (avail-1))) /* Fuse if less than two regs available. */
|
if (!(avail & (avail-1))) /* Fuse if less than two regs available. */
|
||||||
return asm_fuseloadk64(as, ir);
|
return asm_fuseloadk64(as, ir);
|
||||||
} else if (ref == REF_BASE || ir->o == IR_KINT64) {
|
} else if (ref == REF_BASE || ir->o == IR_KINT64) {
|
||||||
RegSet avail = as->freeset & ~as->modset & RSET_GPR;
|
RegSet avail = as->freeset & ~as->modset & RSET_GPR;
|
||||||
lua_assert(allow != RSET_EMPTY);
|
lj_assertA(allow != RSET_EMPTY, "no register allowed");
|
||||||
if (!(avail & (avail-1))) { /* Fuse if less than two regs available. */
|
if (!(avail & (avail-1))) { /* Fuse if less than two regs available. */
|
||||||
if (ref == REF_BASE) {
|
if (ref == REF_BASE) {
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
@@ -606,7 +609,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
#endif
|
#endif
|
||||||
emit_loadi(as, r, ir->i);
|
emit_loadi(as, r, ir->i);
|
||||||
} else {
|
} else {
|
||||||
lua_assert(rset_test(as->freeset, r)); /* Must have been evicted. */
|
/* Must have been evicted. */
|
||||||
|
lj_assertA(rset_test(as->freeset, r), "reg %d not free", r);
|
||||||
if (ra_hasreg(ir->r)) {
|
if (ra_hasreg(ir->r)) {
|
||||||
ra_noweak(as, ir->r);
|
ra_noweak(as, ir->r);
|
||||||
emit_movrr(as, ir, r, ir->r);
|
emit_movrr(as, ir, r, ir->r);
|
||||||
@@ -615,7 +619,8 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (irt_isfp(ir->t)) { /* FP argument is on stack. */
|
} else if (irt_isfp(ir->t)) { /* FP argument is on stack. */
|
||||||
lua_assert(!(irt_isfloat(ir->t) && irref_isk(ref))); /* No float k. */
|
lj_assertA(!(irt_isfloat(ir->t) && irref_isk(ref)),
|
||||||
|
"unexpected float constant");
|
||||||
if (LJ_32 && (ofs & 4) && irref_isk(ref)) {
|
if (LJ_32 && (ofs & 4) && irref_isk(ref)) {
|
||||||
/* Split stores for unaligned FP consts. */
|
/* Split stores for unaligned FP consts. */
|
||||||
emit_movmroi(as, RID_ESP, ofs, (int32_t)ir_knum(ir)->u32.lo);
|
emit_movmroi(as, RID_ESP, ofs, (int32_t)ir_knum(ir)->u32.lo);
|
||||||
@@ -691,7 +696,7 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
|||||||
ra_destpair(as, ir);
|
ra_destpair(as, ir);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
lua_assert(!irt_ispri(ir->t));
|
lj_assertA(!irt_ispri(ir->t), "PRI dest");
|
||||||
ra_destreg(as, ir, RID_RET);
|
ra_destreg(as, ir, RID_RET);
|
||||||
}
|
}
|
||||||
} else if (LJ_32 && irt_isfp(ir->t) && !(ci->flags & CCI_CASTU64)) {
|
} else if (LJ_32 && irt_isfp(ir->t) && !(ci->flags & CCI_CASTU64)) {
|
||||||
@@ -810,8 +815,10 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
int st64 = (st == IRT_I64 || st == IRT_U64 || (LJ_64 && st == IRT_P64));
|
int st64 = (st == IRT_I64 || st == IRT_U64 || (LJ_64 && st == IRT_P64));
|
||||||
int stfp = (st == IRT_NUM || st == IRT_FLOAT);
|
int stfp = (st == IRT_NUM || st == IRT_FLOAT);
|
||||||
IRRef lref = ir->op1;
|
IRRef lref = ir->op1;
|
||||||
lua_assert(irt_type(ir->t) != st);
|
lj_assertA(irt_type(ir->t) != st, "inconsistent types for CONV");
|
||||||
lua_assert(!(LJ_32 && (irt_isint64(ir->t) || st64))); /* Handled by SPLIT. */
|
lj_assertA(!(LJ_32 && (irt_isint64(ir->t) || st64)),
|
||||||
|
"IR %04d has unsplit 64 bit type",
|
||||||
|
(int)(ir - as->ir) - REF_BIAS);
|
||||||
if (irt_isfp(ir->t)) {
|
if (irt_isfp(ir->t)) {
|
||||||
Reg dest = ra_dest(as, ir, RSET_FPR);
|
Reg dest = ra_dest(as, ir, RSET_FPR);
|
||||||
if (stfp) { /* FP to FP conversion. */
|
if (stfp) { /* FP to FP conversion. */
|
||||||
@@ -847,7 +854,8 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
} else if (stfp) { /* FP to integer conversion. */
|
} else if (stfp) { /* FP to integer conversion. */
|
||||||
if (irt_isguard(ir->t)) {
|
if (irt_isguard(ir->t)) {
|
||||||
/* Checked conversions are only supported from number to int. */
|
/* 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));
|
asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
|
||||||
} else {
|
} else {
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
@@ -882,7 +890,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
Reg left, dest = ra_dest(as, ir, RSET_GPR);
|
Reg left, dest = ra_dest(as, ir, RSET_GPR);
|
||||||
RegSet allow = RSET_GPR;
|
RegSet allow = RSET_GPR;
|
||||||
x86Op op;
|
x86Op op;
|
||||||
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 (st == IRT_I8) {
|
if (st == IRT_I8) {
|
||||||
op = XO_MOVSXb; allow = RSET_GPR8; dest |= FORCE_REX;
|
op = XO_MOVSXb; allow = RSET_GPR8; dest |= FORCE_REX;
|
||||||
} else if (st == IRT_U8) {
|
} else if (st == IRT_U8) {
|
||||||
@@ -953,7 +961,7 @@ static void asm_conv_fp_int64(ASMState *as, IRIns *ir)
|
|||||||
emit_sjcc(as, CC_NS, l_end);
|
emit_sjcc(as, CC_NS, l_end);
|
||||||
emit_rr(as, XO_TEST, hi, hi); /* Check if u64 >= 2^63. */
|
emit_rr(as, XO_TEST, hi, hi); /* Check if u64 >= 2^63. */
|
||||||
} else {
|
} else {
|
||||||
lua_assert(((ir-1)->op2 & IRCONV_SRCMASK) == IRT_I64);
|
lj_assertA(((ir-1)->op2 & IRCONV_SRCMASK) == IRT_I64, "bad type for CONV");
|
||||||
}
|
}
|
||||||
emit_rmro(as, XO_FILDq, XOg_FILDq, RID_ESP, 0);
|
emit_rmro(as, XO_FILDq, XOg_FILDq, RID_ESP, 0);
|
||||||
/* NYI: Avoid narrow-to-wide store-to-load forwarding stall. */
|
/* NYI: Avoid narrow-to-wide store-to-load forwarding stall. */
|
||||||
@@ -967,8 +975,8 @@ static void asm_conv_int64_fp(ASMState *as, IRIns *ir)
|
|||||||
IRType st = (IRType)((ir-1)->op2 & IRCONV_SRCMASK);
|
IRType st = (IRType)((ir-1)->op2 & IRCONV_SRCMASK);
|
||||||
IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH);
|
IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH);
|
||||||
Reg lo, hi;
|
Reg lo, hi;
|
||||||
lua_assert(st == IRT_NUM || st == IRT_FLOAT);
|
lj_assertA(st == IRT_NUM || st == IRT_FLOAT, "bad type for CONV");
|
||||||
lua_assert(dt == IRT_I64 || dt == IRT_U64);
|
lj_assertA(dt == IRT_I64 || dt == IRT_U64, "bad type for CONV");
|
||||||
hi = ra_dest(as, ir, RSET_GPR);
|
hi = ra_dest(as, ir, RSET_GPR);
|
||||||
lo = ra_dest(as, ir-1, rset_exclude(RSET_GPR, hi));
|
lo = ra_dest(as, ir-1, rset_exclude(RSET_GPR, hi));
|
||||||
if (ra_used(ir-1)) emit_rmro(as, XO_MOV, lo, RID_ESP, 0);
|
if (ra_used(ir-1)) emit_rmro(as, XO_MOV, lo, RID_ESP, 0);
|
||||||
@@ -1180,13 +1188,13 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
emit_rmro(as, XO_CMP, tmp|REX_64, dest, offsetof(Node, key.u64));
|
emit_rmro(as, XO_CMP, tmp|REX_64, dest, offsetof(Node, key.u64));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lua_assert(irt_ispri(kt) && !irt_isnil(kt));
|
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
|
||||||
emit_u32(as, (irt_toitype(kt)<<15)|0x7fff);
|
emit_u32(as, (irt_toitype(kt)<<15)|0x7fff);
|
||||||
emit_rmro(as, XO_ARITHi, XOg_CMP, dest, offsetof(Node, key.it));
|
emit_rmro(as, XO_ARITHi, XOg_CMP, dest, offsetof(Node, key.it));
|
||||||
#else
|
#else
|
||||||
} else {
|
} else {
|
||||||
if (!irt_ispri(kt)) {
|
if (!irt_ispri(kt)) {
|
||||||
lua_assert(irt_isaddr(kt));
|
lj_assertA(irt_isaddr(kt), "bad HREF key type");
|
||||||
if (isk)
|
if (isk)
|
||||||
emit_gmroi(as, XG_ARITHi(XOg_CMP), dest, offsetof(Node, key.gcr),
|
emit_gmroi(as, XG_ARITHi(XOg_CMP), dest, offsetof(Node, key.gcr),
|
||||||
ptr2addr(ir_kgc(irkey)));
|
ptr2addr(ir_kgc(irkey)));
|
||||||
@@ -1194,7 +1202,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
emit_rmro(as, XO_CMP, key, dest, offsetof(Node, key.gcr));
|
emit_rmro(as, XO_CMP, key, dest, offsetof(Node, key.gcr));
|
||||||
emit_sjcc(as, CC_NE, l_next);
|
emit_sjcc(as, CC_NE, l_next);
|
||||||
}
|
}
|
||||||
lua_assert(!irt_isnil(kt));
|
lj_assertA(!irt_isnil(kt), "bad HREF key type");
|
||||||
emit_i8(as, irt_toitype(kt));
|
emit_i8(as, irt_toitype(kt));
|
||||||
emit_rmro(as, XO_ARITHi8, XOg_CMP, dest, offsetof(Node, key.it));
|
emit_rmro(as, XO_ARITHi8, XOg_CMP, dest, offsetof(Node, key.it));
|
||||||
#endif
|
#endif
|
||||||
@@ -1209,23 +1217,18 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Load main position relative to tab->node into dest. */
|
/* Load main position relative to tab->node into dest. */
|
||||||
khash = isk ? ir_khash(irkey) : 1;
|
khash = isk ? ir_khash(as, irkey) : 1;
|
||||||
if (khash == 0) {
|
if (khash == 0) {
|
||||||
emit_rmro(as, XO_MOV, dest|REX_GC64, tab, offsetof(GCtab, node));
|
emit_rmro(as, XO_MOV, dest|REX_GC64, tab, offsetof(GCtab, node));
|
||||||
} else {
|
} else {
|
||||||
emit_rmro(as, XO_ARITH(XOg_ADD), dest|REX_GC64, tab, offsetof(GCtab,node));
|
emit_rmro(as, XO_ARITH(XOg_ADD), dest|REX_GC64, tab, offsetof(GCtab,node));
|
||||||
if ((as->flags & JIT_F_PREFER_IMUL)) {
|
emit_shifti(as, XOg_SHL, dest, 3);
|
||||||
emit_i8(as, sizeof(Node));
|
emit_rmrxo(as, XO_LEA, dest, dest, dest, XM_SCALE2, 0);
|
||||||
emit_rr(as, XO_IMULi8, dest, dest);
|
|
||||||
} else {
|
|
||||||
emit_shifti(as, XOg_SHL, dest, 3);
|
|
||||||
emit_rmrxo(as, XO_LEA, dest, dest, dest, XM_SCALE2, 0);
|
|
||||||
}
|
|
||||||
if (isk) {
|
if (isk) {
|
||||||
emit_gri(as, XG_ARITHi(XOg_AND), dest, (int32_t)khash);
|
emit_gri(as, XG_ARITHi(XOg_AND), dest, (int32_t)khash);
|
||||||
emit_rmro(as, XO_MOV, dest, tab, offsetof(GCtab, hmask));
|
emit_rmro(as, XO_MOV, dest, tab, offsetof(GCtab, hmask));
|
||||||
} else if (irt_isstr(kt)) {
|
} else if (irt_isstr(kt)) {
|
||||||
emit_rmro(as, XO_ARITH(XOg_AND), dest, key, offsetof(GCstr, hash));
|
emit_rmro(as, XO_ARITH(XOg_AND), dest, key, offsetof(GCstr, sid));
|
||||||
emit_rmro(as, XO_MOV, dest, tab, offsetof(GCtab, hmask));
|
emit_rmro(as, XO_MOV, dest, tab, offsetof(GCtab, hmask));
|
||||||
} else { /* Must match with hashrot() in lj_tab.c. */
|
} else { /* Must match with hashrot() in lj_tab.c. */
|
||||||
emit_rmro(as, XO_ARITH(XOg_AND), dest, tab, offsetof(GCtab, hmask));
|
emit_rmro(as, XO_ARITH(XOg_AND), dest, tab, offsetof(GCtab, hmask));
|
||||||
@@ -1276,10 +1279,10 @@ static void asm_hrefk(ASMState *as, IRIns *ir)
|
|||||||
#if !LJ_64
|
#if !LJ_64
|
||||||
MCLabel l_exit;
|
MCLabel l_exit;
|
||||||
#endif
|
#endif
|
||||||
lua_assert(ofs % sizeof(Node) == 0);
|
lj_assertA(ofs % sizeof(Node) == 0, "unaligned HREFK slot");
|
||||||
if (ra_hasreg(dest)) {
|
if (ra_hasreg(dest)) {
|
||||||
if (ofs != 0) {
|
if (ofs != 0) {
|
||||||
if (dest == node && !(as->flags & JIT_F_LEA_AGU))
|
if (dest == node)
|
||||||
emit_gri(as, XG_ARITHi(XOg_ADD), dest|REX_GC64, ofs);
|
emit_gri(as, XG_ARITHi(XOg_ADD), dest|REX_GC64, ofs);
|
||||||
else
|
else
|
||||||
emit_rmro(as, XO_LEA, dest|REX_GC64, node, ofs);
|
emit_rmro(as, XO_LEA, dest|REX_GC64, node, ofs);
|
||||||
@@ -1293,7 +1296,8 @@ static void asm_hrefk(ASMState *as, IRIns *ir)
|
|||||||
Reg key = ra_scratch(as, rset_exclude(RSET_GPR, node));
|
Reg key = ra_scratch(as, rset_exclude(RSET_GPR, node));
|
||||||
emit_rmro(as, XO_CMP, key|REX_64, node,
|
emit_rmro(as, XO_CMP, key|REX_64, node,
|
||||||
ofs + (int32_t)offsetof(Node, key.u64));
|
ofs + (int32_t)offsetof(Node, key.u64));
|
||||||
lua_assert(irt_isnum(irkey->t) || irt_isgcv(irkey->t));
|
lj_assertA(irt_isnum(irkey->t) || irt_isgcv(irkey->t),
|
||||||
|
"bad HREFK key type");
|
||||||
/* Assumes -0.0 is already canonicalized to +0.0. */
|
/* Assumes -0.0 is already canonicalized to +0.0. */
|
||||||
emit_loadu64(as, key, irt_isnum(irkey->t) ? ir_knum(irkey)->u64 :
|
emit_loadu64(as, key, irt_isnum(irkey->t) ? ir_knum(irkey)->u64 :
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
@@ -1304,7 +1308,7 @@ static void asm_hrefk(ASMState *as, IRIns *ir)
|
|||||||
(uint64_t)(uint32_t)ptr2addr(ir_kgc(irkey)));
|
(uint64_t)(uint32_t)ptr2addr(ir_kgc(irkey)));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
lua_assert(!irt_isnil(irkey->t));
|
lj_assertA(!irt_isnil(irkey->t), "bad HREFK key type");
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
emit_i32(as, (irt_toitype(irkey->t)<<15)|0x7fff);
|
emit_i32(as, (irt_toitype(irkey->t)<<15)|0x7fff);
|
||||||
emit_rmro(as, XO_ARITHi, XOg_CMP, node,
|
emit_rmro(as, XO_ARITHi, XOg_CMP, node,
|
||||||
@@ -1328,13 +1332,13 @@ static void asm_hrefk(ASMState *as, IRIns *ir)
|
|||||||
(int32_t)ir_knum(irkey)->u32.hi);
|
(int32_t)ir_knum(irkey)->u32.hi);
|
||||||
} else {
|
} else {
|
||||||
if (!irt_ispri(irkey->t)) {
|
if (!irt_ispri(irkey->t)) {
|
||||||
lua_assert(irt_isgcv(irkey->t));
|
lj_assertA(irt_isgcv(irkey->t), "bad HREFK key type");
|
||||||
emit_gmroi(as, XG_ARITHi(XOg_CMP), node,
|
emit_gmroi(as, XG_ARITHi(XOg_CMP), node,
|
||||||
ofs + (int32_t)offsetof(Node, key.gcr),
|
ofs + (int32_t)offsetof(Node, key.gcr),
|
||||||
ptr2addr(ir_kgc(irkey)));
|
ptr2addr(ir_kgc(irkey)));
|
||||||
emit_sjcc(as, CC_NE, l_exit);
|
emit_sjcc(as, CC_NE, l_exit);
|
||||||
}
|
}
|
||||||
lua_assert(!irt_isnil(irkey->t));
|
lj_assertA(!irt_isnil(irkey->t), "bad HREFK key type");
|
||||||
emit_i8(as, irt_toitype(irkey->t));
|
emit_i8(as, irt_toitype(irkey->t));
|
||||||
emit_rmro(as, XO_ARITHi8, XOg_CMP, node,
|
emit_rmro(as, XO_ARITHi8, XOg_CMP, node,
|
||||||
ofs + (int32_t)offsetof(Node, key.it));
|
ofs + (int32_t)offsetof(Node, key.it));
|
||||||
@@ -1407,7 +1411,8 @@ static void asm_fxload(ASMState *as, IRIns *ir)
|
|||||||
if (LJ_64 && irt_is64(ir->t))
|
if (LJ_64 && irt_is64(ir->t))
|
||||||
dest |= REX_64;
|
dest |= REX_64;
|
||||||
else
|
else
|
||||||
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),
|
||||||
|
"unsplit 64 bit load");
|
||||||
xo = XO_MOV;
|
xo = XO_MOV;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1452,13 +1457,16 @@ static void asm_fxstore(ASMState *as, IRIns *ir)
|
|||||||
case IRT_NUM: xo = XO_MOVSDto; break;
|
case IRT_NUM: xo = XO_MOVSDto; break;
|
||||||
case IRT_FLOAT: xo = XO_MOVSSto; break;
|
case IRT_FLOAT: xo = XO_MOVSSto; break;
|
||||||
#if LJ_64 && !LJ_GC64
|
#if LJ_64 && !LJ_GC64
|
||||||
case IRT_LIGHTUD: lua_assert(0); /* NYI: mask 64 bit lightuserdata. */
|
case IRT_LIGHTUD:
|
||||||
|
/* NYI: mask 64 bit lightuserdata. */
|
||||||
|
lj_assertA(0, "store of lightuserdata");
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
if (LJ_64 && irt_is64(ir->t))
|
if (LJ_64 && irt_is64(ir->t))
|
||||||
src |= REX_64;
|
src |= REX_64;
|
||||||
else
|
else
|
||||||
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),
|
||||||
|
"unsplit 64 bit store");
|
||||||
xo = XO_MOVto;
|
xo = XO_MOVto;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1472,8 +1480,8 @@ static void asm_fxstore(ASMState *as, IRIns *ir)
|
|||||||
emit_i8(as, k);
|
emit_i8(as, k);
|
||||||
emit_mrm(as, XO_MOVmib, 0, RID_MRM);
|
emit_mrm(as, XO_MOVmib, 0, RID_MRM);
|
||||||
} else {
|
} else {
|
||||||
lua_assert(irt_is64(ir->t) || irt_isint(ir->t) || irt_isu32(ir->t) ||
|
lj_assertA(irt_is64(ir->t) || irt_isint(ir->t) || irt_isu32(ir->t) ||
|
||||||
irt_isaddr(ir->t));
|
irt_isaddr(ir->t), "bad store type");
|
||||||
emit_i32(as, k);
|
emit_i32(as, k);
|
||||||
emit_mrm(as, XO_MOVmi, REX_64IR(ir, 0), RID_MRM);
|
emit_mrm(as, XO_MOVmi, REX_64IR(ir, 0), RID_MRM);
|
||||||
}
|
}
|
||||||
@@ -1508,8 +1516,9 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
Reg tmp = RID_NONE;
|
Reg tmp = RID_NONE;
|
||||||
#endif
|
#endif
|
||||||
lua_assert(irt_isnum(ir->t) || irt_ispri(ir->t) || irt_isaddr(ir->t) ||
|
lj_assertA(irt_isnum(ir->t) || irt_ispri(ir->t) || irt_isaddr(ir->t) ||
|
||||||
(LJ_DUALNUM && irt_isint(ir->t)));
|
(LJ_DUALNUM && irt_isint(ir->t)),
|
||||||
|
"bad load type %d", irt_type(ir->t));
|
||||||
#if LJ_64 && !LJ_GC64
|
#if LJ_64 && !LJ_GC64
|
||||||
if (irt_islightud(ir->t)) {
|
if (irt_islightud(ir->t)) {
|
||||||
Reg dest = asm_load_lightud64(as, ir, 1);
|
Reg dest = asm_load_lightud64(as, ir, 1);
|
||||||
@@ -1556,7 +1565,8 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
as->mrm.ofs += 4;
|
as->mrm.ofs += 4;
|
||||||
asm_guardcc(as, irt_isnum(ir->t) ? CC_AE : CC_NE);
|
asm_guardcc(as, irt_isnum(ir->t) ? CC_AE : CC_NE);
|
||||||
if (LJ_64 && irt_type(ir->t) >= IRT_NUM) {
|
if (LJ_64 && irt_type(ir->t) >= IRT_NUM) {
|
||||||
lua_assert(irt_isinteger(ir->t) || irt_isnum(ir->t));
|
lj_assertA(irt_isinteger(ir->t) || irt_isnum(ir->t),
|
||||||
|
"bad load type %d", irt_type(ir->t));
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
emit_u32(as, LJ_TISNUM << 15);
|
emit_u32(as, LJ_TISNUM << 15);
|
||||||
#else
|
#else
|
||||||
@@ -1638,13 +1648,14 @@ static void asm_ahustore(ASMState *as, IRIns *ir)
|
|||||||
#endif
|
#endif
|
||||||
emit_mrm(as, XO_MOVto, src, RID_MRM);
|
emit_mrm(as, XO_MOVto, src, RID_MRM);
|
||||||
} else if (!irt_ispri(irr->t)) {
|
} else if (!irt_ispri(irr->t)) {
|
||||||
lua_assert(irt_isaddr(ir->t) || (LJ_DUALNUM && irt_isinteger(ir->t)));
|
lj_assertA(irt_isaddr(ir->t) || (LJ_DUALNUM && irt_isinteger(ir->t)),
|
||||||
|
"bad store type");
|
||||||
emit_i32(as, irr->i);
|
emit_i32(as, irr->i);
|
||||||
emit_mrm(as, XO_MOVmi, 0, RID_MRM);
|
emit_mrm(as, XO_MOVmi, 0, RID_MRM);
|
||||||
}
|
}
|
||||||
as->mrm.ofs += 4;
|
as->mrm.ofs += 4;
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
lua_assert(LJ_DUALNUM && irt_isinteger(ir->t));
|
lj_assertA(LJ_DUALNUM && irt_isinteger(ir->t), "bad store type");
|
||||||
emit_i32(as, LJ_TNUMX << 15);
|
emit_i32(as, LJ_TNUMX << 15);
|
||||||
#else
|
#else
|
||||||
emit_i32(as, (int32_t)irt_toitype(ir->t));
|
emit_i32(as, (int32_t)irt_toitype(ir->t));
|
||||||
@@ -1659,10 +1670,13 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
(!LJ_FR2 && (ir->op2 & IRSLOAD_FRAME) ? 4 : 0);
|
(!LJ_FR2 && (ir->op2 & IRSLOAD_FRAME) ? 4 : 0);
|
||||||
IRType1 t = ir->t;
|
IRType1 t = ir->t;
|
||||||
Reg base;
|
Reg base;
|
||||||
lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */
|
lj_assertA(!(ir->op2 & IRSLOAD_PARENT),
|
||||||
lua_assert(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK));
|
"bad parent SLOAD"); /* Handled by asm_head_side(). */
|
||||||
lua_assert(LJ_DUALNUM ||
|
lj_assertA(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK),
|
||||||
!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)));
|
"inconsistent SLOAD variant");
|
||||||
|
lj_assertA(LJ_DUALNUM ||
|
||||||
|
!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)),
|
||||||
|
"bad SLOAD type");
|
||||||
if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) {
|
if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) {
|
||||||
Reg left = ra_scratch(as, RSET_FPR);
|
Reg left = ra_scratch(as, RSET_FPR);
|
||||||
asm_tointg(as, ir, left); /* Frees dest reg. Do this before base alloc. */
|
asm_tointg(as, ir, left); /* Frees dest reg. Do this before base alloc. */
|
||||||
@@ -1682,7 +1696,8 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
RegSet allow = irt_isnum(t) ? RSET_FPR : RSET_GPR;
|
RegSet allow = irt_isnum(t) ? RSET_FPR : RSET_GPR;
|
||||||
Reg dest = ra_dest(as, ir, allow);
|
Reg dest = ra_dest(as, ir, allow);
|
||||||
base = ra_alloc1(as, REF_BASE, RSET_GPR);
|
base = ra_alloc1(as, REF_BASE, RSET_GPR);
|
||||||
lua_assert(irt_isnum(t) || irt_isint(t) || irt_isaddr(t));
|
lj_assertA(irt_isnum(t) || irt_isint(t) || irt_isaddr(t),
|
||||||
|
"bad SLOAD type %d", irt_type(t));
|
||||||
if ((ir->op2 & IRSLOAD_CONVERT)) {
|
if ((ir->op2 & IRSLOAD_CONVERT)) {
|
||||||
t.irt = irt_isint(t) ? IRT_NUM : IRT_INT; /* Check for original type. */
|
t.irt = irt_isint(t) ? IRT_NUM : IRT_INT; /* Check for original type. */
|
||||||
emit_rmro(as, irt_isint(t) ? XO_CVTSI2SD : XO_CVTTSD2SI, dest, base, ofs);
|
emit_rmro(as, irt_isint(t) ? XO_CVTSI2SD : XO_CVTTSD2SI, dest, base, ofs);
|
||||||
@@ -1728,7 +1743,8 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
/* Need type check, even if the load result is unused. */
|
/* Need type check, even if the load result is unused. */
|
||||||
asm_guardcc(as, irt_isnum(t) ? CC_AE : CC_NE);
|
asm_guardcc(as, irt_isnum(t) ? CC_AE : CC_NE);
|
||||||
if (LJ_64 && irt_type(t) >= IRT_NUM) {
|
if (LJ_64 && irt_type(t) >= IRT_NUM) {
|
||||||
lua_assert(irt_isinteger(t) || irt_isnum(t));
|
lj_assertA(irt_isinteger(t) || irt_isnum(t),
|
||||||
|
"bad SLOAD type %d", irt_type(t));
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
emit_u32(as, LJ_TISNUM << 15);
|
emit_u32(as, LJ_TISNUM << 15);
|
||||||
#else
|
#else
|
||||||
@@ -1780,7 +1796,8 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
CTInfo info = lj_ctype_info(cts, id, &sz);
|
CTInfo info = lj_ctype_info(cts, id, &sz);
|
||||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
|
||||||
IRRef args[4];
|
IRRef args[4];
|
||||||
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++;
|
as->gcsteps++;
|
||||||
asm_setupresult(as, ir, ci); /* GCcdata * */
|
asm_setupresult(as, ir, ci); /* GCcdata * */
|
||||||
@@ -1810,7 +1827,7 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
int32_t ofs = sizeof(GCcdata);
|
int32_t ofs = sizeof(GCcdata);
|
||||||
if (sz == 8) {
|
if (sz == 8) {
|
||||||
ofs += 4; ir++;
|
ofs += 4; ir++;
|
||||||
lua_assert(ir->o == IR_HIOP);
|
lj_assertA(ir->o == IR_HIOP, "missing CNEWI HIOP");
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
if (irref_isk(ir->op2)) {
|
if (irref_isk(ir->op2)) {
|
||||||
@@ -1824,7 +1841,7 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
ofs -= 4; ir--;
|
ofs -= 4; ir--;
|
||||||
} while (1);
|
} while (1);
|
||||||
#endif
|
#endif
|
||||||
lua_assert(sz == 4 || sz == 8);
|
lj_assertA(sz == 4 || sz == 8, "bad CNEWI size %d", sz);
|
||||||
} else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
|
} else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
|
||||||
ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
|
ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
|
||||||
args[0] = ASMREF_L; /* lua_State *L */
|
args[0] = ASMREF_L; /* lua_State *L */
|
||||||
@@ -1848,8 +1865,6 @@ static void asm_cnew(ASMState *as, IRIns *ir)
|
|||||||
asm_gencall(as, ci, args);
|
asm_gencall(as, ci, args);
|
||||||
emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)(sz+sizeof(GCcdata)));
|
emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)(sz+sizeof(GCcdata)));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define asm_cnew(as, ir) ((void)0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -- Write barriers ------------------------------------------------------ */
|
/* -- Write barriers ------------------------------------------------------ */
|
||||||
@@ -1876,7 +1891,7 @@ static void asm_obar(ASMState *as, IRIns *ir)
|
|||||||
MCLabel l_end;
|
MCLabel l_end;
|
||||||
Reg obj;
|
Reg obj;
|
||||||
/* No need for other object barriers (yet). */
|
/* 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);
|
ra_evictset(as, RSET_SCRATCH);
|
||||||
l_end = emit_label(as);
|
l_end = emit_label(as);
|
||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
@@ -1955,15 +1970,11 @@ static void asm_fpmath(ASMState *as, IRIns *ir)
|
|||||||
fpm == IRFPM_CEIL ? lj_vm_ceil_sse : lj_vm_trunc_sse);
|
fpm == IRFPM_CEIL ? lj_vm_ceil_sse : lj_vm_trunc_sse);
|
||||||
ra_left(as, RID_XMM0, ir->op1);
|
ra_left(as, RID_XMM0, ir->op1);
|
||||||
}
|
}
|
||||||
} else if (fpm == IRFPM_EXP2 && asm_fpjoin_pow(as, ir)) {
|
|
||||||
/* Rejoined to pow(). */
|
|
||||||
} else {
|
} else {
|
||||||
asm_callid(as, ir, IRCALL_lj_vm_floor + fpm);
|
asm_callid(as, ir, IRCALL_lj_vm_floor + fpm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define asm_atan2(as, ir) asm_callid(as, ir, IRCALL_atan2)
|
|
||||||
|
|
||||||
static void asm_ldexp(ASMState *as, IRIns *ir)
|
static void asm_ldexp(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
int32_t ofs = sps_scale(ir->s); /* Use spill slot or temp slots. */
|
int32_t ofs = sps_scale(ir->s); /* Use spill slot or temp slots. */
|
||||||
@@ -1993,22 +2004,11 @@ static void asm_fppowi(ASMState *as, IRIns *ir)
|
|||||||
ra_left(as, RID_EAX, ir->op2);
|
ra_left(as, RID_EAX, ir->op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
asm_fppowi(as, ir);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int asm_swapops(ASMState *as, IRIns *ir)
|
static int asm_swapops(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
IRIns *irl = IR(ir->op1);
|
IRIns *irl = IR(ir->op1);
|
||||||
IRIns *irr = IR(ir->op2);
|
IRIns *irr = IR(ir->op2);
|
||||||
lua_assert(ra_noreg(irr->r));
|
lj_assertA(ra_noreg(irr->r), "bad usage");
|
||||||
if (!irm_iscomm(lj_ir_mode[ir->o]))
|
if (!irm_iscomm(lj_ir_mode[ir->o]))
|
||||||
return 0; /* Can't swap non-commutative operations. */
|
return 0; /* Can't swap non-commutative operations. */
|
||||||
if (irref_isk(ir->op2))
|
if (irref_isk(ir->op2))
|
||||||
@@ -2061,8 +2061,9 @@ static void asm_intarith(ASMState *as, IRIns *ir, x86Arith xa)
|
|||||||
int32_t k = 0;
|
int32_t k = 0;
|
||||||
if (as->flagmcp == as->mcp) { /* Drop test r,r instruction. */
|
if (as->flagmcp == as->mcp) { /* Drop test r,r instruction. */
|
||||||
MCode *p = as->mcp + ((LJ_64 && *as->mcp < XI_TESTb) ? 3 : 2);
|
MCode *p = as->mcp + ((LJ_64 && *as->mcp < XI_TESTb) ? 3 : 2);
|
||||||
if ((p[1] & 15) < 14) {
|
MCode *q = p[0] == 0x0f ? p+1 : p;
|
||||||
if ((p[1] & 15) >= 12) p[1] -= 4; /* L <->S, NL <-> NS */
|
if ((*q & 15) < 14) {
|
||||||
|
if ((*q & 15) >= 12) *q -= 4; /* L <->S, NL <-> NS */
|
||||||
as->flagmcp = NULL;
|
as->flagmcp = NULL;
|
||||||
as->mcp = p;
|
as->mcp = p;
|
||||||
} /* else: cannot transform LE/NLE to cc without use of OF. */
|
} /* else: cannot transform LE/NLE to cc without use of OF. */
|
||||||
@@ -2179,8 +2180,7 @@ static void asm_add(ASMState *as, IRIns *ir)
|
|||||||
{
|
{
|
||||||
if (irt_isnum(ir->t))
|
if (irt_isnum(ir->t))
|
||||||
asm_fparith(as, ir, XO_ADDSD);
|
asm_fparith(as, ir, XO_ADDSD);
|
||||||
else if ((as->flags & JIT_F_LEA_AGU) || as->flagmcp == as->mcp ||
|
else if (as->flagmcp == as->mcp || irt_is64(ir->t) || !asm_lea(as, ir))
|
||||||
irt_is64(ir->t) || !asm_lea(as, ir))
|
|
||||||
asm_intarith(as, ir, XOg_ADD);
|
asm_intarith(as, ir, XOg_ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2200,27 +2200,7 @@ static void asm_mul(ASMState *as, IRIns *ir)
|
|||||||
asm_intarith(as, ir, XOg_X_IMUL);
|
asm_intarith(as, ir, XOg_X_IMUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_div(ASMState *as, IRIns *ir)
|
#define asm_fpdiv(as, ir) asm_fparith(as, ir, XO_DIVSD)
|
||||||
{
|
|
||||||
#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_fparith(as, ir, XO_DIVSD);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_neg_not(ASMState *as, IRIns *ir, x86Group3 xg)
|
static void asm_neg_not(ASMState *as, IRIns *ir, x86Group3 xg)
|
||||||
{
|
{
|
||||||
@@ -2320,7 +2300,7 @@ static void asm_bitshift(ASMState *as, IRIns *ir, x86Shift xs, x86Op xv)
|
|||||||
dest = ra_dest(as, ir, rset_exclude(RSET_GPR, RID_ECX));
|
dest = ra_dest(as, ir, rset_exclude(RSET_GPR, RID_ECX));
|
||||||
if (dest == RID_ECX) {
|
if (dest == RID_ECX) {
|
||||||
dest = ra_scratch(as, rset_exclude(RSET_GPR, RID_ECX));
|
dest = ra_scratch(as, rset_exclude(RSET_GPR, RID_ECX));
|
||||||
emit_rr(as, XO_MOV, RID_ECX, dest);
|
emit_rr(as, XO_MOV, REX_64IR(ir, RID_ECX), dest);
|
||||||
}
|
}
|
||||||
right = irr->r;
|
right = irr->r;
|
||||||
if (ra_noreg(right))
|
if (ra_noreg(right))
|
||||||
@@ -2418,8 +2398,9 @@ static void asm_comp(ASMState *as, IRIns *ir)
|
|||||||
IROp leftop = (IROp)(IR(lref)->o);
|
IROp leftop = (IROp)(IR(lref)->o);
|
||||||
Reg r64 = REX_64IR(ir, 0);
|
Reg r64 = REX_64IR(ir, 0);
|
||||||
int32_t imm = 0;
|
int32_t imm = 0;
|
||||||
lua_assert(irt_is64(ir->t) || irt_isint(ir->t) ||
|
lj_assertA(irt_is64(ir->t) || irt_isint(ir->t) ||
|
||||||
irt_isu32(ir->t) || irt_isaddr(ir->t) || irt_isu8(ir->t));
|
irt_isu32(ir->t) || irt_isaddr(ir->t) || irt_isu8(ir->t),
|
||||||
|
"bad comparison data type %d", irt_type(ir->t));
|
||||||
/* Swap constants (only for ABC) and fusable loads to the right. */
|
/* Swap constants (only for ABC) and fusable loads to the right. */
|
||||||
if (irref_isk(lref) || (!irref_isk(rref) && opisfusableload(leftop))) {
|
if (irref_isk(lref) || (!irref_isk(rref) && opisfusableload(leftop))) {
|
||||||
if ((cc & 0xc) == 0xc) cc ^= 0x53; /* L <-> G, LE <-> GE */
|
if ((cc & 0xc) == 0xc) cc ^= 0x53; /* L <-> G, LE <-> GE */
|
||||||
@@ -2501,7 +2482,7 @@ static void asm_comp(ASMState *as, IRIns *ir)
|
|||||||
/* Use test r,r instead of cmp r,0. */
|
/* Use test r,r instead of cmp r,0. */
|
||||||
x86Op xo = XO_TEST;
|
x86Op xo = XO_TEST;
|
||||||
if (irt_isu8(ir->t)) {
|
if (irt_isu8(ir->t)) {
|
||||||
lua_assert(ir->o == IR_EQ || ir->o == IR_NE);
|
lj_assertA(ir->o == IR_EQ || ir->o == IR_NE, "bad usage");
|
||||||
xo = XO_TESTb;
|
xo = XO_TESTb;
|
||||||
if (!rset_test(RSET_RANGE(RID_EAX, RID_EBX+1), left)) {
|
if (!rset_test(RSET_RANGE(RID_EAX, RID_EBX+1), left)) {
|
||||||
if (LJ_64) {
|
if (LJ_64) {
|
||||||
@@ -2657,10 +2638,11 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
case IR_CNEWI:
|
case IR_CNEWI:
|
||||||
/* Nothing to do here. Handled by CNEWI itself. */
|
/* Nothing to do here. Handled by CNEWI itself. */
|
||||||
break;
|
break;
|
||||||
default: lua_assert(0); break;
|
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
UNUSED(as); UNUSED(ir); lua_assert(0); /* Unused on x64 or without FFI. */
|
/* Unused on x64 or without FFI. */
|
||||||
|
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2726,8 +2708,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
Reg src = ra_alloc1(as, ref, RSET_FPR);
|
Reg src = ra_alloc1(as, ref, RSET_FPR);
|
||||||
emit_rmro(as, XO_MOVSDto, src, RID_BASE, ofs);
|
emit_rmro(as, XO_MOVSDto, src, RID_BASE, ofs);
|
||||||
} else {
|
} else {
|
||||||
lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t) ||
|
lj_assertA(irt_ispri(ir->t) || irt_isaddr(ir->t) ||
|
||||||
(LJ_DUALNUM && irt_isinteger(ir->t)));
|
(LJ_DUALNUM && irt_isinteger(ir->t)),
|
||||||
|
"restore of IR type %d", irt_type(ir->t));
|
||||||
if (!irref_isk(ref)) {
|
if (!irref_isk(ref)) {
|
||||||
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, RID_BASE));
|
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, RID_BASE));
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
@@ -2772,7 +2755,7 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
}
|
}
|
||||||
checkmclim(as);
|
checkmclim(as);
|
||||||
}
|
}
|
||||||
lua_assert(map + nent == flinks);
|
lj_assertA(map + nent == flinks, "inconsistent frames in snapshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- GC handling --------------------------------------------------------- */
|
/* -- GC handling --------------------------------------------------------- */
|
||||||
@@ -2816,16 +2799,16 @@ static void asm_loop_fixup(ASMState *as)
|
|||||||
MCode *target = as->mcp;
|
MCode *target = as->mcp;
|
||||||
if (as->realign) { /* Realigned loops use short jumps. */
|
if (as->realign) { /* Realigned loops use short jumps. */
|
||||||
as->realign = NULL; /* Stop another retry. */
|
as->realign = NULL; /* Stop another retry. */
|
||||||
lua_assert(((intptr_t)target & 15) == 0);
|
lj_assertA(((intptr_t)target & 15) == 0, "loop realign failed");
|
||||||
if (as->loopinv) { /* Inverted loop branch? */
|
if (as->loopinv) { /* Inverted loop branch? */
|
||||||
p -= 5;
|
p -= 5;
|
||||||
p[0] = XI_JMP;
|
p[0] = XI_JMP;
|
||||||
lua_assert(target - p >= -128);
|
lj_assertA(target - p >= -128, "loop realign failed");
|
||||||
p[-1] = (MCode)(target - p); /* Patch sjcc. */
|
p[-1] = (MCode)(target - p); /* Patch sjcc. */
|
||||||
if (as->loopinv == 2)
|
if (as->loopinv == 2)
|
||||||
p[-3] = (MCode)(target - p + 2); /* Patch opt. short jp. */
|
p[-3] = (MCode)(target - p + 2); /* Patch opt. short jp. */
|
||||||
} else {
|
} else {
|
||||||
lua_assert(target - p >= -128);
|
lj_assertA(target - p >= -128, "loop realign failed");
|
||||||
p[-1] = (MCode)(int8_t)(target - p); /* Patch short jmp. */
|
p[-1] = (MCode)(int8_t)(target - p); /* Patch short jmp. */
|
||||||
p[-2] = XI_JMPs;
|
p[-2] = XI_JMPs;
|
||||||
}
|
}
|
||||||
@@ -2902,7 +2885,7 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk)
|
|||||||
MCode *target, *q;
|
MCode *target, *q;
|
||||||
int32_t spadj = as->T->spadjust;
|
int32_t spadj = as->T->spadjust;
|
||||||
if (spadj == 0) {
|
if (spadj == 0) {
|
||||||
p -= ((as->flags & JIT_F_LEA_AGU) ? 7 : 6) + (LJ_64 ? 1 : 0);
|
p -= LJ_64 ? 7 : 6;
|
||||||
} else {
|
} else {
|
||||||
MCode *p1;
|
MCode *p1;
|
||||||
/* Patch stack adjustment. */
|
/* Patch stack adjustment. */
|
||||||
@@ -2914,24 +2897,15 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk)
|
|||||||
p1 = p-9;
|
p1 = p-9;
|
||||||
*(int32_t *)p1 = spadj;
|
*(int32_t *)p1 = spadj;
|
||||||
}
|
}
|
||||||
if ((as->flags & JIT_F_LEA_AGU)) {
|
|
||||||
#if LJ_64
|
#if LJ_64
|
||||||
p1[-4] = 0x48;
|
p1[-3] = 0x48;
|
||||||
#endif
|
#endif
|
||||||
p1[-3] = (MCode)XI_LEA;
|
p1[-2] = (MCode)(checki8(spadj) ? XI_ARITHi8 : XI_ARITHi);
|
||||||
p1[-2] = MODRM(checki8(spadj) ? XM_OFS8 : XM_OFS32, RID_ESP, RID_ESP);
|
p1[-1] = MODRM(XM_REG, XOg_ADD, RID_ESP);
|
||||||
p1[-1] = MODRM(XM_SCALE1, RID_ESP, RID_ESP);
|
|
||||||
} else {
|
|
||||||
#if LJ_64
|
|
||||||
p1[-3] = 0x48;
|
|
||||||
#endif
|
|
||||||
p1[-2] = (MCode)(checki8(spadj) ? XI_ARITHi8 : XI_ARITHi);
|
|
||||||
p1[-1] = MODRM(XM_REG, XOg_ADD, RID_ESP);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Patch exit branch. */
|
/* Patch exit branch. */
|
||||||
target = lnk ? traceref(as->J, lnk)->mcode : (MCode *)lj_vm_exit_interp;
|
target = lnk ? traceref(as->J, lnk)->mcode : (MCode *)lj_vm_exit_interp;
|
||||||
*(int32_t *)(p-4) = jmprel(p, target);
|
*(int32_t *)(p-4) = jmprel(as->J, p, target);
|
||||||
p[-5] = XI_JMP;
|
p[-5] = XI_JMP;
|
||||||
/* Drop unused mcode tail. Fill with NOPs to make the prefetcher happy. */
|
/* Drop unused mcode tail. Fill with NOPs to make the prefetcher happy. */
|
||||||
for (q = as->mctop-1; q >= p; q--)
|
for (q = as->mctop-1; q >= p; q--)
|
||||||
@@ -2958,7 +2932,7 @@ static void asm_tail_prep(ASMState *as)
|
|||||||
as->invmcp = as->mcp = p;
|
as->invmcp = as->mcp = p;
|
||||||
} else {
|
} else {
|
||||||
/* Leave room for ESP adjustment: add esp, imm or lea esp, [esp+imm] */
|
/* Leave room for ESP adjustment: add esp, imm or lea esp, [esp+imm] */
|
||||||
as->mcp = p - (((as->flags & JIT_F_LEA_AGU) ? 7 : 6) + (LJ_64 ? 1 : 0));
|
as->mcp = p - (LJ_64 ? 7 : 6);
|
||||||
as->invmcp = NULL;
|
as->invmcp = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3098,23 +3072,30 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
|||||||
MSize len = T->szmcode;
|
MSize len = T->szmcode;
|
||||||
MCode *px = exitstub_addr(J, exitno) - 6;
|
MCode *px = exitstub_addr(J, exitno) - 6;
|
||||||
MCode *pe = p+len-6;
|
MCode *pe = p+len-6;
|
||||||
|
MCode *pgc = NULL;
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
uint32_t statei = (uint32_t)(GG_OFS(g.vmstate) - GG_OFS(dispatch));
|
uint32_t statei = (uint32_t)(GG_OFS(g.vmstate) - GG_OFS(dispatch));
|
||||||
#else
|
#else
|
||||||
uint32_t statei = u32ptr(&J2G(J)->vmstate);
|
uint32_t statei = u32ptr(&J2G(J)->vmstate);
|
||||||
#endif
|
#endif
|
||||||
if (len > 5 && p[len-5] == XI_JMP && p+len-6 + *(int32_t *)(p+len-4) == px)
|
if (len > 5 && p[len-5] == XI_JMP && p+len-6 + *(int32_t *)(p+len-4) == px)
|
||||||
*(int32_t *)(p+len-4) = jmprel(p+len, target);
|
*(int32_t *)(p+len-4) = jmprel(J, p+len, target);
|
||||||
/* Do not patch parent exit for a stack check. Skip beyond vmstate update. */
|
/* Do not patch parent exit for a stack check. Skip beyond vmstate update. */
|
||||||
for (; p < pe; p += asm_x86_inslen(p)) {
|
for (; p < pe; p += asm_x86_inslen(p)) {
|
||||||
intptr_t ofs = LJ_GC64 ? (p[0] & 0xf0) == 0x40 : LJ_64;
|
intptr_t ofs = LJ_GC64 ? (p[0] & 0xf0) == 0x40 : LJ_64;
|
||||||
if (*(uint32_t *)(p+2+ofs) == statei && p[ofs+LJ_GC64-LJ_64] == XI_MOVmi)
|
if (*(uint32_t *)(p+2+ofs) == statei && p[ofs+LJ_GC64-LJ_64] == XI_MOVmi)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lua_assert(p < pe);
|
lj_assertJ(p < pe, "instruction length decoder failed");
|
||||||
for (; p < pe; p += asm_x86_inslen(p))
|
for (; p < pe; p += asm_x86_inslen(p)) {
|
||||||
if ((*(uint16_t *)p & 0xf0ff) == 0x800f && p + *(int32_t *)(p+2) == px)
|
if ((*(uint16_t *)p & 0xf0ff) == 0x800f && p + *(int32_t *)(p+2) == px &&
|
||||||
*(int32_t *)(p+2) = jmprel(p+6, target);
|
p != pgc) {
|
||||||
|
*(int32_t *)(p+2) = jmprel(J, p+6, target);
|
||||||
|
} else if (*p == XI_CALL &&
|
||||||
|
(void *)(p+5+*(int32_t *)(p+1)) == (void *)lj_gc_step_jit) {
|
||||||
|
pgc = p+7; /* Do not patch GC check exit. */
|
||||||
|
}
|
||||||
|
}
|
||||||
lj_mcode_sync(T->mcode, T->mcode + T->szmcode);
|
lj_mcode_sync(T->mcode, T->mcode + T->szmcode);
|
||||||
lj_mcode_patch(J, mcarea, 1);
|
lj_mcode_patch(J, mcarea, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
** Internal assertions.
|
||||||
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define lj_assert_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
|
#if defined(LUA_USE_ASSERT) || defined(LUA_USE_APICHECK)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "lj_obj.h"
|
||||||
|
|
||||||
|
void lj_assert_fail(global_State *g, const char *file, int line,
|
||||||
|
const char *func, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list argp;
|
||||||
|
va_start(argp, fmt);
|
||||||
|
fprintf(stderr, "LuaJIT ASSERT %s:%d: %s: ", file, line, func);
|
||||||
|
vfprintf(stderr, fmt, argp);
|
||||||
|
fputc('\n', stderr);
|
||||||
|
va_end(argp);
|
||||||
|
UNUSED(g); /* May be NULL. TODO: optionally dump state. */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bytecode instruction modes.
|
** Bytecode instruction modes.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_bc_c
|
#define lj_bc_c
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bytecode instruction format.
|
** Bytecode instruction format.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_BC_H
|
#ifndef _LJ_BC_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bytecode dump definitions.
|
** Bytecode dump definitions.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_BCDUMP_H
|
#ifndef _LJ_BCDUMP_H
|
||||||
|
|||||||
+16
-16
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bytecode reader.
|
** Bytecode reader.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_bcread_c
|
#define lj_bcread_c
|
||||||
@@ -47,7 +47,7 @@ static LJ_NOINLINE void bcread_error(LexState *ls, ErrMsg em)
|
|||||||
/* Refill buffer. */
|
/* Refill buffer. */
|
||||||
static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
|
static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
|
||||||
{
|
{
|
||||||
lua_assert(len != 0);
|
lj_assertLS(len != 0, "empty refill");
|
||||||
if (len > LJ_MAX_BUF || ls->c < 0)
|
if (len > LJ_MAX_BUF || ls->c < 0)
|
||||||
bcread_error(ls, LJ_ERR_BCBAD);
|
bcread_error(ls, LJ_ERR_BCBAD);
|
||||||
do {
|
do {
|
||||||
@@ -57,7 +57,7 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
|
|||||||
MSize n = (MSize)(ls->pe - ls->p);
|
MSize n = (MSize)(ls->pe - ls->p);
|
||||||
if (n) { /* Copy remainder to buffer. */
|
if (n) { /* Copy remainder to buffer. */
|
||||||
if (sbuflen(&ls->sb)) { /* Move down in buffer. */
|
if (sbuflen(&ls->sb)) { /* Move down in buffer. */
|
||||||
lua_assert(ls->pe == sbufP(&ls->sb));
|
lj_assertLS(ls->pe == sbufP(&ls->sb), "bad buffer pointer");
|
||||||
if (ls->p != p) memmove(p, ls->p, n);
|
if (ls->p != p) memmove(p, ls->p, n);
|
||||||
} else { /* Copy from buffer provided by reader. */
|
} else { /* Copy from buffer provided by reader. */
|
||||||
p = lj_buf_need(&ls->sb, len);
|
p = lj_buf_need(&ls->sb, len);
|
||||||
@@ -73,6 +73,7 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
|
|||||||
ls->c = -1; /* Only bad if we get called again. */
|
ls->c = -1; /* Only bad if we get called again. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (sz >= LJ_MAX_BUF - n) lj_err_mem(ls->L);
|
||||||
if (n) { /* Append to buffer. */
|
if (n) { /* Append to buffer. */
|
||||||
n += (MSize)sz;
|
n += (MSize)sz;
|
||||||
p = lj_buf_need(&ls->sb, n < len ? len : n);
|
p = lj_buf_need(&ls->sb, n < len ? len : n);
|
||||||
@@ -84,20 +85,20 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
|
|||||||
ls->p = buf;
|
ls->p = buf;
|
||||||
ls->pe = buf + sz;
|
ls->pe = buf + sz;
|
||||||
}
|
}
|
||||||
} while (ls->p + len > ls->pe);
|
} while ((MSize)(ls->pe - ls->p) < len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Need a certain number of bytes. */
|
/* Need a certain number of bytes. */
|
||||||
static LJ_AINLINE void bcread_need(LexState *ls, MSize len)
|
static LJ_AINLINE void bcread_need(LexState *ls, MSize len)
|
||||||
{
|
{
|
||||||
if (LJ_UNLIKELY(ls->p + len > ls->pe))
|
if (LJ_UNLIKELY((MSize)(ls->pe - ls->p) < len))
|
||||||
bcread_fill(ls, len, 1);
|
bcread_fill(ls, len, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Want to read up to a certain number of bytes, but may need less. */
|
/* Want to read up to a certain number of bytes, but may need less. */
|
||||||
static LJ_AINLINE void bcread_want(LexState *ls, MSize len)
|
static LJ_AINLINE void bcread_want(LexState *ls, MSize len)
|
||||||
{
|
{
|
||||||
if (LJ_UNLIKELY(ls->p + len > ls->pe))
|
if (LJ_UNLIKELY((MSize)(ls->pe - ls->p) < len))
|
||||||
bcread_fill(ls, len, 0);
|
bcread_fill(ls, len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +107,7 @@ static LJ_AINLINE uint8_t *bcread_mem(LexState *ls, MSize len)
|
|||||||
{
|
{
|
||||||
uint8_t *p = (uint8_t *)ls->p;
|
uint8_t *p = (uint8_t *)ls->p;
|
||||||
ls->p += len;
|
ls->p += len;
|
||||||
lua_assert(ls->p <= ls->pe);
|
lj_assertLS(ls->p <= ls->pe, "buffer read overflow");
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ static void bcread_block(LexState *ls, void *q, MSize len)
|
|||||||
/* Read byte from buffer. */
|
/* Read byte from buffer. */
|
||||||
static LJ_AINLINE uint32_t bcread_byte(LexState *ls)
|
static LJ_AINLINE uint32_t bcread_byte(LexState *ls)
|
||||||
{
|
{
|
||||||
lua_assert(ls->p < ls->pe);
|
lj_assertLS(ls->p < ls->pe, "buffer read overflow");
|
||||||
return (uint32_t)(uint8_t)*ls->p++;
|
return (uint32_t)(uint8_t)*ls->p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +128,7 @@ static LJ_AINLINE uint32_t bcread_byte(LexState *ls)
|
|||||||
static LJ_AINLINE uint32_t bcread_uleb128(LexState *ls)
|
static LJ_AINLINE uint32_t bcread_uleb128(LexState *ls)
|
||||||
{
|
{
|
||||||
uint32_t v = lj_buf_ruleb128(&ls->p);
|
uint32_t v = lj_buf_ruleb128(&ls->p);
|
||||||
lua_assert(ls->p <= ls->pe);
|
lj_assertLS(ls->p <= ls->pe, "buffer read overflow");
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +145,7 @@ static uint32_t bcread_uleb128_33(LexState *ls)
|
|||||||
} while (*p++ >= 0x80);
|
} while (*p++ >= 0x80);
|
||||||
}
|
}
|
||||||
ls->p = (char *)p;
|
ls->p = (char *)p;
|
||||||
lua_assert(ls->p <= ls->pe);
|
lj_assertLS(ls->p <= ls->pe, "buffer read overflow");
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +192,7 @@ static void bcread_ktabk(LexState *ls, TValue *o)
|
|||||||
o->u32.lo = bcread_uleb128(ls);
|
o->u32.lo = bcread_uleb128(ls);
|
||||||
o->u32.hi = bcread_uleb128(ls);
|
o->u32.hi = bcread_uleb128(ls);
|
||||||
} else {
|
} else {
|
||||||
lua_assert(tp <= BCDUMP_KTAB_TRUE);
|
lj_assertLS(tp <= BCDUMP_KTAB_TRUE, "bad constant type %d", tp);
|
||||||
setpriV(o, ~tp);
|
setpriV(o, ~tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,7 +214,7 @@ static GCtab *bcread_ktab(LexState *ls)
|
|||||||
for (i = 0; i < nhash; i++) {
|
for (i = 0; i < nhash; i++) {
|
||||||
TValue key;
|
TValue key;
|
||||||
bcread_ktabk(ls, &key);
|
bcread_ktabk(ls, &key);
|
||||||
lua_assert(!tvisnil(&key));
|
lj_assertLS(!tvisnil(&key), "nil key");
|
||||||
bcread_ktabk(ls, lj_tab_set(ls->L, t, &key));
|
bcread_ktabk(ls, lj_tab_set(ls->L, t, &key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,7 +251,7 @@ static void bcread_kgc(LexState *ls, GCproto *pt, MSize sizekgc)
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
lua_State *L = ls->L;
|
lua_State *L = ls->L;
|
||||||
lua_assert(tp == BCDUMP_KGC_CHILD);
|
lj_assertLS(tp == BCDUMP_KGC_CHILD, "bad constant type %d", tp);
|
||||||
if (L->top <= bcread_oldtop(L, ls)) /* Stack underflow? */
|
if (L->top <= bcread_oldtop(L, ls)) /* Stack underflow? */
|
||||||
bcread_error(ls, LJ_ERR_BCBAD);
|
bcread_error(ls, LJ_ERR_BCBAD);
|
||||||
L->top--;
|
L->top--;
|
||||||
@@ -421,7 +422,7 @@ static int bcread_header(LexState *ls)
|
|||||||
GCproto *lj_bcread(LexState *ls)
|
GCproto *lj_bcread(LexState *ls)
|
||||||
{
|
{
|
||||||
lua_State *L = ls->L;
|
lua_State *L = ls->L;
|
||||||
lua_assert(ls->c == BCDUMP_HEAD1);
|
lj_assertLS(ls->c == BCDUMP_HEAD1, "bad bytecode header");
|
||||||
bcread_savetop(L, ls, L->top);
|
bcread_savetop(L, ls, L->top);
|
||||||
lj_buf_reset(&ls->sb);
|
lj_buf_reset(&ls->sb);
|
||||||
/* Check for a valid bytecode dump header. */
|
/* Check for a valid bytecode dump header. */
|
||||||
@@ -447,8 +448,7 @@ GCproto *lj_bcread(LexState *ls)
|
|||||||
setprotoV(L, L->top, pt);
|
setprotoV(L, L->top, pt);
|
||||||
incr_top(L);
|
incr_top(L);
|
||||||
}
|
}
|
||||||
if ((int32_t)(2*(uint32_t)(ls->pe - ls->p)) > 0 ||
|
if ((ls->pe != ls->p && !ls->endmark) || L->top-1 != bcread_oldtop(L, ls))
|
||||||
L->top-1 != bcread_oldtop(L, ls))
|
|
||||||
bcread_error(ls, LJ_ERR_BCBAD);
|
bcread_error(ls, LJ_ERR_BCBAD);
|
||||||
/* Pop off last prototype. */
|
/* Pop off last prototype. */
|
||||||
L->top--;
|
L->top--;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bytecode writer.
|
** Bytecode writer.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_bcwrite_c
|
#define lj_bcwrite_c
|
||||||
@@ -29,8 +29,17 @@ typedef struct BCWriteCtx {
|
|||||||
void *wdata; /* Writer callback data. */
|
void *wdata; /* Writer callback data. */
|
||||||
int strip; /* Strip debug info. */
|
int strip; /* Strip debug info. */
|
||||||
int status; /* Status from writer callback. */
|
int status; /* Status from writer callback. */
|
||||||
|
#ifdef LUA_USE_ASSERT
|
||||||
|
global_State *g;
|
||||||
|
#endif
|
||||||
} BCWriteCtx;
|
} BCWriteCtx;
|
||||||
|
|
||||||
|
#ifdef LUA_USE_ASSERT
|
||||||
|
#define lj_assertBCW(c, ...) lj_assertG_(ctx->g, (c), __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define lj_assertBCW(c, ...) ((void)ctx)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -- Bytecode writer ----------------------------------------------------- */
|
/* -- Bytecode writer ----------------------------------------------------- */
|
||||||
|
|
||||||
/* Write a single constant key/value of a template table. */
|
/* Write a single constant key/value of a template table. */
|
||||||
@@ -61,7 +70,7 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
|
|||||||
p = lj_strfmt_wuleb128(p, o->u32.lo);
|
p = lj_strfmt_wuleb128(p, o->u32.lo);
|
||||||
p = lj_strfmt_wuleb128(p, o->u32.hi);
|
p = lj_strfmt_wuleb128(p, o->u32.hi);
|
||||||
} else {
|
} else {
|
||||||
lua_assert(tvispri(o));
|
lj_assertBCW(tvispri(o), "unhandled type %d", itype(o));
|
||||||
*p++ = BCDUMP_KTAB_NIL+~itype(o);
|
*p++ = BCDUMP_KTAB_NIL+~itype(o);
|
||||||
}
|
}
|
||||||
setsbufP(&ctx->sb, p);
|
setsbufP(&ctx->sb, p);
|
||||||
@@ -121,7 +130,7 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt)
|
|||||||
tp = BCDUMP_KGC_STR + gco2str(o)->len;
|
tp = BCDUMP_KGC_STR + gco2str(o)->len;
|
||||||
need = 5+gco2str(o)->len;
|
need = 5+gco2str(o)->len;
|
||||||
} else if (o->gch.gct == ~LJ_TPROTO) {
|
} else if (o->gch.gct == ~LJ_TPROTO) {
|
||||||
lua_assert((pt->flags & PROTO_CHILD));
|
lj_assertBCW((pt->flags & PROTO_CHILD), "prototype has unexpected child");
|
||||||
tp = BCDUMP_KGC_CHILD;
|
tp = BCDUMP_KGC_CHILD;
|
||||||
#if LJ_HASFFI
|
#if LJ_HASFFI
|
||||||
} else if (o->gch.gct == ~LJ_TCDATA) {
|
} else if (o->gch.gct == ~LJ_TCDATA) {
|
||||||
@@ -132,12 +141,14 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt)
|
|||||||
} else if (id == CTID_UINT64) {
|
} else if (id == CTID_UINT64) {
|
||||||
tp = BCDUMP_KGC_U64;
|
tp = BCDUMP_KGC_U64;
|
||||||
} else {
|
} else {
|
||||||
lua_assert(id == CTID_COMPLEX_DOUBLE);
|
lj_assertBCW(id == CTID_COMPLEX_DOUBLE,
|
||||||
|
"bad cdata constant CTID %d", id);
|
||||||
tp = BCDUMP_KGC_COMPLEX;
|
tp = BCDUMP_KGC_COMPLEX;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
lua_assert(o->gch.gct == ~LJ_TTAB);
|
lj_assertBCW(o->gch.gct == ~LJ_TTAB,
|
||||||
|
"bad constant GC type %d", o->gch.gct);
|
||||||
tp = BCDUMP_KGC_TAB;
|
tp = BCDUMP_KGC_TAB;
|
||||||
need = 1+2*5;
|
need = 1+2*5;
|
||||||
}
|
}
|
||||||
@@ -289,7 +300,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
|
|||||||
MSize nn = (lj_fls(n)+8)*9 >> 6;
|
MSize nn = (lj_fls(n)+8)*9 >> 6;
|
||||||
char *q = sbufB(&ctx->sb) + (5 - nn);
|
char *q = sbufB(&ctx->sb) + (5 - nn);
|
||||||
p = lj_strfmt_wuleb128(q, n); /* Fill in final size. */
|
p = lj_strfmt_wuleb128(q, n); /* Fill in final size. */
|
||||||
lua_assert(p == sbufB(&ctx->sb) + 5);
|
lj_assertBCW(p == sbufB(&ctx->sb) + 5, "bad ULEB128 write");
|
||||||
ctx->status = ctx->wfunc(sbufL(&ctx->sb), q, nn+n, ctx->wdata);
|
ctx->status = ctx->wfunc(sbufL(&ctx->sb), q, nn+n, ctx->wdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,6 +360,9 @@ int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data,
|
|||||||
ctx.wdata = data;
|
ctx.wdata = data;
|
||||||
ctx.strip = strip;
|
ctx.strip = strip;
|
||||||
ctx.status = 0;
|
ctx.status = 0;
|
||||||
|
#ifdef LUA_USE_ASSERT
|
||||||
|
ctx.g = G(L);
|
||||||
|
#endif
|
||||||
lj_buf_init(L, &ctx.sb);
|
lj_buf_init(L, &ctx.sb);
|
||||||
status = lj_vm_cpcall(L, NULL, &ctx, cpwriter);
|
status = lj_vm_cpcall(L, NULL, &ctx, cpwriter);
|
||||||
if (status == 0) status = ctx.status;
|
if (status == 0) status = ctx.status;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Buffer handling.
|
** Buffer handling.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_buf_c
|
#define lj_buf_c
|
||||||
@@ -30,7 +30,7 @@ static void buf_grow(SBuf *sb, MSize sz)
|
|||||||
|
|
||||||
LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
|
LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
|
||||||
{
|
{
|
||||||
lua_assert(sz > sbufsz(sb));
|
lj_assertG_(G(sbufL(sb)), sz > sbufsz(sb), "SBuf overflow");
|
||||||
if (LJ_UNLIKELY(sz > LJ_MAX_BUF))
|
if (LJ_UNLIKELY(sz > LJ_MAX_BUF))
|
||||||
lj_err_mem(sbufL(sb));
|
lj_err_mem(sbufL(sb));
|
||||||
buf_grow(sb, sz);
|
buf_grow(sb, sz);
|
||||||
@@ -40,7 +40,7 @@ LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
|
|||||||
LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz)
|
LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz)
|
||||||
{
|
{
|
||||||
MSize len = sbuflen(sb);
|
MSize len = sbuflen(sb);
|
||||||
lua_assert(sz > sbufleft(sb));
|
lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow");
|
||||||
if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
|
if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
|
||||||
lj_err_mem(sbufL(sb));
|
lj_err_mem(sbufL(sb));
|
||||||
buf_grow(sb, len + sz);
|
buf_grow(sb, len + sz);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Buffer handling.
|
** Buffer handling.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_BUF_H
|
#ifndef _LJ_BUF_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** C data arithmetic.
|
** C data arithmetic.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lj_obj.h"
|
#include "lj_obj.h"
|
||||||
@@ -122,7 +122,7 @@ static int carith_ptr(lua_State *L, CTState *cts, CDArith *ca, MMS mm)
|
|||||||
setboolV(L->top-1, ((uintptr_t)pp < (uintptr_t)pp2));
|
setboolV(L->top-1, ((uintptr_t)pp < (uintptr_t)pp2));
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
lua_assert(mm == MM_le);
|
lj_assertL(mm == MM_le, "bad metamethod %d", mm);
|
||||||
setboolV(L->top-1, ((uintptr_t)pp <= (uintptr_t)pp2));
|
setboolV(L->top-1, ((uintptr_t)pp <= (uintptr_t)pp2));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -208,7 +208,9 @@ static int carith_int64(lua_State *L, CTState *cts, CDArith *ca, MMS mm)
|
|||||||
*up = lj_carith_powu64(u0, u1);
|
*up = lj_carith_powu64(u0, u1);
|
||||||
break;
|
break;
|
||||||
case MM_unm: *up = (uint64_t)-(int64_t)u0; break;
|
case MM_unm: *up = (uint64_t)-(int64_t)u0; break;
|
||||||
default: lua_assert(0); break;
|
default:
|
||||||
|
lj_assertL(0, "bad metamethod %d", mm);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
lj_gc_check(L);
|
lj_gc_check(L);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -265,7 +267,7 @@ int lj_carith_op(lua_State *L, MMS mm)
|
|||||||
{
|
{
|
||||||
CTState *cts = ctype_cts(L);
|
CTState *cts = ctype_cts(L);
|
||||||
CDArith ca;
|
CDArith ca;
|
||||||
if (carith_checkarg(L, cts, &ca)) {
|
if (carith_checkarg(L, cts, &ca) && mm != MM_len && mm != MM_concat) {
|
||||||
if (carith_int64(L, cts, &ca, mm) || carith_ptr(L, cts, &ca, mm)) {
|
if (carith_int64(L, cts, &ca, mm) || carith_ptr(L, cts, &ca, mm)) {
|
||||||
copyTV(L, &G(L)->tmptv2, L->top-1); /* Remember for trace recorder. */
|
copyTV(L, &G(L)->tmptv2, L->top-1); /* Remember for trace recorder. */
|
||||||
return 1;
|
return 1;
|
||||||
@@ -274,15 +276,6 @@ int lj_carith_op(lua_State *L, MMS mm)
|
|||||||
return lj_carith_meta(L, cts, &ca, mm);
|
return lj_carith_meta(L, cts, &ca, mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No built-in functionality for length of cdata. */
|
|
||||||
int lj_carith_len(lua_State *L)
|
|
||||||
{
|
|
||||||
CTState *cts = ctype_cts(L);
|
|
||||||
CDArith ca;
|
|
||||||
carith_checkarg(L, cts, &ca);
|
|
||||||
return lj_carith_meta(L, cts, &ca, MM_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- 64 bit bit operations helpers --------------------------------------- */
|
/* -- 64 bit bit operations helpers --------------------------------------- */
|
||||||
|
|
||||||
#if LJ_64
|
#if LJ_64
|
||||||
@@ -310,7 +303,9 @@ uint64_t lj_carith_shift64(uint64_t x, int32_t sh, int op)
|
|||||||
case IR_BSAR-IR_BSHL: x = lj_carith_sar64(x, sh); break;
|
case IR_BSAR-IR_BSHL: x = lj_carith_sar64(x, sh); break;
|
||||||
case IR_BROL-IR_BSHL: x = lj_carith_rol64(x, sh); break;
|
case IR_BROL-IR_BSHL: x = lj_carith_rol64(x, sh); break;
|
||||||
case IR_BROR-IR_BSHL: x = lj_carith_ror64(x, sh); break;
|
case IR_BROR-IR_BSHL: x = lj_carith_ror64(x, sh); break;
|
||||||
default: lua_assert(0); break;
|
default:
|
||||||
|
lj_assertX(0, "bad shift op %d", op);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** C data arithmetic.
|
** C data arithmetic.
|
||||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_CARITH_H
|
#ifndef _LJ_CARITH_H
|
||||||
@@ -11,7 +11,6 @@
|
|||||||
#if LJ_HASFFI
|
#if LJ_HASFFI
|
||||||
|
|
||||||
LJ_FUNC int lj_carith_op(lua_State *L, MMS mm);
|
LJ_FUNC int lj_carith_op(lua_State *L, MMS mm);
|
||||||
LJ_FUNC int lj_carith_len(lua_State *L);
|
|
||||||
|
|
||||||
#if LJ_32
|
#if LJ_32
|
||||||
LJ_FUNC uint64_t lj_carith_shl64(uint64_t x, int32_t sh);
|
LJ_FUNC uint64_t lj_carith_shl64(uint64_t x, int32_t sh);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user